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