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:   int                left  = PetscMax(argc, 0);
663:   const char *const *eargs = args;

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

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

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

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

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

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

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

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

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

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

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

807:   Collective on `PETSC_COMM_WORLD`

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

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

822:   Level: advanced

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

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

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

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

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

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

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

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

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

905: /* These options are not printed with PetscOptionsView() or PetscOptionsMonitor() when PetscCIEnabled is on */
906: /* TODO: get the list from the test harness, do not have it hardwired here. Maybe from gmakegentest.py */
907: 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"};

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

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

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

923:   Logically Collective, No Fortran Support

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

929:   Options Database Key:
930: . -options_view - Activates `PetscOptionsView()` within `PetscFinalize()`

932:   Level: advanced

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

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

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

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

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

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

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

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

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

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

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

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

1031:   Logically Collective

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

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

1041:   Level: advanced

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

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

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

1064:   PetscFunctionBegin;
1065:   PetscAssertPointer(prefix, 2);
1066:   options = options ? options : defaultoptions;
1067:   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);
1068:   key[0] = '-'; /* keys must start with '-' */
1069:   PetscCall(PetscStrncpy(key + 1, prefix, sizeof(key) - 1));
1070:   PetscCall(PetscOptionsValidKey(key, &valid));
1071:   if (!valid && options->prefixind > 0 && isdigit((int)prefix[0])) valid = PETSC_TRUE; /* If the prefix stack is not empty, make numbers a valid prefix */
1072:   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" : "");
1073:   start = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1074:   PetscCall(PetscStrlen(prefix, &n));
1075:   PetscCheck(n + 1 <= sizeof(options->prefix) - start, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum prefix length %zu exceeded", sizeof(options->prefix));
1076:   PetscCall(PetscArraycpy(options->prefix + start, prefix, n + 1));
1077:   options->prefixstack[options->prefixind++] = (int)(start + n);
1078:   PetscFunctionReturn(PETSC_SUCCESS);
1079: }

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

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

1086:   Input Parameter:
1087: . options - options database, or `NULL` for the default global database

1089:   Level: advanced

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

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

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

1109:   Logically Collective

1111:   Input Parameter:
1112: . options - options database, use `NULL` for the default global database

1114:   Level: developer

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

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

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

1131:   PetscFunctionBegin;
1132:   options = options ? options : defaultoptions;
1133:   if (!options) PetscFunctionReturn(PETSC_SUCCESS);

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

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

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

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

