xref: /petsc/src/sys/objects/aoptions.c (revision 1cc06b555e92f8ec64db10330b8bbd830e5bc876)
1 /*
2    Implements the higher-level options database querying methods. These are self-documenting and can attach at runtime to
3    GUI code to display the options and get values from the users.
4 
5 */
6 
7 #include <petsc/private/petscimpl.h> /*I  "petscsys.h"   I*/
8 #include <petscviewer.h>
9 
10 #define ManSection(str) ((str) ? (str) : "None")
11 
12 /*
13     Keep a linked list of options that have been posted and we are waiting for
14    user selection. See the manual page for PetscOptionsBegin()
15 
16     Eventually we'll attach this beast to a MPI_Comm
17 */
18 
19 /*
20     Handles setting up the data structure in a call to PetscOptionsBegin()
21 */
22 PetscErrorCode PetscOptionsBegin_Private(PetscOptionItems *PetscOptionsObject, MPI_Comm comm, const char prefix[], const char title[], const char mansec[])
23 {
24   PetscFunctionBegin;
25   if (prefix) PetscValidCharPointer(prefix, 3);
26   PetscValidCharPointer(title, 4);
27   if (mansec) PetscValidCharPointer(mansec, 5);
28   if (!PetscOptionsObject->alreadyprinted) {
29     if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
30     PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, prefix, title, &PetscOptionsObject->alreadyprinted));
31   }
32   PetscOptionsObject->next          = NULL;
33   PetscOptionsObject->comm          = comm;
34   PetscOptionsObject->changedmethod = PETSC_FALSE;
35 
36   PetscCall(PetscStrallocpy(prefix, &PetscOptionsObject->prefix));
37   PetscCall(PetscStrallocpy(title, &PetscOptionsObject->title));
38 
39   PetscCall(PetscOptionsHasHelp(PetscOptionsObject->options, &PetscOptionsObject->printhelp));
40   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1) {
41     if (!PetscOptionsObject->alreadyprinted) PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\n%s:\n", title));
42   }
43   PetscFunctionReturn(PETSC_SUCCESS);
44 }
45 
46 /*
47     Handles setting up the data structure in a call to PetscObjectOptionsBegin()
48 */
49 PetscErrorCode PetscObjectOptionsBegin_Private(PetscObject obj, PetscOptionItems *PetscOptionsObject)
50 {
51   char      title[256];
52   PetscBool flg;
53 
54   PetscFunctionBegin;
55   PetscValidPointer(PetscOptionsObject, 2);
56   PetscValidHeader(obj, 1);
57   PetscOptionsObject->object         = obj;
58   PetscOptionsObject->alreadyprinted = obj->optionsprinted;
59 
60   PetscCall(PetscStrcmp(obj->description, obj->class_name, &flg));
61   if (flg) PetscCall(PetscSNPrintf(title, sizeof(title), "%s options", obj->class_name));
62   else PetscCall(PetscSNPrintf(title, sizeof(title), "%s (%s) options", obj->description, obj->class_name));
63   PetscCall(PetscOptionsBegin_Private(PetscOptionsObject, obj->comm, obj->prefix, title, obj->mansec));
64   PetscFunctionReturn(PETSC_SUCCESS);
65 }
66 
67 /*
68      Handles adding another option to the list of options within this particular PetscOptionsBegin() PetscOptionsEnd()
69 */
70 static PetscErrorCode PetscOptionItemCreate_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscOptionType t, PetscOptionItem *amsopt)
71 {
72   PetscOptionItem next;
73   PetscBool       valid;
74 
75   PetscFunctionBegin;
76   PetscCall(PetscOptionsValidKey(opt, &valid));
77   PetscCheck(valid, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "The option '%s' is not a valid key", opt);
78 
79   PetscCall(PetscNew(amsopt));
80   (*amsopt)->next = NULL;
81   (*amsopt)->set  = PETSC_FALSE;
82   (*amsopt)->type = t;
83   (*amsopt)->data = NULL;
84 
85   PetscCall(PetscStrallocpy(text, &(*amsopt)->text));
86   PetscCall(PetscStrallocpy(opt, &(*amsopt)->option));
87   PetscCall(PetscStrallocpy(man, &(*amsopt)->man));
88 
89   if (!PetscOptionsObject->next) PetscOptionsObject->next = *amsopt;
90   else {
91     next = PetscOptionsObject->next;
92     while (next->next) next = next->next;
93     next->next = *amsopt;
94   }
95   PetscFunctionReturn(PETSC_SUCCESS);
96 }
97 
98 /*
99     PetscScanString -  Gets user input via stdin from process and broadcasts to all processes
100 
101     Collective
102 
103    Input Parameters:
104 +     commm - communicator for the broadcast, must be PETSC_COMM_WORLD
105 .     n - length of the string, must be the same on all processes
106 -     str - location to store input
107 
108     Bugs:
109 .   Assumes process 0 of the given communicator has access to stdin
110 
111 */
112 static PetscErrorCode PetscScanString(MPI_Comm comm, size_t n, char str[])
113 {
114   PetscMPIInt rank, nm;
115 
116   PetscFunctionBegin;
117   PetscCallMPI(MPI_Comm_rank(comm, &rank));
118   if (rank == 0) {
119     char   c = (char)getchar();
120     size_t i = 0;
121 
122     while (c != '\n' && i < n - 1) {
123       str[i++] = c;
124       c        = (char)getchar();
125     }
126     str[i] = 0;
127   }
128   PetscCall(PetscMPIIntCast(n, &nm));
129   PetscCallMPI(MPI_Bcast(str, nm, MPI_CHAR, 0, comm));
130   PetscFunctionReturn(PETSC_SUCCESS);
131 }
132 
133 /*
134     This is needed because certain strings may be freed by SAWs, hence we cannot use PetscStrallocpy()
135 */
136 static PetscErrorCode PetscStrdup(const char s[], char *t[])
137 {
138   char *tmp = NULL;
139 
140   PetscFunctionBegin;
141   if (s) {
142     size_t len;
143 
144     PetscCall(PetscStrlen(s, &len));
145     tmp = (char *)malloc((len + 1) * sizeof(*tmp));
146     PetscCheck(tmp, PETSC_COMM_SELF, PETSC_ERR_MEM, "No memory to duplicate string");
147     PetscCall(PetscArraycpy(tmp, s, len + 1));
148   }
149   *t = tmp;
150   PetscFunctionReturn(PETSC_SUCCESS);
151 }
152 
153 /*
154     PetscOptionsGetFromTextInput - Presents all the PETSc Options processed by the program so the user may change them at runtime
155 
156     Notes:
157     this isn't really practical, it is just to demonstrate the principle
158 
159     A carriage return indicates no change from the default; but this like -ksp_monitor <stdout>  the default is actually not stdout the default
160     is to do nothing so to get it to use stdout you need to type stdout. This is kind of bug?
161 
162     Bugs:
163 +    All processes must traverse through the exact same set of option queries due to the call to PetscScanString()
164 .    Internal strings have arbitrary length and string copies are not checked that they fit into string space
165 -    Only works for PetscInt == int, PetscReal == double etc
166 
167     Developer Note:
168     Normally the GUI that presents the options the user and retrieves the values would be running in a different
169      address space and communicating with the PETSc program
170 
171 */
172 PetscErrorCode PetscOptionsGetFromTextInput(PetscOptionItems *PetscOptionsObject)
173 {
174   PetscOptionItem next = PetscOptionsObject->next;
175   char            str[512];
176   PetscBool       bid;
177   PetscReal       ir, *valr;
178   PetscInt       *vald;
179   size_t          i;
180 
181   PetscFunctionBegin;
182   PetscCall((*PetscPrintf)(PETSC_COMM_WORLD, "%s --------------------\n", PetscOptionsObject->title));
183   while (next) {
184     switch (next->type) {
185     case OPTION_HEAD:
186       break;
187     case OPTION_INT_ARRAY:
188       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1));
189       vald = (PetscInt *)next->data;
190       for (i = 0; i < next->arraylength; i++) {
191         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT, vald[i]));
192         if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ","));
193       }
194       PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man));
195       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
196       if (str[0]) {
197         PetscToken token;
198         PetscInt   n = 0, nmax = next->arraylength, *dvalue = (PetscInt *)next->data, start, end;
199         size_t     len;
200         char      *value;
201         PetscBool  foundrange;
202 
203         next->set = PETSC_TRUE;
204         value     = str;
205         PetscCall(PetscTokenCreate(value, ',', &token));
206         PetscCall(PetscTokenFind(token, &value));
207         while (n < nmax) {
208           if (!value) break;
209 
210           /* look for form  d-D where d and D are integers */
211           foundrange = PETSC_FALSE;
212           PetscCall(PetscStrlen(value, &len));
213           if (value[0] == '-') i = 2;
214           else i = 1;
215           for (; i < len; i++) {
216             if (value[i] == '-') {
217               PetscCheck(i != len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, value);
218               value[i] = 0;
219               PetscCall(PetscOptionsStringToInt(value, &start));
220               PetscCall(PetscOptionsStringToInt(value + i + 1, &end));
221               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);
222               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);
223               for (; start < end; start++) {
224                 *dvalue = start;
225                 dvalue++;
226                 n++;
227               }
228               foundrange = PETSC_TRUE;
229               break;
230             }
231           }
232           if (!foundrange) {
233             PetscCall(PetscOptionsStringToInt(value, dvalue));
234             dvalue++;
235             n++;
236           }
237           PetscCall(PetscTokenFind(token, &value));
238         }
239         PetscCall(PetscTokenDestroy(&token));
240       }
241       break;
242     case OPTION_REAL_ARRAY:
243       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1));
244       valr = (PetscReal *)next->data;
245       for (i = 0; i < next->arraylength; i++) {
246         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%g", (double)valr[i]));
247         if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ","));
248       }
249       PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man));
250       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
251       if (str[0]) {
252         PetscToken token;
253         PetscInt   n = 0, nmax = next->arraylength;
254         PetscReal *dvalue = (PetscReal *)next->data;
255         char      *value;
256 
257         next->set = PETSC_TRUE;
258         value     = str;
259         PetscCall(PetscTokenCreate(value, ',', &token));
260         PetscCall(PetscTokenFind(token, &value));
261         while (n < nmax) {
262           if (!value) break;
263           PetscCall(PetscOptionsStringToReal(value, dvalue));
264           dvalue++;
265           n++;
266           PetscCall(PetscTokenFind(token, &value));
267         }
268         PetscCall(PetscTokenDestroy(&token));
269       }
270       break;
271     case OPTION_INT:
272       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s <%d>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(int *)next->data, next->text, next->man));
273       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
274       if (str[0]) {
275 #if defined(PETSC_SIZEOF_LONG_LONG)
276         long long lid;
277         sscanf(str, "%lld", &lid);
278         PetscCheck(lid <= PETSC_MAX_INT && lid >= PETSC_MIN_INT, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %lld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid);
279 #else
280         long lid;
281         sscanf(str, "%ld", &lid);
282         PetscCheck(lid <= PETSC_MAX_INT && lid >= PETSC_MIN_INT, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %ld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid);
283 #endif
284 
285         next->set                 = PETSC_TRUE;
286         *((PetscInt *)next->data) = (PetscInt)lid;
287       }
288       break;
289     case OPTION_REAL:
290       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s <%g>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(double *)next->data, next->text, next->man));
291       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
292       if (str[0]) {
293 #if defined(PETSC_USE_REAL_SINGLE)
294         sscanf(str, "%e", &ir);
295 #elif defined(PETSC_USE_REAL___FP16)
296         float irtemp;
297         sscanf(str, "%e", &irtemp);
298         ir = irtemp;
299 #elif defined(PETSC_USE_REAL_DOUBLE)
300         sscanf(str, "%le", &ir);
301 #elif defined(PETSC_USE_REAL___FLOAT128)
302         ir = strtoflt128(str, 0);
303 #else
304         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Unknown scalar type");
305 #endif
306         next->set                  = PETSC_TRUE;
307         *((PetscReal *)next->data) = ir;
308       }
309       break;
310     case OPTION_BOOL:
311       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));
312       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
313       if (str[0]) {
314         PetscCall(PetscOptionsStringToBool(str, &bid));
315         next->set                  = PETSC_TRUE;
316         *((PetscBool *)next->data) = bid;
317       }
318       break;
319     case OPTION_STRING:
320       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s <%s>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, (char *)next->data, next->text, next->man));
321       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
322       if (str[0]) {
323         next->set = PETSC_TRUE;
324         /* must use system malloc since SAWs may free this */
325         PetscCall(PetscStrdup(str, (char **)&next->data));
326       }
327       break;
328     case OPTION_FLIST:
329       PetscCall(PetscFunctionListPrintTypes(PETSC_COMM_WORLD, stdout, PetscOptionsObject->prefix, next->option, next->text, next->man, next->flist, (char *)next->data, (char *)next->data));
330       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
331       if (str[0]) {
332         PetscOptionsObject->changedmethod = PETSC_TRUE;
333         next->set                         = PETSC_TRUE;
334         /* must use system malloc since SAWs may free this */
335         PetscCall(PetscStrdup(str, (char **)&next->data));
336       }
337       break;
338     default:
339       break;
340     }
341     next = next->next;
342   }
343   PetscFunctionReturn(PETSC_SUCCESS);
344 }
345 
346 #if defined(PETSC_HAVE_SAWS)
347   #include <petscviewersaws.h>
348 
349 static int count = 0;
350 
351 PetscErrorCode PetscOptionsSAWsDestroy(void)
352 {
353   PetscFunctionBegin;
354   PetscFunctionReturn(PETSC_SUCCESS);
355 }
356 
357 static const char *OptionsHeader = "<head>\n"
358                                    "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/jquery-1.9.1.js\"></script>\n"
359                                    "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/SAWs.js\"></script>\n"
360                                    "<script type=\"text/javascript\" src=\"js/PETSc.js\"></script>\n"
361                                    "<script>\n"
362                                    "jQuery(document).ready(function() {\n"
363                                    "PETSc.getAndDisplayDirectory(null,\"#variablesInfo\")\n"
364                                    "})\n"
365                                    "</script>\n"
366                                    "</head>\n";
367 
368 /*  Determines the size and style of the scroll region where PETSc options selectable from users are displayed */
369 static const char *OptionsBodyBottom = "<div id=\"variablesInfo\" style=\"background-color:lightblue;height:auto;max-height:500px;overflow:scroll;\"></div>\n<br>\n</body>";
370 
371 /*
372     PetscOptionsSAWsInput - Presents all the PETSc Options processed by the program so the user may change them at runtime using the SAWs
373 
374     Bugs:
375 +    All processes must traverse through the exact same set of option queries do to the call to PetscScanString()
376 .    Internal strings have arbitrary length and string copies are not checked that they fit into string space
377 -    Only works for PetscInt == int, PetscReal == double etc
378 
379 */
380 PetscErrorCode PetscOptionsSAWsInput(PetscOptionItems *PetscOptionsObject)
381 {
382   PetscOptionItem next     = PetscOptionsObject->next;
383   static int      mancount = 0;
384   char            options[16];
385   PetscBool       changedmethod = PETSC_FALSE;
386   PetscBool       stopasking    = PETSC_FALSE;
387   char            manname[16], textname[16];
388   char            dir[1024];
389 
390   PetscFunctionBegin;
391   /* the next line is a bug, this will only work if all processors are here, the comm passed in is ignored!!! */
392   PetscCall(PetscSNPrintf(options, PETSC_STATIC_ARRAY_LENGTH(options), "Options_%d", count++));
393 
394   PetscOptionsObject->pprefix = PetscOptionsObject->prefix; /* SAWs will change this, so cannot pass prefix directly */
395 
396   PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "_title"));
397   PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->title, 1, SAWs_READ, SAWs_STRING));
398   PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "prefix"));
399   PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->pprefix, 1, SAWs_READ, SAWs_STRING));
400   PetscCallSAWs(SAWs_Register, ("/PETSc/Options/ChangedMethod", &changedmethod, 1, SAWs_WRITE, SAWs_BOOLEAN));
401   PetscCallSAWs(SAWs_Register, ("/PETSc/Options/StopAsking", &stopasking, 1, SAWs_WRITE, SAWs_BOOLEAN));
402 
403   while (next) {
404     PetscCall(PetscSNPrintf(manname, PETSC_STATIC_ARRAY_LENGTH(manname), "_man_%d", mancount));
405     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", manname));
406     PetscCallSAWs(SAWs_Register, (dir, &next->man, 1, SAWs_READ, SAWs_STRING));
407     PetscCall(PetscSNPrintf(textname, PETSC_STATIC_ARRAY_LENGTH(textname), "_text_%d", mancount++));
408     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", textname));
409     PetscCallSAWs(SAWs_Register, (dir, &next->text, 1, SAWs_READ, SAWs_STRING));
410 
411     switch (next->type) {
412     case OPTION_HEAD:
413       break;
414     case OPTION_INT_ARRAY:
415       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
416       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_INT));
417       break;
418     case OPTION_REAL_ARRAY:
419       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
420       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_DOUBLE));
421       break;
422     case OPTION_INT:
423       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
424       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_INT));
425       break;
426     case OPTION_REAL:
427       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
428       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_DOUBLE));
429       break;
430     case OPTION_BOOL:
431       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
432       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_BOOLEAN));
433       break;
434     case OPTION_BOOL_ARRAY:
435       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
436       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_BOOLEAN));
437       break;
438     case OPTION_STRING:
439       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
440       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
441       break;
442     case OPTION_STRING_ARRAY:
443       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
444       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_STRING));
445       break;
446     case OPTION_FLIST: {
447       PetscInt ntext;
448       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
449       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
450       PetscCall(PetscFunctionListGet(next->flist, (const char ***)&next->edata, &ntext));
451       PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata));
452     } break;
453     case OPTION_ELIST: {
454       PetscInt ntext = next->nlist;
455       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
456       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
457       PetscCall(PetscMalloc1((ntext + 1), (char ***)&next->edata));
458       PetscCall(PetscMemcpy(next->edata, next->list, ntext * sizeof(char *)));
459       PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata));
460     } break;
461     default:
462       break;
463     }
464     next = next->next;
465   }
466 
467   /* wait until accessor has unlocked the memory */
468   PetscCallSAWs(SAWs_Push_Header, ("index.html", OptionsHeader));
469   PetscCallSAWs(SAWs_Push_Body, ("index.html", 2, OptionsBodyBottom));
470   PetscCall(PetscSAWsBlock());
471   PetscCallSAWs(SAWs_Pop_Header, ("index.html"));
472   PetscCallSAWs(SAWs_Pop_Body, ("index.html", 2));
473 
474   /* determine if any values have been set in GUI */
475   next = PetscOptionsObject->next;
476   while (next) {
477     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
478     PetscCallSAWs(SAWs_Selected, (dir, (int *)&next->set));
479     next = next->next;
480   }
481 
482   /* reset counter to -2; this updates the screen with the new options for the selected method */
483   if (changedmethod) PetscOptionsObject->count = -2;
484 
485   if (stopasking) {
486     PetscOptionsPublish       = PETSC_FALSE;
487     PetscOptionsObject->count = 0; //do not ask for same thing again
488   }
489 
490   PetscCallSAWs(SAWs_Delete, ("/PETSc/Options"));
491   PetscFunctionReturn(PETSC_SUCCESS);
492 }
493 #endif
494 
495 PetscErrorCode PetscOptionsEnd_Private(PetscOptionItems *PetscOptionsObject)
496 {
497   PetscOptionItem last;
498   char            option[256], value[1024], tmp[32];
499   size_t          j;
500 
501   PetscFunctionBegin;
502   if (PetscOptionsObject->next) {
503     if (!PetscOptionsObject->count) {
504 #if defined(PETSC_HAVE_SAWS)
505       PetscCall(PetscOptionsSAWsInput(PetscOptionsObject));
506 #else
507       PetscCall(PetscOptionsGetFromTextInput(PetscOptionsObject));
508 #endif
509     }
510   }
511 
512   PetscCall(PetscFree(PetscOptionsObject->title));
513 
514   /* reset counter to -2; this updates the screen with the new options for the selected method */
515   if (PetscOptionsObject->changedmethod) PetscOptionsObject->count = -2;
516   /* reset alreadyprinted flag */
517   PetscOptionsObject->alreadyprinted = PETSC_FALSE;
518   if (PetscOptionsObject->object) PetscOptionsObject->object->optionsprinted = PETSC_TRUE;
519   PetscOptionsObject->object = NULL;
520 
521   while (PetscOptionsObject->next) {
522     if (PetscOptionsObject->next->set) {
523       if (PetscOptionsObject->prefix) {
524         PetscCall(PetscStrncpy(option, "-", sizeof(option)));
525         PetscCall(PetscStrlcat(option, PetscOptionsObject->prefix, sizeof(option)));
526         PetscCall(PetscStrlcat(option, PetscOptionsObject->next->option + 1, sizeof(option)));
527       } else PetscCall(PetscStrncpy(option, PetscOptionsObject->next->option, sizeof(option)));
528 
529       switch (PetscOptionsObject->next->type) {
530       case OPTION_HEAD:
531         break;
532       case OPTION_INT_ARRAY:
533         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscInt *)PetscOptionsObject->next->data)[0]));
534         for (j = 1; j < PetscOptionsObject->next->arraylength; j++) {
535           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscInt *)PetscOptionsObject->next->data)[j]));
536           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
537           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
538         }
539         break;
540       case OPTION_INT:
541         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)*(PetscInt *)PetscOptionsObject->next->data));
542         break;
543       case OPTION_REAL:
544         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)*(PetscReal *)PetscOptionsObject->next->data));
545         break;
546       case OPTION_REAL_ARRAY:
547         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)((PetscReal *)PetscOptionsObject->next->data)[0]));
548         for (j = 1; j < PetscOptionsObject->next->arraylength; j++) {
549           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g", (double)((PetscReal *)PetscOptionsObject->next->data)[j]));
550           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
551           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
552         }
553         break;
554       case OPTION_SCALAR_ARRAY:
555         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g+%gi", (double)PetscRealPart(((PetscScalar *)PetscOptionsObject->next->data)[0]), (double)PetscImaginaryPart(((PetscScalar *)PetscOptionsObject->next->data)[0])));
556         for (j = 1; j < PetscOptionsObject->next->arraylength; j++) {
557           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g+%gi", (double)PetscRealPart(((PetscScalar *)PetscOptionsObject->next->data)[j]), (double)PetscImaginaryPart(((PetscScalar *)PetscOptionsObject->next->data)[j])));
558           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
559           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
560         }
561         break;
562       case OPTION_BOOL:
563         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", *(int *)PetscOptionsObject->next->data));
564         break;
565       case OPTION_BOOL_ARRAY:
566         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscBool *)PetscOptionsObject->next->data)[0]));
567         for (j = 1; j < PetscOptionsObject->next->arraylength; j++) {
568           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscBool *)PetscOptionsObject->next->data)[j]));
569           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
570           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
571         }
572         break;
573       case OPTION_FLIST:
574         PetscCall(PetscStrncpy(value, (char *)PetscOptionsObject->next->data, sizeof(value)));
575         break;
576       case OPTION_ELIST:
577         PetscCall(PetscStrncpy(value, (char *)PetscOptionsObject->next->data, sizeof(value)));
578         break;
579       case OPTION_STRING:
580         PetscCall(PetscStrncpy(value, (char *)PetscOptionsObject->next->data, sizeof(value)));
581         break;
582       case OPTION_STRING_ARRAY:
583         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%s", ((char **)PetscOptionsObject->next->data)[0]));
584         for (j = 1; j < PetscOptionsObject->next->arraylength; j++) {
585           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%s", ((char **)PetscOptionsObject->next->data)[j]));
586           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
587           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
588         }
589         break;
590       }
591       PetscCall(PetscOptionsSetValue(PetscOptionsObject->options, option, value));
592     }
593     if (PetscOptionsObject->next->type == OPTION_ELIST) PetscCall(PetscStrNArrayDestroy(PetscOptionsObject->next->nlist, (char ***)&PetscOptionsObject->next->list));
594     PetscCall(PetscFree(PetscOptionsObject->next->text));
595     PetscCall(PetscFree(PetscOptionsObject->next->option));
596     PetscCall(PetscFree(PetscOptionsObject->next->man));
597     PetscCall(PetscFree(PetscOptionsObject->next->edata));
598 
599     if ((PetscOptionsObject->next->type == OPTION_STRING) || (PetscOptionsObject->next->type == OPTION_FLIST) || (PetscOptionsObject->next->type == OPTION_ELIST)) {
600       free(PetscOptionsObject->next->data);
601     } else {
602       PetscCall(PetscFree(PetscOptionsObject->next->data));
603     }
604 
605     last                     = PetscOptionsObject->next;
606     PetscOptionsObject->next = PetscOptionsObject->next->next;
607     PetscCall(PetscFree(last));
608   }
609   PetscCall(PetscFree(PetscOptionsObject->prefix));
610   PetscOptionsObject->next = NULL;
611   PetscFunctionReturn(PETSC_SUCCESS);
612 }
613 
614 /*MC
615    PetscOptionsEnum - Gets the enum value for a particular option in the database.
616 
617    Synopsis:
618    #include "petscsys.h"
619    PetscErrorCode  PetscOptionsEnum(const char opt[],const char text[],const char man[],const char *const *list,PetscEnum currentvalue,PetscEnum *value,PetscBool  *set)
620 
621    Logically Collective on the communicator passed in `PetscOptionsBegin()`
622 
623    Input Parameters:
624 +  opt - option name
625 .  text - short string that describes the option
626 .  man - manual page with additional information on option
627 .  list - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
628 -  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
629 .vb
630                  PetscOptionsEnum(..., obj->value,&object->value,...) or
631                  value = defaultvalue
632                  PetscOptionsEnum(..., value,&value,&flg);
633                  if (flg) {
634 .ve
635 
636    Output Parameters:
637 +  value - the  value to return
638 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
639 
640    Level: beginner
641 
642    Notes:
643     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
644 
645           list is usually something like `PCASMTypes` or some other predefined list of enum names
646 
647           If the user does not supply the option at all value is NOT changed. Thus
648           you should ALWAYS initialize value if you access it without first checking if the set flag is true.
649 
650           The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
651 
652 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
653           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
654           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
655           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
656           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
657           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
658           `PetscOptionsFList()`, `PetscOptionsEList()`
659 M*/
660 
661 PetscErrorCode PetscOptionsEnum_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum currentvalue, PetscEnum *value, PetscBool *set)
662 {
663   PetscInt  ntext = 0;
664   PetscInt  tval;
665   PetscBool tflg;
666 
667   PetscFunctionBegin;
668   while (list[ntext++]) PetscCheck(ntext <= 50, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument appears to be wrong or have more than 50 entries");
669   PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
670   ntext -= 3;
671   PetscCall(PetscOptionsEList_Private(PetscOptionsObject, opt, text, man, list, ntext, list[currentvalue], &tval, &tflg));
672   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
673   if (tflg) *value = (PetscEnum)tval;
674   if (set) *set = tflg;
675   PetscFunctionReturn(PETSC_SUCCESS);
676 }
677 
678 /*MC
679    PetscOptionsEnumArray - Gets an array of enum values for a particular
680    option in the database.
681 
682    Synopsis:
683    #include "petscsys.h"
684    PetscErrorCode  PetscOptionsEnumArray(const char opt[],const char text[],const char man[],const char *const *list,PetscEnum value[],PetscInt *n,PetscBool  *set)
685 
686    Logically Collective on the communicator passed in `PetscOptionsBegin()`
687 
688    Input Parameters:
689 +  opt - the option one is seeking
690 .  text - short string describing option
691 .  man - manual page for option
692 .  list - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
693 -  n - maximum number of values allowed in the value array
694 
695    Output Parameters:
696 +  value - location to copy values
697 .  n - actual number of values found
698 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
699 
700    Level: beginner
701 
702    Notes:
703    The array must be passed as a comma separated list.
704 
705    There must be no intervening spaces between the values.
706 
707    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
708 
709 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
710           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
711           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
712           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
713           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
714           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsRealArray()`
715 M*/
716 
717 PetscErrorCode PetscOptionsEnumArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum value[], PetscInt *n, PetscBool *set)
718 {
719   PetscInt        i, nlist = 0;
720   PetscOptionItem amsopt;
721 
722   PetscFunctionBegin;
723   while (list[nlist++]) PetscCheck(nlist <= 50, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument appears to be wrong or have more than 50 entries");
724   PetscCheck(nlist >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
725   nlist -= 3;                            /* drop enum name, prefix, and null termination */
726   if (0 && !PetscOptionsObject->count) { /* XXX Requires additional support */
727     PetscEnum *vals;
728     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY /*XXX OPTION_ENUM_ARRAY*/, &amsopt));
729     PetscCall(PetscStrNArrayallocpy(nlist, list, (char ***)&amsopt->list));
730     amsopt->nlist = nlist;
731     PetscCall(PetscMalloc1(*n, (PetscEnum **)&amsopt->data));
732     amsopt->arraylength = *n;
733     vals                = (PetscEnum *)amsopt->data;
734     for (i = 0; i < *n; i++) vals[i] = value[i];
735   }
736   PetscCall(PetscOptionsGetEnumArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, list, value, n, set));
737   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
738     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%s", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, list[value[0]]));
739     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%s", list[value[i]]));
740     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (choose from)", text));
741     for (i = 0; i < nlist; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " %s", list[i]));
742     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " (%s)\n", ManSection(man)));
743   }
744   PetscFunctionReturn(PETSC_SUCCESS);
745 }
746 
747 /*MC
748    PetscOptionsBoundedInt - Gets an integer value greater than or equal a given bound for a particular option in the database.
749 
750    Synopsis:
751    #include "petscsys.h"
752    PetscErrorCode  PetscOptionsBoundedInt(const char opt[],const char text[],const char man[],PetscInt currentvalue,PetscInt *value,PetscBool *flg,PetscInt bound)
753 
754    Logically Collective on the communicator passed in `PetscOptionsBegin()`
755 
756    Input Parameters:
757 +  opt - option name
758 .  text - short string that describes the option
759 .  man - manual page with additional information on option
760 .  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
761 .vb
762   PetscOptionsInt(..., obj->value,&obj->value,...)
763 .ve
764 or
765 .vb
766   value = defaultvalue
767   PetscOptionsInt(..., value,&value,&flg);
768   if (flg) {
769 .ve
770 -  bound - the requested value should be greater than or equal this bound or an error is generated
771 
772    Output Parameters:
773 +  value - the integer value to return
774 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
775 
776    Level: beginner
777 
778    Notes:
779     If the user does not supply the option at all value is NOT changed. Thus
780     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
781 
782     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
783 
784     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
785 
786 .seealso: `PetscOptionsInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
787           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`, `PetscOptionsRangeInt()`
788           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
789           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
790           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
791           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
792           `PetscOptionsFList()`, `PetscOptionsEList()`
793 M*/
794 
795 /*MC
796    PetscOptionsRangeInt - Gets an integer value within a range of values for a particular option in the database.
797 
798    Synopsis:
799    #include "petscsys.h"
800    PetscErrorCode  PetscOptionsRangeInt(const char opt[],const char text[],const char man[],PetscInt currentvalue,PetscInt *value,PetscBool *flg,PetscInt lb,PetscInt ub)
801 
802    Logically Collective on the communicator passed in `PetscOptionsBegin()`
803 
804    Input Parameters:
805 +  opt - option name
806 .  text - short string that describes the option
807 .  man - manual page with additional information on option
808 .  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
809 .vb
810                  PetscOptionsInt(..., obj->value,&obj->value,...) or
811                  value = defaultvalue
812                  PetscOptionsInt(..., value,&value,&flg);
813                  if (flg) {
814 .ve
815 .  lb - the lower bound, provided value must be greater than or equal to this value or an error is generated
816 -  ub - the upper bound, provided value must be less than or equal to this value or an error is generated
817 
818    Output Parameters:
819 +  value - the integer value to return
820 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
821 
822    Level: beginner
823 
824    Notes:
825     If the user does not supply the option at all value is NOT changed. Thus
826     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
827 
828     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
829 
830     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
831 
832 .seealso: `PetscOptionsInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
833           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`, `PetscOptionsBoundedInt()`
834           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
835           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
836           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
837           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
838           `PetscOptionsFList()`, `PetscOptionsEList()`
839 M*/
840 
841 /*MC
842    PetscOptionsInt - Gets the integer value for a particular option in the database.
843 
844    Synopsis:
845    #include "petscsys.h"
846    PetscErrorCode  PetscOptionsInt(const char opt[],const char text[],const char man[],PetscInt currentvalue,PetscInt *value,PetscBool *flg))
847 
848    Logically Collective on the communicator passed in `PetscOptionsBegin()`
849 
850    Input Parameters:
851 +  opt - option name
852 .  text - short string that describes the option
853 .  man - manual page with additional information on option
854 -  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
855 .vb
856                  PetscOptionsInt(..., obj->value,&obj->value,...) or
857                  value = defaultvalue
858                  PetscOptionsInt(..., value,&value,&flg);
859                  if (flg) {
860 .ve
861 
862    Output Parameters:
863 +  value - the integer value to return
864 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
865 
866    Notes:
867     If the user does not supply the option at all value is NOT changed. Thus
868     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
869 
870     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
871 
872     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
873 
874    Level: beginner
875 
876 .seealso: `PetscOptionsBoundedInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
877           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`, `PetscOptionsRangeInt()`
878           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
879           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
880           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
881           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
882           `PetscOptionsFList()`, `PetscOptionsEList()`
883 M*/
884 
885 PetscErrorCode PetscOptionsInt_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt currentvalue, PetscInt *value, PetscBool *set, PetscInt lb, PetscInt ub)
886 {
887   PetscOptionItem amsopt;
888   PetscBool       wasset;
889 
890   PetscFunctionBegin;
891   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, currentvalue, lb);
892   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, currentvalue, ub);
893   if (!PetscOptionsObject->count) {
894     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
895     PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
896     *(PetscInt *)amsopt->data = currentvalue;
897 
898     PetscCall(PetscOptionsGetInt(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, &currentvalue, &wasset));
899     if (wasset) *(PetscInt *)amsopt->data = currentvalue;
900   }
901   PetscCall(PetscOptionsGetInt(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, &wasset));
902   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, *value, lb);
903   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, *value, ub);
904   if (set) *set = wasset;
905   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
906     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <now %" PetscInt_FMT " : formerly %" PetscInt_FMT ">: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, wasset && value ? *value : currentvalue, currentvalue, text, ManSection(man)));
907   }
908   PetscFunctionReturn(PETSC_SUCCESS);
909 }
910 
911 /*MC
912    PetscOptionsString - Gets the string value for a particular option in the database.
913 
914    Synopsis:
915    #include "petscsys.h"
916    PetscErrorCode  PetscOptionsString(const char opt[],const char text[],const char man[],const char currentvalue[],char value[],size_t len,PetscBool  *set)
917 
918    Logically Collective on the communicator passed in `PetscOptionsBegin()`
919 
920    Input Parameters:
921 +  opt - option name
922 .  text - short string that describes the option
923 .  man - manual page with additional information on option
924 .  currentvalue - the current value; caller is responsible for setting this value correctly. This is not used to set value
925 -  len - length of the result string including null terminator
926 
927    Output Parameters:
928 +  value - the value to return
929 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
930 
931    Level: beginner
932 
933    Notes:
934     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
935 
936    Even if the user provided no string (for example -optionname -someotheroption) the flag is set to PETSC_TRUE (and the string is fulled with nulls).
937 
938           If the user does not supply the option at all value is NOT changed. Thus
939           you should ALWAYS initialize value if you access it without first checking if the set flag is true.
940 
941           The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
942 
943 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
944           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
945           `PetscOptionsInt()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
946           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
947           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
948           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
949           `PetscOptionsFList()`, `PetscOptionsEList()`
950 M*/
951 
952 PetscErrorCode PetscOptionsString_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char currentvalue[], char value[], size_t len, PetscBool *set)
953 {
954   PetscOptionItem amsopt;
955   PetscBool       lset;
956 
957   PetscFunctionBegin;
958   if (!PetscOptionsObject->count) {
959     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
960     /* must use system malloc since SAWs may free this */
961     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
962   }
963   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, len, &lset));
964   if (set) *set = lset;
965   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
966     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <now %s : formerly %s>: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, lset && value ? value : currentvalue, currentvalue, text, ManSection(man)));
967   }
968   PetscFunctionReturn(PETSC_SUCCESS);
969 }
970 
971 /*MC
972    PetscOptionsReal - Gets the `PetscReal` value for a particular option in the database.
973 
974    Synopsis:
975    #include "petscsys.h"
976    PetscErrorCode  PetscOptionsReal(const char opt[],const char text[],const char man[],PetscReal currentvalue,PetscReal *value,PetscBool  *set)
977 
978    Logically Collective on the communicator passed in `PetscOptionsBegin()`
979 
980    Input Parameters:
981 +  opt - option name
982 .  text - short string that describes the option
983 .  man - manual page with additional information on option
984 -  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
985 .vb
986                  PetscOptionsReal(..., obj->value,&obj->value,...) or
987                  value = defaultvalue
988                  PetscOptionsReal(..., value,&value,&flg);
989                  if (flg) {
990 .ve
991 
992    Output Parameters:
993 +  value - the value to return
994 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
995 
996    Notes:
997     If the user does not supply the option at all value is NOT changed. Thus
998     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
999 
1000     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
1001 
1002     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1003 
1004    Level: beginner
1005 
1006 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1007           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
1008           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
1009           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1010           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1011           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1012           `PetscOptionsFList()`, `PetscOptionsEList()`
1013 M*/
1014 
1015 PetscErrorCode PetscOptionsReal_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal currentvalue, PetscReal *value, PetscBool *set)
1016 {
1017   PetscOptionItem amsopt;
1018   PetscBool       lset;
1019 
1020   PetscFunctionBegin;
1021   if (!PetscOptionsObject->count) {
1022     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt));
1023     PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data));
1024 
1025     *(PetscReal *)amsopt->data = currentvalue;
1026   }
1027   PetscCall(PetscOptionsGetReal(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, &lset));
1028   if (set) *set = lset;
1029   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1030     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%g : %g>: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, lset && value ? (double)*value : (double)currentvalue, (double)currentvalue, text, ManSection(man)));
1031   }
1032   PetscFunctionReturn(PETSC_SUCCESS);
1033 }
1034 
1035 /*MC
1036    PetscOptionsScalar - Gets the `PetscScalar` value for a particular option in the database.
1037 
1038    Synopsis:
1039    #include "petscsys.h"
1040    PetscErrorCode PetscOptionsScalar(const char opt[],const char text[],const char man[],PetscScalar currentvalue,PetscScalar *value,PetscBool  *set)
1041 
1042    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1043 
1044    Input Parameters:
1045 +  opt - option name
1046 .  text - short string that describes the option
1047 .  man - manual page with additional information on option
1048 -  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
1049 .vb
1050                  PetscOptionsScalar(..., obj->value,&obj->value,...) or
1051                  value = defaultvalue
1052                  PetscOptionsScalar(..., value,&value,&flg);
1053                  if (flg) {
1054 .ve
1055 
1056    Output Parameters:
1057 +  value - the value to return
1058 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
1059 
1060    Notes:
1061     If the user does not supply the option at all value is NOT changed. Thus
1062     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
1063 
1064     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
1065 
1066     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1067 
1068    Level: beginner
1069 
1070 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1071           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
1072           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
1073           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1074           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1075           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1076           `PetscOptionsFList()`, `PetscOptionsEList()`
1077 M*/
1078 
1079 PetscErrorCode PetscOptionsScalar_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar currentvalue, PetscScalar *value, PetscBool *set)
1080 {
1081   PetscFunctionBegin;
1082 #if !defined(PETSC_USE_COMPLEX)
1083   PetscCall(PetscOptionsReal(opt, text, man, currentvalue, value, set));
1084 #else
1085   PetscCall(PetscOptionsGetScalar(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, set));
1086 #endif
1087   PetscFunctionReturn(PETSC_SUCCESS);
1088 }
1089 
1090 /*MC
1091    PetscOptionsName - Determines if a particular option has been set in the database. This returns true whether the option is a number, string or boolean, even
1092                       its value is set to false.
1093 
1094    Synopsis:
1095    #include "petscsys.h"
1096    PetscErrorCode PetscOptionsName(const char opt[],const char text[],const char man[],PetscBool  *flg)
1097 
1098    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1099 
1100    Input Parameters:
1101 +  opt - option name
1102 .  text - short string that describes the option
1103 -  man - manual page with additional information on option
1104 
1105    Output Parameter:
1106 .  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
1107 
1108    Level: beginner
1109 
1110    Note:
1111     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1112 
1113 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1114           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
1115           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
1116           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1117           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1118           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1119           `PetscOptionsFList()`, `PetscOptionsEList()`
1120 M*/
1121 
1122 PetscErrorCode PetscOptionsName_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
1123 {
1124   PetscOptionItem amsopt;
1125 
1126   PetscFunctionBegin;
1127   if (!PetscOptionsObject->count) {
1128     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1129     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1130 
1131     *(PetscBool *)amsopt->data = PETSC_FALSE;
1132   }
1133   PetscCall(PetscOptionsHasName(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg));
1134   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1135     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1136   }
1137   PetscFunctionReturn(PETSC_SUCCESS);
1138 }
1139 
1140 /*MC
1141      PetscOptionsFList - Puts a list of option values that a single one may be selected from
1142 
1143    Synopsis:
1144    #include "petscsys.h"
1145    PetscErrorCode  PetscOptionsFList(const char opt[],const char ltext[],const char man[],PetscFunctionList list,const char currentvalue[],char value[],size_t len,PetscBool  *set)
1146 
1147    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1148 
1149    Input Parameters:
1150 +  opt - option name
1151 .  text - short string that describes the option
1152 .  man - manual page with additional information on option
1153 .  list - the possible choices
1154 .  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with
1155 .vb
1156                  PetscOptionsFlist(..., obj->value,value,len,&flg);
1157                  if (flg) {
1158 .ve
1159 -  len - the length of the character array value
1160 
1161    Output Parameters:
1162 +  value - the value to return
1163 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1164 
1165    Level: intermediate
1166 
1167    Notes:
1168     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1169 
1170           If the user does not supply the option at all value is NOT changed. Thus
1171           you should ALWAYS initialize value if you access it without first checking if the set flag is true.
1172 
1173           The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
1174 
1175    See `PetscOptionsEList()` for when the choices are given in a string array
1176 
1177    To get a listing of all currently specified options,
1178     see `PetscOptionsView()` or `PetscOptionsGetAll()`
1179 
1180    Developer Note:
1181    This cannot check for invalid selection because of things like `MATAIJ` that are not included in the list
1182 
1183 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1184           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1185           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1186           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1187           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1188           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsEnum()`
1189 M*/
1190 
1191 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)
1192 {
1193   PetscOptionItem amsopt;
1194   PetscBool       lset;
1195 
1196   PetscFunctionBegin;
1197   if (!PetscOptionsObject->count) {
1198     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_FLIST, &amsopt));
1199     /* must use system malloc since SAWs may free this */
1200     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
1201     amsopt->flist = list;
1202   }
1203   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, len, &lset));
1204   if (set) *set = lset;
1205   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1206     PetscCall(PetscFunctionListPrintTypes(PetscOptionsObject->comm, stdout, PetscOptionsObject->prefix, opt, ltext, man, list, currentvalue, lset && value ? value : currentvalue));
1207   }
1208   PetscFunctionReturn(PETSC_SUCCESS);
1209 }
1210 
1211 /*MC
1212      PetscOptionsEList - Puts a list of option values that a single one may be selected from
1213 
1214    Synopsis:
1215    #include "petscsys.h"
1216    PetscErrorCode  PetscOptionsEList(const char opt[],const char ltext[],const char man[],const char *const *list,PetscInt ntext,const char currentvalue[],PetscInt *value,PetscBool  *set)
1217 
1218    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1219 
1220    Input Parameters:
1221 +  opt - option name
1222 .  ltext - short string that describes the option
1223 .  man - manual page with additional information on option
1224 .  list - the possible choices (one of these must be selected, anything else is invalid)
1225 .  ntext - number of choices
1226 -  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with
1227 .vb
1228                  PetscOptionsEList(..., obj->value,&value,&flg);
1229 .ve                 if (flg) {
1230 
1231    Output Parameters:
1232 +  value - the index of the value to return
1233 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1234 
1235    Level: intermediate
1236 
1237    Notes:
1238     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1239 
1240          If the user does not supply the option at all value is NOT changed. Thus
1241           you should ALWAYS initialize value if you access it without first checking if the set flag is true.
1242 
1243    See `PetscOptionsFList()` for when the choices are given in a `PetscFunctionList()`
1244 
1245 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1246           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1247           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1248           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1249           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1250           `PetscOptionsFList()`, `PetscOptionsEnum()`
1251 M*/
1252 
1253 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)
1254 {
1255   PetscInt        i;
1256   PetscOptionItem amsopt;
1257   PetscBool       lset;
1258 
1259   PetscFunctionBegin;
1260   if (!PetscOptionsObject->count) {
1261     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_ELIST, &amsopt));
1262     /* must use system malloc since SAWs may free this */
1263     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
1264     PetscCall(PetscStrNArrayallocpy(ntext, list, (char ***)&amsopt->list));
1265     amsopt->nlist = ntext;
1266   }
1267   PetscCall(PetscOptionsGetEList(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, list, ntext, value, &lset));
1268   if (set) *set = lset;
1269   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1270     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <now %s : formerly %s> %s (choose one of)", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, lset && value ? list[*value] : currentvalue, currentvalue, ltext));
1271     for (i = 0; i < ntext; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " %s", list[i]));
1272     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " (%s)\n", ManSection(man)));
1273   }
1274   PetscFunctionReturn(PETSC_SUCCESS);
1275 }
1276 
1277 /*MC
1278      PetscOptionsBoolGroupBegin - First in a series of logical queries on the options database for
1279        which at most a single value can be true.
1280 
1281    Synopsis:
1282    #include "petscsys.h"
1283    PetscErrorCode PetscOptionsBoolGroupBegin(const char opt[],const char text[],const char man[],PetscBool  *flg)
1284 
1285    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1286 
1287    Input Parameters:
1288 +  opt - option name
1289 .  text - short string that describes the option
1290 -  man - manual page with additional information on option
1291 
1292    Output Parameter:
1293 .  flg - whether that option was set or not
1294 
1295    Level: intermediate
1296 
1297    Notes:
1298     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1299 
1300    Must be followed by 0 or more P`etscOptionsBoolGroup()`s and `PetscOptionsBoolGroupEnd()`
1301 
1302 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1303           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1304           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1305           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1306           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1307           `PetscOptionsFList()`, `PetscOptionsEList()`
1308 M*/
1309 
1310 PetscErrorCode PetscOptionsBoolGroupBegin_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
1311 {
1312   PetscOptionItem amsopt;
1313 
1314   PetscFunctionBegin;
1315   if (!PetscOptionsObject->count) {
1316     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1317     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1318 
1319     *(PetscBool *)amsopt->data = PETSC_FALSE;
1320   }
1321   *flg = PETSC_FALSE;
1322   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg, NULL));
1323   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1324     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  Pick at most one of -------------\n"));
1325     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1326   }
1327   PetscFunctionReturn(PETSC_SUCCESS);
1328 }
1329 
1330 /*MC
1331      PetscOptionsBoolGroup - One in a series of logical queries on the options database for
1332        which at most a single value can be true.
1333 
1334    Synopsis:
1335    #include "petscsys.h"
1336    PetscErrorCode PetscOptionsBoolGroup(const char opt[],const char text[],const char man[],PetscBool  *flg)
1337 
1338    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1339 
1340    Input Parameters:
1341 +  opt - option name
1342 .  text - short string that describes the option
1343 -  man - manual page with additional information on option
1344 
1345    Output Parameter:
1346 .  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
1347 
1348    Level: intermediate
1349 
1350    Notes:
1351     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1352 
1353    Must follow a `PetscOptionsBoolGroupBegin()` and preceded a `PetscOptionsBoolGroupEnd()`
1354 
1355 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1356           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1357           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1358           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1359           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1360           `PetscOptionsFList()`, `PetscOptionsEList()`
1361 M*/
1362 
1363 PetscErrorCode PetscOptionsBoolGroup_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
1364 {
1365   PetscOptionItem amsopt;
1366 
1367   PetscFunctionBegin;
1368   if (!PetscOptionsObject->count) {
1369     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1370     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1371 
1372     *(PetscBool *)amsopt->data = PETSC_FALSE;
1373   }
1374   *flg = PETSC_FALSE;
1375   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg, NULL));
1376   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1377     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1378   }
1379   PetscFunctionReturn(PETSC_SUCCESS);
1380 }
1381 
1382 /*MC
1383      PetscOptionsBoolGroupEnd - Last in a series of logical queries on the options database for
1384        which at most a single value can be true.
1385 
1386    Synopsis:
1387    #include "petscsys.h"
1388    PetscErrorCode PetscOptionsBoolGroupEnd(const char opt[],const char text[],const char man[],PetscBool  *flg)
1389 
1390    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1391 
1392    Input Parameters:
1393 +  opt - option name
1394 .  text - short string that describes the option
1395 -  man - manual page with additional information on option
1396 
1397    Output Parameter:
1398 .  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
1399 
1400    Level: intermediate
1401 
1402    Notes:
1403     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1404 
1405    Must follow a `PetscOptionsBoolGroupBegin()`
1406 
1407 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1408           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1409           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1410           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1411           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1412           `PetscOptionsFList()`, `PetscOptionsEList()`
1413 M*/
1414 
1415 PetscErrorCode PetscOptionsBoolGroupEnd_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
1416 {
1417   PetscOptionItem amsopt;
1418 
1419   PetscFunctionBegin;
1420   if (!PetscOptionsObject->count) {
1421     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1422     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1423 
1424     *(PetscBool *)amsopt->data = PETSC_FALSE;
1425   }
1426   *flg = PETSC_FALSE;
1427   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg, NULL));
1428   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1429     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1430   }
1431   PetscFunctionReturn(PETSC_SUCCESS);
1432 }
1433 
1434 /*MC
1435    PetscOptionsBool - Determines if a particular option is in the database with a true or false
1436 
1437    Synopsis:
1438    #include "petscsys.h"
1439    PetscErrorCode PetscOptionsBool(const char opt[],const char text[],const char man[],PetscBool currentvalue,PetscBool  *flg,PetscBool  *set)
1440 
1441    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1442 
1443    Input Parameters:
1444 +  opt - option name
1445 .  text - short string that describes the option
1446 .  man - manual page with additional information on option
1447 -  currentvalue - the current value
1448 
1449    Output Parameters:
1450 +  flg -` PETSC_TRUE` or `PETSC_FALSE`
1451 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1452 
1453    Notes:
1454        TRUE, true, YES, yes, nostring, and 1 all translate to `PETSC_TRUE`
1455        FALSE, false, NO, no, and 0 all translate to `PETSC_FALSE`
1456 
1457       If the option is given, but no value is provided, then flg and set are both given the value `PETSC_TRUE`. That is -requested_bool
1458      is equivalent to -requested_bool true
1459 
1460        If the user does not supply the option at all flg is NOT changed. Thus
1461      you should ALWAYS initialize the flg if you access it without first checking if the set flag is true.
1462 
1463     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1464 
1465    Level: beginner
1466 
1467 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1468           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
1469           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
1470           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1471           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1472           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1473           `PetscOptionsFList()`, `PetscOptionsEList()`
1474 M*/
1475 
1476 PetscErrorCode PetscOptionsBool_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool currentvalue, PetscBool *flg, PetscBool *set)
1477 {
1478   PetscBool       iset;
1479   PetscOptionItem amsopt;
1480 
1481   PetscFunctionBegin;
1482   if (!PetscOptionsObject->count) {
1483     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1484     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1485 
1486     *(PetscBool *)amsopt->data = currentvalue;
1487   }
1488   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg, &iset));
1489   if (set) *set = iset;
1490   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1491     const char *v = PetscBools[currentvalue], *vn = PetscBools[iset && flg ? *flg : currentvalue];
1492     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <%s : %s> %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, v, vn, text, ManSection(man)));
1493   }
1494   PetscFunctionReturn(PETSC_SUCCESS);
1495 }
1496 
1497 /*MC
1498    PetscOptionsRealArray - Gets an array of double values for a particular
1499    option in the database. The values must be separated with commas with
1500    no intervening spaces.
1501 
1502    Synopsis:
1503    #include "petscsys.h"
1504    PetscErrorCode PetscOptionsRealArray(const char opt[],const char text[],const char man[],PetscReal value[],PetscInt *n,PetscBool  *set)
1505 
1506    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1507 
1508    Input Parameters:
1509 +  opt - the option one is seeking
1510 .  text - short string describing option
1511 .  man - manual page for option
1512 -  n - maximum number of values that value has room for
1513 
1514    Output Parameters:
1515 +  value - location to copy values
1516 .  n - actual number of values found
1517 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1518 
1519    Level: beginner
1520 
1521    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1522 
1523 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1524           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1525           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1526           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1527           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1528           `PetscOptionsFList()`, `PetscOptionsEList()`
1529 M*/
1530 
1531 PetscErrorCode PetscOptionsRealArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal value[], PetscInt *n, PetscBool *set)
1532 {
1533   PetscInt        i;
1534   PetscOptionItem amsopt;
1535 
1536   PetscFunctionBegin;
1537   if (!PetscOptionsObject->count) {
1538     PetscReal *vals;
1539 
1540     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt));
1541     PetscCall(PetscMalloc((*n) * sizeof(PetscReal), &amsopt->data));
1542     vals = (PetscReal *)amsopt->data;
1543     for (i = 0; i < *n; i++) vals[i] = value[i];
1544     amsopt->arraylength = *n;
1545   }
1546   PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, n, set));
1547   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1548     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%g", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, (double)value[0]));
1549     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%g", (double)value[i]));
1550     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (%s)\n", text, ManSection(man)));
1551   }
1552   PetscFunctionReturn(PETSC_SUCCESS);
1553 }
1554 
1555 /*MC
1556    PetscOptionsScalarArray - Gets an array of `PetscScalar` values for a particular
1557    option in the database. The values must be separated with commas with
1558    no intervening spaces.
1559 
1560    Synopsis:
1561    #include "petscsys.h"
1562    PetscErrorCode PetscOptionsScalarArray(const char opt[],const char text[],const char man[],PetscScalar value[],PetscInt *n,PetscBool  *set)
1563 
1564    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1565 
1566    Input Parameters:
1567 +  opt - the option one is seeking
1568 .  text - short string describing option
1569 .  man - manual page for option
1570 -  n - maximum number of values allowed in the value array
1571 
1572    Output Parameters:
1573 +  value - location to copy values
1574 .  n - actual number of values found
1575 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1576 
1577    Level: beginner
1578 
1579    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1580 
1581 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1582           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1583           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1584           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1585           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1586           `PetscOptionsFList()`, `PetscOptionsEList()`
1587 M*/
1588 
1589 PetscErrorCode PetscOptionsScalarArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar value[], PetscInt *n, PetscBool *set)
1590 {
1591   PetscInt        i;
1592   PetscOptionItem amsopt;
1593 
1594   PetscFunctionBegin;
1595   if (!PetscOptionsObject->count) {
1596     PetscScalar *vals;
1597 
1598     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt));
1599     PetscCall(PetscMalloc((*n) * sizeof(PetscScalar), &amsopt->data));
1600     vals = (PetscScalar *)amsopt->data;
1601     for (i = 0; i < *n; i++) vals[i] = value[i];
1602     amsopt->arraylength = *n;
1603   }
1604   PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, n, set));
1605   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1606     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%g+%gi", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0])));
1607     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i])));
1608     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (%s)\n", text, ManSection(man)));
1609   }
1610   PetscFunctionReturn(PETSC_SUCCESS);
1611 }
1612 
1613 /*MC
1614    PetscOptionsIntArray - Gets an array of integers for a particular
1615    option in the database.
1616 
1617    Synopsis:
1618    #include "petscsys.h"
1619    PetscErrorCode PetscOptionsIntArray(const char opt[],const char text[],const char man[],PetscInt value[],PetscInt *n,PetscBool  *set)
1620 
1621    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1622 
1623    Input Parameters:
1624 +  opt - the option one is seeking
1625 .  text - short string describing option
1626 .  man - manual page for option
1627 -  n - maximum number of values
1628 
1629    Output Parameters:
1630 +  value - location to copy values
1631 .  n - actual number of values found
1632 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1633 
1634    Level: beginner
1635 
1636    Notes:
1637    The array can be passed as
1638 +   a comma separated list -                                  0,1,2,3,4,5,6,7
1639 .   a range (start\-end+1) -                                  0-8
1640 .   a range with given increment (start\-end+1:inc) -         0-7:2
1641 -   a combination of values and ranges separated by commas -  0,1-8,8-15:2
1642 
1643    There must be no intervening spaces between the values.
1644 
1645    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1646 
1647 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1648           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1649           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1650           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1651           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1652           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsRealArray()`
1653 M*/
1654 
1655 PetscErrorCode PetscOptionsIntArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt value[], PetscInt *n, PetscBool *set)
1656 {
1657   PetscInt        i;
1658   PetscOptionItem amsopt;
1659 
1660   PetscFunctionBegin;
1661   if (!PetscOptionsObject->count) {
1662     PetscInt *vals;
1663 
1664     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY, &amsopt));
1665     PetscCall(PetscMalloc1(*n, (PetscInt **)&amsopt->data));
1666     vals = (PetscInt *)amsopt->data;
1667     for (i = 0; i < *n; i++) vals[i] = value[i];
1668     amsopt->arraylength = *n;
1669   }
1670   PetscCall(PetscOptionsGetIntArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, n, set));
1671   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1672     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%" PetscInt_FMT, PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, value[0]));
1673     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%" PetscInt_FMT, value[i]));
1674     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (%s)\n", text, ManSection(man)));
1675   }
1676   PetscFunctionReturn(PETSC_SUCCESS);
1677 }
1678 
1679 /*MC
1680    PetscOptionsStringArray - Gets an array of string values for a particular
1681    option in the database. The values must be separated with commas with
1682    no intervening spaces.
1683 
1684    Synopsis:
1685    #include "petscsys.h"
1686    PetscErrorCode PetscOptionsStringArray(const char opt[],const char text[],const char man[],char *value[],PetscInt *nmax,PetscBool  *set)
1687 
1688    Logically Collective on the communicator passed in `PetscOptionsBegin()`; No Fortran Support
1689 
1690    Input Parameters:
1691 +  opt - the option one is seeking
1692 .  text - short string describing option
1693 .  man - manual page for option
1694 -  nmax - maximum number of strings
1695 
1696    Output Parameters:
1697 +  value - location to copy strings
1698 .  nmax - actual number of strings found
1699 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1700 
1701    Level: beginner
1702 
1703    Notes:
1704    The user should pass in an array of pointers to char, to hold all the
1705    strings returned by this function.
1706 
1707    The user is responsible for deallocating the strings that are
1708    returned.
1709 
1710    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1711 
1712 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1713           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1714           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1715           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1716           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1717           `PetscOptionsFList()`, `PetscOptionsEList()`
1718 M*/
1719 
1720 PetscErrorCode PetscOptionsStringArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], char *value[], PetscInt *nmax, PetscBool *set)
1721 {
1722   PetscOptionItem amsopt;
1723 
1724   PetscFunctionBegin;
1725   if (!PetscOptionsObject->count) {
1726     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt));
1727     PetscCall(PetscMalloc1(*nmax, (char **)&amsopt->data));
1728 
1729     amsopt->arraylength = *nmax;
1730   }
1731   PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, nmax, set));
1732   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1733     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <string1,string2,...>: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1734   }
1735   PetscFunctionReturn(PETSC_SUCCESS);
1736 }
1737 
1738 /*MC
1739    PetscOptionsBoolArray - Gets an array of logical values (true or false) for a particular
1740    option in the database. The values must be separated with commas with
1741    no intervening spaces.
1742 
1743    Synopsis:
1744    #include "petscsys.h"
1745    PetscErrorCode PetscOptionsBoolArray(const char opt[],const char text[],const char man[],PetscBool value[],PetscInt *n,PetscBool *set)
1746 
1747    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1748 
1749    Input Parameters:
1750 +  opt - the option one is seeking
1751 .  text - short string describing option
1752 .  man - manual page for option
1753 -  n - maximum number of values allowed in the value array
1754 
1755    Output Parameters:
1756 +  value - location to copy values
1757 .  n - actual number of values found
1758 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1759 
1760    Level: beginner
1761 
1762    Notes:
1763    The user should pass in an array of doubles
1764 
1765    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1766 
1767 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1768           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1769           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1770           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1771           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1772           `PetscOptionsFList()`, `PetscOptionsEList()`
1773 M*/
1774 
1775 PetscErrorCode PetscOptionsBoolArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool value[], PetscInt *n, PetscBool *set)
1776 {
1777   PetscInt        i;
1778   PetscOptionItem amsopt;
1779 
1780   PetscFunctionBegin;
1781   if (!PetscOptionsObject->count) {
1782     PetscBool *vals;
1783 
1784     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt));
1785     PetscCall(PetscMalloc1(*n, (PetscBool **)&amsopt->data));
1786     vals = (PetscBool *)amsopt->data;
1787     for (i = 0; i < *n; i++) vals[i] = value[i];
1788     amsopt->arraylength = *n;
1789   }
1790   PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, n, set));
1791   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1792     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%d", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, value[0]));
1793     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%d", value[i]));
1794     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (%s)\n", text, ManSection(man)));
1795   }
1796   PetscFunctionReturn(PETSC_SUCCESS);
1797 }
1798 
1799 /*MC
1800    PetscOptionsViewer - Gets a viewer appropriate for the type indicated by the user
1801 
1802    Synopsis:
1803    #include "petscsys.h"
1804    PetscErrorCode PetscOptionsViewer(const char opt[],const char text[],const char man[],PetscViewer *viewer,PetscViewerFormat *format,PetscBool *set)
1805 
1806    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1807 
1808    Input Parameters:
1809 +  opt - option name
1810 .  text - short string that describes the option
1811 -  man - manual page with additional information on option
1812 
1813    Output Parameters:
1814 +  viewer - the viewer
1815 .  format - the PetscViewerFormat requested by the user, pass NULL if not needed
1816 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1817 
1818    Level: beginner
1819 
1820    Notes:
1821     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1822 
1823    See `PetscOptionsGetViewer()` for the format of the supplied viewer and its options
1824 
1825 .seealso: `PetscOptionsGetViewer()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1826           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
1827           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
1828           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1829           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1830           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1831           `PetscOptionsFList()`, `PetscOptionsEList()`
1832 M*/
1833 
1834 PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
1835 {
1836   PetscOptionItem amsopt;
1837 
1838   PetscFunctionBegin;
1839   if (!PetscOptionsObject->count) {
1840     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
1841     /* must use system malloc since SAWs may free this */
1842     PetscCall(PetscStrdup("", (char **)&amsopt->data));
1843   }
1844   PetscCall(PetscOptionsGetViewer(PetscOptionsObject->comm, PetscOptionsObject->options, PetscOptionsObject->prefix, opt, viewer, format, set));
1845   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1846     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%s>: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, "", text, ManSection(man)));
1847   }
1848   PetscFunctionReturn(PETSC_SUCCESS);
1849 }
1850