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: 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";

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

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

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

155: */
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];

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

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

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

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

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

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

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

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

261:   if (stopasking) {
262:     PetscOptionsPublish       = PETSC_FALSE;
263:     PetscOptionsObject->count = 0; //do not ask for same thing again
264:   }

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

273:     Collective

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

280:     Bugs:
281: .   Assumes process 0 of the given communicator has access to stdin

283: */
284: static PetscErrorCode PetscScanString(MPI_Comm comm, size_t n, char str[])
285: {
286:   PetscMPIInt rank, nm;

288:   PetscFunctionBegin;
289:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
290:   if (rank == 0) {
291:     char   c = (char)getchar();
292:     size_t i = 0;

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

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

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

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?

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

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

323: */
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;

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;

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;

362:           if (!value) break;
363:           PetscCall(PetscStrallocpy(value, &ivalue));

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;

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

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

503: PetscErrorCode PetscOptionsEnd_Private(PetscOptionItems PetscOptionsObject)
504: {
505:   PetscOptionItem next, last;

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

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

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;

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

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

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

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

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

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

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

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

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;

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

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;

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:   PetscCall(PetscOptionsGetEnumArray(PetscOptionsObject->options, prefix, opt, list, value, n, set));
674:   if (ShouldPrintHelp(PetscOptionsObject)) {
675:     const MPI_Comm comm = PetscOptionsObject->comm;
676:     const PetscInt nv   = *n;

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

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

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

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

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

719: PetscErrorCode PetscOptionsMPIInt_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscMPIInt currentvalue, PetscMPIInt *value, PetscBool *set, PetscMPIInt lb, PetscMPIInt ub)
720: {
721:   const char        *prefix  = PetscOptionsObject->prefix;
722:   const PetscOptions options = PetscOptionsObject->options;
723:   PetscBool          wasset;

725:   PetscFunctionBegin;
726:   PetscAssertPointer(opt, 2);
727:   PetscAssertPointer(value, 6);
728:   if (set) PetscAssertPointer(set, 7);
729:   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d less than allowed bound %d", currentvalue, lb);
730:   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %d greater than allowed bound %d", currentvalue, ub);
731:   if (!PetscOptionsObject->count) {
732:     PetscOptionItem amsopt;

734:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT, &amsopt));
735:     PetscCall(PetscMalloc(sizeof(PetscInt), &amsopt->data));
736:     *(PetscMPIInt *)amsopt->data = currentvalue;

738:     PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, &currentvalue, &wasset));
739:     if (wasset) *(PetscMPIInt *)amsopt->data = currentvalue;
740:   }
741:   PetscCall(PetscOptionsGetMPIInt(options, prefix, opt, value, &wasset));
742:   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d less than allowed bound %d", *value, lb);
743:   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %d greater than allowed bound %d", *value, ub);
744:   if (set) *set = wasset;
745:   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))); }
746:   PetscFunctionReturn(PETSC_SUCCESS);
747: }

749: PetscErrorCode PetscOptionsString_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], const char currentvalue[], char value[], size_t len, PetscBool *set)
750: {
751:   const char *prefix = PetscOptionsObject->prefix;
752:   PetscBool   lset;

754:   PetscFunctionBegin;
755:   PetscAssertPointer(opt, 2);
756:   PetscAssertPointer(value, 6);
757:   if (set) PetscAssertPointer(set, 8);
758:   if (!PetscOptionsObject->count) {
759:     PetscOptionItem amsopt;

761:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
762:     /* must use system malloc since SAWs may free this */
763:     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
764:   }
765:   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset));
766:   if (set) *set = lset;
767:   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)));
768:   PetscFunctionReturn(PETSC_SUCCESS);
769: }

771: PetscErrorCode PetscOptionsReal_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscReal currentvalue, PetscReal *value, PetscBool *set, PetscReal lb, PetscReal ub)
772: {
773:   const char        *prefix  = PetscOptionsObject->prefix;
774:   const PetscOptions options = PetscOptionsObject->options;
775:   PetscBool          wasset;

777:   PetscFunctionBegin;
778:   PetscAssertPointer(opt, 2);
779:   PetscAssertPointer(value, 6);
780:   if (set) PetscAssertPointer(set, 7);
781:   PetscCheck(currentvalue >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g less than allowed bound %g", (double)currentvalue, (double)lb);
782:   PetscCheck(currentvalue <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Current value %g greater than allowed bound %g", (double)currentvalue, (double)ub);
783:   if (!PetscOptionsObject->count) {
784:     PetscOptionItem amsopt;

786:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt));
787:     PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data));
788:     *(PetscReal *)amsopt->data = currentvalue;

