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 PetscDefined(HAVE_MALLOC_H)
 16:   #include <malloc.h>
 17: #endif
 18: #if PetscDefined(HAVE_STRINGS_H)
 19:   #include <strings.h> /* strcasecmp */
 20: #endif

 22: #if PetscDefined(HAVE_STRCASECMP)
 23:   #define PetscOptNameCmp(a, b) strcasecmp(a, b)
 24: #elif PetscDefined(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 */
 95:   int       help_nmansecs; /* number of manual sections given as "-help mansec,..."; 0 means the help output is not restricted; int, not PetscInt, to match PetscStrToArray() */
 96:   char    **help_mansecs;  /* the manual sections themselves; only the options blocks in one of them are printed */

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

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

108: /* list of options which precede others, i.e., are processed in PetscOptionsProcessPrecedentFlags() */
109: /* these options can only take boolean values, the code will crash if given a non-boolean value.
110:    -help is the exception: it also accepts "intro" and a comma-separated list of manual sections. A bare
111:    -help 0, 1, yes, no, on, off, true or false is read as a logical value, so a manual section named that
112:    way can only be selected as part of such a list, as in "-help 0,ksp" */
113: static const char *precedentOptions[] = {"-petsc_ci", "-options_monitor", "-options_monitor_cancel", "-help", "-skip_petscrc"};
114: enum PetscPrecedentOption {
115:   PO_CI_ENABLE,
116:   PO_OPTIONS_MONITOR,
117:   PO_OPTIONS_MONITOR_CANCEL,
118:   PO_HELP,
119:   PO_SKIP_PETSCRC,
120:   PO_NUM
121: };

123: PETSC_INTERN PetscErrorCode PetscOptionsSetValue_Private(PetscOptions, const char[], const char[], int *, PetscOptionSource);
124: PETSC_INTERN PetscErrorCode PetscOptionsInsertStringYAML_Private(PetscOptions, const char[], PetscOptionSource);
125: static PetscErrorCode       PetscOptionsStringToBool_Private(const char[], PetscBool *, PetscBool *);

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

138: /*@
139:   PetscOptionsCreate - Creates an empty options database.

141:   Logically Collective

143:   Output Parameter:
144: . options - Options database object

146:   Level: advanced

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

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

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

156: .seealso: `PetscOptionsDestroy()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`
157: @*/
158: PetscErrorCode PetscOptionsCreate(PetscOptions *options)
159: {
160:   PetscFunctionBegin;
161:   PetscAssertPointer(options, 1);
162:   *options = (PetscOptions)calloc(1, sizeof(**options));
163:   PetscCheck(*options, PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate the options database");
164:   PetscFunctionReturn(PETSC_SUCCESS);
165: }

167: /*@
168:   PetscOptionsDestroy - Destroys an option database.

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

172:   Input Parameter:
173: . options - the `PetscOptions` object

175:   Level: advanced

177: .seealso: `PetscOptionsInsert()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsSetValue()`
178: @*/
179: PetscErrorCode PetscOptionsDestroy(PetscOptions *options)
180: {
181:   PetscFunctionBegin;
182:   PetscAssertPointer(options, 1);
183:   if (!*options) PetscFunctionReturn(PETSC_SUCCESS);
184:   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()");
185:   PetscCall(PetscOptionsClear(*options));
186:   /* XXX what about monitors ? */
187:   free(*options);
188:   *options = NULL;
189:   PetscFunctionReturn(PETSC_SUCCESS);
190: }

192: /*@
193:   PetscOptionsCreateDefault - Creates the default global options database if it does not already exist

195:   Logically collective

197:   Level: developer

199:   Note:
200:   This is called during `PetscInitialize()`; user code normally does not need to call it directly.

202: .seealso: `PetscOptionsDestroyDefault()`, `PetscOptionsCreate()`, `PetscOptionsPush()`, `PetscOptionsPop()`
203: @*/
204: PetscErrorCode PetscOptionsCreateDefault(void)
205: {
206:   PetscFunctionBegin;
207:   if (PetscUnlikely(!defaultoptions)) PetscCall(PetscOptionsCreate(&defaultoptions));
208:   PetscFunctionReturn(PETSC_SUCCESS);
209: }

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

215:   Logically Collective

217:   Input Parameter:
218: . opt - the options obtained with `PetscOptionsCreate()`

220:   Level: advanced

222:   Notes:
223:   Use `PetscOptionsPop()` to return to the previous default options database

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

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

233: .seealso: `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
234: @*/
235: PetscErrorCode PetscOptionsPush(PetscOptions opt)
236: {
237:   PetscFunctionBegin;
238:   PetscCall(PetscOptionsCreateDefault());
239:   opt->previous  = defaultoptions;
240:   defaultoptions = opt;
241:   PetscFunctionReturn(PETSC_SUCCESS);
242: }

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

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

249:   Level: advanced

251: .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
252: @*/
253: PetscErrorCode PetscOptionsPop(void)
254: {
255:   PetscOptions current = defaultoptions;

257:   PetscFunctionBegin;
258:   PetscCheck(defaultoptions, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing default options");
259:   PetscCheck(defaultoptions->previous, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscOptionsPop() called too many times");
260:   defaultoptions    = defaultoptions->previous;
261:   current->previous = NULL;
262:   PetscFunctionReturn(PETSC_SUCCESS);
263: }

265: /*@
266:   PetscOptionsDestroyDefault - Destroys the default global options database

268:   Logically collective

270:   Level: developer

272:   Note:
273:   This is called during `PetscFinalize()`; any options databases the user pushed but did not pop are also destroyed.

275: .seealso: `PetscOptionsCreateDefault()`, `PetscOptionsDestroy()`, `PetscOptionsPush()`, `PetscOptionsPop()`
276: @*/
277: PetscErrorCode PetscOptionsDestroyDefault(void)
278: {
279:   PetscFunctionBegin;
280:   if (!defaultoptions) PetscFunctionReturn(PETSC_SUCCESS);
281:   /* Destroy any options that the user forgot to pop */
282:   while (defaultoptions->previous) {
283:     PetscOptions tmp = defaultoptions;

285:     PetscCall(PetscOptionsPop());
286:     PetscCall(PetscOptionsDestroy(&tmp));
287:   }
288:   PetscCall(PetscOptionsDestroy(&defaultoptions));
289:   PetscFunctionReturn(PETSC_SUCCESS);
290: }

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

295:   Not Collective

297:   Input Parameter:
298: . key - string to check if valid

300:   Output Parameter:
301: . valid - `PETSC_TRUE` if a valid key

303:   Level: intermediate

305: .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`
306: @*/
307: PetscErrorCode PetscOptionsValidKey(const char key[], PetscBool *valid)
308: {
309:   char               *ptr;
310:   PETSC_UNUSED double d;

312:   PetscFunctionBegin;
313:   if (key) PetscAssertPointer(key, 1);
314:   PetscAssertPointer(valid, 2);
315:   *valid = PETSC_FALSE;
316:   if (!key) PetscFunctionReturn(PETSC_SUCCESS);
317:   if (key[0] != '-') PetscFunctionReturn(PETSC_SUCCESS);
318:   if (key[1] == '-') key++;
319:   if (!isalpha((int)key[1])) PetscFunctionReturn(PETSC_SUCCESS);
320:   d = strtod(key, &ptr);
321:   if (ptr != key && !(*ptr == '_' || isalnum((int)*ptr))) PetscFunctionReturn(PETSC_SUCCESS);
322:   *valid = PETSC_TRUE;
323:   PetscFunctionReturn(PETSC_SUCCESS);
324: }

326: static PetscErrorCode PetscOptionsInsertString_Private(PetscOptions options, const char in_str[], PetscOptionSource source)
327: {
328:   const char *first, *second;
329:   PetscToken  token;

331:   PetscFunctionBegin;
332:   PetscCall(PetscTokenCreate(in_str, ' ', &token));
333:   PetscCall(PetscTokenFind(token, &first));
334:   while (first) {
335:     PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;

337:     PetscCall(PetscStrcasecmp(first, "-options_file", &isfile));
338:     PetscCall(PetscStrcasecmp(first, "-options_file_yaml", &isfileyaml));
339:     PetscCall(PetscStrcasecmp(first, "-options_string_yaml", &isstringyaml));
340:     PetscCall(PetscStrcasecmp(first, "-prefix_push", &ispush));
341:     PetscCall(PetscStrcasecmp(first, "-prefix_pop", &ispop));
342:     PetscCall(PetscOptionsValidKey(first, &key));
343:     if (!key) {
344:       PetscCall(PetscTokenFind(token, &first));
345:     } else if (isfile) {
346:       PetscCall(PetscTokenFind(token, &second));
347:       PetscCall(PetscOptionsInsertFile(PETSC_COMM_SELF, options, second, PETSC_TRUE));
348:       PetscCall(PetscTokenFind(token, &first));
349:     } else if (isfileyaml) {
350:       PetscCall(PetscTokenFind(token, &second));
351:       PetscCall(PetscOptionsInsertFileYAML(PETSC_COMM_SELF, options, second, PETSC_TRUE));
352:       PetscCall(PetscTokenFind(token, &first));
353:     } else if (isstringyaml) {
354:       PetscCall(PetscTokenFind(token, &second));
355:       PetscCall(PetscOptionsInsertStringYAML_Private(options, second, source));
356:       PetscCall(PetscTokenFind(token, &first));
357:     } else if (ispush) {
358:       PetscCall(PetscTokenFind(token, &second));
359:       PetscCall(PetscOptionsPrefixPush(options, second));
360:       PetscCall(PetscTokenFind(token, &first));
361:     } else if (ispop) {
362:       PetscCall(PetscOptionsPrefixPop(options));
363:       PetscCall(PetscTokenFind(token, &first));
364:     } else {
365:       PetscCall(PetscTokenFind(token, &second));
366:       PetscCall(PetscOptionsValidKey(second, &key));
367:       if (!key) {
368:         PetscCall(PetscOptionsSetValue_Private(options, first, second, NULL, source));
369:         PetscCall(PetscTokenFind(token, &first));
370:       } else {
371:         PetscCall(PetscOptionsSetValue_Private(options, first, NULL, NULL, source));
372:         first = second;
373:       }
374:     }
375:   }
376:   PetscCall(PetscTokenDestroy(&token));
377:   PetscFunctionReturn(PETSC_SUCCESS);
378: }

380: /*@
381:   PetscOptionsInsertString - Inserts options into the database from a string

383:   Logically Collective

385:   Input Parameters:
386: + options - options object
387: - in_str  - string that contains options separated by blanks

389:   Level: intermediate

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

396:    Contributed by Boyana Norris

398: .seealso: `PetscOptionsSetValue()`, `PetscOptionsView()`, `PetscOptionsHasName()`, `PetscOptionsGetInt()`,
399:           `PetscOptionsGetReal()`, `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
400:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
401:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
402:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
403:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsInsertFile()`
404: @*/
405: PetscErrorCode PetscOptionsInsertString(PetscOptions options, const char in_str[])
406: {
407:   PetscFunctionBegin;
408:   PetscCall(PetscOptionsInsertString_Private(options, in_str, PETSC_OPT_CODE));
409:   PetscFunctionReturn(PETSC_SUCCESS);
410: }

412: /*
413:     Returns a line (ended by a \n, \r or null character of any length. Result should be freed with free()
414: */
415: static char *Petscgetline(FILE *f)
416: {
417:   size_t size = 0;
418:   size_t len  = 0;
419:   size_t last = 0;
420:   char  *buf  = NULL;

422:   if (feof(f)) return NULL;
423:   do {
424:     size += 1024;                             /* BUFSIZ is defined as "the optimal read size for this platform" */
425:     buf = (char *)realloc((void *)buf, size); /* realloc(NULL,n) is the same as malloc(n) */
426:     /* Actually do the read. Note that fgets puts a terminal '\0' on the
427:     end of the string, so we make sure we overwrite this */
428:     if (!fgets(buf + len, 1024, f)) buf[len] = 0;
429:     PetscCallAbort(PETSC_COMM_SELF, PetscStrlen(buf, &len));
430:     last = len - 1;
431:   } while (!feof(f) && buf[last] != '\n' && buf[last] != '\r');
432:   if (len) return buf;
433:   free(buf);
434:   return NULL;
435: }

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

441:   PetscFunctionBegin;
442:   *yaml = PETSC_FALSE;
443:   PetscCall(PetscStrreplace(comm, file, fname, sizeof(fname)));
444:   PetscCall(PetscFixFilename(fname, path));
445:   PetscCall(PetscStrendswith(path, ":yaml", yaml));
446:   if (*yaml) {
447:     PetscCall(PetscStrrchr(path, ':', &tail));
448:     tail[-1] = 0; /* remove ":yaml" suffix from path */
449:   }
450:   PetscCall(PetscStrncpy(filename, path, PETSC_MAX_PATH_LEN));
451:   /* check for standard YAML and JSON filename extensions */
452:   if (!*yaml) PetscCall(PetscStrendswith(filename, ".yaml", yaml));
453:   if (!*yaml) PetscCall(PetscStrendswith(filename, ".yml", yaml));
454:   if (!*yaml) PetscCall(PetscStrendswith(filename, ".json", yaml));
455:   if (!*yaml) { /* check file contents */
456:     PetscMPIInt rank;
457:     PetscCallMPI(MPI_Comm_rank(comm, &rank));
458:     if (rank == 0) {
459:       FILE *fh = fopen(filename, "r");
460:       if (fh) {
461:         char buf[6] = "";
462:         if (fread(buf, 1, 6, fh) > 0) {
463:           PetscCall(PetscStrncmp(buf, "%YAML ", 6, yaml));          /* check for '%YAML' tag */
464:           if (!*yaml) PetscCall(PetscStrncmp(buf, "---", 3, yaml)); /* check for document start */
465:         }
466:         (void)fclose(fh);
467:       }
468:     }
469:     PetscCallMPI(MPI_Bcast(yaml, 1, MPI_C_BOOL, 0, comm));
470:   }
471:   PetscFunctionReturn(PETSC_SUCCESS);
472: }

