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:   PetscErrorCode (*monitordestroy[MAXOPTIONSMONITORS])(void **);                                        /* 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 (!value) value = "";
128:   if (options->monitorFromOptions) PetscCall(PetscOptionsMonitorDefault(name, value, source, NULL));
129:   for (PetscInt i = 0; i < options->numbermonitors; i++) PetscCall((*options->monitor[i])(name, value, source, options->monitorcontext[i]));
130:   PetscFunctionReturn(PETSC_SUCCESS);
131: }

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

136:   Logically Collective

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

141:   Level: advanced

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

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

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

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

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

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

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

170:   Level: advanced

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

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

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

201:   Logically Collective

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

206:   Level: advanced

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

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

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

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

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

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

235:   Level: advanced

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

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

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

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

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

272:   Not Collective

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

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

280:   Level: intermediate

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

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

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

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

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

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

359:   Logically Collective

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

365:   Level: intermediate

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

372:    Contributed by Boyana Norris

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

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

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

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

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

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

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

471:     PetscCall(PetscStrreplace(PETSC_COMM_SELF, file, fpath, sizeof(fpath)));
472:     PetscCall(PetscFixFilename(fpath, fname));

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

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

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

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

568:   counts[0] = acnt;
569:   counts[1] = cnt;
570:   err       = MPI_Bcast(counts, 2, MPI_INT, 0, comm);
571:   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/");
572:   acnt = counts[0];
573:   cnt  = counts[1];
574:   if (rank) PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
575:   if (acnt || cnt) {
576:     PetscCallMPI(MPI_Bcast(packed, 2 + acnt + cnt, MPI_CHAR, 0, comm));
577:     astring = packed;
578:     vstring = packed + acnt + 1;
579:   }

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

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

597: /*@C
598:   PetscOptionsInsertFile - Inserts options into the database from a file.

600:   Collective

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

610:   Level: developer

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

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

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

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

647:   Logically Collective

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

654:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

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

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

807:   Collective on `PETSC_COMM_WORLD`

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

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

822:   Level: advanced

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

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

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

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

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

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

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

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

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

915: static PetscBool PetscCIOption(const char *name)
916: {
917:   PetscInt  idx;
918:   PetscBool found;

920:   if (!PetscCIEnabled) return PETSC_FALSE;
921:   PetscCallAbort(PETSC_COMM_SELF, PetscEListFind(PETSC_STATIC_ARRAY_LENGTH(PetscCIOptions), PetscCIOptions, name, &idx, &found));
922:   return found;
923: }

925: /*@C
926:   PetscOptionsView - Prints the options that have been loaded. This is
927:   useful for debugging purposes.

929:   Logically Collective

931:   Input Parameters:
932: + options - options database, use `NULL` for default global database
933: - viewer  - must be an `PETSCVIEWERASCII` viewer

935:   Options Database Key:
936: . -options_view - Activates `PetscOptionsView()` within `PetscFinalize()`

938:   Level: advanced

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

944: .seealso: `PetscOptionsAllUsed()`
945: @*/
946: PetscErrorCode PetscOptionsView(PetscOptions options, PetscViewer viewer)
947: {
948:   PetscInt  i, N = 0;
949:   PetscBool isascii;

951:   PetscFunctionBegin;
953:   options = options ? options : defaultoptions;
954:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
955:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
956:   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");

958:   for (i = 0; i < options->N; i++) {
959:     if (PetscCIOption(options->names[i])) continue;
960:     N++;
961:   }

963:   if (!N) {
964:     PetscCall(PetscViewerASCIIPrintf(viewer, "#No PETSc Option Table entries\n"));
965:     PetscFunctionReturn(PETSC_SUCCESS);
966:   }

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

982: /*
983:    Called by error handlers to print options used in run
984: */
985: PetscErrorCode PetscOptionsLeftError(void)
986: {
987:   PetscInt i, nopt = 0;

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

1008: PETSC_EXTERN PetscErrorCode PetscOptionsViewError(void)
1009: {
1010:   PetscInt     i, N = 0;
1011:   PetscOptions options = defaultoptions;

1013:   for (i = 0; i < options->N; i++) {
1014:     if (PetscCIOption(options->names[i])) continue;
1015:     N++;
1016:   }

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

1034: /*@C
1035:   PetscOptionsPrefixPush - Designate a prefix to be used by all options insertions to follow.

1037:   Logically Collective

1039:   Input Parameters:
1040: + options - options database, or `NULL` for the default global database
1041: - prefix  - The string to append to the existing prefix

1043:   Options Database Keys:
1044: + -prefix_push <some_prefix_> - push the given prefix
1045: - -prefix_pop                 - pop the last prefix

1047:   Level: advanced

1049:   Notes:
1050:   It is common to use this in conjunction with `-options_file` as in

1052: $ -prefix_push system1_ -options_file system1rc -prefix_pop -prefix_push system2_ -options_file system2rc -prefix_pop

1054:   where the files no longer require all options to be prefixed with `-system2_`.

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

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

1070:   PetscFunctionBegin;
1071:   PetscAssertPointer(prefix, 2);
1072:   options = options ? options : defaultoptions;
1073:   PetscCheck(options->prefixind < MAXPREFIXES, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum depth of prefix stack %d exceeded, recompile \n src/sys/objects/options.c with larger value for MAXPREFIXES", MAXPREFIXES);
1074:   key[0] = '-'; /* keys must start with '-' */
1075:   PetscCall(PetscStrncpy(key + 1, prefix, sizeof(key) - 1));
1076:   PetscCall(PetscOptionsValidKey(key, &valid));
1077:   if (!valid && options->prefixind > 0 && isdigit((int)prefix[0])) valid = PETSC_TRUE; /* If the prefix stack is not empty, make numbers a valid prefix */
1078:   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" : "");
1079:   start = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1080:   PetscCall(PetscStrlen(prefix, &n));
1081:   PetscCheck(n + 1 <= sizeof(options->prefix) - start, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum prefix length %zu exceeded", sizeof(options->prefix));
1082:   PetscCall(PetscArraycpy(options->prefix + start, prefix, n + 1));
1083:   options->prefixstack[options->prefixind++] = start + n;
1084:   PetscFunctionReturn(PETSC_SUCCESS);
1085: }

1087: /*@C
1088:   PetscOptionsPrefixPop - Remove the latest options prefix, see `PetscOptionsPrefixPush()` for details

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

1092:   Input Parameter:
1093: . options - options database, or `NULL` for the default global database

1095:   Level: advanced

1097: .seealso: `PetscOptionsPrefixPush()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1098: @*/
1099: PetscErrorCode PetscOptionsPrefixPop(PetscOptions options)
1100: {
1101:   PetscInt offset;

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

1112: /*@C
1113:   PetscOptionsClear - Removes all options form the database leaving it empty.

1115:   Logically Collective

1117:   Input Parameter:
1118: . options - options database, use `NULL` for the default global database

1120:   Level: developer

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

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

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

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

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

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

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

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

1177:   Logically Collective

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

1184:   Level: advanced

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

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

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

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

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

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

1244:   Logically Collective

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

1251:   Level: intermediate

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

1401:   Logically Collective

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

1407:   Level: intermediate

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

1415: .seealso: `PetscOptionsInsert()`
1416: @*/
1417: PetscErrorCode PetscOptionsClearValue(PetscOptions options, const char name[])
1418: {
1419:   int    N, n, i;
1420:   char **names;

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

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

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

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

1456:   /* destroy hash table */
1457:   kh_destroy(HO, options->ht);
1458:   options->ht = NULL;

1460:   PetscCall(PetscOptionsMonitor(options, name, NULL, PETSC_OPT_CODE));
1461:   PetscFunctionReturn(PETSC_SUCCESS);
1462: }

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

1467:   Not Collective

1469:   Input Parameters:
1470: + options - options database, use `NULL` for the default global database
1471: . pre     - the string to prepend to the name or `NULL`, this SHOULD NOT have the "-" prepended
1472: - name    - name of option, this SHOULD have the "-" prepended

1474:   Output Parameters:
1475: + value - the option value (optional, not used for all options)
1476: - set   - whether the option is set (optional)

1478:   Level: developer

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

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

1491:   PetscFunctionBegin;
1492:   options = options ? options : defaultoptions;
1493:   PetscCheck(!pre || !PetscUnlikely(pre[0] == '-'), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1494:   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);

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

1498:   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1499:   if (pre && pre[0]) {
1500:     char *ptr = buf;
1501:     if (name[0] == '-') {
1502:       *ptr++ = '-';
1503:       name++;
1504:     }
1505:     PetscCall(PetscStrncpy(ptr, pre, buf + sizeof(buf) - ptr));
1506:     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1507:     name = buf;
1508:   }

1510:   if (PetscDefined(USE_DEBUG)) {
1511:     PetscBool valid;
1512:     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1513:     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1514:     PetscCall(PetscOptionsValidKey(key, &valid));
1515:     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1516:   }

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

1534:   if (usehashtable) { /* fast search */
1535:     khash_t(HO) *ht = options->ht;
1536:     khiter_t     it = kh_get(HO, ht, name);
1537:     if (it != kh_end(ht)) {
1538:       int i            = kh_val(ht, it);
1539:       options->used[i] = PETSC_TRUE;
1540:       if (value) *value = options->values[i];
1541:       if (set) *set = PETSC_TRUE;
1542:       PetscFunctionReturn(PETSC_SUCCESS);
1543:     }
1544:   } else { /* slow search */
1545:     int i, N = options->N;
1546:     for (i = 0; i < N; i++) {
1547:       int result = PetscOptNameCmp(options->names[i], name);
1548:       if (!result) {
1549:         options->used[i] = PETSC_TRUE;
1550:         if (value) *value = options->values[i];
1551:         if (set) *set = PETSC_TRUE;
1552:         PetscFunctionReturn(PETSC_SUCCESS);
1553:       } else if (result > 0) {
1554:         break;
1555:       }
1556:     }
1557:   }

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

1594:   if (set) *set = PETSC_FALSE;
1595:   PetscFunctionReturn(PETSC_SUCCESS);
1596: }

1598: /* Check whether any option begins with pre+name */
1599: PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions options, const char pre[], const char name[], const char *value[], PetscBool *set)
1600: {
1601:   char buf[PETSC_MAX_OPTION_NAME];
1602:   int  numCnt = 0, locs[16], loce[16];

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

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

1611:   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1612:   if (pre && pre[0]) {
1613:     char *ptr = buf;
1614:     if (name[0] == '-') {
1615:       *ptr++ = '-';
1616:       name++;
1617:     }
1618:     PetscCall(PetscStrncpy(ptr, pre, sizeof(buf) - ((ptr == buf) ? 0 : 1)));
1619:     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1620:     name = buf;
1621:   }

1623:   if (PetscDefined(USE_DEBUG)) {
1624:     PetscBool valid;
1625:     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1626:     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1627:     PetscCall(PetscOptionsValidKey(key, &valid));
1628:     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1629:   }

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

1649:   /* slow search */
1650:   for (int c = -1; c < numCnt; ++c) {
1651:     char   opt[PETSC_MAX_OPTION_NAME + 2] = "";
1652:     size_t len;

1654:     if (c < 0) {
1655:       PetscCall(PetscStrncpy(opt, name, sizeof(opt)));
1656:     } else {
1657:       PetscCall(PetscStrncpy(opt, name, PetscMin((size_t)(locs[c] + 1), sizeof(opt))));
1658:       PetscCall(PetscStrlcat(opt, name + loce[c], sizeof(opt) - 1));
1659:     }
1660:     PetscCall(PetscStrlen(opt, &len));
1661:     for (int i = 0; i < options->N; i++) {
1662:       PetscBool match;

1664:       PetscCall(PetscStrncmp(options->names[i], opt, len, &match));
1665:       if (match) {
1666:         options->used[i] = PETSC_TRUE;
1667:         if (value) *value = options->values[i];
1668:         if (set) *set = PETSC_TRUE;
1669:         PetscFunctionReturn(PETSC_SUCCESS);
1670:       }
1671:     }
1672:   }

1674:   if (set) *set = PETSC_FALSE;
1675:   PetscFunctionReturn(PETSC_SUCCESS);
1676: }

1678: /*@C
1679:   PetscOptionsReject - Generates an error if a certain option is given.

1681:   Not Collective

1683:   Input Parameters:
1684: + options - options database, use `NULL` for default global database
1685: . pre     - the option prefix (may be `NULL`)
1686: . name    - the option name one is seeking
1687: - mess    - error message (may be `NULL`)

1689:   Level: advanced

1691: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `OptionsHasName()`,
1692:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1693:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1694:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1695:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1696:           `PetscOptionsFList()`, `PetscOptionsEList()`
1697: @*/
1698: PetscErrorCode PetscOptionsReject(PetscOptions options, const char pre[], const char name[], const char mess[])
1699: {
1700:   PetscBool flag = PETSC_FALSE;

1702:   PetscFunctionBegin;
1703:   PetscCall(PetscOptionsHasName(options, pre, name, &flag));
1704:   if (flag) {
1705:     PetscCheck(!mess || !mess[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s with %s", pre ? pre : "", name + 1, mess);
1706:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s", pre ? pre : "", name + 1);
1707:   }
1708:   PetscFunctionReturn(PETSC_SUCCESS);
1709: }

1711: /*@C
1712:   PetscOptionsHasHelp - Determines whether the "-help" option is in the database.

1714:   Not Collective

1716:   Input Parameter:
1717: . options - options database, use `NULL` for default global database

1719:   Output Parameter:
1720: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.

1722:   Level: advanced

1724: .seealso: `PetscOptionsHasName()`
1725: @*/
1726: PetscErrorCode PetscOptionsHasHelp(PetscOptions options, PetscBool *set)
1727: {
1728:   PetscFunctionBegin;
1729:   PetscAssertPointer(set, 2);
1730:   options = options ? options : defaultoptions;
1731:   *set    = options->help;
1732:   PetscFunctionReturn(PETSC_SUCCESS);
1733: }

1735: PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions options, PetscBool *set)
1736: {
1737:   PetscFunctionBegin;
1738:   PetscAssertPointer(set, 2);
1739:   options = options ? options : defaultoptions;
1740:   *set    = options->help_intro;
1741:   PetscFunctionReturn(PETSC_SUCCESS);
1742: }

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

1748:   Not Collective

1750:   Input Parameters:
1751: + options - options database, use `NULL` for default global database
1752: . pre     - string to prepend to the name or `NULL`
1753: - name    - the option one is seeking

1755:   Output Parameter:
1756: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.

1758:   Level: beginner

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

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

1775:   PetscFunctionBegin;
1776:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
1777:   if (set) *set = flag;
1778:   PetscFunctionReturn(PETSC_SUCCESS);
1779: }

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

1784:   Not Collective

1786:   Input Parameter:
1787: . options - the options database, use `NULL` for the default global database

1789:   Output Parameter:
1790: . copts - pointer where string pointer is stored

1792:   Level: advanced

1794:   Notes:
1795:   The array and each entry in the array should be freed with `PetscFree()`

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

1799: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsView()`, `PetscOptionsPush()`, `PetscOptionsPop()`
1800: @*/
1801: PetscErrorCode PetscOptionsGetAll(PetscOptions options, char *copts[])
1802: {
1803:   PetscInt i;
1804:   size_t   len = 1, lent = 0;
1805:   char    *coptions = NULL;

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

1834: /*@C
1835:   PetscOptionsUsed - Indicates if PETSc has used a particular option set in the database

1837:   Not Collective

1839:   Input Parameters:
1840: + options - options database, use `NULL` for default global database
1841: - name    - string name of option

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

1846:   Level: advanced

1848:   Note:
1849:   The value returned may be different on each process and depends on which options have been processed
1850:   on the given process

1852: .seealso: `PetscOptionsView()`, `PetscOptionsLeft()`, `PetscOptionsAllUsed()`
1853: @*/
1854: PetscErrorCode PetscOptionsUsed(PetscOptions options, const char *name, PetscBool *used)
1855: {
1856:   PetscInt i;

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

1873: /*@
1874:   PetscOptionsAllUsed - Returns a count of the number of options in the
1875:   database that have never been selected.

1877:   Not Collective

1879:   Input Parameter:
1880: . options - options database, use `NULL` for default global database

1882:   Output Parameter:
1883: . N - count of options not used

1885:   Level: advanced

1887:   Note:
1888:   The value returned may be different on each process and depends on which options have been processed
1889:   on the given process

1891: .seealso: `PetscOptionsView()`
1892: @*/
1893: PetscErrorCode PetscOptionsAllUsed(PetscOptions options, PetscInt *N)
1894: {
1895:   PetscInt i, n = 0;

1897:   PetscFunctionBegin;
1898:   PetscAssertPointer(N, 2);
1899:   options = options ? options : defaultoptions;
1900:   for (i = 0; i < options->N; i++) {
1901:     if (!options->used[i]) n++;
1902:   }
1903:   *N = n;
1904:   PetscFunctionReturn(PETSC_SUCCESS);
1905: }

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

1910:   Not Collective

1912:   Input Parameter:
1913: . options - options database; use `NULL` for default global database

1915:   Options Database Key:
1916: . -options_left - activates `PetscOptionsAllUsed()` within `PetscFinalize()`

1918:   Level: advanced

1920:   Notes:
1921:   This is rarely used directly, it is called by `PetscFinalize()` in debug more or if -options_left
1922:   is passed otherwise to help users determine possible mistakes in their usage of options. This
1923:   only prints values on process zero of `PETSC_COMM_WORLD`.

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

1928: .seealso: `PetscOptionsAllUsed()`
1929: @*/
1930: PetscErrorCode PetscOptionsLeft(PetscOptions options)
1931: {
1932:   PetscInt     i;
1933:   PetscInt     cnt = 0;
1934:   PetscOptions toptions;

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

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

1962:   Not Collective

1964:   Input Parameter:
1965: . options - options database, use `NULL` for default global database

1967:   Output Parameters:
1968: + N      - count of options not used
1969: . names  - names of options not used
1970: - values - values of options not used

1972:   Level: advanced

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

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

1980: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`
1981: @*/
1982: PetscErrorCode PetscOptionsLeftGet(PetscOptions options, PetscInt *N, char **names[], char **values[])
1983: {
1984:   PetscInt i, n;

1986:   PetscFunctionBegin;
1987:   if (N) PetscAssertPointer(N, 2);
1988:   if (names) PetscAssertPointer(names, 3);
1989:   if (values) PetscAssertPointer(values, 4);
1990:   options = options ? options : defaultoptions;

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

2002:   n = 0;
2003:   if (names || values) {
2004:     for (i = 0; i < options->N; i++) {
2005:       if (!options->used[i]) {
2006:         if (PetscCIOption(options->names[i])) continue;
2007:         if (names) (*names)[n] = options->names[i];
2008:         if (values) (*values)[n] = options->values[i];
2009:         n++;
2010:       }
2011:     }
2012:   }
2013:   PetscFunctionReturn(PETSC_SUCCESS);
2014: }

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

2019:   Not Collective

2021:   Input Parameters:
2022: + options - options database, use `NULL` for default global database
2023: . N       - count of options not used
2024: . names   - names of options not used
2025: - values  - values of options not used

2027:   Level: advanced

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

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

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

2050:   Logically Collective

2052:   Input Parameters:
2053: + name   - option name string
2054: . value  - option value string
2055: . source - The source for the option
2056: - ctx    - a `PETSCVIEWERASCII` or `NULL`

2058:   Level: intermediate

2060:   Notes:
2061:   If ctx is `NULL`, `PetscPrintf()` is used.
2062:   The first MPI rank in the `PetscViewer` viewer actually prints the values, other
2063:   processes may have different values set

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

2067: .seealso: `PetscOptionsMonitorSet()`
2068: @*/
2069: PetscErrorCode PetscOptionsMonitorDefault(const char name[], const char value[], PetscOptionSource source, void *ctx)
2070: {
2071:   PetscFunctionBegin;
2072:   if (PetscCIOption(name)) PetscFunctionReturn(PETSC_SUCCESS);

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

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

2100:   Not Collective

2102:   Input Parameters:
2103: + monitor        - pointer to function (if this is `NULL`, it turns off monitoring
2104: . mctx           - [optional] context for private data for the monitor routine (use `NULL` if
2105:                    no context is desired)
2106: - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)

2108:   Calling sequence of `monitor`:
2109: + name   - option name string
2110: . value  - option value string
2111: . source - option source
2112: - mctx   - optional monitoring context, as set by `PetscOptionsMonitorSet()`

2114:   Calling sequence of `monitordestroy`:
2115: . mctx - [optional] pointer to context to destroy with

2117:   Level: intermediate

2119:   Notes:
2120:   See `PetscInitialize()` for options related to option database monitoring.

2122:   The default is to do nothing.  To print the name and value of options
2123:   being inserted into the database, use `PetscOptionsMonitorDefault()` as the monitoring routine,
2124:   with a null monitoring context.

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

2130: .seealso: `PetscOptionsMonitorDefault()`, `PetscInitialize()`
2131: @*/
2132: PetscErrorCode PetscOptionsMonitorSet(PetscErrorCode (*monitor)(const char name[], const char value[], PetscOptionSource source, void *mctx), void *mctx, PetscErrorCode (*monitordestroy)(void **mctx))
2133: {
2134:   PetscOptions options = defaultoptions;

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

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

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

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

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

2216:   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &tdefault));
2217:   if (!tdefault) PetscCall(PetscStrcasecmp(name, "DEFAULT", &tdefault));
2218:   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &decide));
2219:   if (!decide) PetscCall(PetscStrcasecmp(name, "DECIDE", &decide));
2220:   PetscCall(PetscStrcasecmp(name, "mouse", &mouse));

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

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

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

