LCOV - code coverage report
Current view: top level - src/utils - SplineInterpolationBase.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 55 62 88.7 %
Date: 2025-07-17 01:28:37 Functions: 8 14 57.1 %
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 "SplineInterpolationBase.h"
      11             : #include "MooseError.h"
      12             : #include <limits>
      13             : 
      14             : const Real SplineInterpolationBase::_deriv_bound = std::numeric_limits<Real>::max();
      15             : 
      16         326 : SplineInterpolationBase::SplineInterpolationBase() {}
      17             : 
      18             : void
      19       23976 : SplineInterpolationBase::spline(const std::vector<Real> & x,
      20             :                                 const std::vector<Real> & y,
      21             :                                 std::vector<Real> & y2,
      22             :                                 Real yp1 /* = _deriv_bound*/,
      23             :                                 Real ypn /* = _deriv_bound*/)
      24             : {
      25       23976 :   auto n = x.size();
      26       23976 :   if (n < 2)
      27           0 :     mooseError("You must have at least two knots to create a spline.");
      28             : 
      29       23976 :   std::vector<Real> u(n, 0.);
      30       23976 :   y2.assign(n, 0.);
      31             : 
      32       23976 :   if (yp1 >= 1e30)
      33         287 :     y2[0] = u[0] = 0.;
      34             :   else
      35             :   {
      36       23689 :     y2[0] = -0.5;
      37       23689 :     u[0] = (3.0 / (x[1] - x[0])) * ((y[1] - y[0]) / (x[1] - x[0]) - yp1);
      38             :   }
      39             :   // decomposition of tri-diagonal algorithm (y2 and u are used for temporary storage)
      40       57784 :   for (decltype(n) i = 1; i < n - 1; i++)
      41             :   {
      42       33808 :     Real sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
      43       33808 :     Real p = sig * y2[i - 1] + 2.0;
      44       33808 :     y2[i] = (sig - 1.0) / p;
      45       33808 :     u[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
      46       33808 :     u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p;
      47             :   }
      48             : 
      49             :   Real qn, un;
      50       23976 :   if (ypn >= 1e30)
      51         287 :     qn = un = 0.;
      52             :   else
      53             :   {
      54       23689 :     qn = 0.5;
      55       23689 :     un = (3.0 / (x[n - 1] - x[n - 2])) * (ypn - (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2]));
      56             :   }
      57             : 
      58       23976 :   y2[n - 1] = (un - qn * u[n - 2]) / (qn * y2[n - 2] + 1.);
      59             :   // back substitution
      60       81760 :   for (auto k = n - 1; k >= 1; k--)
      61       57784 :     y2[k - 1] = y2[k - 1] * y2[k] + u[k - 1];
      62       23976 : }
      63             : 
      64             : void
      65       52679 : SplineInterpolationBase::findInterval(const std::vector<Real> & x,
      66             :                                       Real x_int,
      67             :                                       unsigned int & klo,
      68             :                                       unsigned int & khi) const
      69             : {
      70       52679 :   klo = 0;
      71             :   mooseAssert(x.size() >= 2, "You must have at least two knots to create a spline.");
      72       52679 :   khi = x.size() - 1;
      73      124855 :   while (khi - klo > 1)
      74             :   {
      75       72176 :     unsigned int k = (khi + klo) >> 1;
      76       72176 :     if (x[k] > x_int)
      77       32612 :       khi = k;
      78             :     else
      79       39564 :       klo = k;
      80             :   }
      81       52679 : }
      82             : 
      83             : template <typename T>
      84             : void
      85      107907 : SplineInterpolationBase::computeCoeffs(const std::vector<Real> & x,
      86             :                                        unsigned int klo,
      87             :                                        unsigned int khi,
      88             :                                        const T & x_int,
      89             :                                        Real & h,
      90             :                                        T & a,
      91             :                                        T & b) const
      92             : {
      93      107907 :   h = x[khi] - x[klo];
      94      107907 :   if (h == 0)
      95           0 :     mooseError("The values of x must be distinct");
      96      107907 :   a = (x[khi] - x_int) / h;
      97      107907 :   b = (x_int - x[klo]) / h;
      98      107907 : }
      99             : 
     100             : Real
     101        9762 : SplineInterpolationBase::sample(const std::vector<Real> & x,
     102             :                                 const std::vector<Real> & y,
     103             :                                 const std::vector<Real> & y2,
     104             :                                 Real x_int) const
     105             : {
     106             :   unsigned int klo, khi;
     107        9762 :   findInterval(x, x_int, klo, khi);
     108             : 
     109       19524 :   return sample(x, y, y2, x_int, klo, khi);
     110             : }
     111             : 
     112             : ADReal
     113           0 : SplineInterpolationBase::sample(const std::vector<Real> & x,
     114             :                                 const std::vector<Real> & y,
     115             :                                 const std::vector<Real> & y2,
     116             :                                 const ADReal & x_int) const
     117             : {
     118             :   unsigned int klo, khi;
     119           0 :   findInterval(x, MetaPhysicL::raw_value(x_int), klo, khi);
     120             : 
     121           0 :   return sample(x, y, y2, x_int, klo, khi);
     122             : }
     123             : 
     124             : Real
     125       18484 : SplineInterpolationBase::sampleDerivative(const std::vector<Real> & x,
     126             :                                           const std::vector<Real> & y,
     127             :                                           const std::vector<Real> & y2,
     128             :                                           Real x_int) const
     129             : {
     130             :   unsigned int klo, khi;
     131       18484 :   findInterval(x, x_int, klo, khi);
     132             : 
     133             :   Real h, a, b;
     134       18484 :   computeCoeffs(x, klo, khi, x_int, h, a, b);
     135             : 
     136       18484 :   return (y[khi] - y[klo]) / h -
     137       18484 :          (((3.0 * a * a - 1.0) * y2[klo] + (3.0 * b * b - 1.0) * -y2[khi]) * h / 6.0);
     138             : }
     139             : 
     140             : Real
     141        1026 : SplineInterpolationBase::sample2ndDerivative(const std::vector<Real> & x,
     142             :                                              const std::vector<Real> & /*y*/,
     143             :                                              const std::vector<Real> & y2,
     144             :                                              Real x_int) const
     145             : {
     146             :   unsigned int klo, khi;
     147        1026 :   findInterval(x, x_int, klo, khi);
     148             : 
     149             :   Real h, a, b;
     150        1026 :   computeCoeffs(x, klo, khi, x_int, h, a, b);
     151             : 
     152        1026 :   return a * y2[klo] + b * y2[khi];
     153             : }
     154             : 
     155             : template <typename T>
     156             : T
     157       88397 : SplineInterpolationBase::sample(const std::vector<Real> & x,
     158             :                                 const std::vector<Real> & y,
     159             :                                 const std::vector<Real> & y2,
     160             :                                 const T & x_int,
     161             :                                 unsigned int klo,
     162             :                                 unsigned int khi) const
     163             : {
     164             :   Real h;
     165           0 :   T a, b;
     166       88397 :   computeCoeffs(x, klo, khi, x_int, h, a, b);
     167             : 
     168       88397 :   return a * y[klo] + b * y[khi] +
     169       88397 :          ((a * a * a - a) * y2[klo] + (b * b * b - b) * y2[khi]) * (h * h) / 6.0;
     170           0 : }
     171             : 
     172             : template Real SplineInterpolationBase::sample<Real>(const std::vector<Real> & x,
     173             :                                                     const std::vector<Real> & y,
     174             :                                                     const std::vector<Real> & y2,
     175             :                                                     const Real & x_int,
     176             :                                                     unsigned int klo,
     177             :                                                     unsigned int khi) const;
     178             : template ADReal SplineInterpolationBase::sample<ADReal>(const std::vector<Real> & x,
     179             :                                                         const std::vector<Real> & y,
     180             :                                                         const std::vector<Real> & y2,
     181             :                                                         const ADReal & x_int,
     182             :                                                         unsigned int klo,
     183             :                                                         unsigned int khi) const;

Generated by: LCOV version 1.14