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