Actual source code: aoptions.c

  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.

  5: */

  7: #include <petsc/private/petscimpl.h>
  8: #include <petscviewer.h>

 10: static const char *ManSection(const char *str)
 11: {
 12:   return str ? str : "None";
 13: }

 15: static const char *Prefix(const char *str)
 16: {
 17:   return str ? str : "";
 18: }

 20: static int ShouldPrintHelp(const PetscOptionItems *opts)
 21: {
 22:   return opts->printhelp && opts->count == 1 && !opts->alreadyprinted;
 23: }

 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()

 29:     Eventually we'll attach this beast to a MPI_Comm
 30: */

 32: /*
 33:     Handles setting up the data structure in a call to PetscOptionsBegin()
 34: */
 35: PetscErrorCode PetscOptionsBegin_Private(PetscOptionItems *PetscOptionsObject, MPI_Comm comm, const char prefix[], const char title[], const char mansec[])
 36: {
 37:   PetscFunctionBegin;
 38:   if (prefix) 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;

 49:   PetscCall(PetscStrallocpy(prefix, &PetscOptionsObject->prefix));
 50:   PetscCall(PetscStrallocpy(title, &PetscOptionsObject->title));

 52:   PetscCall(PetscOptionsHasHelp(PetscOptionsObject->options, &PetscOptionsObject->printhelp));
 53:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\n%s:\n", title));
 54:   PetscFunctionReturn(PETSC_SUCCESS);
 55: }

 57: /*
 58:     Handles setting up the data structure in a call to PetscObjectOptionsBegin()
 59: */
 60: PetscErrorCode PetscObjectOptionsBegin_Private(PetscObject obj, PetscOptionItems *PetscOptionsObject)
 61: {
 62:   char      title[256];
 63:   PetscBool flg;

 65:   PetscFunctionBegin;
 66:   PetscAssertPointer(PetscOptionsObject, 2);
 68:   PetscOptionsObject->object         = obj;
 69:   PetscOptionsObject->alreadyprinted = obj->optionsprinted;

 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: }

 78: /*
 79:      Handles adding another option to the list of options within this particular PetscOptionsBegin() PetscOptionsEnd()
 80: */
 81: static PetscErrorCode PetscOptionItemCreate_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscOptionType t, PetscOptionItem *amsopt)
 82: {
 83:   PetscBool valid;

 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);

 89:   PetscCall(PetscNew(amsopt));
 90:   (*amsopt)->next = NULL;
 91:   (*amsopt)->set  = PETSC_FALSE;
 92:   (*amsopt)->type = t;
 93:   (*amsopt)->data = NULL;

 95:   PetscCall(PetscStrallocpy(text, &(*amsopt)->text));
 96:   PetscCall(PetscStrallocpy(opt, &(*amsopt)->option));
 97:   PetscCall(PetscStrallocpy(man, &(*amsopt)->man));

 99:   {
100:     PetscOptionItem cur = PetscOptionsObject->next;

102:     while (cur->next) cur = cur->next;
103:     cur->next = *amsopt;
104:   }
105:   PetscFunctionReturn(PETSC_SUCCESS);
106: }

108: /*
109:     This is needed because certain strings may be freed by SAWs, hence we cannot use PetscStrallocpy()
110: */
111: static PetscErrorCode PetscStrdup(const char s[], char *t[])
112: {
113:   char *tmp = NULL;

115:   PetscFunctionBegin;
116:   if (s) {
117:     size_t len;

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: }

128: #if defined(PETSC_HAVE_SAWS)
129: #include <petscviewersaws.h>

131: static int count = 0;

133: PetscErrorCode PetscOptionsSAWsDestroy(void)
134: {
135:   PetscFunctionBegin;
136:   PetscFunctionReturn(PETSC_SUCCESS);
137: }

139: static const char *OptionsHeader = "<head>\n"
140:                                    "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/jquery-1.9.1.js\"></script>\n"
141:                                    "<script type=\"text/javascript\" src=\"https://www.mcs.anl.gov/research/projects/saws/js/SAWs.js\"></script>\n"
142:                                    "<script type=\"text/javascript\" src=\"js/PETSc.js\"></script>\n"
143:                                    "<script>\n"
144:                                    "jQuery(document).ready(function() {\n"
145:                                    "PETSc.getAndDisplayDirectory(null,\"#variablesInfo\")\n"
146:                                    "})\n"
147:                                    "</script>\n"
148:                                    "</head>\n";

150: /*  Determines the size and style of the scroll region where PETSc options selectable from users are displayed */
151: static const char *OptionsBodyBottom = "<div id=\"variablesInfo\" style=\"background-color:lightblue;height:auto;max-height:500px;overflow:scroll;\"></div>\n<br>\n</body>";

153: /*
154:     PetscOptionsSAWsInput - Presents all the PETSc Options processed by the program so the user may change them at runtime using the SAWs

156:     Bugs:
157: +    All processes must traverse through the exact same set of option queries due to the call to PetscScanString()
158: .    Internal strings have arbitrary length and string copies are not checked that they fit into string space
159: -    Only works for PetscInt == int, PetscReal == double etc

161: */
162: static PetscErrorCode PetscOptionsSAWsInput(PetscOptionItems *PetscOptionsObject)
163: {
164:   PetscOptionItem next     = PetscOptionsObject->next;
165:   static int      mancount = 0;
166:   char            options[16];
167:   PetscBool       changedmethod = PETSC_FALSE;
168:   PetscBool       stopasking    = PETSC_FALSE;
169:   char            manname[16], textname[16];
170:   char            dir[1024];

172:   PetscFunctionBegin;
173:   /* the next line is a bug, this will only work if all processors are here, the comm passed in is ignored!!! */
174:   PetscCall(PetscSNPrintf(options, PETSC_STATIC_ARRAY_LENGTH(options), "Options_%d", count++));

176:   PetscOptionsObject->pprefix = PetscOptionsObject->prefix; /* SAWs will change this, so cannot pass prefix directly */

178:   PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "_title"));
179:   PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->title, 1, SAWs_READ, SAWs_STRING));
180:   PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", "prefix"));
181:   PetscCallSAWs(SAWs_Register, (dir, &PetscOptionsObject->pprefix, 1, SAWs_READ, SAWs_STRING));
182:   PetscCallSAWs(SAWs_Register, ("/PETSc/Options/ChangedMethod", &changedmethod, 1, SAWs_WRITE, SAWs_BOOLEAN));
183:   PetscCallSAWs(SAWs_Register, ("/PETSc/Options/StopAsking", &stopasking, 1, SAWs_WRITE, SAWs_BOOLEAN));