2245: #if defined(PETSC_USE_REAL___FLOAT128)
2246:   #include <quadmath.h>
2247: #endif

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

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

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

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

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

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

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

2324:   PetscCall(PetscStrtod(name, a, &endptr));
2325:   PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value", name);
2326:   PetscFunctionReturn(PETSC_SUCCESS);
2327: }

2329: PetscErrorCode PetscOptionsStringToScalar(const char name[], PetscScalar *a)
2330: {
2331:   PetscBool   imag1;
2332:   size_t      len;
2333:   PetscScalar val = 0.;
2334:   char       *ptr = NULL;

2336:   PetscFunctionBegin;
2337:   PetscCall(PetscStrlen(name, &len));
2338:   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2339:   PetscCall(PetscStrtoz(name, &val, &ptr, &imag1));
2340: #if defined(PETSC_USE_COMPLEX)
2341:   if ((size_t)(ptr - name) < len) {
2342:     PetscBool   imag2;
2343:     PetscScalar val2;

2345:     PetscCall(PetscStrtoz(ptr, &val2, &ptr, &imag2));
2346:     if (imag1) PetscCheck(imag2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s: must specify imaginary component second", name);
2347:     val = PetscCMPLX(PetscRealPart(val), PetscImaginaryPart(val2));
2348:   }
2349: #endif
2350:   PetscCheck((size_t)(ptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value ", name);
2351:   *a = val;
2352:   PetscFunctionReturn(PETSC_SUCCESS);
2353: }

2355: /*@C
2356:   PetscOptionsGetBool - Gets the Logical (true or false) value for a particular
2357:   option in the database.

2359:   Not Collective

2361:   Input Parameters:
2362: + options - options database, use `NULL` for default global database
2363: . pre     - the string to prepend to the name or `NULL`
2364: - name    - the option one is seeking

2366:   Output Parameters:
2367: + ivalue - the logical value to return
2368: - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`

2370:   Level: beginner

2372:   Notes:
2373:   TRUE, true, YES, yes, nostring, and 1 all translate to `PETSC_TRUE`
2374:   FALSE, false, NO, no, and 0 all translate to `PETSC_FALSE`

2376:   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
2377:   is equivalent to -requested_bool true

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

2382: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2383:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2384:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2385:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2386:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2387:           `PetscOptionsFList()`, `PetscOptionsEList()`
2388: @*/
2389: PetscErrorCode PetscOptionsGetBool(PetscOptions options, const char pre[], const char name[], PetscBool *ivalue, PetscBool *set)
2390: {
2391:   const char *value;
2392:   PetscBool   flag;

2394:   PetscFunctionBegin;
2395:   PetscAssertPointer(name, 3);
2396:   if (ivalue) PetscAssertPointer(ivalue, 4);
2397:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2398:   if (flag) {
2399:     if (set) *set = PETSC_TRUE;
2400:     PetscCall(PetscOptionsStringToBool(value, &flag));
2401:     if (ivalue) *ivalue = flag;
2402:   } else {
2403:     if (set) *set = PETSC_FALSE;
2404:   }
2405:   PetscFunctionReturn(PETSC_SUCCESS);
2406: }

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

2411:   Not Collective

2413:   Input Parameters:
2414: + options - options database, use `NULL` for default global database
2415: . pre     - the string to prepend to the name or `NULL`
2416: . opt     - option name
2417: . list    - the possible choices (one of these must be selected, anything else is invalid)
2418: - ntext   - number of choices

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

2424:   Level: intermediate

2426:   Notes:
2427:   If the user does not supply the option value is NOT changed. Thus
2428:   you should ALWAYS initialize the ivalue if you access it without first checking if the set flag is true.

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

2432: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2433:           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2434:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2435:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2436:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2437:           `PetscOptionsFList()`, `PetscOptionsEList()`
2438: @*/
2439: PetscErrorCode PetscOptionsGetEList(PetscOptions options, const char pre[], const char opt[], const char *const *list, PetscInt ntext, PetscInt *value, PetscBool *set)
2440: {
2441:   size_t    alen, len = 0, tlen = 0;
2442:   char     *svalue;
2443:   PetscBool aset, flg = PETSC_FALSE;
2444:   PetscInt  i;

2446:   PetscFunctionBegin;
2447:   PetscAssertPointer(opt, 3);
2448:   for (i = 0; i < ntext; i++) {
2449:     PetscCall(PetscStrlen(list[i], &alen));
2450:     if (alen > len) len = alen;
2451:     tlen += len + 1;
2452:   }
2453:   len += 5; /* a little extra space for user mistypes */
2454:   PetscCall(PetscMalloc1(len, &svalue));
2455:   PetscCall(PetscOptionsGetString(options, pre, opt, svalue, len, &aset));
2456:   if (aset) {
2457:     PetscCall(PetscEListFind(ntext, list, svalue, value, &flg));
2458:     if (!flg) {
2459:       char *avail;

2461:       PetscCall(PetscMalloc1(tlen, &avail));
2462:       avail[0] = '\0';
2463:       for (i = 0; i < ntext; i++) {
2464:         PetscCall(PetscStrlcat(avail, list[i], tlen));
2465:         PetscCall(PetscStrlcat(avail, " ", tlen));
2466:       }
2467:       PetscCall(PetscStrtolower(avail));
2468:       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown option %s for -%s%s. Available options: %s", svalue, pre ? pre : "", opt + 1, avail);
2469:     }
2470:     if (set) *set = PETSC_TRUE;
2471:   } else if (set) *set = PETSC_FALSE;
2472:   PetscCall(PetscFree(svalue));
2473:   PetscFunctionReturn(PETSC_SUCCESS);
2474: }

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

2479:   Not Collective

2481:   Input Parameters:
2482: + options - options database, use `NULL` for default global database
2483: . pre     - option prefix or `NULL`
2484: . opt     - option name
2485: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

2487:   Output Parameters:
2488: + value - the  value to return
2489: - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`

2491:   Level: beginner

2493:   Notes:
2494:   If the user does not supply the option value is NOT changed. Thus
2495:   you should ALWAYS initialize the ivalue if you access it without first checking if the set flag is true.

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

2499: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2500:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2501:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2502:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2503:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2504:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2505:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2506: @*/
2507: PetscErrorCode PetscOptionsGetEnum(PetscOptions options, const char pre[], const char opt[], const char *const *list, PetscEnum *value, PetscBool *set)
2508: {
2509:   PetscInt  ntext = 0, tval;
2510:   PetscBool fset;

2512:   PetscFunctionBegin;
2513:   PetscAssertPointer(opt, 3);
2514:   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");
2515:   PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
2516:   ntext -= 3;
2517:   PetscCall(PetscOptionsGetEList(options, pre, opt, list, ntext, &tval, &fset));
2518:   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
2519:   if (fset) *value = (PetscEnum)tval;
2520:   if (set) *set = fset;
2521:   PetscFunctionReturn(PETSC_SUCCESS);
2522: }

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

2527:   Not Collective

2529:   Input Parameters:
2530: + options - options database, use `NULL` for default global database
2531: . pre     - the string to prepend to the name or `NULL`
2532: - name    - the option one is seeking

2534:   Output Parameters:
2535: + ivalue - the integer value to return
2536: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2538:   Level: beginner

2540:   Notes:
2541:   If the user does not supply the option ivalue is NOT changed. Thus
2542:   you should ALWAYS initialize the ivalue if you access it without first checking if the set flag is true.

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

2557:   PetscFunctionBegin;
2558:   PetscAssertPointer(name, 3);
2559:   PetscAssertPointer(ivalue, 4);
2560:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2561:   if (flag) {
2562:     if (!value) {
2563:       if (set) *set = PETSC_FALSE;
2564:     } else {
2565:       if (set) *set = PETSC_TRUE;
2566:       PetscCall(PetscOptionsStringToInt(value, ivalue));
2567:     }
2568:   } else {
2569:     if (set) *set = PETSC_FALSE;
2570:   }
2571:   PetscFunctionReturn(PETSC_SUCCESS);
2572: }

2574: /*@C
2575:   PetscOptionsGetReal - Gets the double precision value for a particular
2576:   option in the database.

2578:   Not Collective

2580:   Input Parameters:
2581: + options - options database, use `NULL` for default global database
2582: . pre     - string to prepend to each name or `NULL`
2583: - name    - the option one is seeking

2585:   Output Parameters:
2586: + dvalue - the double value to return
2587: - set    - `PETSC_TRUE` if found, `PETSC_FALSE` if not found

2589:   Level: beginner

2591:   Note:
2592:   If the user does not supply the option dvalue is NOT changed. Thus
2593:   you should ALWAYS initialize the ivalue if you access it without first checking if the set flag is true.

2595: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2596:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2597:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2598:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2599:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2600:           `PetscOptionsFList()`, `PetscOptionsEList()`
2601: @*/
2602: PetscErrorCode PetscOptionsGetReal(PetscOptions options, const char pre[], const char name[], PetscReal *dvalue, PetscBool *set)
2603: {
2604:   const char *value;
2605:   PetscBool   flag;

2607:   PetscFunctionBegin;
2608:   PetscAssertPointer(name, 3);
2609:   PetscAssertPointer(dvalue, 4);
2610:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2611:   if (flag) {
2612:     if (!value) {
2613:       if (set) *set = PETSC_FALSE;
2614:     } else {
2615:       if (set) *set = PETSC_TRUE;
2616:       PetscCall(PetscOptionsStringToReal(value, dvalue));
2617:     }
2618:   } else {
2619:     if (set) *set = PETSC_FALSE;
2620:   }
2621:   PetscFunctionReturn(PETSC_SUCCESS);
2622: }

2624: /*@C
2625:   PetscOptionsGetScalar - Gets the scalar value for a particular
2626:   option in the database.

2628:   Not Collective

2630:   Input Parameters:
2631: + options - options database, use `NULL` for default global database
2632: . pre     - string to prepend to each name or `NULL`
2633: - name    - the option one is seeking

2635:   Output Parameters:
2636: + dvalue - the double value to return
2637: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2639:   Level: beginner

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

2644:   Note:
2645:   If the user does not supply the option dvalue is NOT changed. Thus
2646:   you should ALWAYS initialize the ivalue if you access it without first checking if the set flag is true.

2648: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2649:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2650:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2651:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2652:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2653:           `PetscOptionsFList()`, `PetscOptionsEList()`
2654: @*/
2655: PetscErrorCode PetscOptionsGetScalar(PetscOptions options, const char pre[], const char name[], PetscScalar *dvalue, PetscBool *set)
2656: {
2657:   const char *value;
2658:   PetscBool   flag;

2660:   PetscFunctionBegin;
2661:   PetscAssertPointer(name, 3);
2662:   PetscAssertPointer(dvalue, 4);
2663:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2664:   if (flag) {
2665:     if (!value) {
2666:       if (set) *set = PETSC_FALSE;
2667:     } else {
2668: #if !defined(PETSC_USE_COMPLEX)
2669:       PetscCall(PetscOptionsStringToReal(value, dvalue));
2670: #else
2671:       PetscCall(PetscOptionsStringToScalar(value, dvalue));
2672: #endif
2673:       if (set) *set = PETSC_TRUE;
2674:     }
2675:   } else { /* flag */
2676:     if (set) *set = PETSC_FALSE;
2677:   }
2678:   PetscFunctionReturn(PETSC_SUCCESS);
2679: }

2681: /*@C
2682:   PetscOptionsGetString - Gets the string value for a particular option in
2683:   the database.

2685:   Not Collective

2687:   Input Parameters:
2688: + options - options database, use `NULL` for default global database
2689: . pre     - string to prepend to name or `NULL`
2690: . name    - the option one is seeking
2691: - len     - maximum length of the string including null termination

2693:   Output Parameters:
2694: + string - location to copy string
2695: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2697:   Level: beginner

2699:   Note:
2700:   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`

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

2705:   Even if the user provided no string (for example -optionname -someotheroption) the flag is set to PETSC_TRUE (and the string is fulled with nulls).

2707:   Fortran Notes:
2708:   The Fortran interface is slightly different from the C/C++
2709:   interface (len is not used).  Sample usage in Fortran follows
2710: .vb
2711:       character *20    string
2712:       PetscErrorCode   ierr
2713:       PetscBool        set
2714:       call PetscOptionsGetString(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-s',string,set,ierr)
2715: .ve

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

2729:   PetscFunctionBegin;
2730:   PetscAssertPointer(name, 3);
2731:   PetscAssertPointer(string, 4);
2732:   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2733:   if (!flag) {
2734:     if (set) *set = PETSC_FALSE;
2735:   } else {
2736:     if (set) *set = PETSC_TRUE;
2737:     if (value) PetscCall(PetscStrncpy(string, value, len));
2738:     else PetscCall(PetscArrayzero(string, len));
2739:   }
2740:   PetscFunctionReturn(PETSC_SUCCESS);
2741: }

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

2747:   Not Collective

2749:   Input Parameters:
2750: + options - options database, use `NULL` for default global database
2751: . pre     - string to prepend to each name or `NULL`
2752: - name    - the option one is seeking

2754:   Output Parameters:
2755: + dvalue - the integer values to return
2756: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2757: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2759:   Level: beginner

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

2764: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2765:           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2766:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2767:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2768:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2769:           `PetscOptionsFList()`, `PetscOptionsEList()`
2770: @*/
2771: PetscErrorCode PetscOptionsGetBoolArray(PetscOptions options, const char pre[], const char name[], PetscBool dvalue[], PetscInt *nmax, PetscBool *set)
2772: {
2773:   const char *svalue;
2774:   char       *value;
2775:   PetscInt    n = 0;
2776:   PetscBool   flag;
2777:   PetscToken  token;

2779:   PetscFunctionBegin;
2780:   PetscAssertPointer(name, 3);
2781:   PetscAssertPointer(dvalue, 4);
2782:   PetscAssertPointer(nmax, 5);

2784:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
2785:   if (!flag || !svalue) {
2786:     if (set) *set = PETSC_FALSE;
2787:     *nmax = 0;
2788:     PetscFunctionReturn(PETSC_SUCCESS);
2789:   }
2790:   if (set) *set = PETSC_TRUE;
2791:   PetscCall(PetscTokenCreate(svalue, ',', &token));
2792:   PetscCall(PetscTokenFind(token, &value));
2793:   while (value && n < *nmax) {
2794:     PetscCall(PetscOptionsStringToBool(value, dvalue));
2795:     PetscCall(PetscTokenFind(token, &value));
2796:     dvalue++;
2797:     n++;
2798:   }
2799:   PetscCall(PetscTokenDestroy(&token));
2800:   *nmax = n;
2801:   PetscFunctionReturn(PETSC_SUCCESS);
2802: }

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

2807:   Not Collective

2809:   Input Parameters:
2810: + options - options database, use `NULL` for default global database
2811: . pre     - option prefix or `NULL`
2812: . name    - option name
2813: - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null

2815:   Output Parameters:
2816: + ivalue - the  enum values to return
2817: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2818: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2820:   Level: beginner

2822:   Notes:
2823:   The array must be passed as a comma separated list.

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

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

2829: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2830:           `PetscOptionsGetEnum()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2831:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsName()`,
2832:           `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, `PetscOptionsStringArray()`, `PetscOptionsRealArray()`,
2833:           `PetscOptionsScalar()`, `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2834:           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2835: @*/
2836: PetscErrorCode PetscOptionsGetEnumArray(PetscOptions options, const char pre[], const char name[], const char *const *list, PetscEnum ivalue[], PetscInt *nmax, PetscBool *set)
2837: {
2838:   const char *svalue;
2839:   char       *value;
2840:   PetscInt    n = 0;
2841:   PetscEnum   evalue;
2842:   PetscBool   flag;
2843:   PetscToken  token;

2845:   PetscFunctionBegin;
2846:   PetscAssertPointer(name, 3);
2847:   PetscAssertPointer(list, 4);
2848:   PetscAssertPointer(ivalue, 5);
2849:   PetscAssertPointer(nmax, 6);

2851:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
2852:   if (!flag || !svalue) {
2853:     if (set) *set = PETSC_FALSE;
2854:     *nmax = 0;
2855:     PetscFunctionReturn(PETSC_SUCCESS);
2856:   }
2857:   if (set) *set = PETSC_TRUE;
2858:   PetscCall(PetscTokenCreate(svalue, ',', &token));
2859:   PetscCall(PetscTokenFind(token, &value));
2860:   while (value && n < *nmax) {
2861:     PetscCall(PetscEnumFind(list, value, &evalue, &flag));
2862:     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown enum value '%s' for -%s%s", svalue, pre ? pre : "", name + 1);
2863:     ivalue[n++] = evalue;
2864:     PetscCall(PetscTokenFind(token, &value));
2865:   }
2866:   PetscCall(PetscTokenDestroy(&token));
2867:   *nmax = n;
2868:   PetscFunctionReturn(PETSC_SUCCESS);
2869: }

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

2874:   Not Collective

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

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

2886:   Level: beginner

2888:   Notes:
2889:   The array can be passed as
2890: +  a comma separated list -                                 0,1,2,3,4,5,6,7
2891: .  a range (start\-end+1) -                                 0-8
2892: .  a range with given increment (start\-end+1:inc) -        0-7:2
2893: -  a combination of values and ranges separated by commas - 0,1-8,8-15:2

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

2897: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2898:           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2899:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2900:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2901:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2902:           `PetscOptionsFList()`, `PetscOptionsEList()`
2903: @*/
2904: PetscErrorCode PetscOptionsGetIntArray(PetscOptions options, const char pre[], const char name[], PetscInt ivalue[], PetscInt *nmax, PetscBool *set)
2905: {
2906:   const char *svalue;
2907:   char       *value;
2908:   PetscInt    n = 0, i, j, start, end, inc, nvalues;
2909:   size_t      len;
2910:   PetscBool   flag, foundrange;
2911:   PetscToken  token;

2913:   PetscFunctionBegin;
2914:   PetscAssertPointer(name, 3);
2915:   PetscAssertPointer(ivalue, 4);
2916:   PetscAssertPointer(nmax, 5);

2918:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
2919:   if (!flag || !svalue) {
2920:     if (set) *set = PETSC_FALSE;
2921:     *nmax = 0;
2922:     PetscFunctionReturn(PETSC_SUCCESS);
2923:   }
2924:   if (set) *set = PETSC_TRUE;
2925:   PetscCall(PetscTokenCreate(svalue, ',', &token));
2926:   PetscCall(PetscTokenFind(token, &value));
2927:   while (value && n < *nmax) {
2928:     /* look for form  d-D where d and D are integers */
2929:     foundrange = PETSC_FALSE;
2930:     PetscCall(PetscStrlen(value, &len));
2931:     if (value[0] == '-') i = 2;
2932:     else i = 1;
2933:     for (; i < (int)len; i++) {
2934:       if (value[i] == '-') {
2935:         PetscCheck(i != (int)len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, value);
2936:         value[i] = 0;

2938:         PetscCall(PetscOptionsStringToInt(value, &start));
2939:         inc = 1;
2940:         j   = i + 1;
2941:         for (; j < (int)len; j++) {
2942:           if (value[j] == ':') {
2943:             value[j] = 0;

2945:             PetscCall(PetscOptionsStringToInt(value + j + 1, &inc));
2946:             PetscCheck(inc > 0, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry,%s cannot have negative increment", n, value + j + 1);
2947:             break;
2948:           }
2949:         }
2950:         PetscCall(PetscOptionsStringToInt(value + i + 1, &end));
2951:         PetscCheck(end > start, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, %s-%s cannot have decreasing list", n, value, value + i + 1);
2952:         nvalues = (end - start) / inc + (end - start) % inc;
2953:         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);
2954:         for (; start < end; start += inc) {
2955:           *ivalue = start;
2956:           ivalue++;
2957:           n++;
2958:         }
2959:         foundrange = PETSC_TRUE;
2960:         break;
2961:       }
2962:     }
2963:     if (!foundrange) {
2964:       PetscCall(PetscOptionsStringToInt(value, ivalue));
2965:       ivalue++;
2966:       n++;
2967:     }
2968:     PetscCall(PetscTokenFind(token, &value));
2969:   }
2970:   PetscCall(PetscTokenDestroy(&token));
2971:   *nmax = n;
2972:   PetscFunctionReturn(PETSC_SUCCESS);
2973: }

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

2979:   Not Collective

2981:   Input Parameters:
2982: + options - options database, use `NULL` for default global database
2983: . pre     - string to prepend to each name or `NULL`
2984: - name    - the option one is seeking

2986:   Output Parameters:
2987: + dvalue - the double values to return
2988: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2989: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

2991:   Level: beginner

2993: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2994:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
2995:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2996:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2997:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2998:           `PetscOptionsFList()`, `PetscOptionsEList()`
2999: @*/
3000: PetscErrorCode PetscOptionsGetRealArray(PetscOptions options, const char pre[], const char name[], PetscReal dvalue[], PetscInt *nmax, PetscBool *set)
3001: {
3002:   const char *svalue;
3003:   char       *value;
3004:   PetscInt    n = 0;
3005:   PetscBool   flag;
3006:   PetscToken  token;

3008:   PetscFunctionBegin;
3009:   PetscAssertPointer(name, 3);
3010:   PetscAssertPointer(dvalue, 4);
3011:   PetscAssertPointer(nmax, 5);

3013:   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3014:   if (!flag || !svalue) {
3015:     if (set) *set = PETSC_FALSE;
3016:     *nmax = 0;
3017:     PetscFunctionReturn(PETSC_SUCCESS);
3018:   }
3019:   if (set) *set = PETSC_TRUE;
3020:   PetscCall(PetscTokenCreate(svalue, ',', &token));
3021:   PetscCall(PetscTokenFind(token, &value));
3022:   while (value && n < *nmax) {
3023:     PetscCall(PetscOptionsStringToReal(value, dvalue++));
3024:     PetscCall(PetscTokenFind(token, &value));
3025:     n++;
3026:   }
3027:   PetscCall(PetscTokenDestroy(&token));
3028:   *nmax = n;
3029:   PetscFunctionReturn(PETSC_SUCCESS);
3030: }

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

3036:   Not Collective

3038:   Input Parameters:
3039: + options - options database, use `NULL` for default global database
3040: . pre     - string to prepend to each name or `NULL`
3041: - name    - the option one is seeking

3043:   Output Parameters:
3044: + dvalue - the scalar values to return
3045: . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3046: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

3048:   Level: beginner

3050: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3051:           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3052:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3053:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3054:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3055:           `PetscOptionsFList()`, `PetscOptionsEList()`
3056: @*/
3057: PetscErrorCode PetscOptionsGetScalarArray(PetscOptions options, const char pre[], const char name[], PetscScalar dvalue[], PetscInt *nmax, PetscBool *set)
3058: {
3059:   const char *svalue;
3060:   char       *value;
3061:   PetscInt    n = 0;
3062:   PetscBool   flag;
3063:   PetscToken  token;

3065:   PetscFunctionBegin;
3066:   PetscAssertPointer(name, 3);
3067:   PetscAssertPointer(dvalue, 4);
3068:   PetscAssertPointer(nmax, 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(PetscOptionsStringToScalar(value, dvalue++));
3081:     PetscCall(PetscTokenFind(token, &value));
3082:     n++;
3083:   }
3084:   PetscCall(PetscTokenDestroy(&token));
3085:   *nmax = n;
3086:   PetscFunctionReturn(PETSC_SUCCESS);
3087: }

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

3093:   Not Collective; No Fortran Support

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

3100:   Output Parameters:
3101: + strings - location to copy strings
3102: . nmax    - On input maximum number of strings, on output the actual number of strings found
3103: - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`

3105:   Level: beginner

3107:   Notes:
3108:   The nmax parameter is used for both input and output.

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

3113:   The user is responsible for deallocating the strings that are
3114:   returned.

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

3131:   PetscFunctionBegin;
3132:   PetscAssertPointer(name, 3);
3133:   PetscAssertPointer(strings, 4);
3134:   PetscAssertPointer(nmax, 5);

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

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

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

3160:   Logically Collective

3162:   Input Parameters:
3163: + PetscOptionsObject - string to prepend to name or `NULL`
3164: . oldname            - the old, deprecated option
3165: . newname            - the new option, or `NULL` if option is purely removed
3166: . version            - a string describing the version of first deprecation, e.g. "3.9"
3167: - info               - additional information string, or `NULL`.

3169:   Options Database Key:
3170: . -options_suppress_deprecated_warnings - do not print deprecation warnings

3172:   Level: developer

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

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

3181:   Must be called between `PetscOptionsBegin()` (or `PetscObjectOptionsBegin()`) and `PetscOptionsEnd()`.
3182:   Only the process of rank zero that owns the `PetscOptionsItems` are argument (managed by `PetscOptionsBegin()` or
3183:   `PetscObjectOptionsBegin()` prints the information
3184:   If newname is provided, the old option is replaced. Otherwise, it remains
3185:   in the options database.
3186:   If an option is not replaced, the info argument should be used to advise the user
3187:   on how to proceed.
3188:   There is a limit on the length of the warning printed, so very long strings
3189:   provided as info may be truncated.

3191: .seealso: `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsScalar()`, `PetscOptionsBool()`, `PetscOptionsString()`, `PetscOptionsSetValue()`
3192: @*/
3193: PetscErrorCode PetscOptionsDeprecated_Private(PetscOptionItems *PetscOptionsObject, const char oldname[], const char newname[], const char version[], const char info[])
3194: {
3195:   PetscBool         found, quiet;
3196:   const char       *value;
3197:   const char *const quietopt = "-options_suppress_deprecated_warnings";
3198:   char              msg[4096];
3199:   char             *prefix  = NULL;
3200:   PetscOptions      options = NULL;
3201:   MPI_Comm          comm    = PETSC_COMM_SELF;

3203:   PetscFunctionBegin;
3204:   PetscAssertPointer(oldname, 2);
3205:   PetscAssertPointer(version, 4);
3206:   if (PetscOptionsObject) {
3207:     prefix  = PetscOptionsObject->prefix;
3208:     options = PetscOptionsObject->options;
3209:     comm    = PetscOptionsObject->comm;
3210:   }
3211:   PetscCall(PetscOptionsFindPair(options, prefix, oldname, &value, &found));
3212:   if (found) {
3213:     if (newname) {
3214:       if (prefix) PetscCall(PetscOptionsPrefixPush(options, prefix));
3215:       PetscCall(PetscOptionsSetValue(options, newname, value));
3216:       if (prefix) PetscCall(PetscOptionsPrefixPop(options));
3217:       PetscCall(PetscOptionsClearValue(options, oldname));
3218:     }
3219:     quiet = PETSC_FALSE;
3220:     PetscCall(PetscOptionsGetBool(options, NULL, quietopt, &quiet, NULL));
3221:     if (!quiet) {
3222:       PetscCall(PetscStrncpy(msg, "** PETSc DEPRECATION WARNING ** : the option ", sizeof(msg)));
3223:       PetscCall(PetscStrlcat(msg, oldname, sizeof(msg)));
3224:       PetscCall(PetscStrlcat(msg, " is deprecated as of version ", sizeof(msg)));
3225:       PetscCall(PetscStrlcat(msg, version, sizeof(msg)));
3226:       PetscCall(PetscStrlcat(msg, " and will be removed in a future release.\n", sizeof(msg)));
3227:       if (newname) {
3228:         PetscCall(PetscStrlcat(msg, "   Use the option ", sizeof(msg)));
3229:         PetscCall(PetscStrlcat(msg, newname, sizeof(msg)));
3230:         PetscCall(PetscStrlcat(msg, " instead.", sizeof(msg)));
3231:       }
3232:       if (info) {
3233:         PetscCall(PetscStrlcat(msg, " ", sizeof(msg)));
3234:         PetscCall(PetscStrlcat(msg, info, sizeof(msg)));
3235:       }
3236:       PetscCall(PetscStrlcat(msg, " (Silence this warning with ", sizeof(msg)));
3237:       PetscCall(PetscStrlcat(msg, quietopt, sizeof(msg)));
3238:       PetscCall(PetscStrlcat(msg, ")\n", sizeof(msg)));
3239:       PetscCall(PetscPrintf(comm, "%s", msg));
3240:     }
3241:   }
3242:   PetscFunctionReturn(PETSC_SUCCESS);
3243: }