Actual source code: bag.c

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

  5: /*
  6:       Adds item to the linked list in a bag
  7: */
  8: static PetscErrorCode PetscBagRegister_Private(PetscBag bag, PetscBagItem item, const char *name, const char *help)
  9: {
 10:   PetscFunctionBegin;
 11:   PetscCall(PetscStrncpy(item->name, name, PETSC_BAG_NAME_LENGTH - 1));
 12:   PetscCall(PetscStrncpy(item->help, help, PETSC_BAG_HELP_LENGTH - 1));
 13:   if (bag->bagitems) {
 14:     PetscBagItem nitem = bag->bagitems;

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

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

 26:   Logically Collective

 28:   Input Parameters:
 29: + bag      - the bag of values
 30: . addr     - location of enum in struct, for example `&params->dt`
 31: . list     - array of strings containing names of enum values followed by enum name followed by enum prefix
 32: . mdefault - the initial value, cast with (`PetscEnum`)
 33: . name     - the name of the item
 34: - help     - longer string with more information about the value

 36:   Level: beginner

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

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

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

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

 84:   Logically Collective

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

 93:   Level: beginner

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

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

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

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

136:   Logically Collective

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

145:   Level: beginner

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

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

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

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

188:   Logically Collective

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

197:   Level: beginner

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

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

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

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

235:   Logically Collective

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

244:   Level: beginner

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

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

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

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

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

283:   Logically Collective

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

292:   Level: beginner

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

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

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

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

335:   Logically Collective

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

345:   Level: beginner

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

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

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

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

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

387:   Logically Collective

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

396:   Level: beginner

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

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

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

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

434:   Logically Collective

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

443:   Level: beginner

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

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

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

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

481:   Logically Collective

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

490:   Level: beginner

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

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

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

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

528:   Collective

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

533:   Level: beginner

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

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

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

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

562:   Collective

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

567:   Level: beginner

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

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

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

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

634:   Collective

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

640:   Level: beginner

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

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

655:   PetscFunctionBegin;
656:   PetscAssertPointer(bag, 1);
658:   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
659:   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERBINARY, &isbinary));
660:   if (isascii) {
661:     if (bag->bagprefix) {
662:       PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object:  %s (%s) %s\n", bag->bagname, bag->bagprefix, bag->baghelp));
663:     } else {
664:       PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object:  %s %s\n", bag->bagname, bag->baghelp));
665:     }
666:     while (nitem) {
667:       if (nitem->dtype == PETSC_CHAR) {
668:         char *value             = ((char *)bag) + nitem->offset;
669:         char  tmp               = value[nitem->msize - 1]; /* special handling for fortran chars without null terminator */
670:         value[nitem->msize - 1] = 0;
671:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = %s; %s\n", nitem->name, value, nitem->help));
672:         value[nitem->msize - 1] = tmp;
673:       } else if (nitem->dtype == PETSC_REAL) {
674:         PetscReal *value = (PetscReal *)(((char *)bag) + nitem->offset);
675:         PetscInt   i;
676:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
677:         for (i = 0; i < nitem->msize; i++) PetscCall(PetscViewerASCIIPrintf(view, "%g ", (double)value[i]));
678:         PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help));
679:       } else if (nitem->dtype == PETSC_SCALAR) {
680:         PetscScalar value = *(PetscScalar *)(((char *)bag) + nitem->offset);
681:         if ((double)PetscImaginaryPart(value)) {
682:           PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g + %gi; %s\n", nitem->name, (double)PetscRealPart(value), (double)PetscImaginaryPart(value), nitem->help));
683:         } else {
684:           PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g; %s\n", nitem->name, (double)PetscRealPart(value), nitem->help));
685:         }
686:       } else if (nitem->dtype == PETSC_INT) {
687:         PetscInt i, *value = (PetscInt *)(((char *)bag) + nitem->offset);
688:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
689:         for (i = 0; i < nitem->msize; i++) PetscCall(PetscViewerASCIIPrintf(view, "%" PetscInt_FMT " ", value[i]));
690:         PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help));
691:       } else if (nitem->dtype == PETSC_BOOL) {
692:         PetscBool *value = (PetscBool *)(((char *)bag) + nitem->offset);
693:         PetscInt   i;
694:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
695:         for (i = 0; i < nitem->msize; i++) {
696:           /* stdbool.h defines true=1 and false=0, but non-conformant Fortran compilers define .true.=0xff (-1 if signed, 255 if unsigned).
697:              with the checks for either PETSC_FALSE or PETSC_TRUE we truly demand that the value be 0 or 1 */
698:           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]);
699:           PetscCall(PetscViewerASCIIPrintf(view, " %s", PetscBools[value[i]]));
700:         }
701:         PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help));
702:       } else if (nitem->dtype == PETSC_ENUM) {
703:         PetscEnum value = *(PetscEnum *)(((char *)bag) + nitem->offset);
704:         PetscInt  i     = 0;
705:         while (nitem->list[i++]);
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));

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

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

748:   Collective

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

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

758:   Level: intermediate

760:   Note:
761:   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,
762:   rather `PetscOptionsCreateViewer()` should be used to construct the viewer once which can then be utilized in the heavily used routine.

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

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

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

795:   Collective

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

801:   Level: beginner

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

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

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

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

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

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

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

870:   Collective

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

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

879:   Level: intermediate

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

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

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

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

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

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

911:   Not Collective

913:   Level: intermediate

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

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

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

938:   Not Collective

940:   Level: intermediate

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

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

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

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

965:   Not Collective

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

970:   Output Parameter:
971: . data - pointer to memory that will have user-data-structure, this can be cast to a pointer of the type the C struct used in
972:          defining the bag

974:   Level: intermediate

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

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

993:   Logically Collective

995:   Level: intermediate

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

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

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

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

1023:   Not Collective

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

1028:   Output Parameter:
1029: . 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.

1031:   Level: intermediate

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

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