474: static PetscErrorCode PetscOptionsInsertFilePetsc(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
475: {
476:   char       *string, *vstring = NULL, *astring = NULL, *packed = NULL;
477:   const char *tokens[4];
478:   size_t      len;
479:   PetscCount  bytes;
480:   FILE       *fd;
481:   PetscToken  token = NULL;
482:   int         err;
483:   char       *cmatch = NULL;
484:   const char  cmt    = '#';
485:   PetscInt    line   = 1;
486:   PetscMPIInt rank, cnt = 0, acnt = 0, counts[2];
487:   PetscBool   isdir, alias = PETSC_FALSE, valid;

489:   PetscFunctionBegin;
490:   PetscCall(PetscMemzero(tokens, sizeof(tokens)));
491:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
492:   if (rank == 0) {
493:     char fpath[PETSC_MAX_PATH_LEN];
494:     char fname[PETSC_MAX_PATH_LEN];

496:     PetscCall(PetscStrreplace(PETSC_COMM_SELF, file, fname, sizeof(fname)));
497:     PetscCall(PetscFixFilename(fname, fpath));
498:     PetscCall(PetscGetFullPath(fpath, fname, sizeof(fname)));

500:     fd = fopen(fname, "r");
501:     PetscCall(PetscTestDirectory(fname, 'r', &isdir));
502:     PetscCheck(!isdir || !require, PETSC_COMM_SELF, PETSC_ERR_USER, "Specified options file %s is a directory", fname);
503:     if (fd && !isdir) {
504:       PetscSegBuffer vseg, aseg;

506:       PetscCall(PetscSegBufferCreate(1, 4000, &vseg));
507:       PetscCall(PetscSegBufferCreate(1, 2000, &aseg));

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

512:       while ((string = Petscgetline(fd))) {
513:         /* eliminate comments from each line */
514:         PetscCall(PetscStrchr(string, cmt, &cmatch));
515:         if (cmatch) *cmatch = 0;
516:         PetscCall(PetscStrlen(string, &len));
517:         /* replace tabs, ^M, \n with " " */
518:         for (size_t i = 0; i < len; i++) {
519:           if (string[i] == '\t' || string[i] == '\r' || string[i] == '\n') string[i] = ' ';
520:         }
521:         PetscCall(PetscTokenCreate(string, ' ', &token));
522:         PetscCall(PetscTokenFind(token, &tokens[0]));
523:         if (!tokens[0]) {
524:           goto destroy;
525:         } else if (!tokens[0][0]) { /* if token 0 is empty (string begins with spaces), redo */
526:           PetscCall(PetscTokenFind(token, &tokens[0]));
527:         }
528:         for (PetscInt i = 1; i < 4; i++) PetscCall(PetscTokenFind(token, &tokens[i]));
529:         if (!tokens[0]) {
530:           goto destroy;
531:         } else if (tokens[0][0] == '-') {
532:           PetscCall(PetscOptionsValidKey(tokens[0], &valid));
533:           PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": invalid option %s", fname, line, tokens[0]);
534:           PetscCall(PetscStrlen(tokens[0], &len));
535:           PetscCall(PetscSegBufferGet(vseg, len + 1, &vstring));
536:           PetscCall(PetscArraycpy(vstring, tokens[0], len));
537:           vstring[len] = ' ';
538:           if (tokens[1]) {
539:             PetscCall(PetscOptionsValidKey(tokens[1], &valid));
540:             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]);
541:             PetscCall(PetscStrlen(tokens[1], &len));
542:             PetscCall(PetscSegBufferGet(vseg, len + 3, &vstring));
543:             vstring[0] = '"';
544:             PetscCall(PetscArraycpy(vstring + 1, tokens[1], len));
545:             vstring[len + 1] = '"';
546:             vstring[len + 2] = ' ';
547:           }
548:         } else {
549:           PetscCall(PetscStrcasecmp(tokens[0], "alias", &alias));
550:           PetscCheck(alias, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown first token in options file %s line %" PetscInt_FMT ": %s", fname, line, tokens[0]);
551:           PetscCall(PetscOptionsValidKey(tokens[1], &valid));
552:           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]);
553:           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]);
554:           PetscCall(PetscOptionsValidKey(tokens[2], &valid));
555:           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]);
556:           PetscCall(PetscStrlen(tokens[1], &len));
557:           PetscCall(PetscSegBufferGet(aseg, len + 1, &astring));
558:           PetscCall(PetscArraycpy(astring, tokens[1], len));
559:           astring[len] = ' ';

561:           PetscCall(PetscStrlen(tokens[2], &len));
562:           PetscCall(PetscSegBufferGet(aseg, len + 1, &astring));
563:           PetscCall(PetscArraycpy(astring, tokens[2], len));
564:           astring[len] = ' ';
565:         }
566:         {
567:           const char *extraToken = alias ? tokens[3] : tokens[2];
568:           PetscCheck(!extraToken, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": extra token %s", fname, line, extraToken);
569:         }
570:       destroy:
571:         free(string);
572:         PetscCall(PetscTokenDestroy(&token));
573:         alias = PETSC_FALSE;
574:         line++;
575:       }
576:       err = fclose(fd);
577:       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file %s", fname);
578:       PetscCall(PetscSegBufferGetSize(aseg, &bytes)); /* size without null termination */
579:       PetscCall(PetscMPIIntCast(bytes, &acnt));
580:       PetscCall(PetscSegBufferGet(aseg, 1, &astring));
581:       astring[0] = 0;
582:       PetscCall(PetscSegBufferGetSize(vseg, &bytes)); /* size without null termination */
583:       PetscCall(PetscMPIIntCast(bytes, &cnt));
584:       PetscCall(PetscSegBufferGet(vseg, 1, &vstring));
585:       vstring[0] = 0;
586:       PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
587:       PetscCall(PetscSegBufferExtractTo(aseg, packed));
588:       PetscCall(PetscSegBufferExtractTo(vseg, packed + acnt + 1));
589:       PetscCall(PetscSegBufferDestroy(&aseg));
590:       PetscCall(PetscSegBufferDestroy(&vseg));
591:     } else PetscCheck(!require, PETSC_COMM_SELF, PETSC_ERR_USER, "Unable to open options file %s", fname);
592:   }

594:   counts[0] = acnt;
595:   counts[1] = cnt;
596:   err       = MPI_Bcast(counts, 2, MPI_INT, 0, comm);
597:   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/");
598:   acnt = counts[0];
599:   cnt  = counts[1];
600:   if (rank) PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
601:   if (acnt || cnt) {
602:     PetscCallMPI(MPI_Bcast(packed, 2 + acnt + cnt, MPI_CHAR, 0, comm));
603:     astring = packed;
604:     vstring = packed + acnt + 1;
605:   }

607:   if (acnt) {
608:     PetscCall(PetscTokenCreate(astring, ' ', &token));
609:     PetscCall(PetscTokenFind(token, &tokens[0]));
610:     while (tokens[0]) {
611:       PetscCall(PetscTokenFind(token, &tokens[1]));
612:       PetscCall(PetscOptionsSetAlias(options, tokens[0], tokens[1]));
613:       PetscCall(PetscTokenFind(token, &tokens[0]));
614:     }
615:     PetscCall(PetscTokenDestroy(&token));
616:   }

618:   if (cnt) PetscCall(PetscOptionsInsertString_Private(options, vstring, PETSC_OPT_FILE));
619:   PetscCall(PetscFree(packed));
620:   PetscFunctionReturn(PETSC_SUCCESS);
621: }

623: /*@
624:   PetscOptionsInsertFile - Inserts options into the database from a file.

626:   Collective

628:   Input Parameters:
629: + comm    - the processes that will share the options (usually `PETSC_COMM_WORLD`)
630: . options - options database, use `NULL` for default global database
631: . file    - name of file,
632:            ".yml" and ".yaml" filename extensions are inserted as YAML options,
633:            append ":yaml" to filename to force YAML options.
634: - require - if `PETSC_TRUE` will generate an error if the file does not exist

636:   Level: developer

638:   Notes:
639:   Use  # for lines that are comments and which should be ignored.
640:   Usually, instead of using this command, one should list the file name in the call to `PetscInitialize()`, this insures that certain options
641:   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
642:   calls to `XXXSetFromOptions()`, it should not be used for options listed under PetscInitialize().
643:   The collectivity of this routine is complex; only the MPI processes in comm will
644:   have the effect of these options. If some processes that create objects call this routine and others do
645:   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
646:   on different ranks.

648: .seealso: `PetscOptionsSetValue()`, `PetscOptionsView()`, `PetscOptionsHasName()`, `PetscOptionsGetInt()`,
649:           `PetscOptionsGetReal()`, `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
650:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
651:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
652:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
653:           `PetscOptionsFList()`, `PetscOptionsEList()`
654: @*/
655: PetscErrorCode PetscOptionsInsertFile(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
656: {
657:   char      filename[PETSC_MAX_PATH_LEN];
658:   PetscBool yaml;

660:   PetscFunctionBegin;
661:   PetscCall(PetscOptionsFilename(comm, file, filename, &yaml));
662:   if (yaml) {
663:     PetscCall(PetscOptionsInsertFileYAML(comm, options, filename, require));
664:   } else {
665:     PetscCall(PetscOptionsInsertFilePetsc(comm, options, filename, require));
666:   }
667:   PetscFunctionReturn(PETSC_SUCCESS);
668: }

670: /*@
671:   PetscOptionsInsertArgs - Inserts options into the database from a array of strings

673:   Logically Collective

675:   Input Parameters:
676: + options - options object
677: . argc    - the array length
678: - args    - the string array

680:   Level: intermediate

682: .seealso: `PetscOptions`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`
683: @*/
684: PetscErrorCode PetscOptionsInsertArgs(PetscOptions options, int argc, const char *const args[])
685: {
686:   int                left  = PetscMax(argc, 0);
687:   const char *const *eargs = args;

689:   PetscFunctionBegin;
690:   while (left) {
691:     PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;
692:     PetscCall(PetscStrcasecmp(eargs[0], "-options_file", &isfile));
693:     PetscCall(PetscStrcasecmp(eargs[0], "-options_file_yaml", &isfileyaml));
694:     PetscCall(PetscStrcasecmp(eargs[0], "-options_string_yaml", &isstringyaml));
695:     PetscCall(PetscStrcasecmp(eargs[0], "-prefix_push", &ispush));
696:     PetscCall(PetscStrcasecmp(eargs[0], "-prefix_pop", &ispop));
697:     PetscCall(PetscOptionsValidKey(eargs[0], &key));
698:     if (!key) {
699:       eargs++;
700:       left--;
701:     } else if (isfile) {
702:       PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file filename option");
703:       PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, eargs[1], PETSC_TRUE));
704:       eargs += 2;
705:       left -= 2;
706:     } else if (isfileyaml) {
707:       PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file_yaml filename option");
708:       PetscCall(PetscOptionsInsertFileYAML(PETSC_COMM_WORLD, options, eargs[1], PETSC_TRUE));
709:       eargs += 2;
710:       left -= 2;
711:     } else if (isstringyaml) {
712:       PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing string for -options_string_yaml string option");
713:       PetscCall(PetscOptionsInsertStringYAML_Private(options, eargs[1], PETSC_OPT_CODE));
714:       eargs += 2;
715:       left -= 2;
716:     } else if (ispush) {
717:       PetscCheck(left > 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option");
718:       PetscCheck(eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option (prefixes cannot start with '-')");
719:       PetscCall(PetscOptionsPrefixPush(options, eargs[1]));
720:       eargs += 2;
721:       left -= 2;
722:     } else if (ispop) {
723:       PetscCall(PetscOptionsPrefixPop(options));
724:       eargs++;
725:       left--;
726:     } else {
727:       PetscBool nextiskey = PETSC_FALSE;
728:       if (left >= 2) PetscCall(PetscOptionsValidKey(eargs[1], &nextiskey));
729:       if (left < 2 || nextiskey) {
730:         PetscCall(PetscOptionsSetValue_Private(options, eargs[0], NULL, NULL, PETSC_OPT_COMMAND_LINE));
731:         eargs++;
732:         left--;
733:       } else {
734:         PetscCall(PetscOptionsSetValue_Private(options, eargs[0], eargs[1], NULL, PETSC_OPT_COMMAND_LINE));
735:         eargs += 2;
736:         left -= 2;
737:       }
738:     }
739:   }
740:   PetscFunctionReturn(PETSC_SUCCESS);
741: }

743: static inline PetscErrorCode PetscOptionsStringToBoolIfSet_Private(enum PetscPrecedentOption opt, const char *val[], const PetscBool set[], PetscBool *flg)
744: {
745:   PetscFunctionBegin;
746:   if (set[opt]) PetscCall(PetscOptionsStringToBool(val[opt], flg));
747:   else *flg = PETSC_FALSE;
748:   PetscFunctionReturn(PETSC_SUCCESS);
749: }

751: /* Process options with absolute precedence, these are only processed from the command line, not the environment or files */
752: static PetscErrorCode PetscOptionsProcessPrecedentFlags(PetscOptions options, int argc, char *args[], PetscBool *skip_petscrc, PetscBool *skip_petscrc_set)
753: {
754:   const char *const *opt = precedentOptions;
755:   const size_t       n   = PO_NUM;
756:   size_t             o;
757:   int                a;
758:   const char       **val;
759:   char             **cval;
760:   PetscBool         *set, unneeded;
761:   PetscBool          isbool = PETSC_FALSE, helpval = PETSC_FALSE;

763:   PetscFunctionBegin;
764:   PetscCall(PetscCalloc2(n, &cval, n, &set));
765:   val = (const char **)cval;

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

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

774:     PetscCall(PetscOptionsValidKey(args[a], &valid));
775:     if (!valid) continue;
776:     for (o = 0; o < n; o++) {
777:       PetscCall(PetscStrcasecmp(args[a], opt[o], &eq));
778:       if (eq) {
779:         set[o] = PETSC_TRUE;
780:         if (a == argc - 1 || !args[a + 1] || !args[a + 1][0] || args[a + 1][0] == '-') val[o] = NULL;
781:         else val[o] = args[a + 1];
782:         break;
783:       }
784:     }
785:   }

787:   /* Process flags */
788:   /* "-help" accepts a logical value, "intro" or a list of manual sections; PetscOptionsSetValue_Private()
789:      reads it the same way below, and records the manual sections when the option is stored */
790:   PetscCall(PetscOptionsStringToBool_Private(val[PO_HELP], &helpval, &isbool));
791:   PetscCall(PetscStrcasecmp(val[PO_HELP], "intro", &options->help_intro));
792:   if (set[PO_HELP]) options->help = isbool ? helpval : PETSC_TRUE;
793:   else options->help = PETSC_FALSE;
794:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_CI_ENABLE, val, set, &unneeded));
795:   /* need to manage PO_CI_ENABLE option before the PetscOptionsMonitor is turned on, so its setting is not monitored */
796:   if (set[PO_CI_ENABLE]) PetscCall(PetscOptionsSetValue_Private(options, opt[PO_CI_ENABLE], val[PO_CI_ENABLE], &a, PETSC_OPT_COMMAND_LINE));
797:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR_CANCEL, val, set, &options->monitorCancel));
798:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR, val, set, &options->monitorFromOptions));
799:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_SKIP_PETSCRC, val, set, skip_petscrc));
800:   *skip_petscrc_set = set[PO_SKIP_PETSCRC];

802:   /* Store precedent options in database and mark them as used */
803:   for (o = 1; o < n; o++) {
804:     if (set[o]) {
805:       PetscCall(PetscOptionsSetValue_Private(options, opt[o], val[o], &a, PETSC_OPT_COMMAND_LINE));
806:       options->used[a] = PETSC_TRUE;
807:     }
808:   }
809:   PetscCall(PetscFree2(cval, set));
810:   options->precedentProcessed = PETSC_TRUE;
811:   PetscFunctionReturn(PETSC_SUCCESS);
812: }

814: static inline PetscErrorCode PetscOptionsSkipPrecedent(PetscOptions options, const char name[], PetscBool *flg)
815: {
816:   PetscFunctionBegin;
817:   PetscAssertPointer(flg, 3);
818:   *flg = PETSC_FALSE;
819:   if (options->precedentProcessed) {
820:     for (int i = 0; i < PO_NUM; ++i) {
821:       if (!PetscOptNameCmp(precedentOptions[i], name)) {
822:         /* check if precedent option has been set already */
823:         PetscCall(PetscOptionsFindPair(options, NULL, name, NULL, flg));
824:         if (*flg) break;
825:       }
826:     }
827:   }
828:   PetscFunctionReturn(PETSC_SUCCESS);
829: }

