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