votca 2024-dev
Loading...
Searching...
No Matches
cubicspline.h
Go to the documentation of this file.
1/*
2 * Copyright 2009-2020 The VOTCA Development Team (http://www.votca.org)
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18#ifndef VOTCA_TOOLS_CUBICSPLINE_H
19#define VOTCA_TOOLS_CUBICSPLINE_H
20
21// Standard includes
22#include <iostream>
23
24// Local VOTCA includes
25#include "eigen.h"
26#include "spline.h"
27
28namespace votca {
29namespace tools {
30
54class CubicSpline : public Spline {
55 public:
56 // default constructor
57 CubicSpline() = default;
58
59 // destructor
60 ~CubicSpline() override = default;
61
62 // construct an interpolation spline
63 // x, y are the the points to construct interpolation, both vectors must be of
64 // same size
65 void Interpolate(const Eigen::VectorXd &x, const Eigen::VectorXd &y) override;
66
67 // fit spline through noisy data
68 // x,y are arrays with noisy data, both vectors must be of same size
69 void Fit(const Eigen::VectorXd &x, const Eigen::VectorXd &y) override;
70
71 // Calculate the function value
72 double Calculate(double r) override;
73
74 // Calculate the function derivative
75 double CalculateDerivative(double r) override;
76
79
80 // set spline parameters to values that were externally computed
81 void setSplineData(const Eigen::VectorXd &f, const Eigen::VectorXd &f2) {
82 f_ = f;
83 f2_ = f2;
84 }
85
96 template <typename matrix_type>
97 void AddToFitMatrix(matrix_type &M, double x, Index offset1,
98 Index offset2 = 0, double scale = 1);
99
111 template <typename matrix_type>
112 void AddToFitMatrix(matrix_type &M, double x, Index offset1, Index offset2,
113 double scale1, double scale2);
114
123 template <typename matrix_type, typename vector_type>
124 void AddToFitMatrix(matrix_type &M, vector_type &x, Index offset1,
125 Index offset2 = 0);
126
133 template <typename matrix_type>
134 void AddBCSumZeroToFitMatrix(matrix_type &M, Index offset1,
135 Index offset2 = 0);
136
143 template <typename matrix_type>
144 void AddBCToFitMatrix(matrix_type &M, Index offset1, Index offset2 = 0);
145
146 private:
147 // y values of grid points
148 Eigen::VectorXd f_;
149 // second derivatives of grid points
150 Eigen::VectorXd f2_;
151 // A spline can be written in the form
152 // S_i(x) = A(x,x_i,x_i+1)*f_i + B(x,x_i,x_i+1)*f'' i_
153 // + C(x,x_i,x_i+1)*f_{i+1} + D(x,x_i,x_i+1)*f''_{i+1}
154 double A(double r);
155 double B(double r);
156 double C(double r);
157 double D(double r);
158
159 double Aprime(double r);
160 double Bprime(double r);
161 double Cprime(double r);
162 double Dprime(double r);
163
164 // tabulated derivatives at grid points. Second argument: 0 - left, 1 - right
165 double A_prime_l(Index i);
166 double A_prime_r(Index i);
167 double B_prime_l(Index i);
168 double B_prime_r(Index i);
169 double C_prime_l(Index i);
170 double C_prime_r(Index i);
171 double D_prime_l(Index i);
172 double D_prime_r(Index i);
173};
174
175template <typename matrix_type>
176inline void CubicSpline::AddToFitMatrix(matrix_type &M, double x, Index offset1,
177 Index offset2, double scale) {
178 Index spi = getInterval(x);
179 M(offset1, offset2 + spi) += A(x) * scale;
180 M(offset1, offset2 + spi + 1) += B(x) * scale;
181 M(offset1, offset2 + spi + r_.size()) += C(x) * scale;
182 M(offset1, offset2 + spi + r_.size() + 1) += D(x) * scale;
183}
184
185// for adding f'(x)*scale1 + f(x)*scale2 as needed for threebody interactions
186template <typename matrix_type>
187inline void CubicSpline::AddToFitMatrix(matrix_type &M, double x, Index offset1,
188 Index offset2, double scale1,
189 double scale2) {
190 Index spi = getInterval(x);
191 M(offset1, offset2 + spi) += Aprime(x) * scale1;
192 M(offset1, offset2 + spi + 1) += Bprime(x) * scale1;
193 M(offset1, offset2 + spi + r_.size()) += Cprime(x) * scale1;
194 M(offset1, offset2 + spi + r_.size() + 1) += Dprime(x) * scale1;
195
196 AddToFitMatrix(M, x, offset1, offset2, scale2);
197}
198
199template <typename matrix_type, typename vector_type>
200inline void CubicSpline::AddToFitMatrix(matrix_type &M, vector_type &x,
201 Index offset1, Index offset2) {
202 for (Index i = 0; i < x.size(); ++i) {
203 Index spi = getInterval(x(i));
204 M(offset1 + i, offset2 + spi) = A(x(i));
205 M(offset1 + i, offset2 + spi + 1) = B(x(i));
206 M(offset1 + i, offset2 + spi + r_.size()) = C(x(i));
207 M(offset1 + i, offset2 + spi + r_.size() + 1) = D(x(i));
208 }
209}
210
211template <typename matrix_type>
212inline void CubicSpline::AddBCSumZeroToFitMatrix(matrix_type &M, Index offset1,
213 Index offset2) {
214 for (Index i = 0; i < r_.size(); ++i) {
215 M(offset1, offset2 + i) = 1;
216 M(offset1, offset2 + r_.size() + i) = 0;
217 }
218}
219
220template <typename matrix_type>
221inline void CubicSpline::AddBCToFitMatrix(matrix_type &M, Index offset1,
222 Index offset2) {
223 for (Index i = 0; i < r_.size() - 2; ++i) {
224 M(offset1 + i + 1, offset2 + i) = A_prime_l(i);
225 M(offset1 + i + 1, offset2 + i + 1) = B_prime_l(i) - A_prime_r(i);
226 M(offset1 + i + 1, offset2 + i + 2) = -B_prime_r(i);
227
228 M(offset1 + i + 1, offset2 + r_.size() + i) = C_prime_l(i);
229 M(offset1 + i + 1, offset2 + r_.size() + i + 1) =
230 D_prime_l(i) - C_prime_r(i);
231 M(offset1 + i + 1, offset2 + r_.size() + i + 2) = -D_prime_r(i);
232 }
233 switch (boundaries_) {
234 case splineNormal:
235 M(offset1, offset2 + r_.size()) = 1;
236 M(offset1 + r_.size() - 1, offset2 + 2 * r_.size() - 1) = 1;
237 break;
239 // y
240 M(offset1 + 0, offset2 + 0) = -1 * A_prime_l(0);
241 M(offset1 + 0, offset2 + 1) = -1 * B_prime_l(0);
242
243 M(offset1 + r_.size() - 1, offset2 + r_.size() - 2) =
244 A_prime_l(r_.size() - 2);
245 M(offset1 + r_.size() - 1, offset2 + r_.size() - 1) =
246 B_prime_l(r_.size() - 2);
247
248 // y''
249 M(offset1 + 0, offset2 + r_.size() + 0) = D_prime_l(0);
250 M(offset1 + 0, offset2 + r_.size() + 1) = C_prime_l(0);
251
252 M(offset1 + r_.size() - 1, offset2 + 2 * r_.size() - 2) =
253 C_prime_l(r_.size() - 2);
254 M(offset1 + r_.size() - 1, offset2 + 2 * r_.size() - 1) =
255 D_prime_l(r_.size() - 2);
256 break;
257 case splinePeriodic:
258 M(offset1, offset2) = 1;
259 M(offset1, offset2 + r_.size() - 1) = -1;
260 M(offset1 + r_.size() - 1, offset2 + r_.size()) = 1;
261 M(offset1 + r_.size() - 1, offset2 + 2 * r_.size() - 1) = -1;
262 break;
263 }
264}
265
266} // namespace tools
267} // namespace votca
268
269#endif // VOTCA_TOOLS_CUBICSPLINE_H
A cubic spline class.
Definition cubicspline.h:54
void AddBCSumZeroToFitMatrix(matrix_type &M, Index offset1, Index offset2=0)
Add boundary condition of sum_i f_i =0 to fitting matrix.
double Cprime(double r)
void Interpolate(const Eigen::VectorXd &x, const Eigen::VectorXd &y) override
Calculate interpolating spline for given (x,y) values. Points on resulting spline can be obtained via...
double C_prime_l(Index i)
void AddToFitMatrix(matrix_type &M, double x, Index offset1, Index offset2=0, double scale=1)
Add a point (one entry) to fitting matrix.
double Aprime(double r)
double Dprime(double r)
void Fit(const Eigen::VectorXd &x, const Eigen::VectorXd &y) override
Fit spline through noisy (x,y) values. Points on resulting fitted spline can be obtained via Calculat...
double D_prime_l(Index i)
double D_prime_r(Index i)
double B_prime_r(Index i)
~CubicSpline() override=default
double B_prime_l(Index i)
double Calculate(double r) override
Calculate spline function value for a given x value on the spline created by Interpolate() or Fit()
double A_prime_r(Index i)
void setSplineData(const Eigen::VectorXd &f, const Eigen::VectorXd &f2)
Definition cubicspline.h:81
double CalculateDerivative(double r) override
Calculate y value for a given x value on the derivative of the spline created by function Interpolate...
void AddBCToFitMatrix(matrix_type &M, Index offset1, Index offset2=0)
Add boundary conditions to fitting matrix.
double Bprime(double r)
double C_prime_r(Index i)
double A_prime_l(Index i)
Spline Class.
Definition spline.h:36
virtual double CalculateDerivative(double x)=0
Calculate y value for a given x value on the derivative of the spline created by function Interpolate...
virtual double Calculate(double x)=0
Calculate spline function value for a given x value on the spline created by Interpolate() or Fit()
Eigen::VectorXd r_
Definition spline.h:173
eBoundary boundaries_
Get the spline data f_.
Definition spline.h:171
Index getInterval(double r)
Determine the index of the interval containing value r.
Definition spline.cc:62
@ splineDerivativeZero
derivatives and end-points are zero.
Definition spline.h:76
@ splinePeriodic
periodic boundary conditions:
Definition spline.h:75
@ splineNormal
normal boundary conditions:
Definition spline.h:74
base class for all analysis tools
Definition basebead.h:33
Eigen::Index Index
Definition types.h:26