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