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