xref: /petsc/src/sys/objects/inherit.c (revision 85f25e71687eef93ec659366612fd9d9ee335aac)
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, PetscObjectDestroyFn *destroy, PetscObjectViewFn *view)
23 {
24   PetscFunctionBegin;
25   if (ierr) PetscFunctionReturn(ierr);
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, PetscObjectDestroyFn *destroy, PetscObjectViewFn *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, No Fortran Support
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, No Fortran Support
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, No Fortran Support
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, `PetscObjectReference`((`PetscObject`)mat);
595 
596   Level: advanced
597 
598   Note:
599   If `obj` is `NULL` this function returns without doing anything.
600 
601 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
602 @*/
603 PetscErrorCode PetscObjectReference(PetscObject obj)
604 {
605   PetscFunctionBegin;
606   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
607   PetscValidHeader(obj, 1);
608   obj->refct++;
609   PetscFunctionReturn(PETSC_SUCCESS);
610 }
611 
612 /*@C
613   PetscObjectGetReference - Gets the current reference count for a PETSc object.
614 
615   Not Collective
616 
617   Input Parameter:
618 . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
619         `PetscObjectGetReference`((`PetscObject`)mat,&cnt); `obj` cannot be `NULL`
620 
621   Output Parameter:
622 . cnt - the reference count
623 
624   Level: advanced
625 
626 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
627 @*/
628 PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
629 {
630   PetscFunctionBegin;
631   PetscValidHeader(obj, 1);
632   PetscAssertPointer(cnt, 2);
633   *cnt = obj->refct;
634   PetscFunctionReturn(PETSC_SUCCESS);
635 }
636 
637 /*@C
638   PetscObjectDereference - Indicates to any `PetscObject` that it is being
639   referenced by one less `PetscObject`. This decreases the reference
640   count for that object by one.
641 
642   Collective on `obj` if reference reaches 0 otherwise Logically Collective
643 
644   Input Parameter:
645 . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
646         `PetscObjectDereference`((`PetscObject`)mat);
647 
648   Level: advanced
649 
650   Notes:
651   `PetscObjectDestroy()` sets the `obj` pointer to `NULL` after the call, this routine does not.
652 
653   If `obj` is `NULL` this function returns without doing anything.
654 
655 .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
656 @*/
657 PetscErrorCode PetscObjectDereference(PetscObject obj)
658 {
659   PetscFunctionBegin;
660   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
661   PetscValidHeader(obj, 1);
662   if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
663   else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
664   PetscFunctionReturn(PETSC_SUCCESS);
665 }
666 
667 /*
668      The following routines are the versions private to the PETSc object
669      data structures.
670 */
671 PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
672 {
673   PetscFunctionBegin;
674   PetscValidHeader(obj, 1);
675   PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
676   PetscFunctionReturn(PETSC_SUCCESS);
677 }
678 
679 /*@C
680   PetscObjectCompose - Associates another PETSc object with a given PETSc object.
681 
682   Not Collective
683 
684   Input Parameters:
685 + obj  - the PETSc object; this must be cast with (`PetscObject`), for example,
686          `PetscObjectCompose`((`PetscObject`)mat,...);
687 . name - name associated with the child object
688 - ptr  - the other PETSc object to associate with the PETSc object; this must also be
689          cast with (`PetscObject`)
690 
691   Level: advanced
692 
693   Notes:
694   The second objects reference count is automatically increased by one when it is
695   composed.
696 
697   Replaces any previous object that had been composed with the same name.
698 
699   If `ptr` is `NULL` and `name` has previously been composed using an object, then that
700   entry is removed from `obj`.
701 
702   `PetscObjectCompose()` can be used with any PETSc object (such as
703   `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
704 
705   `PetscContainerCreate()` can be used to create an object from a
706   user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
707 
708 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
709           `PetscContainerSetPointer()`, `PetscObject`
710 @*/
711 PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
712 {
713   PetscFunctionBegin;
714   PetscValidHeader(obj, 1);
715   PetscAssertPointer(name, 2);
716   if (ptr) PetscValidHeader(ptr, 3);
717   PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself");
718   if (ptr) {
719     char     *tname;
720     PetscBool skipreference;
721 
722     PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
723     if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
724   }
725   PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
726   PetscFunctionReturn(PETSC_SUCCESS);
727 }
728 
729 /*@C
730   PetscObjectQuery  - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
731 
732   Not Collective
733 
734   Input Parameters:
735 + obj  - the PETSc object. It must be cast with a (`PetscObject`), for example,
736          `PetscObjectCompose`((`PetscObject`)mat,...);
737 . name - name associated with child object
738 - ptr  - the other PETSc object associated with the PETSc object, this must be
739          cast with (`PetscObject`*)
740 
741   Level: advanced
742 
743   Note:
744   The reference count of neither object is increased in this call
745 
746 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
747           `PetscContainerGetPointer()`, `PetscObject`
748 @*/
749 PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
750 {
751   PetscFunctionBegin;
752   PetscValidHeader(obj, 1);
753   PetscAssertPointer(name, 2);
754   PetscAssertPointer(ptr, 3);
755   PetscCall(PetscObjectListFind(obj->olist, name, ptr));
756   PetscFunctionReturn(PETSC_SUCCESS);
757 }
758 
759 /*MC
760   PetscObjectComposeFunction - Associates a function with a given PETSc object.
761 
762   Synopsis:
763   #include <petscsys.h>
764   PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void))
765 
766   Logically Collective
767 
768   Input Parameters:
769 + obj  - the PETSc object; this must be cast with a (`PetscObject`), for example,
770          `PetscObjectCompose`((`PetscObject`)mat,...);
771 . name - name associated with the child function
772 - fptr - function pointer
773 
774   Level: advanced
775 
776   Notes:
777   When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
778   can be used to call the function directly with error checking.
779 
780   To remove a registered routine, pass in `NULL` for `fptr`.
781 
782   `PetscObjectComposeFunction()` can be used with any PETSc object (such as
783   `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
784 
785   `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table.
786 
787 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
788           `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
789 M*/
790 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
791 {
792   PetscFunctionBegin;
793   PetscValidHeader(obj, 1);
794   PetscAssertPointer(name, 2);
795   PetscCall(PetscFunctionListAdd(&obj->qlist, name, fptr));
796   PetscFunctionReturn(PETSC_SUCCESS);
797 }
798 
799 /*MC
800   PetscObjectQueryFunction - Gets a function associated with a given object.
801 
802   Synopsis:
803   #include <petscsys.h>
804   PetscErrorCode PetscObjectQueryFunction(PetscObject obj, const char name[], void (**fptr)(void))
805 
806   Logically Collective
807 
808   Input Parameters:
809 + obj  - the PETSc object; this must be cast with (`PetscObject`), for example,
810          `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
811 - name - name associated with the child function
812 
813   Output Parameter:
814 . fptr - function pointer
815 
816   Level: advanced
817 
818 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`
819 M*/
820 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**fptr)(void))
821 {
822   PetscFunctionBegin;
823   PetscValidHeader(obj, 1);
824   PetscAssertPointer(name, 2);
825   PetscCall(PetscFunctionListFind(obj->qlist, name, fptr));
826   PetscFunctionReturn(PETSC_SUCCESS);
827 }
828 
829 struct _p_PetscContainer {
830   PETSCHEADER(int);
831   void *ptr;
832   PetscErrorCode (*userdestroy)(void *);
833 };
834 
835 /*@C
836   PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
837   provided with `PetscContainerSetPointer()`
838 
839   Logically Collective on the `PetscContainer` containing the user data, No Fortran Support
840 
841   Input Parameter:
842 . ctx - pointer to user-provided data
843 
844   Level: advanced
845 
846 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`, `PetscObject`
847 @*/
848 PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
849 {
850   PetscFunctionBegin;
851   PetscCall(PetscFree(ctx));
852   PetscFunctionReturn(PETSC_SUCCESS);
853 }
854 
855 /*@C
856   PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
857 
858   Not Collective, No Fortran Support
859 
860   Input Parameter:
861 . obj - the object created with `PetscContainerCreate()`
862 
863   Output Parameter:
864 . ptr - the pointer value
865 
866   Level: advanced
867 
868 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
869           `PetscContainerSetPointer()`
870 @*/
871 PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
872 {
873   PetscFunctionBegin;
874   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
875   PetscAssertPointer(ptr, 2);
876   *ptr = obj->ptr;
877   PetscFunctionReturn(PETSC_SUCCESS);
878 }
879 
880 /*@C
881   PetscContainerSetPointer - Sets the pointer value contained in the container.
882 
883   Logically Collective, No Fortran Support
884 
885   Input Parameters:
886 + obj - the object created with `PetscContainerCreate()`
887 - ptr - the pointer value
888 
889   Level: advanced
890 
891 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
892           `PetscContainerGetPointer()`
893 @*/
894 PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
895 {
896   PetscFunctionBegin;
897   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
898   if (ptr) PetscAssertPointer(ptr, 2);
899   obj->ptr = ptr;
900   PetscFunctionReturn(PETSC_SUCCESS);
901 }
902 
903 /*@C
904   PetscContainerDestroy - Destroys a PETSc container object.
905 
906   Collective, No Fortran Support
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()`, `PetscObject`
918 @*/
919 PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
920 {
921   PetscFunctionBegin;
922   if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
923   PetscValidHeaderSpecific(*obj, PETSC_CONTAINER_CLASSID, 1);
924   if (--((PetscObject)*obj)->refct > 0) {
925     *obj = NULL;
926     PetscFunctionReturn(PETSC_SUCCESS);
927   }
928   if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
929   PetscCall(PetscHeaderDestroy(obj));
930   PetscFunctionReturn(PETSC_SUCCESS);
931 }
932 
933 /*@C
934   PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
935 
936   Logically Collective, No Fortran Support
937 
938   Input Parameters:
939 + obj - an object that was created with `PetscContainerCreate()`
940 - des - name of the user destroy function
941 
942   Level: advanced
943 
944   Note:
945   Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
946 
947 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`
948 @*/
949 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
950 {
951   PetscFunctionBegin;
952   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
953   obj->userdestroy = des;
954   PetscFunctionReturn(PETSC_SUCCESS);
955 }
956 
957 PetscClassId PETSC_CONTAINER_CLASSID;
958 
959 /*@C
960   PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.
961 
962   Collective, No Fortran Support
963 
964   Input Parameter:
965 . comm - MPI communicator that shares the object
966 
967   Output Parameter:
968 . container - the container created
969 
970   Level: advanced
971 
972   Notes:
973   This allows one to attach any type of data (accessible through a pointer) with the
974   `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
975   call to `PetscContainerSetPointer()`.
976 
977 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
978           `PetscContainerSetUserDestroy()`, `PetscObject`
979 @*/
980 PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
981 {
982   PetscFunctionBegin;
983   PetscAssertPointer(container, 2);
984   PetscCall(PetscSysInitializePackage());
985   PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
986   PetscFunctionReturn(PETSC_SUCCESS);
987 }
988 
989 /*@
990   PetscObjectSetFromOptions - Sets generic parameters from user options.
991 
992   Collective
993 
994   Input Parameter:
995 . obj - the `PetscObject`
996 
997   Level: beginner
998 
999   Note:
1000   We have no generic options at present, so this does nothing
1001 
1002 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
1003 @*/
1004 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1005 {
1006   PetscFunctionBegin;
1007   PetscValidHeader(obj, 1);
1008   PetscFunctionReturn(PETSC_SUCCESS);
1009 }
1010 
1011 /*@
1012   PetscObjectSetUp - Sets up the internal data structures for later use of the object
1013 
1014   Collective
1015 
1016   Input Parameter:
1017 . obj - the `PetscObject`
1018 
1019   Level: advanced
1020 
1021   Note:
1022   This does nothing at present.
1023 
1024 .seealso: `PetscObjectDestroy()`, `PetscObject`
1025 @*/
1026 PetscErrorCode PetscObjectSetUp(PetscObject obj)
1027 {
1028   PetscFunctionBegin;
1029   PetscValidHeader(obj, 1);
1030   PetscFunctionReturn(PETSC_SUCCESS);
1031 }
1032