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