HydroFemPhysics
The GeMA Hydraulic FEM Physics Plugin
Loading...
Searching...
No Matches
gmpPiecewiseCurve.h
Go to the documentation of this file.
1/************************************************************************
2**
3** Copyright (C) 2014 by Carlos Augusto Teixera Mendes
4** All rights reserved.
5**
6** This file is part of the "GeMA" software. It's use should respect
7** the terms in the license agreement that can be found together
8** with this source code.
9** It is provided AS IS, with NO WARRANTY OF ANY KIND,
10** INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR
11** A PARTICULAR PURPOSE.
12**
13************************************************************************/
14
24#include <gmTrace.h>
25#include <gmLog.h>
26#include <assert.h>
27#include <cmath>
28#include <limits>
29#include <gmMathUtils.h>
30
31#ifndef _GEMA_PIECEWISECURVE_H_
32#define _GEMA_PIECEWISECURVE_H_
33
34#ifndef EPSILON
35#define EPSILON 2.2204460492503131e-016
36#endif
37
38namespace GmpPiecewiseCurve
39{
40 // -----------------------------------------------------------------------------------------------------------
43 int findInterval(double value, GmCRMatrix& curve, int col)
44 {
45 S_TRACE();
46 // Check if the given point is located inside the interval defined by the curve
47 if (curve(0, col) < curve(curve.n_rows - 1, col))
48 {
49 /* Monotonically increasing curve */
50 if (value < curve(0, col))
51 return 1;
52 if (value > curve(curve.n_rows - 1, col))
53 return curve.n_rows - 1;
54 int i = 1;
55 while (curve(i, col) < value)
56 i++;
57 return i;
58 }
59 else
60 {
61 /* Monotonically decreasing curve */
62 if (value > curve(0, col))
63 return 1;
64 if (value < curve(curve.n_rows - 1, col))
65 return curve.n_rows - 1;
66 int i = 1;
67 while (curve(i, col) > value)
68 i++;
69 return i;
70 }
71
72 return -1;
73 }
74
75 // -----------------------------------------------------------------------------------------------------------
77 double interpolate(double x, GmCRMatrix& curve, const GmLogCategory& logger)
78 {
79 S_TRACE();
80 // Find the interval where the x value is located
81 int i = findInterval(x, curve, 0);
82 if (i < 1)
83 {
84 gmErrorMsg(logger, "GmpPiecewiseCurve: Error 'x' value is out of the curve range.");
85 return std::numeric_limits<double>::quiet_NaN();
86 }
87 // Interpolate the y value
88 double dx = curve(i, 0) - curve(i - 1, 0);
89 double dy = curve(i, 1) - curve(i - 1, 1);
90 if (std::abs(dx) < EPSILON)
91 {
92 gmErrorMsg(logger, "GmpPiecewiseCurve: Error the given curve has repeated x values.");
93 return std::numeric_limits<double>::quiet_NaN();
94 }
95 double y = (dy / dx) * (x - curve(i - 1, 0)) + curve(i - 1, 1);
96 return y;
97 }
98
99 // -----------------------------------------------------------------------------------------------------------
101 double derivativeGivenY(double y, GmCRMatrix& curve, const GmLogCategory& logger)
102 {
103 S_TRACE();
104
105 // Find the interval where the y value is located
106 int i = findInterval(y, curve, 1);
107 if (i < 1)
108 {
109 gmErrorMsg(logger, "GmpPiecewiseCurve: Error 'y' value is out of the curve range.");
110 return std::numeric_limits<double>::quiet_NaN();
111 }
112
113 // Interpolate the y value
114 double dx = curve(i, 0) - curve(i - 1, 0);
115 double dy = curve(i, 1) - curve(i - 1, 1);
116 if (std::abs(dx) > EPSILON)
117 {
118 return dy / dx;
119 }
120 else
121 {
122 return GmMathUtils::sign(dy) / EPSILON;
123 }
124 }
125};
126#endif
const unsigned int n_rows
#define S_TRACE()
double derivativeGivenY(double y, GmCRMatrix &curve, const GmLogCategory &logger)
Returns the derivative of the curve at a given y value.
Definition gmpPiecewiseCurve.h:101
double interpolate(double x, GmCRMatrix &curve, const GmLogCategory &logger)
Returns the corresponding y value for a given x value.
Definition gmpPiecewiseCurve.h:77
int findInterval(double value, GmCRMatrix &curve, int col)
Definition gmpPiecewiseCurve.h:43
int sign(double a)