https://mooseframework.inl.gov
PiecewiseTabularInterface.C
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
11 #include "DelimitedFileReader.h"
12 #include "JSONFileReader.h"
13 
14 #include "libmesh/int_range.h"
15 
18 {
20 
21  // Parameters shared across all data input methods
22  MooseEnum axis("x=0 y=1 z=2");
23  params.addParam<MooseEnum>(
24  "axis", axis, "The axis used (x, y, or z) if this is to be a function of position");
25 
26  // Data from input file parameters
27  params.addParam<std::vector<Real>>("xy_data",
28  "All function data, supplied in abscissa, ordinate pairs");
29  params.addParam<std::vector<Real>>("x", "The abscissa values");
30  params.addParam<std::vector<Real>>("y", "The ordinate values");
31 
32  // Data from CSV file parameters
33  params.addParam<FileName>("data_file", "File holding CSV data");
34  params.addParam<unsigned int>("x_index_in_file", 0, "The abscissa index in the data file");
35  params.addParam<unsigned int>("y_index_in_file", 1, "The ordinate index in the data file");
36  params.addParam<std::string>(
37  "x_title", "The title of the column/row containing the x data in the data file");
38  params.addParam<std::string>(
39  "y_title", "The title of the column/row containing the y data in the data file");
40  params.addParam<bool>(
41  "xy_in_file_only", true, "If the data file only contains abscissa and ordinate data");
42  MooseEnum format("columns=0 rows=1", "rows");
43  params.addParam<MooseEnum>(
44  "format", format, "Format of csv data file that is in either in columns or rows");
45 
46  // Data from JSON parameters
47  params.addParam<UserObjectName>("json_uo", "JSONFileReader holding the data");
48  params.addParam<std::vector<std::string>>(
49  "x_keys", "Ordered vector of keys in the JSON tree to obtain the abscissa");
50  params.addParam<std::vector<std::string>>(
51  "y_keys", "Ordered vector of keys in the JSON tree to obtain the ordinate");
52 
53  params.addParamNamesToGroup("xy_data x y", "Data from input file");
54  params.addParamNamesToGroup(
55  "data_file x_index_in_file y_index_in_file x_title y_title xy_in_file_only format",
56  "Data from CSV file");
57  params.addParamNamesToGroup("json_uo x_keys y_keys", "Data from JSON");
58 
59  return params;
60 }
61 
63  std::vector<Real> & data_x,
64  std::vector<Real> & data_y)
65  : _has_axis(object.isParamValid("axis")),
66  _object(object),
67  _parameters(object.parameters()),
68  _data_x(data_x),
69  _data_y(data_y)
70 {
71  // determine function argument
72  if (_has_axis)
73  _axis = _parameters.get<MooseEnum>("axis");
74 
75  // Check all parameters for inconsistencies
76  if (_parameters.isParamValid("data_file") + _parameters.isParamValid("json_uo") +
78  _parameters.isParamValid("xy_data") >
79  1)
81  "Either 'data_file' or 'json_uo' or 'x' and 'y' or 'xy_data' must be specified "
82  "exclusively.");
83  if ((_parameters.isParamValid("x") + _parameters.isParamValid("y")) % 2 != 0)
85  "Both 'x' and 'y' parameters or neither (for another input method) must be specified");
86  if (!_parameters.isParamValid("data_file") &&
87  (_parameters.isParamSetByUser("x_index_in_file") ||
88  _parameters.isParamSetByUser("y_index_in_file") || _parameters.isParamValid("x_title") ||
89  _parameters.isParamValid("y_title") || _parameters.isParamSetByUser("xy_in_file_only") ||
90  _parameters.isParamSetByUser("format")))
92  "A parameter was passed for an option using data from a CSV file but the "
93  "'data_file' parameter has not been set. This is not allowed. Please check the parameter "
94  "groups in the documentation for the list of parameters for each data input method.");
95  if (!_parameters.isParamValid("json_uo") &&
96  (_parameters.isParamValid("x_keys") || _parameters.isParamValid("y_keys")))
98  "A parameter was passed for a JSON input option but the 'json_uo' parameter has not "
99  "been set. This is not allowed. Please check the parameter groups in the "
100  "documentation for the list of parameters for each data input method.");
101 }
102 
103 void
105 {
106  // Input parameters
107  const auto & data_file_name = _parameters.get<FileName>("data_file");
108  const MooseEnum & format = _parameters.get<MooseEnum>("format");
109 
110  // xy_in_file_only does not make sense here as it restricts the file to exactly
111  // two cows/columns, which is not a likely scenario when looking up data by name.
112  // A wrong 'format' parameter would be caught by the failing name resolution anyways.
113  bool xy_only = _parameters.get<bool>("xy_in_file_only");
114  if (_parameters.isParamValid("x_title") || _parameters.isParamValid("y_title"))
115  {
116  if (_parameters.isParamSetByUser("xy_in_file_only") && xy_only)
118  "xy_in_file_only",
119  "When accessing data through 'x_title' or 'y_title' this parameter should not be used");
120  else
121  xy_only = false;
122  }
123 
124  // Read the data from CSV file
125  MooseUtils::DelimitedFileReader reader(data_file_name, &comm);
127  reader.setComment("#");
128  reader.read();
129 
130  const auto & columns = reader.getNames();
131  const auto & data = reader.getData();
132 
133  if (data.size() > 2 && xy_only)
134  _object.mooseError("In ",
135  _object.name(),
136  ": Read more than two ",
137  format,
138  " of data from file '",
139  data_file_name,
140  "'. Did you mean to use \"format = ",
141  format == "columns" ? "rows" : "columns",
142  "\" or set \"xy_in_file_only\" to false?");
143 
144  unsigned int x_index = libMesh::invalid_uint;
145  unsigned int y_index = libMesh::invalid_uint;
146  const auto setIndex = [&](unsigned int & index, const std::string & prefix)
147  {
148  if (_parameters.isParamValid(prefix + "_title"))
149  {
150  const auto name = _parameters.get<std::string>(prefix + "_title");
151  for (const auto i : index_range(columns))
152  if (columns[i] == name)
153  index = i;
154 
155  if (index == libMesh::invalid_uint)
156  _parameters.paramError(prefix + "_title",
157  "None of the ",
158  format,
159  " in the data file has the title '",
160  name,
161  "'.");
162  }
163  else
164  index = _parameters.get<unsigned int>(prefix + "_index_in_file");
165 
166  if (index >= data.size())
167  _parameters.paramError(prefix + "_index_in_file",
168  "Index out-of-range of the available data in '",
169  data_file_name,
170  "', which contains ",
171  data.size(),
172  " ",
173  format,
174  " of data.");
175  };
176 
177  setIndex(x_index, "x");
178  setIndex(y_index, "y");
179 
180  if (x_index == y_index)
181  _object.mooseError("In ",
182  _object.name(),
183  ": 'x_index_in_file' and 'y_index_in_file' are set to the same value.");
184 
185  // Update the input vectors to contained the desired data
186  _data_x = reader.getData(x_index);
187  _data_y = reader.getData(y_index);
188 
189  // Size mismatch error
190  if (_data_x.size() != _data_y.size())
191  _object.mooseError("In ", _object.name(), ": Lengths of x and y data do not match.");
192 
193  _raw_data_loaded = true;
194 }
195 
196 void
198 {
199  if (!_parameters.isParamValid("x_keys"))
200  _object.mooseError("Missing 'x_keys' parameters for loading data from JSON");
201  if (!_parameters.isParamValid("y_keys"))
202  _object.mooseError("Missing 'y_keys' parameters for loading data from JSON");
203  json_uo.getVector<Real>(_parameters.get<std::vector<std::string>>("x_keys"), _data_x);
204  json_uo.getVector<Real>(_parameters.get<std::vector<std::string>>("y_keys"), _data_y);
205  _raw_data_loaded = true;
206 
207  // Size mismatch error
208  if (_data_x.size() != _data_y.size())
210  "Lengths of x (", _data_x.size(), ") and y (", _data_y.size(), ") data do not match.");
211 }
212 
213 void
215 {
216  _data_x = _parameters.get<std::vector<Real>>("x");
217  _data_y = _parameters.get<std::vector<Real>>("y");
218  _raw_data_loaded = true;
219 }
220 
221 void
223 {
224  const auto & xy = _parameters.get<std::vector<Real>>("xy_data");
225  const auto xy_size = xy.size();
226  if (xy_size % 2 != 0)
228  "In ", _object.name(), ": Length of data provided in 'xy_data' must be a multiple of 2.");
229 
230  const auto data_size = xy_size / 2;
231  _data_x.resize(data_size);
232  _data_y.resize(data_size);
233  for (const auto i : make_range(data_size))
234  {
235  _data_x[i] = xy[2 * i];
236  _data_y[i] = xy[2 * i + 1];
237  }
238  _raw_data_loaded = true;
239 }
std::string name(const ElemQuality q)
static InputParameters validParams()
const unsigned int invalid_uint
void setComment(const std::string &value)
std::vector< std::pair< R1, R2 > > get(const std::string &param1, const std::string &param2) const
Combine two vector parameters into a single vector of pairs.
User object that reads a JSON file and makes its data available to other objects. ...
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
InputParameters emptyInputParameters()
void buildFromFile(const libMesh::Parallel::Communicator &comm)
Reads data from supplied CSV file.
std::vector< Real > & _data_x
raw function data as read
void paramError(const std::string &param, Args... args) const
Emits a parameter error prefixed with the parameter location and object information if available...
const std::string & name() const
Get the name of the class.
Definition: MooseBase.h:103
Every object that can be built by the factory should be derived from this class.
Definition: MooseObject.h:28
PiecewiseTabularInterface(const MooseObject &object, std::vector< Real > &data_x, std::vector< Real > &data_y)
void getVector(const std::string &vector_name, std::vector< T > &vector_to_fill) const
Getter for vector values.
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type It sho...
Definition: MooseEnum.h:33
void read()
Perform the actual data reading.
const std::vector< std::vector< T > > & getData() const
Return the rows/columns of data.
bool isParamSetByUser(const std::string &name) const
Method returns true if the parameter was set by the user.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
void buildFromXandY()
Builds data from &#39;x&#39; and &#39;y&#39; parameters.
Utility class for reading delimited data (e.g., CSV data).
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:271
const InputParameters & _parameters
Parameters supplied to the object.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object...
unsigned int _axis
if _has_axis is true point component to use as function argument, otherwise use t ...
const MooseObject & _object
The object.
const std::vector< std::string > & getNames() const
Return the column/row names.
void buildFromXY()
Builds data from &#39;xy_data&#39; parameter.
bool _raw_data_loaded
Boolean to keep track of whether the data has been loaded.
auto index_range(const T &sizable)
void buildFromJSON(const JSONFileReader &json_uo)
Reads data from supplied JSON reader.
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
This method takes a space delimited list of parameter names and adds them to the specified group name...
bool isParamValid(const std::string &name) const
This method returns parameters that have been initialized in one fashion or another, i.e.