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