790:     PetscCall(PetscOptionsGetReal(options, prefix, opt, &currentvalue, &wasset));
791:     if (wasset) *(PetscReal *)amsopt->data = currentvalue;
792:   }
793:   PetscCall(PetscOptionsGetReal(PetscOptionsObject->options, prefix, opt, value, &wasset));
794:   PetscCheck(!wasset || *value >= lb, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g less than allowed bound %g", (double)*value, (double)lb);
795:   PetscCheck(!wasset || *value <= ub, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Newly set value %g greater than allowed bound %g", (double)*value, (double)ub);
796:   if (set) *set = wasset;
797:   if (ShouldPrintHelp(PetscOptionsObject)) {
798:     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)));
799:   }
800:   PetscFunctionReturn(PETSC_SUCCESS);
801: }

803: PetscErrorCode PetscOptionsScalar_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscScalar currentvalue, PetscScalar *value, PetscBool *set)
804: {
805:   PetscFunctionBegin;
806: #if !defined(PETSC_USE_COMPLEX)
807:   PetscCall(PetscOptionsReal(opt, text, man, currentvalue, value, set));
808: #else
809:   PetscCall(PetscOptionsGetScalar(PetscOptionsObject->options, PetscOptionsObject->prefix, opt, value, set));
810: #endif
811:   PetscFunctionReturn(PETSC_SUCCESS);
812: }

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

818:   PetscFunctionBegin;
819:   PetscAssertPointer(opt, 2);
820:   PetscAssertPointer(flg, 5);
821:   if (!PetscOptionsObject->count) {
822:     PetscOptionItem amsopt;

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

827:     *(PetscBool *)amsopt->data = PETSC_FALSE;
828:   }
829:   PetscCall(PetscOptionsHasName(PetscOptionsObject->options, prefix, opt, flg));
830:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
831:   PetscFunctionReturn(PETSC_SUCCESS);
832: }

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

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

846:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_FLIST, &amsopt));
847:     /* must use system malloc since SAWs may free this */
848:     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
849:     amsopt->flist = list;
850:   }
851:   PetscCall(PetscOptionsGetString(PetscOptionsObject->options, prefix, opt, value, len, &lset));
852:   if (set) *set = lset;
853:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall(PetscFunctionListPrintTypes(PetscOptionsObject->comm, stdout, Prefix(prefix), opt, ltext, man, list, currentvalue, lset ? value : currentvalue));
854:   PetscFunctionReturn(PETSC_SUCCESS);
855: }

857: #ifdef __cplusplus
858:   #include <type_traits>
859: #endif

861: 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)
862: {
863:   const char *prefix = PetscOptionsObject->prefix;
864:   PetscBool   lset;

866:   PetscFunctionBegin;
867:   PetscAssertPointer(opt, 2);
868:   PetscAssertPointer(value, 8);
869:   if (set) PetscAssertPointer(set, 9);
870:   if (!PetscOptionsObject->count) {
871:     PetscOptionItem amsopt;

873:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, ltext, man, OPTION_ELIST, &amsopt));
874:     /* must use system malloc since SAWs may free this */
875:     PetscCall(PetscStrdup(currentvalue ? currentvalue : "", (char **)&amsopt->data));
876:     PetscCall(PetscStrNArrayallocpy(ntext, list, (char ***)&amsopt->list));
877:     PetscCheck(ntext <= CHAR_MAX, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of list entries %" PetscInt_FMT " > %d", ntext, CHAR_MAX);
878: #ifdef __cplusplus
879:     static_assert(std::is_same<typename std::decay<decltype(amsopt->nlist)>::type, char>::value, "");
880: #endif
881:     amsopt->nlist = (char)ntext;
882:   }
883:   PetscCall(PetscOptionsGetEList(PetscOptionsObject->options, prefix, opt, list, ntext, value, &lset));
884:   if (set) *set = lset;
885:   if (ShouldPrintHelp(PetscOptionsObject)) {
886:     const MPI_Comm comm = PetscOptionsObject->comm;

888:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <now %s : formerly %s> %s (choose one of)", Prefix(prefix), opt + 1, lset ? list[*value] : currentvalue, currentvalue, ltext));
889:     for (PetscInt i = 0; i < ntext; ++i) PetscCall((*PetscHelpPrintf)(comm, " %s", list[i]));
890:     PetscCall((*PetscHelpPrintf)(comm, " (%s)\n", ManSection(man)));
891:   }
892:   PetscFunctionReturn(PETSC_SUCCESS);
893: }

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

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

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

