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