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