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