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