3131#include < bout/output.hxx>
3232#include < bout/traits.hxx>
3333#include < bout/utils.hxx>
34+ #include < bout/bout_enum_class.hxx>
35+ #include < bout/bout_types.hxx>
36+ #include < bout/sys/expressionparser.hxx>
3437
3538#include " fieldgenerators.hxx"
3639
37- #include < algorithm>
3840#include < cmath>
39- #include < iterator>
4041#include < memory>
4142#include < string>
42- #include < vector>
4343
4444using bout::generator::Context;
4545
@@ -53,6 +53,8 @@ FieldGeneratorPtr generator(BoutReal* ptr) {
5353 return std::make_shared<FieldValuePtr>(ptr);
5454}
5555
56+ BOUT_ENUM_CLASS (GridVariableFunction, field3d, field2d, boutreal);
57+
5658namespace {
5759// / Provides a placeholder whose target can be changed after creation.
5860// / This enables recursive FieldGenerator expressions to be generated
@@ -89,41 +91,44 @@ class FieldIndirect : public FieldGenerator {
8991 FieldGeneratorPtr target;
9092};
9193
92- // Split a string on commas and trim whitespace from the results
93- auto trimsplit (const std::string& str) -> std::vector<std::string> {
94- auto split = strsplit (str, ' ,' );
95- std::vector<std::string> result{};
96- result.reserve (split.size ());
97- std::transform (split.begin (), split.end (), std::back_inserter (result),
98- [](const std::string& element) { return trim (element); });
99- return result;
100- }
101-
10294// Read variables from the grid file and make them available in expressions
10395template <class T >
104- auto read_grid_variables (FieldFactory& factory, Mesh& mesh, Options& options,
105- const std::string& option_name) {
106- const auto field_variables =
107- options[" input" ][option_name]
108- .doc (" Variables to read from the grid file and make available in expressions. "
109- " Comma-separated list of variable names" )
110- .withDefault <std::string>(" " );
111-
112- if (not field_variables.empty ()) {
96+ auto add_grid_variable (FieldFactory& factory, Mesh& mesh, const std::string& name) {
97+ T var;
98+ mesh.get (var, name);
99+ factory.addGenerator (name, std::make_shared<GridVariable<T>>(var, name));
100+ }
101+
102+ auto read_grid_variables (FieldFactory& factory, Mesh& mesh, Options& options) {
103+ auto & field_variables = options[" input" ][" grid_variables" ].doc (
104+ " Variables to read from the grid file and make available in expressions" );
105+
106+ for (const auto & [name, value] : field_variables) {
113107 if (not mesh.isDataSourceGridFile ()) {
114- throw BoutException (" A grid file ('mesh:file') is required for `input:{}` " ,
115- option_name );
108+ throw BoutException (
109+ " A grid file ('mesh:file') is required for `input:grid_variables` " );
116110 }
117111
118- for (const auto & name : trimsplit (field_variables)) {
119- if (not mesh.sourceHasVar (name)) {
120- const auto filename = Options::root ()[" mesh" ][" file" ].as <std::string>();
121- throw BoutException (" Grid file '{}' missing `{}` specified in `input:{}`" ,
122- filename, name, option_name);
123- }
124- T var;
112+ if (not mesh.sourceHasVar (name)) {
113+ const auto filename = Options::root ()[" mesh" ][" file" ].as <std::string>();
114+ throw BoutException (
115+ " Grid file '{}' missing `{}` specified in `input:grid_variables`" , filename,
116+ name);
117+ }
118+
119+ const auto func = value.as <GridVariableFunction>();
120+ switch (func) {
121+ case GridVariableFunction::field3d:
122+ add_grid_variable<Field3D>(factory, mesh, name);
123+ break ;
124+ case GridVariableFunction::field2d:
125+ add_grid_variable<Field2D>(factory, mesh, name);
126+ break ;
127+ case GridVariableFunction::boutreal:
128+ BoutReal var{};
125129 mesh.get (var, name);
126- factory.addGenerator (name, std::make_shared<GridVariable<T>>(var, name));
130+ factory.addGenerator (name, std::make_shared<FieldValue>(var));
131+ break ;
127132 }
128133 }
129134}
@@ -225,8 +230,7 @@ FieldFactory::FieldFactory(Mesh* localmesh, Options* opt)
225230 addGenerator (" where" , std::make_shared<FieldWhere>(nullptr , nullptr , nullptr ));
226231
227232 // Variables from the grid file
228- read_grid_variables<Field3D>(*this , *localmesh, nonconst_options, " read_Field3Ds" );
229- read_grid_variables<Field2D>(*this , *localmesh, nonconst_options, " read_Field2Ds" );
233+ read_grid_variables (*this , *localmesh, nonconst_options);
230234}
231235
232236Field2D FieldFactory::create2D (const std::string& value, const Options* opt,
0 commit comments