908:     *(PetscBool *)amsopt->data = PETSC_FALSE;
909:   }
910:   *flg = PETSC_FALSE;
911:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
912:   if (ShouldPrintHelp(PetscOptionsObject)) {
913:     const MPI_Comm comm = PetscOptionsObject->comm;

915:     PetscCall((*PetscHelpPrintf)(comm, "  Pick at most one of -------------\n"));
916:     PetscCall((*PetscHelpPrintf)(comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
917:   }
918:   PetscFunctionReturn(PETSC_SUCCESS);
919: }

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

925:   PetscFunctionBegin;
926:   PetscAssertPointer(opt, 2);
927:   PetscAssertPointer(flg, 5);
928:   if (!PetscOptionsObject->count) {
929:     PetscOptionItem amsopt;

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

934:     *(PetscBool *)amsopt->data = PETSC_FALSE;
935:   }
936:   *flg = PETSC_FALSE;
937:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
938:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
939:   PetscFunctionReturn(PETSC_SUCCESS);
940: }

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

946:   PetscFunctionBegin;
947:   PetscAssertPointer(opt, 2);
948:   PetscAssertPointer(flg, 5);
949:   if (!PetscOptionsObject->count) {
950:     PetscOptionItem amsopt;

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

955:     *(PetscBool *)amsopt->data = PETSC_FALSE;
956:   }
957:   *flg = PETSC_FALSE;
958:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, NULL));
959:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "    -%s%s: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
960:   PetscFunctionReturn(PETSC_SUCCESS);
961: }

963: PetscErrorCode PetscOptionsBool_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool currentvalue, PetscBool *flg, PetscBool *set)
964: {
965:   const char *prefix = PetscOptionsObject->prefix;
966:   PetscBool   iset;

968:   PetscFunctionBegin;
969:   PetscAssertPointer(opt, 2);
970:   PetscAssertPointer(flg, 6);
971:   if (set) PetscAssertPointer(set, 7);
972:   if (!PetscOptionsObject->count) {
973:     PetscOptionItem amsopt;

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

978:     *(PetscBool *)amsopt->data = currentvalue;
979:   }
980:   PetscCall(PetscOptionsGetBool(PetscOptionsObject->options, prefix, opt, flg, &iset));
981:   if (set) *set = iset;
982:   if (ShouldPrintHelp(PetscOptionsObject)) {
983:     const char *curvalue = PetscBools[currentvalue];

985:     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)));
986:   }
987:   PetscFunctionReturn(PETSC_SUCCESS);
988: }

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

994:   PetscFunctionBegin;
995:   PetscAssertPointer(opt, 2);
996:   PetscAssertPointer(n, 6);
997:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
998:   if (*n) PetscAssertPointer(value, 5);
999:   if (set) PetscAssertPointer(set, 7);
1000:   if (!PetscOptionsObject->count) {
1001:     const PetscInt  nv = *n;
1002:     PetscReal      *vals;
1003:     PetscOptionItem amsopt;

1005:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt));
1006:     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
1007:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1008:     amsopt->arraylength = nv;
1009:     amsopt->data        = vals;
1010:   }
1011:   PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1012:   if (ShouldPrintHelp(PetscOptionsObject)) {
1013:     const PetscInt nv   = *n;
1014:     const MPI_Comm comm = PetscOptionsObject->comm;

1016:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g", Prefix(prefix), opt + 1, (double)value[0]));
1017:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g", (double)value[i]));
1018:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1019:   }
1020:   PetscFunctionReturn(PETSC_SUCCESS);
1021: }

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

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

1038:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt));
1039:     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
1040:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1041:     amsopt->arraylength = nv;
1042:     amsopt->data        = vals;
1043:   }
1044:   PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1045:   if (ShouldPrintHelp(PetscOptionsObject)) {
1046:     const PetscInt nv   = *n;
1047:     const MPI_Comm comm = PetscOptionsObject->comm;

1049:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g+%gi", Prefix(prefix), opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0])));
1050:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i])));
1051:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1052:   }
1053:   PetscFunctionReturn(PETSC_SUCCESS);
1054: }

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

