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