Actual source code: options.c

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

135:   Logically Collective

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

140:   Level: advanced

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

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

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

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

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

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

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

169:   Level: advanced

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

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

189:   Logically collective

191:   Level: developer

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

196: .seealso: `PetscOptionsDestroyDefault()`, `PetscOptionsCreate()`, `PetscOptionsPush()`, `PetscOptionsPop()`
197: @*/
198: PetscErrorCode PetscOptionsCreateDefault(void)
199: {
200:   PetscFunctionBegin;
201:   if (PetscUnlikely(!defaultoptions)) PetscCall(PetscOptionsCreate(&defaultoptions));
202:   PetscFunctionReturn(PETSC_SUCCESS);
203: }

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

209:   Logically Collective

211:   Input Parameter:
212: . opt - the options obtained with `PetscOptionsCreate()`

214:   Level: advanced

216:   Notes:
217:   Use `PetscOptionsPop()` to return to the previous default options database

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

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

227: .seealso: `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
228: @*/
229: PetscErrorCode PetscOptionsPush(PetscOptions opt)
230: {
231:   PetscFunctionBegin;
232:   PetscCall(PetscOptionsCreateDefault());
233:   opt->previous  = defaultoptions;
234:   defaultoptions = opt;
235:   PetscFunctionReturn(PETSC_SUCCESS);
236: }

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

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

243:   Level: advanced

245: .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
246: @*/
247: PetscErrorCode PetscOptionsPop(void)
248: {
249:   PetscOptions current = defaultoptions;

251:   PetscFunctionBegin;
252:   PetscCheck(defaultoptions, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing default options");
253:   PetscCheck(defaultoptions->previous, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscOptionsPop() called too many times");
254:   defaultoptions    = defaultoptions->previous;
255:   current->previous = NULL;
256:   PetscFunctionReturn(PETSC_SUCCESS);
257: }

259: /*@
260:   PetscOptionsDestroyDefault - Destroys the default global options database

262:   Logically collective

264:   Level: developer

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

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

279:     PetscCall(PetscOptionsPop());
280:     PetscCall(PetscOptionsDestroy(&tmp));
281:   }
282:   PetscCall(PetscOptionsDestroy(&defaultoptions));
283:   PetscFunctionReturn(PETSC_SUCCESS);
284: }

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

289:   Not Collective

291:   Input Parameter:
292: . key - string to check if valid

294:   Output Parameter:
295: . valid - `PETSC_TRUE` if a valid key

297:   Level: intermediate

299: .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`
300: @*/
301: PetscErrorCode PetscOptionsValidKey(const char key[], PetscBool *valid)
302: {
303:   char               *ptr;
304:   PETSC_UNUSED double d;

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

320: static PetscErrorCode PetscOptionsInsertString_Private(PetscOptions options, const char in_str[], PetscOptionSource source)
321: {
322:   const char *first, *second;
323:   PetscToken  token;

325:   PetscFunctionBegin;
326:   PetscCall(PetscTokenCreate(in_str, ' ', &token));
327:   PetscCall(PetscTokenFind(token, &first));
328:   while (first) {
329:     PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;

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

374: /*@
375:   PetscOptionsInsertString - Inserts options into the database from a string

377:   Logically Collective

379:   Input Parameters:
380: + options - options object
381: - in_str  - string that contains options separated by blanks

383:   Level: intermediate

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

390:    Contributed by Boyana Norris

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

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

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

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

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

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

483:   PetscFunctionBegin;
484:   PetscCall(PetscMemzero(tokens, sizeof(tokens)));
485:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
486:   if (rank == 0) {
487:     char fpath[PETSC_MAX_PATH_LEN];
488:     char fname[PETSC_MAX_PATH_LEN];

490:     PetscCall(PetscStrreplace(PETSC_COMM_SELF, file, fname, sizeof(fname)));
491:     PetscCall(PetscFixFilename(fname, fpath));
492:     PetscCall(PetscGetFullPath(fpath, fname, sizeof(fname)));

494:     fd = fopen(fname, "r");
495:     PetscCall(PetscTestDirectory(fname, 'r', &isdir));
496:     PetscCheck(!isdir || !require, PETSC_COMM_SELF, PETSC_ERR_USER, "Specified options file %s is a directory", fname);
497:     if (fd && !isdir) {
498:       PetscSegBuffer vseg, aseg;

500:       PetscCall(PetscSegBufferCreate(1, 4000, &vseg));
501:       PetscCall(PetscSegBufferCreate(1, 2000, &aseg));

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

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

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

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

601:   if (acnt) {
602:     PetscCall(PetscTokenCreate(astring, ' ', &token));
603:     PetscCall(PetscTokenFind(token, &tokens[0]));
604:     while (tokens[0]) {
605:       PetscCall(PetscTokenFind(token, &tokens[1]));
606:       PetscCall(PetscOptionsSetAlias(options, tokens[0], tokens[1]));
607:       PetscCall(PetscTokenFind(token, &tokens[0]));
608:     }
609:     PetscCall(PetscTokenDestroy(&token));
610:   }

612:   if (cnt) PetscCall(PetscOptionsInsertString_Private(options, vstring, PETSC_OPT_FILE));
613:   PetscCall(PetscFree(packed));
614:   PetscFunctionReturn(PETSC_SUCCESS);
615: }

617: /*@
618:   PetscOptionsInsertFile - Inserts options into the database from a file.

620:   Collective

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

630:   Level: developer

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

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

654:   PetscFunctionBegin;
655:   PetscCall(PetscOptionsFilename(comm, file, filename, &yaml));
656:   if (yaml) {
657:     PetscCall(PetscOptionsInsertFileYAML(comm, options, filename, require));
658:   } else {
659:     PetscCall(PetscOptionsInsertFilePetsc(comm, options, filename, require));
660:   }
661:   PetscFunctionReturn(PETSC_SUCCESS);
662: }

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

667:   Logically Collective

669:   Input Parameters:
670: + options - options object
671: . argc    - the array length
672: - args    - the string array

674:   Level: intermediate

676: .seealso: `PetscOptions`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`
677: @*/
678: PetscErrorCode PetscOptionsInsertArgs(PetscOptions options, int argc, const char *const args[])
679: {
680:   MPI_Comm           comm  = PETSC_COMM_WORLD;
681:   int                left  = PetscMax(argc, 0);
682:   const char *const *eargs = args;

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

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

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

757:   PetscFunctionBegin;
758:   PetscCall(PetscCalloc2(n, &cval, n, &set));
759:   val = (const char **)cval;

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

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

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

781:   /* Process flags */
782:   PetscCall(PetscStrcasecmp(val[PO_HELP], "intro", &options->help_intro));
783:   if (options->help_intro) options->help = PETSC_TRUE;
784:   else PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_HELP, val, set, &options->help));
785:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_CI_ENABLE, val, set, &unneeded));
786:   /* need to manage PO_CI_ENABLE option before the PetscOptionsMonitor is turned on, so its setting is not monitored */
787:   if (set[PO_CI_ENABLE]) PetscCall(PetscOptionsSetValue_Private(options, opt[PO_CI_ENABLE], val[PO_CI_ENABLE], &a, PETSC_OPT_COMMAND_LINE));
788:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR_CANCEL, val, set, &options->monitorCancel));
789:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR, val, set, &options->monitorFromOptions));
790:   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_SKIP_PETSCRC, val, set, skip_petscrc));
791:   *skip_petscrc_set = set[PO_SKIP_PETSCRC];

793:   /* Store precedent options in database and mark them as used */
794:   for (o = 1; o < n; o++) {
795:     if (set[o]) {
796:       PetscCall(PetscOptionsSetValue_Private(options, opt[o], val[o], &a, PETSC_OPT_COMMAND_LINE));
797:       options->used[a] = PETSC_TRUE;
798:     }
799:   }
800:   PetscCall(PetscFree2(cval, set));
801:   options->precedentProcessed = PETSC_TRUE;
802:   PetscFunctionReturn(PETSC_SUCCESS);
803: }

805: static inline PetscErrorCode PetscOptionsSkipPrecedent(PetscOptions options, const char name[], PetscBool *flg)
806: {
807:   PetscFunctionBegin;
808:   PetscAssertPointer(flg, 3);
809:   *flg = PETSC_FALSE;
810:   if (options->precedentProcessed) {
811:     for (int i = 0; i < PO_NUM; ++i) {
812:       if (!PetscOptNameCmp(precedentOptions[i], name)) {
813:         /* check if precedent option has been set already */
814:         PetscCall(PetscOptionsFindPair(options, NULL, name, NULL, flg));
815:         if (*flg) break;
816:       }
817:     }
818:   }
819:   PetscFunctionReturn(PETSC_SUCCESS);
820: }

822: /*@C
823:   PetscOptionsInsert - Inserts into the options database from the command line,
824:   the environmental variable and a file.

826:   Collective on `PETSC_COMM_WORLD`

828:   Input Parameters:
829: + options - options database or `NULL` for the default global database
830: . argc    - count of number of command line arguments
831: . args    - the command line arguments
832: - file    - [optional] PETSc database file, append ":yaml" to filename to specify YAML options format.
833:             Use `NULL` or empty string to not check for code specific file.
834:             Also checks ~/.petscrc, .petscrc and petscrc.
835:             Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.

837:   Options Database Keys:
838: + -options_file filename      - read options from a file
839: - -options_file_yaml filename - read options from a YAML file

841:   Level: advanced

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

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

850: .seealso: `PetscOptionsDestroy()`, `PetscOptionsView()`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`,
851:           `PetscInitialize()`
852: @*/
853: PetscErrorCode PetscOptionsInsert(PetscOptions options, int *argc, char ***args, const char file[]) PeNS
854: {
855:   MPI_Comm    comm = PETSC_COMM_WORLD;
856:   PetscMPIInt rank;
857:   PetscBool   hasArgs     = (argc && *argc) ? PETSC_TRUE : PETSC_FALSE;
858:   PetscBool   skipPetscrc = PETSC_FALSE, skipPetscrcSet = PETSC_FALSE;
859:   char       *eoptions = NULL;
860:   size_t      len      = 0;

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

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

883:     PetscCall(PetscGetHomeDirectory(filename, sizeof(filename)));
884:     PetscCallMPI(MPI_Bcast(filename, (int)sizeof(filename), MPI_CHAR, 0, comm));
885:     if (filename[0]) PetscCall(PetscStrlcat(filename, "/.petscrc", sizeof(filename)));
886:     PetscCall(PetscOptionsInsertFile(comm, options, filename, PETSC_FALSE));
887:     PetscCall(PetscOptionsInsertFile(comm, options, ".petscrc", PETSC_FALSE));
888:     PetscCall(PetscOptionsInsertFile(comm, options, "petscrc", PETSC_FALSE));
889:   }

891:   /* insert environment options */
892:   if (rank == 0) {
893:     eoptions = getenv("PETSC_OPTIONS");
894:     PetscCall(PetscStrlen(eoptions, &len));
895:   }
896:   PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, comm));
897:   if (len) {
898:     if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
899:     PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, comm));
900:     if (rank) eoptions[len] = 0;
901:     PetscCall(PetscOptionsInsertString_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
902:     if (rank) PetscCall(PetscFree(eoptions));
903:   }

