xref: /petsc/src/sys/objects/inherit.c (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc)
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 on src
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;
347   #if defined(PETSC_USE_DEBUG)
348   PetscInt j, k = 0;
349   #endif
350   PetscObject h;
351 
352   PetscFunctionBegin;
353   if (PetscObjectsCounts) {
354     PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "The following objects were never freed\n"));
355     PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "-----------------------------------------\n"));
356     for (i = 0; i < PetscObjectsMaxCounts; i++) {
357       if ((h = PetscObjects[i])) {
358         PetscCall(PetscObjectName(h));
359         {
360   #if defined(PETSC_USE_DEBUG)
361           PetscStack *stack = NULL;
362           char       *create, *rclass;
363 
364           /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
365           PetscCall(PetscMallocGetStack(h, &stack));
366           if (stack) {
367             k = stack->currentsize - 2;
368             if (!all) {
369               k = 0;
370               while (!stack->petscroutine[k]) k++;
371               PetscCall(PetscStrstr(stack->function[k], "Create", &create));
372               if (!create) PetscCall(PetscStrstr(stack->function[k], "Get", &create));
373               PetscCall(PetscStrstr(stack->function[k], h->class_name, &rclass));
374               if (!create) continue;
375               if (!rclass) continue;
376             }
377           }
378   #endif
379 
380           PetscCall(PetscFPrintf(PETSC_COMM_WORLD, fd, "[%d] %s %s %s\n", PetscGlobalRank, h->class_name, h->type_name, h->name));
381 
382   #if defined(PETSC_USE_DEBUG)
383           PetscCall(PetscMallocGetStack(h, &stack));
384           if (stack) {
385             for (j = k; j >= 0; j--) fprintf(fd, "      [%d]  %s() in %s\n", PetscGlobalRank, stack->function[j], stack->file[j]);
386           }
387   #endif
388         }
389       }
390     }
391   }
392   PetscFunctionReturn(0);
393 }
394 #endif
395 
396 #if defined(PETSC_USE_LOG)
397 
398 /*@C
399    PetscObjectsView - Prints the currently existing objects.
400 
401    Logically Collective on viewer
402 
403    Input Parameter:
404 .  viewer - must be an `PETSCVIEWERASCII` viewer
405 
406    Level: advanced
407 
408 @*/
409 PetscErrorCode PetscObjectsView(PetscViewer viewer)
410 {
411   PetscBool isascii;
412   FILE     *fd;
413 
414   PetscFunctionBegin;
415   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
416   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
417   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
418   PetscCall(PetscViewerASCIIGetPointer(viewer, &fd));
419   PetscCall(PetscObjectsDump(fd, PETSC_TRUE));
420   PetscFunctionReturn(0);
421 }
422 
423 /*@C
424    PetscObjectsGetObject - Get a pointer to a named object
425 
426    Not collective
427 
428    Input Parameter:
429 .  name - the name of an object
430 
431    Output Parameters:
432 +  obj - the object or null if there is no object
433 -  classname - the name of the class
434 
435    Level: advanced
436 
437 @*/
438 PetscErrorCode PetscObjectsGetObject(const char *name, PetscObject *obj, char **classname)
439 {
440   PetscInt    i;
441   PetscObject h;
442   PetscBool   flg;
443 
444   PetscFunctionBegin;
445   PetscValidCharPointer(name, 1);
446   PetscValidPointer(obj, 2);
447   *obj = NULL;
448   for (i = 0; i < PetscObjectsMaxCounts; i++) {
449     if ((h = PetscObjects[i])) {
450       PetscCall(PetscObjectName(h));
451       PetscCall(PetscStrcmp(h->name, name, &flg));
452       if (flg) {
453         *obj = h;
454         if (classname) *classname = h->class_name;
455         PetscFunctionReturn(0);
456       }
457     }
458   }
459   PetscFunctionReturn(0);
460 }
461 #endif
462 
463 /*@
464    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
465 
466    Input Parameters:
467 .  obj  - the `PetscObject`
468 
469    Level: developer
470 
471    Developer Note:
472    This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
473    `PCBJACOBI` from all printing the same help messages to the screen
474 
475 .seealso: `PetscOptionsInsert()`
476 @*/
477 PetscErrorCode PetscObjectSetPrintedOptions(PetscObject obj)
478 {
479   PetscFunctionBegin;
480   PetscValidPointer(obj, 1);
481   obj->optionsprinted = PETSC_TRUE;
482   PetscFunctionReturn(0);
483 }
484 
485 /*@
486    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.
487 
488    Input Parameters:
489 +  pobj - the parent object
490 -  obj  - the PetscObject
491 
492    Level: developer
493 
494    Developer Notes:
495    This is used, for example to prevent sequential objects that are created from a parallel object; such as the `KSP` created by
496    `PCBJACOBI` from all printing the same help messages to the screen
497 
498    This will not handle more complicated situations like with `PCGASM` where children may live on any subset of the parent's processes and overlap
499 
500 .seealso: `PetscOptionsInsert()`, `PetscObjectSetPrintedOptions()`
501 @*/
502 PetscErrorCode PetscObjectInheritPrintedOptions(PetscObject pobj, PetscObject obj)
503 {
504   PetscMPIInt prank, size;
505 
506   PetscFunctionBegin;
507   PetscValidHeader(pobj, 1);
508   PetscValidHeader(obj, 2);
509   PetscCallMPI(MPI_Comm_rank(pobj->comm, &prank));
510   PetscCallMPI(MPI_Comm_size(obj->comm, &size));
511   if (size == 1 && prank > 0) obj->optionsprinted = PETSC_TRUE;
512   PetscFunctionReturn(0);
513 }
514 
515 /*@C
516     PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called.
517 
518     Not Collective
519 
520     Input Parameters:
521 +   obj - the PETSc object
522 .   handle - function that checks for options
523 .   destroy - function to destroy context if provided
524 -   ctx - optional context for check function
525 
526     Level: developer
527 
528 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectProcessOptionsHandlers()`, `PetscObjectDestroyOptionsHandlers()`
529 @*/
530 PetscErrorCode PetscObjectAddOptionsHandler(PetscObject obj, PetscErrorCode (*handle)(PetscObject, PetscOptionItems *, void *), PetscErrorCode (*destroy)(PetscObject, void *), void *ctx)
531 {
532   PetscFunctionBegin;
533   PetscValidHeader(obj, 1);
534   PetscCheck(obj->noptionhandler < PETSC_MAX_OPTIONS_HANDLER, obj->comm, PETSC_ERR_ARG_OUTOFRANGE, "To many options handlers added");
535   obj->optionhandler[obj->noptionhandler] = handle;
536   obj->optiondestroy[obj->noptionhandler] = destroy;
537   obj->optionctx[obj->noptionhandler++]   = ctx;
538   PetscFunctionReturn(0);
539 }
540 
541 /*@C
542     PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
543 
544     Not Collective
545 
546     Input Parameters:
547 +   obj - the PETSc object
548 -   PetscOptionsObject - the options context
549 
550     Level: developer
551 
552 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`
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(0);
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 @*/
574 PetscErrorCode PetscObjectDestroyOptionsHandlers(PetscObject obj)
575 {
576   PetscFunctionBegin;
577   PetscValidHeader(obj, 1);
578   for (PetscInt i = 0; i < obj->noptionhandler; i++) {
579     if (obj->optiondestroy[i]) PetscCall((*obj->optiondestroy[i])(obj, obj->optionctx[i]));
580   }
581   obj->noptionhandler = 0;
582   PetscFunctionReturn(0);
583 }
584 
585 /*@C
586    PetscObjectReference - Indicates to any `PetscObject` that it is being
587    referenced by another `PetscObject`. This increases the reference
588    count for that object by one.
589 
590    Logically Collective on obj
591 
592    Input Parameter:
593 .  obj - the PETSc object. This must be cast with (`PetscObject`), for example,
594          `PetscObjectReference`((`PetscObject`)mat);
595 
596    Level: advanced
597 
598 .seealso: `PetscObjectCompose()`, `PetscObjectDereference()`
599 @*/
600 PetscErrorCode PetscObjectReference(PetscObject obj)
601 {
602   PetscFunctionBegin;
603   if (!obj) PetscFunctionReturn(0);
604   PetscValidHeader(obj, 1);
605   obj->refct++;
606   PetscFunctionReturn(0);
607 }
608 
609 /*@C
610    PetscObjectGetReference - Gets the current reference count for
611    any 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()`
625 @*/
626 PetscErrorCode PetscObjectGetReference(PetscObject obj, PetscInt *cnt)
627 {
628   PetscFunctionBegin;
629   PetscValidHeader(obj, 1);
630   PetscValidIntPointer(cnt, 2);
631   *cnt = obj->refct;
632   PetscFunctionReturn(0);
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    Note:
647     `PetscObjectDestroy()` sets the obj pointer to null after the call, this routine does not.
648 
649    Level: advanced
650 
651 .seealso: `PetscObjectCompose()`, `PetscObjectReference()`, `PetscObjectDestroy()`
652 @*/
653 PetscErrorCode PetscObjectDereference(PetscObject obj)
654 {
655   PetscFunctionBegin;
656   if (!obj) PetscFunctionReturn(0);
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(0);
661 }
662 
663 /* ----------------------------------------------------------------------- */
664 /*
665      The following routines are the versions private to the PETSc object
666      data structures.
667 */
668 PetscErrorCode PetscObjectRemoveReference(PetscObject obj, const char name[])
669 {
670   PetscFunctionBegin;
671   PetscValidHeader(obj, 1);
672   PetscCall(PetscObjectListRemoveReference(&obj->olist, name));
673   PetscFunctionReturn(0);
674 }
675 
676 PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj, const char name[], PetscObject ptr)
677 {
678   PetscFunctionBegin;
679   if (ptr) {
680     char     *tname;
681     PetscBool skipreference;
682 
683     PetscCall(PetscObjectListReverseFind(ptr->olist, obj, &tname, &skipreference));
684     if (tname) PetscCheck(skipreference, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "An object cannot be composed with an object that was composed with it");
685   }
686   PetscCall(PetscObjectListAdd(&obj->olist, name, ptr));
687   PetscFunctionReturn(0);
688 }
689 
690 PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj, const char name[], PetscObject *ptr)
691 {
692   PetscFunctionBegin;
693   PetscValidHeader(obj, 1);
694   PetscCall(PetscObjectListFind(obj->olist, name, ptr));
695   PetscFunctionReturn(0);
696 }
697 
698 PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj, const char name[], void (*ptr)(void))
699 {
700   PetscFunctionBegin;
701   PetscValidHeader(obj, 1);
702   PetscCall(PetscFunctionListAdd(&obj->qlist, name, ptr));
703   PetscFunctionReturn(0);
704 }
705 
706 PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj, const char name[], void (**ptr)(void))
707 {
708   PetscFunctionBegin;
709   PetscValidHeader(obj, 1);
710   PetscCall(PetscFunctionListFind(obj->qlist, name, ptr));
711   PetscFunctionReturn(0);
712 }
713 
714 /*@C
715    PetscObjectCompose - Associates another PETSc object with a given PETSc object.
716 
717    Not Collective
718 
719    Input Parameters:
720 +  obj - the PETSc object; this must be cast with (`PetscObject`), for example,
721          `PetscObjectCompose`((`PetscObject`)mat,...);
722 .  name - name associated with the child object
723 -  ptr - the other PETSc object to associate with the PETSc object; this must also be
724          cast with (`PetscObject`)
725 
726    Level: advanced
727 
728    Notes:
729    The second objects reference count is automatically increased by one when it is
730    composed.
731 
732    Replaces any previous object that had the same name.
733 
734    If ptr is null and name has previously been composed using an object, then that
735    entry is removed from the obj.
736 
737    `PetscObjectCompose()` can be used with any PETSc object (such as
738    `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
739 
740    `PetscContainerCreate()` can be used to create an object from a
741    user-provided pointer that may then be composed with PETSc objects using `PetscObjectCompose()`
742 
743 .seealso: `PetscObjectQuery()`, `PetscContainerCreate()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`,
744           `PetscContainerSetPointer()`
745 @*/
746 PetscErrorCode PetscObjectCompose(PetscObject obj, const char name[], PetscObject ptr)
747 {
748   PetscFunctionBegin;
749   PetscValidHeader(obj, 1);
750   PetscValidCharPointer(name, 2);
751   if (ptr) PetscValidHeader(ptr, 3);
752   PetscCheck(obj != ptr, PetscObjectComm((PetscObject)obj), PETSC_ERR_SUP, "Cannot compose object with itself");
753   PetscCall((*obj->bops->compose)(obj, name, ptr));
754   PetscFunctionReturn(0);
755 }
756 
757 /*@C
758    PetscObjectQuery  - Gets a PETSc object associated with a given object that was composed with `PetscObjectCompose()`
759 
760    Not Collective
761 
762    Input Parameters:
763 +  obj - the PETSc object
764          Thus must be cast with a (`PetscObject`), for example,
765          `PetscObjectCompose`((`PetscObject`)mat,...);
766 .  name - name associated with child object
767 -  ptr - the other PETSc object associated with the PETSc object, this must be
768          cast with (`PetscObject`*)
769 
770    Level: advanced
771 
772    Note:
773    The reference count of neither object is increased in this call
774 
775 .seealso: `PetscObjectCompose()`, `PetscObjectComposeFunction()`, `PetscObjectQueryFunction()`, `PetscContainer`
776           `PetscContainerGetPointer()`
777 @*/
778 PetscErrorCode PetscObjectQuery(PetscObject obj, const char name[], PetscObject *ptr)
779 {
780   PetscFunctionBegin;
781   PetscValidHeader(obj, 1);
782   PetscValidCharPointer(name, 2);
783   PetscValidPointer(ptr, 3);
784   PetscCall((*obj->bops->query)(obj, name, ptr));
785   PetscFunctionReturn(0);
786 }
787 
788 /*MC
789    PetscObjectComposeFunction - Associates a function with a given PETSc object.
790 
791     Synopsis:
792     #include <petscsys.h>
793     PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void))
794 
795    Logically Collective on obj
796 
797    Input Parameters:
798 +  obj - the PETSc object; this must be cast with a (`PetscObject`), for example,
799          `PetscObjectCompose`((`PetscObject`)mat,...);
800 .  name - name associated with the child function
801 .  fname - name of the function
802 -  fptr - function pointer
803 
804    Level: advanced
805 
806    Notes:
807    When the first argument of the function is the object within which it has been composed then `PetscTryMethod()` and `PetscUseMethod()`
808    can be used to call the function directly with error checking.
809 
810    To remove a registered routine, pass in NULL for fptr().
811 
812    PetscObjectComposeFunction() can be used with any PETSc object (such as
813    `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
814 
815    `PetscCallMethod()` is used to call a function that is stored in the objects obj->ops table.
816 
817 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
818           `PetscCallMethod()`
819 M*/
820 
821 PetscErrorCode PetscObjectComposeFunction_Private(PetscObject obj, const char name[], void (*fptr)(void))
822 {
823   PetscFunctionBegin;
824   PetscValidHeader(obj, 1);
825   PetscValidCharPointer(name, 2);
826   PetscCall((*obj->bops->composefunction)(obj, name, fptr));
827   PetscFunctionReturn(0);
828 }
829 
830 /*MC
831    PetscObjectQueryFunction - Gets a function associated with a given object.
832 
833     Synopsis:
834     #include <petscsys.h>
835     PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
836 
837    Logically Collective on obj
838 
839    Input Parameters:
840 +  obj - the PETSc object; this must be cast with (`PetscObject`), for example,
841          `PetscObjectQueryFunction`((`PetscObject`)ksp,...);
842 -  name - name associated with the child function
843 
844    Output Parameter:
845 .  fptr - function pointer
846 
847    Level: advanced
848 
849 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`
850 M*/
851 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj, const char name[], void (**ptr)(void))
852 {
853   PetscFunctionBegin;
854   PetscValidHeader(obj, 1);
855   PetscValidCharPointer(name, 2);
856   PetscCall((*obj->bops->queryfunction)(obj, name, ptr));
857   PetscFunctionReturn(0);
858 }
859 
860 struct _p_PetscContainer {
861   PETSCHEADER(int);
862   void *ptr;
863   PetscErrorCode (*userdestroy)(void *);
864 };
865 
866 /*@C
867    PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
868    provided with `PetscContainerSetPointer()`
869 
870    Logically Collective on the `PetscContainer` containing the user data
871 
872    Input Parameter:
873 .  ctx - pointer to user-provided data
874 
875    Level: advanced
876 
877 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`
878 @*/
879 PetscErrorCode PetscContainerUserDestroyDefault(void *ctx)
880 {
881   PetscFunctionBegin;
882   PetscCall(PetscFree(ctx));
883   PetscFunctionReturn(0);
884 }
885 
886 /*@C
887    PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
888 
889    Not Collective
890 
891    Input Parameter:
892 .  obj - the object created with `PetscContainerCreate()`
893 
894    Output Parameter:
895 .  ptr - the pointer value
896 
897    Level: advanced
898 
899 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`,
900           `PetscContainerSetPointer()`
901 @*/
902 PetscErrorCode PetscContainerGetPointer(PetscContainer obj, void **ptr)
903 {
904   PetscFunctionBegin;
905   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
906   PetscValidPointer(ptr, 2);
907   *ptr = obj->ptr;
908   PetscFunctionReturn(0);
909 }
910 
911 /*@C
912    PetscContainerSetPointer - Sets the pointer value contained in the container.
913 
914    Logically Collective on obj
915 
916    Input Parameters:
917 +  obj - the object created with `PetscContainerCreate()`
918 -  ptr - the pointer value
919 
920    Level: advanced
921 
922 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
923           `PetscContainerGetPointer()`
924 @*/
925 PetscErrorCode PetscContainerSetPointer(PetscContainer obj, void *ptr)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
929   if (ptr) PetscValidPointer(ptr, 2);
930   obj->ptr = ptr;
931   PetscFunctionReturn(0);
932 }
933 
934 /*@C
935    PetscContainerDestroy - Destroys a PETSc container object.
936 
937    Collective on obj
938 
939    Input Parameter:
940 .  obj - an object that was created with `PetscContainerCreate()`
941 
942    Level: advanced
943 
944    Note:
945    If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
946    then that function is called to destroy the data.
947 
948 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`
949 @*/
950 PetscErrorCode PetscContainerDestroy(PetscContainer *obj)
951 {
952   PetscFunctionBegin;
953   if (!*obj) PetscFunctionReturn(0);
954   PetscValidHeaderSpecific(*obj, PETSC_CONTAINER_CLASSID, 1);
955   if (--((PetscObject)(*obj))->refct > 0) {
956     *obj = NULL;
957     PetscFunctionReturn(0);
958   }
959   if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
960   PetscCall(PetscHeaderDestroy(obj));
961   PetscFunctionReturn(0);
962 }
963 
964 /*@C
965    PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
966 
967    Logically Collective on obj
968 
969    Input Parameters:
970 +  obj - an object that was created with `PetscContainerCreate()`
971 -  des - name of the user destroy function
972 
973    Note:
974    Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
975 
976    Level: advanced
977 
978 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`
979 @*/
980 PetscErrorCode PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void *))
981 {
982   PetscFunctionBegin;
983   PetscValidHeaderSpecific(obj, PETSC_CONTAINER_CLASSID, 1);
984   obj->userdestroy = des;
985   PetscFunctionReturn(0);
986 }
987 
988 PetscClassId PETSC_CONTAINER_CLASSID;
989 
990 /*@C
991    PetscContainerCreate - Creates a PETSc object that has room to hold
992    a single pointer. This allows one to attach any type of data (accessible
993    through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`.
994    The data item itself is attached by a call to `PetscContainerSetPointer()`.
995 
996    Collective
997 
998    Input Parameters:
999 .  comm - MPI communicator that shares the object
1000 
1001    Output Parameters:
1002 .  container - the container created
1003 
1004    Level: advanced
1005 
1006 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
1007           `PetscContainerSetUserDestroy()`
1008 @*/
1009 PetscErrorCode PetscContainerCreate(MPI_Comm comm, PetscContainer *container)
1010 {
1011   PetscFunctionBegin;
1012   PetscValidPointer(container, 2);
1013   PetscCall(PetscSysInitializePackage());
1014   PetscCall(PetscHeaderCreate(*container, PETSC_CONTAINER_CLASSID, "PetscContainer", "Container", "Sys", comm, PetscContainerDestroy, NULL));
1015   PetscFunctionReturn(0);
1016 }
1017 
1018 /*@
1019    PetscObjectSetFromOptions - Sets generic parameters from user options.
1020 
1021    Collective on obj
1022 
1023    Input Parameter:
1024 .  obj - the `PetscObject`
1025 
1026    Note:
1027    We have no generic options at present, so this does nothing
1028 
1029    Level: beginner
1030 
1031 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`
1032 @*/
1033 PetscErrorCode PetscObjectSetFromOptions(PetscObject obj)
1034 {
1035   PetscFunctionBegin;
1036   PetscValidHeader(obj, 1);
1037   PetscFunctionReturn(0);
1038 }
1039 
1040 /*@
1041    PetscObjectSetUp - Sets up the internal data structures for the later use.
1042 
1043    Collective on obj
1044 
1045    Input Parameters:
1046 .  obj - the `PetscObject`
1047 
1048    Note:
1049    This does nothing at present.
1050 
1051    Level: advanced
1052 
1053 .seealso: `PetscObjectDestroy()`
1054 @*/
1055 PetscErrorCode PetscObjectSetUp(PetscObject obj)
1056 {
1057   PetscFunctionBegin;
1058   PetscValidHeader(obj, 1);
1059   PetscFunctionReturn(0);
1060 }
1061