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