xref: /petsc/src/sys/classes/bag/bag.c (revision 4e278199b78715991f5c71ebbd945c1489263e6c)
1 
2 #include <petsc/private/bagimpl.h>     /*I  "petscbag.h"   I*/
3 #include <petscviewer.h>
4 
5 /*
6       Adds item to the linked list in a bag
7 */
8 static PetscErrorCode PetscBagRegister_Private(PetscBag bag,PetscBagItem item,const char *name,const char *help)
9 {
10   PetscErrorCode ierr;
11 
12   PetscFunctionBegin;
13   ierr = PetscStrncpy(item->name,name,PETSC_BAG_NAME_LENGTH-1);CHKERRQ(ierr);
14   ierr = PetscStrncpy(item->help,help,PETSC_BAG_HELP_LENGTH-1);CHKERRQ(ierr);
15   if (!bag->bagitems) bag->bagitems = item;
16   else {
17     PetscBagItem nitem = bag->bagitems;
18     while (nitem->next) {
19       nitem = nitem->next;
20     }
21     nitem->next = item;
22   }
23   bag->count++;
24   PetscFunctionReturn(0);
25 }
26 
27 /*@C
28    PetscBagRegisterEnum - add an enum value to the bag
29 
30    Logically Collective on PetscBag
31 
32    Input Parameter:
33 +  bag - the bag of values
34 .  addr - location of enum in struct
35 .  mdefault - the initial value
36 .  list - array of strings containing names of enum values followed by enum name followed by enum prefix
37 -  help - longer string with more information about the value
38 
39    Level: beginner
40 
41 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
42            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
43            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName()
44 
45 @*/
46 PetscErrorCode PetscBagRegisterEnum(PetscBag bag,void *addr,const char *const *list,PetscEnum mdefault, const char *name, const char *help)
47 {
48   PetscErrorCode ierr;
49   PetscBagItem   item;
50   char           nname[PETSC_BAG_NAME_LENGTH+1];
51   PetscBool      printhelp;
52   PetscInt       i = 0;
53 
54   PetscFunctionBegin;
55   nname[0] = '-';
56   nname[1] = 0;
57   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
58   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
59   if (printhelp) {
60     while (list[i++]) ;
61     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <%s>: (%s) %s (choose one of) ",bag->bagprefix ? bag->bagprefix : "",name,list[mdefault],list[i-3],help);CHKERRQ(ierr);
62     for (i=0; list[i+2]; i++) {
63       ierr = (*PetscHelpPrintf)(bag->bagcomm," %s",list[i]);CHKERRQ(ierr);
64     }
65     ierr = (*PetscHelpPrintf)(bag->bagcomm,"\n");CHKERRQ(ierr);
66   }
67   ierr = PetscOptionsGetEnum(NULL,bag->bagprefix,nname,list,&mdefault,NULL);CHKERRQ(ierr);
68 
69   ierr         = PetscNew(&item);CHKERRQ(ierr);
70   item->dtype  = PETSC_ENUM;
71   item->offset = ((char*)addr) - ((char*)bag);
72   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
73   item->next        = NULL;
74   item->msize       = 1;
75   ierr              = PetscStrArrayallocpy(list,(char***)&item->list);CHKERRQ(ierr);
76   *(PetscEnum*)addr = mdefault;
77   ierr              = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
78   PetscFunctionReturn(0);
79 }
80 
81 /*@C
82    PetscBagRegisterIntArray - add an integer value to the bag
83 
84    Logically Collective on PetscBag
85 
86    Input Parameter:
87 +  bag - the bag of values
88 .  addr - location of integer in struct
89 .  msize - number of entries in array
90 .  name - name of the integer array
91 -  help - longer string with more information about the value
92 
93    Level: beginner
94 
95 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
96            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
97            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
98 
99 @*/
100 PetscErrorCode PetscBagRegisterIntArray(PetscBag bag,void *addr,PetscInt msize, const char *name, const char *help)
101 {
102   PetscErrorCode ierr;
103   PetscBagItem   item;
104   char           nname[PETSC_BAG_NAME_LENGTH+1];
105   PetscBool      printhelp;
106   PetscInt       i,tmp = msize;
107 
108   PetscFunctionBegin;
109   nname[0] = '-';
110   nname[1] = 0;
111   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
112   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
113   if (printhelp) {
114     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <",bag->bagprefix ? bag->bagprefix : "",name);CHKERRQ(ierr);
115     for (i=0; i<msize; i++) {
116       ierr = (*PetscHelpPrintf)(bag->bagcomm,"%D ",*((PetscInt*)addr)+i);CHKERRQ(ierr);
117     }
118     ierr = (*PetscHelpPrintf)(bag->bagcomm,">: %s \n",help);CHKERRQ(ierr);
119   }
120   ierr = PetscOptionsGetIntArray(NULL,bag->bagprefix,nname,(PetscInt*)addr,&tmp,NULL);CHKERRQ(ierr);
121 
122   ierr         = PetscNew(&item);CHKERRQ(ierr);
123   item->dtype  = PETSC_INT;
124   item->offset = ((char*)addr) - ((char*)bag);
125   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
126   item->next  = NULL;
127   item->msize = msize;
128   ierr        = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
129   PetscFunctionReturn(0);
130 }
131 
132 /*@C
133    PetscBagRegisterRealArray - add an real array to the bag
134 
135    Logically Collective on PetscBag
136 
137    Input Parameter:
138 +  bag - the bag of values
139 .  addr - location of real array in struct
140 .  msize - number of entries in array
141 .  name - name of the integer array
142 -  help - longer string with more information about the value
143 
144    Level: beginner
145 
146 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
147            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
148            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
149 
150 @*/
151 PetscErrorCode PetscBagRegisterRealArray(PetscBag bag,void *addr,PetscInt msize, const char *name, const char *help)
152 {
153   PetscErrorCode ierr;
154   PetscBagItem   item;
155   char           nname[PETSC_BAG_NAME_LENGTH+1];
156   PetscBool      printhelp;
157   PetscInt       i,tmp = msize;
158 
159   PetscFunctionBegin;
160   nname[0] = '-';
161   nname[1] = 0;
162   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
163   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
164   if (printhelp) {
165     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <",bag->bagprefix ? bag->bagprefix : "",name);CHKERRQ(ierr);
166     for (i=0; i<msize; i++) {
167       ierr = (*PetscHelpPrintf)(bag->bagcomm,"%g ",(double)*((PetscReal*)addr)+i);CHKERRQ(ierr);
168     }
169     ierr = (*PetscHelpPrintf)(bag->bagcomm,">: %s \n",help);CHKERRQ(ierr);
170   }
171   ierr = PetscOptionsGetRealArray(NULL,bag->bagprefix,nname,(PetscReal*)addr,&tmp,NULL);CHKERRQ(ierr);
172 
173   ierr         = PetscNew(&item);CHKERRQ(ierr);
174   item->dtype  = PETSC_REAL;
175   item->offset = ((char*)addr) - ((char*)bag);
176   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
177   item->next  = NULL;
178   item->msize = msize;
179   ierr        = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
180   PetscFunctionReturn(0);
181 }
182 
183 /*@C
184    PetscBagRegisterInt - add an integer value to the bag
185 
186    Logically Collective on PetscBag
187 
188    Input Parameter:
189 +  bag - the bag of values
190 .  addr - location of integer in struct
191 .  mdefault - the initial value
192 .  name - name of the integer
193 -  help - longer string with more information about the value
194 
195    Level: beginner
196 
197 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
198            PetscBagRegisterInt64(), PetscBagRegisterBool(), PetscBagRegisterScalar()
199            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
200 
201 @*/
202 PetscErrorCode PetscBagRegisterInt(PetscBag bag,void *addr,PetscInt mdefault,const char *name,const char *help)
203 {
204   PetscErrorCode ierr;
205   PetscBagItem   item;
206   char           nname[PETSC_BAG_NAME_LENGTH+1];
207   PetscBool      printhelp;
208 
209   PetscFunctionBegin;
210   nname[0] = '-';
211   nname[1] = 0;
212   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
213   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
214   if (printhelp) {
215     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <%d>: %s \n",bag->bagprefix ? bag->bagprefix : "",name,mdefault,help);CHKERRQ(ierr);
216   }
217   ierr = PetscOptionsGetInt(NULL,bag->bagprefix,nname,&mdefault,NULL);CHKERRQ(ierr);
218 
219   ierr         = PetscNew(&item);CHKERRQ(ierr);
220   item->dtype  = PETSC_INT;
221   item->offset = ((char*)addr) - ((char*)bag);
222   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
223   item->next       = NULL;
224   item->msize      = 1;
225   *(PetscInt*)addr = mdefault;
226   ierr             = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
227   PetscFunctionReturn(0);
228 }
229 
230 /*@C
231    PetscBagRegisterInt64 - add an integer value to the bag
232 
233    Logically Collective on PetscBag
234 
235    Input Parameter:
236 +  bag - the bag of values
237 .  addr - location of integer in struct
238 .  mdefault - the initial value
239 .  name - name of the integer
240 -  help - longer string with more information about the value
241 
242    Level: beginner
243 
244 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
245            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
246            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
247 
248 @*/
249 PetscErrorCode PetscBagRegisterInt64(PetscBag bag,void *addr,PetscInt64 mdefault,const char *name,const char *help)
250 {
251   PetscErrorCode ierr;
252   PetscBagItem   item;
253   char           nname[PETSC_BAG_NAME_LENGTH+1];
254   PetscBool      printhelp;
255   PetscInt       odefault = (PetscInt)mdefault;
256   PetscBool      flg;
257 
258   PetscFunctionBegin;
259   nname[0] = '-';
260   nname[1] = 0;
261   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
262   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
263   if (printhelp) {
264     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <%d>: %s \n",bag->bagprefix ? bag->bagprefix : "",name,odefault,help);CHKERRQ(ierr);
265   }
266   ierr = PetscOptionsGetInt(NULL,bag->bagprefix,nname,&odefault,&flg);CHKERRQ(ierr);
267   if (flg) mdefault = (PetscInt64)odefault;
268 
269   ierr         = PetscNew(&item);CHKERRQ(ierr);
270   item->dtype  = PETSC_INT;
271   item->offset = ((char*)addr) - ((char*)bag);
272   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
273   item->next       = NULL;
274   item->msize      = 1;
275   *(PetscInt64*)addr = mdefault;
276   ierr             = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
277   PetscFunctionReturn(0);
278 }
279 
280 /*@C
281    PetscBagRegisterBoolArray - add a n logical values to the bag
282 
283    Logically Collective on PetscBag
284 
285    Input Parameter:
286 +  bag - the bag of values
287 .  addr - location of boolean array in struct
288 .  msize - number of entries in array
289 .  name - name of the boolean array
290 -  help - longer string with more information about the value
291 
292    Level: beginner
293 
294 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
295            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
296            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
297 
298 @*/
299 PetscErrorCode PetscBagRegisterBoolArray(PetscBag bag,void *addr,PetscInt msize, const char* name, const char* help)
300 {
301   PetscErrorCode ierr;
302   PetscBagItem   item;
303   char           nname[PETSC_BAG_NAME_LENGTH+1];
304   PetscBool      printhelp;
305   PetscInt       i,tmp = msize;
306 
307   PetscFunctionBegin;
308   nname[0] = '-';
309   nname[1] = 0;
310   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
311   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
312   if (printhelp) {
313     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <",bag->bagprefix?bag->bagprefix:"",name);CHKERRQ(ierr);
314     for (i=0; i<msize; i++) {
315       ierr = (*PetscHelpPrintf)(bag->bagcomm,"%D ",*((PetscInt*)addr)+i);CHKERRQ(ierr);
316     }
317     ierr = (*PetscHelpPrintf)(bag->bagcomm,">: %s \n",help);CHKERRQ(ierr);
318   }
319   ierr = PetscOptionsGetBoolArray(NULL,bag->bagprefix,nname,(PetscBool*)addr,&tmp,NULL);CHKERRQ(ierr);
320 
321   ierr = PetscNew(&item);CHKERRQ(ierr);
322   item->dtype  = PETSC_BOOL;
323   item->offset = ((char*)addr) - ((char*)bag);
324   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
325   item->next   = NULL;
326   item->msize  = msize;
327   ierr = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
328   PetscFunctionReturn(0);
329 }
330 
331 /*@C
332    PetscBagRegisterString - add a string value to the bag
333 
334    Logically Collective on PetscBag
335 
336    Input Parameter:
337 +  bag - the bag of values
338 .  addr - location of start of string in struct
339 .  msize - length of the string space in the struct
340 .  mdefault - the initial value
341 .  name - name of the string
342 -  help - longer string with more information about the value
343 
344    Level: beginner
345 
346    Note: The struct should have the field char mystring[msize]; not char *mystring
347 
348 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
349            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
350            PetscBagSetFromOptions(),PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
351 
352 @*/
353 PetscErrorCode PetscBagRegisterString(PetscBag bag,void *addr,PetscInt msize,const char* mdefault,const char* name,const char* help)
354 {
355   PetscErrorCode ierr;
356   PetscBagItem   item;
357   char           nname[PETSC_BAG_NAME_LENGTH+1];
358   PetscBool      printhelp;
359 
360   PetscFunctionBegin;
361   nname[0] = '-';
362   nname[1] = 0;
363   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
364   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
365   if (printhelp) {
366     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <%s>: %s \n",bag->bagprefix ? bag->bagprefix : "",name,mdefault,help);CHKERRQ(ierr);
367   }
368 
369   ierr         = PetscNew(&item);CHKERRQ(ierr);
370   item->dtype  = PETSC_CHAR;
371   item->offset = ((char*)addr) - ((char*)bag);
372   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
373   item->next  = NULL;
374   item->msize = msize;
375   if (mdefault != (char*)addr) {
376     ierr = PetscStrncpy((char*)addr,mdefault,msize-1);CHKERRQ(ierr);
377   }
378   ierr = PetscOptionsGetString(NULL,bag->bagprefix,nname,(char*)addr,msize,NULL);CHKERRQ(ierr);
379   ierr = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
380   PetscFunctionReturn(0);
381 }
382 
383 /*@C
384    PetscBagRegisterReal - add a real value to the bag
385 
386    Logically Collective on PetscBag
387 
388    Input Parameter:
389 +  bag - the bag of values
390 .  addr - location of double in struct
391 .  mdefault - the initial value
392 .  name - name of the variable
393 -  help - longer string with more information about the value
394 
395    Level: beginner
396 
397 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
398            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
399            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
400 
401 @*/
402 PetscErrorCode PetscBagRegisterReal(PetscBag bag,void *addr,PetscReal mdefault, const char *name, const char *help)
403 {
404   PetscErrorCode ierr;
405   PetscBagItem   item;
406   char           nname[PETSC_BAG_NAME_LENGTH+1];
407   PetscBool      printhelp;
408 
409   PetscFunctionBegin;
410   nname[0] = '-';
411   nname[1] = 0;
412   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
413   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
414   if (printhelp) {
415     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <%g>: %s \n",bag->bagprefix ? bag->bagprefix : "",name,(double)mdefault,help);CHKERRQ(ierr);
416   }
417   ierr = PetscOptionsGetReal(NULL,bag->bagprefix,nname,&mdefault,NULL);CHKERRQ(ierr);
418 
419   ierr         = PetscNew(&item);CHKERRQ(ierr);
420   item->dtype  = PETSC_REAL;
421   item->offset = ((char*)addr) - ((char*)bag);
422   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
423   item->next        = NULL;
424   item->msize       = 1;
425   *(PetscReal*)addr = mdefault;
426   ierr              = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
427   PetscFunctionReturn(0);
428 }
429 
430 /*@C
431    PetscBagRegisterScalar - add a real or complex number value to the bag
432 
433    Logically Collective on PetscBag
434 
435    Input Parameter:
436 +  bag - the bag of values
437 .  addr - location of scalar in struct
438 .  mdefault - the initial value
439 .  name - name of the variable
440 -  help - longer string with more information about the value
441 
442    Level: beginner
443 
444 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
445            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
446            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
447 
448 @*/
449 PetscErrorCode PetscBagRegisterScalar(PetscBag bag,void *addr,PetscScalar mdefault,const char *name,const char *help)
450 {
451   PetscErrorCode ierr;
452   PetscBagItem   item;
453   char           nname[PETSC_BAG_NAME_LENGTH+1];
454   PetscBool      printhelp;
455 
456   PetscFunctionBegin;
457   nname[0] = '-';
458   nname[1] = 0;
459   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
460   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
461   if (printhelp) {
462     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <%g + %gi>: %s \n",bag->bagprefix ? bag->bagprefix : "",name,(double)PetscRealPart(mdefault),(double)PetscImaginaryPart(mdefault),help);CHKERRQ(ierr);
463   }
464   ierr = PetscOptionsGetScalar(NULL,bag->bagprefix,nname,&mdefault,NULL);CHKERRQ(ierr);
465 
466   ierr         = PetscNew(&item);CHKERRQ(ierr);
467   item->dtype  = PETSC_SCALAR;
468   item->offset = ((char*)addr) - ((char*)bag);
469   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
470   item->next          = NULL;
471   item->msize         = 1;
472   *(PetscScalar*)addr = mdefault;
473   ierr                = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
474   PetscFunctionReturn(0);
475 }
476 
477 /*@C
478    PetscBagRegisterBool - add a logical value to the bag
479 
480    Logically Collective on PetscBag
481 
482    Input Parameter:
483 +  bag - the bag of values
484 .  addr - location of logical in struct
485 .  mdefault - the initial value
486 .  name - name of the variable
487 -  help - longer string with more information about the value
488 
489    Level: beginner
490 
491 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
492            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
493            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
494 
495 @*/
496 PetscErrorCode PetscBagRegisterBool(PetscBag bag,void *addr,PetscBool mdefault,const char *name,const char *help)
497 {
498   PetscErrorCode ierr;
499   PetscBagItem   item;
500   char           nname[PETSC_BAG_NAME_LENGTH+1];
501   PetscBool      printhelp;
502 
503   PetscFunctionBegin;
504   /* the checks here with != PETSC_FALSE and PETSC_TRUE is a special case; here we truly demand that the value be 0 or 1 */
505   if (mdefault != PETSC_FALSE && mdefault != PETSC_TRUE) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Boolean %s %s must be boolean; integer value %d",name,help,(int)mdefault);
506   nname[0] = '-';
507   nname[1] = 0;
508   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
509   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
510   if (printhelp) {
511     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <%s>: %s \n",bag->bagprefix ? bag->bagprefix : "",name,PetscBools[mdefault],help);CHKERRQ(ierr);
512   }
513   ierr = PetscOptionsGetBool(NULL,bag->bagprefix,nname,&mdefault,NULL);CHKERRQ(ierr);
514 
515   ierr         = PetscNew(&item);CHKERRQ(ierr);
516   item->dtype  = PETSC_BOOL;
517   item->offset = ((char*)addr) - ((char*)bag);
518   if (item->offset > bag->bagsize) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Registered item %s %s is not in bag memory space",name,help);
519   item->next        = NULL;
520   item->msize       = 1;
521   *(PetscBool*)addr = mdefault;
522   ierr              = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
523   PetscFunctionReturn(0);
524 }
525 
526 /*@C
527    PetscBagDestroy - Destroys a bag values
528 
529    Collective on PetscBag
530 
531    Input Parameter:
532 .  bag - the bag of values
533 
534    Level: beginner
535 
536 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
537            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
538            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
539 
540 @*/
541 PetscErrorCode  PetscBagDestroy(PetscBag *bag)
542 {
543   PetscErrorCode ierr;
544   PetscBagItem   nitem = (*bag)->bagitems,item;
545 
546   PetscFunctionBegin;
547   while (nitem) {
548     item = nitem->next;
549     if (nitem->list) {
550       ierr = PetscStrArrayDestroy(&nitem->list);CHKERRQ(ierr);
551     }
552     ierr  = PetscFree(nitem);CHKERRQ(ierr);
553     nitem = item;
554   }
555   if ((*bag)->bagprefix) { ierr = PetscFree((*bag)->bagprefix);CHKERRQ(ierr); }
556   ierr = PetscFree(*bag);CHKERRQ(ierr);
557   PetscFunctionReturn(0);
558 }
559 
560 /*@
561    PetscBagSetFromOptions - Allows setting options from a bag
562 
563    Collective on PetscBag
564 
565    Input Parameter:
566 .  bag - the bag of values
567 
568    Level: beginner
569 
570 .seealso: PetscBag, PetscBagSetName(), PetscBagDestroy(), PetscBagLoad(), PetscBagGetData()
571            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
572            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagView(), PetscBagRegisterEnum()
573 
574 @*/
575 PetscErrorCode  PetscBagSetFromOptions(PetscBag bag)
576 {
577   PetscErrorCode ierr;
578   PetscBagItem   nitem = bag->bagitems;
579   char           name[PETSC_BAG_NAME_LENGTH+1],helpname[PETSC_BAG_NAME_LENGTH+PETSC_BAG_HELP_LENGTH+3];
580   PetscInt       n;
581 
582   PetscFunctionBegin;
583   ierr = PetscStrncpy(helpname,bag->bagname,sizeof(helpname));CHKERRQ(ierr);
584   ierr = PetscStrlcat(helpname," ",sizeof(helpname));CHKERRQ(ierr);
585   ierr = PetscStrlcat(helpname,bag->baghelp,sizeof(helpname));CHKERRQ(ierr);
586   ierr = PetscOptionsBegin(bag->bagcomm,bag->bagprefix,helpname,NULL);CHKERRQ(ierr);
587   while (nitem) {
588     name[0] = '-';
589     name[1] = 0;
590     ierr    = PetscStrlcat(name,nitem->name,sizeof(name));CHKERRQ(ierr);
591     if (nitem->dtype == PETSC_CHAR) {   /* special handling for fortran required? [due to space padding vs null termination] */
592       char *value = (char*)(((char*)bag) + nitem->offset);
593       ierr = PetscOptionsString(name,nitem->help,"",value,value,nitem->msize,NULL);CHKERRQ(ierr);
594     } else if (nitem->dtype == PETSC_REAL) {
595       PetscReal *value = (PetscReal*)(((char*)bag) + nitem->offset);
596       if (nitem->msize == 1) {
597         ierr = PetscOptionsReal(name,nitem->help,"",*value,value,NULL);CHKERRQ(ierr);
598       } else {
599         n    = nitem->msize;
600         ierr = PetscOptionsRealArray(name,nitem->help,"",value,&n,NULL);CHKERRQ(ierr);
601       }
602     } else if (nitem->dtype == PETSC_SCALAR) {
603       PetscScalar *value = (PetscScalar*)(((char*)bag) + nitem->offset);
604       ierr = PetscOptionsScalar(name,nitem->help,"",*value,value,NULL);CHKERRQ(ierr);
605     } else if (nitem->dtype == PETSC_INT) {
606       PetscInt *value = (PetscInt*)(((char*)bag) + nitem->offset);
607       if (nitem->msize == 1) {
608         ierr = PetscOptionsInt(name,nitem->help,"",*value,value,NULL);CHKERRQ(ierr);
609       } else {
610         n    = nitem->msize;
611         ierr = PetscOptionsIntArray(name,nitem->help,"",value,&n,NULL);CHKERRQ(ierr);
612       }
613     } else if (nitem->dtype == PETSC_ENUM) {
614       PetscEnum *value = (PetscEnum*)(((char*)bag) + nitem->offset);
615       PetscInt  i      = 0;
616       while (nitem->list[i++]) ;
617       ierr = PetscOptionsEnum(name,nitem->help,nitem->list[i-3],(const char*const*)nitem->list,*value,value,NULL);CHKERRQ(ierr);
618     } else if (nitem->dtype == PETSC_BOOL) {
619       PetscBool *value = (PetscBool*)(((char*)bag) + nitem->offset);
620       if (nitem->msize == 1) {
621         ierr = PetscOptionsBool(name,nitem->help,"",*value,value,NULL);CHKERRQ(ierr);
622       } else {
623         n = nitem->msize;
624         ierr = PetscOptionsBoolArray(name,nitem->help,"",value,&n,NULL);CHKERRQ(ierr);
625       }
626     }
627     nitem = nitem->next;
628   }
629   PetscOptionsEnd();
630   PetscFunctionReturn(0);
631 }
632 
633 /*@C
634    PetscBagView - Views a bag of values as either ASCII text or a binary file
635 
636    Collective on PetscBag
637 
638    Input Parameter:
639 +  bag - the bag of values
640 -  viewer - location to view the values
641 
642    Level: beginner
643 
644    Warning: Currently PETSc bags saved in a binary file can only be read back
645      in on a machine of the same architecture. Let us know when this is a problem
646      and we'll fix it.
647 
648 .seealso: PetscBag, PetscBagSetName(), PetscBagDestroy(), PetscBagLoad(), PetscBagGetData()
649            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar(), PetscBagRegisterEnum()
650            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName()
651 
652 @*/
653 PetscErrorCode  PetscBagView(PetscBag bag,PetscViewer view)
654 {
655   PetscBool      isascii,isbinary;
656   PetscErrorCode ierr;
657   PetscBagItem   nitem = bag->bagitems;
658 
659   PetscFunctionBegin;
660   ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
661   ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
662   if (isascii) {
663     if (bag->bagprefix) {
664       ierr = PetscViewerASCIIPrintf(view,"PetscBag Object:  %s (%s) %s\n",bag->bagname,bag->bagprefix,bag->baghelp);CHKERRQ(ierr);
665     } else {
666       ierr = PetscViewerASCIIPrintf(view,"PetscBag Object:  %s %s\n",bag->bagname,bag->baghelp);CHKERRQ(ierr);
667     }
668     while (nitem) {
669       if (nitem->dtype == PETSC_CHAR) {
670         char *value = (char*)(((char*)bag) + nitem->offset);
671         char tmp    = value[nitem->msize-1]; /* special handling for fortran chars wihout null terminator */
672         value[nitem->msize-1] =0;
673         ierr = PetscViewerASCIIPrintf(view,"  %s = %s; %s\n",nitem->name,value,nitem->help);CHKERRQ(ierr);
674         value[nitem->msize-1] = tmp;
675       } else if (nitem->dtype == PETSC_REAL) {
676         PetscReal *value = (PetscReal*)(((char*)bag) + nitem->offset);
677         PetscInt  i;
678         ierr = PetscViewerASCIIPrintf(view,"  %s = ",nitem->name);CHKERRQ(ierr);
679         for (i=0; i<nitem->msize; i++) {
680           ierr = PetscViewerASCIIPrintf(view,"%g ",(double)value[i]);CHKERRQ(ierr);
681         }
682         ierr = PetscViewerASCIIPrintf(view,"; %s\n",nitem->help);CHKERRQ(ierr);
683       } else if (nitem->dtype == PETSC_SCALAR) {
684         PetscScalar value = *(PetscScalar*)(((char*)bag) + nitem->offset);
685 #if defined(PETSC_USE_COMPLEX)
686         if ((double)PetscImaginaryPart(value)) {
687           ierr = PetscViewerASCIIPrintf(view,"  %s = %g + %gi; %s\n",nitem->name,(double)PetscRealPart(value),(double)PetscImaginaryPart(value),nitem->help);CHKERRQ(ierr);
688         } else {
689           ierr = PetscViewerASCIIPrintf(view,"  %s = %g; %s\n",nitem->name,(double)PetscRealPart(value),nitem->help);CHKERRQ(ierr);
690         }
691 #else
692         ierr = PetscViewerASCIIPrintf(view,"  %s = %g; %s\n",nitem->name,(double)value,nitem->help);CHKERRQ(ierr);
693 #endif
694       } else if (nitem->dtype == PETSC_INT) {
695         PetscInt i,*value = (PetscInt*)(((char*)bag) + nitem->offset);
696         ierr = PetscViewerASCIIPrintf(view,"  %s = ",nitem->name);CHKERRQ(ierr);
697         for (i=0; i<nitem->msize; i++) {
698           ierr = PetscViewerASCIIPrintf(view,"%D ",value[i]);CHKERRQ(ierr);
699         }
700         ierr = PetscViewerASCIIPrintf(view,"; %s\n",nitem->help);CHKERRQ(ierr);
701       } else if (nitem->dtype == PETSC_BOOL) {
702         PetscBool  *value = (PetscBool*)(((char*)bag) + nitem->offset);
703         PetscInt  i;
704          /* some Fortran compilers use -1 as boolean */
705         ierr = PetscViewerASCIIPrintf(view,"  %s = ",nitem->name);CHKERRQ(ierr);
706         for (i=0; i<nitem->msize; i++) {
707           if (((int) value[i]) == -1) value[i] = PETSC_TRUE;
708           /* the checks here with != PETSC_FALSE and PETSC_TRUE is a special case; here we truly demand that the value be 0 or 1 */
709           if (value[i] != PETSC_FALSE && value[i] != PETSC_TRUE) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Boolean value for %s %s is corrupt; integer value %d",nitem->name,nitem->help,value);
710           ierr = PetscViewerASCIIPrintf(view," %s",PetscBools[value[i]]);CHKERRQ(ierr);
711         }
712         ierr = PetscViewerASCIIPrintf(view,"; %s\n",nitem->help);CHKERRQ(ierr);
713       } else if (nitem->dtype == PETSC_ENUM) {
714         PetscEnum value = *(PetscEnum*)(((char*)bag) + nitem->offset);
715         PetscInt  i     = 0;
716         while (nitem->list[i++]) ;
717         ierr = PetscViewerASCIIPrintf(view,"  %s = %s; (%s) %s\n",nitem->name,nitem->list[value],nitem->list[i-3],nitem->help);CHKERRQ(ierr);
718       }
719       nitem = nitem->next;
720     }
721   } else if (isbinary) {
722     PetscInt          classid           = PETSC_BAG_FILE_CLASSID, dtype;
723     PetscInt          deprecatedbagsize = 0;
724     PetscViewerFormat format;
725     ierr = PetscViewerBinaryWrite(view,&classid,1,PETSC_INT);CHKERRQ(ierr);
726     ierr = PetscViewerBinaryWrite(view,&deprecatedbagsize,1,PETSC_INT);CHKERRQ(ierr);
727     ierr = PetscViewerBinaryWrite(view,&bag->count,1,PETSC_INT);CHKERRQ(ierr);
728     ierr = PetscViewerBinaryWrite(view,bag->bagname,PETSC_BAG_NAME_LENGTH,PETSC_CHAR);CHKERRQ(ierr);
729     ierr = PetscViewerBinaryWrite(view,bag->baghelp,PETSC_BAG_HELP_LENGTH,PETSC_CHAR);CHKERRQ(ierr);
730     while (nitem) {
731       ierr  = PetscViewerBinaryWrite(view,&nitem->offset,1,PETSC_INT);CHKERRQ(ierr);
732       dtype = (PetscInt)nitem->dtype;
733       ierr  = PetscViewerBinaryWrite(view,&dtype,1,PETSC_INT);CHKERRQ(ierr);
734       ierr  = PetscViewerBinaryWrite(view,nitem->name,PETSC_BAG_NAME_LENGTH,PETSC_CHAR);CHKERRQ(ierr);
735       ierr  = PetscViewerBinaryWrite(view,nitem->help,PETSC_BAG_HELP_LENGTH,PETSC_CHAR);CHKERRQ(ierr);
736       ierr  = PetscViewerBinaryWrite(view,&nitem->msize,1,PETSC_INT);CHKERRQ(ierr);
737       /* some Fortran compilers use -1 as boolean */
738       if (dtype == PETSC_BOOL && ((*(int*) (((char*)bag) + nitem->offset) == -1))) *(int*) (((char*)bag) + nitem->offset) = PETSC_TRUE;
739 
740       ierr = PetscViewerBinaryWrite(view,(((char*)bag) + nitem->offset),nitem->msize,nitem->dtype);CHKERRQ(ierr);
741       if (dtype == PETSC_ENUM) {
742         ierr = PetscViewerBinaryWriteStringArray(view,(const char* const*)nitem->list);CHKERRQ(ierr);
743       }
744       nitem = nitem->next;
745     }
746     ierr = PetscViewerGetFormat(view,&format);CHKERRQ(ierr);
747     if (format == PETSC_VIEWER_BINARY_MATLAB) {
748       MPI_Comm comm;
749       FILE     *info;
750       ierr = PetscObjectGetComm((PetscObject)view,&comm);CHKERRQ(ierr);
751       ierr = PetscViewerBinaryGetInfoPointer(view,&info);CHKERRQ(ierr);
752       ierr = PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
753       ierr = PetscFPrintf(comm,info,"#$$ Set.%s = PetscBinaryRead(fd);\n",bag->bagname);CHKERRQ(ierr);
754       ierr = PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
755     }
756   }
757   PetscFunctionReturn(0);
758 }
759 
760 /*@C
761   PetscBagViewFromOptions - Processes command line options to determine if/how a PetscBag is to be viewed.
762 
763   Collective on PetscBag
764 
765   Input Parameters:
766 + obj   - the object
767 . bobj  - optional other object that provides prefix (if NULL then the prefix in obj is used)
768 - optionname - option to activate viewing
769 
770   Level: intermediate
771 
772 .seealso: PetscBagCreate(), PetscBag, PetscViewer
773 @*/
774 PetscErrorCode PetscBagViewFromOptions(PetscBag bag, PetscObject bobj, const char optionname[])
775 {
776   static PetscBool  incall = PETSC_FALSE;
777   PetscViewer       viewer;
778   PetscViewerFormat format;
779   const char       *prefix, *bprefix = NULL;
780   PetscBool         flg;
781   PetscErrorCode    ierr;
782 
783   PetscFunctionBegin;
784   if (incall) PetscFunctionReturn(0);
785   incall = PETSC_TRUE;
786   if (bobj) {ierr = PetscObjectGetOptionsPrefix(bobj, &bprefix);CHKERRQ(ierr);}
787   prefix = bobj ? bprefix : bag->bagprefix;
788   ierr   = PetscOptionsGetViewer(bag->bagcomm, NULL, prefix, optionname, &viewer, &format, &flg);CHKERRQ(ierr);
789   if (flg) {
790     ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr);
791     ierr = PetscBagView(bag, viewer);CHKERRQ(ierr);
792     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
793     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
794     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
795   }
796   incall = PETSC_FALSE;
797   PetscFunctionReturn(0);
798 }
799 
800 /*@C
801    PetscBagLoad - Loads a bag of values from a binary file
802 
803    Collective on PetscViewer
804 
805    Input Parameter:
806 +  viewer - file to load values from
807 -  bag - the bag of values
808 
809    Notes:
810     You must have created and registered all the fields in the bag before loading into it.
811 
812    Notes:
813    Level: beginner
814 
815 .seealso: PetscBag, PetscBagSetName(), PetscBagDestroy(), PetscBagView(), PetscBagGetData()
816            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
817            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
818 
819 @*/
820 PetscErrorCode  PetscBagLoad(PetscViewer view,PetscBag bag)
821 {
822   PetscErrorCode ierr;
823   PetscBool      isbinary;
824   PetscInt       classid,bagcount,i,dtype,msize,offset,deprecatedbagsize;
825   char           name[PETSC_BAG_NAME_LENGTH],help[PETSC_BAG_HELP_LENGTH],**list;
826   PetscBagItem   nitem;
827   MPI_Comm       comm;
828   PetscMPIInt    flag;
829 
830   PetscFunctionBegin;
831   ierr = PetscObjectGetComm((PetscObject)view,&comm);CHKERRQ(ierr);
832   ierr = MPI_Comm_compare(comm,bag->bagcomm,&flag);CHKERRMPI(ierr);
833   if (flag != MPI_CONGRUENT && flag != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"Different communicators in the viewer and bag"); \
834   ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
835   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for this viewer type");
836 
837   ierr = PetscViewerBinaryRead(view,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr);
838   if (classid != PETSC_BAG_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not PetscBag next in binary file");
839   ierr = PetscViewerBinaryRead(view,&deprecatedbagsize,1,NULL,PETSC_INT);CHKERRQ(ierr);
840   ierr = PetscViewerBinaryRead(view,&bagcount,1,NULL,PETSC_INT);CHKERRQ(ierr);
841   if (bagcount != bag->count) SETERRQ2(comm,PETSC_ERR_ARG_INCOMP,"Bag in file has different number of entries %d then passed in bag %d\n",(int)bagcount,(int)bag->count);
842   ierr = PetscViewerBinaryRead(view,bag->bagname,PETSC_BAG_NAME_LENGTH,NULL,PETSC_CHAR);CHKERRQ(ierr);
843   ierr = PetscViewerBinaryRead(view,bag->baghelp,PETSC_BAG_HELP_LENGTH,NULL,PETSC_CHAR);CHKERRQ(ierr);
844 
845   nitem = bag->bagitems;
846   for (i=0; i<bagcount; i++) {
847     ierr = PetscViewerBinaryRead(view,&offset,1,NULL,PETSC_INT);CHKERRQ(ierr);
848     /* ignore the offset in the file */
849     ierr = PetscViewerBinaryRead(view,&dtype,1,NULL,PETSC_INT);CHKERRQ(ierr);
850     ierr = PetscViewerBinaryRead(view,name,PETSC_BAG_NAME_LENGTH,NULL,PETSC_CHAR);CHKERRQ(ierr);
851     ierr = PetscViewerBinaryRead(view,help,PETSC_BAG_HELP_LENGTH,NULL,PETSC_CHAR);CHKERRQ(ierr);
852     ierr = PetscViewerBinaryRead(view,&msize,1,NULL,PETSC_INT);CHKERRQ(ierr);
853 
854     if (dtype == (PetscInt) PETSC_CHAR) {
855       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,msize,NULL,PETSC_CHAR);CHKERRQ(ierr);
856     } else if (dtype == (PetscInt) PETSC_REAL) {
857       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,msize,NULL,PETSC_REAL);CHKERRQ(ierr);
858     } else if (dtype == (PetscInt) PETSC_SCALAR) {
859       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,1,NULL,PETSC_SCALAR);CHKERRQ(ierr);
860     } else if (dtype == (PetscInt) PETSC_INT) {
861       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,msize,NULL,PETSC_INT);CHKERRQ(ierr);
862     } else if (dtype == (PetscInt) PETSC_BOOL) {
863       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,msize,NULL,PETSC_BOOL);CHKERRQ(ierr);
864     } else if (dtype == (PetscInt) PETSC_ENUM) {
865       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,1,NULL,PETSC_ENUM);CHKERRQ(ierr);
866       ierr = PetscViewerBinaryReadStringArray(view,&list);CHKERRQ(ierr);
867       /* don't need to save list because it is already registered in the bag */
868       ierr = PetscFree(list);CHKERRQ(ierr);
869     }
870     nitem = nitem->next;
871   }
872   PetscFunctionReturn(0);
873 }
874 
875 /*@C
876     PetscBagCreate - Create a bag of values
877 
878   Collective
879 
880   Level: Intermediate
881 
882   Input Parameters:
883 +  comm - communicator to share bag
884 -  bagsize - size of the C structure holding the values
885 
886   Output Parameter:
887 .   bag - the bag of values
888 
889    Notes:
890       The size of the A struct must be small enough to fit in a PetscInt; by default
891       PetscInt is 4 bytes; this means a bag cannot be larger than 2 gigabytes in length.
892       The warning about casting to a shorter length can be ignored below unless your A struct is too large
893 
894 .seealso: PetscBag, PetscBagGetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
895            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
896            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
897 @*/
898 PetscErrorCode PetscBagCreate(MPI_Comm comm, size_t bagsize, PetscBag *bag)
899 {
900   PetscErrorCode ierr;
901   size_t         totalsize = bagsize+sizeof(struct _n_PetscBag)+sizeof(PetscScalar);
902 
903   PetscFunctionBegin;
904   ierr = PetscInfo1(NULL,"Creating Bag with total size %d\n",(int)totalsize);CHKERRQ(ierr);
905   ierr = PetscMalloc(totalsize,bag);CHKERRQ(ierr);
906   ierr = PetscMemzero(*bag,bagsize+sizeof(struct _n_PetscBag)+sizeof(PetscScalar));CHKERRQ(ierr);
907 
908   (*bag)->bagsize        = bagsize+sizeof(struct _n_PetscBag)+sizeof(PetscScalar);
909   (*bag)->bagcomm        = comm;
910   (*bag)->bagprefix      = NULL;
911   (*bag)->structlocation = (void*)(((char*)(*bag)) + sizeof(PetscScalar)*(sizeof(struct _n_PetscBag)/sizeof(PetscScalar)) + sizeof(PetscScalar));
912   PetscFunctionReturn(0);
913 }
914 
915 /*@C
916     PetscBagSetName - Sets the name of a bag of values
917 
918   Not Collective
919 
920   Level: Intermediate
921 
922   Input Parameters:
923 +   bag - the bag of values
924 .   name - the name assigned to the bag
925 -   help - help message for bag
926 
927 .seealso: PetscBag, PetscBagGetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
928            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
929            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
930 @*/
931 
932 PetscErrorCode PetscBagSetName(PetscBag bag, const char *name, const char *help)
933 {
934   PetscErrorCode ierr;
935 
936   PetscFunctionBegin;
937   ierr = PetscStrncpy(bag->bagname,name,PETSC_BAG_NAME_LENGTH-1);CHKERRQ(ierr);
938   ierr = PetscStrncpy(bag->baghelp,help,PETSC_BAG_HELP_LENGTH-1);CHKERRQ(ierr);
939   PetscFunctionReturn(0);
940 }
941 
942 /*@C
943     PetscBagGetName - Gets the name of a bag of values
944 
945   Not Collective
946 
947   Level: Intermediate
948 
949   Input Parameter:
950 .   bag - the bag of values
951 
952   Output Parameter:
953 .   name - the name assigned to the bag
954 
955 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
956            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
957            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
958 @*/
959 PetscErrorCode PetscBagGetName(PetscBag bag, char **name)
960 {
961   PetscFunctionBegin;
962   *name = bag->bagname;
963   PetscFunctionReturn(0);
964 }
965 
966 /*@C
967     PetscBagGetData - Gives back the user - access to memory that
968     should be used for storing user-data-structure
969 
970   Not Collective
971 
972   Level: Intermediate
973 
974   Input Parameter:
975 .   bag - the bag of values
976 
977   Output Parameter:
978 .   data - pointer to memory that will have user-data-structure
979 
980 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad()
981            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
982            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
983 @*/
984 PetscErrorCode PetscBagGetData(PetscBag bag, void **data)
985 {
986   PetscFunctionBegin;
987   *data = bag->structlocation;
988   PetscFunctionReturn(0);
989 }
990 
991 /*@C
992   PetscBagSetOptionsPrefix - Sets the prefix used for searching for all
993   PetscBag items in the options database.
994 
995   Logically collective on Bag.
996 
997   Level: Intermediate
998 
999   Input Parameters:
1000 +   bag - the bag of values
1001 -   prefix - the prefix to prepend all Bag item names with.
1002 
1003   NOTES: Must be called prior to registering any of the bag items.
1004 
1005 .seealso: PetscBag, PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
1006            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
1007 @*/
1008 
1009 PetscErrorCode PetscBagSetOptionsPrefix(PetscBag bag, const char pre[])
1010 {
1011   PetscErrorCode ierr;
1012 
1013   PetscFunctionBegin;
1014   if (!pre) {
1015     ierr = PetscFree(bag->bagprefix);CHKERRQ(ierr);
1016   } else {
1017     if (pre[0] == '-') SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hypen");
1018     ierr = PetscFree(bag->bagprefix);CHKERRQ(ierr);
1019     ierr = PetscStrallocpy(pre,&(bag->bagprefix));CHKERRQ(ierr);
1020   }
1021   PetscFunctionReturn(0);
1022 }
1023 
1024 /*@C
1025   PetscBagGetNames - Get the names of all entries in the bag
1026 
1027   Not collective
1028 
1029   Input Parameters:
1030 + bag   - the bag of values
1031 - names - array of the correct size to hold names
1032 
1033   Output Parameter:
1034 . names - array of char pointers for names
1035 
1036   Level: intermediate
1037 
1038 .seealso: PetscBag, PetscBagGetName(), PetscBagSetName(), PetscBagCreate(), PetscBagGetData()
1039           PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar(), PetscBagRegisterEnum()
1040 @*/
1041 PetscErrorCode PetscBagGetNames(PetscBag bag, const char *names[])
1042 {
1043   PetscBagItem nitem = bag->bagitems;
1044   PetscInt     n;
1045 
1046   PetscFunctionBegin;
1047   for (n = 0; nitem; ++n, nitem = nitem->next) {names[n] = nitem->name;}
1048   PetscFunctionReturn(0);
1049 }
1050