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