Actual source code: bag.c

  1: #include <petsc/private/petscimpl.h>
  2: #include <petsc/private/bagimpl.h>

  4: /*
  5:       Adds item to the linked list in a bag
  6: */
  7: static PetscErrorCode PetscBagRegister_Private(PetscBag bag, PetscBagItem item, const char *name, const char *help)
  8: {
  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;

 15:     while (nitem->next) nitem = nitem->next;
 16:     nitem->next = item;
 17:   } else bag->bagitems = item;
 18:   bag->count++;
 19:   PetscFunctionReturn(PETSC_SUCCESS);
 20: }

 22: /*@
 23:   PetscBagRegisterEnum - add an enum value to a `PetscBag`

 25:   Logically Collective

 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: . name     - the name of the item
 33: - help     - longer string with more information about the value

 35:   Level: beginner

 37: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
 38:           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
 39:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`
 40: @*/
 41: PetscErrorCode PetscBagRegisterEnum(PetscBag bag, void *addr, const char *const *list, PetscEnum mdefault, const char *name, const char *help)
 42: {
 43:   PetscBagItem item;
 44:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
 45:   PetscBool    printhelp;
 46:   PetscInt     i = 0;

 48:   PetscFunctionBegin;
 49:   PetscAssertPointer(bag, 1);
 50:   PetscAssertPointer(addr, 2);
 51:   PetscAssertPointer(list, 3);
 52:   PetscAssertPointer(name, 5);
 53:   PetscAssertPointer(help, 6);
 54:   nname[0] = '-';
 55:   nname[1] = 0;
 56:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
 57:   /* bag options are registered outside a PetscOptionsBegin() block, so they name their manual section
 58:      here; "Bag" is the SUBMANSEC in the makefile of this directory */
 59:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
 60:   if (printhelp) {
 61:     while (list[i++]);
 62:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%s>: (%s) %s (choose one of) ", bag->bagprefix ? bag->bagprefix : "", name, list[mdefault], list[i - 3], help));
 63:     for (i = 0; list[i + 2]; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " %s", list[i]));
 64:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, "\n"));
 65:   }
 66:   PetscCall(PetscOptionsGetEnum(NULL, bag->bagprefix, nname, list, &mdefault, NULL));

 68:   PetscCall(PetscNew(&item));
 69:   item->dtype  = PETSC_ENUM;
 70:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
 71:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
 72:   item->next  = NULL;
 73:   item->msize = 1;
 74:   PetscCall(PetscStrArrayallocpy(list, &item->list));
 75:   *(PetscEnum *)addr = mdefault;
 76:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
 77:   PetscFunctionReturn(PETSC_SUCCESS);
 78: }

 80: /*@
 81:   PetscBagRegisterIntArray - add a `PetscInt` array to a `PetscBag`

 83:   Logically Collective

 85:   Input Parameters:
 86: + bag   - the bag of values
 87: . addr  - location of integer in struct, for example `&params->i`
 88: . msize - number of entries in array
 89: . name  - name of the array
 90: - help  - longer string with more information about the value

 92:   Level: beginner

 94: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
 95:           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
 96:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
 97: @*/
 98: PetscErrorCode PetscBagRegisterIntArray(PetscBag bag, void *addr, PetscInt msize, const char *name, const char *help)
 99: {
100:   PetscBagItem item;
101:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
102:   PetscBool    printhelp;
103:   PetscInt    *values = (PetscInt *)addr;
104:   PetscInt     i, tmp = msize;

106:   PetscFunctionBegin;
107:   PetscAssertPointer(bag, 1);
108:   PetscAssertPointer(addr, 2);
109:   PetscAssertPointer(name, 4);
110:   PetscAssertPointer(help, 5);
111:   nname[0] = '-';
112:   nname[1] = 0;
113:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
114:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
115:   if (printhelp) {
116:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <", bag->bagprefix ? bag->bagprefix : "", name));
117:     for (i = 0; i < msize; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "%" PetscInt_FMT " ", values[i]));
118:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, ">: %s \n", help));
119:   }
120:   PetscCall(PetscOptionsGetIntArray(NULL, bag->bagprefix, nname, values, &tmp, NULL));

122:   PetscCall(PetscNew(&item));
123:   item->dtype  = PETSC_INT;
124:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
125:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
126:   item->next  = NULL;
127:   item->msize = msize;
128:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
129:   PetscFunctionReturn(PETSC_SUCCESS);
130: }

132: /*@
133:   PetscBagRegisterRealArray - add a `PetscReal` array to a `PetscBag`

135:   Logically Collective

137:   Input Parameters:
138: + bag   - the bag of values
139: . addr  - location of real array in struct, for example `&params->d`
140: . msize - number of entries in the array
141: . name  - name of the array
142: - help  - longer string with more information about the value

144:   Level: beginner

146: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
147:           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
148:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
149: @*/
150: PetscErrorCode PetscBagRegisterRealArray(PetscBag bag, void *addr, PetscInt msize, const char *name, const char *help)
151: {
152:   PetscBagItem item;
153:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
154:   PetscReal   *values = (PetscReal *)addr;
155:   PetscBool    printhelp;
156:   PetscInt     i, tmp = msize;

158:   PetscFunctionBegin;
159:   PetscAssertPointer(bag, 1);
160:   PetscAssertPointer(addr, 2);
161:   PetscAssertPointer(name, 4);
162:   PetscAssertPointer(help, 5);
163:   nname[0] = '-';
164:   nname[1] = 0;
165:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
166:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
167:   if (printhelp) {
168:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <", bag->bagprefix ? bag->bagprefix : "", name));
169:     for (i = 0; i < msize; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "%g ", (double)values[i]));
170:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, ">: %s \n", help));
171:   }
172:   PetscCall(PetscOptionsGetRealArray(NULL, bag->bagprefix, nname, values, &tmp, NULL));

