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