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