905:   /* insert YAML environment options */
906:   if (rank == 0) {
907:     eoptions = getenv("PETSC_OPTIONS_YAML");
908:     PetscCall(PetscStrlen(eoptions, &len));
909:   }
910:   PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, comm));
911:   if (len) {
912:     if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
913:     PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, comm));
914:     if (rank) eoptions[len] = 0;
915:     PetscCall(PetscOptionsInsertStringYAML_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
916:     if (rank) PetscCall(PetscFree(eoptions));
917:   }

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

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

929: static PetscBool PetscCIOption(const char *name)
930: {
931:   PetscInt  idx;
932:   PetscBool found;

934:   if (!PetscCIEnabled) return PETSC_FALSE;
935:   PetscCallAbort(PETSC_COMM_SELF, PetscEListFind(PETSC_STATIC_ARRAY_LENGTH(PetscCIOptions), PetscCIOptions, name, &idx, &found));
936:   return found;
937: }

939: /*@
940:   PetscOptionsView - Prints the options that have been loaded. This is
941:   useful for debugging purposes.

943:   Logically Collective, No Fortran Support

945:   Input Parameters:
946: + options - options database, use `NULL` for default global database
947: - viewer  - must be an `PETSCVIEWERASCII` viewer

949:   Options Database Key:
950: . -options_view - Activates `PetscOptionsView()` within `PetscFinalize()`

952:   Level: advanced

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

958: .seealso: `PetscOptionsAllUsed()`
959: @*/
960: PetscErrorCode PetscOptionsView(PetscOptions options, PetscViewer viewer)
961: {
962:   PetscInt  i, N = 0;
963:   PetscBool isascii;

965:   PetscFunctionBegin;
967:   options = options ? options : defaultoptions;
968:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
969:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
970:   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");

972:   for (i = 0; i < options->N; i++) {
973:     if (PetscCIOption(options->names[i])) continue;
974:     N++;
975:   }

977:   if (!N) {
978:     PetscCall(PetscViewerASCIIPrintf(viewer, "#No PETSc Option Table entries\n"));
979:     PetscFunctionReturn(PETSC_SUCCESS);
980:   }

982:   PetscCall(PetscViewerASCIIPrintf(viewer, "#PETSc Option Table entries:\n"));
983:   for (i = 0; i < options->N; i++) {
984:     if (PetscCIOption(options->names[i])) continue;
985:     if (options->values[i]) {
986:       PetscCall(PetscViewerASCIIPrintf(viewer, "-%s %s", options->names[i], options->values[i]));
987:     } else {
988:       PetscCall(PetscViewerASCIIPrintf(viewer, "-%s", options->names[i]));
989:     }
990:     PetscCall(PetscViewerASCIIPrintf(viewer, " # (source: %s)\n", PetscOptionSources[options->source[i]]));
991:   }
992:   PetscCall(PetscViewerASCIIPrintf(viewer, "#End of PETSc Option Table entries\n"));
993:   PetscFunctionReturn(PETSC_SUCCESS);
994: }

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

999:   Not Collective

1001:   Level: developer

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

