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 <ctype.h>
14: #if PetscDefined(HAVE_MALLOC_H)
15: #include <malloc.h>
16: #endif
17: #if PetscDefined(HAVE_STRINGS_H)
18: #include <strings.h> /* strcasecmp */
19: #endif
21: #if PetscDefined(HAVE_STRCASECMP)
22: #define PetscOptNameCmp(a, b) strcasecmp(a, b)
23: #elif PetscDefined(HAVE_STRICMP)
24: #define PetscOptNameCmp(a, b) stricmp(a, b)
25: #else
26: #define PetscOptNameCmp(a, b) Error_strcasecmp_not_found
27: #endif
29: #include <petsc/private/hashtable.h>
31: /* This assumes ASCII encoding and ignores locale settings */
32: /* Using tolower() is about 2X slower in microbenchmarks */
33: static inline int PetscToLower(int c)
34: {
35: return ((c >= 'A') & (c <= 'Z')) ? c + 'a' - 'A' : c;
36: }
38: /* Bob Jenkins's one at a time hash function (case-insensitive) */
39: static inline unsigned int PetscOptHash(const char key[])
40: {
41: unsigned int hash = 0;
42: while (*key) {
43: hash += PetscToLower(*key++);
44: hash += hash << 10;
45: hash ^= hash >> 6;
46: }
47: hash += hash << 3;
48: hash ^= hash >> 11;
49: hash += hash << 15;
50: return hash;
51: }
53: static inline int PetscOptEqual(const char a[], const char b[])
54: {
55: return !PetscOptNameCmp(a, b);
56: }
58: KHASH_INIT(HO, kh_cstr_t, int, 1, PetscOptHash, PetscOptEqual)
60: #define MAXPREFIXES 25
61: #define MAXOPTIONSMONITORS 5
63: const char *PetscOptionSources[] = {"code", "command line", "file", "environment"};
65: // This table holds all the options set by the user
66: struct _n_PetscOptions {
67: PetscOptions previous;
69: int N; /* number of options */
70: int Nalloc; /* number of allocated options */
71: char **names; /* option names */
72: char **values; /* option values */
73: PetscBool *used; /* flag option use */
74: PetscOptionSource *source; /* source for option value */
75: PetscBool precedentProcessed;
77: /* Hash table */
78: khash_t(HO) *ht;
80: /* Prefixes */
81: int prefixind;
82: int prefixstack[MAXPREFIXES];
83: char prefix[PETSC_MAX_OPTION_NAME];
85: /* Aliases */
86: int Na; /* number or aliases */
87: int Naalloc; /* number of allocated aliases */
88: char **aliases1; /* aliased */
89: char **aliases2; /* aliasee */
91: /* Help */
92: PetscBool help; /* flag whether "-help" is in the database */
93: PetscBool help_intro; /* flag whether "-help intro" is in the database */
94: int help_nmansecs; /* number of manual sections given as "-help mansec,..."; 0 means the help output is not restricted; int, not PetscInt, to match PetscStrToArray() */
95: char **help_mansecs; /* the manual sections themselves; only the options blocks in one of them are printed */
97: /* Monitors */
98: PetscBool monitorFromOptions, monitorCancel;
99: PetscErrorCode (*monitor[MAXOPTIONSMONITORS])(const char[], const char[], PetscOptionSource, void *); /* returns control to user after */
100: PetscCtxDestroyFn *monitordestroy[MAXOPTIONSMONITORS]; /* callback for monitor destruction */
101: void *monitorcontext[MAXOPTIONSMONITORS]; /* to pass arbitrary user data into monitor */
102: PetscInt numbermonitors; /* to, for instance, detect options being set */
103: };
105: static PetscOptions defaultoptions = NULL; /* the options database routines query this object for options */
107: /* list of options which precede others, i.e., are processed in PetscOptionsProcessPrecedentFlags() */
108: /* these options can only take boolean values, the code will crash if given a non-boolean value.
109: -help is the exception: it also accepts "intro" and a comma-separated list of manual sections. A bare
110: -help 0, 1, yes, no, on, off, true or false is read as a logical value, so a manual section named that
111: way can only be selected as part of such a list, as in "-help 0,ksp" */
112: static const char *precedentOptions[] = {"-petsc_ci", "-options_monitor", "-options_monitor_cancel", "-help", "-skip_petscrc"};
113: enum PetscPrecedentOption {
114: PO_CI_ENABLE,
115: PO_OPTIONS_MONITOR,
116: PO_OPTIONS_MONITOR_CANCEL,
117: PO_HELP,
118: PO_SKIP_PETSCRC,
119: PO_NUM
120: };
122: PETSC_INTERN PetscErrorCode PetscOptionsSetValue_Private(PetscOptions, const char[], const char[], int *, PetscOptionSource);
123: PETSC_INTERN PetscErrorCode PetscOptionsInsertStringYAML_Private(PetscOptions, const char[], PetscOptionSource);
124: static PetscErrorCode PetscOptionsStringToBool_Private(const char[], PetscBool *, PetscBool *);
126: /*
127: Options events monitor
128: */
129: static PetscErrorCode PetscOptionsMonitor(PetscOptions options, const char name[], const char value[], PetscOptionSource source)
130: {
131: PetscFunctionBegin;
132: if (options->monitorFromOptions) PetscCall(PetscOptionsMonitorDefault(name, value, source, NULL));
133: for (PetscInt i = 0; i < options->numbermonitors; i++) PetscCall((*options->monitor[i])(name, value, source, options->monitorcontext[i]));
134: PetscFunctionReturn(PETSC_SUCCESS);
135: }
137: /*@
138: PetscOptionsCreate - Creates an empty options database.
140: Logically Collective
142: Output Parameter:
143: . options - Options database object
145: Level: advanced
147: Note:
148: Though PETSc has a concept of multiple options database the current code uses a single default `PetscOptions` object
150: Developer Notes:
151: We may want eventually to pass a `MPI_Comm` to determine the ownership of the object
153: This object never got developed after being introduced, it is not clear that supporting multiple `PetscOptions` objects is useful
155: .seealso: `PetscOptionsDestroy()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`
156: @*/
157: PetscErrorCode PetscOptionsCreate(PetscOptions *options)
158: {
159: PetscFunctionBegin;
160: PetscAssertPointer(options, 1);
161: *options = (PetscOptions)calloc(1, sizeof(**options));
162: PetscCheck(*options, PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate the options database");
163: PetscFunctionReturn(PETSC_SUCCESS);
164: }
166: /*@
167: PetscOptionsDestroy - Destroys an option database.
169: Logically Collective on whatever communicator was associated with the call to `PetscOptionsCreate()`
171: Input Parameter:
172: . options - the `PetscOptions` object
174: Level: advanced
176: .seealso: `PetscOptionsInsert()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsSetValue()`
177: @*/
178: PetscErrorCode PetscOptionsDestroy(PetscOptions *options)
179: {
180: PetscFunctionBegin;
181: PetscAssertPointer(options, 1);
182: if (!*options) PetscFunctionReturn(PETSC_SUCCESS);
183: 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()");
184: PetscCall(PetscOptionsClear(*options));
185: /* XXX what about monitors ? */
186: free(*options);
187: *options = NULL;
188: PetscFunctionReturn(PETSC_SUCCESS);
189: }
191: /*@
192: PetscOptionsCreateDefault - Creates the default global options database if it does not already exist
194: Logically collective
196: Level: developer
198: Note:
199: This is called during `PetscInitialize()`; user code normally does not need to call it directly.
201: .seealso: `PetscOptionsDestroyDefault()`, `PetscOptionsCreate()`, `PetscOptionsPush()`, `PetscOptionsPop()`
202: @*/
203: PetscErrorCode PetscOptionsCreateDefault(void)
204: {
205: PetscFunctionBegin;
206: if (PetscUnlikely(!defaultoptions)) PetscCall(PetscOptionsCreate(&defaultoptions));
207: PetscFunctionReturn(PETSC_SUCCESS);
208: }
210: /*@
211: PetscOptionsPush - Push a new `PetscOptions` object as the default provider of options
212: Allows using different parts of a code to use different options databases
214: Logically Collective
216: Input Parameter:
217: . opt - the options obtained with `PetscOptionsCreate()`
219: Level: advanced
221: Notes:
222: Use `PetscOptionsPop()` to return to the previous default options database
224: The collectivity of this routine is complex; only the MPI ranks that call this routine will
225: have the affect of these options. If some processes that create objects call this routine and others do
226: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
227: on different ranks.
229: Developer Notes:
230: Though this functionality has been provided it has never been used in PETSc and might be removed.
232: .seealso: `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
233: @*/
234: PetscErrorCode PetscOptionsPush(PetscOptions opt)
235: {
236: PetscFunctionBegin;
237: PetscCall(PetscOptionsCreateDefault());
238: opt->previous = defaultoptions;
239: defaultoptions = opt;
240: PetscFunctionReturn(PETSC_SUCCESS);
241: }
243: /*@
244: PetscOptionsPop - Pop the most recent `PetscOptionsPush()` to return to the previous default options
246: Logically Collective on whatever communicator was associated with the call to `PetscOptionsCreate()`
248: Level: advanced
250: .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`, `PetscOptionsSetValue()`, `PetscOptionsLeft()`
251: @*/
252: PetscErrorCode PetscOptionsPop(void)
253: {
254: PetscOptions current = defaultoptions;
256: PetscFunctionBegin;
257: PetscCheck(defaultoptions, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Missing default options");
258: PetscCheck(defaultoptions->previous, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PetscOptionsPop() called too many times");
259: defaultoptions = defaultoptions->previous;
260: current->previous = NULL;
261: PetscFunctionReturn(PETSC_SUCCESS);
262: }
264: /*@
265: PetscOptionsDestroyDefault - Destroys the default global options database
267: Logically collective
269: Level: developer
271: Note:
272: This is called during `PetscFinalize()`; any options databases the user pushed but did not pop are also destroyed.
274: .seealso: `PetscOptionsCreateDefault()`, `PetscOptionsDestroy()`, `PetscOptionsPush()`, `PetscOptionsPop()`
275: @*/
276: PetscErrorCode PetscOptionsDestroyDefault(void)
277: {
278: PetscFunctionBegin;
279: if (!defaultoptions) PetscFunctionReturn(PETSC_SUCCESS);
280: /* Destroy any options that the user forgot to pop */
281: while (defaultoptions->previous) {
282: PetscOptions tmp = defaultoptions;
284: PetscCall(PetscOptionsPop());
285: PetscCall(PetscOptionsDestroy(&tmp));
286: }
287: PetscCall(PetscOptionsDestroy(&defaultoptions));
288: PetscFunctionReturn(PETSC_SUCCESS);
289: }
291: /*@
292: PetscOptionsValidKey - PETSc Options database keys must begin with one or two dashes (-) followed by a letter.
294: Not Collective
296: Input Parameter:
297: . key - string to check if valid
299: Output Parameter:
300: . valid - `PETSC_TRUE` if a valid key
302: Level: intermediate
304: .seealso: `PetscOptionsCreate()`, `PetscOptionsInsert()`
305: @*/
306: PetscErrorCode PetscOptionsValidKey(const char key[], PetscBool *valid)
307: {
308: char *ptr;
309: PETSC_UNUSED double d;
311: PetscFunctionBegin;
312: if (key) PetscAssertPointer(key, 1);
313: PetscAssertPointer(valid, 2);
314: *valid = PETSC_FALSE;
315: if (!key) PetscFunctionReturn(PETSC_SUCCESS);
316: if (key[0] != '-') PetscFunctionReturn(PETSC_SUCCESS);
317: if (key[1] == '-') key++;
318: if (!isalpha((int)key[1])) PetscFunctionReturn(PETSC_SUCCESS);
319: d = strtod(key, &ptr);
320: if (ptr != key && !(*ptr == '_' || isalnum((int)*ptr))) PetscFunctionReturn(PETSC_SUCCESS);
321: *valid = PETSC_TRUE;
322: PetscFunctionReturn(PETSC_SUCCESS);
323: }
325: static PetscErrorCode PetscOptionsInsertString_Private(PetscOptions options, const char in_str[], PetscOptionSource source)
326: {
327: const char *first, *second;
328: PetscToken token;
330: PetscFunctionBegin;
331: PetscCall(PetscTokenCreate(in_str, ' ', &token));
332: PetscCall(PetscTokenFind(token, &first));
333: while (first) {
334: PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;
336: PetscCall(PetscStrcasecmp(first, "-options_file", &isfile));
337: PetscCall(PetscStrcasecmp(first, "-options_file_yaml", &isfileyaml));
338: PetscCall(PetscStrcasecmp(first, "-options_string_yaml", &isstringyaml));
339: PetscCall(PetscStrcasecmp(first, "-prefix_push", &ispush));
340: PetscCall(PetscStrcasecmp(first, "-prefix_pop", &ispop));
341: PetscCall(PetscOptionsValidKey(first, &key));
342: if (!key) {
343: PetscCall(PetscTokenFind(token, &first));
344: } else if (isfile) {
345: PetscCall(PetscTokenFind(token, &second));
346: PetscCall(PetscOptionsInsertFile(PETSC_COMM_SELF, options, second, PETSC_TRUE));
347: PetscCall(PetscTokenFind(token, &first));
348: } else if (isfileyaml) {
349: PetscCall(PetscTokenFind(token, &second));
350: PetscCall(PetscOptionsInsertFileYAML(PETSC_COMM_SELF, options, second, PETSC_TRUE));
351: PetscCall(PetscTokenFind(token, &first));
352: } else if (isstringyaml) {
353: PetscCall(PetscTokenFind(token, &second));
354: PetscCall(PetscOptionsInsertStringYAML_Private(options, second, source));
355: PetscCall(PetscTokenFind(token, &first));
356: } else if (ispush) {
357: PetscCall(PetscTokenFind(token, &second));
358: PetscCall(PetscOptionsPrefixPush(options, second));
359: PetscCall(PetscTokenFind(token, &first));
360: } else if (ispop) {
361: PetscCall(PetscOptionsPrefixPop(options));
362: PetscCall(PetscTokenFind(token, &first));
363: } else {
364: PetscCall(PetscTokenFind(token, &second));
365: PetscCall(PetscOptionsValidKey(second, &key));
366: if (!key) {
367: PetscCall(PetscOptionsSetValue_Private(options, first, second, NULL, source));
368: PetscCall(PetscTokenFind(token, &first));
369: } else {
370: PetscCall(PetscOptionsSetValue_Private(options, first, NULL, NULL, source));
371: first = second;
372: }
373: }
374: }
375: PetscCall(PetscTokenDestroy(&token));
376: PetscFunctionReturn(PETSC_SUCCESS);
377: }
379: /*@
380: PetscOptionsInsertString - Inserts options into the database from a string
382: Logically Collective
384: Input Parameters:
385: + options - options object
386: - in_str - string that contains options separated by blanks
388: Level: intermediate
390: The collectivity of this routine is complex; only the MPI processes that call this routine will
391: have the affect of these options. If some processes that create objects call this routine and others do
392: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
393: on different ranks.
395: Contributed by Boyana Norris
397: .seealso: `PetscOptionsSetValue()`, `PetscOptionsView()`, `PetscOptionsHasName()`, `PetscOptionsGetInt()`,
398: `PetscOptionsGetReal()`, `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
399: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
400: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
401: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
402: `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsInsertFile()`
403: @*/
404: PetscErrorCode PetscOptionsInsertString(PetscOptions options, const char in_str[])
405: {
406: PetscFunctionBegin;
407: PetscCall(PetscOptionsInsertString_Private(options, in_str, PETSC_OPT_CODE));
408: PetscFunctionReturn(PETSC_SUCCESS);
409: }
411: /*
412: Returns a line (ended by a \n, \r or null character of any length. Result should be freed with free()
413: */
414: static char *Petscgetline(FILE *f)
415: {
416: size_t size = 0;
417: size_t len = 0;
418: size_t last = 0;
419: char *buf = NULL;
421: if (feof(f)) return NULL;
422: do {
423: size += 1024; /* BUFSIZ is defined as "the optimal read size for this platform" */
424: buf = (char *)realloc((void *)buf, size); /* realloc(NULL,n) is the same as malloc(n) */
425: /* Actually do the read. Note that fgets puts a terminal '\0' on the
426: end of the string, so we make sure we overwrite this */
427: if (!fgets(buf + len, 1024, f)) buf[len] = 0;
428: PetscCallAbort(PETSC_COMM_SELF, PetscStrlen(buf, &len));
429: last = len - 1;
430: } while (!feof(f) && buf[last] != '\n' && buf[last] != '\r');
431: if (len) return buf;
432: free(buf);
433: return NULL;
434: }
436: static PetscErrorCode PetscOptionsFilename(MPI_Comm comm, const char file[], char filename[PETSC_MAX_PATH_LEN], PetscBool *yaml)
437: {
438: char fname[PETSC_MAX_PATH_LEN + 8], path[PETSC_MAX_PATH_LEN + 8], *tail;
440: PetscFunctionBegin;
441: *yaml = PETSC_FALSE;
442: PetscCall(PetscStrreplace(comm, file, fname, sizeof(fname)));
443: PetscCall(PetscFixFilename(fname, path));
444: PetscCall(PetscStrendswith(path, ":yaml", yaml));
445: if (*yaml) {
446: PetscCall(PetscStrrchr(path, ':', &tail));
447: tail[-1] = 0; /* remove ":yaml" suffix from path */
448: }
449: PetscCall(PetscStrncpy(filename, path, PETSC_MAX_PATH_LEN));
450: /* check for standard YAML and JSON filename extensions */
451: if (!*yaml) PetscCall(PetscStrendswith(filename, ".yaml", yaml));
452: if (!*yaml) PetscCall(PetscStrendswith(filename, ".yml", yaml));
453: if (!*yaml) PetscCall(PetscStrendswith(filename, ".json", yaml));
454: if (!*yaml) { /* check file contents */
455: PetscMPIInt rank;
456: PetscCallMPI(MPI_Comm_rank(comm, &rank));
457: if (rank == 0) {
458: FILE *fh = fopen(filename, "r");
459: if (fh) {
460: char buf[6] = "";
461: if (fread(buf, 1, 6, fh) > 0) {
462: PetscCall(PetscStrncmp(buf, "%YAML ", 6, yaml)); /* check for '%YAML' tag */
463: if (!*yaml) PetscCall(PetscStrncmp(buf, "---", 3, yaml)); /* check for document start */
464: }
465: (void)fclose(fh);
466: }
467: }
468: PetscCallMPI(MPI_Bcast(yaml, 1, MPI_C_BOOL, 0, comm));
469: }
470: PetscFunctionReturn(PETSC_SUCCESS);
471: }
473: static PetscErrorCode PetscOptionsInsertFilePetsc(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
474: {
475: char *string, *vstring = NULL, *astring = NULL, *packed = NULL;
476: const char *tokens[4];
477: size_t len;
478: PetscCount bytes;
479: FILE *fd;
480: PetscToken token = NULL;
481: int err;
482: char *cmatch = NULL;
483: const char cmt = '#';
484: PetscInt line = 1;
485: PetscMPIInt rank, cnt = 0, acnt = 0, counts[2];
486: PetscBool isdir, alias = PETSC_FALSE, valid;
488: PetscFunctionBegin;
489: PetscCall(PetscMemzero(tokens, sizeof(tokens)));
490: PetscCallMPI(MPI_Comm_rank(comm, &rank));
491: if (rank == 0) {
492: char fpath[PETSC_MAX_PATH_LEN];
493: char fname[PETSC_MAX_PATH_LEN];
495: PetscCall(PetscStrreplace(PETSC_COMM_SELF, file, fname, sizeof(fname)));
496: PetscCall(PetscFixFilename(fname, fpath));
497: PetscCall(PetscGetFullPath(fpath, fname, sizeof(fname)));
499: fd = fopen(fname, "r");
500: PetscCall(PetscTestDirectory(fname, 'r', &isdir));
501: PetscCheck(!isdir || !require, PETSC_COMM_SELF, PETSC_ERR_USER, "Specified options file %s is a directory", fname);
502: if (fd && !isdir) {
503: PetscSegBuffer vseg, aseg;
505: PetscCall(PetscSegBufferCreate(1, 4000, &vseg));
506: PetscCall(PetscSegBufferCreate(1, 2000, &aseg));
508: /* the following line will not work when opening initial files (like .petscrc) since info is not yet set */
509: PetscCall(PetscInfo(NULL, "Opened options file %s\n", file));
511: while ((string = Petscgetline(fd))) {
512: /* eliminate comments from each line */
513: PetscCall(PetscStrchr(string, cmt, &cmatch));
514: if (cmatch) *cmatch = 0;
515: PetscCall(PetscStrlen(string, &len));
516: /* replace tabs, ^M, \n with " " */
517: for (size_t i = 0; i < len; i++) {
518: if (string[i] == '\t' || string[i] == '\r' || string[i] == '\n') string[i] = ' ';
519: }
520: PetscCall(PetscTokenCreate(string, ' ', &token));
521: PetscCall(PetscTokenFind(token, &tokens[0]));
522: if (!tokens[0]) {
523: goto destroy;
524: } else if (!tokens[0][0]) { /* if token 0 is empty (string begins with spaces), redo */
525: PetscCall(PetscTokenFind(token, &tokens[0]));
526: }
527: for (PetscInt i = 1; i < 4; i++) PetscCall(PetscTokenFind(token, &tokens[i]));
528: if (!tokens[0]) {
529: goto destroy;
530: } else if (tokens[0][0] == '-') {
531: PetscCall(PetscOptionsValidKey(tokens[0], &valid));
532: PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": invalid option %s", fname, line, tokens[0]);
533: PetscCall(PetscStrlen(tokens[0], &len));
534: PetscCall(PetscSegBufferGet(vseg, len + 1, &vstring));
535: PetscCall(PetscArraycpy(vstring, tokens[0], len));
536: vstring[len] = ' ';
537: if (tokens[1]) {
538: PetscCall(PetscOptionsValidKey(tokens[1], &valid));
539: 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]);
540: PetscCall(PetscStrlen(tokens[1], &len));
541: PetscCall(PetscSegBufferGet(vseg, len + 3, &vstring));
542: vstring[0] = '"';
543: PetscCall(PetscArraycpy(vstring + 1, tokens[1], len));
544: vstring[len + 1] = '"';
545: vstring[len + 2] = ' ';
546: }
547: } else {
548: PetscCall(PetscStrcasecmp(tokens[0], "alias", &alias));
549: PetscCheck(alias, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown first token in options file %s line %" PetscInt_FMT ": %s", fname, line, tokens[0]);
550: PetscCall(PetscOptionsValidKey(tokens[1], &valid));
551: 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]);
552: 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]);
553: PetscCall(PetscOptionsValidKey(tokens[2], &valid));
554: 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]);
555: PetscCall(PetscStrlen(tokens[1], &len));
556: PetscCall(PetscSegBufferGet(aseg, len + 1, &astring));
557: PetscCall(PetscArraycpy(astring, tokens[1], len));
558: astring[len] = ' ';
560: PetscCall(PetscStrlen(tokens[2], &len));
561: PetscCall(PetscSegBufferGet(aseg, len + 1, &astring));
562: PetscCall(PetscArraycpy(astring, tokens[2], len));
563: astring[len] = ' ';
564: }
565: {
566: const char *extraToken = alias ? tokens[3] : tokens[2];
567: PetscCheck(!extraToken, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": extra token %s", fname, line, extraToken);
568: }
569: destroy:
570: free(string);
571: PetscCall(PetscTokenDestroy(&token));
572: alias = PETSC_FALSE;
573: line++;
574: }
575: err = fclose(fd);
576: PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file %s", fname);
577: PetscCall(PetscSegBufferGetSize(aseg, &bytes)); /* size without null termination */
578: PetscCall(PetscMPIIntCast(bytes, &acnt));
579: PetscCall(PetscSegBufferGet(aseg, 1, &astring));
580: astring[0] = 0;
581: PetscCall(PetscSegBufferGetSize(vseg, &bytes)); /* size without null termination */
582: PetscCall(PetscMPIIntCast(bytes, &cnt));
583: PetscCall(PetscSegBufferGet(vseg, 1, &vstring));
584: vstring[0] = 0;
585: PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
586: PetscCall(PetscSegBufferExtractTo(aseg, packed));
587: PetscCall(PetscSegBufferExtractTo(vseg, packed + acnt + 1));
588: PetscCall(PetscSegBufferDestroy(&aseg));
589: PetscCall(PetscSegBufferDestroy(&vseg));
590: } else PetscCheck(!require, PETSC_COMM_SELF, PETSC_ERR_USER, "Unable to open options file %s", fname);
591: }
593: counts[0] = acnt;
594: counts[1] = cnt;
595: err = MPI_Bcast(counts, 2, MPI_INT, 0, comm);
596: 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/");
597: acnt = counts[0];
598: cnt = counts[1];
599: if (rank) PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
600: if (acnt || cnt) {
601: PetscCallMPI(MPI_Bcast(packed, 2 + acnt + cnt, MPI_CHAR, 0, comm));
602: astring = packed;
603: vstring = packed + acnt + 1;
604: }
606: if (acnt) {
607: PetscCall(PetscTokenCreate(astring, ' ', &token));
608: PetscCall(PetscTokenFind(token, &tokens[0]));
609: while (tokens[0]) {
610: PetscCall(PetscTokenFind(token, &tokens[1]));
611: PetscCall(PetscOptionsSetAlias(options, tokens[0], tokens[1]));
612: PetscCall(PetscTokenFind(token, &tokens[0]));
613: }
614: PetscCall(PetscTokenDestroy(&token));
615: }
617: if (cnt) PetscCall(PetscOptionsInsertString_Private(options, vstring, PETSC_OPT_FILE));
618: PetscCall(PetscFree(packed));
619: PetscFunctionReturn(PETSC_SUCCESS);
620: }
622: /*@
623: PetscOptionsInsertFile - Inserts options into the database from a file.
625: Collective
627: Input Parameters:
628: + comm - the processes that will share the options (usually `PETSC_COMM_WORLD`)
629: . options - options database, use `NULL` for default global database
630: . file - name of file,
631: ".yml" and ".yaml" filename extensions are inserted as YAML options,
632: append ":yaml" to filename to force YAML options.
633: - require - if `PETSC_TRUE` will generate an error if the file does not exist
635: Level: developer
637: Notes:
638: Use # for lines that are comments and which should be ignored.
639: Usually, instead of using this command, one should list the file name in the call to `PetscInitialize()`, this insures that certain options
640: 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
641: calls to `XXXSetFromOptions()`, it should not be used for options listed under PetscInitialize().
642: The collectivity of this routine is complex; only the MPI processes in comm will
643: have the effect of these options. If some processes that create objects call this routine and others do
644: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
645: on different ranks.
647: .seealso: `PetscOptionsSetValue()`, `PetscOptionsView()`, `PetscOptionsHasName()`, `PetscOptionsGetInt()`,
648: `PetscOptionsGetReal()`, `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
649: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
650: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
651: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
652: `PetscOptionsFList()`, `PetscOptionsEList()`
653: @*/
654: PetscErrorCode PetscOptionsInsertFile(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
655: {
656: char filename[PETSC_MAX_PATH_LEN];
657: PetscBool yaml;
659: PetscFunctionBegin;
660: PetscCall(PetscOptionsFilename(comm, file, filename, &yaml));
661: if (yaml) {
662: PetscCall(PetscOptionsInsertFileYAML(comm, options, filename, require));
663: } else {
664: PetscCall(PetscOptionsInsertFilePetsc(comm, options, filename, require));
665: }
666: PetscFunctionReturn(PETSC_SUCCESS);
667: }
669: /*@
670: PetscOptionsInsertArgs - Inserts options into the database from a array of strings
672: Logically Collective
674: Input Parameters:
675: + options - options object
676: . argc - the array length
677: - args - the string array
679: Level: intermediate
681: .seealso: `PetscOptions`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`
682: @*/
683: PetscErrorCode PetscOptionsInsertArgs(PetscOptions options, int argc, const char *const args[])
684: {
685: int left = PetscMax(argc, 0);
686: const char *const *eargs = args;
688: PetscFunctionBegin;
689: while (left) {
690: PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;
691: PetscCall(PetscStrcasecmp(eargs[0], "-options_file", &isfile));
692: PetscCall(PetscStrcasecmp(eargs[0], "-options_file_yaml", &isfileyaml));
693: PetscCall(PetscStrcasecmp(eargs[0], "-options_string_yaml", &isstringyaml));
694: PetscCall(PetscStrcasecmp(eargs[0], "-prefix_push", &ispush));
695: PetscCall(PetscStrcasecmp(eargs[0], "-prefix_pop", &ispop));
696: PetscCall(PetscOptionsValidKey(eargs[0], &key));
697: if (!key) {
698: eargs++;
699: left--;
700: } else if (isfile) {
701: PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file filename option");
702: PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, eargs[1], PETSC_TRUE));
703: eargs += 2;
704: left -= 2;
705: } else if (isfileyaml) {
706: PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file_yaml filename option");
707: PetscCall(PetscOptionsInsertFileYAML(PETSC_COMM_WORLD, options, eargs[1], PETSC_TRUE));
708: eargs += 2;
709: left -= 2;
710: } else if (isstringyaml) {
711: PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing string for -options_string_yaml string option");
712: PetscCall(PetscOptionsInsertStringYAML_Private(options, eargs[1], PETSC_OPT_CODE));
713: eargs += 2;
714: left -= 2;
715: } else if (ispush) {
716: PetscCheck(left > 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option");
717: PetscCheck(eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option (prefixes cannot start with '-')");
718: PetscCall(PetscOptionsPrefixPush(options, eargs[1]));
719: eargs += 2;
720: left -= 2;
721: } else if (ispop) {
722: PetscCall(PetscOptionsPrefixPop(options));
723: eargs++;
724: left--;
725: } else {
726: PetscBool nextiskey = PETSC_FALSE;
727: if (left >= 2) PetscCall(PetscOptionsValidKey(eargs[1], &nextiskey));
728: if (left < 2 || nextiskey) {
729: PetscCall(PetscOptionsSetValue_Private(options, eargs[0], NULL, NULL, PETSC_OPT_COMMAND_LINE));
730: eargs++;
731: left--;
732: } else {
733: PetscCall(PetscOptionsSetValue_Private(options, eargs[0], eargs[1], NULL, PETSC_OPT_COMMAND_LINE));
734: eargs += 2;
735: left -= 2;
736: }
737: }
738: }
739: PetscFunctionReturn(PETSC_SUCCESS);
740: }
742: static inline PetscErrorCode PetscOptionsStringToBoolIfSet_Private(enum PetscPrecedentOption opt, const char *val[], const PetscBool set[], PetscBool *flg)
743: {
744: PetscFunctionBegin;
745: if (set[opt]) PetscCall(PetscOptionsStringToBool(val[opt], flg));
746: else *flg = PETSC_FALSE;
747: PetscFunctionReturn(PETSC_SUCCESS);
748: }
750: /* Process options with absolute precedence, these are only processed from the command line, not the environment or files */
751: static PetscErrorCode PetscOptionsProcessPrecedentFlags(PetscOptions options, int argc, char *args[], PetscBool *skip_petscrc, PetscBool *skip_petscrc_set)
752: {
753: const char *const *opt = precedentOptions;
754: const size_t n = PO_NUM;
755: size_t o;
756: int a;
757: const char **val;
758: char **cval;
759: PetscBool *set, unneeded;
760: PetscBool isbool = PETSC_FALSE, helpval = PETSC_FALSE;
762: PetscFunctionBegin;
763: PetscCall(PetscCalloc2(n, &cval, n, &set));
764: val = (const char **)cval;
766: /* Look for options possibly set using PetscOptionsSetValue beforehand */
767: for (o = 0; o < n; o++) PetscCall(PetscOptionsFindPair(options, NULL, opt[o], &val[o], &set[o]));
769: /* Loop through all args to collect last occurring value of each option */
770: for (a = 1; a < argc; a++) {
771: PetscBool valid, eq;
773: PetscCall(PetscOptionsValidKey(args[a], &valid));
774: if (!valid) continue;
775: for (o = 0; o < n; o++) {
776: PetscCall(PetscStrcasecmp(args[a], opt[o], &eq));
777: if (eq) {
778: set[o] = PETSC_TRUE;
779: if (a == argc - 1 || !args[a + 1] || !args[a + 1][0] || args[a + 1][0] == '-') val[o] = NULL;
780: else val[o] = args[a + 1];
781: break;
782: }
783: }
784: }
786: /* Process flags */
787: /* "-help" accepts a logical value, "intro" or a list of manual sections; PetscOptionsSetValue_Private()
788: reads it the same way below, and records the manual sections when the option is stored */
789: PetscCall(PetscOptionsStringToBool_Private(val[PO_HELP], &helpval, &isbool));
790: PetscCall(PetscStrcasecmp(val[PO_HELP], "intro", &options->help_intro));
791: if (set[PO_HELP]) options->help = isbool ? helpval : PETSC_TRUE;
792: else options->help = PETSC_FALSE;
793: PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_CI_ENABLE, val, set, &unneeded));
794: /* need to manage PO_CI_ENABLE option before the PetscOptionsMonitor is turned on, so its setting is not monitored */
795: if (set[PO_CI_ENABLE]) PetscCall(PetscOptionsSetValue_Private(options, opt[PO_CI_ENABLE], val[PO_CI_ENABLE], &a, PETSC_OPT_COMMAND_LINE));
796: PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR_CANCEL, val, set, &options->monitorCancel));
797: PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR, val, set, &options->monitorFromOptions));
798: PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_SKIP_PETSCRC, val, set, skip_petscrc));
799: *skip_petscrc_set = set[PO_SKIP_PETSCRC];
801: /* Store precedent options in database and mark them as used */
802: for (o = 1; o < n; o++) {
803: if (set[o]) {
804: PetscCall(PetscOptionsSetValue_Private(options, opt[o], val[o], &a, PETSC_OPT_COMMAND_LINE));
805: options->used[a] = PETSC_TRUE;
806: }
807: }
808: PetscCall(PetscFree2(cval, set));
809: options->precedentProcessed = PETSC_TRUE;
810: PetscFunctionReturn(PETSC_SUCCESS);
811: }
813: static inline PetscErrorCode PetscOptionsSkipPrecedent(PetscOptions options, const char name[], PetscBool *flg)
814: {
815: PetscFunctionBegin;
816: PetscAssertPointer(flg, 3);
817: *flg = PETSC_FALSE;
818: if (options->precedentProcessed) {
819: for (int i = 0; i < PO_NUM; ++i) {
820: if (!PetscOptNameCmp(precedentOptions[i], name)) {
821: /* check if precedent option has been set already */
822: PetscCall(PetscOptionsFindPair(options, NULL, name, NULL, flg));
823: if (*flg) break;
824: }
825: }
826: }
827: PetscFunctionReturn(PETSC_SUCCESS);
828: }
830: /*@
831: PetscOptionsInsert - Inserts into the options database from the command line,
832: the environmental variable and a file.
834: Collective on `PETSC_COMM_WORLD`
836: Input Parameters:
837: + options - options database or `NULL` for the default global database
838: . argc - count of number of command line arguments
839: . args - the command line arguments
840: - file - [optional] PETSc database file, append ":yaml" to filename to specify YAML options format.
841: Use `NULL` or empty string to not check for code specific file.
842: Also checks ~/.petscrc, .petscrc and petscrc.
843: Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.
845: Options Database Keys:
846: + -options_file filename - read options from a file
847: - -options_file_yaml filename - read options from a YAML file
849: Level: advanced
851: Notes:
852: Since `PetscOptionsInsert()` is automatically called by `PetscInitialize()`,
853: the user does not typically need to call this routine. `PetscOptionsInsert()`
854: can be called several times, adding additional entries into the database.
856: See `PetscInitialize()` for options related to option database monitoring.
858: .seealso: `PetscOptionsDestroy()`, `PetscOptionsView()`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`,
859: `PetscInitialize()`
860: @*/
861: PetscErrorCode PetscOptionsInsert(PetscOptions options, int *argc, char ***args, const char file[]) PeNS
862: {
863: PetscMPIInt rank;
864: PetscBool hasArgs = (argc && *argc) ? PETSC_TRUE : PETSC_FALSE;
865: PetscBool skipPetscrc = PETSC_FALSE, skipPetscrcSet = PETSC_FALSE;
866: char *eoptions = NULL;
867: size_t len = 0;
869: PetscFunctionBegin;
870: PetscCheck(!hasArgs || (args && *args), PETSC_COMM_WORLD, PETSC_ERR_ARG_NULL, "*argc > 1 but *args not given");
871: PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank));
873: if (!options) {
874: PetscCall(PetscOptionsCreateDefault());
875: options = defaultoptions;
876: }
877: if (hasArgs) {
878: /* process options with absolute precedence */
879: PetscCall(PetscOptionsProcessPrecedentFlags(options, *argc, *args, &skipPetscrc, &skipPetscrcSet));
880: PetscCall(PetscOptionsGetBool(NULL, NULL, "-petsc_ci", &PetscCIEnabled, NULL));
881: }
882: if (file && file[0]) {
883: PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, file, PETSC_TRUE));
884: /* if -skip_petscrc has not been set from command line, check whether it has been set in the file */
885: if (!skipPetscrcSet) PetscCall(PetscOptionsGetBool(options, NULL, "-skip_petscrc", &skipPetscrc, NULL));
886: }
887: if (!skipPetscrc) {
888: char filename[PETSC_MAX_PATH_LEN];
890: PetscCall(PetscGetHomeDirectory(filename, sizeof(filename)));
891: PetscCallMPI(MPI_Bcast(filename, (int)sizeof(filename), MPI_CHAR, 0, PETSC_COMM_WORLD));
892: if (filename[0]) PetscCall(PetscStrlcat(filename, "/.petscrc", sizeof(filename)));
893: PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, filename, PETSC_FALSE));
894: PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, ".petscrc", PETSC_FALSE));
895: PetscCall(PetscOptionsInsertFile(PETSC_COMM_WORLD, options, "petscrc", PETSC_FALSE));
896: }
898: /* insert environment options */
899: if (rank == 0) {
900: eoptions = getenv("PETSC_OPTIONS");
901: PetscCall(PetscStrlen(eoptions, &len));
902: }
903: PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, PETSC_COMM_WORLD));
904: if (len) {
905: if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
906: PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, PETSC_COMM_WORLD));
907: if (rank) eoptions[len] = 0;
908: PetscCall(PetscOptionsInsertString_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
909: if (rank) PetscCall(PetscFree(eoptions));
910: }
912: /* insert YAML environment options */
913: if (rank == 0) {
914: eoptions = getenv("PETSC_OPTIONS_YAML");
915: PetscCall(PetscStrlen(eoptions, &len));
916: }
917: PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, PETSC_COMM_WORLD));
918: if (len) {
919: if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
920: PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, PETSC_COMM_WORLD));
921: if (rank) eoptions[len] = 0;
922: PetscCall(PetscOptionsInsertStringYAML_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
923: if (rank) PetscCall(PetscFree(eoptions));
924: }
926: /* insert command line options here because they take precedence over arguments in petscrc/environment */
927: if (hasArgs) PetscCall(PetscOptionsInsertArgs(options, *argc - 1, (const char *const *)*args + 1));
928: PetscCall(PetscOptionsGetBool(NULL, NULL, "-petsc_ci_portable_error_output", &PetscCIEnabledPortableErrorOutput, NULL));
929: PetscFunctionReturn(PETSC_SUCCESS);
930: }
932: /* These options are not printed with PetscOptionsView() or PetscOptionsMonitor() when PetscCIEnabled is on */
933: /* TODO: get the list from the test harness, do not have it hardwired here. Maybe from gmakegentest.py */
934: 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"};
936: static PetscBool PetscCIOption(const char *name)
937: {
938: PetscInt idx;
939: PetscBool found;
941: if (!PetscCIEnabled) return PETSC_FALSE;
942: PetscCallAbort(PETSC_COMM_SELF, PetscEListFind(PETSC_STATIC_ARRAY_LENGTH(PetscCIOptions), PetscCIOptions, name, &idx, &found));
943: return found;
944: }
946: /*@
947: PetscOptionsView - Prints the options that have been loaded. This is
948: useful for debugging purposes.
950: Logically Collective, No Fortran Support
952: Input Parameters:
953: + options - options database, use `NULL` for default global database
954: - viewer - must be an `PETSCVIEWERASCII` viewer
956: Options Database Key:
957: . -options_view (true|false) - Activates `PetscOptionsView()` within `PetscFinalize()`.
959: Level: advanced
961: Note:
962: Only the MPI rank 0 of the `MPI_Comm` used to create `viewer` displays the option values. Other processes
963: may have different values but they are not printed.
965: .seealso: `PetscOptionsAllUsed()`
966: @*/
967: PetscErrorCode PetscOptionsView(PetscOptions options, PetscViewer viewer)
968: {
969: PetscInt i, N = 0;
970: PetscBool isascii;
972: PetscFunctionBegin;
974: options = options ? options : defaultoptions;
975: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
976: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
977: PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
979: for (i = 0; i < options->N; i++) {
980: if (PetscCIOption(options->names[i])) continue;
981: N++;
982: }
984: if (!N) {
985: PetscCall(PetscViewerASCIIPrintf(viewer, "#No PETSc Option Table entries\n"));
986: PetscFunctionReturn(PETSC_SUCCESS);
987: }
989: PetscCall(PetscViewerASCIIPrintf(viewer, "#PETSc Option Table entries:\n"));
990: for (i = 0; i < options->N; i++) {
991: if (PetscCIOption(options->names[i])) continue;
992: if (options->values[i]) {
993: PetscCall(PetscViewerASCIIPrintf(viewer, "-%s %s", options->names[i], options->values[i]));
994: } else {
995: PetscCall(PetscViewerASCIIPrintf(viewer, "-%s", options->names[i]));
996: }
997: PetscCall(PetscViewerASCIIPrintf(viewer, " # (source: %s)\n", PetscOptionSources[options->source[i]]));
998: }
999: PetscCall(PetscViewerASCIIPrintf(viewer, "#End of PETSc Option Table entries\n"));
1000: PetscFunctionReturn(PETSC_SUCCESS);
1001: }
1003: /*@
1004: PetscOptionsLeftError - Prints a warning listing any options in the default database that were never used
1006: Not Collective
1008: Level: developer
1010: Note:
1011: This is intended for use inside PETSc error handlers. Unused options may indicate a program that crashed before it
1012: read them, a spelling mistake, or an option intended for a different context.
1014: .seealso: `PetscOptionsLeft()`, `PetscOptionsAllUsed()`, `PetscOptionsView()`
1015: @*/
1016: PetscErrorCode PetscOptionsLeftError(void)
1017: {
1018: PetscInt i, nopt = 0;
1020: for (i = 0; i < defaultoptions->N; i++) {
1021: if (!defaultoptions->used[i]) {
1022: if (PetscCIOption(defaultoptions->names[i])) continue;
1023: nopt++;
1024: }
1025: }
1026: if (nopt) {
1027: PetscCall((*PetscErrorPrintf)("WARNING! There are unused option(s) set! Could be the program crashed before usage or a spelling mistake, etc!\n"));
1028: for (i = 0; i < defaultoptions->N; i++) {
1029: if (!defaultoptions->used[i]) {
1030: if (PetscCIOption(defaultoptions->names[i])) continue;
1031: 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]]));
1032: else PetscCall((*PetscErrorPrintf)(" Option left: name:-%s (no value) source: %s\n", defaultoptions->names[i], PetscOptionSources[defaultoptions->source[i]]));
1033: }
1034: }
1035: }
1036: return PETSC_SUCCESS;
1037: }
1039: PETSC_EXTERN PetscErrorCode PetscOptionsViewError(void)
1040: {
1041: PetscInt i, N = 0;
1042: PetscOptions options = defaultoptions;
1044: for (i = 0; i < options->N; i++) {
1045: if (PetscCIOption(options->names[i])) continue;
1046: N++;
1047: }
1049: if (N) {
1050: PetscCall((*PetscErrorPrintf)("PETSc Option Table entries:\n"));
1051: } else {
1052: PetscCall((*PetscErrorPrintf)("No PETSc Option Table entries\n"));
1053: }
1054: for (i = 0; i < options->N; i++) {
1055: if (PetscCIOption(options->names[i])) continue;
1056: if (options->values[i]) {
1057: PetscCall((*PetscErrorPrintf)("-%s %s (source: %s)\n", options->names[i], options->values[i], PetscOptionSources[options->source[i]]));
1058: } else {
1059: PetscCall((*PetscErrorPrintf)("-%s (source: %s)\n", options->names[i], PetscOptionSources[options->source[i]]));
1060: }
1061: }
1062: return PETSC_SUCCESS;
1063: }
1065: /*@
1066: PetscOptionsPrefixPush - Designate a prefix to be used by all options insertions to follow.
1068: Logically Collective
1070: Input Parameters:
1071: + options - options database, or `NULL` for the default global database
1072: - prefix - The string to append to the existing prefix
1074: Options Database Keys:
1075: + -prefix_push some_prefix_ - push the given prefix
1076: - -prefix_pop - pop the last prefix
1078: Level: advanced
1080: Notes:
1081: It is common to use this in conjunction with `-options_file` as in
1082: .vb
1083: -prefix_push system1_ -options_file system1rc -prefix_pop -prefix_push system2_ -options_file system2rc -prefix_pop
1084: .ve
1085: where the files no longer require all options to be prefixed with `-system2_`.
1087: The collectivity of this routine is complex; only the MPI processes that call this routine will
1088: have the affect of these options. If some processes that create objects call this routine and others do
1089: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1090: on different ranks.
1092: .seealso: `PetscOptionsPrefixPop()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1093: @*/
1094: PetscErrorCode PetscOptionsPrefixPush(PetscOptions options, const char prefix[])
1095: {
1096: size_t n;
1097: PetscInt start;
1098: char key[PETSC_MAX_OPTION_NAME + 1];
1099: PetscBool valid;
1101: PetscFunctionBegin;
1102: PetscAssertPointer(prefix, 2);
1103: options = options ? options : defaultoptions;
1104: 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);
1105: key[0] = '-'; /* keys must start with '-' */
1106: PetscCall(PetscStrncpy(key + 1, prefix, sizeof(key) - 1));
1107: PetscCall(PetscOptionsValidKey(key, &valid));
1108: if (!valid && options->prefixind > 0 && isdigit((int)prefix[0])) valid = PETSC_TRUE; /* If the prefix stack is not empty, make numbers a valid prefix */
1109: 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" : "");
1110: start = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1111: PetscCall(PetscStrlen(prefix, &n));
1112: PetscCheck(n + 1 <= sizeof(options->prefix) - start, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum prefix length %zu exceeded", sizeof(options->prefix));
1113: PetscCall(PetscArraycpy(options->prefix + start, prefix, n + 1));
1114: options->prefixstack[options->prefixind++] = (int)(start + n);
1115: PetscFunctionReturn(PETSC_SUCCESS);
1116: }
1118: /*@
1119: PetscOptionsPrefixPop - Remove the latest options prefix, see `PetscOptionsPrefixPush()` for details
1121: Logically Collective on the `MPI_Comm` used when called `PetscOptionsPrefixPush()`
1123: Input Parameter:
1124: . options - options database, or `NULL` for the default global database
1126: Level: advanced
1128: .seealso: `PetscOptionsPrefixPush()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1129: @*/
1130: PetscErrorCode PetscOptionsPrefixPop(PetscOptions options)
1131: {
1132: PetscInt offset;
1134: PetscFunctionBegin;
1135: options = options ? options : defaultoptions;
1136: PetscCheck(options->prefixind >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More prefixes popped than pushed");
1137: options->prefixind--;
1138: offset = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1139: options->prefix[offset] = 0;
1140: PetscFunctionReturn(PETSC_SUCCESS);
1141: }
1143: /* Releases the manual sections recorded from "-help mansec,..." and marks the help output as unrestricted. */
1144: static PetscErrorCode PetscOptionsHelpManSecsClear_Private(PetscOptions options)
1145: {
1146: PetscFunctionBegin;
1147: PetscCall(PetscStrToArrayDestroy(options->help_nmansecs, options->help_mansecs));
1148: options->help_nmansecs = 0;
1149: options->help_mansecs = NULL;
1150: PetscFunctionReturn(PETSC_SUCCESS);
1151: }
1153: /*@
1154: PetscOptionsClear - Removes all options form the database leaving it empty.
1156: Logically Collective
1158: Input Parameter:
1159: . options - options database, use `NULL` for the default global database
1161: Level: developer
1163: Note:
1164: The collectivity of this routine is complex; only the MPI processes that call this routine will
1165: have the affect of these options. If some processes that create objects call this routine and others do
1166: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1167: on different ranks.
1169: Developer Note:
1170: Uses `free()` directly because the current option values were set with `malloc()`
1172: .seealso: `PetscOptionsInsert()`
1173: @*/
1174: PetscErrorCode PetscOptionsClear(PetscOptions options)
1175: {
1176: PetscInt i;
1178: PetscFunctionBegin;
1179: options = options ? options : defaultoptions;
1180: if (!options) PetscFunctionReturn(PETSC_SUCCESS);
1182: for (i = 0; i < options->N; i++) {
1183: if (options->names[i]) free(options->names[i]);
1184: if (options->values[i]) free(options->values[i]);
1185: }
1186: options->N = 0;
1187: free(options->names);
1188: free(options->values);
1189: free(options->used);
1190: free(options->source);
1191: options->names = NULL;
1192: options->values = NULL;
1193: options->used = NULL;
1194: options->source = NULL;
1195: options->Nalloc = 0;
1197: for (i = 0; i < options->Na; i++) {
1198: free(options->aliases1[i]);
1199: free(options->aliases2[i]);
1200: }
1201: options->Na = 0;
1202: free(options->aliases1);
1203: free(options->aliases2);
1204: options->aliases1 = options->aliases2 = NULL;
1205: options->Naalloc = 0;
1207: /* destroy hash table */
1208: kh_destroy(HO, options->ht);
1209: options->ht = NULL;
1211: options->prefixind = 0;
1212: options->prefix[0] = 0;
1213: options->help = PETSC_FALSE;
1214: options->help_intro = PETSC_FALSE;
1215: PetscCall(PetscOptionsHelpManSecsClear_Private(options));
1216: PetscFunctionReturn(PETSC_SUCCESS);
1217: }
1219: /*@
1220: PetscOptionsSetAlias - Makes a key and alias for another key
1222: Logically Collective
1224: Input Parameters:
1225: + options - options database, or `NULL` for default global database
1226: . newname - the alias
1227: - oldname - the name that alias will refer to
1229: Level: advanced
1231: Note:
1232: The collectivity of this routine is complex; only the MPI processes that call this routine will
1233: have the affect of these options. If some processes that create objects call this routine and others do
1234: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1235: on different ranks.
1237: Developer Note:
1238: Uses `malloc()` directly because PETSc may not be initialized yet.
1240: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1241: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1242: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1243: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1244: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1245: `PetscOptionsFList()`, `PetscOptionsEList()`
1246: @*/
1247: PetscErrorCode PetscOptionsSetAlias(PetscOptions options, const char newname[], const char oldname[])
1248: {
1249: size_t len;
1250: PetscBool valid;
1252: PetscFunctionBegin;
1253: PetscAssertPointer(newname, 2);
1254: PetscAssertPointer(oldname, 3);
1255: options = options ? options : defaultoptions;
1256: PetscCall(PetscOptionsValidKey(newname, &valid));
1257: PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliased option %s", newname);
1258: PetscCall(PetscOptionsValidKey(oldname, &valid));
1259: PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliasee option %s", oldname);
1261: if (options->Na == options->Naalloc) {
1262: char **tmpA1, **tmpA2;
1264: options->Naalloc = PetscMax(4, options->Naalloc * 2);
1265: tmpA1 = (char **)malloc(options->Naalloc * sizeof(char *));
1266: tmpA2 = (char **)malloc(options->Naalloc * sizeof(char *));
1267: for (int i = 0; i < options->Na; ++i) {
1268: tmpA1[i] = options->aliases1[i];
1269: tmpA2[i] = options->aliases2[i];
1270: }
1271: free(options->aliases1);
1272: free(options->aliases2);
1273: options->aliases1 = tmpA1;
1274: options->aliases2 = tmpA2;
1275: }
1276: newname++;
1277: oldname++;
1278: PetscCall(PetscStrlen(newname, &len));
1279: options->aliases1[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1280: PetscCall(PetscStrncpy(options->aliases1[options->Na], newname, len + 1));
1281: PetscCall(PetscStrlen(oldname, &len));
1282: options->aliases2[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1283: PetscCall(PetscStrncpy(options->aliases2[options->Na], oldname, len + 1));
1284: ++options->Na;
1285: PetscFunctionReturn(PETSC_SUCCESS);
1286: }
1288: /*@
1289: PetscOptionsSetValue - Sets an option name-value pair in the options
1290: database, overriding whatever is already present.
1292: Logically Collective
1294: Input Parameters:
1295: + options - options database, use `NULL` for the default global database
1296: . name - name of option, this SHOULD have the - prepended
1297: - value - the option value (not used for all options, so can be `NULL`)
1299: Level: intermediate
1301: Note:
1302: This function can be called BEFORE `PetscInitialize()`
1304: The collectivity of this routine is complex; only the MPI processes that call this routine will
1305: have the affect of these options. If some processes that create objects call this routine and others do
1306: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1307: on different ranks.
1309: Developer Note:
1310: Uses `malloc()` directly because PETSc may not be initialized yet.
1312: .seealso: `PetscOptionsInsert()`, `PetscOptionsClearValue()`
1313: @*/
1314: PetscErrorCode PetscOptionsSetValue(PetscOptions options, const char name[], const char value[])
1315: {
1316: PetscFunctionBegin;
1317: PetscCall(PetscOptionsSetValue_Private(options, name, value, NULL, PETSC_OPT_CODE));
1318: PetscFunctionReturn(PETSC_SUCCESS);
1319: }
1321: PetscErrorCode PetscOptionsSetValue_Private(PetscOptions options, const char name[], const char value[], int *pos, PetscOptionSource source)
1322: {
1323: size_t len;
1324: int n, i;
1325: char **names;
1326: char fullname[PETSC_MAX_OPTION_NAME] = "";
1327: PetscBool flg;
1329: PetscFunctionBegin;
1330: if (!options) {
1331: PetscCall(PetscOptionsCreateDefault());
1332: options = defaultoptions;
1333: }
1334: PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "name %s must start with '-'", name);
1336: PetscCall(PetscOptionsSkipPrecedent(options, name, &flg));
1337: if (flg) PetscFunctionReturn(PETSC_SUCCESS);
1339: name++; /* skip starting dash */
1341: if (options->prefixind > 0) {
1342: strncpy(fullname, options->prefix, sizeof(fullname));
1343: fullname[sizeof(fullname) - 1] = 0;
1344: strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
1345: fullname[sizeof(fullname) - 1] = 0;
1346: name = fullname;
1347: }
1349: /* check against aliases */
1350: for (i = 0; i < options->Na; i++) {
1351: int result = PetscOptNameCmp(options->aliases1[i], name);
1352: if (!result) {
1353: name = options->aliases2[i];
1354: break;
1355: }
1356: }
1358: /* slow search */
1359: n = options->N;
1360: names = options->names;
1361: for (i = 0; i < options->N; i++) {
1362: int result = PetscOptNameCmp(names[i], name);
1363: if (!result) {
1364: n = i;
1365: goto setvalue;
1366: } else if (result > 0) {
1367: n = i;
1368: break;
1369: }
1370: }
1371: if (options->N == options->Nalloc) {
1372: char **names, **values;
1373: PetscBool *used;
1374: PetscOptionSource *source;
1376: options->Nalloc = PetscMax(10, options->Nalloc * 2);
1377: names = (char **)malloc(options->Nalloc * sizeof(char *));
1378: values = (char **)malloc(options->Nalloc * sizeof(char *));
1379: used = (PetscBool *)malloc(options->Nalloc * sizeof(PetscBool));
1380: source = (PetscOptionSource *)malloc(options->Nalloc * sizeof(PetscOptionSource));
1381: for (int i = 0; i < options->N; ++i) {
1382: names[i] = options->names[i];
1383: values[i] = options->values[i];
1384: used[i] = options->used[i];
1385: source[i] = options->source[i];
1386: }
1387: free(options->names);
1388: free(options->values);
1389: free(options->used);
1390: free(options->source);
1391: options->names = names;
1392: options->values = values;
1393: options->used = used;
1394: options->source = source;
1395: }
1397: /* shift remaining values up 1 */
1398: for (i = options->N; i > n; i--) {
1399: options->names[i] = options->names[i - 1];
1400: options->values[i] = options->values[i - 1];
1401: options->used[i] = options->used[i - 1];
1402: options->source[i] = options->source[i - 1];
1403: }
1404: options->names[n] = NULL;
1405: options->values[n] = NULL;
1406: options->used[n] = PETSC_FALSE;
1407: options->source[n] = PETSC_OPT_CODE;
1408: options->N++;
1410: /* destroy hash table */
1411: kh_destroy(HO, options->ht);
1412: options->ht = NULL;
1414: /* set new name */
1415: len = strlen(name);
1416: options->names[n] = (char *)malloc((len + 1) * sizeof(char));
1417: PetscCheck(options->names[n], PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate option name");
1418: strcpy(options->names[n], name);
1420: setvalue:
1421: /* set new value */
1422: if (options->values[n]) free(options->values[n]);
1423: len = value ? strlen(value) : 0;
1424: if (len) {
1425: options->values[n] = (char *)malloc((len + 1) * sizeof(char));
1426: if (!options->values[n]) return PETSC_ERR_MEM;
1427: strcpy(options->values[n], value);
1428: options->values[n][len] = '\0';
1429: } else {
1430: options->values[n] = NULL;
1431: }
1432: options->source[n] = source;
1434: /* handle -help so that it can be set from anywhere */
1435: if (!PetscOptNameCmp(name, "help")) {
1436: PetscBool isbool = PETSC_FALSE, helpval = PETSC_FALSE;
1438: PetscCall(PetscOptionsStringToBool_Private(value, &helpval, &isbool));
1439: options->help = isbool ? helpval : PETSC_TRUE;
1440: options->help_intro = (!isbool && value && !PetscOptNameCmp(value, "intro")) ? PETSC_TRUE : PETSC_FALSE;
1441: options->used[n] = PETSC_TRUE;
1442: PetscCall(PetscOptionsHelpManSecsClear_Private(options));
1443: /* a value that is neither a logical value nor "intro" is a comma-separated list of manual sections that
1444: restricts the help output; PetscStrToArray() uses raw malloc()/free() like names[]/values[], as needed
1445: here since -help is processed before the tracking allocator is set up */
1446: if (!isbool && value && value[0] && !options->help_intro) PetscCall(PetscStrToArray(value, ',', &options->help_nmansecs, &options->help_mansecs));
1447: }
1449: PetscCall(PetscOptionsMonitor(options, name, value ? value : "", source));
1450: if (pos) *pos = n;
1451: PetscFunctionReturn(PETSC_SUCCESS);
1452: }
1454: /*@
1455: PetscOptionsClearValue - Clears an option name-value pair in the options
1456: database, overriding whatever is already present.
1458: Logically Collective
1460: Input Parameters:
1461: + options - options database, use `NULL` for the default global database
1462: - name - name of option, this SHOULD have the - prepended
1464: Level: intermediate
1466: Note:
1467: The collectivity of this routine is complex; only the MPI processes that call this routine will
1468: have the affect of these options. If some processes that create objects call this routine and others do
1469: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1470: on different ranks.
1472: Developer Note:
1473: Uses `free()` directly because the options have been set with `malloc()`
1475: .seealso: `PetscOptionsInsert()`
1476: @*/
1477: PetscErrorCode PetscOptionsClearValue(PetscOptions options, const char name[])
1478: {
1479: int N, n, i;
1480: char **names;
1482: PetscFunctionBegin;
1483: options = options ? options : defaultoptions;
1484: PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1485: if (!PetscOptNameCmp(name, "-help")) {
1486: options->help = options->help_intro = PETSC_FALSE;
1487: PetscCall(PetscOptionsHelpManSecsClear_Private(options));
1488: }
1490: name++; /* skip starting dash */
1492: /* slow search */
1493: N = n = options->N;
1494: names = options->names;
1495: for (i = 0; i < N; i++) {
1496: int result = PetscOptNameCmp(names[i], name);
1497: if (!result) {
1498: n = i;
1499: break;
1500: } else if (result > 0) {
1501: n = N;
1502: break;
1503: }
1504: }
1505: if (n == N) PetscFunctionReturn(PETSC_SUCCESS); /* it was not present */
1507: /* remove name and value */
1508: if (options->names[n]) free(options->names[n]);
1509: if (options->values[n]) free(options->values[n]);
1510: /* shift remaining values down 1 */
1511: for (i = n; i < N - 1; i++) {
1512: options->names[i] = options->names[i + 1];
1513: options->values[i] = options->values[i + 1];
1514: options->used[i] = options->used[i + 1];
1515: options->source[i] = options->source[i + 1];
1516: }
1517: options->N--;
1519: /* destroy hash table */
1520: kh_destroy(HO, options->ht);
1521: options->ht = NULL;
1523: PetscCall(PetscOptionsMonitor(options, name, NULL, PETSC_OPT_CODE));
1524: PetscFunctionReturn(PETSC_SUCCESS);
1525: }
1527: /*@
1528: PetscOptionsFindPair - Gets an option name-value pair from the options database.
1530: Not Collective
1532: Input Parameters:
1533: + options - options database, use `NULL` for the default global database
1534: . pre - the string to prepend to the name or `NULL`, this SHOULD NOT have the "-" prepended
1535: - name - name of option, this SHOULD have the "-" prepended
1537: Output Parameters:
1538: + value - the option value (optional, not used for all options)
1539: - set - whether the option is set (optional)
1541: Level: developer
1543: Note:
1544: Each process may find different values or no value depending on how options were inserted into the database
1546: .seealso: `PetscOptionsSetValue()`, `PetscOptionsClearValue()`
1547: @*/
1548: PetscErrorCode PetscOptionsFindPair(PetscOptions options, const char pre[], const char name[], const char *value[], PetscBool *set)
1549: {
1550: char buf[PETSC_MAX_OPTION_NAME];
1551: PetscBool matchnumbers = PETSC_TRUE;
1553: PetscFunctionBegin;
1554: if (!options) {
1555: PetscCall(PetscOptionsCreateDefault());
1556: options = defaultoptions;
1557: }
1558: PetscCheck(!pre || !PetscUnlikely(pre[0] == '-'), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1559: PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1561: name++; /* skip starting dash */
1563: /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1564: if (pre && pre[0]) {
1565: char *ptr = buf;
1566: if (name[0] == '-') {
1567: *ptr++ = '-';
1568: name++;
1569: }
1570: PetscCall(PetscStrncpy(ptr, pre, buf + sizeof(buf) - ptr));
1571: PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1572: name = buf;
1573: }
1575: if (PetscDefined(USE_DEBUG)) {
1576: PetscBool valid;
1577: char key[PETSC_MAX_OPTION_NAME + 1] = "-";
1578: PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1579: PetscCall(PetscOptionsValidKey(key, &valid));
1580: PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1581: }
1583: if (!options->ht) {
1584: int i, ret;
1585: khiter_t it;
1586: khash_t(HO) *ht;
1587: ht = kh_init(HO);
1588: PetscCheck(ht, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1589: ret = kh_resize(HO, ht, options->N * 2); /* twice the required size to reduce risk of collisions */
1590: PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1591: for (i = 0; i < options->N; i++) {
1592: it = kh_put(HO, ht, options->names[i], &ret);
1593: PetscCheck(ret == 1, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1594: kh_val(ht, it) = i;
1595: }
1596: options->ht = ht;
1597: }
1599: khash_t(HO) *ht = options->ht;
1600: khiter_t it = kh_get(HO, ht, name);
1601: if (it != kh_end(ht)) {
1602: int i = kh_val(ht, it);
1603: options->used[i] = PETSC_TRUE;
1604: if (value) *value = options->values[i];
1605: if (set) *set = PETSC_TRUE;
1606: PetscFunctionReturn(PETSC_SUCCESS);
1607: }
1609: /*
1610: The following block slows down all lookups in the most frequent path (most lookups are unsuccessful).
1611: Maybe this special lookup mode should be enabled on request with a push/pop API.
1612: The feature of matching _%d_ used sparingly in the codebase.
1613: */
1614: if (matchnumbers) {
1615: int i, j, cnt = 0, locs[16], loce[16];
1616: /* determine the location and number of all _%d_ in the key */
1617: for (i = 0; name[i]; i++) {
1618: if (name[i] == '_') {
1619: for (j = i + 1; name[j]; j++) {
1620: if (name[j] >= '0' && name[j] <= '9') continue;
1621: if (name[j] == '_' && j > i + 1) { /* found a number */
1622: locs[cnt] = i + 1;
1623: loce[cnt++] = j + 1;
1624: }
1625: i = j - 1;
1626: break;
1627: }
1628: }
1629: }
1630: for (i = 0; i < cnt; i++) {
1631: PetscBool found;
1632: char opt[PETSC_MAX_OPTION_NAME + 1] = "-", tmp[PETSC_MAX_OPTION_NAME];
1633: PetscCall(PetscStrncpy(tmp, name, PetscMin((size_t)(locs[i] + 1), sizeof(tmp))));
1634: PetscCall(PetscStrlcat(opt, tmp, sizeof(opt)));
1635: PetscCall(PetscStrlcat(opt, name + loce[i], sizeof(opt)));
1636: PetscCall(PetscOptionsFindPair(options, NULL, opt, value, &found));
1637: if (found) {
1638: if (set) *set = PETSC_TRUE;
1639: PetscFunctionReturn(PETSC_SUCCESS);
1640: }
1641: }
1642: }
1644: if (set) *set = PETSC_FALSE;
1645: PetscFunctionReturn(PETSC_SUCCESS);
1646: }
1648: /* Check whether any option begins with pre+name */
1649: PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions options, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *set)
1650: {
1651: char buf[PETSC_MAX_OPTION_NAME];
1652: int numCnt = 0, locs[16], loce[16];
1654: PetscFunctionBegin;
1655: options = options ? options : defaultoptions;
1656: PetscCheck(!pre || pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1657: PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1659: name++; /* skip starting dash */
1661: /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1662: if (pre && pre[0]) {
1663: char *ptr = buf;
1664: if (name[0] == '-') {
1665: *ptr++ = '-';
1666: name++;
1667: }
1668: PetscCall(PetscStrncpy(ptr, pre, sizeof(buf) - ((ptr == buf) ? 0 : 1)));
1669: PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1670: name = buf;
1671: }
1673: if (PetscDefined(USE_DEBUG)) {
1674: PetscBool valid;
1675: char key[PETSC_MAX_OPTION_NAME + 1] = "-";
1676: PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1677: PetscCall(PetscOptionsValidKey(key, &valid));
1678: PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1679: }
1681: /* determine the location and number of all _%d_ in the key */
1682: {
1683: int i, j;
1684: for (i = 0; name[i]; i++) {
1685: if (name[i] == '_') {
1686: for (j = i + 1; name[j]; j++) {
1687: if (name[j] >= '0' && name[j] <= '9') continue;
1688: if (name[j] == '_' && j > i + 1) { /* found a number */
1689: locs[numCnt] = i + 1;
1690: loce[numCnt++] = j + 1;
1691: }
1692: i = j - 1;
1693: break;
1694: }
1695: }
1696: }
1697: }
1699: /* slow search */
1700: for (int c = -1; c < numCnt; ++c) {
1701: char opt[PETSC_MAX_OPTION_NAME + 2] = "";
1702: size_t len;
1704: if (c < 0) {
1705: PetscCall(PetscStrncpy(opt, name, sizeof(opt)));
1706: } else {
1707: PetscCall(PetscStrncpy(opt, name, PetscMin((size_t)(locs[c] + 1), sizeof(opt))));
1708: PetscCall(PetscStrlcat(opt, name + loce[c], sizeof(opt) - 1));
1709: }
1710: PetscCall(PetscStrlen(opt, &len));
1711: for (int i = 0; i < options->N; i++) {
1712: PetscBool match;
1714: PetscCall(PetscStrncmp(options->names[i], opt, len, &match));
1715: if (match) {
1716: options->used[i] = PETSC_TRUE;
1717: if (option) *option = options->names[i];
1718: if (value) *value = options->values[i];
1719: if (set) *set = PETSC_TRUE;
1720: PetscFunctionReturn(PETSC_SUCCESS);
1721: }
1722: }
1723: }
1725: if (set) *set = PETSC_FALSE;
1726: PetscFunctionReturn(PETSC_SUCCESS);
1727: }
1729: /*@
1730: PetscOptionsReject - Generates an error if a certain option is given.
1732: Not Collective
1734: Input Parameters:
1735: + options - options database, use `NULL` for default global database
1736: . pre - the option prefix (may be `NULL`)
1737: . name - the option name one is seeking
1738: - mess - error message (may be `NULL`)
1740: Level: advanced
1742: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1743: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1744: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1745: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1746: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1747: `PetscOptionsFList()`, `PetscOptionsEList()`
1748: @*/
1749: PetscErrorCode PetscOptionsReject(PetscOptions options, const char pre[], const char name[], const char mess[])
1750: {
1751: PetscBool flag = PETSC_FALSE;
1753: PetscFunctionBegin;
1754: PetscCall(PetscOptionsHasName(options, pre, name, &flag));
1755: if (flag) {
1756: PetscCheck(!mess || !mess[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s with %s", pre ? pre : "", name + 1, mess);
1757: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s", pre ? pre : "", name + 1);
1758: }
1759: PetscFunctionReturn(PETSC_SUCCESS);
1760: }
1762: /*@
1763: PetscOptionsHasHelp - Determines whether help output has been requested with the "-help" option.
1765: Not Collective
1767: Input Parameter:
1768: . options - options database, use `NULL` for default global database
1770: Output Parameter:
1771: . set - `PETSC_TRUE` if requested else `PETSC_FALSE`.
1773: Level: advanced
1775: Note:
1776: `-help` accepts a logical value, so this returns `PETSC_FALSE` for `-help 0`, `-help no`, `-help false`
1777: and `-help off` even though "-help" is then in the database. It returns `PETSC_TRUE` for `-help mansec`,
1778: which restricts rather than suppresses the help output.
1780: .seealso: `PetscOptionsHasName()`
1781: @*/
1782: PetscErrorCode PetscOptionsHasHelp(PetscOptions options, PetscBool *set)
1783: {
1784: PetscFunctionBegin;
1785: PetscAssertPointer(set, 2);
1786: options = options ? options : defaultoptions;
1787: *set = options->help;
1788: PetscFunctionReturn(PETSC_SUCCESS);
1789: }
1791: PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions options, PetscBool *set)
1792: {
1793: PetscFunctionBegin;
1794: PetscAssertPointer(set, 2);
1795: options = options ? options : defaultoptions;
1796: *set = options->help_intro;
1797: PetscFunctionReturn(PETSC_SUCCESS);
1798: }
1800: /* Returns the manual sections given with "-help mansec,...", with n set to 0 when the help output should not be
1801: restricted. mansec may be NULL. The returned array is borrowed and remains valid until the option is cleared. */
1802: PetscErrorCode PetscOptionsHelpManSecs_Internal(PetscOptions options, PetscInt *n, const char *const *mansec[])
1803: {
1804: PetscFunctionBegin;
1805: PetscAssertPointer(n, 2);
1806: options = options ? options : defaultoptions;
1807: *n = options->help_nmansecs;
1808: if (mansec) *mansec = (const char *const *)options->help_mansecs;
1809: PetscFunctionReturn(PETSC_SUCCESS);
1810: }
1812: /* Returns in print whether the help output documented in manual section mansec should be printed, taking both
1813: "-help" and any "-help mansec,..." restriction into account. mansec is the manual section that help belongs
1814: to; it may be NULL for help that belongs to none, which a restriction never selects. */
1815: PetscErrorCode PetscOptionsHelpPrintable_Internal(PetscOptions options, const char mansec[], PetscBool *print)
1816: {
1817: PetscInt nmansec = 0, idx = 0;
1818: const char *const *mansecs = NULL;
1820: PetscFunctionBegin;
1821: PetscAssertPointer(print, 3);
1822: PetscCall(PetscOptionsHasHelp(options, print));
1823: if (!*print) PetscFunctionReturn(PETSC_SUCCESS);
1824: PetscCall(PetscOptionsHelpManSecs_Internal(options, &nmansec, &mansecs));
1825: if (!nmansec) PetscFunctionReturn(PETSC_SUCCESS);
1826: *print = PETSC_FALSE;
1827: if (mansec && mansec[0]) PetscCall(PetscEListFind(nmansec, mansecs, mansec, &idx, print));
1828: PetscFunctionReturn(PETSC_SUCCESS);
1829: }
1831: /*@
1832: PetscOptionsHasName - Determines whether a certain option is given in the database. This returns true whether the option is a number, string or Boolean, even
1833: if its value is set to false.
1835: Not Collective
1837: Input Parameters:
1838: + options - options database, use `NULL` for default global database
1839: . pre - string to prepend to the name or `NULL`
1840: - name - the option one is seeking
1842: Output Parameter:
1843: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.
1845: Level: beginner
1847: Note:
1848: In many cases you probably want to use `PetscOptionsGetBool()` instead of calling this, to allowing toggling values.
1850: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1851: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1852: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1853: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1854: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1855: `PetscOptionsFList()`, `PetscOptionsEList()`
1856: @*/
1857: PetscErrorCode PetscOptionsHasName(PetscOptions options, const char pre[], const char name[], PetscBool *set)
1858: {
1859: const char *value;
1860: PetscBool flag;
1862: PetscFunctionBegin;
1863: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
1864: if (set) *set = flag;
1865: PetscFunctionReturn(PETSC_SUCCESS);
1866: }
1868: /*@
1869: PetscOptionsGetAll - Lists all the options the program was run with in a single string.
1871: Not Collective
1873: Input Parameter:
1874: . options - the options database, use `NULL` for the default global database
1876: Output Parameter:
1877: . copts - pointer where string pointer is stored
1879: Level: advanced
1881: Notes:
1882: The string should be freed with `PetscFree()`
1884: Each process may have different values depending on how the options were inserted into the database
1886: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsView()`, `PetscOptionsPush()`, `PetscOptionsPop()`,
1887: `PetscOptionsLeftGet()`
1888: @*/
1889: PetscErrorCode PetscOptionsGetAll(PetscOptions options, char *copts[]) PeNS
1890: {
1891: PetscInt i;
1892: size_t len = 1, lent = 0;
1893: char *coptions = NULL;
1895: PetscFunctionBegin;
1896: PetscAssertPointer(copts, 2);
1897: options = options ? options : defaultoptions;
1898: /* count the length of the required string */
1899: for (i = 0; i < options->N; i++) {
1900: PetscCall(PetscStrlen(options->names[i], &lent));
1901: len += 2 + lent;
1902: if (options->values[i]) {
1903: PetscCall(PetscStrlen(options->values[i], &lent));
1904: len += 1 + lent;
1905: }
1906: }
1907: PetscCall(PetscMalloc1(len, &coptions));
1908: coptions[0] = 0;
1909: for (i = 0; i < options->N; i++) {
1910: PetscCall(PetscStrlcat(coptions, "-", len));
1911: PetscCall(PetscStrlcat(coptions, options->names[i], len));
1912: PetscCall(PetscStrlcat(coptions, " ", len));
1913: if (options->values[i]) {
1914: PetscCall(PetscStrlcat(coptions, options->values[i], len));
1915: PetscCall(PetscStrlcat(coptions, " ", len));
1916: }
1917: }
1918: *copts = coptions;
1919: PetscFunctionReturn(PETSC_SUCCESS);
1920: }
1922: /*@
1923: PetscOptionsUsed - Indicates if PETSc has used a particular option set in the database
1925: Not Collective
1927: Input Parameters:
1928: + options - options database, use `NULL` for default global database
1929: - name - string name of option
1931: Output Parameter:
1932: . used - `PETSC_TRUE` if the option was used, otherwise false, including if option was not found in options database
1934: Level: advanced
1936: Note:
1937: The value returned may be different on each process and depends on which options have been processed
1938: on the given process
1940: .seealso: `PetscOptionsView()`, `PetscOptionsLeft()`, `PetscOptionsAllUsed()`
1941: @*/
1942: PetscErrorCode PetscOptionsUsed(PetscOptions options, const char *name, PetscBool *used)
1943: {
1944: PetscInt i;
1946: PetscFunctionBegin;
1947: PetscAssertPointer(name, 2);
1948: PetscAssertPointer(used, 3);
1949: options = options ? options : defaultoptions;
1950: *used = PETSC_FALSE;
1951: for (i = 0; i < options->N; i++) {
1952: PetscCall(PetscStrcasecmp(options->names[i], name, used));
1953: if (*used) {
1954: *used = options->used[i];
1955: break;
1956: }
1957: }
1958: PetscFunctionReturn(PETSC_SUCCESS);
1959: }
1961: /*@
1962: PetscOptionsAllUsed - Returns a count of the number of options in the
1963: database that have never been selected.
1965: Not Collective
1967: Input Parameter:
1968: . options - options database, use `NULL` for default global database
1970: Output Parameter:
1971: . N - count of options not used
1973: Level: advanced
1975: Note:
1976: The value returned may be different on each process and depends on which options have been processed
1977: on the given process
1979: .seealso: `PetscOptionsView()`
1980: @*/
1981: PetscErrorCode PetscOptionsAllUsed(PetscOptions options, PetscInt *N)
1982: {
1983: PetscInt i, n = 0;
1985: PetscFunctionBegin;
1986: PetscAssertPointer(N, 2);
1987: options = options ? options : defaultoptions;
1988: for (i = 0; i < options->N; i++) {
1989: if (!options->used[i]) n++;
1990: }
1991: *N = n;
1992: PetscFunctionReturn(PETSC_SUCCESS);
1993: }
1995: /*@
1996: PetscOptionsLeft - Prints to screen any options that were set and never used.
1998: Not Collective
2000: Input Parameter:
2001: . options - options database; use `NULL` for default global database
2003: Options Database Key:
2004: . -options_left - activates `PetscOptionsAllUsed()` within `PetscFinalize()`
2006: Level: advanced
2008: Notes:
2009: This is rarely used directly, it is called by `PetscFinalize()` by default (unless
2010: `-options_left false` is specified) to help users determine possible mistakes in their usage of
2011: options. This only prints values on process zero of `PETSC_COMM_WORLD`.
2013: Other processes depending the objects
2014: used may have different options that are left unused.
2016: .seealso: `PetscOptionsAllUsed()`
2017: @*/
2018: PetscErrorCode PetscOptionsLeft(PetscOptions options)
2019: {
2020: PetscInt cnt = 0;
2021: PetscOptions toptions;
2023: PetscFunctionBegin;
2024: toptions = options ? options : defaultoptions;
2025: for (PetscInt i = 0; i < toptions->N; i++) {
2026: if (!toptions->used[i]) {
2027: if (PetscCIOption(toptions->names[i])) continue;
2028: if (toptions->values[i]) {
2029: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s value: %s source: %s\n", toptions->names[i], toptions->values[i], PetscOptionSources[toptions->source[i]]));
2030: } else {
2031: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s (no value) source: %s\n", toptions->names[i], PetscOptionSources[toptions->source[i]]));
2032: }
2033: }
2034: }
2035: if (!options) {
2036: toptions = defaultoptions;
2037: while (toptions->previous) {
2038: cnt++;
2039: toptions = toptions->previous;
2040: }
2041: 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));
2042: }
2043: PetscFunctionReturn(PETSC_SUCCESS);
2044: }
2046: /*@
2047: PetscOptionsLeftGet - Returns all options that were set and never used.
2049: Not Collective
2051: Input Parameter:
2052: . options - options database, use `NULL` for default global database
2054: Output Parameters:
2055: + N - count of options not used
2056: . names - names of options not used
2057: - values - values of options not used
2059: Level: advanced
2061: Notes:
2062: Users should call `PetscOptionsLeftRestore()` to free the memory allocated in this routine
2064: The value returned may be different on each process and depends on which options have been processed
2065: on the given process
2067: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`
2068: @*/
2069: PetscErrorCode PetscOptionsLeftGet(PetscOptions options, PetscInt *N, char **names[], char **values[])
2070: {
2071: PetscInt n;
2073: PetscFunctionBegin;
2074: if (N) PetscAssertPointer(N, 2);
2075: if (names) PetscAssertPointer(names, 3);
2076: if (values) PetscAssertPointer(values, 4);
2077: options = options ? options : defaultoptions;
2079: /* The number of unused PETSc options */
2080: n = 0;
2081: for (PetscInt i = 0; i < options->N; i++) {
2082: if (PetscCIOption(options->names[i])) continue;
2083: if (!options->used[i]) n++;
2084: }
2085: if (N) *N = n;
2086: if (names) PetscCall(PetscMalloc1(n, names));
2087: if (values) PetscCall(PetscMalloc1(n, values));
2089: n = 0;
2090: if (names || values) {
2091: for (PetscInt i = 0; i < options->N; i++) {
2092: if (!options->used[i]) {
2093: if (PetscCIOption(options->names[i])) continue;
2094: if (names) (*names)[n] = options->names[i];
2095: if (values) (*values)[n] = options->values[i];
2096: n++;
2097: }
2098: }
2099: }
2100: PetscFunctionReturn(PETSC_SUCCESS);
2101: }
2103: /*@
2104: PetscOptionsLeftRestore - Free memory for the unused PETSc options obtained using `PetscOptionsLeftGet()`.
2106: Not Collective
2108: Input Parameters:
2109: + options - options database, use `NULL` for default global database
2110: . N - count of options not used
2111: . names - names of options not used
2112: - values - values of options not used
2114: Level: advanced
2116: Notes:
2117: The user should pass the same pointer to `N` as they did when calling `PetscOptionsLeftGet()`
2119: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`, `PetscOptionsLeftGet()`
2120: @*/
2121: PetscErrorCode PetscOptionsLeftRestore(PetscOptions options, PetscInt *N, char **names[], char **values[])
2122: {
2123: PetscFunctionBegin;
2124: (void)options;
2125: if (N) PetscAssertPointer(N, 2);
2126: if (names) PetscAssertPointer(names, 3);
2127: if (values) PetscAssertPointer(values, 4);
2128: if (N) *N = 0;
2129: if (names) PetscCall(PetscFree(*names));
2130: if (values) PetscCall(PetscFree(*values));
2131: PetscFunctionReturn(PETSC_SUCCESS);
2132: }
2134: /*@
2135: PetscOptionsMonitorDefault - Print all options set value events using the supplied `PetscViewer`.
2137: Logically Collective
2139: Input Parameters:
2140: + name - option name string
2141: . value - option value string
2142: . source - The source for the option
2143: - ctx - a `PETSCVIEWERASCII` or `NULL`
2145: Level: intermediate
2147: Notes:
2148: If ctx is `NULL`, `PetscPrintf()` is used.
2149: The first MPI process in the `PetscViewer` viewer actually prints the values, other
2150: processes may have different values set
2152: If `PetscCIEnabled` then do not print the test harness options
2154: .seealso: `PetscOptionsMonitorSet()`
2155: @*/
2156: PetscErrorCode PetscOptionsMonitorDefault(const char name[], const char value[], PetscOptionSource source, PetscCtx ctx)
2157: {
2158: PetscFunctionBegin;
2159: if (PetscCIOption(name)) PetscFunctionReturn(PETSC_SUCCESS);
2161: if (ctx) {
2162: PetscViewer viewer = (PetscViewer)ctx;
2163: if (!value) {
2164: PetscCall(PetscViewerASCIIPrintf(viewer, "Removing option: %s\n", name));
2165: } else if (!value[0]) {
2166: PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2167: } else {
2168: PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2169: }
2170: } else {
2171: if (!value) {
2172: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Removing option: %s\n", name));
2173: } else if (!value[0]) {
2174: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2175: } else {
2176: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2177: }
2178: }
2179: PetscFunctionReturn(PETSC_SUCCESS);
2180: }
2182: /*@
2183: PetscOptionsMonitorSet - Sets an ADDITIONAL function to be called at every method that
2184: modified the PETSc options database.
2186: Not Collective
2188: Input Parameters:
2189: + monitor - pointer to function (if this is `NULL`, it turns off monitoring
2190: . mctx - [optional] context for private data for the monitor routine (use `NULL` if
2191: no context is desired)
2192: - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for its calling sequence
2194: Calling sequence of `monitor`:
2195: + name - option name string
2196: . value - option value string, a value of `NULL` indicates the option is being removed from the database. A value
2197: of "" indicates the option is in the database but has no value.
2198: . source - option source
2199: - mctx - optional monitoring context, as set by `PetscOptionsMonitorSet()`
2201: Options Database Keys:
2202: + -options_monitor viewer - turn on default monitoring of changes to the options database
2203: - -options_monitor_cancel - turn off any option monitors except the default monitor obtained with `-options_monitor`
2205: Level: intermediate
2207: Notes:
2208: See `PetscInitialize()` for options related to option database monitoring.
2210: The default is to do no monitoring. To print the name and value of options
2211: being inserted into the database, use `PetscOptionsMonitorDefault()` as the monitoring routine,
2212: with a `NULL` monitoring context. Or use the option `-options_monitor viewer`.
2214: Several different monitoring routines may be set by calling
2215: `PetscOptionsMonitorSet()` multiple times; all will be called in the
2216: order in which they were set.
2218: .seealso: `PetscOptionsMonitorDefault()`, `PetscInitialize()`, `PetscCtxDestroyFn`
2219: @*/
2220: PetscErrorCode PetscOptionsMonitorSet(PetscErrorCode (*monitor)(const char name[], const char value[], PetscOptionSource source, PetscCtx mctx), PetscCtx mctx, PetscCtxDestroyFn *monitordestroy)
2221: {
2222: PetscOptions options = defaultoptions;
2224: PetscFunctionBegin;
2225: if (options->monitorCancel) PetscFunctionReturn(PETSC_SUCCESS);
2226: PetscCheck(options->numbermonitors < MAXOPTIONSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptions monitors set");
2227: options->monitor[options->numbermonitors] = monitor;
2228: options->monitordestroy[options->numbermonitors] = monitordestroy;
2229: options->monitorcontext[options->numbermonitors++] = mctx;
2230: PetscFunctionReturn(PETSC_SUCCESS);
2231: }
2233: /*
2234: Same as PetscOptionsStringToBool() but reports in isbool whether value is one of the recognized
2235: logical values instead of raising an error when it is not.
2236: */
2237: static PetscErrorCode PetscOptionsStringToBool_Private(const char value[], PetscBool *a, PetscBool *isbool)
2238: {
2239: PetscBool istrue, isfalse;
2240: size_t len;
2242: PetscFunctionBegin;
2243: *isbool = PETSC_TRUE;
2244: /* PetscStrlen() returns 0 for NULL or "" */
2245: PetscCall(PetscStrlen(value, &len));
2246: if (!len) {
2247: *a = PETSC_TRUE;
2248: PetscFunctionReturn(PETSC_SUCCESS);
2249: }
2250: PetscCall(PetscStrcasecmp(value, "TRUE", &istrue));
2251: if (istrue) {
2252: *a = PETSC_TRUE;
2253: PetscFunctionReturn(PETSC_SUCCESS);
2254: }
2255: PetscCall(PetscStrcasecmp(value, "YES", &istrue));
2256: if (istrue) {
2257: *a = PETSC_TRUE;
2258: PetscFunctionReturn(PETSC_SUCCESS);
2259: }
2260: PetscCall(PetscStrcasecmp(value, "1", &istrue));
2261: if (istrue) {
2262: *a = PETSC_TRUE;
2263: PetscFunctionReturn(PETSC_SUCCESS);
2264: }
2265: PetscCall(PetscStrcasecmp(value, "on", &istrue));
2266: if (istrue) {
2267: *a = PETSC_TRUE;
2268: PetscFunctionReturn(PETSC_SUCCESS);
2269: }
2270: PetscCall(PetscStrcasecmp(value, "FALSE", &isfalse));
2271: if (isfalse) {
2272: *a = PETSC_FALSE;
2273: PetscFunctionReturn(PETSC_SUCCESS);
2274: }
2275: PetscCall(PetscStrcasecmp(value, "NO", &isfalse));
2276: if (isfalse) {
2277: *a = PETSC_FALSE;
2278: PetscFunctionReturn(PETSC_SUCCESS);
2279: }
2280: PetscCall(PetscStrcasecmp(value, "0", &isfalse));
2281: if (isfalse) {
2282: *a = PETSC_FALSE;
2283: PetscFunctionReturn(PETSC_SUCCESS);
2284: }
2285: PetscCall(PetscStrcasecmp(value, "off", &isfalse));
2286: if (isfalse) {
2287: *a = PETSC_FALSE;
2288: PetscFunctionReturn(PETSC_SUCCESS);
2289: }
2290: *a = PETSC_FALSE;
2291: *isbool = PETSC_FALSE;
2292: PetscFunctionReturn(PETSC_SUCCESS);
2293: }
2295: /*@
2296: PetscOptionsStringToBool - Converts a string to a `PetscBool`
2298: Not Collective
2300: Input Parameter:
2301: . value - the string to convert; may be `NULL` or `""`
2303: Output Parameter:
2304: . a - the resulting `PetscBool`
2306: Level: developer
2308: Note:
2309: Recognizes (case-insensitive) `TRUE`, `YES`, `1`, `on` as `PETSC_TRUE` and `FALSE`, `NO`, `0`, `off` as `PETSC_FALSE`.
2310: An empty or `NULL` string is treated as `PETSC_TRUE`. Any other input generates an error.
2312: .seealso: `PetscOptionsStringToInt()`, `PetscOptionsStringToReal()`, `PetscOptionsStringToScalar()`, `PetscOptionsGetBool()`
2313: @*/
2314: PetscErrorCode PetscOptionsStringToBool(const char value[], PetscBool *a)
2315: {
2316: PetscBool isbool;
2318: PetscFunctionBegin;
2319: PetscCall(PetscOptionsStringToBool_Private(value, a, &isbool));
2320: PetscCheck(isbool, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown logical value: %s", value);
2321: PetscFunctionReturn(PETSC_SUCCESS);
2322: }
2324: /*@
2325: PetscOptionsStringToInt - Converts a string to an integer value. Handles special cases such as "default" and "decide"
2327: Not Collective
2329: Input Parameter:
2330: . name - the string to convert
2332: Output Parameter:
2333: . a - the resulting `PetscInt` value
2335: Level: developer
2337: Note:
2338: Recognizes the special strings `PETSC_DEFAULT`, `DEFAULT`, `PETSC_DECIDE`, `DECIDE`, `PETSC_DETERMINE`, `DETERMINE`, `PETSC_UNLIMITED`,
2339: `UNLIMITED`, and `mouse` (which returns `-1`). Otherwise the value is parsed as a base-10 integer.
2341: .seealso: `PetscOptionsStringToReal()`, `PetscOptionsStringToScalar()`, `PetscOptionsStringToBool()`, `PetscOptionsGetInt()`
2342: @*/
2343: PetscErrorCode PetscOptionsStringToInt(const char name[], PetscInt *a)
2344: {
2345: size_t len;
2346: PetscBool decide, tdefault, mouse, unlimited;
2348: PetscFunctionBegin;
2349: PetscCall(PetscStrlen(name, &len));
2350: PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2352: PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &tdefault));
2353: if (!tdefault) PetscCall(PetscStrcasecmp(name, "DEFAULT", &tdefault));
2354: PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &decide));
2355: if (!decide) PetscCall(PetscStrcasecmp(name, "DECIDE", &decide));
2356: if (!decide) PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &decide));
2357: if (!decide) PetscCall(PetscStrcasecmp(name, "DETERMINE", &decide));
2358: PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &unlimited));
2359: if (!unlimited) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &unlimited));
2360: PetscCall(PetscStrcasecmp(name, "mouse", &mouse));
2362: if (tdefault) *a = PETSC_DEFAULT;
2363: else if (decide) *a = PETSC_DECIDE;
2364: else if (unlimited) *a = PETSC_UNLIMITED;
2365: else if (mouse) *a = -1;
2366: else {
2367: char *endptr;
2368: long strtolval;
2370: strtolval = strtol(name, &endptr, 10);
2371: 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);
2373: #if PetscDefined(USE_64BIT_INDICES) && PetscDefined(HAVE_ATOLL)
2374: (void)strtolval;
2375: *a = atoll(name);
2376: #elif PetscDefined(USE_64BIT_INDICES) && PetscDefined(HAVE___INT64)
2377: (void)strtolval;
2378: *a = _atoi64(name);
2379: #else
2380: *a = (PetscInt)strtolval;
2381: #endif
2382: }
2383: PetscFunctionReturn(PETSC_SUCCESS);
2384: }
2386: #if PetscDefined(USE_REAL___FLOAT128)
2387: #include <quadmath.h>
2388: #endif
2390: static PetscErrorCode PetscStrtod(const char name[], PetscReal *a, char **endptr)
2391: {
2392: PetscFunctionBegin;
2393: #if PetscDefined(USE_REAL___FLOAT128)
2394: *a = strtoflt128(name, endptr);
2395: #else
2396: *a = (PetscReal)strtod(name, endptr);
2397: #endif
2398: PetscFunctionReturn(PETSC_SUCCESS);
2399: }
2401: static PetscErrorCode PetscStrtoz(const char name[], PetscScalar *a, char **endptr, PetscBool *isImaginary)
2402: {
2403: PetscBool hasi = PETSC_FALSE;
2404: char *ptr;
2405: PetscReal strtoval;
2407: PetscFunctionBegin;
2408: PetscCall(PetscStrtod(name, &strtoval, &ptr));
2409: if (ptr == name) {
2410: strtoval = 1.;
2411: hasi = PETSC_TRUE;
2412: if (name[0] == 'i') {
2413: ptr++;
2414: } else if (name[0] == '+' && name[1] == 'i') {
2415: ptr += 2;
2416: } else if (name[0] == '-' && name[1] == 'i') {
2417: strtoval = -1.;
2418: ptr += 2;
2419: }
2420: } else if (*ptr == 'i') {
2421: hasi = PETSC_TRUE;
2422: ptr++;
2423: }
2424: *endptr = ptr;
2425: *isImaginary = hasi;
2426: if (hasi) {
2427: #if !PetscDefined(USE_COMPLEX)
2428: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s contains imaginary but complex not supported ", name);
2429: #else
2430: *a = PetscCMPLX(0., strtoval);
2431: #endif
2432: } else {
2433: *a = strtoval;
2434: }
2435: PetscFunctionReturn(PETSC_SUCCESS);
2436: }
2438: /*@
2439: PetscOptionsStringToReal - Converts a string to a `PetscReal` value. Handles special cases like `default` and `decide`
2441: Not Collective
2443: Input Parameter:
2444: . name - the string to convert
2446: Output Parameter:
2447: . a - the resulting `PetscReal` value
2449: Level: developer
2451: Note:
2452: Recognizes the special strings `PETSC_DEFAULT`, `DEFAULT`, `PETSC_DECIDE`, `DECIDE`, `PETSC_DETERMINE`, `DETERMINE`,
2453: `PETSC_UNLIMITED`, and `UNLIMITED`. Otherwise the value is parsed as a floating-point number.
2455: .seealso: `PetscOptionsStringToInt()`, `PetscOptionsStringToScalar()`, `PetscOptionsStringToBool()`, `PetscOptionsGetReal()`
2456: @*/
2457: PetscErrorCode PetscOptionsStringToReal(const char name[], PetscReal *a)
2458: {
2459: size_t len;
2460: PetscBool match;
2461: char *endptr;
2463: PetscFunctionBegin;
2464: PetscCall(PetscStrlen(name, &len));
2465: PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "String of length zero has no numerical value");
2467: PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &match));
2468: if (!match) PetscCall(PetscStrcasecmp(name, "DEFAULT", &match));
2469: if (match) {
2470: *a = PETSC_DEFAULT;
2471: PetscFunctionReturn(PETSC_SUCCESS);
2472: }
2474: PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &match));
2475: if (!match) PetscCall(PetscStrcasecmp(name, "DECIDE", &match));
2476: if (match) {
2477: *a = PETSC_DECIDE;
2478: PetscFunctionReturn(PETSC_SUCCESS);
2479: }
2481: PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &match));
2482: if (!match) PetscCall(PetscStrcasecmp(name, "DETERMINE", &match));
2483: if (match) {
2484: *a = PETSC_DETERMINE;
2485: PetscFunctionReturn(PETSC_SUCCESS);
2486: }
2488: PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &match));
2489: if (!match) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &match));
2490: if (match) {
2491: *a = PETSC_UNLIMITED;
2492: PetscFunctionReturn(PETSC_SUCCESS);
2493: }
2495: PetscCall(PetscStrtod(name, a, &endptr));
2496: PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value", name);
2497: PetscFunctionReturn(PETSC_SUCCESS);
2498: }
2500: /*@
2501: PetscOptionsStringToScalar - Converts a string to a `PetscScalar` value; when PETSc is built with complex scalars, parses an optional imaginary part
2503: Not Collective
2505: Input Parameter:
2506: . name - the string to convert
2508: Output Parameter:
2509: . a - the resulting `PetscScalar` value
2511: Level: developer
2513: Note:
2514: Accepts forms such as `1.5`, `-2`, `3+4i`, `i`, or `-i`. Using an imaginary component when PETSc is built without complex scalars is an error.
2516: .seealso: `PetscOptionsStringToInt()`, `PetscOptionsStringToReal()`, `PetscOptionsStringToBool()`, `PetscOptionsGetScalar()`
2517: @*/
2518: PetscErrorCode PetscOptionsStringToScalar(const char name[], PetscScalar *a)
2519: {
2520: PetscBool imag1;
2521: size_t len;
2522: PetscScalar val = 0.;
2523: char *ptr = NULL;
2525: PetscFunctionBegin;
2526: PetscCall(PetscStrlen(name, &len));
2527: PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2528: PetscCall(PetscStrtoz(name, &val, &ptr, &imag1));
2529: #if PetscDefined(USE_COMPLEX)
2530: if ((size_t)(ptr - name) < len) {
2531: PetscBool imag2;
2532: PetscScalar val2;
2534: PetscCall(PetscStrtoz(ptr, &val2, &ptr, &imag2));
2535: if (imag1) PetscCheck(imag2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s: must specify imaginary component second", name);
2536: val = PetscCMPLX(PetscRealPart(val), PetscImaginaryPart(val2));
2537: }
2538: #endif
2539: PetscCheck((size_t)(ptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value ", name);
2540: *a = val;
2541: PetscFunctionReturn(PETSC_SUCCESS);
2542: }
2544: /*@
2545: PetscOptionsGetBool - Gets the Logical (true or false) value for a particular
2546: option in the database.
2548: Not Collective
2550: Input Parameters:
2551: + options - options database, use `NULL` for default global database
2552: . pre - the string to prepend to the name or `NULL`
2553: - name - the option one is seeking
2555: Output Parameters:
2556: + ivalue - the logical value to return
2557: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2559: Level: beginner
2561: Notes:
2562: The option values TRUE, YES, ON (case-insensitive) and 1 all translate to `PETSC_TRUE`
2564: The option values FALSE, NO, OFF (case-insensitive) and 0 all translate to `PETSC_FALSE`
2566: 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`
2567: is equivalent to `-requested_bool true`
2569: If the user does not supply the option at all `ivalue` is NOT changed. Thus
2570: you should ALWAYS initialize `ivalue` if you access it without first checking that the `set` flag is true.
2572: .seealso: `PetscOptionsGetBool3()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2573: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2574: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2575: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2576: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2577: `PetscOptionsFList()`, `PetscOptionsEList()`
2578: @*/
2579: PetscErrorCode PetscOptionsGetBool(PetscOptions options, const char pre[], const char name[], PetscBool *ivalue, PetscBool *set)
2580: {
2581: const char *value;
2582: PetscBool flag;
2584: PetscFunctionBegin;
2585: PetscAssertPointer(name, 3);
2586: if (ivalue) PetscAssertPointer(ivalue, 4);
2587: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2588: if (flag) {
2589: if (set) *set = PETSC_TRUE;
2590: PetscCall(PetscOptionsStringToBool(value, &flag));
2591: if (ivalue) *ivalue = flag;
2592: } else {
2593: if (set) *set = PETSC_FALSE;
2594: }
2595: PetscFunctionReturn(PETSC_SUCCESS);
2596: }
2598: /*@
2599: PetscOptionsGetBool3 - Gets the ternary logical (true, false or unknown) value for a particular
2600: option in the database.
2602: Not Collective
2604: Input Parameters:
2605: + options - options database, use `NULL` for default global database
2606: . pre - the string to prepend to the name or `NULL`
2607: - name - the option one is seeking
2609: Output Parameters:
2610: + ivalue - the ternary logical value to return
2611: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2613: Level: beginner
2615: Notes:
2616: The option values TRUE, YES, ON (case-insensitive) and 1 all translate to `PETSC_BOOL3_TRUE`
2618: The option values FALSE, NO, OFF (case-insensitive) and 0 all translate to `PETSC_BOOL3_FALSE`
2620: The option values UNKNOWN and AUTO (case-insensitive) all translate to `PETSC_BOOL3_UNKNOWN`
2622: 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`
2623: is equivalent to `-requested_bool3 true`
2625: If the user does not supply the option at all `ivalue` is NOT changed. Thus
2626: you should ALWAYS initialize `ivalue` if you access it without first checking that the `set` flag is true.
2628: .seealso: `PetscOptionsGetBool()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2629: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2630: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2631: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2632: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2633: `PetscOptionsFList()`, `PetscOptionsEList()`
2634: @*/
2635: PetscErrorCode PetscOptionsGetBool3(PetscOptions options, const char pre[], const char name[], PetscBool3 *ivalue, PetscBool *set)
2636: {
2637: const char *value;
2638: PetscBool flag;
2640: PetscFunctionBegin;
2641: PetscAssertPointer(name, 3);
2642: if (ivalue) PetscAssertPointer(ivalue, 4);
2643: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2644: if (flag) { // found the option
2645: PetscBool isAUTO = PETSC_FALSE, isUNKNOWN = PETSC_FALSE;
2647: if (set) *set = PETSC_TRUE;
2648: PetscCall(PetscStrcasecmp("AUTO", value, &isAUTO)); // auto or AUTO
2649: if (!isAUTO) PetscCall(PetscStrcasecmp("UNKNOWN", value, &isUNKNOWN)); // unknown or UNKNOWN
2650: if (isAUTO || isUNKNOWN) {
2651: if (ivalue) *ivalue = PETSC_BOOL3_UNKNOWN;
2652: } else { // handle boolean values (if no value is given, it returns true)
2653: PetscCall(PetscOptionsStringToBool(value, &flag));
2654: if (ivalue) *ivalue = PetscBoolToBool3(flag);
2655: }
2656: } else {
2657: if (set) *set = PETSC_FALSE;
2658: }
2659: PetscFunctionReturn(PETSC_SUCCESS);
2660: }
2662: /*@
2663: PetscOptionsGetEList - Puts a list of option values that a single one may be selected from
2665: Not Collective
2667: Input Parameters:
2668: + options - options database, use `NULL` for default global database
2669: . pre - the string to prepend to the name or `NULL`
2670: . opt - option name
2671: . list - the possible choices (one of these must be selected, anything else is invalid)
2672: - ntext - number of choices
2674: Output Parameters:
2675: + value - the index of the value to return (defaults to zero if the option name is given but no choice is listed)
2676: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2678: Level: intermediate
2680: Notes:
2681: If the user does not supply the option `value` is NOT changed. Thus
2682: you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.
2684: See `PetscOptionsFList()` for when the choices are given in a `PetscFunctionList`
2686: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2687: `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2688: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2689: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2690: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2691: `PetscOptionsFList()`, `PetscOptionsEList()`
2692: @*/
2693: PetscErrorCode PetscOptionsGetEList(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscInt ntext, PetscInt *value, PetscBool *set)
2694: {
2695: size_t alen, len = 0, tlen = 0;
2696: char *svalue;
2697: PetscBool aset, flg = PETSC_FALSE;
2699: PetscFunctionBegin;
2700: PetscAssertPointer(opt, 3);
2701: for (PetscInt i = 0; i < ntext; i++) {
2702: PetscCall(PetscStrlen(list[i], &alen));
2703: if (alen > len) len = alen;
2704: tlen += len + 1;
2705: }
2706: len += 5; /* a little extra space for user mistypes */
2707: PetscCall(PetscMalloc1(len, &svalue));
2708: PetscCall(PetscOptionsGetString(options, pre, opt, svalue, len, &aset));
2709: if (aset) {
2710: PetscCall(PetscEListFind(ntext, list, svalue, value, &flg));
2711: if (!flg) {
2712: char *avail;
2714: PetscCall(PetscMalloc1(tlen, &avail));
2715: avail[0] = '\0';
2716: for (PetscInt i = 0; i < ntext; i++) {
2717: PetscCall(PetscStrlcat(avail, list[i], tlen));
2718: PetscCall(PetscStrlcat(avail, " ", tlen));
2719: }
2720: PetscCall(PetscStrtolower(avail));
2721: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown option \"%s\" for -%s%s. Available options: %s", svalue, pre ? pre : "", opt + 1, avail);
2722: }
2723: if (set) *set = PETSC_TRUE;
2724: } else if (set) *set = PETSC_FALSE;
2725: PetscCall(PetscFree(svalue));
2726: PetscFunctionReturn(PETSC_SUCCESS);
2727: }
2729: /*@
2730: PetscOptionsGetEnum - Gets the enum value for a particular option in the database.
2732: Not Collective
2734: Input Parameters:
2735: + options - options database, use `NULL` for default global database
2736: . pre - option prefix or `NULL`
2737: . opt - option name
2738: - list - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
2740: Output Parameters:
2741: + value - the value to return
2742: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2744: Level: beginner
2746: Notes:
2747: If the user does not supply the option `value` is NOT changed. Thus
2748: you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.
2750: `list` is usually something like `PCASMTypes` or some other predefined list of enum names
2752: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2753: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2754: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2755: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2756: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2757: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2758: `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2759: @*/
2760: PetscErrorCode PetscOptionsGetEnum(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscEnum *value, PetscBool *set) PeNSS
2761: {
2762: PetscInt ntext = 0, tval;
2763: PetscBool fset;
2765: PetscFunctionBegin;
2766: PetscAssertPointer(opt, 3);
2767: 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");
2768: PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
2769: ntext -= 3;
2770: PetscCall(PetscOptionsGetEList(options, pre, opt, list, ntext, &tval, &fset));
2771: /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
2772: if (fset) *value = (PetscEnum)tval;
2773: if (set) *set = fset;
2774: PetscFunctionReturn(PETSC_SUCCESS);
2775: }
2777: /*@
2778: PetscOptionsGetInt - Gets the integer value for a particular option in the database.
2780: Not Collective
2782: Input Parameters:
2783: + options - options database, use `NULL` for default global database
2784: . pre - the string to prepend to the name or `NULL`
2785: - name - the option one is seeking
2787: Output Parameters:
2788: + ivalue - the integer value to return
2789: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2791: Level: beginner
2793: Notes:
2794: If the user does not supply the option `ivalue` is NOT changed. Thus
2795: you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.
2797: Accepts the special values `determine`, `decide` and `unlimited`.
2799: Accepts the deprecated value `default`.
2801: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2802: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2803: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2804: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2805: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2806: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2807: `PetscOptionsFList()`, `PetscOptionsEList()`
2808: @*/
2809: PetscErrorCode PetscOptionsGetInt(PetscOptions options, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
2810: {
2811: const char *value;
2812: PetscBool flag;
2814: PetscFunctionBegin;
2815: PetscAssertPointer(name, 3);
2816: PetscAssertPointer(ivalue, 4);
2817: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2818: if (flag) {
2819: if (!value) {
2820: if (set) *set = PETSC_FALSE;
2821: } else {
2822: if (set) *set = PETSC_TRUE;
2823: PetscCall(PetscOptionsStringToInt(value, ivalue));
2824: }
2825: } else {
2826: if (set) *set = PETSC_FALSE;
2827: }
2828: PetscFunctionReturn(PETSC_SUCCESS);
2829: }
2831: /*@
2832: PetscOptionsGetMPIInt - Gets the MPI integer value for a particular option in the database.
2834: Not Collective
2836: Input Parameters:
2837: + options - options database, use `NULL` for default global database
2838: . pre - the string to prepend to the name or `NULL`
2839: - name - the option one is seeking
2841: Output Parameters:
2842: + ivalue - the MPI integer value to return
2843: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2845: Level: beginner
2847: Notes:
2848: If the user does not supply the option `ivalue` is NOT changed. Thus
2849: you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.
2851: Accepts the special values `determine`, `decide` and `unlimited`.
2853: Accepts the deprecated value `default`.
2855: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2856: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2857: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2858: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2859: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2860: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2861: `PetscOptionsFList()`, `PetscOptionsEList()`
2862: @*/
2863: PetscErrorCode PetscOptionsGetMPIInt(PetscOptions options, const char pre[], const char name[], PetscMPIInt *ivalue, PetscBool *set)
2864: {
2865: PetscInt value;
2866: PetscBool flag;
2868: PetscFunctionBegin;
2869: PetscCall(PetscOptionsGetInt(options, pre, name, &value, &flag));
2870: if (flag) PetscCall(PetscMPIIntCast(value, ivalue));
2871: if (set) *set = flag;
2872: PetscFunctionReturn(PETSC_SUCCESS);
2873: }
2875: /*@
2876: PetscOptionsGetReal - Gets the double precision value for a particular
2877: option in the database.
2879: Not Collective
2881: Input Parameters:
2882: + options - options database, use `NULL` for default global database
2883: . pre - string to prepend to each name or `NULL`
2884: - name - the option one is seeking
2886: Output Parameters:
2887: + dvalue - the double value to return
2888: - set - `PETSC_TRUE` if found, `PETSC_FALSE` if not found
2890: Level: beginner
2892: Notes:
2893: Accepts the special values `determine`, `decide` and `unlimited`.
2895: Accepts the deprecated value `default`
2897: If the user does not supply the option `dvalue` is NOT changed. Thus
2898: you should ALWAYS initialize `dvalue` if you access it without first checking that the `set` flag is true.
2900: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2901: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2902: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2903: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2904: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2905: `PetscOptionsFList()`, `PetscOptionsEList()`
2906: @*/
2907: PetscErrorCode PetscOptionsGetReal(PetscOptions options, const char pre[], const char name[], PetscReal *dvalue, PetscBool *set)
2908: {
2909: const char *value;
2910: PetscBool flag;
2912: PetscFunctionBegin;
2913: PetscAssertPointer(name, 3);
2914: PetscAssertPointer(dvalue, 4);
2915: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2916: if (flag) {
2917: if (!value) {
2918: if (set) *set = PETSC_FALSE;
2919: } else {
2920: if (set) *set = PETSC_TRUE;
2921: PetscCall(PetscOptionsStringToReal(value, dvalue));
2922: }
2923: } else {
2924: if (set) *set = PETSC_FALSE;
2925: }
2926: PetscFunctionReturn(PETSC_SUCCESS);
2927: }
2929: /*@
2930: PetscOptionsGetScalar - Gets the scalar value for a particular
2931: option in the database.
2933: Not Collective
2935: Input Parameters:
2936: + options - options database, use `NULL` for default global database
2937: . pre - string to prepend to each name or `NULL`
2938: - name - the option one is seeking
2940: Output Parameters:
2941: + dvalue - the scalar value to return
2942: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2944: Level: beginner
2946: Example Usage:
2947: A complex number 2+3i must be specified with NO spaces
2949: Note:
2950: If the user does not supply the option `dvalue` is NOT changed. Thus
2951: you should ALWAYS initialize `dvalue` if you access it without first checking if the `set` flag is true.
2953: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2954: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2955: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2956: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2957: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2958: `PetscOptionsFList()`, `PetscOptionsEList()`
2959: @*/
2960: PetscErrorCode PetscOptionsGetScalar(PetscOptions options, const char pre[], const char name[], PetscScalar *dvalue, PetscBool *set)
2961: {
2962: const char *value;
2963: PetscBool flag;
2965: PetscFunctionBegin;
2966: PetscAssertPointer(name, 3);
2967: PetscAssertPointer(dvalue, 4);
2968: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2969: if (flag) {
2970: if (!value) {
2971: if (set) *set = PETSC_FALSE;
2972: } else {
2973: #if !PetscDefined(USE_COMPLEX)
2974: PetscCall(PetscOptionsStringToReal(value, dvalue));
2975: #else
2976: PetscCall(PetscOptionsStringToScalar(value, dvalue));
2977: #endif
2978: if (set) *set = PETSC_TRUE;
2979: }
2980: } else { /* flag */
2981: if (set) *set = PETSC_FALSE;
2982: }
2983: PetscFunctionReturn(PETSC_SUCCESS);
2984: }
2986: /*@
2987: PetscOptionsGetString - Gets the string value for a particular option in
2988: the database.
2990: Not Collective
2992: Input Parameters:
2993: + options - options database, use `NULL` for default global database
2994: . pre - string to prepend to name or `NULL`
2995: . name - the option one is seeking
2996: - len - maximum length of the string including null termination
2998: Output Parameters:
2999: + string - location to copy string
3000: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3002: Level: beginner
3004: Note:
3005: 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`
3007: If the user does not use the option then `string` is not changed. Thus
3008: you should ALWAYS initialize `string` if you access it without first checking that the `set` flag is true.
3010: Fortran Notes:
3011: The Fortran interface is slightly different from the C/C++
3012: interface. Sample usage in Fortran follows
3013: .vb
3014: character *20 string
3015: PetscErrorCode ierr
3016: PetscBool set
3017: call PetscOptionsGetString(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-s',string,set,ierr)
3018: .ve
3020: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
3021: `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3022: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3023: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3024: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3025: `PetscOptionsFList()`, `PetscOptionsEList()`
3026: @*/
3027: PetscErrorCode PetscOptionsGetString(PetscOptions options, const char pre[], const char name[], char string[], size_t len, PetscBool *set) PeNS
3028: {
3029: const char *value;
3030: PetscBool flag;
3032: PetscFunctionBegin;
3033: PetscAssertPointer(name, 3);
3034: PetscAssertPointer(string, 4);
3035: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
3036: if (!flag) {
3037: if (set) *set = PETSC_FALSE;
3038: } else {
3039: if (set) *set = PETSC_TRUE;
3040: if (value) PetscCall(PetscStrncpy(string, value, len));
3041: else PetscCall(PetscArrayzero(string, len));
3042: }
3043: PetscFunctionReturn(PETSC_SUCCESS);
3044: }
3046: /*@
3047: PetscOptionsGetBoolArray - Gets an array of Logical (true or false) values for a particular
3048: option in the database. The values must be separated with commas with no intervening spaces.
3050: Not Collective
3052: Input Parameters:
3053: + options - options database, use `NULL` for default global database
3054: . pre - string to prepend to each name or `NULL`
3055: - name - the option one is seeking
3057: Output Parameters:
3058: + dvalue - the Boolean values to return
3059: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
3060: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3062: Level: beginner
3064: Notes:
3065: The option values TRUE, YES, ON (case-insensitive) and 1 all translate to `PETSC_TRUE`
3067: The option values FALSE, NO, OFF (case-insensitive) and 0 all translate to `PETSC_FALSE`
3069: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3070: `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3071: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3072: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3073: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3074: `PetscOptionsFList()`, `PetscOptionsEList()`
3075: @*/
3076: PetscErrorCode PetscOptionsGetBoolArray(PetscOptions options, const char pre[], const char name[], PetscBool dvalue[], PetscInt *nmax, PetscBool *set)
3077: {
3078: const char *svalue;
3079: const char *value;
3080: PetscInt n = 0;
3081: PetscBool flag;
3082: PetscToken token;
3084: PetscFunctionBegin;
3085: PetscAssertPointer(name, 3);
3086: PetscAssertPointer(nmax, 5);
3087: if (*nmax) PetscAssertPointer(dvalue, 4);
3089: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3090: if (!flag || !svalue) {
3091: if (set) *set = PETSC_FALSE;
3092: *nmax = 0;
3093: PetscFunctionReturn(PETSC_SUCCESS);
3094: }
3095: if (set) *set = PETSC_TRUE;
3096: PetscCall(PetscTokenCreate(svalue, ',', &token));
3097: PetscCall(PetscTokenFind(token, &value));
3098: while (value && n < *nmax) {
3099: PetscCall(PetscOptionsStringToBool(value, dvalue));
3100: PetscCall(PetscTokenFind(token, &value));
3101: dvalue++;
3102: n++;
3103: }
3104: PetscCall(PetscTokenDestroy(&token));
3105: *nmax = n;
3106: PetscFunctionReturn(PETSC_SUCCESS);
3107: }
3109: /*@
3110: PetscOptionsGetEnumArray - Gets an array of enum values for a particular option in the database.
3112: Not Collective
3114: Input Parameters:
3115: + options - options database, use `NULL` for default global database
3116: . pre - option prefix or `NULL`
3117: . name - option name
3118: - list - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
3120: Output Parameters:
3121: + ivalue - the enum values to return
3122: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
3123: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3125: Level: beginner
3127: Notes:
3128: The array must be passed as a comma separated list with no spaces between the items.
3130: `list` is usually something like `PCASMTypes` or some other predefined list of enum names.
3132: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
3133: `PetscOptionsGetEnum()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3134: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsName()`,
3135: `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, `PetscOptionsStringArray()`, `PetscOptionsRealArray()`,
3136: `PetscOptionsScalar()`, `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3137: `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
3138: @*/
3139: PetscErrorCode PetscOptionsGetEnumArray(PetscOptions options, const char pre[], const char name[], const char *const list[], PetscEnum ivalue[], PetscInt *nmax, PetscBool *set)
3140: {
3141: const char *svalue;
3142: const char *value;
3143: PetscInt n = 0;
3144: PetscEnum evalue;
3145: PetscBool flag;
3146: PetscToken token;
3148: PetscFunctionBegin;
3149: PetscAssertPointer(name, 3);
3150: PetscAssertPointer(list, 4);
3151: PetscAssertPointer(nmax, 6);
3152: if (*nmax) PetscAssertPointer(ivalue, 5);
3154: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3155: if (!flag || !svalue) {
3156: if (set) *set = PETSC_FALSE;
3157: *nmax = 0;
3158: PetscFunctionReturn(PETSC_SUCCESS);
3159: }
3160: if (set) *set = PETSC_TRUE;
3161: PetscCall(PetscTokenCreate(svalue, ',', &token));
3162: PetscCall(PetscTokenFind(token, &value));
3163: while (value && n < *nmax) {
3164: PetscCall(PetscEnumFind(list, value, &evalue, &flag));
3165: PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown enum value '%s' for -%s%s", svalue, pre ? pre : "", name + 1);
3166: ivalue[n++] = evalue;
3167: PetscCall(PetscTokenFind(token, &value));
3168: }
3169: PetscCall(PetscTokenDestroy(&token));
3170: *nmax = n;
3171: PetscFunctionReturn(PETSC_SUCCESS);
3172: }
3174: /*@
3175: PetscOptionsGetIntArray - Gets an array of integer values for a particular option in the database.
3177: Not Collective
3179: Input Parameters:
3180: + options - options database, use `NULL` for default global database
3181: . pre - string to prepend to each name or `NULL`
3182: - name - the option one is seeking
3184: Output Parameters:
3185: + ivalue - the integer values to return
3186: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
3187: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3189: Level: beginner
3191: Notes:
3192: The array can be passed as
3193: + a comma separated list - 0,1,2,3,4,5,6,7
3194: . a range (start\-end+1) - 0-8
3195: . a range with given increment (start\-end+1:inc) - 0-7:2
3196: - a combination of values and ranges separated by commas - 0,1-8,8-15:2
3198: There must be no intervening spaces between the values.
3200: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3201: `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3202: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3203: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3204: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3205: `PetscOptionsFList()`, `PetscOptionsEList()`
3206: @*/
3207: PetscErrorCode PetscOptionsGetIntArray(PetscOptions options, const char pre[], const char name[], PetscInt ivalue[], PetscInt *nmax, PetscBool *set)
3208: {
3209: const char *svalue;
3210: const char *value;
3211: PetscInt n = 0, i, j, start, end, inc, nvalues;
3212: size_t len;
3213: PetscBool flag, foundrange;
3214: PetscToken token;
3216: PetscFunctionBegin;
3217: PetscAssertPointer(name, 3);
3218: PetscAssertPointer(nmax, 5);
3219: if (*nmax) PetscAssertPointer(ivalue, 4);
3221: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3222: if (!flag || !svalue) {
3223: if (set) *set = PETSC_FALSE;
3224: *nmax = 0;
3225: PetscFunctionReturn(PETSC_SUCCESS);
3226: }
3227: if (set) *set = PETSC_TRUE;
3228: PetscCall(PetscTokenCreate(svalue, ',', &token));
3229: PetscCall(PetscTokenFind(token, &value));
3230: while (value && n < *nmax) {
3231: char *iivalue;
3233: /* look for form d-D where d and D are integers */
3234: PetscCall(PetscStrallocpy(value, &iivalue));
3235: foundrange = PETSC_FALSE;
3236: PetscCall(PetscStrlen(iivalue, &len));
3237: if (iivalue[0] == '-') i = 2;
3238: else i = 1;
3239: for (; i < (int)len; i++) {
3240: if (iivalue[i] == '-') {
3241: PetscCheck(i != (int)len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, iivalue);
3242: iivalue[i] = 0;
3244: PetscCall(PetscOptionsStringToInt(iivalue, &start));
3245: inc = 1;
3246: j = i + 1;
3247: for (; j < (int)len; j++) {
3248: if (iivalue[j] == ':') {
3249: iivalue[j] = 0;
3251: PetscCall(PetscOptionsStringToInt(iivalue + j + 1, &inc));
3252: PetscCheck(inc > 0, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry,%s cannot have negative increment", n, iivalue + j + 1);
3253: break;
3254: }
3255: }
3256: PetscCall(PetscOptionsStringToInt(iivalue + i + 1, &end));
3257: PetscCheck(end > start, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, %s-%s cannot have decreasing list", n, iivalue, iivalue + i + 1);
3258: nvalues = (end - start) / inc + (end - start) % inc;
3259: 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);
3260: for (; start < end; start += inc) {
3261: *ivalue = start;
3262: ivalue++;
3263: n++;
3264: }
3265: foundrange = PETSC_TRUE;
3266: break;
3267: }
3268: }
3269: if (!foundrange) {
3270: PetscCall(PetscOptionsStringToInt(value, ivalue));
3271: ivalue++;
3272: n++;
3273: }
3274: PetscCall(PetscFree(iivalue));
3275: PetscCall(PetscTokenFind(token, &value));
3276: }
3277: PetscCall(PetscTokenDestroy(&token));
3278: *nmax = n;
3279: PetscFunctionReturn(PETSC_SUCCESS);
3280: }
3282: /*@
3283: PetscOptionsGetRealArray - Gets an array of double precision values for a
3284: particular option in the database. The values must be separated with commas with no intervening spaces.
3286: Not Collective
3288: Input Parameters:
3289: + options - options database, use `NULL` for default global database
3290: . pre - string to prepend to each name or `NULL`
3291: - name - the option one is seeking
3293: Output Parameters:
3294: + dvalue - the double values to return
3295: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
3296: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3298: Level: beginner
3300: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3301: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3302: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3303: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3304: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3305: `PetscOptionsFList()`, `PetscOptionsEList()`
3306: @*/
3307: PetscErrorCode PetscOptionsGetRealArray(PetscOptions options, const char pre[], const char name[], PetscReal dvalue[], PetscInt *nmax, PetscBool *set)
3308: {
3309: const char *svalue;
3310: const char *value;
3311: PetscInt n = 0;
3312: PetscBool flag;
3313: PetscToken token;
3315: PetscFunctionBegin;
3316: PetscAssertPointer(name, 3);
3317: PetscAssertPointer(nmax, 5);
3318: if (*nmax) PetscAssertPointer(dvalue, 4);
3320: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3321: if (!flag || !svalue) {
3322: if (set) *set = PETSC_FALSE;
3323: *nmax = 0;
3324: PetscFunctionReturn(PETSC_SUCCESS);
3325: }
3326: if (set) *set = PETSC_TRUE;
3327: PetscCall(PetscTokenCreate(svalue, ',', &token));
3328: PetscCall(PetscTokenFind(token, &value));
3329: while (value && n < *nmax) {
3330: PetscCall(PetscOptionsStringToReal(value, dvalue++));
3331: PetscCall(PetscTokenFind(token, &value));
3332: n++;
3333: }
3334: PetscCall(PetscTokenDestroy(&token));
3335: *nmax = n;
3336: PetscFunctionReturn(PETSC_SUCCESS);
3337: }
3339: /*@
3340: PetscOptionsGetScalarArray - Gets an array of scalars for a
3341: particular option in the database. The values must be separated with commas with no intervening spaces.
3343: Not Collective
3345: Input Parameters:
3346: + options - options database, use `NULL` for default global database
3347: . pre - string to prepend to each name or `NULL`
3348: - name - the option one is seeking
3350: Output Parameters:
3351: + dvalue - the scalar values to return
3352: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
3353: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3355: Level: beginner
3357: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3358: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3359: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3360: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3361: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3362: `PetscOptionsFList()`, `PetscOptionsEList()`
3363: @*/
3364: PetscErrorCode PetscOptionsGetScalarArray(PetscOptions options, const char pre[], const char name[], PetscScalar dvalue[], PetscInt *nmax, PetscBool *set)
3365: {
3366: const char *svalue;
3367: const char *value;
3368: PetscInt n = 0;
3369: PetscBool flag;
3370: PetscToken token;
3372: PetscFunctionBegin;
3373: PetscAssertPointer(name, 3);
3374: PetscAssertPointer(nmax, 5);
3375: if (*nmax) PetscAssertPointer(dvalue, 4);
3377: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3378: if (!flag || !svalue) {
3379: if (set) *set = PETSC_FALSE;
3380: *nmax = 0;
3381: PetscFunctionReturn(PETSC_SUCCESS);
3382: }
3383: if (set) *set = PETSC_TRUE;
3384: PetscCall(PetscTokenCreate(svalue, ',', &token));
3385: PetscCall(PetscTokenFind(token, &value));
3386: while (value && n < *nmax) {
3387: PetscCall(PetscOptionsStringToScalar(value, dvalue++));
3388: PetscCall(PetscTokenFind(token, &value));
3389: n++;
3390: }
3391: PetscCall(PetscTokenDestroy(&token));
3392: *nmax = n;
3393: PetscFunctionReturn(PETSC_SUCCESS);
3394: }
3396: /*@
3397: PetscOptionsGetStringArray - Gets an array of string values for a particular
3398: option in the database. The values must be separated with commas with no intervening spaces.
3400: Not Collective; No Fortran Support
3402: Input Parameters:
3403: + options - options database, use `NULL` for default global database
3404: . pre - string to prepend to name or `NULL`
3405: - name - the option one is seeking
3407: Output Parameters:
3408: + strings - location to copy strings
3409: . nmax - On input maximum number of strings, on output the actual number of strings found
3410: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3412: Level: beginner
3414: Notes:
3415: The `nmax` parameter is used for both input and output.
3417: The user should pass in an array of pointers to `char`, to hold all the
3418: strings returned by this function.
3420: The user is responsible for deallocating the strings that are
3421: returned.
3423: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
3424: `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3425: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3426: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3427: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3428: `PetscOptionsFList()`, `PetscOptionsEList()`
3429: @*/
3430: PetscErrorCode PetscOptionsGetStringArray(PetscOptions options, const char pre[], const char name[], char *strings[], PetscInt *nmax, PetscBool *set) PeNS
3431: {
3432: const char *svalue;
3433: const char *value;
3434: PetscInt n = 0;
3435: PetscBool flag;
3436: PetscToken token;
3438: PetscFunctionBegin;
3439: PetscAssertPointer(name, 3);
3440: PetscAssertPointer(nmax, 5);
3441: if (*nmax) PetscAssertPointer(strings, 4);
3443: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3444: if (!flag || !svalue) {
3445: if (set) *set = PETSC_FALSE;
3446: *nmax = 0;
3447: PetscFunctionReturn(PETSC_SUCCESS);
3448: }
3449: if (set) *set = PETSC_TRUE;
3450: PetscCall(PetscTokenCreate(svalue, ',', &token));
3451: PetscCall(PetscTokenFind(token, &value));
3452: while (value && n < *nmax) {
3453: PetscCall(PetscStrallocpy(value, &strings[n]));
3454: PetscCall(PetscTokenFind(token, &value));
3455: n++;
3456: }
3457: PetscCall(PetscTokenDestroy(&token));
3458: *nmax = n;
3459: PetscFunctionReturn(PETSC_SUCCESS);
3460: }
3462: PetscErrorCode PetscOptionsDeprecated_Private(PetscOptionItems PetscOptionsObject, MPI_Comm incomm, const char inprefix[], const char oldname[], const char newname[], const char version[], const char info[])
3463: {
3464: PetscBool found, quiet;
3465: const char *value;
3466: const char *const quietopt = "-options_suppress_deprecated_warnings";
3467: char msg[4096];
3468: const char *prefix = NULL;
3469: PetscOptions options = NULL;
3470: MPI_Comm comm = PETSC_COMM_SELF;
3472: PetscFunctionBegin;
3473: PetscAssertPointer(oldname, 4);
3474: PetscAssertPointer(version, 6);
3475: if (PetscOptionsObject) {
3476: prefix = PetscOptionsObject->prefix;
3477: options = PetscOptionsObject->options;
3478: comm = PetscOptionsObject->comm;
3479: } else {
3480: prefix = inprefix;
3481: comm = incomm;
3482: }
3484: PetscCall(PetscOptionsFindPair(options, prefix, oldname, &value, &found));
3485: if (found) {
3486: if (newname) {
3487: PetscBool newfound;
3489: /* do not overwrite if the new option has been provided */
3490: PetscCall(PetscOptionsFindPair(options, prefix, newname, NULL, &newfound));
3491: if (!newfound) {
3492: if (prefix) PetscCall(PetscOptionsPrefixPush(options, prefix));
3493: PetscCall(PetscOptionsSetValue(options, newname, value));
3494: if (prefix) PetscCall(PetscOptionsPrefixPop(options));
3495: }
3496: if (prefix) {
3497: char key[PETSC_MAX_OPTION_NAME];
3499: PetscCall(PetscSNPrintf(key, sizeof(key), "-%s%s", prefix, oldname + 1));
3500: PetscCall(PetscOptionsClearValue(options, key));
3501: } else PetscCall(PetscOptionsClearValue(options, oldname));
3502: }
3503: quiet = PETSC_FALSE;
3504: PetscCall(PetscOptionsGetBool(options, NULL, quietopt, &quiet, NULL));
3505: if (!quiet) {
3506: PetscCall(PetscStrncpy(msg, "** PETSc DEPRECATION WARNING ** : the option -", sizeof(msg)));
3507: PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
3508: PetscCall(PetscStrlcat(msg, oldname + 1, sizeof(msg)));
3509: PetscCall(PetscStrlcat(msg, " is deprecated as of version ", sizeof(msg)));
3510: PetscCall(PetscStrlcat(msg, version, sizeof(msg)));
3511: PetscCall(PetscStrlcat(msg, " and will be removed in a future release.\n", sizeof(msg)));
3512: if (newname) {
3513: PetscCall(PetscStrlcat(msg, " Use the option -", sizeof(msg)));
3514: PetscCall(PetscStrlcat(msg, prefix, sizeof(msg)));
3515: PetscCall(PetscStrlcat(msg, newname + 1, sizeof(msg)));
3516: PetscCall(PetscStrlcat(msg, " instead.", sizeof(msg)));
3517: }
3518: if (info) {
3519: PetscCall(PetscStrlcat(msg, " ", sizeof(msg)));
3520: PetscCall(PetscStrlcat(msg, info, sizeof(msg)));
3521: }
3522: PetscCall(PetscStrlcat(msg, " (Silence this warning with ", sizeof(msg)));
3523: PetscCall(PetscStrlcat(msg, quietopt, sizeof(msg)));
3524: PetscCall(PetscStrlcat(msg, ")\n", sizeof(msg)));
3525: PetscCall(PetscPrintf(comm, "%s", msg));
3526: }
3527: }
3528: PetscFunctionReturn(PETSC_SUCCESS);
3529: }