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