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