185:   while (next) {
186:     PetscCall(PetscSNPrintf(manname, PETSC_STATIC_ARRAY_LENGTH(manname), "_man_%d", mancount));
187:     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", manname));
188:     PetscCallSAWs(SAWs_Register, (dir, &next->man, 1, SAWs_READ, SAWs_STRING));
189:     PetscCall(PetscSNPrintf(textname, PETSC_STATIC_ARRAY_LENGTH(textname), "_text_%d", mancount++));
190:     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", textname));
191:     PetscCallSAWs(SAWs_Register, (dir, &next->text, 1, SAWs_READ, SAWs_STRING));

193:     switch (next->type) {
194:     case OPTION_HEAD:
195:       break;
196:     case OPTION_INT_ARRAY:
197:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
198:       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_INT));
199:       break;
200:     case OPTION_REAL_ARRAY:
201:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
202:       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_DOUBLE));
203:       break;
204:     case OPTION_INT:
205:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
206:       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_INT));
207:       break;
208:     case OPTION_REAL:
209:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
210:       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_DOUBLE));
211:       break;
212:     case OPTION_BOOL:
213:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
214:       PetscCallSAWs(SAWs_Register, (dir, next->data, 1, SAWs_WRITE, SAWs_BOOLEAN));
215:       break;
216:     case OPTION_BOOL_ARRAY:
217:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
218:       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_BOOLEAN));
219:       break;
220:     case OPTION_STRING:
221:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
222:       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
223:       break;
224:     case OPTION_STRING_ARRAY:
225:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
226:       PetscCallSAWs(SAWs_Register, (dir, next->data, next->arraylength, SAWs_WRITE, SAWs_STRING));
227:       break;
228:     case OPTION_FLIST: {
229:       PetscInt ntext;
230:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
231:       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
232:       PetscCall(PetscFunctionListGet(next->flist, (const char ***)&next->edata, &ntext));
233:       PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata));
234:     } break;
235:     case OPTION_ELIST: {
236:       PetscInt ntext = next->nlist;
237:       PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
238:       PetscCallSAWs(SAWs_Register, (dir, &next->data, 1, SAWs_WRITE, SAWs_STRING));
239:       PetscCall(PetscMalloc1((ntext + 1), (char ***)&next->edata));
240:       PetscCall(PetscMemcpy(next->edata, next->list, ntext * sizeof(char *)));
241:       PetscCallSAWs(SAWs_Set_Legal_Variable_Values, (dir, ntext, next->edata));
242:     } break;
243:     default:
244:       break;
245:     }
246:     next = next->next;
247:   }

249:   /* wait until accessor has unlocked the memory */
250:   PetscCallSAWs(SAWs_Push_Header, ("index.html", OptionsHeader));
251:   PetscCallSAWs(SAWs_Push_Body, ("index.html", 2, OptionsBodyBottom));
252:   PetscCall(PetscSAWsBlock());
253:   PetscCallSAWs(SAWs_Pop_Header, ("index.html"));
254:   PetscCallSAWs(SAWs_Pop_Body, ("index.html", 2));

256:   /* determine if any values have been set in GUI */
257:   next = PetscOptionsObject->next;
258:   while (next) {
259:     PetscCall(PetscSNPrintf(dir, 1024, "/PETSc/Options/%s", next->option));
260:     PetscCallSAWs(SAWs_Selected, (dir, (int *)&next->set));
261:     next = next->next;
262:   }

264:   /* reset counter to -2; this updates the screen with the new options for the selected method */
265:   if (changedmethod) PetscOptionsObject->count = -2;

267:   if (stopasking) {
268:     PetscOptionsPublish       = PETSC_FALSE;
269:     PetscOptionsObject->count = 0; //do not ask for same thing again
270:   }

272:   PetscCallSAWs(SAWs_Delete, ("/PETSc/Options"));
273:   PetscFunctionReturn(PETSC_SUCCESS);
274: }
275: #else
276: /*
277:     PetscScanString -  Gets user input via stdin from process and broadcasts to all processes

279:     Collective

281:    Input Parameters:
282: +     commm - communicator for the broadcast, must be PETSC_COMM_WORLD
283: .     n - length of the string, must be the same on all processes
284: -     str - location to store input

286:     Bugs:
287: .   Assumes process 0 of the given communicator has access to stdin

289: */
290: static PetscErrorCode PetscScanString(MPI_Comm comm, size_t n, char str[])
291: {
292:   PetscMPIInt rank, nm;

294:   PetscFunctionBegin;
295:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
296:   if (rank == 0) {
297:     char   c = (char)getchar();
298:     size_t i = 0;

300:     while (c != '\n' && i < n - 1) {
301:       str[i++] = c;
302:       c        = (char)getchar();
303:     }
304:     str[i] = '\0';
305:   }
306:   PetscCall(PetscMPIIntCast(n, &nm));
307:   PetscCallMPI(MPI_Bcast(str, nm, MPI_CHAR, 0, comm));
308:   PetscFunctionReturn(PETSC_SUCCESS);
309: }

