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