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