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