174:   PetscCall(PetscNew(&item));
175:   item->dtype  = PETSC_REAL;
176:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
177:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
178:   item->next  = NULL;
179:   item->msize = msize;
180:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
181:   PetscFunctionReturn(PETSC_SUCCESS);
182: }

184: /*@
185:   PetscBagRegisterInt - add a `PetscInt` value to a `PetscBag`

187:   Logically Collective

189:   Input Parameters:
190: + bag      - the bag of values
191: . addr     - location of integer in struct, for example `&params->i`
192: . mdefault - the initial value
193: . name     - name of the integer
194: - help     - longer string with more information about the value

196:   Level: beginner

198: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
199:           `PetscBagRegisterInt64()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
200:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
201: @*/
202: PetscErrorCode PetscBagRegisterInt(PetscBag bag, void *addr, PetscInt mdefault, const char *name, const char *help)
203: {
204:   PetscBagItem item;
205:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
206:   PetscBool    printhelp;

208:   PetscFunctionBegin;
209:   PetscAssertPointer(bag, 1);
210:   PetscAssertPointer(addr, 2);
211:   PetscAssertPointer(name, 4);
212:   PetscAssertPointer(help, 5);
213:   nname[0] = '-';
214:   nname[1] = 0;
215:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
216:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
217:   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%" PetscInt_FMT ">: %s \n", bag->bagprefix ? bag->bagprefix : "", name, mdefault, help));
218:   PetscCall(PetscOptionsGetInt(NULL, bag->bagprefix, nname, &mdefault, NULL));

220:   PetscCall(PetscNew(&item));
221:   item->dtype  = PETSC_INT;
222:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
223:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
224:   item->next        = NULL;
225:   item->msize       = 1;
226:   *(PetscInt *)addr = mdefault;
227:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
228:   PetscFunctionReturn(PETSC_SUCCESS);
229: }

231: /*@
232:   PetscBagRegisterInt64 - add a `PetscInt64` value to a `PetscBag`

234:   Logically Collective

236:   Input Parameters:
237: + bag      - the bag of values
238: . addr     - location of integer in struct, for example `&params->i`
239: . mdefault - the initial value
240: . name     - name of the integer
241: - help     - longer string with more information about the value

243:   Level: beginner

245: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
246:           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
247:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
248: @*/
249: PetscErrorCode PetscBagRegisterInt64(PetscBag bag, void *addr, PetscInt64 mdefault, const char *name, const char *help)
250: {
251:   PetscBagItem item;
252:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
253:   PetscBool    printhelp;
254:   PetscInt     odefault;
255:   PetscBool    flg;

257:   PetscFunctionBegin;
258:   nname[0] = '-';
259:   nname[1] = 0;

261:   PetscCall(PetscIntCast(mdefault, &odefault));
262:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
263:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
264:   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%" PetscInt_FMT ">: %s \n", bag->bagprefix ? bag->bagprefix : "", name, odefault, help));
265:   PetscCall(PetscOptionsGetInt(NULL, bag->bagprefix, nname, &odefault, &flg));
266:   if (flg) mdefault = odefault;

268:   PetscCall(PetscNew(&item));
269:   item->dtype  = PETSC_INT;
270:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
271:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
272:   item->next          = NULL;
273:   item->msize         = 1;
274:   *(PetscInt64 *)addr = mdefault;
275:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
276:   PetscFunctionReturn(PETSC_SUCCESS);
277: }

279: /*@
280:   PetscBagRegisterBoolArray - add a n `PetscBool` values to a `PetscBag`

282:   Logically Collective

284:   Input Parameters:
285: + bag   - the bag of values
286: . addr  - location of boolean array in struct, for example `&params->b`
287: . msize - number of entries in array
288: . name  - name of the boolean array
289: - help  - longer string with more information about the value

291:   Level: beginner

293: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
294:           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
295:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
296: @*/
297: PetscErrorCode PetscBagRegisterBoolArray(PetscBag bag, void *addr, PetscInt msize, const char *name, const char *help)
298: {
299:   PetscBagItem item;
300:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
301:   PetscBool   *values = (PetscBool *)addr;
302:   PetscBool    printhelp;
303:   PetscInt     i, tmp = msize;

305:   PetscFunctionBegin;
306:   PetscAssertPointer(bag, 1);
307:   PetscAssertPointer(addr, 2);
308:   PetscAssertPointer(name, 4);
309:   PetscAssertPointer(help, 5);
310:   nname[0] = '-';
311:   nname[1] = 0;
312:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
313:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
314:   if (printhelp) {
315:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <", bag->bagprefix ? bag->bagprefix : "", name));
316:     for (i = 0; i < msize; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "%" PetscInt_FMT " ", (PetscInt)values[i]));
317:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, ">: %s \n", help));
318:   }
319:   PetscCall(PetscOptionsGetBoolArray(NULL, bag->bagprefix, nname, values, &tmp, NULL));

