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