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:   /* "-help sec1,sec2,..." restricts the help output to the blocks whose manual section is one of those listed;
 53:      a block with no manual section is never selected */
 54:   PetscCall(PetscOptionsHelpPrintable_Internal(PetscOptionsObject->options, mansec, &PetscOptionsObject->printhelp));
 55:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "----------------------------------------\n%s:\n", title));
 56:   PetscFunctionReturn(PETSC_SUCCESS);
 57: }

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

 67:   PetscFunctionBegin;
 68:   PetscAssertPointer(PetscOptionsObject, 2);
 70:   PetscOptionsObject->object         = obj;
 71:   PetscOptionsObject->alreadyprinted = obj->optionsprinted;

 73:   PetscCall(PetscStrcmp(obj->description, obj->class_name, &flg));
 74:   if (flg) PetscCall(PetscSNPrintf(title, sizeof(title), "%s options", obj->class_name));
 75:   else PetscCall(PetscSNPrintf(title, sizeof(title), "%s (%s) options", obj->description, obj->class_name));
 76:   PetscCall(PetscOptionsBegin_Private(PetscOptionsObject, obj->comm, obj->prefix, title, obj->mansec));
 77:   PetscFunctionReturn(PETSC_SUCCESS);
 78: }

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

 87:   PetscFunctionBegin;
 88:   PetscCall(PetscOptionsValidKey(opt, &valid));
 89:   PetscCheck(valid, PETSC_COMM_WORLD, PETSC_ERR_ARG_INCOMP, "The option '%s' is not a valid key", opt);

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

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

101:   {
102:     PetscOptionItem cur = PetscOptionsObject->next;

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

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

117:   PetscFunctionBegin;
118:   if (s) {
119:     size_t len;

121:     PetscCall(PetscStrlen(s, &len));
122:     tmp = (char *)malloc((len + 1) * sizeof(*tmp));
123:     PetscCheck(tmp, PETSC_COMM_SELF, PETSC_ERR_MEM, "No memory to duplicate string");
124:     PetscCall(PetscArraycpy(tmp, s, len + 1));
125:   }
126:   *t = tmp;
127:   PetscFunctionReturn(PETSC_SUCCESS);
128: }

130: #if PetscDefined(HAVE_SAWS)
131: #include <petscviewersaws.h>

133: static int count = 0;

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

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

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

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

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

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

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

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

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

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

245:   /* wait until accessor has unlocked the memory */
246:   PetscCallSAWs(SAWs_Push_Header, "index.html", OptionsHeader);
247:   PetscCallSAWs(SAWs_Push_Body, "index.html", 2, OptionsBodyBottom);
248:   PetscCall(PetscSAWsBlock());
249:   PetscCallSAWs(SAWs_Pop_Header, "index.html");
250:   PetscCallSAWs(SAWs_Pop_Body, "index.html", 2);

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

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

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

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

275:     Collective

277:    Input Parameters:
278: +     commm - communicator for the broadcast, must be PETSC_COMM_WORLD
279: .     n - length of the string, must be the same on all processes
280: -     str - location to store input

282:     Bugs:
283: .   Assumes process 0 of the given communicator has access to stdin

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

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

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

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

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

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

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

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

