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

 21: #if PetscDefined(HAVE_STRCASECMP)
 22:   #define PetscOptNameCmp(a, b) strcasecmp(a, b)
 23: #elif PetscDefined(HAVE_STRICMP)
 24:   #define PetscOptNameCmp(a, b) stricmp(a, b)
 25: #else
 26:   #define PetscOptNameCmp(a, b) Error_strcasecmp_not_found
 27: #endif

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

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

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

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

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

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

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

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

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

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

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

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

 91:   /* Help */
 92:   PetscBool help;          /* flag whether "-help" is in the database */
 93:   PetscBool help_intro;    /* flag whether "-help intro" is in the database */
 94:   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() */
 95:   char    **help_mansecs;  /* the manual sections themselves; only the options blocks in one of them are printed */

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

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

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

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

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

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

140:   Logically Collective

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

145:   Level: advanced

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

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

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

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

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

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

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

174:   Level: advanced

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

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

194:   Logically collective

196:   Level: developer

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

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

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

214:   Logically Collective

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

219:   Level: advanced

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

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

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

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

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

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

248:   Level: advanced

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

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

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

267:   Logically collective

269:   Level: developer

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

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

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

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

294:   Not Collective

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

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

302:   Level: intermediate

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

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

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

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

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

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

382:   Logically Collective

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

388:   Level: intermediate

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

395:    Contributed by Boyana Norris

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

625:   Collective

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

635:   Level: developer

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

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

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

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

672:   Logically Collective

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

679:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

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

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

834:   Collective on `PETSC_COMM_WORLD`

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

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

849:   Level: advanced

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

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

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

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

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

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

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

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

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

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

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

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

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

950:   Logically Collective, No Fortran Support

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

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

959:   Level: advanced

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

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

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

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

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

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

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

1006:   Not Collective

1008:   Level: developer

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

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

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

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

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

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

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

1068:   Logically Collective

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

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

1078:   Level: advanced

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

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

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

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

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

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

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

1126:   Level: advanced

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

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

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

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

1156:   Logically Collective

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

1161:   Level: developer

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

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

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

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

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

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

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

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

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

1222:   Logically Collective

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

1229:   Level: advanced

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

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

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

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

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

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

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

1292:   Logically Collective

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

1299:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1458:   Logically Collective

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

1464:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

1530:   Not Collective

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

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

1541:   Level: developer

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1732:   Not Collective

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

1740:   Level: advanced

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

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

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

1765:   Not Collective

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

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

1773:   Level: advanced

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

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

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

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

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

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

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

1835:   Not Collective

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

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

1845:   Level: beginner

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

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

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

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

1871:   Not Collective

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

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

1879:   Level: advanced

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

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

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

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

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

1925:   Not Collective

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

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

1934:   Level: advanced

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

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

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

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

1965:   Not Collective

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

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

1973:   Level: advanced

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

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

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

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

1998:   Not Collective

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

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

2006:   Level: advanced

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

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

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

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

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

2049:   Not Collective

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

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

2059:   Level: advanced

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

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

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

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

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

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

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

2106:   Not Collective

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

2114:   Level: advanced

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

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

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

2137:   Logically Collective

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

2145:   Level: intermediate

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

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

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

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

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

2186:   Not Collective

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

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

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

2205:   Level: intermediate

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

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

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

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

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

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

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

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

2298:   Not Collective

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

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

2306:   Level: developer

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

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

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

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

2327:   Not Collective

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

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

2335:   Level: developer

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

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

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

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

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

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

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

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

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

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

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

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

2441:   Not Collective

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

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

2449:   Level: developer

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

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

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

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

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

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

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

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

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

2503:   Not Collective

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

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

2511:   Level: developer

2513:   Note:
2514:   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.

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

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

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

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

2548:   Not Collective

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

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

2559:   Level: beginner

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

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

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

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

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

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

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

2602:   Not Collective

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

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

2613:   Level: beginner

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

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

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

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

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

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

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

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

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

2665:   Not Collective

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

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

2678:   Level: intermediate

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

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

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

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

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

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

2732:   Not Collective

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

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

2744:   Level: beginner

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

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

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

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

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

2780:   Not Collective

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

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

2791:   Level: beginner

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

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

2799:   Accepts the deprecated value `default`.

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

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

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

2834:   Not Collective

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

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

2845:   Level: beginner

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

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

2853:   Accepts the deprecated value `default`.

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

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

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

2879:   Not Collective

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

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

2890:   Level: beginner

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

2895:   Accepts the deprecated value `default`

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

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

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

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

2933:   Not Collective

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

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

2944:   Level: beginner

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

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

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

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

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

2990:   Not Collective

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

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

3002:   Level: beginner

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

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

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

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

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

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

3050:   Not Collective

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

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

3062:   Level: beginner

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

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

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

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

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

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

3112:   Not Collective

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

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

3125:   Level: beginner

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

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

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

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

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

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

3177:   Not Collective

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

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

3189:   Level: beginner

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

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

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

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

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

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

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

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

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

3286:   Not Collective

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

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

3298:   Level: beginner

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

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

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

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

3343:   Not Collective

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

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

3355:   Level: beginner

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

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

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

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

3400:   Not Collective; No Fortran Support

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

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

3412:   Level: beginner

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

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

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

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

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

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

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

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

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

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

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