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, MPIU_BOOL, 0, comm));
446: }
447: PetscFunctionReturn(PETSC_SUCCESS);
448: }
450: static PetscErrorCode PetscOptionsInsertFilePetsc(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
451: {
452: char *string, *vstring = NULL, *astring = NULL, *packed = NULL;
453: 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: if (alias) {
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: } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown first token in options file %s line %" PetscInt_FMT ": %s", fname, line, tokens[0]);
542: }
543: {
544: const char *extraToken = alias ? tokens[3] : tokens[2];
545: PetscCheck(!extraToken, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Error in options file %s line %" PetscInt_FMT ": extra token %s", fname, line, extraToken);
546: }
547: destroy:
548: free(string);
549: PetscCall(PetscTokenDestroy(&token));
550: alias = PETSC_FALSE;
551: line++;
552: }
553: err = fclose(fd);
554: PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file %s", fname);
555: PetscCall(PetscSegBufferGetSize(aseg, &bytes)); /* size without null termination */
556: PetscCall(PetscMPIIntCast(bytes, &acnt));
557: PetscCall(PetscSegBufferGet(aseg, 1, &astring));
558: astring[0] = 0;
559: PetscCall(PetscSegBufferGetSize(vseg, &bytes)); /* size without null termination */
560: PetscCall(PetscMPIIntCast(bytes, &cnt));
561: PetscCall(PetscSegBufferGet(vseg, 1, &vstring));
562: vstring[0] = 0;
563: PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
564: PetscCall(PetscSegBufferExtractTo(aseg, packed));
565: PetscCall(PetscSegBufferExtractTo(vseg, packed + acnt + 1));
566: PetscCall(PetscSegBufferDestroy(&aseg));
567: PetscCall(PetscSegBufferDestroy(&vseg));
568: } else PetscCheck(!require, PETSC_COMM_SELF, PETSC_ERR_USER, "Unable to open options file %s", fname);
569: }
571: counts[0] = acnt;
572: counts[1] = cnt;
573: err = MPI_Bcast(counts, 2, MPI_INT, 0, comm);
574: 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/");
575: acnt = counts[0];
576: cnt = counts[1];
577: if (rank) PetscCall(PetscMalloc1(2 + acnt + cnt, &packed));
578: if (acnt || cnt) {
579: PetscCallMPI(MPI_Bcast(packed, 2 + acnt + cnt, MPI_CHAR, 0, comm));
580: astring = packed;
581: vstring = packed + acnt + 1;
582: }
584: if (acnt) {
585: PetscCall(PetscTokenCreate(astring, ' ', &token));
586: PetscCall(PetscTokenFind(token, &tokens[0]));
587: while (tokens[0]) {
588: PetscCall(PetscTokenFind(token, &tokens[1]));
589: PetscCall(PetscOptionsSetAlias(options, tokens[0], tokens[1]));
590: PetscCall(PetscTokenFind(token, &tokens[0]));
591: }
592: PetscCall(PetscTokenDestroy(&token));
593: }
595: if (cnt) PetscCall(PetscOptionsInsertString_Private(options, vstring, PETSC_OPT_FILE));
596: PetscCall(PetscFree(packed));
597: PetscFunctionReturn(PETSC_SUCCESS);
598: }
600: /*@
601: PetscOptionsInsertFile - Inserts options into the database from a file.
603: Collective
605: Input Parameters:
606: + comm - the processes that will share the options (usually `PETSC_COMM_WORLD`)
607: . options - options database, use `NULL` for default global database
608: . file - name of file,
609: ".yml" and ".yaml" filename extensions are inserted as YAML options,
610: append ":yaml" to filename to force YAML options.
611: - require - if `PETSC_TRUE` will generate an error if the file does not exist
613: Level: developer
615: Notes:
616: Use # for lines that are comments and which should be ignored.
617: Usually, instead of using this command, one should list the file name in the call to `PetscInitialize()`, this insures that certain options
618: 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
619: calls to `XXXSetFromOptions()`, it should not be used for options listed under PetscInitialize().
620: The collectivity of this routine is complex; only the MPI processes in comm will
621: have the effect of these options. If some processes that create objects call this routine and others do
622: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
623: on different ranks.
625: .seealso: `PetscOptionsSetValue()`, `PetscOptionsView()`, `PetscOptionsHasName()`, `PetscOptionsGetInt()`,
626: `PetscOptionsGetReal()`, `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
627: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
628: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
629: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
630: `PetscOptionsFList()`, `PetscOptionsEList()`
631: @*/
632: PetscErrorCode PetscOptionsInsertFile(MPI_Comm comm, PetscOptions options, const char file[], PetscBool require)
633: {
634: char filename[PETSC_MAX_PATH_LEN];
635: PetscBool yaml;
637: PetscFunctionBegin;
638: PetscCall(PetscOptionsFilename(comm, file, filename, &yaml));
639: if (yaml) {
640: PetscCall(PetscOptionsInsertFileYAML(comm, options, filename, require));
641: } else {
642: PetscCall(PetscOptionsInsertFilePetsc(comm, options, filename, require));
643: }
644: PetscFunctionReturn(PETSC_SUCCESS);
645: }
647: /*@C
648: PetscOptionsInsertArgs - Inserts options into the database from a array of strings
650: Logically Collective
652: Input Parameters:
653: + options - options object
654: . argc - the array length
655: - args - the string array
657: Level: intermediate
659: .seealso: `PetscOptions`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`
660: @*/
661: PetscErrorCode PetscOptionsInsertArgs(PetscOptions options, int argc, const char *const args[])
662: {
663: MPI_Comm comm = PETSC_COMM_WORLD;
664: int left = PetscMax(argc, 0);
665: const char *const *eargs = args;
667: PetscFunctionBegin;
668: while (left) {
669: PetscBool isfile, isfileyaml, isstringyaml, ispush, ispop, key;
670: PetscCall(PetscStrcasecmp(eargs[0], "-options_file", &isfile));
671: PetscCall(PetscStrcasecmp(eargs[0], "-options_file_yaml", &isfileyaml));
672: PetscCall(PetscStrcasecmp(eargs[0], "-options_string_yaml", &isstringyaml));
673: PetscCall(PetscStrcasecmp(eargs[0], "-prefix_push", &ispush));
674: PetscCall(PetscStrcasecmp(eargs[0], "-prefix_pop", &ispop));
675: PetscCall(PetscOptionsValidKey(eargs[0], &key));
676: if (!key) {
677: eargs++;
678: left--;
679: } else if (isfile) {
680: PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file filename option");
681: PetscCall(PetscOptionsInsertFile(comm, options, eargs[1], PETSC_TRUE));
682: eargs += 2;
683: left -= 2;
684: } else if (isfileyaml) {
685: PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing filename for -options_file_yaml filename option");
686: PetscCall(PetscOptionsInsertFileYAML(comm, options, eargs[1], PETSC_TRUE));
687: eargs += 2;
688: left -= 2;
689: } else if (isstringyaml) {
690: PetscCheck(left > 1 && eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing string for -options_string_yaml string option");
691: PetscCall(PetscOptionsInsertStringYAML_Private(options, eargs[1], PETSC_OPT_CODE));
692: eargs += 2;
693: left -= 2;
694: } else if (ispush) {
695: PetscCheck(left > 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option");
696: PetscCheck(eargs[1][0] != '-', PETSC_COMM_SELF, PETSC_ERR_USER, "Missing prefix for -prefix_push option (prefixes cannot start with '-')");
697: PetscCall(PetscOptionsPrefixPush(options, eargs[1]));
698: eargs += 2;
699: left -= 2;
700: } else if (ispop) {
701: PetscCall(PetscOptionsPrefixPop(options));
702: eargs++;
703: left--;
704: } else {
705: PetscBool nextiskey = PETSC_FALSE;
706: if (left >= 2) PetscCall(PetscOptionsValidKey(eargs[1], &nextiskey));
707: if (left < 2 || nextiskey) {
708: PetscCall(PetscOptionsSetValue_Private(options, eargs[0], NULL, NULL, PETSC_OPT_COMMAND_LINE));
709: eargs++;
710: left--;
711: } else {
712: PetscCall(PetscOptionsSetValue_Private(options, eargs[0], eargs[1], NULL, PETSC_OPT_COMMAND_LINE));
713: eargs += 2;
714: left -= 2;
715: }
716: }
717: }
718: PetscFunctionReturn(PETSC_SUCCESS);
719: }
721: static inline PetscErrorCode PetscOptionsStringToBoolIfSet_Private(enum PetscPrecedentOption opt, const char *val[], const PetscBool set[], PetscBool *flg)
722: {
723: PetscFunctionBegin;
724: if (set[opt]) {
725: PetscCall(PetscOptionsStringToBool(val[opt], flg));
726: } else *flg = PETSC_FALSE;
727: PetscFunctionReturn(PETSC_SUCCESS);
728: }
730: /* Process options with absolute precedence, these are only processed from the command line, not the environment or files */
731: static PetscErrorCode PetscOptionsProcessPrecedentFlags(PetscOptions options, int argc, char *args[], PetscBool *skip_petscrc, PetscBool *skip_petscrc_set)
732: {
733: const char *const *opt = precedentOptions;
734: const size_t n = PO_NUM;
735: size_t o;
736: int a;
737: const char **val;
738: char **cval;
739: PetscBool *set, unneeded;
741: PetscFunctionBegin;
742: PetscCall(PetscCalloc2(n, &cval, n, &set));
743: val = (const char **)cval;
745: /* Look for options possibly set using PetscOptionsSetValue beforehand */
746: for (o = 0; o < n; o++) PetscCall(PetscOptionsFindPair(options, NULL, opt[o], &val[o], &set[o]));
748: /* Loop through all args to collect last occurring value of each option */
749: for (a = 1; a < argc; a++) {
750: PetscBool valid, eq;
752: PetscCall(PetscOptionsValidKey(args[a], &valid));
753: if (!valid) continue;
754: for (o = 0; o < n; o++) {
755: PetscCall(PetscStrcasecmp(args[a], opt[o], &eq));
756: if (eq) {
757: set[o] = PETSC_TRUE;
758: if (a == argc - 1 || !args[a + 1] || !args[a + 1][0] || args[a + 1][0] == '-') val[o] = NULL;
759: else val[o] = args[a + 1];
760: break;
761: }
762: }
763: }
765: /* Process flags */
766: PetscCall(PetscStrcasecmp(val[PO_HELP], "intro", &options->help_intro));
767: if (options->help_intro) options->help = PETSC_TRUE;
768: else PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_HELP, val, set, &options->help));
769: PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_CI_ENABLE, val, set, &unneeded));
770: /* need to manage PO_CI_ENABLE option before the PetscOptionsMonitor is turned on, so its setting is not monitored */
771: if (set[PO_CI_ENABLE]) PetscCall(PetscOptionsSetValue_Private(options, opt[PO_CI_ENABLE], val[PO_CI_ENABLE], &a, PETSC_OPT_COMMAND_LINE));
772: PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR_CANCEL, val, set, &options->monitorCancel));
773: PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_OPTIONS_MONITOR, val, set, &options->monitorFromOptions));
774: PetscCall(PetscOptionsStringToBoolIfSet_Private(PO_SKIP_PETSCRC, val, set, skip_petscrc));
775: *skip_petscrc_set = set[PO_SKIP_PETSCRC];
777: /* Store precedent options in database and mark them as used */
778: for (o = 1; o < n; o++) {
779: if (set[o]) {
780: PetscCall(PetscOptionsSetValue_Private(options, opt[o], val[o], &a, PETSC_OPT_COMMAND_LINE));
781: options->used[a] = PETSC_TRUE;
782: }
783: }
784: PetscCall(PetscFree2(cval, set));
785: options->precedentProcessed = PETSC_TRUE;
786: PetscFunctionReturn(PETSC_SUCCESS);
787: }
789: static inline PetscErrorCode PetscOptionsSkipPrecedent(PetscOptions options, const char name[], PetscBool *flg)
790: {
791: PetscFunctionBegin;
792: PetscAssertPointer(flg, 3);
793: *flg = PETSC_FALSE;
794: if (options->precedentProcessed) {
795: for (int i = 0; i < PO_NUM; ++i) {
796: if (!PetscOptNameCmp(precedentOptions[i], name)) {
797: /* check if precedent option has been set already */
798: PetscCall(PetscOptionsFindPair(options, NULL, name, NULL, flg));
799: if (*flg) break;
800: }
801: }
802: }
803: PetscFunctionReturn(PETSC_SUCCESS);
804: }
806: /*@C
807: PetscOptionsInsert - Inserts into the options database from the command line,
808: the environmental variable and a file.
810: Collective on `PETSC_COMM_WORLD`
812: Input Parameters:
813: + options - options database or `NULL` for the default global database
814: . argc - count of number of command line arguments
815: . args - the command line arguments
816: - file - [optional] PETSc database file, append ":yaml" to filename to specify YAML options format.
817: Use `NULL` or empty string to not check for code specific file.
818: Also checks ~/.petscrc, .petscrc and petscrc.
819: Use -skip_petscrc in the code specific file (or command line) to skip ~/.petscrc, .petscrc and petscrc files.
821: Options Database Keys:
822: + -options_file <filename> - read options from a file
823: - -options_file_yaml <filename> - read options from a YAML file
825: Level: advanced
827: Notes:
828: Since `PetscOptionsInsert()` is automatically called by `PetscInitialize()`,
829: the user does not typically need to call this routine. `PetscOptionsInsert()`
830: can be called several times, adding additional entries into the database.
832: See `PetscInitialize()` for options related to option database monitoring.
834: .seealso: `PetscOptionsDestroy()`, `PetscOptionsView()`, `PetscOptionsInsertString()`, `PetscOptionsInsertFile()`,
835: `PetscInitialize()`
836: @*/
837: PetscErrorCode PetscOptionsInsert(PetscOptions options, int *argc, char ***args, const char file[]) PeNS
838: {
839: MPI_Comm comm = PETSC_COMM_WORLD;
840: PetscMPIInt rank;
841: PetscBool hasArgs = (argc && *argc) ? PETSC_TRUE : PETSC_FALSE;
842: PetscBool skipPetscrc = PETSC_FALSE, skipPetscrcSet = PETSC_FALSE;
843: char *eoptions = NULL;
844: size_t len = 0;
846: PetscFunctionBegin;
847: PetscCheck(!hasArgs || (args && *args), comm, PETSC_ERR_ARG_NULL, "*argc > 1 but *args not given");
848: PetscCallMPI(MPI_Comm_rank(comm, &rank));
850: if (!options) {
851: PetscCall(PetscOptionsCreateDefault());
852: options = defaultoptions;
853: }
854: if (hasArgs) {
855: /* process options with absolute precedence */
856: PetscCall(PetscOptionsProcessPrecedentFlags(options, *argc, *args, &skipPetscrc, &skipPetscrcSet));
857: PetscCall(PetscOptionsGetBool(NULL, NULL, "-petsc_ci", &PetscCIEnabled, NULL));
858: }
859: if (file && file[0]) {
860: PetscCall(PetscOptionsInsertFile(comm, options, file, PETSC_TRUE));
861: /* if -skip_petscrc has not been set from command line, check whether it has been set in the file */
862: if (!skipPetscrcSet) PetscCall(PetscOptionsGetBool(options, NULL, "-skip_petscrc", &skipPetscrc, NULL));
863: }
864: if (!skipPetscrc) {
865: char filename[PETSC_MAX_PATH_LEN];
867: PetscCall(PetscGetHomeDirectory(filename, sizeof(filename)));
868: PetscCallMPI(MPI_Bcast(filename, (int)sizeof(filename), MPI_CHAR, 0, comm));
869: if (filename[0]) PetscCall(PetscStrlcat(filename, "/.petscrc", sizeof(filename)));
870: PetscCall(PetscOptionsInsertFile(comm, options, filename, PETSC_FALSE));
871: PetscCall(PetscOptionsInsertFile(comm, options, ".petscrc", PETSC_FALSE));
872: PetscCall(PetscOptionsInsertFile(comm, options, "petscrc", PETSC_FALSE));
873: }
875: /* insert environment options */
876: if (rank == 0) {
877: eoptions = getenv("PETSC_OPTIONS");
878: PetscCall(PetscStrlen(eoptions, &len));
879: }
880: PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, comm));
881: if (len) {
882: if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
883: PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, comm));
884: if (rank) eoptions[len] = 0;
885: PetscCall(PetscOptionsInsertString_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
886: if (rank) PetscCall(PetscFree(eoptions));
887: }
889: /* insert YAML environment options */
890: if (rank == 0) {
891: eoptions = getenv("PETSC_OPTIONS_YAML");
892: PetscCall(PetscStrlen(eoptions, &len));
893: }
894: PetscCallMPI(MPI_Bcast(&len, 1, MPIU_SIZE_T, 0, comm));
895: if (len) {
896: if (rank) PetscCall(PetscMalloc1(len + 1, &eoptions));
897: PetscCallMPI(MPI_Bcast(eoptions, (PetscMPIInt)len, MPI_CHAR, 0, comm));
898: if (rank) eoptions[len] = 0;
899: PetscCall(PetscOptionsInsertStringYAML_Private(options, eoptions, PETSC_OPT_ENVIRONMENT));
900: if (rank) PetscCall(PetscFree(eoptions));
901: }
903: /* insert command line options here because they take precedence over arguments in petscrc/environment */
904: if (hasArgs) PetscCall(PetscOptionsInsertArgs(options, *argc - 1, (const char *const *)*args + 1));
905: PetscCall(PetscOptionsGetBool(NULL, NULL, "-petsc_ci_portable_error_output", &PetscCIEnabledPortableErrorOutput, NULL));
906: PetscFunctionReturn(PETSC_SUCCESS);
907: }
909: /* These options are not printed with PetscOptionsView() or PetscOptionsMonitor() when PetscCIEnabled is on */
910: /* TODO: get the list from the test harness, do not have it hardwired here. Maybe from gmakegentest.py */
911: 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"};
913: static PetscBool PetscCIOption(const char *name)
914: {
915: PetscInt idx;
916: PetscBool found;
918: if (!PetscCIEnabled) return PETSC_FALSE;
919: PetscCallAbort(PETSC_COMM_SELF, PetscEListFind(PETSC_STATIC_ARRAY_LENGTH(PetscCIOptions), PetscCIOptions, name, &idx, &found));
920: return found;
921: }
923: /*@
924: PetscOptionsView - Prints the options that have been loaded. This is
925: useful for debugging purposes.
927: Logically Collective, No Fortran Support
929: Input Parameters:
930: + options - options database, use `NULL` for default global database
931: - viewer - must be an `PETSCVIEWERASCII` viewer
933: Options Database Key:
934: . -options_view - Activates `PetscOptionsView()` within `PetscFinalize()`
936: Level: advanced
938: Note:
939: Only the MPI rank 0 of the `MPI_Comm` used to create view prints the option values. Other processes
940: may have different values but they are not printed.
942: .seealso: `PetscOptionsAllUsed()`
943: @*/
944: PetscErrorCode PetscOptionsView(PetscOptions options, PetscViewer viewer)
945: {
946: PetscInt i, N = 0;
947: PetscBool isascii;
949: PetscFunctionBegin;
951: options = options ? options : defaultoptions;
952: if (!viewer) viewer = PETSC_VIEWER_STDOUT_WORLD;
953: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
954: PetscCheck(isascii, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only supports ASCII viewer");
956: for (i = 0; i < options->N; i++) {
957: if (PetscCIOption(options->names[i])) continue;
958: N++;
959: }
961: if (!N) {
962: PetscCall(PetscViewerASCIIPrintf(viewer, "#No PETSc Option Table entries\n"));
963: PetscFunctionReturn(PETSC_SUCCESS);
964: }
966: PetscCall(PetscViewerASCIIPrintf(viewer, "#PETSc Option Table entries:\n"));
967: for (i = 0; i < options->N; i++) {
968: if (PetscCIOption(options->names[i])) continue;
969: if (options->values[i]) {
970: PetscCall(PetscViewerASCIIPrintf(viewer, "-%s %s", options->names[i], options->values[i]));
971: } else {
972: PetscCall(PetscViewerASCIIPrintf(viewer, "-%s", options->names[i]));
973: }
974: PetscCall(PetscViewerASCIIPrintf(viewer, " # (source: %s)\n", PetscOptionSources[options->source[i]]));
975: }
976: PetscCall(PetscViewerASCIIPrintf(viewer, "#End of PETSc Option Table entries\n"));
977: PetscFunctionReturn(PETSC_SUCCESS);
978: }
980: /*
981: Called by error handlers to print options used in run
982: */
983: PetscErrorCode PetscOptionsLeftError(void)
984: {
985: PetscInt i, nopt = 0;
987: for (i = 0; i < defaultoptions->N; i++) {
988: if (!defaultoptions->used[i]) {
989: if (PetscCIOption(defaultoptions->names[i])) continue;
990: nopt++;
991: }
992: }
993: if (nopt) {
994: PetscCall((*PetscErrorPrintf)("WARNING! There are unused option(s) set! Could be the program crashed before usage or a spelling mistake, etc!\n"));
995: for (i = 0; i < defaultoptions->N; i++) {
996: if (!defaultoptions->used[i]) {
997: if (PetscCIOption(defaultoptions->names[i])) continue;
998: 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]]));
999: else PetscCall((*PetscErrorPrintf)(" Option left: name:-%s (no value) source: %s\n", defaultoptions->names[i], PetscOptionSources[defaultoptions->source[i]]));
1000: }
1001: }
1002: }
1003: return PETSC_SUCCESS;
1004: }
1006: PETSC_EXTERN PetscErrorCode PetscOptionsViewError(void)
1007: {
1008: PetscInt i, N = 0;
1009: PetscOptions options = defaultoptions;
1011: for (i = 0; i < options->N; i++) {
1012: if (PetscCIOption(options->names[i])) continue;
1013: N++;
1014: }
1016: if (N) {
1017: PetscCall((*PetscErrorPrintf)("PETSc Option Table entries:\n"));
1018: } else {
1019: PetscCall((*PetscErrorPrintf)("No PETSc Option Table entries\n"));
1020: }
1021: for (i = 0; i < options->N; i++) {
1022: if (PetscCIOption(options->names[i])) continue;
1023: if (options->values[i]) {
1024: PetscCall((*PetscErrorPrintf)("-%s %s (source: %s)\n", options->names[i], options->values[i], PetscOptionSources[options->source[i]]));
1025: } else {
1026: PetscCall((*PetscErrorPrintf)("-%s (source: %s)\n", options->names[i], PetscOptionSources[options->source[i]]));
1027: }
1028: }
1029: return PETSC_SUCCESS;
1030: }
1032: /*@
1033: PetscOptionsPrefixPush - Designate a prefix to be used by all options insertions to follow.
1035: Logically Collective
1037: Input Parameters:
1038: + options - options database, or `NULL` for the default global database
1039: - prefix - The string to append to the existing prefix
1041: Options Database Keys:
1042: + -prefix_push <some_prefix_> - push the given prefix
1043: - -prefix_pop - pop the last prefix
1045: Level: advanced
1047: Notes:
1048: It is common to use this in conjunction with `-options_file` as in
1049: .vb
1050: -prefix_push system1_ -options_file system1rc -prefix_pop -prefix_push system2_ -options_file system2rc -prefix_pop
1051: .ve
1052: where the files no longer require all options to be prefixed with `-system2_`.
1054: The collectivity of this routine is complex; only the MPI processes that call this routine will
1055: have the affect of these options. If some processes that create objects call this routine and others do
1056: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1057: on different ranks.
1059: .seealso: `PetscOptionsPrefixPop()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1060: @*/
1061: PetscErrorCode PetscOptionsPrefixPush(PetscOptions options, const char prefix[])
1062: {
1063: size_t n;
1064: PetscInt start;
1065: char key[PETSC_MAX_OPTION_NAME + 1];
1066: PetscBool valid;
1068: PetscFunctionBegin;
1069: PetscAssertPointer(prefix, 2);
1070: options = options ? options : defaultoptions;
1071: 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);
1072: key[0] = '-'; /* keys must start with '-' */
1073: PetscCall(PetscStrncpy(key + 1, prefix, sizeof(key) - 1));
1074: PetscCall(PetscOptionsValidKey(key, &valid));
1075: if (!valid && options->prefixind > 0 && isdigit((int)prefix[0])) valid = PETSC_TRUE; /* If the prefix stack is not empty, make numbers a valid prefix */
1076: 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" : "");
1077: start = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1078: PetscCall(PetscStrlen(prefix, &n));
1079: PetscCheck(n + 1 <= sizeof(options->prefix) - start, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Maximum prefix length %zu exceeded", sizeof(options->prefix));
1080: PetscCall(PetscArraycpy(options->prefix + start, prefix, n + 1));
1081: options->prefixstack[options->prefixind++] = (int)(start + n);
1082: PetscFunctionReturn(PETSC_SUCCESS);
1083: }
1085: /*@
1086: PetscOptionsPrefixPop - Remove the latest options prefix, see `PetscOptionsPrefixPush()` for details
1088: Logically Collective on the `MPI_Comm` used when called `PetscOptionsPrefixPush()`
1090: Input Parameter:
1091: . options - options database, or `NULL` for the default global database
1093: Level: advanced
1095: .seealso: `PetscOptionsPrefixPush()`, `PetscOptionsPush()`, `PetscOptionsPop()`, `PetscOptionsCreate()`, `PetscOptionsSetValue()`
1096: @*/
1097: PetscErrorCode PetscOptionsPrefixPop(PetscOptions options)
1098: {
1099: PetscInt offset;
1101: PetscFunctionBegin;
1102: options = options ? options : defaultoptions;
1103: PetscCheck(options->prefixind >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More prefixes popped than pushed");
1104: options->prefixind--;
1105: offset = options->prefixind ? options->prefixstack[options->prefixind - 1] : 0;
1106: options->prefix[offset] = 0;
1107: PetscFunctionReturn(PETSC_SUCCESS);
1108: }
1110: /*@
1111: PetscOptionsClear - Removes all options form the database leaving it empty.
1113: Logically Collective
1115: Input Parameter:
1116: . options - options database, use `NULL` for the default global database
1118: Level: developer
1120: Note:
1121: The collectivity of this routine is complex; only the MPI processes that call this routine will
1122: have the affect of these options. If some processes that create objects call this routine and others do
1123: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1124: on different ranks.
1126: Developer Note:
1127: Uses `free()` directly because the current option values were set with `malloc()`
1129: .seealso: `PetscOptionsInsert()`
1130: @*/
1131: PetscErrorCode PetscOptionsClear(PetscOptions options)
1132: {
1133: PetscInt i;
1135: PetscFunctionBegin;
1136: options = options ? options : defaultoptions;
1137: if (!options) PetscFunctionReturn(PETSC_SUCCESS);
1139: for (i = 0; i < options->N; i++) {
1140: if (options->names[i]) free(options->names[i]);
1141: if (options->values[i]) free(options->values[i]);
1142: }
1143: options->N = 0;
1144: free(options->names);
1145: free(options->values);
1146: free(options->used);
1147: free(options->source);
1148: options->names = NULL;
1149: options->values = NULL;
1150: options->used = NULL;
1151: options->source = NULL;
1152: options->Nalloc = 0;
1154: for (i = 0; i < options->Na; i++) {
1155: free(options->aliases1[i]);
1156: free(options->aliases2[i]);
1157: }
1158: options->Na = 0;
1159: free(options->aliases1);
1160: free(options->aliases2);
1161: options->aliases1 = options->aliases2 = NULL;
1162: options->Naalloc = 0;
1164: /* destroy hash table */
1165: kh_destroy(HO, options->ht);
1166: options->ht = NULL;
1168: options->prefixind = 0;
1169: options->prefix[0] = 0;
1170: options->help = PETSC_FALSE;
1171: options->help_intro = PETSC_FALSE;
1172: PetscFunctionReturn(PETSC_SUCCESS);
1173: }
1175: /*@
1176: PetscOptionsSetAlias - Makes a key and alias for another key
1178: Logically Collective
1180: Input Parameters:
1181: + options - options database, or `NULL` for default global database
1182: . newname - the alias
1183: - oldname - the name that alias will refer to
1185: Level: advanced
1187: Note:
1188: The collectivity of this routine is complex; only the MPI processes that call this routine will
1189: have the affect of these options. If some processes that create objects call this routine and others do
1190: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1191: on different ranks.
1193: Developer Note:
1194: Uses `malloc()` directly because PETSc may not be initialized yet.
1196: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1197: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1198: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1199: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1200: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1201: `PetscOptionsFList()`, `PetscOptionsEList()`
1202: @*/
1203: PetscErrorCode PetscOptionsSetAlias(PetscOptions options, const char newname[], const char oldname[])
1204: {
1205: size_t len;
1206: PetscBool valid;
1208: PetscFunctionBegin;
1209: PetscAssertPointer(newname, 2);
1210: PetscAssertPointer(oldname, 3);
1211: options = options ? options : defaultoptions;
1212: PetscCall(PetscOptionsValidKey(newname, &valid));
1213: PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliased option %s", newname);
1214: PetscCall(PetscOptionsValidKey(oldname, &valid));
1215: PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid aliasee option %s", oldname);
1217: if (options->Na == options->Naalloc) {
1218: char **tmpA1, **tmpA2;
1220: options->Naalloc = PetscMax(4, options->Naalloc * 2);
1221: tmpA1 = (char **)malloc(options->Naalloc * sizeof(char *));
1222: tmpA2 = (char **)malloc(options->Naalloc * sizeof(char *));
1223: for (int i = 0; i < options->Na; ++i) {
1224: tmpA1[i] = options->aliases1[i];
1225: tmpA2[i] = options->aliases2[i];
1226: }
1227: free(options->aliases1);
1228: free(options->aliases2);
1229: options->aliases1 = tmpA1;
1230: options->aliases2 = tmpA2;
1231: }
1232: newname++;
1233: oldname++;
1234: PetscCall(PetscStrlen(newname, &len));
1235: options->aliases1[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1236: PetscCall(PetscStrncpy(options->aliases1[options->Na], newname, len + 1));
1237: PetscCall(PetscStrlen(oldname, &len));
1238: options->aliases2[options->Na] = (char *)malloc((len + 1) * sizeof(char));
1239: PetscCall(PetscStrncpy(options->aliases2[options->Na], oldname, len + 1));
1240: ++options->Na;
1241: PetscFunctionReturn(PETSC_SUCCESS);
1242: }
1244: /*@
1245: PetscOptionsSetValue - Sets an option name-value pair in the options
1246: database, overriding whatever is already present.
1248: Logically Collective
1250: Input Parameters:
1251: + options - options database, use `NULL` for the default global database
1252: . name - name of option, this SHOULD have the - prepended
1253: - value - the option value (not used for all options, so can be `NULL`)
1255: Level: intermediate
1257: Note:
1258: This function can be called BEFORE `PetscInitialize()`
1260: The collectivity of this routine is complex; only the MPI processes that call this routine will
1261: have the affect of these options. If some processes that create objects call this routine and others do
1262: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1263: on different ranks.
1265: Developer Note:
1266: Uses `malloc()` directly because PETSc may not be initialized yet.
1268: .seealso: `PetscOptionsInsert()`, `PetscOptionsClearValue()`
1269: @*/
1270: PetscErrorCode PetscOptionsSetValue(PetscOptions options, const char name[], const char value[])
1271: {
1272: PetscFunctionBegin;
1273: PetscCall(PetscOptionsSetValue_Private(options, name, value, NULL, PETSC_OPT_CODE));
1274: PetscFunctionReturn(PETSC_SUCCESS);
1275: }
1277: PetscErrorCode PetscOptionsSetValue_Private(PetscOptions options, const char name[], const char value[], int *pos, PetscOptionSource source)
1278: {
1279: size_t len;
1280: int n, i;
1281: char **names;
1282: char fullname[PETSC_MAX_OPTION_NAME] = "";
1283: PetscBool flg;
1285: PetscFunctionBegin;
1286: if (!options) {
1287: PetscCall(PetscOptionsCreateDefault());
1288: options = defaultoptions;
1289: }
1290: PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "name %s must start with '-'", name);
1292: PetscCall(PetscOptionsSkipPrecedent(options, name, &flg));
1293: if (flg) PetscFunctionReturn(PETSC_SUCCESS);
1295: name++; /* skip starting dash */
1297: if (options->prefixind > 0) {
1298: strncpy(fullname, options->prefix, sizeof(fullname));
1299: fullname[sizeof(fullname) - 1] = 0;
1300: strncat(fullname, name, sizeof(fullname) - strlen(fullname) - 1);
1301: fullname[sizeof(fullname) - 1] = 0;
1302: name = fullname;
1303: }
1305: /* check against aliases */
1306: for (i = 0; i < options->Na; i++) {
1307: int result = PetscOptNameCmp(options->aliases1[i], name);
1308: if (!result) {
1309: name = options->aliases2[i];
1310: break;
1311: }
1312: }
1314: /* slow search */
1315: n = options->N;
1316: names = options->names;
1317: for (i = 0; i < options->N; i++) {
1318: int result = PetscOptNameCmp(names[i], name);
1319: if (!result) {
1320: n = i;
1321: goto setvalue;
1322: } else if (result > 0) {
1323: n = i;
1324: break;
1325: }
1326: }
1327: if (options->N == options->Nalloc) {
1328: char **names, **values;
1329: PetscBool *used;
1330: PetscOptionSource *source;
1332: options->Nalloc = PetscMax(10, options->Nalloc * 2);
1333: names = (char **)malloc(options->Nalloc * sizeof(char *));
1334: values = (char **)malloc(options->Nalloc * sizeof(char *));
1335: used = (PetscBool *)malloc(options->Nalloc * sizeof(PetscBool));
1336: source = (PetscOptionSource *)malloc(options->Nalloc * sizeof(PetscOptionSource));
1337: for (int i = 0; i < options->N; ++i) {
1338: names[i] = options->names[i];
1339: values[i] = options->values[i];
1340: used[i] = options->used[i];
1341: source[i] = options->source[i];
1342: }
1343: free(options->names);
1344: free(options->values);
1345: free(options->used);
1346: free(options->source);
1347: options->names = names;
1348: options->values = values;
1349: options->used = used;
1350: options->source = source;
1351: }
1353: /* shift remaining values up 1 */
1354: for (i = options->N; i > n; i--) {
1355: options->names[i] = options->names[i - 1];
1356: options->values[i] = options->values[i - 1];
1357: options->used[i] = options->used[i - 1];
1358: options->source[i] = options->source[i - 1];
1359: }
1360: options->names[n] = NULL;
1361: options->values[n] = NULL;
1362: options->used[n] = PETSC_FALSE;
1363: options->source[n] = PETSC_OPT_CODE;
1364: options->N++;
1366: /* destroy hash table */
1367: kh_destroy(HO, options->ht);
1368: options->ht = NULL;
1370: /* set new name */
1371: len = strlen(name);
1372: options->names[n] = (char *)malloc((len + 1) * sizeof(char));
1373: PetscCheck(options->names[n], PETSC_COMM_SELF, PETSC_ERR_MEM, "Failed to allocate option name");
1374: strcpy(options->names[n], name);
1376: setvalue:
1377: /* set new value */
1378: if (options->values[n]) free(options->values[n]);
1379: len = value ? strlen(value) : 0;
1380: if (len) {
1381: options->values[n] = (char *)malloc((len + 1) * sizeof(char));
1382: if (!options->values[n]) return PETSC_ERR_MEM;
1383: strcpy(options->values[n], value);
1384: options->values[n][len] = '\0';
1385: } else {
1386: options->values[n] = NULL;
1387: }
1388: options->source[n] = source;
1390: /* handle -help so that it can be set from anywhere */
1391: if (!PetscOptNameCmp(name, "help")) {
1392: options->help = PETSC_TRUE;
1393: options->help_intro = (value && !PetscOptNameCmp(value, "intro")) ? PETSC_TRUE : PETSC_FALSE;
1394: options->used[n] = PETSC_TRUE;
1395: }
1397: PetscCall(PetscOptionsMonitor(options, name, value ? value : "", source));
1398: if (pos) *pos = n;
1399: PetscFunctionReturn(PETSC_SUCCESS);
1400: }
1402: /*@
1403: PetscOptionsClearValue - Clears an option name-value pair in the options
1404: database, overriding whatever is already present.
1406: Logically Collective
1408: Input Parameters:
1409: + options - options database, use `NULL` for the default global database
1410: - name - name of option, this SHOULD have the - prepended
1412: Level: intermediate
1414: Note:
1415: The collectivity of this routine is complex; only the MPI processes that call this routine will
1416: have the affect of these options. If some processes that create objects call this routine and others do
1417: not the code may fail in complicated ways because the same parallel solvers may incorrectly use different options
1418: on different ranks.
1420: Developer Note:
1421: Uses `free()` directly because the options have been set with `malloc()`
1423: .seealso: `PetscOptionsInsert()`
1424: @*/
1425: PetscErrorCode PetscOptionsClearValue(PetscOptions options, const char name[])
1426: {
1427: int N, n, i;
1428: char **names;
1430: PetscFunctionBegin;
1431: options = options ? options : defaultoptions;
1432: PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1433: if (!PetscOptNameCmp(name, "-help")) options->help = options->help_intro = PETSC_FALSE;
1435: name++; /* skip starting dash */
1437: /* slow search */
1438: N = n = options->N;
1439: names = options->names;
1440: for (i = 0; i < N; i++) {
1441: int result = PetscOptNameCmp(names[i], name);
1442: if (!result) {
1443: n = i;
1444: break;
1445: } else if (result > 0) {
1446: n = N;
1447: break;
1448: }
1449: }
1450: if (n == N) PetscFunctionReturn(PETSC_SUCCESS); /* it was not present */
1452: /* remove name and value */
1453: if (options->names[n]) free(options->names[n]);
1454: if (options->values[n]) free(options->values[n]);
1455: /* shift remaining values down 1 */
1456: for (i = n; i < N - 1; i++) {
1457: options->names[i] = options->names[i + 1];
1458: options->values[i] = options->values[i + 1];
1459: options->used[i] = options->used[i + 1];
1460: options->source[i] = options->source[i + 1];
1461: }
1462: options->N--;
1464: /* destroy hash table */
1465: kh_destroy(HO, options->ht);
1466: options->ht = NULL;
1468: PetscCall(PetscOptionsMonitor(options, name, NULL, PETSC_OPT_CODE));
1469: PetscFunctionReturn(PETSC_SUCCESS);
1470: }
1472: /*@C
1473: PetscOptionsFindPair - Gets an option name-value pair from the options database.
1475: Not Collective
1477: Input Parameters:
1478: + options - options database, use `NULL` for the default global database
1479: . pre - the string to prepend to the name or `NULL`, this SHOULD NOT have the "-" prepended
1480: - name - name of option, this SHOULD have the "-" prepended
1482: Output Parameters:
1483: + value - the option value (optional, not used for all options)
1484: - set - whether the option is set (optional)
1486: Level: developer
1488: Note:
1489: Each process may find different values or no value depending on how options were inserted into the database
1491: .seealso: `PetscOptionsSetValue()`, `PetscOptionsClearValue()`
1492: @*/
1493: PetscErrorCode PetscOptionsFindPair(PetscOptions options, const char pre[], const char name[], const char *value[], PetscBool *set)
1494: {
1495: char buf[PETSC_MAX_OPTION_NAME];
1496: PetscBool matchnumbers = PETSC_TRUE;
1498: PetscFunctionBegin;
1499: if (!options) {
1500: PetscCall(PetscOptionsCreateDefault());
1501: options = defaultoptions;
1502: }
1503: PetscCheck(!pre || !PetscUnlikely(pre[0] == '-'), PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1504: PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1506: name++; /* skip starting dash */
1508: /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1509: if (pre && pre[0]) {
1510: char *ptr = buf;
1511: if (name[0] == '-') {
1512: *ptr++ = '-';
1513: name++;
1514: }
1515: PetscCall(PetscStrncpy(ptr, pre, buf + sizeof(buf) - ptr));
1516: PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1517: name = buf;
1518: }
1520: if (PetscDefined(USE_DEBUG)) {
1521: PetscBool valid;
1522: char key[PETSC_MAX_OPTION_NAME + 1] = "-";
1523: PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1524: PetscCall(PetscOptionsValidKey(key, &valid));
1525: PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1526: }
1528: if (!options->ht) {
1529: int i, ret;
1530: khiter_t it;
1531: khash_t(HO) *ht;
1532: ht = kh_init(HO);
1533: PetscCheck(ht, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1534: ret = kh_resize(HO, ht, options->N * 2); /* twice the required size to reduce risk of collisions */
1535: PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1536: for (i = 0; i < options->N; i++) {
1537: it = kh_put(HO, ht, options->names[i], &ret);
1538: PetscCheck(ret == 1, PETSC_COMM_SELF, PETSC_ERR_MEM, "Hash table allocation failed");
1539: kh_val(ht, it) = i;
1540: }
1541: options->ht = ht;
1542: }
1544: khash_t(HO) *ht = options->ht;
1545: khiter_t it = kh_get(HO, ht, name);
1546: if (it != kh_end(ht)) {
1547: int i = kh_val(ht, it);
1548: options->used[i] = PETSC_TRUE;
1549: if (value) *value = options->values[i];
1550: if (set) *set = PETSC_TRUE;
1551: PetscFunctionReturn(PETSC_SUCCESS);
1552: }
1554: /*
1555: The following block slows down all lookups in the most frequent path (most lookups are unsuccessful).
1556: Maybe this special lookup mode should be enabled on request with a push/pop API.
1557: The feature of matching _%d_ used sparingly in the codebase.
1558: */
1559: if (matchnumbers) {
1560: int i, j, cnt = 0, locs[16], loce[16];
1561: /* determine the location and number of all _%d_ in the key */
1562: for (i = 0; name[i]; i++) {
1563: if (name[i] == '_') {
1564: for (j = i + 1; name[j]; j++) {
1565: if (name[j] >= '0' && name[j] <= '9') continue;
1566: if (name[j] == '_' && j > i + 1) { /* found a number */
1567: locs[cnt] = i + 1;
1568: loce[cnt++] = j + 1;
1569: }
1570: i = j - 1;
1571: break;
1572: }
1573: }
1574: }
1575: for (i = 0; i < cnt; i++) {
1576: PetscBool found;
1577: char opt[PETSC_MAX_OPTION_NAME + 1] = "-", tmp[PETSC_MAX_OPTION_NAME];
1578: PetscCall(PetscStrncpy(tmp, name, PetscMin((size_t)(locs[i] + 1), sizeof(tmp))));
1579: PetscCall(PetscStrlcat(opt, tmp, sizeof(opt)));
1580: PetscCall(PetscStrlcat(opt, name + loce[i], sizeof(opt)));
1581: PetscCall(PetscOptionsFindPair(options, NULL, opt, value, &found));
1582: if (found) {
1583: if (set) *set = PETSC_TRUE;
1584: PetscFunctionReturn(PETSC_SUCCESS);
1585: }
1586: }
1587: }
1589: if (set) *set = PETSC_FALSE;
1590: PetscFunctionReturn(PETSC_SUCCESS);
1591: }
1593: /* Check whether any option begins with pre+name */
1594: PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions options, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *set)
1595: {
1596: char buf[PETSC_MAX_OPTION_NAME];
1597: int numCnt = 0, locs[16], loce[16];
1599: PetscFunctionBegin;
1600: options = options ? options : defaultoptions;
1601: PetscCheck(!pre || pre[0] != '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Prefix cannot begin with '-': Instead %s", pre);
1602: PetscCheck(name[0] == '-', PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Name must begin with '-': Instead %s", name);
1604: name++; /* skip starting dash */
1606: /* append prefix to name, if prefix="foo_" and option='--bar", prefixed option is --foo_bar */
1607: if (pre && pre[0]) {
1608: char *ptr = buf;
1609: if (name[0] == '-') {
1610: *ptr++ = '-';
1611: name++;
1612: }
1613: PetscCall(PetscStrncpy(ptr, pre, sizeof(buf) - ((ptr == buf) ? 0 : 1)));
1614: PetscCall(PetscStrlcat(buf, name, sizeof(buf)));
1615: name = buf;
1616: }
1618: if (PetscDefined(USE_DEBUG)) {
1619: PetscBool valid;
1620: char key[PETSC_MAX_OPTION_NAME + 1] = "-";
1621: PetscCall(PetscStrncpy(key + 1, name, sizeof(key) - 1));
1622: PetscCall(PetscOptionsValidKey(key, &valid));
1623: PetscCheck(valid, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid option '%s' obtained from pre='%s' and name='%s'", key, pre ? pre : "", name);
1624: }
1626: /* determine the location and number of all _%d_ in the key */
1627: {
1628: int i, j;
1629: for (i = 0; name[i]; i++) {
1630: if (name[i] == '_') {
1631: for (j = i + 1; name[j]; j++) {
1632: if (name[j] >= '0' && name[j] <= '9') continue;
1633: if (name[j] == '_' && j > i + 1) { /* found a number */
1634: locs[numCnt] = i + 1;
1635: loce[numCnt++] = j + 1;
1636: }
1637: i = j - 1;
1638: break;
1639: }
1640: }
1641: }
1642: }
1644: /* slow search */
1645: for (int c = -1; c < numCnt; ++c) {
1646: char opt[PETSC_MAX_OPTION_NAME + 2] = "";
1647: size_t len;
1649: if (c < 0) {
1650: PetscCall(PetscStrncpy(opt, name, sizeof(opt)));
1651: } else {
1652: PetscCall(PetscStrncpy(opt, name, PetscMin((size_t)(locs[c] + 1), sizeof(opt))));
1653: PetscCall(PetscStrlcat(opt, name + loce[c], sizeof(opt) - 1));
1654: }
1655: PetscCall(PetscStrlen(opt, &len));
1656: for (int i = 0; i < options->N; i++) {
1657: PetscBool match;
1659: PetscCall(PetscStrncmp(options->names[i], opt, len, &match));
1660: if (match) {
1661: options->used[i] = PETSC_TRUE;
1662: if (option) *option = options->names[i];
1663: if (value) *value = options->values[i];
1664: if (set) *set = PETSC_TRUE;
1665: PetscFunctionReturn(PETSC_SUCCESS);
1666: }
1667: }
1668: }
1670: if (set) *set = PETSC_FALSE;
1671: PetscFunctionReturn(PETSC_SUCCESS);
1672: }
1674: /*@
1675: PetscOptionsReject - Generates an error if a certain option is given.
1677: Not Collective
1679: Input Parameters:
1680: + options - options database, use `NULL` for default global database
1681: . pre - the option prefix (may be `NULL`)
1682: . name - the option name one is seeking
1683: - mess - error message (may be `NULL`)
1685: Level: advanced
1687: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`,
1688: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1689: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1690: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1691: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1692: `PetscOptionsFList()`, `PetscOptionsEList()`
1693: @*/
1694: PetscErrorCode PetscOptionsReject(PetscOptions options, const char pre[], const char name[], const char mess[])
1695: {
1696: PetscBool flag = PETSC_FALSE;
1698: PetscFunctionBegin;
1699: PetscCall(PetscOptionsHasName(options, pre, name, &flag));
1700: if (flag) {
1701: PetscCheck(!mess || !mess[0], PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s with %s", pre ? pre : "", name + 1, mess);
1702: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Program has disabled option: -%s%s", pre ? pre : "", name + 1);
1703: }
1704: PetscFunctionReturn(PETSC_SUCCESS);
1705: }
1707: /*@
1708: PetscOptionsHasHelp - Determines whether the "-help" option is in the database.
1710: Not Collective
1712: Input Parameter:
1713: . options - options database, use `NULL` for default global database
1715: Output Parameter:
1716: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.
1718: Level: advanced
1720: .seealso: `PetscOptionsHasName()`
1721: @*/
1722: PetscErrorCode PetscOptionsHasHelp(PetscOptions options, PetscBool *set)
1723: {
1724: PetscFunctionBegin;
1725: PetscAssertPointer(set, 2);
1726: options = options ? options : defaultoptions;
1727: *set = options->help;
1728: PetscFunctionReturn(PETSC_SUCCESS);
1729: }
1731: PetscErrorCode PetscOptionsHasHelpIntro_Internal(PetscOptions options, PetscBool *set)
1732: {
1733: PetscFunctionBegin;
1734: PetscAssertPointer(set, 2);
1735: options = options ? options : defaultoptions;
1736: *set = options->help_intro;
1737: PetscFunctionReturn(PETSC_SUCCESS);
1738: }
1740: /*@
1741: PetscOptionsHasName - Determines whether a certain option is given in the database. This returns true whether the option is a number, string or Boolean, even
1742: if its value is set to false.
1744: Not Collective
1746: Input Parameters:
1747: + options - options database, use `NULL` for default global database
1748: . pre - string to prepend to the name or `NULL`
1749: - name - the option one is seeking
1751: Output Parameter:
1752: . set - `PETSC_TRUE` if found else `PETSC_FALSE`.
1754: Level: beginner
1756: Note:
1757: In many cases you probably want to use `PetscOptionsGetBool()` instead of calling this, to allowing toggling values.
1759: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1760: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1761: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1762: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1763: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1764: `PetscOptionsFList()`, `PetscOptionsEList()`
1765: @*/
1766: PetscErrorCode PetscOptionsHasName(PetscOptions options, const char pre[], const char name[], PetscBool *set)
1767: {
1768: const char *value;
1769: PetscBool flag;
1771: PetscFunctionBegin;
1772: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
1773: if (set) *set = flag;
1774: PetscFunctionReturn(PETSC_SUCCESS);
1775: }
1777: /*@C
1778: PetscOptionsGetAll - Lists all the options the program was run with in a single string.
1780: Not Collective
1782: Input Parameter:
1783: . options - the options database, use `NULL` for the default global database
1785: Output Parameter:
1786: . copts - pointer where string pointer is stored
1788: Level: advanced
1790: Notes:
1791: The array and each entry in the array should be freed with `PetscFree()`
1793: Each process may have different values depending on how the options were inserted into the database
1795: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsView()`, `PetscOptionsPush()`, `PetscOptionsPop()`
1796: @*/
1797: PetscErrorCode PetscOptionsGetAll(PetscOptions options, char *copts[]) PeNS
1798: {
1799: PetscInt i;
1800: size_t len = 1, lent = 0;
1801: char *coptions = NULL;
1803: PetscFunctionBegin;
1804: PetscAssertPointer(copts, 2);
1805: options = options ? options : defaultoptions;
1806: /* count the length of the required string */
1807: for (i = 0; i < options->N; i++) {
1808: PetscCall(PetscStrlen(options->names[i], &lent));
1809: len += 2 + lent;
1810: if (options->values[i]) {
1811: PetscCall(PetscStrlen(options->values[i], &lent));
1812: len += 1 + lent;
1813: }
1814: }
1815: PetscCall(PetscMalloc1(len, &coptions));
1816: coptions[0] = 0;
1817: for (i = 0; i < options->N; i++) {
1818: PetscCall(PetscStrlcat(coptions, "-", len));
1819: PetscCall(PetscStrlcat(coptions, options->names[i], len));
1820: PetscCall(PetscStrlcat(coptions, " ", len));
1821: if (options->values[i]) {
1822: PetscCall(PetscStrlcat(coptions, options->values[i], len));
1823: PetscCall(PetscStrlcat(coptions, " ", len));
1824: }
1825: }
1826: *copts = coptions;
1827: PetscFunctionReturn(PETSC_SUCCESS);
1828: }
1830: /*@
1831: PetscOptionsUsed - Indicates if PETSc has used a particular option set in the database
1833: Not Collective
1835: Input Parameters:
1836: + options - options database, use `NULL` for default global database
1837: - name - string name of option
1839: Output Parameter:
1840: . used - `PETSC_TRUE` if the option was used, otherwise false, including if option was not found in options database
1842: Level: advanced
1844: Note:
1845: The value returned may be different on each process and depends on which options have been processed
1846: on the given process
1848: .seealso: `PetscOptionsView()`, `PetscOptionsLeft()`, `PetscOptionsAllUsed()`
1849: @*/
1850: PetscErrorCode PetscOptionsUsed(PetscOptions options, const char *name, PetscBool *used)
1851: {
1852: PetscInt i;
1854: PetscFunctionBegin;
1855: PetscAssertPointer(name, 2);
1856: PetscAssertPointer(used, 3);
1857: options = options ? options : defaultoptions;
1858: *used = PETSC_FALSE;
1859: for (i = 0; i < options->N; i++) {
1860: PetscCall(PetscStrcasecmp(options->names[i], name, used));
1861: if (*used) {
1862: *used = options->used[i];
1863: break;
1864: }
1865: }
1866: PetscFunctionReturn(PETSC_SUCCESS);
1867: }
1869: /*@
1870: PetscOptionsAllUsed - Returns a count of the number of options in the
1871: database that have never been selected.
1873: Not Collective
1875: Input Parameter:
1876: . options - options database, use `NULL` for default global database
1878: Output Parameter:
1879: . N - count of options not used
1881: Level: advanced
1883: Note:
1884: The value returned may be different on each process and depends on which options have been processed
1885: on the given process
1887: .seealso: `PetscOptionsView()`
1888: @*/
1889: PetscErrorCode PetscOptionsAllUsed(PetscOptions options, PetscInt *N)
1890: {
1891: PetscInt i, n = 0;
1893: PetscFunctionBegin;
1894: PetscAssertPointer(N, 2);
1895: options = options ? options : defaultoptions;
1896: for (i = 0; i < options->N; i++) {
1897: if (!options->used[i]) n++;
1898: }
1899: *N = n;
1900: PetscFunctionReturn(PETSC_SUCCESS);
1901: }
1903: /*@
1904: PetscOptionsLeft - Prints to screen any options that were set and never used.
1906: Not Collective
1908: Input Parameter:
1909: . options - options database; use `NULL` for default global database
1911: Options Database Key:
1912: . -options_left - activates `PetscOptionsAllUsed()` within `PetscFinalize()`
1914: Level: advanced
1916: Notes:
1917: This is rarely used directly, it is called by `PetscFinalize()` in debug more or if -options_left
1918: is passed otherwise to help users determine possible mistakes in their usage of options. This
1919: only prints values on process zero of `PETSC_COMM_WORLD`.
1921: Other processes depending the objects
1922: used may have different options that are left unused.
1924: .seealso: `PetscOptionsAllUsed()`
1925: @*/
1926: PetscErrorCode PetscOptionsLeft(PetscOptions options)
1927: {
1928: PetscInt i;
1929: PetscInt cnt = 0;
1930: PetscOptions toptions;
1932: PetscFunctionBegin;
1933: toptions = options ? options : defaultoptions;
1934: for (i = 0; i < toptions->N; i++) {
1935: if (!toptions->used[i]) {
1936: if (PetscCIOption(toptions->names[i])) continue;
1937: if (toptions->values[i]) {
1938: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s value: %s source: %s\n", toptions->names[i], toptions->values[i], PetscOptionSources[toptions->source[i]]));
1939: } else {
1940: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Option left: name:-%s (no value) source: %s\n", toptions->names[i], PetscOptionSources[toptions->source[i]]));
1941: }
1942: }
1943: }
1944: if (!options) {
1945: toptions = defaultoptions;
1946: while (toptions->previous) {
1947: cnt++;
1948: toptions = toptions->previous;
1949: }
1950: 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));
1951: }
1952: PetscFunctionReturn(PETSC_SUCCESS);
1953: }
1955: /*@C
1956: PetscOptionsLeftGet - Returns all options that were set and never used.
1958: Not Collective
1960: Input Parameter:
1961: . options - options database, use `NULL` for default global database
1963: Output Parameters:
1964: + N - count of options not used
1965: . names - names of options not used
1966: - values - values of options not used
1968: Level: advanced
1970: Notes:
1971: Users should call `PetscOptionsLeftRestore()` to free the memory allocated in this routine
1973: The value returned may be different on each process and depends on which options have been processed
1974: on the given process
1976: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`
1977: @*/
1978: PetscErrorCode PetscOptionsLeftGet(PetscOptions options, PetscInt *N, char **names[], char **values[])
1979: {
1980: PetscInt i, n;
1982: PetscFunctionBegin;
1983: if (N) PetscAssertPointer(N, 2);
1984: if (names) PetscAssertPointer(names, 3);
1985: if (values) PetscAssertPointer(values, 4);
1986: options = options ? options : defaultoptions;
1988: /* The number of unused PETSc options */
1989: n = 0;
1990: for (i = 0; i < options->N; i++) {
1991: if (PetscCIOption(options->names[i])) continue;
1992: if (!options->used[i]) n++;
1993: }
1994: if (N) *N = n;
1995: if (names) PetscCall(PetscMalloc1(n, names));
1996: if (values) PetscCall(PetscMalloc1(n, values));
1998: n = 0;
1999: if (names || values) {
2000: for (i = 0; i < options->N; i++) {
2001: if (!options->used[i]) {
2002: if (PetscCIOption(options->names[i])) continue;
2003: if (names) (*names)[n] = options->names[i];
2004: if (values) (*values)[n] = options->values[i];
2005: n++;
2006: }
2007: }
2008: }
2009: PetscFunctionReturn(PETSC_SUCCESS);
2010: }
2012: /*@C
2013: PetscOptionsLeftRestore - Free memory for the unused PETSc options obtained using `PetscOptionsLeftGet()`.
2015: Not Collective
2017: Input Parameters:
2018: + options - options database, use `NULL` for default global database
2019: . N - count of options not used
2020: . names - names of options not used
2021: - values - values of options not used
2023: Level: advanced
2025: Notes:
2026: The user should pass the same pointer to `N` as they did when calling `PetscOptionsLeftGet()`
2028: .seealso: `PetscOptionsAllUsed()`, `PetscOptionsLeft()`, `PetscOptionsLeftGet()`
2029: @*/
2030: PetscErrorCode PetscOptionsLeftRestore(PetscOptions options, PetscInt *N, char **names[], char **values[])
2031: {
2032: PetscFunctionBegin;
2033: (void)options;
2034: if (N) PetscAssertPointer(N, 2);
2035: if (names) PetscAssertPointer(names, 3);
2036: if (values) PetscAssertPointer(values, 4);
2037: if (N) *N = 0;
2038: if (names) PetscCall(PetscFree(*names));
2039: if (values) PetscCall(PetscFree(*values));
2040: PetscFunctionReturn(PETSC_SUCCESS);
2041: }
2043: /*@C
2044: PetscOptionsMonitorDefault - Print all options set value events using the supplied `PetscViewer`.
2046: Logically Collective
2048: Input Parameters:
2049: + name - option name string
2050: . value - option value string
2051: . source - The source for the option
2052: - ctx - a `PETSCVIEWERASCII` or `NULL`
2054: Level: intermediate
2056: Notes:
2057: If ctx is `NULL`, `PetscPrintf()` is used.
2058: The first MPI process in the `PetscViewer` viewer actually prints the values, other
2059: processes may have different values set
2061: If `PetscCIEnabled` then do not print the test harness options
2063: .seealso: `PetscOptionsMonitorSet()`
2064: @*/
2065: PetscErrorCode PetscOptionsMonitorDefault(const char name[], const char value[], PetscOptionSource source, void *ctx)
2066: {
2067: PetscFunctionBegin;
2068: if (PetscCIOption(name)) PetscFunctionReturn(PETSC_SUCCESS);
2070: if (ctx) {
2071: PetscViewer viewer = (PetscViewer)ctx;
2072: if (!value) {
2073: PetscCall(PetscViewerASCIIPrintf(viewer, "Removing option: %s\n", name));
2074: } else if (!value[0]) {
2075: PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2076: } else {
2077: PetscCall(PetscViewerASCIIPrintf(viewer, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2078: }
2079: } else {
2080: MPI_Comm comm = PETSC_COMM_WORLD;
2081: if (!value) {
2082: PetscCall(PetscPrintf(comm, "Removing option: %s\n", name));
2083: } else if (!value[0]) {
2084: PetscCall(PetscPrintf(comm, "Setting option: %s (no value) (source: %s)\n", name, PetscOptionSources[source]));
2085: } else {
2086: PetscCall(PetscPrintf(comm, "Setting option: %s = %s (source: %s)\n", name, value, PetscOptionSources[source]));
2087: }
2088: }
2089: PetscFunctionReturn(PETSC_SUCCESS);
2090: }
2092: /*@C
2093: PetscOptionsMonitorSet - Sets an ADDITIONAL function to be called at every method that
2094: modified the PETSc options database.
2096: Not Collective
2098: Input Parameters:
2099: + monitor - pointer to function (if this is `NULL`, it turns off monitoring
2100: . mctx - [optional] context for private data for the monitor routine (use `NULL` if
2101: no context is desired)
2102: - monitordestroy - [optional] routine that frees monitor context (may be `NULL`), see `PetscCtxDestroyFn` for its calling sequence
2104: Calling sequence of `monitor`:
2105: + name - option name string
2106: . value - option value string, a value of `NULL` indicates the option is being removed from the database. A value
2107: of "" indicates the option is in the database but has no value.
2108: . source - option source
2109: - mctx - optional monitoring context, as set by `PetscOptionsMonitorSet()`
2111: Options Database Keys:
2112: + -options_monitor <viewer> - turn on default monitoring of changes to the options database
2113: - -options_monitor_cancel - turn off any option monitors except the default monitor obtained with `-options_monitor`
2115: Level: intermediate
2117: Notes:
2118: See `PetscInitialize()` for options related to option database monitoring.
2120: The default is to do no monitoring. To print the name and value of options
2121: being inserted into the database, use `PetscOptionsMonitorDefault()` as the monitoring routine,
2122: with a `NULL` monitoring context. Or use the option `-options_monitor` <viewer>.
2124: Several different monitoring routines may be set by calling
2125: `PetscOptionsMonitorSet()` multiple times; all will be called in the
2126: order in which they were set.
2128: .seealso: `PetscOptionsMonitorDefault()`, `PetscInitialize()`, `PetscCtxDestroyFn`
2129: @*/
2130: PetscErrorCode PetscOptionsMonitorSet(PetscErrorCode (*monitor)(const char name[], const char value[], PetscOptionSource source, void *mctx), void *mctx, PetscCtxDestroyFn *monitordestroy)
2131: {
2132: PetscOptions options = defaultoptions;
2134: PetscFunctionBegin;
2135: if (options->monitorCancel) PetscFunctionReturn(PETSC_SUCCESS);
2136: PetscCheck(options->numbermonitors < MAXOPTIONSMONITORS, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Too many PetscOptions monitors set");
2137: options->monitor[options->numbermonitors] = monitor;
2138: options->monitordestroy[options->numbermonitors] = monitordestroy;
2139: options->monitorcontext[options->numbermonitors++] = mctx;
2140: PetscFunctionReturn(PETSC_SUCCESS);
2141: }
2143: /*
2144: PetscOptionsStringToBool - Converts string to PetscBool, handles cases like "yes", "no", "true", "false", "0", "1", "off", "on".
2145: Empty string is considered as true.
2146: */
2147: PetscErrorCode PetscOptionsStringToBool(const char value[], PetscBool *a)
2148: {
2149: PetscBool istrue, isfalse;
2150: size_t len;
2152: PetscFunctionBegin;
2153: /* PetscStrlen() returns 0 for NULL or "" */
2154: PetscCall(PetscStrlen(value, &len));
2155: if (!len) {
2156: *a = PETSC_TRUE;
2157: PetscFunctionReturn(PETSC_SUCCESS);
2158: }
2159: PetscCall(PetscStrcasecmp(value, "TRUE", &istrue));
2160: if (istrue) {
2161: *a = PETSC_TRUE;
2162: PetscFunctionReturn(PETSC_SUCCESS);
2163: }
2164: PetscCall(PetscStrcasecmp(value, "YES", &istrue));
2165: if (istrue) {
2166: *a = PETSC_TRUE;
2167: PetscFunctionReturn(PETSC_SUCCESS);
2168: }
2169: PetscCall(PetscStrcasecmp(value, "1", &istrue));
2170: if (istrue) {
2171: *a = PETSC_TRUE;
2172: PetscFunctionReturn(PETSC_SUCCESS);
2173: }
2174: PetscCall(PetscStrcasecmp(value, "on", &istrue));
2175: if (istrue) {
2176: *a = PETSC_TRUE;
2177: PetscFunctionReturn(PETSC_SUCCESS);
2178: }
2179: PetscCall(PetscStrcasecmp(value, "FALSE", &isfalse));
2180: if (isfalse) {
2181: *a = PETSC_FALSE;
2182: PetscFunctionReturn(PETSC_SUCCESS);
2183: }
2184: PetscCall(PetscStrcasecmp(value, "NO", &isfalse));
2185: if (isfalse) {
2186: *a = PETSC_FALSE;
2187: PetscFunctionReturn(PETSC_SUCCESS);
2188: }
2189: PetscCall(PetscStrcasecmp(value, "0", &isfalse));
2190: if (isfalse) {
2191: *a = PETSC_FALSE;
2192: PetscFunctionReturn(PETSC_SUCCESS);
2193: }
2194: PetscCall(PetscStrcasecmp(value, "off", &isfalse));
2195: if (isfalse) {
2196: *a = PETSC_FALSE;
2197: PetscFunctionReturn(PETSC_SUCCESS);
2198: }
2199: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unknown logical value: %s", value);
2200: }
2202: /*
2203: PetscOptionsStringToInt - Converts a string to an integer value. Handles special cases such as "default" and "decide"
2204: */
2205: PetscErrorCode PetscOptionsStringToInt(const char name[], PetscInt *a)
2206: {
2207: size_t len;
2208: PetscBool decide, tdefault, mouse, unlimited;
2210: PetscFunctionBegin;
2211: PetscCall(PetscStrlen(name, &len));
2212: PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2214: PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &tdefault));
2215: if (!tdefault) PetscCall(PetscStrcasecmp(name, "DEFAULT", &tdefault));
2216: PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &decide));
2217: if (!decide) PetscCall(PetscStrcasecmp(name, "DECIDE", &decide));
2218: if (!decide) PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &decide));
2219: if (!decide) PetscCall(PetscStrcasecmp(name, "DETERMINE", &decide));
2220: PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &unlimited));
2221: if (!unlimited) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &unlimited));
2222: PetscCall(PetscStrcasecmp(name, "mouse", &mouse));
2224: if (tdefault) *a = PETSC_DEFAULT;
2225: else if (decide) *a = PETSC_DECIDE;
2226: else if (unlimited) *a = PETSC_UNLIMITED;
2227: else if (mouse) *a = -1;
2228: else {
2229: char *endptr;
2230: long strtolval;
2232: strtolval = strtol(name, &endptr, 10);
2233: 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);
2235: #if defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE_ATOLL)
2236: (void)strtolval;
2237: *a = atoll(name);
2238: #elif defined(PETSC_USE_64BIT_INDICES) && defined(PETSC_HAVE___INT64)
2239: (void)strtolval;
2240: *a = _atoi64(name);
2241: #else
2242: *a = (PetscInt)strtolval;
2243: #endif
2244: }
2245: PetscFunctionReturn(PETSC_SUCCESS);
2246: }
2248: #if defined(PETSC_USE_REAL___FLOAT128)
2249: #include <quadmath.h>
2250: #endif
2252: static PetscErrorCode PetscStrtod(const char name[], PetscReal *a, char **endptr)
2253: {
2254: PetscFunctionBegin;
2255: #if defined(PETSC_USE_REAL___FLOAT128)
2256: *a = strtoflt128(name, endptr);
2257: #else
2258: *a = (PetscReal)strtod(name, endptr);
2259: #endif
2260: PetscFunctionReturn(PETSC_SUCCESS);
2261: }
2263: static PetscErrorCode PetscStrtoz(const char name[], PetscScalar *a, char **endptr, PetscBool *isImaginary)
2264: {
2265: PetscBool hasi = PETSC_FALSE;
2266: char *ptr;
2267: PetscReal strtoval;
2269: PetscFunctionBegin;
2270: PetscCall(PetscStrtod(name, &strtoval, &ptr));
2271: if (ptr == name) {
2272: strtoval = 1.;
2273: hasi = PETSC_TRUE;
2274: if (name[0] == 'i') {
2275: ptr++;
2276: } else if (name[0] == '+' && name[1] == 'i') {
2277: ptr += 2;
2278: } else if (name[0] == '-' && name[1] == 'i') {
2279: strtoval = -1.;
2280: ptr += 2;
2281: }
2282: } else if (*ptr == 'i') {
2283: hasi = PETSC_TRUE;
2284: ptr++;
2285: }
2286: *endptr = ptr;
2287: *isImaginary = hasi;
2288: if (hasi) {
2289: #if !defined(PETSC_USE_COMPLEX)
2290: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s contains imaginary but complex not supported ", name);
2291: #else
2292: *a = PetscCMPLX(0., strtoval);
2293: #endif
2294: } else {
2295: *a = strtoval;
2296: }
2297: PetscFunctionReturn(PETSC_SUCCESS);
2298: }
2300: /*
2301: Converts a string to PetscReal value. Handles special cases like "default" and "decide"
2302: */
2303: PetscErrorCode PetscOptionsStringToReal(const char name[], PetscReal *a)
2304: {
2305: size_t len;
2306: PetscBool match;
2307: char *endptr;
2309: PetscFunctionBegin;
2310: PetscCall(PetscStrlen(name, &len));
2311: PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "String of length zero has no numerical value");
2313: PetscCall(PetscStrcasecmp(name, "PETSC_DEFAULT", &match));
2314: if (!match) PetscCall(PetscStrcasecmp(name, "DEFAULT", &match));
2315: if (match) {
2316: *a = PETSC_DEFAULT;
2317: PetscFunctionReturn(PETSC_SUCCESS);
2318: }
2320: PetscCall(PetscStrcasecmp(name, "PETSC_DECIDE", &match));
2321: if (!match) PetscCall(PetscStrcasecmp(name, "DECIDE", &match));
2322: if (match) {
2323: *a = PETSC_DECIDE;
2324: PetscFunctionReturn(PETSC_SUCCESS);
2325: }
2327: PetscCall(PetscStrcasecmp(name, "PETSC_DETERMINE", &match));
2328: if (!match) PetscCall(PetscStrcasecmp(name, "DETERMINE", &match));
2329: if (match) {
2330: *a = PETSC_DETERMINE;
2331: PetscFunctionReturn(PETSC_SUCCESS);
2332: }
2334: PetscCall(PetscStrcasecmp(name, "PETSC_UNLIMITED", &match));
2335: if (!match) PetscCall(PetscStrcasecmp(name, "UNLIMITED", &match));
2336: if (match) {
2337: *a = PETSC_UNLIMITED;
2338: PetscFunctionReturn(PETSC_SUCCESS);
2339: }
2341: PetscCall(PetscStrtod(name, a, &endptr));
2342: PetscCheck((size_t)(endptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value", name);
2343: PetscFunctionReturn(PETSC_SUCCESS);
2344: }
2346: PetscErrorCode PetscOptionsStringToScalar(const char name[], PetscScalar *a)
2347: {
2348: PetscBool imag1;
2349: size_t len;
2350: PetscScalar val = 0.;
2351: char *ptr = NULL;
2353: PetscFunctionBegin;
2354: PetscCall(PetscStrlen(name, &len));
2355: PetscCheck(len, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "character string of length zero has no numerical value");
2356: PetscCall(PetscStrtoz(name, &val, &ptr, &imag1));
2357: #if defined(PETSC_USE_COMPLEX)
2358: if ((size_t)(ptr - name) < len) {
2359: PetscBool imag2;
2360: PetscScalar val2;
2362: PetscCall(PetscStrtoz(ptr, &val2, &ptr, &imag2));
2363: if (imag1) PetscCheck(imag2, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s: must specify imaginary component second", name);
2364: val = PetscCMPLX(PetscRealPart(val), PetscImaginaryPart(val2));
2365: }
2366: #endif
2367: PetscCheck((size_t)(ptr - name) == len, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Input string %s has no numeric value ", name);
2368: *a = val;
2369: PetscFunctionReturn(PETSC_SUCCESS);
2370: }
2372: /*@C
2373: PetscOptionsGetBool - Gets the Logical (true or false) value for a particular
2374: option in the database.
2376: Not Collective
2378: Input Parameters:
2379: + options - options database, use `NULL` for default global database
2380: . pre - the string to prepend to the name or `NULL`
2381: - name - the option one is seeking
2383: Output Parameters:
2384: + ivalue - the logical value to return
2385: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2387: Level: beginner
2389: Notes:
2390: TRUE, true, YES, yes, ON, on, nostring, and 1 all translate to `PETSC_TRUE`
2391: FALSE, false, NO, no, OFF, off and 0 all translate to `PETSC_FALSE`
2393: 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`
2394: is equivalent to `-requested_bool true`
2396: If the user does not supply the option at all `ivalue` is NOT changed. Thus
2397: you should ALWAYS initialize `ivalue` if you access it without first checking that the `set` flag is true.
2399: .seealso: `PetscOptionsGetBool3()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2400: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2401: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2402: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2403: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2404: `PetscOptionsFList()`, `PetscOptionsEList()`
2405: @*/
2406: PetscErrorCode PetscOptionsGetBool(PetscOptions options, const char pre[], const char name[], PetscBool *ivalue, PetscBool *set)
2407: {
2408: const char *value;
2409: PetscBool flag;
2411: PetscFunctionBegin;
2412: PetscAssertPointer(name, 3);
2413: if (ivalue) PetscAssertPointer(ivalue, 4);
2414: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2415: if (flag) {
2416: if (set) *set = PETSC_TRUE;
2417: PetscCall(PetscOptionsStringToBool(value, &flag));
2418: if (ivalue) *ivalue = flag;
2419: } else {
2420: if (set) *set = PETSC_FALSE;
2421: }
2422: PetscFunctionReturn(PETSC_SUCCESS);
2423: }
2425: /*@C
2426: PetscOptionsGetBool3 - Gets the ternary logical (true, false or unknown) value for a particular
2427: option in the database.
2429: Not Collective
2431: Input Parameters:
2432: + options - options database, use `NULL` for default global database
2433: . pre - the string to prepend to the name or `NULL`
2434: - name - the option one is seeking
2436: Output Parameters:
2437: + ivalue - the ternary logical value to return
2438: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2440: Level: beginner
2442: Notes:
2443: TRUE, true, YES, yes, ON, on, nostring and 1 all translate to `PETSC_BOOL3_TRUE`
2444: FALSE, false, NO, no, OFF, off and 0 all translate to `PETSC_BOOL3_FALSE`
2445: UNKNOWN, unknown, AUTO and auto all translate to `PETSC_BOOL3_UNKNOWN`
2447: 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`
2448: is equivalent to `-requested_bool3 true`
2450: If the user does not supply the option at all `ivalue` is NOT changed. Thus
2451: you should ALWAYS initialize `ivalue` if you access it without first checking that the `set` flag is true.
2453: .seealso: `PetscOptionsGetBool()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2454: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetInt()`, `PetscOptionsBool()`,
2455: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2456: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2457: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2458: `PetscOptionsFList()`, `PetscOptionsEList()`
2459: @*/
2460: PetscErrorCode PetscOptionsGetBool3(PetscOptions options, const char pre[], const char name[], PetscBool3 *ivalue, PetscBool *set)
2461: {
2462: const char *value;
2463: PetscBool flag;
2465: PetscFunctionBegin;
2466: PetscAssertPointer(name, 3);
2467: if (ivalue) PetscAssertPointer(ivalue, 4);
2468: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2469: if (flag) { // found the option
2470: PetscBool isAUTO = PETSC_FALSE, isUNKNOWN = PETSC_FALSE;
2472: if (set) *set = PETSC_TRUE;
2473: PetscCall(PetscStrcasecmp("AUTO", value, &isAUTO)); // auto or AUTO
2474: if (!isAUTO) PetscCall(PetscStrcasecmp("UNKNOWN", value, &isUNKNOWN)); // unknown or UNKNOWN
2475: if (isAUTO || isUNKNOWN) {
2476: if (ivalue) *ivalue = PETSC_BOOL3_UNKNOWN;
2477: } else { // handle boolean values (if no value is given, it returns true)
2478: PetscCall(PetscOptionsStringToBool(value, &flag));
2479: if (ivalue) *ivalue = PetscBoolToBool3(flag);
2480: }
2481: } else {
2482: if (set) *set = PETSC_FALSE;
2483: }
2484: PetscFunctionReturn(PETSC_SUCCESS);
2485: }
2487: /*@C
2488: PetscOptionsGetEList - Puts a list of option values that a single one may be selected from
2490: Not Collective
2492: Input Parameters:
2493: + options - options database, use `NULL` for default global database
2494: . pre - the string to prepend to the name or `NULL`
2495: . opt - option name
2496: . list - the possible choices (one of these must be selected, anything else is invalid)
2497: - ntext - number of choices
2499: Output Parameters:
2500: + value - the index of the value to return (defaults to zero if the option name is given but no choice is listed)
2501: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2503: Level: intermediate
2505: Notes:
2506: If the user does not supply the option `value` is NOT changed. Thus
2507: you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.
2509: See `PetscOptionsFList()` for when the choices are given in a `PetscFunctionList`
2511: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2512: `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2513: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2514: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2515: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2516: `PetscOptionsFList()`, `PetscOptionsEList()`
2517: @*/
2518: PetscErrorCode PetscOptionsGetEList(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscInt ntext, PetscInt *value, PetscBool *set)
2519: {
2520: size_t alen, len = 0, tlen = 0;
2521: char *svalue;
2522: PetscBool aset, flg = PETSC_FALSE;
2523: PetscInt i;
2525: PetscFunctionBegin;
2526: PetscAssertPointer(opt, 3);
2527: for (i = 0; i < ntext; i++) {
2528: PetscCall(PetscStrlen(list[i], &alen));
2529: if (alen > len) len = alen;
2530: tlen += len + 1;
2531: }
2532: len += 5; /* a little extra space for user mistypes */
2533: PetscCall(PetscMalloc1(len, &svalue));
2534: PetscCall(PetscOptionsGetString(options, pre, opt, svalue, len, &aset));
2535: if (aset) {
2536: PetscCall(PetscEListFind(ntext, list, svalue, value, &flg));
2537: if (!flg) {
2538: char *avail;
2540: PetscCall(PetscMalloc1(tlen, &avail));
2541: avail[0] = '\0';
2542: for (i = 0; i < ntext; i++) {
2543: PetscCall(PetscStrlcat(avail, list[i], tlen));
2544: PetscCall(PetscStrlcat(avail, " ", tlen));
2545: }
2546: PetscCall(PetscStrtolower(avail));
2547: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown option %s for -%s%s. Available options: %s", svalue, pre ? pre : "", opt + 1, avail);
2548: }
2549: if (set) *set = PETSC_TRUE;
2550: } else if (set) *set = PETSC_FALSE;
2551: PetscCall(PetscFree(svalue));
2552: PetscFunctionReturn(PETSC_SUCCESS);
2553: }
2555: /*@C
2556: PetscOptionsGetEnum - Gets the enum value for a particular option in the database.
2558: Not Collective
2560: Input Parameters:
2561: + options - options database, use `NULL` for default global database
2562: . pre - option prefix or `NULL`
2563: . opt - option name
2564: - list - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
2566: Output Parameters:
2567: + value - the value to return
2568: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2570: Level: beginner
2572: Notes:
2573: If the user does not supply the option `value` is NOT changed. Thus
2574: you should ALWAYS initialize `value` if you access it without first checking that the `set` flag is true.
2576: `list` is usually something like `PCASMTypes` or some other predefined list of enum names
2578: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2579: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2580: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2581: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2582: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2583: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2584: `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2585: @*/
2586: PetscErrorCode PetscOptionsGetEnum(PetscOptions options, const char pre[], const char opt[], const char *const list[], PetscEnum *value, PetscBool *set)
2587: {
2588: PetscInt ntext = 0, tval;
2589: PetscBool fset;
2591: PetscFunctionBegin;
2592: PetscAssertPointer(opt, 3);
2593: 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");
2594: PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
2595: ntext -= 3;
2596: PetscCall(PetscOptionsGetEList(options, pre, opt, list, ntext, &tval, &fset));
2597: /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
2598: if (fset) *value = (PetscEnum)tval;
2599: if (set) *set = fset;
2600: PetscFunctionReturn(PETSC_SUCCESS);
2601: }
2603: /*@C
2604: PetscOptionsGetInt - Gets the integer value for a particular option in the database.
2606: Not Collective
2608: Input Parameters:
2609: + options - options database, use `NULL` for default global database
2610: . pre - the string to prepend to the name or `NULL`
2611: - name - the option one is seeking
2613: Output Parameters:
2614: + ivalue - the integer value to return
2615: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2617: Level: beginner
2619: Notes:
2620: If the user does not supply the option `ivalue` is NOT changed. Thus
2621: you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.
2623: Accepts the special values `determine`, `decide` and `unlimited`.
2625: Accepts the deprecated value `default`.
2627: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2628: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2629: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2630: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2631: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2632: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2633: `PetscOptionsFList()`, `PetscOptionsEList()`
2634: @*/
2635: PetscErrorCode PetscOptionsGetInt(PetscOptions options, const char pre[], const char name[], PetscInt *ivalue, PetscBool *set)
2636: {
2637: const char *value;
2638: PetscBool flag;
2640: PetscFunctionBegin;
2641: PetscAssertPointer(name, 3);
2642: PetscAssertPointer(ivalue, 4);
2643: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2644: if (flag) {
2645: if (!value) {
2646: if (set) *set = PETSC_FALSE;
2647: } else {
2648: if (set) *set = PETSC_TRUE;
2649: PetscCall(PetscOptionsStringToInt(value, ivalue));
2650: }
2651: } else {
2652: if (set) *set = PETSC_FALSE;
2653: }
2654: PetscFunctionReturn(PETSC_SUCCESS);
2655: }
2657: /*@C
2658: PetscOptionsGetMPIInt - Gets the MPI integer value for a particular option in the database.
2660: Not Collective
2662: Input Parameters:
2663: + options - options database, use `NULL` for default global database
2664: . pre - the string to prepend to the name or `NULL`
2665: - name - the option one is seeking
2667: Output Parameters:
2668: + ivalue - the MPI integer value to return
2669: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2671: Level: beginner
2673: Notes:
2674: If the user does not supply the option `ivalue` is NOT changed. Thus
2675: you should ALWAYS initialize the `ivalue` if you access it without first checking that the `set` flag is true.
2677: Accepts the special values `determine`, `decide` and `unlimited`.
2679: Accepts the deprecated value `default`.
2681: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
2682: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2683: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
2684: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2685: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2686: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2687: `PetscOptionsFList()`, `PetscOptionsEList()`
2688: @*/
2689: PetscErrorCode PetscOptionsGetMPIInt(PetscOptions options, const char pre[], const char name[], PetscMPIInt *ivalue, PetscBool *set)
2690: {
2691: PetscInt value;
2692: PetscBool flag;
2694: PetscFunctionBegin;
2695: PetscCall(PetscOptionsGetInt(options, pre, name, &value, &flag));
2696: if (flag) PetscCall(PetscMPIIntCast(value, ivalue));
2697: if (set) *set = flag;
2698: PetscFunctionReturn(PETSC_SUCCESS);
2699: }
2701: /*@C
2702: PetscOptionsGetReal - Gets the double precision value for a particular
2703: option in the database.
2705: Not Collective
2707: Input Parameters:
2708: + options - options database, use `NULL` for default global database
2709: . pre - string to prepend to each name or `NULL`
2710: - name - the option one is seeking
2712: Output Parameters:
2713: + dvalue - the double value to return
2714: - set - `PETSC_TRUE` if found, `PETSC_FALSE` if not found
2716: Level: beginner
2718: Notes:
2719: Accepts the special values `determine`, `decide` and `unlimited`.
2721: Accepts the deprecated value `default`
2723: If the user does not supply the option `dvalue` is NOT changed. Thus
2724: you should ALWAYS initialize `dvalue` if you access it without first checking that the `set` flag is true.
2726: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2727: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2728: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2729: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2730: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2731: `PetscOptionsFList()`, `PetscOptionsEList()`
2732: @*/
2733: PetscErrorCode PetscOptionsGetReal(PetscOptions options, const char pre[], const char name[], PetscReal *dvalue, PetscBool *set)
2734: {
2735: const char *value;
2736: PetscBool flag;
2738: PetscFunctionBegin;
2739: PetscAssertPointer(name, 3);
2740: PetscAssertPointer(dvalue, 4);
2741: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2742: if (flag) {
2743: if (!value) {
2744: if (set) *set = PETSC_FALSE;
2745: } else {
2746: if (set) *set = PETSC_TRUE;
2747: PetscCall(PetscOptionsStringToReal(value, dvalue));
2748: }
2749: } else {
2750: if (set) *set = PETSC_FALSE;
2751: }
2752: PetscFunctionReturn(PETSC_SUCCESS);
2753: }
2755: /*@C
2756: PetscOptionsGetScalar - Gets the scalar value for a particular
2757: option in the database.
2759: Not Collective
2761: Input Parameters:
2762: + options - options database, use `NULL` for default global database
2763: . pre - string to prepend to each name or `NULL`
2764: - name - the option one is seeking
2766: Output Parameters:
2767: + dvalue - the scalar value to return
2768: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2770: Level: beginner
2772: Example Usage:
2773: A complex number 2+3i must be specified with NO spaces
2775: Note:
2776: If the user does not supply the option `dvalue` is NOT changed. Thus
2777: you should ALWAYS initialize `dvalue` if you access it without first checking if the `set` flag is true.
2779: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2780: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2781: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2782: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2783: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2784: `PetscOptionsFList()`, `PetscOptionsEList()`
2785: @*/
2786: PetscErrorCode PetscOptionsGetScalar(PetscOptions options, const char pre[], const char name[], PetscScalar *dvalue, PetscBool *set)
2787: {
2788: const char *value;
2789: PetscBool flag;
2791: PetscFunctionBegin;
2792: PetscAssertPointer(name, 3);
2793: PetscAssertPointer(dvalue, 4);
2794: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2795: if (flag) {
2796: if (!value) {
2797: if (set) *set = PETSC_FALSE;
2798: } else {
2799: #if !defined(PETSC_USE_COMPLEX)
2800: PetscCall(PetscOptionsStringToReal(value, dvalue));
2801: #else
2802: PetscCall(PetscOptionsStringToScalar(value, dvalue));
2803: #endif
2804: if (set) *set = PETSC_TRUE;
2805: }
2806: } else { /* flag */
2807: if (set) *set = PETSC_FALSE;
2808: }
2809: PetscFunctionReturn(PETSC_SUCCESS);
2810: }
2812: /*@C
2813: PetscOptionsGetString - Gets the string value for a particular option in
2814: the database.
2816: Not Collective
2818: Input Parameters:
2819: + options - options database, use `NULL` for default global database
2820: . pre - string to prepend to name or `NULL`
2821: . name - the option one is seeking
2822: - len - maximum length of the string including null termination
2824: Output Parameters:
2825: + string - location to copy string
2826: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2828: Level: beginner
2830: Note:
2831: 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`
2833: If the user does not use the option then `string` is not changed. Thus
2834: you should ALWAYS initialize `string` if you access it without first checking that the `set` flag is true.
2836: Fortran Notes:
2837: The Fortran interface is slightly different from the C/C++
2838: interface. Sample usage in Fortran follows
2839: .vb
2840: character *20 string
2841: PetscErrorCode ierr
2842: PetscBool set
2843: call PetscOptionsGetString(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-s',string,set,ierr)
2844: .ve
2846: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
2847: `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2848: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2849: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2850: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2851: `PetscOptionsFList()`, `PetscOptionsEList()`
2852: @*/
2853: PetscErrorCode PetscOptionsGetString(PetscOptions options, const char pre[], const char name[], char string[], size_t len, PetscBool *set) PeNS
2854: {
2855: const char *value;
2856: PetscBool flag;
2858: PetscFunctionBegin;
2859: PetscAssertPointer(name, 3);
2860: PetscAssertPointer(string, 4);
2861: PetscCall(PetscOptionsFindPair(options, pre, name, &value, &flag));
2862: if (!flag) {
2863: if (set) *set = PETSC_FALSE;
2864: } else {
2865: if (set) *set = PETSC_TRUE;
2866: if (value) PetscCall(PetscStrncpy(string, value, len));
2867: else PetscCall(PetscArrayzero(string, len));
2868: }
2869: PetscFunctionReturn(PETSC_SUCCESS);
2870: }
2872: /*@C
2873: PetscOptionsGetBoolArray - Gets an array of Logical (true or false) values for a particular
2874: option in the database. The values must be separated with commas with no intervening spaces.
2876: Not Collective
2878: Input Parameters:
2879: + options - options database, use `NULL` for default global database
2880: . pre - string to prepend to each name or `NULL`
2881: - name - the option one is seeking
2883: Output Parameters:
2884: + dvalue - the Boolean values to return
2885: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
2886: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2888: Level: beginner
2890: Note:
2891: TRUE, true, YES, yes, nostring, and 1 all translate to `PETSC_TRUE`. FALSE, false, NO, no, and 0 all translate to `PETSC_FALSE`
2893: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
2894: `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
2895: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
2896: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
2897: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2898: `PetscOptionsFList()`, `PetscOptionsEList()`
2899: @*/
2900: PetscErrorCode PetscOptionsGetBoolArray(PetscOptions options, const char pre[], const char name[], PetscBool dvalue[], PetscInt *nmax, PetscBool *set)
2901: {
2902: const char *svalue;
2903: const char *value;
2904: PetscInt n = 0;
2905: PetscBool flag;
2906: PetscToken token;
2908: PetscFunctionBegin;
2909: PetscAssertPointer(name, 3);
2910: PetscAssertPointer(dvalue, 4);
2911: PetscAssertPointer(nmax, 5);
2913: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
2914: if (!flag || !svalue) {
2915: if (set) *set = PETSC_FALSE;
2916: *nmax = 0;
2917: PetscFunctionReturn(PETSC_SUCCESS);
2918: }
2919: if (set) *set = PETSC_TRUE;
2920: PetscCall(PetscTokenCreate(svalue, ',', &token));
2921: PetscCall(PetscTokenFind(token, &value));
2922: while (value && n < *nmax) {
2923: PetscCall(PetscOptionsStringToBool(value, dvalue));
2924: PetscCall(PetscTokenFind(token, &value));
2925: dvalue++;
2926: n++;
2927: }
2928: PetscCall(PetscTokenDestroy(&token));
2929: *nmax = n;
2930: PetscFunctionReturn(PETSC_SUCCESS);
2931: }
2933: /*@C
2934: PetscOptionsGetEnumArray - Gets an array of enum values for a particular option in the database.
2936: Not Collective
2938: Input Parameters:
2939: + options - options database, use `NULL` for default global database
2940: . pre - option prefix or `NULL`
2941: . name - option name
2942: - list - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
2944: Output Parameters:
2945: + ivalue - the enum values to return
2946: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
2947: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
2949: Level: beginner
2951: Notes:
2952: The array must be passed as a comma separated list with no spaces between the items.
2954: `list` is usually something like `PCASMTypes` or some other predefined list of enum names.
2956: .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
2957: `PetscOptionsGetEnum()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
2958: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsName()`,
2959: `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, `PetscOptionsStringArray()`, `PetscOptionsRealArray()`,
2960: `PetscOptionsScalar()`, `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
2961: `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsGetEList()`, `PetscOptionsEnum()`
2962: @*/
2963: PetscErrorCode PetscOptionsGetEnumArray(PetscOptions options, const char pre[], const char name[], const char *const list[], PetscEnum ivalue[], PetscInt *nmax, PetscBool *set)
2964: {
2965: const char *svalue;
2966: const char *value;
2967: PetscInt n = 0;
2968: PetscEnum evalue;
2969: PetscBool flag;
2970: PetscToken token;
2972: PetscFunctionBegin;
2973: PetscAssertPointer(name, 3);
2974: PetscAssertPointer(list, 4);
2975: PetscAssertPointer(ivalue, 5);
2976: PetscAssertPointer(nmax, 6);
2978: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
2979: if (!flag || !svalue) {
2980: if (set) *set = PETSC_FALSE;
2981: *nmax = 0;
2982: PetscFunctionReturn(PETSC_SUCCESS);
2983: }
2984: if (set) *set = PETSC_TRUE;
2985: PetscCall(PetscTokenCreate(svalue, ',', &token));
2986: PetscCall(PetscTokenFind(token, &value));
2987: while (value && n < *nmax) {
2988: PetscCall(PetscEnumFind(list, value, &evalue, &flag));
2989: PetscCheck(flag, PETSC_COMM_SELF, PETSC_ERR_USER, "Unknown enum value '%s' for -%s%s", svalue, pre ? pre : "", name + 1);
2990: ivalue[n++] = evalue;
2991: PetscCall(PetscTokenFind(token, &value));
2992: }
2993: PetscCall(PetscTokenDestroy(&token));
2994: *nmax = n;
2995: PetscFunctionReturn(PETSC_SUCCESS);
2996: }
2998: /*@C
2999: PetscOptionsGetIntArray - Gets an array of integer values for a particular option in the database.
3001: Not Collective
3003: Input Parameters:
3004: + options - options database, use `NULL` for default global database
3005: . pre - string to prepend to each name or `NULL`
3006: - name - the option one is seeking
3008: Output Parameters:
3009: + ivalue - the integer values to return
3010: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
3011: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3013: Level: beginner
3015: Notes:
3016: The array can be passed as
3017: + a comma separated list - 0,1,2,3,4,5,6,7
3018: . a range (start\-end+1) - 0-8
3019: . a range with given increment (start\-end+1:inc) - 0-7:2
3020: - a combination of values and ranges separated by commas - 0,1-8,8-15:2
3022: There must be no intervening spaces between the values.
3024: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3025: `PetscOptionsGetString()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3026: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3027: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3028: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3029: `PetscOptionsFList()`, `PetscOptionsEList()`
3030: @*/
3031: PetscErrorCode PetscOptionsGetIntArray(PetscOptions options, const char pre[], const char name[], PetscInt ivalue[], PetscInt *nmax, PetscBool *set)
3032: {
3033: const char *svalue;
3034: const char *value;
3035: PetscInt n = 0, i, j, start, end, inc, nvalues;
3036: size_t len;
3037: PetscBool flag, foundrange;
3038: PetscToken token;
3040: PetscFunctionBegin;
3041: PetscAssertPointer(name, 3);
3042: PetscAssertPointer(ivalue, 4);
3043: PetscAssertPointer(nmax, 5);
3045: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3046: if (!flag || !svalue) {
3047: if (set) *set = PETSC_FALSE;
3048: *nmax = 0;
3049: PetscFunctionReturn(PETSC_SUCCESS);
3050: }
3051: if (set) *set = PETSC_TRUE;
3052: PetscCall(PetscTokenCreate(svalue, ',', &token));
3053: PetscCall(PetscTokenFind(token, &value));
3054: while (value && n < *nmax) {
3055: char *iivalue;
3057: /* look for form d-D where d and D are integers */
3058: PetscCall(PetscStrallocpy(value, &iivalue));
3059: foundrange = PETSC_FALSE;
3060: PetscCall(PetscStrlen(iivalue, &len));
3061: if (iivalue[0] == '-') i = 2;
3062: else i = 1;
3063: for (; i < (int)len; i++) {
3064: if (iivalue[i] == '-') {
3065: PetscCheck(i != (int)len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, iivalue);
3066: iivalue[i] = 0;
3068: PetscCall(PetscOptionsStringToInt(iivalue, &start));
3069: inc = 1;
3070: j = i + 1;
3071: for (; j < (int)len; j++) {
3072: if (iivalue[j] == ':') {
3073: iivalue[j] = 0;
3075: PetscCall(PetscOptionsStringToInt(iivalue + j + 1, &inc));
3076: 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);
3077: break;
3078: }
3079: }
3080: PetscCall(PetscOptionsStringToInt(iivalue + i + 1, &end));
3081: 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);
3082: nvalues = (end - start) / inc + (end - start) % inc;
3083: 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);
3084: for (; start < end; start += inc) {
3085: *ivalue = start;
3086: ivalue++;
3087: n++;
3088: }
3089: foundrange = PETSC_TRUE;
3090: break;
3091: }
3092: }
3093: if (!foundrange) {
3094: PetscCall(PetscOptionsStringToInt(value, ivalue));
3095: ivalue++;
3096: n++;
3097: }
3098: PetscCall(PetscFree(iivalue));
3099: PetscCall(PetscTokenFind(token, &value));
3100: }
3101: PetscCall(PetscTokenDestroy(&token));
3102: *nmax = n;
3103: PetscFunctionReturn(PETSC_SUCCESS);
3104: }
3106: /*@C
3107: PetscOptionsGetRealArray - Gets an array of double precision values for a
3108: particular option in the database. The values must be separated with commas with no intervening spaces.
3110: Not Collective
3112: Input Parameters:
3113: + options - options database, use `NULL` for default global database
3114: . pre - string to prepend to each name or `NULL`
3115: - name - the option one is seeking
3117: Output Parameters:
3118: + dvalue - the double values to return
3119: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
3120: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3122: Level: beginner
3124: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3125: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3126: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3127: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3128: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3129: `PetscOptionsFList()`, `PetscOptionsEList()`
3130: @*/
3131: PetscErrorCode PetscOptionsGetRealArray(PetscOptions options, const char pre[], const char name[], PetscReal dvalue[], PetscInt *nmax, PetscBool *set)
3132: {
3133: const char *svalue;
3134: const char *value;
3135: PetscInt n = 0;
3136: PetscBool flag;
3137: PetscToken token;
3139: PetscFunctionBegin;
3140: PetscAssertPointer(name, 3);
3141: PetscAssertPointer(dvalue, 4);
3142: PetscAssertPointer(nmax, 5);
3144: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3145: if (!flag || !svalue) {
3146: if (set) *set = PETSC_FALSE;
3147: *nmax = 0;
3148: PetscFunctionReturn(PETSC_SUCCESS);
3149: }
3150: if (set) *set = PETSC_TRUE;
3151: PetscCall(PetscTokenCreate(svalue, ',', &token));
3152: PetscCall(PetscTokenFind(token, &value));
3153: while (value && n < *nmax) {
3154: PetscCall(PetscOptionsStringToReal(value, dvalue++));
3155: PetscCall(PetscTokenFind(token, &value));
3156: n++;
3157: }
3158: PetscCall(PetscTokenDestroy(&token));
3159: *nmax = n;
3160: PetscFunctionReturn(PETSC_SUCCESS);
3161: }
3163: /*@C
3164: PetscOptionsGetScalarArray - Gets an array of scalars for a
3165: particular option in the database. The values must be separated with commas with no intervening spaces.
3167: Not Collective
3169: Input Parameters:
3170: + options - options database, use `NULL` for default global database
3171: . pre - string to prepend to each name or `NULL`
3172: - name - the option one is seeking
3174: Output Parameters:
3175: + dvalue - the scalar values to return
3176: . nmax - On input maximum number of values to retrieve, on output the actual number of values retrieved
3177: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3179: Level: beginner
3181: .seealso: `PetscOptionsGetInt()`, `PetscOptionsHasName()`,
3182: `PetscOptionsGetString()`, `PetscOptionsGetIntArray()`, `PetscOptionsBool()`,
3183: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3184: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3185: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3186: `PetscOptionsFList()`, `PetscOptionsEList()`
3187: @*/
3188: PetscErrorCode PetscOptionsGetScalarArray(PetscOptions options, const char pre[], const char name[], PetscScalar dvalue[], PetscInt *nmax, PetscBool *set)
3189: {
3190: const char *svalue;
3191: const char *value;
3192: PetscInt n = 0;
3193: PetscBool flag;
3194: PetscToken token;
3196: PetscFunctionBegin;
3197: PetscAssertPointer(name, 3);
3198: PetscAssertPointer(dvalue, 4);
3199: PetscAssertPointer(nmax, 5);
3201: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3202: if (!flag || !svalue) {
3203: if (set) *set = PETSC_FALSE;
3204: *nmax = 0;
3205: PetscFunctionReturn(PETSC_SUCCESS);
3206: }
3207: if (set) *set = PETSC_TRUE;
3208: PetscCall(PetscTokenCreate(svalue, ',', &token));
3209: PetscCall(PetscTokenFind(token, &value));
3210: while (value && n < *nmax) {
3211: PetscCall(PetscOptionsStringToScalar(value, dvalue++));
3212: PetscCall(PetscTokenFind(token, &value));
3213: n++;
3214: }
3215: PetscCall(PetscTokenDestroy(&token));
3216: *nmax = n;
3217: PetscFunctionReturn(PETSC_SUCCESS);
3218: }
3220: /*@C
3221: PetscOptionsGetStringArray - Gets an array of string values for a particular
3222: option in the database. The values must be separated with commas with no intervening spaces.
3224: Not Collective; No Fortran Support
3226: Input Parameters:
3227: + options - options database, use `NULL` for default global database
3228: . pre - string to prepend to name or `NULL`
3229: - name - the option one is seeking
3231: Output Parameters:
3232: + strings - location to copy strings
3233: . nmax - On input maximum number of strings, on output the actual number of strings found
3234: - set - `PETSC_TRUE` if found, else `PETSC_FALSE`
3236: Level: beginner
3238: Notes:
3239: The `nmax` parameter is used for both input and output.
3241: The user should pass in an array of pointers to `char`, to hold all the
3242: strings returned by this function.
3244: The user is responsible for deallocating the strings that are
3245: returned.
3247: .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
3248: `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
3249: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
3250: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
3251: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
3252: `PetscOptionsFList()`, `PetscOptionsEList()`
3253: @*/
3254: PetscErrorCode PetscOptionsGetStringArray(PetscOptions options, const char pre[], const char name[], char *strings[], PetscInt *nmax, PetscBool *set) PeNS
3255: {
3256: const char *svalue;
3257: const char *value;
3258: PetscInt n = 0;
3259: PetscBool flag;
3260: PetscToken token;
3262: PetscFunctionBegin;
3263: PetscAssertPointer(name, 3);
3264: PetscAssertPointer(strings, 4);
3265: PetscAssertPointer(nmax, 5);
3267: PetscCall(PetscOptionsFindPair(options, pre, name, &svalue, &flag));
3268: if (!flag || !svalue) {
3269: if (set) *set = PETSC_FALSE;
3270: *nmax = 0;
3271: PetscFunctionReturn(PETSC_SUCCESS);
3272: }
3273: if (set) *set = PETSC_TRUE;
3274: PetscCall(PetscTokenCreate(svalue, ',', &token));
3275: PetscCall(PetscTokenFind(token, &value));
3276: while (value && n < *nmax) {
3277: PetscCall(PetscStrallocpy(value, &strings[n]));
3278: PetscCall(PetscTokenFind(token, &value));
3279: n++;
3280: }
3281: PetscCall(PetscTokenDestroy(&token));
3282: *nmax = n;
3283: PetscFunctionReturn(PETSC_SUCCESS);
3284: }
3286: /*@C
3287: PetscOptionsDeprecated_Private - mark an option as deprecated, optionally replacing it with `newname`
3289: Prints a deprecation warning, unless an option is supplied to suppress.
3291: Logically Collective
3293: Input Parameters:
3294: + PetscOptionsObject - string to prepend to name or `NULL`
3295: . oldname - the old, deprecated option
3296: . newname - the new option, or `NULL` if option is purely removed
3297: . version - a string describing the version of first deprecation, e.g. "3.9"
3298: - info - additional information string, or `NULL`.
3300: Options Database Key:
3301: . -options_suppress_deprecated_warnings - do not print deprecation warnings
3303: Level: developer
3305: Notes:
3306: If `newname` is provided then the options database will automatically check the database for `oldname`.
3308: The old call `PetscOptionsXXX`(`oldname`) should be removed from the source code when both (1) the call to `PetscOptionsDeprecated()` occurs before the
3309: new call to `PetscOptionsXXX`(`newname`) and (2) the argument handling of the new call to `PetscOptionsXXX`(`newname`) is identical to the previous call.
3310: See `PTScotch_PartGraph_Seq()` for an example of when (1) fails and `SNESTestJacobian()` where an example of (2) fails.
3312: Must be called between `PetscOptionsBegin()` (or `PetscObjectOptionsBegin()`) and `PetscOptionsEnd()`.
3313: Only the process of rank zero that owns the `PetscOptionsItems` are argument (managed by `PetscOptionsBegin()` or
3314: `PetscObjectOptionsBegin()` prints the information
3315: If newname is provided, the old option is replaced. Otherwise, it remains
3316: in the options database.
3317: If an option is not replaced, the info argument should be used to advise the user
3318: on how to proceed.
3319: There is a limit on the length of the warning printed, so very long strings
3320: provided as info may be truncated.
3322: .seealso: `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsScalar()`, `PetscOptionsBool()`, `PetscOptionsString()`, `PetscOptionsSetValue()`
3323: @*/
3324: PetscErrorCode PetscOptionsDeprecated_Private(PetscOptionItems PetscOptionsObject, const char oldname[], const char newname[], const char version[], const char info[])
3325: {
3326: PetscBool found, quiet;
3327: const char *value;
3328: const char *const quietopt = "-options_suppress_deprecated_warnings";
3329: char msg[4096];
3330: char *prefix = NULL;
3331: PetscOptions options = NULL;
3332: MPI_Comm comm = PETSC_COMM_SELF;
3334: PetscFunctionBegin;
3335: PetscAssertPointer(oldname, 2);
3336: PetscAssertPointer(version, 4);
3337: if (PetscOptionsObject) {
3338: prefix = PetscOptionsObject->prefix;
3339: options = PetscOptionsObject->options;
3340: comm = PetscOptionsObject->comm;
3341: }
3342: PetscCall(PetscOptionsFindPair(options, prefix, oldname, &value, &found));
3343: if (found) {
3344: if (newname) {
3345: if (prefix) PetscCall(PetscOptionsPrefixPush(options, prefix));
3346: PetscCall(PetscOptionsSetValue(options, newname, value));
3347: if (prefix) PetscCall(PetscOptionsPrefixPop(options));
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: }