xref: /petsc/src/sys/objects/inherit.c (revision cb9d8021f64c572d262e10034bbd2fb15469a2b9)
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 #if defined(PETSC_USE_LOG)
9 PetscObject *PetscObjects      = 0;
10 PetscInt    PetscObjectsCounts = 0, PetscObjectsMaxCounts = 0;
11 PetscBool   PetscObjectsLog    = PETSC_FALSE;
12 #endif
13 
14 extern PetscErrorCode PetscObjectGetComm_Petsc(PetscObject,MPI_Comm*);
15 extern PetscErrorCode PetscObjectCompose_Petsc(PetscObject,const char[],PetscObject);
16 extern PetscErrorCode PetscObjectQuery_Petsc(PetscObject,const char[],PetscObject*);
17 extern PetscErrorCode PetscObjectComposeFunction_Petsc(PetscObject,const char[],void (*)(void));
18 extern PetscErrorCode PetscObjectQueryFunction_Petsc(PetscObject,const char[],void (**)(void));
19 
20 #undef __FUNCT__
21 #define __FUNCT__ "PetscHeaderCreate_Private"
22 /*
23    PetscHeaderCreate_Private - Creates a base PETSc object header and fills
24    in the default values.  Called by the macro PetscHeaderCreate().
25 */
26 PetscErrorCode  PetscHeaderCreate_Private(PetscObject h,PetscClassId classid,const char class_name[],const char descr[],const char mansec[],
27                                           MPI_Comm comm,PetscErrorCode (*des)(PetscObject*),PetscErrorCode (*vie)(PetscObject,PetscViewer))
28 {
29   static PetscInt idcnt = 1;
30   PetscErrorCode  ierr;
31 #if defined(PETSC_USE_LOG)
32   PetscObject     *newPetscObjects;
33   PetscInt         newPetscObjectsMaxCounts,i;
34 #endif
35 
36   PetscFunctionBegin;
37   h->classid               = classid;
38   h->type                  = 0;
39   h->class_name            = (char*)class_name;
40   h->description           = (char*)descr;
41   h->mansec                = (char*)mansec;
42   h->prefix                = 0;
43   h->refct                 = 1;
44 #if defined(PETSC_HAVE_SAWS)
45   h->amsmem                = PETSC_FALSE;
46 #endif
47   h->id                    = idcnt++;
48   h->parentid              = 0;
49   h->qlist                 = 0;
50   h->olist                 = 0;
51   h->precision             = (PetscPrecision) sizeof(PetscReal);
52   h->bops->destroy         = des;
53   h->bops->view            = vie;
54   h->bops->getcomm         = PetscObjectGetComm_Petsc;
55   h->bops->compose         = PetscObjectCompose_Petsc;
56   h->bops->query           = PetscObjectQuery_Petsc;
57   h->bops->composefunction = PetscObjectComposeFunction_Petsc;
58   h->bops->queryfunction   = PetscObjectQueryFunction_Petsc;
59 
60   ierr = PetscCommDuplicate(comm,&h->comm,&h->tag);CHKERRQ(ierr);
61 
62 #if defined(PETSC_USE_LOG)
63   /* Keep a record of object created */
64   if (PetscObjectsLog) {
65     PetscObjectsCounts++;
66     for (i=0; i<PetscObjectsMaxCounts; i++) {
67       if (!PetscObjects[i]) {
68         PetscObjects[i] = h;
69         PetscFunctionReturn(0);
70       }
71     }
72     /* Need to increase the space for storing PETSc objects */
73     if (!PetscObjectsMaxCounts) newPetscObjectsMaxCounts = 100;
74     else                        newPetscObjectsMaxCounts = 2*PetscObjectsMaxCounts;
75     ierr = PetscMalloc1(newPetscObjectsMaxCounts,&newPetscObjects);CHKERRQ(ierr);
76     ierr = PetscMemcpy(newPetscObjects,PetscObjects,PetscObjectsMaxCounts*sizeof(PetscObject));CHKERRQ(ierr);
77     ierr = PetscMemzero(newPetscObjects+PetscObjectsMaxCounts,(newPetscObjectsMaxCounts - PetscObjectsMaxCounts)*sizeof(PetscObject));CHKERRQ(ierr);
78     ierr = PetscFree(PetscObjects);CHKERRQ(ierr);
79 
80     PetscObjects                        = newPetscObjects;
81     PetscObjects[PetscObjectsMaxCounts] = h;
82     PetscObjectsMaxCounts               = newPetscObjectsMaxCounts;
83   }
84 #endif
85   PetscFunctionReturn(0);
86 }
87 
88 extern PetscBool      PetscMemoryCollectMaximumUsage;
89 extern PetscLogDouble PetscMemoryMaximumUsage;
90 
91 #undef __FUNCT__
92 #define __FUNCT__ "PetscHeaderDestroy_Private"
93 /*
94     PetscHeaderDestroy_Private - Destroys a base PETSc object header. Called by
95     the macro PetscHeaderDestroy().
96 */
97 PetscErrorCode  PetscHeaderDestroy_Private(PetscObject h)
98 {
99   PetscErrorCode ierr;
100 
101   PetscFunctionBegin;
102   PetscValidHeader(h,1);
103   ierr = PetscLogObjectDestroy(h);CHKERRQ(ierr);
104   ierr = PetscComposedQuantitiesDestroy(h);
105   if (PetscMemoryCollectMaximumUsage) {
106     PetscLogDouble usage;
107     ierr = PetscMemoryGetCurrentUsage(&usage);CHKERRQ(ierr);
108     if (usage > PetscMemoryMaximumUsage) PetscMemoryMaximumUsage = usage;
109   }
110   /* first destroy things that could execute arbitrary code */
111   if (h->python_destroy) {
112     void           *python_context = h->python_context;
113     PetscErrorCode (*python_destroy)(void*) = h->python_destroy;
114     h->python_context = 0;
115     h->python_destroy = 0;
116 
117     ierr = (*python_destroy)(python_context);CHKERRQ(ierr);
118   }
119   ierr = PetscObjectDestroyOptionsHandlers(h);CHKERRQ(ierr);
120   ierr = PetscObjectListDestroy(&h->olist);CHKERRQ(ierr);
121   ierr = PetscCommDestroy(&h->comm);CHKERRQ(ierr);
122   /* next destroy other things */
123   h->classid = PETSCFREEDHEADER;
124 
125   ierr = PetscFree(h->bops);CHKERRQ(ierr);
126   ierr = PetscFunctionListDestroy(&h->qlist);CHKERRQ(ierr);
127   ierr = PetscFree(h->type_name);CHKERRQ(ierr);
128   ierr = PetscFree(h->name);CHKERRQ(ierr);
129   ierr = PetscFree(h->prefix);CHKERRQ(ierr);
130   ierr = PetscFree(h->fortran_func_pointers);CHKERRQ(ierr);
131   ierr = PetscFree(h->fortrancallback[PETSC_FORTRAN_CALLBACK_CLASS]);CHKERRQ(ierr);
132   ierr = PetscFree(h->fortrancallback[PETSC_FORTRAN_CALLBACK_SUBTYPE]);CHKERRQ(ierr);
133 
134 #if defined(PETSC_USE_LOG)
135   if (PetscObjectsLog) {
136     PetscInt i;
137     /* Record object removal from list of all objects */
138     for (i=0; i<PetscObjectsMaxCounts; i++) {
139       if (PetscObjects[i] == h) {
140         PetscObjects[i] = 0;
141         PetscObjectsCounts--;
142         break;
143       }
144     }
145     if (!PetscObjectsCounts) {
146       ierr = PetscFree(PetscObjects);CHKERRQ(ierr);
147       PetscObjectsMaxCounts = 0;
148     }
149   }
150 #endif
151   PetscFunctionReturn(0);
152 }
153 
154 #undef __FUNCT__
155 #define __FUNCT__ "PetscObjectCopyFortranFunctionPointers"
156 /*@C
157    PetscObjectCopyFortranFunctionPointers - Copy function pointers to another object
158 
159    Logically Collective on PetscObject
160 
161    Input Parameter:
162 +  src - source object
163 -  dest - destination object
164 
165    Level: developer
166 
167    Note:
168    Both objects must have the same class.
169 @*/
170 PetscErrorCode PetscObjectCopyFortranFunctionPointers(PetscObject src,PetscObject dest)
171 {
172   PetscErrorCode ierr;
173   PetscInt       cbtype,numcb[PETSC_FORTRAN_CALLBACK_MAXTYPE];
174 
175   PetscFunctionBegin;
176   PetscValidHeader(src,1);
177   PetscValidHeader(dest,2);
178   if (src->classid != dest->classid) SETERRQ(src->comm,PETSC_ERR_ARG_INCOMP,"Objects must be of the same class");
179 
180   ierr = PetscFree(dest->fortran_func_pointers);CHKERRQ(ierr);
181   ierr = PetscMalloc(src->num_fortran_func_pointers*sizeof(void(*)(void)),&dest->fortran_func_pointers);CHKERRQ(ierr);
182   ierr = PetscMemcpy(dest->fortran_func_pointers,src->fortran_func_pointers,src->num_fortran_func_pointers*sizeof(void(*)(void)));CHKERRQ(ierr);
183 
184   dest->num_fortran_func_pointers = src->num_fortran_func_pointers;
185 
186   ierr = PetscFortranCallbackGetSizes(src->classid,&numcb[PETSC_FORTRAN_CALLBACK_CLASS],&numcb[PETSC_FORTRAN_CALLBACK_SUBTYPE]);CHKERRQ(ierr);
187   for (cbtype=PETSC_FORTRAN_CALLBACK_CLASS; cbtype<PETSC_FORTRAN_CALLBACK_MAXTYPE; cbtype++) {
188     ierr = PetscFree(dest->fortrancallback[cbtype]);CHKERRQ(ierr);
189     ierr = PetscCalloc1(numcb[cbtype],&dest->fortrancallback[cbtype]);CHKERRQ(ierr);
190     ierr = PetscMemcpy(dest->fortrancallback[cbtype],src->fortrancallback[cbtype],src->num_fortrancallback[cbtype]*sizeof(PetscFortranCallback));CHKERRQ(ierr);
191   }
192   PetscFunctionReturn(0);
193 }
194 
195 #undef __FUNCT__
196 #define __FUNCT__ "PetscObjectSetFortranCallback"
197 /*@C
198    PetscObjectSetFortranCallback - set fortran callback function pointer and context
199 
200    Logically Collective
201 
202    Input Arguments:
203 +  obj - object on which to set callback
204 .  cbtype - callback type (class or subtype)
205 .  cid - address of callback Id, updated if not yet initialized (zero)
206 .  func - Fortran function
207 -  ctx - Fortran context
208 
209    Level: developer
210 
211 .seealso: PetscObjectGetFortranCallback()
212 @*/
213 PetscErrorCode PetscObjectSetFortranCallback(PetscObject obj,PetscFortranCallbackType cbtype,PetscFortranCallbackId *cid,void (*func)(void),void *ctx)
214 {
215   PetscErrorCode ierr;
216   const char     *subtype = NULL;
217 
218   PetscFunctionBegin;
219   PetscValidHeader(obj,1);
220   if (cbtype == PETSC_FORTRAN_CALLBACK_SUBTYPE) subtype = obj->type_name;
221   if (!*cid) {ierr = PetscFortranCallbackRegister(obj->classid,subtype,cid);CHKERRQ(ierr);}
222   if (*cid >= PETSC_SMALLEST_FORTRAN_CALLBACK+obj->num_fortrancallback[cbtype]) {
223     PetscInt             oldnum = obj->num_fortrancallback[cbtype],newnum = PetscMax(1,2*oldnum);
224     PetscFortranCallback *callback;
225     ierr = PetscMalloc1(newnum,&callback);CHKERRQ(ierr);
226     ierr = PetscMemcpy(callback,obj->fortrancallback[cbtype],oldnum*sizeof(*obj->fortrancallback[cbtype]));CHKERRQ(ierr);
227     ierr = PetscFree(obj->fortrancallback[cbtype]);CHKERRQ(ierr);
228 
229     obj->fortrancallback[cbtype] = callback;
230     obj->num_fortrancallback[cbtype] = newnum;
231   }
232   obj->fortrancallback[cbtype][*cid-PETSC_SMALLEST_FORTRAN_CALLBACK].func = func;
233   obj->fortrancallback[cbtype][*cid-PETSC_SMALLEST_FORTRAN_CALLBACK].ctx = ctx;
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "PetscObjectGetFortranCallback"
239 /*@C
240    PetscObjectGetFortranCallback - get fortran callback function pointer and context
241 
242    Logically Collective
243 
244    Input Arguments:
245 +  obj - object on which to get callback
246 .  cbtype - callback type
247 -  cid - address of callback Id
248 
249    Output Arguments:
250 +  func - Fortran function (or NULL if not needed)
251 -  ctx - Fortran context (or NULL if not needed)
252 
253    Level: developer
254 
255 .seealso: PetscObjectSetFortranCallback()
256 @*/
257 PetscErrorCode PetscObjectGetFortranCallback(PetscObject obj,PetscFortranCallbackType cbtype,PetscFortranCallbackId cid,void (**func)(void),void **ctx)
258 {
259   PetscFortranCallback *cb;
260 
261   PetscFunctionBegin;
262   PetscValidHeader(obj,1);
263   if (PetscUnlikely(cid < PETSC_SMALLEST_FORTRAN_CALLBACK)) SETERRQ(obj->comm,PETSC_ERR_ARG_CORRUPT,"Fortran callback Id invalid");
264   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");
265   cb = &obj->fortrancallback[cbtype][cid-PETSC_SMALLEST_FORTRAN_CALLBACK];
266   if (func) *func = cb->func;
267   if (ctx) *ctx = cb->ctx;
268   PetscFunctionReturn(0);
269 }
270 
271 #if defined(PETSC_USE_LOG)
272 #undef __FUNCT__
273 #define __FUNCT__ "PetscObjectsDump"
274 /*@C
275    PetscObjectsDump - Prints the currently existing objects.
276 
277    Logically Collective on PetscViewer
278 
279    Input Parameter:
280 +  fd - file pointer
281 -  all - by default only tries to display objects created explicitly by the user, if all is PETSC_TRUE then lists all outstanding objects
282 
283    Options Database:
284 .  -objects_dump <all>
285 
286    Level: advanced
287 
288    Concepts: options database^printing
289 
290 @*/
291 PetscErrorCode  PetscObjectsDump(FILE *fd,PetscBool all)
292 {
293   PetscErrorCode ierr;
294   PetscInt       i;
295 #if defined(PETSC_USE_DEBUG)
296   PetscInt       j,k=0;
297 #endif
298   PetscObject    h;
299 
300   PetscFunctionBegin;
301   if (PetscObjectsCounts) {
302     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"The following objects were never freed\n");CHKERRQ(ierr);
303     ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"-----------------------------------------\n");CHKERRQ(ierr);
304     for (i=0; i<PetscObjectsMaxCounts; i++) {
305       if ((h = PetscObjects[i])) {
306         ierr = PetscObjectName(h);CHKERRQ(ierr);
307         {
308 #if defined(PETSC_USE_DEBUG)
309         PetscStack *stack = 0;
310         char       *create,*rclass;
311 
312         /* if the PETSc function the user calls is not a create then this object was NOT directly created by them */
313         ierr = PetscMallocGetStack(h,&stack);CHKERRQ(ierr);
314         if (stack) {
315           k = stack->currentsize-2;
316           if (!all) {
317             k = 0;
318             while (!stack->petscroutine[k]) k++;
319             ierr = PetscStrstr(stack->function[k],"Create",&create);CHKERRQ(ierr);
320             if (!create) {
321               ierr = PetscStrstr(stack->function[k],"Get",&create);CHKERRQ(ierr);
322             }
323             ierr = PetscStrstr(stack->function[k],h->class_name,&rclass);CHKERRQ(ierr);
324             if (!create) continue;
325             if (!rclass) continue;
326           }
327         }
328 #endif
329 
330         ierr = PetscFPrintf(PETSC_COMM_WORLD,fd,"[%d] %s %s %s\n",PetscGlobalRank,h->class_name,h->type_name,h->name);CHKERRQ(ierr);
331 
332 #if defined(PETSC_USE_DEBUG)
333         ierr = PetscMallocGetStack(h,&stack);CHKERRQ(ierr);
334         if (stack) {
335           for (j=k; j>=0; j--) {
336             fprintf(fd,"      [%d]  %s() in %s\n",PetscGlobalRank,stack->function[j],stack->file[j]);
337           }
338         }
339 #endif
340         }
341       }
342     }
343   }
344   PetscFunctionReturn(0);
345 }
346 #endif
347 
348 #if defined(PETSC_USE_LOG)
349 
350 #undef __FUNCT__
351 #define __FUNCT__ "PetscObjectsView"
352 /*@C
353    PetscObjectsView - Prints the currently existing objects.
354 
355    Logically Collective on PetscViewer
356 
357    Input Parameter:
358 .  viewer - must be an PETSCVIEWERASCII viewer
359 
360    Level: advanced
361 
362    Concepts: options database^printing
363 
364 @*/
365 PetscErrorCode  PetscObjectsView(PetscViewer viewer)
366 {
367   PetscErrorCode ierr;
368   PetscBool      isascii;
369   FILE           *fd;
370 
371   PetscFunctionBegin;
372   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
373   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
374   if (!isascii) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Only supports ASCII viewer");
375   ierr = PetscViewerASCIIGetPointer(viewer,&fd);CHKERRQ(ierr);
376   ierr = PetscObjectsDump(fd,PETSC_TRUE);CHKERRQ(ierr);
377   PetscFunctionReturn(0);
378 }
379 
380 #undef __FUNCT__
381 #define __FUNCT__ "PetscObjectsGetObject"
382 /*@C
383    PetscObjectsGetObject - Get a pointer to a named object
384 
385    Not collective
386 
387    Input Parameter:
388 .  name - the name of an object
389 
390    Output Parameter:
391 .   obj - the object or null if there is no object
392 
393    Level: advanced
394 
395    Concepts: options database^printing
396 
397 @*/
398 PetscErrorCode  PetscObjectsGetObject(const char *name,PetscObject *obj,char **classname)
399 {
400   PetscErrorCode ierr;
401   PetscInt       i;
402   PetscObject    h;
403   PetscBool      flg;
404 
405   PetscFunctionBegin;
406   *obj = NULL;
407   for (i=0; i<PetscObjectsMaxCounts; i++) {
408     if ((h = PetscObjects[i])) {
409       ierr = PetscObjectName(h);CHKERRQ(ierr);
410       ierr = PetscStrcmp(h->name,name,&flg);CHKERRQ(ierr);
411       if (flg) {
412         *obj = h;
413         if (classname) *classname = h->class_name;
414         PetscFunctionReturn(0);
415       }
416     }
417   }
418   PetscFunctionReturn(0);
419 }
420 #endif
421 
422 #undef __FUNCT__
423 #define __FUNCT__ "PetscObjectAddOptionsHandler"
424 /*@C
425     PetscObjectAddOptionsHandler - Adds an additional function to check for options when XXXSetFromOptions() is called.
426 
427     Not Collective
428 
429     Input Parameter:
430 +   obj - the PETSc object
431 .   handle - function that checks for options
432 .   destroy - function to destroy context if provided
433 -   ctx - optional context for check function
434 
435     Level: developer
436 
437 
438 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectProcessOptionsHandlers(), PetscObjectDestroyOptionsHandlers()
439 
440 @*/
441 PetscErrorCode  PetscObjectAddOptionsHandler(PetscObject obj,PetscErrorCode (*handle)(PetscObject,void*),PetscErrorCode (*destroy)(PetscObject,void*),void *ctx)
442 {
443   PetscFunctionBegin;
444   PetscValidHeader(obj,1);
445   if (obj->noptionhandler >= PETSC_MAX_OPTIONS_HANDLER) SETERRQ(obj->comm,PETSC_ERR_ARG_OUTOFRANGE,"To many options handlers added");
446   obj->optionhandler[obj->noptionhandler] = handle;
447   obj->optiondestroy[obj->noptionhandler] = destroy;
448   obj->optionctx[obj->noptionhandler++]   = ctx;
449   PetscFunctionReturn(0);
450 }
451 
452 #undef __FUNCT__
453 #define __FUNCT__ "PetscObjectProcessOptionsHandlers"
454 /*@C
455     PetscObjectProcessOptionsHandlers - Calls all the options handlers attached to an object
456 
457     Not Collective
458 
459     Input Parameter:
460 .   obj - the PETSc object
461 
462     Level: developer
463 
464 
465 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectDestroyOptionsHandlers()
466 
467 @*/
468 PetscErrorCode  PetscObjectProcessOptionsHandlers(PetscObject obj)
469 {
470   PetscInt       i;
471   PetscErrorCode ierr;
472 
473   PetscFunctionBegin;
474   PetscValidHeader(obj,1);
475   for (i=0; i<obj->noptionhandler; i++) {
476     ierr = (*obj->optionhandler[i])(obj,obj->optionctx[i]);CHKERRQ(ierr);
477   }
478   PetscFunctionReturn(0);
479 }
480 
481 #undef __FUNCT__
482 #define __FUNCT__ "PetscObjectDestroyOptionsHandlers"
483 /*@C
484     PetscObjectDestroyOptionsHandlers - Destroys all the option handlers attached to an object
485 
486     Not Collective
487 
488     Input Parameter:
489 .   obj - the PETSc object
490 
491     Level: developer
492 
493 
494 .seealso: KSPSetFromOptions(), PCSetFromOptions(), SNESSetFromOptions(), PetscObjectAddOptionsHandler(), PetscObjectProcessOptionsHandlers()
495 
496 @*/
497 PetscErrorCode  PetscObjectDestroyOptionsHandlers(PetscObject obj)
498 {
499   PetscInt       i;
500   PetscErrorCode ierr;
501 
502   PetscFunctionBegin;
503   PetscValidHeader(obj,1);
504   for (i=0; i<obj->noptionhandler; i++) {
505     if (obj->optiondestroy[i]) {
506       ierr = (*obj->optiondestroy[i])(obj,obj->optionctx[i]);CHKERRQ(ierr);
507     }
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   if (!obj) PetscFunctionReturn(0);
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[],void (*ptr)(void))
659 {
660   PetscErrorCode ierr;
661 
662   PetscFunctionBegin;
663   PetscValidHeader(obj,1);
664   ierr = PetscFunctionListAdd(&obj->qlist,name,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->qlist,name,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 /*MC
790    PetscObjectComposeFunction - Associates a function with a given PETSc object.
791 
792     Synopsis:
793     #include <petscsys.h>
794     PetscErrorCode PetscObjectComposeFunction(PetscObject obj,const char name[],void (*fptr)(void))
795 
796    Logically Collective on PetscObject
797 
798    Input Parameters:
799 +  obj - the PETSc object; this must be cast with a (PetscObject), for example,
800          PetscObjectCompose((PetscObject)mat,...);
801 .  name - name associated with the child function
802 .  fname - name of the function
803 -  fptr - function pointer
804 
805    Level: advanced
806 
807    Notes:
808    To remove a registered routine, pass in NULL for fptr().
809 
810    PetscObjectComposeFunction() can be used with any PETSc object (such as
811    Mat, Vec, KSP, SNES, etc.) or any user-provided object.
812 
813    Concepts: objects^composing functions
814    Concepts: composing functions
815    Concepts: functions^querying
816    Concepts: objects^querying
817    Concepts: querying objects
818 
819 .seealso: PetscObjectQueryFunction(), PetscContainerCreate()
820 M*/
821 
822 #undef __FUNCT__
823 #define __FUNCT__ "PetscObjectComposeFunction_Private"
824 PetscErrorCode  PetscObjectComposeFunction_Private(PetscObject obj,const char name[],void (*fptr)(void))
825 {
826   PetscErrorCode ierr;
827 
828   PetscFunctionBegin;
829   PetscValidHeader(obj,1);
830   PetscValidCharPointer(name,2);
831   ierr = (*obj->bops->composefunction)(obj,name,fptr);CHKERRQ(ierr);
832   PetscFunctionReturn(0);
833 }
834 
835 /*MC
836    PetscObjectQueryFunction - Gets a function associated with a given object.
837 
838     Synopsis:
839     #include <petscsys.h>
840     PetscErrorCode PetscObjectQueryFunction(PetscObject obj,const char name[],void (**fptr)(void))
841 
842    Logically Collective on PetscObject
843 
844    Input Parameters:
845 +  obj - the PETSc object; this must be cast with (PetscObject), for example,
846          PetscObjectQueryFunction((PetscObject)ksp,...);
847 -  name - name associated with the child function
848 
849    Output Parameter:
850 .  fptr - function pointer
851 
852    Level: advanced
853 
854    Concepts: objects^composing functions
855    Concepts: composing functions
856    Concepts: functions^querying
857    Concepts: objects^querying
858    Concepts: querying objects
859 
860 .seealso: PetscObjectComposeFunction(), PetscFunctionListFind()
861 M*/
862 #undef __FUNCT__
863 #define __FUNCT__ "PetscObjectQueryFunction_Private"
864 PETSC_EXTERN PetscErrorCode PetscObjectQueryFunction_Private(PetscObject obj,const char name[],void (**ptr)(void))
865 {
866   PetscErrorCode ierr;
867 
868   PetscFunctionBegin;
869   PetscValidHeader(obj,1);
870   PetscValidCharPointer(name,2);
871   ierr = (*obj->bops->queryfunction)(obj,name,ptr);CHKERRQ(ierr);
872   PetscFunctionReturn(0);
873 }
874 
875 struct _p_PetscContainer {
876   PETSCHEADER(int);
877   void           *ptr;
878   PetscErrorCode (*userdestroy)(void*);
879 };
880 
881 #undef __FUNCT__
882 #define __FUNCT__ "PetscContainerGetPointer"
883 /*@C
884    PetscContainerGetPointer - Gets the pointer value contained in the container.
885 
886    Not Collective
887 
888    Input Parameter:
889 .  obj - the object created with PetscContainerCreate()
890 
891    Output Parameter:
892 .  ptr - the pointer value
893 
894    Level: advanced
895 
896 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
897           PetscContainerSetPointer()
898 @*/
899 PetscErrorCode  PetscContainerGetPointer(PetscContainer obj,void **ptr)
900 {
901   PetscFunctionBegin;
902   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
903   PetscValidPointer(ptr,2);
904   *ptr = obj->ptr;
905   PetscFunctionReturn(0);
906 }
907 
908 
909 #undef __FUNCT__
910 #define __FUNCT__ "PetscContainerSetPointer"
911 /*@C
912    PetscContainerSetPointer - Sets the pointer value contained in the container.
913 
914    Logically Collective on PetscContainer
915 
916    Input Parameters:
917 +  obj - the object created with PetscContainerCreate()
918 -  ptr - the pointer value
919 
920    Level: advanced
921 
922 .seealso: PetscContainerCreate(), PetscContainerDestroy(),
923           PetscContainerGetPointer()
924 @*/
925 PetscErrorCode  PetscContainerSetPointer(PetscContainer obj,void *ptr)
926 {
927   PetscFunctionBegin;
928   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
929   if (ptr) PetscValidPointer(ptr,2);
930   obj->ptr = ptr;
931   PetscFunctionReturn(0);
932 }
933 
934 #undef __FUNCT__
935 #define __FUNCT__ "PetscContainerDestroy"
936 /*@C
937    PetscContainerDestroy - Destroys a PETSc container object.
938 
939    Collective on PetscContainer
940 
941    Input Parameter:
942 .  obj - an object that was created with PetscContainerCreate()
943 
944    Level: advanced
945 
946 .seealso: PetscContainerCreate(), PetscContainerSetUserDestroy()
947 @*/
948 PetscErrorCode  PetscContainerDestroy(PetscContainer *obj)
949 {
950   PetscErrorCode ierr;
951 
952   PetscFunctionBegin;
953   if (!*obj) PetscFunctionReturn(0);
954   PetscValidHeaderSpecific(*obj,PETSC_CONTAINER_CLASSID,1);
955   if (--((PetscObject)(*obj))->refct > 0) {*obj = 0; PetscFunctionReturn(0);}
956   if ((*obj)->userdestroy) (*(*obj)->userdestroy)((*obj)->ptr);
957   ierr = PetscHeaderDestroy(obj);CHKERRQ(ierr);
958   PetscFunctionReturn(0);
959 }
960 
961 #undef __FUNCT__
962 #define __FUNCT__ "PetscContainerSetUserDestroy"
963 /*@C
964    PetscContainerSetUserDestroy - Sets name of the user destroy function.
965 
966    Logically Collective on PetscContainer
967 
968    Input Parameter:
969 +  obj - an object that was created with PetscContainerCreate()
970 -  des - name of the user destroy function
971 
972    Level: advanced
973 
974 .seealso: PetscContainerDestroy()
975 @*/
976 PetscErrorCode  PetscContainerSetUserDestroy(PetscContainer obj, PetscErrorCode (*des)(void*))
977 {
978   PetscFunctionBegin;
979   PetscValidHeaderSpecific(obj,PETSC_CONTAINER_CLASSID,1);
980   obj->userdestroy = des;
981   PetscFunctionReturn(0);
982 }
983 
984 PetscClassId PETSC_CONTAINER_CLASSID;
985 
986 #undef __FUNCT__
987 #define __FUNCT__ "PetscContainerCreate"
988 /*@C
989    PetscContainerCreate - Creates a PETSc object that has room to hold
990    a single pointer. This allows one to attach any type of data (accessible
991    through a pointer) with the PetscObjectCompose() function to a PetscObject.
992    The data item itself is attached by a call to PetscContainerSetPointer().
993 
994    Collective on MPI_Comm
995 
996    Input Parameters:
997 .  comm - MPI communicator that shares the object
998 
999    Output Parameters:
1000 .  container - the container created
1001 
1002    Level: advanced
1003 
1004 .seealso: PetscContainerDestroy(), PetscContainerSetPointer(), PetscContainerGetPointer()
1005 @*/
1006 PetscErrorCode  PetscContainerCreate(MPI_Comm comm,PetscContainer *container)
1007 {
1008   PetscErrorCode ierr;
1009   PetscContainer contain;
1010 
1011   PetscFunctionBegin;
1012   PetscValidPointer(container,2);
1013   ierr = PetscSysInitializePackage();CHKERRQ(ierr);
1014   ierr = PetscHeaderCreate(contain,_p_PetscContainer,PetscInt,PETSC_CONTAINER_CLASSID,"PetscContainer","Container","Sys",comm,PetscContainerDestroy,0);CHKERRQ(ierr);
1015   *container = contain;
1016   PetscFunctionReturn(0);
1017 }
1018 
1019 #undef __FUNCT__
1020 #define __FUNCT__ "PetscObjectSetFromOptions"
1021 /*@
1022    PetscObjectSetFromOptions - Sets generic parameters from user options.
1023 
1024    Collective on obj
1025 
1026    Input Parameter:
1027 .  obj - the PetscObjcet
1028 
1029    Options Database Keys:
1030 
1031    Notes:
1032    We have no generic options at present, so this does nothing
1033 
1034    Level: beginner
1035 
1036 .keywords: set, options, database
1037 .seealso: PetscObjectSetOptionsPrefix(), PetscObjectGetOptionsPrefix()
1038 @*/
1039 PetscErrorCode  PetscObjectSetFromOptions(PetscObject obj)
1040 {
1041   PetscFunctionBegin;
1042   PetscValidHeader(obj,1);
1043   PetscFunctionReturn(0);
1044 }
1045 
1046 #undef __FUNCT__
1047 #define __FUNCT__ "PetscObjectSetUp"
1048 /*@
1049    PetscObjectSetUp - Sets up the internal data structures for the later use.
1050 
1051    Collective on PetscObject
1052 
1053    Input Parameters:
1054 .  obj - the PetscObject
1055 
1056    Notes:
1057    This does nothing at present.
1058 
1059    Level: advanced
1060 
1061 .keywords: setup
1062 .seealso: PetscObjectDestroy()
1063 @*/
1064 PetscErrorCode  PetscObjectSetUp(PetscObject obj)
1065 {
1066   PetscFunctionBegin;
1067   PetscValidHeader(obj,1);
1068   PetscFunctionReturn(0);
1069 }
1070