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