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