xref: /petsc/src/sys/objects/inherit.c (revision 47496788044a9390af80626fac4dc6fd93df261a)
1 /*
2      Provides utility routines for manipulating any type of PETSc object.
3 */
4 #include <petsc/private/petscimpl.h> /*I   "petscsys.h"    I*/
5 #include <petscviewer.h>
6 
7 PETSC_INTERN PetscObject *PetscObjects;
8 PETSC_INTERN PetscInt     PetscObjectsCounts;
9 PETSC_INTERN PetscInt     PetscObjectsMaxCounts;
10 PETSC_INTERN PetscBool    PetscObjectsLog;
11 
12 PetscObject *PetscObjects       = NULL;
13 PetscInt     PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;
14 PetscBool    PetscObjectsLog = PETSC_FALSE;
15 
16 PetscObjectId PetscObjectNewId_Internal(void)
17 {
18   static PetscObjectId idcnt = 1;
19   return idcnt++;
20 }
21 
22 PetscErrorCode PetscHeaderCreate_Function(PetscErrorCode ierr, PetscObject *h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
23 {
24   if (ierr) return ierr;
25   PetscFunctionBegin;
26   PetscCall(PetscHeaderCreate_Private(*h, classid, class_name, descr, mansec, comm, destroy, view));
27   PetscCall(PetscLogObjectCreate(*h));
28   PetscFunctionReturn(PETSC_SUCCESS);
29 }
30 
31 /*
32    PetscHeaderCreate_Private - Fills in the default values.
33 */
34 PetscErrorCode PetscHeaderCreate_Private(PetscObject h, PetscClassId classid, const char class_name[], const char descr[], const char mansec[], MPI_Comm comm, PetscObjectDestroyFunction destroy, PetscObjectViewFunction view)
35 {
36   void       *get_tmp;
37   PetscInt64 *cidx;
38   PetscMPIInt flg;
39 
40   PetscFunctionBegin;
41   h->classid               = classid;
42   h->class_name            = (char *)class_name;
43   h->description           = (char *)descr;
44   h->mansec                = (char *)mansec;
45   h->refct                 = 1;
46   h->non_cyclic_references = NULL;
47   h->id                    = PetscObjectNewId_Internal();
48   h->bops->destroy         = destroy;
49   h->bops->view            = view;
50 
51   PetscCall(PetscCommDuplicate(comm, &h->comm, &h->tag));
52 
53   /* Increment and store current object creation index */
54   PetscCallMPI(MPI_Comm_get_attr(h->comm, Petsc_CreationIdx_keyval, &get_tmp, &flg));
55   PetscCheck(flg, h->comm, PETSC_ERR_ARG_CORRUPT, "MPI_Comm does not have an object creation index");
56   cidx    = (PetscInt64 *)get_tmp;
57   h->cidx = (*cidx)++;
58   PetscCallMPI(MPI_Comm_set_attr(h->comm, Petsc_CreationIdx_keyval, cidx));
59 
60   /* Keep a record of object created */
61   if (PetscDefined(USE_LOG) && PetscObjectsLog) {
62     PetscObject *newPetscObjects;
63     PetscInt     newPetscObjectsMaxCounts;
64 
65     PetscObjectsCounts++;
66     for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
67       if (!PetscObjects[i]) {
68         PetscObjects[i] = h;
69         PetscFunctionReturn(PETSC_SUCCESS);
70       }
71     }
72     /* Need to increase the space for storing PETSc objects */
73     if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
74     else newPetscObjectsMaxCounts = 2 * PetscObjectsMaxCounts;
75     PetscCall(PetscCalloc1(newPetscObjectsMaxCounts, &newPetscObjects));
76     PetscCall(PetscArraycpy(newPetscObjects, PetscObjects, PetscObjectsMaxCounts));
77     PetscCall(PetscFree(PetscObjects));
78 
79     PetscObjects                        = newPetscObjects;
80     PetscObjects[PetscObjectsMaxCounts] = h;
81     PetscObjectsMaxCounts               = newPetscObjectsMaxCounts;
82   }
83   PetscFunctionReturn(PETSC_SUCCESS);
84 }
85 
86 PETSC_INTERN PetscBool      PetscMemoryCollectMaximumUsage;
87 PETSC_INTERN PetscLogDouble PetscMemoryMaximumUsage;
88 
89 PetscErrorCode PetscHeaderDestroy_Function(PetscObject *h)
90 {
91   PetscFunctionBegin;
92   PetscCall(PetscLogObjectDestroy(*h));
93   PetscCall(PetscHeaderDestroy_Private(*h, PETSC_FALSE));
94   PetscCall(PetscFree(*h));
95   PetscFunctionReturn(PETSC_SUCCESS);
96 }
97 
98 /*
99     PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
100     the macro PetscHeaderDestroy().
101 */
102 PetscErrorCode PetscHeaderDestroy_Private(PetscObject obj, PetscBool clear_for_reuse)
103 {
104   PetscFunctionBegin;
105   PetscValidHeader(obj, 1);
106   PetscCall(PetscComposedQuantitiesDestroy(obj));
107   if (PetscMemoryCollectMaximumUsage) {
108     PetscLogDouble usage;
109 
110     PetscCall(PetscMemoryGetCurrentUsage(&usage));
111     if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
112   }
113   /* first destroy things that could execute arbitrary code */
114   if (obj->python_destroy) {
115     void *python_context                     = obj->python_context;
116     PetscErrorCode (*python_destroy)(void *) = obj->python_destroy;
117 
118     obj->python_context = NULL;
119     obj->python_destroy = NULL;
120     PetscCall((*python_destroy)(python_context));
121   }
122   PetscCall(PetscObjectDestroyOptionsHandlers(obj));
123   PetscCall(PetscObjectListDestroy(&obj->olist));
124 
125   /* destroy allocated quantities */
126   if (PetscPrintFunctionList) PetscCall(PetscFunctionListPrintNonEmpty(obj->qlist));
127   PetscCheck(--(obj->refct) <= 0, obj->comm, PETSC_ERR_PLIB, "Destroying a PetscObject (%s) with reference count %" PetscInt_FMT " >= 1", obj->name ? obj->name : "unnamed", obj->refct);
128   PetscCall(PetscFree(obj->name));
129   PetscCall(PetscFree(obj->prefix));
130   PetscCall(PetscFree(obj->type_name));
131 
132   if (clear_for_reuse) {
133     /* we will assume that obj->bops->view and destroy are safe to leave as-is */
134 
135     /* reset quantities, in order of appearance in _p_PetscObject */
136     obj->id       = PetscObjectNewId_Internal();
137     obj->refct    = 1;
138     obj->tablevel = 0;
139     obj->state    = 0;
140     /* don't deallocate, zero these out instead */
141     PetscCall(PetscFunctionListClear(obj->qlist));
142     PetscCall(PetscArrayzero(obj->fortran_func_pointers, obj->num_fortran_func_pointers));
143     PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]));
144     PetscCall(PetscArrayzero(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE], obj->num_fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
145     obj->optionsprinted = PETSC_FALSE;
146 #if PetscDefined(HAVE_SAWS)
147     obj->amsmem          = PETSC_FALSE;
148     obj->amspublishblock = PETSC_FALSE;
149 #endif
150     obj->options                                  = NULL;
151     obj->donotPetscObjectPrintClassNamePrefixType = PETSC_FALSE;
152   } else {
153     PetscCall(PetscFunctionListDestroy(&obj->qlist));
154     PetscCall(PetscFree(obj->fortran_func_pointers));
155     PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]));
156     PetscCall(PetscFree(obj->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]));
157     PetscCall(PetscCommDestroy(&obj->comm));
158     obj->classid = PETSCFREEDHEADER;
159 
160     if (PetscDefined(USE_LOG) && PetscObjectsLog) {
161       /* Record object removal from list of all objects */
162       for (PetscInt i = 0; i < PetscObjectsMaxCounts; ++i) {
163         if (PetscObjects[i] == obj) {
164           PetscObjects[i] = NULL;
165           --PetscObjectsCounts;
166           break;
167         }
168       }
169       if (!PetscObjectsCounts) {
170         PetscCall(PetscFree(PetscObjects));
171         PetscObjectsMaxCounts = 0;
172       }
173     }
174   }
175   PetscFunctionReturn(PETSC_SUCCESS);
176 }
177 
178 /*
179   PetscHeaderReset_Internal - "Reset" a PetscObject header. This is tantamount to destroying
180   the object but does not free all resources. The object retains its:
181 
182   - classid
183   - bops->view
184   - bops->destroy
185   - comm
186   - tag
187   - class_name
188   - description
189   - mansec
190   - cpp
191 
192   Note that while subclass information is lost, superclass info remains. Thus this function is
193   intended to be used to reuse a PetscObject within the same class to avoid reallocating its
194   resources.
195 */
196 PetscErrorCode PetscHeaderReset_Internal(PetscObject obj)
197 {
198   PetscFunctionBegin;
199   PetscCall(PetscHeaderDestroy_Private(obj, PETSC_TRUE));
200   PetscFunctionReturn(PETSC_SUCCESS);
201 }
202 
203 /*@C
204   PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object
205 
206   Logically Collective
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
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
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   On rank 0 of `PETSC_COMM_WORLD` prints the values
329 
330   Input Parameters:
331 + fd  - file pointer
332 - all - by default only tries to display objects created explicitly by the user, if all is `PETSC_TRUE` then lists all outstanding objects
333 
334   Options Database Key:
335 . -objects_dump <all> - print information about all the objects that exist at the end of the programs run
336 
337   Level: advanced
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 /*@C
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 /*@C
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
421 - classname - the name of the class
422 
423   Level: advanced
424 
425 .seealso: `PetscObject`
426 @*/
427 PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
428 {
429   PetscInt    i;
430   PetscObject h;
431   PetscBool   flg;
432 
433   PetscFunctionBegin;
434   PetscAssertPointer(name, 1);
435   PetscAssertPointer(obj, 2);
436   *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         *obj = h;
443         if (classname) *classname = h->class_name;
444         PetscFunctionReturn(PETSC_SUCCESS);
445       }
446     }
447   }
448   PetscFunctionReturn(PETSC_SUCCESS);
449 }
450 #endif
451 
452 /*@
453   PetscObjectSetPrintedOptions - indicate to an object that it should behave as if it has already printed the help for its options so it will not display the help message
454 
455   Input Parameter:
456 . obj - the `PetscObject`
457 
458   Level: developer
459 
460   Developer Notes:
461   This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
462   `PCBJACOBI` from all printing the same help messages to the screen
463 
464 .seealso: `PetscOptionsInsert()`, `PetscObject`
465 @*/
466 PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
467 {
468   PetscFunctionBegin;
469   PetscAssertPointer(obj, 1);
470   obj->optionsprinted = PETSC_TRUE;
471   PetscFunctionReturn(PETSC_SUCCESS);
472 }
473 
474 /*@
475   PetscObjectInheritPrintedOptions - If the child object is not on the rank 0 process of the parent object and the child is sequential then the child gets it set.
476 
477   Input Parameters:
478 + pobj - the parent object
479 - obj  - the `PetscObject`
480 
481   Level: developer
482 
483   Developer Notes:
484   This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
485   `PCBJACOBI` from all printing the same help messages to the screen
486 
487   This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap
488 
489 .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`, `PetscObject`
490 @*/
491 PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
492 {
493   PetscMPIInt prank, size;
494 
495   PetscFunctionBegin;
496   PetscValidHeader(pobj, 1);
497   PetscValidHeader(obj, 2);
498   PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank));
499   PetscCallMPI(MPI_Comm_size(obj->comm, &size));
500   if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
501   PetscFunctionReturn(PETSC_SUCCESS);
502 }
503 
504 /*@C
505   PetscObjectAddOptionsHandler - Adds an additional function to check for options when `XXXSetFromOptions()` is called.
506 
507   Not Collective
508 
509   Input Parameters:
510 + obj     - the PETSc object
511 . handle  - function that checks for options
512 . destroy - function to destroy context if provided
513 - ctx     - optional context for check function
514 
515   Level: developer
516 
517 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`,
518           `PetscObject`
519 @*/
520 PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject, PetscOptionItems *, void *), PetscErrorCode (*destroy)(PetscObject, void *), void *ctx)
521 {
522   PetscFunctionBegin;
523   PetscValidHeader(obj, 1);
524   PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "To many options handlers added");
525   obj->optionhandler[obj->noptionhandler] = handle;
526   obj->optiondestroy[obj->noptionhandler] = destroy;
527   obj->optionctx[obj->noptionhandler++]   = ctx;
528   PetscFunctionReturn(PETSC_SUCCESS);
529 }
530 
531 /*@C
532   PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
533 
534   Not Collective
535 
536   Input Parameters:
537 + obj                - the PETSc object
538 - PetscOptionsObject - the options context
539 
540   Level: developer
541 
542 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`,
543           `PetscObject`
544 @*/
545 PetscErrorCode PetscObjectProcessOptionsHandlers(PetscObject obj, PetscOptionItems *PetscOptionsObject)
546 {
547   PetscFunctionBegin;
548   PetscValidHeader(obj, 1);
549   for (PetscInt i = 0; i < obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj, PetscOptionsObject, obj->optionctx[i]));
550   PetscFunctionReturn(PETSC_SUCCESS);
551 }
552 
553 /*@C
554   PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
555 
556   Not Collective
557 
558   Input Parameter:
559 . obj - the PETSc object
560 
561   Level: developer
562 
563 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectProcessOptionsHandlers()`,
564           `PetscObject`
565 @*/
566 PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
567 {
568   PetscFunctionBegin;
569   PetscValidHeader(obj, 1);
570   for (PetscInt i = 0; i < obj->noptionhandler; i++) {
571     if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
572   }
573   obj->noptionhandler = 0;
574   PetscFunctionReturn(PETSC_SUCCESS);
575 }
576 
577 /*@C
578   PetscObjectReference - Indicates to any `PetscObject` that it is being
579   referenced by another `PetscObject`. This increases the reference
580   count for that object by one.
581 
582   Logically Collective
583 
584   Input Parameter:
585 . obj - the PETSc object. This must be cast with (`PetscObject`), for example,
586          `PetscObjectReference`((`PetscObject`)mat);
587 
588   Level: advanced
589 
590 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObject`
591 @*/
592 PetscErrorCode PetscObjectReference(PetscObject obj)
593 {
594   PetscFunctionBegin;
595   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
596   PetscValidHeader(obj, 1);
597   obj->refct++;
598   PetscFunctionReturn(PETSC_SUCCESS);
599 }
600 
601 /*@C
602   PetscObjectGetReference - Gets the current reference count for
603   any PETSc object.
604 
605   Not Collective
606 
607   Input Parameter:
608 . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
609          `PetscObjectGetReference`((`PetscObject`)mat,&cnt);
610 
611   Output Parameter:
612 . cnt - the reference count
613 
614   Level: advanced
615 
616 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`, `PetscObjectReference()`, `PetscObject`
617 @*/
618 PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
619 {
620   PetscFunctionBegin;
621   PetscValidHeader(obj, 1);
622   PetscAssertPointer(cnt, 2);
623   *cnt = obj->refct;
624   PetscFunctionReturn(PETSC_SUCCESS);
625 }
626 
627 /*@C
628   PetscObjectDereference - Indicates to any `PetscObject` that it is being
629   referenced by one less `PetscObject`. This decreases the reference
630   count for that object by one.
631 
632   Collective on obj if reference reaches 0 otherwise Logically Collective
633 
634   Input Parameter:
635 . obj - the PETSc object; this must be cast with (`PetscObject`), for example,
636          `PetscObjectDereference`((`PetscObject`)mat);
637 
638   Level: advanced
639 
640   Note:
641   `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not.
642 
643 .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`, `PetscObject`
644 @*/
645 PetscErrorCode PetscObjectDereference(PetscObject obj)
646 {
647   PetscFunctionBegin;
648   if (!obj) PetscFunctionReturn(PETSC_SUCCESS);
649   PetscValidHeader(obj, 1);
650   if (obj->bops->destroy) PetscCall((*obj->bops->destroy)(&obj));
651   else PetscCheck(--(obj->refct), PETSC_COMM_SELF, PETSC_ERR_SUP, "This PETSc object does not have a generic destroy routine");
652   PetscFunctionReturn(PETSC_SUCCESS);
653 }
654 
655 /*
656      The following routines are the versions private to the PETSc object
657      data structures.
658 */
659 PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
660 {
661   PetscFunctionBegin;
662   PetscValidHeader(obj, 1);
663   PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
664   PetscFunctionReturn(PETSC_SUCCESS);
665 }
666 
667 /*@C
668   PetscObjectCompose - Associates another PETSc object with a given PETSc object.
669 
670   Not Collective
671 
672   Input Parameters:
673 + obj  - the PETSc object; this must be cast with (`PetscObject`), for example,
674          `PetscObjectCompose`((`PetscObject`)mat,...);
675 . name - name associated with the child object
676 - ptr  - the other PETSc object to associate with the PETSc object; this must also be
677          cast with (`PetscObject`)
678 
679   Level: advanced
680 
681   Notes:
682   The second objects reference count is automatically increased by one when it is
683   composed.
684 
685   Replaces any previous object that had the same name.
686 
687   If ptr is null and name has previously been composed using an object, then that
688   entry is removed from the obj.
689 
690   `PetscObjectCompose()` can be used with any PETSc object (such as
691   `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
692 
693   `PetscContainerCreate()` can be used to create an object from a
694   user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
695 
696 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
697           `PetscContainerSetPointer()`, `PetscObject`
698 @*/
699 PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
700 {
701   PetscFunctionBegin;
702   PetscValidHeader(obj, 1);
703   PetscAssertPointer(name, 2);
704   if (ptr) PetscValidHeader(ptr, 3);
705   PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself");
706   if (ptr) {
707     char     *tname;
708     PetscBool skipreference;
709 
710     PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
711     if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
712   }
713   PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
714   PetscFunctionReturn(PETSC_SUCCESS);
715 }
716 
717 /*@C
718   PetscObjectQuery  - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
719 
720   Not Collective
721 
722   Input Parameters:
723 + obj  - the PETSc object
724          Thus must be cast with a (`PetscObject`), for example,
725          `PetscObjectCompose`((`PetscObject`)mat,...);
726 . name - name associated with child object
727 - ptr  - the other PETSc object associated with the PETSc object, this must be
728          cast with (`PetscObject`*)
729 
730   Level: advanced
731 
732   Note:
733   The reference count of neither object is increased in this call
734 
735 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
736           `PetscContainerGetPointer()`, `PetscObject`
737 @*/
738 PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
739 {
740   PetscFunctionBegin;
741   PetscValidHeader(obj, 1);
742   PetscAssertPointer(name, 2);
743   PetscAssertPointer(ptr, 3);
744   PetscCall(PetscObjectListFind(obj->olist, name, ptr));
745   PetscFunctionReturn(PETSC_SUCCESS);
746 }
747 
748 /*MC
749   PetscObjectComposeFunction - Associates a function with a given PETSc object.
750 
751   Synopsis:
752   #include <petscsys.h>
753   PetscErrorCode PetscObjectComposeFunction(PetscObject obj, const char name[], void (*fptr)(void))
754 
755   Logically Collective
756 
757   Input Parameters:
758 + obj  - the PETSc object; this must be cast with a (`PetscObject`), for example,
759          `PetscObjectCompose`((`PetscObject`)mat,...);
760 . name - name associated with the child function
761 - fptr - function pointer
762 
763   Level: advanced
764 
765   Notes:
766   When the first argument of `fptr` is (or is derived from) a `PetscObject` then `PetscTryMethod()` and `PetscUseMethod()`
767   can be used to call the function directly with error checking.
768 
769   To remove a registered routine, pass in `NULL` for `fptr`.
770 
771   `PetscObjectComposeFunction()` can be used with any PETSc object (such as
772   `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
773 
774   `PetscUseTypeMethod()` and `PetscTryTypeMethod()` are used to call a function that is stored in the objects `obj->ops` table.
775 
776 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
777           `PetscUseTypeMethod()`, `PetscTryTypeMethod()`, `PetscObject`
778 M*/
779 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
780 {
781   PetscFunctionBegin;
782   PetscValidHeader(obj, 1);
783   PetscAssertPointer(name, 2);
784   PetscCall(PetscFunctionListAdd(&obj->qlist, name, fptr));
785   PetscFunctionReturn(PETSC_SUCCESS);
786 }
787 
788 /*MC
789   PetscObjectQueryFunction - Gets a function associated with a given object.
790 
791   Synopsis:
792   #include <petscsys.h>
793   PetscErrorCode PetscObjectQueryFunction(PetscObject obj, const char name[], void (**fptr)(void))
794 
795   Logically Collective
796 
797   Input Parameters:
798 + obj  - the PETSc object; this must be cast with (`PetscObject`), for example,
799          `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
800 - name - name associated with the child function
801 
802   Output Parameter:
803 . fptr - function pointer
804 
805   Level: advanced
806 
807 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`
808 M*/
809 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**fptr)(void))
810 {
811   PetscFunctionBegin;
812   PetscValidHeader(obj, 1);
813   PetscAssertPointer(name, 2);
814   PetscCall(PetscFunctionListFind(obj->qlist, name, fptr));
815   PetscFunctionReturn(PETSC_SUCCESS);
816 }
817 
818 struct _p_PetscContainer {
819   PETSCHEADER(int);
820   void *ptr;
821   PetscErrorCode (*userdestroy)(void *);
822 };
823 
824 /*@C
825   PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
826   provided with `PetscContainerSetPointer()`
827 
828   Logically Collective on the `PetscContainer` containing the user data
829 
830   Input Parameter:
831 . ctx - pointer to user-provided data
832 
833   Level: advanced
834 
835 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`, `PetscObject`
836 @*/
837 PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
838 {
839   PetscFunctionBegin;
840   PetscCall(PetscFree(ctx));
841   PetscFunctionReturn(PETSC_SUCCESS);
842 }
843 
844 /*@C
845   PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
846 
847   Not Collective
848 
849   Input Parameter:
850 . obj - the object created with `PetscContainerCreate()`
851 
852   Output Parameter:
853 . ptr - the pointer value
854 
855   Level: advanced
856 
857 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObject`,
858           `PetscContainerSetPointer()`
859 @*/
860 PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
861 {
862   PetscFunctionBegin;
863   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
864   PetscAssertPointer(ptr, 2);
865   *ptr = obj->ptr;
866   PetscFunctionReturn(PETSC_SUCCESS);
867 }
868 
869 /*@C
870   PetscContainerSetPointer - Sets the pointer value contained in the container.
871 
872   Logically Collective
873 
874   Input Parameters:
875 + obj - the object created with `PetscContainerCreate()`
876 - ptr - the pointer value
877 
878   Level: advanced
879 
880 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscObject`,
881           `PetscContainerGetPointer()`
882 @*/
883 PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
884 {
885   PetscFunctionBegin;
886   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
887   if (ptr) PetscAssertPointer(ptr, 2);
888   obj->ptr = ptr;
889   PetscFunctionReturn(PETSC_SUCCESS);
890 }
891 
892 /*@C
893   PetscContainerDestroy - Destroys a PETSc container object.
894 
895   Collective
896 
897   Input Parameter:
898 . obj - an object that was created with `PetscContainerCreate()`
899 
900   Level: advanced
901 
902   Note:
903   If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
904   then that function is called to destroy the data.
905 
906 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`, `PetscObject`
907 @*/
908 PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
909 {
910   PetscFunctionBegin;
911   if (!*obj) PetscFunctionReturn(PETSC_SUCCESS);
912   PetscValidHeaderSpecific(*obj, PETSC_CONTAINER_CLASSID, 1);
913   if (--((PetscObject)(*obj))->refct > 0) {
914     *obj = NULL;
915     PetscFunctionReturn(PETSC_SUCCESS);
916   }
917   if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
918   PetscCall(PetscHeaderDestroy(obj));
919   PetscFunctionReturn(PETSC_SUCCESS);
920 }
921 
922 /*@C
923   PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
924 
925   Logically Collective
926 
927   Input Parameters:
928 + obj - an object that was created with `PetscContainerCreate()`
929 - des - name of the user destroy function
930 
931   Level: advanced
932 
933   Note:
934   Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
935 
936 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`, `PetscObject`
937 @*/
938 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
939 {
940   PetscFunctionBegin;
941   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
942   obj->userdestroy = des;
943   PetscFunctionReturn(PETSC_SUCCESS);
944 }
945 
946 PetscClassId PETSC_CONTAINER_CLASSID;
947 
948 /*@C
949   PetscContainerCreate - Creates a PETSc object that has room to hold a single pointer.
950 
951   Collective
952 
953   Input Parameter:
954 . comm - MPI communicator that shares the object
955 
956   Output Parameter:
957 . container - the container created
958 
959   Level: advanced
960 
961   Notes:
962   This allows one to attach any type of data (accessible through a pointer) with the
963   `PetscObjectCompose()` function to a `PetscObject`. The data item itself is attached by a
964   call to `PetscContainerSetPointer()`.
965 
966 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
967           `PetscContainerSetUserDestroy()`, `PetscObject`
968 @*/
969 PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
970 {
971   PetscFunctionBegin;
972   PetscAssertPointer(container, 2);
973   PetscCall(PetscSysInitializePackage());
974   PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
975   PetscFunctionReturn(PETSC_SUCCESS);
976 }
977 
978 /*@
979   PetscObjectSetFromOptions - Sets generic parameters from user options.
980 
981   Collective
982 
983   Input Parameter:
984 . obj - the `PetscObject`
985 
986   Level: beginner
987 
988   Note:
989   We have no generic options at present, so this does nothing
990 
991 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`, `PetscObject`
992 @*/
993 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
994 {
995   PetscFunctionBegin;
996   PetscValidHeader(obj, 1);
997   PetscFunctionReturn(PETSC_SUCCESS);
998 }
999 
1000 /*@
1001   PetscObjectSetUp - Sets up the internal data structures for the later use.
1002 
1003   Collective
1004 
1005   Input Parameter:
1006 . obj - the `PetscObject`
1007 
1008   Level: advanced
1009 
1010   Note:
1011   This does nothing at present.
1012 
1013 .seealso: `PetscObjectDestroy()`, `PetscObject`
1014 @*/
1015 PetscErrorCode PetscObjectSetUp(PetscObject obj)
1016 {
1017   PetscFunctionBegin;
1018   PetscValidHeader(obj, 1);
1019   PetscFunctionReturn(PETSC_SUCCESS);
1020 }
1021