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