321:   PetscCall(PetscNew(&item));
322:   item->dtype  = PETSC_BOOL;
323:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
324:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
325:   item->next  = NULL;
326:   item->msize = msize;
327:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
328:   PetscFunctionReturn(PETSC_SUCCESS);
329: }

331: /*@
332:   PetscBagRegisterString - add a string value to a `PetscBag`

334:   Logically Collective

336:   Input Parameters:
337: + bag      - the bag of values
338: . addr     - location of start of string in struct, for example `&params->mystring`
339: . msize    - length of the string space in the struct
340: . mdefault - the initial value
341: . name     - name of the string
342: - help     - longer string with more information about the value

344:   Level: beginner

346:   Note:
347:   The struct must have the field char mystring[`msize`]; not char *mystring

349: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
350:           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
351:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
352: @*/
353: PetscErrorCode PetscBagRegisterString(PetscBag bag, void *addr, PetscInt msize, const char *mdefault, const char *name, const char *help) PeNS
354: {
355:   PetscBagItem item;
356:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
357:   PetscBool    printhelp;

359:   PetscFunctionBegin;
360:   PetscAssertPointer(bag, 1);
361:   PetscAssertPointer(addr, 2);
362:   PetscAssertPointer(mdefault, 4);
363:   PetscAssertPointer(name, 5);
364:   PetscAssertPointer(help, 6);
365:   nname[0] = '-';
366:   nname[1] = 0;
367:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
368:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
369:   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%s>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, mdefault, help));

371:   PetscCall(PetscNew(&item));
372:   item->dtype  = PETSC_CHAR;
373:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
374:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
375:   item->next  = NULL;
376:   item->msize = msize;
377:   if (mdefault != (char *)addr) PetscCall(PetscStrncpy((char *)addr, mdefault, msize - 1));
378:   PetscCall(PetscOptionsGetString(NULL, bag->bagprefix, nname, (char *)addr, msize, NULL));
379:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
380:   PetscFunctionReturn(PETSC_SUCCESS);
381: }

383: /*@
384:   PetscBagRegisterReal - add a `PetscReal` value to a `PetscBag`

386:   Logically Collective

388:   Input Parameters:
389: + bag      - the bag of values
390: . addr     - location of `PetscReal` in struct, for example `&params->r`
391: . mdefault - the initial value
392: . name     - name of the variable
393: - help     - longer string with more information about the value

395:   Level: beginner

397: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
398:           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
399:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
400: @*/
401: PetscErrorCode PetscBagRegisterReal(PetscBag bag, void *addr, PetscReal mdefault, const char *name, const char *help)
402: {
403:   PetscBagItem item;
404:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
405:   PetscBool    printhelp;

407:   PetscFunctionBegin;
408:   PetscAssertPointer(bag, 1);
409:   PetscAssertPointer(addr, 2);
410:   PetscAssertPointer(name, 4);
411:   PetscAssertPointer(help, 5);
412:   nname[0] = '-';
413:   nname[1] = 0;
414:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
415:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
416:   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%g>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, (double)mdefault, help));
417:   PetscCall(PetscOptionsGetReal(NULL, bag->bagprefix, nname, &mdefault, NULL));

419:   PetscCall(PetscNew(&item));
420:   item->dtype  = PETSC_REAL;
421:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
422:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
423:   item->next         = NULL;
424:   item->msize        = 1;
425:   *(PetscReal *)addr = mdefault;
426:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
427:   PetscFunctionReturn(PETSC_SUCCESS);
428: }

430: /*@
431:   PetscBagRegisterScalar - add a `PetscScalar` value to a `PetscBag`

433:   Logically Collective

435:   Input Parameters:
436: + bag      - the bag of values
437: . addr     - location of `PetscScalar` in struct, for example `&params->c`
438: . mdefault - the initial value
439: . name     - name of the variable
440: - help     - longer string with more information about the value

442:   Level: beginner

444: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
445:           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagSetFromOptions()`,
446:           `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
447: @*/
448: PetscErrorCode PetscBagRegisterScalar(PetscBag bag, void *addr, PetscScalar mdefault, const char *name, const char *help)
449: {
450:   PetscBagItem item;
451:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
452:   PetscBool    printhelp;

454:   PetscFunctionBegin;
455:   PetscAssertPointer(bag, 1);
456:   PetscAssertPointer(addr, 2);
457:   PetscAssertPointer(name, 4);
458:   PetscAssertPointer(help, 5);
459:   nname[0] = '-';
460:   nname[1] = 0;
461:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
462:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
463:   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%g + %gi>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, (double)PetscRealPart(mdefault), (double)PetscImaginaryPart(mdefault), help));
464:   PetscCall(PetscOptionsGetScalar(NULL, bag->bagprefix, nname, &mdefault, NULL));

