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