1 /* 2 Provides utility routines for manipulating any type of PETSc object. 3 */ 4 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 5 #include <petscviewer.h> 6 7 #if defined(PETSC_USE_LOG) 8 PETSC_INTERN PetscObject *PetscObjects; 9 PETSC_INTERN PetscInt PetscObjectsCounts; 10 PETSC_INTERN PetscInt PetscObjectsMaxCounts; 11 PETSC_INTERN PetscBool PetscObjectsLog; 12 #endif 13 14 #if defined(PETSC_USE_LOG) 15 PetscObject *PetscObjects = NULL; 16 PetscInt PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0; 17 PetscBool PetscObjectsLog = PETSC_FALSE; 18 #endif 19 20 PETSC_EXTERN PetscErrorCode PetscObjectCompose_Petsc(PetscObject, const char[], PetscObject); 21 PETSC_EXTERN PetscErrorCode PetscObjectQuery_Petsc(PetscObject, const char[], PetscObject *); 22 PETSC_EXTERN PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject, const char[], void (*)(void)); 23 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject, const char[], void (**)(void)); 24 25 PetscObjectId PetscObjectNewId_Internal(void) 26 { 27 static PetscObjectId idcnt = 1; 28 return idcnt++; 29 } 30 31 /* 32 PetscHeaderCreate_Private - Creates a base PETSc object header and fills 33 in the default values. Called by the macro PetscHeaderCreate(). 34 */ 35 PetscErrorCode PetscHeaderCreate_Private(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view) 36 { 37 void *get_tmp; 38 PetscInt64 *cidx; 39 PetscMPIInt flg; 40 41 PetscFunctionBegin; 42 h->classid = classid; 43 h->class_name = (char *)class_name; 44 h->description = (char *)descr; 45 h->mansec = (char *)mansec; 46 h->refct = 1; 47 h->non_cyclic_references = NULL; 48 h->id = PetscObjectNewId_Internal(); 49 h->bops->destroy = destroy; 50 h->bops->view = view; 51 h->bops->compose = PetscObjectCompose_Petsc; 52 h->bops->query = PetscObjectQuery_Petsc; 53 h->bops->composefunction = PetscObjectComposeFunction_Petsc; 54 h->bops->queryfunction = PetscObjectQueryFunction_Petsc; 55 56 PetscCall(PetscCommDuplicate(comm, &h->comm, &h->tag)); 57 58 /* Increment and store current object creation index */ 59 PetscCallMPI(MPI_Comm_get_attr(h->comm, Petsc_CreationIdx_keyval, &get_tmp, &flg)); 60 PetscCheck(flg, h->comm, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have an object creation index"); 61 cidx = (PetscInt64 *)get_tmp; 62 h->cidx = (*cidx)++; 63 PetscCallMPI(MPI_Comm_set_attr(h->comm, Petsc_CreationIdx_keyval, cidx)); 64 65 #if defined(PETSC_USE_LOG) 66 /* Keep a record of object created */ 67 if (PetscObjectsLog) { 68 PetscObject *newPetscObjects; 69 PetscInt newPetscObjectsMaxCounts; 70 71 PetscObjectsCounts++; 72 for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) { 73 if (!PetscObjects[i]) { 74 PetscObjects[i] = h; 75 PetscFunctionReturn(PETSC_SUCCESS); 76 } 77 } 78 /* Need to increase the space for storing PETSc objects */ 79 if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100; 80 else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts; 81 PetscCall(PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects)); 82 PetscCall(PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts)); 83 PetscCall(PetscFree(PetscObjects)); 84 85 PetscObjects = newPetscObjects; 86 PetscObjects[PetscObjectsMaxCounts] = h; 87 PetscObjectsMaxCounts = newPetscObjectsMaxCounts; 88 } 89 #endif 90 PetscFunctionReturn(PETSC_SUCCESS); 91 } 92 93 PETSC_INTERN PetscBool PetscMemoryCollectMaximumUsage; 94 PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage; 95 96 /* 97 PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by 98 the macro PetscHeaderDestroy(). 99 */ 100 PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse) 101 { 102 PetscFunctionBegin; 103 PetscValidHeader(obj, 1); 104 PetscCall(PetscLogObjectDestroy(obj)); 105 PetscCall(PetscComposedQuantitiesDestroy(obj)); 106 if (PetscMemoryCollectMaximumUsage) { 107 PetscLogDouble usage; 108 109 PetscCall(PetscMemoryGetCurrentUsage(&usage)); 110 if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage; 111 } 112 /* first destroy things that could execute arbitrary code */ 113 if (obj->python_destroy) { 114 void *python_context = obj->python_context; 115 PetscErrorCode (*python_destroy)(void *) = obj->python_destroy; 116 117 obj->python_context = NULL; 118 obj->python_destroy = NULL; 119 PetscCall((*python_destroy)(python_context)); 120 } 121 PetscCall(PetscObjectDestroyOptionsHandlers(obj)); 122 PetscCall(PetscObjectListDestroy(&obj->olist)); 123 124 /* destroy allocated quantities */ 125 if (PetscPrintFunctionList) PetscCall(PetscFunctionListPrintNonEmpty(obj->qlist)); 126 PetscCheck(--(obj->refct) <= 0, obj->comm, PETSC_ERR_PLIB, "Destroying a PetscObject (%s) with reference count %" PetscInt_FMT " >= 1", obj->name ? obj->name : "unnamed", obj->refct); 127 PetscCall(PetscFree(obj->name)); 128 PetscCall(PetscFree(obj->prefix)); 129 PetscCall(PetscFree(obj->type_name)); 130 131 if (clear_for_reuse) { 132 /* we will assume that obj->bops->view and destroy are safe to leave as-is */ 133 obj->bops->compose = PetscObjectCompose_Petsc; 134 obj->bops->query = PetscObjectQuery_Petsc; 135 obj->bops->composefunction = PetscObjectComposeFunction_Petsc; 136 obj->bops->queryfunction = PetscObjectQueryFunction_Petsc; 137 138 /* reset quantities, in order of appearance in _p_PetscObject */ 139 obj->id = PetscObjectNewId_Internal(); 140 obj->refct = 1; 141 obj->tablevel = 0; 142 obj->state = 0; 143 /* don't deallocate, zero these out instead */ 144 PetscCall(PetscFunctionListClear(obj->qlist)); 145 PetscCall(PetscArrayzero(obj->fortran_func_pointers, obj->num_fortran_func_pointers)); 146 PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS])); 147 PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE])); 148 obj->optionsprinted = PETSC_FALSE; 149 #if PetscDefined(HAVE_SAWS) 150 obj->amsmem = PETSC_FALSE; 151 obj->amspublishblock = PETSC_FALSE; 152 #endif 153 obj->options = NULL; 154 obj->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE; 155 } else { 156 PetscCall(PetscFunctionListDestroy(&obj->qlist)); 157 PetscCall(PetscFree(obj->fortran_func_pointers)); 158 PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS])); 159 PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE])); 160 PetscCall(PetscCommDestroy(&obj->comm)); 161 obj->classid = PETSCFREEDHEADER; 162 163 #if PetscDefined(USE_LOG) 164 if (PetscObjectsLog) { 165 /* Record object removal from list of all objects */ 166 for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) { 167 if (PetscObjects[i] == obj) { 168 PetscObjects[i] = NULL; 169 --PetscObjectsCounts; 170 break; 171 } 172 } 173 if (!PetscObjectsCounts) { 174 PetscCall(PetscFree(PetscObjects)); 175 PetscObjectsMaxCounts = 0; 176 } 177 } 178 #endif 179 } 180 PetscFunctionReturn(PETSC_SUCCESS); 181 } 182 183 /* 184 PetscHeaderReset_Internal - "Reset" a PetscObject header. This is tantamount to destroying 185 the object but does not free all resources. The object retains its: 186 187 - classid 188 - bops->view 189 - bops->destroy 190 - comm 191 - tag 192 - class_name 193 - description 194 - mansec 195 - cpp 196 197 Note that while subclass information is lost, superclass info remains. Thus this function is 198 intended to be used to reuse a PetscObject within the same class to avoid reallocating its 199 resources. 200 */ 201 PetscErrorCode PetscHeaderReset_Internal(PetscObject obj) 202 { 203 PetscFunctionBegin; 204 PetscCall(PetscHeaderDestroy_Private(obj, PETSC_TRUE)); 205 PetscFunctionReturn(PETSC_SUCCESS); 206 } 207 208 /*@C 209 PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object 210 211 Logically Collective 212 213 Input Parameters: 214 + src - source object 215 - dest - destination object 216 217 Level: developer 218 219 Note: 220 Both objects must have the same class. 221 222 This is used to help manage user callback functions that were provided in Fortran 223 224 .seealso: `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()` 225 @*/ 226 PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest) 227 { 228 PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE]; 229 230 PetscFunctionBegin; 231 PetscValidHeader(src, 1); 232 PetscValidHeader(dest, 2); 233 PetscCheck(src->classid == dest->classid, src->comm, PETSC_ERR_ARG_INCOMP, "Objects must be of the same class"); 234 235 PetscCall(PetscFree(dest->fortran_func_pointers)); 236 PetscCall(PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers)); 237 PetscCall(PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void)))); 238 239 dest->num_fortran_func_pointers = src->num_fortran_func_pointers; 240 241 PetscCall(PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE])); 242 for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) { 243 PetscCall(PetscFree(dest->fortrancallback[cbtype])); 244 PetscCall(PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype])); 245 PetscCall(PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback))); 246 dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype]; 247 } 248 PetscFunctionReturn(PETSC_SUCCESS); 249 } 250 251 /*@C 252 PetscObjectSetFortranCallback - set fortran callback function pointer and context 253 254 Logically Collective 255 256 Input Parameters: 257 + obj - object on which to set callback 258 . cbtype - callback type (class or subtype) 259 . cid - address of callback Id, updated if not yet initialized (zero) 260 . func - Fortran function 261 - ctx - Fortran context 262 263 Level: developer 264 265 Note: 266 This is used to help manage user callback functions that were provided in Fortran 267 268 .seealso: `PetscObjectGetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()` 269 @*/ 270 PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId *cid, void (*func)(void), void *ctx) 271 { 272 const char *subtype = NULL; 273 274 PetscFunctionBegin; 275 PetscValidHeader(obj, 1); 276 if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name; 277 if (!*cid) PetscCall(PetscFortranCallbackRegister(obj->classid, subtype, cid)); 278 if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype]) { 279 PetscFortranCallbackId oldnum = obj->num_fortrancallback[cbtype]; 280 PetscFortranCallbackId newnum = PetscMax(*cid - PETSC_SMALLEST_FORTRAN_CALLBACK + 1, 2 * oldnum); 281 PetscFortranCallback *callback; 282 PetscCall(PetscMalloc1(newnum, &callback)); 283 PetscCall(PetscMemcpy(callback, obj->fortrancallback[cbtype], oldnum * sizeof(*obj->fortrancallback[cbtype]))); 284 PetscCall(PetscFree(obj->fortrancallback[cbtype])); 285 286 obj->fortrancallback[cbtype] = callback; 287 obj->num_fortrancallback[cbtype] = newnum; 288 } 289 obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].func = func; 290 obj->fortrancallback[cbtype][*cid - PETSC_SMALLEST_FORTRAN_CALLBACK].ctx = ctx; 291 PetscFunctionReturn(PETSC_SUCCESS); 292 } 293 294 /*@C 295 PetscObjectGetFortranCallback - get fortran callback function pointer and context 296 297 Logically Collective 298 299 Input Parameters: 300 + obj - object on which to get callback 301 . cbtype - callback type 302 - cid - address of callback Id 303 304 Output Parameters: 305 + func - Fortran function (or `NULL` if not needed) 306 - ctx - Fortran context (or `NULL` if not needed) 307 308 Level: developer 309 310 Note: 311 This is used to help manage user callback functions that were provided in Fortran 312 313 .seealso: `PetscObjectSetFortranCallback()`, `PetscObjectGetFortranCallback()`, `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()` 314 @*/ 315 PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj, PetscFortranCallbackType cbtype, PetscFortranCallbackId cid, void (**func)(void), void **ctx) 316 { 317 PetscFortranCallback *cb; 318 319 PetscFunctionBegin; 320 PetscValidHeader(obj, 1); 321 PetscCheck(cid >= PETSC_SMALLEST_FORTRAN_CALLBACK, obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback Id invalid"); 322 PetscCheck(cid < PETSC_SMALLEST_FORTRAN_CALLBACK + obj->num_fortrancallback[cbtype], obj->comm, PETSC_ERR_ARG_CORRUPT, "Fortran callback not set on this object"); 323 cb = &obj->fortrancallback[cbtype][cid - PETSC_SMALLEST_FORTRAN_CALLBACK]; 324 if (func) *func = cb->func; 325 if (ctx) *ctx = cb->ctx; 326 PetscFunctionReturn(PETSC_SUCCESS); 327 } 328 329 #if defined(PETSC_USE_LOG) 330 /*@C 331 PetscObjectsDump - Prints all the currently existing objects. 332 333 On rank 0 of `PETSC_COMM_WORLD` prints the values 334 335 Input Parameters: 336 + fd - file pointer 337 - all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects 338 339 Options Database Key: 340 . -objects_dump <all> - print information about all the objects that exist at the end of the programs run 341 342 Level: advanced 343 344 .seealso: `PetscObject` 345 @*/ 346 PetscErrorCode PetscObjectsDump(FILE *fd, PetscBool all) 347 { 348 PetscInt i, j, k = 0; 349 PetscObject h; 350 351 PetscFunctionBegin; 352 if (PetscObjectsCounts) { 353 PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n")); 354 PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n")); 355 for (i = 0; i < PetscObjectsMaxCounts; i++) { 356 if ((h = PetscObjects[i])) { 357 PetscCall(PetscObjectName(h)); 358 { 359 PetscStack *stack = NULL; 360 char *create = NULL, *rclass = NULL; 361 362 /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */ 363 PetscCall(PetscMallocGetStack(h, &stack)); 364 if (stack) { 365 k = stack->currentsize - 2; 366 if (!all) { 367 k = 0; 368 while (!stack->petscroutine[k]) k++; 369 PetscCall(PetscStrstr(stack->function[k], "Create", &create)); 370 if (!create) PetscCall(PetscStrstr(stack->function[k], "Get", &create)); 371 PetscCall(PetscStrstr(stack->function[k], h->class_name, &rclass)); 372 if (!create) continue; 373 if (!rclass) continue; 374 } 375 } 376 377 PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name)); 378 379 PetscCall(PetscMallocGetStack(h, &stack)); 380 if (stack) { 381 for (j = k; j >= 0; j--) fprintf(fd, " [%d] %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]); 382 } 383 } 384 } 385 } 386 } 387 PetscFunctionReturn(PETSC_SUCCESS); 388 } 389 390 /*@C 391 PetscObjectsView - Prints the currently existing objects. 392 393 Logically Collective 394 395 Input Parameter: 396 . viewer - must be an `PETSCVIEWERASCII` viewer 397 398 Level: advanced 399 400 .seealso: `PetscObject` 401 @*/ 402 PetscErrorCode PetscObjectsView(PetscViewer viewer) 403 { 404 PetscBool isascii; 405 FILE *fd; 406 407 PetscFunctionBegin; 408 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 409 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 410 PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer"); 411 PetscCall(PetscViewerASCIIGetPointer(viewer, &fd)); 412 PetscCall(PetscObjectsDump(fd, PETSC_TRUE)); 413 PetscFunctionReturn(PETSC_SUCCESS); 414 } 415 416 /*@C 417 PetscObjectsGetObject - Get a pointer to a named object 418 419 Not Collective 420 421 Input Parameter: 422 . name - the name of an object 423 424 Output Parameters: 425 + obj - the object or `NULL` if there is no object 426 - classname - the name of the class 427 428 Level: advanced 429 430 .seealso: `PetscObject` 431 @*/ 432 PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname) 433 { 434 PetscInt i; 435 PetscObject h; 436 PetscBool flg; 437 438 PetscFunctionBegin; 439 PetscValidCharPointer(name, 1); 440 PetscValidPointer(obj, 2); 441 *obj = NULL; 442 for (i = 0; i < PetscObjectsMaxCounts; i++) { 443 if ((h = PetscObjects[i])) { 444 PetscCall(PetscObjectName(h)); 445 PetscCall(PetscStrcmp(h->name, name, &flg)); 446 if (flg) { 447 *obj = h; 448 if (classname) *classname = h->class_name; 449 PetscFunctionReturn(PETSC_SUCCESS); 450 } 451 } 452 } 453 PetscFunctionReturn(PETSC_SUCCESS); 454 } 455 #endif 456 457 /*@ 458 PetscObjectSetPrintedOptions - indicate to an object that it should behave as if it has already printed the help for its options so it will not display the help message 459 460 Input Parameter: 461 . obj - the `PetscObject` 462 463 Level: developer 464 465 Developer Note: 466 This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by 467 `PCBJACOBI` from all printing the same help messages to the screen 468 469 .seealso: `PetscOptionsInsert()`, `PetscObject` 470 @*/ 471 PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj) 472 { 473 PetscFunctionBegin; 474 PetscValidPointer(obj, 1); 475 obj->optionsprinted = PETSC_TRUE; 476 PetscFunctionReturn(PETSC_SUCCESS); 477 } 478 479 /*@ 480 PetscObjectInheritPrintedOptions - If the child object is not on the rank 0 process of the parent object and the child is sequential then the child gets it set. 481 482 Input Parameters: 483 + pobj - the parent object 484 - obj - the `PetscObject` 485 486 Level: developer 487 488 Developer Notes: 489 This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by 490 `PCBJACOBI` from all printing the same help messages to the screen 491 492 This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap 493 494 .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`, `PetscObject` 495 @*/ 496 PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj) 497 { 498 PetscMPIInt prank, size; 499 500 PetscFunctionBegin; 501 PetscValidHeader(pobj, 1); 502 PetscValidHeader(obj, 2); 503 PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank)); 504 PetscCallMPI(MPI_Comm_size(obj->comm, &size)); 505 if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE; 506 PetscFunctionReturn(PETSC_SUCCESS); 507 } 508 509 /*@C 510 PetscObjectAddOptionsHandler - Adds an additional function to check for options when `XXXSetFromOptions()` is called. 511 512 Not Collective 513 514 Input Parameters: 515 + obj - the PETSc object 516 . handle - function that checks for options 517 . destroy - function to destroy context if provided 518 - ctx - optional context for check function 519 520 Level: developer 521 522 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`, 523 `PetscObject` 524 @*/ 525 PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject, PetscOptionItems *, void *), PetscErrorCode (*destroy)(PetscObject, void *), void *ctx) 526 { 527 PetscFunctionBegin; 528 PetscValidHeader(obj, 1); 529 PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "To many options handlers added"); 530 obj->optionhandler[obj->noptionhandler] = handle; 531 obj->optiondestroy[obj->noptionhandler] = destroy; 532 obj->optionctx[obj->noptionhandler++] = ctx; 533 PetscFunctionReturn(PETSC_SUCCESS); 534 } 535 536 /*@C 537 PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object 538 539 Not Collective 540 541 Input Parameters: 542 + obj - the PETSc object 543 - PetscOptionsObject - the options context 544 545 Level: developer 546 547 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`, 548 `PetscObject` 549 @*/ 550 PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject) 551 { 552 PetscFunctionBegin; 553 PetscValidHeader(obj, 1); 554 for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i])); 555 PetscFunctionReturn(PETSC_SUCCESS); 556 } 557 558 /*@C 559 PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object 560 561 Not Collective 562 563 Input Parameter: 564 . obj - the PETSc object 565 566 Level: developer 567 568 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`, 569 `PetscObject` 570 @*/ 571 PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj) 572 { 573 PetscFunctionBegin; 574 PetscValidHeader(obj, 1); 575 for (PetscInt i = 0; i < obj->noptionhandler; i++) { 576 if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i])); 577 } 578 obj->noptionhandler = 0; 579 PetscFunctionReturn(PETSC_SUCCESS); 580 } 581 582 /*@C 583 PetscObjectReference - Indicates to any `PetscObject` that it is being 584 referenced by another `PetscObject`. This increases the reference 585 count for that object by one. 586 587 Logically Collective 588 589 Input Parameter: 590 . obj - the PETSc object. This must be cast with (`PetscObject`), for example, 591 `PetscObjectReference`((`PetscObject`)mat); 592 593 Level: advanced 594 595 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject` 596 @*/ 597 PetscErrorCode PetscObjectReference(PetscObject obj) 598 { 599 PetscFunctionBegin; 600 if (!obj) PetscFunctionReturn(PETSC_SUCCESS); 601 PetscValidHeader(obj, 1); 602 obj->refct++; 603 PetscFunctionReturn(PETSC_SUCCESS); 604 } 605 606 /*@C 607 PetscObjectGetReference - Gets the current reference count for 608 any PETSc object. 609 610 Not Collective 611 612 Input Parameter: 613 . obj - the PETSc object; this must be cast with (`PetscObject`), for example, 614 `PetscObjectGetReference`((`PetscObject`)mat,&cnt); 615 616 Output Parameter: 617 . cnt - the reference count 618 619 Level: advanced 620 621 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject` 622 @*/ 623 PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt) 624 { 625 PetscFunctionBegin; 626 PetscValidHeader(obj, 1); 627 PetscValidIntPointer(cnt, 2); 628 *cnt = obj->refct; 629 PetscFunctionReturn(PETSC_SUCCESS); 630 } 631 632 /*@C 633 PetscObjectDereference - Indicates to any `PetscObject` that it is being 634 referenced by one less `PetscObject`. This decreases the reference 635 count for that object by one. 636 637 Collective on obj if reference reaches 0 otherwise Logically Collective 638 639 Input Parameter: 640 . obj - the PETSc object; this must be cast with (`PetscObject`), for example, 641 `PetscObjectDereference`((`PetscObject`)mat); 642 643 Level: advanced 644 645 Note: 646 `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not. 647 648 .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject` 649 @*/ 650 PetscErrorCode PetscObjectDereference(PetscObject obj) 651 { 652 PetscFunctionBegin; 653 if (!obj) PetscFunctionReturn(PETSC_SUCCESS); 654 PetscValidHeader(obj, 1); 655 if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj)); 656 else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine"); 657 PetscFunctionReturn(PETSC_SUCCESS); 658 } 659 660 /* 661 The following routines are the versions private to the PETSc object 662 data structures. 663 */ 664 PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[]) 665 { 666 PetscFunctionBegin; 667 PetscValidHeader(obj, 1); 668 PetscCall(PetscObjectListRemoveReference(&obj->olist, name)); 669 PetscFunctionReturn(PETSC_SUCCESS); 670 } 671 672 PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj, const char name[], PetscObject ptr) 673 { 674 PetscFunctionBegin; 675 if (ptr) { 676 char *tname; 677 PetscBool skipreference; 678 679 PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference)); 680 if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it"); 681 } 682 PetscCall(PetscObjectListAdd(&obj->olist, name, ptr)); 683 PetscFunctionReturn(PETSC_SUCCESS); 684 } 685 686 PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj, const char name[], PetscObject *ptr) 687 { 688 PetscFunctionBegin; 689 PetscValidHeader(obj, 1); 690 PetscCall(PetscObjectListFind(obj->olist, name, ptr)); 691 PetscFunctionReturn(PETSC_SUCCESS); 692 } 693 694 PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj, const char name[], void (*ptr)(void)) 695 { 696 PetscFunctionBegin; 697 PetscValidHeader(obj, 1); 698 PetscCall(PetscFunctionListAdd(&obj->qlist, name, ptr)); 699 PetscFunctionReturn(PETSC_SUCCESS); 700 } 701 702 PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj, const char name[], void (**ptr)(void)) 703 { 704 PetscFunctionBegin; 705 PetscValidHeader(obj, 1); 706 PetscCall(PetscFunctionListFind(obj->qlist, name, ptr)); 707 PetscFunctionReturn(PETSC_SUCCESS); 708 } 709 710 /*@C 711 PetscObjectCompose - Associates another PETSc object with a given PETSc object. 712 713 Not Collective 714 715 Input Parameters: 716 + obj - the PETSc object; this must be cast with (`PetscObject`), for example, 717 `PetscObjectCompose`((`PetscObject`)mat,...); 718 . name - name associated with the child object 719 - ptr - the other PETSc object to associate with the PETSc object; this must also be 720 cast with (`PetscObject`) 721 722 Level: advanced 723 724 Notes: 725 The second objects reference count is automatically increased by one when it is 726 composed. 727 728 Replaces any previous object that had the same name. 729 730 If ptr is null and name has previously been composed using an object, then that 731 entry is removed from the obj. 732 733 `PetscObjectCompose()` can be used with any PETSc object (such as 734 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 735 736 `PetscContainerCreate()` can be used to create an object from a 737 user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()` 738 739 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`, 740 `PetscContainerSetPointer()`, `PetscObject` 741 @*/ 742 PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr) 743 { 744 PetscFunctionBegin; 745 PetscValidHeader(obj, 1); 746 PetscValidCharPointer(name, 2); 747 if (ptr) PetscValidHeader(ptr, 3); 748 PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself"); 749 PetscCall((*obj->bops->compose)(obj, name, ptr)); 750 PetscFunctionReturn(PETSC_SUCCESS); 751 } 752 753 /*@C 754 PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()` 755 756 Not Collective 757 758 Input Parameters: 759 + obj - the PETSc object 760 Thus must be cast with a (`PetscObject`), for example, 761 `PetscObjectCompose`((`PetscObject`)mat,...); 762 . name - name associated with child object 763 - ptr - the other PETSc object associated with the PETSc object, this must be 764 cast with (`PetscObject`*) 765 766 Level: advanced 767 768 Note: 769 The reference count of neither object is increased in this call 770 771 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer` 772 `PetscContainerGetPointer()`, `PetscObject` 773 @*/ 774 PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr) 775 { 776 PetscFunctionBegin; 777 PetscValidHeader(obj, 1); 778 PetscValidCharPointer(name, 2); 779 PetscValidPointer(ptr, 3); 780 PetscCall((*obj->bops->query)(obj, name, ptr)); 781 PetscFunctionReturn(PETSC_SUCCESS); 782 } 783 784 /*MC 785 PetscObjectComposeFunction - Associates a function with a given PETSc object. 786 787 Synopsis: 788 #include <petscsys.h> 789 PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void)) 790 791 Logically Collective 792 793 Input Parameters: 794 + obj - the PETSc object; this must be cast with a (`PetscObject`), for example, 795 `PetscObjectCompose`((`PetscObject`)mat,...); 796 . name - name associated with the child function 797 - fptr - function pointer 798 799 Level: advanced 800 801 Notes: 802 When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()` 803 can be used to call the function directly with error checking. 804 805 To remove a registered routine, pass in `NULL` for `fptr`. 806 807 `PetscObjectComposeFunction()` can be used with any PETSc object (such as 808 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 809 810 `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table. 811 812 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`, 813 `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject` 814 M*/ 815 816 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void)) 817 { 818 PetscFunctionBegin; 819 PetscValidHeader(obj, 1); 820 PetscValidCharPointer(name, 2); 821 PetscCall((*obj->bops->composefunction)(obj, name, fptr)); 822 PetscFunctionReturn(PETSC_SUCCESS); 823 } 824 825 /*MC 826 PetscObjectQueryFunction - Gets a function associated with a given object. 827 828 Synopsis: 829 #include <petscsys.h> 830 PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void)) 831 832 Logically Collective 833 834 Input Parameters: 835 + obj - the PETSc object; this must be cast with (`PetscObject`), for example, 836 `PetscObjectQueryFunction`((`PetscObject`)ksp,...); 837 - name - name associated with the child function 838 839 Output Parameter: 840 . fptr - function pointer 841 842 Level: advanced 843 844 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject` 845 M*/ 846 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void)) 847 { 848 PetscFunctionBegin; 849 PetscValidHeader(obj, 1); 850 PetscValidCharPointer(name, 2); 851 PetscCall((*obj->bops->queryfunction)(obj, name, ptr)); 852 PetscFunctionReturn(PETSC_SUCCESS); 853 } 854 855 struct _p_PetscContainer { 856 PETSCHEADER(int); 857 void *ptr; 858 PetscErrorCode (*userdestroy)(void *); 859 }; 860 861 /*@C 862 PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data 863 provided with `PetscContainerSetPointer()` 864 865 Logically Collective on the `PetscContainer` containing the user data 866 867 Input Parameter: 868 . ctx - pointer to user-provided data 869 870 Level: advanced 871 872 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy(`), `PetscObject` 873 @*/ 874 PetscErrorCode PetscContainerUserDestroyDefault(void *ctx) 875 { 876 PetscFunctionBegin; 877 PetscCall(PetscFree(ctx)); 878 PetscFunctionReturn(PETSC_SUCCESS); 879 } 880 881 /*@C 882 PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()` 883 884 Not Collective 885 886 Input Parameter: 887 . obj - the object created with `PetscContainerCreate()` 888 889 Output Parameter: 890 . ptr - the pointer value 891 892 Level: advanced 893 894 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`, 895 `PetscContainerSetPointer()` 896 @*/ 897 PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr) 898 { 899 PetscFunctionBegin; 900 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 901 PetscValidPointer(ptr, 2); 902 *ptr = obj->ptr; 903 PetscFunctionReturn(PETSC_SUCCESS); 904 } 905 906 /*@C 907 PetscContainerSetPointer - Sets the pointer value contained in the container. 908 909 Logically Collective 910 911 Input Parameters: 912 + obj - the object created with `PetscContainerCreate()` 913 - ptr - the pointer value 914 915 Level: advanced 916 917 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`, 918 `PetscContainerGetPointer()` 919 @*/ 920 PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr) 921 { 922 PetscFunctionBegin; 923 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 924 if (ptr) PetscValidPointer(ptr, 2); 925 obj->ptr = ptr; 926 PetscFunctionReturn(PETSC_SUCCESS); 927 } 928 929 /*@C 930 PetscContainerDestroy - Destroys a PETSc container object. 931 932 Collective 933 934 Input Parameter: 935 . obj - an object that was created with `PetscContainerCreate()` 936 937 Level: advanced 938 939 Note: 940 If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()` 941 then that function is called to destroy the data. 942 943 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`, `PetscObject` 944 @*/ 945 PetscErrorCode PetscContainerDestroy(PetscContainer *obj) 946 { 947 PetscFunctionBegin; 948 if (!*obj) PetscFunctionReturn(PETSC_SUCCESS); 949 PetscValidHeaderSpecific(*obj, PETSC_CONTAINER_CLASSID, 1); 950 if (--((PetscObject)(*obj))->refct > 0) { 951 *obj = NULL; 952 PetscFunctionReturn(PETSC_SUCCESS); 953 } 954 if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr)); 955 PetscCall(PetscHeaderDestroy(obj)); 956 PetscFunctionReturn(PETSC_SUCCESS); 957 } 958 959 /*@C 960 PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()` 961 962 Logically Collective 963 964 Input Parameters: 965 + obj - an object that was created with `PetscContainerCreate()` 966 - des - name of the user destroy function 967 968 Level: advanced 969 970 Note: 971 Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation. 972 973 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject` 974 @*/ 975 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *)) 976 { 977 PetscFunctionBegin; 978 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 979 obj->userdestroy = des; 980 PetscFunctionReturn(PETSC_SUCCESS); 981 } 982 983 PetscClassId PETSC_CONTAINER_CLASSID; 984 985 /*@C 986 PetscContainerCreate - Creates a PETSc object that has room to hold 987 a single pointer. This allows one to attach any type of data (accessible 988 through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`. 989 The data item itself is attached by a call to `PetscContainerSetPointer()`. 990 991 Collective 992 993 Input Parameter: 994 . comm - MPI communicator that shares the object 995 996 Output Parameter: 997 . container - the container created 998 999 Level: advanced 1000 1001 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 1002 `PetscContainerSetUserDestroy()`, `PetscObject` 1003 @*/ 1004 PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container) 1005 { 1006 PetscFunctionBegin; 1007 PetscValidPointer(container, 2); 1008 PetscCall(PetscSysInitializePackage()); 1009 PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL)); 1010 PetscFunctionReturn(PETSC_SUCCESS); 1011 } 1012 1013 /*@ 1014 PetscObjectSetFromOptions - Sets generic parameters from user options. 1015 1016 Collective 1017 1018 Input Parameter: 1019 . obj - the `PetscObject` 1020 1021 Level: beginner 1022 1023 Note: 1024 We have no generic options at present, so this does nothing 1025 1026 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject` 1027 @*/ 1028 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj) 1029 { 1030 PetscFunctionBegin; 1031 PetscValidHeader(obj, 1); 1032 PetscFunctionReturn(PETSC_SUCCESS); 1033 } 1034 1035 /*@ 1036 PetscObjectSetUp - Sets up the internal data structures for the later use. 1037 1038 Collective 1039 1040 Input Parameter: 1041 . obj - the `PetscObject` 1042 1043 Level: advanced 1044 1045 Note: 1046 This does nothing at present. 1047 1048 .seealso: `PetscObjectDestroy()`, `PetscObject` 1049 @*/ 1050 PetscErrorCode PetscObjectSetUp(PetscObject obj) 1051 { 1052 PetscFunctionBegin; 1053 PetscValidHeader(obj, 1); 1054 PetscFunctionReturn(PETSC_SUCCESS); 1055 } 1056