xref: /petsc/src/sys/objects/inherit.c (revision 9a2402e950ff689ca19bdb3cbaeb3a7b77642051)
1 
2 /*
3      Provides utility routines for manipulating any type of PETSc object.
4 */
5 #include <petscsys.h>  /*I   "petscsys.h"    I*/
6 
7 PetscObject *PetscObjects = 0;
8 PetscInt    PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;
9 
10 extern PetscErrorCode PetscObjectGetComm_Petsc(PetscObject,MPI_Comm *);
11 extern PetscErrorCode PetscObjectCompose_Petsc(PetscObject,const char[],PetscObject);
12 extern PetscErrorCode PetscObjectQuery_Petsc(PetscObject,const char[],PetscObject *);
13 extern PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject,const char[],const char[],void (*)(void));
14 extern PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject,const char[],void (**)(void));
15 
16 #undef __FUNCT__
17 #define __FUNCT__ "PetscHeaderCreate_Private"
18 /*
19    PetscHeaderCreate_Private - Creates a base PETSc object header and fills
20    in the default values.  Called by the macro PetscHeaderCreate().
21 */
22 PetscErrorCode  PetscHeaderCreate_Private(PetscObject h,PetscClassId classid,PetscInt type,const char class_name[],MPI_Comm comm,
23                                          PetscErrorCode (*des)(PetscObject*),PetscErrorCode (*vie)(PetscObject,PetscViewer))
24 {
25   static PetscInt idcnt = 1;
26   PetscErrorCode  ierr;
27   PetscObject     *newPetscObjects;
28   PetscInt         newPetscObjectsMaxCounts,i;
29 
30   PetscFunctionBegin;
31   h->classid                = classid;
32   h->type                   = type;
33   h->class_name             = (char*)class_name;
34   h->prefix                 = 0;
35   h->refct                  = 1;
36   h->amem                   = -1;
37   h->id                     = idcnt++;
38   h->parentid               = 0;
39   h->qlist                  = 0;
40   h->olist                  = 0;
41   h->precision              = (PetscPrecision) sizeof(PetscScalar);
42   h->bops->destroy          = des;
43   h->bops->view             = vie;
44   h->bops->getcomm          = PetscObjectGetComm_Petsc;
45   h->bops->compose          = PetscObjectCompose_Petsc;
46   h->bops->query            = PetscObjectQuery_Petsc;
47   h->bops->composefunction  = PetscObjectComposeFunction_Petsc;
48   h->bops->queryfunction    = PetscObjectQueryFunction_Petsc;
49   ierr = PetscCommDuplicate(comm,&h->comm,&h->tag);CHKERRQ(ierr);
50 
51   /* Keep a record of object created */
52   PetscObjectsCounts++;
53   for (i=0; i<PetscObjectsMaxCounts; i++) {
54     if (!PetscObjects[i]) {
55       PetscObjects[i] = h;
56       PetscFunctionReturn(0);
57     }
58   }
59   /* Need to increase the space for storing PETSc objects */
60   if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
61   else                        newPetscObjectsMaxCounts = 2*PetscObjectsMaxCounts;
62   ierr = PetscMalloc(newPetscObjectsMaxCounts*sizeof(PetscObject),&newPetscObjects);CHKERRQ(ierr);
63   ierr = PetscMemcpy(newPetscObjects,PetscObjects,PetscObjectsMaxCounts*sizeof(PetscObject));CHKERRQ(ierr);
64   ierr = PetscMemzero(newPetscObjects+PetscObjectsMaxCounts,(newPetscObjectsMaxCounts - PetscObjectsMaxCounts)*sizeof(PetscObject));CHKERRQ(ierr);
65   ierr = PetscFree(PetscObjects);CHKERRQ(ierr);
66   PetscObjects                        = newPetscObjects;
67   PetscObjects[PetscObjectsMaxCounts] = h;
68   PetscObjectsMaxCounts               = newPetscObjectsMaxCounts;
69 
70   PetscFunctionReturn(0);
71 }
72 
73 extern PetscBool      PetscMemoryCollectMaximumUsage;
74 extern PetscLogDouble PetscMemoryMaximumUsage;
75 
76 #undef __FUNCT__
77 #define __FUNCT__ "PetscHeaderDestroy_Private"
78 /*
79     PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
80     the macro PetscHeaderDestroy().
81 */
82 PetscErrorCode  PetscHeaderDestroy_Private(PetscObject h)
83 {
84   PetscErrorCode ierr;
85   PetscInt       i;
86 
87   PetscFunctionBegin;
88 #if defined(PETSC_HAVE_AMS)
89   if (PetscAMSPublishAll) {
90     ierr = PetscObjectUnPublish((PetscObject)h);CHKERRQ(ierr);
91   }
92 #endif
93   if (PetscMemoryCollectMaximumUsage) {
94     PetscLogDouble usage;
95     ierr = PetscMemoryGetCurrentUsage(&usage);CHKERRQ(ierr);
96     if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
97   }
98   /* first destroy things that could execute arbitrary code */
99   if (h->python_destroy) {
100     void           *python_context          = h->python_context;
101     PetscErrorCode (*python_destroy)(void*) = h->python_destroy;
102     h->python_context = 0;
103     h->python_destroy = 0;
104     ierr = (*python_destroy)(python_context);CHKERRQ(ierr);
105   }
106   ierr = PetscOListDestroy(&h->olist);CHKERRQ(ierr);
107   ierr = PetscCommDestroy(&h->comm);CHKERRQ(ierr);
108   /* next destroy other things */
109   h->classid = PETSCFREEDHEADER;
110   ierr = PetscFree(h->bops);CHKERRQ(ierr);
111   ierr = PetscFListDestroy(&h->qlist);CHKERRQ(ierr);
112   ierr = PetscFree(h->type_name);CHKERRQ(ierr);
113   ierr = PetscFree(h->name);CHKERRQ(ierr);
114   ierr = PetscFree(h->prefix);CHKERRQ(ierr);
115   ierr = PetscFree(h->fortran_func_pointers);CHKERRQ(ierr);
116 
117   /* Record object removal from list of all objects */
118   for (i=0; i<PetscObjectsMaxCounts; i++) {
119     if (PetscObjects[i] == h) {
120       PetscObjects[i] = 0;
121       PetscObjectsCounts--;
122       break;
123     }
124   }
125   if (!PetscObjectsCounts) {
126     ierr = PetscFree(PetscObjects);CHKERRQ(ierr);
127     PetscObjectsMaxCounts = 0;
128   }
129   PetscFunctionReturn(0);
130 }
131 
132 #undef __FUNCT__
133 #define __FUNCT__ "PetscObjectsView"
134 /*@C
135    PetscObjectsView - Prints the currently existing objects.
136 
137    Logically Collective on PetscViewer
138 
139    Input Parameter:
140 .  viewer - must be an PETSCVIEWERASCII viewer
141 
142    Level: advanced
143 
144    Concepts: options database^printing
145 
146 @*/
147 PetscErrorCode  PetscObjectsView(PetscViewer viewer)
148 {
149   PetscErrorCode ierr;
150   PetscInt       i;
151   PetscBool      isascii;
152   PetscObject    h;
153 
154   PetscFunctionBegin;
155   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
156   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
157   if (!isascii) SETERRQ(((PetscObject)viewer)->comm,PETSC_ERR_SUP,"Only supports ASCII viewer");
158 
159   for (i=0; i<PetscObjectsMaxCounts; i++) {
160     if ((h = PetscObjects[i])) {
161       ierr = PetscObjectName(h);CHKERRQ(ierr);
162       ierr = PetscViewerASCIIPrintf(viewer,"%s %s %s\n",h->class_name,h->type_name,h->name);CHKERRQ(ierr);
163     }
164   }
165   PetscFunctionReturn(0);
166 }
167 
168 #undef __FUNCT__
169 #define __FUNCT__ "PetscObjectsGetObject"
170 /*@C
171    PetscObjectsGetObject - Get a pointer to a named object
172 
173    Not collective
174 
175    Input Parameter:
176 .  name - the name of an object
177 
178    Output Parameter:
179 .   obj - the object or null if there is no object
180 
181    Level: advanced
182 
183    Concepts: options database^printing
184 
185 @*/
186 PetscErrorCode  PetscObjectsGetObject(const char* name,PetscObject *obj,char **classname)
187 {
188   PetscErrorCode ierr;
189   PetscInt       i;
190   PetscObject    h;
191   PetscBool      flg;
192 
193   PetscFunctionBegin;
194   *obj = PETSC_NULL;
195   for (i=0; i<PetscObjectsMaxCounts; i++) {
196     if ((h = PetscObjects[i])) {
197       ierr = PetscObjectName(h);CHKERRQ(ierr);
198       ierr = PetscStrcmp(h->name,name,&flg);CHKERRQ(ierr);
199       if (flg) {
200         *obj = h;
201         if (classname) *classname = h->class_name;
202         PetscFunctionReturn(0);
203       }
204     }
205   }
206   PetscFunctionReturn(0);
207 }
208 
209 #undef __FUNCT__
210 #define __FUNCT__ "PetscObjectsGetObjectMatlab"
211 char* PetscObjectsGetObjectMatlab(const char* name,PetscObject *obj)
212 {
213   PetscErrorCode ierr;
214   PetscInt       i;
215   PetscObject    h;
216   PetscBool      flg;
217 
218   PetscFunctionBegin;
219   *obj = PETSC_NULL;
220   for (i=0; i<PetscObjectsMaxCounts; i++) {
221     if ((h = PetscObjects[i])) {
222       ierr = PetscObjectName(h);if (ierr) PetscFunctionReturn(0);
223       ierr = PetscStrcmp(h->name,name,&flg);if (ierr) PetscFunctionReturn(0);
224       if (flg) {
225         *obj = h;
226         PetscFunctionReturn(h->class_name);
227       }
228     }
229   }
230   PetscFunctionReturn(0);
231 }
232 
233 #undef __FUNCT__
234 #define __FUNCT__ "PetscObjectAddOptionsHandler"
235 /*@C
236     PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called.
237 
238     Not Collective
239 
240     Input Parameter:
241 +   obj - the PETSc object
242 .   handle - function that checks for options
243 .   destroy - function to destroy context if provided
244 -   ctx - optional context for check function
245 
246     Level: developer
247 
248 
249 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectProcessOptionsHandlers(), PetscObjectDestroyOptionsHandlers()
250 
251 @*/
252 PetscErrorCode  PetscObjectAddOptionsHandler(PetscObject obj,PetscErrorCode (*handle)(PetscObject,void*),PetscErrorCode (*destroy)(PetscObject,void*),void *ctx)
253 {
254   PetscFunctionBegin;
255   if (obj->noptionhandler >= PETSC_MAX_OPTIONS_HANDLER) SETERRQ(obj->comm,PETSC_ERR_ARG_OUTOFRANGE,"To many options handlers added");
256   obj->optionhandler[obj->noptionhandler]   = handle;
257   obj->optiondestroy[obj->noptionhandler]   = destroy;
258   obj->optionctx[obj->noptionhandler++]     = ctx;
259   PetscFunctionReturn(0);
260 }
261 
262 #undef __FUNCT__
263 #define __FUNCT__ "PetscObjectProcessOptionsHandlers"
264 /*@C
265     PetscObjectProcessOptionsHandlers - Calls all the options handler attached to an object
266 
267     Not Collective
268 
269     Input Parameter:
270 .   obj - the PETSc object
271 
272     Level: developer
273 
274 
275 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectDestroyOptionsHandlers()
276 
277 @*/
278 PetscErrorCode  PetscObjectProcessOptionsHandlers(PetscObject obj)
279 {
280   PetscInt       i;
281   PetscErrorCode ierr;
282 
283   PetscFunctionBegin;
284   for (i=0; i<obj->noptionhandler; i++) {
285     ierr = (*obj->optionhandler[i])(obj,obj->optionctx[i]);CHKERRQ(ierr);
286   }
287   PetscFunctionReturn(0);
288 }
289 
290 #undef __FUNCT__
291 #define __FUNCT__ "PetscObjectDestroyOptionsHandlers"
292 /*@C
293     PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an objeft
294 
295     Not Collective
296 
297     Input Parameter:
298 .   obj - the PETSc object
299 
300     Level: developer
301 
302 
303 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectProcessOptionsHandlers()
304 
305 @*/
306 PetscErrorCode  PetscObjectDestroyOptionsHandlers(PetscObject obj)
307 {
308   PetscInt       i;
309   PetscErrorCode ierr;
310 
311   PetscFunctionBegin;
312   for (i=0; i<obj->noptionhandler; i++) {
313     ierr = (*obj->optiondestroy[i])(obj,obj->optionctx[i]);CHKERRQ(ierr);
314   }
315   obj->noptionhandler = 0;
316   PetscFunctionReturn(0);
317 }
318 
319 
320 #undef __FUNCT__
321 #define __FUNCT__ "PetscObjectReference"
322 /*@
323    PetscObjectReference - Indicates to any PetscObject that it is being
324    referenced by another PetscObject. This increases the reference
325    count for that object by one.
326 
327    Logically Collective on PetscObject
328 
329    Input Parameter:
330 .  obj - the PETSc object. This must be cast with (PetscObject), for example,
331          PetscObjectReference((PetscObject)mat);
332 
333    Level: advanced
334 
335 .seealso: PetscObjectCompose(), PetscObjectDereference()
336 @*/
337 PetscErrorCode  PetscObjectReference(PetscObject obj)
338 {
339   PetscFunctionBegin;
340   PetscValidHeader(obj,1);
341   obj->refct++;
342   PetscFunctionReturn(0);
343 }
344 
345 #undef __FUNCT__
346 #define __FUNCT__ "PetscObjectGetReference"
347 /*@
348    PetscObjectGetReference - Gets the current reference count for
349    any PETSc object.
350 
351    Not Collective
352 
353    Input Parameter:
354 .  obj - the PETSc object; this must be cast with (PetscObject), for example,
355          PetscObjectGetReference((PetscObject)mat,&cnt);
356 
357    Output Parameter:
358 .  cnt - the reference count
359 
360    Level: advanced
361 
362 .seealso: PetscObjectCompose(), PetscObjectDereference(), PetscObjectReference()
363 @*/
364 PetscErrorCode  PetscObjectGetReference(PetscObject obj,PetscInt *cnt)
365 {
366   PetscFunctionBegin;
367   PetscValidHeader(obj,1);
368   PetscValidIntPointer(cnt,2);
369   *cnt = obj->refct;
370   PetscFunctionReturn(0);
371 }
372 
373 #undef __FUNCT__
374 #define __FUNCT__ "PetscObjectDereference"
375 /*@
376    PetscObjectDereference - Indicates to any PetscObject that it is being
377    referenced by one less PetscObject. This decreases the reference
378    count for that object by one.
379 
380    Collective on PetscObject if reference reaches 0 otherwise Logically Collective
381 
382    Input Parameter:
383 .  obj - the PETSc object; this must be cast with (PetscObject), for example,
384          PetscObjectDereference((PetscObject)mat);
385 
386    Notes: PetscObjectDestroy(PetscObject *obj)  sets the obj pointer to null after the call, this routine does not.
387 
388    Level: advanced
389 
390 .seealso: PetscObjectCompose(), PetscObjectReference()
391 @*/
392 PetscErrorCode  PetscObjectDereference(PetscObject obj)
393 {
394   PetscErrorCode ierr;
395 
396   PetscFunctionBegin;
397   PetscValidHeader(obj,1);
398   if (obj->bops->destroy) {
399     ierr = (*obj->bops->destroy)(&obj);CHKERRQ(ierr);
400   } else if (!--obj->refct) {
401     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"This PETSc object does not have a generic destroy routine");
402   }
403   PetscFunctionReturn(0);
404 }
405 
406 /* ----------------------------------------------------------------------- */
407 /*
408      The following routines are the versions private to the PETSc object
409      data structures.
410 */
411 #undef __FUNCT__
412 #define __FUNCT__ "PetscObjectGetComm_Petsc"
413 PetscErrorCode PetscObjectGetComm_Petsc(PetscObject obj,MPI_Comm *comm)
414 {
415   PetscFunctionBegin;
416   *comm = obj->comm;
417   PetscFunctionReturn(0);
418 }
419 
420 #undef __FUNCT__
421 #define __FUNCT__ "PetscObjectCompose_Petsc"
422 PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr)
423 {
424   PetscErrorCode ierr;
425   char           *tname;
426 
427   PetscFunctionBegin;
428   if (ptr) {
429     ierr = PetscOListReverseFind(ptr->olist,obj,&tname);CHKERRQ(ierr);
430     if (tname) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"An object cannot be composed with an object that was compose with it");
431   }
432   ierr = PetscOListAdd(&obj->olist,name,ptr);CHKERRQ(ierr);
433   PetscFunctionReturn(0);
434 }
435 
436 #undef __FUNCT__
437 #define __FUNCT__ "PetscObjectQuery_Petsc"
438 PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char name[],PetscObject *ptr)
439 {
440   PetscErrorCode ierr;
441 
442   PetscFunctionBegin;
443   ierr = PetscOListFind(obj->olist,name,ptr);CHKERRQ(ierr);
444   PetscFunctionReturn(0);
445 }
446 
447 #undef __FUNCT__
448 #define __FUNCT__ "PetscObjectComposeFunction_Petsc"
449 PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char name[],const char fname[],void (*ptr)(void))
450 {
451   PetscErrorCode ierr;
452 
453   PetscFunctionBegin;
454   ierr = PetscFListAdd(&obj->qlist,name,fname,ptr);CHKERRQ(ierr);
455   PetscFunctionReturn(0);
456 }
457 
458 #undef __FUNCT__
459 #define __FUNCT__ "PetscObjectQueryFunction_Petsc"
460 PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char name[],void (**ptr)(void))
461 {
462   PetscErrorCode ierr;
463 
464   PetscFunctionBegin;
465   ierr = PetscFListFind(obj->qlist,obj->comm,name,PETSC_FALSE,ptr);CHKERRQ(ierr);
466   PetscFunctionReturn(0);
467 }
468 
469 #undef __FUNCT__
470 #define __FUNCT__ "PetscObjectCompose"
471 /*@C
472    PetscObjectCompose - Associates another PETSc object with a given PETSc object.
473 
474    Not Collective
475 
476    Input Parameters:
477 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
478          PetscObjectCompose((PetscObject)mat,...);
479 .  name - name associated with the child object
480 -  ptr - the other PETSc object to associate with the PETSc object; this must also be
481          cast with (PetscObject)
482 
483    Level: advanced
484 
485    Notes:
486    The second objects reference count is automatically increased by one when it is
487    composed.
488 
489    Replaces any previous object that had the same name.
490 
491    If ptr is null and name has previously been composed using an object, then that
492    entry is removed from the obj.
493 
494    PetscObjectCompose() can be used with any PETSc object (such as
495    Mat, Vec, KSP, SNES, etc.) or any user-provided object.  See
496    PetscContainerCreate() for info on how to create an object from a
497    user-provided pointer that may then be composed with PETSc objects.
498 
499    Concepts: objects^composing
500    Concepts: composing objects
501 
502 .seealso: PetscObjectQuery(), PetscContainerCreate()
503 @*/
504 PetscErrorCode  PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr)
505 {
506   PetscErrorCode ierr;
507 
508   PetscFunctionBegin;
509   PetscValidHeader(obj,1);
510   PetscValidCharPointer(name,2);
511   if (ptr) PetscValidHeader(ptr,3);
512   ierr = (*obj->bops->compose)(obj,name,ptr);CHKERRQ(ierr);
513   PetscFunctionReturn(0);
514 }
515 
516 #undef __FUNCT__
517 #define __FUNCT__ "PetscObjectSetPrecision"
518 /*@C
519    PetscObjectSetPrecision - sets the precision used within a given object.
520 
521    Collective on the PetscObject
522 
523    Input Parameters:
524 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
525          PetscObjectCompose((PetscObject)mat,...);
526 -  precision - the precision
527 
528    Level: advanced
529 
530 .seealso: PetscObjectQuery(), PetscContainerCreate()
531 @*/
532 PetscErrorCode  PetscObjectSetPrecision(PetscObject obj,PetscPrecision precision)
533 {
534   PetscFunctionBegin;
535   PetscValidHeader(obj,1);
536   obj->precision = precision;
537   PetscFunctionReturn(0);
538 }
539 
540 #undef __FUNCT__
541 #define __FUNCT__ "PetscObjectQuery"
542 /*@C
543    PetscObjectQuery  - Gets a PETSc object associated with a given object.
544 
545    Not Collective
546 
547    Input Parameters:
548 +  obj - the PETSc object
549          Thus must be cast with a (PetscObject), for example,
550          PetscObjectCompose((PetscObject)mat,...);
551 .  name - name associated with child object
552 -  ptr - the other PETSc object associated with the PETSc object, this must also be
553          cast with (PetscObject)
554 
555    Level: advanced
556 
557    Concepts: objects^composing
558    Concepts: composing objects
559    Concepts: objects^querying
560    Concepts: querying objects
561 
562 .seealso: PetscObjectCompose()
563 @*/
564 PetscErrorCode  PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr)
565 {
566   PetscErrorCode ierr;
567 
568   PetscFunctionBegin;
569   PetscValidHeader(obj,1);
570   PetscValidCharPointer(name,2);
571   PetscValidPointer(ptr,3);
572   ierr = (*obj->bops->query)(obj,name,ptr);CHKERRQ(ierr);
573   PetscFunctionReturn(0);
574 }
575 
576 #undef __FUNCT__
577 #define __FUNCT__ "PetscObjectComposeFunction"
578 PetscErrorCode  PetscObjectComposeFunction(PetscObject obj,const char name[],const char fname[],void (*ptr)(void))
579 {
580   PetscErrorCode ierr;
581 
582   PetscFunctionBegin;
583   PetscValidHeader(obj,1);
584   PetscValidCharPointer(name,2);
585   PetscValidCharPointer(fname,3);
586   ierr = (*obj->bops->composefunction)(obj,name,fname,ptr);CHKERRQ(ierr);
587   PetscFunctionReturn(0);
588 }
589 
590 #undef __FUNCT__
591 #define __FUNCT__ "PetscObjectQueryFunction"
592 /*@C
593    PetscObjectQueryFunction - Gets a function associated with a given object.
594 
595    Logically Collective on PetscObject
596 
597    Input Parameters:
598 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
599          PetscObjectQueryFunction((PetscObject)ksp,...);
600 -  name - name associated with the child function
601 
602    Output Parameter:
603 .  ptr - function pointer
604 
605    Level: advanced
606 
607    Concepts: objects^composing functions
608    Concepts: composing functions
609    Concepts: functions^querying
610    Concepts: objects^querying
611    Concepts: querying objects
612 
613 .seealso: PetscObjectComposeFunctionDynamic()
614 @*/
615 PetscErrorCode  PetscObjectQueryFunction(PetscObject obj,const char name[],void (**ptr)(void))
616 {
617   PetscErrorCode ierr;
618 
619   PetscFunctionBegin;
620   PetscValidHeader(obj,1);
621   PetscValidCharPointer(name,2);
622   ierr = (*obj->bops->queryfunction)(obj,name,ptr);CHKERRQ(ierr);
623   PetscFunctionReturn(0);
624 }
625 
626 struct _p_PetscContainer {
627   PETSCHEADER(int);
628   void   *ptr;
629   PetscErrorCode (*userdestroy)(void*);
630 };
631 
632 #undef __FUNCT__
633 #define __FUNCT__ "PetscContainerGetPointer"
634 /*@C
635    PetscContainerGetPointer - Gets the pointer value contained in the container.
636 
637    Not Collective
638 
639    Input Parameter:
640 .  obj - the object created with PetscContainerCreate()
641 
642    Output Parameter:
643 .  ptr - the pointer value
644 
645    Level: advanced
646 
647 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
648           PetscContainerSetPointer()
649 @*/
650 PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
651 {
652   PetscFunctionBegin;
653   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
654   PetscValidPointer(ptr,2);
655   *ptr = obj->ptr;
656   PetscFunctionReturn(0);
657 }
658 
659 
660 #undef __FUNCT__
661 #define __FUNCT__ "PetscContainerSetPointer"
662 /*@C
663    PetscContainerSetPointer - Sets the pointer value contained in the container.
664 
665    Logically Collective on PetscContainer
666 
667    Input Parameters:
668 +  obj - the object created with PetscContainerCreate()
669 -  ptr - the pointer value
670 
671    Level: advanced
672 
673 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
674           PetscContainerGetPointer()
675 @*/
676 PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
677 {
678   PetscFunctionBegin;
679   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
680   if (ptr) PetscValidPointer(ptr,2);
681   obj->ptr = ptr;
682   PetscFunctionReturn(0);
683 }
684 
685 #undef __FUNCT__
686 #define __FUNCT__ "PetscContainerDestroy"
687 /*@C
688    PetscContainerDestroy - Destroys a PETSc container object.
689 
690    Collective on PetscContainer
691 
692    Input Parameter:
693 .  obj - an object that was created with PetscContainerCreate()
694 
695    Level: advanced
696 
697 .seealso: PetscContainerCreate()
698 @*/
699 PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
700 {
701   PetscErrorCode ierr;
702   PetscFunctionBegin;
703   if (!*obj) PetscFunctionReturn(0);
704   PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1);
705   if (--((PetscObject)(*obj))->refct > 0) PetscFunctionReturn(0);
706   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
707   ierr = PetscHeaderDestroy(obj);CHKERRQ(ierr);
708   PetscFunctionReturn(0);
709 }
710 
711 #undef __FUNCT__
712 #define __FUNCT__ "PetscContainerSetUserDestroy"
713 /*@C
714    PetscContainerSetUserDestroy - Sets name of the user destroy function.
715 
716    Logically Collective on PetscContainer
717 
718    Input Parameter:
719 +  obj - an object that was created with PetscContainerCreate()
720 -  des - name of the user destroy function
721 
722    Level: advanced
723 
724 .seealso: PetscContainerDestroy()
725 @*/
726 PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
727 {
728   PetscFunctionBegin;
729   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
730   obj->userdestroy = des;
731   PetscFunctionReturn(0);
732 }
733 
734 PetscClassId  PETSC_CONTAINER_CLASSID;
735 
736 #undef __FUNCT__
737 #define __FUNCT__ "PetscContainerCreate"
738 /*@C
739    PetscContainerCreate - Creates a PETSc object that has room to hold
740    a single pointer. This allows one to attach any type of data (accessible
741    through a pointer) with the PetscObjectCompose() function to a PetscObject.
742    The data item itself is attached by a call to PetscContainerSetPointer.
743 
744    Collective on MPI_Comm
745 
746    Input Parameters:
747 .  comm - MPI communicator that shares the object
748 
749    Output Parameters:
750 .  container - the container created
751 
752    Level: advanced
753 
754 .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer()
755 @*/
756 PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
757 {
758   PetscErrorCode ierr;
759   PetscContainer contain;
760 
761   PetscFunctionBegin;
762   PetscValidPointer(container,2);
763   ierr = PetscHeaderCreate(contain,_p_PetscContainer,PetscInt,PETSC_CONTAINER_CLASSID,0,"PetscContainer",comm,PetscContainerDestroy,0);CHKERRQ(ierr);
764   *container = contain;
765   PetscFunctionReturn(0);
766 }
767 
768 #undef __FUNCT__
769 #define __FUNCT__ "PetscObjectSetFromOptions"
770 /*@
771    PetscObjectSetFromOptions - Sets generic parameters from user options.
772 
773    Collective on obj
774 
775    Input Parameter:
776 .  obj - the PetscObjcet
777 
778    Options Database Keys:
779 
780    Notes:
781    We have no generic options at present, so this does nothing
782 
783    Level: beginner
784 
785 .keywords: set, options, database
786 .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
787 @*/
788 PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
789 {
790   PetscFunctionBegin;
791   PetscValidHeader(obj,1);
792   PetscFunctionReturn(0);
793 }
794 
795 #undef __FUNCT__
796 #define __FUNCT__ "PetscObjectSetUp"
797 /*@
798    PetscObjectSetUp - Sets up the internal data structures for the later use.
799 
800    Collective on PetscObject
801 
802    Input Parameters:
803 .  obj - the PetscObject
804 
805    Notes:
806    This does nothing at present.
807 
808    Level: advanced
809 
810 .keywords: setup
811 .seealso: PetscObjectDestroy()
812 @*/
813 PetscErrorCode  PetscObjectSetUp(PetscObject obj)
814 {
815   PetscFunctionBegin;
816   PetscValidHeader(obj,1);
817   PetscFunctionReturn(0);
818 }
819