#include #include /*I "petscbag.h" I*/ #include /* Adds item to the linked list in a bag */ static PetscErrorCode PetscBagRegister_Private(PetscBag bag, PetscBagItem item, const char *name, const char *help) { PetscFunctionBegin; PetscCall(PetscStrncpy(item->name, name, PETSC_BAG_NAME_LENGTH - 1)); PetscCall(PetscStrncpy(item->help, help, PETSC_BAG_HELP_LENGTH - 1)); if (bag->bagitems) { PetscBagItem nitem = bag->bagitems; while (nitem->next) nitem = nitem->next; nitem->next = item; } else bag->bagitems = item; bag->count++; PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterEnum - add an enum value to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of enum in struct, for example `¶ms->dt` . list - array of strings containing names of enum values followed by enum name followed by enum prefix . mdefault - the initial value, cast with (`PetscEnum`) . name - the name of the item - help - longer string with more information about the value Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()` @*/ PetscErrorCode PetscBagRegisterEnum(PetscBag bag, void *addr, const char *const *list, PetscEnum mdefault, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscInt i = 0; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(addr, 2); PetscAssertPointer(list, 3); PetscAssertPointer(name, 5); PetscAssertPointer(help, 6); nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) { while (list[i++]); PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <%s>: (%s) %s (choose one of) ", bag->bagprefix ? bag->bagprefix : "", name, list[mdefault], list[i - 3], help)); for (i = 0; list[i + 2]; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " %s", list[i])); PetscCall((*PetscHelpPrintf)(bag->bagcomm, "\n")); } PetscCall(PetscOptionsGetEnum(NULL, bag->bagprefix, nname, list, &mdefault, NULL)); PetscCall(PetscNew(&item)); item->dtype = PETSC_ENUM; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = 1; PetscCall(PetscStrArrayallocpy(list, (char ***)&item->list)); *(PetscEnum *)addr = mdefault; PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterIntArray - add a `PetscInt` array to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of integer in struct, for example `¶ms->i` . msize - number of entries in array . name - name of the array - help - longer string with more information about the value Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagRegisterIntArray(PetscBag bag, void *addr, PetscInt msize, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscInt i, tmp = msize; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(addr, 2); PetscAssertPointer(name, 4); PetscAssertPointer(help, 5); nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) { PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <", bag->bagprefix ? bag->bagprefix : "", name)); for (i = 0; i < msize; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "%" PetscInt_FMT " ", *((PetscInt *)addr) + i)); PetscCall((*PetscHelpPrintf)(bag->bagcomm, ">: %s \n", help)); } PetscCall(PetscOptionsGetIntArray(NULL, bag->bagprefix, nname, (PetscInt *)addr, &tmp, NULL)); PetscCall(PetscNew(&item)); item->dtype = PETSC_INT; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = msize; PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterRealArray - add a `PetscReal` array to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of real array in struct, for example `¶ms->d` . msize - number of entries in the array . name - name of the array - help - longer string with more information about the value Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagRegisterRealArray(PetscBag bag, void *addr, PetscInt msize, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscInt i, tmp = msize; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(addr, 2); PetscAssertPointer(name, 4); PetscAssertPointer(help, 5); nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) { PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <", bag->bagprefix ? bag->bagprefix : "", name)); for (i = 0; i < msize; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "%g ", (double)*((PetscReal *)addr) + i)); PetscCall((*PetscHelpPrintf)(bag->bagcomm, ">: %s \n", help)); } PetscCall(PetscOptionsGetRealArray(NULL, bag->bagprefix, nname, (PetscReal *)addr, &tmp, NULL)); PetscCall(PetscNew(&item)); item->dtype = PETSC_REAL; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = msize; PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterInt - add a `PetscInt` value to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of integer in struct, for example `¶ms->i` . mdefault - the initial value . name - name of the integer - help - longer string with more information about the value Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt64()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagRegisterInt(PetscBag bag, void *addr, PetscInt mdefault, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(addr, 2); PetscAssertPointer(name, 4); PetscAssertPointer(help, 5); nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <%" PetscInt_FMT ">: %s \n", bag->bagprefix ? bag->bagprefix : "", name, mdefault, help)); PetscCall(PetscOptionsGetInt(NULL, bag->bagprefix, nname, &mdefault, NULL)); PetscCall(PetscNew(&item)); item->dtype = PETSC_INT; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = 1; *(PetscInt *)addr = mdefault; PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterInt64 - add a `PetscInt64` value to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of integer in struct, for example `¶ms->i` . mdefault - the initial value . name - name of the integer - help - longer string with more information about the value Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagRegisterInt64(PetscBag bag, void *addr, PetscInt64 mdefault, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscInt odefault = (PetscInt)mdefault; PetscBool flg; PetscFunctionBegin; nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <%" PetscInt_FMT ">: %s \n", bag->bagprefix ? bag->bagprefix : "", name, odefault, help)); PetscCall(PetscOptionsGetInt(NULL, bag->bagprefix, nname, &odefault, &flg)); if (flg) mdefault = (PetscInt64)odefault; PetscCall(PetscNew(&item)); item->dtype = PETSC_INT; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = 1; *(PetscInt64 *)addr = mdefault; PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterBoolArray - add a n `PetscBool` values to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of boolean array in struct, for example `¶ms->b` . msize - number of entries in array . name - name of the boolean array - help - longer string with more information about the value Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagRegisterBoolArray(PetscBag bag, void *addr, PetscInt msize, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscInt i, tmp = msize; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(addr, 2); PetscAssertPointer(name, 4); PetscAssertPointer(help, 5); nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) { PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <", bag->bagprefix ? bag->bagprefix : "", name)); for (i = 0; i < msize; i++) PetscCall((*PetscHelpPrintf)(bag->bagcomm, "%" PetscInt_FMT " ", *((PetscInt *)addr) + i)); PetscCall((*PetscHelpPrintf)(bag->bagcomm, ">: %s \n", help)); } PetscCall(PetscOptionsGetBoolArray(NULL, bag->bagprefix, nname, (PetscBool *)addr, &tmp, NULL)); PetscCall(PetscNew(&item)); item->dtype = PETSC_BOOL; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = msize; PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterString - add a string value to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of start of string in struct, for example `¶ms->mystring` . msize - length of the string space in the struct . mdefault - the initial value . name - name of the string - help - longer string with more information about the value Level: beginner Note: The struct must have the field char mystring[`msize`]; not char *mystring .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagRegisterString(PetscBag bag, void *addr, PetscInt msize, const char *mdefault, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(addr, 2); PetscAssertPointer(mdefault, 4); PetscAssertPointer(name, 5); PetscAssertPointer(help, 6); nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <%s>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, mdefault, help)); PetscCall(PetscNew(&item)); item->dtype = PETSC_CHAR; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = msize; if (mdefault != (char *)addr) PetscCall(PetscStrncpy((char *)addr, mdefault, msize - 1)); PetscCall(PetscOptionsGetString(NULL, bag->bagprefix, nname, (char *)addr, msize, NULL)); PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterReal - add a `PetscReal` value to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of `PetscReal` in struct, for example `¶ms->r` . mdefault - the initial value . name - name of the variable - help - longer string with more information about the value Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagRegisterReal(PetscBag bag, void *addr, PetscReal mdefault, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(addr, 2); PetscAssertPointer(name, 4); PetscAssertPointer(help, 5); nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <%g>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, (double)mdefault, help)); PetscCall(PetscOptionsGetReal(NULL, bag->bagprefix, nname, &mdefault, NULL)); PetscCall(PetscNew(&item)); item->dtype = PETSC_REAL; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = 1; *(PetscReal *)addr = mdefault; PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterScalar - add a `PetscScalar` value to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of `PetscScalar` in struct, for example `¶ms->c` . mdefault - the initial value . name - name of the variable - help - longer string with more information about the value Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagRegisterScalar(PetscBag bag, void *addr, PetscScalar mdefault, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(addr, 2); PetscAssertPointer(name, 4); PetscAssertPointer(help, 5); nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <%g + %gi>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, (double)PetscRealPart(mdefault), (double)PetscImaginaryPart(mdefault), help)); PetscCall(PetscOptionsGetScalar(NULL, bag->bagprefix, nname, &mdefault, NULL)); PetscCall(PetscNew(&item)); item->dtype = PETSC_SCALAR; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = 1; *(PetscScalar *)addr = mdefault; PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagRegisterBool - add a `PetscBool` to a `PetscBag` Logically Collective Input Parameters: + bag - the bag of values . addr - location of `PetscBool` in struct, for example `¶ms->b` . mdefault - the initial value, either `PETSC_FALSE` or `PETSC_TRUE` . name - name of the variable - help - longer string with more information about the value Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterInt()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagRegisterBool(PetscBag bag, void *addr, PetscBool mdefault, const char *name, const char *help) { PetscBagItem item; char nname[PETSC_BAG_NAME_LENGTH + 1]; PetscBool printhelp; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(addr, 2); PetscAssertPointer(name, 4); PetscAssertPointer(help, 5); /* the checks here with != PETSC_FALSE and PETSC_TRUE is a special case; here we truly demand that the value be 0 or 1 */ 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); nname[0] = '-'; nname[1] = 0; PetscCall(PetscStrlcat(nname, name, PETSC_BAG_NAME_LENGTH)); PetscCall(PetscOptionsHasHelp(NULL, &printhelp)); if (printhelp) PetscCall((*PetscHelpPrintf)(bag->bagcomm, " -%s%s <%s>: %s \n", bag->bagprefix ? bag->bagprefix : "", name, PetscBools[mdefault], help)); PetscCall(PetscOptionsGetBool(NULL, bag->bagprefix, nname, &mdefault, NULL)); PetscCall(PetscNew(&item)); item->dtype = PETSC_BOOL; item->offset = ((char *)addr) - ((char *)bag); PetscCheck(item->offset <= bag->bagsize, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Registered item %s %s is not in bag memory space", name, help); item->next = NULL; item->msize = 1; *(PetscBool *)addr = mdefault; PetscCall(PetscBagRegister_Private(bag, item, name, help)); PetscFunctionReturn(PETSC_SUCCESS); } /*@ PetscBagDestroy - Destroys a `PetscBag` Collective Input Parameter: . bag - the bag of values Level: beginner .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagDestroy(PetscBag *bag) { PetscBagItem nitem; PetscFunctionBegin; if (!*bag) PetscFunctionReturn(PETSC_SUCCESS); PetscAssertPointer(*bag, 1); nitem = (*bag)->bagitems; while (nitem) { PetscBagItem item = nitem->next; if (nitem->list) PetscCall(PetscStrArrayDestroy(&nitem->list)); PetscCall(PetscFree(nitem)); nitem = item; } if ((*bag)->bagprefix) PetscCall(PetscFree((*bag)->bagprefix)); PetscCall(PetscFree(*bag)); PetscFunctionReturn(PETSC_SUCCESS); } /*@ PetscBagSetFromOptions - Allows setting entries to a `PetscBag` using the options database Collective Input Parameter: . bag - the bag of values Level: beginner Note: The options database keys for the entries are of the form `-[bagprefix]_name value` .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagDestroy()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagSetFromOptions(PetscBag bag) { PetscBagItem nitem = bag->bagitems; char name[PETSC_BAG_NAME_LENGTH + 1], helpname[PETSC_BAG_NAME_LENGTH + PETSC_BAG_HELP_LENGTH + 3]; PetscInt n; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscCall(PetscStrncpy(helpname, bag->bagname, sizeof(helpname))); PetscCall(PetscStrlcat(helpname, " ", sizeof(helpname))); PetscCall(PetscStrlcat(helpname, bag->baghelp, sizeof(helpname))); PetscOptionsBegin(bag->bagcomm, bag->bagprefix, helpname, NULL); while (nitem) { name[0] = '-'; name[1] = 0; PetscCall(PetscStrlcat(name, nitem->name, sizeof(name))); if (nitem->dtype == PETSC_CHAR) { /* special handling for fortran required? [due to space padding vs null termination] */ char *value = (char *)(((char *)bag) + nitem->offset); PetscCall(PetscOptionsString(name, nitem->help, "", value, value, nitem->msize, NULL)); } else if (nitem->dtype == PETSC_REAL) { PetscReal *value = (PetscReal *)(((char *)bag) + nitem->offset); if (nitem->msize == 1) { PetscCall(PetscOptionsReal(name, nitem->help, "", *value, value, NULL)); } else { n = nitem->msize; PetscCall(PetscOptionsRealArray(name, nitem->help, "", value, &n, NULL)); } } else if (nitem->dtype == PETSC_SCALAR) { PetscScalar *value = (PetscScalar *)(((char *)bag) + nitem->offset); PetscCall(PetscOptionsScalar(name, nitem->help, "", *value, value, NULL)); } else if (nitem->dtype == PETSC_INT) { PetscInt *value = (PetscInt *)(((char *)bag) + nitem->offset); if (nitem->msize == 1) { PetscCall(PetscOptionsInt(name, nitem->help, "", *value, value, NULL)); } else { n = nitem->msize; PetscCall(PetscOptionsIntArray(name, nitem->help, "", value, &n, NULL)); } } else if (nitem->dtype == PETSC_ENUM) { PetscEnum *value = (PetscEnum *)(((char *)bag) + nitem->offset); PetscInt i = 0; while (nitem->list[i++]); PetscCall(PetscOptionsEnum(name, nitem->help, nitem->list[i - 3], (const char *const *)nitem->list, *value, value, NULL)); } else if (nitem->dtype == PETSC_BOOL) { PetscBool *value = (PetscBool *)(((char *)bag) + nitem->offset); if (nitem->msize == 1) { PetscCall(PetscOptionsBool(name, nitem->help, "", *value, value, NULL)); } else { n = nitem->msize; PetscCall(PetscOptionsBoolArray(name, nitem->help, "", value, &n, NULL)); } } nitem = nitem->next; } PetscOptionsEnd(); PetscFunctionReturn(PETSC_SUCCESS); } /*@ PetscBagView - Views a bag of values as either ASCII text or a binary file Collective Input Parameters: + bag - the bag of values - view - location to view the values Level: beginner Note: Currently PETSc bags saved in a binary file can only be read back in on a machine with the same binary format. .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagDestroy()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`, `PetscBagRegisterEnum()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()` @*/ PetscErrorCode PetscBagView(PetscBag bag, PetscViewer view) { PetscBool isascii, isbinary; PetscBagItem nitem = bag->bagitems; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscValidHeaderSpecific(view, PETSC_VIEWER_CLASSID, 2); PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERASCII, &isascii)); PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERBINARY, &isbinary)); if (isascii) { if (bag->bagprefix) { PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object: %s (%s) %s\n", bag->bagname, bag->bagprefix, bag->baghelp)); } else { PetscCall(PetscViewerASCIIPrintf(view, "PetscBag Object: %s %s\n", bag->bagname, bag->baghelp)); } while (nitem) { if (nitem->dtype == PETSC_CHAR) { char *value = (char *)(((char *)bag) + nitem->offset); char tmp = value[nitem->msize - 1]; /* special handling for fortran chars without null terminator */ value[nitem->msize - 1] = 0; PetscCall(PetscViewerASCIIPrintf(view, " %s = %s; %s\n", nitem->name, value, nitem->help)); value[nitem->msize - 1] = tmp; } else if (nitem->dtype == PETSC_REAL) { PetscReal *value = (PetscReal *)(((char *)bag) + nitem->offset); PetscInt i; PetscCall(PetscViewerASCIIPrintf(view, " %s = ", nitem->name)); for (i = 0; i < nitem->msize; i++) PetscCall(PetscViewerASCIIPrintf(view, "%g ", (double)value[i])); PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help)); } else if (nitem->dtype == PETSC_SCALAR) { PetscScalar value = *(PetscScalar *)(((char *)bag) + nitem->offset); #if defined(PETSC_USE_COMPLEX) if ((double)PetscImaginaryPart(value)) { PetscCall(PetscViewerASCIIPrintf(view, " %s = %g + %gi; %s\n", nitem->name, (double)PetscRealPart(value), (double)PetscImaginaryPart(value), nitem->help)); } else { PetscCall(PetscViewerASCIIPrintf(view, " %s = %g; %s\n", nitem->name, (double)PetscRealPart(value), nitem->help)); } #else PetscCall(PetscViewerASCIIPrintf(view, " %s = %g; %s\n", nitem->name, (double)value, nitem->help)); #endif } else if (nitem->dtype == PETSC_INT) { PetscInt i, *value = (PetscInt *)(((char *)bag) + nitem->offset); PetscCall(PetscViewerASCIIPrintf(view, " %s = ", nitem->name)); for (i = 0; i < nitem->msize; i++) PetscCall(PetscViewerASCIIPrintf(view, "%" PetscInt_FMT " ", value[i])); PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help)); } else if (nitem->dtype == PETSC_BOOL) { PetscBool *value = (PetscBool *)(((char *)bag) + nitem->offset); PetscInt i; /* some Fortran compilers use -1 as boolean */ PetscCall(PetscViewerASCIIPrintf(view, " %s = ", nitem->name)); for (i = 0; i < nitem->msize; i++) { if (((int)value[i]) == -1) value[i] = PETSC_TRUE; /* the checks here with != PETSC_FALSE and PETSC_TRUE is a special case; here we truly demand that the value be 0 or 1 */ 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]); PetscCall(PetscViewerASCIIPrintf(view, " %s", PetscBools[value[i]])); } PetscCall(PetscViewerASCIIPrintf(view, "; %s\n", nitem->help)); } else if (nitem->dtype == PETSC_ENUM) { PetscEnum value = *(PetscEnum *)(((char *)bag) + nitem->offset); PetscInt i = 0; while (nitem->list[i++]); PetscCall(PetscViewerASCIIPrintf(view, " %s = %s; (%s) %s\n", nitem->name, nitem->list[value], nitem->list[i - 3], nitem->help)); } nitem = nitem->next; } } else if (isbinary) { PetscInt classid = PETSC_BAG_FILE_CLASSID, dtype; PetscInt deprecatedbagsize = 0; PetscViewerFormat format; PetscCall(PetscViewerBinaryWrite(view, &classid, 1, PETSC_INT)); PetscCall(PetscViewerBinaryWrite(view, &deprecatedbagsize, 1, PETSC_INT)); PetscCall(PetscViewerBinaryWrite(view, &bag->count, 1, PETSC_INT)); PetscCall(PetscViewerBinaryWrite(view, bag->bagname, PETSC_BAG_NAME_LENGTH, PETSC_CHAR)); PetscCall(PetscViewerBinaryWrite(view, bag->baghelp, PETSC_BAG_HELP_LENGTH, PETSC_CHAR)); while (nitem) { PetscCall(PetscViewerBinaryWrite(view, &nitem->offset, 1, PETSC_INT)); dtype = (PetscInt)nitem->dtype; PetscCall(PetscViewerBinaryWrite(view, &dtype, 1, PETSC_INT)); PetscCall(PetscViewerBinaryWrite(view, nitem->name, PETSC_BAG_NAME_LENGTH, PETSC_CHAR)); PetscCall(PetscViewerBinaryWrite(view, nitem->help, PETSC_BAG_HELP_LENGTH, PETSC_CHAR)); PetscCall(PetscViewerBinaryWrite(view, &nitem->msize, 1, PETSC_INT)); /* some Fortran compilers use -1 as boolean */ if (dtype == PETSC_BOOL && (*(int *)(((char *)bag) + nitem->offset) == -1)) *(int *)(((char *)bag) + nitem->offset) = PETSC_TRUE; PetscCall(PetscViewerBinaryWrite(view, (((char *)bag) + nitem->offset), nitem->msize, nitem->dtype)); if (dtype == PETSC_ENUM) PetscCall(PetscViewerBinaryWriteStringArray(view, (const char *const *)nitem->list)); nitem = nitem->next; } PetscCall(PetscViewerGetFormat(view, &format)); if (format == PETSC_VIEWER_BINARY_MATLAB) { MPI_Comm comm; FILE *info; PetscCall(PetscObjectGetComm((PetscObject)view, &comm)); PetscCall(PetscViewerBinaryGetInfoPointer(view, &info)); PetscCall(PetscFPrintf(comm, info, "#--- begin code written by PetscViewerBinary for MATLAB format ---#\n")); PetscCall(PetscFPrintf(comm, info, "#$$ Set.%s = PetscBinaryRead(fd);\n", bag->bagname)); PetscCall(PetscFPrintf(comm, info, "#--- end code written by PetscViewerBinary for MATLAB format ---#\n\n")); } } PetscFunctionReturn(PETSC_SUCCESS); } /*@ PetscBagViewFromOptions - Processes command line options to determine if/how a `PetscBag` is to be viewed. Collective Input Parameters: + bag - the object . bobj - optional other object that provides prefix (if `NULL` then the prefix in obj is used) - optionname - option to activate viewing Level: intermediate .seealso: `PetscBagCreate()`, `PetscBag`, `PetscViewer` @*/ PetscErrorCode PetscBagViewFromOptions(PetscBag bag, PetscObject bobj, const char optionname[]) { static PetscBool incall = PETSC_FALSE; PetscViewer viewer; PetscViewerFormat format; const char *prefix, *bprefix = NULL; PetscBool flg; PetscFunctionBegin; if (incall) PetscFunctionReturn(PETSC_SUCCESS); incall = PETSC_TRUE; PetscAssertPointer(bag, 1); if (bobj) PetscCall(PetscObjectGetOptionsPrefix(bobj, &bprefix)); prefix = bobj ? bprefix : bag->bagprefix; PetscCall(PetscOptionsGetViewer(bag->bagcomm, NULL, prefix, optionname, &viewer, &format, &flg)); if (flg) { PetscCall(PetscViewerPushFormat(viewer, format)); PetscCall(PetscBagView(bag, viewer)); PetscCall(PetscViewerFlush(viewer)); PetscCall(PetscViewerPopFormat(viewer)); PetscCall(PetscOptionsRestoreViewer(&viewer)); } incall = PETSC_FALSE; PetscFunctionReturn(PETSC_SUCCESS); } /*@ PetscBagLoad - Loads a bag of values from a binary file Collective Input Parameters: + view - file to load values from - bag - the bag of values Level: beginner Note: You must have created and registered all the fields in the bag before loading into it. This only loads values. .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagDestroy()`, `PetscBagView()`, `PetscBagGetData()` `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagGetName()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagLoad(PetscViewer view, PetscBag bag) { PetscBool isbinary; PetscInt classid, bagcount, dtype, msize, offset, deprecatedbagsize; char name[PETSC_BAG_NAME_LENGTH], help[PETSC_BAG_HELP_LENGTH], **list; PetscBagItem nitem; MPI_Comm comm; PetscMPIInt flag; PetscFunctionBegin; PetscValidHeaderSpecific(view, PETSC_VIEWER_CLASSID, 1); PetscAssertPointer(bag, 2); PetscCall(PetscObjectGetComm((PetscObject)view, &comm)); PetscCallMPI(MPI_Comm_compare(comm, bag->bagcomm, &flag)); PetscCheck(flag == MPI_CONGRUENT || flag == MPI_IDENT, PETSC_COMM_SELF, PETSC_ERR_ARG_NOTSAMECOMM, "Different communicators in the viewer and bag"); PetscCall(PetscObjectTypeCompare((PetscObject)view, PETSCVIEWERBINARY, &isbinary)); PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for this viewer type"); PetscCall(PetscViewerBinaryRead(view, &classid, 1, NULL, PETSC_INT)); PetscCheck(classid == PETSC_BAG_FILE_CLASSID, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not PetscBag next in binary file"); PetscCall(PetscViewerBinaryRead(view, &deprecatedbagsize, 1, NULL, PETSC_INT)); PetscCall(PetscViewerBinaryRead(view, &bagcount, 1, NULL, PETSC_INT)); 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); PetscCall(PetscViewerBinaryRead(view, bag->bagname, PETSC_BAG_NAME_LENGTH, NULL, PETSC_CHAR)); PetscCall(PetscViewerBinaryRead(view, bag->baghelp, PETSC_BAG_HELP_LENGTH, NULL, PETSC_CHAR)); nitem = bag->bagitems; for (PetscInt i = 0; i < bagcount; i++) { PetscCall(PetscViewerBinaryRead(view, &offset, 1, NULL, PETSC_INT)); /* ignore the offset in the file */ PetscCall(PetscViewerBinaryRead(view, &dtype, 1, NULL, PETSC_INT)); PetscCall(PetscViewerBinaryRead(view, name, PETSC_BAG_NAME_LENGTH, NULL, PETSC_CHAR)); PetscCall(PetscViewerBinaryRead(view, help, PETSC_BAG_HELP_LENGTH, NULL, PETSC_CHAR)); PetscCall(PetscViewerBinaryRead(view, &msize, 1, NULL, PETSC_INT)); if (dtype == (PetscInt)PETSC_CHAR) { PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_CHAR)); } else if (dtype == (PetscInt)PETSC_REAL) { PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_REAL)); } else if (dtype == (PetscInt)PETSC_SCALAR) { PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, 1, NULL, PETSC_SCALAR)); } else if (dtype == (PetscInt)PETSC_INT) { PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_INT)); } else if (dtype == (PetscInt)PETSC_BOOL) { PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, msize, NULL, PETSC_BOOL)); } else if (dtype == (PetscInt)PETSC_ENUM) { PetscCall(PetscViewerBinaryRead(view, ((char *)bag) + nitem->offset, 1, NULL, PETSC_ENUM)); PetscCall(PetscViewerBinaryReadStringArray(view, &list)); /* don't need to save list because it is already registered in the bag */ PetscCall(PetscFree(list)); } nitem = nitem->next; } PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagCreate - Create a bag of values. A `PetscBag` is a representation of a C struct that can be saved to and read from files, can have values set from the options database Collective Input Parameters: + comm - communicator to share bag - bagsize - size of the C structure holding the values, for example sizeof(mystruct) Output Parameter: . bag - the bag of values Level: intermediate Notes: After creating the bag, for each entry in the C struct call the appropriate `PetscBagRegisterInt()` etc to define the C structs layout The size of the A struct must be small enough to fit in a `PetscInt`; by default `PetscInt` is 4 bytes; this means a bag cannot be larger than 2 gigabytes in length. The warning about casting to a shorter length can be ignored below unless your A struct is too large .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagCreate(MPI_Comm comm, size_t bagsize, PetscBag *bag) { const size_t totalsize = bagsize + sizeof(struct _n_PetscBag) + sizeof(PetscScalar); PetscFunctionBegin; PetscAssertPointer(bag, 3); PetscCall(PetscInfo(NULL, "Creating Bag with total size %d\n", (int)totalsize)); PetscCall(PetscCalloc(totalsize, bag)); (*bag)->bagsize = totalsize; (*bag)->bagcomm = comm; (*bag)->bagprefix = NULL; (*bag)->structlocation = (void *)(((char *)(*bag)) + sizeof(PetscScalar) * (sizeof(struct _n_PetscBag) / sizeof(PetscScalar)) + sizeof(PetscScalar)); PetscFunctionReturn(PETSC_SUCCESS); } /*@ PetscBagSetName - Sets the name of a bag of values Not Collective Level: intermediate Input Parameters: + bag - the bag of values . name - the name assigned to the bag - help - help message for bag .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagSetName(PetscBag bag, const char *name, const char *help) { PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(name, 2); PetscAssertPointer(help, 3); PetscCall(PetscStrncpy(bag->bagname, name, PETSC_BAG_NAME_LENGTH - 1)); PetscCall(PetscStrncpy(bag->baghelp, help, PETSC_BAG_HELP_LENGTH - 1)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagGetName - Gets the name of a bag of values Not Collective Level: intermediate Input Parameter: . bag - the bag of values Output Parameter: . name - the name assigned to the bag .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()`, `PetscBagGetData()` `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagGetName(PetscBag bag, const char **name) { PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(name, 2); *name = bag->bagname; PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagGetData - Gives back the user - access to memory that can be used for storing user-data-structure Not Collective Input Parameter: . bag - the bag of values Output Parameter: . 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 defining the bag Level: intermediate .seealso: `PetscBag`, `PetscBagSetName()`, `PetscBagView()`, `PetscBagLoad()` `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagGetData(PetscBag bag, void **data) { PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(data, 2); *data = bag->structlocation; PetscFunctionReturn(PETSC_SUCCESS); } /*@ PetscBagSetOptionsPrefix - Sets the prefix used for searching for all `PetscBag` items in the options database. Logically Collective Level: intermediate Input Parameters: + bag - the bag of values - pre - the prefix to prepend all Bag item names with. Note: Must be called prior to registering any of the bag items. .seealso: `PetscBag`, `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()` `PetscBagSetFromOptions()`, `PetscBagCreate()`, `PetscBagDestroy()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagSetOptionsPrefix(PetscBag bag, const char pre[]) { PetscFunctionBegin; PetscAssertPointer(bag, 1); if (pre) { PetscAssertPointer(pre, 2); PetscCheck(pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Options prefix should not begin with a hyphen"); PetscCall(PetscFree(bag->bagprefix)); PetscCall(PetscStrallocpy(pre, &bag->bagprefix)); } else PetscCall(PetscFree(bag->bagprefix)); PetscFunctionReturn(PETSC_SUCCESS); } /*@C PetscBagGetNames - Get the names of all entries in the bag Not Collective Input Parameter: . bag - the bag of values Output Parameter: . names - array of char pointers for names Level: intermediate .seealso: `PetscBag`, `PetscBagGetName()`, `PetscBagSetName()`, `PetscBagCreate()`, `PetscBagGetData()` `PetscBagRegisterReal()`, `PetscBagRegisterInt()`, `PetscBagRegisterBool()`, `PetscBagRegisterScalar()`, `PetscBagRegisterEnum()` @*/ PetscErrorCode PetscBagGetNames(PetscBag bag, const char *names[]) { PetscBagItem nitem = bag->bagitems; PetscFunctionBegin; PetscAssertPointer(bag, 1); PetscAssertPointer(names, 2); for (PetscInt n = 0; nitem; ++n, nitem = nitem->next) names[n] = nitem->name; PetscFunctionReturn(PETSC_SUCCESS); }