https://mooseframework.inl.gov
NearestReporterCoordinatesFunction.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 
13 
16 {
18  params.addClassDescription(
19  "This Function finds the nearest point in the specified vectors of coordinates and returns "
20  "the values specified in the vector of values at the index of the nearest point. All the "
21  "vectors must be specified using either vector postprocessors or reporter vectors. This "
22  "function interpolates linearly in time with transient data.");
23  params.addParam<ReporterName>("x_coord_name",
24  "Name of vector-postprocessor or reporter vector containing "
25  "x-coordinate of points, default is assumed to be all 0s.");
26  params.addParam<ReporterName>("y_coord_name",
27  "Name of vector-postprocessor or reporter vector containing "
28  "y-coordinate of points, default is assumed to be all 0s.");
29  params.addParam<ReporterName>("z_coord_name",
30  "Name of vector-postprocessor or reporter vector containing "
31  "z-coordinate of points, default is assumed to be all 0s.");
32  params.addParam<ReporterName>("time_name",
33  "Name of vector-postprocessor or reporter vector containing time, "
34  "default is assumed to be all 0s.");
36  "value_name", "Name of vector-postprocessor or reporter vector containing value data.");
37  return params;
38 }
39 
41  const InputParameters & parameters)
42  : OptimizationFunction(parameters),
43  ReporterInterface(this),
44  _coordx(isParamValid("x_coord_name") ? getReporterValue<std::vector<Real>>("x_coord_name")
45  : _empty_vec),
46  _coordy(isParamValid("y_coord_name") ? getReporterValue<std::vector<Real>>("y_coord_name")
47  : _empty_vec),
48  _coordz(isParamValid("z_coord_name") ? getReporterValue<std::vector<Real>>("z_coord_name")
49  : _empty_vec),
50  _coordt(isParamValid("time_name") ? getReporterValue<std::vector<Real>>("time_name")
51  : _empty_vec),
52  _values(getReporterValue<std::vector<Real>>("value_name"))
53 {
54 }
55 
56 Real
57 NearestReporterCoordinatesFunction::value(Real t, const Point & p) const
58 {
59  const std::array<std::pair<Real, std::size_t>, 2> tv = findNearestPoint(t, p);
60 
61  // If the indices are equal then t is either less than the minimum time in the data
62  // or greater than the maximum time. In which case will extrapolate using a constant
63  // value.
64  if (tv[0].second == tv[1].second)
65  return _values[tv[0].second];
66 
67  const Real told = tv[0].first;
68  const Real tnew = tv[1].first;
69  const Real vold = _values[tv[0].second];
70  const Real vnew = _values[tv[1].second];
71  return vold + (vnew - vold) * (t - told) / (tnew - told);
72 }
73 
75 NearestReporterCoordinatesFunction::gradient(Real /*t*/, const Point & /*p*/) const
76 {
77  return RealGradient(0, 0, 0);
78 }
79 
80 Real
82 {
83  const std::array<std::pair<Real, std::size_t>, 2> tv = findNearestPoint(t, p);
84 
85  if (tv[0].second == tv[1].second)
86  return 0.0;
87 
88  const Real told = tv[0].first;
89  const Real tnew = tv[1].first;
90  const Real vold = _values[tv[0].second];
91  const Real vnew = _values[tv[1].second];
92  return (vnew - vold) / (tnew - told);
93 }
94 
95 std::vector<Real>
97 {
98  const std::array<std::pair<Real, std::size_t>, 2> tv = findNearestPoint(t, p);
99  std::vector<Real> param_grad(_nval, 0.0);
100 
101  if (tv[0].second == tv[1].second)
102  param_grad[tv[0].second] = 1;
103  else
104  {
105  const Real told = tv[0].first;
106  const Real tnew = tv[1].first;
107  param_grad[tv[0].second] = (tnew - t) / (tnew - told);
108  param_grad[tv[1].second] = (t - told) / (tnew - told);
109  }
110  return param_grad;
111 }
112 
113 void
115 {
116  // Do some size checks
117  _nval = std::max({_coordx.size(), _coordy.size(), _coordz.size(), _coordt.size()});
118  if (_nval == 0)
119  paramError("value", "At least one coordinate vector must not be empty.");
120  else if (!_coordx.empty() && _coordx.size() != _nval)
121  paramError("x_coord_name",
122  "Number of x coordinates (",
123  _coordx.size(),
124  ") does not match number of values (",
125  _nval,
126  ").");
127  else if (!_coordy.empty() && _coordy.size() != _nval)
128  paramError("y_coord_name",
129  "Number of y coordinates (",
130  _coordy.size(),
131  ") does not match number of values (",
132  _nval,
133  ").");
134  else if (!_coordz.empty() && _coordz.size() != _nval)
135  paramError("z_coord_name",
136  "Number of z coordinates (",
137  _coordz.size(),
138  ") does not match number of values (",
139  _nval,
140  ").");
141  else if (!_coordt.empty() && _coordt.size() != _nval)
142  paramError("time_name",
143  "Number of times (",
144  _coordt.size(),
145  ") does not match number of values (",
146  _nval,
147  ").");
148 
149  // Find times for each unique coordinate
150  _coord_mapping.clear();
151  for (const auto & i : make_range(_nval))
152  {
153  Point pt;
154  pt(0) = _coordx.empty() ? 0.0 : _coordx[i];
155  pt(1) = _coordy.empty() ? 0.0 : _coordy[i];
156  pt(2) = _coordz.empty() ? 0.0 : _coordz[i];
157  const Real time = _coordt.empty() ? 0.0 : _coordt[i];
158 
159  std::vector<std::pair<Real, std::size_t>> * vec = nullptr;
160  for (auto & it : _coord_mapping)
161  if (pt.absolute_fuzzy_equals(it.first))
162  {
163  vec = &it.second;
164  break;
165  }
166  if (!vec)
167  vec = &_coord_mapping[pt];
168 
169  vec->emplace_back(time, i);
170  std::sort(vec->begin(),
171  vec->end(),
172  [](const std::pair<Real, Real> & a, const std::pair<Real, Real> & b)
173  { return a.first < b.first; });
174  }
175 }
176 
177 std::array<std::pair<Real, std::size_t>, 2>
179 {
180  if (_coord_mapping.empty())
182 
183  // Make sure values is correct size
184  if (_values.size() != _nval)
185  paramError("value_name",
186  "Size of value vector (",
187  _values.size(),
188  ") does not match number of coordinates specified (",
189  _nval,
190  ").");
191 
192  const auto & tval =
193  std::min_element(_coord_mapping.begin(),
194  _coord_mapping.end(),
195  [&p](const std::pair<Point, std::vector<std::pair<Real, std::size_t>>> & p1,
196  const std::pair<Point, std::vector<std::pair<Real, std::size_t>>> & p2)
197  { return (p - p1.first).norm_sq() < (p - p2.first).norm_sq(); })
198  ->second;
199 
200  if (tval.size() == 1 || MooseUtils::absoluteFuzzyLessEqual(t, tval[0].first))
201  return {tval[0], tval[0]};
202  else if (MooseUtils::absoluteFuzzyGreaterEqual(t, tval.back().first))
203  return {tval.back(), tval.back()};
204  else
205  for (std::size_t ti = 1; ti < tval.size(); ++ti)
206  if (MooseUtils::absoluteFuzzyGreaterEqual(tval[ti].first, t))
207  return {tval[ti - 1], tval[ti]};
208 
209  mooseError("Internal error: unable to find nearest point.");
210  return std::array<std::pair<Real, std::size_t>, 2>();
211 }
void buildCoordinateMapping() const
Builds _coord_mapping object with coordinates from input vectors.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
const std::vector< Real > & _coordy
y-coordinates from reporter
const std::vector< Real > & _coordt
time-coordinates from reporter
const std::vector< Real > & _coordx
x-coordinates from reporter
NearestReporterCoordinatesFunction(const InputParameters &parameters)
std::array< std::pair< Real, std::size_t >, 2 > findNearestPoint(Real t, const Point &p) const
With an input time and point, gets the closest point and two closest times in _coord_mapping.
virtual Real timeDerivative(Real t, const Point &p) const override
void addRequiredParam(const std::string &name, const std::string &doc_string)
const std::vector< Real > & _values
values from reporter
std::size_t _nval
Number of values from coordinate vectors.
Function based on the nearest point to coordinates and values defined by a vector of values...
void paramError(const std::string &param, Args... args) const
virtual RealGradient gradient(Real t, const Point &p) const override
registerMooseObject("OptimizationApp", NearestReporterCoordinatesFunction)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Base class for functions used in inverse optimization The parameterDerivative function is used in adj...
const std::vector< Real > & _coordz
z-coordinates from reporter
auto norm_sq(const T &a) -> decltype(std::norm(a))
virtual std::vector< Real > parameterGradient(Real t, const Point &p) const override
bool absoluteFuzzyLessEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
IntRange< T > make_range(T beg, T end)
bool absoluteFuzzyGreaterEqual(const T &var1, const T2 &var2, const T3 &tol=libMesh::TOLERANCE *libMesh::TOLERANCE)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
std::map< Point, std::vector< std::pair< Real, std::size_t > > > _coord_mapping
Data structure for all current data.
static InputParameters validParams()
virtual Real value(Real t, const Point &p) const override