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