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