1007: .seealso: `PetscOptionsLeft()`, `PetscOptionsAllUsed()`, `PetscOptionsView()`
1008: @*/
1009: PetscErrorCode PetscOptionsLeftError(void)
1010: {
1011:   PetscInt i, nopt = 0;

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

1032: PETSC_EXTERN PetscErrorCode PetscOptionsViewError(void)
1033: {
1034:   PetscInt     i, N = 0;
1035:   PetscOptions options = defaultoptions;

1037:   for (i = 0; i < options->N; i++) {
1038:     if (PetscCIOption(options->names[i])) continue;
1039:     N++;
1040:   }

1042:   if (N) {
1043:     PetscCall((*PetscErrorPrintf)("PETSc Option Table entries:\n"));
1044:   } else {
1045:     PetscCall((*PetscErrorPrintf)("No PETSc Option Table entries\n"));
1046:   }
1047:   for (i = 0; i < options->N; i++) {
1048:     if (PetscCIOption(options->names[i])) continue;
1049:     if (options->values[i]) {
1050:       PetscCall((*PetscErrorPrintf)("-%s %s (source: %s)\n", options->names[i], options->values[i], PetscOptionSources[options->source[i]]));
1051:     } else {
1052:       PetscCall((*PetscErrorPrintf)("-%s (source: %s)\n", options->names[i], PetscOptionSources[options->source[i]]));
1053:     }
1054:   }
1055:   return PETSC_SUCCESS;
1056: }

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

1061:   Logically Collective

1063:   Input Parameters:
1064: + options - options database, or `NULL` for the default global database
1065: - prefix  - The string to append to the existing prefix

1067:   Options Database Keys:
1068: + -prefix_push some_prefix_ - push the given prefix
1069: - -prefix_pop               - pop the last prefix

1071:   Level: advanced

1073:   Notes:
1074:   It is common to use this in conjunction with `-options_file` as in
1075: .vb
1076:  -prefix_push system1_ -options_file system1rc -prefix_pop -prefix_push system2_ -options_file system2rc -prefix_pop
1077: .ve
1078:   where the files no longer require all options to be prefixed with `-system2_`.

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

1085: .seealso: `PetscOptionsPrefixPop()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1086: @*/
1087: PetscErrorCode PetscOptionsPrefixPush(PetscOptions options, const char prefix[])
1088: {
1089:   size_t    n;
1090:   PetscInt  start;
1091:   char      key[PETSC_MAX_OPTION_NAME + 1];
1092:   PetscBool valid;

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

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

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

1116:   Input Parameter:
1117: . options - options database, or `NULL` for the default global database

1119:   Level: advanced

1121: .seealso: `PetscOptionsPrefixPush()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1122: @*/
1123: PetscErrorCode PetscOptionsPrefixPop(PetscOptions options)
1124: {
1125:   PetscInt offset;

1127:   PetscFunctionBegin;
1128:   options = options ? options : defaultoptions;
1129:   PetscCheck(options->prefixind >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More prefixes popped than pushed");
1130:   options->prefixind--;
1131:   offset                  = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1132:   options->prefix[offset] = 0;
1133:   PetscFunctionReturn(PETSC_SUCCESS);
1134: }

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

1139:   Logically Collective

1141:   Input Parameter:
1142: . options - options database, use `NULL` for the default global database

1144:   Level: developer

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

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

1155: .seealso: `PetscOptionsInsert()`
1156: @*/
1157: PetscErrorCode PetscOptionsClear(PetscOptions options)
1158: {
1159:   PetscInt i;

1161:   PetscFunctionBegin;
1162:   options = options ? options : defaultoptions;
1163:   if (!options) PetscFunctionReturn(PETSC_SUCCESS);

1165:   for (i = 0; i < options->N; i++) {
1166:     if (options->names[i]) free(options->names[i]);
1167:     if (options->values[i]) free(options->values[i]);
1168:   }
1169:   options->N = 0;
1170:   free(options->names);
1171:   free(options->values);
1172:   free(options->used);
1173:   free(options->source);
1174:   options->names  = NULL;
1175:   options->values = NULL;
1176:   options->used   = NULL;
1177:   options->source = NULL;
1178:   options->Nalloc = 0;

1180:   for (i = 0; i < options->Na; i++) {
1181:     free(options->aliases1[i]);
1182:     free(options->aliases2[i]);
1183:   }
1184:   options->Na = 0;
1185:   free(options->aliases1);
1186:   free(options->aliases2);
1187:   options->aliases1 = options->aliases2 = NULL;
1188:   options->Naalloc                      = 0;

1190:   /* destroy hash table */
1191:   kh_destroy(HO, options->ht);
1192:   options->ht = NULL;

1194:   options->prefixind  = 0;
1195:   options->prefix[0]  = 0;
1196:   options->help       = PETSC_FALSE;
1197:   options->help_intro = PETSC_FALSE;
1198:   PetscFunctionReturn(PETSC_SUCCESS);
1199: }

1201: /*@
1202:   PetscOptionsSetAlias - Makes a key and alias for another key

1204:   Logically Collective

1206:   Input Parameters:
1207: + options - options database, or `NULL` for default global database
1208: . newname - the alias
1209: - oldname - the name that alias will refer to

1211:   Level: advanced

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

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

1222: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1223:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1224:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1225:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1226:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1227:           `PetscOptionsFList()`, `PetscOptionsEList()`
1228: @*/
1229: PetscErrorCode PetscOptionsSetAlias(PetscOptions options, const char newname[], const char oldname[])
1230: {
1231:   size_t    len;
1232:   PetscBool valid;

1234:   PetscFunctionBegin;
1235:   PetscAssertPointer(newname, 2);
1236:   PetscAssertPointer(oldname, 3);
1237:   options = options ? options : defaultoptions;
1238:   PetscCall(PetscOptionsValidKey(newname, &valid));
1239:   PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliased option %s", newname);
1240:   PetscCall(PetscOptionsValidKey(oldname, &valid));
1241:   PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliasee option %s", oldname);

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

1246:     options->Naalloc = PetscMax(4, options->Naalloc * 2);
1247:     tmpA1            = (char **)malloc(options->Naalloc * sizeof(char *));
1248:     tmpA2            = (char **)malloc(options->Naalloc * sizeof(char *));
1249:     for (int i = 0; i < options->Na; ++i) {
1250:       tmpA1[i] = options->aliases1[i];
1251:       tmpA2[i] = options->aliases2[i];
1252:     }
1253:     free(options->aliases1);
1254:     free(options->aliases2);
1255:     options->aliases1 = tmpA1;
1256:     options->aliases2 = tmpA2;
1257:   }
1258:   newname++;
1259:   oldname++;
1260:   PetscCall(PetscStrlen(newname, &len));
1261:   options->aliases1[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1262:   PetscCall(PetscStrncpy(options->aliases1[options->Na], newname, len + 1));
1263:   PetscCall(PetscStrlen(oldname, &len));
1264:   options->aliases2[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1265:   PetscCall(PetscStrncpy(options->aliases2[options->Na], oldname, len + 1));
1266:   ++options->Na;
1267:   PetscFunctionReturn(PETSC_SUCCESS);
1268: }

1270: /*@
1271:   PetscOptionsSetValue - Sets an option name-value pair in the options
1272:   database, overriding whatever is already present.

1274:   Logically Collective

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

1281:   Level: intermediate

1283:   Note:
1284:   This function can be called BEFORE `PetscInitialize()`

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

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

1294: .seealso: `PetscOptionsInsert()`, `PetscOptionsClearValue()`
1295: @*/
1296: PetscErrorCode PetscOptionsSetValue(PetscOptions options, const char name[], const char value[])
1297: {
1298:   PetscFunctionBegin;
1299:   PetscCall(PetscOptionsSetValue_Private(options, name, value, NULL, PETSC_OPT_CODE));
1300:   PetscFunctionReturn(PETSC_SUCCESS);
1301: }

1303: PetscErrorCode PetscOptionsSetValue_Private(PetscOptions options, const char name[], const char value[], int *pos, PetscOptionSource source)
1304: {
1305:   size_t    len;
1306:   int       n, i;
1307:   char    **names;
1308:   char      fullname[PETSC_MAX_OPTION_NAME] = "";
1309:   PetscBool flg;

1311:   PetscFunctionBegin;
1312:   if (!options) {
1313:     PetscCall(PetscOptionsCreateDefault());
1314:     options = defaultoptions;
1315:   }
1316:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "name %s must start with '-'", name);

1318:   PetscCall(PetscOptionsSkipPrecedent(options, name, &flg));
1319:   if (flg) PetscFunctionReturn(PETSC_SUCCESS);

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

1323:   if (options->prefixind > 0) {
1324:     strncpy(fullname, options->prefix, sizeof(fullname));
1325:     fullname[sizeof(fullname) - 1] = 0;
1326:     strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
1327:     fullname[sizeof(fullname) - 1] = 0;
1328:     name                           = fullname;
1329:   }

1331:   /* check against aliases */
1332:   for (i = 0; i < options->Na; i++) {
1333:     int result = PetscOptNameCmp(options->aliases1[i], name);
1334:     if (!result) {
1335:       name = options->aliases2[i];
1336:       break;
1337:     }
1338:   }

1340:   /* slow search */
1341:   n     = options->N;
1342:   names = options->names;
1343:   for (i = 0; i < options->N; i++) {
1344:     int result = PetscOptNameCmp(names[i], name);
1345:     if (!result) {
1346:       n = i;
1347:       goto setvalue;
1348:     } else if (result > 0) {
1349:       n = i;
1350:       break;
1351:     }
1352:   }
1353:   if (options->N == options->Nalloc) {
1354:     char             **names, **values;
1355:     PetscBool         *used;
1356:     PetscOptionSource *source;

1358:     options->Nalloc = PetscMax(10, options->Nalloc * 2);
1359:     names           = (char **)malloc(options->Nalloc * sizeof(char *));
1360:     values          = (char **)malloc(options->Nalloc * sizeof(char *));
1361:     used            = (PetscBool *)malloc(options->Nalloc * sizeof(PetscBool));
1362:     source          = (PetscOptionSource *)malloc(options->Nalloc * sizeof(PetscOptionSource));
1363:     for (int i = 0; i < options->N; ++i) {
1364:       names[i]  = options->names[i];
1365:       values[i] = options->values[i];
1366:       used[i]   = options->used[i];
1367:       source[i] = options->source[i];
1368:     }
1369:     free(options->names);
1370:     free(options->values);
1371:     free(options->used);
1372:     free(options->source);
1373:     options->names  = names;
1374:     options->values = values;
1375:     options->used   = used;
1376:     options->source = source;
1377:   }

1379:   /* shift remaining values up 1 */
1380:   for (i = options->N; i > n; i--) {
1381:     options->names[i]  = options->names[i - 1];
1382:     options->values[i] = options->values[i - 1];
1383:     options->used[i]   = options->used[i - 1];
1384:     options->source[i] = options->source[i - 1];
1385:   }
1386:   options->names[n]  = NULL;
1387:   options->values[n] = NULL;
1388:   options->used[n]   = PETSC_FALSE;
1389:   options->source[n] = PETSC_OPT_CODE;
1390:   options->N++;

1392:   /* destroy hash table */
1393:   kh_destroy(HO, options->ht);
1394:   options->ht = NULL;

1396:   /* set new name */
1397:   len               = strlen(name);
1398:   options->names[n] = (char *)malloc((len + 1) * sizeof(char));
1399:   PetscCheck(options->names[n], PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate option name");
1400:   strcpy(options->names[n], name);

1402: setvalue:
1403:   /* set new value */
1404:   if (options->values[n]) free(options->values[n]);
1405:   len = value ? strlen(value) : 0;
1406:   if (len) {
1407:     options->values[n] = (char *)malloc((len + 1) * sizeof(char));
1408:     if (!options->values[n]) return PETSC_ERR_MEM;
1409:     strcpy(options->values[n], value);
1410:     options->values[n][len] = '\0';
1411:   } else {
1412:     options->values[n] = NULL;
1413:   }
1414:   options->source[n] = source;

1416:   /* handle -help so that it can be set from anywhere */
1417:   if (!PetscOptNameCmp(name, "help")) {
1418:     options->help       = PETSC_TRUE;
1419:     options->help_intro = (value && !PetscOptNameCmp(value, "intro")) ? PETSC_TRUE : PETSC_FALSE;
1420:     options->used[n]    = PETSC_TRUE;
1421:   }

1423:   PetscCall(PetscOptionsMonitor(options, name, value ? value : "", source));
1424:   if (pos) *pos = n;
1425:   PetscFunctionReturn(PETSC_SUCCESS);
1426: }

1428: /*@
1429:   PetscOptionsClearValue - Clears an option name-value pair in the options
1430:   database, overriding whatever is already present.

1432:   Logically Collective

1434:   Input Parameters:
1435: + options - options database, use `NULL` for the default global database
1436: - name    - name of option, this SHOULD have the - prepended

1438:   Level: intermediate

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

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

1449: .seealso: `PetscOptionsInsert()`
1450: @*/
1451: PetscErrorCode PetscOptionsClearValue(PetscOptions options, const char name[])
1452: {
1453:   int    N, n, i;
1454:   char **names;

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

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

1463:   /* slow search */
1464:   N = n = options->N;
1465:   names = options->names;
1466:   for (i = 0; i < N; i++) {
1467:     int result = PetscOptNameCmp(names[i], name);
1468:     if (!result) {
1469:       n = i;
1470:       break;
1471:     } else if (result > 0) {
1472:       n = N;
1473:       break;
1474:     }
1475:   }
1476:   if (n == N) PetscFunctionReturn(PETSC_SUCCESS); /* it was not present */

1478:   /* remove name and value */
1479:   if (options->names[n]) free(options->names[n]);
1480:   if (options->values[n]) free(options->values[n]);
1481:   /* shift remaining values down 1 */
1482:   for (i = n; i < N - 1; i++) {
1483:     options->names[i]  = options->names[i + 1];
1484:     options->values[i] = options->values[i + 1];
1485:     options->used[i]   = options->used[i + 1];
1486:     options->source[i] = options->source[i + 1];
1487:   }
1488:   options->N--;

1490:   /* destroy hash table */
1491:   kh_destroy(HO, options->ht);
1492:   options->ht = NULL;

1494:   PetscCall(PetscOptionsMonitor(options, name, NULL, PETSC_OPT_CODE));
1495:   PetscFunctionReturn(PETSC_SUCCESS);
1496: }

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

1501:   Not Collective

1503:   Input Parameters:
1504: + options - options database, use `NULL` for the default global database
1505: . pre     - the string to prepend to the name or `NULL`, this SHOULD NOT have the "-" prepended
1506: - name    - name of option, this SHOULD have the "-" prepended

1508:   Output Parameters:
1509: + value - the option value (optional, not used for all options)
1510: - set   - whether the option is set (optional)

1512:   Level: developer

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

1517: .seealso: `PetscOptionsSetValue()`, `PetscOptionsClearValue()`
1518: @*/
1519: PetscErrorCode PetscOptionsFindPair(PetscOptions options, const char pre[], const char name[], const char *value[], PetscBool *set)
1520: {
1521:   char      buf[PETSC_MAX_OPTION_NAME];
1522:   PetscBool matchnumbers = PETSC_TRUE;

1524:   PetscFunctionBegin;
1525:   if (!options) {
1526:     PetscCall(PetscOptionsCreateDefault());
1527:     options = defaultoptions;
1528:   }
1529:   PetscCheck(!pre || !PetscUnlikely(pre[0] == '-'), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1530:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);

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

1534:   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1535:   if (pre && pre[0]) {
1536:     char *ptr = buf;
1537:     if (name[0] == '-') {
1538:       *ptr++ = '-';
1539:       name++;
1540:     }
1541:     PetscCall(PetscStrncpy(ptr, pre, buf + sizeof(buf) - ptr));
1542:     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1543:     name = buf;
1544:   }

1546:   if (PetscDefined(USE_DEBUG)) {
1547:     PetscBool valid;
1548:     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1549:     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1550:     PetscCall(PetscOptionsValidKey(key, &valid));
1551:     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1552:   }

1554:   if (!options->ht) {
1555:     int          i, ret;
1556:     khiter_t     it;
1557:     khash_t(HO) *ht;
1558:     ht = kh_init(HO);
1559:     PetscCheck(ht, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1560:     ret = kh_resize(HO, ht, options->N * 2); /* twice the required size to reduce risk of collisions */
1561:     PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1562:     for (i = 0; i < options->N; i++) {
1563:       it = kh_put(HO, ht, options->names[i], &ret);
1564:       PetscCheck(ret == 1, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1565:       kh_val(ht, it) = i;
1566:     }
1567:     options->ht = ht;
1568:   }

1570:   khash_t(HO) *ht = options->ht;
1571:   khiter_t     it = kh_get(HO, ht, name);
1572:   if (it != kh_end(ht)) {
1573:     int i            = kh_val(ht, it);
1574:     options->used[i] = PETSC_TRUE;
1575:     if (value) *value = options->values[i];
1576:     if (set) *set = PETSC_TRUE;
1577:     PetscFunctionReturn(PETSC_SUCCESS);
1578:   }

1580:   /*
1581:    The following block slows down all lookups in the most frequent path (most lookups are unsuccessful).
1582:    Maybe this special lookup mode should be enabled on request with a push/pop API.
1583:    The feature of matching _%d_ used sparingly in the codebase.
1584:    */
1585:   if (matchnumbers) {
1586:     int i, j, cnt = 0, locs[16], loce[16];
1587:     /* determine the location and number of all _%d_ in the key */
1588:     for (i = 0; name[i]; i++) {
1589:       if (name[i] == '_') {
1590:         for (j = i + 1; name[j]; j++) {
1591:           if (name[j] >= '0' && name[j] <= '9') continue;
1592:           if (name[j] == '_' && j > i + 1) { /* found a number */
1593:             locs[cnt]   = i + 1;
1594:             loce[cnt++] = j + 1;
1595:           }
1596:           i = j - 1;
1597:           break;
1598:         }
1599:       }
1600:     }
1601:     for (i = 0; i < cnt; i++) {
1602:       PetscBool found;
1603:       char      opt[PETSC_MAX_OPTION_NAME + 1] = "-", tmp[PETSC_MAX_OPTION_NAME];
1604:       PetscCall(PetscStrncpy(tmp, name, PetscMin((size_t)(locs[i] + 1), sizeof(tmp))));
1605:       PetscCall(PetscStrlcat(opt, tmp, sizeof(opt)));
1606:       PetscCall(PetscStrlcat(opt, name + loce[i], sizeof(opt)));
1607:       PetscCall(PetscOptionsFindPair(options, NULL, opt, value, &found));
1608:       if (found) {
1609:         if (set) *set = PETSC_TRUE;
1610:         PetscFunctionReturn(PETSC_SUCCESS);
1611:       }
1612:     }
1613:   }

1615:   if (set) *set = PETSC_FALSE;
1616:   PetscFunctionReturn(PETSC_SUCCESS);
1617: }

1619: /* Check whether any option begins with pre+name */
1620: PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions options, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *set)
1621: {
1622:   char buf[PETSC_MAX_OPTION_NAME];
1623:   int  numCnt = 0, locs[16], loce[16];

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

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

1632:   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1633:   if (pre && pre[0]) {
1634:     char *ptr = buf;
1635:     if (name[0] == '-') {
1636:       *ptr++ = '-';
1637:       name++;
1638:     }
1639:     PetscCall(PetscStrncpy(ptr, pre, sizeof(buf) - ((ptr == buf) ? 0 : 1)));
1640:     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1641:     name = buf;
1642:   }

1644:   if (PetscDefined(USE_DEBUG)) {
1645:     PetscBool valid;
1646:     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1647:     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1648:     PetscCall(PetscOptionsValidKey(key, &valid));
1649:     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1650:   }

1652:   /* determine the location and number of all _%d_ in the key */
1653:   {
1654:     int i, j;
1655:     for (i = 0; name[i]; i++) {
1656:       if (name[i] == '_') {
1657:         for (j = i + 1; name[j]; j++) {
1658:           if (name[j] >= '0' && name[j] <= '9') continue;
1659:           if (name[j] == '_' && j > i + 1) { /* found a number */
1660:             locs[numCnt]   = i + 1;
1661:             loce[numCnt++] = j + 1;
1662:           }
1663:           i = j - 1;
1664:           break;
1665:         }
1666:       }
1667:     }
1668:   }

1670:   /* slow search */
1671:   for (int c = -1; c < numCnt; ++c) {
1672:     char   opt[PETSC_MAX_OPTION_NAME + 2] = "";
1673:     size_t len;

1675:     if (c < 0) {
1676:       PetscCall(PetscStrncpy(opt, name, sizeof(opt)));
1677:     } else {
1678:       PetscCall(PetscStrncpy(opt, name, PetscMin((size_t)(locs[c] + 1), sizeof(opt))));
1679:       PetscCall(PetscStrlcat(opt, name + loce[c], sizeof(opt) - 1));
1680:     }
1681:     PetscCall(PetscStrlen(opt, &len));
1682:     for (int i = 0; i < options->N; i++) {
1683:       PetscBool match;

1685:       PetscCall(PetscStrncmp(options->names[i], opt, len, &match));
1686:       if (match) {
1687:         options->used[i] = PETSC_TRUE;
1688:         if (option) *option = options->names[i];
1689:         if (value) *value = options->values[i];
1690:         if (set) *set = PETSC_TRUE;
1691:         PetscFunctionReturn(PETSC_SUCCESS);
1692:       }
1693:     }
1694:   }

1696:   if (set) *set = PETSC_FALSE;
1697:   PetscFunctionReturn(PETSC_SUCCESS);
1698: }

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

1703:   Not Collective

1705:   Input Parameters:
1706: + options - options database, use `NULL` for default global database
1707: . pre     - the option prefix (may be `NULL`)
1708: . name    - the option name one is seeking
1709: - mess    - error message (may be `NULL`)

1711:   Level: advanced

1713: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1714:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1715:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1716:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1717:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1718:           `PetscOptionsFList()`, `PetscOptionsEList()`
1719: @*/
1720: PetscErrorCode PetscOptionsReject(PetscOptions options, const char pre[], const char name[], const char mess[])
1721: {
1722:   PetscBool flag = PETSC_FALSE;

1724:   PetscFunctionBegin;
1725:   PetscCall(PetscOptionsHasName(options, pre, name, &flag));
1726:   if (flag) {
1727:     PetscCheck(!mess || !mess[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s with %s", pre ? pre : "", name + 1, mess);
1728:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s", pre ? pre : "", name + 1);
1729:   }
1730:   PetscFunctionReturn(PETSC_SUCCESS);
1731: }

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

1736:   Not Collective

1738:   Input Parameter:
1739: . options - options database, use `NULL` for default global database

1741:   Output Parameter:
1742: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.

1744:   Level: advanced

1746: .seealso: `PetscOptionsHasName()`
1747: @*/
1748: PetscErrorCode PetscOptionsHasHelp(PetscOptions options, PetscBool *set)
1749: {
1750:   PetscFunctionBegin;
1751:   PetscAssertPointer(set, 2);
1752:   options = options ? options : defaultoptions;
1753:   *set    = options->help;
1754:   PetscFunctionReturn(PETSC_SUCCESS);
1755: }

1757: PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions options, PetscBool *set)
1758: {
1759:   PetscFunctionBegin;
1760:   PetscAssertPointer(set, 2);
1761:   options = options ? options : defaultoptions;
1762:   *set    = options->help_intro;
1763:   PetscFunctionReturn(PETSC_SUCCESS);
1764: }

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

1770:   Not Collective

1772:   Input Parameters:
1773: + options - options database, use `NULL` for default global database
1774: . pre     - string to prepend to the name or `NULL`
1775: - name    - the option one is seeking

1777:   Output Parameter:
1778: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.

1780:   Level: beginner

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

1785: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1786:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1787:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1788:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1789:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1790:           `PetscOptionsFList()`, `PetscOptionsEList()`
1791: @*/
1792: PetscErrorCode PetscOptionsHasName(PetscOptions options, const char pre[], const char name[], PetscBool *set)
1793: {
1794:   const char *value;
1795:   PetscBool   flag;

1797:   PetscFunctionBegin;
1798:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
1799:   if (set) *set = flag;
1800:   PetscFunctionReturn(PETSC_SUCCESS);
1801: }

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

1806:   Not Collective

1808:   Input Parameter:
1809: . options - the options database, use `NULL` for the default global database

1811:   Output Parameter:
1812: . copts - pointer where string pointer is stored

1814:   Level: advanced

1816:   Notes:
1817:   The string should be freed with `PetscFree()`

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

1821: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsView()`, `PetscOptionsPush()`, `PetscOptionsPop()`,
1822:           `PetscOptionsLeftGet()`
1823: @*/
1824: PetscErrorCode PetscOptionsGetAll(PetscOptions options, char *copts[]) PeNS
1825: {
1826:   PetscInt i;
1827:   size_t   len = 1, lent = 0;
1828:   char    *coptions = NULL;

1830:   PetscFunctionBegin;
1831:   PetscAssertPointer(copts, 2);
1832:   options = options ? options : defaultoptions;
1833:   /* count the length of the required string */
1834:   for (i = 0; i < options->N; i++) {
1835:     PetscCall(PetscStrlen(options->names[i], &lent));
1836:     len += 2 + lent;
1837:     if (options->values[i]) {
1838:       PetscCall(PetscStrlen(options->values[i], &lent));
1839:       len += 1 + lent;
1840:     }
1841:   }
1842:   PetscCall(PetscMalloc1(len, &coptions));
1843:   coptions[0] = 0;
1844:   for (i = 0; i < options->N; i++) {
1845:     PetscCall(PetscStrlcat(coptions, "-", len));
1846:     PetscCall(PetscStrlcat(coptions, options->names[i], len));
1847:     PetscCall(PetscStrlcat(coptions, " ", len));
1848:     if (options->values[i]) {
1849:       PetscCall(PetscStrlcat(coptions, options->values[i], len));
1850:       PetscCall(PetscStrlcat(coptions, " ", len));
1851:     }
1852:   }
1853:   *copts = coptions;
1854:   PetscFunctionReturn(PETSC_SUCCESS);
1855: }

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

1860:   Not Collective

1862:   Input Parameters:
1863: + options - options database, use `NULL` for default global database
1864: - name    - string name of option

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

1869:   Level: advanced

1871:   Note:
1872:   The value returned may be different on each process and depends on which options have been processed
1873:   on the given process

1875: .seealso: `PetscOptionsView()`, `PetscOptionsLeft()`, `PetscOptionsAllUsed()`
1876: @*/
1877: PetscErrorCode PetscOptionsUsed(PetscOptions options, const char *name, PetscBool *used)
1878: {
1879:   PetscInt i;

1881:   PetscFunctionBegin;
1882:   PetscAssertPointer(name, 2);
1883:   PetscAssertPointer(used, 3);
1884:   options = options ? options : defaultoptions;
1885:   *used   = PETSC_FALSE;
1886:   for (i = 0; i < options->N; i++) {
1887:     PetscCall(PetscStrcasecmp(options->names[i], name, used));
1888:     if (*used) {
1889:       *used = options->used[i];
1890:       break;
1891:     }
1892:   }
1893:   PetscFunctionReturn(PETSC_SUCCESS);
1894: }

1896: /*@
1897:   PetscOptionsAllUsed - Returns a count of the number of options in the
1898:   database that have never been selected.

1900:   Not Collective

1902:   Input Parameter:
1903: . options - options database, use `NULL` for default global database

1905:   Output Parameter:
1906: . N - count of options not used

1908:   Level: advanced

1910:   Note:
1911:   The value returned may be different on each process and depends on which options have been processed
1912:   on the given process

1914: .seealso: `PetscOptionsView()`
1915: @*/
1916: PetscErrorCode PetscOptionsAllUsed(PetscOptions options, PetscInt *N)
1917: {
1918:   PetscInt i, n = 0;

1920:   PetscFunctionBegin;
1921:   PetscAssertPointer(N, 2);
1922:   options = options ? options : defaultoptions;
1923:   for (i = 0; i < options->N; i++) {
1924:     if (!options->used[i]) n++;
1925:   }
1926:   *N = n;
1927:   PetscFunctionReturn(PETSC_SUCCESS);
1928: }

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

1933:   Not Collective

1935:   Input Parameter:
1936: . options - options database; use `NULL` for default global database

1938:   Options Database Key:
1939: . -options_left - activates `PetscOptionsAllUsed()` within `PetscFinalize()`

1941:   Level: advanced

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

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

1951: .seealso: `PetscOptionsAllUsed()`
1952: @*/
1953: PetscErrorCode PetscOptionsLeft(PetscOptions options)
1954: {
1955:   PetscInt     i;
1956:   PetscInt     cnt = 0;
1957:   PetscOptions toptions;

1959:   PetscFunctionBegin;
1960:   toptions = options ? options : defaultoptions;
1961:   for (i = 0; i < toptions->N; i++) {
1962:     if (!toptions->used[i]) {
1963:       if (PetscCIOption(toptions->names[i])) continue;
1964:       if (toptions->values[i]) {
1965:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s value: %s source: %s\n", toptions->names[i], toptions->values[i], PetscOptionSources[toptions->source[i]]));
1966:       } else {
1967:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s (no value) source: %s\n", toptions->names[i], PetscOptionSources[toptions->source[i]]));
1968:       }
1969:     }
1970:   }
1971:   if (!options) {
1972:     toptions = defaultoptions;
1973:     while (toptions->previous) {
1974:       cnt++;
1975:       toptions = toptions->previous;
1976:     }
1977:     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));
1978:   }
1979:   PetscFunctionReturn(PETSC_SUCCESS);
1980: }

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

1985:   Not Collective

1987:   Input Parameter:
1988: . options - options database, use `NULL` for default global database

1990:   Output Parameters:
1991: + N      - count of options not used
1992: . names  - names of options not used
1993: - values - values of options not used

1995:   Level: advanced

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

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

2003: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`
2004: @*/
2005: PetscErrorCode PetscOptionsLeftGet(PetscOptions options, PetscInt *N, char **names[], char **values[])
2006: {
2007:   PetscInt i, n;

2009:   PetscFunctionBegin;
2010:   if (N) PetscAssertPointer(N, 2);
2011:   if (names) PetscAssertPointer(names, 3);
2012:   if (values) PetscAssertPointer(values, 4);
2013:   options = options ? options : defaultoptions;

2015:   /* The number of unused PETSc options */
2016:   n = 0;
2017:   for (i = 0; i < options->N; i++) {
2018:     if (PetscCIOption(options->names[i])) continue;
2019:     if (!options->used[i]) n++;
2020:   }
2021:   if (N) *N = n;
2022:   if (names) PetscCall(PetscMalloc1(n, names));
2023:   if (values) PetscCall(PetscMalloc1(n, values));

2025:   n = 0;
2026:   if (names || values) {
2027:     for (i = 0; i < options->N; i++) {
2028:       if (!options->used[i]) {
2029:         if (PetscCIOption(options->names[i])) continue;
2030:         if (names) (*names)[n] = options->names[i];
2031:         if (values) (*values)[n] = options->values[i];
2032:         n++;
2033:       }
2034:     }
2035:   }
2036:   PetscFunctionReturn(PETSC_SUCCESS);
2037: }

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

2042:   Not Collective

2044:   Input Parameters:
2045: + options - options database, use `NULL` for default global database
2046: . N       - count of options not used
2047: . names   - names of options not used
2048: - values  - values of options not used

2050:   Level: advanced

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

2055: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`, `PetscOptionsLeftGet()`
2056: @*/
2057: PetscErrorCode PetscOptionsLeftRestore(PetscOptions options, PetscInt *N, char **names[], char **values[])
2058: {
2059:   PetscFunctionBegin;
2060:   (void)options;
2061:   if (N) PetscAssertPointer(N, 2);
2062:   if (names) PetscAssertPointer(names, 3);
2063:   if (values) PetscAssertPointer(values, 4);
2064:   if (N) *N = 0;
2065:   if (names) PetscCall(PetscFree(*names));
2066:   if (values) PetscCall(PetscFree(*values));
2067:   PetscFunctionReturn(PETSC_SUCCESS);
2068: }

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

2073:   Logically Collective

2075:   Input Parameters:
2076: + name   - option name string
2077: . value  - option value string
2078: . source - The source for the option
2079: - ctx    - a `PETSCVIEWERASCII` or `NULL`

2081:   Level: intermediate

2083:   Notes:
2084:   If ctx is `NULL`, `PetscPrintf()` is used.
2085:   The first MPI process in the `PetscViewer` viewer actually prints the values, other
2086:   processes may have different values set

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

2090: .seealso: `PetscOptionsMonitorSet()`
2091: @*/
2092: PetscErrorCode PetscOptionsMonitorDefault(const char name[], const char value[], PetscOptionSource source, PetscCtx ctx)
2093: {
2094:   PetscFunctionBegin;
2095:   if (PetscCIOption(name)) PetscFunctionReturn(PETSC_SUCCESS);

2097:   if (ctx) {
2098:     PetscViewer viewer = (PetscViewer)ctx;
2099:     if (!value) {
2100:       PetscCall(PetscViewerASCIIPrintf(viewer, "Removing option: %s\n", name));
2101:     } else if (!value[0]) {
2102:       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2103:     } else {
2104:       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2105:     }
2106:   } else {
2107:     MPI_Comm comm = PETSC_COMM_WORLD;
2108:     if (!value) {
2109:       PetscCall(PetscPrintf(comm, "Removing option: %s\n", name));
2110:     } else if (!value[0]) {
2111:       PetscCall(PetscPrintf(comm, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2112:     } else {
2113:       PetscCall(PetscPrintf(comm, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2114:     }
2115:   }
2116:   PetscFunctionReturn(PETSC_SUCCESS);
2117: }

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

2123:   Not Collective

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

2131:   Calling sequence of `monitor`:
2132: + name   - option name string
2133: . value  - option value string, a value of `NULL` indicates the option is being removed from the database. A value
2134:            of "" indicates the option is in the database but has no value.
2135: . source - option source
2136: - mctx   - optional monitoring context, as set by `PetscOptionsMonitorSet()`

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

2142:   Level: intermediate

2144:   Notes:
2145:   See `PetscInitialize()` for options related to option database monitoring.

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

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

2155: .seealso: `PetscOptionsMonitorDefault()`, `PetscInitialize()`, `PetscCtxDestroyFn`
2156: @*/
2157: PetscErrorCode PetscOptionsMonitorSet(PetscErrorCode (*monitor)(const char name[], const char value[], PetscOptionSource source, PetscCtx mctx), PetscCtx mctx, PetscCtxDestroyFn *monitordestroy)
2158: {
2159:   PetscOptions options = defaultoptions;

2161:   PetscFunctionBegin;
2162:   if (options->monitorCancel) PetscFunctionReturn(PETSC_SUCCESS);
2163:   PetscCheck(options->numbermonitors < MAXOPTIONSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptions monitors set");
2164:   options->monitor[options->numbermonitors]          = monitor;
2165:   options->monitordestroy[options->numbermonitors]   = monitordestroy;
2166:   options->monitorcontext[options->numbermonitors++] = mctx;
2167:   PetscFunctionReturn(PETSC_SUCCESS);
2168: }

2170: /*@
2171:   PetscOptionsStringToBool - Converts a string to a `PetscBool`

2173:   Not Collective

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

2178:   Output Parameter:
2179: . a - the resulting `PetscBool`

2181:   Level: developer

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

2187: .seealso: `PetscOptionsStringToInt()`, `PetscOptionsStringToReal()`, `PetscOptionsStringToScalar()`, `PetscOptionsGetBool()`
2188: @*/
2189: PetscErrorCode PetscOptionsStringToBool(const char value[], PetscBool *a)
2190: {
2191:   PetscBool istrue, isfalse;
2192:   size_t    len;

2194:   PetscFunctionBegin;
2195:   /* PetscStrlen() returns 0 for NULL or "" */
2196:   PetscCall(PetscStrlen(value, &len));
2197:   if (!len) {
2198:     *a = PETSC_TRUE;
2199:     PetscFunctionReturn(PETSC_SUCCESS);
2200:   }
2201:   PetscCall(PetscStrcasecmp(value, "TRUE", &istrue));
2202:   if (istrue) {
2203:     *a = PETSC_TRUE;
2204:     PetscFunctionReturn(PETSC_SUCCESS);
2205:   }
2206:   PetscCall(PetscStrcasecmp(value, "YES", &istrue));
2207:   if (istrue) {
2208:     *a = PETSC_TRUE;
2209:     PetscFunctionReturn(PETSC_SUCCESS);
2210:   }
2211:   PetscCall(PetscStrcasecmp(value, "1", &istrue));
2212:   if (istrue) {
2213:     *a = PETSC_TRUE;
2214:     PetscFunctionReturn(PETSC_SUCCESS);
2215:   }
2216:   PetscCall(PetscStrcasecmp(value, "on", &istrue));
2217:   if (istrue) {
2218:     *a = PETSC_TRUE;
2219:     PetscFunctionReturn(PETSC_SUCCESS);
2220:   }
2221:   PetscCall(PetscStrcasecmp(value, "FALSE", &isfalse));
2222:   if (isfalse) {
2223:     *a = PETSC_FALSE;
2224:     PetscFunctionReturn(PETSC_SUCCESS);
2225:   }
2226:   PetscCall(PetscStrcasecmp(value, "NO", &isfalse));
2227:   if (isfalse) {
2228:     *a = PETSC_FALSE;
2229:     PetscFunctionReturn(PETSC_SUCCESS);
2230:   }
2231:   PetscCall(PetscStrcasecmp(value, "0", &isfalse));
2232:   if (isfalse) {
2233:     *a = PETSC_FALSE;
2234:     PetscFunctionReturn(PETSC_SUCCESS);
2235:   }
2236:   PetscCall(PetscStrcasecmp(value, "off", &isfalse));
2237:   if (isfalse) {
2238:     *a = PETSC_FALSE;
2239:     PetscFunctionReturn(PETSC_SUCCESS);
2240:   }
2241:   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown logical value: %s", value);
2242: }

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

2247:   Not Collective

2249:   Input Parameter:
2250: . name - the string to convert

2252:   Output Parameter:
2253: . a - the resulting `PetscInt` value

2255:   Level: developer

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

2261: .seealso: `PetscOptionsStringToReal()`, `PetscOptionsStringToScalar()`, `PetscOptionsStringToBool()`, `PetscOptionsGetInt()`
2262: @*/
2263: PetscErrorCode PetscOptionsStringToInt(const char name[], PetscInt *a)
2264: {
2265:   size_t    len;
2266:   PetscBool decide, tdefault, mouse, unlimited;

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

2272:   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &tdefault));
2273:   if (!tdefault) PetscCall(PetscStrcasecmp(name, "DEFAULT", &tdefault));
2274:   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &decide));
2275:   if (!decide) PetscCall(PetscStrcasecmp(name, "DECIDE", &decide));
2276:   if (!decide) PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &decide));
2277:   if (!decide) PetscCall(PetscStrcasecmp(name, "DETERMINE", &decide));
2278:   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &unlimited));
2279:   if (!unlimited) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &unlimited));
2280:   PetscCall(PetscStrcasecmp(name, "mouse", &mouse));

2282:   if (tdefault) *a = PETSC_DEFAULT;
2283:   else if (decide) *a = PETSC_DECIDE;
2284:   else if (unlimited) *a = PETSC_UNLIMITED;
2285:   else if (mouse) *a = -1;
2286:   else {
2287:     char *endptr;
2288:     long  strtolval;

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

2293: #if defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE_ATOLL)
2294:     (void)strtolval;
2295:     *a = atoll(name);
2296: #elif defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE___INT64)
2297:     (void)strtolval;
2298:     *a = _atoi64(name);
2299: #else
2300:     *a = (PetscInt)strtolval;
2301: #endif
2302:   }
2303:   PetscFunctionReturn(PETSC_SUCCESS);
2304: }

2306: #if defined(PETSC_USE_REAL___FLOAT128)
2307:   #include <quadmath.h>
2308: #endif

2310: static PetscErrorCode PetscStrtod(const char name[], PetscReal *a, char **endptr)
2311: {
2312:   PetscFunctionBegin;
2313: #if defined(PETSC_USE_REAL___FLOAT128)
2314:   *a = strtoflt128(name, endptr);
2315: #else
2316:   *a = (PetscReal)strtod(name, endptr);
2317: #endif
2318:   PetscFunctionReturn(PETSC_SUCCESS);
2319: }

2321: static PetscErrorCode PetscStrtoz(const char name[], PetscScalar *a, char **endptr, PetscBool *isImaginary)
2322: {
2323:   PetscBool hasi = PETSC_FALSE;
2324:   char     *ptr;
2325:   PetscReal strtoval;

2327:   PetscFunctionBegin;
2328:   PetscCall(PetscStrtod(name, &strtoval, &ptr));
2329:   if (ptr == name) {
2330:     strtoval = 1.;
2331:     hasi     = PETSC_TRUE;
2332:     if (name[0] == 'i') {
2333:       ptr++;
2334:     } else if (name[0] == '+' && name[1] == 'i') {
2335:       ptr += 2;
2336:     } else if (name[0] == '-' && name[1] == 'i') {
2337:       strtoval = -1.;
2338:       ptr += 2;
2339:     }
2340:   } else if (*ptr == 'i') {
2341:     hasi = PETSC_TRUE;
2342:     ptr++;
2343:   }
2344:   *endptr      = ptr;
2345:   *isImaginary = hasi;
2346:   if (hasi) {
2347: #if !defined(PETSC_USE_COMPLEX)
2348:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s contains imaginary but complex not supported ", name);
2349: #else
2350:     *a = PetscCMPLX(0., strtoval);
2351: #endif
2352:   } else {
2353:     *a = strtoval;
2354:   }
2355:   PetscFunctionReturn(PETSC_SUCCESS);
2356: }

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

2361:   Not Collective

2363:   Input Parameter:
2364: . name - the string to convert

2366:   Output Parameter:
2367: . a - the resulting `PetscReal` value

2369:   Level: developer

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

2375: .seealso: `PetscOptionsStringToInt()`, `PetscOptionsStringToScalar()`, `PetscOptionsStringToBool()`, `PetscOptionsGetReal()`
2376: @*/
2377: PetscErrorCode PetscOptionsStringToReal(const char name[], PetscReal *a)
2378: {
2379:   size_t    len;
2380:   PetscBool match;
2381:   char     *endptr;

2383:   PetscFunctionBegin;
2384:   PetscCall(PetscStrlen(name, &len));
2385:   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "String of length zero has no numerical value");

2387:   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &match));
2388:   if (!match) PetscCall(PetscStrcasecmp(name, "DEFAULT", &match));
2389:   if (match) {
2390:     *a = PETSC_DEFAULT;
2391:     PetscFunctionReturn(PETSC_SUCCESS);
2392:   }

2394:   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &match));
2395:   if (!match) PetscCall(PetscStrcasecmp(name, "DECIDE", &match));
2396:   if (match) {
2397:     *a = PETSC_DECIDE;
2398:     PetscFunctionReturn(PETSC_SUCCESS);
2399:   }

2401:   PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &match));
2402:   if (!match) PetscCall(PetscStrcasecmp(name, "DETERMINE", &match));
2403:   if (match) {
2404:     *a = PETSC_DETERMINE;
2405:     PetscFunctionReturn(PETSC_SUCCESS);
2406:   }

2408:   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &match));
2409:   if (!match) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &match));
2410:   if (match) {
2411:     *a = PETSC_UNLIMITED;
2412:     PetscFunctionReturn(PETSC_SUCCESS);
2413:   }

2415:   PetscCall(PetscStrtod(name, a, &endptr));
2416:   PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value", name);
2417:   PetscFunctionReturn(PETSC_SUCCESS);
2418: }

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

2423:   Not Collective

2425:   Input Parameter:
2426: . name - the string to convert

2428:   Output Parameter:
2429: . a - the resulting `PetscScalar` value

2431:   Level: developer

2433:   Note:
2434:   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.

2436: .seealso: `PetscOptionsStringToInt()`, `PetscOptionsStringToReal()`, `PetscOptionsStringToBool()`, `PetscOptionsGetScalar()`
2437: @*/
2438: PetscErrorCode PetscOptionsStringToScalar(const char name[], PetscScalar *a)
2439: {
2440:   PetscBool   imag1;
2441:   size_t      len;
2442:   PetscScalar val = 0.;
2443:   char       *ptr = NULL;

2445:   PetscFunctionBegin;
2446:   PetscCall(PetscStrlen(name, &len));
2447:   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2448:   PetscCall(PetscStrtoz(name, &val, &ptr, &imag1));
2449: #if defined(PETSC_USE_COMPLEX)
2450:   if ((size_t)(ptr - name) < len) {
2451:     PetscBool   imag2;
2452:     PetscScalar val2;

2454:     PetscCall(PetscStrtoz(ptr, &val2, &ptr, &imag2));
2455:     if (imag1) PetscCheck(imag2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s: must specify imaginary component second", name);
2456:     val = PetscCMPLX(PetscRealPart(val), PetscImaginaryPart(val2));
2457:   }
2458: #endif
2459:   PetscCheck((size_t)(ptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value ", name);
2460:   *a = val;
2461:   PetscFunctionReturn(PETSC_SUCCESS);
2462: }

2464: /*@C
2465:   PetscOptionsGetBool - Gets the Logical (true or false) value for a particular
2466:   option in the database.

2468:   Not Collective

2470:   Input Parameters:
2471: + options - options database, use `NULL` for default global database
2472: . pre     - the string to prepend to the name or `NULL`
2473: - name    - the option one is seeking

2475:   Output Parameters:
2476: + ivalue - the logical value to return
2477: - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`

2479:   Level: beginner

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

2485:   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`
2486:   is equivalent to `-requested_bool true`

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

2491: .seealso: `PetscOptionsGetBool3()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2492:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2493:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2494:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2495:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2496:           `PetscOptionsFList()`, `PetscOptionsEList()`
2497: @*/
2498: PetscErrorCode PetscOptionsGetBool(PetscOptions options, const char pre[], const char name[], PetscBool *ivalue, PetscBool *set)
2499: {
2500:   const char *value;
2501:   PetscBool   flag;

2503:   PetscFunctionBegin;
2504:   PetscAssertPointer(name, 3);
2505:   if (ivalue) PetscAssertPointer(ivalue, 4);
2506:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2507:   if (flag) {
2508:     if (set) *set = PETSC_TRUE;
2509:     PetscCall(PetscOptionsStringToBool(value, &flag));
2510:     if (ivalue) *ivalue = flag;
2511:   } else {
2512:     if (set) *set = PETSC_FALSE;
2513:   }
2514:   PetscFunctionReturn(PETSC_SUCCESS);
2515: }

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

2521:   Not Collective

2523:   Input Parameters:
2524: + options - options database, use `NULL` for default global database
2525: . pre     - the string to prepend to the name or `NULL`
2526: - name    - the option one is seeking

2528:   Output Parameters:
2529: + ivalue - the ternary logical value to return
2530: - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`

2532:   Level: beginner

2534:   Notes:
2535:   TRUE, true, YES, yes, ON, on, nostring and 1 all translate to `PETSC_BOOL3_TRUE`
2536:   FALSE, false, NO, no, OFF, off and 0 all translate to `PETSC_BOOL3_FALSE`
2537:   UNKNOWN, unknown, AUTO and auto all translate to `PETSC_BOOL3_UNKNOWN`

2539:   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`
2540:   is equivalent to `-requested_bool3 true`

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

2545: .seealso: `PetscOptionsGetBool()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2546:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2547:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2548:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2549:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2550:           `PetscOptionsFList()`, `PetscOptionsEList()`
2551: @*/
2552: PetscErrorCode PetscOptionsGetBool3(PetscOptions options, const char pre[], const char name[], PetscBool3 *ivalue, PetscBool *set)
2553: {
2554:   const char *value;
2555:   PetscBool   flag;

2557:   PetscFunctionBegin;
2558:   PetscAssertPointer(name, 3);
2559:   if (ivalue) PetscAssertPointer(ivalue, 4);
2560:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2561:   if (flag) { // found the option
2562:     PetscBool isAUTO = PETSC_FALSE, isUNKNOWN = PETSC_FALSE;

2564:     if (set) *set = PETSC_TRUE;
2565:     PetscCall(PetscStrcasecmp("AUTO", value, &isAUTO));                    // auto or AUTO
2566:     if (!isAUTO) PetscCall(PetscStrcasecmp("UNKNOWN", value, &isUNKNOWN)); // unknown or UNKNOWN
2567:     if (isAUTO || isUNKNOWN) {
2568:       if (ivalue) *ivalue = PETSC_BOOL3_UNKNOWN;
2569:     } else { // handle boolean values (if no value is given, it returns true)
2570:       PetscCall(PetscOptionsStringToBool(value, &flag));
2571:       if (ivalue) *ivalue = PetscBoolToBool3(flag);
2572:     }
2573:   } else {
2574:     if (set) *set = PETSC_FALSE;
2575:   }
2576:   PetscFunctionReturn(PETSC_SUCCESS);
2577: }

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

2582:   Not Collective

2584:   Input Parameters:
2585: + options - options database, use `NULL` for default global database
2586: . pre     - the string to prepend to the name or `NULL`
2587: . opt     - option name
2588: . list    - the possible choices (one of these must be selected, anything else is invalid)
2589: - ntext   - number of choices

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

2595:   Level: intermediate

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

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

2603: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2604:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2605:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2606:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2607:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2608:           `PetscOptionsFList()`, `PetscOptionsEList()`
2609: @*/
2610: PetscErrorCode PetscOptionsGetEList(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscInt ntext, PetscInt *value, PetscBool *set)
2611: {
2612:   size_t    alen, len = 0, tlen = 0;
2613:   char     *svalue;
2614:   PetscBool aset, flg = PETSC_FALSE;
2615:   PetscInt  i;

2617:   PetscFunctionBegin;
2618:   PetscAssertPointer(opt, 3);
2619:   for (i = 0; i < ntext; i++) {
2620:     PetscCall(PetscStrlen(list[i], &alen));
2621:     if (alen > len) len = alen;
2622:     tlen += len + 1;
2623:   }
2624:   len += 5; /* a little extra space for user mistypes */
2625:   PetscCall(PetscMalloc1(len, &svalue));
2626:   PetscCall(PetscOptionsGetString(options, pre, opt, svalue, len, &aset));
2627:   if (aset) {
2628:     PetscCall(PetscEListFind(ntext, list, svalue, value, &flg));
2629:     if (!flg) {
2630:       char *avail;

2632:       PetscCall(PetscMalloc1(tlen, &avail));
2633:       avail[0] = '\0';
2634:       for (i = 0; i < ntext; i++) {
2635:         PetscCall(PetscStrlcat(avail, list[i], tlen));
2636:         PetscCall(PetscStrlcat(avail, " ", tlen));
2637:       }
2638:       PetscCall(PetscStrtolower(avail));
2639:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown option \"%s\" for -%s%s. Available options: %s", svalue, pre ? pre : "", opt + 1, avail);
2640:     }
2641:     if (set) *set = PETSC_TRUE;
2642:   } else if (set) *set = PETSC_FALSE;
2643:   PetscCall(PetscFree(svalue));
2644:   PetscFunctionReturn(PETSC_SUCCESS);
2645: }

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

2650:   Not Collective

2652:   Input Parameters:
2653: + options - options database, use `NULL` for default global database
2654: . pre     - option prefix or `NULL`
2655: . opt     - option name
2656: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

2658:   Output Parameters:
2659: + value - the value to return
2660: - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`

2662:   Level: beginner

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

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

2670: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2671:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2672:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2673:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2674:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2675:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2676:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2677: @*/
2678: PetscErrorCode PetscOptionsGetEnum(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscEnum *value, PetscBool *set) PeNSS
2679: {
2680:   PetscInt  ntext = 0, tval;
2681:   PetscBool fset;

2683:   PetscFunctionBegin;
2684:   PetscAssertPointer(opt, 3);
2685:   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");
2686:   PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
2687:   ntext -= 3;
2688:   PetscCall(PetscOptionsGetEList(options, pre, opt, list, ntext, &tval, &fset));
2689:   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
2690:   if (fset) *value = (PetscEnum)tval;
2691:   if (set) *set = fset;
2692:   PetscFunctionReturn(PETSC_SUCCESS);
2693: }

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

2698:   Not Collective

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

2705:   Output Parameters:
2706: + ivalue - the integer value to return
2707: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2709:   Level: beginner

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

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

2717:   Accepts the deprecated value `default`.

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

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

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

2752:   Not Collective

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

2759:   Output Parameters:
2760: + ivalue - the MPI integer value to return
2761: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2763:   Level: beginner

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

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

2771:   Accepts the deprecated value `default`.

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

2786:   PetscFunctionBegin;
2787:   PetscCall(PetscOptionsGetInt(options, pre, name, &value, &flag));
2788:   if (flag) PetscCall(PetscMPIIntCast(value, ivalue));
2789:   if (set) *set = flag;
2790:   PetscFunctionReturn(PETSC_SUCCESS);
2791: }

2793: /*@C
2794:   PetscOptionsGetReal - Gets the double precision value for a particular
2795:   option in the database.

2797:   Not Collective

2799:   Input Parameters:
2800: + options - options database, use `NULL` for default global database
2801: . pre     - string to prepend to each name or `NULL`
2802: - name    - the option one is seeking

2804:   Output Parameters:
2805: + dvalue - the double value to return
2806: - set    - `PETSC_TRUE` if found, `PETSC_FALSE` if not found

2808:   Level: beginner

2810:   Notes:
2811:   Accepts the special values `determine`, `decide` and `unlimited`.

2813:   Accepts the deprecated value `default`

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

2818: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2819:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2820:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2821:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2822:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2823:           `PetscOptionsFList()`, `PetscOptionsEList()`
2824: @*/
2825: PetscErrorCode PetscOptionsGetReal(PetscOptions options, const char pre[], const char name[], PetscReal *dvalue, PetscBool *set)
2826: {
2827:   const char *value;
2828:   PetscBool   flag;

2830:   PetscFunctionBegin;
2831:   PetscAssertPointer(name, 3);
2832:   PetscAssertPointer(dvalue, 4);
2833:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2834:   if (flag) {
2835:     if (!value) {
2836:       if (set) *set = PETSC_FALSE;
2837:     } else {
2838:       if (set) *set = PETSC_TRUE;
2839:       PetscCall(PetscOptionsStringToReal(value, dvalue));
2840:     }
2841:   } else {
2842:     if (set) *set = PETSC_FALSE;
2843:   }
2844:   PetscFunctionReturn(PETSC_SUCCESS);
2845: }

2847: /*@C
2848:   PetscOptionsGetScalar - Gets the scalar value for a particular
2849:   option in the database.

2851:   Not Collective

2853:   Input Parameters:
2854: + options - options database, use `NULL` for default global database
2855: . pre     - string to prepend to each name or `NULL`
2856: - name    - the option one is seeking

2858:   Output Parameters:
2859: + dvalue - the scalar value to return
2860: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2862:   Level: beginner

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

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

2871: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2872:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2873:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2874:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2875:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2876:           `PetscOptionsFList()`, `PetscOptionsEList()`
2877: @*/
2878: PetscErrorCode PetscOptionsGetScalar(PetscOptions options, const char pre[], const char name[], PetscScalar *dvalue, PetscBool *set)
2879: {
2880:   const char *value;
2881:   PetscBool   flag;

2883:   PetscFunctionBegin;
2884:   PetscAssertPointer(name, 3);
2885:   PetscAssertPointer(dvalue, 4);
2886:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2887:   if (flag) {
2888:     if (!value) {
2889:       if (set) *set = PETSC_FALSE;
2890:     } else {
2891: #if !defined(PETSC_USE_COMPLEX)
2892:       PetscCall(PetscOptionsStringToReal(value, dvalue));
2893: #else
2894:       PetscCall(PetscOptionsStringToScalar(value, dvalue));
2895: #endif
2896:       if (set) *set = PETSC_TRUE;
2897:     }
2898:   } else { /* flag */
2899:     if (set) *set = PETSC_FALSE;
2900:   }
2901:   PetscFunctionReturn(PETSC_SUCCESS);
2902: }

2904: /*@C
2905:   PetscOptionsGetString - Gets the string value for a particular option in
2906:   the database.

2908:   Not Collective

2910:   Input Parameters:
2911: + options - options database, use `NULL` for default global database
2912: . pre     - string to prepend to name or `NULL`
2913: . name    - the option one is seeking
2914: - len     - maximum length of the string including null termination

2916:   Output Parameters:
2917: + string - location to copy string
2918: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2920:   Level: beginner

2922:   Note:
2923:   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`

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

2928:   Fortran Notes:
2929:   The Fortran interface is slightly different from the C/C++
2930:   interface.  Sample usage in Fortran follows
2931: .vb
2932:       character *20    string
2933:       PetscErrorCode   ierr
2934:       PetscBool        set
2935:       call PetscOptionsGetString(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-s',string,set,ierr)
2936: .ve

2938: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2939:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2940:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2941:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2942:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2943:           `PetscOptionsFList()`, `PetscOptionsEList()`
2944: @*/
2945: PetscErrorCode PetscOptionsGetString(PetscOptions options, const char pre[], const char name[], char string[], size_t len, PetscBool *set) PeNS
2946: {
2947:   const char *value;
2948:   PetscBool   flag;

2950:   PetscFunctionBegin;
2951:   PetscAssertPointer(name, 3);
2952:   PetscAssertPointer(string, 4);
2953:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2954:   if (!flag) {
2955:     if (set) *set = PETSC_FALSE;
2956:   } else {
2957:     if (set) *set = PETSC_TRUE;
2958:     if (value) PetscCall(PetscStrncpy(string, value, len));
2959:     else PetscCall(PetscArrayzero(string, len));
2960:   }
2961:   PetscFunctionReturn(PETSC_SUCCESS);
2962: }

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

2968:   Not Collective

2970:   Input Parameters:
2971: + options - options database, use `NULL` for default global database
2972: . pre     - string to prepend to each name or `NULL`
2973: - name    - the option one is seeking

2975:   Output Parameters:
2976: + dvalue - the Boolean values to return
2977: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2978: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2980:   Level: beginner

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

2985: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2986:           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2987:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2988:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2989:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2990:           `PetscOptionsFList()`, `PetscOptionsEList()`
2991: @*/
2992: PetscErrorCode PetscOptionsGetBoolArray(PetscOptions options, const char pre[], const char name[], PetscBool dvalue[], PetscInt *nmax, PetscBool *set)
2993: {
2994:   const char *svalue;
2995:   const char *value;
2996:   PetscInt    n = 0;
2997:   PetscBool   flag;
2998:   PetscToken  token;

3000:   PetscFunctionBegin;
3001:   PetscAssertPointer(name, 3);
3002:   PetscAssertPointer(nmax, 5);
3003:   if (*nmax) PetscAssertPointer(dvalue, 4);

3005:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3006:   if (!flag || !svalue) {
3007:     if (set) *set = PETSC_FALSE;
3008:     *nmax = 0;
3009:     PetscFunctionReturn(PETSC_SUCCESS);
3010:   }
3011:   if (set) *set = PETSC_TRUE;
3012:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3013:   PetscCall(PetscTokenFind(token, &value));
3014:   while (value && n < *nmax) {
3015:     PetscCall(PetscOptionsStringToBool(value, dvalue));
3016:     PetscCall(PetscTokenFind(token, &value));
3017:     dvalue++;
3018:     n++;
3019:   }
3020:   PetscCall(PetscTokenDestroy(&token));
3021:   *nmax = n;
3022:   PetscFunctionReturn(PETSC_SUCCESS);
3023: }

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

3028:   Not Collective

3030:   Input Parameters:
3031: + options - options database, use `NULL` for default global database
3032: . pre     - option prefix or `NULL`
3033: . name    - option name
3034: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

3036:   Output Parameters:
3037: + ivalue - the  enum values to return
3038: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3039: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3041:   Level: beginner

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

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

3048: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
3049:           `PetscOptionsGetEnum()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3050:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsName()`,
3051:           `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, `PetscOptionsStringArray()`, `PetscOptionsRealArray()`,
3052:           `PetscOptionsScalar()`, `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3053:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
3054: @*/
3055: PetscErrorCode PetscOptionsGetEnumArray(PetscOptions options, const char pre[], const char name[], const char *const list[], PetscEnum ivalue[], PetscInt *nmax, PetscBool *set)
3056: {
3057:   const char *svalue;
3058:   const char *value;
3059:   PetscInt    n = 0;
3060:   PetscEnum   evalue;
3061:   PetscBool   flag;
3062:   PetscToken  token;

3064:   PetscFunctionBegin;
3065:   PetscAssertPointer(name, 3);
3066:   PetscAssertPointer(list, 4);
3067:   PetscAssertPointer(nmax, 6);
3068:   if (*nmax) PetscAssertPointer(ivalue, 5);

3070:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3071:   if (!flag || !svalue) {
3072:     if (set) *set = PETSC_FALSE;
3073:     *nmax = 0;
3074:     PetscFunctionReturn(PETSC_SUCCESS);
3075:   }
3076:   if (set) *set = PETSC_TRUE;
3077:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3078:   PetscCall(PetscTokenFind(token, &value));
3079:   while (value && n < *nmax) {
3080:     PetscCall(PetscEnumFind(list, value, &evalue, &flag));
3081:     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown enum value '%s' for -%s%s", svalue, pre ? pre : "", name + 1);
3082:     ivalue[n++] = evalue;
3083:     PetscCall(PetscTokenFind(token, &value));
3084:   }
3085:   PetscCall(PetscTokenDestroy(&token));
3086:   *nmax = n;
3087:   PetscFunctionReturn(PETSC_SUCCESS);
3088: }

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

3093:   Not Collective

3095:   Input Parameters:
3096: + options - options database, use `NULL` for default global database
3097: . pre     - string to prepend to each name or `NULL`
3098: - name    - the option one is seeking

3100:   Output Parameters:
3101: + ivalue - the integer values to return
3102: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3103: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3105:   Level: beginner

3107:   Notes:
3108:   The array can be passed as
3109: +  a comma separated list -                                 0,1,2,3,4,5,6,7
3110: .  a range (start\-end+1) -                                 0-8
3111: .  a range with given increment (start\-end+1:inc) -        0-7:2
3112: -  a combination of values and ranges separated by commas - 0,1-8,8-15:2

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

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

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

3137:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3138:   if (!flag || !svalue) {
3139:     if (set) *set = PETSC_FALSE;
3140:     *nmax = 0;
3141:     PetscFunctionReturn(PETSC_SUCCESS);
3142:   }
3143:   if (set) *set = PETSC_TRUE;
3144:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3145:   PetscCall(PetscTokenFind(token, &value));
3146:   while (value && n < *nmax) {
3147:     char *iivalue;

3149:     /* look for form  d-D where d and D are integers */
3150:     PetscCall(PetscStrallocpy(value, &iivalue));
3151:     foundrange = PETSC_FALSE;
3152:     PetscCall(PetscStrlen(iivalue, &len));
3153:     if (iivalue[0] == '-') i = 2;
3154:     else i = 1;
3155:     for (; i < (int)len; i++) {
3156:       if (iivalue[i] == '-') {
3157:         PetscCheck(i != (int)len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, iivalue);
3158:         iivalue[i] = 0;

3160:         PetscCall(PetscOptionsStringToInt(iivalue, &start));
3161:         inc = 1;
3162:         j   = i + 1;
3163:         for (; j < (int)len; j++) {
3164:           if (iivalue[j] == ':') {
3165:             iivalue[j] = 0;

3167:             PetscCall(PetscOptionsStringToInt(iivalue + j + 1, &inc));
3168:             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);
3169:             break;
3170:           }
3171:         }
3172:         PetscCall(PetscOptionsStringToInt(iivalue + i + 1, &end));
3173:         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);
3174:         nvalues = (end - start) / inc + (end - start) % inc;
3175:         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);
3176:         for (; start < end; start += inc) {
3177:           *ivalue = start;
3178:           ivalue++;
3179:           n++;
3180:         }
3181:         foundrange = PETSC_TRUE;
3182:         break;
3183:       }
3184:     }
3185:     if (!foundrange) {
3186:       PetscCall(PetscOptionsStringToInt(value, ivalue));
3187:       ivalue++;
3188:       n++;
3189:     }
3190:     PetscCall(PetscFree(iivalue));
3191:     PetscCall(PetscTokenFind(token, &value));
3192:   }
3193:   PetscCall(PetscTokenDestroy(&token));
3194:   *nmax = n;
3195:   PetscFunctionReturn(PETSC_SUCCESS);
3196: }

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

