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