Actual source code: bag.c

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

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

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

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

     26:   Logically Collective

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

     36:   Level: beginner

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

     49:   PetscFunctionBegin;
     50:   PetscAssertPointer(bag, 1);
     51:   PetscAssertPointer(addr, 2);
     52:   PetscAssertPointer(list, 3);
     53:   PetscAssertPointer(name, 5);
     54:   PetscAssertPointer(help, 6);
     55:   nname[0] = '-';
     56:   nname[1] = 0;
     57:   PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH));
     58:   PetscCall(PetscOptionsHasHelp(NULL, &printhelp));
     59:   if (printhelp) {
     60:     while (list[i++]);
     61:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, "  -%s%s <%s>: (%s) %s (choose one of) ", bag->bagprefix ? bag->bagprefix : "", name, list[mdefault], list[i - 3], help));
     62:     for (i = 0; list[i + 2]; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " %s", list[i]));
     63:     PetscCall((*PetscHelpPrintf)(bag->bagcomm, "\n"));
     64:   }
     65:   PetscCall(PetscOptionsGetEnum(NULL, bag->bagprefix, nname, list, &mdefault, NULL));

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

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

     82:   Logically Collective

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

     91:   Level: beginner

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

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

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

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

    133:   Logically Collective

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

    142:   Level: beginner

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

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

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

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

    184:   Logically Collective

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

    193:   Level: beginner

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

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

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

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

    231:   Logically Collective

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

    240:   Level: beginner

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

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

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

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

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

    279:   Logically Collective

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

    288:   Level: beginner

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

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

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

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

    330:   Logically Collective

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

    340:   Level: beginner

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

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

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

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

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

    382:   Logically Collective

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

    391:   Level: beginner

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

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

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

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

    429:   Logically Collective

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

    438:   Level: beginner

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

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

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

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

    476:   Logically Collective

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

    485:   Level: beginner

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

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

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

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

    523:   Collective

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

    528:   Level: beginner

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

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

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

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

    557:   Collective

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

    562:   Level: beginner

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

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

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

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

    629:   Collective

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

    635:   Level: beginner

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

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

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

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

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

    747:   Collective

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

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

    757:   Level: intermediate

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

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

    787: /*@
    788:   PetscBagLoad - Loads a bag of values from a binary file

    790:   Collective

    792:   Input Parameters:
    793: + view - file to load values from
    794: - bag  - the bag of values

    796:   Level: beginner

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

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

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

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

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

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

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

    865:   Collective

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

    871:   Output Parameter:
    872: . bag - the bag of values

    874:   Level: intermediate

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

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

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

    891:   PetscFunctionBegin;
    892:   PetscAssertPointer(bag, 3);

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

    903: /*@
    904:   PetscBagSetName - Sets the name of a bag of values

    906:   Not Collective

    908:   Level: intermediate

    910:   Input Parameters:
    911: + bag  - the bag of values
    912: . name - the name assigned to the bag
    913: - help - help message for bag

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

    930: /*@C
    931:   PetscBagGetName - Gets the name of a bag of values

    933:   Not Collective

    935:   Level: intermediate

    937:   Input Parameter:
    938: . bag - the bag of values

    940:   Output Parameter:
    941: . name - the name assigned to the bag

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

    956: /*@C
    957:   PetscBagGetData - Gives back the user - access to memory that
    958:   can be used for storing user-data-structure

    960:   Not Collective

    962:   Input Parameter:
    963: . bag - the bag of values

    965:   Output Parameter:
    966: . 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
    967:          defining the bag

    969:   Level: intermediate

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

    984: /*@
    985:   PetscBagSetOptionsPrefix - Sets the prefix used for searching for all
    986:   `PetscBag` items in the options database.

    988:   Logically Collective

    990:   Level: intermediate

    992:   Input Parameters:
    993: + bag - the bag of values
    994: - pre - the prefix to prepend all Bag item names with.

    996:   Note:
    997:   Must be called prior to registering any of the bag items.

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

    1015: /*@C
    1016:   PetscBagGetNames - Get the names of all entries in the bag

    1018:   Not Collective

    1020:   Input Parameter:
    1021: . bag - the bag of values

    1023:   Output Parameter:
    1024: . 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.

    1026:   Level: intermediate

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

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