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