45#include "math/CubicSpline.hpp"
55 CubicSpline::CubicSpline() : isUniform(true), generated(false) {
60 void CubicSpline::addPoint(
const RealType xp,
const RealType yp) {
65 void CubicSpline::addPoints(
const std::vector<RealType>& xps,
66 const std::vector<RealType>& yps) {
67 assert(xps.size() == yps.size());
69 for (
unsigned int i = 0; i < xps.size(); i++) {
75 void CubicSpline::generate() {
101 for (
int i = 1; i < n; i++) {
102 if ((x_[i] - x_[i - 1]) <= 0.0) sorted =
false;
108 std::vector<int> p = sort_permutation(x_);
109 x_ = apply_permutation(x_, p);
110 y_ = apply_permutation(y_, p);
116 b[0] = x_[1] - x_[0];
117 c[0] = (y_[1] - y_[0]) / b[0];
126 c[0] = -3.0 * pow((y_[1] - y_[0]) / (x_[1] - x_[0]), 2);
127 d[0] = -2.0 * pow((y_[1] - y_[0]) / (x_[1] - x_[0]), 3);
131 dx = 1.0 / (x_[1] - x_[0]);
139 for (
int i = 1; i < n - 1; i++) {
140 b[i] = x_[i + 1] - x_[i];
141 if (fabs(b[i] - b[0]) / b[0] > 1.0e-5) isUniform =
false;
142 c[i] = (y_[i + 1] - y_[i]) / b[i];
143 d[i] = 2.0 * (b[i] + b[i - 1]);
146 d[n - 1] = 2.0 * b[n - 2];
151 fp1 = c[0] - b[0] * (c[1] - c[0]) / (b[0] + b[1]);
155 ((b[0] + b[1]) * (c[2] - c[1]) / (b[1] + b[2]) - c[1] + c[0]) /
158 fpn = c[n - 2] + b[n - 2] * (c[n - 2] - c[n - 3]) / (b[n - 3] + b[n - 2]);
161 fpn = fpn + b[n - 2] *
162 (c[n - 2] - c[n - 3] -
163 (b[n - 3] + b[n - 2]) * (c[n - 3] - c[n - 4]) /
164 (b[n - 3] + b[n - 4])) /
165 (x_[n - 1] - x_[n - 4]);
169 c[n - 1] = 3.0 * (fpn - c[n - 2]);
170 for (
int i = n - 2; i > 0; i--)
171 c[i] = 3.0 * (c[i] - c[i - 1]);
172 c[0] = 3.0 * (c[0] - fp1);
176 for (
int k = 1; k < n; k++) {
177 p = b[k - 1] / d[k - 1];
178 d[k] = d[k] - p * b[k - 1];
179 c[k] = c[k] - p * c[k - 1];
182 c[n - 1] = c[n - 1] / d[n - 1];
184 for (
int k = n - 2; k >= 0; k--)
185 c[k] = (c[k] - b[k] * c[k + 1]) / d[k];
189 for (
int i = 0; i < n - 1; i++) {
190 h = x_[i + 1] - x_[i];
191 d[i] = (c[i + 1] - c[i]) / (3.0 * h);
192 b[i] = (y_[i + 1] - y_[i]) / h - h * (c[i] + h * d[i]);
195 b[n - 1] = b[n - 2] + h * (2.0 * c[n - 2] + h * 3.0 * d[n - 2]);
197 if (isUniform) dx = 1.0 / (x_[1] - x_[0]);
203 RealType CubicSpline::getValueAt(
const RealType& t) {
211 if (!generated) generate();
213 assert(t >= x_.front());
214 assert(t <= x_.back());
220 j = std::max(0, std::min(n - 1,
int((t - x_[0]) * dx)));
225 for (
int i = 0; i < n; i++) {
236 return y_[j] + dt * (b[j] + dt * (c[j] + dt * d[j]));
239 void CubicSpline::getValueAt(
const RealType& t, RealType& v) {
247 if (!generated) generate();
249 assert(t >= x_.front());
250 assert(t <= x_.back());
256 j = std::max(0, std::min(n - 1,
int((t - x_[0]) * dx)));
261 for (
int i = 0; i < n; i++) {
272 v = y_[j] + dt * (b[j] + dt * (c[j] + dt * d[j]));
275 pair<RealType, RealType> CubicSpline::getLimits() {
276 if (!generated) generate();
277 return make_pair(x_.front(), x_.back());
280 RealType CubicSpline::getSpacing() {
281 if (!generated) generate();
289 void CubicSpline::getValueAndDerivativeAt(
const RealType& t, RealType& v,
296 if (!generated) generate();
298 assert(t >= x_.front());
299 assert(t <= x_.back());
305 j = std::max(0, std::min(n - 1,
int((t - x_[0]) * dx)));
310 for (
int i = 0; i < n; i++) {
322 v = y_[j] + dt * (b[j] + dt * (c[j] + dt * d[j]));
323 dv = b[j] + dt * (2.0 * c[j] + 3.0 * dt * d[j]);
326 std::vector<int> CubicSpline::sort_permutation(std::vector<RealType>& v) {
327 std::vector<int> p(v.size());
331 std::vector<int>::iterator i;
332 for (i = p.begin(); i != p.end(); ++i) {
341 std::vector<RealType> CubicSpline::apply_permutation(
342 std::vector<RealType>
const& v, std::vector<int>
const& p) {
343 std::size_t n = p.size();
344 std::vector<RealType> sorted_vec(n);
345 for (std::size_t i = 0; i < n; ++i) {
346 sorted_vec[i] = v[p[i]];
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.