311: /*
312:   PetscOptionsGetFromTextInput - Presents all the PETSc Options processed by the program so the user may change them at runtime

314:   Notes:
315:   this isn't really practical, it is just to demonstrate the principle

317:   A carriage return indicates no change from the default; but this like -ksp_monitor <stdout>  the default is actually not stdout the default
318:   is to do nothing so to get it to use stdout you need to type stdout. This is kind of bug?

320:   Bugs:
321: +    All processes must traverse through the exact same set of option queries due to the call to PetscScanString()
322: .    Internal strings have arbitrary length and string copies are not checked that they fit into string space
323: -    Only works for PetscInt == int, PetscReal == double etc

325:   Developer Notes:
326:   Normally the GUI that presents the options the user and retrieves the values would be running in a different
327:   address space and communicating with the PETSc program

329: */
330: static PetscErrorCode PetscOptionsGetFromTextInput(PetscOptionItems *PetscOptionsObject)
331: {
332:   PetscOptionItem next = PetscOptionsObject->next;
333:   char            str[512];
334:   PetscBool       bid;
335:   PetscReal       ir, *valr;
336:   PetscInt       *vald;
337:   size_t          i;

339:   PetscFunctionBegin;
340:   PetscCall((*PetscPrintf)(PETSC_COMM_WORLD, "%s --------------------\n", PetscOptionsObject->title));
341:   while (next) {
342:     switch (next->type) {
343:     case OPTION_HEAD:
344:       break;
345:     case OPTION_INT_ARRAY:
346:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1));
347:       vald = (PetscInt *)next->data;
348:       for (i = 0; i < next->arraylength; i++) {
349:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%" PetscInt_FMT, vald[i]));
350:         if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ","));
351:       }
352:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man));
353:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
354:       if (str[0]) {
355:         PetscToken token;
356:         PetscInt   n = 0, nmax = next->arraylength, *dvalue = (PetscInt *)next->data, start, end;
357:         size_t     len;
358:         char      *value;
359:         PetscBool  foundrange;

361:         next->set = PETSC_TRUE;
362:         value     = str;
363:         PetscCall(PetscTokenCreate(value, ',', &token));
364:         PetscCall(PetscTokenFind(token, &value));
365:         while (n < nmax) {
366:           if (!value) break;

368:           /* look for form  d-D where d and D are integers */
369:           foundrange = PETSC_FALSE;
370:           PetscCall(PetscStrlen(value, &len));
371:           if (value[0] == '-') i = 2;
372:           else i = 1;
373:           for (; i < len; i++) {
374:             if (value[i] == '-') {
375:               PetscCheck(i != len - 1, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, value);
376:               value[i] = 0;
377:               PetscCall(PetscOptionsStringToInt(value, &start));
378:               PetscCall(PetscOptionsStringToInt(value + i + 1, &end));
379:               PetscCheck(end > start, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, %s-%s cannot have decreasing list", n, value, value + i + 1);
380:               PetscCheck(n + end - start - 1 < nmax, PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry, not enough space in left in array (%" PetscInt_FMT ") to contain entire range from %" PetscInt_FMT " to %" PetscInt_FMT, n, nmax - n, start, end);
381:               for (; start < end; start++) {
382:                 *dvalue = start;
383:                 dvalue++;
384:                 n++;
385:               }
386:               foundrange = PETSC_TRUE;
387:               break;
388:             }
389:           }
390:           if (!foundrange) {
391:             PetscCall(PetscOptionsStringToInt(value, dvalue));
392:             dvalue++;
393:             n++;
394:           }
395:           PetscCall(PetscTokenFind(token, &value));
396:         }
397:         PetscCall(PetscTokenDestroy(&token));
398:       }
399:       break;
400:     case OPTION_REAL_ARRAY:
401:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1));
402:       valr = (PetscReal *)next->data;
403:       for (i = 0; i < next->arraylength; i++) {
404:         PetscCall(PetscPrintf(PETSC_COMM_WORLD, "%g", (double)valr[i]));
405:         if (i < next->arraylength - 1) PetscCall(PetscPrintf(PETSC_COMM_WORLD, ","));
406:       }
407:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, ">: %s (%s) ", next->text, next->man));
408:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
409:       if (str[0]) {
410:         PetscToken token;
411:         PetscInt   n = 0, nmax = next->arraylength;
412:         PetscReal *dvalue = (PetscReal *)next->data;
413:         char      *value;

415:         next->set = PETSC_TRUE;
416:         value     = str;
417:         PetscCall(PetscTokenCreate(value, ',', &token));
418:         PetscCall(PetscTokenFind(token, &value));
419:         while (n < nmax) {
420:           if (!value) break;
421:           PetscCall(PetscOptionsStringToReal(value, dvalue));
422:           dvalue++;
423:           n++;
424:           PetscCall(PetscTokenFind(token, &value));
425:         }
426:         PetscCall(PetscTokenDestroy(&token));
427:       }
428:       break;
429:     case OPTION_INT:
430:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%d>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(int *)next->data, next->text, next->man));
431:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
432:       if (str[0]) {
433:   #if defined(PETSC_SIZEOF_LONG_LONG)
434:         long long lid;
435:         sscanf(str, "%lld", &lid);
436:         PetscCheck(lid <= PETSC_MAX_INT && lid >= PETSC_MIN_INT, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %lld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid);
437:   #else
438:         long lid;
439:         sscanf(str, "%ld", &lid);
440:         PetscCheck(lid <= PETSC_MAX_INT && lid >= PETSC_MIN_INT, PETSC_COMM_WORLD, PETSC_ERR_ARG_OUTOFRANGE, "Argument: -%s%s %ld", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, lid);
441:   #endif

443:         next->set                 = PETSC_TRUE;
444:         *((PetscInt *)next->data) = (PetscInt)lid;
445:       }
446:       break;
447:     case OPTION_REAL:
448:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%g>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(double *)next->data, next->text, next->man));
449:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
450:       if (str[0]) {
451:   #if defined(PETSC_USE_REAL_SINGLE)
452:         sscanf(str, "%e", &ir);
453:   #elif defined(PETSC_USE_REAL___FP16)
454:         float irtemp;
455:         sscanf(str, "%e", &irtemp);
456:         ir = irtemp;
457:   #elif defined(PETSC_USE_REAL_DOUBLE)
458:         sscanf(str, "%le", &ir);
459:   #elif defined(PETSC_USE_REAL___FLOAT128)
460:         ir = strtoflt128(str, 0);
461:   #else
462:         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "Unknown scalar type");
463:   #endif
464:         next->set                  = PETSC_TRUE;
465:         *((PetscReal *)next->data) = ir;
466:       }
467:       break;
468:     case OPTION_BOOL:
469:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%s>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, *(PetscBool *)next->data ? "true" : "false", next->text, next->man));
470:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
471:       if (str[0]) {
472:         PetscCall(PetscOptionsStringToBool(str, &bid));
473:         next->set                  = PETSC_TRUE;
474:         *((PetscBool *)next->data) = bid;
475:       }
476:       break;
477:     case OPTION_STRING:
478:       PetscCall(PetscPrintf(PETSC_COMM_WORLD, "-%s%s: <%s>: %s (%s) ", PetscOptionsObject->prefix ? PetscOptionsObject->prefix : "", next->option + 1, (char *)next->data, next->text, next->man));
479:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
480:       if (str[0]) {
481:         next->set = PETSC_TRUE;
482:         /* must use system malloc since SAWs may free this */
483:         PetscCall(PetscStrdup(str, (char **)&next->data));
484:       }
485:       break;
486:     case OPTION_FLIST:
487:       PetscCall(PetscFunctionListPrintTypes(PETSC_COMM_WORLD, stdout, PetscOptionsObject->prefix, next->option, next->text, next->man, next->flist, (char *)next->data, (char *)next->data));
488:       PetscCall(PetscScanString(PETSC_COMM_WORLD, 512, str));
489:       if (str[0]) {
490:         PetscOptionsObject->changedmethod = PETSC_TRUE;
491:         next->set                         = PETSC_TRUE;
492:         /* must use system malloc since SAWs may free this */
493:         PetscCall(PetscStrdup(str, (char **)&next->data));
494:       }
495:       break;
496:     default:
497:       break;
498:     }
499:     next = next->next;
500:   }
501:   PetscFunctionReturn(PETSC_SUCCESS);
502: }
503: #endif

