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