https://mooseframework.inl.gov
OptimizationData.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 
10 #include "GeneralReporter.h"
11 #include "OptimizationData.h"
12 
13 registerMooseObject("OptimizationApp", OptimizationData);
14 
15 template <typename T>
18 {
20 
21  params.addClassDescription(
22  "Reporter to hold measurement and simulation data for optimization problems");
23  params.addParam<std::vector<Real>>(
24  "measurement_values",
25  "Measurement values collected from locations given by measurement_points");
26  params.addParam<std::vector<Point>>("measurement_points",
27  "Point locations corresponding to each measurement value");
28  params.addParam<std::vector<Real>>("measurement_times",
29  "Times corresponding to each measurement value");
30 
31  params.addParam<FileName>("measurement_file",
32  "CSV file with measurement value and coordinates (value, x, y, z).");
33  params.addParam<std::string>(
34  "file_xcoord", "x", "x coordinate column name from measurement_file csv being read in.");
35  params.addParam<std::string>(
36  "file_ycoord", "y", "y coordinate column name from csv file being read in.");
37  params.addParam<std::string>(
38  "file_zcoord", "z", "z coordinate column name from csv file being read in.");
39  params.addParam<std::string>(
40  "file_time", "time", "time column name from csv file being read in.");
41  params.addParam<std::vector<std::string>>(
42  "file_variable_weights", {}, "variable weight column names from csv file being read in.");
43  params.addParam<std::string>(
44  "file_value", "value", "measurement value column name from csv file being read in.");
45 
46  params.addParam<std::vector<std::string>>(
47  "variable_weight_names",
48  "Vector of weight reporter names that will create a reporter to transfer weights into. The "
49  "ordering of these weight reporter names corresponds to the ordering used in variable.");
50  params.addParam<std::vector<VariableName>>(
51  "variable", "Vector of variable names to sample at measurement points.");
52  params.addParam<ReporterValueName>("objective_name",
53  "Name of reporter value defining the objective.");
54  params.addParamNamesToGroup("measurement_points measurement_values measurement_times",
55  "Input Measurement Data");
56  params.addParamNamesToGroup("measurement_file file_xcoord file_ycoord file_zcoord file_time "
57  "file_value file_variable_weights",
58  "File Measurement Data");
59  return params;
60 }
61 
62 template <typename T>
64  : T(parameters),
65  _measurement_xcoord(this->template declareValueByName<std::vector<Real>>(
66  "measurement_xcoord", REPORTER_MODE_REPLICATED)),
67  _measurement_ycoord(this->template declareValueByName<std::vector<Real>>(
68  "measurement_ycoord", REPORTER_MODE_REPLICATED)),
69  _measurement_zcoord(this->template declareValueByName<std::vector<Real>>(
70  "measurement_zcoord", REPORTER_MODE_REPLICATED)),
71  _measurement_time(this->template declareValueByName<std::vector<Real>>(
72  "measurement_time", REPORTER_MODE_REPLICATED)),
73  _measurement_values(this->template declareValueByName<std::vector<Real>>(
74  "measurement_values", REPORTER_MODE_REPLICATED)),
75  _simulation_values(this->template declareValueByName<std::vector<Real>>(
76  "simulation_values", REPORTER_MODE_REPLICATED)),
77  _misfit_values(this->template declareValueByName<std::vector<Real>>("misfit_values",
79  _objective_val(this->isParamSetByUser("objective_name")
80  ? this->template declareValueByName<Real>(
81  this->template getParam<ReporterValueName>("objective_name"),
83  : this->template declareUnusedValue<Real>())
84 {
85  // read in data
86  if (this->isParamValid("measurement_file") && this->isParamValid("measurement_points"))
87  mooseError("Input file can only define a single input for measurement data. Use only "
88  "measurement_file or measurement_points, but never both");
89  else if (this->isParamValid("measurement_file"))
91  else if (this->isParamValid("measurement_points"))
93 
94  _misfit_values.resize(_measurement_values.size());
95 
96  if (this->isParamValid("variable"))
97  {
98  std::vector<VariableName> var_names(
99  this->template getParam<std::vector<VariableName>>("variable"));
100  for (const auto & name : var_names)
101  _var_vec.push_back(&this->_fe_problem.getVariable(
102  this->_tid, name, Moose::VarKindType::VAR_ANY, Moose::VarFieldType::VAR_FIELD_STANDARD));
103  }
104  if (this->isParamValid("variable_weight_names"))
105  {
106  std::vector<std::string> weight_names(
107  this->template getParam<std::vector<std::string>>("variable_weight_names"));
108  for (const auto & name : weight_names)
109  {
110  if (_weight_names_weights_map.count(name) == 1)
111  {
113  }
114  else
115  {
116  // default is to create a new weight reporter and fill it with 1's
117  // these will be overwritten by a reporter transfer.
118  _variable_weights.push_back(
119  &this->template declareValueByName<std::vector<Real>>(name, REPORTER_MODE_REPLICATED));
120  _variable_weights.back()->assign(_measurement_xcoord.size(), 1);
121  }
122  }
123  }
124  if (this->isParamValid("variable") && this->isParamValid("variable_weight_names") &&
125  _variable_weights.size() != _var_vec.size())
126  {
127  this->paramError(
128  "variable_weight_names",
129  "The same number of names must be in both 'variable_weight_names' and 'variable'.");
130  }
131 }
132 
133 template <typename T>
134 void
136 {
137  computeMisfit();
138  _objective_val = computeMisfitValue();
139 }
140 
141 template <typename T>
142 void
144 {
145  if (_var_vec.empty())
146  return;
147 
148  // FIXME: This is basically copied from PointValue.
149  // Implementation can be improved using the functionality in PointSamplerBase,
150  // but this will require changes in MOOSE to work for reporters.
151 
152  const std::size_t nvals = _measurement_values.size();
153  _simulation_values.resize(nvals, 0.0);
154  _misfit_values.resize(nvals);
155 
156  errorCheckDataSize();
157  for (const auto var_index : make_range(_var_vec.size()))
158  {
159  const auto & sys = _var_vec[var_index]->sys().system();
160  const auto vnum = _var_vec[var_index]->number();
161  // A weight reporter is not automatically created and for those cases, we
162  // set the weight to 1.
163  std::vector<Real> weights(_variable_weights.empty()
164  ? std::vector<Real>(_measurement_xcoord.size(), 1)
165  : (*_variable_weights[var_index]));
166  for (const auto & i : make_range(nvals))
167  {
168  if (MooseUtils::absoluteFuzzyEqual(this->_t, _measurement_time[i]))
169  {
170  const Point point(_measurement_xcoord[i], _measurement_ycoord[i], _measurement_zcoord[i]);
171  const Real val = sys.point_value(vnum, point, false);
172 
173  _simulation_values[i] += weights[i] * val;
174  _misfit_values[i] = _simulation_values[i] - _measurement_values[i];
175  }
176  }
177  }
178 }
179 
180 template <typename T>
181 void
183 {
184  std::string xName = this->template getParam<std::string>("file_xcoord");
185  std::string yName = this->template getParam<std::string>("file_ycoord");
186  std::string zName = this->template getParam<std::string>("file_zcoord");
187  std::string tName = this->template getParam<std::string>("file_time");
188  std::string valueName = this->template getParam<std::string>("file_value");
189  std::vector<std::string> weightNames =
190  this->template getParam<std::vector<std::string>>("file_variable_weights");
191 
192  bool found_x = false;
193  bool found_y = false;
194  bool found_z = false;
195  bool found_t = false;
196  bool found_value = false;
197 
198  MooseUtils::DelimitedFileReader reader(this->template getParam<FileName>("measurement_file"));
199  reader.read();
200 
201  auto const & names = reader.getNames();
202  auto const & data = reader.getData();
203 
204  const std::size_t rows = data[0].size();
205  for (std::size_t i = 0; i < names.size(); ++i)
206  {
207  // make sure all data columns have the same length
208  if (data[i].size() != rows)
209  this->paramError("file", "Mismatching column lengths in file");
210 
211  if (names[i] == xName)
212  {
213  _measurement_xcoord = data[i];
214  found_x = true;
215  }
216  else if (names[i] == yName)
217  {
218  _measurement_ycoord = data[i];
219  found_y = true;
220  }
221  else if (names[i] == zName)
222  {
223  _measurement_zcoord = data[i];
224  found_z = true;
225  }
226  else if (names[i] == tName)
227  {
228  _measurement_time = data[i];
229  found_t = true;
230  }
231  else if (names[i] == valueName)
232  {
233  _measurement_values = data[i];
234  found_value = true;
235  }
236  else if (std::find(weightNames.begin(), weightNames.end(), names[i]) != weightNames.end())
237  {
238  _weight_names_weights_map.emplace(names[i],
239  &(this->template declareValueByName<std::vector<Real>>(
240  names[i], REPORTER_MODE_REPLICATED)));
241  _weight_names_weights_map[names[i]]->assign(data[i].begin(), data[i].end());
242  }
243  }
244 
245  // check if all required columns were found
246  if (!found_x)
247  this->paramError(
248  "measurement_file", "Column with name '", xName, "' missing from measurement file");
249  if (!found_y)
250  this->paramError(
251  "measurement_file", "Column with name '", yName, "' missing from measurement file");
252  if (!found_z)
253  this->paramError(
254  "measurement_file", "Column with name '", zName, "' missing from measurement file");
255  if (!found_t)
256  _measurement_time.assign(rows, 0);
257  if (!found_value)
258  this->paramError(
259  "measurement_file", "Column with name '", valueName, "' missing from measurement file");
260  if (_weight_names_weights_map.size() != weightNames.size())
261  {
262  std::string out("\n Measurement file column names: ");
263  for (const auto & name : names)
264  out += " " + name;
265  out += "\n file_variable_weights names: ";
266  for (const auto & name : weightNames)
267  out += " " + name;
268  this->paramError(
269  "measurement_file",
270  "Not all of the file_variable_weights names were found in the measurement_file.",
271  out);
272  }
273 }
274 
275 template <typename T>
276 void
278 {
279  if (!this->template getParam<std::vector<std::string>>("file_variable_weights").empty())
280  this->paramError(
281  "measurement_values",
282  "file_variable_weights cannot be used with measurement data read from the input "
283  "file, use measure_file input instead.");
284 
285  for (const auto & p : this->template getParam<std::vector<Point>>("measurement_points"))
286  {
287  _measurement_xcoord.push_back(p(0));
288  _measurement_ycoord.push_back(p(1));
289  _measurement_zcoord.push_back(p(2));
290  }
291 
292  if (this->isParamValid("measurement_times"))
293  _measurement_time = this->template getParam<std::vector<Real>>("measurement_times");
294  else
295  _measurement_time.assign(_measurement_xcoord.size(), 0.0);
296 
297  if (this->isParamValid("measurement_values"))
298  _measurement_values = this->template getParam<std::vector<Real>>("measurement_values");
299  else
300  this->paramError("measurement_values", "Input file must contain measurement points and values");
301 }
302 
303 template <typename T>
304 void
306 {
307  const std::size_t nvals = _measurement_values.size();
308  std::string msg = "";
309  if (_measurement_xcoord.size() != nvals)
310  msg += "x-coordinate data (" + std::to_string(_measurement_xcoord.size()) + "), ";
311  if (_measurement_ycoord.size() != nvals)
312  msg += "y-coordinate data (" + std::to_string(_measurement_ycoord.size()) + "), ";
313  if (_measurement_zcoord.size() != nvals)
314  msg += "z-coordinate data (" + std::to_string(_measurement_zcoord.size()) + "), ";
315  if (_measurement_time.size() != nvals)
316  msg += "time data (" + std::to_string(_measurement_time.size()) + "), ";
317  if (!msg.empty())
318  mooseError("Number of entries in ",
319  std::string(msg.begin(), msg.end() - 2),
320  " does not match number of entries in value data (",
321  std::to_string(nvals),
322  ").");
323 }
324 
325 template <typename T>
326 Real
328 {
329  Real val = 0.0;
330  for (auto & misfit : _misfit_values)
331  val += misfit * misfit;
332 
333  return val * 0.5;
334 }
335 
void errorCheckDataSize()
helper to check data sizes
std::vector< Real > & _measurement_values
bool absoluteFuzzyEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
std::vector< Real > & _measurement_xcoord
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void mooseError(Args &&... args)
virtual void execute() override
void readMeasurementsFromFile()
parse measurement data from csv file
OptimizationDataTempl(const InputParameters &parameters)
void readMeasurementsFromInput()
parse measurement data from input file
InputParameters validParams()
const std::string name
Definition: Setup.h:20
void computeMisfit()
Compute misfit vectors from the simulations and measurement values.
std::map< std::string, std::vector< Real > * > _weight_names_weights_map
Weight names to reporter values map created from input file.
std::vector< std::vector< Real > * > _variable_weights
Weight names to reporter values.
const std::vector< std::vector< T > > & getData() const
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
OStreamProxy out
IntRange< T > make_range(T beg, T end)
Real computeMisfitValue()
Compute half the sum of the misfit (squared) values.
void addClassDescription(const std::string &doc_string)
const ReporterMode REPORTER_MODE_REPLICATED
const std::vector< std::string > & getNames() const
std::vector< MooseVariableFieldBase * > _var_vec
variable
registerMooseObject("OptimizationApp", OptimizationData)
std::vector< Real > & _misfit_values
difference between simulation and measurement values at measurement xyzt
void addParamNamesToGroup(const std::string &space_delim_names, const std::string group_name)
static InputParameters validParams()