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: /*@C
 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:   PetscCall(PetscOptionsHasHelp(NULL, &printhelp));
 59:   if (printhelp) {
 60:     while (list[i++]);
 61:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%s>: (%s) %s (choose one of) ", bag->bagprefix ? bag->bagprefix : "", name, list[mdefault], list[i - 3], help));
 62:     for (i = 0; list[i + 2]; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " %s", list[i]));
 63:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, "\n"));
 64:   }
 65:   PetscCall(PetscOptionsGetEnum(NULL, bag->bagprefix, nname, list, &mdefault, NULL));

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

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

 82:   Logically Collective

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

 91:   Level: beginner

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

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

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

130: /*@C
131:   PetscBagRegisterRealArray - add a `PetscReal` array to a `PetscBag`

133:   Logically Collective

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

142:   Level: beginner

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

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

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

181: /*@C
182:   PetscBagRegisterInt - add a `PetscInt` value to a `PetscBag`

184:   Logically Collective

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

193:   Level: beginner

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

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

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

228: /*@C
229:   PetscBagRegisterInt64 - add a `PetscInt64` value to a `PetscBag`

231:   Logically Collective

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

240:   Level: beginner

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

254:   PetscFunctionBegin;
255:   nname[0] = '-';
256:   nname[1] = 0;

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

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

276: /*@C
277:   PetscBagRegisterBoolArray - add a n `PetscBool` values to a `PetscBag`

279:   Logically Collective

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

288:   Level: beginner

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

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

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

327: /*@C
328:   PetscBagRegisterString - add a string value to a `PetscBag`

330:   Logically Collective

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

340:   Level: beginner

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

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

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

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

379: /*@C
380:   PetscBagRegisterReal - add a `PetscReal` value to a `PetscBag`

382:   Logically Collective

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

391:   Level: beginner

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

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

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

426: /*@C
427:   PetscBagRegisterScalar - add a `PetscScalar` value to a `PetscBag`

429:   Logically Collective

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

438:   Level: beginner

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

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

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

473: /*@C
474:   PetscBagRegisterBool - add a `PetscBool` to a `PetscBag`

476:   Logically Collective

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

485:   Level: beginner

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

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

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

520: /*@
521:   PetscBagDestroy - Destroys a `PetscBag`

523:   Collective

525:   Input Parameter:
526: . bag - the bag of values

528:   Level: beginner

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

538:   PetscFunctionBegin;
539:   if (!*bag) PetscFunctionReturn(PETSC_SUCCESS);
540:   PetscAssertPointer(*bag, 1);
541:   nitem = (*bag)->bagitems;
542:   while (nitem) {
543:     PetscBagItem item = nitem->next;

545:     if (nitem->list) PetscCall(PetscStrArrayDestroy(&nitem->list));
546:     PetscCall(PetscFree(nitem));
547:     nitem = item;
548:   }
549:   if ((*bag)->bagprefix) PetscCall(PetscFree((*bag)->bagprefix));
550:   PetscCall(PetscFree(*bag));
551:   PetscFunctionReturn(PETSC_SUCCESS);
552: }

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

557:   Collective

559:   Input Parameter:
560: . bag - the bag of values

562:   Level: beginner

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

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

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

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

629:   Collective

631:   Input Parameters:
632: + bag  - the bag of values
633: - view - location to view the values

635:   Level: beginner

637:   Note:
638:   Currently PETSc bags saved in a binary file can only be read back
639:   in on a machine with the same binary format.

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

650:   PetscFunctionBegin;
651:   PetscAssertPointer(bag, 1);
653:   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii));
654:   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERBINARY, &isbinary));
655:   if (isascii) {
656:     if (bag->bagprefix) {
657:       PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object:  %s (%s) %s\n", bag->bagname, bag->bagprefix, bag->baghelp));
658:     } else {
659:       PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object:  %s %s\n", bag->bagname, bag->baghelp));
660:     }
661:     while (nitem) {
662:       if (nitem->dtype == PETSC_CHAR) {
663:         char *value             = ((char *)bag) + nitem->offset;
664:         char  tmp               = value[nitem->msize - 1]; /* special handling for fortran chars without null terminator */
665:         value[nitem->msize - 1] = 0;
666:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = %s; %s\n", nitem->name, value, nitem->help));
667:         value[nitem->msize - 1] = tmp;
668:       } else if (nitem->dtype == PETSC_REAL) {
669:         PetscReal *value = (PetscReal *)(((char *)bag) + nitem->offset);
670:         PetscInt   i;
671:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = ", nitem->name));
672:         for (i = 0; i < nitem->msize; i++) PetscCall(PetscViewerASCIIPrintf(view, "%g ", (double)value[i]));
673:         PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help));
674:       } else if (nitem->dtype == PETSC_SCALAR) {
675:         PetscScalar value = *(PetscScalar *)(((char *)bag) + nitem->offset);
676: #if defined(PETSC_USE_COMPLEX)
677:         if ((double)PetscImaginaryPart(value)) {
678:           PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g + %gi; %s\n", nitem->name, (double)PetscRealPart(value), (double)PetscImaginaryPart(value), nitem->help));
679:         } else {
680:           PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g; %s\n", nitem->name, (double)PetscRealPart(value), nitem->help));
681:         }
682: #else
683:         PetscCall(PetscViewerASCIIPrintf(view, "  %s = %g; %s\n", nitem->name, (double)value, nitem->help));
684: #endif
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: - optionname - option to activate viewing

754:   Level: intermediate

756: .seealso: `PetscBagCreate()`, `PetscBag`, `PetscViewer`
757: @*/
758: PetscErrorCode PetscBagViewFromOptions(PetscBag bag, PetscObject bobj, const char optionname[])
759: {
760:   static PetscBool  incall = PETSC_FALSE;
761:   PetscViewer       viewer;
762:   PetscViewerFormat format;
763:   const char       *prefix, *bprefix = NULL;
764:   PetscBool         flg;

766:   PetscFunctionBegin;
767:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
768:   incall = PETSC_TRUE;
769:   PetscAssertPointer(bag, 1);
770:   if (bobj) PetscCall(PetscObjectGetOptionsPrefix(bobj, &bprefix));
771:   prefix = bobj ? bprefix : bag->bagprefix;
772:   PetscCall(PetscOptionsCreateViewer(bag->bagcomm, NULL, prefix, optionname, &viewer, &format, &flg));
773:   if (flg) {
774:     PetscCall(PetscViewerPushFormat(viewer, format));
775:     PetscCall(PetscBagView(bag, viewer));
776:     PetscCall(PetscViewerFlush(viewer));
777:     PetscCall(PetscViewerPopFormat(viewer));
778:     PetscCall(PetscViewerDestroy(&viewer));
779:   }
780:   incall = PETSC_FALSE;
781:   PetscFunctionReturn(PETSC_SUCCESS);
782: }

784: /*@
785:   PetscBagLoad - Loads a bag of values from a binary file

787:   Collective

789:   Input Parameters:
790: + view - file to load values from
791: - bag  - the bag of values

793:   Level: beginner

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

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

811:   PetscFunctionBegin;
813:   PetscAssertPointer(bag, 2);
814:   PetscCall(PetscObjectGetComm((PetscObject)view, &comm));
815:   PetscCallMPI(MPI_Comm_compare(comm, bag->bagcomm, &flag));
816:   PetscCheck(flag == MPI_CONGRUENT || flag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "Different communicators in the viewer and bag");
817:   PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERBINARY, &isbinary));
818:   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for this viewer type");

820:   PetscCall(PetscViewerBinaryRead(view, &classid, 1, NULL, PETSC_INT));
821:   PetscCheck(classid == PETSC_BAG_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not PetscBag next in binary file");
822:   PetscCall(PetscViewerBinaryRead(view, &deprecatedbagsize, 1, NULL, PETSC_INT));
823:   PetscCall(PetscViewerBinaryRead(view, &bagcount, 1, NULL, PETSC_INT));
824:   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);
825:   PetscCall(PetscViewerBinaryRead(view, bag->bagname, PETSC_BAG_NAME_LENGTH, NULL, PETSC_CHAR));
826:   PetscCall(PetscViewerBinaryRead(view, bag->baghelp, PETSC_BAG_HELP_LENGTH, NULL, PETSC_CHAR));

828:   nitem = bag->bagitems;
829:   for (PetscInt i = 0; i < bagcount; i++) {
830:     PetscCall(PetscViewerBinaryRead(view, &offset, 1, NULL, PETSC_INT));
831:     /* ignore the offset in the file */
832:     PetscCall(PetscViewerBinaryRead(view, &dtype, 1, NULL, PETSC_INT));
833:     PetscCall(PetscViewerBinaryRead(view, name, PETSC_BAG_NAME_LENGTH, NULL, PETSC_CHAR));
834:     PetscCall(PetscViewerBinaryRead(view, help, PETSC_BAG_HELP_LENGTH, NULL, PETSC_CHAR));
835:     PetscCall(PetscViewerBinaryRead(view, &msize, 1, NULL, PETSC_INT));

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

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

862:   Collective

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

868:   Output Parameter:
869: . bag - the bag of values

871:   Level: intermediate

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

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

880: .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
881:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
882:           `PetscBagSetFromOptions()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
883: @*/
884: PetscErrorCode PetscBagCreate(MPI_Comm comm, size_t bagsize, PetscBag *bag)
885: {
886:   const size_t totalsize = bagsize + sizeof(struct _n_PetscBag) + sizeof(PetscScalar);

888:   PetscFunctionBegin;
889:   PetscAssertPointer(bag, 3);

891:   PetscCall(PetscInfo(NULL, "Creating Bag with total size %d\n", (int)totalsize));
892:   PetscCall(PetscCalloc(totalsize, bag));
893:   PetscCall(PetscIntCast(totalsize, &(*bag)->bagsize));
894:   (*bag)->bagcomm        = comm;
895:   (*bag)->bagprefix      = NULL;
896:   (*bag)->structlocation = (void *)(((char *)(*bag)) + sizeof(PetscScalar) * (sizeof(struct _n_PetscBag) / sizeof(PetscScalar)) + sizeof(PetscScalar));
897:   PetscFunctionReturn(PETSC_SUCCESS);
898: }

900: /*@
901:   PetscBagSetName - Sets the name of a bag of values

903:   Not Collective

905:   Level: intermediate

907:   Input Parameters:
908: + bag  - the bag of values
909: . name - the name assigned to the bag
910: - help - help message for bag

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

927: /*@C
928:   PetscBagGetName - Gets the name of a bag of values

930:   Not Collective

932:   Level: intermediate

934:   Input Parameter:
935: . bag - the bag of values

937:   Output Parameter:
938: . name - the name assigned to the bag

940: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`,
941:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
942:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
943: @*/
944: PetscErrorCode PetscBagGetName(PetscBag bag, const char **name)
945: {
946:   PetscFunctionBegin;
947:   PetscAssertPointer(bag, 1);
948:   PetscAssertPointer(name, 2);
949:   *name = bag->bagname;
950:   PetscFunctionReturn(PETSC_SUCCESS);
951: }

953: /*@C
954:   PetscBagGetData - Gives back the user - access to memory that
955:   can be used for storing user-data-structure

957:   Not Collective

959:   Input Parameter:
960: . bag - the bag of values

962:   Output Parameter:
963: . 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
964:          defining the bag

966:   Level: intermediate

968: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`,
969:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`,
970:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()`
971: @*/
972: PetscErrorCode PetscBagGetData(PetscBag bag, PetscCtxRt data)
973: {
974:   PetscFunctionBegin;
975:   PetscAssertPointer(bag, 1);
976:   PetscAssertPointer(data, 2);
977:   *(void **)data = bag->structlocation;
978:   PetscFunctionReturn(PETSC_SUCCESS);
979: }

981: /*@
982:   PetscBagSetOptionsPrefix - Sets the prefix used for searching for all
983:   `PetscBag` items in the options database.

985:   Logically Collective

987:   Level: intermediate

989:   Input Parameters:
990: + bag - the bag of values
991: - pre - the prefix to prepend all Bag item names with.

993:   Note:
994:   Must be called prior to registering any of the bag items.

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

1012: /*@C
1013:   PetscBagGetNames - Get the names of all entries in the bag

1015:   Not Collective

1017:   Input Parameter:
1018: . bag - the bag of values

1020:   Output Parameter:
1021: . 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.

1023:   Level: intermediate

1025: .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagSetName()`, `PetscBagCreate()`, `PetscBagGetData()`,
1026:           `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`, `PetscBagRegisterEnum()`
1027: @*/
1028: PetscErrorCode PetscBagGetNames(PetscBag bag, const char *names[])
1029: {
1030:   PetscBagItem nitem = bag->bagitems;

1032:   PetscFunctionBegin;
1033:   PetscAssertPointer(bag, 1);
1034:   PetscAssertPointer(names, 2);
1035:   for (PetscInt n = 0; nitem; ++n, nitem = nitem->next) names[n] = nitem->name;
1036:   PetscFunctionReturn(PETSC_SUCCESS);
1037: }