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