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 len; 357 char *value; 358 PetscBool foundrange; 359 PetscInt i; 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 < (PetscInt)len; i++) { 374 if (value[i] == '-') { 375 PetscCheck(i != (PetscInt)(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 (PetscInt 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 PetscOptionsMPIInt_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscMPIInt currentvalue, PetscMPIInt *value, PetscBool *set, PetscMPIInt lb, PetscMPIInt ub) 722 { 723 const char *prefix = PetscOptionsObject->prefix; 724 const PetscOptions options = PetscOptionsObject->options; 725 PetscBool wasset; 726 727 PetscFunctionBegin; 728 PetscAssertPointer(opt, 2); 729 PetscAssertPointer(value, 6); 730 if (set) PetscAssertPointer(set, 7); 731 PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d less than allowed bound %d", currentvalue, lb); 732 PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d greater than allowed bound %d", currentvalue, ub); 733 if (!PetscOptionsObject->count) { 734 PetscOptionItem amsopt; 735 736 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt)); 737 PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data)); 738 *(PetscMPIInt *)amsopt->data = currentvalue; 739 740 PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, ¤tvalue, &wasset)); 741 if (wasset) *(PetscMPIInt *)amsopt->data = currentvalue; 742 } 743 PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, value, &wasset)); 744 PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d less than allowed bound %d", *value, lb); 745 PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d greater than allowed bound %d", *value, ub); 746 if (set) *set = wasset; 747 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))); } 748 PetscFunctionReturn(PETSC_SUCCESS); 749 } 750 751 PetscErrorCode PetscOptionsString_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char currentvalue[], char value[], size_t len, PetscBool *set) 752 { 753 const char *prefix = PetscOptionsObject->prefix; 754 PetscBool lset; 755 756 PetscFunctionBegin; 757 PetscAssertPointer(opt, 2); 758 PetscAssertPointer(value, 6); 759 if (set) PetscAssertPointer(set, 8); 760 if (!PetscOptionsObject->count) { 761 PetscOptionItem amsopt; 762 763 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt)); 764 /* must use system malloc since SAWs may free this */ 765 PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data)); 766 } 767 PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset)); 768 if (set) *set = lset; 769 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))); 770 PetscFunctionReturn(PETSC_SUCCESS); 771 } 772 773 PetscErrorCode PetscOptionsReal_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal currentvalue, PetscReal *value, PetscBool *set, PetscReal lb, PetscReal ub) 774 { 775 const char *prefix = PetscOptionsObject->prefix; 776 const PetscOptions options = PetscOptionsObject->options; 777 PetscBool wasset; 778 779 PetscFunctionBegin; 780 PetscAssertPointer(opt, 2); 781 PetscAssertPointer(value, 6); 782 if (set) PetscAssertPointer(set, 7); 783 PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g less than allowed bound %g", (double)currentvalue, (double)lb); 784 PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g greater than allowed bound %g", (double)currentvalue, (double)ub); 785 if (!PetscOptionsObject->count) { 786 PetscOptionItem amsopt; 787 788 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt)); 789 PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data)); 790 *(PetscReal *)amsopt->data = currentvalue; 791 792 PetscCall(PetscOptionsGetReal(options, prefix, opt, ¤tvalue, &wasset)); 793 if (wasset) *(PetscReal *)amsopt->data = currentvalue; 794 } 795 PetscCall(PetscOptionsGetReal(PetscOptionsObject->options, prefix, opt, value, &wasset)); 796 PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g less than allowed bound %g", (double)*value, (double)lb); 797 PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g greater than allowed bound %g", (double)*value, (double)ub); 798 if (set) *set = wasset; 799 if (ShouldPrintHelp(PetscOptionsObject)) { 800 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))); 801 } 802 PetscFunctionReturn(PETSC_SUCCESS); 803 } 804 805 PetscErrorCode PetscOptionsScalar_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar currentvalue, PetscScalar *value, PetscBool *set) 806 { 807 PetscFunctionBegin; 808 #if !defined(PETSC_USE_COMPLEX) 809 PetscCall(PetscOptionsReal(opt, text, man, currentvalue, value, set)); 810 #else 811 PetscCall(PetscOptionsGetScalar(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, set)); 812 #endif 813 PetscFunctionReturn(PETSC_SUCCESS); 814 } 815 816 PetscErrorCode PetscOptionsName_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 817 { 818 const char *prefix = PetscOptionsObject->prefix; 819 820 PetscFunctionBegin; 821 PetscAssertPointer(opt, 2); 822 PetscAssertPointer(flg, 5); 823 if (!PetscOptionsObject->count) { 824 PetscOptionItem amsopt; 825 826 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 827 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 828 829 *(PetscBool *)amsopt->data = PETSC_FALSE; 830 } 831 PetscCall(PetscOptionsHasName(PetscOptionsObject->options, prefix, opt, flg)); 832 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 833 PetscFunctionReturn(PETSC_SUCCESS); 834 } 835 836 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) 837 { 838 const char *prefix = PetscOptionsObject->prefix; 839 PetscBool lset; 840 841 PetscFunctionBegin; 842 PetscAssertPointer(opt, 2); 843 PetscAssertPointer(value, 7); 844 if (set) PetscAssertPointer(set, 9); 845 if (!PetscOptionsObject->count) { 846 PetscOptionItem amsopt; 847 848 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_FLIST, &amsopt)); 849 /* must use system malloc since SAWs may free this */ 850 PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data)); 851 amsopt->flist = list; 852 } 853 PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset)); 854 if (set) *set = lset; 855 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall(PetscFunctionListPrintTypes(PetscOptionsObject->comm, stdout, Prefix(prefix), opt, ltext, man, list, currentvalue, lset ? value : currentvalue)); 856 PetscFunctionReturn(PETSC_SUCCESS); 857 } 858 859 #ifdef __cplusplus 860 #include <type_traits> 861 #endif 862 863 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) 864 { 865 const char *prefix = PetscOptionsObject->prefix; 866 PetscBool lset; 867 868 PetscFunctionBegin; 869 PetscAssertPointer(opt, 2); 870 PetscAssertPointer(value, 8); 871 if (set) PetscAssertPointer(set, 9); 872 if (!PetscOptionsObject->count) { 873 PetscOptionItem amsopt; 874 875 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_ELIST, &amsopt)); 876 /* must use system malloc since SAWs may free this */ 877 PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data)); 878 PetscCall(PetscStrNArrayallocpy(ntext, list, (char ***)&amsopt->list)); 879 PetscCheck(ntext <= CHAR_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of list entries %" PetscInt_FMT " > %d", ntext, CHAR_MAX); 880 #ifdef __cplusplus 881 static_assert(std::is_same<typename std::decay<decltype(amsopt->nlist)>::type, char>::value, ""); 882 #endif 883 amsopt->nlist = (char)ntext; 884 } 885 PetscCall(PetscOptionsGetEList(PetscOptionsObject->options, prefix, opt, list, ntext, value, &lset)); 886 if (set) *set = lset; 887 if (ShouldPrintHelp(PetscOptionsObject)) { 888 const MPI_Comm comm = PetscOptionsObject->comm; 889 890 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <now %s : formerly %s> %s (choose one of)", Prefix(prefix), opt + 1, lset ? list[*value] : currentvalue, currentvalue, ltext)); 891 for (PetscInt i = 0; i < ntext; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i])); 892 PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man))); 893 } 894 PetscFunctionReturn(PETSC_SUCCESS); 895 } 896 897 PetscErrorCode PetscOptionsBoolGroupBegin_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 898 { 899 const char *prefix = PetscOptionsObject->prefix; 900 901 PetscFunctionBegin; 902 PetscAssertPointer(opt, 2); 903 PetscAssertPointer(flg, 5); 904 if (!PetscOptionsObject->count) { 905 PetscOptionItem amsopt; 906 907 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 908 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 909 910 *(PetscBool *)amsopt->data = PETSC_FALSE; 911 } 912 *flg = PETSC_FALSE; 913 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL)); 914 if (ShouldPrintHelp(PetscOptionsObject)) { 915 const MPI_Comm comm = PetscOptionsObject->comm; 916 917 PetscCall((*PetscHelpPrintf)(comm, " Pick at most one of -------------\n")); 918 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 919 } 920 PetscFunctionReturn(PETSC_SUCCESS); 921 } 922 923 PetscErrorCode PetscOptionsBoolGroup_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 924 { 925 const char *prefix = PetscOptionsObject->prefix; 926 927 PetscFunctionBegin; 928 PetscAssertPointer(opt, 2); 929 PetscAssertPointer(flg, 5); 930 if (!PetscOptionsObject->count) { 931 PetscOptionItem amsopt; 932 933 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 934 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 935 936 *(PetscBool *)amsopt->data = PETSC_FALSE; 937 } 938 *flg = PETSC_FALSE; 939 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL)); 940 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 941 PetscFunctionReturn(PETSC_SUCCESS); 942 } 943 944 PetscErrorCode PetscOptionsBoolGroupEnd_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg) 945 { 946 const char *prefix = PetscOptionsObject->prefix; 947 948 PetscFunctionBegin; 949 PetscAssertPointer(opt, 2); 950 PetscAssertPointer(flg, 5); 951 if (!PetscOptionsObject->count) { 952 PetscOptionItem amsopt; 953 954 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 955 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 956 957 *(PetscBool *)amsopt->data = PETSC_FALSE; 958 } 959 *flg = PETSC_FALSE; 960 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL)); 961 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 962 PetscFunctionReturn(PETSC_SUCCESS); 963 } 964 965 PetscErrorCode PetscOptionsBool_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool currentvalue, PetscBool *flg, PetscBool *set) 966 { 967 const char *prefix = PetscOptionsObject->prefix; 968 PetscBool iset; 969 970 PetscFunctionBegin; 971 PetscAssertPointer(opt, 2); 972 PetscAssertPointer(flg, 6); 973 if (set) PetscAssertPointer(set, 7); 974 if (!PetscOptionsObject->count) { 975 PetscOptionItem amsopt; 976 977 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt)); 978 PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data)); 979 980 *(PetscBool *)amsopt->data = currentvalue; 981 } 982 PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, &iset)); 983 if (set) *set = iset; 984 if (ShouldPrintHelp(PetscOptionsObject)) { 985 const char *curvalue = PetscBools[currentvalue]; 986 987 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))); 988 } 989 PetscFunctionReturn(PETSC_SUCCESS); 990 } 991 992 PetscErrorCode PetscOptionsRealArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal value[], PetscInt *n, PetscBool *set) 993 { 994 const char *prefix = PetscOptionsObject->prefix; 995 996 PetscFunctionBegin; 997 PetscAssertPointer(opt, 2); 998 PetscAssertPointer(n, 6); 999 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1000 if (*n) PetscAssertPointer(value, 5); 1001 if (set) PetscAssertPointer(set, 7); 1002 if (!PetscOptionsObject->count) { 1003 const PetscInt nv = *n; 1004 PetscReal *vals; 1005 PetscOptionItem amsopt; 1006 1007 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt)); 1008 PetscCall(PetscMalloc(nv * sizeof(*vals), &vals)); 1009 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1010 amsopt->arraylength = nv; 1011 amsopt->data = vals; 1012 } 1013 PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1014 if (ShouldPrintHelp(PetscOptionsObject)) { 1015 const PetscInt nv = *n; 1016 const MPI_Comm comm = PetscOptionsObject->comm; 1017 1018 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%g", Prefix(prefix), opt + 1, (double)value[0])); 1019 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g", (double)value[i])); 1020 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1021 } 1022 PetscFunctionReturn(PETSC_SUCCESS); 1023 } 1024 1025 PetscErrorCode PetscOptionsScalarArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar value[], PetscInt *n, PetscBool *set) 1026 { 1027 const char *prefix = PetscOptionsObject->prefix; 1028 1029 PetscFunctionBegin; 1030 PetscAssertPointer(opt, 2); 1031 PetscAssertPointer(n, 6); 1032 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1033 if (*n) PetscAssertPointer(value, 5); 1034 if (set) PetscAssertPointer(set, 7); 1035 if (!PetscOptionsObject->count) { 1036 const PetscInt nv = *n; 1037 PetscOptionItem amsopt; 1038 PetscScalar *vals; 1039 1040 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt)); 1041 PetscCall(PetscMalloc(nv * sizeof(*vals), &vals)); 1042 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1043 amsopt->arraylength = nv; 1044 amsopt->data = vals; 1045 } 1046 PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1047 if (ShouldPrintHelp(PetscOptionsObject)) { 1048 const PetscInt nv = *n; 1049 const MPI_Comm comm = PetscOptionsObject->comm; 1050 1051 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%g+%gi", Prefix(prefix), opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0]))); 1052 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i]))); 1053 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1054 } 1055 PetscFunctionReturn(PETSC_SUCCESS); 1056 } 1057 1058 PetscErrorCode PetscOptionsIntArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt value[], PetscInt *n, PetscBool *set) 1059 { 1060 const char *prefix = PetscOptionsObject->prefix; 1061 1062 PetscFunctionBegin; 1063 PetscAssertPointer(opt, 2); 1064 PetscAssertPointer(n, 6); 1065 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1066 if (*n) PetscAssertPointer(value, 5); 1067 if (set) PetscAssertPointer(set, 7); 1068 if (!PetscOptionsObject->count) { 1069 const PetscInt nv = *n; 1070 PetscInt *vals; 1071 PetscOptionItem amsopt; 1072 1073 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY, &amsopt)); 1074 PetscCall(PetscMalloc1(nv, &vals)); 1075 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1076 amsopt->arraylength = nv; 1077 amsopt->data = vals; 1078 } 1079 PetscCall(PetscOptionsGetIntArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1080 if (ShouldPrintHelp(PetscOptionsObject)) { 1081 const PetscInt nv = *n; 1082 const MPI_Comm comm = PetscOptionsObject->comm; 1083 1084 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%" PetscInt_FMT, Prefix(prefix), opt + 1, value[0])); 1085 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%" PetscInt_FMT, value[i])); 1086 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1087 } 1088 PetscFunctionReturn(PETSC_SUCCESS); 1089 } 1090 1091 PetscErrorCode PetscOptionsStringArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], char *value[], PetscInt *nmax, PetscBool *set) 1092 { 1093 const char *prefix = PetscOptionsObject->prefix; 1094 1095 PetscFunctionBegin; 1096 PetscAssertPointer(opt, 2); 1097 PetscAssertPointer(nmax, 6); 1098 PetscCheck(*nmax >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *nmax); 1099 if (*nmax) PetscAssertPointer(value, 5); 1100 if (set) PetscAssertPointer(set, 7); 1101 if (!PetscOptionsObject->count) { 1102 const PetscInt nmaxv = *nmax; 1103 PetscOptionItem amsopt; 1104 1105 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt)); 1106 PetscCall(PetscMalloc1(nmaxv, (char **)&amsopt->data)); 1107 amsopt->arraylength = nmaxv; 1108 } 1109 PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, prefix, opt, value, nmax, set)); 1110 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " -%s%s: <string1,string2,...>: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man))); 1111 PetscFunctionReturn(PETSC_SUCCESS); 1112 } 1113 1114 PetscErrorCode PetscOptionsBoolArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool value[], PetscInt *n, PetscBool *set) 1115 { 1116 const char *prefix = PetscOptionsObject->prefix; 1117 1118 PetscFunctionBegin; 1119 PetscAssertPointer(opt, 2); 1120 PetscAssertPointer(n, 6); 1121 PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n); 1122 if (*n) PetscAssertPointer(value, 5); 1123 if (set) PetscAssertPointer(set, 7); 1124 if (!PetscOptionsObject->count) { 1125 const PetscInt nv = *n; 1126 PetscBool *vals; 1127 PetscOptionItem amsopt; 1128 1129 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt)); 1130 PetscCall(PetscMalloc1(nv, &vals)); 1131 for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i]; 1132 amsopt->arraylength = nv; 1133 amsopt->data = vals; 1134 } 1135 PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, prefix, opt, value, n, set)); 1136 if (ShouldPrintHelp(PetscOptionsObject)) { 1137 const PetscInt nv = *n; 1138 const MPI_Comm comm = PetscOptionsObject->comm; 1139 1140 PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%d", Prefix(prefix), opt + 1, value[0])); 1141 for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%d", value[i])); 1142 PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man))); 1143 } 1144 PetscFunctionReturn(PETSC_SUCCESS); 1145 } 1146 1147 /*MC 1148 PetscOptionsViewer - Creates a viewer appropriate for the type indicated by the user 1149 1150 Synopsis: 1151 #include <petscviewer.h> 1152 PetscErrorCode PetscOptionsViewer(const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set) 1153 1154 Logically Collective on the communicator passed in `PetscOptionsBegin()` 1155 1156 Input Parameters: 1157 + opt - option name 1158 . text - short string that describes the option 1159 - man - manual page with additional information on option 1160 1161 Output Parameters: 1162 + viewer - the viewer 1163 . format - the PetscViewerFormat requested by the user, pass `NULL` if not needed 1164 - set - `PETSC_TRUE` if found, else `PETSC_FALSE` 1165 1166 Level: beginner 1167 1168 Notes: 1169 Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()` 1170 1171 See `PetscOptionsCreateViewer()` for the format of the supplied viewer and its options 1172 1173 .seealso: `PetscOptionsCreateViewer()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`, 1174 `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()` 1175 `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, 1176 `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`, 1177 `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`, 1178 `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`, 1179 `PetscOptionsFList()`, `PetscOptionsEList()` 1180 M*/ 1181 PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set) 1182 { 1183 const MPI_Comm comm = PetscOptionsObject->comm; 1184 const char *prefix = PetscOptionsObject->prefix; 1185 1186 PetscFunctionBegin; 1187 PetscAssertPointer(opt, 2); 1188 PetscAssertPointer(viewer, 5); 1189 if (format) PetscAssertPointer(format, 6); 1190 if (set) PetscAssertPointer(set, 7); 1191 if (!PetscOptionsObject->count) { 1192 PetscOptionItem amsopt; 1193 1194 PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt)); 1195 /* must use system malloc since SAWs may free this */ 1196 PetscCall(PetscStrdup("", (char **)&amsopt->data)); 1197 } 1198 PetscCall(PetscOptionsCreateViewer(comm, PetscOptionsObject->options, prefix, opt, viewer, format, set)); 1199 if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, " -%s%s: <%s>: %s (%s)\n", Prefix(prefix), opt + 1, "", text, ManSection(man))); 1200 PetscFunctionReturn(PETSC_SUCCESS); 1201 } 1202