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