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