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