505: PetscErrorCode PetscOptionsEnd_Private(PetscOptionItems *PetscOptionsObject)
506: {
507:   PetscOptionItem next, last;

509:   PetscFunctionBegin;
510:   if (PetscOptionsObject->next) {
511:     if (!PetscOptionsObject->count) {
512: #if defined(PETSC_HAVE_SAWS)
513:       PetscCall(PetscOptionsSAWsInput(PetscOptionsObject));
514: #else
515:       PetscCall(PetscOptionsGetFromTextInput(PetscOptionsObject));
516: #endif
517:     }
518:   }

520:   PetscCall(PetscFree(PetscOptionsObject->title));

522:   /* reset counter to -2; this updates the screen with the new options for the selected method */
523:   if (PetscOptionsObject->changedmethod) PetscOptionsObject->count = -2;
524:   /* reset alreadyprinted flag */
525:   PetscOptionsObject->alreadyprinted = PETSC_FALSE;
526:   if (PetscOptionsObject->object) PetscOptionsObject->object->optionsprinted = PETSC_TRUE;
527:   PetscOptionsObject->object = NULL;

529:   while ((next = PetscOptionsObject->next)) {
530:     const PetscOptionType type        = next->type;
531:     const size_t          arraylength = next->arraylength;
532:     void                 *data        = next->data;

534:     if (next->set) {
535:       char option[256], value[1024], tmp[32];

537:       if (PetscOptionsObject->prefix) {
538:         PetscCall(PetscStrncpy(option, "-", sizeof(option)));
539:         PetscCall(PetscStrlcat(option, PetscOptionsObject->prefix, sizeof(option)));
540:         PetscCall(PetscStrlcat(option, next->option + 1, sizeof(option)));
541:       } else {
542:         PetscCall(PetscStrncpy(option, next->option, sizeof(option)));
543:       }

545:       switch (type) {
546:       case OPTION_HEAD:
547:         break;
548:       case OPTION_INT_ARRAY:
549:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscInt *)data)[0]));
550:         for (size_t j = 1; j < arraylength; ++j) {
551:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscInt *)data)[j]));
552:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
553:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
554:         }
555:         break;
556:       case OPTION_INT:
557:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)*(PetscInt *)data));
558:         break;
559:       case OPTION_REAL:
560:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)*(PetscReal *)data));
561:         break;
562:       case OPTION_REAL_ARRAY:
563:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g", (double)((PetscReal *)data)[0]));
564:         for (size_t j = 1; j < arraylength; ++j) {
565:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g", (double)((PetscReal *)data)[j]));
566:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
567:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
568:         }
569:         break;
570:       case OPTION_SCALAR_ARRAY:
571:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[0]), (double)PetscImaginaryPart(((PetscScalar *)data)[0])));
572:         for (size_t j = 1; j < arraylength; ++j) {
573:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%g+%gi", (double)PetscRealPart(((PetscScalar *)data)[j]), (double)PetscImaginaryPart(((PetscScalar *)data)[j])));
574:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
575:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
576:         }
577:         break;
578:       case OPTION_BOOL:
579:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", *(int *)data));
580:         break;
581:       case OPTION_BOOL_ARRAY:
582:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%d", (int)((PetscBool *)data)[0]));
583:         for (size_t j = 1; j < arraylength; ++j) {
584:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%d", (int)((PetscBool *)data)[j]));
585:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
586:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
587:         }
588:         break;
589:       case OPTION_FLIST: // fall-through
590:       case OPTION_ELIST: // fall-through
591:       case OPTION_STRING:
592:         PetscCall(PetscStrncpy(value, (char *)data, sizeof(value)));
593:         break;
594:       case OPTION_STRING_ARRAY:
595:         PetscCall(PetscSNPrintf(value, PETSC_STATIC_ARRAY_LENGTH(value), "%s", ((char **)data)[0]));
596:         for (size_t j = 1; j < arraylength; j++) {
597:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%s", ((char **)data)[j]));
598:           PetscCall(PetscStrlcat(value, ",", sizeof(value)));
599:           PetscCall(PetscStrlcat(value, tmp, sizeof(value)));
600:         }
601:         break;
602:       }
603:       PetscCall(PetscOptionsSetValue(PetscOptionsObject->options, option, value));
604:     }
605:     if (type == OPTION_ELIST) PetscCall(PetscStrNArrayDestroy(next->nlist, (char ***)&next->list));
606:     PetscCall(PetscFree(next->text));
607:     PetscCall(PetscFree(next->option));
608:     PetscCall(PetscFree(next->man));
609:     PetscCall(PetscFree(next->edata));