831: /*@
832:   PetscOptionsInsert - Inserts into the options database from the command line,
833:   the environmental variable and a file.

835:   Collective on `PETSC_COMM_WORLD`

837:   Input Parameters:
838: + options - options database or `NULL` for the default global database
839: . argc    - count of number of command line arguments
840: . args    - the command line arguments
841: - file    - [optional] PETSc database file, append ":yaml" to filename to specify YAML options format.
842:             Use `NULL` or empty string to not check for code specific file.
843:             Also checks ~/.petscrc, .petscrc and petscrc.
844:             Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.

846:   Options Database Keys:
847: + -options_file filename      - read options from a file
848: - -options_file_yaml filename - read options from a YAML file

850:   Level: advanced

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

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

859: .seealso: `PetscOptionsDestroy()`, `PetscOptionsView()`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`,
860:           `PetscInitialize()`
861: @*/
862: PetscErrorCode PetscOptionsInsert(PetscOptions options, int *argc, char ***args, const char file[]) PeNS
863: {
864:   PetscMPIInt rank;
865:   PetscBool   hasArgs     = (argc && *argc) ? PETSC_TRUE : PETSC_FALSE;
866:   PetscBool   skipPetscrc = PETSC_FALSE, skipPetscrcSet = PETSC_FALSE;
867:   char       *eoptions = NULL;
868:   size_t      len      = 0;

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

874:   if (!options) {
875:     PetscCall(PetscOptionsCreateDefault());
876:     options = defaultoptions;
877:   }
878:   if (hasArgs) {
879:     /* process options with absolute precedence */
880:     PetscCall(PetscOptionsProcessPrecedentFlags(options, *argc, *args, &skipPetscrc, &skipPetscrcSet));
881:     PetscCall(PetscOptionsGetBool(NULL, NULL, "-petsc_ci", &PetscCIEnabled, NULL));
882:   }
883:   if (file && file[0]) {
884:     PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, file, PETSC_TRUE));
885:     /* if -skip_petscrc has not been set from command line, check whether it has been set in the file */
886:     if (!skipPetscrcSet) PetscCall(PetscOptionsGetBool(options, NULL, "-skip_petscrc", &skipPetscrc, NULL));
887:   }
888:   if (!skipPetscrc) {
889:     char filename[PETSC_MAX_PATH_LEN];

891:     PetscCall(PetscGetHomeDirectory(filename, sizeof(filename)));
892:     PetscCallMPI(MPI_Bcast(filename, (int)sizeof(filename), MPI_CHAR, 0, PETSC_COMM_WORLD));
893:     if (filename[0]) PetscCall(PetscStrlcat(filename, "/.petscrc", sizeof(filename)));
894:     PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, filename, PETSC_FALSE));
895:     PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, ".petscrc", PETSC_FALSE));
896:     PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, "petscrc", PETSC_FALSE));
897:   }

899:   /* insert environment options */
900:   if (rank == 0) {
901:     eoptions = getenv("PETSC_OPTIONS");
902:     PetscCall(PetscStrlen(eoptions, &len));
903:   }
904:   PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, PETSC_COMM_WORLD));
905:   if (len) {
906:     if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
907:     PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, PETSC_COMM_WORLD));
908:     if (rank) eoptions[len] = 0;
909:     PetscCall(PetscOptionsInsertString_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
910:     if (rank) PetscCall(PetscFree(eoptions));
911:   }

913:   /* insert YAML environment options */
914:   if (rank == 0) {
915:     eoptions = getenv("PETSC_OPTIONS_YAML");
916:     PetscCall(PetscStrlen(eoptions, &len));
917:   }
918:   PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, PETSC_COMM_WORLD));
919:   if (len) {
920:     if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
921:     PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, PETSC_COMM_WORLD));
922:     if (rank) eoptions[len] = 0;
923:     PetscCall(PetscOptionsInsertStringYAML_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
924:     if (rank) PetscCall(PetscFree(eoptions));
925:   }

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

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

937: static PetscBool PetscCIOption(const char *name)
938: {
939:   PetscInt  idx;
940:   PetscBool found;

942:   if (!PetscCIEnabled) return PETSC_FALSE;
943:   PetscCallAbort(PETSC_COMM_SELF, PetscEListFind(PETSC_STATIC_ARRAY_LENGTH(PetscCIOptions), PetscCIOptions, name, &idx, &found));
944:   return found;
945: }

947: /*@
948:   PetscOptionsView - Prints the options that have been loaded. This is
949:   useful for debugging purposes.

951:   Logically Collective, No Fortran Support

953:   Input Parameters:
954: + options - options database, use `NULL` for default global database
955: - viewer  - must be an `PETSCVIEWERASCII` viewer

957:   Options Database Key:
958: . -options_view (true|false) - Activates `PetscOptionsView()` within `PetscFinalize()`.

960:   Level: advanced

962:   Note:
963:   Only the MPI rank 0 of the `MPI_Comm` used to create `viewer` displays the option values. Other processes
964:   may have different values but they are not printed.

966: .seealso: `PetscOptionsAllUsed()`
967: @*/
968: PetscErrorCode PetscOptionsView(PetscOptions options, PetscViewer viewer)
969: {
970:   PetscInt  i, N = 0;
971:   PetscBool isascii;

973:   PetscFunctionBegin;
975:   options = options ? options : defaultoptions;
976:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
977:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
978:   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");

980:   for (i = 0; i < options->N; i++) {
981:     if (PetscCIOption(options->names[i])) continue;
982:     N++;
983:   }

985:   if (!N) {
986:     PetscCall(PetscViewerASCIIPrintf(viewer, "#No PETSc Option Table entries\n"));
987:     PetscFunctionReturn(PETSC_SUCCESS);
988:   }

990:   PetscCall(PetscViewerASCIIPrintf(viewer, "#PETSc Option Table entries:\n"));
991:   for (i = 0; i < options->N; i++) {
992:     if (PetscCIOption(options->names[i])) continue;
993:     if (options->values[i]) {
994:       PetscCall(PetscViewerASCIIPrintf(viewer, "-%s %s", options->names[i], options->values[i]));
995:     } else {
996:       PetscCall(PetscViewerASCIIPrintf(viewer, "-%s", options->names[i]));
997:     }
998:     PetscCall(PetscViewerASCIIPrintf(viewer, " # (source: %s)\n", PetscOptionSources[options->source[i]]));
999:   }
1000:   PetscCall(PetscViewerASCIIPrintf(viewer, "#End of PETSc Option Table entries\n"));
1001:   PetscFunctionReturn(PETSC_SUCCESS);
1002: }

1004: /*@
1005:   PetscOptionsLeftError - Prints a warning listing any options in the default database that were never used

1007:   Not Collective

1009:   Level: developer

1011:   Note:
1012:   This is intended for use inside PETSc error handlers. Unused options may indicate a program that crashed before it
1013:   read them, a spelling mistake, or an option intended for a different context.

1015: .seealso: `PetscOptionsLeft()`, `PetscOptionsAllUsed()`, `PetscOptionsView()`
1016: @*/
1017: PetscErrorCode PetscOptionsLeftError(void)
1018: {
1019:   PetscInt i, nopt = 0;

1021:   for (i = 0; i < defaultoptions->N; i++) {
1022:     if (!defaultoptions->used[i]) {
1023:       if (PetscCIOption(defaultoptions->names[i])) continue;
1024:       nopt++;
1025:     }
1026:   }
1027:   if (nopt) {
1028:     PetscCall((*PetscErrorPrintf)("WARNING! There are unused option(s) set! Could be the program crashed before usage or a spelling mistake, etc!\n"));
1029:     for (i = 0; i < defaultoptions->N; i++) {
1030:       if (!defaultoptions->used[i]) {
1031:         if (PetscCIOption(defaultoptions->names[i])) continue;
1032:         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]]));
1033:         else PetscCall((*PetscErrorPrintf)("  Option left: name:-%s (no value) source: %s\n", defaultoptions->names[i], PetscOptionSources[defaultoptions->source[i]]));
1034:       }
1035:     }
1036:   }
1037:   return PETSC_SUCCESS;
1038: }

1040: PETSC_EXTERN PetscErrorCode PetscOptionsViewError(void)
1041: {
1042:   PetscInt     i, N = 0;
1043:   PetscOptions options = defaultoptions;

1045:   for (i = 0; i < options->N; i++) {
1046:     if (PetscCIOption(options->names[i])) continue;
1047:     N++;
1048:   }

1050:   if (N) {
1051:     PetscCall((*PetscErrorPrintf)("PETSc Option Table entries:\n"));
1052:   } else {
1053:     PetscCall((*PetscErrorPrintf)("No PETSc Option Table entries\n"));
1054:   }
1055:   for (i = 0; i < options->N; i++) {
1056:     if (PetscCIOption(options->names[i])) continue;
1057:     if (options->values[i]) {
1058:       PetscCall((*PetscErrorPrintf)("-%s %s (source: %s)\n", options->names[i], options->values[i], PetscOptionSources[options->source[i]]));
1059:     } else {
1060:       PetscCall((*PetscErrorPrintf)("-%s (source: %s)\n", options->names[i], PetscOptionSources[options->source[i]]));
1061:     }
1062:   }
1063:   return PETSC_SUCCESS;
1064: }

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

1069:   Logically Collective

1071:   Input Parameters:
1072: + options - options database, or `NULL` for the default global database
1073: - prefix  - The string to append to the existing prefix

1075:   Options Database Keys:
1076: + -prefix_push some_prefix_ - push the given prefix
1077: - -prefix_pop               - pop the last prefix

1079:   Level: advanced

1081:   Notes:
1082:   It is common to use this in conjunction with `-options_file` as in
1083: .vb
1084:  -prefix_push system1_ -options_file system1rc -prefix_pop -prefix_push system2_ -options_file system2rc -prefix_pop
1085: .ve
1086:   where the files no longer require all options to be prefixed with `-system2_`.

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

