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, j, k = 0; 347 PetscObject h; 348 349 PetscFunctionBegin; 350 if (PetscObjectsCounts) { 351 PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n")); 352 PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n")); 353 for (i = 0; i < PetscObjectsMaxCounts; i++) { 354 if ((h = PetscObjects[i])) { 355 PetscCall(PetscObjectName(h)); 356 { 357 PetscStack *stack = NULL; 358 char *create, *rclass; 359 360 /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */ 361 PetscCall(PetscMallocGetStack(h, &stack)); 362 if (stack) { 363 k = stack->currentsize - 2; 364 if (!all) { 365 k = 0; 366 while (!stack->petscroutine[k]) k++; 367 PetscCall(PetscStrstr(stack->function[k], "Create", &create)); 368 if (!create) PetscCall(PetscStrstr(stack->function[k], "Get", &create)); 369 PetscCall(PetscStrstr(stack->function[k], h->class_name, &rclass)); 370 if (!create) continue; 371 if (!rclass) continue; 372 } 373 } 374 375 PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name)); 376 377 PetscCall(PetscMallocGetStack(h, &stack)); 378 if (stack) { 379 for (j = k; j >= 0; j--) fprintf(fd, " [%d] %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]); 380 } 381 } 382 } 383 } 384 } 385 PetscFunctionReturn(0); 386 } 387 388 /*@C 389 PetscObjectsView - Prints the currently existing objects. 390 391 Logically Collective 392 393 Input Parameter: 394 . viewer - must be an `PETSCVIEWERASCII` viewer 395 396 Level: advanced 397 398 @*/ 399 PetscErrorCode PetscObjectsView(PetscViewer viewer) 400 { 401 PetscBool isascii; 402 FILE *fd; 403 404 PetscFunctionBegin; 405 if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD; 406 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 407 PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer"); 408 PetscCall(PetscViewerASCIIGetPointer(viewer, &fd)); 409 PetscCall(PetscObjectsDump(fd, PETSC_TRUE)); 410 PetscFunctionReturn(0); 411 } 412 413 /*@C 414 PetscObjectsGetObject - Get a pointer to a named object 415 416 Not collective 417 418 Input Parameter: 419 . name - the name of an object 420 421 Output Parameters: 422 + obj - the object or null if there is no object 423 - classname - the name of the class 424 425 Level: advanced 426 427 @*/ 428 PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname) 429 { 430 PetscInt i; 431 PetscObject h; 432 PetscBool flg; 433 434 PetscFunctionBegin; 435 PetscValidCharPointer(name, 1); 436 PetscValidPointer(obj, 2); 437 *obj = NULL; 438 for (i = 0; i < PetscObjectsMaxCounts; i++) { 439 if ((h = PetscObjects[i])) { 440 PetscCall(PetscObjectName(h)); 441 PetscCall(PetscStrcmp(h->name, name, &flg)); 442 if (flg) { 443 *obj = h; 444 if (classname) *classname = h->class_name; 445 PetscFunctionReturn(0); 446 } 447 } 448 } 449 PetscFunctionReturn(0); 450 } 451 #endif 452 453 /*@ 454 PetscObjectSetPrintedOptions - indicate to an object that it should behave as if it has already printed the help for its options so it will not display the help message 455 456 Input Parameters: 457 . obj - the `PetscObject` 458 459 Level: developer 460 461 Developer Note: 462 This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by 463 `PCBJACOBI` from all printing the same help messages to the screen 464 465 .seealso: `PetscOptionsInsert()` 466 @*/ 467 PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj) 468 { 469 PetscFunctionBegin; 470 PetscValidPointer(obj, 1); 471 obj->optionsprinted = PETSC_TRUE; 472 PetscFunctionReturn(0); 473 } 474 475 /*@ 476 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. 477 478 Input Parameters: 479 + pobj - the parent object 480 - obj - the PetscObject 481 482 Level: developer 483 484 Developer Notes: 485 This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by 486 `PCBJACOBI` from all printing the same help messages to the screen 487 488 This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap 489 490 .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()` 491 @*/ 492 PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj) 493 { 494 PetscMPIInt prank, size; 495 496 PetscFunctionBegin; 497 PetscValidHeader(pobj, 1); 498 PetscValidHeader(obj, 2); 499 PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank)); 500 PetscCallMPI(MPI_Comm_size(obj->comm, &size)); 501 if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE; 502 PetscFunctionReturn(0); 503 } 504 505 /*@C 506 PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called. 507 508 Not Collective 509 510 Input Parameters: 511 + obj - the PETSc object 512 . handle - function that checks for options 513 . destroy - function to destroy context if provided 514 - ctx - optional context for check function 515 516 Level: developer 517 518 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()` 519 @*/ 520 PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject, PetscOptionItems *, void *), PetscErrorCode (*destroy)(PetscObject, void *), void *ctx) 521 { 522 PetscFunctionBegin; 523 PetscValidHeader(obj, 1); 524 PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "To many options handlers added"); 525 obj->optionhandler[obj->noptionhandler] = handle; 526 obj->optiondestroy[obj->noptionhandler] = destroy; 527 obj->optionctx[obj->noptionhandler++] = ctx; 528 PetscFunctionReturn(0); 529 } 530 531 /*@C 532 PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object 533 534 Not Collective 535 536 Input Parameters: 537 + obj - the PETSc object 538 - PetscOptionsObject - the options context 539 540 Level: developer 541 542 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()` 543 @*/ 544 PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject) 545 { 546 PetscFunctionBegin; 547 PetscValidHeader(obj, 1); 548 for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i])); 549 PetscFunctionReturn(0); 550 } 551 552 /*@C 553 PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object 554 555 Not Collective 556 557 Input Parameter: 558 . obj - the PETSc object 559 560 Level: developer 561 562 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()` 563 @*/ 564 PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj) 565 { 566 PetscFunctionBegin; 567 PetscValidHeader(obj, 1); 568 for (PetscInt i = 0; i < obj->noptionhandler; i++) { 569 if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i])); 570 } 571 obj->noptionhandler = 0; 572 PetscFunctionReturn(0); 573 } 574 575 /*@C 576 PetscObjectReference - Indicates to any `PetscObject` that it is being 577 referenced by another `PetscObject`. This increases the reference 578 count for that object by one. 579 580 Logically Collective 581 582 Input Parameter: 583 . obj - the PETSc object. This must be cast with (`PetscObject`), for example, 584 `PetscObjectReference`((`PetscObject`)mat); 585 586 Level: advanced 587 588 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()` 589 @*/ 590 PetscErrorCode PetscObjectReference(PetscObject obj) 591 { 592 PetscFunctionBegin; 593 if (!obj) PetscFunctionReturn(0); 594 PetscValidHeader(obj, 1); 595 obj->refct++; 596 PetscFunctionReturn(0); 597 } 598 599 /*@C 600 PetscObjectGetReference - Gets the current reference count for 601 any PETSc object. 602 603 Not Collective 604 605 Input Parameter: 606 . obj - the PETSc object; this must be cast with (`PetscObject`), for example, 607 `PetscObjectGetReference`((`PetscObject`)mat,&cnt); 608 609 Output Parameter: 610 . cnt - the reference count 611 612 Level: advanced 613 614 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()` 615 @*/ 616 PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt) 617 { 618 PetscFunctionBegin; 619 PetscValidHeader(obj, 1); 620 PetscValidIntPointer(cnt, 2); 621 *cnt = obj->refct; 622 PetscFunctionReturn(0); 623 } 624 625 /*@C 626 PetscObjectDereference - Indicates to any `PetscObject` that it is being 627 referenced by one less `PetscObject`. This decreases the reference 628 count for that object by one. 629 630 Collective on obj if reference reaches 0 otherwise Logically Collective 631 632 Input Parameter: 633 . obj - the PETSc object; this must be cast with (`PetscObject`), for example, 634 `PetscObjectDereference`((`PetscObject`)mat); 635 636 Note: 637 `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not. 638 639 Level: advanced 640 641 .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()` 642 @*/ 643 PetscErrorCode PetscObjectDereference(PetscObject obj) 644 { 645 PetscFunctionBegin; 646 if (!obj) PetscFunctionReturn(0); 647 PetscValidHeader(obj, 1); 648 if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj)); 649 else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine"); 650 PetscFunctionReturn(0); 651 } 652 653 /* ----------------------------------------------------------------------- */ 654 /* 655 The following routines are the versions private to the PETSc object 656 data structures. 657 */ 658 PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[]) 659 { 660 PetscFunctionBegin; 661 PetscValidHeader(obj, 1); 662 PetscCall(PetscObjectListRemoveReference(&obj->olist, name)); 663 PetscFunctionReturn(0); 664 } 665 666 PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj, const char name[], PetscObject ptr) 667 { 668 PetscFunctionBegin; 669 if (ptr) { 670 char *tname; 671 PetscBool skipreference; 672 673 PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference)); 674 if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it"); 675 } 676 PetscCall(PetscObjectListAdd(&obj->olist, name, ptr)); 677 PetscFunctionReturn(0); 678 } 679 680 PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj, const char name[], PetscObject *ptr) 681 { 682 PetscFunctionBegin; 683 PetscValidHeader(obj, 1); 684 PetscCall(PetscObjectListFind(obj->olist, name, ptr)); 685 PetscFunctionReturn(0); 686 } 687 688 PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj, const char name[], void (*ptr)(void)) 689 { 690 PetscFunctionBegin; 691 PetscValidHeader(obj, 1); 692 PetscCall(PetscFunctionListAdd(&obj->qlist, name, ptr)); 693 PetscFunctionReturn(0); 694 } 695 696 PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj, const char name[], void (**ptr)(void)) 697 { 698 PetscFunctionBegin; 699 PetscValidHeader(obj, 1); 700 PetscCall(PetscFunctionListFind(obj->qlist, name, ptr)); 701 PetscFunctionReturn(0); 702 } 703 704 /*@C 705 PetscObjectCompose - Associates another PETSc object with a given PETSc object. 706 707 Not Collective 708 709 Input Parameters: 710 + obj - the PETSc object; this must be cast with (`PetscObject`), for example, 711 `PetscObjectCompose`((`PetscObject`)mat,...); 712 . name - name associated with the child object 713 - ptr - the other PETSc object to associate with the PETSc object; this must also be 714 cast with (`PetscObject`) 715 716 Level: advanced 717 718 Notes: 719 The second objects reference count is automatically increased by one when it is 720 composed. 721 722 Replaces any previous object that had the same name. 723 724 If ptr is null and name has previously been composed using an object, then that 725 entry is removed from the obj. 726 727 `PetscObjectCompose()` can be used with any PETSc object (such as 728 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 729 730 `PetscContainerCreate()` can be used to create an object from a 731 user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()` 732 733 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`, 734 `PetscContainerSetPointer()` 735 @*/ 736 PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr) 737 { 738 PetscFunctionBegin; 739 PetscValidHeader(obj, 1); 740 PetscValidCharPointer(name, 2); 741 if (ptr) PetscValidHeader(ptr, 3); 742 PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself"); 743 PetscCall((*obj->bops->compose)(obj, name, ptr)); 744 PetscFunctionReturn(0); 745 } 746 747 /*@C 748 PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()` 749 750 Not Collective 751 752 Input Parameters: 753 + obj - the PETSc object 754 Thus must be cast with a (`PetscObject`), for example, 755 `PetscObjectCompose`((`PetscObject`)mat,...); 756 . name - name associated with child object 757 - ptr - the other PETSc object associated with the PETSc object, this must be 758 cast with (`PetscObject`*) 759 760 Level: advanced 761 762 Note: 763 The reference count of neither object is increased in this call 764 765 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer` 766 `PetscContainerGetPointer()` 767 @*/ 768 PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr) 769 { 770 PetscFunctionBegin; 771 PetscValidHeader(obj, 1); 772 PetscValidCharPointer(name, 2); 773 PetscValidPointer(ptr, 3); 774 PetscCall((*obj->bops->query)(obj, name, ptr)); 775 PetscFunctionReturn(0); 776 } 777 778 /*MC 779 PetscObjectComposeFunction - Associates a function with a given PETSc object. 780 781 Synopsis: 782 #include <petscsys.h> 783 PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void)) 784 785 Logically Collective 786 787 Input Parameters: 788 + obj - the PETSc object; this must be cast with a (`PetscObject`), for example, 789 `PetscObjectCompose`((`PetscObject`)mat,...); 790 . name - name associated with the child function 791 . fname - name of the function 792 - fptr - function pointer 793 794 Level: advanced 795 796 Notes: 797 When the first argument of the function is the object within which it has been composed then `PetscTryMethod()` and `PetscUseMethod()` 798 can be used to call the function directly with error checking. 799 800 To remove a registered routine, pass in NULL for fptr(). 801 802 PetscObjectComposeFunction() can be used with any PETSc object (such as 803 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 804 805 `PetscCallMethod()` is used to call a function that is stored in the objects obj->ops table. 806 807 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`, 808 `PetscCallMethod()` 809 M*/ 810 811 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void)) 812 { 813 PetscFunctionBegin; 814 PetscValidHeader(obj, 1); 815 PetscValidCharPointer(name, 2); 816 PetscCall((*obj->bops->composefunction)(obj, name, fptr)); 817 PetscFunctionReturn(0); 818 } 819 820 /*MC 821 PetscObjectQueryFunction - Gets a function associated with a given object. 822 823 Synopsis: 824 #include <petscsys.h> 825 PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void)) 826 827 Logically Collective 828 829 Input Parameters: 830 + obj - the PETSc object; this must be cast with (`PetscObject`), for example, 831 `PetscObjectQueryFunction`((`PetscObject`)ksp,...); 832 - name - name associated with the child function 833 834 Output Parameter: 835 . fptr - function pointer 836 837 Level: advanced 838 839 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()` 840 M*/ 841 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void)) 842 { 843 PetscFunctionBegin; 844 PetscValidHeader(obj, 1); 845 PetscValidCharPointer(name, 2); 846 PetscCall((*obj->bops->queryfunction)(obj, name, ptr)); 847 PetscFunctionReturn(0); 848 } 849 850 struct _p_PetscContainer { 851 PETSCHEADER(int); 852 void *ptr; 853 PetscErrorCode (*userdestroy)(void *); 854 }; 855 856 /*@C 857 PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data 858 provided with `PetscContainerSetPointer()` 859 860 Logically Collective on the `PetscContainer` containing the user data 861 862 Input Parameter: 863 . ctx - pointer to user-provided data 864 865 Level: advanced 866 867 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()` 868 @*/ 869 PetscErrorCode PetscContainerUserDestroyDefault(void *ctx) 870 { 871 PetscFunctionBegin; 872 PetscCall(PetscFree(ctx)); 873 PetscFunctionReturn(0); 874 } 875 876 /*@C 877 PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()` 878 879 Not Collective 880 881 Input Parameter: 882 . obj - the object created with `PetscContainerCreate()` 883 884 Output Parameter: 885 . ptr - the pointer value 886 887 Level: advanced 888 889 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, 890 `PetscContainerSetPointer()` 891 @*/ 892 PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr) 893 { 894 PetscFunctionBegin; 895 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 896 PetscValidPointer(ptr, 2); 897 *ptr = obj->ptr; 898 PetscFunctionReturn(0); 899 } 900 901 /*@C 902 PetscContainerSetPointer - Sets the pointer value contained in the container. 903 904 Logically Collective 905 906 Input Parameters: 907 + obj - the object created with `PetscContainerCreate()` 908 - ptr - the pointer value 909 910 Level: advanced 911 912 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 913 `PetscContainerGetPointer()` 914 @*/ 915 PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr) 916 { 917 PetscFunctionBegin; 918 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 919 if (ptr) PetscValidPointer(ptr, 2); 920 obj->ptr = ptr; 921 PetscFunctionReturn(0); 922 } 923 924 /*@C 925 PetscContainerDestroy - Destroys a PETSc container object. 926 927 Collective 928 929 Input Parameter: 930 . obj - an object that was created with `PetscContainerCreate()` 931 932 Level: advanced 933 934 Note: 935 If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()` 936 then that function is called to destroy the data. 937 938 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()` 939 @*/ 940 PetscErrorCode PetscContainerDestroy(PetscContainer *obj) 941 { 942 PetscFunctionBegin; 943 if (!*obj) PetscFunctionReturn(0); 944 PetscValidHeaderSpecific(*obj, PETSC_CONTAINER_CLASSID, 1); 945 if (--((PetscObject)(*obj))->refct > 0) { 946 *obj = NULL; 947 PetscFunctionReturn(0); 948 } 949 if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr)); 950 PetscCall(PetscHeaderDestroy(obj)); 951 PetscFunctionReturn(0); 952 } 953 954 /*@C 955 PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()` 956 957 Logically Collective 958 959 Input Parameters: 960 + obj - an object that was created with `PetscContainerCreate()` 961 - des - name of the user destroy function 962 963 Note: 964 Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation. 965 966 Level: advanced 967 968 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()` 969 @*/ 970 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *)) 971 { 972 PetscFunctionBegin; 973 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 974 obj->userdestroy = des; 975 PetscFunctionReturn(0); 976 } 977 978 PetscClassId PETSC_CONTAINER_CLASSID; 979 980 /*@C 981 PetscContainerCreate - Creates a PETSc object that has room to hold 982 a single pointer. This allows one to attach any type of data (accessible 983 through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`. 984 The data item itself is attached by a call to `PetscContainerSetPointer()`. 985 986 Collective 987 988 Input Parameters: 989 . comm - MPI communicator that shares the object 990 991 Output Parameters: 992 . container - the container created 993 994 Level: advanced 995 996 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 997 `PetscContainerSetUserDestroy()` 998 @*/ 999 PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container) 1000 { 1001 PetscFunctionBegin; 1002 PetscValidPointer(container, 2); 1003 PetscCall(PetscSysInitializePackage()); 1004 PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL)); 1005 PetscFunctionReturn(0); 1006 } 1007 1008 /*@ 1009 PetscObjectSetFromOptions - Sets generic parameters from user options. 1010 1011 Collective 1012 1013 Input Parameter: 1014 . obj - the `PetscObject` 1015 1016 Note: 1017 We have no generic options at present, so this does nothing 1018 1019 Level: beginner 1020 1021 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()` 1022 @*/ 1023 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj) 1024 { 1025 PetscFunctionBegin; 1026 PetscValidHeader(obj, 1); 1027 PetscFunctionReturn(0); 1028 } 1029 1030 /*@ 1031 PetscObjectSetUp - Sets up the internal data structures for the later use. 1032 1033 Collective 1034 1035 Input Parameters: 1036 . obj - the `PetscObject` 1037 1038 Note: 1039 This does nothing at present. 1040 1041 Level: advanced 1042 1043 .seealso: `PetscObjectDestroy()` 1044 @*/ 1045 PetscErrorCode PetscObjectSetUp(PetscObject obj) 1046 { 1047 PetscFunctionBegin; 1048 PetscValidHeader(obj, 1); 1049 PetscFunctionReturn(0); 1050 } 1051