611:     if (type == OPTION_STRING || type == OPTION_FLIST || type == OPTION_ELIST) {
612:       free(data);
613:     } else {
614:       // use next->data instead of data because PetscFree() sets it to NULL
615:       PetscCall(PetscFree(next->data));
616:     }

618:     last                     = next;
619:     PetscOptionsObject->next = next->next;
620:     PetscCall(PetscFree(last));
621:   }
622:   PetscCall(PetscFree(PetscOptionsObject->prefix));
623:   PetscOptionsObject->next = NULL;
624:   PetscFunctionReturn(PETSC_SUCCESS);
625: }

627: static PetscErrorCode GetListLength(const char *const *list, PetscInt *len)
628: {
629:   PetscInt retlen = 0;

631:   PetscFunctionBegin;
632:   PetscAssertPointer(len, 2);
633:   while (list[retlen]) {
634:     PetscAssertPointer(list[retlen], 1);
635:     PetscCheck(++retlen < 50, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "List argument appears to be wrong or have more than 50 entries");
636:   }
637:   PetscCheck(retlen > 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "List argument must have at least 2 entries: typename and type prefix");
638:   /* drop item name and prefix*/
639:   *len = retlen - 2;
640:   PetscFunctionReturn(PETSC_SUCCESS);
641: }

643: PetscErrorCode PetscOptionsEnum_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum currentvalue, PetscEnum *value, PetscBool *set)
644: {
645:   PetscInt  ntext = 0;
646:   PetscInt  tval;
647:   PetscBool tflg;

649:   PetscFunctionBegin;
650:   PetscAssertPointer(opt, 2);
651:   PetscAssertPointer(list, 5);
652:   PetscAssertPointer(value, 7);
653:   if (set) PetscAssertPointer(set, 8);
654:   PetscCall(GetListLength(list, &ntext));
655:   PetscCall(PetscOptionsEList_Private(PetscOptionsObject, opt, text, man, list, ntext, list[currentvalue], &tval, &tflg));
656:   /* with PETSC_USE_64BIT_INDICES sizeof(PetscInt) != sizeof(PetscEnum) */
657:   if (tflg) *value = (PetscEnum)tval;
658:   if (set) *set = tflg;
659:   PetscFunctionReturn(PETSC_SUCCESS);
660: }

662: PetscErrorCode PetscOptionsEnumArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char *const *list, PetscEnum value[], PetscInt *n, PetscBool *set)
663: {
664:   PetscInt    nlist  = 0;
665:   const char *prefix = PetscOptionsObject->prefix;

667:   PetscFunctionBegin;
668:   PetscAssertPointer(opt, 2);
669:   PetscAssertPointer(list, 5);
670:   PetscAssertPointer(value, 6);
671:   PetscAssertPointer(n, 7);
672:   PetscCheck(*n > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") must be > 0", *n);
673:   if (set) PetscAssertPointer(set, 8);
674:   PetscCall(GetListLength(list, &nlist));
675:   PetscCall(PetscOptionsGetEnumArray(PetscOptionsObject->options, prefix, opt, list, value, n, set));
676:   if (ShouldPrintHelp(PetscOptionsObject)) {
677:     const MPI_Comm comm = PetscOptionsObject->comm;
678:     const PetscInt nv   = *n;

680:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%s", Prefix(prefix), opt + 1, list[value[0]]));
681:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%s", list[value[i]]));
682:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (choose from)", text));
683:     for (PetscInt i = 0; i < nlist; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i]));
684:     PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man)));
685:   }
686:   PetscFunctionReturn(PETSC_SUCCESS);
687: }

689: PetscErrorCode PetscOptionsInt_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt currentvalue, PetscInt *value, PetscBool *set, PetscInt lb, PetscInt ub)
690: {
691:   const char        *prefix  = PetscOptionsObject->prefix;
692:   const PetscOptions options = PetscOptionsObject->options;
693:   PetscBool          wasset;

695:   PetscFunctionBegin;
696:   PetscAssertPointer(opt, 2);
697:   PetscAssertPointer(value, 6);
698:   if (set) PetscAssertPointer(set, 7);
699:   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, currentvalue, lb);
700:   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, currentvalue, ub);
701:   if (!PetscOptionsObject->count) {
702:     PetscOptionItem amsopt;

704:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
705:     PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
706:     *(PetscInt *)amsopt->data = currentvalue;

708:     PetscCall(PetscOptionsGetInt(options, prefix, opt, &currentvalue, &wasset));
709:     if (wasset) *(PetscInt *)amsopt->data = currentvalue;
710:   }
711:   PetscCall(PetscOptionsGetInt(options, prefix, opt, value, &wasset));
712:   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " less than allowed bound %" PetscInt_FMT, *value, lb);
713:   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %" PetscInt_FMT " greater than allowed bound %" PetscInt_FMT, *value, ub);
714:   if (set) *set = wasset;
715:   if (ShouldPrintHelp(PetscOptionsObject)) {
716:     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)));
717:   }
718:   PetscFunctionReturn(PETSC_SUCCESS);
719: }

