xref: /petsc/src/sys/classes/bag/bag.c (revision b698fc57f0bea7237255b29c1b77df0acc362ffd)
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 
443    Level: beginner
444 
445 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
446            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
447            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
448 
449 @*/
450 PetscErrorCode PetscBagRegisterScalar(PetscBag bag,void *addr,PetscScalar mdefault,const char *name,const char *help)
451 {
452   PetscErrorCode ierr;
453   PetscBagItem   item;
454   char           nname[PETSC_BAG_NAME_LENGTH+1];
455   PetscBool      printhelp;
456 
457   PetscFunctionBegin;
458   nname[0] = '-';
459   nname[1] = 0;
460   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
461   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
462   if (printhelp) {
463     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <%g + %gi>: %s \n",bag->bagprefix ? bag->bagprefix : "",name,(double)PetscRealPart(mdefault),(double)PetscImaginaryPart(mdefault),help);CHKERRQ(ierr);
464   }
465   ierr = PetscOptionsGetScalar(NULL,bag->bagprefix,nname,&mdefault,NULL);CHKERRQ(ierr);
466 
467   ierr         = PetscNew(&item);CHKERRQ(ierr);
468   item->dtype  = PETSC_SCALAR;
469   item->offset = ((char*)addr) - ((char*)bag);
470   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);
471   item->next          = NULL;
472   item->msize         = 1;
473   *(PetscScalar*)addr = mdefault;
474   ierr                = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
475   PetscFunctionReturn(0);
476 }
477 
478 /*@C
479    PetscBagRegisterBool - add a logical value to the bag
480 
481    Logically Collective on PetscBag
482 
483    Input Parameter:
484 +  bag - the bag of values
485 .  addr - location of logical in struct
486 .  mdefault - the initial value
487 .  name - name of the variable
488 -  help - longer string with more information about the value
489 
490 
491    Level: beginner
492 
493 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
494            PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
495            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
496 
497 @*/
498 PetscErrorCode PetscBagRegisterBool(PetscBag bag,void *addr,PetscBool mdefault,const char *name,const char *help)
499 {
500   PetscErrorCode ierr;
501   PetscBagItem   item;
502   char           nname[PETSC_BAG_NAME_LENGTH+1];
503   PetscBool      printhelp;
504 
505   PetscFunctionBegin;
506   /* the checks here with != PETSC_FALSE and PETSC_TRUE is a special case; here we truly demand that the value be 0 or 1 */
507   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);
508   nname[0] = '-';
509   nname[1] = 0;
510   ierr     = PetscStrlcat(nname,name,PETSC_BAG_NAME_LENGTH);CHKERRQ(ierr);
511   ierr     = PetscOptionsHasHelp(NULL,&printhelp);CHKERRQ(ierr);
512   if (printhelp) {
513     ierr = (*PetscHelpPrintf)(bag->bagcomm,"  -%s%s <%s>: %s \n",bag->bagprefix ? bag->bagprefix : "",name,PetscBools[mdefault],help);CHKERRQ(ierr);
514   }
515   ierr = PetscOptionsGetBool(NULL,bag->bagprefix,nname,&mdefault,NULL);CHKERRQ(ierr);
516 
517   ierr         = PetscNew(&item);CHKERRQ(ierr);
518   item->dtype  = PETSC_BOOL;
519   item->offset = ((char*)addr) - ((char*)bag);
520   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);
521   item->next        = NULL;
522   item->msize       = 1;
523   *(PetscBool*)addr = mdefault;
524   ierr              = PetscBagRegister_Private(bag,item,name,help);CHKERRQ(ierr);
525   PetscFunctionReturn(0);
526 }
527 
528 /*@C
529    PetscBagDestroy - Destroys a bag values
530 
531    Collective on PetscBag
532 
533    Input Parameter:
534 .  bag - the bag of values
535 
536    Level: beginner
537 
538 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
539            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
540            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
541 
542 @*/
543 PetscErrorCode  PetscBagDestroy(PetscBag *bag)
544 {
545   PetscErrorCode ierr;
546   PetscBagItem   nitem = (*bag)->bagitems,item;
547 
548   PetscFunctionBegin;
549   while (nitem) {
550     item = nitem->next;
551     if (nitem->list) {
552       ierr = PetscStrArrayDestroy(&nitem->list);CHKERRQ(ierr);
553     }
554     ierr  = PetscFree(nitem);CHKERRQ(ierr);
555     nitem = item;
556   }
557   if ((*bag)->bagprefix) { ierr = PetscFree((*bag)->bagprefix);CHKERRQ(ierr); }
558   ierr = PetscFree(*bag);CHKERRQ(ierr);
559   PetscFunctionReturn(0);
560 }
561 
562 /*@
563    PetscBagSetFromOptions - Allows setting options from a bag
564 
565    Collective on PetscBag
566 
567    Input Parameter:
568 .  bag - the bag of values
569 
570    Level: beginner
571 
572 .seealso: PetscBag, PetscBagSetName(), PetscBagDestroy(), PetscBagLoad(), PetscBagGetData()
573            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
574            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagView(), PetscBagRegisterEnum()
575 
576 @*/
577 PetscErrorCode  PetscBagSetFromOptions(PetscBag bag)
578 {
579   PetscErrorCode ierr;
580   PetscBagItem   nitem = bag->bagitems;
581   char           name[PETSC_BAG_NAME_LENGTH+1],helpname[PETSC_BAG_NAME_LENGTH+PETSC_BAG_HELP_LENGTH+3];
582   PetscInt       n;
583 
584   PetscFunctionBegin;
585   ierr = PetscStrncpy(helpname,bag->bagname,sizeof(helpname));CHKERRQ(ierr);
586   ierr = PetscStrlcat(helpname," ",sizeof(helpname));CHKERRQ(ierr);
587   ierr = PetscStrlcat(helpname,bag->baghelp,sizeof(helpname));CHKERRQ(ierr);
588   ierr = PetscOptionsBegin(bag->bagcomm,bag->bagprefix,helpname,NULL);CHKERRQ(ierr);
589   while (nitem) {
590     name[0] = '-';
591     name[1] = 0;
592     ierr    = PetscStrlcat(name,nitem->name,sizeof(name));CHKERRQ(ierr);
593     if (nitem->dtype == PETSC_CHAR) {   /* special handling for fortran required? [due to space padding vs null termination] */
594       char *value = (char*)(((char*)bag) + nitem->offset);
595       ierr = PetscOptionsString(name,nitem->help,"",value,value,nitem->msize,NULL);CHKERRQ(ierr);
596     } else if (nitem->dtype == PETSC_REAL) {
597       PetscReal *value = (PetscReal*)(((char*)bag) + nitem->offset);
598       if (nitem->msize == 1) {
599         ierr = PetscOptionsReal(name,nitem->help,"",*value,value,NULL);CHKERRQ(ierr);
600       } else {
601         n    = nitem->msize;
602         ierr = PetscOptionsRealArray(name,nitem->help,"",value,&n,NULL);CHKERRQ(ierr);
603       }
604     } else if (nitem->dtype == PETSC_SCALAR) {
605       PetscScalar *value = (PetscScalar*)(((char*)bag) + nitem->offset);
606       ierr = PetscOptionsScalar(name,nitem->help,"",*value,value,NULL);CHKERRQ(ierr);
607     } else if (nitem->dtype == PETSC_INT) {
608       PetscInt *value = (PetscInt*)(((char*)bag) + nitem->offset);
609       if (nitem->msize == 1) {
610         ierr = PetscOptionsInt(name,nitem->help,"",*value,value,NULL);CHKERRQ(ierr);
611       } else {
612         n    = nitem->msize;
613         ierr = PetscOptionsIntArray(name,nitem->help,"",value,&n,NULL);CHKERRQ(ierr);
614       }
615     } else if (nitem->dtype == PETSC_ENUM) {
616       PetscEnum *value = (PetscEnum*)(((char*)bag) + nitem->offset);
617       PetscInt  i      = 0;
618       while (nitem->list[i++]) ;
619       ierr = PetscOptionsEnum(name,nitem->help,nitem->list[i-3],(const char*const*)nitem->list,*value,value,NULL);CHKERRQ(ierr);
620     } else if (nitem->dtype == PETSC_BOOL) {
621       PetscBool *value = (PetscBool*)(((char*)bag) + nitem->offset);
622       if (nitem->msize == 1) {
623         ierr = PetscOptionsBool(name,nitem->help,"",*value,value,NULL);CHKERRQ(ierr);
624       } else {
625         n = nitem->msize;
626         ierr = PetscOptionsBoolArray(name,nitem->help,"",value,&n,NULL);CHKERRQ(ierr);
627       }
628     }
629     nitem = nitem->next;
630   }
631   PetscOptionsEnd();
632   PetscFunctionReturn(0);
633 }
634 
635 /*@C
636    PetscBagView - Views a bag of values as either ASCII text or a binary file
637 
638    Collective on PetscBag
639 
640    Input Parameter:
641 +  bag - the bag of values
642 -  viewer - location to view the values
643 
644    Level: beginner
645 
646    Warning: Currently PETSc bags saved in a binary file can only be read back
647      in on a machine of the same architecture. Let us know when this is a problem
648      and we'll fix it.
649 
650 .seealso: PetscBag, PetscBagSetName(), PetscBagDestroy(), PetscBagLoad(), PetscBagGetData()
651            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar(), PetscBagRegisterEnum()
652            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName()
653 
654 @*/
655 PetscErrorCode  PetscBagView(PetscBag bag,PetscViewer view)
656 {
657   PetscBool      isascii,isbinary;
658   PetscErrorCode ierr;
659   PetscBagItem   nitem = bag->bagitems;
660 
661   PetscFunctionBegin;
662   ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
663   ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
664   if (isascii) {
665     if (bag->bagprefix) {
666       ierr = PetscViewerASCIIPrintf(view,"PetscBag Object:  %s (%s) %s\n",bag->bagname,bag->bagprefix,bag->baghelp);CHKERRQ(ierr);
667     } else {
668       ierr = PetscViewerASCIIPrintf(view,"PetscBag Object:  %s %s\n",bag->bagname,bag->baghelp);CHKERRQ(ierr);
669     }
670     while (nitem) {
671       if (nitem->dtype == PETSC_CHAR) {
672         char *value = (char*)(((char*)bag) + nitem->offset);
673         char tmp    = value[nitem->msize-1]; /* special handling for fortran chars wihout null terminator */
674         value[nitem->msize-1] =0;
675         ierr = PetscViewerASCIIPrintf(view,"  %s = %s; %s\n",nitem->name,value,nitem->help);CHKERRQ(ierr);
676         value[nitem->msize-1] = tmp;
677       } else if (nitem->dtype == PETSC_REAL) {
678         PetscReal *value = (PetscReal*)(((char*)bag) + nitem->offset);
679         PetscInt  i;
680         ierr = PetscViewerASCIIPrintf(view,"  %s = ",nitem->name);CHKERRQ(ierr);
681         for (i=0; i<nitem->msize; i++) {
682           ierr = PetscViewerASCIIPrintf(view,"%g ",(double)value[i]);CHKERRQ(ierr);
683         }
684         ierr = PetscViewerASCIIPrintf(view,"; %s\n",nitem->help);CHKERRQ(ierr);
685       } else if (nitem->dtype == PETSC_SCALAR) {
686         PetscScalar value = *(PetscScalar*)(((char*)bag) + nitem->offset);
687 #if defined(PETSC_USE_COMPLEX)
688         if ((double)PetscImaginaryPart(value)) {
689           ierr = PetscViewerASCIIPrintf(view,"  %s = %g + %gi; %s\n",nitem->name,(double)PetscRealPart(value),(double)PetscImaginaryPart(value),nitem->help);CHKERRQ(ierr);
690         } else {
691           ierr = PetscViewerASCIIPrintf(view,"  %s = %g; %s\n",nitem->name,(double)PetscRealPart(value),nitem->help);CHKERRQ(ierr);
692         }
693 #else
694         ierr = PetscViewerASCIIPrintf(view,"  %s = %g; %s\n",nitem->name,(double)value,nitem->help);CHKERRQ(ierr);
695 #endif
696       } else if (nitem->dtype == PETSC_INT) {
697         PetscInt i,*value = (PetscInt*)(((char*)bag) + nitem->offset);
698         ierr = PetscViewerASCIIPrintf(view,"  %s = ",nitem->name);CHKERRQ(ierr);
699         for (i=0; i<nitem->msize; i++) {
700           ierr = PetscViewerASCIIPrintf(view,"%D ",value[i]);CHKERRQ(ierr);
701         }
702         ierr = PetscViewerASCIIPrintf(view,"; %s\n",nitem->help);CHKERRQ(ierr);
703       } else if (nitem->dtype == PETSC_BOOL) {
704         PetscBool  *value = (PetscBool*)(((char*)bag) + nitem->offset);
705         PetscInt  i;
706          /* some Fortran compilers use -1 as boolean */
707         ierr = PetscViewerASCIIPrintf(view,"  %s = ",nitem->name);CHKERRQ(ierr);
708         for (i=0; i<nitem->msize; i++) {
709           if (((int) value[i]) == -1) value[i] = PETSC_TRUE;
710           /* the checks here with != PETSC_FALSE and PETSC_TRUE is a special case; here we truly demand that the value be 0 or 1 */
711           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);
712           ierr = PetscViewerASCIIPrintf(view," %s",PetscBools[value[i]]);CHKERRQ(ierr);
713         }
714         ierr = PetscViewerASCIIPrintf(view,"; %s\n",nitem->help);CHKERRQ(ierr);
715       } else if (nitem->dtype == PETSC_ENUM) {
716         PetscEnum value = *(PetscEnum*)(((char*)bag) + nitem->offset);
717         PetscInt  i     = 0;
718         while (nitem->list[i++]) ;
719         ierr = PetscViewerASCIIPrintf(view,"  %s = %s; (%s) %s\n",nitem->name,nitem->list[value],nitem->list[i-3],nitem->help);CHKERRQ(ierr);
720       }
721       nitem = nitem->next;
722     }
723   } else if (isbinary) {
724     PetscInt          classid           = PETSC_BAG_FILE_CLASSID, dtype;
725     PetscInt          deprecatedbagsize = 0;
726     PetscViewerFormat format;
727     ierr = PetscViewerBinaryWrite(view,&classid,1,PETSC_INT);CHKERRQ(ierr);
728     ierr = PetscViewerBinaryWrite(view,&deprecatedbagsize,1,PETSC_INT);CHKERRQ(ierr);
729     ierr = PetscViewerBinaryWrite(view,&bag->count,1,PETSC_INT);CHKERRQ(ierr);
730     ierr = PetscViewerBinaryWrite(view,bag->bagname,PETSC_BAG_NAME_LENGTH,PETSC_CHAR);CHKERRQ(ierr);
731     ierr = PetscViewerBinaryWrite(view,bag->baghelp,PETSC_BAG_HELP_LENGTH,PETSC_CHAR);CHKERRQ(ierr);
732     while (nitem) {
733       ierr  = PetscViewerBinaryWrite(view,&nitem->offset,1,PETSC_INT);CHKERRQ(ierr);
734       dtype = (PetscInt)nitem->dtype;
735       ierr  = PetscViewerBinaryWrite(view,&dtype,1,PETSC_INT);CHKERRQ(ierr);
736       ierr  = PetscViewerBinaryWrite(view,nitem->name,PETSC_BAG_NAME_LENGTH,PETSC_CHAR);CHKERRQ(ierr);
737       ierr  = PetscViewerBinaryWrite(view,nitem->help,PETSC_BAG_HELP_LENGTH,PETSC_CHAR);CHKERRQ(ierr);
738       ierr  = PetscViewerBinaryWrite(view,&nitem->msize,1,PETSC_INT);CHKERRQ(ierr);
739       /* some Fortran compilers use -1 as boolean */
740       if (dtype == PETSC_BOOL && ((*(int*) (((char*)bag) + nitem->offset) == -1))) *(int*) (((char*)bag) + nitem->offset) = PETSC_TRUE;
741 
742       ierr = PetscViewerBinaryWrite(view,(((char*)bag) + nitem->offset),nitem->msize,nitem->dtype);CHKERRQ(ierr);
743       if (dtype == PETSC_ENUM) {
744         ierr = PetscViewerBinaryWriteStringArray(view,(const char* const*)nitem->list);CHKERRQ(ierr);
745       }
746       nitem = nitem->next;
747     }
748     ierr = PetscViewerGetFormat(view,&format);CHKERRQ(ierr);
749     if (format == PETSC_VIEWER_BINARY_MATLAB) {
750       MPI_Comm comm;
751       FILE     *info;
752       ierr = PetscObjectGetComm((PetscObject)view,&comm);CHKERRQ(ierr);
753       ierr = PetscViewerBinaryGetInfoPointer(view,&info);CHKERRQ(ierr);
754       ierr = PetscFPrintf(comm,info,"#--- begin code written by PetscViewerBinary for MATLAB format ---#\n");CHKERRQ(ierr);
755       ierr = PetscFPrintf(comm,info,"#$$ Set.%s = PetscBinaryRead(fd);\n",bag->bagname);CHKERRQ(ierr);
756       ierr = PetscFPrintf(comm,info,"#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n");CHKERRQ(ierr);
757     }
758   }
759   PetscFunctionReturn(0);
760 }
761 
762 /*@C
763   PetscBagViewFromOptions - Processes command line options to determine if/how a PetscBag is to be viewed.
764 
765   Collective on PetscBag
766 
767   Input Parameters:
768 + obj   - the object
769 . bobj  - optional other object that provides prefix (if NULL then the prefix in obj is used)
770 - optionname - option to activate viewing
771 
772   Level: intermediate
773 
774 .seealso: PetscBagCreate(), PetscBag, PetscViewer
775 @*/
776 PetscErrorCode PetscBagViewFromOptions(PetscBag bag, PetscObject bobj, const char optionname[])
777 {
778   static PetscBool  incall = PETSC_FALSE;
779   PetscViewer       viewer;
780   PetscViewerFormat format;
781   const char       *prefix, *bprefix = NULL;
782   PetscBool         flg;
783   PetscErrorCode    ierr;
784 
785   PetscFunctionBegin;
786   if (incall) PetscFunctionReturn(0);
787   incall = PETSC_TRUE;
788   if (bobj) {ierr = PetscObjectGetOptionsPrefix(bobj, &bprefix);CHKERRQ(ierr);}
789   prefix = bobj ? bprefix : bag->bagprefix;
790   ierr   = PetscOptionsGetViewer(bag->bagcomm, NULL, prefix, optionname, &viewer, &format, &flg);CHKERRQ(ierr);
791   if (flg) {
792     ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr);
793     ierr = PetscBagView(bag, viewer);CHKERRQ(ierr);
794     ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
795     ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr);
796     ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr);
797   }
798   incall = PETSC_FALSE;
799   PetscFunctionReturn(0);
800 }
801 
802 /*@C
803    PetscBagLoad - Loads a bag of values from a binary file
804 
805    Collective on PetscViewer
806 
807    Input Parameter:
808 +  viewer - file to load values from
809 -  bag - the bag of values
810 
811    Notes:
812     You must have created and registered all the fields in the bag before loading into it.
813 
814    Notes:
815    Level: beginner
816 
817 .seealso: PetscBag, PetscBagSetName(), PetscBagDestroy(), PetscBagView(), PetscBagGetData()
818            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
819            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagGetName(), PetscBagRegisterEnum()
820 
821 @*/
822 PetscErrorCode  PetscBagLoad(PetscViewer view,PetscBag bag)
823 {
824   PetscErrorCode ierr;
825   PetscBool      isbinary;
826   PetscInt       classid,bagcount,i,dtype,msize,offset,deprecatedbagsize;
827   char           name[PETSC_BAG_NAME_LENGTH],help[PETSC_BAG_HELP_LENGTH],**list;
828   PetscBagItem   nitem;
829   MPI_Comm       comm;
830   PetscMPIInt    flag;
831 
832   PetscFunctionBegin;
833   ierr = PetscObjectGetComm((PetscObject)view,&comm);CHKERRQ(ierr);
834   ierr = MPI_Comm_compare(comm,bag->bagcomm,&flag);CHKERRQ(ierr);
835   if (flag != MPI_CONGRUENT && flag != MPI_IDENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"Different communicators in the viewer and bag"); \
836   ierr = PetscObjectTypeCompare((PetscObject)view,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
837   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support for this viewer type");
838 
839   ierr = PetscViewerBinaryRead(view,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr);
840   if (classid != PETSC_BAG_FILE_CLASSID) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Not PetscBag next in binary file");
841   ierr = PetscViewerBinaryRead(view,&deprecatedbagsize,1,NULL,PETSC_INT);CHKERRQ(ierr);
842   ierr = PetscViewerBinaryRead(view,&bagcount,1,NULL,PETSC_INT);CHKERRQ(ierr);
843   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);
844   ierr = PetscViewerBinaryRead(view,bag->bagname,PETSC_BAG_NAME_LENGTH,NULL,PETSC_CHAR);CHKERRQ(ierr);
845   ierr = PetscViewerBinaryRead(view,bag->baghelp,PETSC_BAG_HELP_LENGTH,NULL,PETSC_CHAR);CHKERRQ(ierr);
846 
847   nitem = bag->bagitems;
848   for (i=0; i<bagcount; i++) {
849     ierr = PetscViewerBinaryRead(view,&offset,1,NULL,PETSC_INT);CHKERRQ(ierr);
850     /* ignore the offset in the file */
851     ierr = PetscViewerBinaryRead(view,&dtype,1,NULL,PETSC_INT);CHKERRQ(ierr);
852     ierr = PetscViewerBinaryRead(view,name,PETSC_BAG_NAME_LENGTH,NULL,PETSC_CHAR);CHKERRQ(ierr);
853     ierr = PetscViewerBinaryRead(view,help,PETSC_BAG_HELP_LENGTH,NULL,PETSC_CHAR);CHKERRQ(ierr);
854     ierr = PetscViewerBinaryRead(view,&msize,1,NULL,PETSC_INT);CHKERRQ(ierr);
855 
856     if (dtype == (PetscInt) PETSC_CHAR) {
857       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,msize,NULL,PETSC_CHAR);CHKERRQ(ierr);
858     } else if (dtype == (PetscInt) PETSC_REAL) {
859       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,msize,NULL,PETSC_REAL);CHKERRQ(ierr);
860     } else if (dtype == (PetscInt) PETSC_SCALAR) {
861       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,1,NULL,PETSC_SCALAR);CHKERRQ(ierr);
862     } else if (dtype == (PetscInt) PETSC_INT) {
863       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,msize,NULL,PETSC_INT);CHKERRQ(ierr);
864     } else if (dtype == (PetscInt) PETSC_BOOL) {
865       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,msize,NULL,PETSC_BOOL);CHKERRQ(ierr);
866     } else if (dtype == (PetscInt) PETSC_ENUM) {
867       ierr = PetscViewerBinaryRead(view,((char*)bag)+nitem->offset,1,NULL,PETSC_ENUM);CHKERRQ(ierr);
868       ierr = PetscViewerBinaryReadStringArray(view,&list);CHKERRQ(ierr);
869       /* don't need to save list because it is already registered in the bag */
870       ierr = PetscFree(list);CHKERRQ(ierr);
871     }
872     nitem = nitem->next;
873   }
874   PetscFunctionReturn(0);
875 }
876 
877 /*@C
878     PetscBagCreate - Create a bag of values
879 
880   Collective
881 
882   Level: Intermediate
883 
884   Input Parameters:
885 +  comm - communicator to share bag
886 -  bagsize - size of the C structure holding the values
887 
888   Output Parameter:
889 .   bag - the bag of values
890 
891    Notes:
892       The size of the A struct must be small enough to fit in a PetscInt; by default
893       PetscInt is 4 bytes; this means a bag cannot be larger than 2 gigabytes in length.
894       The warning about casting to a shorter length can be ignored below unless your A struct is too large
895 
896 .seealso: PetscBag, PetscBagGetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
897            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
898            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
899 @*/
900 PetscErrorCode PetscBagCreate(MPI_Comm comm, size_t bagsize, PetscBag *bag)
901 {
902   PetscErrorCode ierr;
903   size_t         totalsize = bagsize+sizeof(struct _n_PetscBag)+sizeof(PetscScalar);
904 
905   PetscFunctionBegin;
906   ierr = PetscInfo1(NULL,"Creating Bag with total size %d\n",(int)totalsize);CHKERRQ(ierr);
907   ierr = PetscMalloc(totalsize,bag);CHKERRQ(ierr);
908   ierr = PetscMemzero(*bag,bagsize+sizeof(struct _n_PetscBag)+sizeof(PetscScalar));CHKERRQ(ierr);
909 
910   (*bag)->bagsize        = bagsize+sizeof(struct _n_PetscBag)+sizeof(PetscScalar);
911   (*bag)->bagcomm        = comm;
912   (*bag)->bagprefix      = NULL;
913   (*bag)->structlocation = (void*)(((char*)(*bag)) + sizeof(PetscScalar)*(sizeof(struct _n_PetscBag)/sizeof(PetscScalar)) + sizeof(PetscScalar));
914   PetscFunctionReturn(0);
915 }
916 
917 /*@C
918     PetscBagSetName - Sets the name of a bag of values
919 
920   Not Collective
921 
922   Level: Intermediate
923 
924   Input Parameters:
925 +   bag - the bag of values
926 .   name - the name assigned to the bag
927 -   help - help message for bag
928 
929 .seealso: PetscBag, PetscBagGetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
930            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
931            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
932 @*/
933 
934 PetscErrorCode PetscBagSetName(PetscBag bag, const char *name, const char *help)
935 {
936   PetscErrorCode ierr;
937 
938   PetscFunctionBegin;
939   ierr = PetscStrncpy(bag->bagname,name,PETSC_BAG_NAME_LENGTH-1);CHKERRQ(ierr);
940   ierr = PetscStrncpy(bag->baghelp,help,PETSC_BAG_HELP_LENGTH-1);CHKERRQ(ierr);
941   PetscFunctionReturn(0);
942 }
943 
944 
945 /*@C
946     PetscBagGetName - Gets the name of a bag of values
947 
948   Not Collective
949 
950   Level: Intermediate
951 
952   Input Parameter:
953 .   bag - the bag of values
954 
955   Output Parameter:
956 .   name - the name assigned to the bag
957 
958 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad(), PetscBagGetData()
959            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
960            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
961 @*/
962 PetscErrorCode PetscBagGetName(PetscBag bag, char **name)
963 {
964   PetscFunctionBegin;
965   *name = bag->bagname;
966   PetscFunctionReturn(0);
967 }
968 
969 /*@C
970     PetscBagGetData - Gives back the user - access to memory that
971     should be used for storing user-data-structure
972 
973   Not Collective
974 
975   Level: Intermediate
976 
977   Input Parameter:
978 .   bag - the bag of values
979 
980   Output Parameter:
981 .   data - pointer to memory that will have user-data-structure
982 
983 .seealso: PetscBag, PetscBagSetName(), PetscBagView(), PetscBagLoad()
984            PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
985            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
986 @*/
987 PetscErrorCode PetscBagGetData(PetscBag bag, void **data)
988 {
989   PetscFunctionBegin;
990   *data = bag->structlocation;
991   PetscFunctionReturn(0);
992 }
993 
994 /*@C
995   PetscBagSetOptionsPrefix - Sets the prefix used for searching for all
996   PetscBag items in the options database.
997 
998   Logically collective on Bag.
999 
1000   Level: Intermediate
1001 
1002   Input Parameters:
1003 +   bag - the bag of values
1004 -   prefix - the prefix to prepend all Bag item names with.
1005 
1006   NOTES: Must be called prior to registering any of the bag items.
1007 
1008 .seealso: PetscBag, PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar()
1009            PetscBagSetFromOptions(), PetscBagCreate(), PetscBagDestroy(), PetscBagRegisterEnum()
1010 @*/
1011 
1012 PetscErrorCode PetscBagSetOptionsPrefix(PetscBag bag, const char pre[])
1013 {
1014   PetscErrorCode ierr;
1015 
1016   PetscFunctionBegin;
1017   if (!pre) {
1018     ierr = PetscFree(bag->bagprefix);CHKERRQ(ierr);
1019   } else {
1020     if (pre[0] == '-') SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Options prefix should not begin with a hypen");
1021     ierr = PetscFree(bag->bagprefix);CHKERRQ(ierr);
1022     ierr = PetscStrallocpy(pre,&(bag->bagprefix));CHKERRQ(ierr);
1023   }
1024   PetscFunctionReturn(0);
1025 }
1026 
1027 /*@C
1028   PetscBagGetNames - Get the names of all entries in the bag
1029 
1030   Not collective
1031 
1032   Input Parameters:
1033 + bag   - the bag of values
1034 - names - array of the correct size to hold names
1035 
1036   Output Parameter:
1037 . names - array of char pointers for names
1038 
1039   Level: intermediate
1040 
1041 .seealso: PetscBag, PetscBagGetName(), PetscBagSetName(), PetscBagCreate(), PetscBagGetData()
1042           PetscBagRegisterReal(), PetscBagRegisterInt(), PetscBagRegisterBool(), PetscBagRegisterScalar(), PetscBagRegisterEnum()
1043 @*/
1044 PetscErrorCode PetscBagGetNames(PetscBag bag, const char *names[])
1045 {
1046   PetscBagItem nitem = bag->bagitems;
1047   PetscInt     n;
1048 
1049   PetscFunctionBegin;
1050   for (n = 0; nitem; ++n, nitem = nitem->next) {names[n] = nitem->name;}
1051   PetscFunctionReturn(0);
1052 }
1053