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