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