Actual source code: aoptions.c
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.
5: */
7: #include <petsc/private/petscimpl.h>
8: #include <petscviewer.h>
10: static const char *ManSection(const char *str)
11: {
12: return str ? str : "None";
13: }
15: static const char *Prefix(const char *str)
16: {
17: return str ? str : "";
18: }
20: static int ShouldPrintHelp(const PetscOptionItems opts)
21: {
22: return opts->printhelp && opts->count == 1 && !opts->alreadyprinted;
23: }
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()
29: Eventually we'll attach this beast to a MPI_Comm
30: */
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;
49: PetscCall(PetscStrallocpy(prefix, &PetscOptionsObject->prefix));
50: PetscCall(PetscStrallocpy(title, &PetscOptionsObject->title));
52: PetscCall(PetscOptionsHasHelp(PetscOptionsObject->options, &PetscOptionsObject->printhelp));
53: if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\n%s:\n", title));
54: PetscFunctionReturn(PETSC_SUCCESS);
55: }
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;
65: PetscFunctionBegin;
66: PetscAssertPointer(PetscOptionsObject, 2);
68: PetscOptionsObject->object = obj;
69: PetscOptionsObject->alreadyprinted = obj->optionsprinted;
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: }
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;
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);
89: PetscCall(PetscNew(amsopt));
90: (*amsopt)->next = NULL;
91: (*amsopt)->set = PETSC_FALSE;
92: (*amsopt)->type = t;
93: (*amsopt)->data = NULL;
95: PetscCall(PetscStrallocpy(text, &(*amsopt)->text));
96: PetscCall(PetscStrallocpy(opt, &(*amsopt)->option));
97: PetscCall(PetscStrallocpy(man, &(*amsopt)->man));
99: {
100: PetscOptionItem cur = PetscOptionsObject->next;
102: while (cur->next) cur = cur->next;
103: cur->next = *amsopt;
104: }
105: PetscFunctionReturn(PETSC_SUCCESS);
106: }
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;
115: PetscFunctionBegin;
116: if (s) {
117: size_t len;
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: }
128: #if defined(PETSC_HAVE_SAWS)
129: #include <petscviewersaws.h>
131: static int count = 0;
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";
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>";
147: /*
148: PetscOptionsSAWsInput - Presents all the PETSc Options processed by the program so the user may change them at runtime using the SAWs
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
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];
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++));
170: PetscOptionsObject->pprefix = PetscOptionsObject->prefix; /* SAWs will change this, so cannot pass prefix directly */
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));
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));
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: }
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));
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: }
258: /* reset counter to -2; this updates the screen with the new options for the selected method */
259: if (changedmethod) PetscOptionsObject->count = -2;
261: if (stopasking) {
262: PetscOptionsPublish = PETSC_FALSE;
263: PetscOptionsObject->count = 0; //do not ask for same thing again
264: }
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
273: Collective
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
280: Bugs:
281: . Assumes process 0 of the given communicator has access to stdin
283: */
284: static PetscErrorCode PetscScanString(MPI_Comm comm, size_t n, char str[])
285: {
286: PetscMPIInt rank, nm;
288: PetscFunctionBegin;
289: PetscCallMPI(MPI_Comm_rank(comm, &rank));
290: if (rank == 0) {
291: char c = (char)getchar();
292: size_t i = 0;
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: }
305: /*
306: PetscOptionsGetFromTextInput - Presents all the PETSc Options processed by the program so the user may change them at runtime
308: Notes:
309: this isn't really practical, it is just to demonstrate the principle
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?
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
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
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;
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;
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;
362: if (!value) break;
363: PetscCall(PetscStrallocpy(value, &ivalue));
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;
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
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
503: PetscErrorCode PetscOptionsEnd_Private(PetscOptionItems PetscOptionsObject)
504: {
505: PetscOptionItem next, last;
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: }
518: PetscCall(PetscFree(PetscOptionsObject->title));
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;
527: while ((next = PetscOptionsObject->next)) {
528: const PetscOptionType type = next->type;
529: const size_t arraylength = next->arraylength;
530: void *data = next->data;
532: if (next->set) {
533: char option[256], value[1024], tmp[32];
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: }
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));
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: }
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: }
625: static PetscErrorCode GetListLength(const char *const *list, PetscInt *len)
626: {
627: PetscInt retlen = 0;
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: }
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;
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: }
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;
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;
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: }
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;
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;
702: PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
703: PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
704: *(PetscInt *)amsopt->data = currentvalue;
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: }
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;
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;
734: PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
735: PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
736: *(PetscMPIInt *)amsopt->data = currentvalue;
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: }
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;
754: PetscFunctionBegin;
755: PetscAssertPointer(opt, 2);
756: PetscAssertPointer(value, 6);
757: if (set) PetscAssertPointer(set, 8);
758: if (!PetscOptionsObject->count) {
759: PetscOptionItem amsopt;
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: }
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;
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;
786: PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt));
787: PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data));
788: *(PetscReal *)amsopt->data = currentvalue;
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: }
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: }
814: PetscErrorCode PetscOptionsName_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
815: {
816: const char *prefix = PetscOptionsObject->prefix;
818: PetscFunctionBegin;
819: PetscAssertPointer(opt, 2);
820: PetscAssertPointer(flg, 5);
821: if (!PetscOptionsObject->count) {
822: PetscOptionItem amsopt;
824: PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
825: PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
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: }
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;
839: PetscFunctionBegin;
840: PetscAssertPointer(opt, 2);
841: PetscAssertPointer(value, 7);
842: if (set) PetscAssertPointer(set, 9);
843: if (!PetscOptionsObject->count) {
844: PetscOptionItem amsopt;
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: }
857: #ifdef __cplusplus
858: #include <type_traits>
859: #endif
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;
866: PetscFunctionBegin;
867: PetscAssertPointer(opt, 2);
868: PetscAssertPointer(value, 8);
869: if (set) PetscAssertPointer(set, 9);
870: if (!PetscOptionsObject->count) {
871: PetscOptionItem amsopt;
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;
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: }
895: PetscErrorCode PetscOptionsBoolGroupBegin_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
896: {
897: const char *prefix = PetscOptionsObject->prefix;
899: PetscFunctionBegin;
900: PetscAssertPointer(opt, 2);
901: PetscAssertPointer(flg, 5);
902: if (!PetscOptionsObject->count) {
903: PetscOptionItem amsopt;
905: PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
906: PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
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;
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: }
921: PetscErrorCode PetscOptionsBoolGroup_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
922: {
923: const char *prefix = PetscOptionsObject->prefix;
925: PetscFunctionBegin;
926: PetscAssertPointer(opt, 2);
927: PetscAssertPointer(flg, 5);
928: if (!PetscOptionsObject->count) {
929: PetscOptionItem amsopt;
931: PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
932: PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
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: }
942: PetscErrorCode PetscOptionsBoolGroupEnd_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
943: {
944: const char *prefix = PetscOptionsObject->prefix;
946: PetscFunctionBegin;
947: PetscAssertPointer(opt, 2);
948: PetscAssertPointer(flg, 5);
949: if (!PetscOptionsObject->count) {
950: PetscOptionItem amsopt;
952: PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
953: PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
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: }
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;
968: PetscFunctionBegin;
969: PetscAssertPointer(opt, 2);
970: PetscAssertPointer(flg, 6);
971: if (set) PetscAssertPointer(set, 7);
972: if (!PetscOptionsObject->count) {
973: PetscOptionItem amsopt;
975: PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
976: PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
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];
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: }
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;
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;
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;
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: }
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;
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;
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;
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: }
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;
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;
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;
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: }
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;
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;
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: }
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;
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;
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;
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: }
1145: /*MC
1146: PetscOptionsViewer - Creates a viewer appropriate for the type indicated by the user
1148: Synopsis:
1149: #include <petscviewer.h>
1150: PetscErrorCode PetscOptionsViewer(const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
1152: Logically Collective on the communicator passed in `PetscOptionsBegin()`
1154: Input Parameters:
1155: + opt - option name
1156: . text - short string that describes the option
1157: - man - manual page with additional information on option
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`
1164: Level: beginner
1166: Notes:
1167: Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1169: See `PetscOptionsCreateViewer()` for the format of the supplied viewer and its options
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;
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;
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: }