466:   PetscCall(PetscNew(&item));
467:   item->dtype  = PETSC_SCALAR;
468:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
469:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
470:   item->next           = NULL;
471:   item->msize          = 1;
472:   *(PetscScalar *)addr = mdefault;
473:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
474:   PetscFunctionReturn(PETSC_SUCCESS);
475: }

477: /*@
478:   PetscBagRegisterBool - add a `PetscBool` to a `PetscBag`

480:   Logically Collective

482:   Input Parameters:
483: + bag      - the bag of values
484: . addr     - location of `PetscBool` in struct, for example `&params->b`
485: . mdefault - the initial value, either `PETSC_FALSE` or `PETSC_TRUE`
486: . name     - name of the variable
487: - help     - longer string with more information about the value

489:   Level: beginner

491: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
492:           `PetscBagRegisterInt()`, `PetscBagRegisterScalar()`,
493:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
494: @*/
495: PetscErrorCode PetscBagRegisterBool(PetscBag bag, void *addr, PetscBool mdefault, const char *name, const char *help)
496: {
497:   PetscBagItem item;
498:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
499:   PetscBool    printhelp;

501:   PetscFunctionBegin;
502:   PetscAssertPointer(bag, 1);
503:   PetscAssertPointer(addr, 2);
504:   PetscAssertPointer(name, 4);
505:   PetscAssertPointer(help, 5);
506:   nname[0] = '-';
507:   nname[1] = 0;
508:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
509:   PetscCall(PetscOptionsHelpPrintable_Internal(NULL, "Bag", &printhelp));
510:   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%s>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, PetscBools[mdefault], help));
511:   PetscCall(PetscOptionsGetBool(NULL, bag->bagprefix, nname, &mdefault, NULL));

513:   PetscCall(PetscNew(&item));
514:   item->dtype  = PETSC_BOOL;
515:   item->offset = (PetscInt)(((size_t)addr) - ((size_t)bag));
516:   PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help);
517:   item->next         = NULL;
518:   item->msize        = 1;
519:   *(PetscBool *)addr = mdefault;
520:   PetscCall(PetscBagRegister_Private(bag, item, name, help));
521:   PetscFunctionReturn(PETSC_SUCCESS);
522: }

524: /*@
525:   PetscBagDestroy - Destroys a `PetscBag`

527:   Collective

529:   Input Parameter:
530: . bag - the bag of values

532:   Level: beginner

534: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
535:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
536:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
537: @*/
538: PetscErrorCode PetscBagDestroy(PetscBag *bag)
539: {
540:   PetscBagItem nitem;

542:   PetscFunctionBegin;
543:   if (!*bag) PetscFunctionReturn(PETSC_SUCCESS);
544:   PetscAssertPointer(*bag, 1);
545:   nitem = (*bag)->bagitems;
546:   while (nitem) {
547:     PetscBagItem item = nitem->next;

549:     PetscCall(PetscStrArrayDestroy(&nitem->list));
550:     PetscCall(PetscFree(nitem));
551:     nitem = item;
552:   }
553:   PetscCall(PetscFree((*bag)->bagprefix));
554:   PetscCall(PetscFree(*bag));
555:   PetscFunctionReturn(PETSC_SUCCESS);
556: }

