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