3202:   Not Collective

3204:   Input Parameters:
3205: + options - options database, use `NULL` for default global database
3206: . pre     - string to prepend to each name or `NULL`
3207: - name    - the option one is seeking

3209:   Output Parameters:
3210: + dvalue - the double values to return
3211: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3212: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3214:   Level: beginner

3216: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3217:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3218:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3219:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3220:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3221:           `PetscOptionsFList()`, `PetscOptionsEList()`
3222: @*/
3223: PetscErrorCode PetscOptionsGetRealArray(PetscOptions options, const char pre[], const char name[], PetscReal dvalue[], PetscInt *nmax, PetscBool *set)
3224: {
3225:   const char *svalue;
3226:   const char *value;
3227:   PetscInt    n = 0;
3228:   PetscBool   flag;
3229:   PetscToken  token;

3231:   PetscFunctionBegin;
3232:   PetscAssertPointer(name, 3);
3233:   PetscAssertPointer(nmax, 5);
3234:   if (*nmax) PetscAssertPointer(dvalue, 4);

3236:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3237:   if (!flag || !svalue) {
3238:     if (set) *set = PETSC_FALSE;
3239:     *nmax = 0;
3240:     PetscFunctionReturn(PETSC_SUCCESS);
3241:   }
3242:   if (set) *set = PETSC_TRUE;
3243:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3244:   PetscCall(PetscTokenFind(token, &value));
3245:   while (value && n < *nmax) {
3246:     PetscCall(PetscOptionsStringToReal(value, dvalue++));
3247:     PetscCall(PetscTokenFind(token, &value));
3248:     n++;
3249:   }
3250:   PetscCall(PetscTokenDestroy(&token));
3251:   *nmax = n;
3252:   PetscFunctionReturn(PETSC_SUCCESS);
3253: }

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

