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