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