ampsci
High-precision calculations for one- and two-valence atomic systems
Interpolator.hpp
1#pragma once
2#include <cassert>
3#include <gsl/gsl_errno.h>
4#include <gsl/gsl_spline.h>
5#include <gsl/gsl_version.h>
6#include <iostream>
7#include <map>
8#include <vector>
9
10// This should make code work with old versions of GSL
11#ifdef GSL_MAJOR_VERSION
12#if GSL_MAJOR_VERSION == 1
13#define GSL_VERSION_1
14#endif
15#endif
16
17//! Interpolates functions using cubic splines. Uses GSL:
18//! https://www.gnu.org/software/gsl/doc/html/interp.html
19namespace Interpolator {
20
21//! Method (type) of 1D Interpolation used
22/*! @details
23The following interpolation types are provided by GSL
24(see https://www.gnu.org/software/gsl/doc/html/interp.html#c.gsl_interp_type)
25
26linear
27
28 * Linear interpolation. This interpolation method does not require any additional memory.
29
30polynomial
31
32 * Polynomial interpolation. This method should only be used for interpolating small numbers of points because polynomial interpolation introduces large oscillations, even for well-behaved datasets. The number of terms in the interpolating polynomial is equal to the number of points.
33
34cspline
35
36 * Cubic spline with natural boundary conditions. The resulting curve is piecewise cubic on each interval, with matching first and second derivatives at the supplied data-points. The second derivative is chosen to be zero at the first point and last point.
37
38cspline_periodic
39
40 * Cubic spline with periodic boundary conditions. The resulting curve is piecewise cubic on each interval, with matching first and second derivatives at the supplied data-points. The derivatives at the first and last points are also matched. Note that the last point in the data must have the same y-value as the first point, otherwise the resulting periodic interpolation will have a discontinuity at the boundary.
41
42akima
43
44 * Non-rounded Akima spline with natural boundary conditions. This method uses the non-rounded corner algorithm of Wodicka.
45
46akima_periodic
47
48 * Non-rounded Akima spline with periodic boundary conditions. This method uses the non-rounded corner algorithm of Wodicka.
49
50steffen
51
52 * Steffen's method guarantees the monotonicity of the interpolating function between the given data points. Therefore, minima and maxima can only occur exactly at the data points, and there can never be spurious oscillations between data points. The interpolated function is piecewise cubic in each interval. The resulting curve and its first derivative are guaranteed to be continuous, but the second derivative may be discontinuous.
53
54*/
55enum class Method {
56 //! linear interpolation
57 linear,
58 //! polynomial interpolation
60 //! cubic b-spline interpolation
61 cspline,
62 //! cubic b-spline interpolation with periodic boundary condition
64 //! akima interpolation
65 akima,
66 //! akima interpolation with periodic boundary condition
68 //! steffen interpolation (ensure monotonicity between points). Only GSLv2+
70};
71
72//! Maps from enum 'Interpolator::Method' to gsl_interp_type
73static const std::map<Method, const gsl_interp_type *> interp_method{
74 {Method::linear, gsl_interp_linear},
75 {Method::polynomial, gsl_interp_polynomial},
76 {Method::cspline, gsl_interp_cspline},
77 {Method::cspline_periodic, gsl_interp_cspline_periodic},
78 {Method::akima, gsl_interp_akima},
79 {Method::akima_periodic, gsl_interp_akima_periodic}
80#ifndef GSL_VERSION_1
81 ,
82 {Method::steffen, gsl_interp_steffen}
83#endif
84};
85
86//==============================================================================
87
88//! Performs interpolation using GSL (GNU Scientific Library)
89/*! @details
90 On construction takes in vectors x and y, to be interpolated.
91 These are intepreted as function values y(x) at descrete points x.
92 x and y dimensions must match.
93 Given new x', will return y(x') based on interpolation.
94 NOTE: Interpolates, but does NOT extrapolate! Everything outside the region (xmin,xmax) from initial input will be zero.
95 It may use any interpolation method provided by GSL library.
96 See Interpolator::Method for list of options.
97 By default, cspline (cubic b-spline) method is used.
98 Note: gsl function takes *pointers* to x and y data. Therefore, vectors x and y should outlive the Interp object
99*/
100class Interp {
101
102private:
103 gsl_interp_accel *acc;
104 gsl_spline *spline;
105 double x0, xmax;
106
107public:
108 //! x_in and y_in
109 Interp(const std::vector<double> &x, const std::vector<double> &y,
110 Method method = Method::cspline)
111 : acc(gsl_interp_accel_alloc()),
112 spline(gsl_spline_alloc(interp_method.at(method), x.size())),
113 x0(x.front()),
114 xmax(x.back()) {
115 assert(x.size() == y.size() &&
116 "In Interp, input vectors x and y must have same size");
117 assert(x.size() >= gsl_interp_type_min_size(interp_method.at(method)) &&
118 "In Interp, certain interpolation methods require a minimum number "
119 "of points");
120 gsl_spline_init(spline, x.data(), y.data(), x.size());
121 }
122 ~Interp() {
123 gsl_spline_free(spline);
124 gsl_interp_accel_free(acc);
125 }
126 Interp(const Interpolator::Interp &) = delete;
127 Interp &operator=(const Interpolator::Interp &) = delete;
128
129 //! Evaluates interpolation function at point x. Does not extrapolate.
130 double interp(double x) const {
131 if (x < x0 || x > xmax)
132 return 0.0;
133 else
134 return gsl_spline_eval(spline, x, acc);
135 }
136
137 //! Evaluates interpolation function at set of points {x}. Does not extrapolate.
138 std::vector<double> interp(const std::vector<double> &x) const {
139 std::vector<double> y;
140 y.reserve(x.size());
141 for (auto xi : x)
142 y.push_back(interp(xi));
143 return y;
144 }
145
146 //! Evaluates interpolation function at point x. Does not extrapolate.
147 double operator()(double x) const { return interp(x); }
148
149 //! Evaluates interpolation function at set of points {x}. Does not extrapolate.
150 std::vector<double> operator()(const std::vector<double> &x) const {
151 return interp(x);
152 }
153};
154
155//==============================================================================
156
157//! Performs interpolation using GSL (GNU Scientific Library)
158/*! @details Takes set of points {xin, yin}, interpolates and evaluates new y
159 values at positions defined by {x_out}; returns as vector.
160 Just a wrapper for class Interp
161*/
162inline std::vector<double> interpolate(const std::vector<double> &x_in,
163 const std::vector<double> &y_in,
164 const std::vector<double> &x_out,
165 Method method = Method::cspline) {
166 Interp i_func(x_in, y_in, method);
167 return i_func(x_out);
168}
169
170//==============================================================================
171
172//! Check if steffen method available (only with GSL version 2+)
173static constexpr bool has_steffen_method() {
174#ifndef GSL_VERSION_1
175 return true;
176#else
177 return false;
178#endif
179}
180
181} // namespace Interpolator
Performs interpolation using GSL (GNU Scientific Library)
Definition Interpolator.hpp:100
double interp(double x) const
Evaluates interpolation function at point x. Does not extrapolate.
Definition Interpolator.hpp:130
double operator()(double x) const
Evaluates interpolation function at point x. Does not extrapolate.
Definition Interpolator.hpp:147
Interp(const std::vector< double > &x, const std::vector< double > &y, Method method=Method::cspline)
x_in and y_in
Definition Interpolator.hpp:109
std::vector< double > operator()(const std::vector< double > &x) const
Evaluates interpolation function at set of points {x}. Does not extrapolate.
Definition Interpolator.hpp:150
std::vector< double > interp(const std::vector< double > &x) const
Evaluates interpolation function at set of points {x}. Does not extrapolate.
Definition Interpolator.hpp:138
Interpolates functions using cubic splines. Uses GSL: https://www.gnu.org/software/gsl/doc/html/inter...
Definition Interpolator.hpp:19
std::vector< double > interpolate(const std::vector< double > &x_in, const std::vector< double > &y_in, const std::vector< double > &x_out, Method method=Method::cspline)
Performs interpolation using GSL (GNU Scientific Library)
Definition Interpolator.hpp:162
Method
Method (type) of 1D Interpolation used.
Definition Interpolator.hpp:55
@ polynomial
polynomial interpolation
@ akima_periodic
akima interpolation with periodic boundary condition
@ cspline_periodic
cubic b-spline interpolation with periodic boundary condition
@ linear
linear interpolation
@ cspline
cubic b-spline interpolation
@ steffen
steffen interpolation (ensure monotonicity between points). Only GSLv2+
@ akima
akima interpolation