558: /*@
559:   PetscBagSetFromOptions - Allows setting entries to a `PetscBag` using the options database

561:   Collective

563:   Input Parameter:
564: . bag - the bag of values

566:   Level: beginner

568:   Note:
569:   The options database keys for the entries are of the form `-[bagprefix]_name value`

571: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagDestroy()`, `PetscBagLoad()`, `PetscBagGetData()`,
572:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
573:           `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagRegisterEnum()`
574: @*/
575: PetscErrorCode PetscBagSetFromOptions(PetscBag bag)
576: {
577:   PetscBagItem nitem = bag->bagitems;
578:   char         name[PETSC_BAG_NAME_LENGTH + 1], helpname[PETSC_BAG_NAME_LENGTH + PETSC_BAG_HELP_LENGTH + 3];
579:   PetscInt     n;

581:   PetscFunctionBegin;
582:   PetscAssertPointer(bag, 1);
583:   PetscCall(PetscStrncpy(helpname, bag->bagname, sizeof(helpname)));
584:   PetscCall(PetscStrlcat(helpname, " ", sizeof(helpname)));
585:   PetscCall(PetscStrlcat(helpname, bag->baghelp, sizeof(helpname)));
586:   PetscOptionsBegin(bag->bagcomm, bag->bagprefix, helpname, "Bag");
587:   while (nitem) {
588:     name[0] = '-';
589:     name[1] = 0;
590:     PetscCall(PetscStrlcat(name, nitem->name, sizeof(name)));
591:     if (nitem->dtype == PETSC_CHAR) { /* special handling for fortran required? [due to space padding vs null termination] */
592:       char *value = ((char *)bag) + nitem->offset;
593:       PetscCall(PetscOptionsString(name, nitem->help, "", value, value, nitem->msize, NULL));
594:     } else if (nitem->dtype == PETSC_REAL) {
595:       PetscReal *value = (PetscReal *)(((char *)bag) + nitem->offset);
596:       if (nitem->msize == 1) PetscCall(PetscOptionsReal(name, nitem->help, "", *value, value, NULL));
597:       else {
598:         n = nitem->msize;
599:         PetscCall(PetscOptionsRealArray(name, nitem->help, "", value, &n, NULL));
600:       }
601:     } else if (nitem->dtype == PETSC_SCALAR) {
602:       PetscScalar *value = (PetscScalar *)(((char *)bag) + nitem->offset);
603:       PetscCall(PetscOptionsScalar(name, nitem->help, "", *value, value, NULL));
604:     } else if (nitem->dtype == PETSC_INT) {
605:       PetscInt *value = (PetscInt *)(((char *)bag) + nitem->offset);
606:       if (nitem->msize == 1) PetscCall(PetscOptionsInt(name, nitem->help, "", *value, value, NULL));
607:       else {
608:         n = nitem->msize;
609:         PetscCall(PetscOptionsIntArray(name, nitem->help, "", value, &n, NULL));
610:       }
611:     } else if (nitem->dtype == PETSC_ENUM) {
612:       PetscEnum *value = (PetscEnum *)(((char *)bag) + nitem->offset);
613:       PetscInt   i     = 0;
614:       while (nitem->list[i++]);
615:       PetscCall(PetscOptionsEnum(name, nitem->help, nitem->list[i - 3], (const char *const *)nitem->list, *value, value, NULL));
616:     } else if (nitem->dtype == PETSC_BOOL) {
617:       PetscBool *value = (PetscBool *)(((char *)bag) + nitem->offset);
618:       if (nitem->msize == 1) PetscCall(PetscOptionsBool(name, nitem->help, "", *value, value, NULL));
619:       else {
620:         n = nitem->msize;
621:         PetscCall(PetscOptionsBoolArray(name, nitem->help, "", value, &n, NULL));
622:       }
623:     }
624:     nitem = nitem->next;
625:   }
626:   PetscOptionsEnd();
627:   PetscFunctionReturn(PETSC_SUCCESS);
628: }

