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