1093: .seealso: `PetscOptionsPrefixPop()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1094: @*/
1095: PetscErrorCode PetscOptionsPrefixPush(PetscOptions options, const char prefix[])
1096: {
1097:   size_t    n;
1098:   PetscInt  start;
1099:   char      key[PETSC_MAX_OPTION_NAME + 1];
1100:   PetscBool valid;

1102:   PetscFunctionBegin;
1103:   PetscAssertPointer(prefix, 2);
1104:   options = options ? options : defaultoptions;
1105:   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);
1106:   key[0] = '-'; /* keys must start with '-' */
1107:   PetscCall(PetscStrncpy(key + 1, prefix, sizeof(key) - 1));
1108:   PetscCall(PetscOptionsValidKey(key, &valid));
1109:   if (!valid && options->prefixind > 0 && isdigit((int)prefix[0])) valid = PETSC_TRUE; /* If the prefix stack is not empty, make numbers a valid prefix */
1110:   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" : "");
1111:   start = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1112:   PetscCall(PetscStrlen(prefix, &n));
1113:   PetscCheck(n + 1 <= sizeof(options->prefix) - start, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum prefix length %zu exceeded", sizeof(options->prefix));
1114:   PetscCall(PetscArraycpy(options->prefix + start, prefix, n + 1));
1115:   options->prefixstack[options->prefixind++] = (int)(start + n);
1116:   PetscFunctionReturn(PETSC_SUCCESS);
1117: }

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

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

1124:   Input Parameter:
1125: . options - options database, or `NULL` for the default global database

1127:   Level: advanced

1129: .seealso: `PetscOptionsPrefixPush()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1130: @*/
1131: PetscErrorCode PetscOptionsPrefixPop(PetscOptions options)
1132: {
1133:   PetscInt offset;

1135:   PetscFunctionBegin;
1136:   options = options ? options : defaultoptions;
1137:   PetscCheck(options->prefixind >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More prefixes popped than pushed");
1138:   options->prefixind--;
1139:   offset                  = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1140:   options->prefix[offset] = 0;
1141:   PetscFunctionReturn(PETSC_SUCCESS);
1142: }

1144: /* Releases the manual sections recorded from "-help mansec,..." and marks the help output as unrestricted. */
1145: static PetscErrorCode PetscOptionsHelpManSecsClear_Private(PetscOptions options)
1146: {
1147:   PetscFunctionBegin;
1148:   PetscCall(PetscStrToArrayDestroy(options->help_nmansecs, options->help_mansecs));
1149:   options->help_nmansecs = 0;
1150:   options->help_mansecs  = NULL;
1151:   PetscFunctionReturn(PETSC_SUCCESS);
1152: }

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

1157:   Logically Collective

1159:   Input Parameter:
1160: . options - options database, use `NULL` for the default global database

1162:   Level: developer

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

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

1173: .seealso: `PetscOptionsInsert()`
1174: @*/
1175: PetscErrorCode PetscOptionsClear(PetscOptions options)
1176: {
1177:   PetscInt i;

1179:   PetscFunctionBegin;
1180:   options = options ? options : defaultoptions;
1181:   if (!options) PetscFunctionReturn(PETSC_SUCCESS);

1183:   for (i = 0; i < options->N; i++) {
1184:     if (options->names[i]) free(options->names[i]);
1185:     if (options->values[i]) free(options->values[i]);
1186:   }
1187:   options->N = 0;
1188:   free(options->names);
1189:   free(options->values);
1190:   free(options->used);
1191:   free(options->source);
1192:   options->names  = NULL;
1193:   options->values = NULL;
1194:   options->used   = NULL;
1195:   options->source = NULL;
1196:   options->Nalloc = 0;

1198:   for (i = 0; i < options->Na; i++) {
1199:     free(options->aliases1[i]);
1200:     free(options->aliases2[i]);
1201:   }
1202:   options->Na = 0;
1203:   free(options->aliases1);
1204:   free(options->aliases2);
1205:   options->aliases1 = options->aliases2 = NULL;
1206:   options->Naalloc                      = 0;

1208:   /* destroy hash table */
1209:   kh_destroy(HO, options->ht);
1210:   options->ht = NULL;

1212:   options->prefixind  = 0;
1213:   options->prefix[0]  = 0;
1214:   options->help       = PETSC_FALSE;
1215:   options->help_intro = PETSC_FALSE;
1216:   PetscCall(PetscOptionsHelpManSecsClear_Private(options));
1217:   PetscFunctionReturn(PETSC_SUCCESS);
1218: }

1220: /*@
1221:   PetscOptionsSetAlias - Makes a key and alias for another key

1223:   Logically Collective

1225:   Input Parameters:
1226: + options - options database, or `NULL` for default global database
1227: . newname - the alias
1228: - oldname - the name that alias will refer to

1230:   Level: advanced

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

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

1241: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1242:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1243:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1244:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1245:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1246:           `PetscOptionsFList()`, `PetscOptionsEList()`
1247: @*/
1248: PetscErrorCode PetscOptionsSetAlias(PetscOptions options, const char newname[], const char oldname[])
1249: {
1250:   size_t    len;
1251:   PetscBool valid;

1253:   PetscFunctionBegin;
1254:   PetscAssertPointer(newname, 2);
1255:   PetscAssertPointer(oldname, 3);
1256:   options = options ? options : defaultoptions;
1257:   PetscCall(PetscOptionsValidKey(newname, &valid));
1258:   PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliased option %s", newname);
1259:   PetscCall(PetscOptionsValidKey(oldname, &valid));
1260:   PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliasee option %s", oldname);

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

1265:     options->Naalloc = PetscMax(4, options->Naalloc * 2);
1266:     tmpA1            = (char **)malloc(options->Naalloc * sizeof(char *));
1267:     tmpA2            = (char **)malloc(options->Naalloc * sizeof(char *));
1268:     for (int i = 0; i < options->Na; ++i) {
1269:       tmpA1[i] = options->aliases1[i];
1270:       tmpA2[i] = options->aliases2[i];
1271:     }
1272:     free(options->aliases1);
1273:     free(options->aliases2);
1274:     options->aliases1 = tmpA1;
1275:     options->aliases2 = tmpA2;
1276:   }
1277:   newname++;
1278:   oldname++;
1279:   PetscCall(PetscStrlen(newname, &len));
1280:   options->aliases1[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1281:   PetscCall(PetscStrncpy(options->aliases1[options->Na], newname, len + 1));
1282:   PetscCall(PetscStrlen(oldname, &len));
1283:   options->aliases2[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1284:   PetscCall(PetscStrncpy(options->aliases2[options->Na], oldname, len + 1));
1285:   ++options->Na;
1286:   PetscFunctionReturn(PETSC_SUCCESS);
1287: }

1289: /*@
1290:   PetscOptionsSetValue - Sets an option name-value pair in the options
1291:   database, overriding whatever is already present.

1293:   Logically Collective

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

1300:   Level: intermediate

1302:   Note:
1303:   This function can be called BEFORE `PetscInitialize()`

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

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

1313: .seealso: `PetscOptionsInsert()`, `PetscOptionsClearValue()`
1314: @*/
1315: PetscErrorCode PetscOptionsSetValue(PetscOptions options, const char name[], const char value[])
1316: {
1317:   PetscFunctionBegin;
1318:   PetscCall(PetscOptionsSetValue_Private(options, name, value, NULL, PETSC_OPT_CODE));
1319:   PetscFunctionReturn(PETSC_SUCCESS);
1320: }

1322: PetscErrorCode PetscOptionsSetValue_Private(PetscOptions options, const char name[], const char value[], int *pos, PetscOptionSource source)
1323: {
1324:   size_t    len;
1325:   int       n, i;
1326:   char    **names;
1327:   char      fullname[PETSC_MAX_OPTION_NAME] = "";
1328:   PetscBool flg;

1330:   PetscFunctionBegin;
1331:   if (!options) {
1332:     PetscCall(PetscOptionsCreateDefault());
1333:     options = defaultoptions;
1334:   }
1335:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "name %s must start with '-'", name);

1337:   PetscCall(PetscOptionsSkipPrecedent(options, name, &flg));
1338:   if (flg) PetscFunctionReturn(PETSC_SUCCESS);

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

1342:   if (options->prefixind > 0) {
1343:     strncpy(fullname, options->prefix, sizeof(fullname));
1344:     fullname[sizeof(fullname) - 1] = 0;
1345:     strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
1346:     fullname[sizeof(fullname) - 1] = 0;
1347:     name                           = fullname;
1348:   }

1350:   /* check against aliases */
1351:   for (i = 0; i < options->Na; i++) {
1352:     int result = PetscOptNameCmp(options->aliases1[i], name);
1353:     if (!result) {
1354:       name = options->aliases2[i];
1355:       break;
1356:     }
1357:   }

1359:   /* slow search */
1360:   n     = options->N;
1361:   names = options->names;
1362:   for (i = 0; i < options->N; i++) {
1363:     int result = PetscOptNameCmp(names[i], name);
1364:     if (!result) {
1365:       n = i;
1366:       goto setvalue;
1367:     } else if (result > 0) {
1368:       n = i;
1369:       break;
1370:     }
1371:   }
1372:   if (options->N == options->Nalloc) {
1373:     char             **names, **values;
1374:     PetscBool         *used;
1375:     PetscOptionSource *source;

1377:     options->Nalloc = PetscMax(10, options->Nalloc * 2);
1378:     names           = (char **)malloc(options->Nalloc * sizeof(char *));
1379:     values          = (char **)malloc(options->Nalloc * sizeof(char *));
1380:     used            = (PetscBool *)malloc(options->Nalloc * sizeof(PetscBool));
1381:     source          = (PetscOptionSource *)malloc(options->Nalloc * sizeof(PetscOptionSource));
1382:     for (int i = 0; i < options->N; ++i) {
1383:       names[i]  = options->names[i];
1384:       values[i] = options->values[i];
1385:       used[i]   = options->used[i];
1386:       source[i] = options->source[i];
1387:     }
1388:     free(options->names);
1389:     free(options->values);
1390:     free(options->used);
1391:     free(options->source);
1392:     options->names  = names;
1393:     options->values = values;
1394:     options->used   = used;
1395:     options->source = source;
1396:   }

1398:   /* shift remaining values up 1 */
1399:   for (i = options->N; i > n; i--) {
1400:     options->names[i]  = options->names[i - 1];
1401:     options->values[i] = options->values[i - 1];
1402:     options->used[i]   = options->used[i - 1];
1403:     options->source[i] = options->source[i - 1];
1404:   }
1405:   options->names[n]  = NULL;
1406:   options->values[n] = NULL;
1407:   options->used[n]   = PETSC_FALSE;
1408:   options->source[n] = PETSC_OPT_CODE;
1409:   options->N++;

1411:   /* destroy hash table */
1412:   kh_destroy(HO, options->ht);
1413:   options->ht = NULL;

1415:   /* set new name */
1416:   len               = strlen(name);
1417:   options->names[n] = (char *)malloc((len + 1) * sizeof(char));
1418:   PetscCheck(options->names[n], PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate option name");
1419:   strcpy(options->names[n], name);

1421: setvalue:
1422:   /* set new value */
1423:   if (options->values[n]) free(options->values[n]);
1424:   len = value ? strlen(value) : 0;
1425:   if (len) {
1426:     options->values[n] = (char *)malloc((len + 1) * sizeof(char));
1427:     if (!options->values[n]) return PETSC_ERR_MEM;
1428:     strcpy(options->values[n], value);
1429:     options->values[n][len] = '\0';
1430:   } else {
1431:     options->values[n] = NULL;
1432:   }
1433:   options->source[n] = source;

1435:   /* handle -help so that it can be set from anywhere */
1436:   if (!PetscOptNameCmp(name, "help")) {
1437:     PetscBool isbool = PETSC_FALSE, helpval = PETSC_FALSE;

1439:     PetscCall(PetscOptionsStringToBool_Private(value, &helpval, &isbool));
1440:     options->help       = isbool ? helpval : PETSC_TRUE;
1441:     options->help_intro = (!isbool && value && !PetscOptNameCmp(value, "intro")) ? PETSC_TRUE : PETSC_FALSE;
1442:     options->used[n]    = PETSC_TRUE;
1443:     PetscCall(PetscOptionsHelpManSecsClear_Private(options));
1444:     /* a value that is neither a logical value nor "intro" is a comma-separated list of manual sections that
1445:        restricts the help output; PetscStrToArray() uses raw malloc()/free() like names[]/values[], as needed
1446:        here since -help is processed before the tracking allocator is set up */
1447:     if (!isbool && value && value[0] && !options->help_intro) PetscCall(PetscStrToArray(value, ',', &options->help_nmansecs, &options->help_mansecs));
1448:   }

1450:   PetscCall(PetscOptionsMonitor(options, name, value ? value : "", source));
1451:   if (pos) *pos = n;
1452:   PetscFunctionReturn(PETSC_SUCCESS);
1453: }

1455: /*@
1456:   PetscOptionsClearValue - Clears an option name-value pair in the options
1457:   database, overriding whatever is already present.

1459:   Logically Collective

1461:   Input Parameters:
1462: + options - options database, use `NULL` for the default global database
1463: - name    - name of option, this SHOULD have the - prepended

1465:   Level: intermediate

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

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

1476: .seealso: `PetscOptionsInsert()`
1477: @*/
1478: PetscErrorCode PetscOptionsClearValue(PetscOptions options, const char name[])
1479: {
1480:   int    N, n, i;
1481:   char **names;

1483:   PetscFunctionBegin;
1484:   options = options ? options : defaultoptions;
1485:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1486:   if (!PetscOptNameCmp(name, "-help")) {
1487:     options->help = options->help_intro = PETSC_FALSE;
1488:     PetscCall(PetscOptionsHelpManSecsClear_Private(options));
1489:   }

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

1493:   /* slow search */
1494:   N = n = options->N;
1495:   names = options->names;
1496:   for (i = 0; i < N; i++) {
1497:     int result = PetscOptNameCmp(names[i], name);
1498:     if (!result) {
1499:       n = i;
1500:       break;
1501:     } else if (result > 0) {
1502:       n = N;
1503:       break;
1504:     }
1505:   }
1506:   if (n == N) PetscFunctionReturn(PETSC_SUCCESS); /* it was not present */

1508:   /* remove name and value */
1509:   if (options->names[n]) free(options->names[n]);
1510:   if (options->values[n]) free(options->values[n]);
1511:   /* shift remaining values down 1 */
1512:   for (i = n; i < N - 1; i++) {
1513:     options->names[i]  = options->names[i + 1];
1514:     options->values[i] = options->values[i + 1];
1515:     options->used[i]   = options->used[i + 1];
1516:     options->source[i] = options->source[i + 1];
1517:   }
1518:   options->N--;

1520:   /* destroy hash table */
1521:   kh_destroy(HO, options->ht);
1522:   options->ht = NULL;

1524:   PetscCall(PetscOptionsMonitor(options, name, NULL, PETSC_OPT_CODE));
1525:   PetscFunctionReturn(PETSC_SUCCESS);
1526: }

1528: /*@
1529:   PetscOptionsFindPair - Gets an option name-value pair from the options database.

1531:   Not Collective

1533:   Input Parameters:
1534: + options - options database, use `NULL` for the default global database
1535: . pre     - the string to prepend to the name or `NULL`, this SHOULD NOT have the "-" prepended
1536: - name    - name of option, this SHOULD have the "-" prepended

1538:   Output Parameters:
1539: + value - the option value (optional, not used for all options)
1540: - set   - whether the option is set (optional)

1542:   Level: developer

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

1547: .seealso: `PetscOptionsSetValue()`, `PetscOptionsClearValue()`
1548: @*/
1549: PetscErrorCode PetscOptionsFindPair(PetscOptions options, const char pre[], const char name[], const char *value[], PetscBool *set)
1550: {
1551:   char      buf[PETSC_MAX_OPTION_NAME];
1552:   PetscBool matchnumbers = PETSC_TRUE;

1554:   PetscFunctionBegin;
1555:   if (!options) {
1556:     PetscCall(PetscOptionsCreateDefault());
1557:     options = defaultoptions;
1558:   }
1559:   PetscCheck(!pre || !PetscUnlikely(pre[0] == '-'), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1560:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);

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

1564:   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1565:   if (pre && pre[0]) {
1566:     char *ptr = buf;
1567:     if (name[0] == '-') {
1568:       *ptr++ = '-';
1569:       name++;
1570:     }
1571:     PetscCall(PetscStrncpy(ptr, pre, buf + sizeof(buf) - ptr));
1572:     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1573:     name = buf;
1574:   }

1576:   if (PetscDefined(USE_DEBUG)) {
1577:     PetscBool valid;
1578:     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1579:     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1580:     PetscCall(PetscOptionsValidKey(key, &valid));
1581:     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1582:   }

1584:   if (!options->ht) {
1585:     int          i, ret;
1586:     khiter_t     it;
1587:     khash_t(HO) *ht;
1588:     ht = kh_init(HO);
1589:     PetscCheck(ht, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1590:     ret = kh_resize(HO, ht, options->N * 2); /* twice the required size to reduce risk of collisions */
1591:     PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1592:     for (i = 0; i < options->N; i++) {
1593:       it = kh_put(HO, ht, options->names[i], &ret);
1594:       PetscCheck(ret == 1, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1595:       kh_val(ht, it) = i;
1596:     }
1597:     options->ht = ht;
1598:   }

1600:   khash_t(HO) *ht = options->ht;
1601:   khiter_t     it = kh_get(HO, ht, name);
1602:   if (it != kh_end(ht)) {
1603:     int i            = kh_val(ht, it);
1604:     options->used[i] = PETSC_TRUE;
1605:     if (value) *value = options->values[i];
1606:     if (set) *set = PETSC_TRUE;
1607:     PetscFunctionReturn(PETSC_SUCCESS);
1608:   }

1610:   /*
1611:    The following block slows down all lookups in the most frequent path (most lookups are unsuccessful).
1612:    Maybe this special lookup mode should be enabled on request with a push/pop API.
1613:    The feature of matching _%d_ used sparingly in the codebase.
1614:    */
1615:   if (matchnumbers) {
1616:     int i, j, cnt = 0, locs[16], loce[16];
1617:     /* determine the location and number of all _%d_ in the key */
1618:     for (i = 0; name[i]; i++) {
1619:       if (name[i] == '_') {
1620:         for (j = i + 1; name[j]; j++) {
1621:           if (name[j] >= '0' && name[j] <= '9') continue;
1622:           if (name[j] == '_' && j > i + 1) { /* found a number */
1623:             locs[cnt]   = i + 1;
1624:             loce[cnt++] = j + 1;
1625:           }
1626:           i = j - 1;
1627:           break;
1628:         }
1629:       }
1630:     }
1631:     for (i = 0; i < cnt; i++) {
1632:       PetscBool found;
1633:       char      opt[PETSC_MAX_OPTION_NAME + 1] = "-", tmp[PETSC_MAX_OPTION_NAME];
1634:       PetscCall(PetscStrncpy(tmp, name, PetscMin((size_t)(locs[i] + 1), sizeof(tmp))));
1635:       PetscCall(PetscStrlcat(opt, tmp, sizeof(opt)));
1636:       PetscCall(PetscStrlcat(opt, name + loce[i], sizeof(opt)));
1637:       PetscCall(PetscOptionsFindPair(options, NULL, opt, value, &found));
1638:       if (found) {
1639:         if (set) *set = PETSC_TRUE;
1640:         PetscFunctionReturn(PETSC_SUCCESS);
1641:       }
1642:     }
1643:   }

1645:   if (set) *set = PETSC_FALSE;
1646:   PetscFunctionReturn(PETSC_SUCCESS);
1647: }

1649: /* Check whether any option begins with pre+name */
1650: PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions options, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *set)
1651: {
1652:   char buf[PETSC_MAX_OPTION_NAME];
1653:   int  numCnt = 0, locs[16], loce[16];

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

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

1662:   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1663:   if (pre && pre[0]) {
1664:     char *ptr = buf;
1665:     if (name[0] == '-') {
1666:       *ptr++ = '-';
1667:       name++;
1668:     }
1669:     PetscCall(PetscStrncpy(ptr, pre, sizeof(buf) - ((ptr == buf) ? 0 : 1)));
1670:     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1671:     name = buf;
1672:   }

1674:   if (PetscDefined(USE_DEBUG)) {
1675:     PetscBool valid;
1676:     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1677:     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1678:     PetscCall(PetscOptionsValidKey(key, &valid));
1679:     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1680:   }

1682:   /* determine the location and number of all _%d_ in the key */
1683:   {
1684:     int i, j;
1685:     for (i = 0; name[i]; i++) {
1686:       if (name[i] == '_') {
1687:         for (j = i + 1; name[j]; j++) {
1688:           if (name[j] >= '0' && name[j] <= '9') continue;
1689:           if (name[j] == '_' && j > i + 1) { /* found a number */
1690:             locs[numCnt]   = i + 1;
1691:             loce[numCnt++] = j + 1;
1692:           }
1693:           i = j - 1;
1694:           break;
1695:         }
1696:       }
1697:     }
1698:   }

1700:   /* slow search */
1701:   for (int c = -1; c < numCnt; ++c) {
1702:     char   opt[PETSC_MAX_OPTION_NAME + 2] = "";
1703:     size_t len;

1705:     if (c < 0) {
1706:       PetscCall(PetscStrncpy(opt, name, sizeof(opt)));
1707:     } else {
1708:       PetscCall(PetscStrncpy(opt, name, PetscMin((size_t)(locs[c] + 1), sizeof(opt))));
1709:       PetscCall(PetscStrlcat(opt, name + loce[c], sizeof(opt) - 1));
1710:     }
1711:     PetscCall(PetscStrlen(opt, &len));
1712:     for (int i = 0; i < options->N; i++) {
1713:       PetscBool match;

1715:       PetscCall(PetscStrncmp(options->names[i], opt, len, &match));
1716:       if (match) {
1717:         options->used[i] = PETSC_TRUE;
1718:         if (option) *option = options->names[i];
1719:         if (value) *value = options->values[i];
1720:         if (set) *set = PETSC_TRUE;
1721:         PetscFunctionReturn(PETSC_SUCCESS);
1722:       }
1723:     }
1724:   }

1726:   if (set) *set = PETSC_FALSE;
1727:   PetscFunctionReturn(PETSC_SUCCESS);
1728: }

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

1733:   Not Collective

1735:   Input Parameters:
1736: + options - options database, use `NULL` for default global database
1737: . pre     - the option prefix (may be `NULL`)
1738: . name    - the option name one is seeking
1739: - mess    - error message (may be `NULL`)

1741:   Level: advanced

1743: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1744:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1745:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1746:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1747:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1748:           `PetscOptionsFList()`, `PetscOptionsEList()`
1749: @*/
1750: PetscErrorCode PetscOptionsReject(PetscOptions options, const char pre[], const char name[], const char mess[])
1751: {
1752:   PetscBool flag = PETSC_FALSE;

1754:   PetscFunctionBegin;
1755:   PetscCall(PetscOptionsHasName(options, pre, name, &flag));
1756:   if (flag) {
1757:     PetscCheck(!mess || !mess[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s with %s", pre ? pre : "", name + 1, mess);
1758:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s", pre ? pre : "", name + 1);
1759:   }
1760:   PetscFunctionReturn(PETSC_SUCCESS);
1761: }

1763: /*@
1764:   PetscOptionsHasHelp - Determines whether help output has been requested with the "-help" option.

1766:   Not Collective

1768:   Input Parameter:
1769: . options - options database, use `NULL` for default global database

1771:   Output Parameter:
1772: . set - `PETSC_TRUE` if requested else `PETSC_FALSE`.

1774:   Level: advanced

1776:   Note:
1777:   `-help` accepts a logical value, so this returns `PETSC_FALSE` for `-help 0`, `-help no`, `-help false`
1778:   and `-help off` even though "-help" is then in the database. It returns `PETSC_TRUE` for `-help mansec`,
1779:   which restricts rather than suppresses the help output.

1781: .seealso: `PetscOptionsHasName()`
1782: @*/
1783: PetscErrorCode PetscOptionsHasHelp(PetscOptions options, PetscBool *set)
1784: {
1785:   PetscFunctionBegin;
1786:   PetscAssertPointer(set, 2);
1787:   options = options ? options : defaultoptions;
1788:   *set    = options->help;
1789:   PetscFunctionReturn(PETSC_SUCCESS);
1790: }

1792: PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions options, PetscBool *set)
1793: {
1794:   PetscFunctionBegin;
1795:   PetscAssertPointer(set, 2);
1796:   options = options ? options : defaultoptions;
1797:   *set    = options->help_intro;
1798:   PetscFunctionReturn(PETSC_SUCCESS);
1799: }

1801: /* Returns the manual sections given with "-help mansec,...", with n set to 0 when the help output should not be
1802:    restricted. mansec may be NULL. The returned array is borrowed and remains valid until the option is cleared. */
1803: PetscErrorCode PetscOptionsHelpManSecs_Internal(PetscOptions options, PetscInt *n, const char *const *mansec[])
1804: {
1805:   PetscFunctionBegin;
1806:   PetscAssertPointer(n, 2);
1807:   options = options ? options : defaultoptions;
1808:   *n      = options->help_nmansecs;
1809:   if (mansec) *mansec = (const char *const *)options->help_mansecs;
1810:   PetscFunctionReturn(PETSC_SUCCESS);
1811: }

1813: /* Returns in print whether the help output documented in manual section mansec should be printed, taking both
1814:    "-help" and any "-help mansec,..." restriction into account. mansec is the manual section that help belongs
1815:    to; it may be NULL for help that belongs to none, which a restriction never selects. */
1816: PetscErrorCode PetscOptionsHelpPrintable_Internal(PetscOptions options, const char mansec[], PetscBool *print)
1817: {
1818:   PetscInt           nmansec = 0, idx = 0;
1819:   const char *const *mansecs = NULL;

1821:   PetscFunctionBegin;
1822:   PetscAssertPointer(print, 3);
1823:   PetscCall(PetscOptionsHasHelp(options, print));
1824:   if (!*print) PetscFunctionReturn(PETSC_SUCCESS);
1825:   PetscCall(PetscOptionsHelpManSecs_Internal(options, &nmansec, &mansecs));
1826:   if (!nmansec) PetscFunctionReturn(PETSC_SUCCESS);
1827:   *print = PETSC_FALSE;
1828:   if (mansec && mansec[0]) PetscCall(PetscEListFind(nmansec, mansecs, mansec, &idx, print));
1829:   PetscFunctionReturn(PETSC_SUCCESS);
1830: }

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

1836:   Not Collective

1838:   Input Parameters:
1839: + options - options database, use `NULL` for default global database
1840: . pre     - string to prepend to the name or `NULL`
1841: - name    - the option one is seeking

1843:   Output Parameter:
1844: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.

1846:   Level: beginner

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

1851: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1852:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1853:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1854:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1855:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1856:           `PetscOptionsFList()`, `PetscOptionsEList()`
1857: @*/
1858: PetscErrorCode PetscOptionsHasName(PetscOptions options, const char pre[], const char name[], PetscBool *set)
1859: {
1860:   const char *value;
1861:   PetscBool   flag;

1863:   PetscFunctionBegin;
1864:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
1865:   if (set) *set = flag;
1866:   PetscFunctionReturn(PETSC_SUCCESS);
1867: }

1869: /*@
1870:   PetscOptionsGetAll - Lists all the options the program was run with in a single string.

1872:   Not Collective

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

1877:   Output Parameter:
1878: . copts - pointer where string pointer is stored

1880:   Level: advanced

1882:   Notes:
1883:   The string should be freed with `PetscFree()`

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

1887: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsView()`, `PetscOptionsPush()`, `PetscOptionsPop()`,
1888:           `PetscOptionsLeftGet()`
1889: @*/
1890: PetscErrorCode PetscOptionsGetAll(PetscOptions options, char *copts[]) PeNS
1891: {
1892:   PetscInt i;
1893:   size_t   len = 1, lent = 0;
1894:   char    *coptions = NULL;

1896:   PetscFunctionBegin;
1897:   PetscAssertPointer(copts, 2);
1898:   options = options ? options : defaultoptions;
1899:   /* count the length of the required string */
1900:   for (i = 0; i < options->N; i++) {
1901:     PetscCall(PetscStrlen(options->names[i], &lent));
1902:     len += 2 + lent;
1903:     if (options->values[i]) {
1904:       PetscCall(PetscStrlen(options->values[i], &lent));
1905:       len += 1 + lent;
1906:     }
1907:   }
1908:   PetscCall(PetscMalloc1(len, &coptions));
1909:   coptions[0] = 0;
1910:   for (i = 0; i < options->N; i++) {
1911:     PetscCall(PetscStrlcat(coptions, "-", len));
1912:     PetscCall(PetscStrlcat(coptions, options->names[i], len));
1913:     PetscCall(PetscStrlcat(coptions, " ", len));
1914:     if (options->values[i]) {
1915:       PetscCall(PetscStrlcat(coptions, options->values[i], len));
1916:       PetscCall(PetscStrlcat(coptions, " ", len));
1917:     }
1918:   }
1919:   *copts = coptions;
1920:   PetscFunctionReturn(PETSC_SUCCESS);
1921: }

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

1926:   Not Collective

1928:   Input Parameters:
1929: + options - options database, use `NULL` for default global database
1930: - name    - string name of option

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

1935:   Level: advanced

1937:   Note:
1938:   The value returned may be different on each process and depends on which options have been processed
1939:   on the given process

1941: .seealso: `PetscOptionsView()`, `PetscOptionsLeft()`, `PetscOptionsAllUsed()`
1942: @*/
1943: PetscErrorCode PetscOptionsUsed(PetscOptions options, const char *name, PetscBool *used)
1944: {
1945:   PetscInt i;

1947:   PetscFunctionBegin;
1948:   PetscAssertPointer(name, 2);
1949:   PetscAssertPointer(used, 3);
1950:   options = options ? options : defaultoptions;
1951:   *used   = PETSC_FALSE;
1952:   for (i = 0; i < options->N; i++) {
1953:     PetscCall(PetscStrcasecmp(options->names[i], name, used));
1954:     if (*used) {
1955:       *used = options->used[i];
1956:       break;
1957:     }
1958:   }
1959:   PetscFunctionReturn(PETSC_SUCCESS);
1960: }

1962: /*@
1963:   PetscOptionsAllUsed - Returns a count of the number of options in the
1964:   database that have never been selected.

1966:   Not Collective

1968:   Input Parameter:
1969: . options - options database, use `NULL` for default global database

1971:   Output Parameter:
1972: . N - count of options not used

1974:   Level: advanced

1976:   Note:
1977:   The value returned may be different on each process and depends on which options have been processed
1978:   on the given process

1980: .seealso: `PetscOptionsView()`
1981: @*/
1982: PetscErrorCode PetscOptionsAllUsed(PetscOptions options, PetscInt *N)
1983: {
1984:   PetscInt i, n = 0;

1986:   PetscFunctionBegin;
1987:   PetscAssertPointer(N, 2);
1988:   options = options ? options : defaultoptions;
1989:   for (i = 0; i < options->N; i++) {
1990:     if (!options->used[i]) n++;
1991:   }
1992:   *N = n;
1993:   PetscFunctionReturn(PETSC_SUCCESS);
1994: }

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

1999:   Not Collective

2001:   Input Parameter:
2002: . options - options database; use `NULL` for default global database

2004:   Options Database Key:
2005: . -options_left - activates `PetscOptionsAllUsed()` within `PetscFinalize()`

2007:   Level: advanced

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

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

2017: .seealso: `PetscOptionsAllUsed()`
2018: @*/
2019: PetscErrorCode PetscOptionsLeft(PetscOptions options)
2020: {
2021:   PetscInt     cnt = 0;
2022:   PetscOptions toptions;

2024:   PetscFunctionBegin;
2025:   toptions = options ? options : defaultoptions;
2026:   for (PetscInt i = 0; i < toptions->N; i++) {
2027:     if (!toptions->used[i]) {
2028:       if (PetscCIOption(toptions->names[i])) continue;
2029:       if (toptions->values[i]) {
2030:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s value: %s source: %s\n", toptions->names[i], toptions->values[i], PetscOptionSources[toptions->source[i]]));
2031:       } else {
2032:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s (no value) source: %s\n", toptions->names[i], PetscOptionSources[toptions->source[i]]));
2033:       }
2034:     }
2035:   }
2036:   if (!options) {
2037:     toptions = defaultoptions;
2038:     while (toptions->previous) {
2039:       cnt++;
2040:       toptions = toptions->previous;
2041:     }
2042:     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));
2043:   }
2044:   PetscFunctionReturn(PETSC_SUCCESS);
2045: }

2047: /*@
2048:   PetscOptionsLeftGet - Returns all options that were set and never used.

2050:   Not Collective

2052:   Input Parameter:
2053: . options - options database, use `NULL` for default global database

2055:   Output Parameters:
2056: + N      - count of options not used
2057: . names  - names of options not used
2058: - values - values of options not used

2060:   Level: advanced

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

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

2068: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`
2069: @*/
2070: PetscErrorCode PetscOptionsLeftGet(PetscOptions options, PetscInt *N, char **names[], char **values[])
2071: {
2072:   PetscInt n;

2074:   PetscFunctionBegin;
2075:   if (N) PetscAssertPointer(N, 2);
2076:   if (names) PetscAssertPointer(names, 3);
2077:   if (values) PetscAssertPointer(values, 4);
2078:   options = options ? options : defaultoptions;

2080:   /* The number of unused PETSc options */
2081:   n = 0;
2082:   for (PetscInt i = 0; i < options->N; i++) {
2083:     if (PetscCIOption(options->names[i])) continue;
2084:     if (!options->used[i]) n++;
2085:   }
2086:   if (N) *N = n;
2087:   if (names) PetscCall(PetscMalloc1(n, names));
2088:   if (values) PetscCall(PetscMalloc1(n, values));

2090:   n = 0;
2091:   if (names || values) {
2092:     for (PetscInt i = 0; i < options->N; i++) {
2093:       if (!options->used[i]) {
2094:         if (PetscCIOption(options->names[i])) continue;
2095:         if (names) (*names)[n] = options->names[i];
2096:         if (values) (*values)[n] = options->values[i];
2097:         n++;
2098:       }
2099:     }
2100:   }
2101:   PetscFunctionReturn(PETSC_SUCCESS);
2102: }

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

2107:   Not Collective

2109:   Input Parameters:
2110: + options - options database, use `NULL` for default global database
2111: . N       - count of options not used
2112: . names   - names of options not used
2113: - values  - values of options not used

2115:   Level: advanced

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

2120: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`, `PetscOptionsLeftGet()`
2121: @*/
2122: PetscErrorCode PetscOptionsLeftRestore(PetscOptions options, PetscInt *N, char **names[], char **values[])
2123: {
2124:   PetscFunctionBegin;
2125:   (void)options;
2126:   if (N) PetscAssertPointer(N, 2);
2127:   if (names) PetscAssertPointer(names, 3);
2128:   if (values) PetscAssertPointer(values, 4);
2129:   if (N) *N = 0;
2130:   if (names) PetscCall(PetscFree(*names));
2131:   if (values) PetscCall(PetscFree(*values));
2132:   PetscFunctionReturn(PETSC_SUCCESS);
2133: }

2135: /*@
2136:   PetscOptionsMonitorDefault - Print all options set value events using the supplied `PetscViewer`.

2138:   Logically Collective

2140:   Input Parameters:
2141: + name   - option name string
2142: . value  - option value string
2143: . source - The source for the option
2144: - ctx    - a `PETSCVIEWERASCII` or `NULL`

2146:   Level: intermediate

2148:   Notes:
2149:   If ctx is `NULL`, `PetscPrintf()` is used.
2150:   The first MPI process in the `PetscViewer` viewer actually prints the values, other
2151:   processes may have different values set

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

2155: .seealso: `PetscOptionsMonitorSet()`
2156: @*/
2157: PetscErrorCode PetscOptionsMonitorDefault(const char name[], const char value[], PetscOptionSource source, PetscCtx ctx)
2158: {
2159:   PetscFunctionBegin;
2160:   if (PetscCIOption(name)) PetscFunctionReturn(PETSC_SUCCESS);

2162:   if (ctx) {
2163:     PetscViewer viewer = (PetscViewer)ctx;
2164:     if (!value) {
2165:       PetscCall(PetscViewerASCIIPrintf(viewer, "Removing option: %s\n", name));
2166:     } else if (!value[0]) {
2167:       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2168:     } else {
2169:       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2170:     }
2171:   } else {
2172:     if (!value) {
2173:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Removing option: %s\n", name));
2174:     } else if (!value[0]) {
2175:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2176:     } else {
2177:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2178:     }
2179:   }
2180:   PetscFunctionReturn(PETSC_SUCCESS);
2181: }

2183: /*@
2184:   PetscOptionsMonitorSet - Sets an ADDITIONAL function to be called at every method that
2185:   modified the PETSc options database.

2187:   Not Collective

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

2195:   Calling sequence of `monitor`:
2196: + name   - option name string
2197: . value  - option value string, a value of `NULL` indicates the option is being removed from the database. A value
2198:            of "" indicates the option is in the database but has no value.
2199: . source - option source
2200: - mctx   - optional monitoring context, as set by `PetscOptionsMonitorSet()`

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

2206:   Level: intermediate

2208:   Notes:
2209:   See `PetscInitialize()` for options related to option database monitoring.

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

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

2219: .seealso: `PetscOptionsMonitorDefault()`, `PetscInitialize()`, `PetscCtxDestroyFn`
2220: @*/
2221: PetscErrorCode PetscOptionsMonitorSet(PetscErrorCode (*monitor)(const char name[], const char value[], PetscOptionSource source, PetscCtx mctx), PetscCtx mctx, PetscCtxDestroyFn *monitordestroy)
2222: {
2223:   PetscOptions options = defaultoptions;

2225:   PetscFunctionBegin;
2226:   if (options->monitorCancel) PetscFunctionReturn(PETSC_SUCCESS);
2227:   PetscCheck(options->numbermonitors < MAXOPTIONSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptions monitors set");
2228:   options->monitor[options->numbermonitors]          = monitor;
2229:   options->monitordestroy[options->numbermonitors]   = monitordestroy;
2230:   options->monitorcontext[options->numbermonitors++] = mctx;
2231:   PetscFunctionReturn(PETSC_SUCCESS);
2232: }

2234: /*
2235:    Same as PetscOptionsStringToBool() but reports in isbool whether value is one of the recognized
2236:    logical values instead of raising an error when it is not.
2237: */
2238: static PetscErrorCode PetscOptionsStringToBool_Private(const char value[], PetscBool *a, PetscBool *isbool)
2239: {
2240:   PetscBool istrue, isfalse;
2241:   size_t    len;

2243:   PetscFunctionBegin;
2244:   *isbool = PETSC_TRUE;
2245:   /* PetscStrlen() returns 0 for NULL or "" */
2246:   PetscCall(PetscStrlen(value, &len));
2247:   if (!len) {
2248:     *a = PETSC_TRUE;
2249:     PetscFunctionReturn(PETSC_SUCCESS);
2250:   }
2251:   PetscCall(PetscStrcasecmp(value, "TRUE", &istrue));
2252:   if (istrue) {
2253:     *a = PETSC_TRUE;
2254:     PetscFunctionReturn(PETSC_SUCCESS);
2255:   }
2256:   PetscCall(PetscStrcasecmp(value, "YES", &istrue));
2257:   if (istrue) {
2258:     *a = PETSC_TRUE;
2259:     PetscFunctionReturn(PETSC_SUCCESS);
2260:   }
2261:   PetscCall(PetscStrcasecmp(value, "1", &istrue));
2262:   if (istrue) {
2263:     *a = PETSC_TRUE;
2264:     PetscFunctionReturn(PETSC_SUCCESS);
2265:   }
2266:   PetscCall(PetscStrcasecmp(value, "on", &istrue));
2267:   if (istrue) {
2268:     *a = PETSC_TRUE;
2269:     PetscFunctionReturn(PETSC_SUCCESS);
2270:   }
2271:   PetscCall(PetscStrcasecmp(value, "FALSE", &isfalse));
2272:   if (isfalse) {
2273:     *a = PETSC_FALSE;
2274:     PetscFunctionReturn(PETSC_SUCCESS);
2275:   }
2276:   PetscCall(PetscStrcasecmp(value, "NO", &isfalse));
2277:   if (isfalse) {
2278:     *a = PETSC_FALSE;
2279:     PetscFunctionReturn(PETSC_SUCCESS);
2280:   }
2281:   PetscCall(PetscStrcasecmp(value, "0", &isfalse));
2282:   if (isfalse) {
2283:     *a = PETSC_FALSE;
2284:     PetscFunctionReturn(PETSC_SUCCESS);
2285:   }
2286:   PetscCall(PetscStrcasecmp(value, "off", &isfalse));
2287:   if (isfalse) {
2288:     *a = PETSC_FALSE;
2289:     PetscFunctionReturn(PETSC_SUCCESS);
2290:   }
2291:   *a      = PETSC_FALSE;
2292:   *isbool = PETSC_FALSE;
2293:   PetscFunctionReturn(PETSC_SUCCESS);
2294: }

2296: /*@
2297:   PetscOptionsStringToBool - Converts a string to a `PetscBool`

2299:   Not Collective

2301:   Input Parameter:
2302: . value - the string to convert; may be `NULL` or `""`

2304:   Output Parameter:
2305: . a - the resulting `PetscBool`

2307:   Level: developer

2309:   Note:
2310:   Recognizes (case-insensitive) `TRUE`, `YES`, `1`, `on` as `PETSC_TRUE` and `FALSE`, `NO`, `0`, `off` as `PETSC_FALSE`.
2311:   An empty or `NULL` string is treated as `PETSC_TRUE`. Any other input generates an error.

2313: .seealso: `PetscOptionsStringToInt()`, `PetscOptionsStringToReal()`, `PetscOptionsStringToScalar()`, `PetscOptionsGetBool()`
2314: @*/
2315: PetscErrorCode PetscOptionsStringToBool(const char value[], PetscBool *a)
2316: {
2317:   PetscBool isbool;

2319:   PetscFunctionBegin;
2320:   PetscCall(PetscOptionsStringToBool_Private(value, a, &isbool));
2321:   PetscCheck(isbool, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown logical value: %s", value);
2322:   PetscFunctionReturn(PETSC_SUCCESS);
2323: }

2325: /*@
2326:   PetscOptionsStringToInt - Converts a string to an integer value. Handles special cases such as "default" and "decide"

2328:   Not Collective

2330:   Input Parameter:
2331: . name - the string to convert

2333:   Output Parameter:
2334: . a - the resulting `PetscInt` value

2336:   Level: developer

2338:   Note:
2339:   Recognizes the special strings `PETSC_DEFAULT`, `DEFAULT`, `PETSC_DECIDE`, `DECIDE`, `PETSC_DETERMINE`, `DETERMINE`, `PETSC_UNLIMITED`,
2340:   `UNLIMITED`, and `mouse` (which returns `-1`). Otherwise the value is parsed as a base-10 integer.

2342: .seealso: `PetscOptionsStringToReal()`, `PetscOptionsStringToScalar()`, `PetscOptionsStringToBool()`, `PetscOptionsGetInt()`
2343: @*/
2344: PetscErrorCode PetscOptionsStringToInt(const char name[], PetscInt *a)
2345: {
2346:   size_t    len;
2347:   PetscBool decide, tdefault, mouse, unlimited;

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

2353:   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &tdefault));
2354:   if (!tdefault) PetscCall(PetscStrcasecmp(name, "DEFAULT", &tdefault));
2355:   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &decide));
2356:   if (!decide) PetscCall(PetscStrcasecmp(name, "DECIDE", &decide));
2357:   if (!decide) PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &decide));
2358:   if (!decide) PetscCall(PetscStrcasecmp(name, "DETERMINE", &decide));
2359:   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &unlimited));
2360:   if (!unlimited) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &unlimited));
2361:   PetscCall(PetscStrcasecmp(name, "mouse", &mouse));

2363:   if (tdefault) *a = PETSC_DEFAULT;
2364:   else if (decide) *a = PETSC_DECIDE;
2365:   else if (unlimited) *a = PETSC_UNLIMITED;
2366:   else if (mouse) *a = -1;
2367:   else {
2368:     char *endptr;
2369:     long  strtolval;

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

2374: #if PetscDefined(USE_64BIT_INDICES) && PetscDefined(HAVE_ATOLL)
2375:     (void)strtolval;
2376:     *a = atoll(name);
2377: #elif PetscDefined(USE_64BIT_INDICES) && PetscDefined(HAVE___INT64)
2378:     (void)strtolval;
2379:     *a = _atoi64(name);
2380: #else
2381:     *a = (PetscInt)strtolval;
2382: #endif
2383:   }
2384:   PetscFunctionReturn(PETSC_SUCCESS);
2385: }

2387: #if PetscDefined(USE_REAL___FLOAT128)
2388:   #include <quadmath.h>
2389: #endif

2391: static PetscErrorCode PetscStrtod(const char name[], PetscReal *a, char **endptr)
2392: {
2393:   PetscFunctionBegin;
2394: #if PetscDefined(USE_REAL___FLOAT128)
2395:   *a = strtoflt128(name, endptr);
2396: #else
2397:   *a = (PetscReal)strtod(name, endptr);
2398: #endif
2399:   PetscFunctionReturn(PETSC_SUCCESS);
2400: }

2402: static PetscErrorCode PetscStrtoz(const char name[], PetscScalar *a, char **endptr, PetscBool *isImaginary)
2403: {
2404:   PetscBool hasi = PETSC_FALSE;
2405:   char     *ptr;
2406:   PetscReal strtoval;

2408:   PetscFunctionBegin;
2409:   PetscCall(PetscStrtod(name, &strtoval, &ptr));
2410:   if (ptr == name) {
2411:     strtoval = 1.;
2412:     hasi     = PETSC_TRUE;
2413:     if (name[0] == 'i') {
2414:       ptr++;
2415:     } else if (name[0] == '+' && name[1] == 'i') {
2416:       ptr += 2;
2417:     } else if (name[0] == '-' && name[1] == 'i') {
2418:       strtoval = -1.;
2419:       ptr += 2;
2420:     }
2421:   } else if (*ptr == 'i') {
2422:     hasi = PETSC_TRUE;
2423:     ptr++;
2424:   }
2425:   *endptr      = ptr;
2426:   *isImaginary = hasi;
2427:   if (hasi) {
2428: #if !PetscDefined(USE_COMPLEX)
2429:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s contains imaginary but complex not supported ", name);
2430: #else
2431:     *a = PetscCMPLX(0., strtoval);
2432: #endif
2433:   } else {
2434:     *a = strtoval;
2435:   }
2436:   PetscFunctionReturn(PETSC_SUCCESS);
2437: }

2439: /*@
2440:   PetscOptionsStringToReal - Converts a string to a `PetscReal` value. Handles special cases like `default` and `decide`

2442:   Not Collective

2444:   Input Parameter:
2445: . name - the string to convert

2447:   Output Parameter:
2448: . a - the resulting `PetscReal` value

2450:   Level: developer

2452:   Note:
2453:   Recognizes the special strings `PETSC_DEFAULT`, `DEFAULT`, `PETSC_DECIDE`, `DECIDE`, `PETSC_DETERMINE`, `DETERMINE`,
2454:   `PETSC_UNLIMITED`, and `UNLIMITED`. Otherwise the value is parsed as a floating-point number.

2456: .seealso: `PetscOptionsStringToInt()`, `PetscOptionsStringToScalar()`, `PetscOptionsStringToBool()`, `PetscOptionsGetReal()`
2457: @*/
2458: PetscErrorCode PetscOptionsStringToReal(const char name[], PetscReal *a)
2459: {
2460:   size_t    len;
2461:   PetscBool match;
2462:   char     *endptr;

2464:   PetscFunctionBegin;
2465:   PetscCall(PetscStrlen(name, &len));
2466:   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "String of length zero has no numerical value");

2468:   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &match));
2469:   if (!match) PetscCall(PetscStrcasecmp(name, "DEFAULT", &match));
2470:   if (match) {
2471:     *a = PETSC_DEFAULT;
2472:     PetscFunctionReturn(PETSC_SUCCESS);
2473:   }

2475:   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &match));
2476:   if (!match) PetscCall(PetscStrcasecmp(name, "DECIDE", &match));
2477:   if (match) {
2478:     *a = PETSC_DECIDE;
2479:     PetscFunctionReturn(PETSC_SUCCESS);
2480:   }

2482:   PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &match));
2483:   if (!match) PetscCall(PetscStrcasecmp(name, "DETERMINE", &match));
2484:   if (match) {
2485:     *a = PETSC_DETERMINE;
2486:     PetscFunctionReturn(PETSC_SUCCESS);
2487:   }

2489:   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &match));
2490:   if (!match) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &match));
2491:   if (match) {
2492:     *a = PETSC_UNLIMITED;
2493:     PetscFunctionReturn(PETSC_SUCCESS);
2494:   }

2496:   PetscCall(PetscStrtod(name, a, &endptr));
2497:   PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value", name);
2498:   PetscFunctionReturn(PETSC_SUCCESS);
2499: }

2501: /*@
2502:   PetscOptionsStringToScalar - Converts a string to a `PetscScalar` value; when PETSc is built with complex scalars, parses an optional imaginary part

2504:   Not Collective

2506:   Input Parameter:
2507: . name - the string to convert

2509:   Output Parameter:
2510: . a - the resulting `PetscScalar` value

2512:   Level: developer

2514:   Note:
2515:   Accepts forms such as `1.5`, `-2`, `3+4i`, `i`, or `-i`. Using an imaginary component when PETSc is built without complex scalars is an error.

2517: .seealso: `PetscOptionsStringToInt()`, `PetscOptionsStringToReal()`, `PetscOptionsStringToBool()`, `PetscOptionsGetScalar()`
2518: @*/
2519: PetscErrorCode PetscOptionsStringToScalar(const char name[], PetscScalar *a)
2520: {
2521:   PetscBool   imag1;
2522:   size_t      len;
2523:   PetscScalar val = 0.;
2524:   char       *ptr = NULL;

2526:   PetscFunctionBegin;
2527:   PetscCall(PetscStrlen(name, &len));
2528:   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2529:   PetscCall(PetscStrtoz(name, &val, &ptr, &imag1));
2530: #if PetscDefined(USE_COMPLEX)
2531:   if ((size_t)(ptr - name) < len) {
2532:     PetscBool   imag2;
2533:     PetscScalar val2;

2535:     PetscCall(PetscStrtoz(ptr, &val2, &ptr, &imag2));
2536:     if (imag1) PetscCheck(imag2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s: must specify imaginary component second", name);
2537:     val = PetscCMPLX(PetscRealPart(val), PetscImaginaryPart(val2));
2538:   }
2539: #endif
2540:   PetscCheck((size_t)(ptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value ", name);
2541:   *a = val;
2542:   PetscFunctionReturn(PETSC_SUCCESS);
2543: }

2545: /*@
2546:   PetscOptionsGetBool - Gets the Logical (true or false) value for a particular
2547:   option in the database.

2549:   Not Collective

2551:   Input Parameters:
2552: + options - options database, use `NULL` for default global database
2553: . pre     - the string to prepend to the name or `NULL`
2554: - name    - the option one is seeking

2556:   Output Parameters:
2557: + ivalue - the logical value to return
2558: - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`

2560:   Level: beginner

2562:   Notes:
2563:   The option values TRUE, YES, ON (case-insensitive) and 1 all translate to `PETSC_TRUE`

2565:   The option values FALSE, NO, OFF (case-insensitive) and 0 all translate to `PETSC_FALSE`

2567:   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`
2568:   is equivalent to `-requested_bool true`

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

2573: .seealso: `PetscOptionsGetBool3()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2574:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2575:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2576:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2577:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2578:           `PetscOptionsFList()`, `PetscOptionsEList()`
2579: @*/
2580: PetscErrorCode PetscOptionsGetBool(PetscOptions options, const char pre[], const char name[], PetscBool *ivalue, PetscBool *set)
2581: {
2582:   const char *value;
2583:   PetscBool   flag;

2585:   PetscFunctionBegin;
2586:   PetscAssertPointer(name, 3);
2587:   if (ivalue) PetscAssertPointer(ivalue, 4);
2588:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2589:   if (flag) {
2590:     if (set) *set = PETSC_TRUE;
2591:     PetscCall(PetscOptionsStringToBool(value, &flag));
2592:     if (ivalue) *ivalue = flag;
2593:   } else {
2594:     if (set) *set = PETSC_FALSE;
2595:   }
2596:   PetscFunctionReturn(PETSC_SUCCESS);
2597: }

2599: /*@
2600:   PetscOptionsGetBool3 - Gets the ternary logical (true, false or unknown) value for a particular
2601:   option in the database.

2603:   Not Collective

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

2610:   Output Parameters:
2611: + ivalue - the ternary logical value to return
2612: - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`

2614:   Level: beginner

2616:   Notes:
2617:   The option values TRUE, YES, ON (case-insensitive) and 1 all translate to `PETSC_BOOL3_TRUE`

2619:   The option values FALSE, NO, OFF (case-insensitive) and 0 all translate to `PETSC_BOOL3_FALSE`

2621:   The option values UNKNOWN and AUTO (case-insensitive) all translate to `PETSC_BOOL3_UNKNOWN`

2623:   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`
2624:   is equivalent to `-requested_bool3 true`

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

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

2641:   PetscFunctionBegin;
2642:   PetscAssertPointer(name, 3);
2643:   if (ivalue) PetscAssertPointer(ivalue, 4);
2644:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2645:   if (flag) { // found the option
2646:     PetscBool isAUTO = PETSC_FALSE, isUNKNOWN = PETSC_FALSE;

2648:     if (set) *set = PETSC_TRUE;
2649:     PetscCall(PetscStrcasecmp("AUTO", value, &isAUTO));                    // auto or AUTO
2650:     if (!isAUTO) PetscCall(PetscStrcasecmp("UNKNOWN", value, &isUNKNOWN)); // unknown or UNKNOWN
2651:     if (isAUTO || isUNKNOWN) {
2652:       if (ivalue) *ivalue = PETSC_BOOL3_UNKNOWN;
2653:     } else { // handle boolean values (if no value is given, it returns true)
2654:       PetscCall(PetscOptionsStringToBool(value, &flag));
2655:       if (ivalue) *ivalue = PetscBoolToBool3(flag);
2656:     }
2657:   } else {
2658:     if (set) *set = PETSC_FALSE;
2659:   }
2660:   PetscFunctionReturn(PETSC_SUCCESS);
2661: }

2663: /*@
2664:   PetscOptionsGetEList - Puts a list of option values that a single one may be selected from

2666:   Not Collective

2668:   Input Parameters:
2669: + options - options database, use `NULL` for default global database
2670: . pre     - the string to prepend to the name or `NULL`
2671: . opt     - option name
2672: . list    - the possible choices (one of these must be selected, anything else is invalid)
2673: - ntext   - number of choices

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

2679:   Level: intermediate

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

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

2687: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2688:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2689:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2690:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2691:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2692:           `PetscOptionsFList()`, `PetscOptionsEList()`
2693: @*/
2694: PetscErrorCode PetscOptionsGetEList(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscInt ntext, PetscInt *value, PetscBool *set)
2695: {
2696:   size_t    alen, len = 0, tlen = 0;
2697:   char     *svalue;
2698:   PetscBool aset, flg = PETSC_FALSE;

2700:   PetscFunctionBegin;
2701:   PetscAssertPointer(opt, 3);
2702:   for (PetscInt i = 0; i < ntext; i++) {
2703:     PetscCall(PetscStrlen(list[i], &alen));
2704:     if (alen > len) len = alen;
2705:     tlen += len + 1;
2706:   }
2707:   len += 5; /* a little extra space for user mistypes */
2708:   PetscCall(PetscMalloc1(len, &svalue));
2709:   PetscCall(PetscOptionsGetString(options, pre, opt, svalue, len, &aset));
2710:   if (aset) {
2711:     PetscCall(PetscEListFind(ntext, list, svalue, value, &flg));
2712:     if (!flg) {
2713:       char *avail;

2715:       PetscCall(PetscMalloc1(tlen, &avail));
2716:       avail[0] = '\0';
2717:       for (PetscInt i = 0; i < ntext; i++) {
2718:         PetscCall(PetscStrlcat(avail, list[i], tlen));
2719:         PetscCall(PetscStrlcat(avail, " ", tlen));
2720:       }
2721:       PetscCall(PetscStrtolower(avail));
2722:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown option \"%s\" for -%s%s. Available options: %s", svalue, pre ? pre : "", opt + 1, avail);
2723:     }
2724:     if (set) *set = PETSC_TRUE;
2725:   } else if (set) *set = PETSC_FALSE;
2726:   PetscCall(PetscFree(svalue));
2727:   PetscFunctionReturn(PETSC_SUCCESS);
2728: }

2730: /*@
2731:   PetscOptionsGetEnum - Gets the enum value for a particular option in the database.

2733:   Not Collective

2735:   Input Parameters:
2736: + options - options database, use `NULL` for default global database
2737: . pre     - option prefix or `NULL`
2738: . opt     - option name
2739: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

2741:   Output Parameters:
2742: + value - the value to return
2743: - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`

2745:   Level: beginner

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

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

2753: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2754:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2755:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2756:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2757:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2758:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2759:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2760: @*/
2761: PetscErrorCode PetscOptionsGetEnum(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscEnum *value, PetscBool *set) PeNSS
2762: {
2763:   PetscInt  ntext = 0, tval;
2764:   PetscBool fset;

2766:   PetscFunctionBegin;
2767:   PetscAssertPointer(opt, 3);
2768:   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");
2769:   PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
2770:   ntext -= 3;
2771:   PetscCall(PetscOptionsGetEList(options, pre, opt, list, ntext, &tval, &fset));
2772:   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
2773:   if (fset) *value = (PetscEnum)tval;
2774:   if (set) *set = fset;
2775:   PetscFunctionReturn(PETSC_SUCCESS);
2776: }

2778: /*@
2779:   PetscOptionsGetInt - Gets the integer value for a particular option in the database.

2781:   Not Collective

2783:   Input Parameters:
2784: + options - options database, use `NULL` for default global database
2785: . pre     - the string to prepend to the name or `NULL`
2786: - name    - the option one is seeking

2788:   Output Parameters:
2789: + ivalue - the integer value to return
2790: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2792:   Level: beginner

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

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

2800:   Accepts the deprecated value `default`.

2802: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2803:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2804:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2805:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2806:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2807:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2808:           `PetscOptionsFList()`, `PetscOptionsEList()`
2809: @*/
2810: PetscErrorCode PetscOptionsGetInt(PetscOptions options, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
2811: {
2812:   const char *value;
2813:   PetscBool   flag;

2815:   PetscFunctionBegin;
2816:   PetscAssertPointer(name, 3);
2817:   PetscAssertPointer(ivalue, 4);
2818:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2819:   if (flag) {
2820:     if (!value) {
2821:       if (set) *set = PETSC_FALSE;
2822:     } else {
2823:       if (set) *set = PETSC_TRUE;
2824:       PetscCall(PetscOptionsStringToInt(value, ivalue));
2825:     }
2826:   } else {
2827:     if (set) *set = PETSC_FALSE;
2828:   }
2829:   PetscFunctionReturn(PETSC_SUCCESS);
2830: }

2832: /*@
2833:   PetscOptionsGetMPIInt - Gets the MPI integer value for a particular option in the database.

2835:   Not Collective

2837:   Input Parameters:
2838: + options - options database, use `NULL` for default global database
2839: . pre     - the string to prepend to the name or `NULL`
2840: - name    - the option one is seeking

2842:   Output Parameters:
2843: + ivalue - the MPI integer value to return
2844: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2846:   Level: beginner

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

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

2854:   Accepts the deprecated value `default`.

2856: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2857:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2858:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2859:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2860:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2861:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2862:           `PetscOptionsFList()`, `PetscOptionsEList()`
2863: @*/
2864: PetscErrorCode PetscOptionsGetMPIInt(PetscOptions options, const char pre[], const char name[], PetscMPIInt *ivalue, PetscBool *set)
2865: {
2866:   PetscInt  value;
2867:   PetscBool flag;

2869:   PetscFunctionBegin;
2870:   PetscCall(PetscOptionsGetInt(options, pre, name, &value, &flag));
2871:   if (flag) PetscCall(PetscMPIIntCast(value, ivalue));
2872:   if (set) *set = flag;
2873:   PetscFunctionReturn(PETSC_SUCCESS);
2874: }

2876: /*@
2877:   PetscOptionsGetReal - Gets the double precision value for a particular
2878:   option in the database.

2880:   Not Collective

2882:   Input Parameters:
2883: + options - options database, use `NULL` for default global database
2884: . pre     - string to prepend to each name or `NULL`
2885: - name    - the option one is seeking

2887:   Output Parameters:
2888: + dvalue - the double value to return
2889: - set    - `PETSC_TRUE` if found, `PETSC_FALSE` if not found

2891:   Level: beginner

2893:   Notes:
2894:   Accepts the special values `determine`, `decide` and `unlimited`.

2896:   Accepts the deprecated value `default`

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

2901: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2902:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2903:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2904:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2905:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2906:           `PetscOptionsFList()`, `PetscOptionsEList()`
2907: @*/
2908: PetscErrorCode PetscOptionsGetReal(PetscOptions options, const char pre[], const char name[], PetscReal *dvalue, PetscBool *set)
2909: {
2910:   const char *value;
2911:   PetscBool   flag;

2913:   PetscFunctionBegin;
2914:   PetscAssertPointer(name, 3);
2915:   PetscAssertPointer(dvalue, 4);
2916:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2917:   if (flag) {
2918:     if (!value) {
2919:       if (set) *set = PETSC_FALSE;
2920:     } else {
2921:       if (set) *set = PETSC_TRUE;
2922:       PetscCall(PetscOptionsStringToReal(value, dvalue));
2923:     }
2924:   } else {
2925:     if (set) *set = PETSC_FALSE;
2926:   }
2927:   PetscFunctionReturn(PETSC_SUCCESS);
2928: }

2930: /*@
2931:   PetscOptionsGetScalar - Gets the scalar value for a particular
2932:   option in the database.

2934:   Not Collective

2936:   Input Parameters:
2937: + options - options database, use `NULL` for default global database
2938: . pre     - string to prepend to each name or `NULL`
2939: - name    - the option one is seeking

2941:   Output Parameters:
2942: + dvalue - the scalar value to return
2943: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2945:   Level: beginner

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

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

2954: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2955:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2956:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2957:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2958:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2959:           `PetscOptionsFList()`, `PetscOptionsEList()`
2960: @*/
2961: PetscErrorCode PetscOptionsGetScalar(PetscOptions options, const char pre[], const char name[], PetscScalar *dvalue, PetscBool *set)
2962: {
2963:   const char *value;
2964:   PetscBool   flag;

2966:   PetscFunctionBegin;
2967:   PetscAssertPointer(name, 3);
2968:   PetscAssertPointer(dvalue, 4);
2969:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2970:   if (flag) {
2971:     if (!value) {
2972:       if (set) *set = PETSC_FALSE;
2973:     } else {
2974: #if !PetscDefined(USE_COMPLEX)
2975:       PetscCall(PetscOptionsStringToReal(value, dvalue));
2976: #else
2977:       PetscCall(PetscOptionsStringToScalar(value, dvalue));
2978: #endif
2979:       if (set) *set = PETSC_TRUE;
2980:     }
2981:   } else { /* flag */
2982:     if (set) *set = PETSC_FALSE;
2983:   }
2984:   PetscFunctionReturn(PETSC_SUCCESS);
2985: }

2987: /*@
2988:   PetscOptionsGetString - Gets the string value for a particular option in
2989:   the database.

2991:   Not Collective

2993:   Input Parameters:
2994: + options - options database, use `NULL` for default global database
2995: . pre     - string to prepend to name or `NULL`
2996: . name    - the option one is seeking
2997: - len     - maximum length of the string including null termination

2999:   Output Parameters:
3000: + string - location to copy string
3001: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3003:   Level: beginner

3005:   Note:
3006:   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`

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

3011:   Fortran Notes:
3012:   The Fortran interface is slightly different from the C/C++
3013:   interface.  Sample usage in Fortran follows
3014: .vb
3015:       character *20    string
3016:       PetscErrorCode   ierr
3017:       PetscBool        set
3018:       call PetscOptionsGetString(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-s',string,set,ierr)
3019: .ve

3021: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
3022:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3023:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3024:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3025:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3026:           `PetscOptionsFList()`, `PetscOptionsEList()`
3027: @*/
3028: PetscErrorCode PetscOptionsGetString(PetscOptions options, const char pre[], const char name[], char string[], size_t len, PetscBool *set) PeNS
3029: {
3030:   const char *value;
3031:   PetscBool   flag;

3033:   PetscFunctionBegin;
3034:   PetscAssertPointer(name, 3);
3035:   PetscAssertPointer(string, 4);
3036:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
3037:   if (!flag) {
3038:     if (set) *set = PETSC_FALSE;
3039:   } else {
3040:     if (set) *set = PETSC_TRUE;
3041:     if (value) PetscCall(PetscStrncpy(string, value, len));
3042:     else PetscCall(PetscArrayzero(string, len));
3043:   }
3044:   PetscFunctionReturn(PETSC_SUCCESS);
3045: }

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

3051:   Not Collective

3053:   Input Parameters:
3054: + options - options database, use `NULL` for default global database
3055: . pre     - string to prepend to each name or `NULL`
3056: - name    - the option one is seeking

3058:   Output Parameters:
3059: + dvalue - the Boolean values to return
3060: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3061: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3063:   Level: beginner

3065:   Notes:
3066:   The option values TRUE, YES, ON (case-insensitive) and 1 all translate to `PETSC_TRUE`

3068:   The option values FALSE, NO, OFF (case-insensitive) and 0 all translate to `PETSC_FALSE`

3070: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3071:           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3072:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3073:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3074:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3075:           `PetscOptionsFList()`, `PetscOptionsEList()`
3076: @*/
3077: PetscErrorCode PetscOptionsGetBoolArray(PetscOptions options, const char pre[], const char name[], PetscBool dvalue[], PetscInt *nmax, PetscBool *set)
3078: {
3079:   const char *svalue;
3080:   const char *value;
3081:   PetscInt    n = 0;
3082:   PetscBool   flag;
3083:   PetscToken  token;

3085:   PetscFunctionBegin;
3086:   PetscAssertPointer(name, 3);
3087:   PetscAssertPointer(nmax, 5);
3088:   if (*nmax) PetscAssertPointer(dvalue, 4);

3090:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3091:   if (!flag || !svalue) {
3092:     if (set) *set = PETSC_FALSE;
3093:     *nmax = 0;
3094:     PetscFunctionReturn(PETSC_SUCCESS);
3095:   }
3096:   if (set) *set = PETSC_TRUE;
3097:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3098:   PetscCall(PetscTokenFind(token, &value));
3099:   while (value && n < *nmax) {
3100:     PetscCall(PetscOptionsStringToBool(value, dvalue));
3101:     PetscCall(PetscTokenFind(token, &value));
3102:     dvalue++;
3103:     n++;
3104:   }
3105:   PetscCall(PetscTokenDestroy(&token));
3106:   *nmax = n;
3107:   PetscFunctionReturn(PETSC_SUCCESS);
3108: }

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

3113:   Not Collective

3115:   Input Parameters:
3116: + options - options database, use `NULL` for default global database
3117: . pre     - option prefix or `NULL`
3118: . name    - option name
3119: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

3121:   Output Parameters:
3122: + ivalue - the  enum values to return
3123: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3124: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3126:   Level: beginner

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

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

3133: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
3134:           `PetscOptionsGetEnum()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3135:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsName()`,
3136:           `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, `PetscOptionsStringArray()`, `PetscOptionsRealArray()`,
3137:           `PetscOptionsScalar()`, `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3138:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
3139: @*/
3140: PetscErrorCode PetscOptionsGetEnumArray(PetscOptions options, const char pre[], const char name[], const char *const list[], PetscEnum ivalue[], PetscInt *nmax, PetscBool *set)
3141: {
3142:   const char *svalue;
3143:   const char *value;
3144:   PetscInt    n = 0;
3145:   PetscEnum   evalue;
3146:   PetscBool   flag;
3147:   PetscToken  token;

3149:   PetscFunctionBegin;
3150:   PetscAssertPointer(name, 3);
3151:   PetscAssertPointer(list, 4);
3152:   PetscAssertPointer(nmax, 6);
3153:   if (*nmax) PetscAssertPointer(ivalue, 5);

3155:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3156:   if (!flag || !svalue) {
3157:     if (set) *set = PETSC_FALSE;
3158:     *nmax = 0;
3159:     PetscFunctionReturn(PETSC_SUCCESS);
3160:   }
3161:   if (set) *set = PETSC_TRUE;
3162:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3163:   PetscCall(PetscTokenFind(token, &value));
3164:   while (value && n < *nmax) {
3165:     PetscCall(PetscEnumFind(list, value, &evalue, &flag));
3166:     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown enum value '%s' for -%s%s", svalue, pre ? pre : "", name + 1);
3167:     ivalue[n++] = evalue;
3168:     PetscCall(PetscTokenFind(token, &value));
3169:   }
3170:   PetscCall(PetscTokenDestroy(&token));
3171:   *nmax = n;
3172:   PetscFunctionReturn(PETSC_SUCCESS);
3173: }

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

3178:   Not Collective

3180:   Input Parameters:
3181: + options - options database, use `NULL` for default global database
3182: . pre     - string to prepend to each name or `NULL`
3183: - name    - the option one is seeking

3185:   Output Parameters:
3186: + ivalue - the integer values to return
3187: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3188: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3190:   Level: beginner

3192:   Notes:
3193:   The array can be passed as
3194: +  a comma separated list -                                 0,1,2,3,4,5,6,7
3195: .  a range (start\-end+1) -                                 0-8
3196: .  a range with given increment (start\-end+1:inc) -        0-7:2
3197: -  a combination of values and ranges separated by commas - 0,1-8,8-15:2

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

3201: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3202:           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3203:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3204:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3205:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3206:           `PetscOptionsFList()`, `PetscOptionsEList()`
3207: @*/
3208: PetscErrorCode PetscOptionsGetIntArray(PetscOptions options, const char pre[], const char name[], PetscInt ivalue[], PetscInt *nmax, PetscBool *set)
3209: {
3210:   const char *svalue;
3211:   const char *value;
3212:   PetscInt    n = 0, i, j, start, end, inc, nvalues;
3213:   size_t      len;
3214:   PetscBool   flag, foundrange;
3215:   PetscToken  token;

3217:   PetscFunctionBegin;
3218:   PetscAssertPointer(name, 3);
3219:   PetscAssertPointer(nmax, 5);
3220:   if (*nmax) PetscAssertPointer(ivalue, 4);

3222:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3223:   if (!flag || !svalue) {
3224:     if (set) *set = PETSC_FALSE;
3225:     *nmax = 0;
3226:     PetscFunctionReturn(PETSC_SUCCESS);
3227:   }
3228:   if (set) *set = PETSC_TRUE;
3229:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3230:   PetscCall(PetscTokenFind(token, &value));
3231:   while (value && n < *nmax) {
3232:     char *iivalue;

3234:     /* look for form  d-D where d and D are integers */
3235:     PetscCall(PetscStrallocpy(value, &iivalue));
3236:     foundrange = PETSC_FALSE;
3237:     PetscCall(PetscStrlen(iivalue, &len));
3238:     if (iivalue[0] == '-') i = 2;
3239:     else i = 1;
3240:     for (; i < (int)len; i++) {
3241:       if (iivalue[i] == '-') {
3242:         PetscCheck(i != (int)len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, iivalue);
3243:         iivalue[i] = 0;

3245:         PetscCall(PetscOptionsStringToInt(iivalue, &start));
3246:         inc = 1;
3247:         j   = i + 1;
3248:         for (; j < (int)len; j++) {
3249:           if (iivalue[j] == ':') {
3250:             iivalue[j] = 0;

3252:             PetscCall(PetscOptionsStringToInt(iivalue + j + 1, &inc));
3253:             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);
3254:             break;
3255:           }
3256:         }
3257:         PetscCall(PetscOptionsStringToInt(iivalue + i + 1, &end));
3258:         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);
3259:         nvalues = (end - start) / inc + (end - start) % inc;
3260:         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);
3261:         for (; start < end; start += inc) {
3262:           *ivalue = start;
3263:           ivalue++;
3264:           n++;
3265:         }
3266:         foundrange = PETSC_TRUE;
3267:         break;
3268:       }
3269:     }
3270:     if (!foundrange) {
3271:       PetscCall(PetscOptionsStringToInt(value, ivalue));
3272:       ivalue++;
3273:       n++;
3274:     }
3275:     PetscCall(PetscFree(iivalue));
3276:     PetscCall(PetscTokenFind(token, &value));
3277:   }
3278:   PetscCall(PetscTokenDestroy(&token));
3279:   *nmax = n;
3280:   PetscFunctionReturn(PETSC_SUCCESS);
3281: }

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