325: */
326: static PetscErrorCode PetscOptionsGetFromTextInput(PetscOptionItems PetscOptionsObject)
327: {
328:   PetscOptionItem next = PetscOptionsObject->next;
329:   char            str[512];
330:   PetscBool       bid;
331:   PetscReal       ir, *valr;
332:   PetscInt       *vald;

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

356:         next->set = PETSC_TRUE;
357:         value     = str;
358:         PetscCall(PetscTokenCreate(value, ',', &token));
359:         PetscCall(PetscTokenFind(token, &value));
360:         while (n < nmax) {
361:           char    *ivalue;
362:           PetscInt i;

364:           if (!value) break;
365:           PetscCall(PetscStrallocpy(value, &ivalue));

367:           /* look for form  d-D where d and D are integers */
368:           foundrange = PETSC_FALSE;
369:           PetscCall(PetscStrlen(ivalue, &len));
370:           if (ivalue[0] == '-') i = 2;
371:           else i = 1;
372:           for (; i < (PetscInt)len; i++) {
373:             if (ivalue[i] == '-') {
374:               PetscCheck(i != (PetscInt)(len - 1), PETSC_COMM_SELF, PETSC_ERR_USER, "Error in %" PetscInt_FMT "-th array entry %s", n, ivalue);
375:               ivalue[i] = 0;
376:               PetscCall(PetscOptionsStringToInt(ivalue, &start));
377:               PetscCall(PetscOptionsStringToInt(ivalue + i + 1, &end));
378:               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);
379:               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);
380:               for (; start < end; start++) {
381:                 *dvalue = start;
382:                 dvalue++;
383:                 n++;
384:               }
385:               foundrange = PETSC_TRUE;
386:               break;
387:             }
388:           }
389:           if (!foundrange) {
390:             PetscCall(PetscOptionsStringToInt(ivalue, dvalue));
391:             dvalue++;
392:             n++;
393:           }
394:           PetscCall(PetscFree(ivalue));
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 (PetscInt 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:         const 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_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);
437:   #else
438:         long lid;
439:         sscanf(str, "%ld", &lid);
440:         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);
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 PetscDefined(USE_REAL_SINGLE)
452:         sscanf(str, "%e", &ir);
453:   #elif PetscDefined(USE_REAL___FP16)
454:         float irtemp;
455:         sscanf(str, "%e", &irtemp);
456:         ir = irtemp;
457:   #elif PetscDefined(USE_REAL_DOUBLE)
458:         sscanf(str, "%le", &ir);
459:   #elif PetscDefined(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 PetscDefined(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), "%" PetscInt_FMT, ((PetscInt *)data)[0]));
550:         for (size_t j = 1; j < arraylength; ++j) {
551:           PetscCall(PetscSNPrintf(tmp, PETSC_STATIC_ARRAY_LENGTH(tmp), "%" PetscInt_FMT, ((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), "%" PetscInt_FMT, *(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[(int)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:   const PetscInt nin = *n;
676:   PetscCall(PetscOptionsGetEnumArray(PetscOptionsObject->options, prefix, opt, list, value, n, set));
677:   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
678:     const MPI_Comm comm = PetscOptionsObject->comm;
679:     const PetscInt nv   = *n;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

789:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL, &amsopt));
790:     PetscCall(PetscMalloc(sizeof(PetscReal), &amsopt->data));
791:     *(PetscReal *)amsopt->data = currentvalue;

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

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

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

821:   PetscFunctionBegin;
822:   PetscAssertPointer(opt, 2);
823:   PetscAssertPointer(flg, 5);
824:   if (!PetscOptionsObject->count) {
825:     PetscOptionItem amsopt;

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

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

837: 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)
838: {
839:   const char *prefix = PetscOptionsObject->prefix;
840:   PetscBool   lset;

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

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

860: #if defined(__cplusplus)
861:   #include <type_traits>
862: #endif

864: 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)
865: {
866:   const char *prefix = PetscOptionsObject->prefix;
867:   PetscBool   lset;

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

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

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

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

902:   PetscFunctionBegin;
903:   PetscAssertPointer(opt, 2);
904:   PetscAssertPointer(flg, 5);
905:   if (!PetscOptionsObject->count) {
906:     PetscOptionItem amsopt;

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

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

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

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

928:   PetscFunctionBegin;
929:   PetscAssertPointer(opt, 2);
930:   PetscAssertPointer(flg, 5);
931:   if (!PetscOptionsObject->count) {
932:     PetscOptionItem amsopt;

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

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

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

949:   PetscFunctionBegin;
950:   PetscAssertPointer(opt, 2);
951:   PetscAssertPointer(flg, 5);
952:   if (!PetscOptionsObject->count) {
953:     PetscOptionItem amsopt;

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

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

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

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

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

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

988:     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)));
989:   }
990:   PetscFunctionReturn(PETSC_SUCCESS);
991: }

993: PetscErrorCode PetscOptionsBool3_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscBool3 currentvalue, PetscBool3 *flg, PetscBool *set)
994: {
995:   const char *prefix = PetscOptionsObject->prefix;
996:   PetscBool   iset;

998:   PetscFunctionBegin;
999:   PetscAssertPointer(opt, 2);
1000:   PetscAssertPointer(flg, 6);
1001:   if (set) PetscAssertPointer(set, 7);
1002:   PetscCall(PetscOptionsGetBool3(PetscOptionsObject->options, prefix, opt, flg, &iset));
1003:   if (set) *set = iset;
1004:   if (ShouldPrintHelp(PetscOptionsObject)) {
1005:     const char *curvalue = PetscBool3s[currentvalue];

1007:     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)));
1008:   }
1009:   PetscFunctionReturn(PETSC_SUCCESS);
1010: }

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

1016:   PetscFunctionBegin;
1017:   PetscAssertPointer(opt, 2);
1018:   PetscAssertPointer(n, 6);
1019:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1020:   if (*n) PetscAssertPointer(value, 5);
1021:   if (set) PetscAssertPointer(set, 7);
1022:   if (!PetscOptionsObject->count) {
1023:     const PetscInt  nv = *n;
1024:     PetscReal      *vals;
1025:     PetscOptionItem amsopt;

1027:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_REAL_ARRAY, &amsopt));
1028:     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
1029:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1030:     amsopt->arraylength = nv;
1031:     amsopt->data        = vals;
1032:   }
1033:   const PetscInt nin = *n;
1034:   PetscCall(PetscOptionsGetRealArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1035:   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
1036:     const PetscInt nv   = *n;
1037:     const MPI_Comm comm = PetscOptionsObject->comm;

1039:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g", Prefix(prefix), opt + 1, (double)value[0]));
1040:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g", (double)value[i]));
1041:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1042:   }
1043:   PetscFunctionReturn(PETSC_SUCCESS);
1044: }

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

