xref: /petsc/src/sys/objects/aoptions.c (revision 9e210917fd2290210f7150e13ff15b3541f55af7)
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 
ManSection(const char * str)10 static const char *ManSection(const char *str)
11 {
12   return str ? str : "None";
13 }
14 
Prefix(const char * str)15 static const char *Prefix(const char *str)
16 {
17   return str ? str : "";
18 }
19 
ShouldPrintHelp(const PetscOptionItems opts)20 static int ShouldPrintHelp(const PetscOptionItems opts)
21 {
22   return opts->printhelp && opts->count == 1 && !opts->alreadyprinted;
23 }
24 
25 /*
26     Keep a linked list of options that have been posted and we are waiting for
27    user selection. See the manual page for PetscOptionsBegin()
28 
29     Eventually we'll attach this beast to a MPI_Comm
30 */
31 
32 /*
33     Handles setting up the data structure in a call to PetscOptionsBegin()
34 */
PetscOptionsBegin_Private(PetscOptionItems PetscOptionsObject,MPI_Comm comm,const char prefix[],const char title[],const char mansec[])35 PetscErrorCode PetscOptionsBegin_Private(PetscOptionItems PetscOptionsObject, MPI_Comm comm, const char prefix[], const char title[], const char mansec[])
36 {
37   PetscFunctionBegin;
38   if (prefix) PetscAssertPointer(prefix, 3);
39   PetscAssertPointer(title, 4);
40   if (mansec) PetscAssertPointer(mansec, 5);
41   if (!PetscOptionsObject->alreadyprinted) {
42     if (!PetscOptionsHelpPrintedSingleton) PetscCall(PetscOptionsHelpPrintedCreate(&PetscOptionsHelpPrintedSingleton));
43     PetscCall(PetscOptionsHelpPrintedCheck(PetscOptionsHelpPrintedSingleton, prefix, title, &PetscOptionsObject->alreadyprinted));
44   }
45   PetscOptionsObject->next          = NULL;
46   PetscOptionsObject->comm          = comm;
47   PetscOptionsObject->changedmethod = PETSC_FALSE;
48 
49   PetscCall(PetscStrallocpy(prefix, &PetscOptionsObject->prefix));
50   PetscCall(PetscStrallocpy(title, &PetscOptionsObject->title));
51 
52   PetscCall(PetscOptionsHasHelp(PetscOptionsObject->options, &PetscOptionsObject->printhelp));
53   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\n%s:\n", title));
54   PetscFunctionReturn(PETSC_SUCCESS);
55 }
56 
57 /*
58     Handles setting up the data structure in a call to PetscObjectOptionsBegin()
59 */
PetscObjectOptionsBegin_Private(PetscObject obj,PetscOptionItems PetscOptionsObject)60 PetscErrorCode PetscObjectOptionsBegin_Private(PetscObject obj, PetscOptionItems PetscOptionsObject)
61 {
62   char      title[256];
63   PetscBool flg;
64 
65   PetscFunctionBegin;
66   PetscAssertPointer(PetscOptionsObject, 2);
67   PetscValidHeader(obj, 1);
68   PetscOptionsObject->object         = obj;
69   PetscOptionsObject->alreadyprinted = obj->optionsprinted;
70 
71   PetscCall(PetscStrcmp(obj->description, obj->class_name, &flg));
72   if (flg) PetscCall(PetscSNPrintf(title, sizeof(title), "%s options", obj->class_name));
73   else PetscCall(PetscSNPrintf(title, sizeof(title), "%s (%s) options", obj->description, obj->class_name));
74   PetscCall(PetscOptionsBegin_Private(PetscOptionsObject, obj->comm, obj->prefix, title, obj->mansec));
75   PetscFunctionReturn(PETSC_SUCCESS);
76 }
77 
78 /*
79      Handles adding another option to the list of options within this particular PetscOptionsBegin() PetscOptionsEnd()
80 */
PetscOptionItemCreate_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscOptionType t,PetscOptionItem * amsopt)81 static PetscErrorCode PetscOptionItemCreate_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscOptionType t, PetscOptionItem *amsopt)
82 {
83   PetscBool valid;
84 
85   PetscFunctionBegin;
86   PetscCall(PetscOptionsValidKey(opt, &valid));
87   PetscCheck(valid, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "The option '%s' is not a valid key", opt);
88 
89   PetscCall(PetscNew(amsopt));
90   (*amsopt)->next = NULL;
91   (*amsopt)->set  = PETSC_FALSE;
92   (*amsopt)->type = t;
93   (*amsopt)->data = NULL;
94 
95   PetscCall(PetscStrallocpy(text, &(*amsopt)->text));
96   PetscCall(PetscStrallocpy(opt, &(*amsopt)->option));
97   PetscCall(PetscStrallocpy(man, &(*amsopt)->man));
98 
99   {
100     PetscOptionItem cur = PetscOptionsObject->next;
101 
102     while (cur->next) cur = cur->next;
103     cur->next = *amsopt;
104   }
105   PetscFunctionReturn(PETSC_SUCCESS);
106 }
107 
108 /*
109     This is needed because certain strings may be freed by SAWs, hence we cannot use PetscStrallocpy()
110 */
PetscStrdup(const char s[],char * t[])111 static PetscErrorCode PetscStrdup(const char s[], char *t[])
112 {
113   char *tmp = NULL;
114 
115   PetscFunctionBegin;
116   if (s) {
117     size_t len;
118 
119     PetscCall(PetscStrlen(s, &len));
120     tmp = (char *)malloc((len + 1) * sizeof(*tmp));
121     PetscCheck(tmp, PETSC_COMM_SELF, PETSC_ERR_MEM, "No memory to duplicate string");
122     PetscCall(PetscArraycpy(tmp, s, len + 1));
123   }
124   *t = tmp;
125   PetscFunctionReturn(PETSC_SUCCESS);
126 }
127 
128 #if defined(PETSC_HAVE_SAWS)
129   #include <petscviewersaws.h>
130 
131 static int count = 0;
132 
133 static const char *OptionsHeader = "<head>\n"
134                                    "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/jquery-1.9.1.js\"></script>\n"
135                                    "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/SAWs.js\"></script>\n"
136                                    "<script type=\"text/javascript\" src=\"js/PETSc.js\"></script>\n"
137                                    "<script>\n"
138                                    "jQuery(document).ready(function() {\n"
139                                    "PETSc.getAndDisplayDirectory(null,\"#variablesInfo\")\n"
140                                    "})\n"
141                                    "</script>\n"
142                                    "</head>\n";
143 
144 /*  Determines the size and style of the scroll region where PETSc options selectable from users are displayed */
145 static const char *OptionsBodyBottom = "<div id=\"variablesInfo\" style=\"background-color:lightblue;height:auto;max-height:500px;overflow:scroll;\"></div>\n<br>\n</body>";
146 
147 /*
148     PetscOptionsSAWsInput - Presents all the PETSc Options processed by the program so the user may change them at runtime using the SAWs
149 
150     Bugs:
151 +    All processes must traverse through the exact same set of option queries due to the call to PetscScanString()
152 .    Internal strings have arbitrary length and string copies are not checked that they fit into string space
153 -    Only works for PetscInt == int, PetscReal == double etc
154 
155 */
PetscOptionsSAWsInput(PetscOptionItems PetscOptionsObject)156 static PetscErrorCode PetscOptionsSAWsInput(PetscOptionItems PetscOptionsObject)
157 {
158   PetscOptionItem next     = PetscOptionsObject->next;
159   static int      mancount = 0;
160   char            options[16];
161   PetscBool       changedmethod = PETSC_FALSE;
162   PetscBool       stopasking    = PETSC_FALSE;
163   char            manname[16], textname[16];
164   char            dir[1024];
165 
166   PetscFunctionBegin;
167   /* the next line is a bug, this will only work if all processors are here, the comm passed in is ignored!!! */
168   PetscCall(PetscSNPrintf(options, PETSC_STATIC_ARRAY_LENGTH(options), "Options_%d", count++));
169 
170   PetscOptionsObject->pprefix = PetscOptionsObject->prefix; /* SAWs will change this, so cannot pass prefix directly */
171 
172   PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "_title"));
173   PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->title, 1, SAWs_READ, SAWs_STRING));
174   PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "prefix"));
175   PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->pprefix, 1, SAWs_READ, SAWs_STRING));
176   PetscCallSAWs(SAWs_Register, ("/PETSc/Options/ChangedMethod", &changedmethod, 1, SAWs_WRITE, SAWs_BOOLEAN));
177   PetscCallSAWs(SAWs_Register, ("/PETSc/Options/StopAsking", &stopasking, 1, SAWs_WRITE, SAWs_BOOLEAN));
178 
179   while (next) {
180     PetscCall(PetscSNPrintf(manname, PETSC_STATIC_ARRAY_LENGTH(manname), "_man_%d", mancount));
181     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", manname));
182     PetscCallSAWs(SAWs_Register, (dir, &next->man, 1, SAWs_READ, SAWs_STRING));
183     PetscCall(PetscSNPrintf(textname, PETSC_STATIC_ARRAY_LENGTH(textname), "_text_%d", mancount++));
184     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", textname));
185     PetscCallSAWs(SAWs_Register, (dir, &next->text, 1, SAWs_READ, SAWs_STRING));
186 
187     switch (next->type) {
188     case OPTION_HEAD:
189       break;
190     case OPTION_INT_ARRAY:
191       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
192       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_INT));
193       break;
194     case OPTION_REAL_ARRAY:
195       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
196       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_DOUBLE));
197       break;
198     case OPTION_INT:
199       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
200       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_INT));
201       break;
202     case OPTION_REAL:
203       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
204       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_DOUBLE));
205       break;
206     case OPTION_BOOL:
207       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
208       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_BOOLEAN));
209       break;
210     case OPTION_BOOL_ARRAY:
211       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
212       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_BOOLEAN));
213       break;
214     case OPTION_STRING:
215       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
216       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
217       break;
218     case OPTION_STRING_ARRAY:
219       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
220       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_STRING));
221       break;
222     case OPTION_FLIST: {
223       PetscInt ntext;
224       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
225       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
226       PetscCall(PetscFunctionListGet(next->flist, (const char ***)&next->edata, &ntext));
227       PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata));
228     } break;
229     case OPTION_ELIST: {
230       PetscInt ntext = next->nlist;
231       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
232       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
233       PetscCall(PetscMalloc1(ntext + 1, (char ***)&next->edata));
234       PetscCall(PetscMemcpy(next->edata, next->list, ntext * sizeof(char *)));
235       PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata));
236     } break;
237     default:
238       break;
239     }
240     next = next->next;
241   }
242 
243   /* wait until accessor has unlocked the memory */
244   PetscCallSAWs(SAWs_Push_Header, ("index.html", OptionsHeader));
245   PetscCallSAWs(SAWs_Push_Body, ("index.html", 2, OptionsBodyBottom));
246   PetscCall(PetscSAWsBlock());
247   PetscCallSAWs(SAWs_Pop_Header, ("index.html"));
248   PetscCallSAWs(SAWs_Pop_Body, ("index.html", 2));
249 
250   /* determine if any values have been set in GUI */
251   next = PetscOptionsObject->next;
252   while (next) {
253     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
254     PetscCallSAWs(SAWs_Selected, (dir, (int *)&next->set));
255     next = next->next;
256   }
257 
258   /* reset counter to -2; this updates the screen with the new options for the selected method */
259   if (changedmethod) PetscOptionsObject->count = -2;
260 
261   if (stopasking) {
262     PetscOptionsPublish       = PETSC_FALSE;
263     PetscOptionsObject->count = 0; //do not ask for same thing again
264   }
265 
266   PetscCallSAWs(SAWs_Delete, ("/PETSc/Options"));
267   PetscFunctionReturn(PETSC_SUCCESS);
268 }
269 #else
270 /*
271     PetscScanString -  Gets user input via stdin from process and broadcasts to all processes
272 
273     Collective
274 
275    Input Parameters:
276 +     commm - communicator for the broadcast, must be PETSC_COMM_WORLD
277 .     n - length of the string, must be the same on all processes
278 -     str - location to store input
279 
280     Bugs:
281 .   Assumes process 0 of the given communicator has access to stdin
282 
283 */
PetscScanString(MPI_Comm comm,size_t n,char str[])284 static PetscErrorCode PetscScanString(MPI_Comm comm, size_t n, char str[])
285 {
286   PetscMPIInt rank, nm;
287 
288   PetscFunctionBegin;
289   PetscCallMPI(MPI_Comm_rank(comm, &rank));
290   if (rank == 0) {
291     char   c = (char)getchar();
292     size_t i = 0;
293 
294     while (c != '\n' && i < n - 1) {
295       str[i++] = c;
296       c        = (char)getchar();
297     }
298     str[i] = '\0';
299   }
300   PetscCall(PetscMPIIntCast(n, &nm));
301   PetscCallMPI(MPI_Bcast(str, nm, MPI_CHAR, 0, comm));
302   PetscFunctionReturn(PETSC_SUCCESS);
303 }
304 
305 /*
306   PetscOptionsGetFromTextInput - Presents all the PETSc Options processed by the program so the user may change them at runtime
307 
308   Notes:
309   this isn't really practical, it is just to demonstrate the principle
310 
311   A carriage return indicates no change from the default; but this like -ksp_monitor <stdout>  the default is actually not stdout the default
312   is to do nothing so to get it to use stdout you need to type stdout. This is kind of bug?
313 
314   Bugs:
315 +    All processes must traverse through the exact same set of option queries due to the call to PetscScanString()
316 .    Internal strings have arbitrary length and string copies are not checked that they fit into string space
317 -    Only works for PetscInt == int, PetscReal == double etc
318 
319   Developer Notes:
320   Normally the GUI that presents the options the user and retrieves the values would be running in a different
321   address space and communicating with the PETSc program
322 
323 */
PetscOptionsGetFromTextInput(PetscOptionItems PetscOptionsObject)324 static PetscErrorCode PetscOptionsGetFromTextInput(PetscOptionItems PetscOptionsObject)
325 {
326   PetscOptionItem next = PetscOptionsObject->next;
327   char            str[512];
328   PetscBool       bid;
329   PetscReal       ir, *valr;
330   PetscInt       *vald;
331 
332   PetscFunctionBegin;
333   PetscCall((*PetscPrintf)(PETSC_COMM_WORLD, "%s --------------------\n", PetscOptionsObject->title));
334   while (next) {
335     switch (next->type) {
336     case OPTION_HEAD:
337       break;
338     case OPTION_INT_ARRAY:
339       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1));
340       vald = (PetscInt *)next->data;
341       for (PetscInt i = 0; i < next->arraylength; i++) {
342         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT, vald[i]));
343         if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ","));
344       }
345       PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man));
346       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
347       if (str[0]) {
348         PetscToken  token;
349         PetscInt    n = 0, nmax = next->arraylength, *dvalue = (PetscInt *)next->data, start, end;
350         size_t      len;
351         const char *value;
352         PetscBool   foundrange;
353 
354         next->set = PETSC_TRUE;
355         value     = str;
356         PetscCall(PetscTokenCreate(value, ',', &token));
357         PetscCall(PetscTokenFind(token, &value));
358         while (n < nmax) {
359           char    *ivalue;
360           PetscInt i;
361 
362           if (!value) break;
363           PetscCall(PetscStrallocpy(value, &ivalue));
364 
365           /* look for form  d-D where d and D are integers */
366           foundrange = PETSC_FALSE;
367           PetscCall(PetscStrlen(ivalue, &len));
368           if (ivalue[0] == '-') i = 2;
369           else i = 1;
370           for (; i < (PetscInt)len; i++) {
371             if (ivalue[i] == '-') {
372               PetscCheck(i != (PetscInt)(len - 1), PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, ivalue);
373               ivalue[i] = 0;
374               PetscCall(PetscOptionsStringToInt(ivalue, &start));
375               PetscCall(PetscOptionsStringToInt(ivalue + i + 1, &end));
376               PetscCheck(end > start, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, %s-%s cannot have decreasing list", n, ivalue, ivalue + i + 1);
377               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);
378               for (; start < end; start++) {
379                 *dvalue = start;
380                 dvalue++;
381                 n++;
382               }
383               foundrange = PETSC_TRUE;
384               break;
385             }
386           }
387           if (!foundrange) {
388             PetscCall(PetscOptionsStringToInt(ivalue, dvalue));
389             dvalue++;
390             n++;
391           }
392           PetscCall(PetscFree(ivalue));
393           PetscCall(PetscTokenFind(token, &value));
394         }
395         PetscCall(PetscTokenDestroy(&token));
396       }
397       break;
398     case OPTION_REAL_ARRAY:
399       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1));
400       valr = (PetscReal *)next->data;
401       for (PetscInt i = 0; i < next->arraylength; i++) {
402         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%g", (double)valr[i]));
403         if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ","));
404       }
405       PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man));
406       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
407       if (str[0]) {
408         PetscToken  token;
409         PetscInt    n = 0, nmax = next->arraylength;
410         PetscReal  *dvalue = (PetscReal *)next->data;
411         const char *value;
412 
413         next->set = PETSC_TRUE;
414         value     = str;
415         PetscCall(PetscTokenCreate(value, ',', &token));
416         PetscCall(PetscTokenFind(token, &value));
417         while (n < nmax) {
418           if (!value) break;
419           PetscCall(PetscOptionsStringToReal(value, dvalue));
420           dvalue++;
421           n++;
422           PetscCall(PetscTokenFind(token, &value));
423         }
424         PetscCall(PetscTokenDestroy(&token));
425       }
426       break;
427     case OPTION_INT:
428       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%d>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(int *)next->data, next->text, next->man));
429       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
430       if (str[0]) {
431   #if defined(PETSC_SIZEOF_LONG_LONG)
432         long long lid;
433         sscanf(str, "%lld", &lid);
434         PetscCheck(lid <= PETSC_INT_MAX && lid >= PETSC_INT_MIN, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %lld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid);
435   #else
436         long lid;
437         sscanf(str, "%ld", &lid);
438         PetscCheck(lid <= PETSC_INT_MAX && lid >= PETSC_INT_MIN, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %ld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid);
439   #endif
440 
441         next->set                 = PETSC_TRUE;
442         *((PetscInt *)next->data) = (PetscInt)lid;
443       }
444       break;
445     case OPTION_REAL:
446       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%g>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(double *)next->data, next->text, next->man));
447       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
448       if (str[0]) {
449   #if defined(PETSC_USE_REAL_SINGLE)
450         sscanf(str, "%e", &ir);
451   #elif defined(PETSC_USE_REAL___FP16)
452         float irtemp;
453         sscanf(str, "%e", &irtemp);
454         ir = irtemp;
455   #elif defined(PETSC_USE_REAL_DOUBLE)
456         sscanf(str, "%le", &ir);
457   #elif defined(PETSC_USE_REAL___FLOAT128)
458         ir = strtoflt128(str, 0);
459   #else
460         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Unknown scalar type");
461   #endif
462         next->set                  = PETSC_TRUE;
463         *((PetscReal *)next->data) = ir;
464       }
465       break;
466     case OPTION_BOOL:
467       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));
468       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
469       if (str[0]) {
470         PetscCall(PetscOptionsStringToBool(str, &bid));
471         next->set                  = PETSC_TRUE;
472         *((PetscBool *)next->data) = bid;
473       }
474       break;
475     case OPTION_STRING:
476       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%s>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, (char *)next->data, next->text, next->man));
477       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
478       if (str[0]) {
479         next->set = PETSC_TRUE;
480         /* must use system malloc since SAWs may free this */
481         PetscCall(PetscStrdup(str, (char **)&next->data));
482       }
483       break;
484     case OPTION_FLIST:
485       PetscCall(PetscFunctionListPrintTypes(PETSC_COMM_WORLD, stdout, PetscOptionsObject->prefix, next->option, next->text, next->man, next->flist, (char *)next->data, (char *)next->data));
486       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
487       if (str[0]) {
488         PetscOptionsObject->changedmethod = PETSC_TRUE;
489         next->set                         = PETSC_TRUE;
490         /* must use system malloc since SAWs may free this */
491         PetscCall(PetscStrdup(str, (char **)&next->data));
492       }
493       break;
494     default:
495       break;
496     }
497     next = next->next;
498   }
499   PetscFunctionReturn(PETSC_SUCCESS);
500 }
501 #endif
502 
PetscOptionsEnd_Private(PetscOptionItems PetscOptionsObject)503 PetscErrorCode PetscOptionsEnd_Private(PetscOptionItems PetscOptionsObject)
504 {
505   PetscOptionItem next, last;
506 
507   PetscFunctionBegin;
508   if (PetscOptionsObject->next) {
509     if (!PetscOptionsObject->count) {
510 #if defined(PETSC_HAVE_SAWS)
511       PetscCall(PetscOptionsSAWsInput(PetscOptionsObject));
512 #else
513       PetscCall(PetscOptionsGetFromTextInput(PetscOptionsObject));
514 #endif
515     }
516   }
517 
518   PetscCall(PetscFree(PetscOptionsObject->title));
519 
520   /* reset counter to -2; this updates the screen with the new options for the selected method */
521   if (PetscOptionsObject->changedmethod) PetscOptionsObject->count = -2;
522   /* reset alreadyprinted flag */
523   PetscOptionsObject->alreadyprinted = PETSC_FALSE;
524   if (PetscOptionsObject->object) PetscOptionsObject->object->optionsprinted = PETSC_TRUE;
525   PetscOptionsObject->object = NULL;
526 
527   while ((next = PetscOptionsObject->next)) {
528     const PetscOptionType type        = next->type;
529     const size_t          arraylength = next->arraylength;
530     void                 *data        = next->data;
531 
532     if (next->set) {
533       char option[256], value[1024], tmp[32];
534 
535       if (PetscOptionsObject->prefix) {
536         PetscCall(PetscStrncpy(option, "-", sizeof(option)));
537         PetscCall(PetscStrlcat(option, PetscOptionsObject->prefix, sizeof(option)));
538         PetscCall(PetscStrlcat(option, next->option + 1, sizeof(option)));
539       } else {
540         PetscCall(PetscStrncpy(option, next->option, sizeof(option)));
541       }
542 
543       switch (type) {
544       case OPTION_HEAD:
545         break;
546       case OPTION_INT_ARRAY:
547         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%" PetscInt_FMT, ((PetscInt *)data)[0]));
548         for (size_t j = 1; j < arraylength; ++j) {
549           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%" PetscInt_FMT, ((PetscInt *)data)[j]));
550           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
551           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
552         }
553         break;
554       case OPTION_INT:
555         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%" PetscInt_FMT, *(PetscInt *)data));
556         break;
557       case OPTION_REAL:
558         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)*(PetscReal *)data));
559         break;
560       case OPTION_REAL_ARRAY:
561         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)((PetscReal *)data)[0]));
562         for (size_t j = 1; j < arraylength; ++j) {
563           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g", (double)((PetscReal *)data)[j]));
564           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
565           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
566         }
567         break;
568       case OPTION_SCALAR_ARRAY:
569         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[0]), (double)PetscImaginaryPart(((PetscScalar *)data)[0])));
570         for (size_t j = 1; j < arraylength; ++j) {
571           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[j]), (double)PetscImaginaryPart(((PetscScalar *)data)[j])));
572           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
573           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
574         }
575         break;
576       case OPTION_BOOL:
577         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", *(int *)data));
578         break;
579       case OPTION_BOOL_ARRAY:
580         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscBool *)data)[0]));
581         for (size_t j = 1; j < arraylength; ++j) {
582           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscBool *)data)[j]));
583           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
584           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
585         }
586         break;
587       case OPTION_FLIST: // fall-through
588       case OPTION_ELIST: // fall-through
589       case OPTION_STRING:
590         PetscCall(PetscStrncpy(value, (char *)data, sizeof(value)));
591         break;
592       case OPTION_STRING_ARRAY:
593         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%s", ((char **)data)[0]));
594         for (size_t j = 1; j < arraylength; j++) {
595           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%s", ((char **)data)[j]));
596           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
597           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
598         }
599         break;
600       }
601       PetscCall(PetscOptionsSetValue(PetscOptionsObject->options, option, value));
602     }
603     if (type == OPTION_ELIST) PetscCall(PetscStrNArrayDestroy(next->nlist, (char ***)&next->list));
604     PetscCall(PetscFree(next->text));
605     PetscCall(PetscFree(next->option));
606     PetscCall(PetscFree(next->man));
607     PetscCall(PetscFree(next->edata));
608 
609     if (type == OPTION_STRING || type == OPTION_FLIST || type == OPTION_ELIST) {
610       free(data);
611     } else {
612       // use next->data instead of data because PetscFree() sets it to NULL
613       PetscCall(PetscFree(next->data));
614     }
615 
616     last                     = next;
617     PetscOptionsObject->next = next->next;
618     PetscCall(PetscFree(last));
619   }
620   PetscCall(PetscFree(PetscOptionsObject->prefix));
621   PetscOptionsObject->next = NULL;
622   PetscFunctionReturn(PETSC_SUCCESS);
623 }
624 
GetListLength(const char * const * list,PetscInt * len)625 static PetscErrorCode GetListLength(const char *const *list, PetscInt *len)
626 {
627   PetscInt retlen = 0;
628 
629   PetscFunctionBegin;
630   PetscAssertPointer(len, 2);
631   while (list[retlen]) {
632     PetscAssertPointer(list[retlen], 1);
633     PetscCheck(++retlen < 50, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "List argument appears to be wrong or have more than 50 entries");
634   }
635   PetscCheck(retlen > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least 2 entries: typename and type prefix");
636   /* drop item name and prefix*/
637   *len = retlen - 2;
638   PetscFunctionReturn(PETSC_SUCCESS);
639 }
640 
PetscOptionsEnum_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],const char * const * list,PetscEnum currentvalue,PetscEnum * value,PetscBool * set)641 PetscErrorCode PetscOptionsEnum_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum currentvalue, PetscEnum *value, PetscBool *set)
642 {
643   PetscInt  ntext = 0;
644   PetscInt  tval;
645   PetscBool tflg;
646 
647   PetscFunctionBegin;
648   PetscAssertPointer(opt, 2);
649   PetscAssertPointer(list, 5);
650   PetscAssertPointer(value, 7);
651   if (set) PetscAssertPointer(set, 8);
652   PetscCall(GetListLength(list, &ntext));
653   PetscCall(PetscOptionsEList_Private(PetscOptionsObject, opt, text, man, list, ntext, list[(int)currentvalue], &tval, &tflg));
654   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
655   if (tflg) *value = (PetscEnum)tval;
656   if (set) *set = tflg;
657   PetscFunctionReturn(PETSC_SUCCESS);
658 }
659 
PetscOptionsEnumArray_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],const char * const * list,PetscEnum value[],PetscInt * n,PetscBool * set)660 PetscErrorCode PetscOptionsEnumArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum value[], PetscInt *n, PetscBool *set)
661 {
662   PetscInt    nlist  = 0;
663   const char *prefix = PetscOptionsObject->prefix;
664 
665   PetscFunctionBegin;
666   PetscAssertPointer(opt, 2);
667   PetscAssertPointer(list, 5);
668   PetscAssertPointer(value, 6);
669   PetscAssertPointer(n, 7);
670   PetscCheck(*n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") must be > 0", *n);
671   if (set) PetscAssertPointer(set, 8);
672   PetscCall(GetListLength(list, &nlist));
673   const PetscInt nin = *n;
674   PetscCall(PetscOptionsGetEnumArray(PetscOptionsObject->options, prefix, opt, list, value, n, set));
675   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
676     const MPI_Comm comm = PetscOptionsObject->comm;
677     const PetscInt nv   = *n;
678 
679     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%s", Prefix(prefix), opt + 1, list[value[0]]));
680     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%s", list[value[i]]));
681     PetscCall((*PetscHelpPrintf)(comm, ">: %s (choose from)", text));
682     for (PetscInt i = 0; i < nlist; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i]));
683     PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man)));
684   }
685   PetscFunctionReturn(PETSC_SUCCESS);
686 }
687 
PetscOptionsInt_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscInt currentvalue,PetscInt * value,PetscBool * set,PetscInt lb,PetscInt ub)688 PetscErrorCode PetscOptionsInt_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt currentvalue, PetscInt *value, PetscBool *set, PetscInt lb, PetscInt ub)
689 {
690   const char        *prefix  = PetscOptionsObject->prefix;
691   const PetscOptions options = PetscOptionsObject->options;
692   PetscBool          wasset;
693 
694   PetscFunctionBegin;
695   PetscAssertPointer(opt, 2);
696   PetscAssertPointer(value, 6);
697   if (set) PetscAssertPointer(set, 7);
698   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, currentvalue, lb);
699   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, currentvalue, ub);
700   if (!PetscOptionsObject->count) {
701     PetscOptionItem amsopt;
702 
703     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
704     PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
705     *(PetscInt *)amsopt->data = currentvalue;
706 
707     PetscCall(PetscOptionsGetInt(options, prefix, opt, &currentvalue, &wasset));
708     if (wasset) *(PetscInt *)amsopt->data = currentvalue;
709   }
710   PetscCall(PetscOptionsGetInt(options, prefix, opt, value, &wasset));
711   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, *value, lb);
712   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, *value, ub);
713   if (set) *set = wasset;
714   if (ShouldPrintHelp(PetscOptionsObject)) {
715     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %" PetscInt_FMT " : formerly %" PetscInt_FMT ">: %s (%s)\n", Prefix(prefix), opt + 1, wasset ? *value : currentvalue, currentvalue, text, ManSection(man)));
716   }
717   PetscFunctionReturn(PETSC_SUCCESS);
718 }
719 
PetscOptionsMPIInt_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscMPIInt currentvalue,PetscMPIInt * value,PetscBool * set,PetscMPIInt lb,PetscMPIInt ub)720 PetscErrorCode PetscOptionsMPIInt_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscMPIInt currentvalue, PetscMPIInt *value, PetscBool *set, PetscMPIInt lb, PetscMPIInt ub)
721 {
722   const char        *prefix  = PetscOptionsObject->prefix;
723   const PetscOptions options = PetscOptionsObject->options;
724   PetscBool          wasset;
725 
726   PetscFunctionBegin;
727   PetscAssertPointer(opt, 2);
728   PetscAssertPointer(value, 6);
729   if (set) PetscAssertPointer(set, 7);
730   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d less than allowed bound %d", currentvalue, lb);
731   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d greater than allowed bound %d", currentvalue, ub);
732   if (!PetscOptionsObject->count) {
733     PetscOptionItem amsopt;
734 
735     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
736     PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
737     *(PetscMPIInt *)amsopt->data = currentvalue;
738 
739     PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, &currentvalue, &wasset));
740     if (wasset) *(PetscMPIInt *)amsopt->data = currentvalue;
741   }
742   PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, value, &wasset));
743   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d less than allowed bound %d", *value, lb);
744   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d greater than allowed bound %d", *value, ub);
745   if (set) *set = wasset;
746   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %d : formerly %d>: %s (%s)\n", Prefix(prefix), opt + 1, wasset ? *value : currentvalue, currentvalue, text, ManSection(man)));
747   PetscFunctionReturn(PETSC_SUCCESS);
748 }
749 
PetscOptionsString_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],const char currentvalue[],char value[],size_t len,PetscBool * set)750 PetscErrorCode PetscOptionsString_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], const char currentvalue[], char value[], size_t len, PetscBool *set)
751 {
752   const char *prefix = PetscOptionsObject->prefix;
753   PetscBool   lset;
754 
755   PetscFunctionBegin;
756   PetscAssertPointer(opt, 2);
757   PetscAssertPointer(value, 6);
758   if (set) PetscAssertPointer(set, 8);
759   if (!PetscOptionsObject->count) {
760     PetscOptionItem amsopt;
761 
762     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
763     /* must use system malloc since SAWs may free this */
764     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
765   }
766   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset));
767   if (set) *set = lset;
768   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %s : formerly %s>: %s (%s)\n", Prefix(prefix), opt + 1, lset ? value : currentvalue, currentvalue, text, ManSection(man)));
769   PetscFunctionReturn(PETSC_SUCCESS);
770 }
771 
PetscOptionsReal_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscReal currentvalue,PetscReal * value,PetscBool * set,PetscReal lb,PetscReal ub)772 PetscErrorCode PetscOptionsReal_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal currentvalue, PetscReal *value, PetscBool *set, PetscReal lb, PetscReal ub)
773 {
774   const char        *prefix  = PetscOptionsObject->prefix;
775   const PetscOptions options = PetscOptionsObject->options;
776   PetscBool          wasset;
777 
778   PetscFunctionBegin;
779   PetscAssertPointer(opt, 2);
780   PetscAssertPointer(value, 6);
781   if (set) PetscAssertPointer(set, 7);
782   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g less than allowed bound %g", (double)currentvalue, (double)lb);
783   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g greater than allowed bound %g", (double)currentvalue, (double)ub);
784   if (!PetscOptionsObject->count) {
785     PetscOptionItem amsopt;
786 
787     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt));
788     PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data));
789     *(PetscReal *)amsopt->data = currentvalue;
790 
791     PetscCall(PetscOptionsGetReal(options, prefix, opt, &currentvalue, &wasset));
792     if (wasset) *(PetscReal *)amsopt->data = currentvalue;
793   }
794   PetscCall(PetscOptionsGetReal(PetscOptionsObject->options, prefix, opt, value, &wasset));
795   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g less than allowed bound %g", (double)*value, (double)lb);
796   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g greater than allowed bound %g", (double)*value, (double)ub);
797   if (set) *set = wasset;
798   if (ShouldPrintHelp(PetscOptionsObject)) {
799     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %g : formerly %g>: %s (%s)\n", Prefix(prefix), opt + 1, wasset ? (double)*value : (double)currentvalue, (double)currentvalue, text, ManSection(man)));
800   }
801   PetscFunctionReturn(PETSC_SUCCESS);
802 }
803 
PetscOptionsScalar_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscScalar currentvalue,PetscScalar * value,PetscBool * set)804 PetscErrorCode PetscOptionsScalar_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar currentvalue, PetscScalar *value, PetscBool *set)
805 {
806   PetscFunctionBegin;
807 #if !defined(PETSC_USE_COMPLEX)
808   PetscCall(PetscOptionsReal(opt, text, man, currentvalue, value, set));
809 #else
810   PetscCall(PetscOptionsGetScalar(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, set));
811 #endif
812   PetscFunctionReturn(PETSC_SUCCESS);
813 }
814 
PetscOptionsName_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscBool * flg)815 PetscErrorCode PetscOptionsName_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
816 {
817   const char *prefix = PetscOptionsObject->prefix;
818 
819   PetscFunctionBegin;
820   PetscAssertPointer(opt, 2);
821   PetscAssertPointer(flg, 5);
822   if (!PetscOptionsObject->count) {
823     PetscOptionItem amsopt;
824 
825     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
826     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
827 
828     *(PetscBool *)amsopt->data = PETSC_FALSE;
829   }
830   PetscCall(PetscOptionsHasName(PetscOptionsObject->options, prefix, opt, flg));
831   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
832   PetscFunctionReturn(PETSC_SUCCESS);
833 }
834 
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)835 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)
836 {
837   const char *prefix = PetscOptionsObject->prefix;
838   PetscBool   lset;
839 
840   PetscFunctionBegin;
841   PetscAssertPointer(opt, 2);
842   PetscAssertPointer(value, 7);
843   if (set) PetscAssertPointer(set, 9);
844   if (!PetscOptionsObject->count) {
845     PetscOptionItem amsopt;
846 
847     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_FLIST, &amsopt));
848     /* must use system malloc since SAWs may free this */
849     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
850     amsopt->flist = list;
851   }
852   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset));
853   if (set) *set = lset;
854   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall(PetscFunctionListPrintTypes(PetscOptionsObject->comm, stdout, Prefix(prefix), opt, ltext, man, list, currentvalue, lset ? value : currentvalue));
855   PetscFunctionReturn(PETSC_SUCCESS);
856 }
857 
858 #ifdef __cplusplus
859   #include <type_traits>
860 #endif
861 
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)862 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)
863 {
864   const char *prefix = PetscOptionsObject->prefix;
865   PetscBool   lset;
866 
867   PetscFunctionBegin;
868   PetscAssertPointer(opt, 2);
869   PetscAssertPointer(value, 8);
870   if (set) PetscAssertPointer(set, 9);
871   if (!PetscOptionsObject->count) {
872     PetscOptionItem amsopt;
873 
874     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_ELIST, &amsopt));
875     /* must use system malloc since SAWs may free this */
876     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
877     PetscCall(PetscStrNArrayallocpy(ntext, list, (char ***)&amsopt->list));
878     PetscCheck(ntext <= CHAR_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of list entries %" PetscInt_FMT " > %d", ntext, CHAR_MAX);
879 #ifdef __cplusplus
880     static_assert(std::is_same<typename std::decay<decltype(amsopt->nlist)>::type, char>::value, "");
881 #endif
882     amsopt->nlist = (char)ntext;
883   }
884   PetscCall(PetscOptionsGetEList(PetscOptionsObject->options, prefix, opt, list, ntext, value, &lset));
885   if (set) *set = lset;
886   if (ShouldPrintHelp(PetscOptionsObject)) {
887     const MPI_Comm comm = PetscOptionsObject->comm;
888 
889     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <now %s : formerly %s> %s (choose one of)", Prefix(prefix), opt + 1, lset ? list[*value] : currentvalue, currentvalue, ltext));
890     for (PetscInt i = 0; i < ntext; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i]));
891     PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man)));
892   }
893   PetscFunctionReturn(PETSC_SUCCESS);
894 }
895 
PetscOptionsBoolGroupBegin_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscBool * flg)896 PetscErrorCode PetscOptionsBoolGroupBegin_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
897 {
898   const char *prefix = PetscOptionsObject->prefix;
899 
900   PetscFunctionBegin;
901   PetscAssertPointer(opt, 2);
902   PetscAssertPointer(flg, 5);
903   if (!PetscOptionsObject->count) {
904     PetscOptionItem amsopt;
905 
906     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
907     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
908 
909     *(PetscBool *)amsopt->data = PETSC_FALSE;
910   }
911   *flg = PETSC_FALSE;
912   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
913   if (ShouldPrintHelp(PetscOptionsObject)) {
914     const MPI_Comm comm = PetscOptionsObject->comm;
915 
916     PetscCall((*PetscHelpPrintf)(comm, "  Pick at most one of -------------\n"));
917     PetscCall((*PetscHelpPrintf)(comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
918   }
919   PetscFunctionReturn(PETSC_SUCCESS);
920 }
921 
PetscOptionsBoolGroup_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscBool * flg)922 PetscErrorCode PetscOptionsBoolGroup_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
923 {
924   const char *prefix = PetscOptionsObject->prefix;
925 
926   PetscFunctionBegin;
927   PetscAssertPointer(opt, 2);
928   PetscAssertPointer(flg, 5);
929   if (!PetscOptionsObject->count) {
930     PetscOptionItem amsopt;
931 
932     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
933     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
934 
935     *(PetscBool *)amsopt->data = PETSC_FALSE;
936   }
937   *flg = PETSC_FALSE;
938   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
939   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
940   PetscFunctionReturn(PETSC_SUCCESS);
941 }
942 
PetscOptionsBoolGroupEnd_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscBool * flg)943 PetscErrorCode PetscOptionsBoolGroupEnd_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
944 {
945   const char *prefix = PetscOptionsObject->prefix;
946 
947   PetscFunctionBegin;
948   PetscAssertPointer(opt, 2);
949   PetscAssertPointer(flg, 5);
950   if (!PetscOptionsObject->count) {
951     PetscOptionItem amsopt;
952 
953     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
954     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
955 
956     *(PetscBool *)amsopt->data = PETSC_FALSE;
957   }
958   *flg = PETSC_FALSE;
959   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
960   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
961   PetscFunctionReturn(PETSC_SUCCESS);
962 }
963 
PetscOptionsBool_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscBool currentvalue,PetscBool * flg,PetscBool * set)964 PetscErrorCode PetscOptionsBool_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool currentvalue, PetscBool *flg, PetscBool *set)
965 {
966   const char *prefix = PetscOptionsObject->prefix;
967   PetscBool   iset;
968 
969   PetscFunctionBegin;
970   PetscAssertPointer(opt, 2);
971   PetscAssertPointer(flg, 6);
972   if (set) PetscAssertPointer(set, 7);
973   if (!PetscOptionsObject->count) {
974     PetscOptionItem amsopt;
975 
976     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
977     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));
978 
979     *(PetscBool *)amsopt->data = currentvalue;
980   }
981   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, &iset));
982   if (set) *set = iset;
983   if (ShouldPrintHelp(PetscOptionsObject)) {
984     const char *curvalue = PetscBools[currentvalue];
985 
986     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %s : formerly %s> %s (%s)\n", Prefix(prefix), opt + 1, iset ? PetscBools[*flg] : curvalue, curvalue, text, ManSection(man)));
987   }
988   PetscFunctionReturn(PETSC_SUCCESS);
989 }
990 
PetscOptionsBool3_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscBool3 currentvalue,PetscBool3 * flg,PetscBool * set)991 PetscErrorCode PetscOptionsBool3_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool3 currentvalue, PetscBool3 *flg, PetscBool *set)
992 {
993   const char *prefix = PetscOptionsObject->prefix;
994   PetscBool   iset;
995 
996   PetscFunctionBegin;
997   PetscAssertPointer(opt, 2);
998   PetscAssertPointer(flg, 6);
999   if (set) PetscAssertPointer(set, 7);
1000   PetscCall(PetscOptionsGetBool3(PetscOptionsObject->options, prefix, opt, flg, &iset));
1001   if (set) *set = iset;
1002   if (ShouldPrintHelp(PetscOptionsObject)) {
1003     const char *curvalue = PetscBool3s[currentvalue];
1004 
1005     PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <now %s : formerly %s> %s (%s)\n", Prefix(prefix), opt + 1, iset ? PetscBools[*flg] : curvalue, curvalue, text, ManSection(man)));
1006   }
1007   PetscFunctionReturn(PETSC_SUCCESS);
1008 }
1009 
PetscOptionsRealArray_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscReal value[],PetscInt * n,PetscBool * set)1010 PetscErrorCode PetscOptionsRealArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal value[], PetscInt *n, PetscBool *set)
1011 {
1012   const char *prefix = PetscOptionsObject->prefix;
1013 
1014   PetscFunctionBegin;
1015   PetscAssertPointer(opt, 2);
1016   PetscAssertPointer(n, 6);
1017   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1018   if (*n) PetscAssertPointer(value, 5);
1019   if (set) PetscAssertPointer(set, 7);
1020   if (!PetscOptionsObject->count) {
1021     const PetscInt  nv = *n;
1022     PetscReal      *vals;
1023     PetscOptionItem amsopt;
1024 
1025     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt));
1026     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
1027     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1028     amsopt->arraylength = nv;
1029     amsopt->data        = vals;
1030   }
1031   const PetscInt nin = *n;
1032   PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1033   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
1034     const PetscInt nv   = *n;
1035     const MPI_Comm comm = PetscOptionsObject->comm;
1036 
1037     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g", Prefix(prefix), opt + 1, (double)value[0]));
1038     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g", (double)value[i]));
1039     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1040   }
1041   PetscFunctionReturn(PETSC_SUCCESS);
1042 }
1043 
PetscOptionsScalarArray_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscScalar value[],PetscInt * n,PetscBool * set)1044 PetscErrorCode PetscOptionsScalarArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar value[], PetscInt *n, PetscBool *set)
1045 {
1046   const char *prefix = PetscOptionsObject->prefix;
1047 
1048   PetscFunctionBegin;
1049   PetscAssertPointer(opt, 2);
1050   PetscAssertPointer(n, 6);
1051   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1052   if (*n) PetscAssertPointer(value, 5);
1053   if (set) PetscAssertPointer(set, 7);
1054   if (!PetscOptionsObject->count) {
1055     const PetscInt  nv = *n;
1056     PetscOptionItem amsopt;
1057     PetscScalar    *vals;
1058 
1059     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt));
1060     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
1061     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1062     amsopt->arraylength = nv;
1063     amsopt->data        = vals;
1064   }
1065   const PetscInt nin = *n;
1066   PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1067   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
1068     const PetscInt nv   = *n;
1069     const MPI_Comm comm = PetscOptionsObject->comm;
1070 
1071     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g+%gi", Prefix(prefix), opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0])));
1072     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i])));
1073     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1074   }
1075   PetscFunctionReturn(PETSC_SUCCESS);
1076 }
1077 
PetscOptionsIntArray_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscInt value[],PetscInt * n,PetscBool * set)1078 PetscErrorCode PetscOptionsIntArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt value[], PetscInt *n, PetscBool *set)
1079 {
1080   const char *prefix = PetscOptionsObject->prefix;
1081 
1082   PetscFunctionBegin;
1083   PetscAssertPointer(opt, 2);
1084   PetscAssertPointer(n, 6);
1085   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1086   if (*n) PetscAssertPointer(value, 5);
1087   if (set) PetscAssertPointer(set, 7);
1088   if (!PetscOptionsObject->count) {
1089     const PetscInt  nv = *n;
1090     PetscInt       *vals;
1091     PetscOptionItem amsopt;
1092 
1093     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY, &amsopt));
1094     PetscCall(PetscMalloc1(nv, &vals));
1095     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1096     amsopt->arraylength = nv;
1097     amsopt->data        = vals;
1098   }
1099   const PetscInt nin = *n;
1100   PetscCall(PetscOptionsGetIntArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1101   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
1102     const PetscInt nv   = *n;
1103     const MPI_Comm comm = PetscOptionsObject->comm;
1104 
1105     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%" PetscInt_FMT, Prefix(prefix), opt + 1, value[0]));
1106     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%" PetscInt_FMT, value[i]));
1107     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1108   }
1109   PetscFunctionReturn(PETSC_SUCCESS);
1110 }
1111 
PetscOptionsStringArray_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],char * value[],PetscInt * nmax,PetscBool * set)1112 PetscErrorCode PetscOptionsStringArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], char *value[], PetscInt *nmax, PetscBool *set)
1113 {
1114   const char *prefix = PetscOptionsObject->prefix;
1115 
1116   PetscFunctionBegin;
1117   PetscAssertPointer(opt, 2);
1118   PetscAssertPointer(nmax, 6);
1119   PetscCheck(*nmax >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *nmax);
1120   if (*nmax) PetscAssertPointer(value, 5);
1121   if (set) PetscAssertPointer(set, 7);
1122   if (!PetscOptionsObject->count) {
1123     const PetscInt  nmaxv = *nmax;
1124     PetscOptionItem amsopt;
1125 
1126     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt));
1127     PetscCall(PetscMalloc1(nmaxv, (char **)&amsopt->data));
1128     amsopt->arraylength = nmaxv;
1129   }
1130   const PetscInt nin = *nmax;
1131   PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, prefix, opt, value, nmax, set));
1132   if (ShouldPrintHelp(PetscOptionsObject) && nin) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <string1,string2,...>: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
1133   PetscFunctionReturn(PETSC_SUCCESS);
1134 }
1135 
PetscOptionsBoolArray_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscBool value[],PetscInt * n,PetscBool * set)1136 PetscErrorCode PetscOptionsBoolArray_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool value[], PetscInt *n, PetscBool *set)
1137 {
1138   const char *prefix = PetscOptionsObject->prefix;
1139 
1140   PetscFunctionBegin;
1141   PetscAssertPointer(opt, 2);
1142   PetscAssertPointer(n, 6);
1143   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1144   if (*n) PetscAssertPointer(value, 5);
1145   if (set) PetscAssertPointer(set, 7);
1146   if (!PetscOptionsObject->count) {
1147     const PetscInt  nv = *n;
1148     PetscBool      *vals;
1149     PetscOptionItem amsopt;
1150 
1151     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt));
1152     PetscCall(PetscMalloc1(nv, &vals));
1153     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1154     amsopt->arraylength = nv;
1155     amsopt->data        = vals;
1156   }
1157   const PetscInt nin = *n;
1158   PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1159   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
1160     const PetscInt nv   = *n;
1161     const MPI_Comm comm = PetscOptionsObject->comm;
1162 
1163     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%d", Prefix(prefix), opt + 1, value[0]));
1164     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%d", value[i]));
1165     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1166   }
1167   PetscFunctionReturn(PETSC_SUCCESS);
1168 }
1169 
1170 /*MC
1171   PetscOptionsViewer - Creates a viewer appropriate for the type indicated by the user
1172 
1173   Synopsis:
1174   #include <petscviewer.h>
1175   PetscErrorCode PetscOptionsViewer(const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
1176 
1177   Logically Collective on the communicator passed in `PetscOptionsBegin()`
1178 
1179   Input Parameters:
1180 + opt  - option name
1181 . text - short string that describes the option
1182 - man  - manual page with additional information on option
1183 
1184   Output Parameters:
1185 + viewer - the viewer
1186 . format - the PetscViewerFormat requested by the user, pass `NULL` if not needed
1187 - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`
1188 
1189   Level: beginner
1190 
1191   Notes:
1192   Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`
1193 
1194   See `PetscOptionsCreateViewer()` for the format of the supplied viewer and its options
1195 
1196 .seealso: `PetscOptionsCreateViewer()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1197           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
1198           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
1199           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1200           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1201           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1202           `PetscOptionsFList()`, `PetscOptionsEList()`
1203 M*/
PetscOptionsViewer_Private(PetscOptionItems PetscOptionsObject,const char opt[],const char text[],const char man[],PetscViewer * viewer,PetscViewerFormat * format,PetscBool * set)1204 PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
1205 {
1206   const MPI_Comm comm   = PetscOptionsObject->comm;
1207   const char    *prefix = PetscOptionsObject->prefix;
1208 
1209   PetscFunctionBegin;
1210   PetscAssertPointer(opt, 2);
1211   PetscAssertPointer(viewer, 5);
1212   if (format) PetscAssertPointer(format, 6);
1213   if (set) PetscAssertPointer(set, 7);
1214   if (!PetscOptionsObject->count) {
1215     PetscOptionItem amsopt;
1216 
1217     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
1218     /* must use system malloc since SAWs may free this */
1219     PetscCall(PetscStrdup("", (char **)&amsopt->data));
1220   }
1221   PetscCall(PetscOptionsCreateViewer(comm, PetscOptionsObject->options, prefix, opt, viewer, format, set));
1222   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%s>: %s (%s)\n", Prefix(prefix), opt + 1, "", text, ManSection(man)));
1223   PetscFunctionReturn(PETSC_SUCCESS);
1224 }
1225