630: /*@
631:   PetscBagView - Views a bag of values as either ASCII text or a binary file

633:   Collective

635:   Input Parameters:
636: + bag  - the bag of values
637: - view - location to view the values

639:   Level: beginner

641:   Note:
642:   Currently PETSc bags saved in a binary file can only be read back
643:   in on a machine with the same binary format.

645: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagDestroy()`, `PetscBagLoad()`, `PetscBagGetData()`,
646:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`, `PetscBagRegisterEnum()`,
647:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`
648: @*/
649: PetscErrorCode PetscBagView(PetscBag bag, PetscViewer view)
650: {
651:   PetscBool    isascii, isbinary;
652:   PetscBagItem nitem = bag->bagitems;

654:   PetscFunctionBegin;
655:   PetscAssertPointer(bag, 1);
657:   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
658:   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERBINARY, &isbinary));
659:   if (isascii) {
660:     if (bag->bagprefix) {
661:       PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object:  %s (%s) %s\n", bag->bagname, bag->bagprefix, bag->baghelp));
662:     } else {
663:       PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object:  %s %s\n", bag->bagname, bag->baghelp));
664:     }
665:     while (nitem) {
666:       if (nitem->dtype == PETSC_CHAR) {
667:         char *value             = ((char *)bag) + nitem->offset;
668:         char  tmp               = value[nitem->msize - 1]; /* special handling for fortran chars without null terminator */
669:         value[nitem->msize - 1] = 0;
670:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = %s; %s\n", nitem->name, value, nitem->help));
671:         value[nitem->msize - 1] = tmp;
672:       } else if (nitem->dtype == PETSC_REAL) {
673:         PetscReal *value = (PetscReal *)(((char *)bag) + nitem->offset);
674:         PetscInt   i;
675:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
676:         for (i = 0; i < nitem->msize; i++) PetscCall(PetscViewerASCIIPrintf(view, "%g ", (double)value[i]));
677:         PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help));
678:       } else if (nitem->dtype == PETSC_SCALAR) {
679:         PetscScalar value = *(PetscScalar *)(((char *)bag) + nitem->offset);
680:         if ((double)PetscImaginaryPart(value)) {
681:           PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g + %gi; %s\n", nitem->name, (double)PetscRealPart(value), (double)PetscImaginaryPart(value), nitem->help));
682:         } else {
683:           PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g; %s\n", nitem->name, (double)PetscRealPart(value), nitem->help));
684:         }
685:       } else if (nitem->dtype == PETSC_INT) {
686:         PetscInt i, *value = (PetscInt *)(((char *)bag) + nitem->offset);
687:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
688:         for (i = 0; i < nitem->msize; i++) PetscCall(PetscViewerASCIIPrintf(view, "%" PetscInt_FMT " ", value[i]));
689:         PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help));
690:       } else if (nitem->dtype == PETSC_BOOL) {
691:         PetscBool *value = (PetscBool *)(((char *)bag) + nitem->offset);
692:         PetscInt   i;
693:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
694:         for (i = 0; i < nitem->msize; i++) {
695:           /* stdbool.h defines true=1 and false=0, but non-conformant Fortran compilers define .true.=0xff (-1 if signed, 255 if unsigned).
696:              with the checks for either PETSC_FALSE or PETSC_TRUE 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:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = %s; (%s) %s\n", nitem->name, nitem->list[value], nitem->list[i - 3], nitem->help));
706:       }
707:       nitem = nitem->next;
708:     }
709:   } else if (isbinary) {
710:     PetscInt          classid           = PETSC_BAG_FILE_CLASSID, dtype;
711:     PetscInt          deprecatedbagsize = 0;
712:     PetscViewerFormat format;
713:     PetscCall(PetscViewerBinaryWrite(view, &classid, 1, PETSC_INT));
714:     PetscCall(PetscViewerBinaryWrite(view, &deprecatedbagsize, 1, PETSC_INT));
715:     PetscCall(PetscViewerBinaryWrite(view, &bag->count, 1, PETSC_INT));
716:     PetscCall(PetscViewerBinaryWrite(view, bag->bagname, PETSC_BAG_NAME_LENGTH, PETSC_CHAR));
717:     PetscCall(PetscViewerBinaryWrite(view, bag->baghelp, PETSC_BAG_HELP_LENGTH, PETSC_CHAR));
718:     while (nitem) {
719:       PetscCall(PetscViewerBinaryWrite(view, &nitem->offset, 1, PETSC_INT));
720:       dtype = (PetscInt)nitem->dtype;
721:       PetscCall(PetscViewerBinaryWrite(view, &dtype, 1, PETSC_INT));
722:       PetscCall(PetscViewerBinaryWrite(view, nitem->name, PETSC_BAG_NAME_LENGTH, PETSC_CHAR));
723:       PetscCall(PetscViewerBinaryWrite(view, nitem->help, PETSC_BAG_HELP_LENGTH, PETSC_CHAR));
724:       PetscCall(PetscViewerBinaryWrite(view, &nitem->msize, 1, PETSC_INT));

726:       PetscCall(PetscViewerBinaryWrite(view, (char *)bag + nitem->offset, nitem->msize, nitem->dtype));
727:       if (dtype == PETSC_ENUM) PetscCall(PetscViewerBinaryWriteStringArray(view, (const char *const *)nitem->list));
728:       nitem = nitem->next;
729:     }
730:     PetscCall(PetscViewerGetFormat(view, &format));
731:     if (format == PETSC_VIEWER_BINARY_MATLAB) {
732:       MPI_Comm comm;
733:       FILE    *info;
734:       PetscCall(PetscObjectGetComm((PetscObject)view, &comm));
735:       PetscCall(PetscViewerBinaryGetInfoPointer(view, &info));
736:       PetscCall(PetscFPrintf(comm, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n"));
737:       PetscCall(PetscFPrintf(comm, info, "#$$ Set.%s = PetscBinaryRead(fd);\n", bag->bagname));
738:       PetscCall(PetscFPrintf(comm, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n"));
739:     }
740:   }
741:   PetscFunctionReturn(PETSC_SUCCESS);
742: }

744: /*@
745:   PetscBagViewFromOptions - Processes command line options to determine if/how a `PetscBag` is to be viewed.

747:   Collective

749:   Input Parameters:
750: + bag  - the object
751: . bobj - optional other object that provides prefix (if `NULL` then the prefix in obj is used)
752: - name - option to activate viewing

754:   Options Database Key:
755: . -name viewer_specification - See `PetscOptionsCreateViewer()` for the values of `viewer_specification`

757:   Level: intermediate

759:   Note:
760:   This checks the options database, creates the viewer on-the-fly, uses it and then destroys it. Hence it should not be called in heavily used routines,
761:   rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.

763: .seealso: `PetscBagCreate()`, `PetscBag`, `PetscViewer`, `PetscBagView()`, `PetscObjectViewFromOptions()`, `PetscOptionsCreateViewer()`
764: @*/
765: PetscErrorCode PetscBagViewFromOptions(PetscBag bag, PetscObject bobj, const char name[])
766: {
767:   static PetscBool  incall = PETSC_FALSE;
768:   PetscViewer       viewer;
769:   PetscViewerFormat format;
770:   const char       *prefix, *bprefix = NULL;
771:   PetscBool         flg;

773:   PetscFunctionBegin;
774:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
775:   incall = PETSC_TRUE;
776:   PetscAssertPointer(bag, 1);
777:   if (bobj) PetscCall(PetscObjectGetOptionsPrefix(bobj, &bprefix));
778:   prefix = bobj ? bprefix : bag->bagprefix;
779:   PetscCall(PetscOptionsCreateViewer(bag->bagcomm, NULL, prefix, name, &viewer, &format, &flg));
780:   if (flg) {
781:     PetscCall(PetscViewerPushFormat(viewer, format));
782:     PetscCall(PetscBagView(bag, viewer));
783:     PetscCall(PetscViewerFlush(viewer));
784:     PetscCall(PetscViewerPopFormat(viewer));
785:     PetscCall(PetscViewerDestroy(&viewer));
786:   }
787:   incall = PETSC_FALSE;
788:   PetscFunctionReturn(PETSC_SUCCESS);
789: }

791: /*@
792:   PetscBagLoad - Loads a bag of values from a binary file

794:   Collective

796:   Input Parameters:
797: + view - file to load values from
798: - bag  - the bag of values

800:   Level: beginner

802:   Note:
803:   You must have created and registered all the fields in the bag before loading into it. This only loads values.

805: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagDestroy()`, `PetscBagView()`, `PetscBagGetData()`,
806:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
807:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
808: @*/
809: PetscErrorCode PetscBagLoad(PetscViewer view, PetscBag bag)
810: {
811:   PetscBool    isbinary;
812:   PetscInt     classid, bagcount, dtype, msize, offset, deprecatedbagsize;
813:   char         name[PETSC_BAG_NAME_LENGTH], help[PETSC_BAG_HELP_LENGTH], **list;
814:   PetscBagItem nitem;
815:   MPI_Comm     comm;
816:   PetscMPIInt  flag;

818:   PetscFunctionBegin;
820:   PetscAssertPointer(bag, 2);
821:   PetscCall(PetscObjectGetComm((PetscObject)view, &comm));
822:   PetscCallMPI(MPI_Comm_compare(comm, bag->bagcomm, &flag));
823:   PetscCheck(flag == MPI_CONGRUENT || flag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "Different communicators in the viewer and bag");
824:   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERBINARY, &isbinary));
825:   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for this viewer type");

827:   PetscCall(PetscViewerBinaryRead(view, &classid, 1, NULL, PETSC_INT));
828:   PetscCheck(classid == PETSC_BAG_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not PetscBag next in binary file");
829:   PetscCall(PetscViewerBinaryRead(view, &deprecatedbagsize, 1, NULL, PETSC_INT));
830:   PetscCall(PetscViewerBinaryRead(view, &bagcount, 1, NULL, PETSC_INT));
831:   PetscCheck(bagcount == bag->count, comm, PETSC_ERR_ARG_INCOMP, "Bag in file has different number of entries %" PetscInt_FMT " then passed in bag %" PetscInt_FMT, bagcount, bag->count);
832:   PetscCall(PetscViewerBinaryRead(view, bag->bagname, PETSC_BAG_NAME_LENGTH, NULL, PETSC_CHAR));
833:   PetscCall(PetscViewerBinaryRead(view, bag->baghelp, PETSC_BAG_HELP_LENGTH, NULL, PETSC_CHAR));

835:   nitem = bag->bagitems;
836:   for (PetscInt i = 0; i < bagcount; i++) {
837:     PetscCall(PetscViewerBinaryRead(view, &offset, 1, NULL, PETSC_INT));
838:     /* ignore the offset in the file */
839:     PetscCall(PetscViewerBinaryRead(view, &dtype, 1, NULL, PETSC_INT));
840:     PetscCall(PetscViewerBinaryRead(view, name, PETSC_BAG_NAME_LENGTH, NULL, PETSC_CHAR));
841:     PetscCall(PetscViewerBinaryRead(view, help, PETSC_BAG_HELP_LENGTH, NULL, PETSC_CHAR));
842:     PetscCall(PetscViewerBinaryRead(view, &msize, 1, NULL, PETSC_INT));

844:     if (dtype == (PetscInt)PETSC_CHAR) {
845:       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_CHAR));
846:     } else if (dtype == (PetscInt)PETSC_REAL) {
847:       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_REAL));
848:     } else if (dtype == (PetscInt)PETSC_SCALAR) {
849:       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, 1, NULL, PETSC_SCALAR));
850:     } else if (dtype == (PetscInt)PETSC_INT) {
851:       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_INT));
852:     } else if (dtype == (PetscInt)PETSC_BOOL) {
853:       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_BOOL));
854:     } else if (dtype == (PetscInt)PETSC_ENUM) {
855:       PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, 1, NULL, PETSC_ENUM));
856:       PetscCall(PetscViewerBinaryReadStringArray(view, &list));
857:       /* don't need to save list because it is already registered in the bag */
858:       PetscCall(PetscFree(list));
859:     }
860:     nitem = nitem->next;
861:   }
862:   PetscFunctionReturn(PETSC_SUCCESS);
863: }

