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