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