1171: /*@
1172:   PetscOptionsSetAlias - Makes a key and alias for another key

1174:   Logically Collective

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

1181:   Level: advanced

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

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

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

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

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

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

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

1244:   Logically Collective

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

1251:   Level: intermediate

1253:   Note:
1254:   This function can be called BEFORE `PetscInitialize()`

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

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

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

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

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

1288:   PetscCall(PetscOptionsSkipPrecedent(options, name, &flg));
1289:   if (flg) PetscFunctionReturn(PETSC_SUCCESS);

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

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

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

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

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

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

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

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

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

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

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

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

1402:   Logically Collective

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

1408:   Level: intermediate

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

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

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

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

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

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

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

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

1464:   PetscCall(PetscOptionsMonitor(options, name, NULL, PETSC_OPT_CODE));
1465:   PetscFunctionReturn(PETSC_SUCCESS);
1466: }

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

1471:   Not Collective

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

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

1482:   Level: developer

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

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

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

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

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

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

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

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

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

1585:   if (set) *set = PETSC_FALSE;
1586:   PetscFunctionReturn(PETSC_SUCCESS);
1587: }

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

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

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

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

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

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

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

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

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

1666:   if (set) *set = PETSC_FALSE;
1667:   PetscFunctionReturn(PETSC_SUCCESS);
1668: }

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

1673:   Not Collective

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

1681:   Level: advanced

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

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

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

1706:   Not Collective

1708:   Input Parameter:
1709: . options - options database, use `NULL` for default global database

1711:   Output Parameter:
1712: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.

1714:   Level: advanced

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

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

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

1740:   Not Collective

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

1747:   Output Parameter:
1748: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.

1750:   Level: beginner

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

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

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

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

1776:   Not Collective

1778:   Input Parameter:
1779: . options - the options database, use `NULL` for the default global database

1781:   Output Parameter:
1782: . copts - pointer where string pointer is stored

1784:   Level: advanced

1786:   Notes:
1787:   The string should be freed with `PetscFree()`

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

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

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

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

1830:   Not Collective

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

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

1839:   Level: advanced

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

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

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

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

1870:   Not Collective

1872:   Input Parameter:
1873: . options - options database, use `NULL` for default global database

1875:   Output Parameter:
1876: . N - count of options not used

1878:   Level: advanced

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

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

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

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

1903:   Not Collective

1905:   Input Parameter:
1906: . options - options database; use `NULL` for default global database

1908:   Options Database Key:
1909: . -options_left - activates `PetscOptionsAllUsed()` within `PetscFinalize()`

1911:   Level: advanced

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

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

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

1928:   PetscFunctionBegin;
1929:   toptions = options ? options : defaultoptions;
1930:   for (PetscInt i = 0; i < toptions->N; i++) {
1931:     if (!toptions->used[i]) {
1932:       if (PetscCIOption(toptions->names[i])) continue;
1933:       if (toptions->values[i]) {
1934:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s value: %s source: %s\n", toptions->names[i], toptions->values[i], PetscOptionSources[toptions->source[i]]));
1935:       } else {
1936:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s (no value) source: %s\n", toptions->names[i], PetscOptionSources[toptions->source[i]]));
1937:       }
1938:     }
1939:   }
1940:   if (!options) {
1941:     toptions = defaultoptions;
1942:     while (toptions->previous) {
1943:       cnt++;
1944:       toptions = toptions->previous;
1945:     }
1946:     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));
1947:   }
1948:   PetscFunctionReturn(PETSC_SUCCESS);
1949: }

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

1954:   Not Collective

1956:   Input Parameter:
1957: . options - options database, use `NULL` for default global database

1959:   Output Parameters:
1960: + N      - count of options not used
1961: . names  - names of options not used
1962: - values - values of options not used

1964:   Level: advanced

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

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

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

1978:   PetscFunctionBegin;
1979:   if (N) PetscAssertPointer(N, 2);
1980:   if (names) PetscAssertPointer(names, 3);
1981:   if (values) PetscAssertPointer(values, 4);
1982:   options = options ? options : defaultoptions;

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

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

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

2011:   Not Collective

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

2019:   Level: advanced

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

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

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

2042:   Logically Collective

2044:   Input Parameters:
2045: + name   - option name string
2046: . value  - option value string
2047: . source - The source for the option
2048: - ctx    - a `PETSCVIEWERASCII` or `NULL`

2050:   Level: intermediate

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

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

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

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

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

2091:   Not Collective

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

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

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

2110:   Level: intermediate

2112:   Notes:
2113:   See `PetscInitialize()` for options related to option database monitoring.

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

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

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

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

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

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

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

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

2209:   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &tdefault));
2210:   if (!tdefault) PetscCall(PetscStrcasecmp(name, "DEFAULT", &tdefault));
2211:   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &decide));
2212:   if (!decide) PetscCall(PetscStrcasecmp(name, "DECIDE", &decide));
2213:   if (!decide) PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &decide));
2214:   if (!decide) PetscCall(PetscStrcasecmp(name, "DETERMINE", &decide));
2215:   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &unlimited));
2216:   if (!unlimited) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &unlimited));
2217:   PetscCall(PetscStrcasecmp(name, "mouse", &mouse));

2219:   if (tdefault) *a = PETSC_DEFAULT;
2220:   else if (decide) *a = PETSC_DECIDE;
2221:   else if (unlimited) *a = PETSC_UNLIMITED;
2222:   else if (mouse) *a = -1;
2223:   else {
2224:     char *endptr;
2225:     long  strtolval;

2227:     strtolval = strtol(name, &endptr, 10);
2228:     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);

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

2243: #if defined(PETSC_USE_REAL___FLOAT128)
2244:   #include <quadmath.h>
2245: #endif

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

2258: static PetscErrorCode PetscStrtoz(const char name[], PetscScalar *a, char **endptr, PetscBool *isImaginary)
2259: {
2260:   PetscBool hasi = PETSC_FALSE;
2261:   char     *ptr;
2262:   PetscReal strtoval;

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

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

2304:   PetscFunctionBegin;
2305:   PetscCall(PetscStrlen(name, &len));
2306:   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "String of length zero has no numerical value");

2308:   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &match));
2309:   if (!match) PetscCall(PetscStrcasecmp(name, "DEFAULT", &match));
2310:   if (match) {
2311:     *a = PETSC_DEFAULT;
2312:     PetscFunctionReturn(PETSC_SUCCESS);
2313:   }

2315:   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &match));
2316:   if (!match) PetscCall(PetscStrcasecmp(name, "DECIDE", &match));
2317:   if (match) {
2318:     *a = PETSC_DECIDE;
2319:     PetscFunctionReturn(PETSC_SUCCESS);
2320:   }

2322:   PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &match));
2323:   if (!match) PetscCall(PetscStrcasecmp(name, "DETERMINE", &match));
2324:   if (match) {
2325:     *a = PETSC_DETERMINE;
2326:     PetscFunctionReturn(PETSC_SUCCESS);
2327:   }

2329:   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &match));
2330:   if (!match) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &match));
2331:   if (match) {
2332:     *a = PETSC_UNLIMITED;
2333:     PetscFunctionReturn(PETSC_SUCCESS);
2334:   }

2336:   PetscCall(PetscStrtod(name, a, &endptr));
2337:   PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value", name);
2338:   PetscFunctionReturn(PETSC_SUCCESS);
2339: }

2341: PetscErrorCode PetscOptionsStringToScalar(const char name[], PetscScalar *a)
2342: {
2343:   PetscBool   imag1;
2344:   size_t      len;
2345:   PetscScalar val = 0.;
2346:   char       *ptr = NULL;

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

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

2367: /*@C
2368:   PetscOptionsGetBool - Gets the Logical (true or false) value for a particular
2369:   option in the database.

2371:   Not Collective

2373:   Input Parameters:
2374: + options - options database, use `NULL` for default global database
2375: . pre     - the string to prepend to the name or `NULL`
2376: - name    - the option one is seeking

2378:   Output Parameters:
2379: + ivalue - the logical value to return
2380: - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`

2382:   Level: beginner

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

2388:   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`
2389:   is equivalent to `-requested_bool true`

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

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

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

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

2424:   Not Collective

2426:   Input Parameters:
2427: + options - options database, use `NULL` for default global database
2428: . pre     - the string to prepend to the name or `NULL`
2429: - name    - the option one is seeking

2431:   Output Parameters:
2432: + ivalue - the ternary logical value to return
2433: - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`

2435:   Level: beginner

2437:   Notes:
2438:   TRUE, true, YES, yes, ON, on, nostring and 1 all translate to `PETSC_BOOL3_TRUE`
2439:   FALSE, false, NO, no, OFF, off and 0 all translate to `PETSC_BOOL3_FALSE`
2440:   UNKNOWN, unknown, AUTO and auto all translate to `PETSC_BOOL3_UNKNOWN`

2442:   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`
2443:   is equivalent to `-requested_bool3 true`

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

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

2460:   PetscFunctionBegin;
2461:   PetscAssertPointer(name, 3);
2462:   if (ivalue) PetscAssertPointer(ivalue, 4);
2463:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2464:   if (flag) { // found the option
2465:     PetscBool isAUTO = PETSC_FALSE, isUNKNOWN = PETSC_FALSE;

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

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

2485:   Not Collective

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

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

2498:   Level: intermediate

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

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

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

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

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

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

2552:   Not Collective

2554:   Input Parameters:
2555: + options - options database, use `NULL` for default global database
2556: . pre     - option prefix or `NULL`
2557: . opt     - option name
2558: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

2560:   Output Parameters:
2561: + value - the value to return
2562: - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`

2564:   Level: beginner

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

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

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

2585:   PetscFunctionBegin;
2586:   PetscAssertPointer(opt, 3);
2587:   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");
2588:   PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
2589:   ntext -= 3;
2590:   PetscCall(PetscOptionsGetEList(options, pre, opt, list, ntext, &tval, &fset));
2591:   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
2592:   if (fset) *value = (PetscEnum)tval;
2593:   if (set) *set = fset;
2594:   PetscFunctionReturn(PETSC_SUCCESS);
2595: }

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

2600:   Not Collective

2602:   Input Parameters:
2603: + options - options database, use `NULL` for default global database
2604: . pre     - the string to prepend to the name or `NULL`
2605: - name    - the option one is seeking

2607:   Output Parameters:
2608: + ivalue - the integer value to return
2609: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2611:   Level: beginner

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

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

2619:   Accepts the deprecated value `default`.

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

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

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

2654:   Not Collective

2656:   Input Parameters:
2657: + options - options database, use `NULL` for default global database
2658: . pre     - the string to prepend to the name or `NULL`
2659: - name    - the option one is seeking

2661:   Output Parameters:
2662: + ivalue - the MPI integer value to return
2663: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2665:   Level: beginner

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

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

2673:   Accepts the deprecated value `default`.

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

2688:   PetscFunctionBegin;
2689:   PetscCall(PetscOptionsGetInt(options, pre, name, &value, &flag));
2690:   if (flag) PetscCall(PetscMPIIntCast(value, ivalue));
2691:   if (set) *set = flag;
2692:   PetscFunctionReturn(PETSC_SUCCESS);
2693: }

2695: /*@C
2696:   PetscOptionsGetReal - Gets the double precision value for a particular
2697:   option in the database.

2699:   Not Collective

2701:   Input Parameters:
2702: + options - options database, use `NULL` for default global database
2703: . pre     - string to prepend to each name or `NULL`
2704: - name    - the option one is seeking

2706:   Output Parameters:
2707: + dvalue - the double value to return
2708: - set    - `PETSC_TRUE` if found, `PETSC_FALSE` if not found

2710:   Level: beginner

2712:   Notes:
2713:   Accepts the special values `determine`, `decide` and `unlimited`.

2715:   Accepts the deprecated value `default`

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

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

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

2749: /*@C
2750:   PetscOptionsGetScalar - Gets the scalar value for a particular
2751:   option in the database.

2753:   Not Collective

2755:   Input Parameters:
2756: + options - options database, use `NULL` for default global database
2757: . pre     - string to prepend to each name or `NULL`
2758: - name    - the option one is seeking

2760:   Output Parameters:
2761: + dvalue - the scalar value to return
2762: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2764:   Level: beginner

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

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

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

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

2806: /*@C
2807:   PetscOptionsGetString - Gets the string value for a particular option in
2808:   the database.

2810:   Not Collective

2812:   Input Parameters:
2813: + options - options database, use `NULL` for default global database
2814: . pre     - string to prepend to name or `NULL`
2815: . name    - the option one is seeking
2816: - len     - maximum length of the string including null termination

2818:   Output Parameters:
2819: + string - location to copy string
2820: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2822:   Level: beginner

2824:   Note:
2825:   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`

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

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

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

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

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

2870:   Not Collective

2872:   Input Parameters:
2873: + options - options database, use `NULL` for default global database
2874: . pre     - string to prepend to each name or `NULL`
2875: - name    - the option one is seeking

2877:   Output Parameters:
2878: + dvalue - the Boolean values to return
2879: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2880: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2882:   Level: beginner

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

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

2902:   PetscFunctionBegin;
2903:   PetscAssertPointer(name, 3);
2904:   PetscAssertPointer(nmax, 5);
2905:   if (*nmax) PetscAssertPointer(dvalue, 4);

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

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

2930:   Not Collective

2932:   Input Parameters:
2933: + options - options database, use `NULL` for default global database
2934: . pre     - option prefix or `NULL`
2935: . name    - option name
2936: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

2938:   Output Parameters:
2939: + ivalue - the  enum values to return
2940: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2941: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2943:   Level: beginner

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

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

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

2966:   PetscFunctionBegin;
2967:   PetscAssertPointer(name, 3);
2968:   PetscAssertPointer(list, 4);
2969:   PetscAssertPointer(nmax, 6);
2970:   if (*nmax) PetscAssertPointer(ivalue, 5);

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

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

2995:   Not Collective

2997:   Input Parameters:
2998: + options - options database, use `NULL` for default global database
2999: . pre     - string to prepend to each name or `NULL`
3000: - name    - the option one is seeking

3002:   Output Parameters:
3003: + ivalue - the integer values to return
3004: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3005: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3007:   Level: beginner

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

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

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

3034:   PetscFunctionBegin;
3035:   PetscAssertPointer(name, 3);
3036:   PetscAssertPointer(nmax, 5);
3037:   if (*nmax) PetscAssertPointer(ivalue, 4);

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

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

3062:         PetscCall(PetscOptionsStringToInt(iivalue, &start));
3063:         inc = 1;
3064:         j   = i + 1;
3065:         for (; j < (int)len; j++) {
3066:           if (iivalue[j] == ':') {
3067:             iivalue[j] = 0;

3069:             PetscCall(PetscOptionsStringToInt(iivalue + j + 1, &inc));
3070:             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);
3071:             break;
3072:           }
3073:         }
3074:         PetscCall(PetscOptionsStringToInt(iivalue + i + 1, &end));
3075:         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);
3076:         nvalues = (end - start) / inc + (end - start) % inc;
3077:         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);
3078:         for (; start < end; start += inc) {
3079:           *ivalue = start;
3080:           ivalue++;
3081:           n++;
3082:         }
3083:         foundrange = PETSC_TRUE;
3084:         break;
3085:       }
3086:     }
3087:     if (!foundrange) {
3088:       PetscCall(PetscOptionsStringToInt(value, ivalue));
3089:       ivalue++;
3090:       n++;
3091:     }
3092:     PetscCall(PetscFree(iivalue));
3093:     PetscCall(PetscTokenFind(token, &value));
3094:   }
3095:   PetscCall(PetscTokenDestroy(&token));
3096:   *nmax = n;
3097:   PetscFunctionReturn(PETSC_SUCCESS);
3098: }

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

3104:   Not Collective

3106:   Input Parameters:
3107: + options - options database, use `NULL` for default global database
3108: . pre     - string to prepend to each name or `NULL`
3109: - name    - the option one is seeking

3111:   Output Parameters:
3112: + dvalue - the double values to return
3113: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3114: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3116:   Level: beginner

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

3133:   PetscFunctionBegin;
3134:   PetscAssertPointer(name, 3);
3135:   PetscAssertPointer(nmax, 5);
3136:   if (*nmax) PetscAssertPointer(dvalue, 4);

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

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

3161:   Not Collective

3163:   Input Parameters:
3164: + options - options database, use `NULL` for default global database
3165: . pre     - string to prepend to each name or `NULL`
3166: - name    - the option one is seeking

3168:   Output Parameters:
3169: + dvalue - the scalar values to return
3170: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3171: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3173:   Level: beginner

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

3190:   PetscFunctionBegin;
3191:   PetscAssertPointer(name, 3);
3192:   PetscAssertPointer(nmax, 5);
3193:   if (*nmax) PetscAssertPointer(dvalue, 4);

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

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

3218:   Not Collective; No Fortran Support

3220:   Input Parameters:
3221: + options - options database, use `NULL` for default global database
3222: . pre     - string to prepend to name or `NULL`
3223: - name    - the option one is seeking

3225:   Output Parameters:
3226: + strings - location to copy strings
3227: . nmax    - On input maximum number of strings, on output the actual number of strings found
3228: - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`

3230:   Level: beginner

3232:   Notes:
3233:   The `nmax` parameter is used for both input and output.

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

3238:   The user is responsible for deallocating the strings that are
3239:   returned.

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

3256:   PetscFunctionBegin;
3257:   PetscAssertPointer(name, 3);
3258:   PetscAssertPointer(nmax, 5);
3259:   if (*nmax) PetscAssertPointer(strings, 4);

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

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

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

3285:   Logically Collective

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

3294:   Options Database Key:
3295: . -options_suppress_deprecated_warnings - do not print deprecation warnings

3297:   Level: developer

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

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

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

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

3328:   PetscFunctionBegin;
3329:   PetscAssertPointer(oldname, 2);
3330:   PetscAssertPointer(version, 4);
3331:   if (PetscOptionsObject) {
3332:     prefix  = PetscOptionsObject->prefix;
3333:     options = PetscOptionsObject->options;
3334:     comm    = PetscOptionsObject->comm;
3335:   }
3336:   PetscCall(PetscOptionsFindPair(options, prefix, oldname, &value, &found));
3337:   if (found) {
3338:     if (newname) {
3339:       PetscBool newfound;

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