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