3.2-git
DUNE for Multi-{Phase, Component, Scale, Physics, ...} flow and transport in porous media
monotonecubicspline.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3/*****************************************************************************
4 * See the file COPYING for full copying permissions. *
5 * *
6 * This program is free software: you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation, either version 3 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
18 *****************************************************************************/
24#ifndef DUMUX_COMMON_MONOTONE_CUBIC_SPLINE_HH
25#define DUMUX_COMMON_MONOTONE_CUBIC_SPLINE_HH
26
27#include <cmath>
28#include <cassert>
29#include <iterator>
30#include <vector>
31#include <algorithm>
32
33#include <dune/common/float_cmp.hh>
34
35// Hermite basis functions
37
38namespace Dumux {
39
46template<class Scalar = double>
48{
50public:
55
62 MonotoneCubicSpline(const std::vector<Scalar>& x, const std::vector<Scalar> y)
63 {
64 // check some requirements
65 assert (x.size() == y.size());
66 assert (x.size() >=2);
67 assert (std::is_sorted(x.begin(), x.end()));
68
69 updatePoints(x, y);
70 }
71
77 void updatePoints(const std::vector<Scalar>& x, const std::vector<Scalar>& y)
78 {
79 // save a copy of the control points
80 x_ = x;
81 y_ = y;
82
83 // the number of control points
84 numPoints_ = x.size();
85
86 // the slope at every control point
87 m_.resize(numPoints_);
88
89 // compute slopes (see Fritsch & Butland (1984), Eq. (5))
90 Scalar deltaX = (x[1]-x[0]);
91 Scalar secant = m_.front() = (y[1]-y[0])/deltaX;
92 Scalar prevDeltaX = deltaX;
93 Scalar prevSecant = secant;
94 for (int i = 1; i < numPoints_-1; ++i, prevSecant = secant, prevDeltaX = deltaX)
95 {
96 deltaX = (x[i+1]-x[i]);
97 secant = (y[i+1]-y[i])/deltaX;
98 const auto alpha = (prevDeltaX + 2*deltaX)/(3*(prevDeltaX + deltaX));
99 m_[i] = prevSecant*secant > 0.0 ? prevSecant*secant/(alpha*secant + (1.0-alpha)*prevSecant) : 0.0;
100 }
101 m_.back() = secant;
102 }
103
109 Scalar eval(const Scalar x) const
110 {
111 if (x <= x_.front())
112 return y_.front() + m_.front()*(x - x_.front());
113 else if (x > x_.back())
114 return y_.back() + m_.back()*(x - x_.back());
115 else
116 {
117 const auto lookUpIndex = std::distance(x_.begin(), std::lower_bound(x_.begin(), x_.end(), x));
118 assert(lookUpIndex != 0);
119
120 // interpolate parametrization parameter t in [0,1]
121 const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]);
122 const auto t = (x - x_[lookUpIndex-1])/h;
123 return y_[lookUpIndex-1]*Basis::h00(t) + h*m_[lookUpIndex-1]*Basis::h10(t)
124 + y_[lookUpIndex]*Basis::h01(t) + h*m_[lookUpIndex]*Basis::h11(t);
125 }
126 }
127
133 Scalar evalDerivative(const Scalar x) const
134 {
135 if (x <= x_.front())
136 return m_.front();
137 else if (x > x_.back())
138 return m_.back();
139 else
140 {
141 const auto lookUpIndex = std::distance(x_.begin(), std::lower_bound(x_.begin(), x_.end(), x));
142 assert(lookUpIndex != 0);
143
144 // interpolate parametrization parameter t in [0,1]
145 const auto h = (x_[lookUpIndex] - x_[lookUpIndex-1]);
146 const auto t = (x - x_[lookUpIndex-1])/h;
147 const auto dtdx = 1.0/h;
148 return y_[lookUpIndex-1]*Basis::dh00(t)*dtdx + m_[lookUpIndex-1]*Basis::dh10(t)
149 + y_[lookUpIndex]*Basis::dh01(t)*dtdx + m_[lookUpIndex]*Basis::dh11(t);
150 }
151 }
152
153private:
154 std::vector<Scalar> x_;
155 std::vector<Scalar> y_;
156 std::vector<Scalar> m_;
157 std::size_t numPoints_;
158};
159
160} // end namespace Dumux
161
162#endif
The cubic hermite spline basis.
Definition: adapt.hh:29
The cubic spline hermite basis.
Definition: cubicsplinehermitebasis.hh:36
static constexpr Scalar h01(const Scalar t)
Definition: cubicsplinehermitebasis.hh:43
static constexpr Scalar dh01(const Scalar t)
Definition: cubicsplinehermitebasis.hh:55
static constexpr Scalar dh11(const Scalar t)
Definition: cubicsplinehermitebasis.hh:58
static constexpr Scalar h11(const Scalar t)
Definition: cubicsplinehermitebasis.hh:46
static constexpr Scalar h00(const Scalar t)
Definition: cubicsplinehermitebasis.hh:37
static constexpr Scalar dh10(const Scalar t)
Definition: cubicsplinehermitebasis.hh:52
static constexpr Scalar h10(const Scalar t)
Definition: cubicsplinehermitebasis.hh:40
static constexpr Scalar dh00(const Scalar t)
Definition: cubicsplinehermitebasis.hh:49
A monotone cubic spline.
Definition: monotonecubicspline.hh:48
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:77
Scalar eval(const Scalar x) const
Evaluate the y value at a given x value.
Definition: monotonecubicspline.hh:109
MonotoneCubicSpline(const std::vector< Scalar > &x, const std::vector< Scalar > y)
Contruct a monotone cubic spline from the control points (x[i], y[i])
Definition: monotonecubicspline.hh:62
Scalar evalDerivative(const Scalar x) const
Evaluate the first derivative dy/dx at a given x value.
Definition: monotonecubicspline.hh:133