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