3259:   Not Collective

3261:   Input Parameters:
3262: + options - options database, use `NULL` for default global database
3263: . pre     - string to prepend to each name or `NULL`
3264: - name    - the option one is seeking

3266:   Output Parameters:
3267: + dvalue - the scalar values to return
3268: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3269: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3271:   Level: beginner

3273: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3274:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3275:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3276:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3277:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3278:           `PetscOptionsFList()`, `PetscOptionsEList()`
3279: @*/
3280: PetscErrorCode PetscOptionsGetScalarArray(PetscOptions options, const char pre[], const char name[], PetscScalar dvalue[], PetscInt *nmax, PetscBool *set)
3281: {
3282:   const char *svalue;
3283:   const char *value;
3284:   PetscInt    n = 0;
3285:   PetscBool   flag;
3286:   PetscToken  token;

3288:   PetscFunctionBegin;
3289:   PetscAssertPointer(name, 3);
3290:   PetscAssertPointer(nmax, 5);
3291:   if (*nmax) PetscAssertPointer(dvalue, 4);

3293:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3294:   if (!flag || !svalue) {
3295:     if (set) *set = PETSC_FALSE;
3296:     *nmax = 0;
3297:     PetscFunctionReturn(PETSC_SUCCESS);
3298:   }
3299:   if (set) *set = PETSC_TRUE;
3300:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3301:   PetscCall(PetscTokenFind(token, &value));
3302:   while (value && n < *nmax) {
3303:     PetscCall(PetscOptionsStringToScalar(value, dvalue++));
3304:     PetscCall(PetscTokenFind(token, &value));
3305:     n++;
3306:   }
3307:   PetscCall(PetscTokenDestroy(&token));
3308:   *nmax = n;
3309:   PetscFunctionReturn(PETSC_SUCCESS);
3310: }

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

