xref: /petsc/src/sys/objects/inherit.c (revision f8e4bde84cdee892096ab78baf4256ae384d8e42)
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 +  fd - file pointer
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    Options Database:
281 .  -objects_dump <all>
282 
283    Level: advanced
284 
285    Concepts: options database^printing
286 
287 @*/
288 PetscErrorCode  PetscObjectsDump(FILE *fd,PetscBool all)
289 {
290   PetscErrorCode ierr;
291   PetscInt       i;
292 #if defined(PETSC_USE_DEBUG)
293   PetscInt       j,k=0;
294 #endif
295   PetscObject    h;
296 
297   PetscFunctionBegin;
298   if (PetscObjectsCounts) {
299     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"The following objects were never freed\n");CHKERRQ(ierr);
300     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"-----------------------------------------\n");CHKERRQ(ierr);
301     for (i=0; i<PetscObjectsMaxCounts; i++) {
302       if ((h = PetscObjects[i])) {
303         ierr = PetscObjectName(h);CHKERRQ(ierr);
304         {
305 #if defined(PETSC_USE_DEBUG)
306         PetscStack *stack = 0;
307         char       *create,*rclass;
308 
309         /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
310         ierr = PetscMallocGetStack(h,&stack);CHKERRQ(ierr);
311         if (stack) {
312           k = stack->currentsize-2;
313           if (!all) {
314             k = 0;
315             while (!stack->petscroutine[k]) k++;
316             ierr = PetscStrstr(stack->function[k],"Create",&create);CHKERRQ(ierr);
317             if (!create) {
318               ierr = PetscStrstr(stack->function[k],"Get",&create);CHKERRQ(ierr);
319             }
320             ierr = PetscStrstr(stack->function[k],h->class_name,&rclass);CHKERRQ(ierr);
321             if (!create) continue;
322             if (!rclass) continue;
323           }
324         }
325 #endif
326 
327         ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"[%d] %s %s %s\n",PetscGlobalRank,h->class_name,h->type_name,h->name);CHKERRQ(ierr);
328 
329 #if defined(PETSC_USE_DEBUG)
330         ierr = PetscMallocGetStack(h,&stack);CHKERRQ(ierr);
331         if (stack) {
332           for (j=k; j>=0; j--) {
333             fprintf(fd,"      [%d]  %s() in %s\n",PetscGlobalRank,stack->function[j],stack->file[j]);
334           }
335         }
336 #endif
337         }
338       }
339     }
340   }
341   PetscFunctionReturn(0);
342 }
343 #endif
344 
345 #if defined(PETSC_USE_LOG)
346 
347 #undef __FUNCT__
348 #define __FUNCT__ "PetscObjectsView"
349 /*@C
350    PetscObjectsView - Prints the currently existing objects.
351 
352    Logically Collective on PetscViewer
353 
354    Input Parameter:
355 .  viewer - must be an PETSCVIEWERASCII viewer
356 
357    Level: advanced
358 
359    Concepts: options database^printing
360 
361 @*/
362 PetscErrorCode  PetscObjectsView(PetscViewer viewer)
363 {
364   PetscErrorCode ierr;
365   PetscBool      isascii;
366   FILE           *fd;
367 
368   PetscFunctionBegin;
369   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
370   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
371   if (!isascii) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Only supports ASCII viewer");
372   ierr = PetscViewerASCIIGetPointer(viewer,&fd);CHKERRQ(ierr);
373   ierr = PetscObjectsDump(fd,PETSC_TRUE);CHKERRQ(ierr);
374   PetscFunctionReturn(0);
375 }
376 
377 #undef __FUNCT__
378 #define __FUNCT__ "PetscObjectsGetObject"
379 /*@C
380    PetscObjectsGetObject - Get a pointer to a named object
381 
382    Not collective
383 
384    Input Parameter:
385 .  name - the name of an object
386 
387    Output Parameter:
388 .   obj - the object or null if there is no object
389 
390    Level: advanced
391 
392    Concepts: options database^printing
393 
394 @*/
395 PetscErrorCode  PetscObjectsGetObject(const char *name,PetscObject *obj,char **classname)
396 {
397   PetscErrorCode ierr;
398   PetscInt       i;
399   PetscObject    h;
400   PetscBool      flg;
401 
402   PetscFunctionBegin;
403   *obj = NULL;
404   for (i=0; i<PetscObjectsMaxCounts; i++) {
405     if ((h = PetscObjects[i])) {
406       ierr = PetscObjectName(h);CHKERRQ(ierr);
407       ierr = PetscStrcmp(h->name,name,&flg);CHKERRQ(ierr);
408       if (flg) {
409         *obj = h;
410         if (classname) *classname = h->class_name;
411         PetscFunctionReturn(0);
412       }
413     }
414   }
415   PetscFunctionReturn(0);
416 }
417 #endif
418 
419 #undef __FUNCT__
420 #define __FUNCT__ "PetscObjectAddOptionsHandler"
421 /*@C
422     PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called.
423 
424     Not Collective
425 
426     Input Parameter:
427 +   obj - the PETSc object
428 .   handle - function that checks for options
429 .   destroy - function to destroy context if provided
430 -   ctx - optional context for check function
431 
432     Level: developer
433 
434 
435 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectProcessOptionsHandlers(), PetscObjectDestroyOptionsHandlers()
436 
437 @*/
438 PetscErrorCode  PetscObjectAddOptionsHandler(PetscObject obj,PetscErrorCode (*handle)(PetscObject,void*),PetscErrorCode (*destroy)(PetscObject,void*),void *ctx)
439 {
440   PetscFunctionBegin;
441   PetscValidHeader(obj,1);
442   if (obj->noptionhandler >= PETSC_MAX_OPTIONS_HANDLER) SETERRQ(obj->comm,PETSC_ERR_ARG_OUTOFRANGE,"To many options handlers added");
443   obj->optionhandler[obj->noptionhandler] = handle;
444   obj->optiondestroy[obj->noptionhandler] = destroy;
445   obj->optionctx[obj->noptionhandler++]   = ctx;
446   PetscFunctionReturn(0);
447 }
448 
449 #undef __FUNCT__
450 #define __FUNCT__ "PetscObjectProcessOptionsHandlers"
451 /*@C
452     PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
453 
454     Not Collective
455 
456     Input Parameter:
457 .   obj - the PETSc object
458 
459     Level: developer
460 
461 
462 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectDestroyOptionsHandlers()
463 
464 @*/
465 PetscErrorCode  PetscObjectProcessOptionsHandlers(PetscObject obj)
466 {
467   PetscInt       i;
468   PetscErrorCode ierr;
469 
470   PetscFunctionBegin;
471   PetscValidHeader(obj,1);
472   for (i=0; i<obj->noptionhandler; i++) {
473     ierr = (*obj->optionhandler[i])(obj,obj->optionctx[i]);CHKERRQ(ierr);
474   }
475   PetscFunctionReturn(0);
476 }
477 
478 #undef __FUNCT__
479 #define __FUNCT__ "PetscObjectDestroyOptionsHandlers"
480 /*@C
481     PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
482 
483     Not Collective
484 
485     Input Parameter:
486 .   obj - the PETSc object
487 
488     Level: developer
489 
490 
491 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectProcessOptionsHandlers()
492 
493 @*/
494 PetscErrorCode  PetscObjectDestroyOptionsHandlers(PetscObject obj)
495 {
496   PetscInt       i;
497   PetscErrorCode ierr;
498 
499   PetscFunctionBegin;
500   PetscValidHeader(obj,1);
501   for (i=0; i<obj->noptionhandler; i++) {
502     if (obj->optiondestroy[i]) {
503       ierr = (*obj->optiondestroy[i])(obj,obj->optionctx[i]);CHKERRQ(ierr);
504     }
505   }
506   obj->noptionhandler = 0;
507   PetscFunctionReturn(0);
508 }
509 
510 
511 #undef __FUNCT__
512 #define __FUNCT__ "PetscObjectReference"
513 /*@
514    PetscObjectReference - Indicates to any PetscObject that it is being
515    referenced by another PetscObject. This increases the reference
516    count for that object by one.
517 
518    Logically Collective on PetscObject
519 
520    Input Parameter:
521 .  obj - the PETSc object. This must be cast with (PetscObject), for example,
522          PetscObjectReference((PetscObject)mat);
523 
524    Level: advanced
525 
526 .seealso: PetscObjectCompose(), PetscObjectDereference()
527 @*/
528 PetscErrorCode  PetscObjectReference(PetscObject obj)
529 {
530   PetscFunctionBegin;
531   if (!obj) PetscFunctionReturn(0);
532   PetscValidHeader(obj,1);
533   obj->refct++;
534   PetscFunctionReturn(0);
535 }
536 
537 #undef __FUNCT__
538 #define __FUNCT__ "PetscObjectGetReference"
539 /*@
540    PetscObjectGetReference - Gets the current reference count for
541    any PETSc object.
542 
543    Not Collective
544 
545    Input Parameter:
546 .  obj - the PETSc object; this must be cast with (PetscObject), for example,
547          PetscObjectGetReference((PetscObject)mat,&cnt);
548 
549    Output Parameter:
550 .  cnt - the reference count
551 
552    Level: advanced
553 
554 .seealso: PetscObjectCompose(), PetscObjectDereference(), PetscObjectReference()
555 @*/
556 PetscErrorCode  PetscObjectGetReference(PetscObject obj,PetscInt *cnt)
557 {
558   PetscFunctionBegin;
559   PetscValidHeader(obj,1);
560   PetscValidIntPointer(cnt,2);
561   *cnt = obj->refct;
562   PetscFunctionReturn(0);
563 }
564 
565 #undef __FUNCT__
566 #define __FUNCT__ "PetscObjectDereference"
567 /*@
568    PetscObjectDereference - Indicates to any PetscObject that it is being
569    referenced by one less PetscObject. This decreases the reference
570    count for that object by one.
571 
572    Collective on PetscObject if reference reaches 0 otherwise Logically Collective
573 
574    Input Parameter:
575 .  obj - the PETSc object; this must be cast with (PetscObject), for example,
576          PetscObjectDereference((PetscObject)mat);
577 
578    Notes: PetscObjectDestroy(PetscObject *obj)  sets the obj pointer to null after the call, this routine does not.
579 
580    Level: advanced
581 
582 .seealso: PetscObjectCompose(), PetscObjectReference()
583 @*/
584 PetscErrorCode  PetscObjectDereference(PetscObject obj)
585 {
586   PetscErrorCode ierr;
587 
588   PetscFunctionBegin;
589   if (!obj) PetscFunctionReturn(0);
590   PetscValidHeader(obj,1);
591   if (obj->bops->destroy) {
592     ierr = (*obj->bops->destroy)(&obj);CHKERRQ(ierr);
593   } else if (!--obj->refct) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"This PETSc object does not have a generic destroy routine");
594   PetscFunctionReturn(0);
595 }
596 
597 /* ----------------------------------------------------------------------- */
598 /*
599      The following routines are the versions private to the PETSc object
600      data structures.
601 */
602 #undef __FUNCT__
603 #define __FUNCT__ "PetscObjectGetComm_Petsc"
604 PetscErrorCode PetscObjectGetComm_Petsc(PetscObject obj,MPI_Comm *comm)
605 {
606   PetscFunctionBegin;
607   PetscValidHeader(obj,1);
608   *comm = obj->comm;
609   PetscFunctionReturn(0);
610 }
611 
612 #undef __FUNCT__
613 #define __FUNCT__ "PetscObjectRemoveReference"
614 PetscErrorCode PetscObjectRemoveReference(PetscObject obj,const char name[])
615 {
616   PetscErrorCode ierr;
617 
618   PetscFunctionBegin;
619   PetscValidHeader(obj,1);
620   ierr = PetscObjectListRemoveReference(&obj->olist,name);CHKERRQ(ierr);
621   PetscFunctionReturn(0);
622 }
623 
624 #undef __FUNCT__
625 #define __FUNCT__ "PetscObjectCompose_Petsc"
626 PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr)
627 {
628   PetscErrorCode ierr;
629   char           *tname;
630   PetscBool      skipreference;
631 
632   PetscFunctionBegin;
633   if (ptr) {
634     ierr = PetscObjectListReverseFind(ptr->olist,obj,&tname,&skipreference);CHKERRQ(ierr);
635     if (tname && !skipreference) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"An object cannot be composed with an object that was composed with it");
636   }
637   ierr = PetscObjectListAdd(&obj->olist,name,ptr);CHKERRQ(ierr);
638   PetscFunctionReturn(0);
639 }
640 
641 #undef __FUNCT__
642 #define __FUNCT__ "PetscObjectQuery_Petsc"
643 PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char name[],PetscObject *ptr)
644 {
645   PetscErrorCode ierr;
646 
647   PetscFunctionBegin;
648   PetscValidHeader(obj,1);
649   ierr = PetscObjectListFind(obj->olist,name,ptr);CHKERRQ(ierr);
650   PetscFunctionReturn(0);
651 }
652 
653 #undef __FUNCT__
654 #define __FUNCT__ "PetscObjectComposeFunction_Petsc"
655 PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char name[],void (*ptr)(void))
656 {
657   PetscErrorCode ierr;
658 
659   PetscFunctionBegin;
660   PetscValidHeader(obj,1);
661   ierr = PetscFunctionListAdd(&obj->qlist,name,ptr);CHKERRQ(ierr);
662   PetscFunctionReturn(0);
663 }
664 
665 #undef __FUNCT__
666 #define __FUNCT__ "PetscObjectQueryFunction_Petsc"
667 PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char name[],void (**ptr)(void))
668 {
669   PetscErrorCode ierr;
670 
671   PetscFunctionBegin;
672   PetscValidHeader(obj,1);
673   ierr = PetscFunctionListFind(obj->qlist,name,ptr);CHKERRQ(ierr);
674   PetscFunctionReturn(0);
675 }
676 
677 #undef __FUNCT__
678 #define __FUNCT__ "PetscObjectCompose"
679 /*@C
680    PetscObjectCompose - Associates another PETSc object with a given PETSc object.
681 
682    Not Collective
683 
684    Input Parameters:
685 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
686          PetscObjectCompose((PetscObject)mat,...);
687 .  name - name associated with the child object
688 -  ptr - the other PETSc object to associate with the PETSc object; this must also be
689          cast with (PetscObject)
690 
691    Level: advanced
692 
693    Notes:
694    The second objects reference count is automatically increased by one when it is
695    composed.
696 
697    Replaces any previous object that had the same name.
698 
699    If ptr is null and name has previously been composed using an object, then that
700    entry is removed from the obj.
701 
702    PetscObjectCompose() can be used with any PETSc object (such as
703    Mat, Vec, KSP, SNES, etc.) or any user-provided object.  See
704    PetscContainerCreate() for info on how to create an object from a
705    user-provided pointer that may then be composed with PETSc objects.
706 
707    Concepts: objects^composing
708    Concepts: composing objects
709 
710 .seealso: PetscObjectQuery(), PetscContainerCreate()
711 @*/
712 PetscErrorCode  PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr)
713 {
714   PetscErrorCode ierr;
715 
716   PetscFunctionBegin;
717   PetscValidHeader(obj,1);
718   PetscValidCharPointer(name,2);
719   if (ptr) PetscValidHeader(ptr,3);
720   ierr = (*obj->bops->compose)(obj,name,ptr);CHKERRQ(ierr);
721   PetscFunctionReturn(0);
722 }
723 
724 #undef __FUNCT__
725 #define __FUNCT__ "PetscObjectSetPrecision"
726 /*@C
727    PetscObjectSetPrecision - sets the precision used within a given object.
728 
729    Collective on the PetscObject
730 
731    Input Parameters:
732 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
733          PetscObjectCompose((PetscObject)mat,...);
734 -  precision - the precision
735 
736    Level: advanced
737 
738 .seealso: PetscObjectQuery(), PetscContainerCreate()
739 @*/
740 PetscErrorCode  PetscObjectSetPrecision(PetscObject obj,PetscPrecision precision)
741 {
742   PetscFunctionBegin;
743   PetscValidHeader(obj,1);
744   obj->precision = precision;
745   PetscFunctionReturn(0);
746 }
747 
748 #undef __FUNCT__
749 #define __FUNCT__ "PetscObjectQuery"
750 /*@C
751    PetscObjectQuery  - Gets a PETSc object associated with a given object.
752 
753    Not Collective
754 
755    Input Parameters:
756 +  obj - the PETSc object
757          Thus must be cast with a (PetscObject), for example,
758          PetscObjectCompose((PetscObject)mat,...);
759 .  name - name associated with child object
760 -  ptr - the other PETSc object associated with the PETSc object, this must be
761          cast with (PetscObject*)
762 
763    Level: advanced
764 
765    The reference count of neither object is increased in this call
766 
767    Concepts: objects^composing
768    Concepts: composing objects
769    Concepts: objects^querying
770    Concepts: querying objects
771 
772 .seealso: PetscObjectCompose()
773 @*/
774 PetscErrorCode  PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr)
775 {
776   PetscErrorCode ierr;
777 
778   PetscFunctionBegin;
779   PetscValidHeader(obj,1);
780   PetscValidCharPointer(name,2);
781   PetscValidPointer(ptr,3);
782   ierr = (*obj->bops->query)(obj,name,ptr);CHKERRQ(ierr);
783   PetscFunctionReturn(0);
784 }
785 
786 /*MC
787    PetscObjectComposeFunction - Associates a function with a given PETSc object.
788 
789     Synopsis:
790     #include <petscsys.h>
791     PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void))
792 
793    Logically Collective on PetscObject
794 
795    Input Parameters:
796 +  obj - the PETSc object; this must be cast with a (PetscObject), for example,
797          PetscObjectCompose((PetscObject)mat,...);
798 .  name - name associated with the child function
799 .  fname - name of the function
800 -  fptr - function pointer
801 
802    Level: advanced
803 
804    Notes:
805    To remove a registered routine, pass in NULL for fptr().
806 
807    PetscObjectComposeFunction() can be used with any PETSc object (such as
808    Mat, Vec, KSP, SNES, etc.) or any user-provided object.
809 
810    Concepts: objects^composing functions
811    Concepts: composing functions
812    Concepts: functions^querying
813    Concepts: objects^querying
814    Concepts: querying objects
815 
816 .seealso: PetscObjectQueryFunction(), PetscContainerCreate()
817 M*/
818 
819 #undef __FUNCT__
820 #define __FUNCT__ "PetscObjectComposeFunction_Private"
821 PetscErrorCode  PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void))
822 {
823   PetscErrorCode ierr;
824 
825   PetscFunctionBegin;
826   PetscValidHeader(obj,1);
827   PetscValidCharPointer(name,2);
828   ierr = (*obj->bops->composefunction)(obj,name,fptr);CHKERRQ(ierr);
829   PetscFunctionReturn(0);
830 }
831 
832 /*MC
833    PetscObjectQueryFunction - Gets a function associated with a given object.
834 
835     Synopsis:
836     #include <petscsys.h>
837     PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
838 
839    Logically Collective on PetscObject
840 
841    Input Parameters:
842 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
843          PetscObjectQueryFunction((PetscObject)ksp,...);
844 -  name - name associated with the child function
845 
846    Output Parameter:
847 .  fptr - function pointer
848 
849    Level: advanced
850 
851    Concepts: objects^composing functions
852    Concepts: composing functions
853    Concepts: functions^querying
854    Concepts: objects^querying
855    Concepts: querying objects
856 
857 .seealso: PetscObjectComposeFunction(), PetscFunctionListFind()
858 M*/
859 #undef __FUNCT__
860 #define __FUNCT__ "PetscObjectQueryFunction_Private"
861 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void))
862 {
863   PetscErrorCode ierr;
864 
865   PetscFunctionBegin;
866   PetscValidHeader(obj,1);
867   PetscValidCharPointer(name,2);
868   ierr = (*obj->bops->queryfunction)(obj,name,ptr);CHKERRQ(ierr);
869   PetscFunctionReturn(0);
870 }
871 
872 struct _p_PetscContainer {
873   PETSCHEADER(int);
874   void           *ptr;
875   PetscErrorCode (*userdestroy)(void*);
876 };
877 
878 #undef __FUNCT__
879 #define __FUNCT__ "PetscContainerGetPointer"
880 /*@C
881    PetscContainerGetPointer - Gets the pointer value contained in the container.
882 
883    Not Collective
884 
885    Input Parameter:
886 .  obj - the object created with PetscContainerCreate()
887 
888    Output Parameter:
889 .  ptr - the pointer value
890 
891    Level: advanced
892 
893 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
894           PetscContainerSetPointer()
895 @*/
896 PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
897 {
898   PetscFunctionBegin;
899   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
900   PetscValidPointer(ptr,2);
901   *ptr = obj->ptr;
902   PetscFunctionReturn(0);
903 }
904 
905 
906 #undef __FUNCT__
907 #define __FUNCT__ "PetscContainerSetPointer"
908 /*@C
909    PetscContainerSetPointer - Sets the pointer value contained in the container.
910 
911    Logically Collective on PetscContainer
912 
913    Input Parameters:
914 +  obj - the object created with PetscContainerCreate()
915 -  ptr - the pointer value
916 
917    Level: advanced
918 
919 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
920           PetscContainerGetPointer()
921 @*/
922 PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
923 {
924   PetscFunctionBegin;
925   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
926   if (ptr) PetscValidPointer(ptr,2);
927   obj->ptr = ptr;
928   PetscFunctionReturn(0);
929 }
930 
931 #undef __FUNCT__
932 #define __FUNCT__ "PetscContainerDestroy"
933 /*@C
934    PetscContainerDestroy - Destroys a PETSc container object.
935 
936    Collective on PetscContainer
937 
938    Input Parameter:
939 .  obj - an object that was created with PetscContainerCreate()
940 
941    Level: advanced
942 
943 .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
944 @*/
945 PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
946 {
947   PetscErrorCode ierr;
948 
949   PetscFunctionBegin;
950   if (!*obj) PetscFunctionReturn(0);
951   PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1);
952   if (--((PetscObject)(*obj))->refct > 0) {*obj = 0; PetscFunctionReturn(0);}
953   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
954   ierr = PetscHeaderDestroy(obj);CHKERRQ(ierr);
955   PetscFunctionReturn(0);
956 }
957 
958 #undef __FUNCT__
959 #define __FUNCT__ "PetscContainerSetUserDestroy"
960 /*@C
961    PetscContainerSetUserDestroy - Sets name of the user destroy function.
962 
963    Logically Collective on PetscContainer
964 
965    Input Parameter:
966 +  obj - an object that was created with PetscContainerCreate()
967 -  des - name of the user destroy function
968 
969    Level: advanced
970 
971 .seealso: PetscContainerDestroy()
972 @*/
973 PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
974 {
975   PetscFunctionBegin;
976   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
977   obj->userdestroy = des;
978   PetscFunctionReturn(0);
979 }
980 
981 PetscClassId PETSC_CONTAINER_CLASSID;
982 
983 #undef __FUNCT__
984 #define __FUNCT__ "PetscContainerCreate"
985 /*@C
986    PetscContainerCreate - Creates a PETSc object that has room to hold
987    a single pointer. This allows one to attach any type of data (accessible
988    through a pointer) with the PetscObjectCompose() function to a PetscObject.
989    The data item itself is attached by a call to PetscContainerSetPointer().
990 
991    Collective on MPI_Comm
992 
993    Input Parameters:
994 .  comm - MPI communicator that shares the object
995 
996    Output Parameters:
997 .  container - the container created
998 
999    Level: advanced
1000 
1001 .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer()
1002 @*/
1003 PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
1004 {
1005   PetscErrorCode ierr;
1006   PetscContainer contain;
1007 
1008   PetscFunctionBegin;
1009   PetscValidPointer(container,2);
1010   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
1011   ierr = PetscHeaderCreate(contain,_p_PetscContainer,PetscInt,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,0);CHKERRQ(ierr);
1012   *container = contain;
1013   PetscFunctionReturn(0);
1014 }
1015 
1016 #undef __FUNCT__
1017 #define __FUNCT__ "PetscObjectSetFromOptions"
1018 /*@
1019    PetscObjectSetFromOptions - Sets generic parameters from user options.
1020 
1021    Collective on obj
1022 
1023    Input Parameter:
1024 .  obj - the PetscObjcet
1025 
1026    Options Database Keys:
1027 
1028    Notes:
1029    We have no generic options at present, so this does nothing
1030 
1031    Level: beginner
1032 
1033 .keywords: set, options, database
1034 .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
1035 @*/
1036 PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
1037 {
1038   PetscFunctionBegin;
1039   PetscValidHeader(obj,1);
1040   PetscFunctionReturn(0);
1041 }
1042 
1043 #undef __FUNCT__
1044 #define __FUNCT__ "PetscObjectSetUp"
1045 /*@
1046    PetscObjectSetUp - Sets up the internal data structures for the later use.
1047 
1048    Collective on PetscObject
1049 
1050    Input Parameters:
1051 .  obj - the PetscObject
1052 
1053    Notes:
1054    This does nothing at present.
1055 
1056    Level: advanced
1057 
1058 .keywords: setup
1059 .seealso: PetscObjectDestroy()
1060 @*/
1061 PetscErrorCode  PetscObjectSetUp(PetscObject obj)
1062 {
1063   PetscFunctionBegin;
1064   PetscValidHeader(obj,1);
1065   PetscFunctionReturn(0);
1066 }
1067