xref: /petsc/src/sys/objects/inherit.c (revision 5b6bfdb9644f185dbf5e5a09b808ec241507e1e7)
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 /*@C
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 /*@C
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 /*@C
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   if (obj == ptr) SETERRQ(PetscObjectComm((PetscObject)obj),PETSC_ERR_SUP,"Cannot compose object with itself");
681   ierr = (*obj->bops->compose)(obj,name,ptr);CHKERRQ(ierr);
682   PetscFunctionReturn(0);
683 }
684 
685 /*@C
686    PetscObjectQuery  - Gets a PETSc object associated with a given object.
687 
688    Not Collective
689 
690    Input Parameters:
691 +  obj - the PETSc object
692          Thus must be cast with a (PetscObject), for example,
693          PetscObjectCompose((PetscObject)mat,...);
694 .  name - name associated with child object
695 -  ptr - the other PETSc object associated with the PETSc object, this must be
696          cast with (PetscObject*)
697 
698    Level: advanced
699 
700    The reference count of neither object is increased in this call
701 
702    Concepts: objects^composing
703    Concepts: composing objects
704    Concepts: objects^querying
705    Concepts: querying objects
706 
707 .seealso: PetscObjectCompose()
708 @*/
709 PetscErrorCode  PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr)
710 {
711   PetscErrorCode ierr;
712 
713   PetscFunctionBegin;
714   PetscValidHeader(obj,1);
715   PetscValidCharPointer(name,2);
716   PetscValidPointer(ptr,3);
717   ierr = (*obj->bops->query)(obj,name,ptr);CHKERRQ(ierr);
718   PetscFunctionReturn(0);
719 }
720 
721 /*MC
722    PetscObjectComposeFunction - Associates a function with a given PETSc object.
723 
724     Synopsis:
725     #include <petscsys.h>
726     PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void))
727 
728    Logically Collective on PetscObject
729 
730    Input Parameters:
731 +  obj - the PETSc object; this must be cast with a (PetscObject), for example,
732          PetscObjectCompose((PetscObject)mat,...);
733 .  name - name associated with the child function
734 .  fname - name of the function
735 -  fptr - function pointer
736 
737    Level: advanced
738 
739    Notes:
740    To remove a registered routine, pass in NULL for fptr().
741 
742    PetscObjectComposeFunction() can be used with any PETSc object (such as
743    Mat, Vec, KSP, SNES, etc.) or any user-provided object.
744 
745    Concepts: objects^composing functions
746    Concepts: composing functions
747    Concepts: functions^querying
748    Concepts: objects^querying
749    Concepts: querying objects
750 
751 .seealso: PetscObjectQueryFunction(), PetscContainerCreate()
752 M*/
753 
754 PetscErrorCode  PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void))
755 {
756   PetscErrorCode ierr;
757 
758   PetscFunctionBegin;
759   PetscValidHeader(obj,1);
760   PetscValidCharPointer(name,2);
761   ierr = (*obj->bops->composefunction)(obj,name,fptr);CHKERRQ(ierr);
762   PetscFunctionReturn(0);
763 }
764 
765 /*MC
766    PetscObjectQueryFunction - Gets a function associated with a given object.
767 
768     Synopsis:
769     #include <petscsys.h>
770     PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
771 
772    Logically Collective on PetscObject
773 
774    Input Parameters:
775 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
776          PetscObjectQueryFunction((PetscObject)ksp,...);
777 -  name - name associated with the child function
778 
779    Output Parameter:
780 .  fptr - function pointer
781 
782    Level: advanced
783 
784    Concepts: objects^composing functions
785    Concepts: composing functions
786    Concepts: functions^querying
787    Concepts: objects^querying
788    Concepts: querying objects
789 
790 .seealso: PetscObjectComposeFunction(), PetscFunctionListFind()
791 M*/
792 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void))
793 {
794   PetscErrorCode ierr;
795 
796   PetscFunctionBegin;
797   PetscValidHeader(obj,1);
798   PetscValidCharPointer(name,2);
799   ierr = (*obj->bops->queryfunction)(obj,name,ptr);CHKERRQ(ierr);
800   PetscFunctionReturn(0);
801 }
802 
803 struct _p_PetscContainer {
804   PETSCHEADER(int);
805   void           *ptr;
806   PetscErrorCode (*userdestroy)(void*);
807 };
808 
809 /*@C
810    PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls PetscFree().
811 
812    Logically Collective on PetscContainer
813 
814    Input Parameter:
815 .  ctx - pointer to user-provided data
816 
817    Level: advanced
818 
819 .seealso: PetscContainerDestroy(), PetscContainterSetUserDestroy()
820 @*/
821 PetscErrorCode PetscContainerUserDestroyDefault(void* ctx)
822 {
823   PetscErrorCode ierr;
824 
825   PetscFunctionBegin;
826   PetscValidPointer(ctx,1);
827   ierr = PetscFree(ctx);CHKERRQ(ierr);
828   PetscFunctionReturn(0);
829 }
830 
831 /*@C
832    PetscContainerGetPointer - Gets the pointer value contained in the container.
833 
834    Not Collective
835 
836    Input Parameter:
837 .  obj - the object created with PetscContainerCreate()
838 
839    Output Parameter:
840 .  ptr - the pointer value
841 
842    Level: advanced
843 
844 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
845           PetscContainerSetPointer()
846 @*/
847 PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
848 {
849   PetscFunctionBegin;
850   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
851   PetscValidPointer(ptr,2);
852   *ptr = obj->ptr;
853   PetscFunctionReturn(0);
854 }
855 
856 
857 /*@C
858    PetscContainerSetPointer - Sets the pointer value contained in the container.
859 
860    Logically Collective on PetscContainer
861 
862    Input Parameters:
863 +  obj - the object created with PetscContainerCreate()
864 -  ptr - the pointer value
865 
866    Level: advanced
867 
868 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
869           PetscContainerGetPointer()
870 @*/
871 PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
872 {
873   PetscFunctionBegin;
874   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
875   if (ptr) PetscValidPointer(ptr,2);
876   obj->ptr = ptr;
877   PetscFunctionReturn(0);
878 }
879 
880 /*@C
881    PetscContainerDestroy - Destroys a PETSc container object.
882 
883    Collective on PetscContainer
884 
885    Input Parameter:
886 .  obj - an object that was created with PetscContainerCreate()
887 
888    Level: advanced
889 
890 .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
891 @*/
892 PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
893 {
894   PetscErrorCode ierr;
895 
896   PetscFunctionBegin;
897   if (!*obj) PetscFunctionReturn(0);
898   PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1);
899   if (--((PetscObject)(*obj))->refct > 0) {*obj = 0; PetscFunctionReturn(0);}
900   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
901   ierr = PetscHeaderDestroy(obj);CHKERRQ(ierr);
902   PetscFunctionReturn(0);
903 }
904 
905 /*@C
906    PetscContainerSetUserDestroy - Sets name of the user destroy function.
907 
908    Logically Collective on PetscContainer
909 
910    Input Parameter:
911 +  obj - an object that was created with PetscContainerCreate()
912 -  des - name of the user destroy function
913 
914    Notes:
915    Use PetscContainerUserDestroyDefault() if the memory was obtained by calling PetscMalloc or one of its variants for single memory allocation.
916 
917    Level: advanced
918 
919 .seealso: PetscContainerDestroy(), PetscContainerUserDestroyDefault(), PetscMalloc(), PetscMalloc1(), PetscCalloc(), PetscCalloc1()
920 @*/
921 PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
922 {
923   PetscFunctionBegin;
924   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
925   obj->userdestroy = des;
926   PetscFunctionReturn(0);
927 }
928 
929 PetscClassId PETSC_CONTAINER_CLASSID;
930 
931 /*@C
932    PetscContainerCreate - Creates a PETSc object that has room to hold
933    a single pointer. This allows one to attach any type of data (accessible
934    through a pointer) with the PetscObjectCompose() function to a PetscObject.
935    The data item itself is attached by a call to PetscContainerSetPointer().
936 
937    Collective on MPI_Comm
938 
939    Input Parameters:
940 .  comm - MPI communicator that shares the object
941 
942    Output Parameters:
943 .  container - the container created
944 
945    Level: advanced
946 
947 .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer()
948 @*/
949 PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
950 {
951   PetscErrorCode ierr;
952   PetscContainer contain;
953 
954   PetscFunctionBegin;
955   PetscValidPointer(container,2);
956   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
957   ierr = PetscHeaderCreate(contain,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL);CHKERRQ(ierr);
958   *container = contain;
959   PetscFunctionReturn(0);
960 }
961 
962 /*@
963    PetscObjectSetFromOptions - Sets generic parameters from user options.
964 
965    Collective on obj
966 
967    Input Parameter:
968 .  obj - the PetscObjcet
969 
970    Options Database Keys:
971 
972    Notes:
973    We have no generic options at present, so this does nothing
974 
975    Level: beginner
976 
977 .keywords: set, options, database
978 .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
979 @*/
980 PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
981 {
982   PetscFunctionBegin;
983   PetscValidHeader(obj,1);
984   PetscFunctionReturn(0);
985 }
986 
987 /*@
988    PetscObjectSetUp - Sets up the internal data structures for the later use.
989 
990    Collective on PetscObject
991 
992    Input Parameters:
993 .  obj - the PetscObject
994 
995    Notes:
996    This does nothing at present.
997 
998    Level: advanced
999 
1000 .keywords: setup
1001 .seealso: PetscObjectDestroy()
1002 @*/
1003 PetscErrorCode  PetscObjectSetUp(PetscObject obj)
1004 {
1005   PetscFunctionBegin;
1006   PetscValidHeader(obj,1);
1007   PetscFunctionReturn(0);
1008 }
1009