1050:   PetscFunctionBegin;
1051:   PetscAssertPointer(opt, 2);
1052:   PetscAssertPointer(n, 6);
1053:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1054:   if (*n) PetscAssertPointer(value, 5);
1055:   if (set) PetscAssertPointer(set, 7);
1056:   if (!PetscOptionsObject->count) {
1057:     const PetscInt  nv = *n;
1058:     PetscOptionItem amsopt;
1059:     PetscScalar    *vals;

1061:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_SCALAR_ARRAY, &amsopt));
1062:     PetscCall(PetscMalloc(nv * sizeof(*vals), &vals));
1063:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1064:     amsopt->arraylength = nv;
1065:     amsopt->data        = vals;
1066:   }
1067:   const PetscInt nin = *n;
1068:   PetscCall(PetscOptionsGetScalarArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1069:   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
1070:     const PetscInt nv   = *n;
1071:     const MPI_Comm comm = PetscOptionsObject->comm;

1073:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%g+%gi", Prefix(prefix), opt + 1, (double)PetscRealPart(value[0]), (double)PetscImaginaryPart(value[0])));
1074:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%g+%gi", (double)PetscRealPart(value[i]), (double)PetscImaginaryPart(value[i])));
1075:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1076:   }
1077:   PetscFunctionReturn(PETSC_SUCCESS);
1078: }

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

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

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

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

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

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

1128:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING_ARRAY, &amsopt));
1129:     PetscCall(PetscMalloc1(nmaxv, (char **)&amsopt->data));
1130:     amsopt->arraylength = nmaxv;
1131:   }
1132:   const PetscInt nin = *nmax;
1133:   PetscCall(PetscOptionsGetStringArray(PetscOptionsObject->options, prefix, opt, value, nmax, set));
1134:   if (ShouldPrintHelp(PetscOptionsObject) && nin) PetscCall((*PetscHelpPrintf)(PetscOptionsObject->comm, "  -%s%s: <string1,string2,...>: %s (%s)\n", Prefix(prefix), opt + 1, text, ManSection(man)));
1135:   PetscFunctionReturn(PETSC_SUCCESS);
1136: }

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

1142:   PetscFunctionBegin;
1143:   PetscAssertPointer(opt, 2);
1144:   PetscAssertPointer(n, 6);
1145:   PetscCheck(*n >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "n (%" PetscInt_FMT ") cannot be negative", *n);
1146:   if (*n) PetscAssertPointer(value, 5);
1147:   if (set) PetscAssertPointer(set, 7);
1148:   if (!PetscOptionsObject->count) {
1149:     const PetscInt  nv = *n;
1150:     PetscBool      *vals;
1151:     PetscOptionItem amsopt;

1153:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_BOOL_ARRAY, &amsopt));
1154:     PetscCall(PetscMalloc1(nv, &vals));
1155:     for (PetscInt i = 0; i < nv; ++i) vals[i] = value[i];
1156:     amsopt->arraylength = nv;
1157:     amsopt->data        = vals;
1158:   }
1159:   const PetscInt nin = *n;
1160:   PetscCall(PetscOptionsGetBoolArray(PetscOptionsObject->options, prefix, opt, value, n, set));
1161:   if (ShouldPrintHelp(PetscOptionsObject) && nin) {
1162:     const PetscInt nv   = *n;
1163:     const MPI_Comm comm = PetscOptionsObject->comm;

1165:     PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%d", Prefix(prefix), opt + 1, value[0]));
1166:     for (PetscInt i = 1; i < nv; ++i) PetscCall((*PetscHelpPrintf)(comm, ",%d", value[i]));
1167:     PetscCall((*PetscHelpPrintf)(comm, ">: %s (%s)\n", text, ManSection(man)));
1168:   }
1169:   PetscFunctionReturn(PETSC_SUCCESS);
1170: }

1172: PetscErrorCode PetscOptionsViewer_Private(PetscOptionItems PetscOptionsObject, const char opt[], const char text[], const char man[], PetscViewer *viewer, PetscViewerFormat *format, PetscBool *set)
1173: {
1174:   const MPI_Comm comm   = PetscOptionsObject->comm;
1175:   const char    *prefix = PetscOptionsObject->prefix;

1177:   PetscFunctionBegin;
1178:   PetscAssertPointer(opt, 2);
1179:   PetscAssertPointer(viewer, 5);
1180:   if (format) PetscAssertPointer(format, 6);
1181:   if (set) PetscAssertPointer(set, 7);
1182:   if (!PetscOptionsObject->count) {
1183:     PetscOptionItem amsopt;

1185:     PetscCall(PetscOptionItemCreate_Private(PetscOptionsObject, opt, text, man, OPTION_STRING, &amsopt));
1186:     /* must use system malloc since SAWs may free this */
1187:     PetscCall(PetscStrdup("", (char **)&amsopt->data));
1188:   }
1189:   PetscCall(PetscOptionsCreateViewer(comm, PetscOptionsObject->options, prefix, opt, viewer, format, set));
1190:   if (ShouldPrintHelp(PetscOptionsObject)) PetscCall((*PetscHelpPrintf)(comm, "  -%s%s: <%s>: %s (%s)\n", Prefix(prefix), opt + 1, "", text, ManSection(man)));
1191:   PetscFunctionReturn(PETSC_SUCCESS);
1192: }