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