3287:   Not Collective

3289:   Input Parameters:
3290: + options - options database, use `NULL` for default global database
3291: . pre     - string to prepend to each name or `NULL`
3292: - name    - the option one is seeking

3294:   Output Parameters:
3295: + dvalue - the double values to return
3296: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3297: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3299:   Level: beginner

3301: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3302:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3303:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3304:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3305:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3306:           `PetscOptionsFList()`, `PetscOptionsEList()`
3307: @*/
3308: PetscErrorCode PetscOptionsGetRealArray(PetscOptions options, const char pre[], const char name[], PetscReal dvalue[], PetscInt *nmax, PetscBool *set)
3309: {
3310:   const char *svalue;
3311:   const char *value;
3312:   PetscInt    n = 0;
3313:   PetscBool   flag;
3314:   PetscToken  token;

3316:   PetscFunctionBegin;
3317:   PetscAssertPointer(name, 3);
3318:   PetscAssertPointer(nmax, 5);
3319:   if (*nmax) PetscAssertPointer(dvalue, 4);

3321:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3322:   if (!flag || !svalue) {
3323:     if (set) *set = PETSC_FALSE;
3324:     *nmax = 0;
3325:     PetscFunctionReturn(PETSC_SUCCESS);
3326:   }
3327:   if (set) *set = PETSC_TRUE;
3328:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3329:   PetscCall(PetscTokenFind(token, &value));
3330:   while (value && n < *nmax) {
3331:     PetscCall(PetscOptionsStringToReal(value, dvalue++));
3332:     PetscCall(PetscTokenFind(token, &value));
3333:     n++;
3334:   }
3335:   PetscCall(PetscTokenDestroy(&token));
3336:   *nmax = n;
3337:   PetscFunctionReturn(PETSC_SUCCESS);
3338: }

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

