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