15#include "libmesh/int_range.h"
18 const std::vector<Real> & x2,
19 const std::vector<std::vector<Real>> & y)
34 for (
const auto k : make_range(4))
65 unsigned int x1l, x1u, x2l, x2u;
71 for (
const auto i : make_range(4))
72 for (
const auto j : make_range(4))
81 unsigned int x1l, x1u, x2l, x2u;
90 Real sample_deriv = 0.0;
91 for (
const auto i : make_range(1, 4))
92 for (
const auto j : make_range(4))
96 Real d =
_x1[x1u] -
_x1[x1l];
98 if (!MooseUtils::absoluteFuzzyEqual(d, 0.0))
106 else if (deriv_var == 2)
108 Real sample_deriv = 0.0;
110 for (
const auto i : make_range(4))
111 for (
const auto j : make_range(1, 4))
115 Real d =
_x2[x2u] -
_x2[x2l];
117 if (!MooseUtils::absoluteFuzzyEqual(d, Real(0.0)))
124 mooseError(
"deriv_var must be either 1 or 2 in BicubicInterpolation");
130 unsigned int x1l, x1u, x2l, x2u;
139 Real sample_deriv = 0.0;
140 for (
const auto i : make_range(2, 4))
141 for (
const auto j : make_range(4))
145 Real d =
_x1[x1u] -
_x1[x1l];
147 if (!MooseUtils::absoluteFuzzyEqual(d, Real(0.0)))
148 sample_deriv /= (d * d);
155 else if (deriv_var == 2)
157 Real sample_deriv = 0.0;
158 for (
const auto i : make_range(4))
159 for (
const auto j : make_range(2, 4))
163 Real d =
_x2[x2u] -
_x2[x2l];
165 if (!MooseUtils::absoluteFuzzyEqual(d, Real(0.0)))
166 sample_deriv /= (d * d);
173 else if (deriv_var == 3)
175 Real sample_deriv = 0.0;
176 for (
const auto i : make_range(1, 4))
177 for (
const auto j : make_range(1, 4))
181 const Real d1 =
_x1[x1u] -
_x1[x1l];
182 const Real d2 =
_x2[x2u] -
_x2[x2l];
184 if (!MooseUtils::absoluteFuzzyEqual(d1, Real(0.0)) &&
185 !MooseUtils::absoluteFuzzyEqual(d2, Real(0.0)))
186 sample_deriv /= (d1 * d2);
192 mooseError(
"deriv_var must be either 1, 2 or 3 in BicubicInterpolation");
197 Real x1, Real x2, Real & y, Real & dy1, Real & dy2)
const
222 unsigned int x1l, x1u, x2l, x2u;
228 for (
const auto i : make_range(4))
229 for (
const auto j : make_range(4))
234 for (
const auto i : make_range(1, 4))
235 for (
const auto j : make_range(4))
240 for (
const auto i : make_range(4))
241 for (
const auto j : make_range(1, 4))
244 T d1 =
_x1[x1u] -
_x1[x1l];
246 if (!MooseUtils::absoluteFuzzyEqual(d1, 0.0))
249 T d2 =
_x2[x2u] -
_x2[x2l];
251 if (!MooseUtils::absoluteFuzzyEqual(d2, 0.0))
260 std::vector<std::vector<Real>> dy_dx1, dy_dx2, d2y_dx1x2;
268 const Real d1 =
_x1[i + 1] -
_x1[i];
269 const Real d2 =
_x2[j + 1] -
_x2[j];
272 std::vector<Real> y = {
_y[i][j],
_y[i + 1][j],
_y[i + 1][j + 1],
_y[i][j + 1]};
273 std::vector<Real> y1 = {
274 dy_dx1[i][j], dy_dx1[i + 1][j], dy_dx1[i + 1][j + 1], dy_dx1[i][j + 1]};
275 std::vector<Real> y2 = {
276 dy_dx2[i][j], dy_dx2[i + 1][j], dy_dx2[i + 1][j + 1], dy_dx2[i][j + 1]};
277 std::vector<Real> y12 = {
278 d2y_dx1x2[i][j], d2y_dx1x2[i + 1][j], d2y_dx1x2[i + 1][j + 1], d2y_dx1x2[i][j + 1]};
280 std::vector<Real> cl(16), x(16);
282 unsigned int count = 0;
285 for (
const auto k : make_range(4))
288 x[k + 4] = y1[k] * d1;
289 x[k + 8] = y2[k] * d2;
290 x[k + 12] = y12[k] * d1 * d2;
294 for (
const auto k : make_range(16))
297 for (
const auto q : make_range(16))
298 xx +=
_wt[k][q] * x[q];
304 for (
const auto k : make_range(4))
305 for (
const auto q : make_range(4))
315 std::vector<std::vector<Real>> & dy_dx2,
316 std::vector<std::vector<Real>> & d2y_dx1x2)
318 const auto m =
_x1.size();
319 const auto n =
_x2.size();
324 for (
const auto i : make_range(m))
328 d2y_dx1x2[i].resize(n);
332 for (
const auto i : make_range(m))
333 for (
const auto j : make_range(n))
338 dy_dx1[i][j] = (
_y[i + 1][j] -
_y[i][j]) / (
_x1[i + 1] -
_x1[i]);
341 dy_dx1[i][j] = (
_y[i][j] -
_y[i - 1][j]) / (
_x1[i] -
_x1[i - 1]);
343 dy_dx1[i][j] = (
_y[i + 1][j] -
_y[i - 1][j]) / (
_x1[i + 1] -
_x1[i - 1]);
347 dy_dx2[i][j] = (
_y[i][j + 1] -
_y[i][j]) / (
_x2[j + 1] -
_x2[j]);
349 dy_dx2[i][j] = (
_y[i][j] -
_y[i][j - 1]) / (
_x2[j] -
_x2[j - 1]);
351 dy_dx2[i][j] = (
_y[i][j + 1] -
_y[i][j - 1]) / (
_x2[j + 1] -
_x2[j - 1]);
354 if (i == 0 && j == 0)
355 d2y_dx1x2[i][j] = (
_y[i + 1][j + 1] -
_y[i + 1][j] -
_y[i][j + 1] +
_y[i][j]) /
357 else if (i == 0 && j == n - 1)
358 d2y_dx1x2[i][j] = (
_y[i + 1][j] -
_y[i + 1][j - 1] -
_y[i][j] +
_y[i][j - 1]) /
360 else if (i == m - 1 && j == 0)
361 d2y_dx1x2[i][j] = (
_y[i][j + 1] -
_y[i][j] -
_y[i - 1][j + 1] +
_y[i - 1][j]) /
363 else if (i == m - 1 && j == n - 1)
364 d2y_dx1x2[i][j] = (
_y[i][j] -
_y[i][j - 1] -
_y[i - 1][j] +
_y[i - 1][j - 1]) /
367 d2y_dx1x2[i][j] = (
_y[i + 1][j + 1] -
_y[i + 1][j - 1] -
_y[i][j + 1] +
_y[i][j - 1]) /
370 d2y_dx1x2[i][j] = (
_y[i][j + 1] -
_y[i][j - 1] -
_y[i - 1][j + 1] +
_y[i - 1][j - 1]) /
373 d2y_dx1x2[i][j] = (
_y[i + 1][j + 1] -
_y[i + 1][j] -
_y[i - 1][j + 1] +
_y[i - 1][j]) /
376 d2y_dx1x2[i][j] = (
_y[i + 1][j] -
_y[i + 1][j - 1] -
_y[i - 1][j] +
_y[i - 1][j - 1]) /
380 (
_y[i + 1][j + 1] -
_y[i + 1][j - 1] -
_y[i - 1][j + 1] +
_y[i - 1][j - 1]) /
388 const std::vector<Real> & x,
const T &
xi,
unsigned int & klo,
unsigned int & khi, T & xs)
const
392 mooseAssert(x.size() >= 2,
393 "There must be at least two points in the table in BicubicInterpolation");
396 while (khi - klo > 1)
398 unsigned int kmid = (khi + klo) / 2;
406 Real d = x[khi] - x[klo];
409 if (!MooseUtils::absoluteFuzzyEqual(d, Real(0.0)))
427 auto m =
_x1.size(), n =
_x2.size();
430 mooseError(
"y row dimension does not match the size of x1 in BicubicInterpolation");
432 for (
const auto i : index_range(
_y))
433 if (
_y[i].size() != n)
434 mooseError(
"y column dimension does not match the size of x2 in BicubicInterpolation");
DualNumber< Real, DNDerivativeType, true > ADReal
DualNumber< Real, Real > ChainedReal
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
std::vector< std::vector< std::vector< std::vector< Real > > > > _bicubic_coeffs
Matrix of precomputed coefficients There are four coefficients in each direction at each dependent va...
void tableDerivatives(std::vector< std::vector< Real > > &dy_dx1, std::vector< std::vector< Real > > &dy_dx2, std::vector< std::vector< Real > > &d2y_dx1x2)
Provides the values of the first derivatives in each direction at all points in the table of data,...
Real sample(const Real x1, const Real x2) const override
Samples value at point (x1, x2)
Real sample2ndDerivative(Real x1, Real x2, unsigned int deriv_var) const override
Samples second derivative at point (x1, x2)
T sampleInternal(const T &x1, const T &x2) const
BicubicInterpolation(const std::vector< Real > &x1, const std::vector< Real > &x2, const std::vector< std::vector< Real > > &y)
void findInterval(const std::vector< Real > &x, const T &xi, unsigned int &klo, unsigned int &khi, T &xs) const
Find the indices of the dependent values axis which bracket the point xi.
const std::vector< std::vector< int > > _wt
Matrix used to calculate bicubic interpolation coefficients (from Numerical Recipes)
std::vector< std::vector< Real > > _y
The dependent values at (x1, x2) points.
void sampleValueAndDerivativesInternal(T x1, T x2, T &y, T &dy1, T &dy2) const
Real sampleDerivative(Real x1, Real x2, unsigned int deriv_var) const override
Samples first derivative at point (x1, x2)
virtual void sampleValueAndDerivatives(Real x1, Real x2, Real &y, Real &dy1, Real &dy2) const override
Samples value and first derivatives at point (x1, x2) Use this function for speed when computing both...
void errorCheck()
Sanity checks on input data.
void precomputeCoefficients()
Precompute all of the coefficients for the bicubic interpolation to avoid calculating them repeatedly...
This class interpolates tabulated data with a Bidimension function (either bicubic or bilinear).
std::vector< Real > _x1
Independent values in the x1 direction.
std::vector< Real > _x2
Independent values in the x2 direction.