1 /* 2 Implements the higher-level options database querying methods. These are self-documenting and can attach at runtime to 3 GUI code to display the options and get values from the users. 4 5 */ 6 7 #include <petsc/private/petscimpl.h> /*I "petscsys.h" I*/ 8 #include <petscviewer.h> 9 10 static const char *ManSection(const char *str) 11 { 12 return str ? str : "None"; 13 } 14 15 static const char *Prefix(const char *str) 16 { 17 return str ? str : ""; 18 } 19 20 static int ShouldPrintHelp(const PetscOptionItems *opts) 21 { 22 return opts->printhelp && opts->count == 1 && !opts->alreadyprinted; 23 } 24 25 /* 26 Keep a linked list of options that have been posted and we are waiting for 27 user selection. See the manual page for PetscOptionsBegin() 28 29 Eventually we'll attach this beast to a MPI_Comm 30 */ 31 32 /* 33 Handles setting up the data structure in a call to PetscOptionsBegin() 34 */ 35 PetscErrorCode PetscOptionsBegin_Private(PetscOptionItems *PetscOptionsObject, MPI_Comm comm, const char prefix[], const char title[], const char mansec[]) 36 { 37 PetscFunctionBegin; 38 if (prefix) PetscAssertPointer(prefix, 3); 39 PetscAssertPointer(title, 4); 40 if (mansec) PetscAssertPointer(mansec, 5); 41 if (!PetscOptionsObject->alreadyprinted) { 42 if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton)); 43 PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, prefix, title, &PetscOptionsObject->alreadyprinted)); 44 } 45 PetscOptionsObject->next = NULL; 46 PetscOptionsObject->comm = comm; 47 PetscOptionsObject->changedmethod = PETSC_FALSE; 48 49 PetscCall(PetscStrallocpy(prefix, &PetscOptionsObject->prefix)); 50 PetscCall(PetscStrallocpy(title, &PetscOptionsObject->title)); 51 52 PetscCall(PetscOptionsHasHelp(PetscOptionsObject->options, &PetscOptionsObject->printhelp)); 53 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\n%s:\n", title)); 54 PetscFunctionReturn(PETSC_SUCCESS); 55 } 56 57 /* 58 Handles setting up the data structure in a call to PetscObjectOptionsBegin() 59 */ 60 PetscErrorCode PetscObjectOptionsBegin_Private(PetscObject obj, PetscOptionItems *PetscOptionsObject) 61 { 62 char title[256]; 63 PetscBool flg; 64 65 PetscFunctionBegin; 66 PetscAssertPointer(PetscOptionsObject, 2); 67 PetscValidHeader(obj, 1); 68 PetscOptionsObject->object = obj; 69 PetscOptionsObject->alreadyprinted = obj->optionsprinted; 70 71 PetscCall(PetscStrcmp(obj->description, obj->class_name, &flg)); 72 if (flg) PetscCall(PetscSNPrintf(title, sizeof(title), "%s options", obj->class_name)); 73 else PetscCall(PetscSNPrintf(title, sizeof(title), "%s (%s) options", obj->description, obj->class_name)); 74 PetscCall(PetscOptionsBegin_Private(PetscOptionsObject, obj->comm, obj->prefix, title, obj->mansec)); 75 PetscFunctionReturn(PETSC_SUCCESS); 76 } 77 78 /* 79 Handles adding another option to the list of options within this particular PetscOptionsBegin() PetscOptionsEnd() 80 */ 81 static PetscErrorCode PetscOptionItemCreate_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscOptionType t, PetscOptionItem *amsopt) 82 { 83 PetscBool valid; 84 85 PetscFunctionBegin; 86 PetscCall(PetscOptionsValidKey(opt, &valid)); 87 PetscCheck(valid, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "The option '%s' is not a valid key", opt); 88 89 PetscCall(PetscNew(amsopt)); 90 (*amsopt)->next = NULL; 91 (*amsopt)->set = PETSC_FALSE; 92 (*amsopt)->type = t; 93 (*amsopt)->data = NULL; 94 95 PetscCall(PetscStrallocpy(text, &(*amsopt)->text)); 96 PetscCall(PetscStrallocpy(opt, &(*amsopt)->option)); 97 PetscCall(PetscStrallocpy(man, &(*amsopt)->man)); 98 99 { 100 PetscOptionItem cur = PetscOptionsObject->next; 101 102 while (cur->next) cur = cur->next; 103 cur->next = *amsopt; 104 } 105 PetscFunctionReturn(PETSC_SUCCESS); 106 } 107 108 /* 109 This is needed because certain strings may be freed by SAWs, hence we cannot use PetscStrallocpy() 110 */ 111 static PetscErrorCode PetscStrdup(const char s[], char *t[]) 112 { 113 char *tmp = NULL; 114 115 PetscFunctionBegin; 116 if (s) { 117 size_t len; 118 119 PetscCall(PetscStrlen(s, &len)); 120 tmp = (char *)malloc((len + 1) * sizeof(*tmp)); 121 PetscCheck(tmp, PETSC_COMM_SELF, PETSC_ERR_MEM, "No memory to duplicate string"); 122 PetscCall(PetscArraycpy(tmp, s, len + 1)); 123 } 124 *t = tmp; 125 PetscFunctionReturn(PETSC_SUCCESS); 126 } 127 128 #if defined(PETSC_HAVE_SAWS) 129 #include <petscviewersaws.h> 130 131 static int count = 0; 132 133 PetscErrorCode PetscOptionsSAWsDestroy(void) 134 { 135 PetscFunctionBegin; 136 PetscFunctionReturn(PETSC_SUCCESS); 137 } 138 139 static const char *OptionsHeader = "<head>\n" 140 "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/jquery-1.9.1.js\"></script>\n" 141 "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/SAWs.js\"></script>\n" 142 "<script type=\"text/javascript\" src=\"js/PETSc.js\"></script>\n" 143 "<script>\n" 144 "jQuery(document).ready(function() {\n" 145 "PETSc.getAndDisplayDirectory(null,\"#variablesInfo\")\n" 146 "})\n" 147 "</script>\n" 148 "</head>\n"; 149 150 /* Determines the size and style of the scroll region where PETSc options selectable from users are displayed */ 151 static const char *OptionsBodyBottom = "<div id=\"variablesInfo\" style=\"background-color:lightblue;height:auto;max-height:500px;overflow:scroll;\"></div>\n<br>\n</body>"; 152 153 /* 154 PetscOptionsSAWsInput - Presents all the PETSc Options processed by the program so the user may change them at runtime using the SAWs 155 156 Bugs: 157 + All processes must traverse through the exact same set of option queries due to the call to PetscScanString() 158 . Internal strings have arbitrary length and string copies are not checked that they fit into string space 159 - Only works for PetscInt == int, PetscReal == double etc 160 161 */ 162 static PetscErrorCode PetscOptionsSAWsInput(PetscOptionItems *PetscOptionsObject) 163 { 164 PetscOptionItem next = PetscOptionsObject->next; 165 static int mancount = 0; 166 char options[16]; 167 PetscBool changedmethod = PETSC_FALSE; 168 PetscBool stopasking = PETSC_FALSE; 169 char manname[16], textname[16]; 170 char dir[1024]; 171 172 PetscFunctionBegin; 173 /* the next line is a bug, this will only work if all processors are here, the comm passed in is ignored!!! */ 174 PetscCall(PetscSNPrintf(options, PETSC_STATIC_ARRAY_LENGTH(options), "Options_%d", count++)); 175 176 PetscOptionsObject->pprefix = PetscOptionsObject->prefix; /* SAWs will change this, so cannot pass prefix directly */ 177 178 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "_title")); 179 PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->title, 1, SAWs_READ, SAWs_STRING)); 180 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "prefix")); 181 PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->pprefix, 1, SAWs_READ, SAWs_STRING)); 182 PetscCallSAWs(SAWs_Register, ("/PETSc/Options/ChangedMethod", &changedmethod, 1, SAWs_WRITE, SAWs_BOOLEAN)); 183 PetscCallSAWs(SAWs_Register, ("/PETSc/Options/StopAsking", &stopasking, 1, SAWs_WRITE, SAWs_BOOLEAN)); 184 185 while (next) { 186 PetscCall(PetscSNPrintf(manname, PETSC_STATIC_ARRAY_LENGTH(manname), "_man_%d", mancount)); 187 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", manname)); 188 PetscCallSAWs(SAWs_Register, (dir, &next->man, 1, SAWs_READ, SAWs_STRING)); 189 PetscCall(PetscSNPrintf(textname, PETSC_STATIC_ARRAY_LENGTH(textname), "_text_%d", mancount++)); 190 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", textname)); 191 PetscCallSAWs(SAWs_Register, (dir, &next->text, 1, SAWs_READ, SAWs_STRING)); 192 193 switch (next->type) { 194 case OPTION_HEAD: 195 break; 196 case OPTION_INT_ARRAY: 197 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 198 PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_INT)); 199 break; 200 case OPTION_REAL_ARRAY: 201 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 202 PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_DOUBLE)); 203 break; 204 case OPTION_INT: 205 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 206 PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_INT)); 207 break; 208 case OPTION_REAL: 209 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 210 PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_DOUBLE)); 211 break; 212 case OPTION_BOOL: 213 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 214 PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_BOOLEAN)); 215 break; 216 case OPTION_BOOL_ARRAY: 217 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 218 PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_BOOLEAN)); 219 break; 220 case OPTION_STRING: 221 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 222 PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING)); 223 break; 224 case OPTION_STRING_ARRAY: 225 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 226 PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_STRING)); 227 break; 228 case OPTION_FLIST: { 229 PetscInt ntext; 230 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 231 PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING)); 232 PetscCall(PetscFunctionListGet(next->flist, (const char ***)&next->edata, &ntext)); 233 PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata)); 234 } break; 235 case OPTION_ELIST: { 236 PetscInt ntext = next->nlist; 237 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 238 PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING)); 239 PetscCall(PetscMalloc1((ntext + 1), (char ***)&next->edata)); 240 PetscCall(PetscMemcpy(next->edata, next->list, ntext * sizeof(char *))); 241 PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata)); 242 } break; 243 default: 244 break; 245 } 246 next = next->next; 247 } 248 249 /* wait until accessor has unlocked the memory */ 250 PetscCallSAWs(SAWs_Push_Header, ("index.html", OptionsHeader)); 251 PetscCallSAWs(SAWs_Push_Body, ("index.html", 2, OptionsBodyBottom)); 252 PetscCall(PetscSAWsBlock()); 253 PetscCallSAWs(SAWs_Pop_Header, ("index.html")); 254 PetscCallSAWs(SAWs_Pop_Body, ("index.html", 2)); 255 256 /* determine if any values have been set in GUI */ 257 next = PetscOptionsObject->next; 258 while (next) { 259 PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option)); 260 PetscCallSAWs(SAWs_Selected, (dir, (int *)&next->set)); 261 next = next->next; 262 } 263 264 /* reset counter to -2; this updates the screen with the new options for the selected method */ 265 if (changedmethod) PetscOptionsObject->count = -2; 266 267 if (stopasking) { 268 PetscOptionsPublish = PETSC_FALSE; 269 PetscOptionsObject->count = 0; //do not ask for same thing again 270 } 271 272 PetscCallSAWs(SAWs_Delete, ("/PETSc/Options")); 273 PetscFunctionReturn(PETSC_SUCCESS); 274 } 275 #else 276 /* 277 PetscScanString - Gets user input via stdin from process and broadcasts to all processes 278 279 Collective 280 281 Input Parameters: 282 + commm - communicator for the broadcast, must be PETSC_COMM_WORLD 283 . n - length of the string, must be the same on all processes 284 - str - location to store input 285 286 Bugs: 287 . Assumes process 0 of the given communicator has access to stdin 288 289 */ 290 static PetscErrorCode PetscScanString(MPI_Comm comm, size_t n, char str[]) 291 { 292 PetscMPIInt rank, nm; 293 294 PetscFunctionBegin; 295 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 296 if (rank == 0) { 297 char c = (char)getchar(); 298 size_t i = 0; 299 300 while (c != '\n' && i < n - 1) { 301 str[i++] = c; 302 c = (char)getchar(); 303 } 304 str[i] = '\0'; 305 } 306 PetscCall(PetscMPIIntCast(n, &nm)); 307 PetscCallMPI(MPI_Bcast(str, nm, MPI_CHAR, 0, comm)); 308 PetscFunctionReturn(PETSC_SUCCESS); 309 } 310 311 /* 312 PetscOptionsGetFromTextInput - Presents all the PETSc Options processed by the program so the user may change them at runtime 313 314 Notes: 315 this isn't really practical, it is just to demonstrate the principle 316 317 A carriage return indicates no change from the default; but this like -ksp_monitor <stdout> the default is actually not stdout the default 318 is to do nothing so to get it to use stdout you need to type stdout. This is kind of bug? 319 320 Bugs: 321 + All processes must traverse through the exact same set of option queries due to the call to PetscScanString() 322 . Internal strings have arbitrary length and string copies are not checked that they fit into string space 323 - Only works for PetscInt == int, PetscReal == double etc 324 325 Developer Notes: 326 Normally the GUI that presents the options the user and retrieves the values would be running in a different 327 address space and communicating with the PETSc program 328 329 */ 330 static PetscErrorCode PetscOptionsGetFromTextInput(PetscOptionItems *PetscOptionsObject) 331 { 332 PetscOptionItem next = PetscOptionsObject->next; 333 char str[512]; 334 PetscBool bid; 335 PetscReal ir, *valr; 336 PetscInt *vald; 337 size_t i; 338 339 PetscFunctionBegin; 340 PetscCall((*PetscPrintf)(PETSC_COMM_WORLD, "%s --------------------\n", PetscOptionsObject->title)); 341 while (next) { 342 switch (next->type) { 343 case OPTION_HEAD: 344 break; 345 case OPTION_INT_ARRAY: 346 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1)); 347 vald = (PetscInt *)next->data; 348 for (i = 0; i < next->arraylength; i++) { 349 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT, vald[i])); 350 if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ",")); 351 } 352 PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man)); 353 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 354 if (str[0]) { 355 PetscToken token; 356 PetscInt n = 0, nmax = next->arraylength, *dvalue = (PetscInt *)next->data, start, end; 357 size_t len; 358 char *value; 359 PetscBool foundrange; 360 361 next->set = PETSC_TRUE; 362 value = str; 363 PetscCall(PetscTokenCreate(value, ',', &token)); 364 PetscCall(PetscTokenFind(token, &value)); 365 while (n < nmax) { 366 if (!value) break; 367 368 /* look for form d-D where d and D are integers */ 369 foundrange = PETSC_FALSE; 370 PetscCall(PetscStrlen(value, &len)); 371 if (value[0] == '-') i = 2; 372 else i = 1; 373 for (; i < len; i++) { 374 if (value[i] == '-') { 375 PetscCheck(i != len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, value); 376 value[i] = 0; 377 PetscCall(PetscOptionsStringToInt(value, &start)); 378 PetscCall(PetscOptionsStringToInt(value + i + 1, &end)); 379 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); 380 PetscCheck(n + end - start - 1 < nmax, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, not enough space in left in array (%" PetscInt_FMT ") to contain entire range from %" PetscInt_FMT " to %" PetscInt_FMT, n, nmax - n, start, end); 381 for (; start < end; start++) { 382 *dvalue = start; 383 dvalue++; 384 n++; 385 } 386 foundrange = PETSC_TRUE; 387 break; 388 } 389 } 390 if (!foundrange) { 391 PetscCall(PetscOptionsStringToInt(value, dvalue)); 392 dvalue++; 393 n++; 394 } 395 PetscCall(PetscTokenFind(token, &value)); 396 } 397 PetscCall(PetscTokenDestroy(&token)); 398 } 399 break; 400 case OPTION_REAL_ARRAY: 401 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1)); 402 valr = (PetscReal *)next->data; 403 for (i = 0; i < next->arraylength; i++) { 404 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%g", (double)valr[i])); 405 if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ",")); 406 } 407 PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man)); 408 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 409 if (str[0]) { 410 PetscToken token; 411 PetscInt n = 0, nmax = next->arraylength; 412 PetscReal *dvalue = (PetscReal *)next->data; 413 char *value; 414 415 next->set = PETSC_TRUE; 416 value = str; 417 PetscCall(PetscTokenCreate(value, ',', &token)); 418 PetscCall(PetscTokenFind(token, &value)); 419 while (n < nmax) { 420 if (!value) break; 421 PetscCall(PetscOptionsStringToReal(value, dvalue)); 422 dvalue++; 423 n++; 424 PetscCall(PetscTokenFind(token, &value)); 425 } 426 PetscCall(PetscTokenDestroy(&token)); 427 } 428 break; 429 case OPTION_INT: 430 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%d>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(int *)next->data, next->text, next->man)); 431 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 432 if (str[0]) { 433 #if defined(PETSC_SIZEOF_LONG_LONG) 434 long long lid; 435 sscanf(str, "%lld", &lid); 436 PetscCheck(lid <= PETSC_MAX_INT && lid >= PETSC_MIN_INT, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %lld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid); 437 #else 438 long lid; 439 sscanf(str, "%ld", &lid); 440 PetscCheck(lid <= PETSC_MAX_INT && lid >= PETSC_MIN_INT, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %ld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid); 441 #endif 442 443 next->set = PETSC_TRUE; 444 *((PetscInt *)next->data) = (PetscInt)lid; 445 } 446 break; 447 case OPTION_REAL: 448 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%g>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(double *)next->data, next->text, next->man)); 449 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 450 if (str[0]) { 451 #if defined(PETSC_USE_REAL_SINGLE) 452 sscanf(str, "%e", &ir); 453 #elif defined(PETSC_USE_REAL___FP16) 454 float irtemp; 455 sscanf(str, "%e", &irtemp); 456 ir = irtemp; 457 #elif defined(PETSC_USE_REAL_DOUBLE) 458 sscanf(str, "%le", &ir); 459 #elif defined(PETSC_USE_REAL___FLOAT128) 460 ir = strtoflt128(str, 0); 461 #else 462 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Unknown scalar type"); 463 #endif 464 next->set = PETSC_TRUE; 465 *((PetscReal *)next->data) = ir; 466 } 467 break; 468 case OPTION_BOOL: 469 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%s>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(PetscBool *)next->data ? "true" : "false", next->text, next->man)); 470 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 471 if (str[0]) { 472 PetscCall(PetscOptionsStringToBool(str, &bid)); 473 next->set = PETSC_TRUE; 474 *((PetscBool *)next->data) = bid; 475 } 476 break; 477 case OPTION_STRING: 478 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%s>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, (char *)next->data, next->text, next->man)); 479 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 480 if (str[0]) { 481 next->set = PETSC_TRUE; 482 /* must use system malloc since SAWs may free this */ 483 PetscCall(PetscStrdup(str, (char **)&next->data)); 484 } 485 break; 486 case OPTION_FLIST: 487 PetscCall(PetscFunctionListPrintTypes(PETSC_COMM_WORLD, stdout, PetscOptionsObject->prefix, next->option, next->text, next->man, next->flist, (char *)next->data, (char *)next->data)); 488 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 489 if (str[0]) { 490 PetscOptionsObject->changedmethod = PETSC_TRUE; 491 next->set = PETSC_TRUE; 492 /* must use system malloc since SAWs may free this */ 493 PetscCall(PetscStrdup(str, (char **)&next->data)); 494 } 495 break; 496 default: 497 break; 498 } 499 next = next->next; 500 } 501 PetscFunctionReturn(PETSC_SUCCESS); 502 } 503 #endif 504 505 PetscErrorCode PetscOptionsEnd_Private(PetscOptionItems *PetscOptionsObject) 506 { 507 PetscOptionItem next, last; 508 509 PetscFunctionBegin; 510 if (PetscOptionsObject->next) { 511 if (!PetscOptionsObject->count) { 512 #if defined(PETSC_HAVE_SAWS) 513 PetscCall(PetscOptionsSAWsInput(PetscOptionsObject)); 514 #else 515 PetscCall(PetscOptionsGetFromTextInput(PetscOptionsObject)); 516 #endif 517 } 518 } 519 520 PetscCall(PetscFree(PetscOptionsObject->title)); 521 522 /* reset counter to -2; this updates the screen with the new options for the selected method */ 523 if (PetscOptionsObject->changedmethod) PetscOptionsObject->count = -2; 524 /* reset alreadyprinted flag */ 525 PetscOptionsObject->alreadyprinted = PETSC_FALSE; 526 if (PetscOptionsObject->object) PetscOptionsObject->object->optionsprinted = PETSC_TRUE; 527 PetscOptionsObject->object = NULL; 528 529 while ((next = PetscOptionsObject->next)) { 530 const PetscOptionType type = next->type; 531 const size_t arraylength = next->arraylength; 532 void *data = next->data; 533 534 if (next->set) { 535 char option[256], value[1024], tmp[32]; 536 537 if (PetscOptionsObject->prefix) { 538 PetscCall(PetscStrncpy(option, "-", sizeof(option))); 539 PetscCall(PetscStrlcat(option, PetscOptionsObject->prefix, sizeof(option))); 540 PetscCall(PetscStrlcat(option, next->option + 1, sizeof(option))); 541 } else { 542 PetscCall(PetscStrncpy(option, next->option, sizeof(option))); 543 } 544 545 switch (type) { 546 case OPTION_HEAD: 547 break; 548 case OPTION_INT_ARRAY: 549 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscInt *)data)[0])); 550 for (size_t j = 1; j < arraylength; ++j) { 551 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscInt *)data)[j])); 552 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 553 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 554 } 555 break; 556 case OPTION_INT: 557 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)*(PetscInt *)data)); 558 break; 559 case OPTION_REAL: 560 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)*(PetscReal *)data)); 561 break; 562 case OPTION_REAL_ARRAY: 563 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)((PetscReal *)data)[0])); 564 for (size_t j = 1; j < arraylength; ++j) { 565 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g", (double)((PetscReal *)data)[j])); 566 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 567 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 568 } 569 break; 570 case OPTION_SCALAR_ARRAY: 571 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[0]), (double)PetscImaginaryPart(((PetscScalar *)data)[0]))); 572 for (size_t j = 1; j < arraylength; ++j) { 573 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[j]), (double)PetscImaginaryPart(((PetscScalar *)data)[j]))); 574 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 575 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 576 } 577 break; 578 case OPTION_BOOL: 579 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", *(int *)data)); 580 break; 581 case OPTION_BOOL_ARRAY: 582 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscBool *)data)[0])); 583 for (size_t j = 1; j < arraylength; ++j) { 584 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscBool *)data)[j])); 585 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 586 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 587 } 588 break; 589 case OPTION_FLIST: // fall-through 590 case OPTION_ELIST: // fall-through 591 case OPTION_STRING: 592 PetscCall(PetscStrncpy(value, (char *)data, sizeof(value))); 593 break; 594 case OPTION_STRING_ARRAY: 595 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%s", ((char **)data)[0])); 596 for (size_t j = 1; j < arraylength; j++) { 597 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%s", ((char **)data)[j])); 598 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 599 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 600 } 601 break; 602 } 603 PetscCall(PetscOptionsSetValue(PetscOptionsObject->options, option, value)); 604 } 605 if (type == OPTION_ELIST) PetscCall(PetscStrNArrayDestroy(next->nlist, (char ***)&next->list)); 606 PetscCall(PetscFree(next->text)); 607 PetscCall(PetscFree(next->option)); 608 PetscCall(PetscFree(next->man)); 609 PetscCall(PetscFree(next->edata)); 610 611 if (type == OPTION_STRING || type == OPTION_FLIST || type == OPTION_ELIST) { 612 free(data); 613 } else { 614 // use next->data instead of data because PetscFree() sets it to NULL 615 PetscCall(PetscFree(next->data)); 616 } 617 618 last = next; 619 PetscOptionsObject->next = next->next; 620 PetscCall(PetscFree(last)); 621 } 622 PetscCall(PetscFree(PetscOptionsObject->prefix)); 623 PetscOptionsObject->next = NULL; 624 PetscFunctionReturn(PETSC_SUCCESS); 625 } 626 627 static PetscErrorCode GetListLength(const char *const *list, PetscInt *len) 628 { 629 PetscInt retlen = 0; 630 631 PetscFunctionBegin; 632 PetscAssertPointer(len, 2); 633 while (list[retlen]) { 634 PetscAssertPointer(list[retlen], 1); 635 PetscCheck(++retlen < 50, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "List argument appears to be wrong or have more than 50 entries"); 636 } 637 PetscCheck(retlen > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least 2 entries: typename and type prefix"); 638 /* drop item name and prefix*/ 639 *len = retlen - 2; 640 PetscFunctionReturn(PETSC_SUCCESS); 641 } 642 643 PetscErrorCode PetscOptionsEnum_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum currentvalue, PetscEnum *value, PetscBool *set) 644 { 645 PetscInt ntext = 0; 646 PetscInt tval; 647 PetscBool tflg; 648 649 PetscFunctionBegin; 650 PetscAssertPointer(opt, 2); 651 PetscAssertPointer(list, 5); 652 PetscAssertPointer(value, 7); 653 if (set) PetscAssertPointer(set, 8); 654 PetscCall(GetListLength(list, &ntext)); 655 PetscCall(PetscOptionsEList_Private(PetscOptionsObject, opt, text, man, list, ntext, list[currentvalue], &tval, &tflg)); 656 /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */ 657 if (tflg) *value = (PetscEnum)tval; 658 if (set) *set = tflg; 659 PetscFunctionReturn(PETSC_SUCCESS); 660 } 661 662 PetscErrorCode PetscOptionsEnumArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum value[], PetscInt *n, PetscBool *set) 663 { 664 PetscInt nlist = 0; 665 const char *prefix = PetscOptionsObject->prefix; 666 667 PetscFunctionBegin; 668 PetscAssertPointer(opt, 2); 669 PetscAssertPointer(list, 5); 670 PetscAssertPointer(value, 6); 671 PetscAssertPointer(n, 7); 672 PetscCheck(*n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") must be > 0", *n); 673 if (set) PetscAssertPointer(set, 8); 674 PetscCall(GetListLength(list, &nlist)); 675 PetscCall(PetscOptionsGetEnumArray(PetscOptionsObject->options, prefix, opt, list, value, n, set)); 676 if (ShouldPrintHelp(PetscOptionsObject)) { 677 const MPI_Comm comm = PetscOptionsObject->comm; 678 const PetscInt nv = *n; 679 680 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%s", Prefix(prefix), opt + 1, list[value[0]])); 681 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%s", list[value[i]])); 682 PetscCall((*PetscHelpPrintf)(comm, ">: %s (choose from)", text)); 683 for (PetscInt i = 0; i < nlist; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i])); 684 PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man))); 685 } 686 PetscFunctionReturn(PETSC_SUCCESS); 687 } 688 689 PetscErrorCode PetscOptionsInt_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt currentvalue, PetscInt *value, PetscBool *set, PetscInt lb, PetscInt ub) 690 { 691 const char *prefix = PetscOptionsObject->prefix; 692 const PetscOptions options = PetscOptionsObject->options; 693 PetscBool wasset; 694 695 PetscFunctionBegin; 696 PetscAssertPointer(opt, 2); 697 PetscAssertPointer(value, 6); 698 if (set) PetscAssertPointer(set, 7); 699 PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, currentvalue, lb); 700 PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, currentvalue, ub); 701 if (!PetscOptionsObject->count) { 702 PetscOptionItem amsopt; 703 704 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt)); 705 PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data)); 706 *(PetscInt *)amsopt->data = currentvalue; 707 708 PetscCall(PetscOptionsGetInt(options, prefix, opt, ¤tvalue, &wasset)); 709 if (wasset) *(PetscInt *)amsopt->data = currentvalue; 710 } 711 PetscCall(PetscOptionsGetInt(options, prefix, opt, value, &wasset)); 712 PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, *value, lb); 713 PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, *value, ub); 714 if (set) *set = wasset; 715 if (ShouldPrintHelp(PetscOptionsObject)) { 716 PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: <now %" PetscInt_FMT " : formerly %" PetscInt_FMT ">: %s (%s)\n", Prefix(prefix), opt + 1, wasset ? *value : currentvalue, currentvalue, text, ManSection(man))); 717 } 718 PetscFunctionReturn(PETSC_SUCCESS); 719 } 720 721 PetscErrorCode PetscOptionsString_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char currentvalue[], char value[], size_t len, PetscBool *set) 722 { 723 const char *prefix = PetscOptionsObject->prefix; 724 PetscBool lset; 725 726 PetscFunctionBegin; 727 PetscAssertPointer(opt, 2); 728 PetscAssertPointer(value, 6); 729 if (set) PetscAssertPointer(set, 8); 730 if (!PetscOptionsObject->count) { 731 PetscOptionItem amsopt; 732 733 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt)); 734 /* must use system malloc since SAWs may free this */ 735 PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data)); 736 } 737 PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset)); 738 if (set) *set = lset; 739 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: <now %s : formerly %s>: %s (%s)\n", Prefix(prefix), opt + 1, lset ? value : currentvalue, currentvalue, text, ManSection(man))); 740 PetscFunctionReturn(PETSC_SUCCESS); 741 } 742 743 PetscErrorCode PetscOptionsReal_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal currentvalue, PetscReal *value, PetscBool *set, PetscReal lb, PetscReal ub) 744 { 745 const char *prefix = PetscOptionsObject->prefix; 746 const PetscOptions options = PetscOptionsObject->options; 747 PetscBool wasset; 748 749 PetscFunctionBegin; 750 PetscAssertPointer(opt, 2); 751 PetscAssertPointer(value, 6); 752 if (set) PetscAssertPointer(set, 7); 753 PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g less than allowed bound %g", (double)currentvalue, (double)lb); 754 PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g greater than allowed bound %g", (double)currentvalue, (double)ub); 755 if (!PetscOptionsObject->count) { 756 PetscOptionItem amsopt; 757 758 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt)); 759 PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data)); 760 *(PetscReal *)amsopt->data = currentvalue; 761 762 PetscCall(PetscOptionsGetReal(options, prefix, opt, ¤tvalue, &wasset)); 763 if (wasset) *(PetscReal *)amsopt->data = currentvalue; 764 } 765 PetscCall(PetscOptionsGetReal(PetscOptionsObject->options, prefix, opt, value, &wasset)); 766 PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g less than allowed bound %g", (double)*value, (double)lb); 767 PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g greater than allowed bound %g", (double)*value, (double)ub); 768 if (set) *set = wasset; 769 if (ShouldPrintHelp(PetscOptionsObject)) { 770 PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: <now %g : formerly %g>: %s (%s)\n", Prefix(prefix), opt + 1, wasset ? (double)*value : (double)currentvalue, (double)currentvalue, text, ManSection(man))); 771 } 772 PetscFunctionReturn(PETSC_SUCCESS); 773 } 774 775 PetscErrorCode PetscOptionsScalar_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar currentvalue, PetscScalar *value, PetscBool *set) 776 { 777 PetscFunctionBegin; 778 #if !defined(PETSC_USE_COMPLEX) 779 PetscCall(PetscOptionsReal(opt, text, man, currentvalue, value, set)); 780 #else 781 PetscCall(PetscOptionsGetScalar(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, set)); 782 #endif 783 PetscFunctionReturn(PETSC_SUCCESS); 784 } 785 786 PetscErrorCode PetscOptionsName_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 787 { 788 const char *prefix = PetscOptionsObject->prefix; 789 790 PetscFunctionBegin; 791 PetscAssertPointer(opt, 2); 792 PetscAssertPointer(flg, 5); 793 if (!PetscOptionsObject->count) { 794 PetscOptionItem amsopt; 795 796 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 797 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 798 799 *(PetscBool *)amsopt->data = PETSC_FALSE; 800 } 801 PetscCall(PetscOptionsHasName(PetscOptionsObject->options, prefix, opt, flg)); 802 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 803 PetscFunctionReturn(PETSC_SUCCESS); 804 } 805 806 PetscErrorCode PetscOptionsFList_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char ltext[], const char man[], PetscFunctionList list, const char currentvalue[], char value[], size_t len, PetscBool *set) 807 { 808 const char *prefix = PetscOptionsObject->prefix; 809 PetscBool lset; 810 811 PetscFunctionBegin; 812 PetscAssertPointer(opt, 2); 813 PetscAssertPointer(value, 7); 814 if (set) PetscAssertPointer(set, 9); 815 if (!PetscOptionsObject->count) { 816 PetscOptionItem amsopt; 817 818 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_FLIST, &amsopt)); 819 /* must use system malloc since SAWs may free this */ 820 PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data)); 821 amsopt->flist = list; 822 } 823 PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset)); 824 if (set) *set = lset; 825 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall(PetscFunctionListPrintTypes(PetscOptionsObject->comm, stdout, Prefix(prefix), opt, ltext, man, list, currentvalue, lset ? value : currentvalue)); 826 PetscFunctionReturn(PETSC_SUCCESS); 827 } 828 829 #ifdef __cplusplus 830 #include <type_traits> 831 #endif 832 833 PetscErrorCode PetscOptionsEList_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char ltext[], const char man[], const char *const *list, PetscInt ntext, const char currentvalue[], PetscInt *value, PetscBool *set) 834 { 835 const char *prefix = PetscOptionsObject->prefix; 836 PetscBool lset; 837 838 PetscFunctionBegin; 839 PetscAssertPointer(opt, 2); 840 PetscAssertPointer(value, 8); 841 if (set) PetscAssertPointer(set, 9); 842 if (!PetscOptionsObject->count) { 843 PetscOptionItem amsopt; 844 845 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_ELIST, &amsopt)); 846 /* must use system malloc since SAWs may free this */ 847 PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data)); 848 PetscCall(PetscStrNArrayallocpy(ntext, list, (char ***)&amsopt->list)); 849 PetscCheck(ntext <= CHAR_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of list entries %" PetscInt_FMT " > %d", ntext, CHAR_MAX); 850 #ifdef __cplusplus 851 static_assert(std::is_same<typename std::decay<decltype(amsopt->nlist)>::type, char>::value, ""); 852 #endif 853 amsopt->nlist = (char)ntext; 854 } 855 PetscCall(PetscOptionsGetEList(PetscOptionsObject->options, prefix, opt, list, ntext, value, &lset)); 856 if (set) *set = lset; 857 if (ShouldPrintHelp(PetscOptionsObject)) { 858 const MPI_Comm comm = PetscOptionsObject->comm; 859 860 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <now %s : formerly %s> %s (choose one of)", Prefix(prefix), opt + 1, lset ? list[*value] : currentvalue, currentvalue, ltext)); 861 for (PetscInt i = 0; i < ntext; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i])); 862 PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man))); 863 } 864 PetscFunctionReturn(PETSC_SUCCESS); 865 } 866 867 PetscErrorCode PetscOptionsBoolGroupBegin_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 868 { 869 const char *prefix = PetscOptionsObject->prefix; 870 871 PetscFunctionBegin; 872 PetscAssertPointer(opt, 2); 873 PetscAssertPointer(flg, 5); 874 if (!PetscOptionsObject->count) { 875 PetscOptionItem amsopt; 876 877 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 878 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 879 880 *(PetscBool *)amsopt->data = PETSC_FALSE; 881 } 882 *flg = PETSC_FALSE; 883 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL)); 884 if (ShouldPrintHelp(PetscOptionsObject)) { 885 const MPI_Comm comm = PetscOptionsObject->comm; 886 887 PetscCall((*PetscHelpPrintf)(comm, " Pick at most one of -------------\n")); 888 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 889 } 890 PetscFunctionReturn(PETSC_SUCCESS); 891 } 892 893 PetscErrorCode PetscOptionsBoolGroup_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 894 { 895 const char *prefix = PetscOptionsObject->prefix; 896 897 PetscFunctionBegin; 898 PetscAssertPointer(opt, 2); 899 PetscAssertPointer(flg, 5); 900 if (!PetscOptionsObject->count) { 901 PetscOptionItem amsopt; 902 903 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 904 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 905 906 *(PetscBool *)amsopt->data = PETSC_FALSE; 907 } 908 *flg = PETSC_FALSE; 909 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL)); 910 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 911 PetscFunctionReturn(PETSC_SUCCESS); 912 } 913 914 PetscErrorCode PetscOptionsBoolGroupEnd_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 915 { 916 const char *prefix = PetscOptionsObject->prefix; 917 918 PetscFunctionBegin; 919 PetscAssertPointer(opt, 2); 920 PetscAssertPointer(flg, 5); 921 if (!PetscOptionsObject->count) { 922 PetscOptionItem amsopt; 923 924 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 925 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 926 927 *(PetscBool *)amsopt->data = PETSC_FALSE; 928 } 929 *flg = PETSC_FALSE; 930 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL)); 931 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 932 PetscFunctionReturn(PETSC_SUCCESS); 933 } 934 935 PetscErrorCode PetscOptionsBool_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool currentvalue, PetscBool *flg, PetscBool *set) 936 { 937 const char *prefix = PetscOptionsObject->prefix; 938 PetscBool iset; 939 940 PetscFunctionBegin; 941 PetscAssertPointer(opt, 2); 942 PetscAssertPointer(flg, 6); 943 if (set) PetscAssertPointer(set, 7); 944 if (!PetscOptionsObject->count) { 945 PetscOptionItem amsopt; 946 947 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 948 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 949 950 *(PetscBool *)amsopt->data = currentvalue; 951 } 952 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, &iset)); 953 if (set) *set = iset; 954 if (ShouldPrintHelp(PetscOptionsObject)) { 955 const char *curvalue = PetscBools[currentvalue]; 956 957 PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: <now %s : formerly %s> %s (%s)\n", Prefix(prefix), opt + 1, iset ? PetscBools[*flg] : curvalue, curvalue, text, ManSection(man))); 958 } 959 PetscFunctionReturn(PETSC_SUCCESS); 960 } 961 962 PetscErrorCode PetscOptionsRealArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal value[], PetscInt *n, PetscBool *set) 963 { 964 const char *prefix = PetscOptionsObject->prefix; 965 966 PetscFunctionBegin; 967 PetscAssertPointer(opt, 2); 968 PetscAssertPointer(n, 6); 969 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 970 if (*n) PetscAssertPointer(value, 5); 971 if (set) PetscAssertPointer(set, 7); 972 if (!PetscOptionsObject->count) { 973 const PetscInt nv = *n; 974 PetscReal *vals; 975 PetscOptionItem amsopt; 976 977 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt)); 978 PetscCall(PetscMalloc(nv * sizeof(*vals), &vals)); 979 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 980 amsopt->arraylength = nv; 981 amsopt->data = vals; 982 } 983 PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 984 if (ShouldPrintHelp(PetscOptionsObject)) { 985 const PetscInt nv = *n; 986 const MPI_Comm comm = PetscOptionsObject->comm; 987 988 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%g", Prefix(prefix), opt + 1, (double)value[0])); 989 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g", (double)value[i])); 990 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 991 } 992 PetscFunctionReturn(PETSC_SUCCESS); 993 } 994 995 PetscErrorCode PetscOptionsScalarArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar value[], PetscInt *n, PetscBool *set) 996 { 997 const char *prefix = PetscOptionsObject->prefix; 998 999 PetscFunctionBegin; 1000 PetscAssertPointer(opt, 2); 1001 PetscAssertPointer(n, 6); 1002 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1003 if (*n) PetscAssertPointer(value, 5); 1004 if (set) PetscAssertPointer(set, 7); 1005 if (!PetscOptionsObject->count) { 1006 const PetscInt nv = *n; 1007 PetscOptionItem amsopt; 1008 PetscScalar *vals; 1009 1010 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt)); 1011 PetscCall(PetscMalloc(nv * sizeof(*vals), &vals)); 1012 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1013 amsopt->arraylength = nv; 1014 amsopt->data = vals; 1015 } 1016 PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1017 if (ShouldPrintHelp(PetscOptionsObject)) { 1018 const PetscInt nv = *n; 1019 const MPI_Comm comm = PetscOptionsObject->comm; 1020 1021 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%g+%gi", Prefix(prefix), opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0]))); 1022 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i]))); 1023 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1024 } 1025 PetscFunctionReturn(PETSC_SUCCESS); 1026 } 1027 1028 PetscErrorCode PetscOptionsIntArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt value[], PetscInt *n, PetscBool *set) 1029 { 1030 const char *prefix = PetscOptionsObject->prefix; 1031 1032 PetscFunctionBegin; 1033 PetscAssertPointer(opt, 2); 1034 PetscAssertPointer(n, 6); 1035 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1036 if (*n) PetscAssertPointer(value, 5); 1037 if (set) PetscAssertPointer(set, 7); 1038 if (!PetscOptionsObject->count) { 1039 const PetscInt nv = *n; 1040 PetscInt *vals; 1041 PetscOptionItem amsopt; 1042 1043 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY, &amsopt)); 1044 PetscCall(PetscMalloc1(nv, &vals)); 1045 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1046 amsopt->arraylength = nv; 1047 amsopt->data = vals; 1048 } 1049 PetscCall(PetscOptionsGetIntArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1050 if (ShouldPrintHelp(PetscOptionsObject)) { 1051 const PetscInt nv = *n; 1052 const MPI_Comm comm = PetscOptionsObject->comm; 1053 1054 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%" PetscInt_FMT, Prefix(prefix), opt + 1, value[0])); 1055 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%" PetscInt_FMT, value[i])); 1056 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1057 } 1058 PetscFunctionReturn(PETSC_SUCCESS); 1059 } 1060 1061 PetscErrorCode PetscOptionsStringArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], char *value[], PetscInt *nmax, PetscBool *set) 1062 { 1063 const char *prefix = PetscOptionsObject->prefix; 1064 1065 PetscFunctionBegin; 1066 PetscAssertPointer(opt, 2); 1067 PetscAssertPointer(nmax, 6); 1068 PetscCheck(*nmax >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *nmax); 1069 if (*nmax) PetscAssertPointer(value, 5); 1070 if (set) PetscAssertPointer(set, 7); 1071 if (!PetscOptionsObject->count) { 1072 const PetscInt nmaxv = *nmax; 1073 PetscOptionItem amsopt; 1074 1075 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt)); 1076 PetscCall(PetscMalloc1(nmaxv, (char **)&amsopt->data)); 1077 amsopt->arraylength = nmaxv; 1078 } 1079 PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, prefix, opt, value, nmax, set)); 1080 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: <string1,string2,...>: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 1081 PetscFunctionReturn(PETSC_SUCCESS); 1082 } 1083 1084 PetscErrorCode PetscOptionsBoolArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool value[], PetscInt *n, PetscBool *set) 1085 { 1086 const char *prefix = PetscOptionsObject->prefix; 1087 1088 PetscFunctionBegin; 1089 PetscAssertPointer(opt, 2); 1090 PetscAssertPointer(n, 6); 1091 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1092 if (*n) PetscAssertPointer(value, 5); 1093 if (set) PetscAssertPointer(set, 7); 1094 if (!PetscOptionsObject->count) { 1095 const PetscInt nv = *n; 1096 PetscBool *vals; 1097 PetscOptionItem amsopt; 1098 1099 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt)); 1100 PetscCall(PetscMalloc1(nv, &vals)); 1101 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1102 amsopt->arraylength = nv; 1103 amsopt->data = vals; 1104 } 1105 PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1106 if (ShouldPrintHelp(PetscOptionsObject)) { 1107 const PetscInt nv = *n; 1108 const MPI_Comm comm = PetscOptionsObject->comm; 1109 1110 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%d", Prefix(prefix), opt + 1, value[0])); 1111 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%d", value[i])); 1112 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1113 } 1114 PetscFunctionReturn(PETSC_SUCCESS); 1115 } 1116 1117 /*MC 1118 PetscOptionsViewer - Gets a viewer appropriate for the type indicated by the user 1119 1120 Synopsis: 1121 #include <petscviewer.h> 1122 PetscErrorCode PetscOptionsViewer(const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set) 1123 1124 Logically Collective on the communicator passed in `PetscOptionsBegin()` 1125 1126 Input Parameters: 1127 + opt - option name 1128 . text - short string that describes the option 1129 - man - manual page with additional information on option 1130 1131 Output Parameters: 1132 + viewer - the viewer 1133 . format - the PetscViewerFormat requested by the user, pass `NULL` if not needed 1134 - set - `PETSC_TRUE` if found, else `PETSC_FALSE` 1135 1136 Level: beginner 1137 1138 Notes: 1139 Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()` 1140 1141 See `PetscOptionsGetViewer()` for the format of the supplied viewer and its options 1142 1143 .seealso: `PetscOptionsGetViewer()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`, 1144 `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 1145 `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 1146 `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 1147 `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 1148 `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 1149 `PetscOptionsFList()`, `PetscOptionsEList()` 1150 M*/ 1151 PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set) 1152 { 1153 const MPI_Comm comm = PetscOptionsObject->comm; 1154 const char *prefix = PetscOptionsObject->prefix; 1155 1156 PetscFunctionBegin; 1157 PetscAssertPointer(opt, 2); 1158 PetscAssertPointer(viewer, 5); 1159 if (format) PetscAssertPointer(format, 6); 1160 if (set) PetscAssertPointer(set, 7); 1161 if (!PetscOptionsObject->count) { 1162 PetscOptionItem amsopt; 1163 1164 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt)); 1165 /* must use system malloc since SAWs may free this */ 1166 PetscCall(PetscStrdup("", (char **)&amsopt->data)); 1167 } 1168 PetscCall(PetscOptionsGetViewer(comm, PetscOptionsObject->options, prefix, opt, viewer, format, set)); 1169 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%s>: %s (%s)\n", Prefix(prefix), opt + 1, "", text, ManSection(man))); 1170 PetscFunctionReturn(PETSC_SUCCESS); 1171 } 1172