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