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