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