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