xref: /petsc/src/sys/objects/inherit.c (revision 3de71b31db709282ed802e6ac0677e6c8e42aed3)
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    PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls PetscFree().
810 
811    Logically Collective on PetscContainer
812 
813    Input Parameter:
814 .  ctx - pointer to user-provided data
815 
816    Level: advanced
817 
818 .seealso: PetscContainerDestroy(), PetscContainterSetUserDestroy()
819 @*/
820 PetscErrorCode PetscContainerUserDestroyDefault(void* ctx)
821 {
822   PetscErrorCode ierr;
823 
824   PetscFunctionBegin;
825   PetscValidPointer(ctx,1);
826   ierr = PetscFree(ctx);CHKERRQ(ierr);
827   PetscFunctionReturn(0);
828 }
829 
830 /*@C
831    PetscContainerGetPointer - Gets the pointer value contained in the container.
832 
833    Not Collective
834 
835    Input Parameter:
836 .  obj - the object created with PetscContainerCreate()
837 
838    Output Parameter:
839 .  ptr - the pointer value
840 
841    Level: advanced
842 
843 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
844           PetscContainerSetPointer()
845 @*/
846 PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
847 {
848   PetscFunctionBegin;
849   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
850   PetscValidPointer(ptr,2);
851   *ptr = obj->ptr;
852   PetscFunctionReturn(0);
853 }
854 
855 
856 /*@C
857    PetscContainerSetPointer - Sets the pointer value contained in the container.
858 
859    Logically Collective on PetscContainer
860 
861    Input Parameters:
862 +  obj - the object created with PetscContainerCreate()
863 -  ptr - the pointer value
864 
865    Level: advanced
866 
867 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
868           PetscContainerGetPointer()
869 @*/
870 PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
871 {
872   PetscFunctionBegin;
873   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
874   if (ptr) PetscValidPointer(ptr,2);
875   obj->ptr = ptr;
876   PetscFunctionReturn(0);
877 }
878 
879 /*@C
880    PetscContainerDestroy - Destroys a PETSc container object.
881 
882    Collective on PetscContainer
883 
884    Input Parameter:
885 .  obj - an object that was created with PetscContainerCreate()
886 
887    Level: advanced
888 
889 .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
890 @*/
891 PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
892 {
893   PetscErrorCode ierr;
894 
895   PetscFunctionBegin;
896   if (!*obj) PetscFunctionReturn(0);
897   PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1);
898   if (--((PetscObject)(*obj))->refct > 0) {*obj = 0; PetscFunctionReturn(0);}
899   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
900   ierr = PetscHeaderDestroy(obj);CHKERRQ(ierr);
901   PetscFunctionReturn(0);
902 }
903 
904 /*@C
905    PetscContainerSetUserDestroy - Sets name of the user destroy function.
906 
907    Logically Collective on PetscContainer
908 
909    Input Parameter:
910 +  obj - an object that was created with PetscContainerCreate()
911 -  des - name of the user destroy function
912 
913    Notes:
914    Use PetscContainerUserDestroyDefault() if the memory was obtained by calling PetscMalloc or one of its variants for single memory allocation.
915 
916    Level: advanced
917 
918 .seealso: PetscContainerDestroy(), PetscContainerUserDestroyDefault(), PetscMalloc(), PetscMalloc1(), PetscCalloc(), PetscCalloc1()
919 @*/
920 PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
921 {
922   PetscFunctionBegin;
923   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
924   obj->userdestroy = des;
925   PetscFunctionReturn(0);
926 }
927 
928 PetscClassId PETSC_CONTAINER_CLASSID;
929 
930 /*@C
931    PetscContainerCreate - Creates a PETSc object that has room to hold
932    a single pointer. This allows one to attach any type of data (accessible
933    through a pointer) with the PetscObjectCompose() function to a PetscObject.
934    The data item itself is attached by a call to PetscContainerSetPointer().
935 
936    Collective on MPI_Comm
937 
938    Input Parameters:
939 .  comm - MPI communicator that shares the object
940 
941    Output Parameters:
942 .  container - the container created
943 
944    Level: advanced
945 
946 .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer()
947 @*/
948 PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
949 {
950   PetscErrorCode ierr;
951   PetscContainer contain;
952 
953   PetscFunctionBegin;
954   PetscValidPointer(container,2);
955   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
956   ierr = PetscHeaderCreate(contain,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL);CHKERRQ(ierr);
957   *container = contain;
958   PetscFunctionReturn(0);
959 }
960 
961 /*@
962    PetscObjectSetFromOptions - Sets generic parameters from user options.
963 
964    Collective on obj
965 
966    Input Parameter:
967 .  obj - the PetscObjcet
968 
969    Options Database Keys:
970 
971    Notes:
972    We have no generic options at present, so this does nothing
973 
974    Level: beginner
975 
976 .keywords: set, options, database
977 .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
978 @*/
979 PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
980 {
981   PetscFunctionBegin;
982   PetscValidHeader(obj,1);
983   PetscFunctionReturn(0);
984 }
985 
986 /*@
987    PetscObjectSetUp - Sets up the internal data structures for the later use.
988 
989    Collective on PetscObject
990 
991    Input Parameters:
992 .  obj - the PetscObject
993 
994    Notes:
995    This does nothing at present.
996 
997    Level: advanced
998 
999 .keywords: setup
1000 .seealso: PetscObjectDestroy()
1001 @*/
1002 PetscErrorCode  PetscObjectSetUp(PetscObject obj)
1003 {
1004   PetscFunctionBegin;
1005   PetscValidHeader(obj,1);
1006   PetscFunctionReturn(0);
1007 }
1008