24#ifndef DUMUX_SPLINE_COMMON__HH
25#define DUMUX_SPLINE_COMMON__HH
31#include <dune/common/exceptions.hh>
32#include <dune/common/float_cmp.hh>
43template<
class ScalarT,
class ImplementationT>
46 using Scalar = ScalarT;
47 using Implementation = ImplementationT;
49 Implementation &asImp_()
50 {
return *
static_cast<Implementation*
>(
this); }
51 const Implementation &asImp_()
const
52 {
return *
static_cast<const Implementation*
>(
this); }
92 void printCSV(Scalar xi0, Scalar xi1,
int k)
const
96 Scalar x0 = min(xi0, xi1);
97 Scalar x1 = max(xi0, xi1);
99 for (
int i = 0; i <= k; ++i) {
100 double x = i*(x1 - x0)/k + x0;
101 double x_p1 = x + (x1 - x0)/k;
108 y = (x -
x_(0))*dy_dx +
y_(0);
109 mono = (dy_dx>0)?1:-1;
111 else if (x >
x_(n)) {
113 y = (x -
x_(n))*dy_dx +
y_(n);
114 mono = (dy_dx>0)?1:-1;
117 std::cerr <<
"ooops: " << x <<
"\n";
124 mono =
monotonic(max<Scalar>(
x_(0), x), min<Scalar>(
x_(n), x_p1));
127 std::cout << x <<
" " << y <<
" " << dy_dx <<
" " << mono <<
"\n";
142 Scalar
eval(Scalar x,
bool extrapolate=
false)
const
144 assert(extrapolate ||
applies(x));
151 return y0 + m*(x -
xMin());
153 else if (x >
xMax()) {
156 return y0 + m*(x -
xMax());
178 assert(extrapolate ||
applies(x));
180 if (Dune::FloatCmp::le(x,
xMin()))
182 else if (Dune::FloatCmp::ge(x,
xMax()))
195 Scalar
intersect(Scalar a, Scalar b, Scalar c, Scalar d)
const
197 return intersectIntervall(
xMin(),
xMax(), a, b, c, d);
207 Scalar a, Scalar b, Scalar c, Scalar d)
const
215 for (
int i = iFirst; i <= iLast; ++i)
220 DUNE_THROW(Dune::MathError,
221 "Spline has more than one intersection");
226 DUNE_THROW(Dune::MathError,
227 "Spline has no intersection");
244 assert(Dune::FloatCmp::ne<Scalar>(x0, x1));
254 if (Dune::FloatCmp::eq<Scalar>(
moment_(0), 0) &&
255 Dune::FloatCmp::eq<Scalar>(
moment_(1), 0) &&
256 Dune::FloatCmp::eq<Scalar>(
y_(0),
y_(1)))
265 if (
x_(i) <= x0 && x1 <=
x_(i+1)) {
275 for (; i < iEnd - 1; ++i)
304 template <
class DestVector,
class SourceVector>
307 const SourceVector &srcX,
308 const SourceVector &srcY,
311 assert(numSamples >= 2);
315 for (
int i = 0; i < numSamples; ++i) {
317 if (srcX[0] > srcX[numSamples - 1])
318 idx = numSamples - i - 1;
319 destX[i] = srcX[idx];
320 destY[i] = srcY[idx];
324 template <
class DestVector,
class ListIterator>
327 const ListIterator &srcBegin,
328 const ListIterator &srcEnd,
331 assert(numSamples >= 2);
334 ListIterator it = srcBegin;
336 bool reverse =
false;
337 if ((*srcBegin)[0] > (*it)[0])
342 for (
int i = 0; it != srcEnd; ++i, ++it) {
345 idx = numSamples - i - 1;
358 template <
class DestVector,
class ListIterator>
361 ListIterator srcBegin,
365 assert(numSamples >= 2);
371 ListIterator it = srcBegin;
373 bool reverse =
false;
374 if (std::get<0>(*srcBegin) > std::get<0>(*it))
379 for (
int i = 0; it != srcEnd; ++i, ++it) {
382 idx = numSamples - i - 1;
383 destX[i] = std::get<0>(*it);
384 destY[i] = std::get<1>(*it);
396 template <
class Vector,
class Matrix>
403 makeNaturalSystem(M, d);
407 Scalar lambda_n =
h_(1)/(
h_(n) +
h_(1));
408 Scalar lambda_1 = M[1][2];
409 Scalar mu_1 = 1 - lambda_1;
410 Scalar mu_n = 1 - lambda_n;
428 template <
class Vector,
class Matrix>
436 d[0] = 6/
h_(1) * ( (
y_(1) -
y_(0))/
h_(1) - m0);
445 (m1 - (
y_(n) -
y_(n - 1))/
h_(n));
453 template <
class Vector,
class Matrix>
462 for (
int i = 1; i < n; ++i) {
463 const Scalar lambda_i =
h_(i + 1) / (
h_(i) +
h_(i+1));
464 const Scalar mu_i = 1 - lambda_i;
466 6 / (
h_(i) +
h_(i+1))
472 M[i][i + 1] = lambda_i;
492 Scalar h_i1 =
h_(i + 1);
493 Scalar x_i = x -
x_(i);
494 Scalar x_i1 =
x_(i+1) - x;
497 (
y_(i+1) -
y_(i))/h_i1
500 Scalar B_i =
y_(i) -
moment_(i)* (h_i1*h_i1) / 6;
503 moment_(i)* x_i1*x_i1*x_i1 / (6 * h_i1)
505 moment_(i + 1)* x_i*x_i*x_i / (6 * h_i1)
518 Scalar h_i1 =
h_(i + 1);
519 Scalar x_i = x -
x_(i);
520 Scalar x_i1 =
x_(i+1) - x;
523 (
y_(i+1) -
y_(i))/h_i1
528 -
moment_(i) * x_i1*x_i1 / (2 * h_i1)
530 moment_(i + 1) * x_i*x_i / (2 * h_i1)
554 Scalar
disc = 4*b*b - 12*a*c;
558 return (x0*(x0*3*a + 2*b) + c > 0) ? 1 : -1;
562 Scalar xE1 = (-2*b +
disc)/(6*a);
563 Scalar xE2 = (-2*b -
disc)/(6*a);
565 if (Dune::FloatCmp::eq<Scalar>(
disc, 0)) {
567 if (Dune::FloatCmp::eq<Scalar>(xE1, x0))
572 return sign(x0*(x0*3*a + 2*b) + c);
574 if ((x0 < xE1 && xE1 < x1) ||
575 (x0 < xE2 && xE2 < x1))
583 return sign(x0*(x0*3*a + 2*b) + c);
592 Scalar a, Scalar b, Scalar c, Scalar d,
593 Scalar x0 = -1e100, Scalar x1 = 1e100)
const
601 x0 = max(
x_(segIdx), x0);
602 x1 = max(
x_(segIdx+1), x1);
606 for (
int j = 0; j < n; ++j) {
607 sol[j] +=
x_(segIdx);
608 if (x0 <= sol[j] && sol[j] <= x1) {
623 while (iLow + 1 < iHigh) {
624 int i = (iLow + iHigh) / 2;
636 Scalar
h_(
int i)
const
638 assert(
x_(i) >
x_(i-1));
640 return x_(i) -
x_(i - 1);
646 Scalar
x_(
int i)
const
647 {
return asImp_().x_(i); }
652 Scalar
y_(
int i)
const
653 {
return asImp_().y_(i); }
660 {
return asImp_().moment_(i); }
664 Scalar
a_(
int i)
const
669 Scalar
b_(
int i)
const
674 Scalar
c_(
int i)
const
679 Scalar
d_(
int i)
const
686 {
return asImp_().numSamples(); }
Define some often used mathematical functions.
Some templates to wrap the valgrind macros.
int invertCubicPolynomial(SolContainer *sol, Scalar a, Scalar b, Scalar c, Scalar d)
Invert a cubic polynomial analytically.
Definition: math.hh:242
void SetUndefined(const T &value)
Make the memory on which an object resides undefined.
Definition: valgrind.hh:102
constexpr int sign(const ValueType &value) noexcept
Sign or signum function.
Definition: math.hh:618
The common code for all 3rd order polynomial splines.
Definition: splinecommon_.hh:45
Scalar evalDerivative_(Scalar x, int i) const
Definition: splinecommon_.hh:514
Scalar moment_(int i) const
Returns the moment (i.e. second derivative) of the spline at the i-th sampling point.
Definition: splinecommon_.hh:659
Scalar evalDerivative(Scalar x, bool extrapolate=false) const
Evaluate the spline's derivative at a given position.
Definition: splinecommon_.hh:176
Scalar y_(int i) const
Returns the y coordinate of the i-th sampling point.
Definition: splinecommon_.hh:652
Scalar intersectInterval(Scalar x0, Scalar x1, Scalar a, Scalar b, Scalar c, Scalar d) const
Find the intersections of the spline with a cubic polynomial in a sub-intervall of the spline,...
Definition: splinecommon_.hh:206
int intersectSegment_(Scalar *sol, int segIdx, Scalar a, Scalar b, Scalar c, Scalar d, Scalar x0=-1e100, Scalar x1=1e100) const
Find all the intersections of a segment of the spline with a cubic polynomial within a specified inte...
Definition: splinecommon_.hh:590
Scalar eval(Scalar x, bool extrapolate=false) const
Evaluate the spline at a given position.
Definition: splinecommon_.hh:142
int segmentIdx_(Scalar x) const
Definition: splinecommon_.hh:617
void makeFullSystem_(Matrix &M, Vector &d, Scalar m0, Scalar m1)
Make the linear system of equations Mx = d which results in the moments of the full spline.
Definition: splinecommon_.hh:429
void assignFromArrayList_(DestVector &destX, DestVector &destY, const ListIterator &srcBegin, const ListIterator &srcEnd, int numSamples)
Definition: splinecommon_.hh:325
void assignSamplingPoints_(DestVector &destX, DestVector &destY, const SourceVector &srcX, const SourceVector &srcY, int numSamples)
Set the sampling point vectors.
Definition: splinecommon_.hh:305
Scalar a_(int i) const
Definition: splinecommon_.hh:664
int monotonic_(int i, Scalar x0, Scalar x1) const
Definition: splinecommon_.hh:543
void assignFromTupleList_(DestVector &destX, DestVector &destY, ListIterator srcBegin, ListIterator srcEnd, int numSamples)
Set the sampling points.
Definition: splinecommon_.hh:359
Scalar xMax() const
Return the x value of the rightmost sampling point.
Definition: splinecommon_.hh:72
int numSamples_() const
Returns the number of sampling points.
Definition: splinecommon_.hh:685
Scalar xMin() const
Return the x value of the leftmost sampling point.
Definition: splinecommon_.hh:66
Scalar c_(int i) const
Definition: splinecommon_.hh:674
Scalar b_(int i) const
Definition: splinecommon_.hh:669
int monotonic() const
Same as monotonic(x0, x1), but with the entire range of the spline as interval.
Definition: splinecommon_.hh:290
int monotonic(Scalar x0, Scalar x1) const
Returns 1 if the spline is monotonically increasing, -1 if the spline is mononously decreasing and 0 ...
Definition: splinecommon_.hh:240
void makeNaturalSystem_(Matrix &M, Vector &d)
Make the linear system of equations Mx = d which results in the moments of the natural spline....
Definition: splinecommon_.hh:454
void makePeriodicSystem_(Matrix &M, Vector &d)
Make the linear system of equations Mx = d which results in the moments of the periodic spline.
Definition: splinecommon_.hh:397
bool applies(Scalar x) const
Return true if the given x is in range [x1, xn].
Definition: splinecommon_.hh:58
Scalar intersect(Scalar a, Scalar b, Scalar c, Scalar d) const
Find the intersections of the spline with a cubic polynomial in the whole intervall,...
Definition: splinecommon_.hh:195
Scalar h_(int i) const
Returns x[i] - x[i - 1].
Definition: splinecommon_.hh:636
void printCSV(Scalar xi0, Scalar xi1, int k) const
Prints k tuples of the format (x, y, dx/dy, isMonotonic) to stdout.
Definition: splinecommon_.hh:92
Scalar x_(int i) const
Returns the y coordinate of the i-th sampling point.
Definition: splinecommon_.hh:646
Scalar eval_(Scalar x, int i) const
Definition: splinecommon_.hh:488
SplineCommon_()
Definition: splinecommon_.hh:295
Scalar d_(int i) const
Definition: splinecommon_.hh:679