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