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