LCOV - code coverage report
Current view: top level - src/utils - BicubicSplineInterpolation.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 99787a Lines: 120 136 88.2 %
Date: 2025-10-14 20:01:24 Functions: 13 13 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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 "BicubicSplineInterpolation.h"
      11             : #include "MooseError.h"
      12             : 
      13             : int BicubicSplineInterpolation::_file_number = 0;
      14             : 
      15          42 : BicubicSplineInterpolation::BicubicSplineInterpolation() {}
      16             : 
      17           2 : BicubicSplineInterpolation::BicubicSplineInterpolation(const std::vector<Real> & x1,
      18             :                                                        const std::vector<Real> & x2,
      19             :                                                        const std::vector<std::vector<Real>> & y,
      20             :                                                        const std::vector<Real> & yx11,
      21             :                                                        const std::vector<Real> & yx1n,
      22             :                                                        const std::vector<Real> & yx21,
      23           2 :                                                        const std::vector<Real> & yx2n)
      24             :   : SplineInterpolationBase(),
      25           2 :     _x1(x1),
      26           2 :     _x2(x2),
      27           2 :     _y(y),
      28           2 :     _yx11(yx11),
      29           2 :     _yx1n(yx1n),
      30           2 :     _yx21(yx21),
      31           6 :     _yx2n(yx2n)
      32             : {
      33           2 :   auto n = _x2.size();
      34           2 :   _row_spline_second_derivs.resize(n);
      35           2 :   _column_spline_eval.resize(n);
      36             : 
      37           2 :   auto m = _x1.size();
      38           2 :   _column_spline_second_derivs.resize(m);
      39           2 :   _row_spline_eval.resize(m);
      40             : 
      41           2 :   errorCheck();
      42           2 :   solve();
      43           2 : }
      44             : 
      45             : void
      46          42 : BicubicSplineInterpolation::setData(const std::vector<Real> & x1,
      47             :                                     const std::vector<Real> & x2,
      48             :                                     const std::vector<std::vector<Real>> & y,
      49             :                                     const std::vector<Real> & yx11,
      50             :                                     const std::vector<Real> & yx1n,
      51             :                                     const std::vector<Real> & yx21,
      52             :                                     const std::vector<Real> & yx2n)
      53             : {
      54          42 :   _x1 = x1;
      55          42 :   _x2 = x2;
      56          42 :   _y = y;
      57          42 :   _yx11 = yx11;
      58          42 :   _yx1n = yx1n;
      59          42 :   _yx21 = yx21;
      60          42 :   _yx2n = yx2n;
      61             : 
      62          42 :   auto n = _x2.size();
      63          42 :   _row_spline_second_derivs.resize(n);
      64          42 :   _column_spline_eval.resize(n);
      65             : 
      66          42 :   auto m = _x1.size();
      67          42 :   _column_spline_second_derivs.resize(m);
      68          42 :   _row_spline_eval.resize(m);
      69             : 
      70          42 :   errorCheck();
      71          42 :   solve();
      72          42 : }
      73             : 
      74             : void
      75          44 : BicubicSplineInterpolation::errorCheck()
      76             : {
      77          44 :   auto m = _x1.size(), n = _x2.size();
      78             : 
      79          44 :   if (_y.size() != m)
      80           0 :     mooseError("y row dimension does not match the size of x1.");
      81             :   else
      82         180 :     for (decltype(m) i = 0; i < _y.size(); ++i)
      83         136 :       if (_y[i].size() != n)
      84           0 :         mooseError("y column dimension does not match the size of x2.");
      85             : 
      86          44 :   if (_yx11.empty())
      87           0 :     _yx11.resize(n, _deriv_bound);
      88          44 :   else if (_yx11.size() != n)
      89           0 :     mooseError("The length of the vectors holding the first derivatives of y with respect to x1 "
      90             :                "must match the length of x2.");
      91             : 
      92          44 :   if (_yx1n.empty())
      93           0 :     _yx1n.resize(n, _deriv_bound);
      94          44 :   else if (_yx1n.size() != n)
      95           0 :     mooseError("The length of the vectors holding the first derivatives of y with respect to x1 "
      96             :                "must match the length of x2.");
      97             : 
      98          44 :   if (_yx21.empty())
      99           0 :     _yx21.resize(m, _deriv_bound);
     100          44 :   else if (_yx21.size() != m)
     101           0 :     mooseError("The length of the vectors holding the first derivatives of y with respect to x2 "
     102             :                "must match the length of x1.");
     103             : 
     104          44 :   if (_yx2n.empty())
     105           0 :     _yx2n.resize(m, _deriv_bound);
     106          44 :   else if (_yx2n.size() != m)
     107           0 :     mooseError("The length of the vectors holding the first derivatives of y with respect to x2 "
     108             :                "must match the length of x1.");
     109          44 : }
     110             : 
     111             : void
     112          44 : BicubicSplineInterpolation::constructRowSplineSecondDerivativeTable()
     113             : {
     114          44 :   auto m = _x1.size();
     115          44 :   _y2_rows.resize(m);
     116             : 
     117          44 :   if (_yx21.empty())
     118           0 :     for (decltype(m) j = 0; j < m; ++j)
     119           0 :       spline(_x2, _y[j], _y2_rows[j]);
     120             : 
     121             :   else
     122         180 :     for (decltype(m) j = 0; j < m; ++j)
     123         136 :       spline(_x2, _y[j], _y2_rows[j], _yx21[j], _yx2n[j]);
     124          44 : }
     125             : 
     126             : void
     127          44 : BicubicSplineInterpolation::constructColumnSplineSecondDerivativeTable()
     128             : {
     129          44 :   auto m = _x1.size();
     130          44 :   auto n = _x2.size();
     131          44 :   _y2_columns.resize(n);
     132          44 :   _y_trans.resize(n);
     133             : 
     134         222 :   for (decltype(n) j = 0; j < n; ++j)
     135         178 :     _y_trans[j].resize(m);
     136             : 
     137             :   // transpose the _y values so the columns can be easily iterated over
     138         180 :   for (decltype(n) i = 0; i < _y.size(); ++i)
     139         690 :     for (decltype(n) j = 0; j < _y[0].size(); ++j)
     140         554 :       _y_trans[j][i] = _y[i][j];
     141             : 
     142          44 :   if (_yx11.empty())
     143           0 :     for (decltype(n) j = 0; j < n; ++j)
     144           0 :       spline(_x1, _y_trans[j], _y2_columns[j]);
     145             : 
     146             :   else
     147         222 :     for (decltype(n) j = 0; j < n; ++j)
     148         178 :       spline(_x1, _y_trans[j], _y2_columns[j], _yx11[j], _yx1n[j]);
     149          44 : }
     150             : 
     151             : void
     152          44 : BicubicSplineInterpolation::solve()
     153             : {
     154          44 :   constructRowSplineSecondDerivativeTable();
     155          44 :   constructColumnSplineSecondDerivativeTable();
     156          44 : }
     157             : 
     158             : Real
     159        7452 : BicubicSplineInterpolation::sample(Real x1,
     160             :                                    Real x2,
     161             :                                    Real yx11 /* = _deriv_bound*/,
     162             :                                    Real yx1n /* = _deriv_bound*/)
     163             : {
     164        7452 :   constructColumnSpline(x2, _row_spline_eval, _column_spline_second_derivs, yx11, yx1n);
     165             : 
     166             :   // Evaluate newly constructed column spline
     167        7452 :   return SplineInterpolationBase::sample(_x1, _row_spline_eval, _column_spline_second_derivs, x1);
     168             : }
     169             : 
     170             : Real
     171       19004 : BicubicSplineInterpolation::sampleDerivative(Real x1,
     172             :                                              Real x2,
     173             :                                              unsigned int deriv_var,
     174             :                                              Real yp1 /* = _deriv_bound*/,
     175             :                                              Real ypn /* = _deriv_bound*/)
     176             : {
     177             :   // Take derivative along x1 axis
     178       19004 :   if (deriv_var == 1)
     179             :   {
     180        9502 :     constructColumnSpline(x2, _row_spline_eval, _column_spline_second_derivs, yp1, ypn);
     181             : 
     182             :     // Evaluate derivative wrt x1 of newly constructed column spline
     183       19004 :     return SplineInterpolationBase::sampleDerivative(
     184        9502 :         _x1, _row_spline_eval, _column_spline_second_derivs, x1);
     185             :   }
     186             : 
     187             :   // Take derivative along x2 axis
     188        9502 :   else if (deriv_var == 2)
     189             :   {
     190        9502 :     constructRowSpline(x1, _column_spline_eval, _row_spline_second_derivs, yp1, ypn);
     191             : 
     192             :     // Evaluate derivative wrt x2 of newly constructed row spline
     193       19004 :     return SplineInterpolationBase::sampleDerivative(
     194        9502 :         _x2, _column_spline_eval, _row_spline_second_derivs, x2);
     195             :   }
     196             : 
     197             :   else
     198           0 :     mooseError("deriv_var must be either 1 or 2 in BicubicSplineInterpolation");
     199             : }
     200             : 
     201             : Real
     202           4 : BicubicSplineInterpolation::sample2ndDerivative(Real x1,
     203             :                                                 Real x2,
     204             :                                                 unsigned int deriv_var,
     205             :                                                 Real yp1 /* = _deriv_bound*/,
     206             :                                                 Real ypn /* = _deriv_bound*/)
     207             : {
     208             :   // Take second derivative along x1 axis
     209           4 :   if (deriv_var == 1)
     210             :   {
     211           2 :     constructColumnSpline(x2, _row_spline_eval, _column_spline_second_derivs, yp1, ypn);
     212             : 
     213             :     // Evaluate second derivative wrt x1 of newly constructed column spline
     214           4 :     return SplineInterpolationBase::sample2ndDerivative(
     215           2 :         _x1, _row_spline_eval, _column_spline_second_derivs, x1);
     216             :   }
     217             : 
     218             :   // Take second derivative along x2 axis
     219           2 :   else if (deriv_var == 2)
     220             :   {
     221           2 :     constructRowSpline(x1, _column_spline_eval, _row_spline_second_derivs, yp1, ypn);
     222             : 
     223             :     // Evaluate second derivative wrt x2 of newly constructed row spline
     224           4 :     return SplineInterpolationBase::sample2ndDerivative(
     225           2 :         _x2, _column_spline_eval, _row_spline_second_derivs, x2);
     226             :   }
     227             : 
     228             :   else
     229           0 :     mooseError("deriv_var must be either 1 or 2 in BicubicSplineInterpolation");
     230             : }
     231             : 
     232             : void
     233           2 : BicubicSplineInterpolation::sampleValueAndDerivatives(Real x1,
     234             :                                                       Real x2,
     235             :                                                       Real & y,
     236             :                                                       Real & dy1,
     237             :                                                       Real & dy2,
     238             :                                                       Real yx11 /* = _deriv_bound*/,
     239             :                                                       Real yx1n /* = _deriv_bound*/,
     240             :                                                       Real yx21 /* = _deriv_bound*/,
     241             :                                                       Real yx2n /* = _deriv_bound*/)
     242             : {
     243           2 :   constructColumnSpline(x2, _row_spline_eval, _column_spline_second_derivs, yx11, yx1n);
     244           2 :   y = SplineInterpolationBase::sample(_x1, _row_spline_eval, _column_spline_second_derivs, x1);
     245           4 :   dy1 = SplineInterpolationBase::sampleDerivative(
     246           2 :       _x1, _row_spline_eval, _column_spline_second_derivs, x1);
     247             : 
     248           2 :   constructRowSpline(x1, _column_spline_eval, _row_spline_second_derivs, yx21, yx2n);
     249           4 :   dy2 = SplineInterpolationBase::sampleDerivative(
     250           2 :       _x2, _column_spline_eval, _row_spline_second_derivs, x2);
     251           2 : }
     252             : 
     253             : void
     254        9506 : BicubicSplineInterpolation::constructRowSpline(Real x1,
     255             :                                                std::vector<Real> & column_spline_eval,
     256             :                                                std::vector<Real> & row_spline_second_derivs,
     257             :                                                Real yx11 /*= _deriv_bound*/,
     258             :                                                Real yx1n /*= _deriv_bound*/)
     259             : {
     260        9506 :   auto n = _x2.size();
     261             : 
     262             :   // Find the indices that bound the point x1
     263             :   unsigned int klo, khi;
     264        9506 :   findInterval(_x1, x1, klo, khi);
     265             : 
     266             :   // Evaluate n column-splines to get y-values for row spline construction using
     267             :   // the indices above to avoid computing them for each j
     268       47536 :   for (decltype(n) j = 0; j < n; ++j)
     269       38030 :     _column_spline_eval[j] =
     270       38030 :         SplineInterpolationBase::sample(_x1, _y_trans[j], _y2_columns[j], x1, klo, khi);
     271             : 
     272             :   // Construct single row spline; get back the second derivatives wrt x2 coord
     273             :   // on the x2 grid points
     274        9506 :   spline(_x2, column_spline_eval, row_spline_second_derivs, yx11, yx1n);
     275        9506 : }
     276             : 
     277             : void
     278       16958 : BicubicSplineInterpolation::constructColumnSpline(Real x2,
     279             :                                                   std::vector<Real> & row_spline_eval,
     280             :                                                   std::vector<Real> & column_spline_second_derivs,
     281             :                                                   Real yx21 /*= _deriv_bound*/,
     282             :                                                   Real yx2n /*= _deriv_bound*/)
     283             : {
     284       16958 :   auto m = _x1.size();
     285             : 
     286             :   // Find the indices that bound the point x2
     287             :   unsigned int klo, khi;
     288       16958 :   findInterval(_x2, x2, klo, khi);
     289             : 
     290             :   // Evaluate m row-splines to get y-values for column spline construction using
     291             :   // the indices above to avoid computing them for each j
     292       67848 :   for (decltype(m) j = 0; j < m; ++j)
     293       50890 :     _row_spline_eval[j] = SplineInterpolationBase::sample(_x2, _y[j], _y2_rows[j], x2, klo, khi);
     294             : 
     295             :   // Construct single column spline; get back the second derivatives wrt x1 coord
     296             :   // on the x1 grid points
     297       16958 :   spline(_x1, row_spline_eval, column_spline_second_derivs, yx21, yx2n);
     298       16958 : }

Generated by: LCOV version 1.14