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