721: PetscErrorCode PetscOptionsString_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], const char currentvalue[], char value[], size_t len, PetscBool *set)
722: {
723:   const char *prefix = PetscOptionsObject->prefix;
724:   PetscBool   lset;

726:   PetscFunctionBegin;
727:   PetscAssertPointer(opt, 2);
728:   PetscAssertPointer(value, 6);
729:   if (set) PetscAssertPointer(set, 8);
730:   if (!PetscOptionsObject->count) {
731:     PetscOptionItem amsopt;

733:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
734:     /* must use system malloc since SAWs may free this */
735:     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
736:   }
737:   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset));
738:   if (set) *set = lset;
739:   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)));
740:   PetscFunctionReturn(PETSC_SUCCESS);
741: }

743: PetscErrorCode PetscOptionsReal_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal currentvalue, PetscReal *value, PetscBool *set, PetscReal lb, PetscReal ub)
744: {
745:   const char        *prefix  = PetscOptionsObject->prefix;
746:   const PetscOptions options = PetscOptionsObject->options;
747:   PetscBool          wasset;

749:   PetscFunctionBegin;
750:   PetscAssertPointer(opt, 2);
751:   PetscAssertPointer(value, 6);
752:   if (set) PetscAssertPointer(set, 7);
753:   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g less than allowed bound %g", (double)currentvalue, (double)lb);
754:   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g greater than allowed bound %g", (double)currentvalue, (double)ub);
755:   if (!PetscOptionsObject->count) {
756:     PetscOptionItem amsopt;

758:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt));
759:     PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data));
760:     *(PetscReal *)amsopt->data = currentvalue;

762:     PetscCall(PetscOptionsGetReal(options, prefix, opt, &currentvalue, &wasset));
763:     if (wasset) *(PetscReal *)amsopt->data = currentvalue;
764:   }
765:   PetscCall(PetscOptionsGetReal(PetscOptionsObject->options, prefix, opt, value, &wasset));
766:   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g less than allowed bound %g", (double)*value, (double)lb);
767:   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g greater than allowed bound %g", (double)*value, (double)ub);
768:   if (set) *set = wasset;
769:   if (ShouldPrintHelp(PetscOptionsObject)) {
770:     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)));
771:   }
772:   PetscFunctionReturn(PETSC_SUCCESS);
773: }

775: PetscErrorCode PetscOptionsScalar_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar currentvalue, PetscScalar *value, PetscBool *set)
776: {
777:   PetscFunctionBegin;
778: #if !defined(PETSC_USE_COMPLEX)
779:   PetscCall(PetscOptionsReal(opt, text, man, currentvalue, value, set));
780: #else
781:   PetscCall(PetscOptionsGetScalar(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, set));
782: #endif
783:   PetscFunctionReturn(PETSC_SUCCESS);
784: }

786: PetscErrorCode PetscOptionsName_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
787: {
788:   const char *prefix = PetscOptionsObject->prefix;

790:   PetscFunctionBegin;
791:   PetscAssertPointer(opt, 2);
792:   PetscAssertPointer(flg, 5);
793:   if (!PetscOptionsObject->count) {
794:     PetscOptionItem amsopt;

796:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
797:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

799:     *(PetscBool *)amsopt->data = PETSC_FALSE;
800:   }
801:   PetscCall(PetscOptionsHasName(PetscOptionsObject->options, prefix, opt, flg));
802:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
803:   PetscFunctionReturn(PETSC_SUCCESS);
804: }

806: 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)
807: {
808:   const char *prefix = PetscOptionsObject->prefix;
809:   PetscBool   lset;

811:   PetscFunctionBegin;
812:   PetscAssertPointer(opt, 2);
813:   PetscAssertPointer(value, 7);
814:   if (set) PetscAssertPointer(set, 9);
815:   if (!PetscOptionsObject->count) {
816:     PetscOptionItem amsopt;

818:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_FLIST, &amsopt));
819:     /* must use system malloc since SAWs may free this */
820:     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
821:     amsopt->flist = list;
822:   }
823:   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset));
824:   if (set) *set = lset;
825:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall(PetscFunctionListPrintTypes(PetscOptionsObject->comm, stdout, Prefix(prefix), opt, ltext, man, list, currentvalue, lset ? value : currentvalue));
826:   PetscFunctionReturn(PETSC_SUCCESS);
827: }

829: #ifdef __cplusplus
830:   #include <type_traits>
831: #endif

833: 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)
834: {
835:   const char *prefix = PetscOptionsObject->prefix;
836:   PetscBool   lset;

838:   PetscFunctionBegin;
839:   PetscAssertPointer(opt, 2);
840:   PetscAssertPointer(value, 8);
841:   if (set) PetscAssertPointer(set, 9);
842:   if (!PetscOptionsObject->count) {
843:     PetscOptionItem amsopt;

845:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_ELIST, &amsopt));
846:     /* must use system malloc since SAWs may free this */
847:     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
848:     PetscCall(PetscStrNArrayallocpy(ntext, list, (char ***)&amsopt->list));
849:     PetscCheck(ntext <= CHAR_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of list entries %" PetscInt_FMT " > %d", ntext, CHAR_MAX);
850: #ifdef __cplusplus
851:     static_assert(std::is_same<typename std::decay<decltype(amsopt->nlist)>::type, char>::value, "");
852: #endif
853:     amsopt->nlist = (char)ntext;
854:   }
855:   PetscCall(PetscOptionsGetEList(PetscOptionsObject->options, prefix, opt, list, ntext, value, &lset));
856:   if (set) *set = lset;
857:   if (ShouldPrintHelp(PetscOptionsObject)) {
858:     const MPI_Comm comm = PetscOptionsObject->comm;

860:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <now %s : formerly %s> %s (choose one of)", Prefix(prefix), opt + 1, lset ? list[*value] : currentvalue, currentvalue, ltext));
861:     for (PetscInt i = 0; i < ntext; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i]));
862:     PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man)));
863:   }
864:   PetscFunctionReturn(PETSC_SUCCESS);
865: }

