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