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