867: PetscErrorCode PetscOptionsBoolGroupBegin_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
868: {
869:   const char *prefix = PetscOptionsObject->prefix;

871:   PetscFunctionBegin;
872:   PetscAssertPointer(opt, 2);
873:   PetscAssertPointer(flg, 5);
874:   if (!PetscOptionsObject->count) {
875:     PetscOptionItem amsopt;

877:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
878:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

880:     *(PetscBool *)amsopt->data = PETSC_FALSE;
881:   }
882:   *flg = PETSC_FALSE;
883:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
884:   if (ShouldPrintHelp(PetscOptionsObject)) {
885:     const MPI_Comm comm = PetscOptionsObject->comm;

887:     PetscCall((*PetscHelpPrintf)(comm, "  Pick at most one of -------------\n"));
888:     PetscCall((*PetscHelpPrintf)(comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
889:   }
890:   PetscFunctionReturn(PETSC_SUCCESS);
891: }

893: PetscErrorCode PetscOptionsBoolGroup_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
894: {
895:   const char *prefix = PetscOptionsObject->prefix;

897:   PetscFunctionBegin;
898:   PetscAssertPointer(opt, 2);
899:   PetscAssertPointer(flg, 5);
900:   if (!PetscOptionsObject->count) {
901:     PetscOptionItem amsopt;

903:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
904:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

906:     *(PetscBool *)amsopt->data = PETSC_FALSE;
907:   }
908:   *flg = PETSC_FALSE;
909:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
910:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
911:   PetscFunctionReturn(PETSC_SUCCESS);
912: }

914: PetscErrorCode PetscOptionsBoolGroupEnd_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool *flg)
915: {
916:   const char *prefix = PetscOptionsObject->prefix;

918:   PetscFunctionBegin;
919:   PetscAssertPointer(opt, 2);
920:   PetscAssertPointer(flg, 5);
921:   if (!PetscOptionsObject->count) {
922:     PetscOptionItem amsopt;

924:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
925:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

927:     *(PetscBool *)amsopt->data = PETSC_FALSE;
928:   }
929:   *flg = PETSC_FALSE;
930:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
931:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
932:   PetscFunctionReturn(PETSC_SUCCESS);
933: }

935: PetscErrorCode PetscOptionsBool_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool currentvalue, PetscBool *flg, PetscBool *set)
936: {
937:   const char *prefix = PetscOptionsObject->prefix;
938:   PetscBool   iset;

940:   PetscFunctionBegin;
941:   PetscAssertPointer(opt, 2);
942:   PetscAssertPointer(flg, 6);
943:   if (set) PetscAssertPointer(set, 7);
944:   if (!PetscOptionsObject->count) {
945:     PetscOptionItem amsopt;

947:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL, &amsopt));
948:     PetscCall(PetscMalloc(sizeof(PetscBool), &amsopt->data));

950:     *(PetscBool *)amsopt->data = currentvalue;
951:   }
952:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, &iset));
953:   if (set) *set = iset;
954:   if (ShouldPrintHelp(PetscOptionsObject)) {
955:     const char *curvalue = PetscBools[currentvalue];

957:     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)));
958:   }
959:   PetscFunctionReturn(PETSC_SUCCESS);
960: }

962: PetscErrorCode PetscOptionsRealArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal value[], PetscInt *n, PetscBool *set)
963: {
964:   const char *prefix = PetscOptionsObject->prefix;

966:   PetscFunctionBegin;
967:   PetscAssertPointer(opt, 2);
968:   PetscAssertPointer(n, 6);
969:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
970:   if (*n) PetscAssertPointer(value, 5);
971:   if (set) PetscAssertPointer(set, 7);
972:   if (!PetscOptionsObject->count) {
973:     const PetscInt  nv = *n;
974:     PetscReal      *vals;
975:     PetscOptionItem amsopt;

977:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt));
978:     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
979:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
980:     amsopt->arraylength = nv;
981:     amsopt->data        = vals;
982:   }
983:   PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, prefix, opt, value, n, set));
984:   if (ShouldPrintHelp(PetscOptionsObject)) {
985:     const PetscInt nv   = *n;
986:     const MPI_Comm comm = PetscOptionsObject->comm;

988:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g", Prefix(prefix), opt + 1, (double)value[0]));
989:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g", (double)value[i]));
990:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
991:   }
992:   PetscFunctionReturn(PETSC_SUCCESS);
993: }

995: PetscErrorCode PetscOptionsScalarArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar value[], PetscInt *n, PetscBool *set)
996: {
997:   const char *prefix = PetscOptionsObject->prefix;

999:   PetscFunctionBegin;
1000:   PetscAssertPointer(opt, 2);
1001:   PetscAssertPointer(n, 6);
1002:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1003:   if (*n) PetscAssertPointer(value, 5);
1004:   if (set) PetscAssertPointer(set, 7);
1005:   if (!PetscOptionsObject->count) {
1006:     const PetscInt  nv = *n;
1007:     PetscOptionItem amsopt;
1008:     PetscScalar    *vals;

1010:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt));
1011:     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
1012:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1013:     amsopt->arraylength = nv;
1014:     amsopt->data        = vals;
1015:   }
1016:   PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1017:   if (ShouldPrintHelp(PetscOptionsObject)) {
1018:     const PetscInt nv   = *n;
1019:     const MPI_Comm comm = PetscOptionsObject->comm;

1021:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g+%gi", Prefix(prefix), opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0])));
1022:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i])));
1023:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1024:   }
1025:   PetscFunctionReturn(PETSC_SUCCESS);
1026: }

