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