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