1028: PetscErrorCode PetscOptionsIntArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscInt value[], PetscInt *n, PetscBool *set)
1029: {
1030:   const char *prefix = PetscOptionsObject->prefix;

1032:   PetscFunctionBegin;
1033:   PetscAssertPointer(opt, 2);
1034:   PetscAssertPointer(n, 6);
1035:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1036:   if (*n) PetscAssertPointer(value, 5);
1037:   if (set) PetscAssertPointer(set, 7);
1038:   if (!PetscOptionsObject->count) {
1039:     const PetscInt  nv = *n;
1040:     PetscInt       *vals;
1041:     PetscOptionItem amsopt;

1043:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY, &amsopt));
1044:     PetscCall(PetscMalloc1(nv, &vals));
1045:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1046:     amsopt->arraylength = nv;
1047:     amsopt->data        = vals;
1048:   }
1049:   PetscCall(PetscOptionsGetIntArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1050:   if (ShouldPrintHelp(PetscOptionsObject)) {
1051:     const PetscInt nv   = *n;
1052:     const MPI_Comm comm = PetscOptionsObject->comm;

1054:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%" PetscInt_FMT, Prefix(prefix), opt + 1, value[0]));
1055:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%" PetscInt_FMT, value[i]));
1056:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1057:   }
1058:   PetscFunctionReturn(PETSC_SUCCESS);
1059: }

1061: PetscErrorCode PetscOptionsStringArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], char *value[], PetscInt *nmax, PetscBool *set)
1062: {
1063:   const char *prefix = PetscOptionsObject->prefix;

1065:   PetscFunctionBegin;
1066:   PetscAssertPointer(opt, 2);
1067:   PetscAssertPointer(nmax, 6);
1068:   PetscCheck(*nmax >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *nmax);
1069:   if (*nmax) PetscAssertPointer(value, 5);
1070:   if (set) PetscAssertPointer(set, 7);
1071:   if (!PetscOptionsObject->count) {
1072:     const PetscInt  nmaxv = *nmax;
1073:     PetscOptionItem amsopt;

1075:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt));
1076:     PetscCall(PetscMalloc1(nmaxv, (char **)&amsopt->data));
1077:     amsopt->arraylength = nmaxv;
1078:   }
1079:   PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, prefix, opt, value, nmax, set));
1080:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <string1,string2,...>: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
1081:   PetscFunctionReturn(PETSC_SUCCESS);
1082: }

1084: PetscErrorCode PetscOptionsBoolArray_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool value[], PetscInt *n, PetscBool *set)
1085: {
1086:   const char *prefix = PetscOptionsObject->prefix;

1088:   PetscFunctionBegin;
1089:   PetscAssertPointer(opt, 2);
1090:   PetscAssertPointer(n, 6);
1091:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1092:   if (*n) PetscAssertPointer(value, 5);
1093:   if (set) PetscAssertPointer(set, 7);
1094:   if (!PetscOptionsObject->count) {
1095:     const PetscInt  nv = *n;
1096:     PetscBool      *vals;
1097:     PetscOptionItem amsopt;

1099:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt));
1100:     PetscCall(PetscMalloc1(nv, &vals));
1101:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1102:     amsopt->arraylength = nv;
1103:     amsopt->data        = vals;
1104:   }
1105:   PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1106:   if (ShouldPrintHelp(PetscOptionsObject)) {
1107:     const PetscInt nv   = *n;
1108:     const MPI_Comm comm = PetscOptionsObject->comm;

1110:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%d", Prefix(prefix), opt + 1, value[0]));
1111:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%d", value[i]));
1112:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1113:   }
1114:   PetscFunctionReturn(PETSC_SUCCESS);
1115: }

1117: /*MC
1118:   PetscOptionsViewer - Gets a viewer appropriate for the type indicated by the user

1120:   Synopsis:
1121: #include <petscviewer.h>
1122:   PetscErrorCode PetscOptionsViewer(const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)

1124:   Logically Collective on the communicator passed in `PetscOptionsBegin()`

1126:   Input Parameters:
1127: + opt  - option name
1128: . text - short string that describes the option
1129: - man  - manual page with additional information on option

1131:   Output Parameters:
1132: + viewer - the viewer
1133: . format - the PetscViewerFormat requested by the user, pass `NULL` if not needed
1134: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

1136:   Level: beginner

1138:   Notes:
1139:   Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`

1141:   See `PetscOptionsGetViewer()` for the format of the supplied viewer and its options

1143: .seealso: `PetscOptionsGetViewer()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1144:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
1145:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
1146:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1147:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1148:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1149:           `PetscOptionsFList()`, `PetscOptionsEList()`
1150: M*/
1151: PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems *PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
1152: {
1153:   const MPI_Comm comm   = PetscOptionsObject->comm;
1154:   const char    *prefix = PetscOptionsObject->prefix;

1156:   PetscFunctionBegin;
1157:   PetscAssertPointer(opt, 2);
1158:   PetscAssertPointer(viewer, 5);
1159:   if (format) PetscAssertPointer(format, 6);
1160:   if (set) PetscAssertPointer(set, 7);
1161:   if (!PetscOptionsObject->count) {
1162:     PetscOptionItem amsopt;

1164:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
1165:     /* must use system malloc since SAWs may free this */
1166:     PetscCall(PetscStrdup("", (char **)&amsopt->data));
1167:   }
1168:   PetscCall(PetscOptionsGetViewer(comm, PetscOptionsObject->options, prefix, opt, viewer, format, set));
1169:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%s>: %s (%s)\n", Prefix(prefix), opt + 1, "", text, ManSection(man)));
1170:   PetscFunctionReturn(PETSC_SUCCESS);
1171: }