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