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