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