865: /*@
866:   PetscBagCreate - Create a bag of values. A `PetscBag` is a representation of a C struct that can be saved to and read from files,
867:   can have values set from the options database

869:   Collective

871:   Input Parameters:
872: + comm    - communicator to share bag
873: - bagsize - size of the C structure holding the values, for example `sizeof(mystruct)`

875:   Output Parameter:
876: . bag - the bag of values

878:   Level: intermediate

880:   Notes:
881:   After creating the bag, for each entry in the C struct call the appropriate `PetscBagRegisterInt()` etc to define the C structs layout

883:   The size of the struct must be small enough to fit in a `PetscInt`; by default
884:   `PetscInt` is 4 bytes; this means a bag cannot be larger than 2 gigabytes in length.
885:   The warning about casting to a shorter length can be ignored below unless your struct is too large

887: .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
888:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
889:           `PetscBagSetFromOptions()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
890: @*/
891: PetscErrorCode PetscBagCreate(MPI_Comm comm, size_t bagsize, PetscBag *bag)
892: {
893:   const size_t totalsize = bagsize + sizeof(struct _n_PetscBag) + sizeof(PetscScalar);

895:   PetscFunctionBegin;
896:   PetscAssertPointer(bag, 3);

898:   PetscCall(PetscInfo(NULL, "Creating Bag with total size %d\n", (int)totalsize));
899:   PetscCall(PetscCalloc(totalsize, bag));
900:   PetscCall(PetscIntCast(totalsize, &(*bag)->bagsize));
901:   (*bag)->bagcomm        = comm;
902:   (*bag)->bagprefix      = NULL;
903:   (*bag)->structlocation = (void *)(((char *)(*bag)) + sizeof(PetscScalar) * (sizeof(struct _n_PetscBag) / sizeof(PetscScalar)) + sizeof(PetscScalar));
904:   PetscFunctionReturn(PETSC_SUCCESS);
905: }

