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