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 /*@ 204 PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object 205 206 Logically Collective 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 /*@ 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 /*@ 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, const 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 #else 451 PetscErrorCode PetscObjectsView(PetscViewer viewer) 452 { 453 PetscFunctionReturn(PETSC_SUCCESS); 454 } 455 456 PetscErrorCode PetscObjectsGetObject(const char name[], PetscObject *obj, const char *classname[]) 457 { 458 PetscFunctionReturn(PETSC_SUCCESS); 459 } 460 #endif 461 462 /*@ 463 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 464 465 Input Parameter: 466 . obj - the `PetscObject` 467 468 Level: developer 469 470 Developer Notes: 471 This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by 472 `PCBJACOBI` from all printing the same help messages to the screen 473 474 .seealso: `PetscOptionsInsert()`, `PetscObject` 475 @*/ 476 PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj) 477 { 478 PetscFunctionBegin; 479 PetscAssertPointer(obj, 1); 480 obj->optionsprinted = PETSC_TRUE; 481 PetscFunctionReturn(PETSC_SUCCESS); 482 } 483 484 /*@ 485 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. 486 487 Input Parameters: 488 + pobj - the parent object 489 - obj - the `PetscObject` 490 491 Level: developer 492 493 Developer Notes: 494 This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by 495 `PCBJACOBI` from all printing the same help messages to the screen 496 497 This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap 498 499 .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`, `PetscObject` 500 @*/ 501 PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj) 502 { 503 PetscMPIInt prank, size; 504 505 PetscFunctionBegin; 506 PetscValidHeader(pobj, 1); 507 PetscValidHeader(obj, 2); 508 PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank)); 509 PetscCallMPI(MPI_Comm_size(obj->comm, &size)); 510 if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE; 511 PetscFunctionReturn(PETSC_SUCCESS); 512 } 513 514 /*@C 515 PetscObjectAddOptionsHandler - Adds an additional function to check for options when `XXXSetFromOptions()` is called. 516 517 Not Collective 518 519 Input Parameters: 520 + obj - the PETSc object 521 . handle - function that checks for options 522 . destroy - function to destroy `ctx` if provided 523 - ctx - optional context for check function 524 525 Calling sequence of `handle`: 526 + obj - the PETSc object 527 . PetscOptionsObject - the `PetscOptionItems` object 528 - ctx - optional context for `handle` 529 530 Calling sequence of `destroy`: 531 + obj - the PETSc object 532 - ctx - optional context for `handle` 533 534 Level: developer 535 536 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`, 537 `PetscObject` 538 @*/ 539 PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject obj, PetscOptionItems *PetscOptionsObject, void *ctx), PetscErrorCode (*destroy)(PetscObject obj, void *ctx), void *ctx) 540 { 541 PetscFunctionBegin; 542 PetscValidHeader(obj, 1); 543 for (PetscInt i = 0; i < obj->noptionhandler; i++) { 544 PetscBool identical = (PetscBool)(obj->optionhandler[i] == handle && obj->optiondestroy[i] == destroy && obj->optionctx[i] == ctx); 545 if (identical) PetscFunctionReturn(PETSC_SUCCESS); 546 } 547 PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "Too many options handlers added"); 548 obj->optionhandler[obj->noptionhandler] = handle; 549 obj->optiondestroy[obj->noptionhandler] = destroy; 550 obj->optionctx[obj->noptionhandler++] = ctx; 551 PetscFunctionReturn(PETSC_SUCCESS); 552 } 553 554 /*@C 555 PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object 556 557 Not Collective 558 559 Input Parameters: 560 + obj - the PETSc object 561 - PetscOptionsObject - the options context 562 563 Level: developer 564 565 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`, 566 `PetscObject` 567 @*/ 568 PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject) 569 { 570 PetscFunctionBegin; 571 PetscValidHeader(obj, 1); 572 for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i])); 573 PetscFunctionReturn(PETSC_SUCCESS); 574 } 575 576 /*@ 577 PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object 578 579 Not Collective 580 581 Input Parameter: 582 . obj - the PETSc object 583 584 Level: developer 585 586 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`, 587 `PetscObject` 588 @*/ 589 PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj) 590 { 591 PetscFunctionBegin; 592 PetscValidHeader(obj, 1); 593 for (PetscInt i = 0; i < obj->noptionhandler; i++) { 594 if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i])); 595 } 596 obj->noptionhandler = 0; 597 PetscFunctionReturn(PETSC_SUCCESS); 598 } 599 600 /*@ 601 PetscObjectReference - Indicates to a `PetscObject` that it is being 602 referenced by another `PetscObject`. This increases the reference 603 count for that object by one. 604 605 Logically Collective 606 607 Input Parameter: 608 . obj - the PETSc object. This must be cast with (`PetscObject`), for example, `PetscObjectReference`((`PetscObject`)mat); 609 610 Level: advanced 611 612 Note: 613 If `obj` is `NULL` this function returns without doing anything. 614 615 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject` 616 @*/ 617 PetscErrorCode PetscObjectReference(PetscObject obj) 618 { 619 PetscFunctionBegin; 620 if (!obj) PetscFunctionReturn(PETSC_SUCCESS); 621 PetscValidHeader(obj, 1); 622 obj->refct++; 623 PetscFunctionReturn(PETSC_SUCCESS); 624 } 625 626 /*@ 627 PetscObjectGetReference - Gets the current reference count for a PETSc object. 628 629 Not Collective 630 631 Input Parameter: 632 . obj - the PETSc object; this must be cast with (`PetscObject`), for example, 633 `PetscObjectGetReference`((`PetscObject`)mat,&cnt); `obj` cannot be `NULL` 634 635 Output Parameter: 636 . cnt - the reference count 637 638 Level: advanced 639 640 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject` 641 @*/ 642 PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt) 643 { 644 PetscFunctionBegin; 645 PetscValidHeader(obj, 1); 646 PetscAssertPointer(cnt, 2); 647 *cnt = obj->refct; 648 PetscFunctionReturn(PETSC_SUCCESS); 649 } 650 651 /*@ 652 PetscObjectDereference - Indicates to any `PetscObject` that it is being 653 referenced by one less `PetscObject`. This decreases the reference 654 count for that object by one. 655 656 Collective on `obj` if reference reaches 0 otherwise Logically Collective 657 658 Input Parameter: 659 . obj - the PETSc object; this must be cast with (`PetscObject`), for example, 660 `PetscObjectDereference`((`PetscObject`)mat); 661 662 Level: advanced 663 664 Notes: 665 `PetscObjectDestroy()` sets the `obj` pointer to `NULL` after the call, this routine does not. 666 667 If `obj` is `NULL` this function returns without doing anything. 668 669 .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject` 670 @*/ 671 PetscErrorCode PetscObjectDereference(PetscObject obj) 672 { 673 PetscFunctionBegin; 674 if (!obj) PetscFunctionReturn(PETSC_SUCCESS); 675 PetscValidHeader(obj, 1); 676 if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj)); 677 else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine"); 678 PetscFunctionReturn(PETSC_SUCCESS); 679 } 680 681 /* 682 The following routines are the versions private to the PETSc object 683 data structures. 684 */ 685 PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[]) 686 { 687 PetscFunctionBegin; 688 PetscValidHeader(obj, 1); 689 PetscCall(PetscObjectListRemoveReference(&obj->olist, name)); 690 PetscFunctionReturn(PETSC_SUCCESS); 691 } 692 693 /*@ 694 PetscObjectCompose - Associates another PETSc object with a given PETSc object. 695 696 Not Collective 697 698 Input Parameters: 699 + obj - the PETSc object; this must be cast with (`PetscObject`), for example, 700 `PetscObjectCompose`((`PetscObject`)mat,...); 701 . name - name associated with the child object 702 - ptr - the other PETSc object to associate with the PETSc object; this must also be 703 cast with (`PetscObject`) 704 705 Level: advanced 706 707 Notes: 708 The second objects reference count is automatically increased by one when it is 709 composed. 710 711 Replaces any previous object that had been composed with the same name. 712 713 If `ptr` is `NULL` and `name` has previously been composed using an object, then that 714 entry is removed from `obj`. 715 716 `PetscObjectCompose()` can be used with any PETSc object (such as 717 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 718 719 `PetscContainerCreate()` can be used to create an object from a 720 user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()` 721 722 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`, 723 `PetscContainerSetPointer()`, `PetscObject` 724 @*/ 725 PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr) 726 { 727 PetscFunctionBegin; 728 PetscValidHeader(obj, 1); 729 PetscAssertPointer(name, 2); 730 if (ptr) PetscValidHeader(ptr, 3); 731 PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself"); 732 if (ptr) { 733 char *tname; 734 PetscBool skipreference; 735 736 PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference)); 737 if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it"); 738 } 739 PetscCall(PetscObjectListAdd(&obj->olist, name, ptr)); 740 PetscFunctionReturn(PETSC_SUCCESS); 741 } 742 743 /*@ 744 PetscObjectQuery - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()` 745 746 Not Collective 747 748 Input Parameters: 749 + obj - the PETSc object. It must be cast with a (`PetscObject`), for example, 750 `PetscObjectCompose`((`PetscObject`)mat,...); 751 . name - name associated with child object 752 - ptr - the other PETSc object associated with the PETSc object, this must be 753 cast with (`PetscObject`*) 754 755 Level: advanced 756 757 Note: 758 The reference count of neither object is increased in this call 759 760 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer` 761 `PetscContainerGetPointer()`, `PetscObject` 762 @*/ 763 PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr) 764 { 765 PetscFunctionBegin; 766 PetscValidHeader(obj, 1); 767 PetscAssertPointer(name, 2); 768 PetscAssertPointer(ptr, 3); 769 PetscCall(PetscObjectListFind(obj->olist, name, ptr)); 770 PetscFunctionReturn(PETSC_SUCCESS); 771 } 772 773 /*MC 774 PetscObjectComposeFunction - Associates a function with a given PETSc object. 775 776 Synopsis: 777 #include <petscsys.h> 778 PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void)) 779 780 Logically Collective 781 782 Input Parameters: 783 + obj - the PETSc object; this must be cast with a (`PetscObject`), for example, 784 `PetscObjectCompose`((`PetscObject`)mat,...); 785 . name - name associated with the child function 786 - fptr - function pointer 787 788 Level: advanced 789 790 Notes: 791 When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()` 792 can be used to call the function directly with error checking. 793 794 To remove a registered routine, pass in `NULL` for `fptr`. 795 796 `PetscObjectComposeFunction()` can be used with any PETSc object (such as 797 `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object. 798 799 `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table. 800 801 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`, 802 `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject` 803 M*/ 804 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void)) 805 { 806 PetscFunctionBegin; 807 PetscValidHeader(obj, 1); 808 PetscAssertPointer(name, 2); 809 PetscCall(PetscFunctionListAdd(&obj->qlist, name, fptr)); 810 PetscFunctionReturn(PETSC_SUCCESS); 811 } 812 813 /*MC 814 PetscObjectQueryFunction - Gets a function associated with a given object. 815 816 Synopsis: 817 #include <petscsys.h> 818 PetscErrorCode PetscObjectQueryFunction(PetscObject obj, const char name[], void (**fptr)(void)) 819 820 Logically Collective 821 822 Input Parameters: 823 + obj - the PETSc object; this must be cast with (`PetscObject`), for example, 824 `PetscObjectQueryFunction`((`PetscObject`)ksp,...); 825 - name - name associated with the child function 826 827 Output Parameter: 828 . fptr - function pointer 829 830 Level: advanced 831 832 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject` 833 M*/ 834 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**fptr)(void)) 835 { 836 PetscFunctionBegin; 837 PetscValidHeader(obj, 1); 838 PetscAssertPointer(name, 2); 839 PetscCall(PetscFunctionListFind(obj->qlist, name, fptr)); 840 PetscFunctionReturn(PETSC_SUCCESS); 841 } 842 843 struct _p_PetscContainer { 844 PETSCHEADER(int); 845 void *ptr; 846 PetscErrorCode (*userdestroy)(void *); 847 }; 848 849 /*@C 850 PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data 851 provided with `PetscContainerSetPointer()` 852 853 Logically Collective on the `PetscContainer` containing the user data, No Fortran Support 854 855 Input Parameter: 856 . ctx - pointer to user-provided data 857 858 Level: advanced 859 860 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`, `PetscObject` 861 @*/ 862 PetscErrorCode PetscContainerUserDestroyDefault(void *ctx) 863 { 864 PetscFunctionBegin; 865 PetscCall(PetscFree(ctx)); 866 PetscFunctionReturn(PETSC_SUCCESS); 867 } 868 869 /*@C 870 PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()` 871 872 Not Collective, No Fortran Support 873 874 Input Parameter: 875 . obj - the object created with `PetscContainerCreate()` 876 877 Output Parameter: 878 . ptr - the pointer value 879 880 Level: advanced 881 882 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`, 883 `PetscContainerSetPointer()` 884 @*/ 885 PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr) 886 { 887 PetscFunctionBegin; 888 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 889 PetscAssertPointer(ptr, 2); 890 *ptr = obj->ptr; 891 PetscFunctionReturn(PETSC_SUCCESS); 892 } 893 894 /*@C 895 PetscContainerSetPointer - Sets the pointer value contained in the container. 896 897 Logically Collective, No Fortran Support 898 899 Input Parameters: 900 + obj - the object created with `PetscContainerCreate()` 901 - ptr - the pointer value 902 903 Level: advanced 904 905 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`, 906 `PetscContainerGetPointer()` 907 @*/ 908 PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr) 909 { 910 PetscFunctionBegin; 911 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 912 if (ptr) PetscAssertPointer(ptr, 2); 913 obj->ptr = ptr; 914 PetscFunctionReturn(PETSC_SUCCESS); 915 } 916 917 /*@C 918 PetscContainerDestroy - Destroys a PETSc container object. 919 920 Collective, No Fortran Support 921 922 Input Parameter: 923 . obj - an object that was created with `PetscContainerCreate()` 924 925 Level: advanced 926 927 Note: 928 If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()` 929 then that function is called to destroy the data. 930 931 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`, `PetscObject` 932 @*/ 933 PetscErrorCode PetscContainerDestroy(PetscContainer *obj) 934 { 935 PetscFunctionBegin; 936 if (!*obj) PetscFunctionReturn(PETSC_SUCCESS); 937 PetscValidHeaderSpecific(*obj, PETSC_CONTAINER_CLASSID, 1); 938 if (--((PetscObject)*obj)->refct > 0) { 939 *obj = NULL; 940 PetscFunctionReturn(PETSC_SUCCESS); 941 } 942 if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr)); 943 PetscCall(PetscHeaderDestroy(obj)); 944 PetscFunctionReturn(PETSC_SUCCESS); 945 } 946 947 /*@C 948 PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()` 949 950 Logically Collective, No Fortran Support 951 952 Input Parameters: 953 + obj - an object that was created with `PetscContainerCreate()` 954 - des - name of the user destroy function 955 956 Level: advanced 957 958 Note: 959 Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation. 960 961 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject` 962 @*/ 963 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *)) 964 { 965 PetscFunctionBegin; 966 PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1); 967 obj->userdestroy = des; 968 PetscFunctionReturn(PETSC_SUCCESS); 969 } 970 971 PetscClassId PETSC_CONTAINER_CLASSID; 972 973 /*@C 974 PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer. 975 976 Collective, No Fortran Support 977 978 Input Parameter: 979 . comm - MPI communicator that shares the object 980 981 Output Parameter: 982 . container - the container created 983 984 Level: advanced 985 986 Notes: 987 This allows one to attach any type of data (accessible through a pointer) with the 988 `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a 989 call to `PetscContainerSetPointer()`. 990 991 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`, 992 `PetscContainerSetUserDestroy()`, `PetscObject` 993 @*/ 994 PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container) 995 { 996 PetscFunctionBegin; 997 PetscAssertPointer(container, 2); 998 PetscCall(PetscSysInitializePackage()); 999 PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL)); 1000 PetscFunctionReturn(PETSC_SUCCESS); 1001 } 1002 1003 /*@ 1004 PetscObjectSetFromOptions - Sets generic parameters from user options. 1005 1006 Collective 1007 1008 Input Parameter: 1009 . obj - the `PetscObject` 1010 1011 Level: beginner 1012 1013 Note: 1014 We have no generic options at present, so this does nothing 1015 1016 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject` 1017 @*/ 1018 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj) 1019 { 1020 PetscFunctionBegin; 1021 PetscValidHeader(obj, 1); 1022 PetscFunctionReturn(PETSC_SUCCESS); 1023 } 1024 1025 /*@ 1026 PetscObjectSetUp - Sets up the internal data structures for later use of the object 1027 1028 Collective 1029 1030 Input Parameter: 1031 . obj - the `PetscObject` 1032 1033 Level: advanced 1034 1035 Note: 1036 This does nothing at present. 1037 1038 .seealso: `PetscObjectDestroy()`, `PetscObject` 1039 @*/ 1040 PetscErrorCode PetscObjectSetUp(PetscObject obj) 1041 { 1042 PetscFunctionBegin; 1043 PetscValidHeader(obj, 1); 1044 PetscFunctionReturn(PETSC_SUCCESS); 1045 } 1046 1047 /*MC 1048 PetscObjectIsNull - returns true if the given PETSc object is a null object 1049 1050 Fortran only 1051 1052 Synopsis: 1053 #include <petsc/finclude/petscsys.h> 1054 PetscBool PetscObjectIsNull(PetscObject obj) 1055 1056 Logically Collective 1057 1058 Input Parameters: 1059 . obj - the PETSc object 1060 1061 Level: beginner 1062 1063 Example Usage: 1064 .vb 1065 if (PetscObjectIsNull(dm)) then 1066 if (.not. PetscObjectIsNull(dm)) then 1067 .ve 1068 1069 Note: 1070 Code such as 1071 .vb 1072 if (dm == PETSC_NULL_DM) then 1073 .ve 1074 is not allowed. 1075 1076 .seealso: `PetscObject`, `PETSC_NULL_OBJECT`, `PETSC_NULL_VEC`, `PETSC_NULL_VEC_ARRAY` 1077 M*/ 1078