xref: /petsc/src/sys/objects/inherit.c (revision 14e7b07eeb9e40f6f4410f12e254190850606b19)
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 /*@
204   PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object
205 
206   Logically Collective
207 
208   Input Parameters:
209 + src  - source object
210 - dest - destination object
211 
212   Level: developer
213 
214   Note:
215   Both objects must have the same class.
216 
217   This is used to help manage user callback functions that were provided in Fortran
218 
219 .seealso: `PetscFortranCallbackRegister()`, `PetscFortranCallbackGetSizes()`
220 @*/
221 PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src, PetscObject dest)
222 {
223   PetscFortranCallbackId cbtype, numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];
224 
225   PetscFunctionBegin;
226   PetscValidHeader(src, 1);
227   PetscValidHeader(dest, 2);
228   PetscCheck(src->classid == dest->classid, src->comm, PETSC_ERR_ARG_INCOMP, "Objects must be of the same class");
229 
230   PetscCall(PetscFree(dest->fortran_func_pointers));
231   PetscCall(PetscMalloc(src->num_fortran_func_pointers * sizeof(void (*)(void)), &dest->fortran_func_pointers));
232   PetscCall(PetscMemcpy(dest->fortran_func_pointers, src->fortran_func_pointers, src->num_fortran_func_pointers * sizeof(void (*)(void))));
233 
234   dest->num_fortran_func_pointers = src->num_fortran_func_pointers;
235 
236   PetscCall(PetscFortranCallbackGetSizes(src->classid, &numcb[PETSC_FORTRAN_CALLBACK_CLASS], &numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
237   for (cbtype = PETSC_FORTRAN_CALLBACK_CLASS; cbtype < PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
238     PetscCall(PetscFree(dest->fortrancallback[cbtype]));
239     PetscCall(PetscCalloc1(numcb[cbtype], &dest->fortrancallback[cbtype]));
240     PetscCall(PetscMemcpy(dest->fortrancallback[cbtype], src->fortrancallback[cbtype], src->num_fortrancallback[cbtype] * sizeof(PetscFortranCallback)));
241     dest->num_fortrancallback[cbtype] = src->num_fortrancallback[cbtype];
242   }
243   PetscFunctionReturn(PETSC_SUCCESS);
244 }
245 
246 /*@C
247   PetscObjectSetFortranCallback - set Fortran callback function pointer and context
248 
249   Logically Collective, 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 /*@
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 /*@
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, const 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 #else
451 PetscErrorCode PetscObjectsView(PetscViewer viewer)
452 {
453   PetscFunctionReturn(PETSC_SUCCESS);
454 }
455 
456 PetscErrorCode PetscObjectsGetObject(const char name[], PetscObject *obj, const char *classname[])
457 {
458   PetscFunctionReturn(PETSC_SUCCESS);
459 }
460 #endif
461 
462 /*@
463   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
464 
465   Input Parameter:
466 . obj - the `PetscObject`
467 
468   Level: developer
469 
470   Developer Notes:
471   This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
472   `PCBJACOBI` from all printing the same help messages to the screen
473 
474 .seealso: `PetscOptionsInsert()`, `PetscObject`
475 @*/
476 PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
477 {
478   PetscFunctionBegin;
479   PetscAssertPointer(obj, 1);
480   obj->optionsprinted = PETSC_TRUE;
481   PetscFunctionReturn(PETSC_SUCCESS);
482 }
483 
484 /*@
485   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.
486 
487   Input Parameters:
488 + pobj - the parent object
489 - obj  - the `PetscObject`
490 
491   Level: developer
492 
493   Developer Notes:
494   This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
495   `PCBJACOBI` from all printing the same help messages to the screen
496 
497   This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap
498 
499 .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`, `PetscObject`
500 @*/
501 PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
502 {
503   PetscMPIInt prank, size;
504 
505   PetscFunctionBegin;
506   PetscValidHeader(pobj, 1);
507   PetscValidHeader(obj, 2);
508   PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank));
509   PetscCallMPI(MPI_Comm_size(obj->comm, &size));
510   if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
511   PetscFunctionReturn(PETSC_SUCCESS);
512 }
513 
514 /*@C
515   PetscObjectAddOptionsHandler - Adds an additional function to check for options when `XXXSetFromOptions()` is called.
516 
517   Not Collective
518 
519   Input Parameters:
520 + obj     - the PETSc object
521 . handle  - function that checks for options
522 . destroy - function to destroy `ctx` if provided
523 - ctx     - optional context for check function
524 
525   Calling sequence of `handle`:
526 + obj                - the PETSc object
527 . PetscOptionsObject - the `PetscOptionItems` object
528 - ctx                - optional context for `handle`
529 
530   Calling sequence of `destroy`:
531 + obj - the PETSc object
532 - ctx - optional context for `handle`
533 
534   Level: developer
535 
536 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`,
537           `PetscObject`
538 @*/
539 PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject obj, PetscOptionItems *PetscOptionsObject, void *ctx), PetscErrorCode (*destroy)(PetscObject obj, void *ctx), void *ctx)
540 {
541   PetscFunctionBegin;
542   PetscValidHeader(obj, 1);
543   PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "To many options handlers added");
544   obj->optionhandler[obj->noptionhandler] = handle;
545   obj->optiondestroy[obj->noptionhandler] = destroy;
546   obj->optionctx[obj->noptionhandler++]   = ctx;
547   PetscFunctionReturn(PETSC_SUCCESS);
548 }
549 
550 /*@C
551   PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
552 
553   Not Collective
554 
555   Input Parameters:
556 + obj                - the PETSc object
557 - PetscOptionsObject - the options context
558 
559   Level: developer
560 
561 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`,
562           `PetscObject`
563 @*/
564 PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
565 {
566   PetscFunctionBegin;
567   PetscValidHeader(obj, 1);
568   for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]));
569   PetscFunctionReturn(PETSC_SUCCESS);
570 }
571 
572 /*@
573   PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
574 
575   Not Collective
576 
577   Input Parameter:
578 . obj - the PETSc object
579 
580   Level: developer
581 
582 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`,
583           `PetscObject`
584 @*/
585 PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
586 {
587   PetscFunctionBegin;
588   PetscValidHeader(obj, 1);
589   for (PetscInt i = 0; i < obj->noptionhandler; i++) {
590     if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
591   }
592   obj->noptionhandler = 0;
593   PetscFunctionReturn(PETSC_SUCCESS);
594 }
595 
596 /*@
597   PetscObjectReference - Indicates to a `PetscObject` that it is being
598   referenced by another `PetscObject`. This increases the reference
599   count for that object by one.
600 
601   Logically Collective
602 
603   Input Parameter:
604 . obj - the PETSc object. This must be cast with (`PetscObject`), for example, `PetscObjectReference`((`PetscObject`)mat);
605 
606   Level: advanced
607 
608   Note:
609   If `obj` is `NULL` this function returns without doing anything.
610 
611 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
612 @*/
613 PetscErrorCode PetscObjectReference(PetscObject obj)
614 {
615   PetscFunctionBegin;
616   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
617   PetscValidHeader(obj, 1);
618   obj->refct++;
619   PetscFunctionReturn(PETSC_SUCCESS);
620 }
621 
622 /*@
623   PetscObjectGetReference - Gets the current reference count for a PETSc object.
624 
625   Not Collective
626 
627   Input Parameter:
628 . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
629         `PetscObjectGetReference`((`PetscObject`)mat,&cnt); `obj` cannot be `NULL`
630 
631   Output Parameter:
632 . cnt - the reference count
633 
634   Level: advanced
635 
636 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
637 @*/
638 PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
639 {
640   PetscFunctionBegin;
641   PetscValidHeader(obj, 1);
642   PetscAssertPointer(cnt, 2);
643   *cnt = obj->refct;
644   PetscFunctionReturn(PETSC_SUCCESS);
645 }
646 
647 /*@
648   PetscObjectDereference - Indicates to any `PetscObject` that it is being
649   referenced by one less `PetscObject`. This decreases the reference
650   count for that object by one.
651 
652   Collective on `obj` if reference reaches 0 otherwise Logically Collective
653 
654   Input Parameter:
655 . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
656         `PetscObjectDereference`((`PetscObject`)mat);
657 
658   Level: advanced
659 
660   Notes:
661   `PetscObjectDestroy()` sets the `obj` pointer to `NULL` after the call, this routine does not.
662 
663   If `obj` is `NULL` this function returns without doing anything.
664 
665 .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
666 @*/
667 PetscErrorCode PetscObjectDereference(PetscObject obj)
668 {
669   PetscFunctionBegin;
670   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
671   PetscValidHeader(obj, 1);
672   if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
673   else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
674   PetscFunctionReturn(PETSC_SUCCESS);
675 }
676 
677 /*
678      The following routines are the versions private to the PETSc object
679      data structures.
680 */
681 PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
682 {
683   PetscFunctionBegin;
684   PetscValidHeader(obj, 1);
685   PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
686   PetscFunctionReturn(PETSC_SUCCESS);
687 }
688 
689 /*@
690   PetscObjectCompose - Associates another PETSc object with a given PETSc object.
691 
692   Not Collective
693 
694   Input Parameters:
695 + obj  - the PETSc object; this must be cast with (`PetscObject`), for example,
696          `PetscObjectCompose`((`PetscObject`)mat,...);
697 . name - name associated with the child object
698 - ptr  - the other PETSc object to associate with the PETSc object; this must also be
699          cast with (`PetscObject`)
700 
701   Level: advanced
702 
703   Notes:
704   The second objects reference count is automatically increased by one when it is
705   composed.
706 
707   Replaces any previous object that had been composed with the same name.
708 
709   If `ptr` is `NULL` and `name` has previously been composed using an object, then that
710   entry is removed from `obj`.
711 
712   `PetscObjectCompose()` can be used with any PETSc object (such as
713   `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
714 
715   `PetscContainerCreate()` can be used to create an object from a
716   user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
717 
718 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
719           `PetscContainerSetPointer()`, `PetscObject`
720 @*/
721 PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
722 {
723   PetscFunctionBegin;
724   PetscValidHeader(obj, 1);
725   PetscAssertPointer(name, 2);
726   if (ptr) PetscValidHeader(ptr, 3);
727   PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself");
728   if (ptr) {
729     char     *tname;
730     PetscBool skipreference;
731 
732     PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
733     if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
734   }
735   PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
736   PetscFunctionReturn(PETSC_SUCCESS);
737 }
738 
739 /*@
740   PetscObjectQuery  - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
741 
742   Not Collective
743 
744   Input Parameters:
745 + obj  - the PETSc object. It must be cast with a (`PetscObject`), for example,
746          `PetscObjectCompose`((`PetscObject`)mat,...);
747 . name - name associated with child object
748 - ptr  - the other PETSc object associated with the PETSc object, this must be
749          cast with (`PetscObject`*)
750 
751   Level: advanced
752 
753   Note:
754   The reference count of neither object is increased in this call
755 
756 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
757           `PetscContainerGetPointer()`, `PetscObject`
758 @*/
759 PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
760 {
761   PetscFunctionBegin;
762   PetscValidHeader(obj, 1);
763   PetscAssertPointer(name, 2);
764   PetscAssertPointer(ptr, 3);
765   PetscCall(PetscObjectListFind(obj->olist, name, ptr));
766   PetscFunctionReturn(PETSC_SUCCESS);
767 }
768 
769 /*MC
770   PetscObjectComposeFunction - Associates a function with a given PETSc object.
771 
772   Synopsis:
773   #include <petscsys.h>
774   PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void))
775 
776   Logically Collective
777 
778   Input Parameters:
779 + obj  - the PETSc object; this must be cast with a (`PetscObject`), for example,
780          `PetscObjectCompose`((`PetscObject`)mat,...);
781 . name - name associated with the child function
782 - fptr - function pointer
783 
784   Level: advanced
785 
786   Notes:
787   When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
788   can be used to call the function directly with error checking.
789 
790   To remove a registered routine, pass in `NULL` for `fptr`.
791 
792   `PetscObjectComposeFunction()` can be used with any PETSc object (such as
793   `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
794 
795   `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table.
796 
797 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
798           `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
799 M*/
800 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
801 {
802   PetscFunctionBegin;
803   PetscValidHeader(obj, 1);
804   PetscAssertPointer(name, 2);
805   PetscCall(PetscFunctionListAdd(&obj->qlist, name, fptr));
806   PetscFunctionReturn(PETSC_SUCCESS);
807 }
808 
809 /*MC
810   PetscObjectQueryFunction - Gets a function associated with a given object.
811 
812   Synopsis:
813   #include <petscsys.h>
814   PetscErrorCode PetscObjectQueryFunction(PetscObject obj, const char name[], void (**fptr)(void))
815 
816   Logically Collective
817 
818   Input Parameters:
819 + obj  - the PETSc object; this must be cast with (`PetscObject`), for example,
820          `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
821 - name - name associated with the child function
822 
823   Output Parameter:
824 . fptr - function pointer
825 
826   Level: advanced
827 
828 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`
829 M*/
830 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**fptr)(void))
831 {
832   PetscFunctionBegin;
833   PetscValidHeader(obj, 1);
834   PetscAssertPointer(name, 2);
835   PetscCall(PetscFunctionListFind(obj->qlist, name, fptr));
836   PetscFunctionReturn(PETSC_SUCCESS);
837 }
838 
839 struct _p_PetscContainer {
840   PETSCHEADER(int);
841   void *ptr;
842   PetscErrorCode (*userdestroy)(void *);
843 };
844 
845 /*@C
846   PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
847   provided with `PetscContainerSetPointer()`
848 
849   Logically Collective on the `PetscContainer` containing the user data, No Fortran Support
850 
851   Input Parameter:
852 . ctx - pointer to user-provided data
853 
854   Level: advanced
855 
856 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`, `PetscObject`
857 @*/
858 PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
859 {
860   PetscFunctionBegin;
861   PetscCall(PetscFree(ctx));
862   PetscFunctionReturn(PETSC_SUCCESS);
863 }
864 
865 /*@C
866   PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
867 
868   Not Collective, No Fortran Support
869 
870   Input Parameter:
871 . obj - the object created with `PetscContainerCreate()`
872 
873   Output Parameter:
874 . ptr - the pointer value
875 
876   Level: advanced
877 
878 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
879           `PetscContainerSetPointer()`
880 @*/
881 PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
882 {
883   PetscFunctionBegin;
884   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
885   PetscAssertPointer(ptr, 2);
886   *ptr = obj->ptr;
887   PetscFunctionReturn(PETSC_SUCCESS);
888 }
889 
890 /*@C
891   PetscContainerSetPointer - Sets the pointer value contained in the container.
892 
893   Logically Collective, No Fortran Support
894 
895   Input Parameters:
896 + obj - the object created with `PetscContainerCreate()`
897 - ptr - the pointer value
898 
899   Level: advanced
900 
901 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
902           `PetscContainerGetPointer()`
903 @*/
904 PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
905 {
906   PetscFunctionBegin;
907   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
908   if (ptr) PetscAssertPointer(ptr, 2);
909   obj->ptr = ptr;
910   PetscFunctionReturn(PETSC_SUCCESS);
911 }
912 
913 /*@C
914   PetscContainerDestroy - Destroys a PETSc container object.
915 
916   Collective, No Fortran Support
917 
918   Input Parameter:
919 . obj - an object that was created with `PetscContainerCreate()`
920 
921   Level: advanced
922 
923   Note:
924   If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
925   then that function is called to destroy the data.
926 
927 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`, `PetscObject`
928 @*/
929 PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
930 {
931   PetscFunctionBegin;
932   if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
933   PetscValidHeaderSpecific(*obj, PETSC_CONTAINER_CLASSID, 1);
934   if (--((PetscObject)*obj)->refct > 0) {
935     *obj = NULL;
936     PetscFunctionReturn(PETSC_SUCCESS);
937   }
938   if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
939   PetscCall(PetscHeaderDestroy(obj));
940   PetscFunctionReturn(PETSC_SUCCESS);
941 }
942 
943 /*@C
944   PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
945 
946   Logically Collective, No Fortran Support
947 
948   Input Parameters:
949 + obj - an object that was created with `PetscContainerCreate()`
950 - des - name of the user destroy function
951 
952   Level: advanced
953 
954   Note:
955   Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
956 
957 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`
958 @*/
959 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
960 {
961   PetscFunctionBegin;
962   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
963   obj->userdestroy = des;
964   PetscFunctionReturn(PETSC_SUCCESS);
965 }
966 
967 PetscClassId PETSC_CONTAINER_CLASSID;
968 
969 /*@C
970   PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.
971 
972   Collective, No Fortran Support
973 
974   Input Parameter:
975 . comm - MPI communicator that shares the object
976 
977   Output Parameter:
978 . container - the container created
979 
980   Level: advanced
981 
982   Notes:
983   This allows one to attach any type of data (accessible through a pointer) with the
984   `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
985   call to `PetscContainerSetPointer()`.
986 
987 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
988           `PetscContainerSetUserDestroy()`, `PetscObject`
989 @*/
990 PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
991 {
992   PetscFunctionBegin;
993   PetscAssertPointer(container, 2);
994   PetscCall(PetscSysInitializePackage());
995   PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
996   PetscFunctionReturn(PETSC_SUCCESS);
997 }
998 
999 /*@
1000   PetscObjectSetFromOptions - Sets generic parameters from user options.
1001 
1002   Collective
1003 
1004   Input Parameter:
1005 . obj - the `PetscObject`
1006 
1007   Level: beginner
1008 
1009   Note:
1010   We have no generic options at present, so this does nothing
1011 
1012 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
1013 @*/
1014 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1015 {
1016   PetscFunctionBegin;
1017   PetscValidHeader(obj, 1);
1018   PetscFunctionReturn(PETSC_SUCCESS);
1019 }
1020 
1021 /*@
1022   PetscObjectSetUp - Sets up the internal data structures for later use of the object
1023 
1024   Collective
1025 
1026   Input Parameter:
1027 . obj - the `PetscObject`
1028 
1029   Level: advanced
1030 
1031   Note:
1032   This does nothing at present.
1033 
1034 .seealso: `PetscObjectDestroy()`, `PetscObject`
1035 @*/
1036 PetscErrorCode PetscObjectSetUp(PetscObject obj)
1037 {
1038   PetscFunctionBegin;
1039   PetscValidHeader(obj, 1);
1040   PetscFunctionReturn(PETSC_SUCCESS);
1041 }
1042 
1043 /*MC
1044   PetscObjectIsNull - returns true if the given PETSc object is a null object
1045 
1046   Fortran only
1047 
1048   Synopsis:
1049   #include <petsc/finclude/petscsys.h>
1050   PetscBool PetscObjectIsNull(PetscObject obj)
1051 
1052   Logically Collective
1053 
1054   Input Parameters:
1055 . obj  - the PETSc object
1056 
1057   Level: beginner
1058 
1059   Example Usage:
1060 .vb
1061   if (PetscObjectIsNull(dm)) then
1062   if (.not. PetscObjectIsNull(dm)) then
1063 .ve
1064 
1065   Note:
1066   Code such as
1067 .vb
1068   if (dm == PETSC_NULL_DM) then
1069 .ve
1070   is not allowed.
1071 
1072 .seealso: `PetscObject`, `PETSC_NULL_OBJECT`, `PETSC_NULL_VEC`, `PETSC_NULL_VEC_ARRAY`
1073 M*/
1074