xref: /petsc/src/sys/objects/inherit.c (revision dbbe0bcd3f3a8fbab5a45420dc06f8387e5764c6)
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)(PetscObject,PetscOptionItems*,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 +   obj - the PETSc object
487 -   PetscOptionsObject - the options context
488 
489     Level: developer
490 
491 .seealso: `KSPSetFromOptions()`, `PCSetFromOptions()`, `SNESSetFromOptions()`, `PetscObjectAddOptionsHandler()`, `PetscObjectDestroyOptionsHandlers()`
492 
493 @*/
494 PetscErrorCode  PetscObjectProcessOptionsHandlers(PetscObject obj,PetscOptionItems *PetscOptionsObject)
495 {
496   PetscFunctionBegin;
497   PetscValidHeader(obj,1);
498   for (PetscInt i=0; i<obj->noptionhandler; i++) PetscCall((*obj->optionhandler[i])(obj,PetscOptionsObject,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    When the first argument of the function is the object within which it has been composed then `PetscTryMethod()` and `PetscUseMethod()`
758    can be used to call the function directly with error checking.
759 
760    To remove a registered routine, pass in NULL for fptr().
761 
762    PetscObjectComposeFunction() can be used with any PETSc object (such as
763    `Mat`, `Vec`, `KSP`, `SNES`, etc.) or any user-provided object.
764 
765    `PetscCallMethod()` is used to call a function that is stored in the objects obj->ops table.
766 
767 .seealso: `PetscObjectQueryFunction()`, `PetscContainerCreate()` `PetscObjectCompose()`, `PetscObjectQuery()`, `PetscTryMethod()`, `PetscUseMethod()`,
768           `PetscCallMethod()`
769 M*/
770 
771 PetscErrorCode  PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void))
772 {
773   PetscFunctionBegin;
774   PetscValidHeader(obj,1);
775   PetscValidCharPointer(name,2);
776   PetscCall((*obj->bops->composefunction)(obj,name,fptr));
777   PetscFunctionReturn(0);
778 }
779 
780 /*MC
781    PetscObjectQueryFunction - Gets a function associated with a given object.
782 
783     Synopsis:
784     #include <petscsys.h>
785     PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
786 
787    Logically Collective on PetscObject
788 
789    Input Parameters:
790 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
791          PetscObjectQueryFunction((PetscObject)ksp,...);
792 -  name - name associated with the child function
793 
794    Output Parameter:
795 .  fptr - function pointer
796 
797    Level: advanced
798 
799 .seealso: `PetscObjectComposeFunction()`, `PetscFunctionListFind()`, `PetscObjectCompose()`, `PetscObjectQuery()`
800 M*/
801 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void))
802 {
803   PetscFunctionBegin;
804   PetscValidHeader(obj,1);
805   PetscValidCharPointer(name,2);
806   PetscCall((*obj->bops->queryfunction)(obj,name,ptr));
807   PetscFunctionReturn(0);
808 }
809 
810 struct _p_PetscContainer {
811   PETSCHEADER(int);
812   void           *ptr;
813   PetscErrorCode (*userdestroy)(void*);
814 };
815 
816 /*@C
817    PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls `PetscFree()` in the data
818    provided with `PetscContainerSetPointer()`
819 
820    Logically Collective on `PetscContainer`
821 
822    Input Parameter:
823 .  ctx - pointer to user-provided data
824 
825    Level: advanced
826 
827 .seealso: `PetscContainerDestroy()`, `PetscContainerSetUserDestroy()`
828 @*/
829 PetscErrorCode PetscContainerUserDestroyDefault(void* ctx)
830 {
831   PetscFunctionBegin;
832   PetscCall(PetscFree(ctx));
833   PetscFunctionReturn(0);
834 }
835 
836 /*@C
837    PetscContainerGetPointer - Gets the pointer value contained in the container that was provided with `PetscContainerSetPointer()`
838 
839    Not Collective
840 
841    Input Parameter:
842 .  obj - the object created with `PetscContainerCreate()`
843 
844    Output Parameter:
845 .  ptr - the pointer value
846 
847    Level: advanced
848 
849 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`,
850           `PetscContainerSetPointer()`
851 @*/
852 PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
853 {
854   PetscFunctionBegin;
855   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
856   PetscValidPointer(ptr,2);
857   *ptr = obj->ptr;
858   PetscFunctionReturn(0);
859 }
860 
861 /*@C
862    PetscContainerSetPointer - Sets the pointer value contained in the container.
863 
864    Logically Collective on `PetscContainer`
865 
866    Input Parameters:
867 +  obj - the object created with `PetscContainerCreate()`
868 -  ptr - the pointer value
869 
870    Level: advanced
871 
872 .seealso: `PetscContainerCreate()`, `PetscContainerDestroy()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
873           `PetscContainerGetPointer()`
874 @*/
875 PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
876 {
877   PetscFunctionBegin;
878   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
879   if (ptr) PetscValidPointer(ptr,2);
880   obj->ptr = ptr;
881   PetscFunctionReturn(0);
882 }
883 
884 /*@C
885    PetscContainerDestroy - Destroys a PETSc container object.
886 
887    Collective on `PetscContainer`
888 
889    Input Parameter:
890 .  obj - an object that was created with `PetscContainerCreate()`
891 
892    Level: advanced
893 
894    Notes:
895    If `PetscContainerSetUserDestroy()` was used to provide a user destroy object for the data provided with `PetscContainerSetPointer()`
896    then that function is called to destroy the data.
897 
898 .seealso: `PetscContainerCreate()`, `PetscContainerSetUserDestroy()`
899 @*/
900 PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
901 {
902   PetscFunctionBegin;
903   if (!*obj) PetscFunctionReturn(0);
904   PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1);
905   if (--((PetscObject)(*obj))->refct > 0) {*obj = NULL; PetscFunctionReturn(0);}
906   if ((*obj)->userdestroy) PetscCall((*(*obj)->userdestroy)((*obj)->ptr));
907   PetscCall(PetscHeaderDestroy(obj));
908   PetscFunctionReturn(0);
909 }
910 
911 /*@C
912    PetscContainerSetUserDestroy - Sets name of the user destroy function for the data provided to the `PetscContainer` with `PetscContainerSetPointer()`
913 
914    Logically Collective on `PetscContainer`
915 
916    Input Parameters:
917 +  obj - an object that was created with `PetscContainerCreate()`
918 -  des - name of the user destroy function
919 
920    Notes:
921    Use `PetscContainerUserDestroyDefault()` if the memory was obtained by calling `PetscMalloc()` or one of its variants for single memory allocation.
922 
923    Level: advanced
924 
925 .seealso: `PetscContainerDestroy()`, `PetscContainerUserDestroyDefault()`, `PetscMalloc()`, `PetscMalloc1()`, `PetscCalloc()`, `PetscCalloc1()`
926 @*/
927 PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
928 {
929   PetscFunctionBegin;
930   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
931   obj->userdestroy = des;
932   PetscFunctionReturn(0);
933 }
934 
935 PetscClassId PETSC_CONTAINER_CLASSID;
936 
937 /*@C
938    PetscContainerCreate - Creates a PETSc object that has room to hold
939    a single pointer. This allows one to attach any type of data (accessible
940    through a pointer) with the `PetscObjectCompose()` function to a `PetscObject`.
941    The data item itself is attached by a call to `PetscContainerSetPointer()`.
942 
943    Collective
944 
945    Input Parameters:
946 .  comm - MPI communicator that shares the object
947 
948    Output Parameters:
949 .  container - the container created
950 
951    Level: advanced
952 
953 .seealso: `PetscContainerDestroy()`, `PetscContainerSetPointer()`, `PetscContainerGetPointer()`, `PetscObjectCompose()`, `PetscObjectQuery()`,
954           `PetscContainerSetUserDestroy()`
955 @*/
956 PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
957 {
958   PetscFunctionBegin;
959   PetscValidPointer(container,2);
960   PetscCall(PetscSysInitializePackage());
961   PetscCall(PetscHeaderCreate(*container,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL));
962   PetscFunctionReturn(0);
963 }
964 
965 /*@
966    PetscObjectSetFromOptions - Sets generic parameters from user options.
967 
968    Collective on obj
969 
970    Input Parameter:
971 .  obj - the `PetscObject`
972 
973    Options Database Keys:
974 
975    Notes:
976    We have no generic options at present, so this does nothing
977 
978    Level: beginner
979 
980 .seealso: `PetscObjectSetOptionsPrefix()`, `PetscObjectGetOptionsPrefix()`
981 @*/
982 PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
983 {
984   PetscFunctionBegin;
985   PetscValidHeader(obj,1);
986   PetscFunctionReturn(0);
987 }
988 
989 /*@
990    PetscObjectSetUp - Sets up the internal data structures for the later use.
991 
992    Collective on `PetscObject`
993 
994    Input Parameters:
995 .  obj - the `PetscObject`
996 
997    Notes:
998    This does nothing at present.
999 
1000    Level: advanced
1001 
1002 .seealso: `PetscObjectDestroy()`
1003 @*/
1004 PetscErrorCode  PetscObjectSetUp(PetscObject obj)
1005 {
1006   PetscFunctionBegin;
1007   PetscValidHeader(obj,1);
1008   PetscFunctionReturn(0);
1009 }
1010