3316:   Not Collective; No Fortran Support

3318:   Input Parameters:
3319: + options - options database, use `NULL` for default global database
3320: . pre     - string to prepend to name or `NULL`
3321: - name    - the option one is seeking

3323:   Output Parameters:
3324: + strings - location to copy strings
3325: . nmax    - On input maximum number of strings, on output the actual number of strings found
3326: - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`

3328:   Level: beginner

3330:   Notes:
3331:   The `nmax` parameter is used for both input and output.

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

3336:   The user is responsible for deallocating the strings that are
3337:   returned.

3339: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
3340:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3341:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3342:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3343:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3344:           `PetscOptionsFList()`, `PetscOptionsEList()`
3345: @*/
3346: PetscErrorCode PetscOptionsGetStringArray(PetscOptions options, const char pre[], const char name[], char *strings[], PetscInt *nmax, PetscBool *set) PeNS
3347: {
3348:   const char *svalue;
3349:   const char *value;
3350:   PetscInt    n = 0;
3351:   PetscBool   flag;
3352:   PetscToken  token;

3354:   PetscFunctionBegin;
3355:   PetscAssertPointer(name, 3);
3356:   PetscAssertPointer(nmax, 5);
3357:   if (*nmax) PetscAssertPointer(strings, 4);

3359:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3360:   if (!flag || !svalue) {
3361:     if (set) *set = PETSC_FALSE;
3362:     *nmax = 0;
3363:     PetscFunctionReturn(PETSC_SUCCESS);
3364:   }
3365:   if (set) *set = PETSC_TRUE;
3366:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3367:   PetscCall(PetscTokenFind(token, &value));
3368:   while (value && n < *nmax) {
3369:     PetscCall(PetscStrallocpy(value, &strings[n]));
3370:     PetscCall(PetscTokenFind(token, &value));
3371:     n++;
3372:   }
3373:   PetscCall(PetscTokenDestroy(&token));
3374:   *nmax = n;
3375:   PetscFunctionReturn(PETSC_SUCCESS);
3376: }

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

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

3383:   Logically Collective

3385:   Input Parameters:
3386: + PetscOptionsObject - string to prepend to name or `NULL`
3387: . oldname            - the old, deprecated option
3388: . newname            - the new option, or `NULL` if option is purely removed
3389: . version            - a string describing the version of first deprecation, e.g. "3.9"
3390: - info               - additional information string, or `NULL`.

3392:   Options Database Key:
3393: . -options_suppress_deprecated_warnings - do not print deprecation warnings

3395:   Level: developer

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

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

3404:   Must be called between `PetscOptionsBegin()` (or `PetscObjectOptionsBegin()`) and `PetscOptionsEnd()`.
3405:   Only the process of rank zero that owns the `PetscOptionsItems` are argument (managed by `PetscOptionsBegin()` or
3406:   `PetscObjectOptionsBegin()` prints the information
3407:   If newname is provided, the old option is replaced. Otherwise, it remains
3408:   in the options database.
3409:   If an option is not replaced, the info argument should be used to advise the user
3410:   on how to proceed.
3411:   There is a limit on the length of the warning printed, so very long strings
3412:   provided as info may be truncated.

3414: .seealso: `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsScalar()`, `PetscOptionsBool()`, `PetscOptionsString()`, `PetscOptionsSetValue()`
3415: @*/
3416: PetscErrorCode PetscOptionsDeprecated_Private(PetscOptionItems PetscOptionsObject, const char oldname[], const char newname[], const char version[], const char info[])
3417: {
3418:   PetscBool         found, quiet;
3419:   const char       *value;
3420:   const char *const quietopt = "-options_suppress_deprecated_warnings";
3421:   char              msg[4096];
3422:   char             *prefix  = NULL;
3423:   PetscOptions      options = NULL;
3424:   MPI_Comm          comm    = PETSC_COMM_SELF;

3426:   PetscFunctionBegin;
3427:   PetscAssertPointer(oldname, 2);
3428:   PetscAssertPointer(version, 4);
3429:   if (PetscOptionsObject) {
3430:     prefix  = PetscOptionsObject->prefix;
3431:     options = PetscOptionsObject->options;
3432:     comm    = PetscOptionsObject->comm;
3433:   }
3434:   PetscCall(PetscOptionsFindPair(options, prefix, oldname, &value, &found));
3435:   if (found) {
3436:     if (newname) {
3437:       PetscBool newfound;

3439:       /* do not overwrite if the new option has been provided */
3440:       PetscCall(PetscOptionsFindPair(options, prefix, newname, NULL, &newfound));
3441:       if (!newfound) {
3442:         if (prefix) PetscCall(PetscOptionsPrefixPush(options, prefix));
3443:         PetscCall(PetscOptionsSetValue(options, newname, value));
3444:         if (prefix) PetscCall(PetscOptionsPrefixPop(options));
3445:       }
3446:       PetscCall(PetscOptionsClearValue(options, oldname));
3447:     }
3448:     quiet = PETSC_FALSE;
3449:     PetscCall(PetscOptionsGetBool(options, NULL, quietopt, &quiet, NULL));
3450:     if (!quiet) {
3451:       PetscCall(PetscStrncpy(msg, "** PETSc DEPRECATION WARNING ** : the option -", sizeof(msg)));
3452:       PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
3453:       PetscCall(PetscStrlcat(msg, oldname + 1, sizeof(msg)));
3454:       PetscCall(PetscStrlcat(msg, " is deprecated as of version ", sizeof(msg)));
3455:       PetscCall(PetscStrlcat(msg, version, sizeof(msg)));
3456:       PetscCall(PetscStrlcat(msg, " and will be removed in a future release.\n", sizeof(msg)));
3457:       if (newname) {
3458:         PetscCall(PetscStrlcat(msg, "   Use the option -", sizeof(msg)));
3459:         PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
3460:         PetscCall(PetscStrlcat(msg, newname + 1, sizeof(msg)));
3461:         PetscCall(PetscStrlcat(msg, " instead.", sizeof(msg)));
3462:       }
3463:       if (info) {
3464:         PetscCall(PetscStrlcat(msg, " ", sizeof(msg)));
3465:         PetscCall(PetscStrlcat(msg, info, sizeof(msg)));
3466:       }
3467:       PetscCall(PetscStrlcat(msg, " (Silence this warning with ", sizeof(msg)));
3468:       PetscCall(PetscStrlcat(msg, quietopt, sizeof(msg)));
3469:       PetscCall(PetscStrlcat(msg, ")\n", sizeof(msg)));
3470:       PetscCall(PetscPrintf(comm, "%s", msg));
3471:     }
3472:   }
3473:   PetscFunctionReturn(PETSC_SUCCESS);
3474: }