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