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