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