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 338 PetscFunctionBegin; 339 PetscCall((*PetscPrintf)(PETSC_COMM_WORLD, "%s --------------------\n", PetscOptionsObject->title)); 340 while (next) { 341 switch (next->type) { 342 case OPTION_HEAD: 343 break; 344 case OPTION_INT_ARRAY: 345 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1)); 346 vald = (PetscInt *)next->data; 347 for (PetscInt i = 0; i < next->arraylength; i++) { 348 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT, vald[i])); 349 if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ",")); 350 } 351 PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man)); 352 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 353 if (str[0]) { 354 PetscToken token; 355 PetscInt n = 0, nmax = next->arraylength, *dvalue = (PetscInt *)next->data, start, end; 356 size_t i, len; 357 char *value; 358 PetscBool foundrange; 359 360 next->set = PETSC_TRUE; 361 value = str; 362 PetscCall(PetscTokenCreate(value, ',', &token)); 363 PetscCall(PetscTokenFind(token, &value)); 364 while (n < nmax) { 365 if (!value) break; 366 367 /* look for form d-D where d and D are integers */ 368 foundrange = PETSC_FALSE; 369 PetscCall(PetscStrlen(value, &len)); 370 if (value[0] == '-') i = 2; 371 else i = 1; 372 for (; i < len; i++) { 373 if (value[i] == '-') { 374 PetscCheck(i != len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, value); 375 value[i] = 0; 376 PetscCall(PetscOptionsStringToInt(value, &start)); 377 PetscCall(PetscOptionsStringToInt(value + i + 1, &end)); 378 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); 379 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); 380 for (; start < end; start++) { 381 *dvalue = start; 382 dvalue++; 383 n++; 384 } 385 foundrange = PETSC_TRUE; 386 break; 387 } 388 } 389 if (!foundrange) { 390 PetscCall(PetscOptionsStringToInt(value, dvalue)); 391 dvalue++; 392 n++; 393 } 394 PetscCall(PetscTokenFind(token, &value)); 395 } 396 PetscCall(PetscTokenDestroy(&token)); 397 } 398 break; 399 case OPTION_REAL_ARRAY: 400 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1)); 401 valr = (PetscReal *)next->data; 402 for (PetscInt i = 0; i < next->arraylength; i++) { 403 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%g", (double)valr[i])); 404 if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ",")); 405 } 406 PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man)); 407 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 408 if (str[0]) { 409 PetscToken token; 410 PetscInt n = 0, nmax = next->arraylength; 411 PetscReal *dvalue = (PetscReal *)next->data; 412 char *value; 413 414 next->set = PETSC_TRUE; 415 value = str; 416 PetscCall(PetscTokenCreate(value, ',', &token)); 417 PetscCall(PetscTokenFind(token, &value)); 418 while (n < nmax) { 419 if (!value) break; 420 PetscCall(PetscOptionsStringToReal(value, dvalue)); 421 dvalue++; 422 n++; 423 PetscCall(PetscTokenFind(token, &value)); 424 } 425 PetscCall(PetscTokenDestroy(&token)); 426 } 427 break; 428 case OPTION_INT: 429 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%d>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(int *)next->data, next->text, next->man)); 430 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 431 if (str[0]) { 432 #if defined(PETSC_SIZEOF_LONG_LONG) 433 long long lid; 434 sscanf(str, "%lld", &lid); 435 PetscCheck(lid <= PETSC_INT_MAX && lid >= PETSC_INT_MIN, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %lld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid); 436 #else 437 long lid; 438 sscanf(str, "%ld", &lid); 439 PetscCheck(lid <= PETSC_INT_MAX && lid >= PETSC_INT_MIN, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %ld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid); 440 #endif 441 442 next->set = PETSC_TRUE; 443 *((PetscInt *)next->data) = (PetscInt)lid; 444 } 445 break; 446 case OPTION_REAL: 447 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%g>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(double *)next->data, next->text, next->man)); 448 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 449 if (str[0]) { 450 #if defined(PETSC_USE_REAL_SINGLE) 451 sscanf(str, "%e", &ir); 452 #elif defined(PETSC_USE_REAL___FP16) 453 float irtemp; 454 sscanf(str, "%e", &irtemp); 455 ir = irtemp; 456 #elif defined(PETSC_USE_REAL_DOUBLE) 457 sscanf(str, "%le", &ir); 458 #elif defined(PETSC_USE_REAL___FLOAT128) 459 ir = strtoflt128(str, 0); 460 #else 461 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Unknown scalar type"); 462 #endif 463 next->set = PETSC_TRUE; 464 *((PetscReal *)next->data) = ir; 465 } 466 break; 467 case OPTION_BOOL: 468 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)); 469 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 470 if (str[0]) { 471 PetscCall(PetscOptionsStringToBool(str, &bid)); 472 next->set = PETSC_TRUE; 473 *((PetscBool *)next->data) = bid; 474 } 475 break; 476 case OPTION_STRING: 477 PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%s>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, (char *)next->data, next->text, next->man)); 478 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 479 if (str[0]) { 480 next->set = PETSC_TRUE; 481 /* must use system malloc since SAWs may free this */ 482 PetscCall(PetscStrdup(str, (char **)&next->data)); 483 } 484 break; 485 case OPTION_FLIST: 486 PetscCall(PetscFunctionListPrintTypes(PETSC_COMM_WORLD, stdout, PetscOptionsObject->prefix, next->option, next->text, next->man, next->flist, (char *)next->data, (char *)next->data)); 487 PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str)); 488 if (str[0]) { 489 PetscOptionsObject->changedmethod = PETSC_TRUE; 490 next->set = PETSC_TRUE; 491 /* must use system malloc since SAWs may free this */ 492 PetscCall(PetscStrdup(str, (char **)&next->data)); 493 } 494 break; 495 default: 496 break; 497 } 498 next = next->next; 499 } 500 PetscFunctionReturn(PETSC_SUCCESS); 501 } 502 #endif 503 504 PetscErrorCode PetscOptionsEnd_Private(PetscOptionItems *PetscOptionsObject) 505 { 506 PetscOptionItem next, last; 507 508 PetscFunctionBegin; 509 if (PetscOptionsObject->next) { 510 if (!PetscOptionsObject->count) { 511 #if defined(PETSC_HAVE_SAWS) 512 PetscCall(PetscOptionsSAWsInput(PetscOptionsObject)); 513 #else 514 PetscCall(PetscOptionsGetFromTextInput(PetscOptionsObject)); 515 #endif 516 } 517 } 518 519 PetscCall(PetscFree(PetscOptionsObject->title)); 520 521 /* reset counter to -2; this updates the screen with the new options for the selected method */ 522 if (PetscOptionsObject->changedmethod) PetscOptionsObject->count = -2; 523 /* reset alreadyprinted flag */ 524 PetscOptionsObject->alreadyprinted = PETSC_FALSE; 525 if (PetscOptionsObject->object) PetscOptionsObject->object->optionsprinted = PETSC_TRUE; 526 PetscOptionsObject->object = NULL; 527 528 while ((next = PetscOptionsObject->next)) { 529 const PetscOptionType type = next->type; 530 const size_t arraylength = next->arraylength; 531 void *data = next->data; 532 533 if (next->set) { 534 char option[256], value[1024], tmp[32]; 535 536 if (PetscOptionsObject->prefix) { 537 PetscCall(PetscStrncpy(option, "-", sizeof(option))); 538 PetscCall(PetscStrlcat(option, PetscOptionsObject->prefix, sizeof(option))); 539 PetscCall(PetscStrlcat(option, next->option + 1, sizeof(option))); 540 } else { 541 PetscCall(PetscStrncpy(option, next->option, sizeof(option))); 542 } 543 544 switch (type) { 545 case OPTION_HEAD: 546 break; 547 case OPTION_INT_ARRAY: 548 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscInt *)data)[0])); 549 for (size_t j = 1; j < arraylength; ++j) { 550 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscInt *)data)[j])); 551 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 552 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 553 } 554 break; 555 case OPTION_INT: 556 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)*(PetscInt *)data)); 557 break; 558 case OPTION_REAL: 559 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)*(PetscReal *)data)); 560 break; 561 case OPTION_REAL_ARRAY: 562 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)((PetscReal *)data)[0])); 563 for (size_t j = 1; j < arraylength; ++j) { 564 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g", (double)((PetscReal *)data)[j])); 565 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 566 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 567 } 568 break; 569 case OPTION_SCALAR_ARRAY: 570 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[0]), (double)PetscImaginaryPart(((PetscScalar *)data)[0]))); 571 for (size_t j = 1; j < arraylength; ++j) { 572 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[j]), (double)PetscImaginaryPart(((PetscScalar *)data)[j]))); 573 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 574 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 575 } 576 break; 577 case OPTION_BOOL: 578 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", *(int *)data)); 579 break; 580 case OPTION_BOOL_ARRAY: 581 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscBool *)data)[0])); 582 for (size_t j = 1; j < arraylength; ++j) { 583 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscBool *)data)[j])); 584 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 585 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 586 } 587 break; 588 case OPTION_FLIST: // fall-through 589 case OPTION_ELIST: // fall-through 590 case OPTION_STRING: 591 PetscCall(PetscStrncpy(value, (char *)data, sizeof(value))); 592 break; 593 case OPTION_STRING_ARRAY: 594 PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%s", ((char **)data)[0])); 595 for (size_t j = 1; j < arraylength; j++) { 596 PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%s", ((char **)data)[j])); 597 PetscCall(PetscStrlcat(value, ",", sizeof(value))); 598 PetscCall(PetscStrlcat(value, tmp, sizeof(value))); 599 } 600 break; 601 } 602 PetscCall(PetscOptionsSetValue(PetscOptionsObject->options, option, value)); 603 } 604 if (type == OPTION_ELIST) PetscCall(PetscStrNArrayDestroy(next->nlist, (char ***)&next->list)); 605 PetscCall(PetscFree(next->text)); 606 PetscCall(PetscFree(next->option)); 607 PetscCall(PetscFree(next->man)); 608 PetscCall(PetscFree(next->edata)); 609 610 if (type == OPTION_STRING || type == OPTION_FLIST || type == OPTION_ELIST) { 611 free(data); 612 } else { 613 // use next->data instead of data because PetscFree() sets it to NULL 614 PetscCall(PetscFree(next->data)); 615 } 616 617 last = next; 618 PetscOptionsObject->next = next->next; 619 PetscCall(PetscFree(last)); 620 } 621 PetscCall(PetscFree(PetscOptionsObject->prefix)); 622 PetscOptionsObject->next = NULL; 623 PetscFunctionReturn(PETSC_SUCCESS); 624 } 625 626 static PetscErrorCode GetListLength(const char *const *list, PetscInt *len) 627 { 628 PetscInt retlen = 0; 629 630 PetscFunctionBegin; 631 PetscAssertPointer(len, 2); 632 while (list[retlen]) { 633 PetscAssertPointer(list[retlen], 1); 634 PetscCheck(++retlen < 50, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "List argument appears to be wrong or have more than 50 entries"); 635 } 636 PetscCheck(retlen > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least 2 entries: typename and type prefix"); 637 /* drop item name and prefix*/ 638 *len = retlen - 2; 639 PetscFunctionReturn(PETSC_SUCCESS); 640 } 641 642 PetscErrorCode PetscOptionsEnum_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum currentvalue, PetscEnum *value, PetscBool *set) 643 { 644 PetscInt ntext = 0; 645 PetscInt tval; 646 PetscBool tflg; 647 648 PetscFunctionBegin; 649 PetscAssertPointer(opt, 2); 650 PetscAssertPointer(list, 5); 651 PetscAssertPointer(value, 7); 652 if (set) PetscAssertPointer(set, 8); 653 PetscCall(GetListLength(list, &ntext)); 654 PetscCall(PetscOptionsEList_Private(PetscOptionsObject, opt, text, man, list, ntext, list[currentvalue], &tval, &tflg)); 655 /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */ 656 if (tflg) *value = (PetscEnum)tval; 657 if (set) *set = tflg; 658 PetscFunctionReturn(PETSC_SUCCESS); 659 } 660 661 PetscErrorCode PetscOptionsEnumArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum value[], PetscInt *n, PetscBool *set) 662 { 663 PetscInt nlist = 0; 664 const char *prefix = PetscOptionsObject->prefix; 665 666 PetscFunctionBegin; 667 PetscAssertPointer(opt, 2); 668 PetscAssertPointer(list, 5); 669 PetscAssertPointer(value, 6); 670 PetscAssertPointer(n, 7); 671 PetscCheck(*n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") must be > 0", *n); 672 if (set) PetscAssertPointer(set, 8); 673 PetscCall(GetListLength(list, &nlist)); 674 PetscCall(PetscOptionsGetEnumArray(PetscOptionsObject->options, prefix, opt, list, value, n, set)); 675 if (ShouldPrintHelp(PetscOptionsObject)) { 676 const MPI_Comm comm = PetscOptionsObject->comm; 677 const PetscInt nv = *n; 678 679 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%s", Prefix(prefix), opt + 1, list[value[0]])); 680 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%s", list[value[i]])); 681 PetscCall((*PetscHelpPrintf)(comm, ">: %s (choose from)", text)); 682 for (PetscInt i = 0; i < nlist; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i])); 683 PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man))); 684 } 685 PetscFunctionReturn(PETSC_SUCCESS); 686 } 687 688 PetscErrorCode PetscOptionsInt_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt currentvalue, PetscInt *value, PetscBool *set, PetscInt lb, PetscInt ub) 689 { 690 const char *prefix = PetscOptionsObject->prefix; 691 const PetscOptions options = PetscOptionsObject->options; 692 PetscBool wasset; 693 694 PetscFunctionBegin; 695 PetscAssertPointer(opt, 2); 696 PetscAssertPointer(value, 6); 697 if (set) PetscAssertPointer(set, 7); 698 PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, currentvalue, lb); 699 PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, currentvalue, ub); 700 if (!PetscOptionsObject->count) { 701 PetscOptionItem amsopt; 702 703 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt)); 704 PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data)); 705 *(PetscInt *)amsopt->data = currentvalue; 706 707 PetscCall(PetscOptionsGetInt(options, prefix, opt, ¤tvalue, &wasset)); 708 if (wasset) *(PetscInt *)amsopt->data = currentvalue; 709 } 710 PetscCall(PetscOptionsGetInt(options, prefix, opt, value, &wasset)); 711 PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, *value, lb); 712 PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, *value, ub); 713 if (set) *set = wasset; 714 if (ShouldPrintHelp(PetscOptionsObject)) { 715 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))); 716 } 717 PetscFunctionReturn(PETSC_SUCCESS); 718 } 719 720 PetscErrorCode PetscOptionsMPIInt_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscMPIInt currentvalue, PetscMPIInt *value, PetscBool *set, PetscMPIInt lb, PetscMPIInt ub) 721 { 722 const char *prefix = PetscOptionsObject->prefix; 723 const PetscOptions options = PetscOptionsObject->options; 724 PetscBool wasset; 725 726 PetscFunctionBegin; 727 PetscAssertPointer(opt, 2); 728 PetscAssertPointer(value, 6); 729 if (set) PetscAssertPointer(set, 7); 730 PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d less than allowed bound %d", currentvalue, lb); 731 PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d greater than allowed bound %d", currentvalue, ub); 732 if (!PetscOptionsObject->count) { 733 PetscOptionItem amsopt; 734 735 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt)); 736 PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data)); 737 *(PetscMPIInt *)amsopt->data = currentvalue; 738 739 PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, ¤tvalue, &wasset)); 740 if (wasset) *(PetscMPIInt *)amsopt->data = currentvalue; 741 } 742 PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, value, &wasset)); 743 PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d less than allowed bound %d", *value, lb); 744 PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d greater than allowed bound %d", *value, ub); 745 if (set) *set = wasset; 746 if (ShouldPrintHelp(PetscOptionsObject)) { PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: <now %d : formerly %d>: %s (%s)\n", Prefix(prefix), opt + 1, wasset ? *value : currentvalue, currentvalue, text, ManSection(man))); } 747 PetscFunctionReturn(PETSC_SUCCESS); 748 } 749 750 PetscErrorCode PetscOptionsString_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char currentvalue[], char value[], size_t len, PetscBool *set) 751 { 752 const char *prefix = PetscOptionsObject->prefix; 753 PetscBool lset; 754 755 PetscFunctionBegin; 756 PetscAssertPointer(opt, 2); 757 PetscAssertPointer(value, 6); 758 if (set) PetscAssertPointer(set, 8); 759 if (!PetscOptionsObject->count) { 760 PetscOptionItem amsopt; 761 762 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt)); 763 /* must use system malloc since SAWs may free this */ 764 PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data)); 765 } 766 PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset)); 767 if (set) *set = lset; 768 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))); 769 PetscFunctionReturn(PETSC_SUCCESS); 770 } 771 772 PetscErrorCode PetscOptionsReal_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal currentvalue, PetscReal *value, PetscBool *set, PetscReal lb, PetscReal ub) 773 { 774 const char *prefix = PetscOptionsObject->prefix; 775 const PetscOptions options = PetscOptionsObject->options; 776 PetscBool wasset; 777 778 PetscFunctionBegin; 779 PetscAssertPointer(opt, 2); 780 PetscAssertPointer(value, 6); 781 if (set) PetscAssertPointer(set, 7); 782 PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g less than allowed bound %g", (double)currentvalue, (double)lb); 783 PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g greater than allowed bound %g", (double)currentvalue, (double)ub); 784 if (!PetscOptionsObject->count) { 785 PetscOptionItem amsopt; 786 787 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt)); 788 PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data)); 789 *(PetscReal *)amsopt->data = currentvalue; 790 791 PetscCall(PetscOptionsGetReal(options, prefix, opt, ¤tvalue, &wasset)); 792 if (wasset) *(PetscReal *)amsopt->data = currentvalue; 793 } 794 PetscCall(PetscOptionsGetReal(PetscOptionsObject->options, prefix, opt, value, &wasset)); 795 PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g less than allowed bound %g", (double)*value, (double)lb); 796 PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g greater than allowed bound %g", (double)*value, (double)ub); 797 if (set) *set = wasset; 798 if (ShouldPrintHelp(PetscOptionsObject)) { 799 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))); 800 } 801 PetscFunctionReturn(PETSC_SUCCESS); 802 } 803 804 PetscErrorCode PetscOptionsScalar_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar currentvalue, PetscScalar *value, PetscBool *set) 805 { 806 PetscFunctionBegin; 807 #if !defined(PETSC_USE_COMPLEX) 808 PetscCall(PetscOptionsReal(opt, text, man, currentvalue, value, set)); 809 #else 810 PetscCall(PetscOptionsGetScalar(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, set)); 811 #endif 812 PetscFunctionReturn(PETSC_SUCCESS); 813 } 814 815 PetscErrorCode PetscOptionsName_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 816 { 817 const char *prefix = PetscOptionsObject->prefix; 818 819 PetscFunctionBegin; 820 PetscAssertPointer(opt, 2); 821 PetscAssertPointer(flg, 5); 822 if (!PetscOptionsObject->count) { 823 PetscOptionItem amsopt; 824 825 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 826 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 827 828 *(PetscBool *)amsopt->data = PETSC_FALSE; 829 } 830 PetscCall(PetscOptionsHasName(PetscOptionsObject->options, prefix, opt, flg)); 831 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 832 PetscFunctionReturn(PETSC_SUCCESS); 833 } 834 835 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) 836 { 837 const char *prefix = PetscOptionsObject->prefix; 838 PetscBool lset; 839 840 PetscFunctionBegin; 841 PetscAssertPointer(opt, 2); 842 PetscAssertPointer(value, 7); 843 if (set) PetscAssertPointer(set, 9); 844 if (!PetscOptionsObject->count) { 845 PetscOptionItem amsopt; 846 847 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_FLIST, &amsopt)); 848 /* must use system malloc since SAWs may free this */ 849 PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data)); 850 amsopt->flist = list; 851 } 852 PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset)); 853 if (set) *set = lset; 854 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall(PetscFunctionListPrintTypes(PetscOptionsObject->comm, stdout, Prefix(prefix), opt, ltext, man, list, currentvalue, lset ? value : currentvalue)); 855 PetscFunctionReturn(PETSC_SUCCESS); 856 } 857 858 #ifdef __cplusplus 859 #include <type_traits> 860 #endif 861 862 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) 863 { 864 const char *prefix = PetscOptionsObject->prefix; 865 PetscBool lset; 866 867 PetscFunctionBegin; 868 PetscAssertPointer(opt, 2); 869 PetscAssertPointer(value, 8); 870 if (set) PetscAssertPointer(set, 9); 871 if (!PetscOptionsObject->count) { 872 PetscOptionItem amsopt; 873 874 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_ELIST, &amsopt)); 875 /* must use system malloc since SAWs may free this */ 876 PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data)); 877 PetscCall(PetscStrNArrayallocpy(ntext, list, (char ***)&amsopt->list)); 878 PetscCheck(ntext <= CHAR_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of list entries %" PetscInt_FMT " > %d", ntext, CHAR_MAX); 879 #ifdef __cplusplus 880 static_assert(std::is_same<typename std::decay<decltype(amsopt->nlist)>::type, char>::value, ""); 881 #endif 882 amsopt->nlist = (char)ntext; 883 } 884 PetscCall(PetscOptionsGetEList(PetscOptionsObject->options, prefix, opt, list, ntext, value, &lset)); 885 if (set) *set = lset; 886 if (ShouldPrintHelp(PetscOptionsObject)) { 887 const MPI_Comm comm = PetscOptionsObject->comm; 888 889 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <now %s : formerly %s> %s (choose one of)", Prefix(prefix), opt + 1, lset ? list[*value] : currentvalue, currentvalue, ltext)); 890 for (PetscInt i = 0; i < ntext; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i])); 891 PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man))); 892 } 893 PetscFunctionReturn(PETSC_SUCCESS); 894 } 895 896 PetscErrorCode PetscOptionsBoolGroupBegin_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 897 { 898 const char *prefix = PetscOptionsObject->prefix; 899 900 PetscFunctionBegin; 901 PetscAssertPointer(opt, 2); 902 PetscAssertPointer(flg, 5); 903 if (!PetscOptionsObject->count) { 904 PetscOptionItem amsopt; 905 906 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 907 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 908 909 *(PetscBool *)amsopt->data = PETSC_FALSE; 910 } 911 *flg = PETSC_FALSE; 912 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL)); 913 if (ShouldPrintHelp(PetscOptionsObject)) { 914 const MPI_Comm comm = PetscOptionsObject->comm; 915 916 PetscCall((*PetscHelpPrintf)(comm, " Pick at most one of -------------\n")); 917 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 918 } 919 PetscFunctionReturn(PETSC_SUCCESS); 920 } 921 922 PetscErrorCode PetscOptionsBoolGroup_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 923 { 924 const char *prefix = PetscOptionsObject->prefix; 925 926 PetscFunctionBegin; 927 PetscAssertPointer(opt, 2); 928 PetscAssertPointer(flg, 5); 929 if (!PetscOptionsObject->count) { 930 PetscOptionItem amsopt; 931 932 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 933 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 934 935 *(PetscBool *)amsopt->data = PETSC_FALSE; 936 } 937 *flg = PETSC_FALSE; 938 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL)); 939 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 940 PetscFunctionReturn(PETSC_SUCCESS); 941 } 942 943 PetscErrorCode PetscOptionsBoolGroupEnd_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 944 { 945 const char *prefix = PetscOptionsObject->prefix; 946 947 PetscFunctionBegin; 948 PetscAssertPointer(opt, 2); 949 PetscAssertPointer(flg, 5); 950 if (!PetscOptionsObject->count) { 951 PetscOptionItem amsopt; 952 953 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 954 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 955 956 *(PetscBool *)amsopt->data = PETSC_FALSE; 957 } 958 *flg = PETSC_FALSE; 959 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL)); 960 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 961 PetscFunctionReturn(PETSC_SUCCESS); 962 } 963 964 PetscErrorCode PetscOptionsBool_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool currentvalue, PetscBool *flg, PetscBool *set) 965 { 966 const char *prefix = PetscOptionsObject->prefix; 967 PetscBool iset; 968 969 PetscFunctionBegin; 970 PetscAssertPointer(opt, 2); 971 PetscAssertPointer(flg, 6); 972 if (set) PetscAssertPointer(set, 7); 973 if (!PetscOptionsObject->count) { 974 PetscOptionItem amsopt; 975 976 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 977 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 978 979 *(PetscBool *)amsopt->data = currentvalue; 980 } 981 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, &iset)); 982 if (set) *set = iset; 983 if (ShouldPrintHelp(PetscOptionsObject)) { 984 const char *curvalue = PetscBools[currentvalue]; 985 986 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))); 987 } 988 PetscFunctionReturn(PETSC_SUCCESS); 989 } 990 991 PetscErrorCode PetscOptionsRealArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal value[], PetscInt *n, PetscBool *set) 992 { 993 const char *prefix = PetscOptionsObject->prefix; 994 995 PetscFunctionBegin; 996 PetscAssertPointer(opt, 2); 997 PetscAssertPointer(n, 6); 998 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 999 if (*n) PetscAssertPointer(value, 5); 1000 if (set) PetscAssertPointer(set, 7); 1001 if (!PetscOptionsObject->count) { 1002 const PetscInt nv = *n; 1003 PetscReal *vals; 1004 PetscOptionItem amsopt; 1005 1006 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt)); 1007 PetscCall(PetscMalloc(nv * sizeof(*vals), &vals)); 1008 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1009 amsopt->arraylength = nv; 1010 amsopt->data = vals; 1011 } 1012 PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1013 if (ShouldPrintHelp(PetscOptionsObject)) { 1014 const PetscInt nv = *n; 1015 const MPI_Comm comm = PetscOptionsObject->comm; 1016 1017 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%g", Prefix(prefix), opt + 1, (double)value[0])); 1018 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g", (double)value[i])); 1019 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1020 } 1021 PetscFunctionReturn(PETSC_SUCCESS); 1022 } 1023 1024 PetscErrorCode PetscOptionsScalarArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar value[], PetscInt *n, PetscBool *set) 1025 { 1026 const char *prefix = PetscOptionsObject->prefix; 1027 1028 PetscFunctionBegin; 1029 PetscAssertPointer(opt, 2); 1030 PetscAssertPointer(n, 6); 1031 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1032 if (*n) PetscAssertPointer(value, 5); 1033 if (set) PetscAssertPointer(set, 7); 1034 if (!PetscOptionsObject->count) { 1035 const PetscInt nv = *n; 1036 PetscOptionItem amsopt; 1037 PetscScalar *vals; 1038 1039 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt)); 1040 PetscCall(PetscMalloc(nv * sizeof(*vals), &vals)); 1041 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1042 amsopt->arraylength = nv; 1043 amsopt->data = vals; 1044 } 1045 PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1046 if (ShouldPrintHelp(PetscOptionsObject)) { 1047 const PetscInt nv = *n; 1048 const MPI_Comm comm = PetscOptionsObject->comm; 1049 1050 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%g+%gi", Prefix(prefix), opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0]))); 1051 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i]))); 1052 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1053 } 1054 PetscFunctionReturn(PETSC_SUCCESS); 1055 } 1056 1057 PetscErrorCode PetscOptionsIntArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt value[], PetscInt *n, PetscBool *set) 1058 { 1059 const char *prefix = PetscOptionsObject->prefix; 1060 1061 PetscFunctionBegin; 1062 PetscAssertPointer(opt, 2); 1063 PetscAssertPointer(n, 6); 1064 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1065 if (*n) PetscAssertPointer(value, 5); 1066 if (set) PetscAssertPointer(set, 7); 1067 if (!PetscOptionsObject->count) { 1068 const PetscInt nv = *n; 1069 PetscInt *vals; 1070 PetscOptionItem amsopt; 1071 1072 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY, &amsopt)); 1073 PetscCall(PetscMalloc1(nv, &vals)); 1074 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1075 amsopt->arraylength = nv; 1076 amsopt->data = vals; 1077 } 1078 PetscCall(PetscOptionsGetIntArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1079 if (ShouldPrintHelp(PetscOptionsObject)) { 1080 const PetscInt nv = *n; 1081 const MPI_Comm comm = PetscOptionsObject->comm; 1082 1083 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%" PetscInt_FMT, Prefix(prefix), opt + 1, value[0])); 1084 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%" PetscInt_FMT, value[i])); 1085 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1086 } 1087 PetscFunctionReturn(PETSC_SUCCESS); 1088 } 1089 1090 PetscErrorCode PetscOptionsStringArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], char *value[], PetscInt *nmax, PetscBool *set) 1091 { 1092 const char *prefix = PetscOptionsObject->prefix; 1093 1094 PetscFunctionBegin; 1095 PetscAssertPointer(opt, 2); 1096 PetscAssertPointer(nmax, 6); 1097 PetscCheck(*nmax >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *nmax); 1098 if (*nmax) PetscAssertPointer(value, 5); 1099 if (set) PetscAssertPointer(set, 7); 1100 if (!PetscOptionsObject->count) { 1101 const PetscInt nmaxv = *nmax; 1102 PetscOptionItem amsopt; 1103 1104 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt)); 1105 PetscCall(PetscMalloc1(nmaxv, (char **)&amsopt->data)); 1106 amsopt->arraylength = nmaxv; 1107 } 1108 PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, prefix, opt, value, nmax, set)); 1109 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: <string1,string2,...>: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 1110 PetscFunctionReturn(PETSC_SUCCESS); 1111 } 1112 1113 PetscErrorCode PetscOptionsBoolArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool value[], PetscInt *n, PetscBool *set) 1114 { 1115 const char *prefix = PetscOptionsObject->prefix; 1116 1117 PetscFunctionBegin; 1118 PetscAssertPointer(opt, 2); 1119 PetscAssertPointer(n, 6); 1120 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1121 if (*n) PetscAssertPointer(value, 5); 1122 if (set) PetscAssertPointer(set, 7); 1123 if (!PetscOptionsObject->count) { 1124 const PetscInt nv = *n; 1125 PetscBool *vals; 1126 PetscOptionItem amsopt; 1127 1128 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt)); 1129 PetscCall(PetscMalloc1(nv, &vals)); 1130 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1131 amsopt->arraylength = nv; 1132 amsopt->data = vals; 1133 } 1134 PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1135 if (ShouldPrintHelp(PetscOptionsObject)) { 1136 const PetscInt nv = *n; 1137 const MPI_Comm comm = PetscOptionsObject->comm; 1138 1139 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%d", Prefix(prefix), opt + 1, value[0])); 1140 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%d", value[i])); 1141 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1142 } 1143 PetscFunctionReturn(PETSC_SUCCESS); 1144 } 1145 1146 /*MC 1147 PetscOptionsViewer - Creates a viewer appropriate for the type indicated by the user 1148 1149 Synopsis: 1150 #include <petscviewer.h> 1151 PetscErrorCode PetscOptionsViewer(const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set) 1152 1153 Logically Collective on the communicator passed in `PetscOptionsBegin()` 1154 1155 Input Parameters: 1156 + opt - option name 1157 . text - short string that describes the option 1158 - man - manual page with additional information on option 1159 1160 Output Parameters: 1161 + viewer - the viewer 1162 . format - the PetscViewerFormat requested by the user, pass `NULL` if not needed 1163 - set - `PETSC_TRUE` if found, else `PETSC_FALSE` 1164 1165 Level: beginner 1166 1167 Notes: 1168 Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()` 1169 1170 See `PetscOptionsCreateViewer()` for the format of the supplied viewer and its options 1171 1172 .seealso: `PetscOptionsCreateViewer()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`, 1173 `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 1174 `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 1175 `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 1176 `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 1177 `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 1178 `PetscOptionsFList()`, `PetscOptionsEList()` 1179 M*/ 1180 PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set) 1181 { 1182 const MPI_Comm comm = PetscOptionsObject->comm; 1183 const char *prefix = PetscOptionsObject->prefix; 1184 1185 PetscFunctionBegin; 1186 PetscAssertPointer(opt, 2); 1187 PetscAssertPointer(viewer, 5); 1188 if (format) PetscAssertPointer(format, 6); 1189 if (set) PetscAssertPointer(set, 7); 1190 if (!PetscOptionsObject->count) { 1191 PetscOptionItem amsopt; 1192 1193 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt)); 1194 /* must use system malloc since SAWs may free this */ 1195 PetscCall(PetscStrdup("", (char **)&amsopt->data)); 1196 } 1197 PetscCall(PetscOptionsCreateViewer(comm, PetscOptionsObject->options, prefix, opt, viewer, format, set)); 1198 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%s>: %s (%s)\n", Prefix(prefix), opt + 1, "", text, ManSection(man))); 1199 PetscFunctionReturn(PETSC_SUCCESS); 1200 } 1201