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 "GeneralReporter.h"
11#include "OptimizationData.h"
12
14
15template <typename T>
18{
19 InputParameters params = T::validParams();
20
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.");
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
62template <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
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
133template <typename T>
134void
136{
137 computeMisfit();
138 _objective_val = computeMisfitValue();
139}
140
141template <typename T>
142void
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 // If we are on the first var, make sure reset the simulation values so they aren't
171 // accumulated on repeated timesteps
172 if (var_index == 0)
173 _simulation_values[i] = 0.0;
174
175 const Point point(_measurement_xcoord[i], _measurement_ycoord[i], _measurement_zcoord[i]);
176 const Real val = sys.point_value(vnum, point, false);
177
178 _simulation_values[i] += weights[i] * val;
179 _misfit_values[i] = _simulation_values[i] - _measurement_values[i];
180 }
181 }
182 }
183}
184
185template <typename T>
186void
188{
189 std::string xName = this->template getParam<std::string>("file_xcoord");
190 std::string yName = this->template getParam<std::string>("file_ycoord");
191 std::string zName = this->template getParam<std::string>("file_zcoord");
192 std::string tName = this->template getParam<std::string>("file_time");
193 std::string valueName = this->template getParam<std::string>("file_value");
194 std::vector<std::string> weightNames =
195 this->template getParam<std::vector<std::string>>("file_variable_weights");
196
197 bool found_x = false;
198 bool found_y = false;
199 bool found_z = false;
200 bool found_t = false;
201 bool found_value = false;
202
203 MooseUtils::DelimitedFileReader reader(this->template getParam<FileName>("measurement_file"));
204 reader.read();
205
206 auto const & names = reader.getNames();
207 auto const & data = reader.getData();
208
209 const std::size_t rows = data[0].size();
210 for (std::size_t i = 0; i < names.size(); ++i)
211 {
212 // make sure all data columns have the same length
213 if (data[i].size() != rows)
214 this->paramError("file", "Mismatching column lengths in file");
215
216 if (names[i] == xName)
217 {
218 _measurement_xcoord = data[i];
219 found_x = true;
220 }
221 else if (names[i] == yName)
222 {
223 _measurement_ycoord = data[i];
224 found_y = true;
225 }
226 else if (names[i] == zName)
227 {
228 _measurement_zcoord = data[i];
229 found_z = true;
230 }
231 else if (names[i] == tName)
232 {
233 _measurement_time = data[i];
234 found_t = true;
235 }
236 else if (names[i] == valueName)
237 {
238 _measurement_values = data[i];
239 found_value = true;
240 }
241 else if (std::find(weightNames.begin(), weightNames.end(), names[i]) != weightNames.end())
242 {
243 _weight_names_weights_map.emplace(names[i],
244 &(this->template declareValueByName<std::vector<Real>>(
245 names[i], REPORTER_MODE_REPLICATED)));
246 _weight_names_weights_map[names[i]]->assign(data[i].begin(), data[i].end());
247 }
248 }
249
250 // check if all required columns were found
251 if (!found_x)
252 this->paramError(
253 "measurement_file", "Column with name '", xName, "' missing from measurement file");
254 if (!found_y)
255 this->paramError(
256 "measurement_file", "Column with name '", yName, "' missing from measurement file");
257 if (!found_z)
258 this->paramError(
259 "measurement_file", "Column with name '", zName, "' missing from measurement file");
260 if (!found_t)
261 _measurement_time.assign(rows, 0);
262 if (!found_value)
263 this->paramError(
264 "measurement_file", "Column with name '", valueName, "' missing from measurement file");
265 if (_weight_names_weights_map.size() != weightNames.size())
266 {
267 std::string out("\n Measurement file column names: ");
268 for (const auto & name : names)
269 out += " " + name;
270 out += "\n file_variable_weights names: ";
271 for (const auto & name : weightNames)
272 out += " " + name;
273 this->paramError(
274 "measurement_file",
275 "Not all of the file_variable_weights names were found in the measurement_file.",
276 out);
277 }
278}
279
280template <typename T>
281void
283{
284 if (!this->template getParam<std::vector<std::string>>("file_variable_weights").empty())
285 this->paramError(
286 "measurement_values",
287 "file_variable_weights cannot be used with measurement data read from the input "
288 "file, use measure_file input instead.");
289
290 for (const auto & p : this->template getParam<std::vector<Point>>("measurement_points"))
291 {
292 _measurement_xcoord.push_back(p(0));
293 _measurement_ycoord.push_back(p(1));
294 _measurement_zcoord.push_back(p(2));
295 }
296
297 if (this->isParamValid("measurement_times"))
298 _measurement_time = this->template getParam<std::vector<Real>>("measurement_times");
299 else
300 _measurement_time.assign(_measurement_xcoord.size(), 0.0);
301
302 if (this->isParamValid("measurement_values"))
303 _measurement_values = this->template getParam<std::vector<Real>>("measurement_values");
304 else
305 this->paramError("measurement_values", "Input file must contain measurement points and values");
306}
307
308template <typename T>
309void
311{
312 const std::size_t nvals = _measurement_values.size();
313 std::string msg = "";
314 if (_measurement_xcoord.size() != nvals)
315 msg += "x-coordinate data (" + std::to_string(_measurement_xcoord.size()) + "), ";
316 if (_measurement_ycoord.size() != nvals)
317 msg += "y-coordinate data (" + std::to_string(_measurement_ycoord.size()) + "), ";
318 if (_measurement_zcoord.size() != nvals)
319 msg += "z-coordinate data (" + std::to_string(_measurement_zcoord.size()) + "), ";
320 if (_measurement_time.size() != nvals)
321 msg += "time data (" + std::to_string(_measurement_time.size()) + "), ";
322 if (!msg.empty())
323 mooseError("Number of entries in ",
324 std::string(msg.begin(), msg.end() - 2),
325 " does not match number of entries in value data (",
326 std::to_string(nvals),
327 ").");
328}
329
330template <typename T>
331Real
333{
334 Real val = 0.0;
335 for (auto & misfit : _misfit_values)
336 val += misfit * misfit;
337
338 return val * 0.5;
339}
340
const Real p
const double T
void mooseError(Args &&... args)
registerMooseObject("OptimizationApp", OptimizationData)
const ReporterMode REPORTER_MODE_REPLICATED
const std::string name
Definition Setup.h:21
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::vector< std::string > & getNames() const
const std::vector< std::vector< T > > & getData() const
std::vector< std::vector< Real > * > _variable_weights
Weight names to reporter values.
std::vector< MooseVariableFieldBase * > _var_vec
variable
void readMeasurementsFromInput()
parse measurement data from input file
std::map< std::string, std::vector< Real > * > _weight_names_weights_map
Weight names to reporter values map created from input file.
static InputParameters validParams()
void readMeasurementsFromFile()
parse measurement data from csv file
void errorCheckDataSize()
helper to check data sizes
Real computeMisfitValue()
Compute half the sum of the misfit (squared) values.
void computeMisfit()
Compute misfit vectors from the simulations and measurement values.
OptimizationDataTempl(const InputParameters &parameters)
std::vector< Real > & _measurement_values
std::vector< Real > & _misfit_values
difference between simulation and measurement values at measurement xyzt
virtual void execute() override
std::vector< Real > & _measurement_xcoord