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