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