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