xref: /petsc/src/sys/objects/inherit.c (revision 3e1910f1ab6113d8365e15c6b8c907ccce7ce4ea)
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[],void (*fptr)(void))
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 -  fptr - function pointer
803 
804    Level: advanced
805 
806    Notes:
807    To remove a registered routine, pass in NULL for fptr().
808 
809    PetscObjectComposeFunction() 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(), PetscContainerCreate()
819 M*/
820 
821 #undef __FUNCT__
822 #define __FUNCT__ "PetscObjectComposeFunction_Private"
823 PetscErrorCode  PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void))
824 {
825   PetscErrorCode ierr;
826 
827   PetscFunctionBegin;
828   PetscValidHeader(obj,1);
829   PetscValidCharPointer(name,2);
830   ierr = (*obj->bops->composefunction)(obj,name,fptr);CHKERRQ(ierr);
831   PetscFunctionReturn(0);
832 }
833 
834 /*MC
835    PetscObjectQueryFunction - Gets a function associated with a given object.
836 
837     Synopsis:
838     #include "petscsys.h"
839     PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
840 
841    Logically Collective on PetscObject
842 
843    Input Parameters:
844 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
845          PetscObjectQueryFunction((PetscObject)ksp,...);
846 -  name - name associated with the child function
847 
848    Output Parameter:
849 .  fptr - function pointer
850 
851    Level: advanced
852 
853    Concepts: objects^composing functions
854    Concepts: composing functions
855    Concepts: functions^querying
856    Concepts: objects^querying
857    Concepts: querying objects
858 
859 .seealso: PetscObjectComposeFunction(), PetscFunctionListFind()
860 M*/
861 #undef __FUNCT__
862 #define __FUNCT__ "PetscObjectQueryFunction_Private"
863 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void))
864 {
865   PetscErrorCode ierr;
866 
867   PetscFunctionBegin;
868   PetscValidHeader(obj,1);
869   PetscValidCharPointer(name,2);
870   ierr = (*obj->bops->queryfunction)(obj,name,ptr);CHKERRQ(ierr);
871   PetscFunctionReturn(0);
872 }
873 
874 struct _p_PetscContainer {
875   PETSCHEADER(int);
876   void           *ptr;
877   PetscErrorCode (*userdestroy)(void*);
878 };
879 
880 #undef __FUNCT__
881 #define __FUNCT__ "PetscContainerGetPointer"
882 /*@C
883    PetscContainerGetPointer - Gets the pointer value contained in the container.
884 
885    Not Collective
886 
887    Input Parameter:
888 .  obj - the object created with PetscContainerCreate()
889 
890    Output Parameter:
891 .  ptr - the pointer value
892 
893    Level: advanced
894 
895 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
896           PetscContainerSetPointer()
897 @*/
898 PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
899 {
900   PetscFunctionBegin;
901   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
902   PetscValidPointer(ptr,2);
903   *ptr = obj->ptr;
904   PetscFunctionReturn(0);
905 }
906 
907 
908 #undef __FUNCT__
909 #define __FUNCT__ "PetscContainerSetPointer"
910 /*@C
911    PetscContainerSetPointer - Sets the pointer value contained in the container.
912 
913    Logically Collective on PetscContainer
914 
915    Input Parameters:
916 +  obj - the object created with PetscContainerCreate()
917 -  ptr - the pointer value
918 
919    Level: advanced
920 
921 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
922           PetscContainerGetPointer()
923 @*/
924 PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
925 {
926   PetscFunctionBegin;
927   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
928   if (ptr) PetscValidPointer(ptr,2);
929   obj->ptr = ptr;
930   PetscFunctionReturn(0);
931 }
932 
933 #undef __FUNCT__
934 #define __FUNCT__ "PetscContainerDestroy"
935 /*@C
936    PetscContainerDestroy - Destroys a PETSc container object.
937 
938    Collective on PetscContainer
939 
940    Input Parameter:
941 .  obj - an object that was created with PetscContainerCreate()
942 
943    Level: advanced
944 
945 .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
946 @*/
947 PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
948 {
949   PetscErrorCode ierr;
950 
951   PetscFunctionBegin;
952   if (!*obj) PetscFunctionReturn(0);
953   PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1);
954   if (--((PetscObject)(*obj))->refct > 0) {*obj = 0; PetscFunctionReturn(0);}
955   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
956   ierr = PetscHeaderDestroy(obj);CHKERRQ(ierr);
957   PetscFunctionReturn(0);
958 }
959 
960 #undef __FUNCT__
961 #define __FUNCT__ "PetscContainerSetUserDestroy"
962 /*@C
963    PetscContainerSetUserDestroy - Sets name of the user destroy function.
964 
965    Logically Collective on PetscContainer
966 
967    Input Parameter:
968 +  obj - an object that was created with PetscContainerCreate()
969 -  des - name of the user destroy function
970 
971    Level: advanced
972 
973 .seealso: PetscContainerDestroy()
974 @*/
975 PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
976 {
977   PetscFunctionBegin;
978   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
979   obj->userdestroy = des;
980   PetscFunctionReturn(0);
981 }
982 
983 PetscClassId PETSC_CONTAINER_CLASSID;
984 
985 #undef __FUNCT__
986 #define __FUNCT__ "PetscContainerCreate"
987 /*@C
988    PetscContainerCreate - Creates a PETSc object that has room to hold
989    a single pointer. This allows one to attach any type of data (accessible
990    through a pointer) with the PetscObjectCompose() function to a PetscObject.
991    The data item itself is attached by a call to PetscContainerSetPointer().
992 
993    Collective on MPI_Comm
994 
995    Input Parameters:
996 .  comm - MPI communicator that shares the object
997 
998    Output Parameters:
999 .  container - the container created
1000 
1001    Level: advanced
1002 
1003 .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer()
1004 @*/
1005 PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
1006 {
1007   PetscErrorCode ierr;
1008   PetscContainer contain;
1009 
1010   PetscFunctionBegin;
1011   PetscValidPointer(container,2);
1012   ierr = PetscHeaderCreate(contain,_p_PetscContainer,PetscInt,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,0);CHKERRQ(ierr);
1013   *container = contain;
1014   PetscFunctionReturn(0);
1015 }
1016 
1017 #undef __FUNCT__
1018 #define __FUNCT__ "PetscObjectSetFromOptions"
1019 /*@
1020    PetscObjectSetFromOptions - Sets generic parameters from user options.
1021 
1022    Collective on obj
1023 
1024    Input Parameter:
1025 .  obj - the PetscObjcet
1026 
1027    Options Database Keys:
1028 
1029    Notes:
1030    We have no generic options at present, so this does nothing
1031 
1032    Level: beginner
1033 
1034 .keywords: set, options, database
1035 .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
1036 @*/
1037 PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
1038 {
1039   PetscFunctionBegin;
1040   PetscValidHeader(obj,1);
1041   PetscFunctionReturn(0);
1042 }
1043 
1044 #undef __FUNCT__
1045 #define __FUNCT__ "PetscObjectSetUp"
1046 /*@
1047    PetscObjectSetUp - Sets up the internal data structures for the later use.
1048 
1049    Collective on PetscObject
1050 
1051    Input Parameters:
1052 .  obj - the PetscObject
1053 
1054    Notes:
1055    This does nothing at present.
1056 
1057    Level: advanced
1058 
1059 .keywords: setup
1060 .seealso: PetscObjectDestroy()
1061 @*/
1062 PetscErrorCode  PetscObjectSetUp(PetscObject obj)
1063 {
1064   PetscFunctionBegin;
1065   PetscValidHeader(obj,1);
1066   PetscFunctionReturn(0);
1067 }
1068