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