xref: /petsc/src/sys/objects/inherit.c (revision 249cb5c497384507c8233e20189d5c9ded68a4fc) !
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:
553     PetscObjectDestroy(PetscObject *obj)  sets the obj pointer to null after the call, this routine does not.
554 
555    Level: advanced
556 
557 .seealso: PetscObjectCompose(), PetscObjectReference()
558 @*/
559 PetscErrorCode  PetscObjectDereference(PetscObject obj)
560 {
561   PetscErrorCode ierr;
562 
563   PetscFunctionBegin;
564   if (!obj) PetscFunctionReturn(0);
565   PetscValidHeader(obj,1);
566   if (obj->bops->destroy) {
567     ierr = (*obj->bops->destroy)(&obj);CHKERRQ(ierr);
568   } else if (!--obj->refct) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"This PETSc object does not have a generic destroy routine");
569   PetscFunctionReturn(0);
570 }
571 
572 /* ----------------------------------------------------------------------- */
573 /*
574      The following routines are the versions private to the PETSc object
575      data structures.
576 */
577 PetscErrorCode PetscObjectGetComm_Petsc(PetscObject obj,MPI_Comm *comm)
578 {
579   PetscFunctionBegin;
580   PetscValidHeader(obj,1);
581   *comm = obj->comm;
582   PetscFunctionReturn(0);
583 }
584 
585 PetscErrorCode PetscObjectRemoveReference(PetscObject obj,const char name[])
586 {
587   PetscErrorCode ierr;
588 
589   PetscFunctionBegin;
590   PetscValidHeader(obj,1);
591   ierr = PetscObjectListRemoveReference(&obj->olist,name);CHKERRQ(ierr);
592   PetscFunctionReturn(0);
593 }
594 
595 PetscErrorCode PetscObjectCompose_Petsc(PetscObject obj,const char name[],PetscObject ptr)
596 {
597   PetscErrorCode ierr;
598   char           *tname;
599   PetscBool      skipreference;
600 
601   PetscFunctionBegin;
602   if (ptr) {
603     ierr = PetscObjectListReverseFind(ptr->olist,obj,&tname,&skipreference);CHKERRQ(ierr);
604     if (tname && !skipreference) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"An object cannot be composed with an object that was composed with it");
605   }
606   ierr = PetscObjectListAdd(&obj->olist,name,ptr);CHKERRQ(ierr);
607   PetscFunctionReturn(0);
608 }
609 
610 PetscErrorCode PetscObjectQuery_Petsc(PetscObject obj,const char name[],PetscObject *ptr)
611 {
612   PetscErrorCode ierr;
613 
614   PetscFunctionBegin;
615   PetscValidHeader(obj,1);
616   ierr = PetscObjectListFind(obj->olist,name,ptr);CHKERRQ(ierr);
617   PetscFunctionReturn(0);
618 }
619 
620 PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject obj,const char name[],void (*ptr)(void))
621 {
622   PetscErrorCode ierr;
623 
624   PetscFunctionBegin;
625   PetscValidHeader(obj,1);
626   ierr = PetscFunctionListAdd(&obj->qlist,name,ptr);CHKERRQ(ierr);
627   PetscFunctionReturn(0);
628 }
629 
630 PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject obj,const char name[],void (**ptr)(void))
631 {
632   PetscErrorCode ierr;
633 
634   PetscFunctionBegin;
635   PetscValidHeader(obj,1);
636   ierr = PetscFunctionListFind(obj->qlist,name,ptr);CHKERRQ(ierr);
637   PetscFunctionReturn(0);
638 }
639 
640 /*@C
641    PetscObjectCompose - Associates another PETSc object with a given PETSc object.
642 
643    Not Collective
644 
645    Input Parameters:
646 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
647          PetscObjectCompose((PetscObject)mat,...);
648 .  name - name associated with the child object
649 -  ptr - the other PETSc object to associate with the PETSc object; this must also be
650          cast with (PetscObject)
651 
652    Level: advanced
653 
654    Notes:
655    The second objects reference count is automatically increased by one when it is
656    composed.
657 
658    Replaces any previous object that had the same name.
659 
660    If ptr is null and name has previously been composed using an object, then that
661    entry is removed from the obj.
662 
663    PetscObjectCompose() can be used with any PETSc object (such as
664    Mat, Vec, KSP, SNES, etc.) or any user-provided object.  See
665    PetscContainerCreate() for info on how to create an object from a
666    user-provided pointer that may then be composed with PETSc objects.
667 
668    Concepts: objects^composing
669    Concepts: composing objects
670 
671 .seealso: PetscObjectQuery(), PetscContainerCreate()
672 @*/
673 PetscErrorCode  PetscObjectCompose(PetscObject obj,const char name[],PetscObject ptr)
674 {
675   PetscErrorCode ierr;
676 
677   PetscFunctionBegin;
678   PetscValidHeader(obj,1);
679   PetscValidCharPointer(name,2);
680   if (ptr) PetscValidHeader(ptr,3);
681   if (obj == ptr) SETERRQ(PetscObjectComm((PetscObject)obj),PETSC_ERR_SUP,"Cannot compose object with itself");
682   ierr = (*obj->bops->compose)(obj,name,ptr);CHKERRQ(ierr);
683   PetscFunctionReturn(0);
684 }
685 
686 /*@C
687    PetscObjectQuery  - Gets a PETSc object associated with a given object.
688 
689    Not Collective
690 
691    Input Parameters:
692 +  obj - the PETSc object
693          Thus must be cast with a (PetscObject), for example,
694          PetscObjectCompose((PetscObject)mat,...);
695 .  name - name associated with child object
696 -  ptr - the other PETSc object associated with the PETSc object, this must be
697          cast with (PetscObject*)
698 
699    Level: advanced
700 
701    The reference count of neither object is increased in this call
702 
703    Concepts: objects^composing
704    Concepts: composing objects
705    Concepts: objects^querying
706    Concepts: querying objects
707 
708 .seealso: PetscObjectCompose()
709 @*/
710 PetscErrorCode  PetscObjectQuery(PetscObject obj,const char name[],PetscObject *ptr)
711 {
712   PetscErrorCode ierr;
713 
714   PetscFunctionBegin;
715   PetscValidHeader(obj,1);
716   PetscValidCharPointer(name,2);
717   PetscValidPointer(ptr,3);
718   ierr = (*obj->bops->query)(obj,name,ptr);CHKERRQ(ierr);
719   PetscFunctionReturn(0);
720 }
721 
722 /*MC
723    PetscObjectComposeFunction - Associates a function with a given PETSc object.
724 
725     Synopsis:
726     #include <petscsys.h>
727     PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void))
728 
729    Logically Collective on PetscObject
730 
731    Input Parameters:
732 +  obj - the PETSc object; this must be cast with a (PetscObject), for example,
733          PetscObjectCompose((PetscObject)mat,...);
734 .  name - name associated with the child function
735 .  fname - name of the function
736 -  fptr - function pointer
737 
738    Level: advanced
739 
740    Notes:
741    To remove a registered routine, pass in NULL for fptr().
742 
743    PetscObjectComposeFunction() can be used with any PETSc object (such as
744    Mat, Vec, KSP, SNES, etc.) or any user-provided object.
745 
746    Concepts: objects^composing functions
747    Concepts: composing functions
748    Concepts: functions^querying
749    Concepts: objects^querying
750    Concepts: querying objects
751 
752 .seealso: PetscObjectQueryFunction(), PetscContainerCreate()
753 M*/
754 
755 PetscErrorCode  PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void))
756 {
757   PetscErrorCode ierr;
758 
759   PetscFunctionBegin;
760   PetscValidHeader(obj,1);
761   PetscValidCharPointer(name,2);
762   ierr = (*obj->bops->composefunction)(obj,name,fptr);CHKERRQ(ierr);
763   PetscFunctionReturn(0);
764 }
765 
766 /*MC
767    PetscObjectQueryFunction - Gets a function associated with a given object.
768 
769     Synopsis:
770     #include <petscsys.h>
771     PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
772 
773    Logically Collective on PetscObject
774 
775    Input Parameters:
776 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
777          PetscObjectQueryFunction((PetscObject)ksp,...);
778 -  name - name associated with the child function
779 
780    Output Parameter:
781 .  fptr - function pointer
782 
783    Level: advanced
784 
785    Concepts: objects^composing functions
786    Concepts: composing functions
787    Concepts: functions^querying
788    Concepts: objects^querying
789    Concepts: querying objects
790 
791 .seealso: PetscObjectComposeFunction(), PetscFunctionListFind()
792 M*/
793 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void))
794 {
795   PetscErrorCode ierr;
796 
797   PetscFunctionBegin;
798   PetscValidHeader(obj,1);
799   PetscValidCharPointer(name,2);
800   ierr = (*obj->bops->queryfunction)(obj,name,ptr);CHKERRQ(ierr);
801   PetscFunctionReturn(0);
802 }
803 
804 struct _p_PetscContainer {
805   PETSCHEADER(int);
806   void           *ptr;
807   PetscErrorCode (*userdestroy)(void*);
808 };
809 
810 /*@C
811    PetscContainerUserDestroyDefault - Default destroy routine for user-provided data that simply calls PetscFree().
812 
813    Logically Collective on PetscContainer
814 
815    Input Parameter:
816 .  ctx - pointer to user-provided data
817 
818    Level: advanced
819 
820 .seealso: PetscContainerDestroy(), PetscContainterSetUserDestroy()
821 @*/
822 PetscErrorCode PetscContainerUserDestroyDefault(void* ctx)
823 {
824   PetscErrorCode ierr;
825 
826   PetscFunctionBegin;
827   PetscValidPointer(ctx,1);
828   ierr = PetscFree(ctx);CHKERRQ(ierr);
829   PetscFunctionReturn(0);
830 }
831 
832 /*@C
833    PetscContainerGetPointer - Gets the pointer value contained in the container.
834 
835    Not Collective
836 
837    Input Parameter:
838 .  obj - the object created with PetscContainerCreate()
839 
840    Output Parameter:
841 .  ptr - the pointer value
842 
843    Level: advanced
844 
845 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
846           PetscContainerSetPointer()
847 @*/
848 PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
849 {
850   PetscFunctionBegin;
851   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
852   PetscValidPointer(ptr,2);
853   *ptr = obj->ptr;
854   PetscFunctionReturn(0);
855 }
856 
857 
858 /*@C
859    PetscContainerSetPointer - Sets the pointer value contained in the container.
860 
861    Logically Collective on PetscContainer
862 
863    Input Parameters:
864 +  obj - the object created with PetscContainerCreate()
865 -  ptr - the pointer value
866 
867    Level: advanced
868 
869 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
870           PetscContainerGetPointer()
871 @*/
872 PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
873 {
874   PetscFunctionBegin;
875   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
876   if (ptr) PetscValidPointer(ptr,2);
877   obj->ptr = ptr;
878   PetscFunctionReturn(0);
879 }
880 
881 /*@C
882    PetscContainerDestroy - Destroys a PETSc container object.
883 
884    Collective on PetscContainer
885 
886    Input Parameter:
887 .  obj - an object that was created with PetscContainerCreate()
888 
889    Level: advanced
890 
891 .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
892 @*/
893 PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
894 {
895   PetscErrorCode ierr;
896 
897   PetscFunctionBegin;
898   if (!*obj) PetscFunctionReturn(0);
899   PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1);
900   if (--((PetscObject)(*obj))->refct > 0) {*obj = 0; PetscFunctionReturn(0);}
901   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
902   ierr = PetscHeaderDestroy(obj);CHKERRQ(ierr);
903   PetscFunctionReturn(0);
904 }
905 
906 /*@C
907    PetscContainerSetUserDestroy - Sets name of the user destroy function.
908 
909    Logically Collective on PetscContainer
910 
911    Input Parameter:
912 +  obj - an object that was created with PetscContainerCreate()
913 -  des - name of the user destroy function
914 
915    Notes:
916    Use PetscContainerUserDestroyDefault() if the memory was obtained by calling PetscMalloc or one of its variants for single memory allocation.
917 
918    Level: advanced
919 
920 .seealso: PetscContainerDestroy(), PetscContainerUserDestroyDefault(), PetscMalloc(), PetscMalloc1(), PetscCalloc(), PetscCalloc1()
921 @*/
922 PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
923 {
924   PetscFunctionBegin;
925   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
926   obj->userdestroy = des;
927   PetscFunctionReturn(0);
928 }
929 
930 PetscClassId PETSC_CONTAINER_CLASSID;
931 
932 /*@C
933    PetscContainerCreate - Creates a PETSc object that has room to hold
934    a single pointer. This allows one to attach any type of data (accessible
935    through a pointer) with the PetscObjectCompose() function to a PetscObject.
936    The data item itself is attached by a call to PetscContainerSetPointer().
937 
938    Collective on MPI_Comm
939 
940    Input Parameters:
941 .  comm - MPI communicator that shares the object
942 
943    Output Parameters:
944 .  container - the container created
945 
946    Level: advanced
947 
948 .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer()
949 @*/
950 PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
951 {
952   PetscErrorCode ierr;
953   PetscContainer contain;
954 
955   PetscFunctionBegin;
956   PetscValidPointer(container,2);
957   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
958   ierr = PetscHeaderCreate(contain,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,NULL);CHKERRQ(ierr);
959   *container = contain;
960   PetscFunctionReturn(0);
961 }
962 
963 /*@
964    PetscObjectSetFromOptions - Sets generic parameters from user options.
965 
966    Collective on obj
967 
968    Input Parameter:
969 .  obj - the PetscObjcet
970 
971    Options Database Keys:
972 
973    Notes:
974    We have no generic options at present, so this does nothing
975 
976    Level: beginner
977 
978 .keywords: set, options, database
979 .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
980 @*/
981 PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
982 {
983   PetscFunctionBegin;
984   PetscValidHeader(obj,1);
985   PetscFunctionReturn(0);
986 }
987 
988 /*@
989    PetscObjectSetUp - Sets up the internal data structures for the later use.
990 
991    Collective on PetscObject
992 
993    Input Parameters:
994 .  obj - the PetscObject
995 
996    Notes:
997    This does nothing at present.
998 
999    Level: advanced
1000 
1001 .keywords: setup
1002 .seealso: PetscObjectDestroy()
1003 @*/
1004 PetscErrorCode  PetscObjectSetUp(PetscObject obj)
1005 {
1006   PetscFunctionBegin;
1007   PetscValidHeader(obj,1);
1008   PetscFunctionReturn(0);
1009 }
1010