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