Actual source code: options.c

      1: /* Define Feature test macros to make sure atoll is available (SVr4, POSIX.1-2001, 4.3BSD, C99), not in (C89 and POSIX.1-1996) */
      2: #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for atoll() */

      4: /*
      5:    These routines simplify the use of command line, file options, etc., and are used to manipulate the options database.
      6:    This provides the low-level interface, the high level interface is in aoptions.c

      8:    Some routines use regular malloc and free because it cannot know  what malloc is requested with the
      9:    options database until it has already processed the input.
     10: */

     12: #include <petsc/private/petscimpl.h>
     13: #include <petscviewer.h>
     14: #include <ctype.h>
     15: #if defined(PETSC_HAVE_MALLOC_H)
     16:   #include <malloc.h>
     17: #endif
     18: #if defined(PETSC_HAVE_STRINGS_H)
     19:   #include <strings.h> /* strcasecmp */
     20: #endif

     22: #if defined(PETSC_HAVE_STRCASECMP)
     23:   #define PetscOptNameCmp(a, b) strcasecmp(a, b)
     24: #elif defined(PETSC_HAVE_STRICMP)
     25:   #define PetscOptNameCmp(a, b) stricmp(a, b)
     26: #else
     27:   #define PetscOptNameCmp(a, b) Error_strcasecmp_not_found
     28: #endif

     30: #include <petsc/private/hashtable.h>

     32: /* This assumes ASCII encoding and ignores locale settings */
     33: /* Using tolower() is about 2X slower in microbenchmarks   */
     34: static inline int PetscToLower(int c)
     35: {
     36:   return ((c >= 'A') & (c <= 'Z')) ? c + 'a' - 'A' : c;
     37: }

     39: /* Bob Jenkins's one at a time hash function (case-insensitive) */
     40: static inline unsigned int PetscOptHash(const char key[])
     41: {
     42:   unsigned int hash = 0;
     43:   while (*key) {
     44:     hash += PetscToLower(*key++);
     45:     hash += hash << 10;
     46:     hash ^= hash >> 6;
     47:   }
     48:   hash += hash << 3;
     49:   hash ^= hash >> 11;
     50:   hash += hash << 15;
     51:   return hash;
     52: }

     54: static inline int PetscOptEqual(const char a[], const char b[])
     55: {
     56:   return !PetscOptNameCmp(a, b);
     57: }

     59: KHASH_INIT(HO, kh_cstr_t, int, 1, PetscOptHash, PetscOptEqual)

     61: #define MAXPREFIXES        25
     62: #define MAXOPTIONSMONITORS 5

     64: const char *PetscOptionSources[] = {"code", "command line", "file", "environment"};

     66: // This table holds all the options set by the user
     67: struct _n_PetscOptions {
     68:   PetscOptions previous;

     70:   int                N;      /* number of options */
     71:   int                Nalloc; /* number of allocated options */
     72:   char             **names;  /* option names */
     73:   char             **values; /* option values */
     74:   PetscBool         *used;   /* flag option use */
     75:   PetscOptionSource *source; /* source for option value */
     76:   PetscBool          precedentProcessed;

     78:   /* Hash table */
     79:   khash_t(HO) *ht;

     81:   /* Prefixes */
     82:   int  prefixind;
     83:   int  prefixstack[MAXPREFIXES];
     84:   char prefix[PETSC_MAX_OPTION_NAME];

     86:   /* Aliases */
     87:   int    Na;       /* number or aliases */
     88:   int    Naalloc;  /* number of allocated aliases */
     89:   char **aliases1; /* aliased */
     90:   char **aliases2; /* aliasee */

     92:   /* Help */
     93:   PetscBool help;       /* flag whether "-help" is in the database */
     94:   PetscBool help_intro; /* flag whether "-help intro" is in the database */

     96:   /* Monitors */
     97:   PetscBool monitorFromOptions, monitorCancel;
     98:   PetscErrorCode (*monitor[MAXOPTIONSMONITORS])(const char[], const char[], PetscOptionSource, void *); /* returns control to user after */
     99:   PetscCtxDestroyFn *monitordestroy[MAXOPTIONSMONITORS];                                                /* callback for monitor destruction */
    100:   void              *monitorcontext[MAXOPTIONSMONITORS];                                                /* to pass arbitrary user data into monitor */
    101:   PetscInt           numbermonitors;                                                                    /* to, for instance, detect options being set */
    102: };

    104: static PetscOptions defaultoptions = NULL; /* the options database routines query this object for options */

    106: /* list of options which precede others, i.e., are processed in PetscOptionsProcessPrecedentFlags() */
    107: /* these options can only take boolean values, the code will crash if given a non-boolean value */
    108: static const char *precedentOptions[] = {"-petsc_ci", "-options_monitor", "-options_monitor_cancel", "-help", "-skip_petscrc"};
    109: enum PetscPrecedentOption {
    110:   PO_CI_ENABLE,
    111:   PO_OPTIONS_MONITOR,
    112:   PO_OPTIONS_MONITOR_CANCEL,
    113:   PO_HELP,
    114:   PO_SKIP_PETSCRC,
    115:   PO_NUM
    116: };

    118: PETSC_INTERN PetscErrorCode PetscOptionsSetValue_Private(PetscOptions, const char[], const char[], int *, PetscOptionSource);
    119: PETSC_INTERN PetscErrorCode PetscOptionsInsertStringYAML_Private(PetscOptions, const char[], PetscOptionSource);

    121: /*
    122:     Options events monitor
    123: */
    124: static PetscErrorCode PetscOptionsMonitor(PetscOptions options, const char name[], const char value[], PetscOptionSource source)
    125: {
    126:   PetscFunctionBegin;
    127:   if (options->monitorFromOptions) PetscCall(PetscOptionsMonitorDefault(name, value, source, NULL));
    128:   for (PetscInt i = 0; i < options->numbermonitors; i++) PetscCall((*options->monitor[i])(name, value, source, options->monitorcontext[i]));
    129:   PetscFunctionReturn(PETSC_SUCCESS);
    130: }

    132: /*@
    133:   PetscOptionsCreate - Creates an empty options database.

    135:   Logically Collective

    137:   Output Parameter:
    138: . options - Options database object

    140:   Level: advanced

    142:   Note:
    143:   Though PETSc has a concept of multiple options database the current code uses a single default `PetscOptions` object

    145:   Developer Notes:
    146:   We may want eventually to pass a `MPI_Comm` to determine the ownership of the object

    148:   This object never got developed after being introduced, it is not clear that supporting multiple `PetscOptions` objects is useful

    150: .seealso: `PetscOptionsDestroy()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`
    151: @*/
    152: PetscErrorCode PetscOptionsCreate(PetscOptions *options)
    153: {
    154:   PetscFunctionBegin;
    155:   PetscAssertPointer(options, 1);
    156:   *options = (PetscOptions)calloc(1, sizeof(**options));
    157:   PetscCheck(*options, PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate the options database");
    158:   PetscFunctionReturn(PETSC_SUCCESS);
    159: }

    161: /*@
    162:   PetscOptionsDestroy - Destroys an option database.

    164:   Logically Collective on whatever communicator was associated with the call to `PetscOptionsCreate()`

    166:   Input Parameter:
    167: . options - the `PetscOptions` object

    169:   Level: advanced

    171: .seealso: `PetscOptionsInsert()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsSetValue()`
    172: @*/
    173: PetscErrorCode PetscOptionsDestroy(PetscOptions *options)
    174: {
    175:   PetscFunctionBegin;
    176:   PetscAssertPointer(options, 1);
    177:   if (!*options) PetscFunctionReturn(PETSC_SUCCESS);
    178:   PetscCheck(!(*options)->previous, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "You are destroying an option that has been used with PetscOptionsPush() but does not have a corresponding PetscOptionsPop()");
    179:   PetscCall(PetscOptionsClear(*options));
    180:   /* XXX what about monitors ? */
    181:   free(*options);
    182:   *options = NULL;
    183:   PetscFunctionReturn(PETSC_SUCCESS);
    184: }

    186: /*
    187:     PetscOptionsCreateDefault - Creates the default global options database
    188: */
    189: PetscErrorCode PetscOptionsCreateDefault(void)
    190: {
    191:   PetscFunctionBegin;
    192:   if (PetscUnlikely(!defaultoptions)) PetscCall(PetscOptionsCreate(&defaultoptions));
    193:   PetscFunctionReturn(PETSC_SUCCESS);
    194: }

    196: /*@
    197:   PetscOptionsPush - Push a new `PetscOptions` object as the default provider of options
    198:   Allows using different parts of a code to use different options databases

    200:   Logically Collective

    202:   Input Parameter:
    203: . opt - the options obtained with `PetscOptionsCreate()`

    205:   Level: advanced

    207:   Notes:
    208:   Use `PetscOptionsPop()` to return to the previous default options database

    210:   The collectivity of this routine is complex; only the MPI ranks that call this routine will
    211:   have the affect of these options. If some processes that create objects call this routine and others do
    212:   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
    213:   on different ranks.

    215:   Developer Notes:
    216:   Though this functionality has been provided it has never been used in PETSc and might be removed.

    218: .seealso: `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
    219: @*/
    220: PetscErrorCode PetscOptionsPush(PetscOptions opt)
    221: {
    222:   PetscFunctionBegin;
    223:   PetscCall(PetscOptionsCreateDefault());
    224:   opt->previous  = defaultoptions;
    225:   defaultoptions = opt;
    226:   PetscFunctionReturn(PETSC_SUCCESS);
    227: }

    229: /*@
    230:   PetscOptionsPop - Pop the most recent `PetscOptionsPush()` to return to the previous default options

    232:   Logically Collective on whatever communicator was associated with the call to `PetscOptionsCreate()`

    234:   Level: advanced

    236: .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
    237: @*/
    238: PetscErrorCode PetscOptionsPop(void)
    239: {
    240:   PetscOptions current = defaultoptions;

    242:   PetscFunctionBegin;
    243:   PetscCheck(defaultoptions, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing default options");
    244:   PetscCheck(defaultoptions->previous, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscOptionsPop() called too many times");
    245:   defaultoptions    = defaultoptions->previous;
    246:   current->previous = NULL;
    247:   PetscFunctionReturn(PETSC_SUCCESS);
    248: }

    250: /*
    251:     PetscOptionsDestroyDefault - Destroys the default global options database
    252: */
    253: PetscErrorCode PetscOptionsDestroyDefault(void)
    254: {
    255:   PetscFunctionBegin;
    256:   if (!defaultoptions) PetscFunctionReturn(PETSC_SUCCESS);
    257:   /* Destroy any options that the user forgot to pop */
    258:   while (defaultoptions->previous) {
    259:     PetscOptions tmp = defaultoptions;

    261:     PetscCall(PetscOptionsPop());
    262:     PetscCall(PetscOptionsDestroy(&tmp));
    263:   }
    264:   PetscCall(PetscOptionsDestroy(&defaultoptions));
    265:   PetscFunctionReturn(PETSC_SUCCESS);
    266: }

    268: /*@
    269:   PetscOptionsValidKey - PETSc Options database keys must begin with one or two dashes (-) followed by a letter.

    271:   Not Collective

    273:   Input Parameter:
    274: . key - string to check if valid

    276:   Output Parameter:
    277: . valid - `PETSC_TRUE` if a valid key

    279:   Level: intermediate

    281: .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`
    282: @*/
    283: PetscErrorCode PetscOptionsValidKey(const char key[], PetscBool *valid)
    284: {
    285:   char               *ptr;
    286:   PETSC_UNUSED double d;

    288:   PetscFunctionBegin;
    289:   if (key) PetscAssertPointer(key, 1);
    290:   PetscAssertPointer(valid, 2);
    291:   *valid = PETSC_FALSE;
    292:   if (!key) PetscFunctionReturn(PETSC_SUCCESS);
    293:   if (key[0] != '-') PetscFunctionReturn(PETSC_SUCCESS);
    294:   if (key[1] == '-') key++;
    295:   if (!isalpha((int)key[1])) PetscFunctionReturn(PETSC_SUCCESS);
    296:   d = strtod(key, &ptr);
    297:   if (ptr != key && !(*ptr == '_' || isalnum((int)*ptr))) PetscFunctionReturn(PETSC_SUCCESS);
    298:   *valid = PETSC_TRUE;
    299:   PetscFunctionReturn(PETSC_SUCCESS);
    300: }

    302: static PetscErrorCode PetscOptionsInsertString_Private(PetscOptions options, const char in_str[], PetscOptionSource source)
    303: {
    304:   const char *first, *second;
    305:   PetscToken  token;

    307:   PetscFunctionBegin;
    308:   PetscCall(PetscTokenCreate(in_str, ' ', &token));
    309:   PetscCall(PetscTokenFind(token, &first));
    310:   while (first) {
    311:     PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;

    313:     PetscCall(PetscStrcasecmp(first, "-options_file", &isfile));
    314:     PetscCall(PetscStrcasecmp(first, "-options_file_yaml", &isfileyaml));
    315:     PetscCall(PetscStrcasecmp(first, "-options_string_yaml", &isstringyaml));
    316:     PetscCall(PetscStrcasecmp(first, "-prefix_push", &ispush));
    317:     PetscCall(PetscStrcasecmp(first, "-prefix_pop", &ispop));
    318:     PetscCall(PetscOptionsValidKey(first, &key));
    319:     if (!key) {
    320:       PetscCall(PetscTokenFind(token, &first));
    321:     } else if (isfile) {
    322:       PetscCall(PetscTokenFind(token, &second));
    323:       PetscCall(PetscOptionsInsertFile(PETSC_COMM_SELF, options, second, PETSC_TRUE));
    324:       PetscCall(PetscTokenFind(token, &first));
    325:     } else if (isfileyaml) {
    326:       PetscCall(PetscTokenFind(token, &second));
    327:       PetscCall(PetscOptionsInsertFileYAML(PETSC_COMM_SELF, options, second, PETSC_TRUE));
    328:       PetscCall(PetscTokenFind(token, &first));
    329:     } else if (isstringyaml) {
    330:       PetscCall(PetscTokenFind(token, &second));
    331:       PetscCall(PetscOptionsInsertStringYAML_Private(options, second, source));
    332:       PetscCall(PetscTokenFind(token, &first));
    333:     } else if (ispush) {
    334:       PetscCall(PetscTokenFind(token, &second));
    335:       PetscCall(PetscOptionsPrefixPush(options, second));
    336:       PetscCall(PetscTokenFind(token, &first));
    337:     } else if (ispop) {
    338:       PetscCall(PetscOptionsPrefixPop(options));
    339:       PetscCall(PetscTokenFind(token, &first));
    340:     } else {
    341:       PetscCall(PetscTokenFind(token, &second));
    342:       PetscCall(PetscOptionsValidKey(second, &key));
    343:       if (!key) {
    344:         PetscCall(PetscOptionsSetValue_Private(options, first, second, NULL, source));
    345:         PetscCall(PetscTokenFind(token, &first));
    346:       } else {
    347:         PetscCall(PetscOptionsSetValue_Private(options, first, NULL, NULL, source));
    348:         first = second;
    349:       }
    350:     }
    351:   }
    352:   PetscCall(PetscTokenDestroy(&token));
    353:   PetscFunctionReturn(PETSC_SUCCESS);
    354: }

    356: /*@
    357:   PetscOptionsInsertString - Inserts options into the database from a string

    359:   Logically Collective

    361:   Input Parameters:
    362: + options - options object
    363: - in_str  - string that contains options separated by blanks

    365:   Level: intermediate

    367:   The collectivity of this routine is complex; only the MPI processes that call this routine will
    368:   have the affect of these options. If some processes that create objects call this routine and others do
    369:   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
    370:   on different ranks.

    372:    Contributed by Boyana Norris

    374: .seealso: `PetscOptionsSetValue()`, `PetscOptionsView()`, `PetscOptionsHasName()`, `PetscOptionsGetInt()`,
    375:           `PetscOptionsGetReal()`, `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
    376:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    377:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    378:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    379:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsInsertFile()`
    380: @*/
    381: PetscErrorCode PetscOptionsInsertString(PetscOptions options, const char in_str[])
    382: {
    383:   PetscFunctionBegin;
    384:   PetscCall(PetscOptionsInsertString_Private(options, in_str, PETSC_OPT_CODE));
    385:   PetscFunctionReturn(PETSC_SUCCESS);
    386: }

    388: /*
    389:     Returns a line (ended by a \n, \r or null character of any length. Result should be freed with free()
    390: */
    391: static char *Petscgetline(FILE *f)
    392: {
    393:   size_t size = 0;
    394:   size_t len  = 0;
    395:   size_t last = 0;
    396:   char  *buf  = NULL;

    398:   if (feof(f)) return NULL;
    399:   do {
    400:     size += 1024;                             /* BUFSIZ is defined as "the optimal read size for this platform" */
    401:     buf = (char *)realloc((void *)buf, size); /* realloc(NULL,n) is the same as malloc(n) */
    402:     /* Actually do the read. Note that fgets puts a terminal '\0' on the
    403:     end of the string, so we make sure we overwrite this */
    404:     if (!fgets(buf + len, 1024, f)) buf[len] = 0;
    405:     PetscCallAbort(PETSC_COMM_SELF, PetscStrlen(buf, &len));
    406:     last = len - 1;
    407:   } while (!feof(f) && buf[last] != '\n' && buf[last] != '\r');
    408:   if (len) return buf;
    409:   free(buf);
    410:   return NULL;
    411: }

    413: static PetscErrorCode PetscOptionsFilename(MPI_Comm comm, const char file[], char filename[PETSC_MAX_PATH_LEN], PetscBool *yaml)
    414: {
    415:   char fname[PETSC_MAX_PATH_LEN + 8], path[PETSC_MAX_PATH_LEN + 8], *tail;

    417:   PetscFunctionBegin;
    418:   *yaml = PETSC_FALSE;
    419:   PetscCall(PetscStrreplace(comm, file, fname, sizeof(fname)));
    420:   PetscCall(PetscFixFilename(fname, path));
    421:   PetscCall(PetscStrendswith(path, ":yaml", yaml));
    422:   if (*yaml) {
    423:     PetscCall(PetscStrrchr(path, ':', &tail));
    424:     tail[-1] = 0; /* remove ":yaml" suffix from path */
    425:   }
    426:   PetscCall(PetscStrncpy(filename, path, PETSC_MAX_PATH_LEN));
    427:   /* check for standard YAML and JSON filename extensions */
    428:   if (!*yaml) PetscCall(PetscStrendswith(filename, ".yaml", yaml));
    429:   if (!*yaml) PetscCall(PetscStrendswith(filename, ".yml", yaml));
    430:   if (!*yaml) PetscCall(PetscStrendswith(filename, ".json", yaml));
    431:   if (!*yaml) { /* check file contents */
    432:     PetscMPIInt rank;
    433:     PetscCallMPI(MPI_Comm_rank(comm, &rank));
    434:     if (rank == 0) {
    435:       FILE *fh = fopen(filename, "r");
    436:       if (fh) {
    437:         char buf[6] = "";
    438:         if (fread(buf, 1, 6, fh) > 0) {
    439:           PetscCall(PetscStrncmp(buf, "%YAML ", 6, yaml));          /* check for '%YAML' tag */
    440:           if (!*yaml) PetscCall(PetscStrncmp(buf, "---", 3, yaml)); /* check for document start */
    441:         }
    442:         (void)fclose(fh);
    443:       }
    444:     }
    445:     PetscCallMPI(MPI_Bcast(yaml, 1, MPI_C_BOOL, 0, comm));
    446:   }
    447:   PetscFunctionReturn(PETSC_SUCCESS);
    448: }

    450: static PetscErrorCode PetscOptionsInsertFilePetsc(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
    451: {
    452:   char       *string, *vstring = NULL, *astring = NULL, *packed = NULL;
    453:   const char *tokens[4];
    454:   size_t      len;
    455:   PetscCount  bytes;
    456:   FILE       *fd;
    457:   PetscToken  token = NULL;
    458:   int         err;
    459:   char       *cmatch = NULL;
    460:   const char  cmt    = '#';
    461:   PetscInt    line   = 1;
    462:   PetscMPIInt rank, cnt = 0, acnt = 0, counts[2];
    463:   PetscBool   isdir, alias = PETSC_FALSE, valid;

    465:   PetscFunctionBegin;
    466:   PetscCall(PetscMemzero(tokens, sizeof(tokens)));
    467:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
    468:   if (rank == 0) {
    469:     char fpath[PETSC_MAX_PATH_LEN];
    470:     char fname[PETSC_MAX_PATH_LEN];

    472:     PetscCall(PetscStrreplace(PETSC_COMM_SELF, file, fname, sizeof(fname)));
    473:     PetscCall(PetscFixFilename(fname, fpath));
    474:     PetscCall(PetscGetFullPath(fpath, fname, sizeof(fname)));

    476:     fd = fopen(fname, "r");
    477:     PetscCall(PetscTestDirectory(fname, 'r', &isdir));
    478:     PetscCheck(!isdir || !require, PETSC_COMM_SELF, PETSC_ERR_USER, "Specified options file %s is a directory", fname);
    479:     if (fd && !isdir) {
    480:       PetscSegBuffer vseg, aseg;

    482:       PetscCall(PetscSegBufferCreate(1, 4000, &vseg));
    483:       PetscCall(PetscSegBufferCreate(1, 2000, &aseg));

    485:       /* the following line will not work when opening initial files (like .petscrc) since info is not yet set */
    486:       PetscCall(PetscInfo(NULL, "Opened options file %s\n", file));

    488:       while ((string = Petscgetline(fd))) {
    489:         /* eliminate comments from each line */
    490:         PetscCall(PetscStrchr(string, cmt, &cmatch));
    491:         if (cmatch) *cmatch = 0;
    492:         PetscCall(PetscStrlen(string, &len));
    493:         /* replace tabs, ^M, \n with " " */
    494:         for (size_t i = 0; i < len; i++) {
    495:           if (string[i] == '\t' || string[i] == '\r' || string[i] == '\n') string[i] = ' ';
    496:         }
    497:         PetscCall(PetscTokenCreate(string, ' ', &token));
    498:         PetscCall(PetscTokenFind(token, &tokens[0]));
    499:         if (!tokens[0]) {
    500:           goto destroy;
    501:         } else if (!tokens[0][0]) { /* if token 0 is empty (string begins with spaces), redo */
    502:           PetscCall(PetscTokenFind(token, &tokens[0]));
    503:         }
    504:         for (PetscInt i = 1; i < 4; i++) PetscCall(PetscTokenFind(token, &tokens[i]));
    505:         if (!tokens[0]) {
    506:           goto destroy;
    507:         } else if (tokens[0][0] == '-') {
    508:           PetscCall(PetscOptionsValidKey(tokens[0], &valid));
    509:           PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": invalid option %s", fname, line, tokens[0]);
    510:           PetscCall(PetscStrlen(tokens[0], &len));
    511:           PetscCall(PetscSegBufferGet(vseg, len + 1, &vstring));
    512:           PetscCall(PetscArraycpy(vstring, tokens[0], len));
    513:           vstring[len] = ' ';
    514:           if (tokens[1]) {
    515:             PetscCall(PetscOptionsValidKey(tokens[1], &valid));
    516:             PetscCheck(!valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": cannot specify two options per line (%s %s)", fname, line, tokens[0], tokens[1]);
    517:             PetscCall(PetscStrlen(tokens[1], &len));
    518:             PetscCall(PetscSegBufferGet(vseg, len + 3, &vstring));
    519:             vstring[0] = '"';
    520:             PetscCall(PetscArraycpy(vstring + 1, tokens[1], len));
    521:             vstring[len + 1] = '"';
    522:             vstring[len + 2] = ' ';
    523:           }
    524:         } else {
    525:           PetscCall(PetscStrcasecmp(tokens[0], "alias", &alias));
    526:           PetscCheck(alias, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown first token in options file %s line %" PetscInt_FMT ": %s", fname, line, tokens[0]);
    527:           PetscCall(PetscOptionsValidKey(tokens[1], &valid));
    528:           PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": invalid aliased option %s", fname, line, tokens[1]);
    529:           PetscCheck(tokens[2], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": alias missing for %s", fname, line, tokens[1]);
    530:           PetscCall(PetscOptionsValidKey(tokens[2], &valid));
    531:           PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": invalid aliasee option %s", fname, line, tokens[2]);
    532:           PetscCall(PetscStrlen(tokens[1], &len));
    533:           PetscCall(PetscSegBufferGet(aseg, len + 1, &astring));
    534:           PetscCall(PetscArraycpy(astring, tokens[1], len));
    535:           astring[len] = ' ';

    537:           PetscCall(PetscStrlen(tokens[2], &len));
    538:           PetscCall(PetscSegBufferGet(aseg, len + 1, &astring));
    539:           PetscCall(PetscArraycpy(astring, tokens[2], len));
    540:           astring[len] = ' ';
    541:         }
    542:         {
    543:           const char *extraToken = alias ? tokens[3] : tokens[2];
    544:           PetscCheck(!extraToken, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": extra token %s", fname, line, extraToken);
    545:         }
    546:       destroy:
    547:         free(string);
    548:         PetscCall(PetscTokenDestroy(&token));
    549:         alias = PETSC_FALSE;
    550:         line++;
    551:       }
    552:       err = fclose(fd);
    553:       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file %s", fname);
    554:       PetscCall(PetscSegBufferGetSize(aseg, &bytes)); /* size without null termination */
    555:       PetscCall(PetscMPIIntCast(bytes, &acnt));
    556:       PetscCall(PetscSegBufferGet(aseg, 1, &astring));
    557:       astring[0] = 0;
    558:       PetscCall(PetscSegBufferGetSize(vseg, &bytes)); /* size without null termination */
    559:       PetscCall(PetscMPIIntCast(bytes, &cnt));
    560:       PetscCall(PetscSegBufferGet(vseg, 1, &vstring));
    561:       vstring[0] = 0;
    562:       PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
    563:       PetscCall(PetscSegBufferExtractTo(aseg, packed));
    564:       PetscCall(PetscSegBufferExtractTo(vseg, packed + acnt + 1));
    565:       PetscCall(PetscSegBufferDestroy(&aseg));
    566:       PetscCall(PetscSegBufferDestroy(&vseg));
    567:     } else PetscCheck(!require, PETSC_COMM_SELF, PETSC_ERR_USER, "Unable to open options file %s", fname);
    568:   }

    570:   counts[0] = acnt;
    571:   counts[1] = cnt;
    572:   err       = MPI_Bcast(counts, 2, MPI_INT, 0, comm);
    573:   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in first MPI collective call, could be caused by using an incorrect mpiexec or a network problem, it can be caused by having VPN running: see https://petsc.org/release/faq/");
    574:   acnt = counts[0];
    575:   cnt  = counts[1];
    576:   if (rank) PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
    577:   if (acnt || cnt) {
    578:     PetscCallMPI(MPI_Bcast(packed, 2 + acnt + cnt, MPI_CHAR, 0, comm));
    579:     astring = packed;
    580:     vstring = packed + acnt + 1;
    581:   }

    583:   if (acnt) {
    584:     PetscCall(PetscTokenCreate(astring, ' ', &token));
    585:     PetscCall(PetscTokenFind(token, &tokens[0]));
    586:     while (tokens[0]) {
    587:       PetscCall(PetscTokenFind(token, &tokens[1]));
    588:       PetscCall(PetscOptionsSetAlias(options, tokens[0], tokens[1]));
    589:       PetscCall(PetscTokenFind(token, &tokens[0]));
    590:     }
    591:     PetscCall(PetscTokenDestroy(&token));
    592:   }

    594:   if (cnt) PetscCall(PetscOptionsInsertString_Private(options, vstring, PETSC_OPT_FILE));
    595:   PetscCall(PetscFree(packed));
    596:   PetscFunctionReturn(PETSC_SUCCESS);
    597: }

    599: /*@
    600:   PetscOptionsInsertFile - Inserts options into the database from a file.

    602:   Collective

    604:   Input Parameters:
    605: + comm    - the processes that will share the options (usually `PETSC_COMM_WORLD`)
    606: . options - options database, use `NULL` for default global database
    607: . file    - name of file,
    608:            ".yml" and ".yaml" filename extensions are inserted as YAML options,
    609:            append ":yaml" to filename to force YAML options.
    610: - require - if `PETSC_TRUE` will generate an error if the file does not exist

    612:   Level: developer

    614:   Notes:
    615:   Use  # for lines that are comments and which should be ignored.
    616:   Usually, instead of using this command, one should list the file name in the call to `PetscInitialize()`, this insures that certain options
    617:   such as `-log_view` or `-malloc_debug` are processed properly. This routine only sets options into the options database that will be processed by later
    618:   calls to `XXXSetFromOptions()`, it should not be used for options listed under PetscInitialize().
    619:   The collectivity of this routine is complex; only the MPI processes in comm will
    620:   have the effect of these options. If some processes that create objects call this routine and others do
    621:   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
    622:   on different ranks.

    624: .seealso: `PetscOptionsSetValue()`, `PetscOptionsView()`, `PetscOptionsHasName()`, `PetscOptionsGetInt()`,
    625:           `PetscOptionsGetReal()`, `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
    626:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    627:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    628:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    629:           `PetscOptionsFList()`, `PetscOptionsEList()`
    630: @*/
    631: PetscErrorCode PetscOptionsInsertFile(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
    632: {
    633:   char      filename[PETSC_MAX_PATH_LEN];
    634:   PetscBool yaml;

    636:   PetscFunctionBegin;
    637:   PetscCall(PetscOptionsFilename(comm, file, filename, &yaml));
    638:   if (yaml) {
    639:     PetscCall(PetscOptionsInsertFileYAML(comm, options, filename, require));
    640:   } else {
    641:     PetscCall(PetscOptionsInsertFilePetsc(comm, options, filename, require));
    642:   }
    643:   PetscFunctionReturn(PETSC_SUCCESS);
    644: }

    646: /*@C
    647:   PetscOptionsInsertArgs - Inserts options into the database from a array of strings

    649:   Logically Collective

    651:   Input Parameters:
    652: + options - options object
    653: . argc    - the array length
    654: - args    - the string array

    656:   Level: intermediate

    658: .seealso: `PetscOptions`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`
    659: @*/
    660: PetscErrorCode PetscOptionsInsertArgs(PetscOptions options, int argc, const char *const args[])
    661: {
    662:   MPI_Comm           comm  = PETSC_COMM_WORLD;
    663:   int                left  = PetscMax(argc, 0);
    664:   const char *const *eargs = args;

    666:   PetscFunctionBegin;
    667:   while (left) {
    668:     PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;
    669:     PetscCall(PetscStrcasecmp(eargs[0], "-options_file", &isfile));
    670:     PetscCall(PetscStrcasecmp(eargs[0], "-options_file_yaml", &isfileyaml));
    671:     PetscCall(PetscStrcasecmp(eargs[0], "-options_string_yaml", &isstringyaml));
    672:     PetscCall(PetscStrcasecmp(eargs[0], "-prefix_push", &ispush));
    673:     PetscCall(PetscStrcasecmp(eargs[0], "-prefix_pop", &ispop));
    674:     PetscCall(PetscOptionsValidKey(eargs[0], &key));
    675:     if (!key) {
    676:       eargs++;
    677:       left--;
    678:     } else if (isfile) {
    679:       PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file filename option");
    680:       PetscCall(PetscOptionsInsertFile(comm, options, eargs[1], PETSC_TRUE));
    681:       eargs += 2;
    682:       left -= 2;
    683:     } else if (isfileyaml) {
    684:       PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file_yaml filename option");
    685:       PetscCall(PetscOptionsInsertFileYAML(comm, options, eargs[1], PETSC_TRUE));
    686:       eargs += 2;
    687:       left -= 2;
    688:     } else if (isstringyaml) {
    689:       PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing string for -options_string_yaml string option");
    690:       PetscCall(PetscOptionsInsertStringYAML_Private(options, eargs[1], PETSC_OPT_CODE));
    691:       eargs += 2;
    692:       left -= 2;
    693:     } else if (ispush) {
    694:       PetscCheck(left > 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option");
    695:       PetscCheck(eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option (prefixes cannot start with '-')");
    696:       PetscCall(PetscOptionsPrefixPush(options, eargs[1]));
    697:       eargs += 2;
    698:       left -= 2;
    699:     } else if (ispop) {
    700:       PetscCall(PetscOptionsPrefixPop(options));
    701:       eargs++;
    702:       left--;
    703:     } else {
    704:       PetscBool nextiskey = PETSC_FALSE;
    705:       if (left >= 2) PetscCall(PetscOptionsValidKey(eargs[1], &nextiskey));
    706:       if (left < 2 || nextiskey) {
    707:         PetscCall(PetscOptionsSetValue_Private(options, eargs[0], NULL, NULL, PETSC_OPT_COMMAND_LINE));
    708:         eargs++;
    709:         left--;
    710:       } else {
    711:         PetscCall(PetscOptionsSetValue_Private(options, eargs[0], eargs[1], NULL, PETSC_OPT_COMMAND_LINE));
    712:         eargs += 2;
    713:         left -= 2;
    714:       }
    715:     }
    716:   }
    717:   PetscFunctionReturn(PETSC_SUCCESS);
    718: }

    720: static inline PetscErrorCode PetscOptionsStringToBoolIfSet_Private(enum PetscPrecedentOption opt, const char *val[], const PetscBool set[], PetscBool *flg)
    721: {
    722:   PetscFunctionBegin;
    723:   if (set[opt]) PetscCall(PetscOptionsStringToBool(val[opt], flg));
    724:   else *flg = PETSC_FALSE;
    725:   PetscFunctionReturn(PETSC_SUCCESS);
    726: }

    728: /* Process options with absolute precedence, these are only processed from the command line, not the environment or files */
    729: static PetscErrorCode PetscOptionsProcessPrecedentFlags(PetscOptions options, int argc, char *args[], PetscBool *skip_petscrc, PetscBool *skip_petscrc_set)
    730: {
    731:   const char *const *opt = precedentOptions;
    732:   const size_t       n   = PO_NUM;
    733:   size_t             o;
    734:   int                a;
    735:   const char       **val;
    736:   char             **cval;
    737:   PetscBool         *set, unneeded;

    739:   PetscFunctionBegin;
    740:   PetscCall(PetscCalloc2(n, &cval, n, &set));
    741:   val = (const char **)cval;

    743:   /* Look for options possibly set using PetscOptionsSetValue beforehand */
    744:   for (o = 0; o < n; o++) PetscCall(PetscOptionsFindPair(options, NULL, opt[o], &val[o], &set[o]));

    746:   /* Loop through all args to collect last occurring value of each option */
    747:   for (a = 1; a < argc; a++) {
    748:     PetscBool valid, eq;

    750:     PetscCall(PetscOptionsValidKey(args[a], &valid));
    751:     if (!valid) continue;
    752:     for (o = 0; o < n; o++) {
    753:       PetscCall(PetscStrcasecmp(args[a], opt[o], &eq));
    754:       if (eq) {
    755:         set[o] = PETSC_TRUE;
    756:         if (a == argc - 1 || !args[a + 1] || !args[a + 1][0] || args[a + 1][0] == '-') val[o] = NULL;
    757:         else val[o] = args[a + 1];
    758:         break;
    759:       }
    760:     }
    761:   }

    763:   /* Process flags */
    764:   PetscCall(PetscStrcasecmp(val[PO_HELP], "intro", &options->help_intro));
    765:   if (options->help_intro) options->help = PETSC_TRUE;
    766:   else PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_HELP, val, set, &options->help));
    767:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_CI_ENABLE, val, set, &unneeded));
    768:   /* need to manage PO_CI_ENABLE option before the PetscOptionsMonitor is turned on, so its setting is not monitored */
    769:   if (set[PO_CI_ENABLE]) PetscCall(PetscOptionsSetValue_Private(options, opt[PO_CI_ENABLE], val[PO_CI_ENABLE], &a, PETSC_OPT_COMMAND_LINE));
    770:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR_CANCEL, val, set, &options->monitorCancel));
    771:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR, val, set, &options->monitorFromOptions));
    772:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_SKIP_PETSCRC, val, set, skip_petscrc));
    773:   *skip_petscrc_set = set[PO_SKIP_PETSCRC];

    775:   /* Store precedent options in database and mark them as used */
    776:   for (o = 1; o < n; o++) {
    777:     if (set[o]) {
    778:       PetscCall(PetscOptionsSetValue_Private(options, opt[o], val[o], &a, PETSC_OPT_COMMAND_LINE));
    779:       options->used[a] = PETSC_TRUE;
    780:     }
    781:   }
    782:   PetscCall(PetscFree2(cval, set));
    783:   options->precedentProcessed = PETSC_TRUE;
    784:   PetscFunctionReturn(PETSC_SUCCESS);
    785: }

    787: static inline PetscErrorCode PetscOptionsSkipPrecedent(PetscOptions options, const char name[], PetscBool *flg)
    788: {
    789:   PetscFunctionBegin;
    790:   PetscAssertPointer(flg, 3);
    791:   *flg = PETSC_FALSE;
    792:   if (options->precedentProcessed) {
    793:     for (int i = 0; i < PO_NUM; ++i) {
    794:       if (!PetscOptNameCmp(precedentOptions[i], name)) {
    795:         /* check if precedent option has been set already */
    796:         PetscCall(PetscOptionsFindPair(options, NULL, name, NULL, flg));
    797:         if (*flg) break;
    798:       }
    799:     }
    800:   }
    801:   PetscFunctionReturn(PETSC_SUCCESS);
    802: }

    804: /*@C
    805:   PetscOptionsInsert - Inserts into the options database from the command line,
    806:   the environmental variable and a file.

    808:   Collective on `PETSC_COMM_WORLD`

    810:   Input Parameters:
    811: + options - options database or `NULL` for the default global database
    812: . argc    - count of number of command line arguments
    813: . args    - the command line arguments
    814: - file    - [optional] PETSc database file, append ":yaml" to filename to specify YAML options format.
    815:             Use `NULL` or empty string to not check for code specific file.
    816:             Also checks ~/.petscrc, .petscrc and petscrc.
    817:             Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.

    819:   Options Database Keys:
    820: + -options_file filename      - read options from a file
    821: - -options_file_yaml filename - read options from a YAML file

    823:   Level: advanced

    825:   Notes:
    826:   Since `PetscOptionsInsert()` is automatically called by `PetscInitialize()`,
    827:   the user does not typically need to call this routine. `PetscOptionsInsert()`
    828:   can be called several times, adding additional entries into the database.

    830:   See `PetscInitialize()` for options related to option database monitoring.

    832: .seealso: `PetscOptionsDestroy()`, `PetscOptionsView()`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`,
    833:           `PetscInitialize()`
    834: @*/
    835: PetscErrorCode PetscOptionsInsert(PetscOptions options, int *argc, char ***args, const char file[]) PeNS
    836: {
    837:   MPI_Comm    comm = PETSC_COMM_WORLD;
    838:   PetscMPIInt rank;
    839:   PetscBool   hasArgs     = (argc && *argc) ? PETSC_TRUE : PETSC_FALSE;
    840:   PetscBool   skipPetscrc = PETSC_FALSE, skipPetscrcSet = PETSC_FALSE;
    841:   char       *eoptions = NULL;
    842:   size_t      len      = 0;

    844:   PetscFunctionBegin;
    845:   PetscCheck(!hasArgs || (args && *args), comm, PETSC_ERR_ARG_NULL, "*argc > 1 but *args not given");
    846:   PetscCallMPI(MPI_Comm_rank(comm, &rank));

    848:   if (!options) {
    849:     PetscCall(PetscOptionsCreateDefault());
    850:     options = defaultoptions;
    851:   }
    852:   if (hasArgs) {
    853:     /* process options with absolute precedence */
    854:     PetscCall(PetscOptionsProcessPrecedentFlags(options, *argc, *args, &skipPetscrc, &skipPetscrcSet));
    855:     PetscCall(PetscOptionsGetBool(NULL, NULL, "-petsc_ci", &PetscCIEnabled, NULL));
    856:   }
    857:   if (file && file[0]) {
    858:     PetscCall(PetscOptionsInsertFile(comm, options, file, PETSC_TRUE));
    859:     /* if -skip_petscrc has not been set from command line, check whether it has been set in the file */
    860:     if (!skipPetscrcSet) PetscCall(PetscOptionsGetBool(options, NULL, "-skip_petscrc", &skipPetscrc, NULL));
    861:   }
    862:   if (!skipPetscrc) {
    863:     char filename[PETSC_MAX_PATH_LEN];

    865:     PetscCall(PetscGetHomeDirectory(filename, sizeof(filename)));
    866:     PetscCallMPI(MPI_Bcast(filename, (int)sizeof(filename), MPI_CHAR, 0, comm));
    867:     if (filename[0]) PetscCall(PetscStrlcat(filename, "/.petscrc", sizeof(filename)));
    868:     PetscCall(PetscOptionsInsertFile(comm, options, filename, PETSC_FALSE));
    869:     PetscCall(PetscOptionsInsertFile(comm, options, ".petscrc", PETSC_FALSE));
    870:     PetscCall(PetscOptionsInsertFile(comm, options, "petscrc", PETSC_FALSE));
    871:   }

    873:   /* insert environment options */
    874:   if (rank == 0) {
    875:     eoptions = getenv("PETSC_OPTIONS");
    876:     PetscCall(PetscStrlen(eoptions, &len));
    877:   }
    878:   PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, comm));
    879:   if (len) {
    880:     if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
    881:     PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, comm));
    882:     if (rank) eoptions[len] = 0;
    883:     PetscCall(PetscOptionsInsertString_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
    884:     if (rank) PetscCall(PetscFree(eoptions));
    885:   }

    887:   /* insert YAML environment options */
    888:   if (rank == 0) {
    889:     eoptions = getenv("PETSC_OPTIONS_YAML");
    890:     PetscCall(PetscStrlen(eoptions, &len));
    891:   }
    892:   PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, comm));
    893:   if (len) {
    894:     if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
    895:     PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, comm));
    896:     if (rank) eoptions[len] = 0;
    897:     PetscCall(PetscOptionsInsertStringYAML_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
    898:     if (rank) PetscCall(PetscFree(eoptions));
    899:   }

    901:   /* insert command line options here because they take precedence over arguments in petscrc/environment */
    902:   if (hasArgs) PetscCall(PetscOptionsInsertArgs(options, *argc - 1, (const char *const *)*args + 1));
    903:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-petsc_ci_portable_error_output", &PetscCIEnabledPortableErrorOutput, NULL));
    904:   PetscFunctionReturn(PETSC_SUCCESS);
    905: }

    907: /* These options are not printed with PetscOptionsView() or PetscOptionsMonitor() when PetscCIEnabled is on */
    908: /* TODO: get the list from the test harness, do not have it hardwired here. Maybe from gmakegentest.py */
    909: static const char *PetscCIOptions[] = {"malloc_debug", "malloc_dump", "malloc_test", "malloc", "nox", "nox_warning", "display", "saws_port_auto_select", "saws_port_auto_select_silent", "vecscatter_mpi1", "check_pointer_intensity", "cuda_initialize", "error_output_stdout", "use_gpu_aware_mpi", "checkfunctionlist", "fp_trap", "petsc_ci", "petsc_ci_portable_error_output", "options_left"};

    911: static PetscBool PetscCIOption(const char *name)
    912: {
    913:   PetscInt  idx;
    914:   PetscBool found;

    916:   if (!PetscCIEnabled) return PETSC_FALSE;
    917:   PetscCallAbort(PETSC_COMM_SELF, PetscEListFind(PETSC_STATIC_ARRAY_LENGTH(PetscCIOptions), PetscCIOptions, name, &idx, &found));
    918:   return found;
    919: }

    921: /*@
    922:   PetscOptionsView - Prints the options that have been loaded. This is
    923:   useful for debugging purposes.

    925:   Logically Collective, No Fortran Support

    927:   Input Parameters:
    928: + options - options database, use `NULL` for default global database
    929: - viewer  - must be an `PETSCVIEWERASCII` viewer

    931:   Options Database Key:
    932: . -options_view - Activates `PetscOptionsView()` within `PetscFinalize()`

    934:   Level: advanced

    936:   Note:
    937:   Only the MPI rank 0 of the `MPI_Comm` used to create view prints the option values. Other processes
    938:   may have different values but they are not printed.

    940: .seealso: `PetscOptionsAllUsed()`
    941: @*/
    942: PetscErrorCode PetscOptionsView(PetscOptions options, PetscViewer viewer)
    943: {
    944:   PetscInt  i, N = 0;
    945:   PetscBool isascii;

    947:   PetscFunctionBegin;
    949:   options = options ? options : defaultoptions;
    950:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
    951:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
    952:   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");

    954:   for (i = 0; i < options->N; i++) {
    955:     if (PetscCIOption(options->names[i])) continue;
    956:     N++;
    957:   }

    959:   if (!N) {
    960:     PetscCall(PetscViewerASCIIPrintf(viewer, "#No PETSc Option Table entries\n"));
    961:     PetscFunctionReturn(PETSC_SUCCESS);
    962:   }

    964:   PetscCall(PetscViewerASCIIPrintf(viewer, "#PETSc Option Table entries:\n"));
    965:   for (i = 0; i < options->N; i++) {
    966:     if (PetscCIOption(options->names[i])) continue;
    967:     if (options->values[i]) {
    968:       PetscCall(PetscViewerASCIIPrintf(viewer, "-%s %s", options->names[i], options->values[i]));
    969:     } else {
    970:       PetscCall(PetscViewerASCIIPrintf(viewer, "-%s", options->names[i]));
    971:     }
    972:     PetscCall(PetscViewerASCIIPrintf(viewer, " # (source: %s)\n", PetscOptionSources[options->source[i]]));
    973:   }
    974:   PetscCall(PetscViewerASCIIPrintf(viewer, "#End of PETSc Option Table entries\n"));
    975:   PetscFunctionReturn(PETSC_SUCCESS);
    976: }

    978: /*
    979:    Called by error handlers to print options used in run
    980: */
    981: PetscErrorCode PetscOptionsLeftError(void)
    982: {
    983:   PetscInt i, nopt = 0;

    985:   for (i = 0; i < defaultoptions->N; i++) {
    986:     if (!defaultoptions->used[i]) {
    987:       if (PetscCIOption(defaultoptions->names[i])) continue;
    988:       nopt++;
    989:     }
    990:   }
    991:   if (nopt) {
    992:     PetscCall((*PetscErrorPrintf)("WARNING! There are unused option(s) set! Could be the program crashed before usage or a spelling mistake, etc!\n"));
    993:     for (i = 0; i < defaultoptions->N; i++) {
    994:       if (!defaultoptions->used[i]) {
    995:         if (PetscCIOption(defaultoptions->names[i])) continue;
    996:         if (defaultoptions->values[i]) PetscCall((*PetscErrorPrintf)("  Option left: name:-%s value: %s source: %s\n", defaultoptions->names[i], defaultoptions->values[i], PetscOptionSources[defaultoptions->source[i]]));
    997:         else PetscCall((*PetscErrorPrintf)("  Option left: name:-%s (no value) source: %s\n", defaultoptions->names[i], PetscOptionSources[defaultoptions->source[i]]));
    998:       }
    999:     }
    1000:   }
    1001:   return PETSC_SUCCESS;
    1002: }

    1004: PETSC_EXTERN PetscErrorCode PetscOptionsViewError(void)
    1005: {
    1006:   PetscInt     i, N = 0;
    1007:   PetscOptions options = defaultoptions;

    1009:   for (i = 0; i < options->N; i++) {
    1010:     if (PetscCIOption(options->names[i])) continue;
    1011:     N++;
    1012:   }

    1014:   if (N) {
    1015:     PetscCall((*PetscErrorPrintf)("PETSc Option Table entries:\n"));
    1016:   } else {
    1017:     PetscCall((*PetscErrorPrintf)("No PETSc Option Table entries\n"));
    1018:   }
    1019:   for (i = 0; i < options->N; i++) {
    1020:     if (PetscCIOption(options->names[i])) continue;
    1021:     if (options->values[i]) {
    1022:       PetscCall((*PetscErrorPrintf)("-%s %s (source: %s)\n", options->names[i], options->values[i], PetscOptionSources[options->source[i]]));
    1023:     } else {
    1024:       PetscCall((*PetscErrorPrintf)("-%s (source: %s)\n", options->names[i], PetscOptionSources[options->source[i]]));
    1025:     }
    1026:   }
    1027:   return PETSC_SUCCESS;
    1028: }

    1030: /*@
    1031:   PetscOptionsPrefixPush - Designate a prefix to be used by all options insertions to follow.

    1033:   Logically Collective

    1035:   Input Parameters:
    1036: + options - options database, or `NULL` for the default global database
    1037: - prefix  - The string to append to the existing prefix

    1039:   Options Database Keys:
    1040: + -prefix_push some_prefix_ - push the given prefix
    1041: - -prefix_pop               - pop the last prefix

    1043:   Level: advanced

    1045:   Notes:
    1046:   It is common to use this in conjunction with `-options_file` as in
    1047: .vb
    1048:  -prefix_push system1_ -options_file system1rc -prefix_pop -prefix_push system2_ -options_file system2rc -prefix_pop
    1049: .ve
    1050:   where the files no longer require all options to be prefixed with `-system2_`.

    1052:   The collectivity of this routine is complex; only the MPI processes that call this routine will
    1053:   have the affect of these options. If some processes that create objects call this routine and others do
    1054:   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
    1055:   on different ranks.

    1057: .seealso: `PetscOptionsPrefixPop()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
    1058: @*/
    1059: PetscErrorCode PetscOptionsPrefixPush(PetscOptions options, const char prefix[])
    1060: {
    1061:   size_t    n;
    1062:   PetscInt  start;
    1063:   char      key[PETSC_MAX_OPTION_NAME + 1];
    1064:   PetscBool valid;

    1066:   PetscFunctionBegin;
    1067:   PetscAssertPointer(prefix, 2);
    1068:   options = options ? options : defaultoptions;
    1069:   PetscCheck(options->prefixind < MAXPREFIXES, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum depth of prefix stack %d exceeded, recompile src/sys/objects/options.c with larger value for MAXPREFIXES", MAXPREFIXES);
    1070:   key[0] = '-'; /* keys must start with '-' */
    1071:   PetscCall(PetscStrncpy(key + 1, prefix, sizeof(key) - 1));
    1072:   PetscCall(PetscOptionsValidKey(key, &valid));
    1073:   if (!valid && options->prefixind > 0 && isdigit((int)prefix[0])) valid = PETSC_TRUE; /* If the prefix stack is not empty, make numbers a valid prefix */
    1074:   PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_USER, "Given prefix \"%s\" not valid (the first character must be a letter%s, do not include leading '-')", prefix, options->prefixind ? " or digit" : "");
    1075:   start = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
    1076:   PetscCall(PetscStrlen(prefix, &n));
    1077:   PetscCheck(n + 1 <= sizeof(options->prefix) - start, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum prefix length %zu exceeded", sizeof(options->prefix));
    1078:   PetscCall(PetscArraycpy(options->prefix + start, prefix, n + 1));
    1079:   options->prefixstack[options->prefixind++] = (int)(start + n);
    1080:   PetscFunctionReturn(PETSC_SUCCESS);
    1081: }

    1083: /*@
    1084:   PetscOptionsPrefixPop - Remove the latest options prefix, see `PetscOptionsPrefixPush()` for details

    1086:   Logically Collective on the `MPI_Comm` used when called `PetscOptionsPrefixPush()`

    1088:   Input Parameter:
    1089: . options - options database, or `NULL` for the default global database

    1091:   Level: advanced

    1093: .seealso: `PetscOptionsPrefixPush()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
    1094: @*/
    1095: PetscErrorCode PetscOptionsPrefixPop(PetscOptions options)
    1096: {
    1097:   PetscInt offset;

    1099:   PetscFunctionBegin;
    1100:   options = options ? options : defaultoptions;
    1101:   PetscCheck(options->prefixind >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More prefixes popped than pushed");
    1102:   options->prefixind--;
    1103:   offset                  = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
    1104:   options->prefix[offset] = 0;
    1105:   PetscFunctionReturn(PETSC_SUCCESS);
    1106: }

    1108: /*@
    1109:   PetscOptionsClear - Removes all options form the database leaving it empty.

    1111:   Logically Collective

    1113:   Input Parameter:
    1114: . options - options database, use `NULL` for the default global database

    1116:   Level: developer

    1118:   Note:
    1119:   The collectivity of this routine is complex; only the MPI processes that call this routine will
    1120:   have the affect of these options. If some processes that create objects call this routine and others do
    1121:   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
    1122:   on different ranks.

    1124:   Developer Note:
    1125:   Uses `free()` directly because the current option values were set with `malloc()`

    1127: .seealso: `PetscOptionsInsert()`
    1128: @*/
    1129: PetscErrorCode PetscOptionsClear(PetscOptions options)
    1130: {
    1131:   PetscInt i;

    1133:   PetscFunctionBegin;
    1134:   options = options ? options : defaultoptions;
    1135:   if (!options) PetscFunctionReturn(PETSC_SUCCESS);

    1137:   for (i = 0; i < options->N; i++) {
    1138:     if (options->names[i]) free(options->names[i]);
    1139:     if (options->values[i]) free(options->values[i]);
    1140:   }
    1141:   options->N = 0;
    1142:   free(options->names);
    1143:   free(options->values);
    1144:   free(options->used);
    1145:   free(options->source);
    1146:   options->names  = NULL;
    1147:   options->values = NULL;
    1148:   options->used   = NULL;
    1149:   options->source = NULL;
    1150:   options->Nalloc = 0;

    1152:   for (i = 0; i < options->Na; i++) {
    1153:     free(options->aliases1[i]);
    1154:     free(options->aliases2[i]);
    1155:   }
    1156:   options->Na = 0;
    1157:   free(options->aliases1);
    1158:   free(options->aliases2);
    1159:   options->aliases1 = options->aliases2 = NULL;
    1160:   options->Naalloc                      = 0;

    1162:   /* destroy hash table */
    1163:   kh_destroy(HO, options->ht);
    1164:   options->ht = NULL;

    1166:   options->prefixind  = 0;
    1167:   options->prefix[0]  = 0;
    1168:   options->help       = PETSC_FALSE;
    1169:   options->help_intro = PETSC_FALSE;
    1170:   PetscFunctionReturn(PETSC_SUCCESS);
    1171: }

    1173: /*@
    1174:   PetscOptionsSetAlias - Makes a key and alias for another key

    1176:   Logically Collective

    1178:   Input Parameters:
    1179: + options - options database, or `NULL` for default global database
    1180: . newname - the alias
    1181: - oldname - the name that alias will refer to

    1183:   Level: advanced

    1185:   Note:
    1186:   The collectivity of this routine is complex; only the MPI processes that call this routine will
    1187:   have the affect of these options. If some processes that create objects call this routine and others do
    1188:   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
    1189:   on different ranks.

    1191:   Developer Note:
    1192:   Uses `malloc()` directly because PETSc may not be initialized yet.

    1194: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
    1195:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    1196:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    1197:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    1198:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    1199:           `PetscOptionsFList()`, `PetscOptionsEList()`
    1200: @*/
    1201: PetscErrorCode PetscOptionsSetAlias(PetscOptions options, const char newname[], const char oldname[])
    1202: {
    1203:   size_t    len;
    1204:   PetscBool valid;

    1206:   PetscFunctionBegin;
    1207:   PetscAssertPointer(newname, 2);
    1208:   PetscAssertPointer(oldname, 3);
    1209:   options = options ? options : defaultoptions;
    1210:   PetscCall(PetscOptionsValidKey(newname, &valid));
    1211:   PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliased option %s", newname);
    1212:   PetscCall(PetscOptionsValidKey(oldname, &valid));
    1213:   PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliasee option %s", oldname);

    1215:   if (options->Na == options->Naalloc) {
    1216:     char **tmpA1, **tmpA2;

    1218:     options->Naalloc = PetscMax(4, options->Naalloc * 2);
    1219:     tmpA1            = (char **)malloc(options->Naalloc * sizeof(char *));
    1220:     tmpA2            = (char **)malloc(options->Naalloc * sizeof(char *));
    1221:     for (int i = 0; i < options->Na; ++i) {
    1222:       tmpA1[i] = options->aliases1[i];
    1223:       tmpA2[i] = options->aliases2[i];
    1224:     }
    1225:     free(options->aliases1);
    1226:     free(options->aliases2);
    1227:     options->aliases1 = tmpA1;
    1228:     options->aliases2 = tmpA2;
    1229:   }
    1230:   newname++;
    1231:   oldname++;
    1232:   PetscCall(PetscStrlen(newname, &len));
    1233:   options->aliases1[options->Na] = (char *)malloc((len + 1) * sizeof(char));
    1234:   PetscCall(PetscStrncpy(options->aliases1[options->Na], newname, len + 1));
    1235:   PetscCall(PetscStrlen(oldname, &len));
    1236:   options->aliases2[options->Na] = (char *)malloc((len + 1) * sizeof(char));
    1237:   PetscCall(PetscStrncpy(options->aliases2[options->Na], oldname, len + 1));
    1238:   ++options->Na;
    1239:   PetscFunctionReturn(PETSC_SUCCESS);
    1240: }

    1242: /*@
    1243:   PetscOptionsSetValue - Sets an option name-value pair in the options
    1244:   database, overriding whatever is already present.

    1246:   Logically Collective

    1248:   Input Parameters:
    1249: + options - options database, use `NULL` for the default global database
    1250: . name    - name of option, this SHOULD have the - prepended
    1251: - value   - the option value (not used for all options, so can be `NULL`)

    1253:   Level: intermediate

    1255:   Note:
    1256:   This function can be called BEFORE `PetscInitialize()`

    1258:   The collectivity of this routine is complex; only the MPI processes that call this routine will
    1259:   have the affect of these options. If some processes that create objects call this routine and others do
    1260:   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
    1261:   on different ranks.

    1263:   Developer Note:
    1264:   Uses `malloc()` directly because PETSc may not be initialized yet.

    1266: .seealso: `PetscOptionsInsert()`, `PetscOptionsClearValue()`
    1267: @*/
    1268: PetscErrorCode PetscOptionsSetValue(PetscOptions options, const char name[], const char value[])
    1269: {
    1270:   PetscFunctionBegin;
    1271:   PetscCall(PetscOptionsSetValue_Private(options, name, value, NULL, PETSC_OPT_CODE));
    1272:   PetscFunctionReturn(PETSC_SUCCESS);
    1273: }

    1275: PetscErrorCode PetscOptionsSetValue_Private(PetscOptions options, const char name[], const char value[], int *pos, PetscOptionSource source)
    1276: {
    1277:   size_t    len;
    1278:   int       n, i;
    1279:   char    **names;
    1280:   char      fullname[PETSC_MAX_OPTION_NAME] = "";
    1281:   PetscBool flg;

    1283:   PetscFunctionBegin;
    1284:   if (!options) {
    1285:     PetscCall(PetscOptionsCreateDefault());
    1286:     options = defaultoptions;
    1287:   }
    1288:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "name %s must start with '-'", name);

    1290:   PetscCall(PetscOptionsSkipPrecedent(options, name, &flg));
    1291:   if (flg) PetscFunctionReturn(PETSC_SUCCESS);

    1293:   name++; /* skip starting dash */

    1295:   if (options->prefixind > 0) {
    1296:     strncpy(fullname, options->prefix, sizeof(fullname));
    1297:     fullname[sizeof(fullname) - 1] = 0;
    1298:     strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
    1299:     fullname[sizeof(fullname) - 1] = 0;
    1300:     name                           = fullname;
    1301:   }

    1303:   /* check against aliases */
    1304:   for (i = 0; i < options->Na; i++) {
    1305:     int result = PetscOptNameCmp(options->aliases1[i], name);
    1306:     if (!result) {
    1307:       name = options->aliases2[i];
    1308:       break;
    1309:     }
    1310:   }

    1312:   /* slow search */
    1313:   n     = options->N;
    1314:   names = options->names;
    1315:   for (i = 0; i < options->N; i++) {
    1316:     int result = PetscOptNameCmp(names[i], name);
    1317:     if (!result) {
    1318:       n = i;
    1319:       goto setvalue;
    1320:     } else if (result > 0) {
    1321:       n = i;
    1322:       break;
    1323:     }
    1324:   }
    1325:   if (options->N == options->Nalloc) {
    1326:     char             **names, **values;
    1327:     PetscBool         *used;
    1328:     PetscOptionSource *source;

    1330:     options->Nalloc = PetscMax(10, options->Nalloc * 2);
    1331:     names           = (char **)malloc(options->Nalloc * sizeof(char *));
    1332:     values          = (char **)malloc(options->Nalloc * sizeof(char *));
    1333:     used            = (PetscBool *)malloc(options->Nalloc * sizeof(PetscBool));
    1334:     source          = (PetscOptionSource *)malloc(options->Nalloc * sizeof(PetscOptionSource));
    1335:     for (int i = 0; i < options->N; ++i) {
    1336:       names[i]  = options->names[i];
    1337:       values[i] = options->values[i];
    1338:       used[i]   = options->used[i];
    1339:       source[i] = options->source[i];
    1340:     }
    1341:     free(options->names);
    1342:     free(options->values);
    1343:     free(options->used);
    1344:     free(options->source);
    1345:     options->names  = names;
    1346:     options->values = values;
    1347:     options->used   = used;
    1348:     options->source = source;
    1349:   }

    1351:   /* shift remaining values up 1 */
    1352:   for (i = options->N; i > n; i--) {
    1353:     options->names[i]  = options->names[i - 1];
    1354:     options->values[i] = options->values[i - 1];
    1355:     options->used[i]   = options->used[i - 1];
    1356:     options->source[i] = options->source[i - 1];
    1357:   }
    1358:   options->names[n]  = NULL;
    1359:   options->values[n] = NULL;
    1360:   options->used[n]   = PETSC_FALSE;
    1361:   options->source[n] = PETSC_OPT_CODE;
    1362:   options->N++;

    1364:   /* destroy hash table */
    1365:   kh_destroy(HO, options->ht);
    1366:   options->ht = NULL;

    1368:   /* set new name */
    1369:   len               = strlen(name);
    1370:   options->names[n] = (char *)malloc((len + 1) * sizeof(char));
    1371:   PetscCheck(options->names[n], PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate option name");
    1372:   strcpy(options->names[n], name);

    1374: setvalue:
    1375:   /* set new value */
    1376:   if (options->values[n]) free(options->values[n]);
    1377:   len = value ? strlen(value) : 0;
    1378:   if (len) {
    1379:     options->values[n] = (char *)malloc((len + 1) * sizeof(char));
    1380:     if (!options->values[n]) return PETSC_ERR_MEM;
    1381:     strcpy(options->values[n], value);
    1382:     options->values[n][len] = '\0';
    1383:   } else {
    1384:     options->values[n] = NULL;
    1385:   }
    1386:   options->source[n] = source;

    1388:   /* handle -help so that it can be set from anywhere */
    1389:   if (!PetscOptNameCmp(name, "help")) {
    1390:     options->help       = PETSC_TRUE;
    1391:     options->help_intro = (value && !PetscOptNameCmp(value, "intro")) ? PETSC_TRUE : PETSC_FALSE;
    1392:     options->used[n]    = PETSC_TRUE;
    1393:   }

    1395:   PetscCall(PetscOptionsMonitor(options, name, value ? value : "", source));
    1396:   if (pos) *pos = n;
    1397:   PetscFunctionReturn(PETSC_SUCCESS);
    1398: }

    1400: /*@
    1401:   PetscOptionsClearValue - Clears an option name-value pair in the options
    1402:   database, overriding whatever is already present.

    1404:   Logically Collective

    1406:   Input Parameters:
    1407: + options - options database, use `NULL` for the default global database
    1408: - name    - name of option, this SHOULD have the - prepended

    1410:   Level: intermediate

    1412:   Note:
    1413:   The collectivity of this routine is complex; only the MPI processes that call this routine will
    1414:   have the affect of these options. If some processes that create objects call this routine and others do
    1415:   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
    1416:   on different ranks.

    1418:   Developer Note:
    1419:   Uses `free()` directly because the options have been set with `malloc()`

    1421: .seealso: `PetscOptionsInsert()`
    1422: @*/
    1423: PetscErrorCode PetscOptionsClearValue(PetscOptions options, const char name[])
    1424: {
    1425:   int    N, n, i;
    1426:   char **names;

    1428:   PetscFunctionBegin;
    1429:   options = options ? options : defaultoptions;
    1430:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
    1431:   if (!PetscOptNameCmp(name, "-help")) options->help = options->help_intro = PETSC_FALSE;

    1433:   name++; /* skip starting dash */

    1435:   /* slow search */
    1436:   N = n = options->N;
    1437:   names = options->names;
    1438:   for (i = 0; i < N; i++) {
    1439:     int result = PetscOptNameCmp(names[i], name);
    1440:     if (!result) {
    1441:       n = i;
    1442:       break;
    1443:     } else if (result > 0) {
    1444:       n = N;
    1445:       break;
    1446:     }
    1447:   }
    1448:   if (n == N) PetscFunctionReturn(PETSC_SUCCESS); /* it was not present */

    1450:   /* remove name and value */
    1451:   if (options->names[n]) free(options->names[n]);
    1452:   if (options->values[n]) free(options->values[n]);
    1453:   /* shift remaining values down 1 */
    1454:   for (i = n; i < N - 1; i++) {
    1455:     options->names[i]  = options->names[i + 1];
    1456:     options->values[i] = options->values[i + 1];
    1457:     options->used[i]   = options->used[i + 1];
    1458:     options->source[i] = options->source[i + 1];
    1459:   }
    1460:   options->N--;

    1462:   /* destroy hash table */
    1463:   kh_destroy(HO, options->ht);
    1464:   options->ht = NULL;

    1466:   PetscCall(PetscOptionsMonitor(options, name, NULL, PETSC_OPT_CODE));
    1467:   PetscFunctionReturn(PETSC_SUCCESS);
    1468: }

    1470: /*@C
    1471:   PetscOptionsFindPair - Gets an option name-value pair from the options database.

    1473:   Not Collective

    1475:   Input Parameters:
    1476: + options - options database, use `NULL` for the default global database
    1477: . pre     - the string to prepend to the name or `NULL`, this SHOULD NOT have the "-" prepended
    1478: - name    - name of option, this SHOULD have the "-" prepended

    1480:   Output Parameters:
    1481: + value - the option value (optional, not used for all options)
    1482: - set   - whether the option is set (optional)

    1484:   Level: developer

    1486:   Note:
    1487:   Each process may find different values or no value depending on how options were inserted into the database

    1489: .seealso: `PetscOptionsSetValue()`, `PetscOptionsClearValue()`
    1490: @*/
    1491: PetscErrorCode PetscOptionsFindPair(PetscOptions options, const char pre[], const char name[], const char *value[], PetscBool *set)
    1492: {
    1493:   char      buf[PETSC_MAX_OPTION_NAME];
    1494:   PetscBool matchnumbers = PETSC_TRUE;

    1496:   PetscFunctionBegin;
    1497:   if (!options) {
    1498:     PetscCall(PetscOptionsCreateDefault());
    1499:     options = defaultoptions;
    1500:   }
    1501:   PetscCheck(!pre || !PetscUnlikely(pre[0] == '-'), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
    1502:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);

    1504:   name++; /* skip starting dash */

    1506:   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
    1507:   if (pre && pre[0]) {
    1508:     char *ptr = buf;
    1509:     if (name[0] == '-') {
    1510:       *ptr++ = '-';
    1511:       name++;
    1512:     }
    1513:     PetscCall(PetscStrncpy(ptr, pre, buf + sizeof(buf) - ptr));
    1514:     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
    1515:     name = buf;
    1516:   }

    1518:   if (PetscDefined(USE_DEBUG)) {
    1519:     PetscBool valid;
    1520:     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
    1521:     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
    1522:     PetscCall(PetscOptionsValidKey(key, &valid));
    1523:     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
    1524:   }

    1526:   if (!options->ht) {
    1527:     int          i, ret;
    1528:     khiter_t     it;
    1529:     khash_t(HO) *ht;
    1530:     ht = kh_init(HO);
    1531:     PetscCheck(ht, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
    1532:     ret = kh_resize(HO, ht, options->N * 2); /* twice the required size to reduce risk of collisions */
    1533:     PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
    1534:     for (i = 0; i < options->N; i++) {
    1535:       it = kh_put(HO, ht, options->names[i], &ret);
    1536:       PetscCheck(ret == 1, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
    1537:       kh_val(ht, it) = i;
    1538:     }
    1539:     options->ht = ht;
    1540:   }

    1542:   khash_t(HO) *ht = options->ht;
    1543:   khiter_t     it = kh_get(HO, ht, name);
    1544:   if (it != kh_end(ht)) {
    1545:     int i            = kh_val(ht, it);
    1546:     options->used[i] = PETSC_TRUE;
    1547:     if (value) *value = options->values[i];
    1548:     if (set) *set = PETSC_TRUE;
    1549:     PetscFunctionReturn(PETSC_SUCCESS);
    1550:   }

    1552:   /*
    1553:    The following block slows down all lookups in the most frequent path (most lookups are unsuccessful).
    1554:    Maybe this special lookup mode should be enabled on request with a push/pop API.
    1555:    The feature of matching _%d_ used sparingly in the codebase.
    1556:    */
    1557:   if (matchnumbers) {
    1558:     int i, j, cnt = 0, locs[16], loce[16];
    1559:     /* determine the location and number of all _%d_ in the key */
    1560:     for (i = 0; name[i]; i++) {
    1561:       if (name[i] == '_') {
    1562:         for (j = i + 1; name[j]; j++) {
    1563:           if (name[j] >= '0' && name[j] <= '9') continue;
    1564:           if (name[j] == '_' && j > i + 1) { /* found a number */
    1565:             locs[cnt]   = i + 1;
    1566:             loce[cnt++] = j + 1;
    1567:           }
    1568:           i = j - 1;
    1569:           break;
    1570:         }
    1571:       }
    1572:     }
    1573:     for (i = 0; i < cnt; i++) {
    1574:       PetscBool found;
    1575:       char      opt[PETSC_MAX_OPTION_NAME + 1] = "-", tmp[PETSC_MAX_OPTION_NAME];
    1576:       PetscCall(PetscStrncpy(tmp, name, PetscMin((size_t)(locs[i] + 1), sizeof(tmp))));
    1577:       PetscCall(PetscStrlcat(opt, tmp, sizeof(opt)));
    1578:       PetscCall(PetscStrlcat(opt, name + loce[i], sizeof(opt)));
    1579:       PetscCall(PetscOptionsFindPair(options, NULL, opt, value, &found));
    1580:       if (found) {
    1581:         if (set) *set = PETSC_TRUE;
    1582:         PetscFunctionReturn(PETSC_SUCCESS);
    1583:       }
    1584:     }
    1585:   }

    1587:   if (set) *set = PETSC_FALSE;
    1588:   PetscFunctionReturn(PETSC_SUCCESS);
    1589: }

    1591: /* Check whether any option begins with pre+name */
    1592: PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions options, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *set)
    1593: {
    1594:   char buf[PETSC_MAX_OPTION_NAME];
    1595:   int  numCnt = 0, locs[16], loce[16];

    1597:   PetscFunctionBegin;
    1598:   options = options ? options : defaultoptions;
    1599:   PetscCheck(!pre || pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
    1600:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);

    1602:   name++; /* skip starting dash */

    1604:   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
    1605:   if (pre && pre[0]) {
    1606:     char *ptr = buf;
    1607:     if (name[0] == '-') {
    1608:       *ptr++ = '-';
    1609:       name++;
    1610:     }
    1611:     PetscCall(PetscStrncpy(ptr, pre, sizeof(buf) - ((ptr == buf) ? 0 : 1)));
    1612:     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
    1613:     name = buf;
    1614:   }

    1616:   if (PetscDefined(USE_DEBUG)) {
    1617:     PetscBool valid;
    1618:     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
    1619:     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
    1620:     PetscCall(PetscOptionsValidKey(key, &valid));
    1621:     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
    1622:   }

    1624:   /* determine the location and number of all _%d_ in the key */
    1625:   {
    1626:     int i, j;
    1627:     for (i = 0; name[i]; i++) {
    1628:       if (name[i] == '_') {
    1629:         for (j = i + 1; name[j]; j++) {
    1630:           if (name[j] >= '0' && name[j] <= '9') continue;
    1631:           if (name[j] == '_' && j > i + 1) { /* found a number */
    1632:             locs[numCnt]   = i + 1;
    1633:             loce[numCnt++] = j + 1;
    1634:           }
    1635:           i = j - 1;
    1636:           break;
    1637:         }
    1638:       }
    1639:     }
    1640:   }

    1642:   /* slow search */
    1643:   for (int c = -1; c < numCnt; ++c) {
    1644:     char   opt[PETSC_MAX_OPTION_NAME + 2] = "";
    1645:     size_t len;

    1647:     if (c < 0) {
    1648:       PetscCall(PetscStrncpy(opt, name, sizeof(opt)));
    1649:     } else {
    1650:       PetscCall(PetscStrncpy(opt, name, PetscMin((size_t)(locs[c] + 1), sizeof(opt))));
    1651:       PetscCall(PetscStrlcat(opt, name + loce[c], sizeof(opt) - 1));
    1652:     }
    1653:     PetscCall(PetscStrlen(opt, &len));
    1654:     for (int i = 0; i < options->N; i++) {
    1655:       PetscBool match;

    1657:       PetscCall(PetscStrncmp(options->names[i], opt, len, &match));
    1658:       if (match) {
    1659:         options->used[i] = PETSC_TRUE;
    1660:         if (option) *option = options->names[i];
    1661:         if (value) *value = options->values[i];
    1662:         if (set) *set = PETSC_TRUE;
    1663:         PetscFunctionReturn(PETSC_SUCCESS);
    1664:       }
    1665:     }
    1666:   }

    1668:   if (set) *set = PETSC_FALSE;
    1669:   PetscFunctionReturn(PETSC_SUCCESS);
    1670: }

    1672: /*@
    1673:   PetscOptionsReject - Generates an error if a certain option is given.

    1675:   Not Collective

    1677:   Input Parameters:
    1678: + options - options database, use `NULL` for default global database
    1679: . pre     - the option prefix (may be `NULL`)
    1680: . name    - the option name one is seeking
    1681: - mess    - error message (may be `NULL`)

    1683:   Level: advanced

    1685: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
    1686:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    1687:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    1688:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    1689:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    1690:           `PetscOptionsFList()`, `PetscOptionsEList()`
    1691: @*/
    1692: PetscErrorCode PetscOptionsReject(PetscOptions options, const char pre[], const char name[], const char mess[])
    1693: {
    1694:   PetscBool flag = PETSC_FALSE;

    1696:   PetscFunctionBegin;
    1697:   PetscCall(PetscOptionsHasName(options, pre, name, &flag));
    1698:   if (flag) {
    1699:     PetscCheck(!mess || !mess[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s with %s", pre ? pre : "", name + 1, mess);
    1700:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s", pre ? pre : "", name + 1);
    1701:   }
    1702:   PetscFunctionReturn(PETSC_SUCCESS);
    1703: }

    1705: /*@
    1706:   PetscOptionsHasHelp - Determines whether the "-help" option is in the database.

    1708:   Not Collective

    1710:   Input Parameter:
    1711: . options - options database, use `NULL` for default global database

    1713:   Output Parameter:
    1714: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.

    1716:   Level: advanced

    1718: .seealso: `PetscOptionsHasName()`
    1719: @*/
    1720: PetscErrorCode PetscOptionsHasHelp(PetscOptions options, PetscBool *set)
    1721: {
    1722:   PetscFunctionBegin;
    1723:   PetscAssertPointer(set, 2);
    1724:   options = options ? options : defaultoptions;
    1725:   *set    = options->help;
    1726:   PetscFunctionReturn(PETSC_SUCCESS);
    1727: }

    1729: PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions options, PetscBool *set)
    1730: {
    1731:   PetscFunctionBegin;
    1732:   PetscAssertPointer(set, 2);
    1733:   options = options ? options : defaultoptions;
    1734:   *set    = options->help_intro;
    1735:   PetscFunctionReturn(PETSC_SUCCESS);
    1736: }

    1738: /*@
    1739:   PetscOptionsHasName - Determines whether a certain option is given in the database. This returns true whether the option is a number, string or Boolean, even
    1740:   if its value is set to false.

    1742:   Not Collective

    1744:   Input Parameters:
    1745: + options - options database, use `NULL` for default global database
    1746: . pre     - string to prepend to the name or `NULL`
    1747: - name    - the option one is seeking

    1749:   Output Parameter:
    1750: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.

    1752:   Level: beginner

    1754:   Note:
    1755:   In many cases you probably want to use `PetscOptionsGetBool()` instead of calling this, to allowing toggling values.

    1757: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
    1758:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    1759:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    1760:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    1761:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    1762:           `PetscOptionsFList()`, `PetscOptionsEList()`
    1763: @*/
    1764: PetscErrorCode PetscOptionsHasName(PetscOptions options, const char pre[], const char name[], PetscBool *set)
    1765: {
    1766:   const char *value;
    1767:   PetscBool   flag;

    1769:   PetscFunctionBegin;
    1770:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
    1771:   if (set) *set = flag;
    1772:   PetscFunctionReturn(PETSC_SUCCESS);
    1773: }

    1775: /*@C
    1776:   PetscOptionsGetAll - Lists all the options the program was run with in a single string.

    1778:   Not Collective

    1780:   Input Parameter:
    1781: . options - the options database, use `NULL` for the default global database

    1783:   Output Parameter:
    1784: . copts - pointer where string pointer is stored

    1786:   Level: advanced

    1788:   Notes:
    1789:   The string should be freed with `PetscFree()`

    1791:   Each process may have different values depending on how the options were inserted into the database

    1793: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsView()`, `PetscOptionsPush()`, `PetscOptionsPop()`,
    1794:           `PetscOptionsLeftGet()`
    1795: @*/
    1796: PetscErrorCode PetscOptionsGetAll(PetscOptions options, char *copts[]) PeNS
    1797: {
    1798:   PetscInt i;
    1799:   size_t   len = 1, lent = 0;
    1800:   char    *coptions = NULL;

    1802:   PetscFunctionBegin;
    1803:   PetscAssertPointer(copts, 2);
    1804:   options = options ? options : defaultoptions;
    1805:   /* count the length of the required string */
    1806:   for (i = 0; i < options->N; i++) {
    1807:     PetscCall(PetscStrlen(options->names[i], &lent));
    1808:     len += 2 + lent;
    1809:     if (options->values[i]) {
    1810:       PetscCall(PetscStrlen(options->values[i], &lent));
    1811:       len += 1 + lent;
    1812:     }
    1813:   }
    1814:   PetscCall(PetscMalloc1(len, &coptions));
    1815:   coptions[0] = 0;
    1816:   for (i = 0; i < options->N; i++) {
    1817:     PetscCall(PetscStrlcat(coptions, "-", len));
    1818:     PetscCall(PetscStrlcat(coptions, options->names[i], len));
    1819:     PetscCall(PetscStrlcat(coptions, " ", len));
    1820:     if (options->values[i]) {
    1821:       PetscCall(PetscStrlcat(coptions, options->values[i], len));
    1822:       PetscCall(PetscStrlcat(coptions, " ", len));
    1823:     }
    1824:   }
    1825:   *copts = coptions;
    1826:   PetscFunctionReturn(PETSC_SUCCESS);
    1827: }

    1829: /*@
    1830:   PetscOptionsUsed - Indicates if PETSc has used a particular option set in the database

    1832:   Not Collective

    1834:   Input Parameters:
    1835: + options - options database, use `NULL` for default global database
    1836: - name    - string name of option

    1838:   Output Parameter:
    1839: . used - `PETSC_TRUE` if the option was used, otherwise false, including if option was not found in options database

    1841:   Level: advanced

    1843:   Note:
    1844:   The value returned may be different on each process and depends on which options have been processed
    1845:   on the given process

    1847: .seealso: `PetscOptionsView()`, `PetscOptionsLeft()`, `PetscOptionsAllUsed()`
    1848: @*/
    1849: PetscErrorCode PetscOptionsUsed(PetscOptions options, const char *name, PetscBool *used)
    1850: {
    1851:   PetscInt i;

    1853:   PetscFunctionBegin;
    1854:   PetscAssertPointer(name, 2);
    1855:   PetscAssertPointer(used, 3);
    1856:   options = options ? options : defaultoptions;
    1857:   *used   = PETSC_FALSE;
    1858:   for (i = 0; i < options->N; i++) {
    1859:     PetscCall(PetscStrcasecmp(options->names[i], name, used));
    1860:     if (*used) {
    1861:       *used = options->used[i];
    1862:       break;
    1863:     }
    1864:   }
    1865:   PetscFunctionReturn(PETSC_SUCCESS);
    1866: }

    1868: /*@
    1869:   PetscOptionsAllUsed - Returns a count of the number of options in the
    1870:   database that have never been selected.

    1872:   Not Collective

    1874:   Input Parameter:
    1875: . options - options database, use `NULL` for default global database

    1877:   Output Parameter:
    1878: . N - count of options not used

    1880:   Level: advanced

    1882:   Note:
    1883:   The value returned may be different on each process and depends on which options have been processed
    1884:   on the given process

    1886: .seealso: `PetscOptionsView()`
    1887: @*/
    1888: PetscErrorCode PetscOptionsAllUsed(PetscOptions options, PetscInt *N)
    1889: {
    1890:   PetscInt i, n = 0;

    1892:   PetscFunctionBegin;
    1893:   PetscAssertPointer(N, 2);
    1894:   options = options ? options : defaultoptions;
    1895:   for (i = 0; i < options->N; i++) {
    1896:     if (!options->used[i]) n++;
    1897:   }
    1898:   *N = n;
    1899:   PetscFunctionReturn(PETSC_SUCCESS);
    1900: }

    1902: /*@
    1903:   PetscOptionsLeft - Prints to screen any options that were set and never used.

    1905:   Not Collective

    1907:   Input Parameter:
    1908: . options - options database; use `NULL` for default global database

    1910:   Options Database Key:
    1911: . -options_left - activates `PetscOptionsAllUsed()` within `PetscFinalize()`

    1913:   Level: advanced

    1915:   Notes:
    1916:   This is rarely used directly, it is called by `PetscFinalize()` by default (unless
    1917:   `-options_left false` is specified) to help users determine possible mistakes in their usage of
    1918:   options. This only prints values on process zero of `PETSC_COMM_WORLD`.

    1920:   Other processes depending the objects
    1921:   used may have different options that are left unused.

    1923: .seealso: `PetscOptionsAllUsed()`
    1924: @*/
    1925: PetscErrorCode PetscOptionsLeft(PetscOptions options)
    1926: {
    1927:   PetscInt     i;
    1928:   PetscInt     cnt = 0;
    1929:   PetscOptions toptions;

    1931:   PetscFunctionBegin;
    1932:   toptions = options ? options : defaultoptions;
    1933:   for (i = 0; i < toptions->N; i++) {
    1934:     if (!toptions->used[i]) {
    1935:       if (PetscCIOption(toptions->names[i])) continue;
    1936:       if (toptions->values[i]) {
    1937:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s value: %s source: %s\n", toptions->names[i], toptions->values[i], PetscOptionSources[toptions->source[i]]));
    1938:       } else {
    1939:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s (no value) source: %s\n", toptions->names[i], PetscOptionSources[toptions->source[i]]));
    1940:       }
    1941:     }
    1942:   }
    1943:   if (!options) {
    1944:     toptions = defaultoptions;
    1945:     while (toptions->previous) {
    1946:       cnt++;
    1947:       toptions = toptions->previous;
    1948:     }
    1949:     if (cnt) PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: You may have forgotten some calls to PetscOptionsPop(),\n             PetscOptionsPop() has been called %" PetscInt_FMT " less times than PetscOptionsPush()\n", cnt));
    1950:   }
    1951:   PetscFunctionReturn(PETSC_SUCCESS);
    1952: }

    1954: /*@C
    1955:   PetscOptionsLeftGet - Returns all options that were set and never used.

    1957:   Not Collective

    1959:   Input Parameter:
    1960: . options - options database, use `NULL` for default global database

    1962:   Output Parameters:
    1963: + N      - count of options not used
    1964: . names  - names of options not used
    1965: - values - values of options not used

    1967:   Level: advanced

    1969:   Notes:
    1970:   Users should call `PetscOptionsLeftRestore()` to free the memory allocated in this routine

    1972:   The value returned may be different on each process and depends on which options have been processed
    1973:   on the given process

    1975: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`
    1976: @*/
    1977: PetscErrorCode PetscOptionsLeftGet(PetscOptions options, PetscInt *N, char **names[], char **values[])
    1978: {
    1979:   PetscInt i, n;

    1981:   PetscFunctionBegin;
    1982:   if (N) PetscAssertPointer(N, 2);
    1983:   if (names) PetscAssertPointer(names, 3);
    1984:   if (values) PetscAssertPointer(values, 4);
    1985:   options = options ? options : defaultoptions;

    1987:   /* The number of unused PETSc options */
    1988:   n = 0;
    1989:   for (i = 0; i < options->N; i++) {
    1990:     if (PetscCIOption(options->names[i])) continue;
    1991:     if (!options->used[i]) n++;
    1992:   }
    1993:   if (N) *N = n;
    1994:   if (names) PetscCall(PetscMalloc1(n, names));
    1995:   if (values) PetscCall(PetscMalloc1(n, values));

    1997:   n = 0;
    1998:   if (names || values) {
    1999:     for (i = 0; i < options->N; i++) {
    2000:       if (!options->used[i]) {
    2001:         if (PetscCIOption(options->names[i])) continue;
    2002:         if (names) (*names)[n] = options->names[i];
    2003:         if (values) (*values)[n] = options->values[i];
    2004:         n++;
    2005:       }
    2006:     }
    2007:   }
    2008:   PetscFunctionReturn(PETSC_SUCCESS);
    2009: }

    2011: /*@C
    2012:   PetscOptionsLeftRestore - Free memory for the unused PETSc options obtained using `PetscOptionsLeftGet()`.

    2014:   Not Collective

    2016:   Input Parameters:
    2017: + options - options database, use `NULL` for default global database
    2018: . N       - count of options not used
    2019: . names   - names of options not used
    2020: - values  - values of options not used

    2022:   Level: advanced

    2024:   Notes:
    2025:   The user should pass the same pointer to `N` as they did when calling `PetscOptionsLeftGet()`

    2027: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`, `PetscOptionsLeftGet()`
    2028: @*/
    2029: PetscErrorCode PetscOptionsLeftRestore(PetscOptions options, PetscInt *N, char **names[], char **values[])
    2030: {
    2031:   PetscFunctionBegin;
    2032:   (void)options;
    2033:   if (N) PetscAssertPointer(N, 2);
    2034:   if (names) PetscAssertPointer(names, 3);
    2035:   if (values) PetscAssertPointer(values, 4);
    2036:   if (N) *N = 0;
    2037:   if (names) PetscCall(PetscFree(*names));
    2038:   if (values) PetscCall(PetscFree(*values));
    2039:   PetscFunctionReturn(PETSC_SUCCESS);
    2040: }

    2042: /*@C
    2043:   PetscOptionsMonitorDefault - Print all options set value events using the supplied `PetscViewer`.

    2045:   Logically Collective

    2047:   Input Parameters:
    2048: + name   - option name string
    2049: . value  - option value string
    2050: . source - The source for the option
    2051: - ctx    - a `PETSCVIEWERASCII` or `NULL`

    2053:   Level: intermediate

    2055:   Notes:
    2056:   If ctx is `NULL`, `PetscPrintf()` is used.
    2057:   The first MPI process in the `PetscViewer` viewer actually prints the values, other
    2058:   processes may have different values set

    2060:   If `PetscCIEnabled` then do not print the test harness options

    2062: .seealso: `PetscOptionsMonitorSet()`
    2063: @*/
    2064: PetscErrorCode PetscOptionsMonitorDefault(const char name[], const char value[], PetscOptionSource source, PetscCtx ctx)
    2065: {
    2066:   PetscFunctionBegin;
    2067:   if (PetscCIOption(name)) PetscFunctionReturn(PETSC_SUCCESS);

    2069:   if (ctx) {
    2070:     PetscViewer viewer = (PetscViewer)ctx;
    2071:     if (!value) {
    2072:       PetscCall(PetscViewerASCIIPrintf(viewer, "Removing option: %s\n", name));
    2073:     } else if (!value[0]) {
    2074:       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
    2075:     } else {
    2076:       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
    2077:     }
    2078:   } else {
    2079:     MPI_Comm comm = PETSC_COMM_WORLD;
    2080:     if (!value) {
    2081:       PetscCall(PetscPrintf(comm, "Removing option: %s\n", name));
    2082:     } else if (!value[0]) {
    2083:       PetscCall(PetscPrintf(comm, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
    2084:     } else {
    2085:       PetscCall(PetscPrintf(comm, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
    2086:     }
    2087:   }
    2088:   PetscFunctionReturn(PETSC_SUCCESS);
    2089: }

    2091: /*@C
    2092:   PetscOptionsMonitorSet - Sets an ADDITIONAL function to be called at every method that
    2093:   modified the PETSc options database.

    2095:   Not Collective

    2097:   Input Parameters:
    2098: + monitor        - pointer to function (if this is `NULL`, it turns off monitoring
    2099: . mctx           - [optional] context for private data for the monitor routine (use `NULL` if
    2100:                    no context is desired)
    2101: - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for its calling sequence

    2103:   Calling sequence of `monitor`:
    2104: + name   - option name string
    2105: . value  - option value string, a value of `NULL` indicates the option is being removed from the database. A value
    2106:            of "" indicates the option is in the database but has no value.
    2107: . source - option source
    2108: - mctx   - optional monitoring context, as set by `PetscOptionsMonitorSet()`

    2110:   Options Database Keys:
    2111: + -options_monitor viewer - turn on default monitoring of changes to the options database
    2112: - -options_monitor_cancel - turn off any option monitors except the default monitor obtained with `-options_monitor`

    2114:   Level: intermediate

    2116:   Notes:
    2117:   See `PetscInitialize()` for options related to option database monitoring.

    2119:   The default is to do no monitoring.  To print the name and value of options
    2120:   being inserted into the database, use `PetscOptionsMonitorDefault()` as the monitoring routine,
    2121:   with a `NULL` monitoring context. Or use the option `-options_monitor viewer`.

    2123:   Several different monitoring routines may be set by calling
    2124:   `PetscOptionsMonitorSet()` multiple times; all will be called in the
    2125:   order in which they were set.

    2127: .seealso: `PetscOptionsMonitorDefault()`, `PetscInitialize()`, `PetscCtxDestroyFn`
    2128: @*/
    2129: PetscErrorCode PetscOptionsMonitorSet(PetscErrorCode (*monitor)(const char name[], const char value[], PetscOptionSource source, PetscCtx mctx), PetscCtx mctx, PetscCtxDestroyFn *monitordestroy)
    2130: {
    2131:   PetscOptions options = defaultoptions;

    2133:   PetscFunctionBegin;
    2134:   if (options->monitorCancel) PetscFunctionReturn(PETSC_SUCCESS);
    2135:   PetscCheck(options->numbermonitors < MAXOPTIONSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptions monitors set");
    2136:   options->monitor[options->numbermonitors]          = monitor;
    2137:   options->monitordestroy[options->numbermonitors]   = monitordestroy;
    2138:   options->monitorcontext[options->numbermonitors++] = mctx;
    2139:   PetscFunctionReturn(PETSC_SUCCESS);
    2140: }

    2142: /*
    2143:    PetscOptionsStringToBool - Converts string to PetscBool, handles cases like "yes", "no", "true", "false", "0", "1", "off", "on".
    2144:      Empty string is considered as true.
    2145: */
    2146: PetscErrorCode PetscOptionsStringToBool(const char value[], PetscBool *a)
    2147: {
    2148:   PetscBool istrue, isfalse;
    2149:   size_t    len;

    2151:   PetscFunctionBegin;
    2152:   /* PetscStrlen() returns 0 for NULL or "" */
    2153:   PetscCall(PetscStrlen(value, &len));
    2154:   if (!len) {
    2155:     *a = PETSC_TRUE;
    2156:     PetscFunctionReturn(PETSC_SUCCESS);
    2157:   }
    2158:   PetscCall(PetscStrcasecmp(value, "TRUE", &istrue));
    2159:   if (istrue) {
    2160:     *a = PETSC_TRUE;
    2161:     PetscFunctionReturn(PETSC_SUCCESS);
    2162:   }
    2163:   PetscCall(PetscStrcasecmp(value, "YES", &istrue));
    2164:   if (istrue) {
    2165:     *a = PETSC_TRUE;
    2166:     PetscFunctionReturn(PETSC_SUCCESS);
    2167:   }
    2168:   PetscCall(PetscStrcasecmp(value, "1", &istrue));
    2169:   if (istrue) {
    2170:     *a = PETSC_TRUE;
    2171:     PetscFunctionReturn(PETSC_SUCCESS);
    2172:   }
    2173:   PetscCall(PetscStrcasecmp(value, "on", &istrue));
    2174:   if (istrue) {
    2175:     *a = PETSC_TRUE;
    2176:     PetscFunctionReturn(PETSC_SUCCESS);
    2177:   }
    2178:   PetscCall(PetscStrcasecmp(value, "FALSE", &isfalse));
    2179:   if (isfalse) {
    2180:     *a = PETSC_FALSE;
    2181:     PetscFunctionReturn(PETSC_SUCCESS);
    2182:   }
    2183:   PetscCall(PetscStrcasecmp(value, "NO", &isfalse));
    2184:   if (isfalse) {
    2185:     *a = PETSC_FALSE;
    2186:     PetscFunctionReturn(PETSC_SUCCESS);
    2187:   }
    2188:   PetscCall(PetscStrcasecmp(value, "0", &isfalse));
    2189:   if (isfalse) {
    2190:     *a = PETSC_FALSE;
    2191:     PetscFunctionReturn(PETSC_SUCCESS);
    2192:   }
    2193:   PetscCall(PetscStrcasecmp(value, "off", &isfalse));
    2194:   if (isfalse) {
    2195:     *a = PETSC_FALSE;
    2196:     PetscFunctionReturn(PETSC_SUCCESS);
    2197:   }
    2198:   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown logical value: %s", value);
    2199: }

    2201: /*
    2202:    PetscOptionsStringToInt - Converts a string to an integer value. Handles special cases such as "default" and "decide"
    2203: */
    2204: PetscErrorCode PetscOptionsStringToInt(const char name[], PetscInt *a)
    2205: {
    2206:   size_t    len;
    2207:   PetscBool decide, tdefault, mouse, unlimited;

    2209:   PetscFunctionBegin;
    2210:   PetscCall(PetscStrlen(name, &len));
    2211:   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");

    2213:   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &tdefault));
    2214:   if (!tdefault) PetscCall(PetscStrcasecmp(name, "DEFAULT", &tdefault));
    2215:   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &decide));
    2216:   if (!decide) PetscCall(PetscStrcasecmp(name, "DECIDE", &decide));
    2217:   if (!decide) PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &decide));
    2218:   if (!decide) PetscCall(PetscStrcasecmp(name, "DETERMINE", &decide));
    2219:   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &unlimited));
    2220:   if (!unlimited) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &unlimited));
    2221:   PetscCall(PetscStrcasecmp(name, "mouse", &mouse));

    2223:   if (tdefault) *a = PETSC_DEFAULT;
    2224:   else if (decide) *a = PETSC_DECIDE;
    2225:   else if (unlimited) *a = PETSC_UNLIMITED;
    2226:   else if (mouse) *a = -1;
    2227:   else {
    2228:     char *endptr;
    2229:     long  strtolval;

    2231:     strtolval = strtol(name, &endptr, 10);
    2232:     PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no integer value (do not include . in it)", name);

    2234: #if defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE_ATOLL)
    2235:     (void)strtolval;
    2236:     *a = atoll(name);
    2237: #elif defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE___INT64)
    2238:     (void)strtolval;
    2239:     *a = _atoi64(name);
    2240: #else
    2241:     *a = (PetscInt)strtolval;
    2242: #endif
    2243:   }
    2244:   PetscFunctionReturn(PETSC_SUCCESS);
    2245: }

    2247: #if defined(PETSC_USE_REAL___FLOAT128)
    2248:   #include <quadmath.h>
    2249: #endif

    2251: static PetscErrorCode PetscStrtod(const char name[], PetscReal *a, char **endptr)
    2252: {
    2253:   PetscFunctionBegin;
    2254: #if defined(PETSC_USE_REAL___FLOAT128)
    2255:   *a = strtoflt128(name, endptr);
    2256: #else
    2257:   *a = (PetscReal)strtod(name, endptr);
    2258: #endif
    2259:   PetscFunctionReturn(PETSC_SUCCESS);
    2260: }

    2262: static PetscErrorCode PetscStrtoz(const char name[], PetscScalar *a, char **endptr, PetscBool *isImaginary)
    2263: {
    2264:   PetscBool hasi = PETSC_FALSE;
    2265:   char     *ptr;
    2266:   PetscReal strtoval;

    2268:   PetscFunctionBegin;
    2269:   PetscCall(PetscStrtod(name, &strtoval, &ptr));
    2270:   if (ptr == name) {
    2271:     strtoval = 1.;
    2272:     hasi     = PETSC_TRUE;
    2273:     if (name[0] == 'i') {
    2274:       ptr++;
    2275:     } else if (name[0] == '+' && name[1] == 'i') {
    2276:       ptr += 2;
    2277:     } else if (name[0] == '-' && name[1] == 'i') {
    2278:       strtoval = -1.;
    2279:       ptr += 2;
    2280:     }
    2281:   } else if (*ptr == 'i') {
    2282:     hasi = PETSC_TRUE;
    2283:     ptr++;
    2284:   }
    2285:   *endptr      = ptr;
    2286:   *isImaginary = hasi;
    2287:   if (hasi) {
    2288: #if !defined(PETSC_USE_COMPLEX)
    2289:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s contains imaginary but complex not supported ", name);
    2290: #else
    2291:     *a = PetscCMPLX(0., strtoval);
    2292: #endif
    2293:   } else {
    2294:     *a = strtoval;
    2295:   }
    2296:   PetscFunctionReturn(PETSC_SUCCESS);
    2297: }

    2299: /*
    2300:    Converts a string to PetscReal value. Handles special cases like "default" and "decide"
    2301: */
    2302: PetscErrorCode PetscOptionsStringToReal(const char name[], PetscReal *a)
    2303: {
    2304:   size_t    len;
    2305:   PetscBool match;
    2306:   char     *endptr;

    2308:   PetscFunctionBegin;
    2309:   PetscCall(PetscStrlen(name, &len));
    2310:   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "String of length zero has no numerical value");

    2312:   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &match));
    2313:   if (!match) PetscCall(PetscStrcasecmp(name, "DEFAULT", &match));
    2314:   if (match) {
    2315:     *a = PETSC_DEFAULT;
    2316:     PetscFunctionReturn(PETSC_SUCCESS);
    2317:   }

    2319:   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &match));
    2320:   if (!match) PetscCall(PetscStrcasecmp(name, "DECIDE", &match));
    2321:   if (match) {
    2322:     *a = PETSC_DECIDE;
    2323:     PetscFunctionReturn(PETSC_SUCCESS);
    2324:   }

    2326:   PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &match));
    2327:   if (!match) PetscCall(PetscStrcasecmp(name, "DETERMINE", &match));
    2328:   if (match) {
    2329:     *a = PETSC_DETERMINE;
    2330:     PetscFunctionReturn(PETSC_SUCCESS);
    2331:   }

    2333:   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &match));
    2334:   if (!match) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &match));
    2335:   if (match) {
    2336:     *a = PETSC_UNLIMITED;
    2337:     PetscFunctionReturn(PETSC_SUCCESS);
    2338:   }

    2340:   PetscCall(PetscStrtod(name, a, &endptr));
    2341:   PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value", name);
    2342:   PetscFunctionReturn(PETSC_SUCCESS);
    2343: }

    2345: PetscErrorCode PetscOptionsStringToScalar(const char name[], PetscScalar *a)
    2346: {
    2347:   PetscBool   imag1;
    2348:   size_t      len;
    2349:   PetscScalar val = 0.;
    2350:   char       *ptr = NULL;

    2352:   PetscFunctionBegin;
    2353:   PetscCall(PetscStrlen(name, &len));
    2354:   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
    2355:   PetscCall(PetscStrtoz(name, &val, &ptr, &imag1));
    2356: #if defined(PETSC_USE_COMPLEX)
    2357:   if ((size_t)(ptr - name) < len) {
    2358:     PetscBool   imag2;
    2359:     PetscScalar val2;

    2361:     PetscCall(PetscStrtoz(ptr, &val2, &ptr, &imag2));
    2362:     if (imag1) PetscCheck(imag2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s: must specify imaginary component second", name);
    2363:     val = PetscCMPLX(PetscRealPart(val), PetscImaginaryPart(val2));
    2364:   }
    2365: #endif
    2366:   PetscCheck((size_t)(ptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value ", name);
    2367:   *a = val;
    2368:   PetscFunctionReturn(PETSC_SUCCESS);
    2369: }

    2371: /*@C
    2372:   PetscOptionsGetBool - Gets the Logical (true or false) value for a particular
    2373:   option in the database.

    2375:   Not Collective

    2377:   Input Parameters:
    2378: + options - options database, use `NULL` for default global database
    2379: . pre     - the string to prepend to the name or `NULL`
    2380: - name    - the option one is seeking

    2382:   Output Parameters:
    2383: + ivalue - the logical value to return
    2384: - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`

    2386:   Level: beginner

    2388:   Notes:
    2389:   TRUE, true, YES, yes, ON, on, nostring, and 1 all translate to `PETSC_TRUE`
    2390:   FALSE, false, NO, no, OFF, off and 0 all translate to `PETSC_FALSE`

    2392:   If the option is given, but no value is provided, then `ivalue` and `set` are both given the value `PETSC_TRUE`. That is `-requested_bool`
    2393:   is equivalent to `-requested_bool true`

    2395:   If the user does not supply the option at all `ivalue` is NOT changed. Thus
    2396:   you should ALWAYS initialize `ivalue` if you access it without first checking that the `set` flag is true.

    2398: .seealso: `PetscOptionsGetBool3()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
    2399:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
    2400:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2401:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2402:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2403:           `PetscOptionsFList()`, `PetscOptionsEList()`
    2404: @*/
    2405: PetscErrorCode PetscOptionsGetBool(PetscOptions options, const char pre[], const char name[], PetscBool *ivalue, PetscBool *set)
    2406: {
    2407:   const char *value;
    2408:   PetscBool   flag;

    2410:   PetscFunctionBegin;
    2411:   PetscAssertPointer(name, 3);
    2412:   if (ivalue) PetscAssertPointer(ivalue, 4);
    2413:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
    2414:   if (flag) {
    2415:     if (set) *set = PETSC_TRUE;
    2416:     PetscCall(PetscOptionsStringToBool(value, &flag));
    2417:     if (ivalue) *ivalue = flag;
    2418:   } else {
    2419:     if (set) *set = PETSC_FALSE;
    2420:   }
    2421:   PetscFunctionReturn(PETSC_SUCCESS);
    2422: }

    2424: /*@C
    2425:   PetscOptionsGetBool3 - Gets the ternary logical (true, false or unknown) value for a particular
    2426:   option in the database.

    2428:   Not Collective

    2430:   Input Parameters:
    2431: + options - options database, use `NULL` for default global database
    2432: . pre     - the string to prepend to the name or `NULL`
    2433: - name    - the option one is seeking

    2435:   Output Parameters:
    2436: + ivalue - the ternary logical value to return
    2437: - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`

    2439:   Level: beginner

    2441:   Notes:
    2442:   TRUE, true, YES, yes, ON, on, nostring and 1 all translate to `PETSC_BOOL3_TRUE`
    2443:   FALSE, false, NO, no, OFF, off and 0 all translate to `PETSC_BOOL3_FALSE`
    2444:   UNKNOWN, unknown, AUTO and auto all translate to `PETSC_BOOL3_UNKNOWN`

    2446:   If the option is given, but no value is provided, then `ivalue` will be set to `PETSC_BOOL3_TRUE` and `set` will be set to `PETSC_TRUE`. That is `-requested_bool3`
    2447:   is equivalent to `-requested_bool3 true`

    2449:   If the user does not supply the option at all `ivalue` is NOT changed. Thus
    2450:   you should ALWAYS initialize `ivalue` if you access it without first checking that the `set` flag is true.

    2452: .seealso: `PetscOptionsGetBool()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
    2453:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
    2454:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2455:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2456:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2457:           `PetscOptionsFList()`, `PetscOptionsEList()`
    2458: @*/
    2459: PetscErrorCode PetscOptionsGetBool3(PetscOptions options, const char pre[], const char name[], PetscBool3 *ivalue, PetscBool *set)
    2460: {
    2461:   const char *value;
    2462:   PetscBool   flag;

    2464:   PetscFunctionBegin;
    2465:   PetscAssertPointer(name, 3);
    2466:   if (ivalue) PetscAssertPointer(ivalue, 4);
    2467:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
    2468:   if (flag) { // found the option
    2469:     PetscBool isAUTO = PETSC_FALSE, isUNKNOWN = PETSC_FALSE;

    2471:     if (set) *set = PETSC_TRUE;
    2472:     PetscCall(PetscStrcasecmp("AUTO", value, &isAUTO));                    // auto or AUTO
    2473:     if (!isAUTO) PetscCall(PetscStrcasecmp("UNKNOWN", value, &isUNKNOWN)); // unknown or UNKNOWN
    2474:     if (isAUTO || isUNKNOWN) {
    2475:       if (ivalue) *ivalue = PETSC_BOOL3_UNKNOWN;
    2476:     } else { // handle boolean values (if no value is given, it returns true)
    2477:       PetscCall(PetscOptionsStringToBool(value, &flag));
    2478:       if (ivalue) *ivalue = PetscBoolToBool3(flag);
    2479:     }
    2480:   } else {
    2481:     if (set) *set = PETSC_FALSE;
    2482:   }
    2483:   PetscFunctionReturn(PETSC_SUCCESS);
    2484: }

    2486: /*@C
    2487:   PetscOptionsGetEList - Puts a list of option values that a single one may be selected from

    2489:   Not Collective

    2491:   Input Parameters:
    2492: + options - options database, use `NULL` for default global database
    2493: . pre     - the string to prepend to the name or `NULL`
    2494: . opt     - option name
    2495: . list    - the possible choices (one of these must be selected, anything else is invalid)
    2496: - ntext   - number of choices

    2498:   Output Parameters:
    2499: + value - the index of the value to return (defaults to zero if the option name is given but no choice is listed)
    2500: - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`

    2502:   Level: intermediate

    2504:   Notes:
    2505:   If the user does not supply the option `value` is NOT changed. Thus
    2506:   you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.

    2508:   See `PetscOptionsFList()` for when the choices are given in a `PetscFunctionList`

    2510: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
    2511:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    2512:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2513:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2514:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2515:           `PetscOptionsFList()`, `PetscOptionsEList()`
    2516: @*/
    2517: PetscErrorCode PetscOptionsGetEList(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscInt ntext, PetscInt *value, PetscBool *set)
    2518: {
    2519:   size_t    alen, len = 0, tlen = 0;
    2520:   char     *svalue;
    2521:   PetscBool aset, flg = PETSC_FALSE;
    2522:   PetscInt  i;

    2524:   PetscFunctionBegin;
    2525:   PetscAssertPointer(opt, 3);
    2526:   for (i = 0; i < ntext; i++) {
    2527:     PetscCall(PetscStrlen(list[i], &alen));
    2528:     if (alen > len) len = alen;
    2529:     tlen += len + 1;
    2530:   }
    2531:   len += 5; /* a little extra space for user mistypes */
    2532:   PetscCall(PetscMalloc1(len, &svalue));
    2533:   PetscCall(PetscOptionsGetString(options, pre, opt, svalue, len, &aset));
    2534:   if (aset) {
    2535:     PetscCall(PetscEListFind(ntext, list, svalue, value, &flg));
    2536:     if (!flg) {
    2537:       char *avail;

    2539:       PetscCall(PetscMalloc1(tlen, &avail));
    2540:       avail[0] = '\0';
    2541:       for (i = 0; i < ntext; i++) {
    2542:         PetscCall(PetscStrlcat(avail, list[i], tlen));
    2543:         PetscCall(PetscStrlcat(avail, " ", tlen));
    2544:       }
    2545:       PetscCall(PetscStrtolower(avail));
    2546:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown option \"%s\" for -%s%s. Available options: %s", svalue, pre ? pre : "", opt + 1, avail);
    2547:     }
    2548:     if (set) *set = PETSC_TRUE;
    2549:   } else if (set) *set = PETSC_FALSE;
    2550:   PetscCall(PetscFree(svalue));
    2551:   PetscFunctionReturn(PETSC_SUCCESS);
    2552: }

    2554: /*@C
    2555:   PetscOptionsGetEnum - Gets the enum value for a particular option in the database.

    2557:   Not Collective

    2559:   Input Parameters:
    2560: + options - options database, use `NULL` for default global database
    2561: . pre     - option prefix or `NULL`
    2562: . opt     - option name
    2563: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

    2565:   Output Parameters:
    2566: + value - the value to return
    2567: - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`

    2569:   Level: beginner

    2571:   Notes:
    2572:   If the user does not supply the option `value` is NOT changed. Thus
    2573:   you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.

    2575:   `list` is usually something like `PCASMTypes` or some other predefined list of enum names

    2577: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
    2578:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    2579:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
    2580:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2581:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2582:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2583:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
    2584: @*/
    2585: PetscErrorCode PetscOptionsGetEnum(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscEnum *value, PetscBool *set) PeNSS
    2586: {
    2587:   PetscInt  ntext = 0, tval;
    2588:   PetscBool fset;

    2590:   PetscFunctionBegin;
    2591:   PetscAssertPointer(opt, 3);
    2592:   while (list[ntext++]) PetscCheck(ntext <= 50, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument appears to be wrong or have more than 50 entries");
    2593:   PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
    2594:   ntext -= 3;
    2595:   PetscCall(PetscOptionsGetEList(options, pre, opt, list, ntext, &tval, &fset));
    2596:   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
    2597:   if (fset) *value = (PetscEnum)tval;
    2598:   if (set) *set = fset;
    2599:   PetscFunctionReturn(PETSC_SUCCESS);
    2600: }

    2602: /*@C
    2603:   PetscOptionsGetInt - Gets the integer value for a particular option in the database.

    2605:   Not Collective

    2607:   Input Parameters:
    2608: + options - options database, use `NULL` for default global database
    2609: . pre     - the string to prepend to the name or `NULL`
    2610: - name    - the option one is seeking

    2612:   Output Parameters:
    2613: + ivalue - the integer value to return
    2614: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    2616:   Level: beginner

    2618:   Notes:
    2619:   If the user does not supply the option `ivalue` is NOT changed. Thus
    2620:   you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.

    2622:   Accepts the special values `determine`, `decide` and `unlimited`.

    2624:   Accepts the deprecated value `default`.

    2626: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
    2627:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    2628:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
    2629:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2630:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2631:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2632:           `PetscOptionsFList()`, `PetscOptionsEList()`
    2633: @*/
    2634: PetscErrorCode PetscOptionsGetInt(PetscOptions options, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
    2635: {
    2636:   const char *value;
    2637:   PetscBool   flag;

    2639:   PetscFunctionBegin;
    2640:   PetscAssertPointer(name, 3);
    2641:   PetscAssertPointer(ivalue, 4);
    2642:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
    2643:   if (flag) {
    2644:     if (!value) {
    2645:       if (set) *set = PETSC_FALSE;
    2646:     } else {
    2647:       if (set) *set = PETSC_TRUE;
    2648:       PetscCall(PetscOptionsStringToInt(value, ivalue));
    2649:     }
    2650:   } else {
    2651:     if (set) *set = PETSC_FALSE;
    2652:   }
    2653:   PetscFunctionReturn(PETSC_SUCCESS);
    2654: }

    2656: /*@C
    2657:   PetscOptionsGetMPIInt - Gets the MPI integer value for a particular option in the database.

    2659:   Not Collective

    2661:   Input Parameters:
    2662: + options - options database, use `NULL` for default global database
    2663: . pre     - the string to prepend to the name or `NULL`
    2664: - name    - the option one is seeking

    2666:   Output Parameters:
    2667: + ivalue - the MPI integer value to return
    2668: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    2670:   Level: beginner

    2672:   Notes:
    2673:   If the user does not supply the option `ivalue` is NOT changed. Thus
    2674:   you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.

    2676:   Accepts the special values `determine`, `decide` and `unlimited`.

    2678:   Accepts the deprecated value `default`.

    2680: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
    2681:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    2682:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
    2683:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2684:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2685:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2686:           `PetscOptionsFList()`, `PetscOptionsEList()`
    2687: @*/
    2688: PetscErrorCode PetscOptionsGetMPIInt(PetscOptions options, const char pre[], const char name[], PetscMPIInt *ivalue, PetscBool *set)
    2689: {
    2690:   PetscInt  value;
    2691:   PetscBool flag;

    2693:   PetscFunctionBegin;
    2694:   PetscCall(PetscOptionsGetInt(options, pre, name, &value, &flag));
    2695:   if (flag) PetscCall(PetscMPIIntCast(value, ivalue));
    2696:   if (set) *set = flag;
    2697:   PetscFunctionReturn(PETSC_SUCCESS);
    2698: }

    2700: /*@C
    2701:   PetscOptionsGetReal - Gets the double precision value for a particular
    2702:   option in the database.

    2704:   Not Collective

    2706:   Input Parameters:
    2707: + options - options database, use `NULL` for default global database
    2708: . pre     - string to prepend to each name or `NULL`
    2709: - name    - the option one is seeking

    2711:   Output Parameters:
    2712: + dvalue - the double value to return
    2713: - set    - `PETSC_TRUE` if found, `PETSC_FALSE` if not found

    2715:   Level: beginner

    2717:   Notes:
    2718:   Accepts the special values `determine`, `decide` and `unlimited`.

    2720:   Accepts the deprecated value `default`

    2722:   If the user does not supply the option `dvalue` is NOT changed. Thus
    2723:   you should ALWAYS initialize `dvalue` if you access it without first checking that the `set` flag is true.

    2725: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
    2726:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    2727:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2728:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2729:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2730:           `PetscOptionsFList()`, `PetscOptionsEList()`
    2731: @*/
    2732: PetscErrorCode PetscOptionsGetReal(PetscOptions options, const char pre[], const char name[], PetscReal *dvalue, PetscBool *set)
    2733: {
    2734:   const char *value;
    2735:   PetscBool   flag;

    2737:   PetscFunctionBegin;
    2738:   PetscAssertPointer(name, 3);
    2739:   PetscAssertPointer(dvalue, 4);
    2740:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
    2741:   if (flag) {
    2742:     if (!value) {
    2743:       if (set) *set = PETSC_FALSE;
    2744:     } else {
    2745:       if (set) *set = PETSC_TRUE;
    2746:       PetscCall(PetscOptionsStringToReal(value, dvalue));
    2747:     }
    2748:   } else {
    2749:     if (set) *set = PETSC_FALSE;
    2750:   }
    2751:   PetscFunctionReturn(PETSC_SUCCESS);
    2752: }

    2754: /*@C
    2755:   PetscOptionsGetScalar - Gets the scalar value for a particular
    2756:   option in the database.

    2758:   Not Collective

    2760:   Input Parameters:
    2761: + options - options database, use `NULL` for default global database
    2762: . pre     - string to prepend to each name or `NULL`
    2763: - name    - the option one is seeking

    2765:   Output Parameters:
    2766: + dvalue - the scalar value to return
    2767: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    2769:   Level: beginner

    2771:   Example Usage:
    2772:   A complex number 2+3i must be specified with NO spaces

    2774:   Note:
    2775:   If the user does not supply the option `dvalue` is NOT changed. Thus
    2776:   you should ALWAYS initialize `dvalue` if you access it without first checking if the `set` flag is true.

    2778: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
    2779:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    2780:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2781:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2782:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2783:           `PetscOptionsFList()`, `PetscOptionsEList()`
    2784: @*/
    2785: PetscErrorCode PetscOptionsGetScalar(PetscOptions options, const char pre[], const char name[], PetscScalar *dvalue, PetscBool *set)
    2786: {
    2787:   const char *value;
    2788:   PetscBool   flag;

    2790:   PetscFunctionBegin;
    2791:   PetscAssertPointer(name, 3);
    2792:   PetscAssertPointer(dvalue, 4);
    2793:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
    2794:   if (flag) {
    2795:     if (!value) {
    2796:       if (set) *set = PETSC_FALSE;
    2797:     } else {
    2798: #if !defined(PETSC_USE_COMPLEX)
    2799:       PetscCall(PetscOptionsStringToReal(value, dvalue));
    2800: #else
    2801:       PetscCall(PetscOptionsStringToScalar(value, dvalue));
    2802: #endif
    2803:       if (set) *set = PETSC_TRUE;
    2804:     }
    2805:   } else { /* flag */
    2806:     if (set) *set = PETSC_FALSE;
    2807:   }
    2808:   PetscFunctionReturn(PETSC_SUCCESS);
    2809: }

    2811: /*@C
    2812:   PetscOptionsGetString - Gets the string value for a particular option in
    2813:   the database.

    2815:   Not Collective

    2817:   Input Parameters:
    2818: + options - options database, use `NULL` for default global database
    2819: . pre     - string to prepend to name or `NULL`
    2820: . name    - the option one is seeking
    2821: - len     - maximum length of the string including null termination

    2823:   Output Parameters:
    2824: + string - location to copy string
    2825: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    2827:   Level: beginner

    2829:   Note:
    2830:   if the option is given but no string is provided then an empty string is returned and `set` is given the value of `PETSC_TRUE`

    2832:   If the user does not use the option then `string` is not changed. Thus
    2833:   you should ALWAYS initialize `string` if you access it without first checking that the `set` flag is true.

    2835:   Fortran Notes:
    2836:   The Fortran interface is slightly different from the C/C++
    2837:   interface.  Sample usage in Fortran follows
    2838: .vb
    2839:       character *20    string
    2840:       PetscErrorCode   ierr
    2841:       PetscBool        set
    2842:       call PetscOptionsGetString(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-s',string,set,ierr)
    2843: .ve

    2845: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
    2846:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    2847:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2848:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2849:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2850:           `PetscOptionsFList()`, `PetscOptionsEList()`
    2851: @*/
    2852: PetscErrorCode PetscOptionsGetString(PetscOptions options, const char pre[], const char name[], char string[], size_t len, PetscBool *set) PeNS
    2853: {
    2854:   const char *value;
    2855:   PetscBool   flag;

    2857:   PetscFunctionBegin;
    2858:   PetscAssertPointer(name, 3);
    2859:   PetscAssertPointer(string, 4);
    2860:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
    2861:   if (!flag) {
    2862:     if (set) *set = PETSC_FALSE;
    2863:   } else {
    2864:     if (set) *set = PETSC_TRUE;
    2865:     if (value) PetscCall(PetscStrncpy(string, value, len));
    2866:     else PetscCall(PetscArrayzero(string, len));
    2867:   }
    2868:   PetscFunctionReturn(PETSC_SUCCESS);
    2869: }

    2871: /*@C
    2872:   PetscOptionsGetBoolArray - Gets an array of Logical (true or false) values for a particular
    2873:   option in the database.  The values must be separated with commas with no intervening spaces.

    2875:   Not Collective

    2877:   Input Parameters:
    2878: + options - options database, use `NULL` for default global database
    2879: . pre     - string to prepend to each name or `NULL`
    2880: - name    - the option one is seeking

    2882:   Output Parameters:
    2883: + dvalue - the Boolean values to return
    2884: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
    2885: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    2887:   Level: beginner

    2889:   Note:
    2890:   TRUE, true, YES, yes, nostring, and 1 all translate to `PETSC_TRUE`. FALSE, false, NO, no, and 0 all translate to `PETSC_FALSE`

    2892: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
    2893:           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    2894:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    2895:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    2896:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2897:           `PetscOptionsFList()`, `PetscOptionsEList()`
    2898: @*/
    2899: PetscErrorCode PetscOptionsGetBoolArray(PetscOptions options, const char pre[], const char name[], PetscBool dvalue[], PetscInt *nmax, PetscBool *set)
    2900: {
    2901:   const char *svalue;
    2902:   const char *value;
    2903:   PetscInt    n = 0;
    2904:   PetscBool   flag;
    2905:   PetscToken  token;

    2907:   PetscFunctionBegin;
    2908:   PetscAssertPointer(name, 3);
    2909:   PetscAssertPointer(nmax, 5);
    2910:   if (*nmax) PetscAssertPointer(dvalue, 4);

    2912:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
    2913:   if (!flag || !svalue) {
    2914:     if (set) *set = PETSC_FALSE;
    2915:     *nmax = 0;
    2916:     PetscFunctionReturn(PETSC_SUCCESS);
    2917:   }
    2918:   if (set) *set = PETSC_TRUE;
    2919:   PetscCall(PetscTokenCreate(svalue, ',', &token));
    2920:   PetscCall(PetscTokenFind(token, &value));
    2921:   while (value && n < *nmax) {
    2922:     PetscCall(PetscOptionsStringToBool(value, dvalue));
    2923:     PetscCall(PetscTokenFind(token, &value));
    2924:     dvalue++;
    2925:     n++;
    2926:   }
    2927:   PetscCall(PetscTokenDestroy(&token));
    2928:   *nmax = n;
    2929:   PetscFunctionReturn(PETSC_SUCCESS);
    2930: }

    2932: /*@C
    2933:   PetscOptionsGetEnumArray - Gets an array of enum values for a particular option in the database.

    2935:   Not Collective

    2937:   Input Parameters:
    2938: + options - options database, use `NULL` for default global database
    2939: . pre     - option prefix or `NULL`
    2940: . name    - option name
    2941: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

    2943:   Output Parameters:
    2944: + ivalue - the  enum values to return
    2945: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
    2946: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    2948:   Level: beginner

    2950:   Notes:
    2951:   The array must be passed as a comma separated list with no spaces between the items.

    2953:   `list` is usually something like `PCASMTypes` or some other predefined list of enum names.

    2955: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
    2956:           `PetscOptionsGetEnum()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    2957:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsName()`,
    2958:           `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, `PetscOptionsStringArray()`, `PetscOptionsRealArray()`,
    2959:           `PetscOptionsScalar()`, `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    2960:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
    2961: @*/
    2962: PetscErrorCode PetscOptionsGetEnumArray(PetscOptions options, const char pre[], const char name[], const char *const list[], PetscEnum ivalue[], PetscInt *nmax, PetscBool *set)
    2963: {
    2964:   const char *svalue;
    2965:   const char *value;
    2966:   PetscInt    n = 0;
    2967:   PetscEnum   evalue;
    2968:   PetscBool   flag;
    2969:   PetscToken  token;

    2971:   PetscFunctionBegin;
    2972:   PetscAssertPointer(name, 3);
    2973:   PetscAssertPointer(list, 4);
    2974:   PetscAssertPointer(nmax, 6);
    2975:   if (*nmax) PetscAssertPointer(ivalue, 5);

    2977:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
    2978:   if (!flag || !svalue) {
    2979:     if (set) *set = PETSC_FALSE;
    2980:     *nmax = 0;
    2981:     PetscFunctionReturn(PETSC_SUCCESS);
    2982:   }
    2983:   if (set) *set = PETSC_TRUE;
    2984:   PetscCall(PetscTokenCreate(svalue, ',', &token));
    2985:   PetscCall(PetscTokenFind(token, &value));
    2986:   while (value && n < *nmax) {
    2987:     PetscCall(PetscEnumFind(list, value, &evalue, &flag));
    2988:     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown enum value '%s' for -%s%s", svalue, pre ? pre : "", name + 1);
    2989:     ivalue[n++] = evalue;
    2990:     PetscCall(PetscTokenFind(token, &value));
    2991:   }
    2992:   PetscCall(PetscTokenDestroy(&token));
    2993:   *nmax = n;
    2994:   PetscFunctionReturn(PETSC_SUCCESS);
    2995: }

    2997: /*@C
    2998:   PetscOptionsGetIntArray - Gets an array of integer values for a particular option in the database.

    3000:   Not Collective

    3002:   Input Parameters:
    3003: + options - options database, use `NULL` for default global database
    3004: . pre     - string to prepend to each name or `NULL`
    3005: - name    - the option one is seeking

    3007:   Output Parameters:
    3008: + ivalue - the integer values to return
    3009: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
    3010: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    3012:   Level: beginner

    3014:   Notes:
    3015:   The array can be passed as
    3016: +  a comma separated list -                                 0,1,2,3,4,5,6,7
    3017: .  a range (start\-end+1) -                                 0-8
    3018: .  a range with given increment (start\-end+1:inc) -        0-7:2
    3019: -  a combination of values and ranges separated by commas - 0,1-8,8-15:2

    3021:   There must be no intervening spaces between the values.

    3023: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
    3024:           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    3025:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    3026:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    3027:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    3028:           `PetscOptionsFList()`, `PetscOptionsEList()`
    3029: @*/
    3030: PetscErrorCode PetscOptionsGetIntArray(PetscOptions options, const char pre[], const char name[], PetscInt ivalue[], PetscInt *nmax, PetscBool *set)
    3031: {
    3032:   const char *svalue;
    3033:   const char *value;
    3034:   PetscInt    n = 0, i, j, start, end, inc, nvalues;
    3035:   size_t      len;
    3036:   PetscBool   flag, foundrange;
    3037:   PetscToken  token;

    3039:   PetscFunctionBegin;
    3040:   PetscAssertPointer(name, 3);
    3041:   PetscAssertPointer(nmax, 5);
    3042:   if (*nmax) PetscAssertPointer(ivalue, 4);

    3044:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
    3045:   if (!flag || !svalue) {
    3046:     if (set) *set = PETSC_FALSE;
    3047:     *nmax = 0;
    3048:     PetscFunctionReturn(PETSC_SUCCESS);
    3049:   }
    3050:   if (set) *set = PETSC_TRUE;
    3051:   PetscCall(PetscTokenCreate(svalue, ',', &token));
    3052:   PetscCall(PetscTokenFind(token, &value));
    3053:   while (value && n < *nmax) {
    3054:     char *iivalue;

    3056:     /* look for form  d-D where d and D are integers */
    3057:     PetscCall(PetscStrallocpy(value, &iivalue));
    3058:     foundrange = PETSC_FALSE;
    3059:     PetscCall(PetscStrlen(iivalue, &len));
    3060:     if (iivalue[0] == '-') i = 2;
    3061:     else i = 1;
    3062:     for (; i < (int)len; i++) {
    3063:       if (iivalue[i] == '-') {
    3064:         PetscCheck(i != (int)len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, iivalue);
    3065:         iivalue[i] = 0;

    3067:         PetscCall(PetscOptionsStringToInt(iivalue, &start));
    3068:         inc = 1;
    3069:         j   = i + 1;
    3070:         for (; j < (int)len; j++) {
    3071:           if (iivalue[j] == ':') {
    3072:             iivalue[j] = 0;

    3074:             PetscCall(PetscOptionsStringToInt(iivalue + j + 1, &inc));
    3075:             PetscCheck(inc > 0, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry,%s cannot have negative increment", n, iivalue + j + 1);
    3076:             break;
    3077:           }
    3078:         }
    3079:         PetscCall(PetscOptionsStringToInt(iivalue + i + 1, &end));
    3080:         PetscCheck(end > start, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, %s-%s cannot have decreasing list", n, iivalue, iivalue + i + 1);
    3081:         nvalues = (end - start) / inc + (end - start) % inc;
    3082:         PetscCheck(n + nvalues <= *nmax, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, not enough space left in array (%" PetscInt_FMT ") to contain entire range from %" PetscInt_FMT " to %" PetscInt_FMT, n, *nmax - n, start, end);
    3083:         for (; start < end; start += inc) {
    3084:           *ivalue = start;
    3085:           ivalue++;
    3086:           n++;
    3087:         }
    3088:         foundrange = PETSC_TRUE;
    3089:         break;
    3090:       }
    3091:     }
    3092:     if (!foundrange) {
    3093:       PetscCall(PetscOptionsStringToInt(value, ivalue));
    3094:       ivalue++;
    3095:       n++;
    3096:     }
    3097:     PetscCall(PetscFree(iivalue));
    3098:     PetscCall(PetscTokenFind(token, &value));
    3099:   }
    3100:   PetscCall(PetscTokenDestroy(&token));
    3101:   *nmax = n;
    3102:   PetscFunctionReturn(PETSC_SUCCESS);
    3103: }

    3105: /*@C
    3106:   PetscOptionsGetRealArray - Gets an array of double precision values for a
    3107:   particular option in the database.  The values must be separated with commas with no intervening spaces.

    3109:   Not Collective

    3111:   Input Parameters:
    3112: + options - options database, use `NULL` for default global database
    3113: . pre     - string to prepend to each name or `NULL`
    3114: - name    - the option one is seeking

    3116:   Output Parameters:
    3117: + dvalue - the double values to return
    3118: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
    3119: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    3121:   Level: beginner

    3123: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
    3124:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
    3125:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    3126:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    3127:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    3128:           `PetscOptionsFList()`, `PetscOptionsEList()`
    3129: @*/
    3130: PetscErrorCode PetscOptionsGetRealArray(PetscOptions options, const char pre[], const char name[], PetscReal dvalue[], PetscInt *nmax, PetscBool *set)
    3131: {
    3132:   const char *svalue;
    3133:   const char *value;
    3134:   PetscInt    n = 0;
    3135:   PetscBool   flag;
    3136:   PetscToken  token;

    3138:   PetscFunctionBegin;
    3139:   PetscAssertPointer(name, 3);
    3140:   PetscAssertPointer(nmax, 5);
    3141:   if (*nmax) PetscAssertPointer(dvalue, 4);

    3143:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
    3144:   if (!flag || !svalue) {
    3145:     if (set) *set = PETSC_FALSE;
    3146:     *nmax = 0;
    3147:     PetscFunctionReturn(PETSC_SUCCESS);
    3148:   }
    3149:   if (set) *set = PETSC_TRUE;
    3150:   PetscCall(PetscTokenCreate(svalue, ',', &token));
    3151:   PetscCall(PetscTokenFind(token, &value));
    3152:   while (value && n < *nmax) {
    3153:     PetscCall(PetscOptionsStringToReal(value, dvalue++));
    3154:     PetscCall(PetscTokenFind(token, &value));
    3155:     n++;
    3156:   }
    3157:   PetscCall(PetscTokenDestroy(&token));
    3158:   *nmax = n;
    3159:   PetscFunctionReturn(PETSC_SUCCESS);
    3160: }

    3162: /*@C
    3163:   PetscOptionsGetScalarArray - Gets an array of scalars for a
    3164:   particular option in the database.  The values must be separated with commas with no intervening spaces.

    3166:   Not Collective

    3168:   Input Parameters:
    3169: + options - options database, use `NULL` for default global database
    3170: . pre     - string to prepend to each name or `NULL`
    3171: - name    - the option one is seeking

    3173:   Output Parameters:
    3174: + dvalue - the scalar values to return
    3175: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
    3176: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

    3178:   Level: beginner

    3180: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
    3181:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
    3182:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    3183:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    3184:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    3185:           `PetscOptionsFList()`, `PetscOptionsEList()`
    3186: @*/
    3187: PetscErrorCode PetscOptionsGetScalarArray(PetscOptions options, const char pre[], const char name[], PetscScalar dvalue[], PetscInt *nmax, PetscBool *set)
    3188: {
    3189:   const char *svalue;
    3190:   const char *value;
    3191:   PetscInt    n = 0;
    3192:   PetscBool   flag;
    3193:   PetscToken  token;

    3195:   PetscFunctionBegin;
    3196:   PetscAssertPointer(name, 3);
    3197:   PetscAssertPointer(nmax, 5);
    3198:   if (*nmax) PetscAssertPointer(dvalue, 4);

    3200:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
    3201:   if (!flag || !svalue) {
    3202:     if (set) *set = PETSC_FALSE;
    3203:     *nmax = 0;
    3204:     PetscFunctionReturn(PETSC_SUCCESS);
    3205:   }
    3206:   if (set) *set = PETSC_TRUE;
    3207:   PetscCall(PetscTokenCreate(svalue, ',', &token));
    3208:   PetscCall(PetscTokenFind(token, &value));
    3209:   while (value && n < *nmax) {
    3210:     PetscCall(PetscOptionsStringToScalar(value, dvalue++));
    3211:     PetscCall(PetscTokenFind(token, &value));
    3212:     n++;
    3213:   }
    3214:   PetscCall(PetscTokenDestroy(&token));
    3215:   *nmax = n;
    3216:   PetscFunctionReturn(PETSC_SUCCESS);
    3217: }

    3219: /*@C
    3220:   PetscOptionsGetStringArray - Gets an array of string values for a particular
    3221:   option in the database. The values must be separated with commas with no intervening spaces.

    3223:   Not Collective; No Fortran Support

    3225:   Input Parameters:
    3226: + options - options database, use `NULL` for default global database
    3227: . pre     - string to prepend to name or `NULL`
    3228: - name    - the option one is seeking

    3230:   Output Parameters:
    3231: + strings - location to copy strings
    3232: . nmax    - On input maximum number of strings, on output the actual number of strings found
    3233: - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`

    3235:   Level: beginner

    3237:   Notes:
    3238:   The `nmax` parameter is used for both input and output.

    3240:   The user should pass in an array of pointers to `char`, to hold all the
    3241:   strings returned by this function.

    3243:   The user is responsible for deallocating the strings that are
    3244:   returned.

    3246: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
    3247:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
    3248:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
    3249:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
    3250:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
    3251:           `PetscOptionsFList()`, `PetscOptionsEList()`
    3252: @*/
    3253: PetscErrorCode PetscOptionsGetStringArray(PetscOptions options, const char pre[], const char name[], char *strings[], PetscInt *nmax, PetscBool *set) PeNS
    3254: {
    3255:   const char *svalue;
    3256:   const char *value;
    3257:   PetscInt    n = 0;
    3258:   PetscBool   flag;
    3259:   PetscToken  token;

    3261:   PetscFunctionBegin;
    3262:   PetscAssertPointer(name, 3);
    3263:   PetscAssertPointer(nmax, 5);
    3264:   if (*nmax) PetscAssertPointer(strings, 4);

    3266:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
    3267:   if (!flag || !svalue) {
    3268:     if (set) *set = PETSC_FALSE;
    3269:     *nmax = 0;
    3270:     PetscFunctionReturn(PETSC_SUCCESS);
    3271:   }
    3272:   if (set) *set = PETSC_TRUE;
    3273:   PetscCall(PetscTokenCreate(svalue, ',', &token));
    3274:   PetscCall(PetscTokenFind(token, &value));
    3275:   while (value && n < *nmax) {
    3276:     PetscCall(PetscStrallocpy(value, &strings[n]));
    3277:     PetscCall(PetscTokenFind(token, &value));
    3278:     n++;
    3279:   }
    3280:   PetscCall(PetscTokenDestroy(&token));
    3281:   *nmax = n;
    3282:   PetscFunctionReturn(PETSC_SUCCESS);
    3283: }

    3285: /*@C
    3286:   PetscOptionsDeprecated_Private - mark an option as deprecated, optionally replacing it with `newname`

    3288:   Prints a deprecation warning, unless an option is supplied to suppress.

    3290:   Logically Collective

    3292:   Input Parameters:
    3293: + PetscOptionsObject - string to prepend to name or `NULL`
    3294: . oldname            - the old, deprecated option
    3295: . newname            - the new option, or `NULL` if option is purely removed
    3296: . version            - a string describing the version of first deprecation, e.g. "3.9"
    3297: - info               - additional information string, or `NULL`.

    3299:   Options Database Key:
    3300: . -options_suppress_deprecated_warnings - do not print deprecation warnings

    3302:   Level: developer

    3304:   Notes:
    3305:   If `newname` is provided then the options database will automatically check the database for `oldname`.

    3307:   The old call `PetscOptionsXXX`(`oldname`) should be removed from the source code when both (1) the call to `PetscOptionsDeprecated()` occurs before the
    3308:   new call to `PetscOptionsXXX`(`newname`) and (2) the argument handling of the new call to `PetscOptionsXXX`(`newname`) is identical to the previous call.
    3309:   See `PTScotch_PartGraph_Seq()` for an example of when (1) fails and `SNESTestJacobian()` where an example of (2) fails.

    3311:   Must be called between `PetscOptionsBegin()` (or `PetscObjectOptionsBegin()`) and `PetscOptionsEnd()`.
    3312:   Only the process of rank zero that owns the `PetscOptionsItems` are argument (managed by `PetscOptionsBegin()` or
    3313:   `PetscObjectOptionsBegin()` prints the information
    3314:   If newname is provided, the old option is replaced. Otherwise, it remains
    3315:   in the options database.
    3316:   If an option is not replaced, the info argument should be used to advise the user
    3317:   on how to proceed.
    3318:   There is a limit on the length of the warning printed, so very long strings
    3319:   provided as info may be truncated.

    3321: .seealso: `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsScalar()`, `PetscOptionsBool()`, `PetscOptionsString()`, `PetscOptionsSetValue()`
    3322: @*/
    3323: PetscErrorCode PetscOptionsDeprecated_Private(PetscOptionItems PetscOptionsObject, const char oldname[], const char newname[], const char version[], const char info[])
    3324: {
    3325:   PetscBool         found, quiet;
    3326:   const char       *value;
    3327:   const char *const quietopt = "-options_suppress_deprecated_warnings";
    3328:   char              msg[4096];
    3329:   char             *prefix  = NULL;
    3330:   PetscOptions      options = NULL;
    3331:   MPI_Comm          comm    = PETSC_COMM_SELF;

    3333:   PetscFunctionBegin;
    3334:   PetscAssertPointer(oldname, 2);
    3335:   PetscAssertPointer(version, 4);
    3336:   if (PetscOptionsObject) {
    3337:     prefix  = PetscOptionsObject->prefix;
    3338:     options = PetscOptionsObject->options;
    3339:     comm    = PetscOptionsObject->comm;
    3340:   }
    3341:   PetscCall(PetscOptionsFindPair(options, prefix, oldname, &value, &found));
    3342:   if (found) {
    3343:     if (newname) {
    3344:       PetscBool newfound;

    3346:       /* do not overwrite if the new option has been provided */
    3347:       PetscCall(PetscOptionsFindPair(options, prefix, newname, NULL, &newfound));
    3348:       if (!newfound) {
    3349:         if (prefix) PetscCall(PetscOptionsPrefixPush(options, prefix));
    3350:         PetscCall(PetscOptionsSetValue(options, newname, value));
    3351:         if (prefix) PetscCall(PetscOptionsPrefixPop(options));
    3352:       }
    3353:       PetscCall(PetscOptionsClearValue(options, oldname));
    3354:     }
    3355:     quiet = PETSC_FALSE;
    3356:     PetscCall(PetscOptionsGetBool(options, NULL, quietopt, &quiet, NULL));
    3357:     if (!quiet) {
    3358:       PetscCall(PetscStrncpy(msg, "** PETSc DEPRECATION WARNING ** : the option -", sizeof(msg)));
    3359:       PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
    3360:       PetscCall(PetscStrlcat(msg, oldname + 1, sizeof(msg)));
    3361:       PetscCall(PetscStrlcat(msg, " is deprecated as of version ", sizeof(msg)));
    3362:       PetscCall(PetscStrlcat(msg, version, sizeof(msg)));
    3363:       PetscCall(PetscStrlcat(msg, " and will be removed in a future release.\n", sizeof(msg)));
    3364:       if (newname) {
    3365:         PetscCall(PetscStrlcat(msg, "   Use the option -", sizeof(msg)));
    3366:         PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
    3367:         PetscCall(PetscStrlcat(msg, newname + 1, sizeof(msg)));
    3368:         PetscCall(PetscStrlcat(msg, " instead.", sizeof(msg)));
    3369:       }
    3370:       if (info) {
    3371:         PetscCall(PetscStrlcat(msg, " ", sizeof(msg)));
    3372:         PetscCall(PetscStrlcat(msg, info, sizeof(msg)));
    3373:       }
    3374:       PetscCall(PetscStrlcat(msg, " (Silence this warning with ", sizeof(msg)));
    3375:       PetscCall(PetscStrlcat(msg, quietopt, sizeof(msg)));
    3376:       PetscCall(PetscStrlcat(msg, ")\n", sizeof(msg)));
    3377:       PetscCall(PetscPrintf(comm, "%s", msg));
    3378:     }
    3379:   }
    3380:   PetscFunctionReturn(PETSC_SUCCESS);
    3381: }