xref: /petsc/src/sys/classes/bag/bag.c (revision d71ae5a4db6382e7f06317b8d368875286fe9008)
1 #include <petsc/private/petscimpl.h>
2 #include <petsc/private/bagimpl.h> /*I  "petscbag.h"   I*/
3 #include <petscviewer.h>
4 
5 /*
6       Adds item to the linked list in a bag
7 */
8 static PetscErrorCode PetscBagRegister_Private(PetscBag bag, PetscBagItem item, const char *name, const char *help)
9 {
10   PetscFunctionBegin;
11   PetscCall(PetscStrncpy(item->name, name, PETSC_BAG_NAME_LENGTH - 1));
12   PetscCall(PetscStrncpy(item->help, help, PETSC_BAG_HELP_LENGTH - 1));
13   if (bag->bagitems) {
14     PetscBagItem nitem = bag->bagitems;
15 
16     while (nitem->next) nitem = nitem->next;
17     nitem->next = item;
18   } else bag->bagitems = item;
19   bag->count++;
20   PetscFunctionReturn(0);
21 }
22 
23 /*@C
24    PetscBagRegisterEnum - add an enum value to a `PetscBag`
25 
26    Logically Collective on bag
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(0);
77 }
78 
79 /*@C
80    PetscBagRegisterIntArray - add an `PetscInt` array to a `PetscBag`
81 
82    Logically Collective on bag
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(0);
128 }
129 
130 /*@C
131    PetscBagRegisterRealArray - add an `PetscReal` array to a `PetscBag`
132 
133    Logically Collective on bag
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(0);
179 }
180 
181 /*@C
182    PetscBagRegisterInt - add an `PetscInt` value to a `PetscBag`
183 
184    Logically Collective on bag
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(0);
226 }
227 
228 /*@C
229    PetscBagRegisterInt64 - add a `PetscInt64` value to a `PetscBag`
230 
231    Logically Collective on bag
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(0);
272 }
273 
274 /*@C
275    PetscBagRegisterBoolArray - add a n `PetscBool` values to a `PetscBag`
276 
277    Logically Collective on bag
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(0);
323 }
324 
325 /*@C
326    PetscBagRegisterString - add a string value to a `PetscBag`
327 
328    Logically Collective on bag
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: The struct should have the field char mystring[msize]; not char *mystring
341 
342 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`
343           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
344           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
345 @*/
346 PetscErrorCode PetscBagRegisterString(PetscBag bag, void *addr, PetscInt msize, const char *mdefault, const char *name, const char *help)
347 {
348   PetscBagItem item;
349   char         nname[PETSC_BAG_NAME_LENGTH + 1];
350   PetscBool    printhelp;
351 
352   PetscFunctionBegin;
353   PetscValidPointer(bag, 1);
354   PetscValidPointer(addr, 2);
355   PetscValidCharPointer(mdefault, 4);
356   PetscValidCharPointer(name, 5);
357   PetscValidCharPointer(help, 6);
358   nname[0] = '-';
359   nname[1] = 0;
360   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
361   PetscCall(PetscOptionsHasHelp(NULL, &printhelp));
362   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%s>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, mdefault, help));
363 
364   PetscCall(PetscNew(&item));
365   item->dtype  = PETSC_CHAR;
366   item->offset = ((char *)addr) - ((char *)bag);
367   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
368   item->next  = NULL;
369   item->msize = msize;
370   if (mdefault != (char *)addr) PetscCall(PetscStrncpy((char *)addr, mdefault, msize - 1));
371   PetscCall(PetscOptionsGetString(NULL, bag->bagprefix, nname, (char *)addr, msize, NULL));
372   PetscCall(PetscBagRegister_Private(bag, item, name, help));
373   PetscFunctionReturn(0);
374 }
375 
376 /*@C
377    PetscBagRegisterReal - add a `PetscReal` value to a `PetscBag`
378 
379    Logically Collective on bag
380 
381    Input Parameters:
382 +  bag - the bag of values
383 .  addr - location of double in struct, for example `&params->r`
384 .  mdefault - the initial value
385 .  name - name of the variable
386 -  help - longer string with more information about the value
387 
388    Level: beginner
389 
390 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`
391           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
392           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
393 @*/
394 PetscErrorCode PetscBagRegisterReal(PetscBag bag, void *addr, PetscReal mdefault, const char *name, const char *help)
395 {
396   PetscBagItem item;
397   char         nname[PETSC_BAG_NAME_LENGTH + 1];
398   PetscBool    printhelp;
399 
400   PetscFunctionBegin;
401   PetscValidPointer(bag, 1);
402   PetscValidPointer(addr, 2);
403   PetscValidCharPointer(name, 4);
404   PetscValidCharPointer(help, 5);
405   nname[0] = '-';
406   nname[1] = 0;
407   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
408   PetscCall(PetscOptionsHasHelp(NULL, &printhelp));
409   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%g>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, (double)mdefault, help));
410   PetscCall(PetscOptionsGetReal(NULL, bag->bagprefix, nname, &mdefault, NULL));
411 
412   PetscCall(PetscNew(&item));
413   item->dtype  = PETSC_REAL;
414   item->offset = ((char *)addr) - ((char *)bag);
415   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
416   item->next         = NULL;
417   item->msize        = 1;
418   *(PetscReal *)addr = mdefault;
419   PetscCall(PetscBagRegister_Private(bag, item, name, help));
420   PetscFunctionReturn(0);
421 }
422 
423 /*@C
424    PetscBagRegisterScalar - add a `PetscScalar` value to a `PetscBag`
425 
426    Logically Collective on bag
427 
428    Input Parameters:
429 +  bag - the bag of values
430 .  addr - location of scalar in struct, for example `&params->c`
431 .  mdefault - the initial value
432 .  name - name of the variable
433 -  help - longer string with more information about the value
434 
435    Level: beginner
436 
437 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`
438           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
439           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
440 @*/
441 PetscErrorCode PetscBagRegisterScalar(PetscBag bag, void *addr, PetscScalar mdefault, const char *name, const char *help)
442 {
443   PetscBagItem item;
444   char         nname[PETSC_BAG_NAME_LENGTH + 1];
445   PetscBool    printhelp;
446 
447   PetscFunctionBegin;
448   PetscValidPointer(bag, 1);
449   PetscValidPointer(addr, 2);
450   PetscValidCharPointer(name, 4);
451   PetscValidCharPointer(help, 5);
452   nname[0] = '-';
453   nname[1] = 0;
454   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
455   PetscCall(PetscOptionsHasHelp(NULL, &printhelp));
456   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%g + %gi>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, (double)PetscRealPart(mdefault), (double)PetscImaginaryPart(mdefault), help));
457   PetscCall(PetscOptionsGetScalar(NULL, bag->bagprefix, nname, &mdefault, NULL));
458 
459   PetscCall(PetscNew(&item));
460   item->dtype  = PETSC_SCALAR;
461   item->offset = ((char *)addr) - ((char *)bag);
462   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
463   item->next           = NULL;
464   item->msize          = 1;
465   *(PetscScalar *)addr = mdefault;
466   PetscCall(PetscBagRegister_Private(bag, item, name, help));
467   PetscFunctionReturn(0);
468 }
469 
470 /*@C
471    PetscBagRegisterBool - add a `PetscBool` to a `PetscBag`
472 
473    Logically Collective on bag
474 
475    Input Parameters:
476 +  bag - the bag of values
477 .  addr - location of logical in struct, for example `&params->b`
478 .  mdefault - the initial value, either `PETSC_FALSE` or `PETSC_TRUE`
479 .  name - name of the variable
480 -  help - longer string with more information about the value
481 
482    Level: beginner
483 
484 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`
485           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
486           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
487 @*/
488 PetscErrorCode PetscBagRegisterBool(PetscBag bag, void *addr, PetscBool mdefault, const char *name, const char *help)
489 {
490   PetscBagItem item;
491   char         nname[PETSC_BAG_NAME_LENGTH + 1];
492   PetscBool    printhelp;
493 
494   PetscFunctionBegin;
495   PetscValidPointer(bag, 1);
496   PetscValidPointer(addr, 2);
497   PetscValidCharPointer(name, 4);
498   PetscValidCharPointer(help, 5);
499   /* the checks here with != PETSC_FALSE and PETSC_TRUE is a special case; here we truly demand that the value be 0 or 1 */
500   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);
501   nname[0] = '-';
502   nname[1] = 0;
503   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
504   PetscCall(PetscOptionsHasHelp(NULL, &printhelp));
505   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%s>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, PetscBools[mdefault], help));
506   PetscCall(PetscOptionsGetBool(NULL, bag->bagprefix, nname, &mdefault, NULL));
507 
508   PetscCall(PetscNew(&item));
509   item->dtype  = PETSC_BOOL;
510   item->offset = ((char *)addr) - ((char *)bag);
511   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
512   item->next         = NULL;
513   item->msize        = 1;
514   *(PetscBool *)addr = mdefault;
515   PetscCall(PetscBagRegister_Private(bag, item, name, help));
516   PetscFunctionReturn(0);
517 }
518 
519 /*@C
520    PetscBagDestroy - Destroys a `PetscBag`
521 
522    Collective on bag
523 
524    Input Parameter:
525 .  bag - the bag of values
526 
527    Level: beginner
528 
529 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`
530           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
531           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
532 @*/
533 PetscErrorCode PetscBagDestroy(PetscBag *bag)
534 {
535   PetscBagItem nitem;
536 
537   PetscFunctionBegin;
538   if (!*bag) PetscFunctionReturn(0);
539   PetscValidPointer(*bag, 1);
540   nitem = (*bag)->bagitems;
541   while (nitem) {
542     PetscBagItem item = nitem->next;
543 
544     if (nitem->list) PetscCall(PetscStrArrayDestroy(&nitem->list));
545     PetscCall(PetscFree(nitem));
546     nitem = item;
547   }
548   if ((*bag)->bagprefix) PetscCall(PetscFree((*bag)->bagprefix));
549   PetscCall(PetscFree(*bag));
550   PetscFunctionReturn(0);
551 }
552 
553 /*@
554    PetscBagSetFromOptions - Allows setting entries to a `PetscBag` using the options database
555 
556    Collective on bag
557 
558    Input Parameter:
559 .  bag - the bag of values
560 
561    Level: beginner
562 
563    Note:
564    The options database keys for the entries are of the form `-[bagprefix]_name value`
565 
566 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagDestroy()`, `PetscBagLoad()`, `PetscBagGetData()`
567           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
568           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagRegisterEnum()`
569 @*/
570 PetscErrorCode PetscBagSetFromOptions(PetscBag bag)
571 {
572   PetscBagItem nitem = bag->bagitems;
573   char         name[PETSC_BAG_NAME_LENGTH + 1], helpname[PETSC_BAG_NAME_LENGTH + PETSC_BAG_HELP_LENGTH + 3];
574   PetscInt     n;
575 
576   PetscFunctionBegin;
577   PetscValidPointer(bag, 1);
578   PetscCall(PetscStrncpy(helpname, bag->bagname, sizeof(helpname)));
579   PetscCall(PetscStrlcat(helpname, " ", sizeof(helpname)));
580   PetscCall(PetscStrlcat(helpname, bag->baghelp, sizeof(helpname)));
581   PetscOptionsBegin(bag->bagcomm, bag->bagprefix, helpname, NULL);
582   while (nitem) {
583     name[0] = '-';
584     name[1] = 0;
585     PetscCall(PetscStrlcat(name, nitem->name, sizeof(name)));
586     if (nitem->dtype == PETSC_CHAR) { /* special handling for fortran required? [due to space padding vs null termination] */
587       char *value = (char *)(((char *)bag) + nitem->offset);
588       PetscCall(PetscOptionsString(name, nitem->help, "", value, value, nitem->msize, NULL));
589     } else if (nitem->dtype == PETSC_REAL) {
590       PetscReal *value = (PetscReal *)(((char *)bag) + nitem->offset);
591       if (nitem->msize == 1) {
592         PetscCall(PetscOptionsReal(name, nitem->help, "", *value, value, NULL));
593       } else {
594         n = nitem->msize;
595         PetscCall(PetscOptionsRealArray(name, nitem->help, "", value, &n, NULL));
596       }
597     } else if (nitem->dtype == PETSC_SCALAR) {
598       PetscScalar *value = (PetscScalar *)(((char *)bag) + nitem->offset);
599       PetscCall(PetscOptionsScalar(name, nitem->help, "", *value, value, NULL));
600     } else if (nitem->dtype == PETSC_INT) {
601       PetscInt *value = (PetscInt *)(((char *)bag) + nitem->offset);
602       if (nitem->msize == 1) {
603         PetscCall(PetscOptionsInt(name, nitem->help, "", *value, value, NULL));
604       } else {
605         n = nitem->msize;
606         PetscCall(PetscOptionsIntArray(name, nitem->help, "", value, &n, NULL));
607       }
608     } else if (nitem->dtype == PETSC_ENUM) {
609       PetscEnum *value = (PetscEnum *)(((char *)bag) + nitem->offset);
610       PetscInt   i     = 0;
611       while (nitem->list[i++])
612         ;
613       PetscCall(PetscOptionsEnum(name, nitem->help, nitem->list[i - 3], (const char *const *)nitem->list, *value, value, NULL));
614     } else if (nitem->dtype == PETSC_BOOL) {
615       PetscBool *value = (PetscBool *)(((char *)bag) + nitem->offset);
616       if (nitem->msize == 1) {
617         PetscCall(PetscOptionsBool(name, nitem->help, "", *value, value, NULL));
618       } else {
619         n = nitem->msize;
620         PetscCall(PetscOptionsBoolArray(name, nitem->help, "", value, &n, NULL));
621       }
622     }
623     nitem = nitem->next;
624   }
625   PetscOptionsEnd();
626   PetscFunctionReturn(0);
627 }
628 
629 /*@C
630    PetscBagView - Views a bag of values as either ASCII text or a binary file
631 
632    Collective on bag
633 
634    Input Parameters:
635 +  bag - the bag of values
636 -  viewer - location to view the values
637 
638    Level: beginner
639 
640    Note:
641    Currently PETSc bags saved in a binary file can only be read back
642    in on a machine of the same architecture.
643 
644 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagDestroy()`, `PetscBagLoad()`, `PetscBagGetData()`
645           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`, `PetscBagRegisterEnum()`
646           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`
647 @*/
648 PetscErrorCode PetscBagView(PetscBag bag, PetscViewer view)
649 {
650   PetscBool    isascii, isbinary;
651   PetscBagItem nitem = bag->bagitems;
652 
653   PetscFunctionBegin;
654   PetscValidPointer(bag, 1);
655   PetscValidHeaderSpecific(view, PETSC_VIEWER_CLASSID, 2);
656   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
657   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERBINARY, &isbinary));
658   if (isascii) {
659     if (bag->bagprefix) {
660       PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object:  %s (%s) %s\n", bag->bagname, bag->bagprefix, bag->baghelp));
661     } else {
662       PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object:  %s %s\n", bag->bagname, bag->baghelp));
663     }
664     while (nitem) {
665       if (nitem->dtype == PETSC_CHAR) {
666         char *value             = (char *)(((char *)bag) + nitem->offset);
667         char  tmp               = value[nitem->msize - 1]; /* special handling for fortran chars wihout null terminator */
668         value[nitem->msize - 1] = 0;
669         PetscCall(PetscViewerASCIIPrintf(view, "  %s = %s; %s\n", nitem->name, value, nitem->help));
670         value[nitem->msize - 1] = tmp;
671       } else if (nitem->dtype == PETSC_REAL) {
672         PetscReal *value = (PetscReal *)(((char *)bag) + nitem->offset);
673         PetscInt   i;
674         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
675         for (i = 0; i < nitem->msize; i++) PetscCall(PetscViewerASCIIPrintf(view, "%g ", (double)value[i]));
676         PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help));
677       } else if (nitem->dtype == PETSC_SCALAR) {
678         PetscScalar value = *(PetscScalar *)(((char *)bag) + nitem->offset);
679 #if defined(PETSC_USE_COMPLEX)
680         if ((double)PetscImaginaryPart(value)) {
681           PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g + %gi; %s\n", nitem->name, (double)PetscRealPart(value), (double)PetscImaginaryPart(value), nitem->help));
682         } else {
683           PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g; %s\n", nitem->name, (double)PetscRealPart(value), nitem->help));
684         }
685 #else
686         PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g; %s\n", nitem->name, (double)value, nitem->help));
687 #endif
688       } else if (nitem->dtype == PETSC_INT) {
689         PetscInt i, *value = (PetscInt *)(((char *)bag) + nitem->offset);
690         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
691         for (i = 0; i < nitem->msize; i++) PetscCall(PetscViewerASCIIPrintf(view, "%" PetscInt_FMT " ", value[i]));
692         PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help));
693       } else if (nitem->dtype == PETSC_BOOL) {
694         PetscBool *value = (PetscBool *)(((char *)bag) + nitem->offset);
695         PetscInt   i;
696         /* some Fortran compilers use -1 as boolean */
697         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
698         for (i = 0; i < nitem->msize; i++) {
699           if (((int)value[i]) == -1) value[i] = PETSC_TRUE;
700           /* the checks here with != PETSC_FALSE and PETSC_TRUE is a special case; here we truly demand that the value be 0 or 1 */
701           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]));
702           PetscCall(PetscViewerASCIIPrintf(view, " %s", PetscBools[value[i]]));
703         }
704         PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help));
705       } else if (nitem->dtype == PETSC_ENUM) {
706         PetscEnum value = *(PetscEnum *)(((char *)bag) + nitem->offset);
707         PetscInt  i     = 0;
708         while (nitem->list[i++])
709           ;
710         PetscCall(PetscViewerASCIIPrintf(view, "  %s = %s; (%s) %s\n", nitem->name, nitem->list[value], nitem->list[i - 3], nitem->help));
711       }
712       nitem = nitem->next;
713     }
714   } else if (isbinary) {
715     PetscInt          classid           = PETSC_BAG_FILE_CLASSID, dtype;
716     PetscInt          deprecatedbagsize = 0;
717     PetscViewerFormat format;
718     PetscCall(PetscViewerBinaryWrite(view, &classid, 1, PETSC_INT));
719     PetscCall(PetscViewerBinaryWrite(view, &deprecatedbagsize, 1, PETSC_INT));
720     PetscCall(PetscViewerBinaryWrite(view, &bag->count, 1, PETSC_INT));
721     PetscCall(PetscViewerBinaryWrite(view, bag->bagname, PETSC_BAG_NAME_LENGTH, PETSC_CHAR));
722     PetscCall(PetscViewerBinaryWrite(view, bag->baghelp, PETSC_BAG_HELP_LENGTH, PETSC_CHAR));
723     while (nitem) {
724       PetscCall(PetscViewerBinaryWrite(view, &nitem->offset, 1, PETSC_INT));
725       dtype = (PetscInt)nitem->dtype;
726       PetscCall(PetscViewerBinaryWrite(view, &dtype, 1, PETSC_INT));
727       PetscCall(PetscViewerBinaryWrite(view, nitem->name, PETSC_BAG_NAME_LENGTH, PETSC_CHAR));
728       PetscCall(PetscViewerBinaryWrite(view, nitem->help, PETSC_BAG_HELP_LENGTH, PETSC_CHAR));
729       PetscCall(PetscViewerBinaryWrite(view, &nitem->msize, 1, PETSC_INT));
730       /* some Fortran compilers use -1 as boolean */
731       if (dtype == PETSC_BOOL && ((*(int *)(((char *)bag) + nitem->offset) == -1))) *(int *)(((char *)bag) + nitem->offset) = PETSC_TRUE;
732 
733       PetscCall(PetscViewerBinaryWrite(view, (((char *)bag) + nitem->offset), nitem->msize, nitem->dtype));
734       if (dtype == PETSC_ENUM) PetscCall(PetscViewerBinaryWriteStringArray(view, (const char *const *)nitem->list));
735       nitem = nitem->next;
736     }
737     PetscCall(PetscViewerGetFormat(view, &format));
738     if (format == PETSC_VIEWER_BINARY_MATLAB) {
739       MPI_Comm comm;
740       FILE    *info;
741       PetscCall(PetscObjectGetComm((PetscObject)view, &comm));
742       PetscCall(PetscViewerBinaryGetInfoPointer(view, &info));
743       PetscCall(PetscFPrintf(comm, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n"));
744       PetscCall(PetscFPrintf(comm, info, "#$$ Set.%s = PetscBinaryRead(fd);\n", bag->bagname));
745       PetscCall(PetscFPrintf(comm, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n"));
746     }
747   }
748   PetscFunctionReturn(0);
749 }
750 
751 /*@C
752   PetscBagViewFromOptions - Processes command line options to determine if/how a PetscBag is to be viewed.
753 
754   Collective on bag
755 
756   Input Parameters:
757 + obj   - the object
758 . bobj  - optional other object that provides prefix (if NULL then the prefix in obj is used)
759 - optionname - option to activate viewing
760 
761   Level: intermediate
762 
763 .seealso: `PetscBagCreate()`, `PetscBag`, `PetscViewer`
764 @*/
765 PetscErrorCode PetscBagViewFromOptions(PetscBag bag, PetscObject bobj, const char optionname[])
766 {
767   static PetscBool  incall = PETSC_FALSE;
768   PetscViewer       viewer;
769   PetscViewerFormat format;
770   const char       *prefix, *bprefix = NULL;
771   PetscBool         flg;
772 
773   PetscFunctionBegin;
774   if (incall) PetscFunctionReturn(0);
775   incall = PETSC_TRUE;
776   PetscValidPointer(bag, 1);
777   if (bobj) PetscCall(PetscObjectGetOptionsPrefix(bobj, &bprefix));
778   prefix = bobj ? bprefix : bag->bagprefix;
779   PetscCall(PetscOptionsGetViewer(bag->bagcomm, NULL, prefix, optionname, &viewer, &format, &flg));
780   if (flg) {
781     PetscCall(PetscViewerPushFormat(viewer, format));
782     PetscCall(PetscBagView(bag, viewer));
783     PetscCall(PetscViewerFlush(viewer));
784     PetscCall(PetscViewerPopFormat(viewer));
785     PetscCall(PetscViewerDestroy(&viewer));
786   }
787   incall = PETSC_FALSE;
788   PetscFunctionReturn(0);
789 }
790 
791 /*@C
792    PetscBagLoad - Loads a bag of values from a binary file
793 
794    Collective on view
795 
796    Input Parameters:
797 +  viewer - file to load values from
798 -  bag - the bag of values
799 
800    Note:
801     You must have created and registered all the fields in the bag before loading into it.
802 
803    Level: beginner
804 
805 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagDestroy()`, `PetscBagView()`, `PetscBagGetData()`
806           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
807           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
808 @*/
809 PetscErrorCode PetscBagLoad(PetscViewer view, PetscBag bag)
810 {
811   PetscBool    isbinary;
812   PetscInt     classid, bagcount, dtype, msize, offset, deprecatedbagsize;
813   char         name[PETSC_BAG_NAME_LENGTH], help[PETSC_BAG_HELP_LENGTH], **list;
814   PetscBagItem nitem;
815   MPI_Comm     comm;
816   PetscMPIInt  flag;
817 
818   PetscFunctionBegin;
819   PetscValidHeaderSpecific(view, PETSC_VIEWER_CLASSID, 1);
820   PetscValidPointer(bag, 2);
821   PetscCall(PetscObjectGetComm((PetscObject)view, &comm));
822   PetscCallMPI(MPI_Comm_compare(comm, bag->bagcomm, &flag));
823   PetscCheck(flag == MPI_CONGRUENT || flag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "Different communicators in the viewer and bag");
824   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERBINARY, &isbinary));
825   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for this viewer type");
826 
827   PetscCall(PetscViewerBinaryRead(view, &classid, 1, NULL, PETSC_INT));
828   PetscCheck(classid == PETSC_BAG_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not PetscBag next in binary file");
829   PetscCall(PetscViewerBinaryRead(view, &deprecatedbagsize, 1, NULL, PETSC_INT));
830   PetscCall(PetscViewerBinaryRead(view, &bagcount, 1, NULL, PETSC_INT));
831   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);
832   PetscCall(PetscViewerBinaryRead(view, bag->bagname, PETSC_BAG_NAME_LENGTH, NULL, PETSC_CHAR));
833   PetscCall(PetscViewerBinaryRead(view, bag->baghelp, PETSC_BAG_HELP_LENGTH, NULL, PETSC_CHAR));
834 
835   nitem = bag->bagitems;
836   for (PetscInt i = 0; i < bagcount; i++) {
837     PetscCall(PetscViewerBinaryRead(view, &offset, 1, NULL, PETSC_INT));
838     /* ignore the offset in the file */
839     PetscCall(PetscViewerBinaryRead(view, &dtype, 1, NULL, PETSC_INT));
840     PetscCall(PetscViewerBinaryRead(view, name, PETSC_BAG_NAME_LENGTH, NULL, PETSC_CHAR));
841     PetscCall(PetscViewerBinaryRead(view, help, PETSC_BAG_HELP_LENGTH, NULL, PETSC_CHAR));
842     PetscCall(PetscViewerBinaryRead(view, &msize, 1, NULL, PETSC_INT));
843 
844     if (dtype == (PetscInt)PETSC_CHAR) {
845       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_CHAR));
846     } else if (dtype == (PetscInt)PETSC_REAL) {
847       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_REAL));
848     } else if (dtype == (PetscInt)PETSC_SCALAR) {
849       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, 1, NULL, PETSC_SCALAR));
850     } else if (dtype == (PetscInt)PETSC_INT) {
851       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_INT));
852     } else if (dtype == (PetscInt)PETSC_BOOL) {
853       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_BOOL));
854     } else if (dtype == (PetscInt)PETSC_ENUM) {
855       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, 1, NULL, PETSC_ENUM));
856       PetscCall(PetscViewerBinaryReadStringArray(view, &list));
857       /* don't need to save list because it is already registered in the bag */
858       PetscCall(PetscFree(list));
859     }
860     nitem = nitem->next;
861   }
862   PetscFunctionReturn(0);
863 }
864 
865 /*@C
866     PetscBagCreate - Create a bag of values. A `PetscBag` is a representation of a C struct that can be saved to and read from files, can have values set from the
867     options database
868 
869   Collective
870 
871   Level: Intermediate
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    Notes:
881    After creating the bag, for each entry in the C struct call the appropriate `PetscBagRegisterInt()` etc to define the C structs layout
882 
883    The size of the A struct must be small enough to fit in a `PetscInt`; by default
884    `PetscInt` is 4 bytes; this means a bag cannot be larger than 2 gigabytes in length.
885    The warning about casting to a shorter length can be ignored below unless your A struct is too large
886 
887 .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`
888           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
889           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
890 @*/
891 PetscErrorCode PetscBagCreate(MPI_Comm comm, size_t bagsize, PetscBag *bag)
892 {
893   const size_t totalsize = bagsize + sizeof(struct _n_PetscBag) + sizeof(PetscScalar);
894 
895   PetscFunctionBegin;
896   PetscValidPointer(bag, 3);
897   PetscCall(PetscInfo(NULL, "Creating Bag with total size %d\n", (int)totalsize));
898   PetscCall(PetscCalloc(totalsize, bag));
899 
900   (*bag)->bagsize        = totalsize;
901   (*bag)->bagcomm        = comm;
902   (*bag)->bagprefix      = NULL;
903   (*bag)->structlocation = (void *)(((char *)(*bag)) + sizeof(PetscScalar) * (sizeof(struct _n_PetscBag) / sizeof(PetscScalar)) + sizeof(PetscScalar));
904   PetscFunctionReturn(0);
905 }
906 
907 /*@C
908     PetscBagSetName - Sets the name of a bag of values
909 
910   Not Collective
911 
912   Level: Intermediate
913 
914   Input Parameters:
915 +   bag - the bag of values
916 .   name - the name assigned to the bag
917 -   help - help message for bag
918 
919 .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`
920           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
921           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
922 @*/
923 PetscErrorCode PetscBagSetName(PetscBag bag, const char *name, const char *help)
924 {
925   PetscFunctionBegin;
926   PetscValidPointer(bag, 1);
927   PetscValidCharPointer(name, 2);
928   PetscValidCharPointer(help, 3);
929   PetscCall(PetscStrncpy(bag->bagname, name, PETSC_BAG_NAME_LENGTH - 1));
930   PetscCall(PetscStrncpy(bag->baghelp, help, PETSC_BAG_HELP_LENGTH - 1));
931   PetscFunctionReturn(0);
932 }
933 
934 /*@C
935     PetscBagGetName - Gets the name of a bag of values
936 
937   Not Collective
938 
939   Level: Intermediate
940 
941   Input Parameter:
942 .   bag - the bag of values
943 
944   Output Parameter:
945 .   name - the name assigned to the bag
946 
947 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`
948           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
949           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
950 @*/
951 PetscErrorCode PetscBagGetName(PetscBag bag, char **name)
952 {
953   PetscFunctionBegin;
954   PetscValidPointer(bag, 1);
955   PetscValidPointer(name, 2);
956   *name = bag->bagname;
957   PetscFunctionReturn(0);
958 }
959 
960 /*@C
961     PetscBagGetData - Gives back the user - access to memory that
962     can be used for storing user-data-structure
963 
964   Not Collective
965 
966   Level: Intermediate
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 defining the bag
973 
974 .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`
975           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
976           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
977 @*/
978 PetscErrorCode PetscBagGetData(PetscBag bag, void **data)
979 {
980   PetscFunctionBegin;
981   PetscValidPointer(bag, 1);
982   PetscValidPointer(data, 2);
983   *data = bag->structlocation;
984   PetscFunctionReturn(0);
985 }
986 
987 /*@C
988   PetscBagSetOptionsPrefix - Sets the prefix used for searching for all
989   `PetscBag` items in the options database.
990 
991   Logically collective on bag
992 
993   Level: Intermediate
994 
995   Input Parameters:
996 +   bag - the bag of values
997 -   prefix - the prefix to prepend all Bag item names with.
998 
999   NOTES: Must be called prior to registering any of the bag items.
1000 
1001 .seealso: `PetscBag`, `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
1002           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
1003 @*/
1004 
1005 PetscErrorCode PetscBagSetOptionsPrefix(PetscBag bag, const char pre[])
1006 {
1007   PetscFunctionBegin;
1008   PetscValidPointer(bag, 1);
1009   if (pre) {
1010     PetscValidCharPointer(pre, 2);
1011     PetscCheck(pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
1012     PetscCall(PetscFree(bag->bagprefix));
1013     PetscCall(PetscStrallocpy(pre, &(bag->bagprefix)));
1014   } else PetscCall(PetscFree(bag->bagprefix));
1015   PetscFunctionReturn(0);
1016 }
1017 
1018 /*@C
1019   PetscBagGetNames - Get the names of all entries in the bag
1020 
1021   Not collective
1022 
1023   Input Parameters:
1024 + bag   - the bag of values
1025 - names - array of the correct size to hold names, must be long enough to hold all the names
1026 
1027   Output Parameter:
1028 . names - array of char pointers for names
1029 
1030   Level: intermediate
1031 
1032 .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagSetName()`, `PetscBagCreate()`, `PetscBagGetData()`
1033           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`, `PetscBagRegisterEnum()`
1034 @*/
1035 PetscErrorCode PetscBagGetNames(PetscBag bag, const char *names[])
1036 {
1037   PetscBagItem nitem = bag->bagitems;
1038 
1039   PetscFunctionBegin;
1040   PetscValidPointer(bag, 1);
1041   PetscValidPointer(names, 2);
1042   for (PetscInt n = 0; nitem; ++n, nitem = nitem->next) names[n] = nitem->name;
1043   PetscFunctionReturn(0);
1044 }
1045