xref: /petsc/src/sys/objects/options.c (revision a336c15037c72f93cd561f5a5e11e93175f2efd9)
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() */
3 
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
7 
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 */
11 
12 #include <petsc/private/petscimpl.h> /*I  "petscsys.h"   I*/
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
21 
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
29 
30 #include <petsc/private/hashtable.h>
31 
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 }
38 
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 }
53 
54 static inline int PetscOptEqual(const char a[], const char b[])
55 {
56   return !PetscOptNameCmp(a, b);
57 }
58 
59 KHASH_INIT(HO, kh_cstr_t, int, 1, PetscOptHash, PetscOptEqual)
60 
61 #define MAXPREFIXES        25
62 #define MAXOPTIONSMONITORS 5
63 
64 const char *PetscOptionSources[] = {"code", "command line", "file", "environment"};
65 
66 // This table holds all the options set by the user
67 struct _n_PetscOptions {
68   PetscOptions previous;
69 
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;
77 
78   /* Hash table */
79   khash_t(HO) *ht;
80 
81   /* Prefixes */
82   int  prefixind;
83   int  prefixstack[MAXPREFIXES];
84   char prefix[PETSC_MAX_OPTION_NAME];
85 
86   /* Aliases */
87   int    Na;       /* number or aliases */
88   int    Naalloc;  /* number of allocated aliases */
89   char **aliases1; /* aliased */
90   char **aliases2; /* aliasee */
91 
92   /* Help */
93   PetscBool help;       /* flag whether "-help" is in the database */
94   PetscBool help_intro; /* flag whether "-help intro" is in the database */
95 
96   /* Monitors */
97   PetscBool monitorFromOptions, monitorCancel;
98   PetscErrorCode (*monitor[MAXOPTIONSMONITORS])(const char[], const char[], PetscOptionSource, void *); /* returns control to user after */
99   PetscCtxDestroyFn *monitordestroy[MAXOPTIONSMONITORS];                                                /* callback for monitor destruction */
100   void              *monitorcontext[MAXOPTIONSMONITORS];                                                /* to pass arbitrary user data into monitor */
101   PetscInt           numbermonitors;                                                                    /* to, for instance, detect options being set */
102 };
103 
104 static PetscOptions defaultoptions = NULL; /* the options database routines query this object for options */
105 
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 };
117 
118 PETSC_INTERN PetscErrorCode PetscOptionsSetValue_Private(PetscOptions, const char[], const char[], int *, PetscOptionSource);
119 PETSC_INTERN PetscErrorCode PetscOptionsInsertStringYAML_Private(PetscOptions, const char[], PetscOptionSource);
120 
121 /*
122     Options events monitor
123 */
124 static PetscErrorCode PetscOptionsMonitor(PetscOptions options, const char name[], const char value[], PetscOptionSource source)
125 {
126   PetscFunctionBegin;
127   if (options->monitorFromOptions) PetscCall(PetscOptionsMonitorDefault(name, value, source, NULL));
128   for (PetscInt i = 0; i < options->numbermonitors; i++) PetscCall((*options->monitor[i])(name, value, source, options->monitorcontext[i]));
129   PetscFunctionReturn(PETSC_SUCCESS);
130 }
131 
132 /*@
133   PetscOptionsCreate - Creates an empty options database.
134 
135   Logically Collective
136 
137   Output Parameter:
138 . options - Options database object
139 
140   Level: advanced
141 
142   Note:
143   Though PETSc has a concept of multiple options database the current code uses a single default `PetscOptions` object
144 
145   Developer Notes:
146   We may want eventually to pass a `MPI_Comm` to determine the ownership of the object
147 
148   This object never got developed after being introduced, it is not clear that supporting multiple `PetscOptions` objects is useful
149 
150 .seealso: `PetscOptionsDestroy()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`
151 @*/
152 PetscErrorCode PetscOptionsCreate(PetscOptions *options)
153 {
154   PetscFunctionBegin;
155   PetscAssertPointer(options, 1);
156   *options = (PetscOptions)calloc(1, sizeof(**options));
157   PetscCheck(*options, PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate the options database");
158   PetscFunctionReturn(PETSC_SUCCESS);
159 }
160 
161 /*@
162   PetscOptionsDestroy - Destroys an option database.
163 
164   Logically Collective on whatever communicator was associated with the call to `PetscOptionsCreate()`
165 
166   Input Parameter:
167 . options - the `PetscOptions` object
168 
169   Level: advanced
170 
171 .seealso: `PetscOptionsInsert()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsSetValue()`
172 @*/
173 PetscErrorCode PetscOptionsDestroy(PetscOptions *options)
174 {
175   PetscFunctionBegin;
176   PetscAssertPointer(options, 1);
177   if (!*options) PetscFunctionReturn(PETSC_SUCCESS);
178   PetscCheck(!(*options)->previous, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "You are destroying an option that has been used with PetscOptionsPush() but does not have a corresponding PetscOptionsPop()");
179   PetscCall(PetscOptionsClear(*options));
180   /* XXX what about monitors ? */
181   free(*options);
182   *options = NULL;
183   PetscFunctionReturn(PETSC_SUCCESS);
184 }
185 
186 /*
187     PetscOptionsCreateDefault - Creates the default global options database
188 */
189 PetscErrorCode PetscOptionsCreateDefault(void)
190 {
191   PetscFunctionBegin;
192   if (PetscUnlikely(!defaultoptions)) PetscCall(PetscOptionsCreate(&defaultoptions));
193   PetscFunctionReturn(PETSC_SUCCESS);
194 }
195 
196 /*@
197   PetscOptionsPush - Push a new `PetscOptions` object as the default provider of options
198   Allows using different parts of a code to use different options databases
199 
200   Logically Collective
201 
202   Input Parameter:
203 . opt - the options obtained with `PetscOptionsCreate()`
204 
205   Level: advanced
206 
207   Notes:
208   Use `PetscOptionsPop()` to return to the previous default options database
209 
210   The collectivity of this routine is complex; only the MPI ranks that call this routine will
211   have the affect of these options. If some processes that create objects call this routine and others do
212   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
213   on different ranks.
214 
215   Developer Notes:
216   Though this functionality has been provided it has never been used in PETSc and might be removed.
217 
218 .seealso: `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
219 @*/
220 PetscErrorCode PetscOptionsPush(PetscOptions opt)
221 {
222   PetscFunctionBegin;
223   PetscCall(PetscOptionsCreateDefault());
224   opt->previous  = defaultoptions;
225   defaultoptions = opt;
226   PetscFunctionReturn(PETSC_SUCCESS);
227 }
228 
229 /*@
230   PetscOptionsPop - Pop the most recent `PetscOptionsPush()` to return to the previous default options
231 
232   Logically Collective on whatever communicator was associated with the call to `PetscOptionsCreate()`
233 
234   Level: advanced
235 
236 .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
237 @*/
238 PetscErrorCode PetscOptionsPop(void)
239 {
240   PetscOptions current = defaultoptions;
241 
242   PetscFunctionBegin;
243   PetscCheck(defaultoptions, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing default options");
244   PetscCheck(defaultoptions->previous, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscOptionsPop() called too many times");
245   defaultoptions    = defaultoptions->previous;
246   current->previous = NULL;
247   PetscFunctionReturn(PETSC_SUCCESS);
248 }
249 
250 /*
251     PetscOptionsDestroyDefault - Destroys the default global options database
252 */
253 PetscErrorCode PetscOptionsDestroyDefault(void)
254 {
255   PetscFunctionBegin;
256   if (!defaultoptions) PetscFunctionReturn(PETSC_SUCCESS);
257   /* Destroy any options that the user forgot to pop */
258   while (defaultoptions->previous) {
259     PetscOptions tmp = defaultoptions;
260 
261     PetscCall(PetscOptionsPop());
262     PetscCall(PetscOptionsDestroy(&tmp));
263   }
264   PetscCall(PetscOptionsDestroy(&defaultoptions));
265   PetscFunctionReturn(PETSC_SUCCESS);
266 }
267 
268 /*@
269   PetscOptionsValidKey - PETSc Options database keys must begin with one or two dashes (-) followed by a letter.
270 
271   Not Collective
272 
273   Input Parameter:
274 . key - string to check if valid
275 
276   Output Parameter:
277 . valid - `PETSC_TRUE` if a valid key
278 
279   Level: intermediate
280 
281 .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`
282 @*/
283 PetscErrorCode PetscOptionsValidKey(const char key[], PetscBool *valid)
284 {
285   char               *ptr;
286   PETSC_UNUSED double d;
287 
288   PetscFunctionBegin;
289   if (key) PetscAssertPointer(key, 1);
290   PetscAssertPointer(valid, 2);
291   *valid = PETSC_FALSE;
292   if (!key) PetscFunctionReturn(PETSC_SUCCESS);
293   if (key[0] != '-') PetscFunctionReturn(PETSC_SUCCESS);
294   if (key[1] == '-') key++;
295   if (!isalpha((int)key[1])) PetscFunctionReturn(PETSC_SUCCESS);
296   d = strtod(key, &ptr);
297   if (ptr != key && !(*ptr == '_' || isalnum((int)*ptr))) PetscFunctionReturn(PETSC_SUCCESS);
298   *valid = PETSC_TRUE;
299   PetscFunctionReturn(PETSC_SUCCESS);
300 }
301 
302 static PetscErrorCode PetscOptionsInsertString_Private(PetscOptions options, const char in_str[], PetscOptionSource source)
303 {
304   const char *first, *second;
305   PetscToken  token;
306 
307   PetscFunctionBegin;
308   PetscCall(PetscTokenCreate(in_str, ' ', &token));
309   PetscCall(PetscTokenFind(token, &first));
310   while (first) {
311     PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;
312 
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 }
355 
356 /*@
357   PetscOptionsInsertString - Inserts options into the database from a string
358 
359   Logically Collective
360 
361   Input Parameters:
362 + options - options object
363 - in_str  - string that contains options separated by blanks
364 
365   Level: intermediate
366 
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.
371 
372    Contributed by Boyana Norris
373 
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 }
387 
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;
397 
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 }
412 
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;
416 
417   PetscFunctionBegin;
418   *yaml = PETSC_FALSE;
419   PetscCall(PetscStrreplace(comm, file, fname, sizeof(fname)));
420   PetscCall(PetscFixFilename(fname, path));
421   PetscCall(PetscStrendswith(path, ":yaml", yaml));
422   if (*yaml) {
423     PetscCall(PetscStrrchr(path, ':', &tail));
424     tail[-1] = 0; /* remove ":yaml" suffix from path */
425   }
426   PetscCall(PetscStrncpy(filename, path, PETSC_MAX_PATH_LEN));
427   /* check for standard YAML and JSON filename extensions */
428   if (!*yaml) PetscCall(PetscStrendswith(filename, ".yaml", yaml));
429   if (!*yaml) PetscCall(PetscStrendswith(filename, ".yml", yaml));
430   if (!*yaml) PetscCall(PetscStrendswith(filename, ".json", yaml));
431   if (!*yaml) { /* check file contents */
432     PetscMPIInt rank;
433     PetscCallMPI(MPI_Comm_rank(comm, &rank));
434     if (rank == 0) {
435       FILE *fh = fopen(filename, "r");
436       if (fh) {
437         char buf[6] = "";
438         if (fread(buf, 1, 6, fh) > 0) {
439           PetscCall(PetscStrncmp(buf, "%YAML ", 6, yaml));          /* check for '%YAML' tag */
440           if (!*yaml) PetscCall(PetscStrncmp(buf, "---", 3, yaml)); /* check for document start */
441         }
442         (void)fclose(fh);
443       }
444     }
445     PetscCallMPI(MPI_Bcast(yaml, 1, MPI_C_BOOL, 0, comm));
446   }
447   PetscFunctionReturn(PETSC_SUCCESS);
448 }
449 
450 static PetscErrorCode PetscOptionsInsertFilePetsc(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
451 {
452   char       *string, *vstring = NULL, *astring = NULL, *packed = NULL;
453   const char *tokens[4];
454   size_t      len;
455   PetscCount  bytes;
456   FILE       *fd;
457   PetscToken  token = NULL;
458   int         err;
459   char       *cmatch = NULL;
460   const char  cmt    = '#';
461   PetscInt    line   = 1;
462   PetscMPIInt rank, cnt = 0, acnt = 0, counts[2];
463   PetscBool   isdir, alias = PETSC_FALSE, valid;
464 
465   PetscFunctionBegin;
466   PetscCall(PetscMemzero(tokens, sizeof(tokens)));
467   PetscCallMPI(MPI_Comm_rank(comm, &rank));
468   if (rank == 0) {
469     char fpath[PETSC_MAX_PATH_LEN];
470     char fname[PETSC_MAX_PATH_LEN];
471 
472     PetscCall(PetscStrreplace(PETSC_COMM_SELF, file, fname, sizeof(fname)));
473     PetscCall(PetscFixFilename(fname, fpath));
474     PetscCall(PetscGetFullPath(fpath, fname, sizeof(fname)));
475 
476     fd = fopen(fname, "r");
477     PetscCall(PetscTestDirectory(fname, 'r', &isdir));
478     PetscCheck(!isdir || !require, PETSC_COMM_SELF, PETSC_ERR_USER, "Specified options file %s is a directory", fname);
479     if (fd && !isdir) {
480       PetscSegBuffer vseg, aseg;
481 
482       PetscCall(PetscSegBufferCreate(1, 4000, &vseg));
483       PetscCall(PetscSegBufferCreate(1, 2000, &aseg));
484 
485       /* the following line will not work when opening initial files (like .petscrc) since info is not yet set */
486       PetscCall(PetscInfo(NULL, "Opened options file %s\n", file));
487 
488       while ((string = Petscgetline(fd))) {
489         /* eliminate comments from each line */
490         PetscCall(PetscStrchr(string, cmt, &cmatch));
491         if (cmatch) *cmatch = 0;
492         PetscCall(PetscStrlen(string, &len));
493         /* replace tabs, ^M, \n with " " */
494         for (size_t i = 0; i < len; i++) {
495           if (string[i] == '\t' || string[i] == '\r' || string[i] == '\n') string[i] = ' ';
496         }
497         PetscCall(PetscTokenCreate(string, ' ', &token));
498         PetscCall(PetscTokenFind(token, &tokens[0]));
499         if (!tokens[0]) {
500           goto destroy;
501         } else if (!tokens[0][0]) { /* if token 0 is empty (string begins with spaces), redo */
502           PetscCall(PetscTokenFind(token, &tokens[0]));
503         }
504         for (PetscInt i = 1; i < 4; i++) PetscCall(PetscTokenFind(token, &tokens[i]));
505         if (!tokens[0]) {
506           goto destroy;
507         } else if (tokens[0][0] == '-') {
508           PetscCall(PetscOptionsValidKey(tokens[0], &valid));
509           PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": invalid option %s", fname, line, tokens[0]);
510           PetscCall(PetscStrlen(tokens[0], &len));
511           PetscCall(PetscSegBufferGet(vseg, len + 1, &vstring));
512           PetscCall(PetscArraycpy(vstring, tokens[0], len));
513           vstring[len] = ' ';
514           if (tokens[1]) {
515             PetscCall(PetscOptionsValidKey(tokens[1], &valid));
516             PetscCheck(!valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": cannot specify two options per line (%s %s)", fname, line, tokens[0], tokens[1]);
517             PetscCall(PetscStrlen(tokens[1], &len));
518             PetscCall(PetscSegBufferGet(vseg, len + 3, &vstring));
519             vstring[0] = '"';
520             PetscCall(PetscArraycpy(vstring + 1, tokens[1], len));
521             vstring[len + 1] = '"';
522             vstring[len + 2] = ' ';
523           }
524         } else {
525           PetscCall(PetscStrcasecmp(tokens[0], "alias", &alias));
526           PetscCheck(alias, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown first token in options file %s line %" PetscInt_FMT ": %s", fname, line, tokens[0]);
527           PetscCall(PetscOptionsValidKey(tokens[1], &valid));
528           PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": invalid aliased option %s", fname, line, tokens[1]);
529           PetscCheck(tokens[2], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": alias missing for %s", fname, line, tokens[1]);
530           PetscCall(PetscOptionsValidKey(tokens[2], &valid));
531           PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": invalid aliasee option %s", fname, line, tokens[2]);
532           PetscCall(PetscStrlen(tokens[1], &len));
533           PetscCall(PetscSegBufferGet(aseg, len + 1, &astring));
534           PetscCall(PetscArraycpy(astring, tokens[1], len));
535           astring[len] = ' ';
536 
537           PetscCall(PetscStrlen(tokens[2], &len));
538           PetscCall(PetscSegBufferGet(aseg, len + 1, &astring));
539           PetscCall(PetscArraycpy(astring, tokens[2], len));
540           astring[len] = ' ';
541         }
542         {
543           const char *extraToken = alias ? tokens[3] : tokens[2];
544           PetscCheck(!extraToken, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": extra token %s", fname, line, extraToken);
545         }
546       destroy:
547         free(string);
548         PetscCall(PetscTokenDestroy(&token));
549         alias = PETSC_FALSE;
550         line++;
551       }
552       err = fclose(fd);
553       PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file %s", fname);
554       PetscCall(PetscSegBufferGetSize(aseg, &bytes)); /* size without null termination */
555       PetscCall(PetscMPIIntCast(bytes, &acnt));
556       PetscCall(PetscSegBufferGet(aseg, 1, &astring));
557       astring[0] = 0;
558       PetscCall(PetscSegBufferGetSize(vseg, &bytes)); /* size without null termination */
559       PetscCall(PetscMPIIntCast(bytes, &cnt));
560       PetscCall(PetscSegBufferGet(vseg, 1, &vstring));
561       vstring[0] = 0;
562       PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
563       PetscCall(PetscSegBufferExtractTo(aseg, packed));
564       PetscCall(PetscSegBufferExtractTo(vseg, packed + acnt + 1));
565       PetscCall(PetscSegBufferDestroy(&aseg));
566       PetscCall(PetscSegBufferDestroy(&vseg));
567     } else PetscCheck(!require, PETSC_COMM_SELF, PETSC_ERR_USER, "Unable to open options file %s", fname);
568   }
569 
570   counts[0] = acnt;
571   counts[1] = cnt;
572   err       = MPI_Bcast(counts, 2, MPI_INT, 0, comm);
573   PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_LIB, "Error in first MPI collective call, could be caused by using an incorrect mpiexec or a network problem, it can be caused by having VPN running: see https://petsc.org/release/faq/");
574   acnt = counts[0];
575   cnt  = counts[1];
576   if (rank) PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
577   if (acnt || cnt) {
578     PetscCallMPI(MPI_Bcast(packed, 2 + acnt + cnt, MPI_CHAR, 0, comm));
579     astring = packed;
580     vstring = packed + acnt + 1;
581   }
582 
583   if (acnt) {
584     PetscCall(PetscTokenCreate(astring, ' ', &token));
585     PetscCall(PetscTokenFind(token, &tokens[0]));
586     while (tokens[0]) {
587       PetscCall(PetscTokenFind(token, &tokens[1]));
588       PetscCall(PetscOptionsSetAlias(options, tokens[0], tokens[1]));
589       PetscCall(PetscTokenFind(token, &tokens[0]));
590     }
591     PetscCall(PetscTokenDestroy(&token));
592   }
593 
594   if (cnt) PetscCall(PetscOptionsInsertString_Private(options, vstring, PETSC_OPT_FILE));
595   PetscCall(PetscFree(packed));
596   PetscFunctionReturn(PETSC_SUCCESS);
597 }
598 
599 /*@
600   PetscOptionsInsertFile - Inserts options into the database from a file.
601 
602   Collective
603 
604   Input Parameters:
605 + comm    - the processes that will share the options (usually `PETSC_COMM_WORLD`)
606 . options - options database, use `NULL` for default global database
607 . file    - name of file,
608            ".yml" and ".yaml" filename extensions are inserted as YAML options,
609            append ":yaml" to filename to force YAML options.
610 - require - if `PETSC_TRUE` will generate an error if the file does not exist
611 
612   Level: developer
613 
614   Notes:
615   Use  # for lines that are comments and which should be ignored.
616   Usually, instead of using this command, one should list the file name in the call to `PetscInitialize()`, this insures that certain options
617   such as `-log_view` or `-malloc_debug` are processed properly. This routine only sets options into the options database that will be processed by later
618   calls to `XXXSetFromOptions()`, it should not be used for options listed under PetscInitialize().
619   The collectivity of this routine is complex; only the MPI processes in comm will
620   have the effect of these options. If some processes that create objects call this routine and others do
621   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
622   on different ranks.
623 
624 .seealso: `PetscOptionsSetValue()`, `PetscOptionsView()`, `PetscOptionsHasName()`, `PetscOptionsGetInt()`,
625           `PetscOptionsGetReal()`, `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
626           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
627           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
628           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
629           `PetscOptionsFList()`, `PetscOptionsEList()`
630 @*/
631 PetscErrorCode PetscOptionsInsertFile(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
632 {
633   char      filename[PETSC_MAX_PATH_LEN];
634   PetscBool yaml;
635 
636   PetscFunctionBegin;
637   PetscCall(PetscOptionsFilename(comm, file, filename, &yaml));
638   if (yaml) {
639     PetscCall(PetscOptionsInsertFileYAML(comm, options, filename, require));
640   } else {
641     PetscCall(PetscOptionsInsertFilePetsc(comm, options, filename, require));
642   }
643   PetscFunctionReturn(PETSC_SUCCESS);
644 }
645 
646 /*@C
647   PetscOptionsInsertArgs - Inserts options into the database from a array of strings
648 
649   Logically Collective
650 
651   Input Parameters:
652 + options - options object
653 . argc    - the array length
654 - args    - the string array
655 
656   Level: intermediate
657 
658 .seealso: `PetscOptions`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`
659 @*/
660 PetscErrorCode PetscOptionsInsertArgs(PetscOptions options, int argc, const char *const args[])
661 {
662   MPI_Comm           comm  = PETSC_COMM_WORLD;
663   int                left  = PetscMax(argc, 0);
664   const char *const *eargs = args;
665 
666   PetscFunctionBegin;
667   while (left) {
668     PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;
669     PetscCall(PetscStrcasecmp(eargs[0], "-options_file", &isfile));
670     PetscCall(PetscStrcasecmp(eargs[0], "-options_file_yaml", &isfileyaml));
671     PetscCall(PetscStrcasecmp(eargs[0], "-options_string_yaml", &isstringyaml));
672     PetscCall(PetscStrcasecmp(eargs[0], "-prefix_push", &ispush));
673     PetscCall(PetscStrcasecmp(eargs[0], "-prefix_pop", &ispop));
674     PetscCall(PetscOptionsValidKey(eargs[0], &key));
675     if (!key) {
676       eargs++;
677       left--;
678     } else if (isfile) {
679       PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file filename option");
680       PetscCall(PetscOptionsInsertFile(comm, options, eargs[1], PETSC_TRUE));
681       eargs += 2;
682       left -= 2;
683     } else if (isfileyaml) {
684       PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file_yaml filename option");
685       PetscCall(PetscOptionsInsertFileYAML(comm, options, eargs[1], PETSC_TRUE));
686       eargs += 2;
687       left -= 2;
688     } else if (isstringyaml) {
689       PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing string for -options_string_yaml string option");
690       PetscCall(PetscOptionsInsertStringYAML_Private(options, eargs[1], PETSC_OPT_CODE));
691       eargs += 2;
692       left -= 2;
693     } else if (ispush) {
694       PetscCheck(left > 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option");
695       PetscCheck(eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option (prefixes cannot start with '-')");
696       PetscCall(PetscOptionsPrefixPush(options, eargs[1]));
697       eargs += 2;
698       left -= 2;
699     } else if (ispop) {
700       PetscCall(PetscOptionsPrefixPop(options));
701       eargs++;
702       left--;
703     } else {
704       PetscBool nextiskey = PETSC_FALSE;
705       if (left >= 2) PetscCall(PetscOptionsValidKey(eargs[1], &nextiskey));
706       if (left < 2 || nextiskey) {
707         PetscCall(PetscOptionsSetValue_Private(options, eargs[0], NULL, NULL, PETSC_OPT_COMMAND_LINE));
708         eargs++;
709         left--;
710       } else {
711         PetscCall(PetscOptionsSetValue_Private(options, eargs[0], eargs[1], NULL, PETSC_OPT_COMMAND_LINE));
712         eargs += 2;
713         left -= 2;
714       }
715     }
716   }
717   PetscFunctionReturn(PETSC_SUCCESS);
718 }
719 
720 static inline PetscErrorCode PetscOptionsStringToBoolIfSet_Private(enum PetscPrecedentOption opt, const char *val[], const PetscBool set[], PetscBool *flg)
721 {
722   PetscFunctionBegin;
723   if (set[opt]) PetscCall(PetscOptionsStringToBool(val[opt], flg));
724   else *flg = PETSC_FALSE;
725   PetscFunctionReturn(PETSC_SUCCESS);
726 }
727 
728 /* Process options with absolute precedence, these are only processed from the command line, not the environment or files */
729 static PetscErrorCode PetscOptionsProcessPrecedentFlags(PetscOptions options, int argc, char *args[], PetscBool *skip_petscrc, PetscBool *skip_petscrc_set)
730 {
731   const char *const *opt = precedentOptions;
732   const size_t       n   = PO_NUM;
733   size_t             o;
734   int                a;
735   const char       **val;
736   char             **cval;
737   PetscBool         *set, unneeded;
738 
739   PetscFunctionBegin;
740   PetscCall(PetscCalloc2(n, &cval, n, &set));
741   val = (const char **)cval;
742 
743   /* Look for options possibly set using PetscOptionsSetValue beforehand */
744   for (o = 0; o < n; o++) PetscCall(PetscOptionsFindPair(options, NULL, opt[o], &val[o], &set[o]));
745 
746   /* Loop through all args to collect last occurring value of each option */
747   for (a = 1; a < argc; a++) {
748     PetscBool valid, eq;
749 
750     PetscCall(PetscOptionsValidKey(args[a], &valid));
751     if (!valid) continue;
752     for (o = 0; o < n; o++) {
753       PetscCall(PetscStrcasecmp(args[a], opt[o], &eq));
754       if (eq) {
755         set[o] = PETSC_TRUE;
756         if (a == argc - 1 || !args[a + 1] || !args[a + 1][0] || args[a + 1][0] == '-') val[o] = NULL;
757         else val[o] = args[a + 1];
758         break;
759       }
760     }
761   }
762 
763   /* Process flags */
764   PetscCall(PetscStrcasecmp(val[PO_HELP], "intro", &options->help_intro));
765   if (options->help_intro) options->help = PETSC_TRUE;
766   else PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_HELP, val, set, &options->help));
767   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_CI_ENABLE, val, set, &unneeded));
768   /* need to manage PO_CI_ENABLE option before the PetscOptionsMonitor is turned on, so its setting is not monitored */
769   if (set[PO_CI_ENABLE]) PetscCall(PetscOptionsSetValue_Private(options, opt[PO_CI_ENABLE], val[PO_CI_ENABLE], &a, PETSC_OPT_COMMAND_LINE));
770   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR_CANCEL, val, set, &options->monitorCancel));
771   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR, val, set, &options->monitorFromOptions));
772   PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_SKIP_PETSCRC, val, set, skip_petscrc));
773   *skip_petscrc_set = set[PO_SKIP_PETSCRC];
774 
775   /* Store precedent options in database and mark them as used */
776   for (o = 1; o < n; o++) {
777     if (set[o]) {
778       PetscCall(PetscOptionsSetValue_Private(options, opt[o], val[o], &a, PETSC_OPT_COMMAND_LINE));
779       options->used[a] = PETSC_TRUE;
780     }
781   }
782   PetscCall(PetscFree2(cval, set));
783   options->precedentProcessed = PETSC_TRUE;
784   PetscFunctionReturn(PETSC_SUCCESS);
785 }
786 
787 static inline PetscErrorCode PetscOptionsSkipPrecedent(PetscOptions options, const char name[], PetscBool *flg)
788 {
789   PetscFunctionBegin;
790   PetscAssertPointer(flg, 3);
791   *flg = PETSC_FALSE;
792   if (options->precedentProcessed) {
793     for (int i = 0; i < PO_NUM; ++i) {
794       if (!PetscOptNameCmp(precedentOptions[i], name)) {
795         /* check if precedent option has been set already */
796         PetscCall(PetscOptionsFindPair(options, NULL, name, NULL, flg));
797         if (*flg) break;
798       }
799     }
800   }
801   PetscFunctionReturn(PETSC_SUCCESS);
802 }
803 
804 /*@C
805   PetscOptionsInsert - Inserts into the options database from the command line,
806   the environmental variable and a file.
807 
808   Collective on `PETSC_COMM_WORLD`
809 
810   Input Parameters:
811 + options - options database or `NULL` for the default global database
812 . argc    - count of number of command line arguments
813 . args    - the command line arguments
814 - file    - [optional] PETSc database file, append ":yaml" to filename to specify YAML options format.
815           Use `NULL` or empty string to not check for code specific file.
816           Also checks ~/.petscrc, .petscrc and petscrc.
817           Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.
818 
819   Options Database Keys:
820 + -options_file <filename>      - read options from a file
821 - -options_file_yaml <filename> - read options from a YAML file
822 
823   Level: advanced
824 
825   Notes:
826   Since `PetscOptionsInsert()` is automatically called by `PetscInitialize()`,
827   the user does not typically need to call this routine. `PetscOptionsInsert()`
828   can be called several times, adding additional entries into the database.
829 
830   See `PetscInitialize()` for options related to option database monitoring.
831 
832 .seealso: `PetscOptionsDestroy()`, `PetscOptionsView()`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`,
833           `PetscInitialize()`
834 @*/
835 PetscErrorCode PetscOptionsInsert(PetscOptions options, int *argc, char ***args, const char file[]) PeNS
836 {
837   MPI_Comm    comm = PETSC_COMM_WORLD;
838   PetscMPIInt rank;
839   PetscBool   hasArgs     = (argc && *argc) ? PETSC_TRUE : PETSC_FALSE;
840   PetscBool   skipPetscrc = PETSC_FALSE, skipPetscrcSet = PETSC_FALSE;
841   char       *eoptions = NULL;
842   size_t      len      = 0;
843 
844   PetscFunctionBegin;
845   PetscCheck(!hasArgs || (args && *args), comm, PETSC_ERR_ARG_NULL, "*argc > 1 but *args not given");
846   PetscCallMPI(MPI_Comm_rank(comm, &rank));
847 
848   if (!options) {
849     PetscCall(PetscOptionsCreateDefault());
850     options = defaultoptions;
851   }
852   if (hasArgs) {
853     /* process options with absolute precedence */
854     PetscCall(PetscOptionsProcessPrecedentFlags(options, *argc, *args, &skipPetscrc, &skipPetscrcSet));
855     PetscCall(PetscOptionsGetBool(NULL, NULL, "-petsc_ci", &PetscCIEnabled, NULL));
856   }
857   if (file && file[0]) {
858     PetscCall(PetscOptionsInsertFile(comm, options, file, PETSC_TRUE));
859     /* if -skip_petscrc has not been set from command line, check whether it has been set in the file */
860     if (!skipPetscrcSet) PetscCall(PetscOptionsGetBool(options, NULL, "-skip_petscrc", &skipPetscrc, NULL));
861   }
862   if (!skipPetscrc) {
863     char filename[PETSC_MAX_PATH_LEN];
864 
865     PetscCall(PetscGetHomeDirectory(filename, sizeof(filename)));
866     PetscCallMPI(MPI_Bcast(filename, (int)sizeof(filename), MPI_CHAR, 0, comm));
867     if (filename[0]) PetscCall(PetscStrlcat(filename, "/.petscrc", sizeof(filename)));
868     PetscCall(PetscOptionsInsertFile(comm, options, filename, PETSC_FALSE));
869     PetscCall(PetscOptionsInsertFile(comm, options, ".petscrc", PETSC_FALSE));
870     PetscCall(PetscOptionsInsertFile(comm, options, "petscrc", PETSC_FALSE));
871   }
872 
873   /* insert environment options */
874   if (rank == 0) {
875     eoptions = getenv("PETSC_OPTIONS");
876     PetscCall(PetscStrlen(eoptions, &len));
877   }
878   PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, comm));
879   if (len) {
880     if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
881     PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, comm));
882     if (rank) eoptions[len] = 0;
883     PetscCall(PetscOptionsInsertString_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
884     if (rank) PetscCall(PetscFree(eoptions));
885   }
886 
887   /* insert YAML environment options */
888   if (rank == 0) {
889     eoptions = getenv("PETSC_OPTIONS_YAML");
890     PetscCall(PetscStrlen(eoptions, &len));
891   }
892   PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, comm));
893   if (len) {
894     if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
895     PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, comm));
896     if (rank) eoptions[len] = 0;
897     PetscCall(PetscOptionsInsertStringYAML_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
898     if (rank) PetscCall(PetscFree(eoptions));
899   }
900 
901   /* insert command line options here because they take precedence over arguments in petscrc/environment */
902   if (hasArgs) PetscCall(PetscOptionsInsertArgs(options, *argc - 1, (const char *const *)*args + 1));
903   PetscCall(PetscOptionsGetBool(NULL, NULL, "-petsc_ci_portable_error_output", &PetscCIEnabledPortableErrorOutput, NULL));
904   PetscFunctionReturn(PETSC_SUCCESS);
905 }
906 
907 /* These options are not printed with PetscOptionsView() or PetscOptionsMonitor() when PetscCIEnabled is on */
908 /* TODO: get the list from the test harness, do not have it hardwired here. Maybe from gmakegentest.py */
909 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"};
910 
911 static PetscBool PetscCIOption(const char *name)
912 {
913   PetscInt  idx;
914   PetscBool found;
915 
916   if (!PetscCIEnabled) return PETSC_FALSE;
917   PetscCallAbort(PETSC_COMM_SELF, PetscEListFind(PETSC_STATIC_ARRAY_LENGTH(PetscCIOptions), PetscCIOptions, name, &idx, &found));
918   return found;
919 }
920 
921 /*@
922   PetscOptionsView - Prints the options that have been loaded. This is
923   useful for debugging purposes.
924 
925   Logically Collective, No Fortran Support
926 
927   Input Parameters:
928 + options - options database, use `NULL` for default global database
929 - viewer  - must be an `PETSCVIEWERASCII` viewer
930 
931   Options Database Key:
932 . -options_view - Activates `PetscOptionsView()` within `PetscFinalize()`
933 
934   Level: advanced
935 
936   Note:
937   Only the MPI rank 0 of the `MPI_Comm` used to create view prints the option values. Other processes
938   may have different values but they are not printed.
939 
940 .seealso: `PetscOptionsAllUsed()`
941 @*/
942 PetscErrorCode PetscOptionsView(PetscOptions options, PetscViewer viewer)
943 {
944   PetscInt  i, N = 0;
945   PetscBool isascii;
946 
947   PetscFunctionBegin;
948   if (viewer) PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
949   options = options ? options : defaultoptions;
950   if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
951   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
952   PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
953 
954   for (i = 0; i < options->N; i++) {
955     if (PetscCIOption(options->names[i])) continue;
956     N++;
957   }
958 
959   if (!N) {
960     PetscCall(PetscViewerASCIIPrintf(viewer, "#No PETSc Option Table entries\n"));
961     PetscFunctionReturn(PETSC_SUCCESS);
962   }
963 
964   PetscCall(PetscViewerASCIIPrintf(viewer, "#PETSc Option Table entries:\n"));
965   for (i = 0; i < options->N; i++) {
966     if (PetscCIOption(options->names[i])) continue;
967     if (options->values[i]) {
968       PetscCall(PetscViewerASCIIPrintf(viewer, "-%s %s", options->names[i], options->values[i]));
969     } else {
970       PetscCall(PetscViewerASCIIPrintf(viewer, "-%s", options->names[i]));
971     }
972     PetscCall(PetscViewerASCIIPrintf(viewer, " # (source: %s)\n", PetscOptionSources[options->source[i]]));
973   }
974   PetscCall(PetscViewerASCIIPrintf(viewer, "#End of PETSc Option Table entries\n"));
975   PetscFunctionReturn(PETSC_SUCCESS);
976 }
977 
978 /*
979    Called by error handlers to print options used in run
980 */
981 PetscErrorCode PetscOptionsLeftError(void)
982 {
983   PetscInt i, nopt = 0;
984 
985   for (i = 0; i < defaultoptions->N; i++) {
986     if (!defaultoptions->used[i]) {
987       if (PetscCIOption(defaultoptions->names[i])) continue;
988       nopt++;
989     }
990   }
991   if (nopt) {
992     PetscCall((*PetscErrorPrintf)("WARNING! There are unused option(s) set! Could be the program crashed before usage or a spelling mistake, etc!\n"));
993     for (i = 0; i < defaultoptions->N; i++) {
994       if (!defaultoptions->used[i]) {
995         if (PetscCIOption(defaultoptions->names[i])) continue;
996         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]]));
997         else PetscCall((*PetscErrorPrintf)("  Option left: name:-%s (no value) source: %s\n", defaultoptions->names[i], PetscOptionSources[defaultoptions->source[i]]));
998       }
999     }
1000   }
1001   return PETSC_SUCCESS;
1002 }
1003 
1004 PETSC_EXTERN PetscErrorCode PetscOptionsViewError(void)
1005 {
1006   PetscInt     i, N = 0;
1007   PetscOptions options = defaultoptions;
1008 
1009   for (i = 0; i < options->N; i++) {
1010     if (PetscCIOption(options->names[i])) continue;
1011     N++;
1012   }
1013 
1014   if (N) {
1015     PetscCall((*PetscErrorPrintf)("PETSc Option Table entries:\n"));
1016   } else {
1017     PetscCall((*PetscErrorPrintf)("No PETSc Option Table entries\n"));
1018   }
1019   for (i = 0; i < options->N; i++) {
1020     if (PetscCIOption(options->names[i])) continue;
1021     if (options->values[i]) {
1022       PetscCall((*PetscErrorPrintf)("-%s %s (source: %s)\n", options->names[i], options->values[i], PetscOptionSources[options->source[i]]));
1023     } else {
1024       PetscCall((*PetscErrorPrintf)("-%s (source: %s)\n", options->names[i], PetscOptionSources[options->source[i]]));
1025     }
1026   }
1027   return PETSC_SUCCESS;
1028 }
1029 
1030 /*@
1031   PetscOptionsPrefixPush - Designate a prefix to be used by all options insertions to follow.
1032 
1033   Logically Collective
1034 
1035   Input Parameters:
1036 + options - options database, or `NULL` for the default global database
1037 - prefix  - The string to append to the existing prefix
1038 
1039   Options Database Keys:
1040 + -prefix_push <some_prefix_> - push the given prefix
1041 - -prefix_pop                 - pop the last prefix
1042 
1043   Level: advanced
1044 
1045   Notes:
1046   It is common to use this in conjunction with `-options_file` as in
1047 .vb
1048  -prefix_push system1_ -options_file system1rc -prefix_pop -prefix_push system2_ -options_file system2rc -prefix_pop
1049 .ve
1050   where the files no longer require all options to be prefixed with `-system2_`.
1051 
1052   The collectivity of this routine is complex; only the MPI processes that call this routine will
1053   have the affect of these options. If some processes that create objects call this routine and others do
1054   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1055   on different ranks.
1056 
1057 .seealso: `PetscOptionsPrefixPop()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1058 @*/
1059 PetscErrorCode PetscOptionsPrefixPush(PetscOptions options, const char prefix[])
1060 {
1061   size_t    n;
1062   PetscInt  start;
1063   char      key[PETSC_MAX_OPTION_NAME + 1];
1064   PetscBool valid;
1065 
1066   PetscFunctionBegin;
1067   PetscAssertPointer(prefix, 2);
1068   options = options ? options : defaultoptions;
1069   PetscCheck(options->prefixind < MAXPREFIXES, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum depth of prefix stack %d exceeded, recompile src/sys/objects/options.c with larger value for MAXPREFIXES", MAXPREFIXES);
1070   key[0] = '-'; /* keys must start with '-' */
1071   PetscCall(PetscStrncpy(key + 1, prefix, sizeof(key) - 1));
1072   PetscCall(PetscOptionsValidKey(key, &valid));
1073   if (!valid && options->prefixind > 0 && isdigit((int)prefix[0])) valid = PETSC_TRUE; /* If the prefix stack is not empty, make numbers a valid prefix */
1074   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" : "");
1075   start = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1076   PetscCall(PetscStrlen(prefix, &n));
1077   PetscCheck(n + 1 <= sizeof(options->prefix) - start, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum prefix length %zu exceeded", sizeof(options->prefix));
1078   PetscCall(PetscArraycpy(options->prefix + start, prefix, n + 1));
1079   options->prefixstack[options->prefixind++] = (int)(start + n);
1080   PetscFunctionReturn(PETSC_SUCCESS);
1081 }
1082 
1083 /*@
1084   PetscOptionsPrefixPop - Remove the latest options prefix, see `PetscOptionsPrefixPush()` for details
1085 
1086   Logically Collective on the `MPI_Comm` used when called `PetscOptionsPrefixPush()`
1087 
1088   Input Parameter:
1089 . options - options database, or `NULL` for the default global database
1090 
1091   Level: advanced
1092 
1093 .seealso: `PetscOptionsPrefixPush()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1094 @*/
1095 PetscErrorCode PetscOptionsPrefixPop(PetscOptions options)
1096 {
1097   PetscInt offset;
1098 
1099   PetscFunctionBegin;
1100   options = options ? options : defaultoptions;
1101   PetscCheck(options->prefixind >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More prefixes popped than pushed");
1102   options->prefixind--;
1103   offset                  = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1104   options->prefix[offset] = 0;
1105   PetscFunctionReturn(PETSC_SUCCESS);
1106 }
1107 
1108 /*@
1109   PetscOptionsClear - Removes all options form the database leaving it empty.
1110 
1111   Logically Collective
1112 
1113   Input Parameter:
1114 . options - options database, use `NULL` for the default global database
1115 
1116   Level: developer
1117 
1118   Note:
1119   The collectivity of this routine is complex; only the MPI processes that call this routine will
1120   have the affect of these options. If some processes that create objects call this routine and others do
1121   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1122   on different ranks.
1123 
1124   Developer Note:
1125   Uses `free()` directly because the current option values were set with `malloc()`
1126 
1127 .seealso: `PetscOptionsInsert()`
1128 @*/
1129 PetscErrorCode PetscOptionsClear(PetscOptions options)
1130 {
1131   PetscInt i;
1132 
1133   PetscFunctionBegin;
1134   options = options ? options : defaultoptions;
1135   if (!options) PetscFunctionReturn(PETSC_SUCCESS);
1136 
1137   for (i = 0; i < options->N; i++) {
1138     if (options->names[i]) free(options->names[i]);
1139     if (options->values[i]) free(options->values[i]);
1140   }
1141   options->N = 0;
1142   free(options->names);
1143   free(options->values);
1144   free(options->used);
1145   free(options->source);
1146   options->names  = NULL;
1147   options->values = NULL;
1148   options->used   = NULL;
1149   options->source = NULL;
1150   options->Nalloc = 0;
1151 
1152   for (i = 0; i < options->Na; i++) {
1153     free(options->aliases1[i]);
1154     free(options->aliases2[i]);
1155   }
1156   options->Na = 0;
1157   free(options->aliases1);
1158   free(options->aliases2);
1159   options->aliases1 = options->aliases2 = NULL;
1160   options->Naalloc                      = 0;
1161 
1162   /* destroy hash table */
1163   kh_destroy(HO, options->ht);
1164   options->ht = NULL;
1165 
1166   options->prefixind  = 0;
1167   options->prefix[0]  = 0;
1168   options->help       = PETSC_FALSE;
1169   options->help_intro = PETSC_FALSE;
1170   PetscFunctionReturn(PETSC_SUCCESS);
1171 }
1172 
1173 /*@
1174   PetscOptionsSetAlias - Makes a key and alias for another key
1175 
1176   Logically Collective
1177 
1178   Input Parameters:
1179 + options - options database, or `NULL` for default global database
1180 . newname - the alias
1181 - oldname - the name that alias will refer to
1182 
1183   Level: advanced
1184 
1185   Note:
1186   The collectivity of this routine is complex; only the MPI processes that call this routine will
1187   have the affect of these options. If some processes that create objects call this routine and others do
1188   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1189   on different ranks.
1190 
1191   Developer Note:
1192   Uses `malloc()` directly because PETSc may not be initialized yet.
1193 
1194 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1195           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1196           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1197           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1198           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1199           `PetscOptionsFList()`, `PetscOptionsEList()`
1200 @*/
1201 PetscErrorCode PetscOptionsSetAlias(PetscOptions options, const char newname[], const char oldname[])
1202 {
1203   size_t    len;
1204   PetscBool valid;
1205 
1206   PetscFunctionBegin;
1207   PetscAssertPointer(newname, 2);
1208   PetscAssertPointer(oldname, 3);
1209   options = options ? options : defaultoptions;
1210   PetscCall(PetscOptionsValidKey(newname, &valid));
1211   PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliased option %s", newname);
1212   PetscCall(PetscOptionsValidKey(oldname, &valid));
1213   PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliasee option %s", oldname);
1214 
1215   if (options->Na == options->Naalloc) {
1216     char **tmpA1, **tmpA2;
1217 
1218     options->Naalloc = PetscMax(4, options->Naalloc * 2);
1219     tmpA1            = (char **)malloc(options->Naalloc * sizeof(char *));
1220     tmpA2            = (char **)malloc(options->Naalloc * sizeof(char *));
1221     for (int i = 0; i < options->Na; ++i) {
1222       tmpA1[i] = options->aliases1[i];
1223       tmpA2[i] = options->aliases2[i];
1224     }
1225     free(options->aliases1);
1226     free(options->aliases2);
1227     options->aliases1 = tmpA1;
1228     options->aliases2 = tmpA2;
1229   }
1230   newname++;
1231   oldname++;
1232   PetscCall(PetscStrlen(newname, &len));
1233   options->aliases1[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1234   PetscCall(PetscStrncpy(options->aliases1[options->Na], newname, len + 1));
1235   PetscCall(PetscStrlen(oldname, &len));
1236   options->aliases2[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1237   PetscCall(PetscStrncpy(options->aliases2[options->Na], oldname, len + 1));
1238   ++options->Na;
1239   PetscFunctionReturn(PETSC_SUCCESS);
1240 }
1241 
1242 /*@
1243   PetscOptionsSetValue - Sets an option name-value pair in the options
1244   database, overriding whatever is already present.
1245 
1246   Logically Collective
1247 
1248   Input Parameters:
1249 + options - options database, use `NULL` for the default global database
1250 . name    - name of option, this SHOULD have the - prepended
1251 - value   - the option value (not used for all options, so can be `NULL`)
1252 
1253   Level: intermediate
1254 
1255   Note:
1256   This function can be called BEFORE `PetscInitialize()`
1257 
1258   The collectivity of this routine is complex; only the MPI processes that call this routine will
1259   have the affect of these options. If some processes that create objects call this routine and others do
1260   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1261   on different ranks.
1262 
1263   Developer Note:
1264   Uses `malloc()` directly because PETSc may not be initialized yet.
1265 
1266 .seealso: `PetscOptionsInsert()`, `PetscOptionsClearValue()`
1267 @*/
1268 PetscErrorCode PetscOptionsSetValue(PetscOptions options, const char name[], const char value[])
1269 {
1270   PetscFunctionBegin;
1271   PetscCall(PetscOptionsSetValue_Private(options, name, value, NULL, PETSC_OPT_CODE));
1272   PetscFunctionReturn(PETSC_SUCCESS);
1273 }
1274 
1275 PetscErrorCode PetscOptionsSetValue_Private(PetscOptions options, const char name[], const char value[], int *pos, PetscOptionSource source)
1276 {
1277   size_t    len;
1278   int       n, i;
1279   char    **names;
1280   char      fullname[PETSC_MAX_OPTION_NAME] = "";
1281   PetscBool flg;
1282 
1283   PetscFunctionBegin;
1284   if (!options) {
1285     PetscCall(PetscOptionsCreateDefault());
1286     options = defaultoptions;
1287   }
1288   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "name %s must start with '-'", name);
1289 
1290   PetscCall(PetscOptionsSkipPrecedent(options, name, &flg));
1291   if (flg) PetscFunctionReturn(PETSC_SUCCESS);
1292 
1293   name++; /* skip starting dash */
1294 
1295   if (options->prefixind > 0) {
1296     strncpy(fullname, options->prefix, sizeof(fullname));
1297     fullname[sizeof(fullname) - 1] = 0;
1298     strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
1299     fullname[sizeof(fullname) - 1] = 0;
1300     name                           = fullname;
1301   }
1302 
1303   /* check against aliases */
1304   for (i = 0; i < options->Na; i++) {
1305     int result = PetscOptNameCmp(options->aliases1[i], name);
1306     if (!result) {
1307       name = options->aliases2[i];
1308       break;
1309     }
1310   }
1311 
1312   /* slow search */
1313   n     = options->N;
1314   names = options->names;
1315   for (i = 0; i < options->N; i++) {
1316     int result = PetscOptNameCmp(names[i], name);
1317     if (!result) {
1318       n = i;
1319       goto setvalue;
1320     } else if (result > 0) {
1321       n = i;
1322       break;
1323     }
1324   }
1325   if (options->N == options->Nalloc) {
1326     char             **names, **values;
1327     PetscBool         *used;
1328     PetscOptionSource *source;
1329 
1330     options->Nalloc = PetscMax(10, options->Nalloc * 2);
1331     names           = (char **)malloc(options->Nalloc * sizeof(char *));
1332     values          = (char **)malloc(options->Nalloc * sizeof(char *));
1333     used            = (PetscBool *)malloc(options->Nalloc * sizeof(PetscBool));
1334     source          = (PetscOptionSource *)malloc(options->Nalloc * sizeof(PetscOptionSource));
1335     for (int i = 0; i < options->N; ++i) {
1336       names[i]  = options->names[i];
1337       values[i] = options->values[i];
1338       used[i]   = options->used[i];
1339       source[i] = options->source[i];
1340     }
1341     free(options->names);
1342     free(options->values);
1343     free(options->used);
1344     free(options->source);
1345     options->names  = names;
1346     options->values = values;
1347     options->used   = used;
1348     options->source = source;
1349   }
1350 
1351   /* shift remaining values up 1 */
1352   for (i = options->N; i > n; i--) {
1353     options->names[i]  = options->names[i - 1];
1354     options->values[i] = options->values[i - 1];
1355     options->used[i]   = options->used[i - 1];
1356     options->source[i] = options->source[i - 1];
1357   }
1358   options->names[n]  = NULL;
1359   options->values[n] = NULL;
1360   options->used[n]   = PETSC_FALSE;
1361   options->source[n] = PETSC_OPT_CODE;
1362   options->N++;
1363 
1364   /* destroy hash table */
1365   kh_destroy(HO, options->ht);
1366   options->ht = NULL;
1367 
1368   /* set new name */
1369   len               = strlen(name);
1370   options->names[n] = (char *)malloc((len + 1) * sizeof(char));
1371   PetscCheck(options->names[n], PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate option name");
1372   strcpy(options->names[n], name);
1373 
1374 setvalue:
1375   /* set new value */
1376   if (options->values[n]) free(options->values[n]);
1377   len = value ? strlen(value) : 0;
1378   if (len) {
1379     options->values[n] = (char *)malloc((len + 1) * sizeof(char));
1380     if (!options->values[n]) return PETSC_ERR_MEM;
1381     strcpy(options->values[n], value);
1382     options->values[n][len] = '\0';
1383   } else {
1384     options->values[n] = NULL;
1385   }
1386   options->source[n] = source;
1387 
1388   /* handle -help so that it can be set from anywhere */
1389   if (!PetscOptNameCmp(name, "help")) {
1390     options->help       = PETSC_TRUE;
1391     options->help_intro = (value && !PetscOptNameCmp(value, "intro")) ? PETSC_TRUE : PETSC_FALSE;
1392     options->used[n]    = PETSC_TRUE;
1393   }
1394 
1395   PetscCall(PetscOptionsMonitor(options, name, value ? value : "", source));
1396   if (pos) *pos = n;
1397   PetscFunctionReturn(PETSC_SUCCESS);
1398 }
1399 
1400 /*@
1401   PetscOptionsClearValue - Clears an option name-value pair in the options
1402   database, overriding whatever is already present.
1403 
1404   Logically Collective
1405 
1406   Input Parameters:
1407 + options - options database, use `NULL` for the default global database
1408 - name    - name of option, this SHOULD have the - prepended
1409 
1410   Level: intermediate
1411 
1412   Note:
1413   The collectivity of this routine is complex; only the MPI processes that call this routine will
1414   have the affect of these options. If some processes that create objects call this routine and others do
1415   not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1416   on different ranks.
1417 
1418   Developer Note:
1419   Uses `free()` directly because the options have been set with `malloc()`
1420 
1421 .seealso: `PetscOptionsInsert()`
1422 @*/
1423 PetscErrorCode PetscOptionsClearValue(PetscOptions options, const char name[])
1424 {
1425   int    N, n, i;
1426   char **names;
1427 
1428   PetscFunctionBegin;
1429   options = options ? options : defaultoptions;
1430   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1431   if (!PetscOptNameCmp(name, "-help")) options->help = options->help_intro = PETSC_FALSE;
1432 
1433   name++; /* skip starting dash */
1434 
1435   /* slow search */
1436   N = n = options->N;
1437   names = options->names;
1438   for (i = 0; i < N; i++) {
1439     int result = PetscOptNameCmp(names[i], name);
1440     if (!result) {
1441       n = i;
1442       break;
1443     } else if (result > 0) {
1444       n = N;
1445       break;
1446     }
1447   }
1448   if (n == N) PetscFunctionReturn(PETSC_SUCCESS); /* it was not present */
1449 
1450   /* remove name and value */
1451   if (options->names[n]) free(options->names[n]);
1452   if (options->values[n]) free(options->values[n]);
1453   /* shift remaining values down 1 */
1454   for (i = n; i < N - 1; i++) {
1455     options->names[i]  = options->names[i + 1];
1456     options->values[i] = options->values[i + 1];
1457     options->used[i]   = options->used[i + 1];
1458     options->source[i] = options->source[i + 1];
1459   }
1460   options->N--;
1461 
1462   /* destroy hash table */
1463   kh_destroy(HO, options->ht);
1464   options->ht = NULL;
1465 
1466   PetscCall(PetscOptionsMonitor(options, name, NULL, PETSC_OPT_CODE));
1467   PetscFunctionReturn(PETSC_SUCCESS);
1468 }
1469 
1470 /*@C
1471   PetscOptionsFindPair - Gets an option name-value pair from the options database.
1472 
1473   Not Collective
1474 
1475   Input Parameters:
1476 + options - options database, use `NULL` for the default global database
1477 . pre     - the string to prepend to the name or `NULL`, this SHOULD NOT have the "-" prepended
1478 - name    - name of option, this SHOULD have the "-" prepended
1479 
1480   Output Parameters:
1481 + value - the option value (optional, not used for all options)
1482 - set   - whether the option is set (optional)
1483 
1484   Level: developer
1485 
1486   Note:
1487   Each process may find different values or no value depending on how options were inserted into the database
1488 
1489 .seealso: `PetscOptionsSetValue()`, `PetscOptionsClearValue()`
1490 @*/
1491 PetscErrorCode PetscOptionsFindPair(PetscOptions options, const char pre[], const char name[], const char *value[], PetscBool *set)
1492 {
1493   char      buf[PETSC_MAX_OPTION_NAME];
1494   PetscBool matchnumbers = PETSC_TRUE;
1495 
1496   PetscFunctionBegin;
1497   if (!options) {
1498     PetscCall(PetscOptionsCreateDefault());
1499     options = defaultoptions;
1500   }
1501   PetscCheck(!pre || !PetscUnlikely(pre[0] == '-'), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1502   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1503 
1504   name++; /* skip starting dash */
1505 
1506   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1507   if (pre && pre[0]) {
1508     char *ptr = buf;
1509     if (name[0] == '-') {
1510       *ptr++ = '-';
1511       name++;
1512     }
1513     PetscCall(PetscStrncpy(ptr, pre, buf + sizeof(buf) - ptr));
1514     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1515     name = buf;
1516   }
1517 
1518   if (PetscDefined(USE_DEBUG)) {
1519     PetscBool valid;
1520     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1521     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1522     PetscCall(PetscOptionsValidKey(key, &valid));
1523     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1524   }
1525 
1526   if (!options->ht) {
1527     int          i, ret;
1528     khiter_t     it;
1529     khash_t(HO) *ht;
1530     ht = kh_init(HO);
1531     PetscCheck(ht, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1532     ret = kh_resize(HO, ht, options->N * 2); /* twice the required size to reduce risk of collisions */
1533     PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1534     for (i = 0; i < options->N; i++) {
1535       it = kh_put(HO, ht, options->names[i], &ret);
1536       PetscCheck(ret == 1, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1537       kh_val(ht, it) = i;
1538     }
1539     options->ht = ht;
1540   }
1541 
1542   khash_t(HO) *ht = options->ht;
1543   khiter_t     it = kh_get(HO, ht, name);
1544   if (it != kh_end(ht)) {
1545     int i            = kh_val(ht, it);
1546     options->used[i] = PETSC_TRUE;
1547     if (value) *value = options->values[i];
1548     if (set) *set = PETSC_TRUE;
1549     PetscFunctionReturn(PETSC_SUCCESS);
1550   }
1551 
1552   /*
1553    The following block slows down all lookups in the most frequent path (most lookups are unsuccessful).
1554    Maybe this special lookup mode should be enabled on request with a push/pop API.
1555    The feature of matching _%d_ used sparingly in the codebase.
1556    */
1557   if (matchnumbers) {
1558     int i, j, cnt = 0, locs[16], loce[16];
1559     /* determine the location and number of all _%d_ in the key */
1560     for (i = 0; name[i]; i++) {
1561       if (name[i] == '_') {
1562         for (j = i + 1; name[j]; j++) {
1563           if (name[j] >= '0' && name[j] <= '9') continue;
1564           if (name[j] == '_' && j > i + 1) { /* found a number */
1565             locs[cnt]   = i + 1;
1566             loce[cnt++] = j + 1;
1567           }
1568           i = j - 1;
1569           break;
1570         }
1571       }
1572     }
1573     for (i = 0; i < cnt; i++) {
1574       PetscBool found;
1575       char      opt[PETSC_MAX_OPTION_NAME + 1] = "-", tmp[PETSC_MAX_OPTION_NAME];
1576       PetscCall(PetscStrncpy(tmp, name, PetscMin((size_t)(locs[i] + 1), sizeof(tmp))));
1577       PetscCall(PetscStrlcat(opt, tmp, sizeof(opt)));
1578       PetscCall(PetscStrlcat(opt, name + loce[i], sizeof(opt)));
1579       PetscCall(PetscOptionsFindPair(options, NULL, opt, value, &found));
1580       if (found) {
1581         if (set) *set = PETSC_TRUE;
1582         PetscFunctionReturn(PETSC_SUCCESS);
1583       }
1584     }
1585   }
1586 
1587   if (set) *set = PETSC_FALSE;
1588   PetscFunctionReturn(PETSC_SUCCESS);
1589 }
1590 
1591 /* Check whether any option begins with pre+name */
1592 PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions options, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *set)
1593 {
1594   char buf[PETSC_MAX_OPTION_NAME];
1595   int  numCnt = 0, locs[16], loce[16];
1596 
1597   PetscFunctionBegin;
1598   options = options ? options : defaultoptions;
1599   PetscCheck(!pre || pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1600   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1601 
1602   name++; /* skip starting dash */
1603 
1604   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1605   if (pre && pre[0]) {
1606     char *ptr = buf;
1607     if (name[0] == '-') {
1608       *ptr++ = '-';
1609       name++;
1610     }
1611     PetscCall(PetscStrncpy(ptr, pre, sizeof(buf) - ((ptr == buf) ? 0 : 1)));
1612     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1613     name = buf;
1614   }
1615 
1616   if (PetscDefined(USE_DEBUG)) {
1617     PetscBool valid;
1618     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1619     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1620     PetscCall(PetscOptionsValidKey(key, &valid));
1621     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1622   }
1623 
1624   /* determine the location and number of all _%d_ in the key */
1625   {
1626     int i, j;
1627     for (i = 0; name[i]; i++) {
1628       if (name[i] == '_') {
1629         for (j = i + 1; name[j]; j++) {
1630           if (name[j] >= '0' && name[j] <= '9') continue;
1631           if (name[j] == '_' && j > i + 1) { /* found a number */
1632             locs[numCnt]   = i + 1;
1633             loce[numCnt++] = j + 1;
1634           }
1635           i = j - 1;
1636           break;
1637         }
1638       }
1639     }
1640   }
1641 
1642   /* slow search */
1643   for (int c = -1; c < numCnt; ++c) {
1644     char   opt[PETSC_MAX_OPTION_NAME + 2] = "";
1645     size_t len;
1646 
1647     if (c < 0) {
1648       PetscCall(PetscStrncpy(opt, name, sizeof(opt)));
1649     } else {
1650       PetscCall(PetscStrncpy(opt, name, PetscMin((size_t)(locs[c] + 1), sizeof(opt))));
1651       PetscCall(PetscStrlcat(opt, name + loce[c], sizeof(opt) - 1));
1652     }
1653     PetscCall(PetscStrlen(opt, &len));
1654     for (int i = 0; i < options->N; i++) {
1655       PetscBool match;
1656 
1657       PetscCall(PetscStrncmp(options->names[i], opt, len, &match));
1658       if (match) {
1659         options->used[i] = PETSC_TRUE;
1660         if (option) *option = options->names[i];
1661         if (value) *value = options->values[i];
1662         if (set) *set = PETSC_TRUE;
1663         PetscFunctionReturn(PETSC_SUCCESS);
1664       }
1665     }
1666   }
1667 
1668   if (set) *set = PETSC_FALSE;
1669   PetscFunctionReturn(PETSC_SUCCESS);
1670 }
1671 
1672 /*@
1673   PetscOptionsReject - Generates an error if a certain option is given.
1674 
1675   Not Collective
1676 
1677   Input Parameters:
1678 + options - options database, use `NULL` for default global database
1679 . pre     - the option prefix (may be `NULL`)
1680 . name    - the option name one is seeking
1681 - mess    - error message (may be `NULL`)
1682 
1683   Level: advanced
1684 
1685 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1686           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1687           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1688           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1689           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1690           `PetscOptionsFList()`, `PetscOptionsEList()`
1691 @*/
1692 PetscErrorCode PetscOptionsReject(PetscOptions options, const char pre[], const char name[], const char mess[])
1693 {
1694   PetscBool flag = PETSC_FALSE;
1695 
1696   PetscFunctionBegin;
1697   PetscCall(PetscOptionsHasName(options, pre, name, &flag));
1698   if (flag) {
1699     PetscCheck(!mess || !mess[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s with %s", pre ? pre : "", name + 1, mess);
1700     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s", pre ? pre : "", name + 1);
1701   }
1702   PetscFunctionReturn(PETSC_SUCCESS);
1703 }
1704 
1705 /*@
1706   PetscOptionsHasHelp - Determines whether the "-help" option is in the database.
1707 
1708   Not Collective
1709 
1710   Input Parameter:
1711 . options - options database, use `NULL` for default global database
1712 
1713   Output Parameter:
1714 . set - `PETSC_TRUE` if found else `PETSC_FALSE`.
1715 
1716   Level: advanced
1717 
1718 .seealso: `PetscOptionsHasName()`
1719 @*/
1720 PetscErrorCode PetscOptionsHasHelp(PetscOptions options, PetscBool *set)
1721 {
1722   PetscFunctionBegin;
1723   PetscAssertPointer(set, 2);
1724   options = options ? options : defaultoptions;
1725   *set    = options->help;
1726   PetscFunctionReturn(PETSC_SUCCESS);
1727 }
1728 
1729 PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions options, PetscBool *set)
1730 {
1731   PetscFunctionBegin;
1732   PetscAssertPointer(set, 2);
1733   options = options ? options : defaultoptions;
1734   *set    = options->help_intro;
1735   PetscFunctionReturn(PETSC_SUCCESS);
1736 }
1737 
1738 /*@
1739   PetscOptionsHasName - Determines whether a certain option is given in the database. This returns true whether the option is a number, string or Boolean, even
1740   if its value is set to false.
1741 
1742   Not Collective
1743 
1744   Input Parameters:
1745 + options - options database, use `NULL` for default global database
1746 . pre     - string to prepend to the name or `NULL`
1747 - name    - the option one is seeking
1748 
1749   Output Parameter:
1750 . set - `PETSC_TRUE` if found else `PETSC_FALSE`.
1751 
1752   Level: beginner
1753 
1754   Note:
1755   In many cases you probably want to use `PetscOptionsGetBool()` instead of calling this, to allowing toggling values.
1756 
1757 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1758           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1759           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1760           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1761           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1762           `PetscOptionsFList()`, `PetscOptionsEList()`
1763 @*/
1764 PetscErrorCode PetscOptionsHasName(PetscOptions options, const char pre[], const char name[], PetscBool *set)
1765 {
1766   const char *value;
1767   PetscBool   flag;
1768 
1769   PetscFunctionBegin;
1770   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
1771   if (set) *set = flag;
1772   PetscFunctionReturn(PETSC_SUCCESS);
1773 }
1774 
1775 /*@C
1776   PetscOptionsGetAll - Lists all the options the program was run with in a single string.
1777 
1778   Not Collective
1779 
1780   Input Parameter:
1781 . options - the options database, use `NULL` for the default global database
1782 
1783   Output Parameter:
1784 . copts - pointer where string pointer is stored
1785 
1786   Level: advanced
1787 
1788   Notes:
1789   The array and each entry in the array should be freed with `PetscFree()`
1790 
1791   Each process may have different values depending on how the options were inserted into the database
1792 
1793 .seealso: `PetscOptionsAllUsed()`, `PetscOptionsView()`, `PetscOptionsPush()`, `PetscOptionsPop()`
1794 @*/
1795 PetscErrorCode PetscOptionsGetAll(PetscOptions options, char *copts[]) PeNS
1796 {
1797   PetscInt i;
1798   size_t   len = 1, lent = 0;
1799   char    *coptions = NULL;
1800 
1801   PetscFunctionBegin;
1802   PetscAssertPointer(copts, 2);
1803   options = options ? options : defaultoptions;
1804   /* count the length of the required string */
1805   for (i = 0; i < options->N; i++) {
1806     PetscCall(PetscStrlen(options->names[i], &lent));
1807     len += 2 + lent;
1808     if (options->values[i]) {
1809       PetscCall(PetscStrlen(options->values[i], &lent));
1810       len += 1 + lent;
1811     }
1812   }
1813   PetscCall(PetscMalloc1(len, &coptions));
1814   coptions[0] = 0;
1815   for (i = 0; i < options->N; i++) {
1816     PetscCall(PetscStrlcat(coptions, "-", len));
1817     PetscCall(PetscStrlcat(coptions, options->names[i], len));
1818     PetscCall(PetscStrlcat(coptions, " ", len));
1819     if (options->values[i]) {
1820       PetscCall(PetscStrlcat(coptions, options->values[i], len));
1821       PetscCall(PetscStrlcat(coptions, " ", len));
1822     }
1823   }
1824   *copts = coptions;
1825   PetscFunctionReturn(PETSC_SUCCESS);
1826 }
1827 
1828 /*@
1829   PetscOptionsUsed - Indicates if PETSc has used a particular option set in the database
1830 
1831   Not Collective
1832 
1833   Input Parameters:
1834 + options - options database, use `NULL` for default global database
1835 - name    - string name of option
1836 
1837   Output Parameter:
1838 . used - `PETSC_TRUE` if the option was used, otherwise false, including if option was not found in options database
1839 
1840   Level: advanced
1841 
1842   Note:
1843   The value returned may be different on each process and depends on which options have been processed
1844   on the given process
1845 
1846 .seealso: `PetscOptionsView()`, `PetscOptionsLeft()`, `PetscOptionsAllUsed()`
1847 @*/
1848 PetscErrorCode PetscOptionsUsed(PetscOptions options, const char *name, PetscBool *used)
1849 {
1850   PetscInt i;
1851 
1852   PetscFunctionBegin;
1853   PetscAssertPointer(name, 2);
1854   PetscAssertPointer(used, 3);
1855   options = options ? options : defaultoptions;
1856   *used   = PETSC_FALSE;
1857   for (i = 0; i < options->N; i++) {
1858     PetscCall(PetscStrcasecmp(options->names[i], name, used));
1859     if (*used) {
1860       *used = options->used[i];
1861       break;
1862     }
1863   }
1864   PetscFunctionReturn(PETSC_SUCCESS);
1865 }
1866 
1867 /*@
1868   PetscOptionsAllUsed - Returns a count of the number of options in the
1869   database that have never been selected.
1870 
1871   Not Collective
1872 
1873   Input Parameter:
1874 . options - options database, use `NULL` for default global database
1875 
1876   Output Parameter:
1877 . N - count of options not used
1878 
1879   Level: advanced
1880 
1881   Note:
1882   The value returned may be different on each process and depends on which options have been processed
1883   on the given process
1884 
1885 .seealso: `PetscOptionsView()`
1886 @*/
1887 PetscErrorCode PetscOptionsAllUsed(PetscOptions options, PetscInt *N)
1888 {
1889   PetscInt i, n = 0;
1890 
1891   PetscFunctionBegin;
1892   PetscAssertPointer(N, 2);
1893   options = options ? options : defaultoptions;
1894   for (i = 0; i < options->N; i++) {
1895     if (!options->used[i]) n++;
1896   }
1897   *N = n;
1898   PetscFunctionReturn(PETSC_SUCCESS);
1899 }
1900 
1901 /*@
1902   PetscOptionsLeft - Prints to screen any options that were set and never used.
1903 
1904   Not Collective
1905 
1906   Input Parameter:
1907 . options - options database; use `NULL` for default global database
1908 
1909   Options Database Key:
1910 . -options_left - activates `PetscOptionsAllUsed()` within `PetscFinalize()`
1911 
1912   Level: advanced
1913 
1914   Notes:
1915   This is rarely used directly, it is called by `PetscFinalize()` by default (unless
1916   `-options_left false` is specified) to help users determine possible mistakes in their usage of
1917   options. This only prints values on process zero of `PETSC_COMM_WORLD`.
1918 
1919   Other processes depending the objects
1920   used may have different options that are left unused.
1921 
1922 .seealso: `PetscOptionsAllUsed()`
1923 @*/
1924 PetscErrorCode PetscOptionsLeft(PetscOptions options)
1925 {
1926   PetscInt     i;
1927   PetscInt     cnt = 0;
1928   PetscOptions toptions;
1929 
1930   PetscFunctionBegin;
1931   toptions = options ? options : defaultoptions;
1932   for (i = 0; i < toptions->N; i++) {
1933     if (!toptions->used[i]) {
1934       if (PetscCIOption(toptions->names[i])) continue;
1935       if (toptions->values[i]) {
1936         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s value: %s source: %s\n", toptions->names[i], toptions->values[i], PetscOptionSources[toptions->source[i]]));
1937       } else {
1938         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s (no value) source: %s\n", toptions->names[i], PetscOptionSources[toptions->source[i]]));
1939       }
1940     }
1941   }
1942   if (!options) {
1943     toptions = defaultoptions;
1944     while (toptions->previous) {
1945       cnt++;
1946       toptions = toptions->previous;
1947     }
1948     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));
1949   }
1950   PetscFunctionReturn(PETSC_SUCCESS);
1951 }
1952 
1953 /*@C
1954   PetscOptionsLeftGet - Returns all options that were set and never used.
1955 
1956   Not Collective
1957 
1958   Input Parameter:
1959 . options - options database, use `NULL` for default global database
1960 
1961   Output Parameters:
1962 + N      - count of options not used
1963 . names  - names of options not used
1964 - values - values of options not used
1965 
1966   Level: advanced
1967 
1968   Notes:
1969   Users should call `PetscOptionsLeftRestore()` to free the memory allocated in this routine
1970 
1971   The value returned may be different on each process and depends on which options have been processed
1972   on the given process
1973 
1974 .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`
1975 @*/
1976 PetscErrorCode PetscOptionsLeftGet(PetscOptions options, PetscInt *N, char **names[], char **values[])
1977 {
1978   PetscInt i, n;
1979 
1980   PetscFunctionBegin;
1981   if (N) PetscAssertPointer(N, 2);
1982   if (names) PetscAssertPointer(names, 3);
1983   if (values) PetscAssertPointer(values, 4);
1984   options = options ? options : defaultoptions;
1985 
1986   /* The number of unused PETSc options */
1987   n = 0;
1988   for (i = 0; i < options->N; i++) {
1989     if (PetscCIOption(options->names[i])) continue;
1990     if (!options->used[i]) n++;
1991   }
1992   if (N) *N = n;
1993   if (names) PetscCall(PetscMalloc1(n, names));
1994   if (values) PetscCall(PetscMalloc1(n, values));
1995 
1996   n = 0;
1997   if (names || values) {
1998     for (i = 0; i < options->N; i++) {
1999       if (!options->used[i]) {
2000         if (PetscCIOption(options->names[i])) continue;
2001         if (names) (*names)[n] = options->names[i];
2002         if (values) (*values)[n] = options->values[i];
2003         n++;
2004       }
2005     }
2006   }
2007   PetscFunctionReturn(PETSC_SUCCESS);
2008 }
2009 
2010 /*@C
2011   PetscOptionsLeftRestore - Free memory for the unused PETSc options obtained using `PetscOptionsLeftGet()`.
2012 
2013   Not Collective
2014 
2015   Input Parameters:
2016 + options - options database, use `NULL` for default global database
2017 . N       - count of options not used
2018 . names   - names of options not used
2019 - values  - values of options not used
2020 
2021   Level: advanced
2022 
2023   Notes:
2024   The user should pass the same pointer to `N` as they did when calling `PetscOptionsLeftGet()`
2025 
2026 .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`, `PetscOptionsLeftGet()`
2027 @*/
2028 PetscErrorCode PetscOptionsLeftRestore(PetscOptions options, PetscInt *N, char **names[], char **values[])
2029 {
2030   PetscFunctionBegin;
2031   (void)options;
2032   if (N) PetscAssertPointer(N, 2);
2033   if (names) PetscAssertPointer(names, 3);
2034   if (values) PetscAssertPointer(values, 4);
2035   if (N) *N = 0;
2036   if (names) PetscCall(PetscFree(*names));
2037   if (values) PetscCall(PetscFree(*values));
2038   PetscFunctionReturn(PETSC_SUCCESS);
2039 }
2040 
2041 /*@C
2042   PetscOptionsMonitorDefault - Print all options set value events using the supplied `PetscViewer`.
2043 
2044   Logically Collective
2045 
2046   Input Parameters:
2047 + name   - option name string
2048 . value  - option value string
2049 . source - The source for the option
2050 - ctx    - a `PETSCVIEWERASCII` or `NULL`
2051 
2052   Level: intermediate
2053 
2054   Notes:
2055   If ctx is `NULL`, `PetscPrintf()` is used.
2056   The first MPI process in the `PetscViewer` viewer actually prints the values, other
2057   processes may have different values set
2058 
2059   If `PetscCIEnabled` then do not print the test harness options
2060 
2061 .seealso: `PetscOptionsMonitorSet()`
2062 @*/
2063 PetscErrorCode PetscOptionsMonitorDefault(const char name[], const char value[], PetscOptionSource source, PetscCtx ctx)
2064 {
2065   PetscFunctionBegin;
2066   if (PetscCIOption(name)) PetscFunctionReturn(PETSC_SUCCESS);
2067 
2068   if (ctx) {
2069     PetscViewer viewer = (PetscViewer)ctx;
2070     if (!value) {
2071       PetscCall(PetscViewerASCIIPrintf(viewer, "Removing option: %s\n", name));
2072     } else if (!value[0]) {
2073       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2074     } else {
2075       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2076     }
2077   } else {
2078     MPI_Comm comm = PETSC_COMM_WORLD;
2079     if (!value) {
2080       PetscCall(PetscPrintf(comm, "Removing option: %s\n", name));
2081     } else if (!value[0]) {
2082       PetscCall(PetscPrintf(comm, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2083     } else {
2084       PetscCall(PetscPrintf(comm, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2085     }
2086   }
2087   PetscFunctionReturn(PETSC_SUCCESS);
2088 }
2089 
2090 /*@C
2091   PetscOptionsMonitorSet - Sets an ADDITIONAL function to be called at every method that
2092   modified the PETSc options database.
2093 
2094   Not Collective
2095 
2096   Input Parameters:
2097 + monitor        - pointer to function (if this is `NULL`, it turns off monitoring
2098 . mctx           - [optional] context for private data for the monitor routine (use `NULL` if
2099                    no context is desired)
2100 - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for its calling sequence
2101 
2102   Calling sequence of `monitor`:
2103 + name   - option name string
2104 . value  - option value string, a value of `NULL` indicates the option is being removed from the database. A value
2105            of "" indicates the option is in the database but has no value.
2106 . source - option source
2107 - mctx   - optional monitoring context, as set by `PetscOptionsMonitorSet()`
2108 
2109   Options Database Keys:
2110 + -options_monitor <viewer> - turn on default monitoring of changes to the options database
2111 - -options_monitor_cancel   - turn off any option monitors except the default monitor obtained with `-options_monitor`
2112 
2113   Level: intermediate
2114 
2115   Notes:
2116   See `PetscInitialize()` for options related to option database monitoring.
2117 
2118   The default is to do no monitoring.  To print the name and value of options
2119   being inserted into the database, use `PetscOptionsMonitorDefault()` as the monitoring routine,
2120   with a `NULL` monitoring context. Or use the option `-options_monitor` <viewer>.
2121 
2122   Several different monitoring routines may be set by calling
2123   `PetscOptionsMonitorSet()` multiple times; all will be called in the
2124   order in which they were set.
2125 
2126 .seealso: `PetscOptionsMonitorDefault()`, `PetscInitialize()`, `PetscCtxDestroyFn`
2127 @*/
2128 PetscErrorCode PetscOptionsMonitorSet(PetscErrorCode (*monitor)(const char name[], const char value[], PetscOptionSource source, PetscCtx mctx), PetscCtx mctx, PetscCtxDestroyFn *monitordestroy)
2129 {
2130   PetscOptions options = defaultoptions;
2131 
2132   PetscFunctionBegin;
2133   if (options->monitorCancel) PetscFunctionReturn(PETSC_SUCCESS);
2134   PetscCheck(options->numbermonitors < MAXOPTIONSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptions monitors set");
2135   options->monitor[options->numbermonitors]          = monitor;
2136   options->monitordestroy[options->numbermonitors]   = monitordestroy;
2137   options->monitorcontext[options->numbermonitors++] = mctx;
2138   PetscFunctionReturn(PETSC_SUCCESS);
2139 }
2140 
2141 /*
2142    PetscOptionsStringToBool - Converts string to PetscBool, handles cases like "yes", "no", "true", "false", "0", "1", "off", "on".
2143      Empty string is considered as true.
2144 */
2145 PetscErrorCode PetscOptionsStringToBool(const char value[], PetscBool *a)
2146 {
2147   PetscBool istrue, isfalse;
2148   size_t    len;
2149 
2150   PetscFunctionBegin;
2151   /* PetscStrlen() returns 0 for NULL or "" */
2152   PetscCall(PetscStrlen(value, &len));
2153   if (!len) {
2154     *a = PETSC_TRUE;
2155     PetscFunctionReturn(PETSC_SUCCESS);
2156   }
2157   PetscCall(PetscStrcasecmp(value, "TRUE", &istrue));
2158   if (istrue) {
2159     *a = PETSC_TRUE;
2160     PetscFunctionReturn(PETSC_SUCCESS);
2161   }
2162   PetscCall(PetscStrcasecmp(value, "YES", &istrue));
2163   if (istrue) {
2164     *a = PETSC_TRUE;
2165     PetscFunctionReturn(PETSC_SUCCESS);
2166   }
2167   PetscCall(PetscStrcasecmp(value, "1", &istrue));
2168   if (istrue) {
2169     *a = PETSC_TRUE;
2170     PetscFunctionReturn(PETSC_SUCCESS);
2171   }
2172   PetscCall(PetscStrcasecmp(value, "on", &istrue));
2173   if (istrue) {
2174     *a = PETSC_TRUE;
2175     PetscFunctionReturn(PETSC_SUCCESS);
2176   }
2177   PetscCall(PetscStrcasecmp(value, "FALSE", &isfalse));
2178   if (isfalse) {
2179     *a = PETSC_FALSE;
2180     PetscFunctionReturn(PETSC_SUCCESS);
2181   }
2182   PetscCall(PetscStrcasecmp(value, "NO", &isfalse));
2183   if (isfalse) {
2184     *a = PETSC_FALSE;
2185     PetscFunctionReturn(PETSC_SUCCESS);
2186   }
2187   PetscCall(PetscStrcasecmp(value, "0", &isfalse));
2188   if (isfalse) {
2189     *a = PETSC_FALSE;
2190     PetscFunctionReturn(PETSC_SUCCESS);
2191   }
2192   PetscCall(PetscStrcasecmp(value, "off", &isfalse));
2193   if (isfalse) {
2194     *a = PETSC_FALSE;
2195     PetscFunctionReturn(PETSC_SUCCESS);
2196   }
2197   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown logical value: %s", value);
2198 }
2199 
2200 /*
2201    PetscOptionsStringToInt - Converts a string to an integer value. Handles special cases such as "default" and "decide"
2202 */
2203 PetscErrorCode PetscOptionsStringToInt(const char name[], PetscInt *a)
2204 {
2205   size_t    len;
2206   PetscBool decide, tdefault, mouse, unlimited;
2207 
2208   PetscFunctionBegin;
2209   PetscCall(PetscStrlen(name, &len));
2210   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2211 
2212   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &tdefault));
2213   if (!tdefault) PetscCall(PetscStrcasecmp(name, "DEFAULT", &tdefault));
2214   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &decide));
2215   if (!decide) PetscCall(PetscStrcasecmp(name, "DECIDE", &decide));
2216   if (!decide) PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &decide));
2217   if (!decide) PetscCall(PetscStrcasecmp(name, "DETERMINE", &decide));
2218   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &unlimited));
2219   if (!unlimited) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &unlimited));
2220   PetscCall(PetscStrcasecmp(name, "mouse", &mouse));
2221 
2222   if (tdefault) *a = PETSC_DEFAULT;
2223   else if (decide) *a = PETSC_DECIDE;
2224   else if (unlimited) *a = PETSC_UNLIMITED;
2225   else if (mouse) *a = -1;
2226   else {
2227     char *endptr;
2228     long  strtolval;
2229 
2230     strtolval = strtol(name, &endptr, 10);
2231     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 
2233 #if defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE_ATOLL)
2234     (void)strtolval;
2235     *a = atoll(name);
2236 #elif defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE___INT64)
2237     (void)strtolval;
2238     *a = _atoi64(name);
2239 #else
2240     *a = (PetscInt)strtolval;
2241 #endif
2242   }
2243   PetscFunctionReturn(PETSC_SUCCESS);
2244 }
2245 
2246 #if defined(PETSC_USE_REAL___FLOAT128)
2247   #include <quadmath.h>
2248 #endif
2249 
2250 static PetscErrorCode PetscStrtod(const char name[], PetscReal *a, char **endptr)
2251 {
2252   PetscFunctionBegin;
2253 #if defined(PETSC_USE_REAL___FLOAT128)
2254   *a = strtoflt128(name, endptr);
2255 #else
2256   *a = (PetscReal)strtod(name, endptr);
2257 #endif
2258   PetscFunctionReturn(PETSC_SUCCESS);
2259 }
2260 
2261 static PetscErrorCode PetscStrtoz(const char name[], PetscScalar *a, char **endptr, PetscBool *isImaginary)
2262 {
2263   PetscBool hasi = PETSC_FALSE;
2264   char     *ptr;
2265   PetscReal strtoval;
2266 
2267   PetscFunctionBegin;
2268   PetscCall(PetscStrtod(name, &strtoval, &ptr));
2269   if (ptr == name) {
2270     strtoval = 1.;
2271     hasi     = PETSC_TRUE;
2272     if (name[0] == 'i') {
2273       ptr++;
2274     } else if (name[0] == '+' && name[1] == 'i') {
2275       ptr += 2;
2276     } else if (name[0] == '-' && name[1] == 'i') {
2277       strtoval = -1.;
2278       ptr += 2;
2279     }
2280   } else if (*ptr == 'i') {
2281     hasi = PETSC_TRUE;
2282     ptr++;
2283   }
2284   *endptr      = ptr;
2285   *isImaginary = hasi;
2286   if (hasi) {
2287 #if !defined(PETSC_USE_COMPLEX)
2288     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s contains imaginary but complex not supported ", name);
2289 #else
2290     *a = PetscCMPLX(0., strtoval);
2291 #endif
2292   } else {
2293     *a = strtoval;
2294   }
2295   PetscFunctionReturn(PETSC_SUCCESS);
2296 }
2297 
2298 /*
2299    Converts a string to PetscReal value. Handles special cases like "default" and "decide"
2300 */
2301 PetscErrorCode PetscOptionsStringToReal(const char name[], PetscReal *a)
2302 {
2303   size_t    len;
2304   PetscBool match;
2305   char     *endptr;
2306 
2307   PetscFunctionBegin;
2308   PetscCall(PetscStrlen(name, &len));
2309   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "String of length zero has no numerical value");
2310 
2311   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &match));
2312   if (!match) PetscCall(PetscStrcasecmp(name, "DEFAULT", &match));
2313   if (match) {
2314     *a = PETSC_DEFAULT;
2315     PetscFunctionReturn(PETSC_SUCCESS);
2316   }
2317 
2318   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &match));
2319   if (!match) PetscCall(PetscStrcasecmp(name, "DECIDE", &match));
2320   if (match) {
2321     *a = PETSC_DECIDE;
2322     PetscFunctionReturn(PETSC_SUCCESS);
2323   }
2324 
2325   PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &match));
2326   if (!match) PetscCall(PetscStrcasecmp(name, "DETERMINE", &match));
2327   if (match) {
2328     *a = PETSC_DETERMINE;
2329     PetscFunctionReturn(PETSC_SUCCESS);
2330   }
2331 
2332   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &match));
2333   if (!match) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &match));
2334   if (match) {
2335     *a = PETSC_UNLIMITED;
2336     PetscFunctionReturn(PETSC_SUCCESS);
2337   }
2338 
2339   PetscCall(PetscStrtod(name, a, &endptr));
2340   PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value", name);
2341   PetscFunctionReturn(PETSC_SUCCESS);
2342 }
2343 
2344 PetscErrorCode PetscOptionsStringToScalar(const char name[], PetscScalar *a)
2345 {
2346   PetscBool   imag1;
2347   size_t      len;
2348   PetscScalar val = 0.;
2349   char       *ptr = NULL;
2350 
2351   PetscFunctionBegin;
2352   PetscCall(PetscStrlen(name, &len));
2353   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2354   PetscCall(PetscStrtoz(name, &val, &ptr, &imag1));
2355 #if defined(PETSC_USE_COMPLEX)
2356   if ((size_t)(ptr - name) < len) {
2357     PetscBool   imag2;
2358     PetscScalar val2;
2359 
2360     PetscCall(PetscStrtoz(ptr, &val2, &ptr, &imag2));
2361     if (imag1) PetscCheck(imag2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s: must specify imaginary component second", name);
2362     val = PetscCMPLX(PetscRealPart(val), PetscImaginaryPart(val2));
2363   }
2364 #endif
2365   PetscCheck((size_t)(ptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value ", name);
2366   *a = val;
2367   PetscFunctionReturn(PETSC_SUCCESS);
2368 }
2369 
2370 /*@C
2371   PetscOptionsGetBool - Gets the Logical (true or false) value for a particular
2372   option in the database.
2373 
2374   Not Collective
2375 
2376   Input Parameters:
2377 + options - options database, use `NULL` for default global database
2378 . pre     - the string to prepend to the name or `NULL`
2379 - name    - the option one is seeking
2380 
2381   Output Parameters:
2382 + ivalue - the logical value to return
2383 - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`
2384 
2385   Level: beginner
2386 
2387   Notes:
2388   TRUE, true, YES, yes, ON, on, nostring, and 1 all translate to `PETSC_TRUE`
2389   FALSE, false, NO, no, OFF, off and 0 all translate to `PETSC_FALSE`
2390 
2391   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`
2392   is equivalent to `-requested_bool true`
2393 
2394   If the user does not supply the option at all `ivalue` is NOT changed. Thus
2395   you should ALWAYS initialize `ivalue` if you access it without first checking that the `set` flag is true.
2396 
2397 .seealso: `PetscOptionsGetBool3()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2398           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2399           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2400           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2401           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2402           `PetscOptionsFList()`, `PetscOptionsEList()`
2403 @*/
2404 PetscErrorCode PetscOptionsGetBool(PetscOptions options, const char pre[], const char name[], PetscBool *ivalue, PetscBool *set)
2405 {
2406   const char *value;
2407   PetscBool   flag;
2408 
2409   PetscFunctionBegin;
2410   PetscAssertPointer(name, 3);
2411   if (ivalue) PetscAssertPointer(ivalue, 4);
2412   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2413   if (flag) {
2414     if (set) *set = PETSC_TRUE;
2415     PetscCall(PetscOptionsStringToBool(value, &flag));
2416     if (ivalue) *ivalue = flag;
2417   } else {
2418     if (set) *set = PETSC_FALSE;
2419   }
2420   PetscFunctionReturn(PETSC_SUCCESS);
2421 }
2422 
2423 /*@C
2424   PetscOptionsGetBool3 - Gets the ternary logical (true, false or unknown) value for a particular
2425   option in the database.
2426 
2427   Not Collective
2428 
2429   Input Parameters:
2430 + options - options database, use `NULL` for default global database
2431 . pre     - the string to prepend to the name or `NULL`
2432 - name    - the option one is seeking
2433 
2434   Output Parameters:
2435 + ivalue - the ternary logical value to return
2436 - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`
2437 
2438   Level: beginner
2439 
2440   Notes:
2441   TRUE, true, YES, yes, ON, on, nostring and 1 all translate to `PETSC_BOOL3_TRUE`
2442   FALSE, false, NO, no, OFF, off and 0 all translate to `PETSC_BOOL3_FALSE`
2443   UNKNOWN, unknown, AUTO and auto all translate to `PETSC_BOOL3_UNKNOWN`
2444 
2445   If the option is given, but no value is provided, then `ivalue` will be set to `PETSC_BOOL3_TRUE` and `set` will be set to `PETSC_TRUE`. That is `-requested_bool3`
2446   is equivalent to `-requested_bool3 true`
2447 
2448   If the user does not supply the option at all `ivalue` is NOT changed. Thus
2449   you should ALWAYS initialize `ivalue` if you access it without first checking that the `set` flag is true.
2450 
2451 .seealso: `PetscOptionsGetBool()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2452           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2453           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2454           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2455           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2456           `PetscOptionsFList()`, `PetscOptionsEList()`
2457 @*/
2458 PetscErrorCode PetscOptionsGetBool3(PetscOptions options, const char pre[], const char name[], PetscBool3 *ivalue, PetscBool *set)
2459 {
2460   const char *value;
2461   PetscBool   flag;
2462 
2463   PetscFunctionBegin;
2464   PetscAssertPointer(name, 3);
2465   if (ivalue) PetscAssertPointer(ivalue, 4);
2466   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2467   if (flag) { // found the option
2468     PetscBool isAUTO = PETSC_FALSE, isUNKNOWN = PETSC_FALSE;
2469 
2470     if (set) *set = PETSC_TRUE;
2471     PetscCall(PetscStrcasecmp("AUTO", value, &isAUTO));                    // auto or AUTO
2472     if (!isAUTO) PetscCall(PetscStrcasecmp("UNKNOWN", value, &isUNKNOWN)); // unknown or UNKNOWN
2473     if (isAUTO || isUNKNOWN) {
2474       if (ivalue) *ivalue = PETSC_BOOL3_UNKNOWN;
2475     } else { // handle boolean values (if no value is given, it returns true)
2476       PetscCall(PetscOptionsStringToBool(value, &flag));
2477       if (ivalue) *ivalue = PetscBoolToBool3(flag);
2478     }
2479   } else {
2480     if (set) *set = PETSC_FALSE;
2481   }
2482   PetscFunctionReturn(PETSC_SUCCESS);
2483 }
2484 
2485 /*@C
2486   PetscOptionsGetEList - Puts a list of option values that a single one may be selected from
2487 
2488   Not Collective
2489 
2490   Input Parameters:
2491 + options - options database, use `NULL` for default global database
2492 . pre     - the string to prepend to the name or `NULL`
2493 . opt     - option name
2494 . list    - the possible choices (one of these must be selected, anything else is invalid)
2495 - ntext   - number of choices
2496 
2497   Output Parameters:
2498 + value - the index of the value to return (defaults to zero if the option name is given but no choice is listed)
2499 - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`
2500 
2501   Level: intermediate
2502 
2503   Notes:
2504   If the user does not supply the option `value` is NOT changed. Thus
2505   you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.
2506 
2507   See `PetscOptionsFList()` for when the choices are given in a `PetscFunctionList`
2508 
2509 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2510           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2511           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2512           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2513           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2514           `PetscOptionsFList()`, `PetscOptionsEList()`
2515 @*/
2516 PetscErrorCode PetscOptionsGetEList(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscInt ntext, PetscInt *value, PetscBool *set)
2517 {
2518   size_t    alen, len = 0, tlen = 0;
2519   char     *svalue;
2520   PetscBool aset, flg = PETSC_FALSE;
2521   PetscInt  i;
2522 
2523   PetscFunctionBegin;
2524   PetscAssertPointer(opt, 3);
2525   for (i = 0; i < ntext; i++) {
2526     PetscCall(PetscStrlen(list[i], &alen));
2527     if (alen > len) len = alen;
2528     tlen += len + 1;
2529   }
2530   len += 5; /* a little extra space for user mistypes */
2531   PetscCall(PetscMalloc1(len, &svalue));
2532   PetscCall(PetscOptionsGetString(options, pre, opt, svalue, len, &aset));
2533   if (aset) {
2534     PetscCall(PetscEListFind(ntext, list, svalue, value, &flg));
2535     if (!flg) {
2536       char *avail;
2537 
2538       PetscCall(PetscMalloc1(tlen, &avail));
2539       avail[0] = '\0';
2540       for (i = 0; i < ntext; i++) {
2541         PetscCall(PetscStrlcat(avail, list[i], tlen));
2542         PetscCall(PetscStrlcat(avail, " ", tlen));
2543       }
2544       PetscCall(PetscStrtolower(avail));
2545       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown option \"%s\" for -%s%s. Available options: %s", svalue, pre ? pre : "", opt + 1, avail);
2546     }
2547     if (set) *set = PETSC_TRUE;
2548   } else if (set) *set = PETSC_FALSE;
2549   PetscCall(PetscFree(svalue));
2550   PetscFunctionReturn(PETSC_SUCCESS);
2551 }
2552 
2553 /*@C
2554   PetscOptionsGetEnum - Gets the enum value for a particular option in the database.
2555 
2556   Not Collective
2557 
2558   Input Parameters:
2559 + options - options database, use `NULL` for default global database
2560 . pre     - option prefix or `NULL`
2561 . opt     - option name
2562 - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
2563 
2564   Output Parameters:
2565 + value - the value to return
2566 - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`
2567 
2568   Level: beginner
2569 
2570   Notes:
2571   If the user does not supply the option `value` is NOT changed. Thus
2572   you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.
2573 
2574   `list` is usually something like `PCASMTypes` or some other predefined list of enum names
2575 
2576 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2577           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2578           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2579           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2580           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2581           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2582           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2583 @*/
2584 PetscErrorCode PetscOptionsGetEnum(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscEnum *value, PetscBool *set) PeNSS
2585 {
2586   PetscInt  ntext = 0, tval;
2587   PetscBool fset;
2588 
2589   PetscFunctionBegin;
2590   PetscAssertPointer(opt, 3);
2591   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");
2592   PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
2593   ntext -= 3;
2594   PetscCall(PetscOptionsGetEList(options, pre, opt, list, ntext, &tval, &fset));
2595   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
2596   if (fset) *value = (PetscEnum)tval;
2597   if (set) *set = fset;
2598   PetscFunctionReturn(PETSC_SUCCESS);
2599 }
2600 
2601 /*@C
2602   PetscOptionsGetInt - Gets the integer value for a particular option in the database.
2603 
2604   Not Collective
2605 
2606   Input Parameters:
2607 + options - options database, use `NULL` for default global database
2608 . pre     - the string to prepend to the name or `NULL`
2609 - name    - the option one is seeking
2610 
2611   Output Parameters:
2612 + ivalue - the integer value to return
2613 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2614 
2615   Level: beginner
2616 
2617   Notes:
2618   If the user does not supply the option `ivalue` is NOT changed. Thus
2619   you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.
2620 
2621   Accepts the special values `determine`, `decide` and `unlimited`.
2622 
2623   Accepts the deprecated value `default`.
2624 
2625 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2626           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2627           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2628           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2629           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2630           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2631           `PetscOptionsFList()`, `PetscOptionsEList()`
2632 @*/
2633 PetscErrorCode PetscOptionsGetInt(PetscOptions options, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
2634 {
2635   const char *value;
2636   PetscBool   flag;
2637 
2638   PetscFunctionBegin;
2639   PetscAssertPointer(name, 3);
2640   PetscAssertPointer(ivalue, 4);
2641   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2642   if (flag) {
2643     if (!value) {
2644       if (set) *set = PETSC_FALSE;
2645     } else {
2646       if (set) *set = PETSC_TRUE;
2647       PetscCall(PetscOptionsStringToInt(value, ivalue));
2648     }
2649   } else {
2650     if (set) *set = PETSC_FALSE;
2651   }
2652   PetscFunctionReturn(PETSC_SUCCESS);
2653 }
2654 
2655 /*@C
2656   PetscOptionsGetMPIInt - Gets the MPI integer value for a particular option in the database.
2657 
2658   Not Collective
2659 
2660   Input Parameters:
2661 + options - options database, use `NULL` for default global database
2662 . pre     - the string to prepend to the name or `NULL`
2663 - name    - the option one is seeking
2664 
2665   Output Parameters:
2666 + ivalue - the MPI integer value to return
2667 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2668 
2669   Level: beginner
2670 
2671   Notes:
2672   If the user does not supply the option `ivalue` is NOT changed. Thus
2673   you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.
2674 
2675   Accepts the special values `determine`, `decide` and `unlimited`.
2676 
2677   Accepts the deprecated value `default`.
2678 
2679 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2680           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2681           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2682           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2683           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2684           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2685           `PetscOptionsFList()`, `PetscOptionsEList()`
2686 @*/
2687 PetscErrorCode PetscOptionsGetMPIInt(PetscOptions options, const char pre[], const char name[], PetscMPIInt *ivalue, PetscBool *set)
2688 {
2689   PetscInt  value;
2690   PetscBool flag;
2691 
2692   PetscFunctionBegin;
2693   PetscCall(PetscOptionsGetInt(options, pre, name, &value, &flag));
2694   if (flag) PetscCall(PetscMPIIntCast(value, ivalue));
2695   if (set) *set = flag;
2696   PetscFunctionReturn(PETSC_SUCCESS);
2697 }
2698 
2699 /*@C
2700   PetscOptionsGetReal - Gets the double precision value for a particular
2701   option in the database.
2702 
2703   Not Collective
2704 
2705   Input Parameters:
2706 + options - options database, use `NULL` for default global database
2707 . pre     - string to prepend to each name or `NULL`
2708 - name    - the option one is seeking
2709 
2710   Output Parameters:
2711 + dvalue - the double value to return
2712 - set    - `PETSC_TRUE` if found, `PETSC_FALSE` if not found
2713 
2714   Level: beginner
2715 
2716   Notes:
2717   Accepts the special values `determine`, `decide` and `unlimited`.
2718 
2719   Accepts the deprecated value `default`
2720 
2721   If the user does not supply the option `dvalue` is NOT changed. Thus
2722   you should ALWAYS initialize `dvalue` if you access it without first checking that the `set` flag is true.
2723 
2724 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2725           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2726           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2727           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2728           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2729           `PetscOptionsFList()`, `PetscOptionsEList()`
2730 @*/
2731 PetscErrorCode PetscOptionsGetReal(PetscOptions options, const char pre[], const char name[], PetscReal *dvalue, PetscBool *set)
2732 {
2733   const char *value;
2734   PetscBool   flag;
2735 
2736   PetscFunctionBegin;
2737   PetscAssertPointer(name, 3);
2738   PetscAssertPointer(dvalue, 4);
2739   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2740   if (flag) {
2741     if (!value) {
2742       if (set) *set = PETSC_FALSE;
2743     } else {
2744       if (set) *set = PETSC_TRUE;
2745       PetscCall(PetscOptionsStringToReal(value, dvalue));
2746     }
2747   } else {
2748     if (set) *set = PETSC_FALSE;
2749   }
2750   PetscFunctionReturn(PETSC_SUCCESS);
2751 }
2752 
2753 /*@C
2754   PetscOptionsGetScalar - Gets the scalar value for a particular
2755   option in the database.
2756 
2757   Not Collective
2758 
2759   Input Parameters:
2760 + options - options database, use `NULL` for default global database
2761 . pre     - string to prepend to each name or `NULL`
2762 - name    - the option one is seeking
2763 
2764   Output Parameters:
2765 + dvalue - the scalar value to return
2766 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2767 
2768   Level: beginner
2769 
2770   Example Usage:
2771   A complex number 2+3i must be specified with NO spaces
2772 
2773   Note:
2774   If the user does not supply the option `dvalue` is NOT changed. Thus
2775   you should ALWAYS initialize `dvalue` if you access it without first checking if the `set` flag is true.
2776 
2777 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2778           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2779           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2780           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2781           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2782           `PetscOptionsFList()`, `PetscOptionsEList()`
2783 @*/
2784 PetscErrorCode PetscOptionsGetScalar(PetscOptions options, const char pre[], const char name[], PetscScalar *dvalue, PetscBool *set)
2785 {
2786   const char *value;
2787   PetscBool   flag;
2788 
2789   PetscFunctionBegin;
2790   PetscAssertPointer(name, 3);
2791   PetscAssertPointer(dvalue, 4);
2792   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2793   if (flag) {
2794     if (!value) {
2795       if (set) *set = PETSC_FALSE;
2796     } else {
2797 #if !defined(PETSC_USE_COMPLEX)
2798       PetscCall(PetscOptionsStringToReal(value, dvalue));
2799 #else
2800       PetscCall(PetscOptionsStringToScalar(value, dvalue));
2801 #endif
2802       if (set) *set = PETSC_TRUE;
2803     }
2804   } else { /* flag */
2805     if (set) *set = PETSC_FALSE;
2806   }
2807   PetscFunctionReturn(PETSC_SUCCESS);
2808 }
2809 
2810 /*@C
2811   PetscOptionsGetString - Gets the string value for a particular option in
2812   the database.
2813 
2814   Not Collective
2815 
2816   Input Parameters:
2817 + options - options database, use `NULL` for default global database
2818 . pre     - string to prepend to name or `NULL`
2819 . name    - the option one is seeking
2820 - len     - maximum length of the string including null termination
2821 
2822   Output Parameters:
2823 + string - location to copy string
2824 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2825 
2826   Level: beginner
2827 
2828   Note:
2829   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`
2830 
2831   If the user does not use the option then `string` is not changed. Thus
2832   you should ALWAYS initialize `string` if you access it without first checking that the `set` flag is true.
2833 
2834   Fortran Notes:
2835   The Fortran interface is slightly different from the C/C++
2836   interface.  Sample usage in Fortran follows
2837 .vb
2838       character *20    string
2839       PetscErrorCode   ierr
2840       PetscBool        set
2841       call PetscOptionsGetString(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-s',string,set,ierr)
2842 .ve
2843 
2844 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2845           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2846           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2847           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2848           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2849           `PetscOptionsFList()`, `PetscOptionsEList()`
2850 @*/
2851 PetscErrorCode PetscOptionsGetString(PetscOptions options, const char pre[], const char name[], char string[], size_t len, PetscBool *set) PeNS
2852 {
2853   const char *value;
2854   PetscBool   flag;
2855 
2856   PetscFunctionBegin;
2857   PetscAssertPointer(name, 3);
2858   PetscAssertPointer(string, 4);
2859   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2860   if (!flag) {
2861     if (set) *set = PETSC_FALSE;
2862   } else {
2863     if (set) *set = PETSC_TRUE;
2864     if (value) PetscCall(PetscStrncpy(string, value, len));
2865     else PetscCall(PetscArrayzero(string, len));
2866   }
2867   PetscFunctionReturn(PETSC_SUCCESS);
2868 }
2869 
2870 /*@C
2871   PetscOptionsGetBoolArray - Gets an array of Logical (true or false) values for a particular
2872   option in the database.  The values must be separated with commas with no intervening spaces.
2873 
2874   Not Collective
2875 
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
2880 
2881   Output Parameters:
2882 + dvalue - the Boolean 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`
2885 
2886   Level: beginner
2887 
2888   Note:
2889   TRUE, true, YES, yes, nostring, and 1 all translate to `PETSC_TRUE`. FALSE, false, NO, no, and 0 all translate to `PETSC_FALSE`
2890 
2891 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2892           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2893           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2894           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2895           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2896           `PetscOptionsFList()`, `PetscOptionsEList()`
2897 @*/
2898 PetscErrorCode PetscOptionsGetBoolArray(PetscOptions options, const char pre[], const char name[], PetscBool dvalue[], PetscInt *nmax, PetscBool *set)
2899 {
2900   const char *svalue;
2901   const char *value;
2902   PetscInt    n = 0;
2903   PetscBool   flag;
2904   PetscToken  token;
2905 
2906   PetscFunctionBegin;
2907   PetscAssertPointer(name, 3);
2908   PetscAssertPointer(nmax, 5);
2909   if (*nmax) PetscAssertPointer(dvalue, 4);
2910 
2911   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
2912   if (!flag || !svalue) {
2913     if (set) *set = PETSC_FALSE;
2914     *nmax = 0;
2915     PetscFunctionReturn(PETSC_SUCCESS);
2916   }
2917   if (set) *set = PETSC_TRUE;
2918   PetscCall(PetscTokenCreate(svalue, ',', &token));
2919   PetscCall(PetscTokenFind(token, &value));
2920   while (value && n < *nmax) {
2921     PetscCall(PetscOptionsStringToBool(value, dvalue));
2922     PetscCall(PetscTokenFind(token, &value));
2923     dvalue++;
2924     n++;
2925   }
2926   PetscCall(PetscTokenDestroy(&token));
2927   *nmax = n;
2928   PetscFunctionReturn(PETSC_SUCCESS);
2929 }
2930 
2931 /*@C
2932   PetscOptionsGetEnumArray - Gets an array of enum values for a particular option in the database.
2933 
2934   Not Collective
2935 
2936   Input Parameters:
2937 + options - options database, use `NULL` for default global database
2938 . pre     - option prefix or `NULL`
2939 . name    - option name
2940 - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
2941 
2942   Output Parameters:
2943 + ivalue - the  enum values to return
2944 . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2945 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2946 
2947   Level: beginner
2948 
2949   Notes:
2950   The array must be passed as a comma separated list with no spaces between the items.
2951 
2952   `list` is usually something like `PCASMTypes` or some other predefined list of enum names.
2953 
2954 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2955           `PetscOptionsGetEnum()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2956           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsName()`,
2957           `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, `PetscOptionsStringArray()`, `PetscOptionsRealArray()`,
2958           `PetscOptionsScalar()`, `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2959           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2960 @*/
2961 PetscErrorCode PetscOptionsGetEnumArray(PetscOptions options, const char pre[], const char name[], const char *const list[], PetscEnum ivalue[], PetscInt *nmax, PetscBool *set)
2962 {
2963   const char *svalue;
2964   const char *value;
2965   PetscInt    n = 0;
2966   PetscEnum   evalue;
2967   PetscBool   flag;
2968   PetscToken  token;
2969 
2970   PetscFunctionBegin;
2971   PetscAssertPointer(name, 3);
2972   PetscAssertPointer(list, 4);
2973   PetscAssertPointer(nmax, 6);
2974   if (*nmax) PetscAssertPointer(ivalue, 5);
2975 
2976   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
2977   if (!flag || !svalue) {
2978     if (set) *set = PETSC_FALSE;
2979     *nmax = 0;
2980     PetscFunctionReturn(PETSC_SUCCESS);
2981   }
2982   if (set) *set = PETSC_TRUE;
2983   PetscCall(PetscTokenCreate(svalue, ',', &token));
2984   PetscCall(PetscTokenFind(token, &value));
2985   while (value && n < *nmax) {
2986     PetscCall(PetscEnumFind(list, value, &evalue, &flag));
2987     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown enum value '%s' for -%s%s", svalue, pre ? pre : "", name + 1);
2988     ivalue[n++] = evalue;
2989     PetscCall(PetscTokenFind(token, &value));
2990   }
2991   PetscCall(PetscTokenDestroy(&token));
2992   *nmax = n;
2993   PetscFunctionReturn(PETSC_SUCCESS);
2994 }
2995 
2996 /*@C
2997   PetscOptionsGetIntArray - Gets an array of integer values for a particular option in the database.
2998 
2999   Not Collective
3000 
3001   Input Parameters:
3002 + options - options database, use `NULL` for default global database
3003 . pre     - string to prepend to each name or `NULL`
3004 - name    - the option one is seeking
3005 
3006   Output Parameters:
3007 + ivalue - the integer values to return
3008 . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3009 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
3010 
3011   Level: beginner
3012 
3013   Notes:
3014   The array can be passed as
3015 +  a comma separated list -                                 0,1,2,3,4,5,6,7
3016 .  a range (start\-end+1) -                                 0-8
3017 .  a range with given increment (start\-end+1:inc) -        0-7:2
3018 -  a combination of values and ranges separated by commas - 0,1-8,8-15:2
3019 
3020   There must be no intervening spaces between the values.
3021 
3022 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3023           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3024           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3025           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3026           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3027           `PetscOptionsFList()`, `PetscOptionsEList()`
3028 @*/
3029 PetscErrorCode PetscOptionsGetIntArray(PetscOptions options, const char pre[], const char name[], PetscInt ivalue[], PetscInt *nmax, PetscBool *set)
3030 {
3031   const char *svalue;
3032   const char *value;
3033   PetscInt    n = 0, i, j, start, end, inc, nvalues;
3034   size_t      len;
3035   PetscBool   flag, foundrange;
3036   PetscToken  token;
3037 
3038   PetscFunctionBegin;
3039   PetscAssertPointer(name, 3);
3040   PetscAssertPointer(nmax, 5);
3041   if (*nmax) PetscAssertPointer(ivalue, 4);
3042 
3043   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3044   if (!flag || !svalue) {
3045     if (set) *set = PETSC_FALSE;
3046     *nmax = 0;
3047     PetscFunctionReturn(PETSC_SUCCESS);
3048   }
3049   if (set) *set = PETSC_TRUE;
3050   PetscCall(PetscTokenCreate(svalue, ',', &token));
3051   PetscCall(PetscTokenFind(token, &value));
3052   while (value && n < *nmax) {
3053     char *iivalue;
3054 
3055     /* look for form  d-D where d and D are integers */
3056     PetscCall(PetscStrallocpy(value, &iivalue));
3057     foundrange = PETSC_FALSE;
3058     PetscCall(PetscStrlen(iivalue, &len));
3059     if (iivalue[0] == '-') i = 2;
3060     else i = 1;
3061     for (; i < (int)len; i++) {
3062       if (iivalue[i] == '-') {
3063         PetscCheck(i != (int)len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, iivalue);
3064         iivalue[i] = 0;
3065 
3066         PetscCall(PetscOptionsStringToInt(iivalue, &start));
3067         inc = 1;
3068         j   = i + 1;
3069         for (; j < (int)len; j++) {
3070           if (iivalue[j] == ':') {
3071             iivalue[j] = 0;
3072 
3073             PetscCall(PetscOptionsStringToInt(iivalue + j + 1, &inc));
3074             PetscCheck(inc > 0, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry,%s cannot have negative increment", n, iivalue + j + 1);
3075             break;
3076           }
3077         }
3078         PetscCall(PetscOptionsStringToInt(iivalue + i + 1, &end));
3079         PetscCheck(end > start, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, %s-%s cannot have decreasing list", n, iivalue, iivalue + i + 1);
3080         nvalues = (end - start) / inc + (end - start) % inc;
3081         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);
3082         for (; start < end; start += inc) {
3083           *ivalue = start;
3084           ivalue++;
3085           n++;
3086         }
3087         foundrange = PETSC_TRUE;
3088         break;
3089       }
3090     }
3091     if (!foundrange) {
3092       PetscCall(PetscOptionsStringToInt(value, ivalue));
3093       ivalue++;
3094       n++;
3095     }
3096     PetscCall(PetscFree(iivalue));
3097     PetscCall(PetscTokenFind(token, &value));
3098   }
3099   PetscCall(PetscTokenDestroy(&token));
3100   *nmax = n;
3101   PetscFunctionReturn(PETSC_SUCCESS);
3102 }
3103 
3104 /*@C
3105   PetscOptionsGetRealArray - Gets an array of double precision values for a
3106   particular option in the database.  The values must be separated with commas with no intervening spaces.
3107 
3108   Not Collective
3109 
3110   Input Parameters:
3111 + options - options database, use `NULL` for default global database
3112 . pre     - string to prepend to each name or `NULL`
3113 - name    - the option one is seeking
3114 
3115   Output Parameters:
3116 + dvalue - the double values to return
3117 . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3118 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
3119 
3120   Level: beginner
3121 
3122 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3123           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3124           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3125           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3126           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3127           `PetscOptionsFList()`, `PetscOptionsEList()`
3128 @*/
3129 PetscErrorCode PetscOptionsGetRealArray(PetscOptions options, const char pre[], const char name[], PetscReal dvalue[], PetscInt *nmax, PetscBool *set)
3130 {
3131   const char *svalue;
3132   const char *value;
3133   PetscInt    n = 0;
3134   PetscBool   flag;
3135   PetscToken  token;
3136 
3137   PetscFunctionBegin;
3138   PetscAssertPointer(name, 3);
3139   PetscAssertPointer(nmax, 5);
3140   if (*nmax) PetscAssertPointer(dvalue, 4);
3141 
3142   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3143   if (!flag || !svalue) {
3144     if (set) *set = PETSC_FALSE;
3145     *nmax = 0;
3146     PetscFunctionReturn(PETSC_SUCCESS);
3147   }
3148   if (set) *set = PETSC_TRUE;
3149   PetscCall(PetscTokenCreate(svalue, ',', &token));
3150   PetscCall(PetscTokenFind(token, &value));
3151   while (value && n < *nmax) {
3152     PetscCall(PetscOptionsStringToReal(value, dvalue++));
3153     PetscCall(PetscTokenFind(token, &value));
3154     n++;
3155   }
3156   PetscCall(PetscTokenDestroy(&token));
3157   *nmax = n;
3158   PetscFunctionReturn(PETSC_SUCCESS);
3159 }
3160 
3161 /*@C
3162   PetscOptionsGetScalarArray - Gets an array of scalars for a
3163   particular option in the database.  The values must be separated with commas with no intervening spaces.
3164 
3165   Not Collective
3166 
3167   Input Parameters:
3168 + options - options database, use `NULL` for default global database
3169 . pre     - string to prepend to each name or `NULL`
3170 - name    - the option one is seeking
3171 
3172   Output Parameters:
3173 + dvalue - the scalar values to return
3174 . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3175 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
3176 
3177   Level: beginner
3178 
3179 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3180           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3181           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3182           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3183           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3184           `PetscOptionsFList()`, `PetscOptionsEList()`
3185 @*/
3186 PetscErrorCode PetscOptionsGetScalarArray(PetscOptions options, const char pre[], const char name[], PetscScalar dvalue[], PetscInt *nmax, PetscBool *set)
3187 {
3188   const char *svalue;
3189   const char *value;
3190   PetscInt    n = 0;
3191   PetscBool   flag;
3192   PetscToken  token;
3193 
3194   PetscFunctionBegin;
3195   PetscAssertPointer(name, 3);
3196   PetscAssertPointer(nmax, 5);
3197   if (*nmax) PetscAssertPointer(dvalue, 4);
3198 
3199   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3200   if (!flag || !svalue) {
3201     if (set) *set = PETSC_FALSE;
3202     *nmax = 0;
3203     PetscFunctionReturn(PETSC_SUCCESS);
3204   }
3205   if (set) *set = PETSC_TRUE;
3206   PetscCall(PetscTokenCreate(svalue, ',', &token));
3207   PetscCall(PetscTokenFind(token, &value));
3208   while (value && n < *nmax) {
3209     PetscCall(PetscOptionsStringToScalar(value, dvalue++));
3210     PetscCall(PetscTokenFind(token, &value));
3211     n++;
3212   }
3213   PetscCall(PetscTokenDestroy(&token));
3214   *nmax = n;
3215   PetscFunctionReturn(PETSC_SUCCESS);
3216 }
3217 
3218 /*@C
3219   PetscOptionsGetStringArray - Gets an array of string values for a particular
3220   option in the database. The values must be separated with commas with no intervening spaces.
3221 
3222   Not Collective; No Fortran Support
3223 
3224   Input Parameters:
3225 + options - options database, use `NULL` for default global database
3226 . pre     - string to prepend to name or `NULL`
3227 - name    - the option one is seeking
3228 
3229   Output Parameters:
3230 + strings - location to copy strings
3231 . nmax    - On input maximum number of strings, on output the actual number of strings found
3232 - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`
3233 
3234   Level: beginner
3235 
3236   Notes:
3237   The `nmax` parameter is used for both input and output.
3238 
3239   The user should pass in an array of pointers to `char`, to hold all the
3240   strings returned by this function.
3241 
3242   The user is responsible for deallocating the strings that are
3243   returned.
3244 
3245 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
3246           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3247           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3248           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3249           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3250           `PetscOptionsFList()`, `PetscOptionsEList()`
3251 @*/
3252 PetscErrorCode PetscOptionsGetStringArray(PetscOptions options, const char pre[], const char name[], char *strings[], PetscInt *nmax, PetscBool *set) PeNS
3253 {
3254   const char *svalue;
3255   const char *value;
3256   PetscInt    n = 0;
3257   PetscBool   flag;
3258   PetscToken  token;
3259 
3260   PetscFunctionBegin;
3261   PetscAssertPointer(name, 3);
3262   PetscAssertPointer(nmax, 5);
3263   if (*nmax) PetscAssertPointer(strings, 4);
3264 
3265   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3266   if (!flag || !svalue) {
3267     if (set) *set = PETSC_FALSE;
3268     *nmax = 0;
3269     PetscFunctionReturn(PETSC_SUCCESS);
3270   }
3271   if (set) *set = PETSC_TRUE;
3272   PetscCall(PetscTokenCreate(svalue, ',', &token));
3273   PetscCall(PetscTokenFind(token, &value));
3274   while (value && n < *nmax) {
3275     PetscCall(PetscStrallocpy(value, &strings[n]));
3276     PetscCall(PetscTokenFind(token, &value));
3277     n++;
3278   }
3279   PetscCall(PetscTokenDestroy(&token));
3280   *nmax = n;
3281   PetscFunctionReturn(PETSC_SUCCESS);
3282 }
3283 
3284 /*@C
3285   PetscOptionsDeprecated_Private - mark an option as deprecated, optionally replacing it with `newname`
3286 
3287   Prints a deprecation warning, unless an option is supplied to suppress.
3288 
3289   Logically Collective
3290 
3291   Input Parameters:
3292 + PetscOptionsObject - string to prepend to name or `NULL`
3293 . oldname            - the old, deprecated option
3294 . newname            - the new option, or `NULL` if option is purely removed
3295 . version            - a string describing the version of first deprecation, e.g. "3.9"
3296 - info               - additional information string, or `NULL`.
3297 
3298   Options Database Key:
3299 . -options_suppress_deprecated_warnings - do not print deprecation warnings
3300 
3301   Level: developer
3302 
3303   Notes:
3304   If `newname` is provided then the options database will automatically check the database for `oldname`.
3305 
3306   The old call `PetscOptionsXXX`(`oldname`) should be removed from the source code when both (1) the call to `PetscOptionsDeprecated()` occurs before the
3307   new call to `PetscOptionsXXX`(`newname`) and (2) the argument handling of the new call to `PetscOptionsXXX`(`newname`) is identical to the previous call.
3308   See `PTScotch_PartGraph_Seq()` for an example of when (1) fails and `SNESTestJacobian()` where an example of (2) fails.
3309 
3310   Must be called between `PetscOptionsBegin()` (or `PetscObjectOptionsBegin()`) and `PetscOptionsEnd()`.
3311   Only the process of rank zero that owns the `PetscOptionsItems` are argument (managed by `PetscOptionsBegin()` or
3312   `PetscObjectOptionsBegin()` prints the information
3313   If newname is provided, the old option is replaced. Otherwise, it remains
3314   in the options database.
3315   If an option is not replaced, the info argument should be used to advise the user
3316   on how to proceed.
3317   There is a limit on the length of the warning printed, so very long strings
3318   provided as info may be truncated.
3319 
3320 .seealso: `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsScalar()`, `PetscOptionsBool()`, `PetscOptionsString()`, `PetscOptionsSetValue()`
3321 @*/
3322 PetscErrorCode PetscOptionsDeprecated_Private(PetscOptionItems PetscOptionsObject, const char oldname[], const char newname[], const char version[], const char info[])
3323 {
3324   PetscBool         found, quiet;
3325   const char       *value;
3326   const char *const quietopt = "-options_suppress_deprecated_warnings";
3327   char              msg[4096];
3328   char             *prefix  = NULL;
3329   PetscOptions      options = NULL;
3330   MPI_Comm          comm    = PETSC_COMM_SELF;
3331 
3332   PetscFunctionBegin;
3333   PetscAssertPointer(oldname, 2);
3334   PetscAssertPointer(version, 4);
3335   if (PetscOptionsObject) {
3336     prefix  = PetscOptionsObject->prefix;
3337     options = PetscOptionsObject->options;
3338     comm    = PetscOptionsObject->comm;
3339   }
3340   PetscCall(PetscOptionsFindPair(options, prefix, oldname, &value, &found));
3341   if (found) {
3342     if (newname) {
3343       PetscBool newfound;
3344 
3345       /* do not overwrite if the new option has been provided */
3346       PetscCall(PetscOptionsFindPair(options, prefix, newname, NULL, &newfound));
3347       if (!newfound) {
3348         if (prefix) PetscCall(PetscOptionsPrefixPush(options, prefix));
3349         PetscCall(PetscOptionsSetValue(options, newname, value));
3350         if (prefix) PetscCall(PetscOptionsPrefixPop(options));
3351       }
3352       PetscCall(PetscOptionsClearValue(options, oldname));
3353     }
3354     quiet = PETSC_FALSE;
3355     PetscCall(PetscOptionsGetBool(options, NULL, quietopt, &quiet, NULL));
3356     if (!quiet) {
3357       PetscCall(PetscStrncpy(msg, "** PETSc DEPRECATION WARNING ** : the option -", sizeof(msg)));
3358       PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
3359       PetscCall(PetscStrlcat(msg, oldname + 1, sizeof(msg)));
3360       PetscCall(PetscStrlcat(msg, " is deprecated as of version ", sizeof(msg)));
3361       PetscCall(PetscStrlcat(msg, version, sizeof(msg)));
3362       PetscCall(PetscStrlcat(msg, " and will be removed in a future release.\n", sizeof(msg)));
3363       if (newname) {
3364         PetscCall(PetscStrlcat(msg, "   Use the option -", sizeof(msg)));
3365         PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
3366         PetscCall(PetscStrlcat(msg, newname + 1, sizeof(msg)));
3367         PetscCall(PetscStrlcat(msg, " instead.", sizeof(msg)));
3368       }
3369       if (info) {
3370         PetscCall(PetscStrlcat(msg, " ", sizeof(msg)));
3371         PetscCall(PetscStrlcat(msg, info, sizeof(msg)));
3372       }
3373       PetscCall(PetscStrlcat(msg, " (Silence this warning with ", sizeof(msg)));
3374       PetscCall(PetscStrlcat(msg, quietopt, sizeof(msg)));
3375       PetscCall(PetscStrlcat(msg, ")\n", sizeof(msg)));
3376       PetscCall(PetscPrintf(comm, "%s", msg));
3377     }
3378   }
3379   PetscFunctionReturn(PETSC_SUCCESS);
3380 }
3381