27 #ifndef OPM_TABULATED_1D_FUNCTION_HPP 28 #define OPM_TABULATED_1D_FUNCTION_HPP 30 #include <opm/common/OpmLog/OpmLog.hpp> 50 template <
class Scalar>
70 template <
class ScalarArrayX,
class ScalarArrayY>
72 const ScalarArrayX& x,
73 const ScalarArrayY& y,
74 bool sortInputs =
true)
86 template <
class ScalarContainer>
88 const ScalarContainer& y,
89 bool sortInputs =
true)
99 template <
class Po
intContainer>
101 bool sortInputs =
true)
109 template <
class ScalarArrayX,
class ScalarArrayY>
111 const ScalarArrayX& x,
112 const ScalarArrayY& y,
113 bool sortInputs =
true)
115 assert(nSamples > 1);
117 resizeArrays_(nSamples);
118 for (std::size_t i = 0; i < nSamples; ++i) {
125 else if (xValues_[0] > xValues_[
numSamples() - 1])
126 reverseSamplingPoints_();
134 template <
class ScalarContainerX,
class ScalarContainerY>
136 const ScalarContainerY& y,
137 bool sortInputs =
true)
139 assert(x.size() == y.size());
141 resizeArrays_(x.size());
143 std::ranges::copy(x, xValues_.begin());
144 std::ranges::copy(y, yValues_.begin());
148 else if (xValues_[0] > xValues_[
numSamples() - 1])
149 reverseSamplingPoints_();
156 template <
class Po
intArray>
158 const PointArray& points,
159 bool sortInputs =
true)
163 assert(nSamples > 1);
165 resizeArrays_(nSamples);
166 for (std::size_t i = 0; i < nSamples; ++i) {
167 xValues_[i] = points[i][0];
168 yValues_[i] = points[i][1];
173 else if (xValues_[0] > xValues_[
numSamples() - 1])
174 reverseSamplingPoints_();
191 template <
class XYContainer>
193 bool sortInputs =
true)
197 assert(points.size() > 1);
199 resizeArrays_(points.size());
200 typename XYContainer::const_iterator it = points.begin();
201 typename XYContainer::const_iterator endIt = points.end();
202 for (
unsigned i = 0; it != endIt; ++i, ++it) {
203 xValues_[i] = std::get<0>(*it);
204 yValues_[i] = std::get<1>(*it);
209 else if (xValues_[0] > xValues_[
numSamples() - 1])
210 reverseSamplingPoints_();
217 {
return xValues_.size(); }
223 {
return xValues_[0]; }
234 Scalar
xAt(std::size_t i)
const 235 {
return xValues_[i]; }
237 const std::vector<Scalar>& xValues()
const 240 const std::vector<Scalar>& yValues()
const 247 {
return yValues_[i]; }
252 template <
class Evaluation>
254 {
return xValues_[0] <= x && x <= xValues_[
numSamples() - 1]; }
265 template <
class Evaluation>
266 Evaluation
eval(
const Evaluation& x,
bool extrapolate =
false)
const 269 return eval(x, segIdx);
272 template <
class Evaluation>
275 std::size_t segIdx = segIdxIn.value;
276 Scalar x0 = xValues_[segIdx];
277 Scalar x1 = xValues_[segIdx + 1];
279 Scalar y0 = yValues_[segIdx];
280 Scalar y1 = yValues_[segIdx + 1];
282 return y0 + (y1 - y0)*(x - x0)/(x1 - x0);
296 template <
class Evaluation>
299 std::size_t segIdx = findSegmentIndex(x, extrapolate).value;
300 return evalDerivative_(x, segIdx);
317 template <
class Evaluation>
335 template <
class Evaluation>
348 [[maybe_unused]]
bool extrapolate =
false)
const 365 std::size_t i = findSegmentIndex(x0, extrapolate).value;
366 if (xValues_[i + 1] >= x1) {
369 updateMonotonicity_(i, r);
375 updateMonotonicity_(i, r);
380 std::size_t iEnd = findSegmentIndex(x1, extrapolate).value;
381 for (; i < iEnd - 1; ++i) {
382 updateMonotonicity_(i, r);
395 return (r < 0 || r==3) ? -1 : 0;
397 return r > 0 ? 1 : 0;
403 updateMonotonicity_(iEnd, r);
431 void printCSV(Scalar xi0, Scalar xi1,
unsigned k, std::ostream& os)
const;
434 return xValues_ == data.xValues_ &&
435 yValues_ == data.yValues_;
438 template <
class Evaluation>
439 SegmentIndex findSegmentIndex(
const Evaluation& x,
bool extrapolate =
false)
const 442 throw std::runtime_error(
"We can not search for extrapolation/interpolation " 443 "segment in an 1D table for non-finite value " +
444 std::to_string(getValue(x)) +
" .");
447 if (!extrapolate && !
applies(x))
448 throw std::logic_error(
"Trying to evaluate a tabulated function outside of its range");
452 throw std::logic_error(
"We need at least two sampling points to " 453 "do interpolation/extrapolation, " 454 "and the table only contains " +
459 if (x <= xValues_[1])
460 return SegmentIndex{0};
461 else if (x >= xValues_[xValues_.size() - 2])
462 return SegmentIndex{xValues_.size() - 2};
465 std::size_t lowerIdx = 1;
466 std::size_t upperIdx = xValues_.size() - 2;
467 while (lowerIdx + 1 < upperIdx) {
468 std::size_t pivotIdx = (lowerIdx + upperIdx) / 2;
469 if (x < xValues_[pivotIdx])
475 if (xValues_[lowerIdx] > x || x > xValues_[lowerIdx + 1]) {
476 std::string msg =
"Problematic interpolation/extrapolation " 477 "segment is found for the input value " +
478 std::to_string(Opm::getValue(x)) +
479 "\nthe lower index of the found segment is " +
480 std::to_string(lowerIdx) +
481 ", the size of the table is " +
483 ",\nand the end values of the found segment are " +
484 std::to_string(xValues_[lowerIdx]) +
486 std::to_string(xValues_[lowerIdx + 1]) +
488 msg +=
"Outputting the problematic table for more information " 489 "(with *** marking the found segment):";
490 for (std::size_t i = 0; i <
numSamples(); ++i) {
495 msg +=
" " + std::to_string(xValues_[i]);
496 if (i == lowerIdx + 1)
501 throw std::runtime_error(msg);
503 return SegmentIndex{lowerIdx};
508 template <
class Evaluation>
509 Evaluation evalDerivative_(
const Evaluation& x, std::size_t segIdx)
const 512 Scalar x0 = xValues_[segIdx];
513 Scalar x1 = xValues_[segIdx + 1];
515 Scalar y0 = yValues_[segIdx];
516 Scalar y1 = yValues_[segIdx + 1];
518 Evaluation ret = blank(x);
519 ret = (y1 - y0)/(x1 - x0);
531 int updateMonotonicity_(std::size_t i,
int& r)
const 533 if (yValues_[i] < yValues_[i + 1]) {
535 if (r == 3 || r == 1)
541 else if (yValues_[i] > yValues_[i + 1]) {
543 if (r == 3 || r == -1)
558 explicit ComparatorX_(
const std::vector<Scalar>& x)
562 bool operator ()(std::size_t idxA, std::size_t idxB)
const 563 {
return x_.at(idxA) < x_.at(idxB); }
565 const std::vector<Scalar>& x_;
576 std::vector<unsigned> idxVector(n);
577 for (
unsigned i = 0; i < n; ++i)
582 ComparatorX_ cmp(xValues_);
583 std::ranges::sort(idxVector, cmp);
586 std::vector<Scalar> tmpX(n), tmpY(n);
587 for (std::size_t i = 0; i < idxVector.size(); ++ i) {
588 tmpX[i] = xValues_[idxVector[i]];
589 tmpY[i] = yValues_[idxVector[i]];
599 void reverseSamplingPoints_()
603 for (std::size_t i = 0; i <= (n - 1)/2; ++i) {
604 std::swap(xValues_[i], xValues_[n - i - 1]);
605 std::swap(yValues_[i], yValues_[n - i - 1]);
612 void resizeArrays_(std::size_t nSamples)
614 xValues_.resize(nSamples);
615 yValues_.resize(nSamples);
618 std::vector<Scalar> xValues_;
619 std::vector<Scalar> yValues_;
bool applies(const Evaluation &x) const
Return true iff the given x is in range [x1, xn].
Definition: Tabulated1DFunction.hpp:253
Scalar xMin() const
Return the x value of the leftmost sampling point.
Definition: Tabulated1DFunction.hpp:222
Evaluation evalDerivative(const Evaluation &x, bool extrapolate=false) const
Evaluate the spline's derivative at a given position.
Definition: Tabulated1DFunction.hpp:297
void setXYContainers(const ScalarContainerX &x, const ScalarContainerY &y, bool sortInputs=true)
Set the sampling points for the piecewise linear function.
Definition: Tabulated1DFunction.hpp:135
Evaluation evalThirdDerivative(const Evaluation &, bool=false) const
Evaluate the function's third derivative at a given position.
Definition: Tabulated1DFunction.hpp:336
std::size_t numSamples() const
Returns the number of sampling points.
Definition: Tabulated1DFunction.hpp:216
Scalar valueAt(std::size_t i) const
Return the value of the a sample point with a given index.
Definition: Tabulated1DFunction.hpp:246
Tabulated1DFunction()
Default constructor for a piecewise linear function.
Definition: Tabulated1DFunction.hpp:59
This class implements a small container which holds the transmissibility mulitpliers for all the face...
Definition: Exceptions.hpp:30
Evaluation eval(const Evaluation &x, bool extrapolate=false) const
Evaluate the spline at a given position.
Definition: Tabulated1DFunction.hpp:266
A number of commonly used algebraic functions for the localized OPM automatic differentiation (AD) fr...
Tabulated1DFunction(const PointContainer &points, bool sortInputs=true)
Convenience constructor for a piecewise linear function.
Definition: Tabulated1DFunction.hpp:100
Scalar xMax() const
Return the x value of the rightmost sampling point.
Definition: Tabulated1DFunction.hpp:228
int monotonic() const
Same as monotonic(x0, x1), but with the entire range of the function as interval. ...
Definition: Tabulated1DFunction.hpp:412
Tabulated1DFunction(std::size_t nSamples, const ScalarArrayX &x, const ScalarArrayY &y, bool sortInputs=true)
Convenience constructor for a piecewise linear function.
Definition: Tabulated1DFunction.hpp:71
void setArrayOfPoints(std::size_t nSamples, const PointArray &points, bool sortInputs=true)
Set the sampling points for the piecewise linear function.
Definition: Tabulated1DFunction.hpp:157
Evaluation evalSecondDerivative(const Evaluation &, bool=false) const
Evaluate the function's second derivative at a given position.
Definition: Tabulated1DFunction.hpp:318
int monotonic(Scalar x0, Scalar x1, [[maybe_unused]] bool extrapolate=false) const
Returns 1 if the function is monotonically increasing, -1 if the function is mononously decreasing an...
Definition: Tabulated1DFunction.hpp:347
void printCSV(Scalar xi0, Scalar xi1, unsigned k, std::ostream &os) const
Prints k tuples of the format (x, y, dx/dy, isMonotonic) to stdout.
Definition: Tabulated1DFunction.cpp:33
void setContainerOfTuples(const XYContainer &points, bool sortInputs=true)
Set the sampling points of the piecewise linear function using a STL-compatible container of tuple-li...
Definition: Tabulated1DFunction.hpp:192
void setXYArrays(std::size_t nSamples, const ScalarArrayX &x, const ScalarArrayY &y, bool sortInputs=true)
Set the sampling points for the piecewise linear function.
Definition: Tabulated1DFunction.hpp:110
Implements a linearly interpolated scalar function that depends on one variable.
Definition: Tabulated1DFunction.hpp:51
Scalar xAt(std::size_t i) const
Return the x value of the a sample point with a given index.
Definition: Tabulated1DFunction.hpp:234
Definition: Tabulated1DFunction.hpp:42
Tabulated1DFunction(const ScalarContainer &x, const ScalarContainer &y, bool sortInputs=true)
Convenience constructor for a piecewise linear function.
Definition: Tabulated1DFunction.hpp:87