3344:   Not Collective

3346:   Input Parameters:
3347: + options - options database, use `NULL` for default global database
3348: . pre     - string to prepend to each name or `NULL`
3349: - name    - the option one is seeking

3351:   Output Parameters:
3352: + dvalue - the scalar values to return
3353: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3354: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3356:   Level: beginner

3358: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3359:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3360:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3361:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3362:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3363:           `PetscOptionsFList()`, `PetscOptionsEList()`
3364: @*/
3365: PetscErrorCode PetscOptionsGetScalarArray(PetscOptions options, const char pre[], const char name[], PetscScalar dvalue[], PetscInt *nmax, PetscBool *set)
3366: {
3367:   const char *svalue;
3368:   const char *value;
3369:   PetscInt    n = 0;
3370:   PetscBool   flag;
3371:   PetscToken  token;

3373:   PetscFunctionBegin;
3374:   PetscAssertPointer(name, 3);
3375:   PetscAssertPointer(nmax, 5);
3376:   if (*nmax) PetscAssertPointer(dvalue, 4);

3378:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3379:   if (!flag || !svalue) {
3380:     if (set) *set = PETSC_FALSE;
3381:     *nmax = 0;
3382:     PetscFunctionReturn(PETSC_SUCCESS);
3383:   }
3384:   if (set) *set = PETSC_TRUE;
3385:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3386:   PetscCall(PetscTokenFind(token, &value));
3387:   while (value && n < *nmax) {
3388:     PetscCall(PetscOptionsStringToScalar(value, dvalue++));
3389:     PetscCall(PetscTokenFind(token, &value));
3390:     n++;
3391:   }
3392:   PetscCall(PetscTokenDestroy(&token));
3393:   *nmax = n;
3394:   PetscFunctionReturn(PETSC_SUCCESS);
3395: }

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

