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 on src 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 on viewer 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 on obj 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 on obj 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 . fname - name of the function 802 - fptr - function pointer 803 804 Level: advanced 805 806 Notes: 807 When the first argument of the function is the object within which it has been composed then `PetscTryMethod()` and `PetscUseMethod()` 808 can be used to call the function directly with error checking. 809 810 To remove a registered routine, pass in NULL for fptr(). 811 812 PetscObjectComposeFunction() can be used with any PETSc object (such as 813 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 814 815 `PetscCallMethod()` is used to call a function that is stored in the objects obj->ops table. 816 817 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`, 818 `PetscCallMethod()` 819 M*/ 820 821 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void)) 822 { 823 PetscFunctionBegin; 824 PetscValidHeader(obj, 1); 825 PetscValidCharPointer(name, 2); 826 PetscCall((*obj->bops->composefunction)(obj, name, fptr)); 827 PetscFunctionReturn(0); 828 } 829 830 /*MC 831 PetscObjectQueryFunction - Gets a function associated with a given object. 832 833 Synopsis: 834 #include <petscsys.h> 835 PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void)) 836 837 Logically Collective on obj 838 839 Input Parameters: 840 + obj - the PETSc object; this must be cast with (`PetscObject`), for example, 841 `PetscObjectQueryFunction`((`PetscObject`)ksp,...); 842 - name - name associated with the child function 843 844 Output Parameter: 845 . fptr - function pointer 846 847 Level: advanced 848 849 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()` 850 M*/ 851 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void)) 852 { 853 PetscFunctionBegin; 854 PetscValidHeader(obj, 1); 855 PetscValidCharPointer(name, 2); 856 PetscCall((*obj->bops->queryfunction)(obj, name, ptr)); 857 PetscFunctionReturn(0); 858 } 859 860 struct _p_PetscContainer { 861 PETSCHEADER(int); 862 void *ptr; 863 PetscErrorCode (*userdestroy)(void *); 864 }; 865 866 /*@C 867 PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data 868 provided with `PetscContainerSetPointer()` 869 870 Logically Collective on the `PetscContainer` containing the user data 871 872 Input Parameter: 873 . ctx - pointer to user-provided data 874 875 Level: advanced 876 877 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()` 878 @*/ 879 PetscErrorCode PetscContainerUserDestroyDefault(void *ctx) 880 { 881 PetscFunctionBegin; 882 PetscCall(PetscFree(ctx)); 883 PetscFunctionReturn(0); 884 } 885 886 /*@C 887 PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()` 888 889 Not Collective 890 891 Input Parameter: 892 . obj - the object created with `PetscContainerCreate()` 893 894 Output Parameter: 895 . ptr - the pointer value 896 897 Level: advanced 898 899 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, 900 `PetscContainerSetPointer()` 901 @*/ 902 PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr) 903 { 904 PetscFunctionBegin; 905 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 906 PetscValidPointer(ptr, 2); 907 *ptr = obj->ptr; 908 PetscFunctionReturn(0); 909 } 910 911 /*@C 912 PetscContainerSetPointer - Sets the pointer value contained in the container. 913 914 Logically Collective on obj 915 916 Input Parameters: 917 + obj - the object created with `PetscContainerCreate()` 918 - ptr - the pointer value 919 920 Level: advanced 921 922 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 923 `PetscContainerGetPointer()` 924 @*/ 925 PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr) 926 { 927 PetscFunctionBegin; 928 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 929 if (ptr) PetscValidPointer(ptr, 2); 930 obj->ptr = ptr; 931 PetscFunctionReturn(0); 932 } 933 934 /*@C 935 PetscContainerDestroy - Destroys a PETSc container object. 936 937 Collective on obj 938 939 Input Parameter: 940 . obj - an object that was created with `PetscContainerCreate()` 941 942 Level: advanced 943 944 Note: 945 If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()` 946 then that function is called to destroy the data. 947 948 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()` 949 @*/ 950 PetscErrorCode PetscContainerDestroy(PetscContainer *obj) 951 { 952 PetscFunctionBegin; 953 if (!*obj) PetscFunctionReturn(0); 954 PetscValidHeaderSpecific(*obj, PETSC_CONTAINER_CLASSID, 1); 955 if (--((PetscObject)(*obj))->refct > 0) { 956 *obj = NULL; 957 PetscFunctionReturn(0); 958 } 959 if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr)); 960 PetscCall(PetscHeaderDestroy(obj)); 961 PetscFunctionReturn(0); 962 } 963 964 /*@C 965 PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()` 966 967 Logically Collective on obj 968 969 Input Parameters: 970 + obj - an object that was created with `PetscContainerCreate()` 971 - des - name of the user destroy function 972 973 Note: 974 Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation. 975 976 Level: advanced 977 978 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()` 979 @*/ 980 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *)) 981 { 982 PetscFunctionBegin; 983 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 984 obj->userdestroy = des; 985 PetscFunctionReturn(0); 986 } 987 988 PetscClassId PETSC_CONTAINER_CLASSID; 989 990 /*@C 991 PetscContainerCreate - Creates a PETSc object that has room to hold 992 a single pointer. This allows one to attach any type of data (accessible 993 through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`. 994 The data item itself is attached by a call to `PetscContainerSetPointer()`. 995 996 Collective 997 998 Input Parameters: 999 . comm - MPI communicator that shares the object 1000 1001 Output Parameters: 1002 . container - the container created 1003 1004 Level: advanced 1005 1006 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 1007 `PetscContainerSetUserDestroy()` 1008 @*/ 1009 PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container) 1010 { 1011 PetscFunctionBegin; 1012 PetscValidPointer(container, 2); 1013 PetscCall(PetscSysInitializePackage()); 1014 PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL)); 1015 PetscFunctionReturn(0); 1016 } 1017 1018 /*@ 1019 PetscObjectSetFromOptions - Sets generic parameters from user options. 1020 1021 Collective on obj 1022 1023 Input Parameter: 1024 . obj - the `PetscObject` 1025 1026 Note: 1027 We have no generic options at present, so this does nothing 1028 1029 Level: beginner 1030 1031 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()` 1032 @*/ 1033 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj) 1034 { 1035 PetscFunctionBegin; 1036 PetscValidHeader(obj, 1); 1037 PetscFunctionReturn(0); 1038 } 1039 1040 /*@ 1041 PetscObjectSetUp - Sets up the internal data structures for the later use. 1042 1043 Collective on obj 1044 1045 Input Parameters: 1046 . obj - the `PetscObject` 1047 1048 Note: 1049 This does nothing at present. 1050 1051 Level: advanced 1052 1053 .seealso: `PetscObjectDestroy()` 1054 @*/ 1055 PetscErrorCode PetscObjectSetUp(PetscObject obj) 1056 { 1057 PetscFunctionBegin; 1058 PetscValidHeader(obj, 1); 1059 PetscFunctionReturn(0); 1060 } 1061