907: /*@
908:   PetscBagSetName - Sets the name of a bag of values

910:   Not Collective

912:   Level: intermediate

914:   Input Parameters:
915: + bag  - the bag of values
916: . name - the name assigned to the bag
917: - help - help message for bag

919: .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
920:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
921:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
922: @*/
923: PetscErrorCode PetscBagSetName(PetscBag bag, const char name[], const char help[])
924: {
925:   PetscFunctionBegin;
926:   PetscAssertPointer(bag, 1);
927:   PetscAssertPointer(name, 2);
928:   PetscAssertPointer(help, 3);
929:   PetscCall(PetscStrncpy(bag->bagname, name, PETSC_BAG_NAME_LENGTH - 1));
930:   PetscCall(PetscStrncpy(bag->baghelp, help, PETSC_BAG_HELP_LENGTH - 1));
931:   PetscFunctionReturn(PETSC_SUCCESS);
932: }

934: /*@
935:   PetscBagGetName - Gets the name of a bag of values

937:   Not Collective

939:   Level: intermediate

941:   Input Parameter:
942: . bag - the bag of values

944:   Output Parameter:
945: . name - the name assigned to the bag

947: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
948:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
949:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
950: @*/
951: PetscErrorCode PetscBagGetName(PetscBag bag, const char *name[])
952: {
953:   PetscFunctionBegin;
954:   PetscAssertPointer(bag, 1);
955:   PetscAssertPointer(name, 2);
956:   *name = bag->bagname;
957:   PetscFunctionReturn(PETSC_SUCCESS);
958: }

960: /*@
961:   PetscBagGetData - Gives back the user - access to memory that
962:   can be used for storing user-data-structure

964:   Not Collective

966:   Input Parameter:
967: . bag - the bag of values

969:   Output Parameter:
970: . 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
971:          defining the bag

973:   Level: intermediate

975: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`,
976:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
977:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
978: @*/
979: PetscErrorCode PetscBagGetData(PetscBag bag, PetscCtxRt data)
980: {
981:   PetscFunctionBegin;
982:   PetscAssertPointer(bag, 1);
983:   PetscAssertPointer(data, 2);
984:   *(void **)data = bag->structlocation;
985:   PetscFunctionReturn(PETSC_SUCCESS);
986: }

988: /*@
989:   PetscBagSetOptionsPrefix - Sets the prefix used for searching for all
990:   `PetscBag` items in the options database.

992:   Logically Collective

994:   Level: intermediate

996:   Input Parameters:
997: + bag - the bag of values
998: - pre - the prefix to prepend all Bag item names with.

1000:   Note:
1001:   Must be called prior to registering any of the bag items.

1003: .seealso: `PetscBag`, `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
1004:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
1005: @*/
1006: PetscErrorCode PetscBagSetOptionsPrefix(PetscBag bag, const char pre[])
1007: {
1008:   PetscFunctionBegin;
1009:   PetscAssertPointer(bag, 1);
1010:   if (pre) {
1011:     PetscAssertPointer(pre, 2);
1012:     PetscCheck(pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen");
1013:     PetscCall(PetscFree(bag->bagprefix));
1014:     PetscCall(PetscStrallocpy(pre, &bag->bagprefix));
1015:   } else PetscCall(PetscFree(bag->bagprefix));
1016:   PetscFunctionReturn(PETSC_SUCCESS);
1017: }

1019: /*@
1020:   PetscBagGetNames - Get the names of all entries in the bag

1022:   Not Collective

1024:   Input Parameter:
1025: . bag - the bag of values

1027:   Output Parameter:
1028: . names - pass in an array of char pointers to hold the names. The array must be as long as the number of items in the bag.

1030:   Level: intermediate

1032: .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagSetName()`, `PetscBagCreate()`, `PetscBagGetData()`,
1033:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`, `PetscBagRegisterEnum()`
1034: @*/
1035: PetscErrorCode PetscBagGetNames(PetscBag bag, const char *names[])
1036: {
1037:   PetscBagItem nitem = bag->bagitems;

1039:   PetscFunctionBegin;
1040:   PetscAssertPointer(bag, 1);
1041:   PetscAssertPointer(names, 2);
1042:   for (PetscInt n = 0; nitem; ++n, nitem = nitem->next) names[n] = nitem->name;
1043:   PetscFunctionReturn(PETSC_SUCCESS);
1044: }