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