OGS
PiecewiseLinearMonotonicCurve.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
5
6#include <algorithm>
7#include <cmath>
8#include <limits>
9
10#include "BaseLib/Error.h"
11
12namespace MathLib
13{
15 std::vector<double> x, std::vector<double> y)
16 : PiecewiseLinearInterpolation(std::move(x), std::move(y), false)
17{
18 if (!isStrongMonotonic())
19 {
20 OGS_FATAL("The given curve is not strong monotonic.");
21 }
22}
23
25{
26 const double gradient0 = getDerivative(supp_pnts_[0]);
27
28 if (std::abs(gradient0) < std::numeric_limits<double>::min())
29 {
30 return false;
31 }
32
33 return std::none_of(supp_pnts_.begin(), supp_pnts_.end(),
34 [&](const double p)
35 { return this->getDerivative(p) * gradient0 <= 0.; });
36}
37
39{
40 std::size_t interval_idx = 0;
41 if (values_at_supp_pnts_.front() < values_at_supp_pnts_.back())
42 {
43 if (y <= values_at_supp_pnts_.front())
44 {
45 return supp_pnts_[0];
46 }
47 if (y >= values_at_supp_pnts_.back())
48 {
49 return supp_pnts_[supp_pnts_.size() - 1];
50 }
51
52 // search interval that has the point inside
53 auto const& it(std::lower_bound(values_at_supp_pnts_.begin(),
54 values_at_supp_pnts_.end(), y));
55 interval_idx = std::distance(values_at_supp_pnts_.begin(), it) - 1;
56 }
57 else
58 {
59 if (y >= values_at_supp_pnts_.front())
60 {
61 return supp_pnts_[0];
62 }
63 if (y <= values_at_supp_pnts_.back())
64 {
65 return supp_pnts_[supp_pnts_.size() - 1];
66 }
67
68 // search interval in the reverse direction for the point inside
69 auto const& it(std::lower_bound(values_at_supp_pnts_.rbegin(),
70 values_at_supp_pnts_.rend(), y));
71 interval_idx = values_at_supp_pnts_.size() -
72 (std::distance(values_at_supp_pnts_.rbegin(), it)) - 1;
73 }
74
75 const double xi_1 = supp_pnts_[interval_idx + 1];
76 const double xi = supp_pnts_[interval_idx];
77 const double yi_1 = values_at_supp_pnts_[interval_idx + 1];
78 const double yi = values_at_supp_pnts_[interval_idx];
79
80 // compute gradient: m = (x_{i+1} - x_i) / (y_{i+1} - y_i)
81 const double m = (xi_1 - xi) / (yi_1 - yi);
82
83 // compute the variable by linear interpolation: x = m * (y - y_i) + x_i,
84 // and then return the result.
85 return m * (y - yi) + xi;
86}
87
88} // namespace MathLib
#define OGS_FATAL(...)
Definition Error.h:19
PiecewiseLinearInterpolation(std::vector< double > supporting_points, std::vector< double > values_at_supp_pnts, bool supp_pnts_sorted=false)
double getDerivative(double const pnt_to_interpolate) const
Calculates derivative using quadratic interpolation and central difference quotient.
PiecewiseLinearMonotonicCurve(std::vector< double > x, std::vector< double > y)
static const double p