xref: /petsc/src/sys/objects/options.c (revision 0d5ef98addb54ced821e7e5fade9ccac0ec8ccde)
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   options = options ? options : defaultoptions;
1499   PetscCheck(!pre || !PetscUnlikely(pre[0] == '-'), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1500   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1501 
1502   name++; /* skip starting dash */
1503 
1504   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1505   if (pre && pre[0]) {
1506     char *ptr = buf;
1507     if (name[0] == '-') {
1508       *ptr++ = '-';
1509       name++;
1510     }
1511     PetscCall(PetscStrncpy(ptr, pre, buf + sizeof(buf) - ptr));
1512     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1513     name = buf;
1514   }
1515 
1516   if (PetscDefined(USE_DEBUG)) {
1517     PetscBool valid;
1518     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1519     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1520     PetscCall(PetscOptionsValidKey(key, &valid));
1521     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1522   }
1523 
1524   if (!options->ht && usehashtable) {
1525     int          i, ret;
1526     khiter_t     it;
1527     khash_t(HO) *ht;
1528     ht = kh_init(HO);
1529     PetscCheck(ht, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1530     ret = kh_resize(HO, ht, options->N * 2); /* twice the required size to reduce risk of collisions */
1531     PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1532     for (i = 0; i < options->N; i++) {
1533       it = kh_put(HO, ht, options->names[i], &ret);
1534       PetscCheck(ret == 1, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1535       kh_val(ht, it) = i;
1536     }
1537     options->ht = ht;
1538   }
1539 
1540   if (usehashtable) { /* fast search */
1541     khash_t(HO) *ht = options->ht;
1542     khiter_t     it = kh_get(HO, ht, name);
1543     if (it != kh_end(ht)) {
1544       int i            = kh_val(ht, it);
1545       options->used[i] = PETSC_TRUE;
1546       if (value) *value = options->values[i];
1547       if (set) *set = PETSC_TRUE;
1548       PetscFunctionReturn(PETSC_SUCCESS);
1549     }
1550   } else { /* slow search */
1551     int i, N = options->N;
1552     for (i = 0; i < N; i++) {
1553       int result = PetscOptNameCmp(options->names[i], name);
1554       if (!result) {
1555         options->used[i] = PETSC_TRUE;
1556         if (value) *value = options->values[i];
1557         if (set) *set = PETSC_TRUE;
1558         PetscFunctionReturn(PETSC_SUCCESS);
1559       } else if (result > 0) {
1560         break;
1561       }
1562     }
1563   }
1564 
1565   /*
1566    The following block slows down all lookups in the most frequent path (most lookups are unsuccessful).
1567    Maybe this special lookup mode should be enabled on request with a push/pop API.
1568    The feature of matching _%d_ used sparingly in the codebase.
1569    */
1570   if (matchnumbers) {
1571     int i, j, cnt = 0, locs[16], loce[16];
1572     /* determine the location and number of all _%d_ in the key */
1573     for (i = 0; name[i]; i++) {
1574       if (name[i] == '_') {
1575         for (j = i + 1; name[j]; j++) {
1576           if (name[j] >= '0' && name[j] <= '9') continue;
1577           if (name[j] == '_' && j > i + 1) { /* found a number */
1578             locs[cnt]   = i + 1;
1579             loce[cnt++] = j + 1;
1580           }
1581           i = j - 1;
1582           break;
1583         }
1584       }
1585     }
1586     for (i = 0; i < cnt; i++) {
1587       PetscBool found;
1588       char      opt[PETSC_MAX_OPTION_NAME + 1] = "-", tmp[PETSC_MAX_OPTION_NAME];
1589       PetscCall(PetscStrncpy(tmp, name, PetscMin((size_t)(locs[i] + 1), sizeof(tmp))));
1590       PetscCall(PetscStrlcat(opt, tmp, sizeof(opt)));
1591       PetscCall(PetscStrlcat(opt, name + loce[i], sizeof(opt)));
1592       PetscCall(PetscOptionsFindPair(options, NULL, opt, value, &found));
1593       if (found) {
1594         if (set) *set = PETSC_TRUE;
1595         PetscFunctionReturn(PETSC_SUCCESS);
1596       }
1597     }
1598   }
1599 
1600   if (set) *set = PETSC_FALSE;
1601   PetscFunctionReturn(PETSC_SUCCESS);
1602 }
1603 
1604 /* Check whether any option begins with pre+name */
1605 PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions options, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *set)
1606 {
1607   char buf[PETSC_MAX_OPTION_NAME];
1608   int  numCnt = 0, locs[16], loce[16];
1609 
1610   PetscFunctionBegin;
1611   options = options ? options : defaultoptions;
1612   PetscCheck(!pre || pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1613   PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1614 
1615   name++; /* skip starting dash */
1616 
1617   /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1618   if (pre && pre[0]) {
1619     char *ptr = buf;
1620     if (name[0] == '-') {
1621       *ptr++ = '-';
1622       name++;
1623     }
1624     PetscCall(PetscStrncpy(ptr, pre, sizeof(buf) - ((ptr == buf) ? 0 : 1)));
1625     PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1626     name = buf;
1627   }
1628 
1629   if (PetscDefined(USE_DEBUG)) {
1630     PetscBool valid;
1631     char      key[PETSC_MAX_OPTION_NAME + 1] = "-";
1632     PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1633     PetscCall(PetscOptionsValidKey(key, &valid));
1634     PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1635   }
1636 
1637   /* determine the location and number of all _%d_ in the key */
1638   {
1639     int i, j;
1640     for (i = 0; name[i]; i++) {
1641       if (name[i] == '_') {
1642         for (j = i + 1; name[j]; j++) {
1643           if (name[j] >= '0' && name[j] <= '9') continue;
1644           if (name[j] == '_' && j > i + 1) { /* found a number */
1645             locs[numCnt]   = i + 1;
1646             loce[numCnt++] = j + 1;
1647           }
1648           i = j - 1;
1649           break;
1650         }
1651       }
1652     }
1653   }
1654 
1655   /* slow search */
1656   for (int c = -1; c < numCnt; ++c) {
1657     char   opt[PETSC_MAX_OPTION_NAME + 2] = "";
1658     size_t len;
1659 
1660     if (c < 0) {
1661       PetscCall(PetscStrncpy(opt, name, sizeof(opt)));
1662     } else {
1663       PetscCall(PetscStrncpy(opt, name, PetscMin((size_t)(locs[c] + 1), sizeof(opt))));
1664       PetscCall(PetscStrlcat(opt, name + loce[c], sizeof(opt) - 1));
1665     }
1666     PetscCall(PetscStrlen(opt, &len));
1667     for (int i = 0; i < options->N; i++) {
1668       PetscBool match;
1669 
1670       PetscCall(PetscStrncmp(options->names[i], opt, len, &match));
1671       if (match) {
1672         options->used[i] = PETSC_TRUE;
1673         if (option) *option = options->names[i];
1674         if (value) *value = options->values[i];
1675         if (set) *set = PETSC_TRUE;
1676         PetscFunctionReturn(PETSC_SUCCESS);
1677       }
1678     }
1679   }
1680 
1681   if (set) *set = PETSC_FALSE;
1682   PetscFunctionReturn(PETSC_SUCCESS);
1683 }
1684 
1685 /*@
1686   PetscOptionsReject - Generates an error if a certain option is given.
1687 
1688   Not Collective
1689 
1690   Input Parameters:
1691 + options - options database, use `NULL` for default global database
1692 . pre     - the option prefix (may be `NULL`)
1693 . name    - the option name one is seeking
1694 - mess    - error message (may be `NULL`)
1695 
1696   Level: advanced
1697 
1698 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1699           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1700           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1701           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1702           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1703           `PetscOptionsFList()`, `PetscOptionsEList()`
1704 @*/
1705 PetscErrorCode PetscOptionsReject(PetscOptions options, const char pre[], const char name[], const char mess[])
1706 {
1707   PetscBool flag = PETSC_FALSE;
1708 
1709   PetscFunctionBegin;
1710   PetscCall(PetscOptionsHasName(options, pre, name, &flag));
1711   if (flag) {
1712     PetscCheck(!mess || !mess[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s with %s", pre ? pre : "", name + 1, mess);
1713     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s", pre ? pre : "", name + 1);
1714   }
1715   PetscFunctionReturn(PETSC_SUCCESS);
1716 }
1717 
1718 /*@
1719   PetscOptionsHasHelp - Determines whether the "-help" option is in the database.
1720 
1721   Not Collective
1722 
1723   Input Parameter:
1724 . options - options database, use `NULL` for default global database
1725 
1726   Output Parameter:
1727 . set - `PETSC_TRUE` if found else `PETSC_FALSE`.
1728 
1729   Level: advanced
1730 
1731 .seealso: `PetscOptionsHasName()`
1732 @*/
1733 PetscErrorCode PetscOptionsHasHelp(PetscOptions options, PetscBool *set)
1734 {
1735   PetscFunctionBegin;
1736   PetscAssertPointer(set, 2);
1737   options = options ? options : defaultoptions;
1738   *set    = options->help;
1739   PetscFunctionReturn(PETSC_SUCCESS);
1740 }
1741 
1742 PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions options, PetscBool *set)
1743 {
1744   PetscFunctionBegin;
1745   PetscAssertPointer(set, 2);
1746   options = options ? options : defaultoptions;
1747   *set    = options->help_intro;
1748   PetscFunctionReturn(PETSC_SUCCESS);
1749 }
1750 
1751 /*@
1752   PetscOptionsHasName - Determines whether a certain option is given in the database. This returns true whether the option is a number, string or Boolean, even
1753   if its value is set to false.
1754 
1755   Not Collective
1756 
1757   Input Parameters:
1758 + options - options database, use `NULL` for default global database
1759 . pre     - string to prepend to the name or `NULL`
1760 - name    - the option one is seeking
1761 
1762   Output Parameter:
1763 . set - `PETSC_TRUE` if found else `PETSC_FALSE`.
1764 
1765   Level: beginner
1766 
1767   Note:
1768   In many cases you probably want to use `PetscOptionsGetBool()` instead of calling this, to allowing toggling values.
1769 
1770 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1771           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1772           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1773           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1774           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1775           `PetscOptionsFList()`, `PetscOptionsEList()`
1776 @*/
1777 PetscErrorCode PetscOptionsHasName(PetscOptions options, const char pre[], const char name[], PetscBool *set)
1778 {
1779   const char *value;
1780   PetscBool   flag;
1781 
1782   PetscFunctionBegin;
1783   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
1784   if (set) *set = flag;
1785   PetscFunctionReturn(PETSC_SUCCESS);
1786 }
1787 
1788 /*@C
1789   PetscOptionsGetAll - Lists all the options the program was run with in a single string.
1790 
1791   Not Collective
1792 
1793   Input Parameter:
1794 . options - the options database, use `NULL` for the default global database
1795 
1796   Output Parameter:
1797 . copts - pointer where string pointer is stored
1798 
1799   Level: advanced
1800 
1801   Notes:
1802   The array and each entry in the array should be freed with `PetscFree()`
1803 
1804   Each process may have different values depending on how the options were inserted into the database
1805 
1806 .seealso: `PetscOptionsAllUsed()`, `PetscOptionsView()`, `PetscOptionsPush()`, `PetscOptionsPop()`
1807 @*/
1808 PetscErrorCode PetscOptionsGetAll(PetscOptions options, char *copts[])
1809 {
1810   PetscInt i;
1811   size_t   len = 1, lent = 0;
1812   char    *coptions = NULL;
1813 
1814   PetscFunctionBegin;
1815   PetscAssertPointer(copts, 2);
1816   options = options ? options : defaultoptions;
1817   /* count the length of the required string */
1818   for (i = 0; i < options->N; i++) {
1819     PetscCall(PetscStrlen(options->names[i], &lent));
1820     len += 2 + lent;
1821     if (options->values[i]) {
1822       PetscCall(PetscStrlen(options->values[i], &lent));
1823       len += 1 + lent;
1824     }
1825   }
1826   PetscCall(PetscMalloc1(len, &coptions));
1827   coptions[0] = 0;
1828   for (i = 0; i < options->N; i++) {
1829     PetscCall(PetscStrlcat(coptions, "-", len));
1830     PetscCall(PetscStrlcat(coptions, options->names[i], len));
1831     PetscCall(PetscStrlcat(coptions, " ", len));
1832     if (options->values[i]) {
1833       PetscCall(PetscStrlcat(coptions, options->values[i], len));
1834       PetscCall(PetscStrlcat(coptions, " ", len));
1835     }
1836   }
1837   *copts = coptions;
1838   PetscFunctionReturn(PETSC_SUCCESS);
1839 }
1840 
1841 /*@
1842   PetscOptionsUsed - Indicates if PETSc has used a particular option set in the database
1843 
1844   Not Collective
1845 
1846   Input Parameters:
1847 + options - options database, use `NULL` for default global database
1848 - name    - string name of option
1849 
1850   Output Parameter:
1851 . used - `PETSC_TRUE` if the option was used, otherwise false, including if option was not found in options database
1852 
1853   Level: advanced
1854 
1855   Note:
1856   The value returned may be different on each process and depends on which options have been processed
1857   on the given process
1858 
1859 .seealso: `PetscOptionsView()`, `PetscOptionsLeft()`, `PetscOptionsAllUsed()`
1860 @*/
1861 PetscErrorCode PetscOptionsUsed(PetscOptions options, const char *name, PetscBool *used)
1862 {
1863   PetscInt i;
1864 
1865   PetscFunctionBegin;
1866   PetscAssertPointer(name, 2);
1867   PetscAssertPointer(used, 3);
1868   options = options ? options : defaultoptions;
1869   *used   = PETSC_FALSE;
1870   for (i = 0; i < options->N; i++) {
1871     PetscCall(PetscStrcasecmp(options->names[i], name, used));
1872     if (*used) {
1873       *used = options->used[i];
1874       break;
1875     }
1876   }
1877   PetscFunctionReturn(PETSC_SUCCESS);
1878 }
1879 
1880 /*@
1881   PetscOptionsAllUsed - Returns a count of the number of options in the
1882   database that have never been selected.
1883 
1884   Not Collective
1885 
1886   Input Parameter:
1887 . options - options database, use `NULL` for default global database
1888 
1889   Output Parameter:
1890 . N - count of options not used
1891 
1892   Level: advanced
1893 
1894   Note:
1895   The value returned may be different on each process and depends on which options have been processed
1896   on the given process
1897 
1898 .seealso: `PetscOptionsView()`
1899 @*/
1900 PetscErrorCode PetscOptionsAllUsed(PetscOptions options, PetscInt *N)
1901 {
1902   PetscInt i, n = 0;
1903 
1904   PetscFunctionBegin;
1905   PetscAssertPointer(N, 2);
1906   options = options ? options : defaultoptions;
1907   for (i = 0; i < options->N; i++) {
1908     if (!options->used[i]) n++;
1909   }
1910   *N = n;
1911   PetscFunctionReturn(PETSC_SUCCESS);
1912 }
1913 
1914 /*@
1915   PetscOptionsLeft - Prints to screen any options that were set and never used.
1916 
1917   Not Collective
1918 
1919   Input Parameter:
1920 . options - options database; use `NULL` for default global database
1921 
1922   Options Database Key:
1923 . -options_left - activates `PetscOptionsAllUsed()` within `PetscFinalize()`
1924 
1925   Level: advanced
1926 
1927   Notes:
1928   This is rarely used directly, it is called by `PetscFinalize()` in debug more or if -options_left
1929   is passed otherwise to help users determine possible mistakes in their usage of options. This
1930   only prints values on process zero of `PETSC_COMM_WORLD`.
1931 
1932   Other processes depending the objects
1933   used may have different options that are left unused.
1934 
1935 .seealso: `PetscOptionsAllUsed()`
1936 @*/
1937 PetscErrorCode PetscOptionsLeft(PetscOptions options)
1938 {
1939   PetscInt     i;
1940   PetscInt     cnt = 0;
1941   PetscOptions toptions;
1942 
1943   PetscFunctionBegin;
1944   toptions = options ? options : defaultoptions;
1945   for (i = 0; i < toptions->N; i++) {
1946     if (!toptions->used[i]) {
1947       if (PetscCIOption(toptions->names[i])) continue;
1948       if (toptions->values[i]) {
1949         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s value: %s source: %s\n", toptions->names[i], toptions->values[i], PetscOptionSources[toptions->source[i]]));
1950       } else {
1951         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s (no value) source: %s\n", toptions->names[i], PetscOptionSources[toptions->source[i]]));
1952       }
1953     }
1954   }
1955   if (!options) {
1956     toptions = defaultoptions;
1957     while (toptions->previous) {
1958       cnt++;
1959       toptions = toptions->previous;
1960     }
1961     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));
1962   }
1963   PetscFunctionReturn(PETSC_SUCCESS);
1964 }
1965 
1966 /*@C
1967   PetscOptionsLeftGet - Returns all options that were set and never used.
1968 
1969   Not Collective
1970 
1971   Input Parameter:
1972 . options - options database, use `NULL` for default global database
1973 
1974   Output Parameters:
1975 + N      - count of options not used
1976 . names  - names of options not used
1977 - values - values of options not used
1978 
1979   Level: advanced
1980 
1981   Notes:
1982   Users should call `PetscOptionsLeftRestore()` to free the memory allocated in this routine
1983 
1984   The value returned may be different on each process and depends on which options have been processed
1985   on the given process
1986 
1987 .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`
1988 @*/
1989 PetscErrorCode PetscOptionsLeftGet(PetscOptions options, PetscInt *N, char **names[], char **values[])
1990 {
1991   PetscInt i, n;
1992 
1993   PetscFunctionBegin;
1994   if (N) PetscAssertPointer(N, 2);
1995   if (names) PetscAssertPointer(names, 3);
1996   if (values) PetscAssertPointer(values, 4);
1997   options = options ? options : defaultoptions;
1998 
1999   /* The number of unused PETSc options */
2000   n = 0;
2001   for (i = 0; i < options->N; i++) {
2002     if (PetscCIOption(options->names[i])) continue;
2003     if (!options->used[i]) n++;
2004   }
2005   if (N) *N = n;
2006   if (names) PetscCall(PetscMalloc1(n, names));
2007   if (values) PetscCall(PetscMalloc1(n, values));
2008 
2009   n = 0;
2010   if (names || values) {
2011     for (i = 0; i < options->N; i++) {
2012       if (!options->used[i]) {
2013         if (PetscCIOption(options->names[i])) continue;
2014         if (names) (*names)[n] = options->names[i];
2015         if (values) (*values)[n] = options->values[i];
2016         n++;
2017       }
2018     }
2019   }
2020   PetscFunctionReturn(PETSC_SUCCESS);
2021 }
2022 
2023 /*@C
2024   PetscOptionsLeftRestore - Free memory for the unused PETSc options obtained using `PetscOptionsLeftGet()`.
2025 
2026   Not Collective
2027 
2028   Input Parameters:
2029 + options - options database, use `NULL` for default global database
2030 . N       - count of options not used
2031 . names   - names of options not used
2032 - values  - values of options not used
2033 
2034   Level: advanced
2035 
2036   Notes:
2037   The user should pass the same pointer to `N` as they did when calling `PetscOptionsLeftGet()`
2038 
2039 .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`, `PetscOptionsLeftGet()`
2040 @*/
2041 PetscErrorCode PetscOptionsLeftRestore(PetscOptions options, PetscInt *N, char **names[], char **values[])
2042 {
2043   PetscFunctionBegin;
2044   (void)options;
2045   if (N) PetscAssertPointer(N, 2);
2046   if (names) PetscAssertPointer(names, 3);
2047   if (values) PetscAssertPointer(values, 4);
2048   if (N) *N = 0;
2049   if (names) PetscCall(PetscFree(*names));
2050   if (values) PetscCall(PetscFree(*values));
2051   PetscFunctionReturn(PETSC_SUCCESS);
2052 }
2053 
2054 /*@C
2055   PetscOptionsMonitorDefault - Print all options set value events using the supplied `PetscViewer`.
2056 
2057   Logically Collective
2058 
2059   Input Parameters:
2060 + name   - option name string
2061 . value  - option value string
2062 . source - The source for the option
2063 - ctx    - a `PETSCVIEWERASCII` or `NULL`
2064 
2065   Level: intermediate
2066 
2067   Notes:
2068   If ctx is `NULL`, `PetscPrintf()` is used.
2069   The first MPI process in the `PetscViewer` viewer actually prints the values, other
2070   processes may have different values set
2071 
2072   If `PetscCIEnabled` then do not print the test harness options
2073 
2074 .seealso: `PetscOptionsMonitorSet()`
2075 @*/
2076 PetscErrorCode PetscOptionsMonitorDefault(const char name[], const char value[], PetscOptionSource source, void *ctx)
2077 {
2078   PetscFunctionBegin;
2079   if (PetscCIOption(name)) PetscFunctionReturn(PETSC_SUCCESS);
2080 
2081   if (ctx) {
2082     PetscViewer viewer = (PetscViewer)ctx;
2083     if (!value) {
2084       PetscCall(PetscViewerASCIIPrintf(viewer, "Removing option: %s\n", name));
2085     } else if (!value[0]) {
2086       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2087     } else {
2088       PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2089     }
2090   } else {
2091     MPI_Comm comm = PETSC_COMM_WORLD;
2092     if (!value) {
2093       PetscCall(PetscPrintf(comm, "Removing option: %s\n", name));
2094     } else if (!value[0]) {
2095       PetscCall(PetscPrintf(comm, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2096     } else {
2097       PetscCall(PetscPrintf(comm, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2098     }
2099   }
2100   PetscFunctionReturn(PETSC_SUCCESS);
2101 }
2102 
2103 /*@C
2104   PetscOptionsMonitorSet - Sets an ADDITIONAL function to be called at every method that
2105   modified the PETSc options database.
2106 
2107   Not Collective
2108 
2109   Input Parameters:
2110 + monitor        - pointer to function (if this is `NULL`, it turns off monitoring
2111 . mctx           - [optional] context for private data for the monitor routine (use `NULL` if
2112                    no context is desired)
2113 - monitordestroy - [optional] routine that frees monitor context (may be `NULL`)
2114 
2115   Calling sequence of `monitor`:
2116 + name   - option name string
2117 . value  - option value string, a value of `NULL` indicates the option is being removed from the database. A value
2118            of "" indicates the option is in the database but has no value.
2119 . source - option source
2120 - mctx   - optional monitoring context, as set by `PetscOptionsMonitorSet()`
2121 
2122   Calling sequence of `monitordestroy`:
2123 . mctx - [optional] pointer to context to destroy with
2124 
2125   Options Database Keys:
2126 + -options_monitor <viewer> - turn on default monitoring
2127 - -options_monitor_cancel   - turn off any option monitors except the default monitor obtained with `-options_monitor`
2128 
2129   Level: intermediate
2130 
2131   Notes:
2132   See `PetscInitialize()` for options related to option database monitoring.
2133 
2134   The default is to do no monitoring.  To print the name and value of options
2135   being inserted into the database, use `PetscOptionsMonitorDefault()` as the monitoring routine,
2136   with a `NULL` monitoring context. Or use the option `-options_monitor` <viewer>.
2137 
2138   Several different monitoring routines may be set by calling
2139   `PetscOptionsMonitorSet()` multiple times; all will be called in the
2140   order in which they were set.
2141 
2142 .seealso: `PetscOptionsMonitorDefault()`, `PetscInitialize()`
2143 @*/
2144 PetscErrorCode PetscOptionsMonitorSet(PetscErrorCode (*monitor)(const char name[], const char value[], PetscOptionSource source, void *mctx), void *mctx, PetscErrorCode (*monitordestroy)(void **mctx))
2145 {
2146   PetscOptions options = defaultoptions;
2147 
2148   PetscFunctionBegin;
2149   if (options->monitorCancel) PetscFunctionReturn(PETSC_SUCCESS);
2150   PetscCheck(options->numbermonitors < MAXOPTIONSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptions monitors set");
2151   options->monitor[options->numbermonitors]          = monitor;
2152   options->monitordestroy[options->numbermonitors]   = monitordestroy;
2153   options->monitorcontext[options->numbermonitors++] = (void *)mctx;
2154   PetscFunctionReturn(PETSC_SUCCESS);
2155 }
2156 
2157 /*
2158    PetscOptionsStringToBool - Converts string to PetscBool, handles cases like "yes", "no", "true", "false", "0", "1", "off", "on".
2159      Empty string is considered as true.
2160 */
2161 PetscErrorCode PetscOptionsStringToBool(const char value[], PetscBool *a)
2162 {
2163   PetscBool istrue, isfalse;
2164   size_t    len;
2165 
2166   PetscFunctionBegin;
2167   /* PetscStrlen() returns 0 for NULL or "" */
2168   PetscCall(PetscStrlen(value, &len));
2169   if (!len) {
2170     *a = PETSC_TRUE;
2171     PetscFunctionReturn(PETSC_SUCCESS);
2172   }
2173   PetscCall(PetscStrcasecmp(value, "TRUE", &istrue));
2174   if (istrue) {
2175     *a = PETSC_TRUE;
2176     PetscFunctionReturn(PETSC_SUCCESS);
2177   }
2178   PetscCall(PetscStrcasecmp(value, "YES", &istrue));
2179   if (istrue) {
2180     *a = PETSC_TRUE;
2181     PetscFunctionReturn(PETSC_SUCCESS);
2182   }
2183   PetscCall(PetscStrcasecmp(value, "1", &istrue));
2184   if (istrue) {
2185     *a = PETSC_TRUE;
2186     PetscFunctionReturn(PETSC_SUCCESS);
2187   }
2188   PetscCall(PetscStrcasecmp(value, "on", &istrue));
2189   if (istrue) {
2190     *a = PETSC_TRUE;
2191     PetscFunctionReturn(PETSC_SUCCESS);
2192   }
2193   PetscCall(PetscStrcasecmp(value, "FALSE", &isfalse));
2194   if (isfalse) {
2195     *a = PETSC_FALSE;
2196     PetscFunctionReturn(PETSC_SUCCESS);
2197   }
2198   PetscCall(PetscStrcasecmp(value, "NO", &isfalse));
2199   if (isfalse) {
2200     *a = PETSC_FALSE;
2201     PetscFunctionReturn(PETSC_SUCCESS);
2202   }
2203   PetscCall(PetscStrcasecmp(value, "0", &isfalse));
2204   if (isfalse) {
2205     *a = PETSC_FALSE;
2206     PetscFunctionReturn(PETSC_SUCCESS);
2207   }
2208   PetscCall(PetscStrcasecmp(value, "off", &isfalse));
2209   if (isfalse) {
2210     *a = PETSC_FALSE;
2211     PetscFunctionReturn(PETSC_SUCCESS);
2212   }
2213   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown logical value: %s", value);
2214 }
2215 
2216 /*
2217    PetscOptionsStringToInt - Converts a string to an integer value. Handles special cases such as "default" and "decide"
2218 */
2219 PetscErrorCode PetscOptionsStringToInt(const char name[], PetscInt *a)
2220 {
2221   size_t    len;
2222   PetscBool decide, tdefault, mouse, unlimited;
2223 
2224   PetscFunctionBegin;
2225   PetscCall(PetscStrlen(name, &len));
2226   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2227 
2228   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &tdefault));
2229   if (!tdefault) PetscCall(PetscStrcasecmp(name, "DEFAULT", &tdefault));
2230   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &decide));
2231   if (!decide) PetscCall(PetscStrcasecmp(name, "DECIDE", &decide));
2232   if (!decide) PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &decide));
2233   if (!decide) PetscCall(PetscStrcasecmp(name, "DETERMINE", &decide));
2234   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &unlimited));
2235   if (!unlimited) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &unlimited));
2236   PetscCall(PetscStrcasecmp(name, "mouse", &mouse));
2237 
2238   if (tdefault) *a = PETSC_DEFAULT;
2239   else if (decide) *a = PETSC_DECIDE;
2240   else if (unlimited) *a = PETSC_UNLIMITED;
2241   else if (mouse) *a = -1;
2242   else {
2243     char *endptr;
2244     long  strtolval;
2245 
2246     strtolval = strtol(name, &endptr, 10);
2247     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);
2248 
2249 #if defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE_ATOLL)
2250     (void)strtolval;
2251     *a = atoll(name);
2252 #elif defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE___INT64)
2253     (void)strtolval;
2254     *a = _atoi64(name);
2255 #else
2256     *a = (PetscInt)strtolval;
2257 #endif
2258   }
2259   PetscFunctionReturn(PETSC_SUCCESS);
2260 }
2261 
2262 #if defined(PETSC_USE_REAL___FLOAT128)
2263   #include <quadmath.h>
2264 #endif
2265 
2266 static PetscErrorCode PetscStrtod(const char name[], PetscReal *a, char **endptr)
2267 {
2268   PetscFunctionBegin;
2269 #if defined(PETSC_USE_REAL___FLOAT128)
2270   *a = strtoflt128(name, endptr);
2271 #else
2272   *a = (PetscReal)strtod(name, endptr);
2273 #endif
2274   PetscFunctionReturn(PETSC_SUCCESS);
2275 }
2276 
2277 static PetscErrorCode PetscStrtoz(const char name[], PetscScalar *a, char **endptr, PetscBool *isImaginary)
2278 {
2279   PetscBool hasi = PETSC_FALSE;
2280   char     *ptr;
2281   PetscReal strtoval;
2282 
2283   PetscFunctionBegin;
2284   PetscCall(PetscStrtod(name, &strtoval, &ptr));
2285   if (ptr == name) {
2286     strtoval = 1.;
2287     hasi     = PETSC_TRUE;
2288     if (name[0] == 'i') {
2289       ptr++;
2290     } else if (name[0] == '+' && name[1] == 'i') {
2291       ptr += 2;
2292     } else if (name[0] == '-' && name[1] == 'i') {
2293       strtoval = -1.;
2294       ptr += 2;
2295     }
2296   } else if (*ptr == 'i') {
2297     hasi = PETSC_TRUE;
2298     ptr++;
2299   }
2300   *endptr      = ptr;
2301   *isImaginary = hasi;
2302   if (hasi) {
2303 #if !defined(PETSC_USE_COMPLEX)
2304     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s contains imaginary but complex not supported ", name);
2305 #else
2306     *a = PetscCMPLX(0., strtoval);
2307 #endif
2308   } else {
2309     *a = strtoval;
2310   }
2311   PetscFunctionReturn(PETSC_SUCCESS);
2312 }
2313 
2314 /*
2315    Converts a string to PetscReal value. Handles special cases like "default" and "decide"
2316 */
2317 PetscErrorCode PetscOptionsStringToReal(const char name[], PetscReal *a)
2318 {
2319   size_t    len;
2320   PetscBool match;
2321   char     *endptr;
2322 
2323   PetscFunctionBegin;
2324   PetscCall(PetscStrlen(name, &len));
2325   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "String of length zero has no numerical value");
2326 
2327   PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &match));
2328   if (!match) PetscCall(PetscStrcasecmp(name, "DEFAULT", &match));
2329   if (match) {
2330     *a = PETSC_DEFAULT;
2331     PetscFunctionReturn(PETSC_SUCCESS);
2332   }
2333 
2334   PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &match));
2335   if (!match) PetscCall(PetscStrcasecmp(name, "DECIDE", &match));
2336   if (match) {
2337     *a = PETSC_DECIDE;
2338     PetscFunctionReturn(PETSC_SUCCESS);
2339   }
2340 
2341   PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &match));
2342   if (!match) PetscCall(PetscStrcasecmp(name, "DETERMINE", &match));
2343   if (match) {
2344     *a = PETSC_DETERMINE;
2345     PetscFunctionReturn(PETSC_SUCCESS);
2346   }
2347 
2348   PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &match));
2349   if (!match) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &match));
2350   if (match) {
2351     *a = PETSC_UNLIMITED;
2352     PetscFunctionReturn(PETSC_SUCCESS);
2353   }
2354 
2355   PetscCall(PetscStrtod(name, a, &endptr));
2356   PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value", name);
2357   PetscFunctionReturn(PETSC_SUCCESS);
2358 }
2359 
2360 PetscErrorCode PetscOptionsStringToScalar(const char name[], PetscScalar *a)
2361 {
2362   PetscBool   imag1;
2363   size_t      len;
2364   PetscScalar val = 0.;
2365   char       *ptr = NULL;
2366 
2367   PetscFunctionBegin;
2368   PetscCall(PetscStrlen(name, &len));
2369   PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2370   PetscCall(PetscStrtoz(name, &val, &ptr, &imag1));
2371 #if defined(PETSC_USE_COMPLEX)
2372   if ((size_t)(ptr - name) < len) {
2373     PetscBool   imag2;
2374     PetscScalar val2;
2375 
2376     PetscCall(PetscStrtoz(ptr, &val2, &ptr, &imag2));
2377     if (imag1) PetscCheck(imag2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s: must specify imaginary component second", name);
2378     val = PetscCMPLX(PetscRealPart(val), PetscImaginaryPart(val2));
2379   }
2380 #endif
2381   PetscCheck((size_t)(ptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value ", name);
2382   *a = val;
2383   PetscFunctionReturn(PETSC_SUCCESS);
2384 }
2385 
2386 /*@C
2387   PetscOptionsGetBool - Gets the Logical (true or false) value for a particular
2388   option in the database.
2389 
2390   Not Collective
2391 
2392   Input Parameters:
2393 + options - options database, use `NULL` for default global database
2394 . pre     - the string to prepend to the name or `NULL`
2395 - name    - the option one is seeking
2396 
2397   Output Parameters:
2398 + ivalue - the logical value to return
2399 - set    - `PETSC_TRUE`  if found, else `PETSC_FALSE`
2400 
2401   Level: beginner
2402 
2403   Notes:
2404   TRUE, true, YES, yes, nostring, and 1 all translate to `PETSC_TRUE`
2405   FALSE, false, NO, no, and 0 all translate to `PETSC_FALSE`
2406 
2407   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`
2408   is equivalent to `-requested_bool true`
2409 
2410   If the user does not supply the option at all `ivalue` is NOT changed. Thus
2411   you should ALWAYS initialize `ivalue` if you access it without first checking that the `set` flag is true.
2412 
2413 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2414           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2415           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2416           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2417           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2418           `PetscOptionsFList()`, `PetscOptionsEList()`
2419 @*/
2420 PetscErrorCode PetscOptionsGetBool(PetscOptions options, const char pre[], const char name[], PetscBool *ivalue, PetscBool *set)
2421 {
2422   const char *value;
2423   PetscBool   flag;
2424 
2425   PetscFunctionBegin;
2426   PetscAssertPointer(name, 3);
2427   if (ivalue) PetscAssertPointer(ivalue, 4);
2428   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2429   if (flag) {
2430     if (set) *set = PETSC_TRUE;
2431     PetscCall(PetscOptionsStringToBool(value, &flag));
2432     if (ivalue) *ivalue = flag;
2433   } else {
2434     if (set) *set = PETSC_FALSE;
2435   }
2436   PetscFunctionReturn(PETSC_SUCCESS);
2437 }
2438 
2439 /*@C
2440   PetscOptionsGetEList - Puts a list of option values that a single one may be selected from
2441 
2442   Not Collective
2443 
2444   Input Parameters:
2445 + options - options database, use `NULL` for default global database
2446 . pre     - the string to prepend to the name or `NULL`
2447 . opt     - option name
2448 . list    - the possible choices (one of these must be selected, anything else is invalid)
2449 - ntext   - number of choices
2450 
2451   Output Parameters:
2452 + value - the index of the value to return (defaults to zero if the option name is given but no choice is listed)
2453 - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`
2454 
2455   Level: intermediate
2456 
2457   Notes:
2458   If the user does not supply the option `value` is NOT changed. Thus
2459   you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.
2460 
2461   See `PetscOptionsFList()` for when the choices are given in a `PetscFunctionList`
2462 
2463 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2464           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2465           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2466           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2467           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2468           `PetscOptionsFList()`, `PetscOptionsEList()`
2469 @*/
2470 PetscErrorCode PetscOptionsGetEList(PetscOptions options, const char pre[], const char opt[], const char *const *list, PetscInt ntext, PetscInt *value, PetscBool *set)
2471 {
2472   size_t    alen, len = 0, tlen = 0;
2473   char     *svalue;
2474   PetscBool aset, flg = PETSC_FALSE;
2475   PetscInt  i;
2476 
2477   PetscFunctionBegin;
2478   PetscAssertPointer(opt, 3);
2479   for (i = 0; i < ntext; i++) {
2480     PetscCall(PetscStrlen(list[i], &alen));
2481     if (alen > len) len = alen;
2482     tlen += len + 1;
2483   }
2484   len += 5; /* a little extra space for user mistypes */
2485   PetscCall(PetscMalloc1(len, &svalue));
2486   PetscCall(PetscOptionsGetString(options, pre, opt, svalue, len, &aset));
2487   if (aset) {
2488     PetscCall(PetscEListFind(ntext, list, svalue, value, &flg));
2489     if (!flg) {
2490       char *avail;
2491 
2492       PetscCall(PetscMalloc1(tlen, &avail));
2493       avail[0] = '\0';
2494       for (i = 0; i < ntext; i++) {
2495         PetscCall(PetscStrlcat(avail, list[i], tlen));
2496         PetscCall(PetscStrlcat(avail, " ", tlen));
2497       }
2498       PetscCall(PetscStrtolower(avail));
2499       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown option %s for -%s%s. Available options: %s", svalue, pre ? pre : "", opt + 1, avail);
2500     }
2501     if (set) *set = PETSC_TRUE;
2502   } else if (set) *set = PETSC_FALSE;
2503   PetscCall(PetscFree(svalue));
2504   PetscFunctionReturn(PETSC_SUCCESS);
2505 }
2506 
2507 /*@C
2508   PetscOptionsGetEnum - Gets the enum value for a particular option in the database.
2509 
2510   Not Collective
2511 
2512   Input Parameters:
2513 + options - options database, use `NULL` for default global database
2514 . pre     - option prefix or `NULL`
2515 . opt     - option name
2516 - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
2517 
2518   Output Parameters:
2519 + value - the value to return
2520 - set   - `PETSC_TRUE` if found, else `PETSC_FALSE`
2521 
2522   Level: beginner
2523 
2524   Notes:
2525   If the user does not supply the option `value` is NOT changed. Thus
2526   you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.
2527 
2528   `list` is usually something like `PCASMTypes` or some other predefined list of enum names
2529 
2530 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2531           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2532           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2533           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2534           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2535           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2536           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2537 @*/
2538 PetscErrorCode PetscOptionsGetEnum(PetscOptions options, const char pre[], const char opt[], const char *const *list, PetscEnum *value, PetscBool *set)
2539 {
2540   PetscInt  ntext = 0, tval;
2541   PetscBool fset;
2542 
2543   PetscFunctionBegin;
2544   PetscAssertPointer(opt, 3);
2545   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");
2546   PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
2547   ntext -= 3;
2548   PetscCall(PetscOptionsGetEList(options, pre, opt, list, ntext, &tval, &fset));
2549   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
2550   if (fset) *value = (PetscEnum)tval;
2551   if (set) *set = fset;
2552   PetscFunctionReturn(PETSC_SUCCESS);
2553 }
2554 
2555 /*@C
2556   PetscOptionsGetInt - Gets the integer value for a particular option in the database.
2557 
2558   Not Collective
2559 
2560   Input Parameters:
2561 + options - options database, use `NULL` for default global database
2562 . pre     - the string to prepend to the name or `NULL`
2563 - name    - the option one is seeking
2564 
2565   Output Parameters:
2566 + ivalue - the integer value to return
2567 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2568 
2569   Level: beginner
2570 
2571   Notes:
2572   If the user does not supply the option `ivalue` is NOT changed. Thus
2573   you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.
2574 
2575   Accepts the special values `determine`, `decide` and `unlimited`.
2576 
2577   Accepts the deprecated value `default`.
2578 
2579 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2580           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2581           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2582           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2583           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2584           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2585           `PetscOptionsFList()`, `PetscOptionsEList()`
2586 @*/
2587 PetscErrorCode PetscOptionsGetInt(PetscOptions options, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
2588 {
2589   const char *value;
2590   PetscBool   flag;
2591 
2592   PetscFunctionBegin;
2593   PetscAssertPointer(name, 3);
2594   PetscAssertPointer(ivalue, 4);
2595   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2596   if (flag) {
2597     if (!value) {
2598       if (set) *set = PETSC_FALSE;
2599     } else {
2600       if (set) *set = PETSC_TRUE;
2601       PetscCall(PetscOptionsStringToInt(value, ivalue));
2602     }
2603   } else {
2604     if (set) *set = PETSC_FALSE;
2605   }
2606   PetscFunctionReturn(PETSC_SUCCESS);
2607 }
2608 
2609 /*@C
2610   PetscOptionsGetMPIInt - Gets the MPI integer value for a particular option in the database.
2611 
2612   Not Collective
2613 
2614   Input Parameters:
2615 + options - options database, use `NULL` for default global database
2616 . pre     - the string to prepend to the name or `NULL`
2617 - name    - the option one is seeking
2618 
2619   Output Parameters:
2620 + ivalue - the MPI integer value to return
2621 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2622 
2623   Level: beginner
2624 
2625   Notes:
2626   If the user does not supply the option `ivalue` is NOT changed. Thus
2627   you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.
2628 
2629   Accepts the special values `determine`, `decide` and `unlimited`.
2630 
2631   Accepts the deprecated value `default`.
2632 
2633 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2634           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2635           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2636           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2637           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2638           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2639           `PetscOptionsFList()`, `PetscOptionsEList()`
2640 @*/
2641 PetscErrorCode PetscOptionsGetMPIInt(PetscOptions options, const char pre[], const char name[], PetscMPIInt *ivalue, PetscBool *set)
2642 {
2643   PetscInt  value;
2644   PetscBool flag;
2645 
2646   PetscFunctionBegin;
2647   PetscCall(PetscOptionsGetInt(options, pre, name, &value, &flag));
2648   if (flag) PetscCall(PetscMPIIntCast(value, ivalue));
2649   if (set) *set = flag;
2650   PetscFunctionReturn(PETSC_SUCCESS);
2651 }
2652 
2653 /*@C
2654   PetscOptionsGetReal - Gets the double precision value for a particular
2655   option in the database.
2656 
2657   Not Collective
2658 
2659   Input Parameters:
2660 + options - options database, use `NULL` for default global database
2661 . pre     - string to prepend to each name or `NULL`
2662 - name    - the option one is seeking
2663 
2664   Output Parameters:
2665 + dvalue - the double value to return
2666 - set    - `PETSC_TRUE` if found, `PETSC_FALSE` if not found
2667 
2668   Level: beginner
2669 
2670   Notes:
2671   Accepts the special values `determine`, `decide` and `unlimited`.
2672 
2673   Accepts the deprecated value `default`
2674 
2675   If the user does not supply the option `dvalue` is NOT changed. Thus
2676   you should ALWAYS initialize `dvalue` if you access it without first checking that the `set` flag is true.
2677 
2678 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2679           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2680           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2681           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2682           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2683           `PetscOptionsFList()`, `PetscOptionsEList()`
2684 @*/
2685 PetscErrorCode PetscOptionsGetReal(PetscOptions options, const char pre[], const char name[], PetscReal *dvalue, PetscBool *set)
2686 {
2687   const char *value;
2688   PetscBool   flag;
2689 
2690   PetscFunctionBegin;
2691   PetscAssertPointer(name, 3);
2692   PetscAssertPointer(dvalue, 4);
2693   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2694   if (flag) {
2695     if (!value) {
2696       if (set) *set = PETSC_FALSE;
2697     } else {
2698       if (set) *set = PETSC_TRUE;
2699       PetscCall(PetscOptionsStringToReal(value, dvalue));
2700     }
2701   } else {
2702     if (set) *set = PETSC_FALSE;
2703   }
2704   PetscFunctionReturn(PETSC_SUCCESS);
2705 }
2706 
2707 /*@C
2708   PetscOptionsGetScalar - Gets the scalar value for a particular
2709   option in the database.
2710 
2711   Not Collective
2712 
2713   Input Parameters:
2714 + options - options database, use `NULL` for default global database
2715 . pre     - string to prepend to each name or `NULL`
2716 - name    - the option one is seeking
2717 
2718   Output Parameters:
2719 + dvalue - the scalar value to return
2720 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2721 
2722   Level: beginner
2723 
2724   Example Usage:
2725   A complex number 2+3i must be specified with NO spaces
2726 
2727   Note:
2728   If the user does not supply the option `dvalue` is NOT changed. Thus
2729   you should ALWAYS initialize `dvalue` if you access it without first checking if the `set` flag is true.
2730 
2731 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2732           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2733           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2734           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2735           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2736           `PetscOptionsFList()`, `PetscOptionsEList()`
2737 @*/
2738 PetscErrorCode PetscOptionsGetScalar(PetscOptions options, const char pre[], const char name[], PetscScalar *dvalue, PetscBool *set)
2739 {
2740   const char *value;
2741   PetscBool   flag;
2742 
2743   PetscFunctionBegin;
2744   PetscAssertPointer(name, 3);
2745   PetscAssertPointer(dvalue, 4);
2746   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2747   if (flag) {
2748     if (!value) {
2749       if (set) *set = PETSC_FALSE;
2750     } else {
2751 #if !defined(PETSC_USE_COMPLEX)
2752       PetscCall(PetscOptionsStringToReal(value, dvalue));
2753 #else
2754       PetscCall(PetscOptionsStringToScalar(value, dvalue));
2755 #endif
2756       if (set) *set = PETSC_TRUE;
2757     }
2758   } else { /* flag */
2759     if (set) *set = PETSC_FALSE;
2760   }
2761   PetscFunctionReturn(PETSC_SUCCESS);
2762 }
2763 
2764 /*@C
2765   PetscOptionsGetString - Gets the string value for a particular option in
2766   the database.
2767 
2768   Not Collective
2769 
2770   Input Parameters:
2771 + options - options database, use `NULL` for default global database
2772 . pre     - string to prepend to name or `NULL`
2773 . name    - the option one is seeking
2774 - len     - maximum length of the string including null termination
2775 
2776   Output Parameters:
2777 + string - location to copy string
2778 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2779 
2780   Level: beginner
2781 
2782   Note:
2783   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`
2784 
2785   If the user does not use the option then `string` is not changed. Thus
2786   you should ALWAYS initialize `string` if you access it without first checking that the `set` flag is true.
2787 
2788   Fortran Notes:
2789   The Fortran interface is slightly different from the C/C++
2790   interface (len is not used).  Sample usage in Fortran follows
2791 .vb
2792       character *20    string
2793       PetscErrorCode   ierr
2794       PetscBool        set
2795       call PetscOptionsGetString(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-s',string,set,ierr)
2796 .ve
2797 
2798 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2799           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2800           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2801           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2802           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2803           `PetscOptionsFList()`, `PetscOptionsEList()`
2804 @*/
2805 PetscErrorCode PetscOptionsGetString(PetscOptions options, const char pre[], const char name[], char string[], size_t len, PetscBool *set)
2806 {
2807   const char *value;
2808   PetscBool   flag;
2809 
2810   PetscFunctionBegin;
2811   PetscAssertPointer(name, 3);
2812   PetscAssertPointer(string, 4);
2813   PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2814   if (!flag) {
2815     if (set) *set = PETSC_FALSE;
2816   } else {
2817     if (set) *set = PETSC_TRUE;
2818     if (value) PetscCall(PetscStrncpy(string, value, len));
2819     else PetscCall(PetscArrayzero(string, len));
2820   }
2821   PetscFunctionReturn(PETSC_SUCCESS);
2822 }
2823 
2824 /*@C
2825   PetscOptionsGetBoolArray - Gets an array of Logical (true or false) values for a particular
2826   option in the database.  The values must be separated with commas with no intervening spaces.
2827 
2828   Not Collective
2829 
2830   Input Parameters:
2831 + options - options database, use `NULL` for default global database
2832 . pre     - string to prepend to each name or `NULL`
2833 - name    - the option one is seeking
2834 
2835   Output Parameters:
2836 + dvalue - the Boolean values to return
2837 . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2838 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2839 
2840   Level: beginner
2841 
2842   Note:
2843   TRUE, true, YES, yes, nostring, and 1 all translate to `PETSC_TRUE`. FALSE, false, NO, no, and 0 all translate to `PETSC_FALSE`
2844 
2845 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2846           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2847           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2848           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2849           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2850           `PetscOptionsFList()`, `PetscOptionsEList()`
2851 @*/
2852 PetscErrorCode PetscOptionsGetBoolArray(PetscOptions options, const char pre[], const char name[], PetscBool dvalue[], PetscInt *nmax, PetscBool *set)
2853 {
2854   const char *svalue;
2855   char       *value;
2856   PetscInt    n = 0;
2857   PetscBool   flag;
2858   PetscToken  token;
2859 
2860   PetscFunctionBegin;
2861   PetscAssertPointer(name, 3);
2862   PetscAssertPointer(dvalue, 4);
2863   PetscAssertPointer(nmax, 5);
2864 
2865   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
2866   if (!flag || !svalue) {
2867     if (set) *set = PETSC_FALSE;
2868     *nmax = 0;
2869     PetscFunctionReturn(PETSC_SUCCESS);
2870   }
2871   if (set) *set = PETSC_TRUE;
2872   PetscCall(PetscTokenCreate(svalue, ',', &token));
2873   PetscCall(PetscTokenFind(token, &value));
2874   while (value && n < *nmax) {
2875     PetscCall(PetscOptionsStringToBool(value, dvalue));
2876     PetscCall(PetscTokenFind(token, &value));
2877     dvalue++;
2878     n++;
2879   }
2880   PetscCall(PetscTokenDestroy(&token));
2881   *nmax = n;
2882   PetscFunctionReturn(PETSC_SUCCESS);
2883 }
2884 
2885 /*@C
2886   PetscOptionsGetEnumArray - Gets an array of enum values for a particular option in the database.
2887 
2888   Not Collective
2889 
2890   Input Parameters:
2891 + options - options database, use `NULL` for default global database
2892 . pre     - option prefix or `NULL`
2893 . name    - option name
2894 - list    - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
2895 
2896   Output Parameters:
2897 + ivalue - the  enum values to return
2898 . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2899 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2900 
2901   Level: beginner
2902 
2903   Notes:
2904   The array must be passed as a comma separated list with no spaces between the items.
2905 
2906   `list` is usually something like `PCASMTypes` or some other predefined list of enum names.
2907 
2908 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2909           `PetscOptionsGetEnum()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2910           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsName()`,
2911           `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, `PetscOptionsStringArray()`, `PetscOptionsRealArray()`,
2912           `PetscOptionsScalar()`, `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2913           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2914 @*/
2915 PetscErrorCode PetscOptionsGetEnumArray(PetscOptions options, const char pre[], const char name[], const char *const *list, PetscEnum ivalue[], PetscInt *nmax, PetscBool *set)
2916 {
2917   const char *svalue;
2918   char       *value;
2919   PetscInt    n = 0;
2920   PetscEnum   evalue;
2921   PetscBool   flag;
2922   PetscToken  token;
2923 
2924   PetscFunctionBegin;
2925   PetscAssertPointer(name, 3);
2926   PetscAssertPointer(list, 4);
2927   PetscAssertPointer(ivalue, 5);
2928   PetscAssertPointer(nmax, 6);
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(PetscEnumFind(list, value, &evalue, &flag));
2941     PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown enum value '%s' for -%s%s", svalue, pre ? pre : "", name + 1);
2942     ivalue[n++] = evalue;
2943     PetscCall(PetscTokenFind(token, &value));
2944   }
2945   PetscCall(PetscTokenDestroy(&token));
2946   *nmax = n;
2947   PetscFunctionReturn(PETSC_SUCCESS);
2948 }
2949 
2950 /*@C
2951   PetscOptionsGetIntArray - Gets an array of integer 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     - string to prepend to each name or `NULL`
2958 - name    - the option one is seeking
2959 
2960   Output Parameters:
2961 + ivalue - the integer values to return
2962 . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
2963 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
2964 
2965   Level: beginner
2966 
2967   Notes:
2968   The array can be passed as
2969 +  a comma separated list -                                 0,1,2,3,4,5,6,7
2970 .  a range (start\-end+1) -                                 0-8
2971 .  a range with given increment (start\-end+1:inc) -        0-7:2
2972 -  a combination of values and ranges separated by commas - 0,1-8,8-15:2
2973 
2974   There must be no intervening spaces between the values.
2975 
2976 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2977           `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2978           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2979           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2980           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2981           `PetscOptionsFList()`, `PetscOptionsEList()`
2982 @*/
2983 PetscErrorCode PetscOptionsGetIntArray(PetscOptions options, const char pre[], const char name[], PetscInt ivalue[], PetscInt *nmax, PetscBool *set)
2984 {
2985   const char *svalue;
2986   char       *value;
2987   PetscInt    n = 0, i, j, start, end, inc, nvalues;
2988   size_t      len;
2989   PetscBool   flag, foundrange;
2990   PetscToken  token;
2991 
2992   PetscFunctionBegin;
2993   PetscAssertPointer(name, 3);
2994   PetscAssertPointer(ivalue, 4);
2995   PetscAssertPointer(nmax, 5);
2996 
2997   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
2998   if (!flag || !svalue) {
2999     if (set) *set = PETSC_FALSE;
3000     *nmax = 0;
3001     PetscFunctionReturn(PETSC_SUCCESS);
3002   }
3003   if (set) *set = PETSC_TRUE;
3004   PetscCall(PetscTokenCreate(svalue, ',', &token));
3005   PetscCall(PetscTokenFind(token, &value));
3006   while (value && n < *nmax) {
3007     /* look for form  d-D where d and D are integers */
3008     foundrange = PETSC_FALSE;
3009     PetscCall(PetscStrlen(value, &len));
3010     if (value[0] == '-') i = 2;
3011     else i = 1;
3012     for (; i < (int)len; i++) {
3013       if (value[i] == '-') {
3014         PetscCheck(i != (int)len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, value);
3015         value[i] = 0;
3016 
3017         PetscCall(PetscOptionsStringToInt(value, &start));
3018         inc = 1;
3019         j   = i + 1;
3020         for (; j < (int)len; j++) {
3021           if (value[j] == ':') {
3022             value[j] = 0;
3023 
3024             PetscCall(PetscOptionsStringToInt(value + j + 1, &inc));
3025             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);
3026             break;
3027           }
3028         }
3029         PetscCall(PetscOptionsStringToInt(value + i + 1, &end));
3030         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);
3031         nvalues = (end - start) / inc + (end - start) % inc;
3032         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);
3033         for (; start < end; start += inc) {
3034           *ivalue = start;
3035           ivalue++;
3036           n++;
3037         }
3038         foundrange = PETSC_TRUE;
3039         break;
3040       }
3041     }
3042     if (!foundrange) {
3043       PetscCall(PetscOptionsStringToInt(value, ivalue));
3044       ivalue++;
3045       n++;
3046     }
3047     PetscCall(PetscTokenFind(token, &value));
3048   }
3049   PetscCall(PetscTokenDestroy(&token));
3050   *nmax = n;
3051   PetscFunctionReturn(PETSC_SUCCESS);
3052 }
3053 
3054 /*@C
3055   PetscOptionsGetRealArray - Gets an array of double precision values for a
3056   particular option in the database.  The values must be separated with commas with no intervening spaces.
3057 
3058   Not Collective
3059 
3060   Input Parameters:
3061 + options - options database, use `NULL` for default global database
3062 . pre     - string to prepend to each name or `NULL`
3063 - name    - the option one is seeking
3064 
3065   Output Parameters:
3066 + dvalue - the double values to return
3067 . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3068 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
3069 
3070   Level: beginner
3071 
3072 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3073           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3074           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3075           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3076           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3077           `PetscOptionsFList()`, `PetscOptionsEList()`
3078 @*/
3079 PetscErrorCode PetscOptionsGetRealArray(PetscOptions options, const char pre[], const char name[], PetscReal dvalue[], PetscInt *nmax, PetscBool *set)
3080 {
3081   const char *svalue;
3082   char       *value;
3083   PetscInt    n = 0;
3084   PetscBool   flag;
3085   PetscToken  token;
3086 
3087   PetscFunctionBegin;
3088   PetscAssertPointer(name, 3);
3089   PetscAssertPointer(dvalue, 4);
3090   PetscAssertPointer(nmax, 5);
3091 
3092   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3093   if (!flag || !svalue) {
3094     if (set) *set = PETSC_FALSE;
3095     *nmax = 0;
3096     PetscFunctionReturn(PETSC_SUCCESS);
3097   }
3098   if (set) *set = PETSC_TRUE;
3099   PetscCall(PetscTokenCreate(svalue, ',', &token));
3100   PetscCall(PetscTokenFind(token, &value));
3101   while (value && n < *nmax) {
3102     PetscCall(PetscOptionsStringToReal(value, dvalue++));
3103     PetscCall(PetscTokenFind(token, &value));
3104     n++;
3105   }
3106   PetscCall(PetscTokenDestroy(&token));
3107   *nmax = n;
3108   PetscFunctionReturn(PETSC_SUCCESS);
3109 }
3110 
3111 /*@C
3112   PetscOptionsGetScalarArray - Gets an array of scalars for a
3113   particular option in the database.  The values must be separated with commas with no intervening spaces.
3114 
3115   Not Collective
3116 
3117   Input Parameters:
3118 + options - options database, use `NULL` for default global database
3119 . pre     - string to prepend to each name or `NULL`
3120 - name    - the option one is seeking
3121 
3122   Output Parameters:
3123 + dvalue - the scalar values to return
3124 . nmax   - On input maximum number of values to retrieve, on output the actual number of values retrieved
3125 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
3126 
3127   Level: beginner
3128 
3129 .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3130           `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3131           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3132           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3133           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3134           `PetscOptionsFList()`, `PetscOptionsEList()`
3135 @*/
3136 PetscErrorCode PetscOptionsGetScalarArray(PetscOptions options, const char pre[], const char name[], PetscScalar dvalue[], PetscInt *nmax, PetscBool *set)
3137 {
3138   const char *svalue;
3139   char       *value;
3140   PetscInt    n = 0;
3141   PetscBool   flag;
3142   PetscToken  token;
3143 
3144   PetscFunctionBegin;
3145   PetscAssertPointer(name, 3);
3146   PetscAssertPointer(dvalue, 4);
3147   PetscAssertPointer(nmax, 5);
3148 
3149   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3150   if (!flag || !svalue) {
3151     if (set) *set = PETSC_FALSE;
3152     *nmax = 0;
3153     PetscFunctionReturn(PETSC_SUCCESS);
3154   }
3155   if (set) *set = PETSC_TRUE;
3156   PetscCall(PetscTokenCreate(svalue, ',', &token));
3157   PetscCall(PetscTokenFind(token, &value));
3158   while (value && n < *nmax) {
3159     PetscCall(PetscOptionsStringToScalar(value, dvalue++));
3160     PetscCall(PetscTokenFind(token, &value));
3161     n++;
3162   }
3163   PetscCall(PetscTokenDestroy(&token));
3164   *nmax = n;
3165   PetscFunctionReturn(PETSC_SUCCESS);
3166 }
3167 
3168 /*@C
3169   PetscOptionsGetStringArray - Gets an array of string values for a particular
3170   option in the database. The values must be separated with commas with no intervening spaces.
3171 
3172   Not Collective; No Fortran Support
3173 
3174   Input Parameters:
3175 + options - options database, use `NULL` for default global database
3176 . pre     - string to prepend to name or `NULL`
3177 - name    - the option one is seeking
3178 
3179   Output Parameters:
3180 + strings - location to copy strings
3181 . nmax    - On input maximum number of strings, on output the actual number of strings found
3182 - set     - `PETSC_TRUE` if found, else `PETSC_FALSE`
3183 
3184   Level: beginner
3185 
3186   Notes:
3187   The `nmax` parameter is used for both input and output.
3188 
3189   The user should pass in an array of pointers to char, to hold all the
3190   strings returned by this function.
3191 
3192   The user is responsible for deallocating the strings that are
3193   returned.
3194 
3195 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
3196           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3197           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3198           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3199           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3200           `PetscOptionsFList()`, `PetscOptionsEList()`
3201 @*/
3202 PetscErrorCode PetscOptionsGetStringArray(PetscOptions options, const char pre[], const char name[], char *strings[], PetscInt *nmax, PetscBool *set)
3203 {
3204   const char *svalue;
3205   char       *value;
3206   PetscInt    n = 0;
3207   PetscBool   flag;
3208   PetscToken  token;
3209 
3210   PetscFunctionBegin;
3211   PetscAssertPointer(name, 3);
3212   PetscAssertPointer(strings, 4);
3213   PetscAssertPointer(nmax, 5);
3214 
3215   PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3216   if (!flag || !svalue) {
3217     if (set) *set = PETSC_FALSE;
3218     *nmax = 0;
3219     PetscFunctionReturn(PETSC_SUCCESS);
3220   }
3221   if (set) *set = PETSC_TRUE;
3222   PetscCall(PetscTokenCreate(svalue, ',', &token));
3223   PetscCall(PetscTokenFind(token, &value));
3224   while (value && n < *nmax) {
3225     PetscCall(PetscStrallocpy(value, &strings[n]));
3226     PetscCall(PetscTokenFind(token, &value));
3227     n++;
3228   }
3229   PetscCall(PetscTokenDestroy(&token));
3230   *nmax = n;
3231   PetscFunctionReturn(PETSC_SUCCESS);
3232 }
3233 
3234 /*@C
3235   PetscOptionsDeprecated_Private - mark an option as deprecated, optionally replacing it with `newname`
3236 
3237   Prints a deprecation warning, unless an option is supplied to suppress.
3238 
3239   Logically Collective
3240 
3241   Input Parameters:
3242 + PetscOptionsObject - string to prepend to name or `NULL`
3243 . oldname            - the old, deprecated option
3244 . newname            - the new option, or `NULL` if option is purely removed
3245 . version            - a string describing the version of first deprecation, e.g. "3.9"
3246 - info               - additional information string, or `NULL`.
3247 
3248   Options Database Key:
3249 . -options_suppress_deprecated_warnings - do not print deprecation warnings
3250 
3251   Level: developer
3252 
3253   Notes:
3254   If `newname` is provided then the options database will automatically check the database for `oldname`.
3255 
3256   The old call `PetscOptionsXXX`(`oldname`) should be removed from the source code when both (1) the call to `PetscOptionsDeprecated()` occurs before the
3257   new call to `PetscOptionsXXX`(`newname`) and (2) the argument handling of the new call to `PetscOptionsXXX`(`newname`) is identical to the previous call.
3258   See `PTScotch_PartGraph_Seq()` for an example of when (1) fails and `SNESTestJacobian()` where an example of (2) fails.
3259 
3260   Must be called between `PetscOptionsBegin()` (or `PetscObjectOptionsBegin()`) and `PetscOptionsEnd()`.
3261   Only the process of rank zero that owns the `PetscOptionsItems` are argument (managed by `PetscOptionsBegin()` or
3262   `PetscObjectOptionsBegin()` prints the information
3263   If newname is provided, the old option is replaced. Otherwise, it remains
3264   in the options database.
3265   If an option is not replaced, the info argument should be used to advise the user
3266   on how to proceed.
3267   There is a limit on the length of the warning printed, so very long strings
3268   provided as info may be truncated.
3269 
3270 .seealso: `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsScalar()`, `PetscOptionsBool()`, `PetscOptionsString()`, `PetscOptionsSetValue()`
3271 @*/
3272 PetscErrorCode PetscOptionsDeprecated_Private(PetscOptionItems *PetscOptionsObject, const char oldname[], const char newname[], const char version[], const char info[])
3273 {
3274   PetscBool         found, quiet;
3275   const char       *value;
3276   const char *const quietopt = "-options_suppress_deprecated_warnings";
3277   char              msg[4096];
3278   char             *prefix  = NULL;
3279   PetscOptions      options = NULL;
3280   MPI_Comm          comm    = PETSC_COMM_SELF;
3281 
3282   PetscFunctionBegin;
3283   PetscAssertPointer(oldname, 2);
3284   PetscAssertPointer(version, 4);
3285   if (PetscOptionsObject) {
3286     prefix  = PetscOptionsObject->prefix;
3287     options = PetscOptionsObject->options;
3288     comm    = PetscOptionsObject->comm;
3289   }
3290   PetscCall(PetscOptionsFindPair(options, prefix, oldname, &value, &found));
3291   if (found) {
3292     if (newname) {
3293       if (prefix) PetscCall(PetscOptionsPrefixPush(options, prefix));
3294       PetscCall(PetscOptionsSetValue(options, newname, value));
3295       if (prefix) PetscCall(PetscOptionsPrefixPop(options));
3296       PetscCall(PetscOptionsClearValue(options, oldname));
3297     }
3298     quiet = PETSC_FALSE;
3299     PetscCall(PetscOptionsGetBool(options, NULL, quietopt, &quiet, NULL));
3300     if (!quiet) {
3301       PetscCall(PetscStrncpy(msg, "** PETSc DEPRECATION WARNING ** : the option ", sizeof(msg)));
3302       PetscCall(PetscStrlcat(msg, oldname, sizeof(msg)));
3303       PetscCall(PetscStrlcat(msg, " is deprecated as of version ", sizeof(msg)));
3304       PetscCall(PetscStrlcat(msg, version, sizeof(msg)));
3305       PetscCall(PetscStrlcat(msg, " and will be removed in a future release.\n", sizeof(msg)));
3306       if (newname) {
3307         PetscCall(PetscStrlcat(msg, "   Use the option ", sizeof(msg)));
3308         PetscCall(PetscStrlcat(msg, newname, sizeof(msg)));
3309         PetscCall(PetscStrlcat(msg, " instead.", sizeof(msg)));
3310       }
3311       if (info) {
3312         PetscCall(PetscStrlcat(msg, " ", sizeof(msg)));
3313         PetscCall(PetscStrlcat(msg, info, sizeof(msg)));
3314       }
3315       PetscCall(PetscStrlcat(msg, " (Silence this warning with ", sizeof(msg)));
3316       PetscCall(PetscStrlcat(msg, quietopt, sizeof(msg)));
3317       PetscCall(PetscStrlcat(msg, ")\n", sizeof(msg)));
3318       PetscCall(PetscPrintf(comm, "%s", msg));
3319     }
3320   }
3321   PetscFunctionReturn(PETSC_SUCCESS);
3322 }
3323