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