xref: /petsc/src/sys/objects/aoptions.c (revision c8c5c547f526914c69472d8cade615559dc64129)
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(PetscStrcpy(tmp, s));
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(PetscStrcpy(option, "-"));
525         PetscCall(PetscStrcat(option, PetscOptionsObject->prefix));
526         PetscCall(PetscStrcat(option, PetscOptionsObject->next->option + 1));
527       } else PetscCall(PetscStrcpy(option, PetscOptionsObject->next->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(PetscStrcat(value, ","));
537           PetscCall(PetscStrcat(value, tmp));
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(PetscStrcat(value, ","));
551           PetscCall(PetscStrcat(value, tmp));
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(PetscStrcat(value, ","));
559           PetscCall(PetscStrcat(value, tmp));
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(PetscStrcat(value, ","));
570           PetscCall(PetscStrcat(value, tmp));
571         }
572         break;
573       case OPTION_FLIST:
574         PetscCall(PetscStrcpy(value, (char *)PetscOptionsObject->next->data));
575         break;
576       case OPTION_ELIST:
577         PetscCall(PetscStrcpy(value, (char *)PetscOptionsObject->next->data));
578         break;
579       case OPTION_STRING:
580         PetscCall(PetscStrcpy(value, (char *)PetscOptionsObject->next->data));
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(PetscStrcat(value, ","));
587           PetscCall(PetscStrcat(value, tmp));
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    Logically Collective on the communicator passed in `PetscOptionsBegin()`
618 
619    Synopsis:
620    #include "petscsys.h"
621    PetscErrorCode  PetscOptionsEnum(const char opt[],const char text[],const char man[],const char *const *list,PetscEnum currentvalue,PetscEnum *value,PetscBool  *set)
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 $                 PetscOptionsEnum(..., obj->value,&object->value,...) or
630 $                 value = defaultvalue
631 $                 PetscOptionsEnum(..., value,&value,&flg);
632 $                 if (flg) {
633 
634    Output Parameters:
635 +  value - the  value to return
636 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
637 
638    Level: beginner
639 
640    Notes:
641     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
642 
643           list is usually something like `PCASMTypes` or some other predefined list of enum names
644 
645           If the user does not supply the option at all value is NOT changed. Thus
646           you should ALWAYS initialize value if you access it without first checking if the set flag is true.
647 
648           The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
649 
650 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
651           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
652           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
653           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
654           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
655           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
656           `PetscOptionsFList()`, `PetscOptionsEList()`
657 M*/
658 
659 PetscErrorCode PetscOptionsEnum_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum currentvalue, PetscEnum *value, PetscBool *set)
660 {
661   PetscInt  ntext = 0;
662   PetscInt  tval;
663   PetscBool tflg;
664 
665   PetscFunctionBegin;
666   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");
667   PetscCheck(ntext >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
668   ntext -= 3;
669   PetscCall(PetscOptionsEList_Private(PetscOptionsObject, opt, text, man, list, ntext, list[currentvalue], &tval, &tflg));
670   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
671   if (tflg) *value = (PetscEnum)tval;
672   if (set) *set = tflg;
673   PetscFunctionReturn(PETSC_SUCCESS);
674 }
675 
676 /*MC
677    PetscOptionsEnumArray - Gets an array of enum values for a particular
678    option in the database.
679 
680    Logically Collective on the communicator passed in `PetscOptionsBegin()`
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    Input Parameters:
687 +  opt - the option one is seeking
688 .  text - short string describing option
689 .  man - manual page for option
690 .  list - array containing the list of choices, followed by the enum name, followed by the enum prefix, followed by a null
691 -  n - maximum number of values allowed in the value array
692 
693    Output Parameters:
694 +  value - location to copy values
695 .  n - actual number of values found
696 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
697 
698    Level: beginner
699 
700    Notes:
701    The array must be passed as a comma separated list.
702 
703    There must be no intervening spaces between the values.
704 
705    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
706 
707 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
708           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
709           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
710           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
711           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
712           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsRealArray()`
713 M*/
714 
715 PetscErrorCode PetscOptionsEnumArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum value[], PetscInt *n, PetscBool *set)
716 {
717   PetscInt        i, nlist = 0;
718   PetscOptionItem amsopt;
719 
720   PetscFunctionBegin;
721   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");
722   PetscCheck(nlist >= 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least two entries: typename and type prefix");
723   nlist -= 3;                            /* drop enum name, prefix, and null termination */
724   if (0 && !PetscOptionsObject->count) { /* XXX Requires additional support */
725     PetscEnum *vals;
726     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY /*XXX OPTION_ENUM_ARRAY*/, &amsopt));
727     PetscCall(PetscStrNArrayallocpy(nlist, list, (char ***)&amsopt->list));
728     amsopt->nlist = nlist;
729     PetscCall(PetscMalloc1(*n, (PetscEnum **)&amsopt->data));
730     amsopt->arraylength = *n;
731     vals                = (PetscEnum *)amsopt->data;
732     for (i = 0; i < *n; i++) vals[i] = value[i];
733   }
734   PetscCall(PetscOptionsGetEnumArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, list, value, n, set));
735   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
736     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%s", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, list[value[0]]));
737     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%s", list[value[i]]));
738     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (choose from)", text));
739     for (i = 0; i < nlist; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " %s", list[i]));
740     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " (%s)\n", ManSection(man)));
741   }
742   PetscFunctionReturn(PETSC_SUCCESS);
743 }
744 
745 /*MC
746    PetscOptionsBoundedInt - Gets an integer value greater than or equal a given bound for a particular option in the database.
747 
748    Logically Collective on the communicator passed in `PetscOptionsBegin()`
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    Input Parameters:
755 +  opt - option name
756 .  text - short string that describes the option
757 .  man - manual page with additional information on option
758 .  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
759 .vb
760   PetscOptionsInt(..., obj->value,&obj->value,...)
761 .ve
762 or
763 .vb
764   value = defaultvalue
765   PetscOptionsInt(..., value,&value,&flg);
766   if (flg) {
767 .ve
768 -  bound - the requested value should be greater than or equal this bound or an error is generated
769 
770    Output Parameters:
771 +  value - the integer value to return
772 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
773 
774    Notes:
775     If the user does not supply the option at all value is NOT changed. Thus
776     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
777 
778     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
779 
780     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
781 
782    Level: beginner
783 
784 .seealso: `PetscOptionsInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
785           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`, `PetscOptionsRangeInt()`
786           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
787           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
788           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
789           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
790           `PetscOptionsFList()`, `PetscOptionsEList()`
791 M*/
792 
793 /*MC
794    PetscOptionsRangeInt - Gets an integer value within a range of values for a particular option in the database.
795 
796    Logically Collective on the communicator passed in `PetscOptionsBegin()`
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    Input Parameters:
803 +  opt - option name
804 .  text - short string that describes the option
805 .  man - manual page with additional information on option
806 .  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
807 $                 PetscOptionsInt(..., obj->value,&obj->value,...) or
808 $                 value = defaultvalue
809 $                 PetscOptionsInt(..., value,&value,&flg);
810 $                 if (flg) {
811 .  lb - the lower bound, provided value must be greater than or equal to this value or an error is generated
812 -  ub - the upper bound, provided value must be less than or equal to this value or an error is generated
813 
814    Output Parameters:
815 +  value - the integer value to return
816 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
817 
818    Notes:
819     If the user does not supply the option at all value is NOT changed. Thus
820     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
821 
822     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
823 
824     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
825 
826    Level: beginner
827 
828 .seealso: `PetscOptionsInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
829           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`, `PetscOptionsBoundedInt()`
830           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
831           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
832           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
833           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
834           `PetscOptionsFList()`, `PetscOptionsEList()`
835 M*/
836 
837 /*MC
838    PetscOptionsInt - Gets the integer value for a particular option in the database.
839 
840    Logically Collective on the communicator passed in `PetscOptionsBegin()`
841 
842    Synopsis:
843    #include "petscsys.h"
844    PetscErrorCode  PetscOptionsInt(const char opt[],const char text[],const char man[],PetscInt currentvalue,PetscInt *value,PetscBool *flg))
845 
846    Input Parameters:
847 +  opt - option name
848 .  text - short string that describes the option
849 .  man - manual page with additional information on option
850 -  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
851 $                 PetscOptionsInt(..., obj->value,&obj->value,...) or
852 $                 value = defaultvalue
853 $                 PetscOptionsInt(..., value,&value,&flg);
854 $                 if (flg) {
855 
856    Output Parameters:
857 +  value - the integer value to return
858 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
859 
860    Notes:
861     If the user does not supply the option at all value is NOT changed. Thus
862     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
863 
864     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
865 
866     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
867 
868    Level: beginner
869 
870 .seealso: `PetscOptionsBoundedInt()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
871           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`, `PetscOptionsRangeInt()`
872           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
873           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
874           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
875           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
876           `PetscOptionsFList()`, `PetscOptionsEList()`
877 M*/
878 
879 PetscErrorCode PetscOptionsInt_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt currentvalue, PetscInt *value, PetscBool *set, PetscInt lb, PetscInt ub)
880 {
881   PetscOptionItem amsopt;
882   PetscBool       wasset;
883 
884   PetscFunctionBegin;
885   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, currentvalue, lb);
886   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, currentvalue, ub);
887   if (!PetscOptionsObject->count) {
888     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
889     PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
890     *(PetscInt *)amsopt->data = currentvalue;
891 
892     PetscCall(PetscOptionsGetInt(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, &currentvalue, &wasset));
893     if (wasset) *(PetscInt *)amsopt->data = currentvalue;
894   }
895   PetscCall(PetscOptionsGetInt(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, &wasset));
896   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, *value, lb);
897   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, *value, ub);
898   if (set) *set = wasset;
899   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
900     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)));
901   }
902   PetscFunctionReturn(PETSC_SUCCESS);
903 }
904 
905 /*MC
906    PetscOptionsString - Gets the string value for a particular option in the database.
907 
908    Logically Collective on the communicator passed in `PetscOptionsBegin()`
909 
910    Synopsis:
911    #include "petscsys.h"
912    PetscErrorCode  PetscOptionsString(const char opt[],const char text[],const char man[],const char currentvalue[],char value[],size_t len,PetscBool  *set)
913 
914    Input Parameters:
915 +  opt - option name
916 .  text - short string that describes the option
917 .  man - manual page with additional information on option
918 .  currentvalue - the current value; caller is responsible for setting this value correctly. This is not used to set value
919 -  len - length of the result string including null terminator
920 
921    Output Parameters:
922 +  value - the value to return
923 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
924 
925    Level: beginner
926 
927    Notes:
928     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
929 
930    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).
931 
932           If the user does not supply the option at all value is NOT changed. Thus
933           you should ALWAYS initialize value if you access it without first checking if the set flag is true.
934 
935           The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
936 
937 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
938           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
939           `PetscOptionsInt()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
940           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
941           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
942           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
943           `PetscOptionsFList()`, `PetscOptionsEList()`
944 M*/
945 
946 PetscErrorCode PetscOptionsString_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char currentvalue[], char value[], size_t len, PetscBool *set)
947 {
948   PetscOptionItem amsopt;
949   PetscBool       lset;
950 
951   PetscFunctionBegin;
952   if (!PetscOptionsObject->count) {
953     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
954     /* must use system malloc since SAWs may free this */
955     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
956   }
957   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, len, &lset));
958   if (set) *set = lset;
959   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
960     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)));
961   }
962   PetscFunctionReturn(PETSC_SUCCESS);
963 }
964 
965 /*MC
966    PetscOptionsReal - Gets the `PetscReal` value for a particular option in the database.
967 
968    Logically Collective on the communicator passed in `PetscOptionsBegin()`
969 
970    Synopsis:
971    #include "petscsys.h"
972    PetscErrorCode  PetscOptionsReal(const char opt[],const char text[],const char man[],PetscReal currentvalue,PetscReal *value,PetscBool  *set)
973 
974    Input Parameters:
975 +  opt - option name
976 .  text - short string that describes the option
977 .  man - manual page with additional information on option
978 -  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
979 $                 PetscOptionsReal(..., obj->value,&obj->value,...) or
980 $                 value = defaultvalue
981 $                 PetscOptionsReal(..., value,&value,&flg);
982 $                 if (flg) {
983 
984    Output Parameters:
985 +  value - the value to return
986 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
987 
988    Notes:
989     If the user does not supply the option at all value is NOT changed. Thus
990     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
991 
992     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
993 
994     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
995 
996    Level: beginner
997 
998 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
999           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
1000           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
1001           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1002           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1003           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1004           `PetscOptionsFList()`, `PetscOptionsEList()`
1005 M*/
1006 
1007 PetscErrorCode PetscOptionsReal_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal currentvalue, PetscReal *value, PetscBool *set)
1008 {
1009   PetscOptionItem amsopt;
1010   PetscBool       lset;
1011 
1012   PetscFunctionBegin;
1013   if (!PetscOptionsObject->count) {
1014     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt));
1015     PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data));
1016 
1017     *(PetscReal *)amsopt->data = currentvalue;
1018   }
1019   PetscCall(PetscOptionsGetReal(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, &lset));
1020   if (set) *set = lset;
1021   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1022     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)));
1023   }
1024   PetscFunctionReturn(PETSC_SUCCESS);
1025 }
1026 
1027 /*MC
1028    PetscOptionsScalar - Gets the `PetscScalar` value for a particular option in the database.
1029 
1030    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1031 
1032    Synopsis:
1033    #include "petscsys.h"
1034    PetscErrorCode PetscOptionsScalar(const char opt[],const char text[],const char man[],PetscScalar currentvalue,PetscScalar *value,PetscBool  *set)
1035 
1036    Input Parameters:
1037 +  opt - option name
1038 .  text - short string that describes the option
1039 .  man - manual page with additional information on option
1040 -  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with either
1041 $                 PetscOptionsScalar(..., obj->value,&obj->value,...) or
1042 $                 value = defaultvalue
1043 $                 PetscOptionsScalar(..., value,&value,&flg);
1044 $                 if (flg) {
1045 
1046    Output Parameters:
1047 +  value - the value to return
1048 -  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
1049 
1050    Notes:
1051     If the user does not supply the option at all value is NOT changed. Thus
1052     you should ALWAYS initialize value if you access it without first checking if the set flag is true.
1053 
1054     The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
1055 
1056     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1057 
1058    Level: beginner
1059 
1060 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1061           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
1062           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
1063           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1064           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1065           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1066           `PetscOptionsFList()`, `PetscOptionsEList()`
1067 M*/
1068 
1069 PetscErrorCode PetscOptionsScalar_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar currentvalue, PetscScalar *value, PetscBool *set)
1070 {
1071   PetscFunctionBegin;
1072 #if !defined(PETSC_USE_COMPLEX)
1073   PetscCall(PetscOptionsReal(opt, text, man, currentvalue, value, set));
1074 #else
1075   PetscCall(PetscOptionsGetScalar(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, set));
1076 #endif
1077   PetscFunctionReturn(PETSC_SUCCESS);
1078 }
1079 
1080 /*MC
1081    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
1082                       its value is set to false.
1083 
1084    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1085 
1086    Synopsis:
1087    #include "petscsys.h"
1088    PetscErrorCode PetscOptionsName(const char opt[],const char text[],const char man[],PetscBool  *flg)
1089 
1090    Input Parameters:
1091 +  opt - option name
1092 .  text - short string that describes the option
1093 -  man - manual page with additional information on option
1094 
1095    Output Parameter:
1096 .  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
1097 
1098    Level: beginner
1099 
1100    Note:
1101     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1102 
1103 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1104           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
1105           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
1106           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1107           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1108           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1109           `PetscOptionsFList()`, `PetscOptionsEList()`
1110 M*/
1111 
1112 PetscErrorCode PetscOptionsName_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
1113 {
1114   PetscOptionItem amsopt;
1115 
1116   PetscFunctionBegin;
1117   if (!PetscOptionsObject->count) {
1118     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1119     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1120 
1121     *(PetscBool *)amsopt->data = PETSC_FALSE;
1122   }
1123   PetscCall(PetscOptionsHasName(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg));
1124   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1125     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1126   }
1127   PetscFunctionReturn(PETSC_SUCCESS);
1128 }
1129 
1130 /*MC
1131      PetscOptionsFList - Puts a list of option values that a single one may be selected from
1132 
1133    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1134 
1135    Synopsis:
1136    #include "petscsys.h"
1137    PetscErrorCode  PetscOptionsFList(const char opt[],const char ltext[],const char man[],PetscFunctionList list,const char currentvalue[],char value[],size_t len,PetscBool  *set)
1138 
1139    Input Parameters:
1140 +  opt - option name
1141 .  text - short string that describes the option
1142 .  man - manual page with additional information on option
1143 .  list - the possible choices
1144 .  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with
1145 $                 PetscOptionsFlist(..., obj->value,value,len,&flg);
1146 $                 if (flg) {
1147 -  len - the length of the character array value
1148 
1149    Output Parameters:
1150 +  value - the value to return
1151 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1152 
1153    Level: intermediate
1154 
1155    Notes:
1156     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1157 
1158           If the user does not supply the option at all value is NOT changed. Thus
1159           you should ALWAYS initialize value if you access it without first checking if the set flag is true.
1160 
1161           The default/currentvalue passed into this routine does not get transferred to the output value variable automatically.
1162 
1163    See `PetscOptionsEList()` for when the choices are given in a string array
1164 
1165    To get a listing of all currently specified options,
1166     see `PetscOptionsView()` or `PetscOptionsGetAll()`
1167 
1168    Developer Note:
1169    This cannot check for invalid selection because of things like `MATAIJ` that are not included in the list
1170 
1171 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1172           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1173           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1174           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1175           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1176           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsEnum()`
1177 M*/
1178 
1179 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)
1180 {
1181   PetscOptionItem amsopt;
1182   PetscBool       lset;
1183 
1184   PetscFunctionBegin;
1185   if (!PetscOptionsObject->count) {
1186     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_FLIST, &amsopt));
1187     /* must use system malloc since SAWs may free this */
1188     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
1189     amsopt->flist = list;
1190   }
1191   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, len, &lset));
1192   if (set) *set = lset;
1193   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1194     PetscCall(PetscFunctionListPrintTypes(PetscOptionsObject->comm, stdout, PetscOptionsObject->prefix, opt, ltext, man, list, currentvalue, lset && value ? value : currentvalue));
1195   }
1196   PetscFunctionReturn(PETSC_SUCCESS);
1197 }
1198 
1199 /*MC
1200      PetscOptionsEList - Puts a list of option values that a single one may be selected from
1201 
1202    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1203 
1204    Synopsis:
1205    #include "petscsys.h"
1206    PetscErrorCode  PetscOptionsEList(const char opt[],const char ltext[],const char man[],const char *const *list,PetscInt ntext,const char currentvalue[],PetscInt *value,PetscBool  *set)
1207 
1208    Input Parameters:
1209 +  opt - option name
1210 .  ltext - short string that describes the option
1211 .  man - manual page with additional information on option
1212 .  list - the possible choices (one of these must be selected, anything else is invalid)
1213 .  ntext - number of choices
1214 -  currentvalue - the current value; caller is responsible for setting this value correctly. Normally this is done with
1215 $                 PetscOptionsElist(..., obj->value,&value,&flg);
1216 $                 if (flg) {
1217 
1218    Output Parameters:
1219 +  value - the index of the value to return
1220 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1221 
1222    Level: intermediate
1223 
1224    Notes:
1225     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1226 
1227          If the user does not supply the option at all value is NOT changed. Thus
1228           you should ALWAYS initialize value if you access it without first checking if the set flag is true.
1229 
1230    See `PetscOptionsFList()` for when the choices are given in a `PetscFunctionList()`
1231 
1232 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1233           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1234           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1235           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1236           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1237           `PetscOptionsFList()`, `PetscOptionsEnum()`
1238 M*/
1239 
1240 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)
1241 {
1242   PetscInt        i;
1243   PetscOptionItem amsopt;
1244   PetscBool       lset;
1245 
1246   PetscFunctionBegin;
1247   if (!PetscOptionsObject->count) {
1248     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_ELIST, &amsopt));
1249     /* must use system malloc since SAWs may free this */
1250     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
1251     PetscCall(PetscStrNArrayallocpy(ntext, list, (char ***)&amsopt->list));
1252     amsopt->nlist = ntext;
1253   }
1254   PetscCall(PetscOptionsGetEList(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, list, ntext, value, &lset));
1255   if (set) *set = lset;
1256   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1257     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));
1258     for (i = 0; i < ntext; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " %s", list[i]));
1259     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, " (%s)\n", ManSection(man)));
1260   }
1261   PetscFunctionReturn(PETSC_SUCCESS);
1262 }
1263 
1264 /*MC
1265      PetscOptionsBoolGroupBegin - First in a series of logical queries on the options database for
1266        which at most a single value can be true.
1267 
1268    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1269 
1270    Synopsis:
1271    #include "petscsys.h"
1272    PetscErrorCode PetscOptionsBoolGroupBegin(const char opt[],const char text[],const char man[],PetscBool  *flg)
1273 
1274    Input Parameters:
1275 +  opt - option name
1276 .  text - short string that describes the option
1277 -  man - manual page with additional information on option
1278 
1279    Output Parameter:
1280 .  flg - whether that option was set or not
1281 
1282    Level: intermediate
1283 
1284    Notes:
1285     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1286 
1287    Must be followed by 0 or more P`etscOptionsBoolGroup()`s and `PetscOptionsBoolGroupEnd()`
1288 
1289 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1290           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1291           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1292           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1293           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1294           `PetscOptionsFList()`, `PetscOptionsEList()`
1295 M*/
1296 
1297 PetscErrorCode PetscOptionsBoolGroupBegin_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
1298 {
1299   PetscOptionItem amsopt;
1300 
1301   PetscFunctionBegin;
1302   if (!PetscOptionsObject->count) {
1303     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1304     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1305 
1306     *(PetscBool *)amsopt->data = PETSC_FALSE;
1307   }
1308   *flg = PETSC_FALSE;
1309   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg, NULL));
1310   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1311     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  Pick at most one of -------------\n"));
1312     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1313   }
1314   PetscFunctionReturn(PETSC_SUCCESS);
1315 }
1316 
1317 /*MC
1318      PetscOptionsBoolGroup - One in a series of logical queries on the options database for
1319        which at most a single value can be true.
1320 
1321    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1322 
1323    Synopsis:
1324    #include "petscsys.h"
1325    PetscErrorCode PetscOptionsBoolGroup(const char opt[],const char text[],const char man[],PetscBool  *flg)
1326 
1327    Input Parameters:
1328 +  opt - option name
1329 .  text - short string that describes the option
1330 -  man - manual page with additional information on option
1331 
1332    Output Parameter:
1333 .  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
1334 
1335    Level: intermediate
1336 
1337    Notes:
1338     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1339 
1340    Must follow a `PetscOptionsBoolGroupBegin()` and preceded a `PetscOptionsBoolGroupEnd()`
1341 
1342 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1343           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1344           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1345           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1346           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1347           `PetscOptionsFList()`, `PetscOptionsEList()`
1348 M*/
1349 
1350 PetscErrorCode PetscOptionsBoolGroup_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
1351 {
1352   PetscOptionItem amsopt;
1353 
1354   PetscFunctionBegin;
1355   if (!PetscOptionsObject->count) {
1356     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1357     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1358 
1359     *(PetscBool *)amsopt->data = PETSC_FALSE;
1360   }
1361   *flg = PETSC_FALSE;
1362   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg, NULL));
1363   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1364     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1365   }
1366   PetscFunctionReturn(PETSC_SUCCESS);
1367 }
1368 
1369 /*MC
1370      PetscOptionsBoolGroupEnd - Last in a series of logical queries on the options database for
1371        which at most a single value can be true.
1372 
1373    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1374 
1375    Synopsis:
1376    #include "petscsys.h"
1377    PetscErrorCode PetscOptionsBoolGroupEnd(const char opt[],const char text[],const char man[],PetscBool  *flg)
1378 
1379    Input Parameters:
1380 +  opt - option name
1381 .  text - short string that describes the option
1382 -  man - manual page with additional information on option
1383 
1384    Output Parameter:
1385 .  flg - `PETSC_TRUE` if found, else `PETSC_FALSE`
1386 
1387    Level: intermediate
1388 
1389    Notes:
1390     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1391 
1392    Must follow a `PetscOptionsBoolGroupBegin()`
1393 
1394 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1395           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1396           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1397           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1398           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1399           `PetscOptionsFList()`, `PetscOptionsEList()`
1400 M*/
1401 
1402 PetscErrorCode PetscOptionsBoolGroupEnd_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
1403 {
1404   PetscOptionItem amsopt;
1405 
1406   PetscFunctionBegin;
1407   if (!PetscOptionsObject->count) {
1408     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1409     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1410 
1411     *(PetscBool *)amsopt->data = PETSC_FALSE;
1412   }
1413   *flg = PETSC_FALSE;
1414   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg, NULL));
1415   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1416     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1417   }
1418   PetscFunctionReturn(PETSC_SUCCESS);
1419 }
1420 
1421 /*MC
1422    PetscOptionsBool - Determines if a particular option is in the database with a true or false
1423 
1424    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1425 
1426    Synopsis:
1427    #include "petscsys.h"
1428    PetscErrorCode PetscOptionsBool(const char opt[],const char text[],const char man[],PetscBool currentvalue,PetscBool  *flg,PetscBool  *set)
1429 
1430    Input Parameters:
1431 +  opt - option name
1432 .  text - short string that describes the option
1433 .  man - manual page with additional information on option
1434 -  currentvalue - the current value
1435 
1436    Output Parameters:
1437 +  flg -` PETSC_TRUE` or `PETSC_FALSE`
1438 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1439 
1440    Notes:
1441        TRUE, true, YES, yes, nostring, and 1 all translate to `PETSC_TRUE`
1442        FALSE, false, NO, no, and 0 all translate to `PETSC_FALSE`
1443 
1444       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
1445      is equivalent to -requested_bool true
1446 
1447        If the user does not supply the option at all flg is NOT changed. Thus
1448      you should ALWAYS initialize the flg if you access it without first checking if the set flag is true.
1449 
1450     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1451 
1452    Level: beginner
1453 
1454 .seealso: `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1455           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsGetBool()`,
1456           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
1457           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1458           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1459           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1460           `PetscOptionsFList()`, `PetscOptionsEList()`
1461 M*/
1462 
1463 PetscErrorCode PetscOptionsBool_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool currentvalue, PetscBool *flg, PetscBool *set)
1464 {
1465   PetscBool       iset;
1466   PetscOptionItem amsopt;
1467 
1468   PetscFunctionBegin;
1469   if (!PetscOptionsObject->count) {
1470     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
1471     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
1472 
1473     *(PetscBool *)amsopt->data = currentvalue;
1474   }
1475   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, flg, &iset));
1476   if (set) *set = iset;
1477   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1478     const char *v = PetscBools[currentvalue], *vn = PetscBools[iset && flg ? *flg : currentvalue];
1479     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <%s : %s> %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, v, vn, text, ManSection(man)));
1480   }
1481   PetscFunctionReturn(PETSC_SUCCESS);
1482 }
1483 
1484 /*MC
1485    PetscOptionsRealArray - Gets an array of double values for a particular
1486    option in the database. The values must be separated with commas with
1487    no intervening spaces.
1488 
1489    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1490 
1491    Synopsis:
1492    #include "petscsys.h"
1493    PetscErrorCode PetscOptionsRealArray(const char opt[],const char text[],const char man[],PetscReal value[],PetscInt *n,PetscBool  *set)
1494 
1495    Input Parameters:
1496 +  opt - the option one is seeking
1497 .  text - short string describing option
1498 .  man - manual page for option
1499 -  n - maximum number of values that value has room for
1500 
1501    Output Parameters:
1502 +  value - location to copy values
1503 .  n - actual number of values found
1504 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1505 
1506    Level: beginner
1507 
1508    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1509 
1510 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1511           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1512           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1513           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1514           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1515           `PetscOptionsFList()`, `PetscOptionsEList()`
1516 M*/
1517 
1518 PetscErrorCode PetscOptionsRealArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal value[], PetscInt *n, PetscBool *set)
1519 {
1520   PetscInt        i;
1521   PetscOptionItem amsopt;
1522 
1523   PetscFunctionBegin;
1524   if (!PetscOptionsObject->count) {
1525     PetscReal *vals;
1526 
1527     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt));
1528     PetscCall(PetscMalloc((*n) * sizeof(PetscReal), &amsopt->data));
1529     vals = (PetscReal *)amsopt->data;
1530     for (i = 0; i < *n; i++) vals[i] = value[i];
1531     amsopt->arraylength = *n;
1532   }
1533   PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, n, set));
1534   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1535     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%g", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, (double)value[0]));
1536     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%g", (double)value[i]));
1537     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (%s)\n", text, ManSection(man)));
1538   }
1539   PetscFunctionReturn(PETSC_SUCCESS);
1540 }
1541 
1542 /*MC
1543    PetscOptionsScalarArray - Gets an array of `PetscScalar` values for a particular
1544    option in the database. The values must be separated with commas with
1545    no intervening spaces.
1546 
1547    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1548 
1549    Synopsis:
1550    #include "petscsys.h"
1551    PetscErrorCode PetscOptionsScalarArray(const char opt[],const char text[],const char man[],PetscScalar value[],PetscInt *n,PetscBool  *set)
1552 
1553    Input Parameters:
1554 +  opt - the option one is seeking
1555 .  text - short string describing option
1556 .  man - manual page for option
1557 -  n - maximum number of values allowed in the value array
1558 
1559    Output Parameters:
1560 +  value - location to copy values
1561 .  n - actual number of values found
1562 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1563 
1564    Level: beginner
1565 
1566    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1567 
1568 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1569           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1570           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1571           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1572           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1573           `PetscOptionsFList()`, `PetscOptionsEList()`
1574 M*/
1575 
1576 PetscErrorCode PetscOptionsScalarArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar value[], PetscInt *n, PetscBool *set)
1577 {
1578   PetscInt        i;
1579   PetscOptionItem amsopt;
1580 
1581   PetscFunctionBegin;
1582   if (!PetscOptionsObject->count) {
1583     PetscScalar *vals;
1584 
1585     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt));
1586     PetscCall(PetscMalloc((*n) * sizeof(PetscScalar), &amsopt->data));
1587     vals = (PetscScalar *)amsopt->data;
1588     for (i = 0; i < *n; i++) vals[i] = value[i];
1589     amsopt->arraylength = *n;
1590   }
1591   PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, n, set));
1592   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1593     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%g+%gi", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0])));
1594     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i])));
1595     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (%s)\n", text, ManSection(man)));
1596   }
1597   PetscFunctionReturn(PETSC_SUCCESS);
1598 }
1599 
1600 /*MC
1601    PetscOptionsIntArray - Gets an array of integers for a particular
1602    option in the database.
1603 
1604    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1605 
1606    Synopsis:
1607    #include "petscsys.h"
1608    PetscErrorCode PetscOptionsIntArray(const char opt[],const char text[],const char man[],PetscInt value[],PetscInt *n,PetscBool  *set)
1609 
1610    Input Parameters:
1611 +  opt - the option one is seeking
1612 .  text - short string describing option
1613 .  man - manual page for option
1614 -  n - maximum number of values
1615 
1616    Output Parameters:
1617 +  value - location to copy values
1618 .  n - actual number of values found
1619 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1620 
1621    Level: beginner
1622 
1623    Notes:
1624    The array can be passed as
1625 +   a comma separated list -                                  0,1,2,3,4,5,6,7
1626 .   a range (start\-end+1) -                                  0-8
1627 .   a range with given increment (start\-end+1:inc) -         0-7:2
1628 -   a combination of values and ranges separated by commas -  0,1-8,8-15:2
1629 
1630    There must be no intervening spaces between the values.
1631 
1632    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1633 
1634 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1635           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1636           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1637           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1638           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1639           `PetscOptionsFList()`, `PetscOptionsEList()`, `PetscOptionsRealArray()`
1640 M*/
1641 
1642 PetscErrorCode PetscOptionsIntArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt value[], PetscInt *n, PetscBool *set)
1643 {
1644   PetscInt        i;
1645   PetscOptionItem amsopt;
1646 
1647   PetscFunctionBegin;
1648   if (!PetscOptionsObject->count) {
1649     PetscInt *vals;
1650 
1651     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY, &amsopt));
1652     PetscCall(PetscMalloc1(*n, (PetscInt **)&amsopt->data));
1653     vals = (PetscInt *)amsopt->data;
1654     for (i = 0; i < *n; i++) vals[i] = value[i];
1655     amsopt->arraylength = *n;
1656   }
1657   PetscCall(PetscOptionsGetIntArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, n, set));
1658   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1659     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%" PetscInt_FMT, PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, value[0]));
1660     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%" PetscInt_FMT, value[i]));
1661     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (%s)\n", text, ManSection(man)));
1662   }
1663   PetscFunctionReturn(PETSC_SUCCESS);
1664 }
1665 
1666 /*MC
1667    PetscOptionsStringArray - Gets an array of string values for a particular
1668    option in the database. The values must be separated with commas with
1669    no intervening spaces.
1670 
1671    Logically Collective on the communicator passed in `PetscOptionsBegin()`; No Fortran Support
1672 
1673    Synopsis:
1674    #include "petscsys.h"
1675    PetscErrorCode PetscOptionsStringArray(const char opt[],const char text[],const char man[],char *value[],PetscInt *nmax,PetscBool  *set)
1676 
1677    Input Parameters:
1678 +  opt - the option one is seeking
1679 .  text - short string describing option
1680 .  man - manual page for option
1681 -  nmax - maximum number of strings
1682 
1683    Output Parameters:
1684 +  value - location to copy strings
1685 .  nmax - actual number of strings found
1686 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1687 
1688    Level: beginner
1689 
1690    Notes:
1691    The user should pass in an array of pointers to char, to hold all the
1692    strings returned by this function.
1693 
1694    The user is responsible for deallocating the strings that are
1695    returned.
1696 
1697    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1698 
1699 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1700           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1701           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1702           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1703           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1704           `PetscOptionsFList()`, `PetscOptionsEList()`
1705 M*/
1706 
1707 PetscErrorCode PetscOptionsStringArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], char *value[], PetscInt *nmax, PetscBool *set)
1708 {
1709   PetscOptionItem amsopt;
1710 
1711   PetscFunctionBegin;
1712   if (!PetscOptionsObject->count) {
1713     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt));
1714     PetscCall(PetscMalloc1(*nmax, (char **)&amsopt->data));
1715 
1716     amsopt->arraylength = *nmax;
1717   }
1718   PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, nmax, set));
1719   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1720     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <string1,string2,...>: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, text, ManSection(man)));
1721   }
1722   PetscFunctionReturn(PETSC_SUCCESS);
1723 }
1724 
1725 /*MC
1726    PetscOptionsBoolArray - Gets an array of logical values (true or false) for a particular
1727    option in the database. The values must be separated with commas with
1728    no intervening spaces.
1729 
1730    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1731 
1732    Synopsis:
1733    #include "petscsys.h"
1734    PetscErrorCode PetscOptionsBoolArray(const char opt[],const char text[],const char man[],PetscBool value[],PetscInt *n,PetscBool *set)
1735 
1736    Input Parameters:
1737 +  opt - the option one is seeking
1738 .  text - short string describing option
1739 .  man - manual page for option
1740 -  n - maximum number of values allowed in the value array
1741 
1742    Output Parameters:
1743 +  value - location to copy values
1744 .  n - actual number of values found
1745 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1746 
1747    Level: beginner
1748 
1749    Notes:
1750    The user should pass in an array of doubles
1751 
1752    Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1753 
1754 .seealso: `PetscOptionsGetInt()`, `PetscOptionsGetReal()`,
1755           `PetscOptionsHasName()`, `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`,
1756           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1757           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1758           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1759           `PetscOptionsFList()`, `PetscOptionsEList()`
1760 M*/
1761 
1762 PetscErrorCode PetscOptionsBoolArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool value[], PetscInt *n, PetscBool *set)
1763 {
1764   PetscInt        i;
1765   PetscOptionItem amsopt;
1766 
1767   PetscFunctionBegin;
1768   if (!PetscOptionsObject->count) {
1769     PetscBool *vals;
1770 
1771     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt));
1772     PetscCall(PetscMalloc1(*n, (PetscBool **)&amsopt->data));
1773     vals = (PetscBool *)amsopt->data;
1774     for (i = 0; i < *n; i++) vals[i] = value[i];
1775     amsopt->arraylength = *n;
1776   }
1777   PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, n, set));
1778   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1779     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%d", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, value[0]));
1780     for (i = 1; i < *n; i++) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ",%d", value[i]));
1781     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, ">: %s (%s)\n", text, ManSection(man)));
1782   }
1783   PetscFunctionReturn(PETSC_SUCCESS);
1784 }
1785 
1786 /*MC
1787    PetscOptionsViewer - Gets a viewer appropriate for the type indicated by the user
1788 
1789    Logically Collective on the communicator passed in `PetscOptionsBegin()`
1790 
1791    Synopsis:
1792    #include "petscsys.h"
1793    PetscErrorCode PetscOptionsViewer(const char opt[],const char text[],const char man[],PetscViewer *viewer,PetscViewerFormat *format,PetscBool *set)
1794 
1795    Input Parameters:
1796 +  opt - option name
1797 .  text - short string that describes the option
1798 -  man - manual page with additional information on option
1799 
1800    Output Parameters:
1801 +  viewer - the viewer
1802 .  format - the PetscViewerFormat requested by the user, pass NULL if not needed
1803 -  set - `PETSC_TRUE` if found, else `PETSC_FALSE`
1804 
1805    Level: beginner
1806 
1807    Notes:
1808     Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1809 
1810    See `PetscOptionsGetViewer()` for the format of the supplied viewer and its options
1811 
1812 .seealso: `PetscOptionsGetViewer()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1813           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
1814           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`, `PetscOptionsBool()`,
1815           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1816           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1817           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1818           `PetscOptionsFList()`, `PetscOptionsEList()`
1819 M*/
1820 
1821 PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
1822 {
1823   PetscOptionItem amsopt;
1824 
1825   PetscFunctionBegin;
1826   if (!PetscOptionsObject->count) {
1827     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
1828     /* must use system malloc since SAWs may free this */
1829     PetscCall(PetscStrdup("", (char **)&amsopt->data));
1830   }
1831   PetscCall(PetscOptionsGetViewer(PetscOptionsObject->comm, PetscOptionsObject->options, PetscOptionsObject->prefix, opt, viewer, format, set));
1832   if (PetscOptionsObject->printhelp && PetscOptionsObject->count == 1 && !PetscOptionsObject->alreadyprinted) {
1833     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s <%s>: %s (%s)\n", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", opt + 1, "", text, ManSection(man)));
1834   }
1835   PetscFunctionReturn(PETSC_SUCCESS);
1836 }
1837