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