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    *values = (PetscInt *)addr;
103:   PetscInt     i, tmp = msize;

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

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

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

134:   Logically Collective

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

143:   Level: beginner

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

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

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

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

186:   Logically Collective

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

195:   Level: beginner

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

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

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

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

233:   Logically Collective

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

242:   Level: beginner

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

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

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

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

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

281:   Logically Collective

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

290:   Level: beginner

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

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

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

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

333:   Logically Collective

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

343:   Level: beginner

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

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

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

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

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

385:   Logically Collective

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

394:   Level: beginner

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

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

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

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

432:   Logically Collective

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

441:   Level: beginner

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

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

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

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

479:   Logically Collective

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

488:   Level: beginner

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

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

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

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

526:   Collective

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

531:   Level: beginner

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

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

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

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

560:   Collective

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

565:   Level: beginner

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

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

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

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

632:   Collective

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

638:   Level: beginner

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

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

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

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

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

750:   Collective

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

757:   Options Database Key:
758: . -name [viewertype][:...] - option name and values. See `PetscObjectViewFromOptions()` for the possible arguments

760:   Level: intermediate

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

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

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

793:   Collective

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

799:   Level: beginner

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

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

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

826:   PetscCall(PetscViewerBinaryRead(view, &classid, 1, NULL, PETSC_INT));
827:   PetscCheck(classid == PETSC_BAG_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not PetscBag next in binary file");
828:   PetscCall(PetscViewerBinaryRead(view, &deprecatedbagsize, 1, NULL, PETSC_INT));
829:   PetscCall(PetscViewerBinaryRead(view, &bagcount, 1, NULL, PETSC_INT));
830:   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);
831:   PetscCall(PetscViewerBinaryRead(view, bag->bagname, PETSC_BAG_NAME_LENGTH, NULL, PETSC_CHAR));
832:   PetscCall(PetscViewerBinaryRead(view, bag->baghelp, PETSC_BAG_HELP_LENGTH, NULL, PETSC_CHAR));

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

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

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

868:   Collective

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

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

877:   Level: intermediate

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

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

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

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

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

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

909:   Not Collective

911:   Level: intermediate

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

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

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

936:   Not Collective

938:   Level: intermediate

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

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

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

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

963:   Not Collective

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

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

972:   Level: intermediate

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

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

991:   Logically Collective

993:   Level: intermediate

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

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

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

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

1021:   Not Collective

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

1026:   Output Parameter:
1027: . 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.

1029:   Level: intermediate

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

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