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

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

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

 83:   Logically Collective

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

 92:   Level: beginner

 94: .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()`
 95:           `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`
 96:           `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()`
 97: @*/
 98: PetscErrorCode PetscBagRegisterIntArray(PetscBag bag, void *addr, PetscInt msize, const char *name, const char *help)
 99: {
100:   PetscBagItem item;
101:   char         nname[PETSC_BAG_NAME_LENGTH + 1];
102:   PetscBool    printhelp;
103:   PetscInt     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 " ", *((PetscInt *)addr) + i));
117:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, ">: %s \n", help));
118:   }
119:   PetscCall(PetscOptionsGetIntArray(NULL, bag->bagprefix, nname, (PetscInt *)addr, &tmp, NULL));

121:   PetscCall(PetscNew(&item));
122:   item->dtype  = PETSC_INT;
123:   item->offset = ((char *)addr) - ((char *)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:   PetscBool    printhelp;
154:   PetscInt     i, tmp = msize;

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

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

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

185:   Logically Collective

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

194:   Level: beginner

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

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

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

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

232:   Logically Collective

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

241:   Level: beginner

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

255:   PetscFunctionBegin;
256:   nname[0] = '-';
257:   nname[1] = 0;
258:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
259:   PetscCall(PetscOptionsHasHelp(NULL, &printhelp));
260:   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%" PetscInt_FMT ">: %s \n", bag->bagprefix ? bag->bagprefix : "", name, odefault, help));
261:   PetscCall(PetscOptionsGetInt(NULL, bag->bagprefix, nname, &odefault, &flg));
262:   if (flg) mdefault = (PetscInt64)odefault;

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

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

278:   Logically Collective

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

287:   Level: beginner

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

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

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

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

329:   Logically Collective

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

339:   Level: beginner

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

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

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

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

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

381:   Logically Collective

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

390:   Level: beginner

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

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

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

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

428:   Logically Collective

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

437:   Level: beginner

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

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

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

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

475:   Logically Collective

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

484:   Level: beginner

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

496:   PetscFunctionBegin;
497:   PetscAssertPointer(bag, 1);
498:   PetscAssertPointer(addr, 2);
499:   PetscAssertPointer(name, 4);
500:   PetscAssertPointer(help, 5);
501:   /* the checks here with != PETSC_FALSE and PETSC_TRUE is a special case; here we truly demand that the value be 0 or 1 */
502:   PetscCheck(mdefault == PETSC_FALSE || mdefault == PETSC_TRUE, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Boolean %s %s must be boolean; integer value %d", name, help, (int)mdefault);
503:   nname[0] = '-';
504:   nname[1] = 0;
505:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
506:   PetscCall(PetscOptionsHasHelp(NULL, &printhelp));
507:   if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%s>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, PetscBools[mdefault], help));
508:   PetscCall(PetscOptionsGetBool(NULL, bag->bagprefix, nname, &mdefault, NULL));

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

521: /*@C
522:   PetscBagDestroy - Destroys a `PetscBag`

524:   Collective

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

529:   Level: beginner

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

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

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

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

558:   Collective

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

563:   Level: beginner

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

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

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

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

634:   Collective

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

640:   Level: beginner

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

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

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

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

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

756:   Collective

758:   Input Parameters:
759: + bag        - the object
760: . bobj       - optional other object that provides prefix (if `NULL` then the prefix in obj is used)
761: - optionname - option to activate viewing

763:   Level: intermediate

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

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

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

796:   Collective

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

802:   Level: beginner

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

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

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

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

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

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

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

871:   Collective

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

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

880:   Level: intermediate

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

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

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

897:   PetscFunctionBegin;
898:   PetscAssertPointer(bag, 3);
899:   PetscCall(PetscInfo(NULL, "Creating Bag with total size %d\n", (int)totalsize));
900:   PetscCall(PetscCalloc(totalsize, bag));

902:   (*bag)->bagsize        = totalsize;
903:   (*bag)->bagcomm        = comm;
904:   (*bag)->bagprefix      = NULL;
905:   (*bag)->structlocation = (void *)(((char *)(*bag)) + sizeof(PetscScalar) * (sizeof(struct _n_PetscBag) / sizeof(PetscScalar)) + sizeof(PetscScalar));
906:   PetscFunctionReturn(PETSC_SUCCESS);
907: }

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

912:   Not Collective

914:   Level: intermediate

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

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

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

939:   Not Collective

941:   Level: intermediate

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

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

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

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

966:   Not Collective

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

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

975:   Level: intermediate

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

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

994:   Logically Collective

996:   Level: intermediate

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

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

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

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

1024:   Not Collective

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

1029:   Output Parameter:
1030: . names - array of char pointers for names

1032:   Level: intermediate

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

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