1060:   PetscFunctionBegin;
1061:   PetscAssertPointer(opt, 2);
1062:   PetscAssertPointer(n, 6);
1063:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1064:   if (*n) PetscAssertPointer(value, 5);
1065:   if (set) PetscAssertPointer(set, 7);
1066:   if (!PetscOptionsObject->count) {
1067:     const PetscInt  nv = *n;
1068:     PetscInt       *vals;
1069:     PetscOptionItem amsopt;

1071:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_INT_ARRAY, &amsopt));
1072:     PetscCall(PetscMalloc1(nv, &vals));
1073:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1074:     amsopt->arraylength = nv;
1075:     amsopt->data        = vals;
1076:   }
1077:   PetscCall(PetscOptionsGetIntArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1078:   if (ShouldPrintHelp(PetscOptionsObject)) {
1079:     const PetscInt nv   = *n;
1080:     const MPI_Comm comm = PetscOptionsObject->comm;

1082:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%" PetscInt_FMT, Prefix(prefix), opt + 1, value[0]));
1083:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%" PetscInt_FMT, value[i]));
1084:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1085:   }
1086:   PetscFunctionReturn(PETSC_SUCCESS);
1087: }

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

1093:   PetscFunctionBegin;
1094:   PetscAssertPointer(opt, 2);
1095:   PetscAssertPointer(nmax, 6);
1096:   PetscCheck(*nmax >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *nmax);
1097:   if (*nmax) PetscAssertPointer(value, 5);
1098:   if (set) PetscAssertPointer(set, 7);
1099:   if (!PetscOptionsObject->count) {
1100:     const PetscInt  nmaxv = *nmax;
1101:     PetscOptionItem amsopt;

1103:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt));
1104:     PetscCall(PetscMalloc1(nmaxv, (char **)&amsopt->data));
1105:     amsopt->arraylength = nmaxv;
1106:   }
1107:   PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, prefix, opt, value, nmax, set));
1108:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <string1,string2,...>: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
1109:   PetscFunctionReturn(PETSC_SUCCESS);
1110: }

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

1116:   PetscFunctionBegin;
1117:   PetscAssertPointer(opt, 2);
1118:   PetscAssertPointer(n, 6);
1119:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1120:   if (*n) PetscAssertPointer(value, 5);
1121:   if (set) PetscAssertPointer(set, 7);
1122:   if (!PetscOptionsObject->count) {
1123:     const PetscInt  nv = *n;
1124:     PetscBool      *vals;
1125:     PetscOptionItem amsopt;

1127:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt));
1128:     PetscCall(PetscMalloc1(nv, &vals));
1129:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1130:     amsopt->arraylength = nv;
1131:     amsopt->data        = vals;
1132:   }
1133:   PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1134:   if (ShouldPrintHelp(PetscOptionsObject)) {
1135:     const PetscInt nv   = *n;
1136:     const MPI_Comm comm = PetscOptionsObject->comm;

1138:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%d", Prefix(prefix), opt + 1, value[0]));
1139:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%d", value[i]));
1140:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1141:   }
1142:   PetscFunctionReturn(PETSC_SUCCESS);
1143: }

1145: /*MC
1146:   PetscOptionsViewer - Creates a viewer appropriate for the type indicated by the user

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

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

1154:   Input Parameters:
1155: + opt  - option name
1156: . text - short string that describes the option
1157: - man  - manual page with additional information on option

1159:   Output Parameters:
1160: + viewer - the viewer
1161: . format - the PetscViewerFormat requested by the user, pass `NULL` if not needed
1162: - set    - `PETSC_TRUE` if found, else `PETSC_FALSE`

1164:   Level: beginner

1166:   Notes:
1167:   Must be between a `PetscOptionsBegin()` and a `PetscOptionsEnd()`

1169:   See `PetscOptionsCreateViewer()` for the format of the supplied viewer and its options

1171: .seealso: `PetscOptionsCreateViewer()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`, `PetscOptionsGetInt()`,
1172:           `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
1173:           `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
1174:           `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
1175:           `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
1176:           `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
1177:           `PetscOptionsFList()`, `PetscOptionsEList()`
1178: M*/
1179: PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
1180: {
1181:   const MPI_Comm comm   = PetscOptionsObject->comm;
1182:   const char    *prefix = PetscOptionsObject->prefix;

1184:   PetscFunctionBegin;
1185:   PetscAssertPointer(opt, 2);
1186:   PetscAssertPointer(viewer, 5);
1187:   if (format) PetscAssertPointer(format, 6);
1188:   if (set) PetscAssertPointer(set, 7);
1189:   if (!PetscOptionsObject->count) {
1190:     PetscOptionItem amsopt;

1192:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
1193:     /* must use system malloc since SAWs may free this */
1194:     PetscCall(PetscStrdup("", (char **)&amsopt->data));
1195:   }
1196:   PetscCall(PetscOptionsCreateViewer(comm, PetscOptionsObject->options, prefix, opt, viewer, format, set));
1197:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%s>: %s (%s)\n", Prefix(prefix), opt + 1, "", text, ManSection(man)));
1198:   PetscFunctionReturn(PETSC_SUCCESS);
1199: }