12#ifndef DUMUX_COMMON_MONOTONE_CUBIC_SPLINE_HH 
   13#define DUMUX_COMMON_MONOTONE_CUBIC_SPLINE_HH 
   21#include <dune/common/float_cmp.hh> 
   37template<
class Scalar = 
double>
 
   63    void updatePoints(
const std::vector<Scalar>& x, 
const std::vector<Scalar>& y)
 
   66        assert (x.size() == y.size());
 
   67        assert (x.size() >=2);
 
   68        assert (std::is_sorted(x.begin(), x.end()) || std::is_sorted(x.rbegin(), x.rend()));
 
   75        numPoints_ = x.size();
 
   78        increasingX_ = x_.back() > x_.front();
 
   79        increasingY_ = y_.back() > y_.front();
 
   82        m_.resize(numPoints_);
 
   85        Scalar deltaX = (x[1]-x[0]);
 
   86        Scalar secant = m_.front() = (y[1]-y[0])/deltaX;
 
   87        Scalar prevDeltaX = deltaX;
 
   88        Scalar prevSecant = secant;
 
   89        for (
int i = 1; i < numPoints_-1; ++i, prevSecant = secant, prevDeltaX = deltaX)
 
   91            deltaX = (x[i+1]-x[i]);
 
   92            secant = (y[i+1]-y[i])/deltaX;
 
   93            const auto alpha = (prevDeltaX + 2*deltaX)/(3*(prevDeltaX + deltaX));
 
   94            m_[i] = prevSecant*secant > 0.0 ? prevSecant*secant/(alpha*secant + (1.0-alpha)*prevSecant) : 0.0;
 
 
  104    Scalar 
eval(
const Scalar x)
 const 
  106        if ((x <= x_.front() && increasingX_) || (x >= x_.front() && !increasingX_))
 
  107            return y_.front() + m_.front()*(x - x_.front());
 
  108        else if ((x > x_.back() && increasingX_) || (x < x_.back() && !increasingX_))
 
  109            return y_.back() + m_.back()*(x - x_.back());
 
 
  121        if ((x <= x_.front() && increasingX_) || (x >= x_.front() && !increasingX_))
 
  123        else if ((x > x_.back() && increasingX_) || (x < x_.back() && !increasingX_))
 
  126        return evalDerivative_(x);
 
 
  137        if ((y <= y_.front() && increasingY_) || (y >= y_.front() && !increasingY_))
 
  138            return x_.front() + (y - y_.front())/m_.front();
 
  139        else if ((y > y_.back() && increasingY_) || (y < y_.back() && !increasingY_))
 
  140            return x_.back() + (y - y_.back())/m_.back();
 
  142        return evalInverse_(y);
 
 
  146    Scalar eval_(
const Scalar x)
 const 
  149        const auto lookUpIndex = lookUpIndex_(x_, x, increasingX_);
 
  150        const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]);
 
  151        const auto t = (x - x_[lookUpIndex-1])/h;
 
  156    Scalar evalDerivative_(
const Scalar x)
 const 
  159        const auto lookUpIndex = lookUpIndex_(x_, x, increasingX_);
 
  160        const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]);
 
  161        const auto t = (x - x_[lookUpIndex-1])/h;
 
  162        const auto dtdx = 1.0/h;
 
  167    Scalar evalInverse_(
const Scalar y)
 const 
  169        const auto lookUpIndex = lookUpIndex_(y_, y, increasingY_);
 
  170        auto localPolynomial = [&](
const auto x) {
 
  172            const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]);
 
  173            const auto t = (x - x_[lookUpIndex-1])/h;
 
  179        const auto eps = (x_[lookUpIndex]-x_[lookUpIndex-1])*1e-5;
 
  183    auto lookUpIndex_(
const std::vector<Scalar>& vec, 
const Scalar v, 
bool increasing)
 const 
  185        return increasing ? lookUpIndexIncreasing_(vec, v) : lookUpIndexDecreasing_(vec, v);
 
  188    auto lookUpIndexIncreasing_(
const std::vector<Scalar>& vec, 
const Scalar v)
 const 
  190        const auto lookUpIndex = std::distance(vec.begin(), std::lower_bound(vec.begin(), vec.end(), v));
 
  191        assert(lookUpIndex != 0 && lookUpIndex < vec.size());
 
  195    auto lookUpIndexDecreasing_(
const std::vector<Scalar>& vec, 
const Scalar v)
 const 
  197        const auto lookUpIndex = vec.size() - std::distance(vec.rbegin(), std::upper_bound(vec.rbegin(), vec.rend(), v));
 
  198        assert(lookUpIndex != 0 && lookUpIndex < vec.size());
 
  202    std::vector<Scalar> x_; 
 
  203    std::vector<Scalar> y_; 
 
  204    std::vector<Scalar> m_; 
 
  205    std::size_t numPoints_; 
 
 
MonotoneCubicSpline()=default
Default constructor.
void updatePoints(const std::vector< Scalar > &x, const std::vector< Scalar > &y)
Create a monotone cubic spline from the control points (x[i], y[i])
Definition monotonecubicspline.hh:63
Scalar evalInverse(const Scalar y) const
Evaluate the inverse function.
Definition monotonecubicspline.hh:135
Scalar eval(const Scalar x) const
Evaluate the y value at a given x value.
Definition monotonecubicspline.hh:104
Scalar evalDerivative(const Scalar x) const
Evaluate the first derivative dy/dx at a given x value.
Definition monotonecubicspline.hh:119
MonotoneCubicSpline(const std::vector< Scalar > &x, const std::vector< Scalar > &y)
Construct a monotone cubic spline from the control points (x[i], y[i])
Definition monotonecubicspline.hh:53
The cubic hermite spline basis.
Root finding algorithms for scalar functions.
Scalar findScalarRootBrent(Scalar a, Scalar b, const ResFunc &residual, const Scalar tol=1e-13, const int maxIter=200)
Brent's root finding algorithm for scalar functions.
Definition findscalarroot.hh:99
The cubic spline hermite basis.
Definition cubicsplinehermitebasis.hh:24
static constexpr Scalar h01(const Scalar t)
Definition cubicsplinehermitebasis.hh:31
static constexpr Scalar dh01(const Scalar t)
Definition cubicsplinehermitebasis.hh:43
static constexpr Scalar dh11(const Scalar t)
Definition cubicsplinehermitebasis.hh:46
static constexpr Scalar h11(const Scalar t)
Definition cubicsplinehermitebasis.hh:34
static constexpr Scalar h00(const Scalar t)
Definition cubicsplinehermitebasis.hh:25
static constexpr Scalar dh10(const Scalar t)
Definition cubicsplinehermitebasis.hh:40
static constexpr Scalar h10(const Scalar t)
Definition cubicsplinehermitebasis.hh:28
static constexpr Scalar dh00(const Scalar t)
Definition cubicsplinehermitebasis.hh:37