3401:   Not Collective; No Fortran Support

3403:   Input Parameters:
3404: + options - options database, use `NULL` for default global database
3405: . pre     - string to prepend to name or `NULL`
3406: - name    - the option one is seeking

3408:   Output Parameters:
3409: + strings - location to copy strings
3410: . nmax    - On input maximum number of strings, on output the actual number of strings found
3411: - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`

3413:   Level: beginner

3415:   Notes:
3416:   The `nmax` parameter is used for both input and output.

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

3421:   The user is responsible for deallocating the strings that are
3422:   returned.

3424: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
3425:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3426:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3427:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3428:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3429:           `PetscOptionsFList()`, `PetscOptionsEList()`
3430: @*/
3431: PetscErrorCode PetscOptionsGetStringArray(PetscOptions options, const char pre[], const char name[], char *strings[], PetscInt *nmax, PetscBool *set) PeNS
3432: {
3433:   const char *svalue;
3434:   const char *value;
3435:   PetscInt    n = 0;
3436:   PetscBool   flag;
3437:   PetscToken  token;

3439:   PetscFunctionBegin;
3440:   PetscAssertPointer(name, 3);
3441:   PetscAssertPointer(nmax, 5);
3442:   if (*nmax) PetscAssertPointer(strings, 4);

3444:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3445:   if (!flag || !svalue) {
3446:     if (set) *set = PETSC_FALSE;
3447:     *nmax = 0;
3448:     PetscFunctionReturn(PETSC_SUCCESS);
3449:   }
3450:   if (set) *set = PETSC_TRUE;
3451:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3452:   PetscCall(PetscTokenFind(token, &value));
3453:   while (value && n < *nmax) {
3454:     PetscCall(PetscStrallocpy(value, &strings[n]));
3455:     PetscCall(PetscTokenFind(token, &value));
3456:     n++;
3457:   }
3458:   PetscCall(PetscTokenDestroy(&token));
3459:   *nmax = n;
3460:   PetscFunctionReturn(PETSC_SUCCESS);
3461: }

3463: PetscErrorCode PetscOptionsDeprecated_Private(PetscOptionItems PetscOptionsObject, MPI_Comm incomm, const char inprefix[], const char oldname[], const char newname[], const char version[], const char info[])
3464: {
3465:   PetscBool         found, quiet;
3466:   const char       *value;
3467:   const char *const quietopt = "-options_suppress_deprecated_warnings";
3468:   char              msg[4096];
3469:   const char       *prefix  = NULL;
3470:   PetscOptions      options = NULL;
3471:   MPI_Comm          comm    = PETSC_COMM_SELF;

3473:   PetscFunctionBegin;
3474:   PetscAssertPointer(oldname, 4);
3475:   PetscAssertPointer(version, 6);
3476:   if (PetscOptionsObject) {
3477:     prefix  = PetscOptionsObject->prefix;
3478:     options = PetscOptionsObject->options;
3479:     comm    = PetscOptionsObject->comm;
3480:   } else {
3481:     prefix = inprefix;
3482:     comm   = incomm;
3483:   }

3485:   PetscCall(PetscOptionsFindPair(options, prefix, oldname, &value, &found));
3486:   if (found) {
3487:     if (newname) {
3488:       PetscBool newfound;

3490:       /* do not overwrite if the new option has been provided */
3491:       PetscCall(PetscOptionsFindPair(options, prefix, newname, NULL, &newfound));
3492:       if (!newfound) {
3493:         if (prefix) PetscCall(PetscOptionsPrefixPush(options, prefix));
3494:         PetscCall(PetscOptionsSetValue(options, newname, value));
3495:         if (prefix) PetscCall(PetscOptionsPrefixPop(options));
3496:       }
3497:       if (prefix) {
3498:         char key[PETSC_MAX_OPTION_NAME];

3500:         PetscCall(PetscSNPrintf(key, sizeof(key), "-%s%s", prefix, oldname + 1));
3501:         PetscCall(PetscOptionsClearValue(options, key));
3502:       } else PetscCall(PetscOptionsClearValue(options, oldname));
3503:     }
3504:     quiet = PETSC_FALSE;
3505:     PetscCall(PetscOptionsGetBool(options, NULL, quietopt, &quiet, NULL));
3506:     if (!quiet) {
3507:       PetscCall(PetscStrncpy(msg, "** PETSc DEPRECATION WARNING ** : the option -", sizeof(msg)));
3508:       PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
3509:       PetscCall(PetscStrlcat(msg, oldname + 1, sizeof(msg)));
3510:       PetscCall(PetscStrlcat(msg, " is deprecated as of version ", sizeof(msg)));
3511:       PetscCall(PetscStrlcat(msg, version, sizeof(msg)));
3512:       PetscCall(PetscStrlcat(msg, " and will be removed in a future release.\n", sizeof(msg)));
3513:       if (newname) {
3514:         PetscCall(PetscStrlcat(msg, "   Use the option -", sizeof(msg)));
3515:         PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
3516:         PetscCall(PetscStrlcat(msg, newname + 1, sizeof(msg)));
3517:         PetscCall(PetscStrlcat(msg, " instead.", sizeof(msg)));
3518:       }
3519:       if (info) {
3520:         PetscCall(PetscStrlcat(msg, " ", sizeof(msg)));
3521:         PetscCall(PetscStrlcat(msg, info, sizeof(msg)));
3522:       }
3523:       PetscCall(PetscStrlcat(msg, " (Silence this warning with ", sizeof(msg)));
3524:       PetscCall(PetscStrlcat(msg, quietopt, sizeof(msg)));
3525:       PetscCall(PetscStrlcat(msg, ")\n", sizeof(msg)));
3526:       PetscCall(PetscPrintf(comm, "%s", msg));
3527:     }
3528:   }
3529:   PetscFunctionReturn(PETSC_SUCCESS);
3530: }