33template<
typename Scalar>
59 CubicSpline(
const std::vector<Scalar>& X,
const std::vector<Scalar>& Y,
79 void setPoints(
const std::vector<Scalar>& x,
const std::vector<Scalar>& y)
88 std::vector<Scalar> rhs(n);
89 for (
size_t i = 1; i < n - 1; i++)
91 A(i, i - 1) = 1.0 / 3.0 * (x[i] - x[i - 1]);
92 A(i, i) = 2.0 / 3.0 * (x[i + 1] - x[i - 1]);
93 A(i, i + 1) = 1.0 / 3.0 * (x[i + 1] - x[i]);
94 rhs[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i]) - (y[i] - y[i - 1]) / (x[i] - x[i - 1]);
108 A(0, 0) = 2.0 * (x[1] - x[0]);
109 A(0, 1) = 1.0 * (x[1] - x[0]);
116 A(0, 0) = -(x[2] - x[1]);
117 A(0, 1) = x[2] - x[0];
118 A(0, 2) = -(x[1] - x[0]);
124 A(n - 1, n - 1) = 2.0;
125 A(n - 1, n - 2) = 0.0;
133 A(n - 1, n - 1) = 2.0 * (x[n - 1] - x[n - 2]);
134 A(n - 1, n - 2) = 1.0 * (x[n - 1] - x[n - 2]);
141 A(n - 1, n - 3) = -(x[n - 1] - x[n - 2]);
142 A(n - 1, n - 2) = x[n - 1] - x[n - 3];
143 A(n - 1, n - 1) = -(x[n - 2] - x[n - 3]);
153 for (
size_t i = 0; i < n - 1; i++)
156 coef_b[i] = (y[i + 1] - y[i]) / (x[i + 1] - x[i])
157 - 1.0 / 3.0 * (2.0 *
coef_c[i] +
coef_c[i + 1]) * (x[i + 1] - x[i]);
161 auto h = x[n - 1] - x[n - 2];
174 [[nodiscard]]
size_t size() const noexcept
205 [[nodiscard]] Scalar
derivative(
size_t order, Scalar x)
const
223 else if (x >
vals_x[n - 1])
230 return 2.0 *
coef_c[n - 1];
267 auto it = std::upper_bound(
vals_x.begin(),
vals_x.end(), x);
268 return static_cast<size_t>(std::max(
static_cast<int>(it -
vals_x.begin()) - 1, 0));
289 [[nodiscard]]
const Scalar&
operator()(
size_t i,
size_t j)
const
298 [[nodiscard]] std::vector<Scalar>
lu_solve(
const std::vector<Scalar>& b,
bool is_lu_decomposed =
false)
300 INS_ASSERT_USER_ERROR(
dim() == b.size(),
"The BandMatrix dimension must be the same as the vector b in the equation Ax = b.");
302 if (!is_lu_decomposed)
313 [[nodiscard]]
size_t dim()
const
333 for (
size_t i = 0; i <
dim(); i++)
335 assert(this->
operator()(i, i) != 0.0);
339 for (
size_t j = j_min; j <= j_max; j++)
347 for (
size_t k = 0; k <
dim(); k++)
350 for (
size_t i = k + 1; i <= i_max; i++)
352 assert(this->
operator()(k, k) != 0.0);
357 for (
size_t j = k + 1; j <= j_max; j++)
367 [[nodiscard]] std::vector<Scalar>
l_solve(
const std::vector<Scalar>& b)
const
369 INS_ASSERT_USER_ERROR(
dim() == b.size(),
"The BandMatrix dimension must be the same as the vector b in the equation Ax = b.");
371 std::vector<Scalar> x(
dim());
372 for (
size_t i = 0; i <
dim(); i++)
376 for (
size_t j = j_start; j < i; j++)
385 [[nodiscard]] std::vector<Scalar>
u_solve(
const std::vector<Scalar>& b)
const
387 INS_ASSERT_USER_ERROR(
dim() == b.size(),
"The BandMatrix dimension must be the same as the vector b in the equation Ax = b.");
389 std::vector<Scalar> x(
dim());
390 for (
size_t i =
dim(); i-- > 0;)
394 for (
size_t j = i + 1; j <= j_stop; j++)
398 x[i] = (b[i] - sum) / this->
operator()(i, i);
#define INS_ASSERT_USER_ERROR(_EXP, _MSG)
Assert function with message.
Sparse matrix whose non-zero entries are confined to a diagonal band, comprising the main diagonal an...
std::vector< Scalar > lu_solve(const std::vector< Scalar > &b, bool is_lu_decomposed=false)
std::vector< std::vector< Scalar > > upperBand
upper diagonal band
std::vector< std::vector< Scalar > > lowerBand
lower diagonal band
BandMatrix(size_t dim, size_t nUpper, size_t nLower)
Constructor.
size_t dimLowerBand() const
Returns the dimension of the lower band.
Scalar & operator()(size_t i, size_t j)
Access operator i ∈ [i=0,...,dim()-1].
size_t dim() const
Returns the matrix dimension.
std::vector< Scalar > u_solve(const std::vector< Scalar > &b) const
Solves the equation Ux = b for x.
std::vector< Scalar > l_solve(const std::vector< Scalar > &b) const
Solves the equation Lx = b for x.
void lu_decompose()
Calculate the LU decomposition.
size_t dimUpperBand() const
Returns the dimension of the upper band.
const Scalar & operator()(size_t i, size_t j) const
Access operator i ∈ [i=0,...,dim()-1].
void setPoints(const std::vector< Scalar > &x, const std::vector< Scalar > &y)
Set the points/knots of the spline and calculate the spline coefficients.
size_t findClosestIdx(Scalar x) const
Finds the closest index so that vals_x[idx] <= x (return 0 if x < vals_x[0])
std::vector< Scalar > vals_y
y coordinates of the knots
void setBoundaries(BoundaryCondition leftBoundaryCondition, BoundaryCondition rightBoundaryCondition)
Set the boundaries conditions. Has to be called before setPoints.
CubicSpline(const std::vector< Scalar > &X, const std::vector< Scalar > &Y, BoundaryCondition leftBoundaryCondition={ BoundaryCondition::SecondDerivative, 0.0 }, BoundaryCondition rightBoundaryCondition={ BoundaryCondition::SecondDerivative, 0.0 })
Constructor.
std::vector< Scalar > coef_b
Spline coefficients b.
CubicSpline()=default
Default Constructor.
Scalar derivative(size_t order, Scalar x) const
Calculates the derivative of the spline.
Scalar coef_c0
Spline coefficient c0 for left extrapolation.
size_t size() const noexcept
Returns the size of the spline vector.
BoundaryCondition boundaryConditionRight
Boundary condition for the right knot.
std::vector< Scalar > coef_d
Spline coefficients d.
Scalar operator()(Scalar x) const
Interpolates or extrapolates a value on the spline.
std::vector< Scalar > coef_c
Spline coefficients c.
BoundaryCondition boundaryConditionLeft
Boundary condition for the left knot.
std::vector< Scalar > vals_x
x coordinates of the knots
Boundary conditions for the spline end-points.
BoundaryType type
Type of the boundary condition.
Scalar value
Value of the boundary condition.
BoundaryType
Boundary type.
@ NotAKnot
not-a-knot: At the first and last interior break, even the third derivative is continuous (up to roun...
@ FirstDerivative
First derivative has to match a certain value.
@ SecondDerivative
Second derivative has to match a certain value.