Actual source code: aoptions.c

      1: /*
      2:    Implements the higher-level options database querying methods. These are self-documenting and can attach at runtime to
      3:    GUI code to display the options and get values from the users.

      5: */

      7: #include <petsc/private/petscimpl.h>
      8: #include <petscviewer.h>

     10: static const char *ManSection(const char *str)
     11: {
     12:   return str ? str : "None";
     13: }

     15: static const char *Prefix(const char *str)
     16: {
     17:   return str ? str : "";
     18: }

     20: static int ShouldPrintHelp(const PetscOptionItems opts)
     21: {
     22:   return opts->printhelp && opts->count == 1 && !opts->alreadyprinted;
     23: }

     25: /*
     26:     Keep a linked list of options that have been posted and we are waiting for
     27:    user selection. See the manual page for PetscOptionsBegin()

     29:     Eventually we'll attach this beast to a MPI_Comm
     30: */

     32: /*
     33:     Handles setting up the data structure in a call to PetscOptionsBegin()
     34: */
     35: PetscErrorCode PetscOptionsBegin_Private(PetscOptionItems PetscOptionsObject, MPI_Comm comm, const char prefix[], const char title[], const char mansec[])
     36: {
     37:   PetscFunctionBegin;
     38:   if (prefix) PetscAssertPointer(prefix, 3);
     39:   PetscAssertPointer(title, 4);
     40:   if (mansec) PetscAssertPointer(mansec, 5);
     41:   if (!PetscOptionsObject->alreadyprinted) {
     42:     if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
     43:     PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, prefix, title, &PetscOptionsObject->alreadyprinted));
     44:   }
     45:   PetscOptionsObject->next          = NULL;
     46:   PetscOptionsObject->comm          = comm;
     47:   PetscOptionsObject->changedmethod = PETSC_FALSE;

     49:   PetscCall(PetscStrallocpy(prefix, &PetscOptionsObject->prefix));
     50:   PetscCall(PetscStrallocpy(title, &PetscOptionsObject->title));

     52:   PetscCall(PetscOptionsHasHelp(PetscOptionsObject->options, &PetscOptionsObject->printhelp));
     53:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\n%s:\n", title));
     54:   PetscFunctionReturn(PETSC_SUCCESS);
     55: }

     57: /*
     58:     Handles setting up the data structure in a call to PetscObjectOptionsBegin()
     59: */
     60: PetscErrorCode PetscObjectOptionsBegin_Private(PetscObject obj, PetscOptionItems PetscOptionsObject)
     61: {
     62:   char      title[256];
     63:   PetscBool flg;

     65:   PetscFunctionBegin;
     66:   PetscAssertPointer(PetscOptionsObject, 2);
     68:   PetscOptionsObject->object         = obj;
     69:   PetscOptionsObject->alreadyprinted = obj->optionsprinted;

     71:   PetscCall(PetscStrcmp(obj->description, obj->class_name, &flg));
     72:   if (flg) PetscCall(PetscSNPrintf(title, sizeof(title), "%s options", obj->class_name));
     73:   else PetscCall(PetscSNPrintf(title, sizeof(title), "%s (%s) options", obj->description, obj->class_name));
     74:   PetscCall(PetscOptionsBegin_Private(PetscOptionsObject, obj->comm, obj->prefix, title, obj->mansec));
     75:   PetscFunctionReturn(PETSC_SUCCESS);
     76: }

     78: /*
     79:      Handles adding another option to the list of options within this particular PetscOptionsBegin() PetscOptionsEnd()
     80: */
     81: static PetscErrorCode PetscOptionItemCreate_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscOptionType t, PetscOptionItem *amsopt)
     82: {
     83:   PetscBool valid;

     85:   PetscFunctionBegin;
     86:   PetscCall(PetscOptionsValidKey(opt, &valid));
     87:   PetscCheck(valid, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "The option '%s' is not a valid key", opt);

     89:   PetscCall(PetscNew(amsopt));
     90:   (*amsopt)->next = NULL;
     91:   (*amsopt)->set  = PETSC_FALSE;
     92:   (*amsopt)->type = t;
     93:   (*amsopt)->data = NULL;

     95:   PetscCall(PetscStrallocpy(text, &(*amsopt)->text));
     96:   PetscCall(PetscStrallocpy(opt, &(*amsopt)->option));
     97:   PetscCall(PetscStrallocpy(man, &(*amsopt)->man));

     99:   {
    100:     PetscOptionItem cur = PetscOptionsObject->next;

    102:     while (cur->next) cur = cur->next;
    103:     cur->next = *amsopt;
    104:   }
    105:   PetscFunctionReturn(PETSC_SUCCESS);
    106: }

    108: /*
    109:     This is needed because certain strings may be freed by SAWs, hence we cannot use PetscStrallocpy()
    110: */
    111: static PetscErrorCode PetscStrdup(const char s[], char *t[])
    112: {
    113:   char *tmp = NULL;

    115:   PetscFunctionBegin;
    116:   if (s) {
    117:     size_t len;

    119:     PetscCall(PetscStrlen(s, &len));
    120:     tmp = (char *)malloc((len + 1) * sizeof(*tmp));
    121:     PetscCheck(tmp, PETSC_COMM_SELF, PETSC_ERR_MEM, "No memory to duplicate string");
    122:     PetscCall(PetscArraycpy(tmp, s, len + 1));
    123:   }
    124:   *t = tmp;
    125:   PetscFunctionReturn(PETSC_SUCCESS);
    126: }

    128: #if defined(PETSC_HAVE_SAWS)
    129: #include <petscviewersaws.h>

    131: static int count = 0;

    133: static const char *OptionsHeader = "<head>\n"
    134:                                    "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/jquery-1.9.1.js\"></script>\n"
    135:                                    "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/SAWs.js\"></script>\n"
    136:                                    "<script type=\"text/javascript\" src=\"js/PETSc.js\"></script>\n"
    137:                                    "<script>\n"
    138:                                    "jQuery(document).ready(function() {\n"
    139:                                    "PETSc.getAndDisplayDirectory(null,\"#variablesInfo\")\n"
    140:                                    "})\n"
    141:                                    "</script>\n"
    142:                                    "</head>\n";

    144: /*  Determines the size and style of the scroll region where PETSc options selectable from users are displayed */
    145: static const char *OptionsBodyBottom = "<div id=\"variablesInfo\" style=\"background-color:lightblue;height:auto;max-height:500px;overflow:scroll;\"></div>\n<br>\n</body>";

    147: /*
    148:     PetscOptionsSAWsInput - Presents all the PETSc Options processed by the program so the user may change them at runtime using the SAWs

    150:     Bugs:
    151: +    All processes must traverse through the exact same set of option queries due to the call to PetscScanString()
    152: .    Internal strings have arbitrary length and string copies are not checked that they fit into string space
    153: -    Only works for PetscInt == int, PetscReal == double etc

    155: */
    156: static PetscErrorCode PetscOptionsSAWsInput(PetscOptionItems PetscOptionsObject)
    157: {
    158:   PetscOptionItem next     = PetscOptionsObject->next;
    159:   static int      mancount = 0;
    160:   char            options[16];
    161:   PetscBool       changedmethod = PETSC_FALSE;
    162:   PetscBool       stopasking    = PETSC_FALSE;
    163:   char            manname[16], textname[16];
    164:   char            dir[1024];

    166:   PetscFunctionBegin;
    167:   /* the next line is a bug, this will only work if all processors are here, the comm passed in is ignored!!! */
    168:   PetscCall(PetscSNPrintf(options, PETSC_STATIC_ARRAY_LENGTH(options), "Options_%d", count++));

    170:   PetscOptionsObject->pprefix = PetscOptionsObject->prefix; /* SAWs will change this, so cannot pass prefix directly */

    172:   PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "_title"));
    173:   PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->title, 1, SAWs_READ, SAWs_STRING));
    174:   PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "prefix"));
    175:   PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->pprefix, 1, SAWs_READ, SAWs_STRING));
    176:   PetscCallSAWs(SAWs_Register, ("/PETSc/Options/ChangedMethod", &changedmethod, 1, SAWs_WRITE, SAWs_BOOLEAN));
    177:   PetscCallSAWs(SAWs_Register, ("/PETSc/Options/StopAsking", &stopasking, 1, SAWs_WRITE, SAWs_BOOLEAN));

    179:   while (next) {
    180:     PetscCall(PetscSNPrintf(manname, PETSC_STATIC_ARRAY_LENGTH(manname), "_man_%d", mancount));
    181:     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", manname));
    182:     PetscCallSAWs(SAWs_Register, (dir, &next->man, 1, SAWs_READ, SAWs_STRING));
    183:     PetscCall(PetscSNPrintf(textname, PETSC_STATIC_ARRAY_LENGTH(textname), "_text_%d", mancount++));
    184:     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", textname));
    185:     PetscCallSAWs(SAWs_Register, (dir, &next->text, 1, SAWs_READ, SAWs_STRING));

    187:     switch (next->type) {
    188:     case OPTION_HEAD:
    189:       break;
    190:     case OPTION_INT_ARRAY:
    191:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    192:       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_INT));
    193:       break;
    194:     case OPTION_REAL_ARRAY:
    195:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    196:       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_DOUBLE));
    197:       break;
    198:     case OPTION_INT:
    199:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    200:       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_INT));
    201:       break;
    202:     case OPTION_REAL:
    203:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    204:       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_DOUBLE));
    205:       break;
    206:     case OPTION_BOOL:
    207:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    208:       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_BOOLEAN));
    209:       break;
    210:     case OPTION_BOOL_ARRAY:
    211:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    212:       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_BOOLEAN));
    213:       break;
    214:     case OPTION_STRING:
    215:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    216:       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
    217:       break;
    218:     case OPTION_STRING_ARRAY:
    219:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    220:       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_STRING));
    221:       break;
    222:     case OPTION_FLIST: {
    223:       PetscInt ntext;
    224:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    225:       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
    226:       PetscCall(PetscFunctionListGet(next->flist, (const char ***)&next->edata, &ntext));
    227:       PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata));
    228:     } break;
    229:     case OPTION_ELIST: {
    230:       PetscInt ntext = next->nlist;
    231:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    232:       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
    233:       PetscCall(PetscMalloc1(ntext + 1, (char ***)&next->edata));
    234:       PetscCall(PetscMemcpy(next->edata, next->list, ntext * sizeof(char *)));
    235:       PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata));
    236:     } break;
    237:     default:
    238:       break;
    239:     }
    240:     next = next->next;
    241:   }

    243:   /* wait until accessor has unlocked the memory */
    244:   PetscCallSAWs(SAWs_Push_Header, ("index.html", OptionsHeader));
    245:   PetscCallSAWs(SAWs_Push_Body, ("index.html", 2, OptionsBodyBottom));
    246:   PetscCall(PetscSAWsBlock());
    247:   PetscCallSAWs(SAWs_Pop_Header, ("index.html"));
    248:   PetscCallSAWs(SAWs_Pop_Body, ("index.html", 2));

    250:   /* determine if any values have been set in GUI */
    251:   next = PetscOptionsObject->next;
    252:   while (next) {
    253:     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
    254:     PetscCallSAWs(SAWs_Selected, (dir, (int *)&next->set));
    255:     next = next->next;
    256:   }

    258:   /* reset counter to -2; this updates the screen with the new options for the selected method */
    259:   if (changedmethod) PetscOptionsObject->count = -2;

    261:   if (stopasking) {
    262:     PetscOptionsPublish       = PETSC_FALSE;
    263:     PetscOptionsObject->count = 0; //do not ask for same thing again
    264:   }

    266:   PetscCallSAWs(SAWs_Delete, ("/PETSc/Options"));
    267:   PetscFunctionReturn(PETSC_SUCCESS);
    268: }
    269: #else
    270: /*
    271:     PetscScanString -  Gets user input via stdin from process and broadcasts to all processes

    273:     Collective

    275:    Input Parameters:
    276: +     commm - communicator for the broadcast, must be PETSC_COMM_WORLD
    277: .     n - length of the string, must be the same on all processes
    278: -     str - location to store input

    280:     Bugs:
    281: .   Assumes process 0 of the given communicator has access to stdin

    283: */
    284: static PetscErrorCode PetscScanString(MPI_Comm comm, size_t n, char str[])
    285: {
    286:   PetscMPIInt rank, nm;

    288:   PetscFunctionBegin;
    289:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
    290:   if (rank == 0) {
    291:     char   c = (char)getchar();
    292:     size_t i = 0;

    294:     while (c != '\n' && i < n - 1) {
    295:       str[i++] = c;
    296:       c        = (char)getchar();
    297:     }
    298:     str[i] = '\0';
    299:   }
    300:   PetscCall(PetscMPIIntCast(n, &nm));
    301:   PetscCallMPI(MPI_Bcast(str, nm, MPI_CHAR, 0, comm));
    302:   PetscFunctionReturn(PETSC_SUCCESS);
    303: }

    305: /*
    306:   PetscOptionsGetFromTextInput - Presents all the PETSc Options processed by the program so the user may change them at runtime

    308:   Notes:
    309:   this isn't really practical, it is just to demonstrate the principle

    311:   A carriage return indicates no change from the default; but this like -ksp_monitor <stdout>  the default is actually not stdout the default
    312:   is to do nothing so to get it to use stdout you need to type stdout. This is kind of bug?

    314:   Bugs:
    315: +    All processes must traverse through the exact same set of option queries due to the call to PetscScanString()
    316: .    Internal strings have arbitrary length and string copies are not checked that they fit into string space
    317: -    Only works for PetscInt == int, PetscReal == double etc

    319:   Developer Notes:
    320:   Normally the GUI that presents the options the user and retrieves the values would be running in a different
    321:   address space and communicating with the PETSc program

    323: */
    324: static PetscErrorCode PetscOptionsGetFromTextInput(PetscOptionItems PetscOptionsObject)
    325: {
    326:   PetscOptionItem next = PetscOptionsObject->next;
    327:   char            str[512];
    328:   PetscBool       bid;
    329:   PetscReal       ir, *valr;
    330:   PetscInt       *vald;

    332:   PetscFunctionBegin;
    333:   PetscCall((*PetscPrintf)(PETSC_COMM_WORLD, "%s --------------------\n", PetscOptionsObject->title));
    334:   while (next) {
    335:     switch (next->type) {
    336:     case OPTION_HEAD:
    337:       break;
    338:     case OPTION_INT_ARRAY:
    339:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1));
    340:       vald = (PetscInt *)next->data;
    341:       for (PetscInt i = 0; i < next->arraylength; i++) {
    342:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT, vald[i]));
    343:         if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ","));
    344:       }
    345:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man));
    346:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
    347:       if (str[0]) {
    348:         PetscToken  token;
    349:         PetscInt    n = 0, nmax = next->arraylength, *dvalue = (PetscInt *)next->data, start, end;
    350:         size_t      len;
    351:         const char *value;
    352:         PetscBool   foundrange;

    354:         next->set = PETSC_TRUE;
    355:         value     = str;
    356:         PetscCall(PetscTokenCreate(value, ',', &token));
    357:         PetscCall(PetscTokenFind(token, &value));
    358:         while (n < nmax) {
    359:           char    *ivalue;
    360:           PetscInt i;

    362:           if (!value) break;
    363:           PetscCall(PetscStrallocpy(value, &ivalue));

    365:           /* look for form  d-D where d and D are integers */
    366:           foundrange = PETSC_FALSE;
    367:           PetscCall(PetscStrlen(ivalue, &len));
    368:           if (ivalue[0] == '-') i = 2;
    369:           else i = 1;
    370:           for (; i < (PetscInt)len; i++) {
    371:             if (ivalue[i] == '-') {
    372:               PetscCheck(i != (PetscInt)(len - 1), PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, ivalue);
    373:               ivalue[i] = 0;
    374:               PetscCall(PetscOptionsStringToInt(ivalue, &start));
    375:               PetscCall(PetscOptionsStringToInt(ivalue + i + 1, &end));
    376:               PetscCheck(end > start, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, %s-%s cannot have decreasing list", n, ivalue, ivalue + i + 1);
    377:               PetscCheck(n + end - start - 1 < nmax, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, not enough space in left in array (%" PetscInt_FMT ") to contain entire range from %" PetscInt_FMT " to %" PetscInt_FMT, n, nmax - n, start, end);
    378:               for (; start < end; start++) {
    379:                 *dvalue = start;
    380:                 dvalue++;
    381:                 n++;
    382:               }
    383:               foundrange = PETSC_TRUE;
    384:               break;
    385:             }
    386:           }
    387:           if (!foundrange) {
    388:             PetscCall(PetscOptionsStringToInt(ivalue, dvalue));
    389:             dvalue++;
    390:             n++;
    391:           }
    392:           PetscCall(PetscFree(ivalue));
    393:           PetscCall(PetscTokenFind(token, &value));
    394:         }
    395:         PetscCall(PetscTokenDestroy(&token));
    396:       }
    397:       break;
    398:     case OPTION_REAL_ARRAY:
    399:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1));
    400:       valr = (PetscReal *)next->data;
    401:       for (PetscInt i = 0; i < next->arraylength; i++) {
    402:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%g", (double)valr[i]));
    403:         if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ","));
    404:       }
    405:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man));
    406:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
    407:       if (str[0]) {
    408:         PetscToken  token;
    409:         PetscInt    n = 0, nmax = next->arraylength;
    410:         PetscReal  *dvalue = (PetscReal *)next->data;
    411:         const char *value;

    413:         next->set = PETSC_TRUE;
    414:         value     = str;
    415:         PetscCall(PetscTokenCreate(value, ',', &token));
    416:         PetscCall(PetscTokenFind(token, &value));
    417:         while (n < nmax) {
    418:           if (!value) break;
    419:           PetscCall(PetscOptionsStringToReal(value, dvalue));
    420:           dvalue++;
    421:           n++;
    422:           PetscCall(PetscTokenFind(token, &value));
    423:         }
    424:         PetscCall(PetscTokenDestroy(&token));
    425:       }
    426:       break;
    427:     case OPTION_INT:
    428:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%d>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(int *)next->data, next->text, next->man));
    429:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
    430:       if (str[0]) {
    431:   #if defined(PETSC_SIZEOF_LONG_LONG)
    432:         long long lid;
    433:         sscanf(str, "%lld", &lid);
    434:         PetscCheck(lid <= PETSC_INT_MAX && lid >= PETSC_INT_MIN, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %lld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid);
    435:   #else
    436:         long lid;
    437:         sscanf(str, "%ld", &lid);
    438:         PetscCheck(lid <= PETSC_INT_MAX && lid >= PETSC_INT_MIN, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %ld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid);
    439:   #endif

    441:         next->set                 = PETSC_TRUE;
    442:         *((PetscInt *)next->data) = (PetscInt)lid;
    443:       }
    444:       break;
    445:     case OPTION_REAL:
    446:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%g>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(double *)next->data, next->text, next->man));
    447:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
    448:       if (str[0]) {
    449:   #if defined(PETSC_USE_REAL_SINGLE)
    450:         sscanf(str, "%e", &ir);
    451:   #elif defined(PETSC_USE_REAL___FP16)
    452:         float irtemp;
    453:         sscanf(str, "%e", &irtemp);
    454:         ir = irtemp;
    455:   #elif defined(PETSC_USE_REAL_DOUBLE)
    456:         sscanf(str, "%le", &ir);
    457:   #elif defined(PETSC_USE_REAL___FLOAT128)
    458:         ir = strtoflt128(str, 0);
    459:   #else
    460:         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Unknown scalar type");
    461:   #endif
    462:         next->set                  = PETSC_TRUE;
    463:         *((PetscReal *)next->data) = ir;
    464:       }
    465:       break;
    466:     case OPTION_BOOL:
    467:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%s>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(PetscBool *)next->data ? "true" : "false", next->text, next->man));
    468:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
    469:       if (str[0]) {
    470:         PetscCall(PetscOptionsStringToBool(str, &bid));
    471:         next->set                  = PETSC_TRUE;
    472:         *((PetscBool *)next->data) = bid;
    473:       }
    474:       break;
    475:     case OPTION_STRING:
    476:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%s>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, (char *)next->data, next->text, next->man));
    477:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
    478:       if (str[0]) {
    479:         next->set = PETSC_TRUE;
    480:         /* must use system malloc since SAWs may free this */
    481:         PetscCall(PetscStrdup(str, (char **)&next->data));
    482:       }
    483:       break;
    484:     case OPTION_FLIST:
    485:       PetscCall(PetscFunctionListPrintTypes(PETSC_COMM_WORLD, stdout, PetscOptionsObject->prefix, next->option, next->text, next->man, next->flist, (char *)next->data, (char *)next->data));
    486:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
    487:       if (str[0]) {
    488:         PetscOptionsObject->changedmethod = PETSC_TRUE;
    489:         next->set                         = PETSC_TRUE;
    490:         /* must use system malloc since SAWs may free this */
    491:         PetscCall(PetscStrdup(str, (char **)&next->data));
    492:       }
    493:       break;
    494:     default:
    495:       break;
    496:     }
    497:     next = next->next;
    498:   }
    499:   PetscFunctionReturn(PETSC_SUCCESS);
    500: }
    501: #endif

    503: PetscErrorCode PetscOptionsEnd_Private(PetscOptionItems PetscOptionsObject)
    504: {
    505:   PetscOptionItem next, last;

    507:   PetscFunctionBegin;
    508:   if (PetscOptionsObject->next) {
    509:     if (!PetscOptionsObject->count) {
    510: #if defined(PETSC_HAVE_SAWS)
    511:       PetscCall(PetscOptionsSAWsInput(PetscOptionsObject));
    512: #else
    513:       PetscCall(PetscOptionsGetFromTextInput(PetscOptionsObject));
    514: #endif
    515:     }
    516:   }

    518:   PetscCall(PetscFree(PetscOptionsObject->title));

    520:   /* reset counter to -2; this updates the screen with the new options for the selected method */
    521:   if (PetscOptionsObject->changedmethod) PetscOptionsObject->count = -2;
    522:   /* reset alreadyprinted flag */
    523:   PetscOptionsObject->alreadyprinted = PETSC_FALSE;
    524:   if (PetscOptionsObject->object) PetscOptionsObject->object->optionsprinted = PETSC_TRUE;
    525:   PetscOptionsObject->object = NULL;

    527:   while ((next = PetscOptionsObject->next)) {
    528:     const PetscOptionType type        = next->type;
    529:     const size_t          arraylength = next->arraylength;
    530:     void                 *data        = next->data;

    532:     if (next->set) {
    533:       char option[256], value[1024], tmp[32];

    535:       if (PetscOptionsObject->prefix) {
    536:         PetscCall(PetscStrncpy(option, "-", sizeof(option)));
    537:         PetscCall(PetscStrlcat(option, PetscOptionsObject->prefix, sizeof(option)));
    538:         PetscCall(PetscStrlcat(option, next->option + 1, sizeof(option)));
    539:       } else {
    540:         PetscCall(PetscStrncpy(option, next->option, sizeof(option)));
    541:       }

    543:       switch (type) {
    544:       case OPTION_HEAD:
    545:         break;
    546:       case OPTION_INT_ARRAY:
    547:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%" PetscInt_FMT, ((PetscInt *)data)[0]));
    548:         for (size_t j = 1; j < arraylength; ++j) {
    549:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%" PetscInt_FMT, ((PetscInt *)data)[j]));
    550:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
    551:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
    552:         }
    553:         break;
    554:       case OPTION_INT:
    555:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%" PetscInt_FMT, *(PetscInt *)data));
    556:         break;
    557:       case OPTION_REAL:
    558:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)*(PetscReal *)data));
    559:         break;
    560:       case OPTION_REAL_ARRAY:
    561:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)((PetscReal *)data)[0]));
    562:         for (size_t j = 1; j < arraylength; ++j) {
    563:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g", (double)((PetscReal *)data)[j]));
    564:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
    565:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
    566:         }
    567:         break;
    568:       case OPTION_SCALAR_ARRAY:
    569:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[0]), (double)PetscImaginaryPart(((PetscScalar *)data)[0])));
    570:         for (size_t j = 1; j < arraylength; ++j) {
    571:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[j]), (double)PetscImaginaryPart(((PetscScalar *)data)[j])));
    572:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
    573:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
    574:         }
    575:         break;
    576:       case OPTION_BOOL:
    577:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", *(int *)data));
    578:         break;
    579:       case OPTION_BOOL_ARRAY:
    580:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscBool *)data)[0]));
    581:         for (size_t j = 1; j < arraylength; ++j) {
    582:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscBool *)data)[j]));
    583:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
    584:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
    585:         }
    586:         break;
    587:       case OPTION_FLIST: // fall-through
    588:       case OPTION_ELIST: // fall-through
    589:       case OPTION_STRING:
    590:         PetscCall(PetscStrncpy(value, (char *)data, sizeof(value)));
    591:         break;
    592:       case OPTION_STRING_ARRAY:
    593:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%s", ((char **)data)[0]));
    594:         for (size_t j = 1; j < arraylength; j++) {
    595:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%s", ((char **)data)[j]));
    596:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
    597:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
    598:         }
    599:         break;
    600:       }
    601:       PetscCall(PetscOptionsSetValue(PetscOptionsObject->options, option, value));
    602:     }
    603:     if (type == OPTION_ELIST) PetscCall(PetscStrNArrayDestroy(next->nlist, (char ***)&next->list));
    604:     PetscCall(PetscFree(next->text));
    605:     PetscCall(PetscFree(next->option));
    606:     PetscCall(PetscFree(next->man));
    607:     PetscCall(PetscFree(next->edata));

    609:     if (type == OPTION_STRING || type == OPTION_FLIST || type == OPTION_ELIST) {
    610:       free(data);
    611:     } else {
    612:       // use next->data instead of data because PetscFree() sets it to NULL
    613:       PetscCall(PetscFree(next->data));
    614:     }

    616:     last                     = next;
    617:     PetscOptionsObject->next = next->next;
    618:     PetscCall(PetscFree(last));
    619:   }
    620:   PetscCall(PetscFree(PetscOptionsObject->prefix));
    621:   PetscOptionsObject->next = NULL;
    622:   PetscFunctionReturn(PETSC_SUCCESS);
    623: }

    625: static PetscErrorCode GetListLength(const char *const *list, PetscInt *len)
    626: {
    627:   PetscInt retlen = 0;

    629:   PetscFunctionBegin;
    630:   PetscAssertPointer(len, 2);
    631:   while (list[retlen]) {
    632:     PetscAssertPointer(list[retlen], 1);
    633:     PetscCheck(++retlen < 50, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "List argument appears to be wrong or have more than 50 entries");
    634:   }
    635:   PetscCheck(retlen > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least 2 entries: typename and type prefix");
    636:   /* drop item name and prefix*/
    637:   *len = retlen - 2;
    638:   PetscFunctionReturn(PETSC_SUCCESS);
    639: }

    641: PetscErrorCode PetscOptionsEnum_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum currentvalue, PetscEnum *value, PetscBool *set)
    642: {
    643:   PetscInt  ntext = 0;
    644:   PetscInt  tval;
    645:   PetscBool tflg;

    647:   PetscFunctionBegin;
    648:   PetscAssertPointer(opt, 2);
    649:   PetscAssertPointer(list, 5);
    650:   PetscAssertPointer(value, 7);
    651:   if (set) PetscAssertPointer(set, 8);
    652:   PetscCall(GetListLength(list, &ntext));
    653:   PetscCall(PetscOptionsEList_Private(PetscOptionsObject, opt, text, man, list, ntext, list[(int)currentvalue], &tval, &tflg));
    654:   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
    655:   if (tflg) *value = (PetscEnum)tval;
    656:   if (set) *set = tflg;
    657:   PetscFunctionReturn(PETSC_SUCCESS);
    658: }

    660: PetscErrorCode PetscOptionsEnumArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum value[], PetscInt *n, PetscBool *set)
    661: {
    662:   PetscInt    nlist  = 0;
    663:   const char *prefix = PetscOptionsObject->prefix;

    665:   PetscFunctionBegin;
    666:   PetscAssertPointer(opt, 2);
    667:   PetscAssertPointer(list, 5);
    668:   PetscAssertPointer(value, 6);
    669:   PetscAssertPointer(n, 7);
    670:   PetscCheck(*n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") must be > 0", *n);
    671:   if (set) PetscAssertPointer(set, 8);
    672:   PetscCall(GetListLength(list, &nlist));
    673:   const PetscInt nin = *n;
    674:   PetscCall(PetscOptionsGetEnumArray(PetscOptionsObject->options, prefix, opt, list, value, n, set));
    675:   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
    676:     const MPI_Comm comm = PetscOptionsObject->comm;
    677:     const PetscInt nv   = *n;

    679:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%s", Prefix(prefix), opt + 1, list[value[0]]));
    680:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%s", list[value[i]]));
    681:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (choose from)", text));
    682:     for (PetscInt i = 0; i < nlist; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i]));
    683:     PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man)));
    684:   }
    685:   PetscFunctionReturn(PETSC_SUCCESS);
    686: }

    688: PetscErrorCode PetscOptionsInt_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt currentvalue, PetscInt *value, PetscBool *set, PetscInt lb, PetscInt ub)
    689: {
    690:   const char        *prefix  = PetscOptionsObject->prefix;
    691:   const PetscOptions options = PetscOptionsObject->options;
    692:   PetscBool          wasset;

    694:   PetscFunctionBegin;
    695:   PetscAssertPointer(opt, 2);
    696:   PetscAssertPointer(value, 6);
    697:   if (set) PetscAssertPointer(set, 7);
    698:   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, currentvalue, lb);
    699:   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, currentvalue, ub);
    700:   if (!PetscOptionsObject->count) {
    701:     PetscOptionItem amsopt;

    703:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
    704:     PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
    705:     *(PetscInt *)amsopt->data = currentvalue;

    707:     PetscCall(PetscOptionsGetInt(options, prefix, opt, &currentvalue, &wasset));
    708:     if (wasset) *(PetscInt *)amsopt->data = currentvalue;
    709:   }
    710:   PetscCall(PetscOptionsGetInt(options, prefix, opt, value, &wasset));
    711:   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, *value, lb);
    712:   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, *value, ub);
    713:   if (set) *set = wasset;
    714:   if (ShouldPrintHelp(PetscOptionsObject)) {
    715:     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %" PetscInt_FMT " : formerly %" PetscInt_FMT ">: %s (%s)\n", Prefix(prefix), opt + 1, wasset ? *value : currentvalue, currentvalue, text, ManSection(man)));
    716:   }
    717:   PetscFunctionReturn(PETSC_SUCCESS);
    718: }

    720: PetscErrorCode PetscOptionsMPIInt_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscMPIInt currentvalue, PetscMPIInt *value, PetscBool *set, PetscMPIInt lb, PetscMPIInt ub)
    721: {
    722:   const char        *prefix  = PetscOptionsObject->prefix;
    723:   const PetscOptions options = PetscOptionsObject->options;
    724:   PetscBool          wasset;

    726:   PetscFunctionBegin;
    727:   PetscAssertPointer(opt, 2);
    728:   PetscAssertPointer(value, 6);
    729:   if (set) PetscAssertPointer(set, 7);
    730:   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d less than allowed bound %d", currentvalue, lb);
    731:   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d greater than allowed bound %d", currentvalue, ub);
    732:   if (!PetscOptionsObject->count) {
    733:     PetscOptionItem amsopt;

    735:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
    736:     PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
    737:     *(PetscMPIInt *)amsopt->data = currentvalue;

    739:     PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, &currentvalue, &wasset));
    740:     if (wasset) *(PetscMPIInt *)amsopt->data = currentvalue;
    741:   }
    742:   PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, value, &wasset));
    743:   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d less than allowed bound %d", *value, lb);
    744:   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d greater than allowed bound %d", *value, ub);
    745:   if (set) *set = wasset;
    746:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %d : formerly %d>: %s (%s)\n", Prefix(prefix), opt + 1, wasset ? *value : currentvalue, currentvalue, text, ManSection(man)));
    747:   PetscFunctionReturn(PETSC_SUCCESS);
    748: }

    750: PetscErrorCode PetscOptionsString_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], const char currentvalue[], char value[], size_t len, PetscBool *set)
    751: {
    752:   const char *prefix = PetscOptionsObject->prefix;
    753:   PetscBool   lset;

    755:   PetscFunctionBegin;
    756:   PetscAssertPointer(opt, 2);
    757:   PetscAssertPointer(value, 6);
    758:   if (set) PetscAssertPointer(set, 8);
    759:   if (!PetscOptionsObject->count) {
    760:     PetscOptionItem amsopt;

    762:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
    763:     /* must use system malloc since SAWs may free this */
    764:     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
    765:   }
    766:   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset));
    767:   if (set) *set = lset;
    768:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %s : formerly %s>: %s (%s)\n", Prefix(prefix), opt + 1, lset ? value : currentvalue, currentvalue, text, ManSection(man)));
    769:   PetscFunctionReturn(PETSC_SUCCESS);
    770: }

    772: PetscErrorCode PetscOptionsReal_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal currentvalue, PetscReal *value, PetscBool *set, PetscReal lb, PetscReal ub)
    773: {
    774:   const char        *prefix  = PetscOptionsObject->prefix;
    775:   const PetscOptions options = PetscOptionsObject->options;
    776:   PetscBool          wasset;

    778:   PetscFunctionBegin;
    779:   PetscAssertPointer(opt, 2);
    780:   PetscAssertPointer(value, 6);
    781:   if (set) PetscAssertPointer(set, 7);
    782:   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g less than allowed bound %g", (double)currentvalue, (double)lb);
    783:   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g greater than allowed bound %g", (double)currentvalue, (double)ub);
    784:   if (!PetscOptionsObject->count) {
    785:     PetscOptionItem amsopt;

    787:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt));
    788:     PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data));
    789:     *(PetscReal *)amsopt->data = currentvalue;

    791:     PetscCall(PetscOptionsGetReal(options, prefix, opt, &currentvalue, &wasset));
    792:     if (wasset) *(PetscReal *)amsopt->data = currentvalue;
    793:   }
    794:   PetscCall(PetscOptionsGetReal(PetscOptionsObject->options, prefix, opt, value, &wasset));
    795:   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g less than allowed bound %g", (double)*value, (double)lb);
    796:   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g greater than allowed bound %g", (double)*value, (double)ub);
    797:   if (set) *set = wasset;
    798:   if (ShouldPrintHelp(PetscOptionsObject)) {
    799:     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %g : formerly %g>: %s (%s)\n", Prefix(prefix), opt + 1, wasset ? (double)*value : (double)currentvalue, (double)currentvalue, text, ManSection(man)));
    800:   }
    801:   PetscFunctionReturn(PETSC_SUCCESS);
    802: }

    804: PetscErrorCode PetscOptionsScalar_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar currentvalue, PetscScalar *value, PetscBool *set)
    805: {
    806:   PetscFunctionBegin;
    807: #if !defined(PETSC_USE_COMPLEX)
    808:   PetscCall(PetscOptionsReal(opt, text, man, currentvalue, value, set));
    809: #else
    810:   PetscCall(PetscOptionsGetScalar(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, set));
    811: #endif
    812:   PetscFunctionReturn(PETSC_SUCCESS);
    813: }

    815: PetscErrorCode PetscOptionsName_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
    816: {
    817:   const char *prefix = PetscOptionsObject->prefix;

    819:   PetscFunctionBegin;
    820:   PetscAssertPointer(opt, 2);
    821:   PetscAssertPointer(flg, 5);
    822:   if (!PetscOptionsObject->count) {
    823:     PetscOptionItem amsopt;

    825:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
    826:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

    828:     *(PetscBool *)amsopt->data = PETSC_FALSE;
    829:   }
    830:   PetscCall(PetscOptionsHasName(PetscOptionsObject->options, prefix, opt, flg));
    831:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
    832:   PetscFunctionReturn(PETSC_SUCCESS);
    833: }

    835: PetscErrorCode PetscOptionsFList_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char ltext[], const char man[], PetscFunctionList list, const char currentvalue[], char value[], size_t len, PetscBool *set)
    836: {
    837:   const char *prefix = PetscOptionsObject->prefix;
    838:   PetscBool   lset;

    840:   PetscFunctionBegin;
    841:   PetscAssertPointer(opt, 2);
    842:   PetscAssertPointer(value, 7);
    843:   if (set) PetscAssertPointer(set, 9);
    844:   if (!PetscOptionsObject->count) {
    845:     PetscOptionItem amsopt;

    847:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_FLIST, &amsopt));
    848:     /* must use system malloc since SAWs may free this */
    849:     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
    850:     amsopt->flist = list;
    851:   }
    852:   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset));
    853:   if (set) *set = lset;
    854:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall(PetscFunctionListPrintTypes(PetscOptionsObject->comm, stdout, Prefix(prefix), opt, ltext, man, list, currentvalue, lset ? value : currentvalue));
    855:   PetscFunctionReturn(PETSC_SUCCESS);
    856: }

    858: #ifdef __cplusplus
    859:   #include <type_traits>
    860: #endif

    862: PetscErrorCode PetscOptionsEList_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char ltext[], const char man[], const char *const *list, PetscInt ntext, const char currentvalue[], PetscInt *value, PetscBool *set)
    863: {
    864:   const char *prefix = PetscOptionsObject->prefix;
    865:   PetscBool   lset;

    867:   PetscFunctionBegin;
    868:   PetscAssertPointer(opt, 2);
    869:   PetscAssertPointer(value, 8);
    870:   if (set) PetscAssertPointer(set, 9);
    871:   if (!PetscOptionsObject->count) {
    872:     PetscOptionItem amsopt;

    874:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_ELIST, &amsopt));
    875:     /* must use system malloc since SAWs may free this */
    876:     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
    877:     PetscCall(PetscStrNArrayallocpy(ntext, list, (char ***)&amsopt->list));
    878:     PetscCheck(ntext <= CHAR_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of list entries %" PetscInt_FMT " > %d", ntext, CHAR_MAX);
    879: #ifdef __cplusplus
    880:     static_assert(std::is_same<typename std::decay<decltype(amsopt->nlist)>::type, char>::value, "");
    881: #endif
    882:     amsopt->nlist = (char)ntext;
    883:   }
    884:   PetscCall(PetscOptionsGetEList(PetscOptionsObject->options, prefix, opt, list, ntext, value, &lset));
    885:   if (set) *set = lset;
    886:   if (ShouldPrintHelp(PetscOptionsObject)) {
    887:     const MPI_Comm comm = PetscOptionsObject->comm;

    889:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <now %s : formerly %s> %s (choose one of)", Prefix(prefix), opt + 1, lset ? list[*value] : currentvalue, currentvalue, ltext));
    890:     for (PetscInt i = 0; i < ntext; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i]));
    891:     PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man)));
    892:   }
    893:   PetscFunctionReturn(PETSC_SUCCESS);
    894: }

    896: PetscErrorCode PetscOptionsBoolGroupBegin_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
    897: {
    898:   const char *prefix = PetscOptionsObject->prefix;

    900:   PetscFunctionBegin;
    901:   PetscAssertPointer(opt, 2);
    902:   PetscAssertPointer(flg, 5);
    903:   if (!PetscOptionsObject->count) {
    904:     PetscOptionItem amsopt;

    906:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
    907:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

    909:     *(PetscBool *)amsopt->data = PETSC_FALSE;
    910:   }
    911:   *flg = PETSC_FALSE;
    912:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
    913:   if (ShouldPrintHelp(PetscOptionsObject)) {
    914:     const MPI_Comm comm = PetscOptionsObject->comm;

    916:     PetscCall((*PetscHelpPrintf)(comm, "  Pick at most one of -------------\n"));
    917:     PetscCall((*PetscHelpPrintf)(comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
    918:   }
    919:   PetscFunctionReturn(PETSC_SUCCESS);
    920: }

    922: PetscErrorCode PetscOptionsBoolGroup_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
    923: {
    924:   const char *prefix = PetscOptionsObject->prefix;

    926:   PetscFunctionBegin;
    927:   PetscAssertPointer(opt, 2);
    928:   PetscAssertPointer(flg, 5);
    929:   if (!PetscOptionsObject->count) {
    930:     PetscOptionItem amsopt;

    932:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
    933:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

    935:     *(PetscBool *)amsopt->data = PETSC_FALSE;
    936:   }
    937:   *flg = PETSC_FALSE;
    938:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
    939:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
    940:   PetscFunctionReturn(PETSC_SUCCESS);
    941: }

    943: PetscErrorCode PetscOptionsBoolGroupEnd_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
    944: {
    945:   const char *prefix = PetscOptionsObject->prefix;

    947:   PetscFunctionBegin;
    948:   PetscAssertPointer(opt, 2);
    949:   PetscAssertPointer(flg, 5);
    950:   if (!PetscOptionsObject->count) {
    951:     PetscOptionItem amsopt;

    953:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
    954:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

    956:     *(PetscBool *)amsopt->data = PETSC_FALSE;
    957:   }
    958:   *flg = PETSC_FALSE;
    959:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
    960:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
    961:   PetscFunctionReturn(PETSC_SUCCESS);
    962: }

    964: PetscErrorCode PetscOptionsBool_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool currentvalue, PetscBool *flg, PetscBool *set)
    965: {
    966:   const char *prefix = PetscOptionsObject->prefix;
    967:   PetscBool   iset;

    969:   PetscFunctionBegin;
    970:   PetscAssertPointer(opt, 2);
    971:   PetscAssertPointer(flg, 6);
    972:   if (set) PetscAssertPointer(set, 7);
    973:   if (!PetscOptionsObject->count) {
    974:     PetscOptionItem amsopt;

    976:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
    977:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

    979:     *(PetscBool *)amsopt->data = currentvalue;
    980:   }
    981:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, &iset));
    982:   if (set) *set = iset;
    983:   if (ShouldPrintHelp(PetscOptionsObject)) {
    984:     const char *curvalue = PetscBools[currentvalue];

    986:     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %s : formerly %s> %s (%s)\n", Prefix(prefix), opt + 1, iset ? PetscBools[*flg] : curvalue, curvalue, text, ManSection(man)));
    987:   }
    988:   PetscFunctionReturn(PETSC_SUCCESS);
    989: }

    991: PetscErrorCode PetscOptionsBool3_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool3 currentvalue, PetscBool3 *flg, PetscBool *set)
    992: {
    993:   const char *prefix = PetscOptionsObject->prefix;
    994:   PetscBool   iset;

    996:   PetscFunctionBegin;
    997:   PetscAssertPointer(opt, 2);
    998:   PetscAssertPointer(flg, 6);
    999:   if (set) PetscAssertPointer(set, 7);
    1000:   PetscCall(PetscOptionsGetBool3(PetscOptionsObject->options, prefix, opt, flg, &iset));
    1001:   if (set) *set = iset;
    1002:   if (ShouldPrintHelp(PetscOptionsObject)) {
    1003:     const char *curvalue = PetscBool3s[currentvalue];

    1005:     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %s : formerly %s> %s (%s)\n", Prefix(prefix), opt + 1, iset ? PetscBools[*flg] : curvalue, curvalue, text, ManSection(man)));
    1006:   }
    1007:   PetscFunctionReturn(PETSC_SUCCESS);
    1008: }

    1010: PetscErrorCode PetscOptionsRealArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal value[], PetscInt *n, PetscBool *set)
    1011: {
    1012:   const char *prefix = PetscOptionsObject->prefix;

    1014:   PetscFunctionBegin;
    1015:   PetscAssertPointer(opt, 2);
    1016:   PetscAssertPointer(n, 6);
    1017:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
    1018:   if (*n) PetscAssertPointer(value, 5);
    1019:   if (set) PetscAssertPointer(set, 7);
    1020:   if (!PetscOptionsObject->count) {
    1021:     const PetscInt  nv = *n;
    1022:     PetscReal      *vals;
    1023:     PetscOptionItem amsopt;

    1025:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt));
    1026:     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
    1027:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
    1028:     amsopt->arraylength = nv;
    1029:     amsopt->data        = vals;
    1030:   }
    1031:   const PetscInt nin = *n;
    1032:   PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, prefix, opt, value, n, set));
    1033:   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
    1034:     const PetscInt nv   = *n;
    1035:     const MPI_Comm comm = PetscOptionsObject->comm;

    1037:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g", Prefix(prefix), opt + 1, (double)value[0]));
    1038:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g", (double)value[i]));
    1039:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
    1040:   }
    1041:   PetscFunctionReturn(PETSC_SUCCESS);
    1042: }

    1044: PetscErrorCode PetscOptionsScalarArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar value[], PetscInt *n, PetscBool *set)
    1045: {
    1046:   const char *prefix = PetscOptionsObject->prefix;

    1048:   PetscFunctionBegin;
    1049:   PetscAssertPointer(opt, 2);
    1050:   PetscAssertPointer(n, 6);
    1051:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
    1052:   if (*n) PetscAssertPointer(value, 5);
    1053:   if (set) PetscAssertPointer(set, 7);
    1054:   if (!PetscOptionsObject->count) {
    1055:     const PetscInt  nv = *n;
    1056:     PetscOptionItem amsopt;
    1057:     PetscScalar    *vals;

    1059:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt));
    1060:     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
    1061:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
    1062:     amsopt->arraylength = nv;
    1063:     amsopt->data        = vals;
    1064:   }
    1065:   const PetscInt nin = *n;
    1066:   PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, prefix, opt, value, n, set));
    1067:   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
    1068:     const PetscInt nv   = *n;
    1069:     const MPI_Comm comm = PetscOptionsObject->comm;

    1071:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g+%gi", Prefix(prefix), opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0])));
    1072:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i])));
    1073:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
    1074:   }
    1075:   PetscFunctionReturn(PETSC_SUCCESS);
    1076: }

    1078: PetscErrorCode PetscOptionsIntArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt value[], PetscInt *n, PetscBool *set)
    1079: {
    1080:   const char *prefix = PetscOptionsObject->prefix;

    1082:   PetscFunctionBegin;
    1083:   PetscAssertPointer(opt, 2);
    1084:   PetscAssertPointer(n, 6);
    1085:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
    1086:   if (*n) PetscAssertPointer(value, 5);
    1087:   if (set) PetscAssertPointer(set, 7);
    1088:   if (!PetscOptionsObject->count) {
    1089:     const PetscInt  nv = *n;
    1090:     PetscInt       *vals;
    1091:     PetscOptionItem amsopt;

    1093:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY, &amsopt));
    1094:     PetscCall(PetscMalloc1(nv, &vals));
    1095:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
    1096:     amsopt->arraylength = nv;
    1097:     amsopt->data        = vals;
    1098:   }
    1099:   const PetscInt nin = *n;
    1100:   PetscCall(PetscOptionsGetIntArray(PetscOptionsObject->options, prefix, opt, value, n, set));
    1101:   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
    1102:     const PetscInt nv   = *n;
    1103:     const MPI_Comm comm = PetscOptionsObject->comm;

    1105:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%" PetscInt_FMT, Prefix(prefix), opt + 1, value[0]));
    1106:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%" PetscInt_FMT, value[i]));
    1107:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
    1108:   }
    1109:   PetscFunctionReturn(PETSC_SUCCESS);
    1110: }

    1112: PetscErrorCode PetscOptionsStringArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], char *value[], PetscInt *nmax, PetscBool *set)
    1113: {
    1114:   const char *prefix = PetscOptionsObject->prefix;

    1116:   PetscFunctionBegin;
    1117:   PetscAssertPointer(opt, 2);
    1118:   PetscAssertPointer(nmax, 6);
    1119:   PetscCheck(*nmax >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *nmax);
    1120:   if (*nmax) PetscAssertPointer(value, 5);
    1121:   if (set) PetscAssertPointer(set, 7);
    1122:   if (!PetscOptionsObject->count) {
    1123:     const PetscInt  nmaxv = *nmax;
    1124:     PetscOptionItem amsopt;

    1126:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt));
    1127:     PetscCall(PetscMalloc1(nmaxv, (char **)&amsopt->data));
    1128:     amsopt->arraylength = nmaxv;
    1129:   }
    1130:   const PetscInt nin = *nmax;
    1131:   PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, prefix, opt, value, nmax, set));
    1132:   if (ShouldPrintHelp(PetscOptionsObject) && nin) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <string1,string2,...>: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
    1133:   PetscFunctionReturn(PETSC_SUCCESS);
    1134: }

    1136: PetscErrorCode PetscOptionsBoolArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool value[], PetscInt *n, PetscBool *set)
    1137: {
    1138:   const char *prefix = PetscOptionsObject->prefix;

    1140:   PetscFunctionBegin;
    1141:   PetscAssertPointer(opt, 2);
    1142:   PetscAssertPointer(n, 6);
    1143:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
    1144:   if (*n) PetscAssertPointer(value, 5);
    1145:   if (set) PetscAssertPointer(set, 7);
    1146:   if (!PetscOptionsObject->count) {
    1147:     const PetscInt  nv = *n;
    1148:     PetscBool      *vals;
    1149:     PetscOptionItem amsopt;

    1151:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt));
    1152:     PetscCall(PetscMalloc1(nv, &vals));
    1153:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
    1154:     amsopt->arraylength = nv;
    1155:     amsopt->data        = vals;
    1156:   }
    1157:   const PetscInt nin = *n;
    1158:   PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, prefix, opt, value, n, set));
    1159:   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
    1160:     const PetscInt nv   = *n;
    1161:     const MPI_Comm comm = PetscOptionsObject->comm;

    1163:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%d", Prefix(prefix), opt + 1, value[0]));
    1164:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%d", value[i]));
    1165:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
    1166:   }
    1167:   PetscFunctionReturn(PETSC_SUCCESS);
    1168: }

    1170: /*MC
    1171:   PetscOptionsViewer - Creates a viewer appropriate for the type indicated by the user

    1173:   Synopsis:
    1174: #include <petscviewer.h>
    1175:   PetscErrorCode PetscOptionsViewer(const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)

    1177:   Logically Collective on the communicator passed in `PetscOptionsBegin()`

    1179:   Input Parameters:
    1180: + opt  - option name
    1181: . text - short string that describes the option
    1182: - man  - manual page with additional information on option

    1184:   Output Parameters:
    1185: + viewer - the viewer
    1186: . format - the PetscViewerFormat requested by the user, pass `NULL` if not needed
    1187: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    1189:   Level: beginner

    1191:   Notes:
    1192:   Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`

    1194:   See `PetscOptionsCreateViewer()` for the format of the supplied viewer and its options

    1196: .seealso: `PetscOptionsCreateViewer()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
    1197:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
    1198:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
    1199:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    1200:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    1201:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    1202:           `PetscOptionsFList()`, `PetscOptionsEList()`
    1203: M*/
    1204: PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
    1205: {
    1206:   const MPI_Comm comm   = PetscOptionsObject->comm;
    1207:   const char    *prefix = PetscOptionsObject->prefix;

    1209:   PetscFunctionBegin;
    1210:   PetscAssertPointer(opt, 2);
    1211:   PetscAssertPointer(viewer, 5);
    1212:   if (format) PetscAssertPointer(format, 6);
    1213:   if (set) PetscAssertPointer(set, 7);
    1214:   if (!PetscOptionsObject->count) {
    1215:     PetscOptionItem amsopt;

    1217:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
    1218:     /* must use system malloc since SAWs may free this */
    1219:     PetscCall(PetscStrdup("", (char **)&amsopt->data));
    1220:   }
    1221:   PetscCall(PetscOptionsCreateViewer(comm, PetscOptionsObject->options, prefix, opt, viewer, format, set));
    1222:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%s>: %s (%s)\n", Prefix(prefix), opt + 1, "", text, ManSection(man)));
    1223:   PetscFunctionReturn(PETSC_SUCCESS);
    1224: }