Version: SMASH-3.1
interpolation.h
Go to the documentation of this file.
1 /*
2  *
3  * Copyright (c) 2015-2018,2020,2022
4  * SMASH Team
5  *
6  * GNU General Public License (GPLv3 or later)
7  *
8  */
9 
10 #ifndef SRC_INCLUDE_SMASH_INTERPOLATION_H_
11 #define SRC_INCLUDE_SMASH_INTERPOLATION_H_
12 
13 #include <algorithm>
14 #include <cassert>
15 #include <cstddef>
16 #include <numeric>
17 #include <sstream>
18 #include <stdexcept>
19 #include <string>
20 #include <utility>
21 #include <vector>
22 
23 #include "gsl/gsl_errno.h"
24 #include "gsl/gsl_spline.h"
25 
26 namespace smash {
27 
33 template <typename T>
35  public:
37  T slope_;
45  InterpolateLinear(T x0, T y0, T x1, T y1);
46 
53  T operator()(T x) const;
54 };
55 
61 template <typename T>
63  public:
75  InterpolateDataLinear(const std::vector<T>& x, const std::vector<T>& y);
82  T operator()(T x) const;
83 
84  private:
86  std::vector<T> x_;
88  std::vector<InterpolateLinear<T>> f_;
89 };
90 
91 template <typename T>
92 InterpolateLinear<T>::InterpolateLinear(T x0, T y0, T x1, T y1) {
93  assert(x0 != x1);
94  slope_ = (y1 - y0) / (x1 - x0);
95  yintercept_ = y0 - slope_ * x0;
96 }
97 
98 template <typename T>
100  return slope_ * x + yintercept_;
101 }
102 
125 template <typename T>
126 T interpolate_trilinear(T ax, T ay, T az, T f1, T f2, T f3, T f4, T f5, T f6,
127  T f7, T f8) {
128  T res = az * (ax * (ay * f8 + (1.0 - ay) * f6) +
129  (1.0 - ax) * (ay * f7 + (1.0 - ay) * f5)) +
130  (1 - az) * (ax * (ay * f4 + (1.0 - ay) * f2) +
131  (1.0 - ax) * (ay * f3 + (1.0 - ay) * f1));
132  return res;
133 }
134 
136 using Permutation = std::vector<size_t>;
137 
146 template <typename T, typename Cmp>
147 Permutation generate_sort_permutation(std::vector<T> const& v, Cmp compare) {
148  Permutation p(v.size());
149  std::iota(p.begin(), p.end(), 0);
150  std::sort(p.begin(), p.end(),
151  [&](size_t i, size_t j) { return compare(v[i], v[j]); });
152  return p;
153 }
154 
163 template <typename T>
164 std::vector<T> apply_permutation(const std::vector<T>& v,
165  const Permutation& p) {
166  std::vector<T> copied_v = v;
167  std::transform(p.begin(), p.end(), copied_v.begin(),
168  [&](size_t i) { return v[i]; });
169  return copied_v;
170 }
171 
182 template <typename T>
183 void check_duplicates(const std::vector<T>& x,
184  const std::string& error_position) {
185  auto it = std::adjacent_find(x.begin(), x.end());
186  if (it != x.end()) {
187  std::stringstream error_msg;
188  error_msg << error_position << ": Each x value must be unique. \"" << *it
189  << "\" was found twice.";
190  throw std::runtime_error(error_msg.str());
191  }
192 }
193 
194 template <typename T>
196  const std::vector<T>& y) {
197  assert(x.size() == y.size());
198  const size_t n = x.size();
199  const auto p = generate_sort_permutation(
200  x, [&](T const& a, T const& b) { return a < b; });
201  x_ = apply_permutation(x, p);
202  check_duplicates(x_, "InterpolateDataLinear");
203  std::vector<T> y_sorted = std::move(apply_permutation(y, p));
204  f_.reserve(n - 1);
205  for (size_t i = 0; i < n - 1; i++) {
206  f_.emplace_back(
207  InterpolateLinear<T>(x_[i], y_sorted[i], x_[i + 1], y_sorted[i + 1]));
208  }
209 }
210 
229 template <typename T>
230 size_t find_index(const std::vector<T>& v, T x) {
231  const auto it = std::lower_bound(v.begin(), v.end(), x);
232  if (it == v.begin()) {
233  return 0;
234  } else {
235  return it - 1 - v.begin();
236  }
237 }
238 
239 template <typename T>
241  // Find the piecewise linear interpolation corresponding to x0.
242  size_t i = find_index(x_, x0);
243  if (i >= f_.size()) {
244  // We don't have a linear interpolation beyond the last point in x_.
245  // Use the last linear interpolation instead.
246  i = f_.size() - 1;
247  }
248  return f_[i](x0);
249 }
250 
253  public:
265  InterpolateDataSpline(const std::vector<double>& x,
266  const std::vector<double>& y);
267 
270 
277  double operator()(double x) const;
278 
279  private:
281  double first_x_;
283  double last_x_;
285  double first_y_;
287  double last_y_;
289  gsl_interp_accel* acc_;
291  gsl_spline* spline_;
292 };
293 
294 } // namespace smash
295 
296 #endif // SRC_INCLUDE_SMASH_INTERPOLATION_H_
Represent a piecewise linear interpolation.
Definition: interpolation.h:62
std::vector< InterpolateLinear< T > > f_
Piecewise linear interpolation using f(x_i)
Definition: interpolation.h:88
std::vector< T > x_
x_i
Definition: interpolation.h:86
T operator()(T x) const
Calculate spline interpolation at x.
InterpolateDataLinear(const std::vector< T > &x, const std::vector< T > &y)
Interpolate function f given discrete samples f(x_i) = y_i.
Represent a cubic spline interpolation.
double first_x_
First x value.
gsl_spline * spline_
GSL spline.
InterpolateDataSpline(const std::vector< double > &x, const std::vector< double > &y)
Interpolate function f given discrete samples f(x_i) = y_i.
double last_y_
Last y value.
double operator()(double x) const
Calculate spline interpolation at x.
double first_y_
First y value.
gsl_interp_accel * acc_
GSL iterator for interpolation lookups.
double last_x_
Last x value.
Represent a linear interpolation.
Definition: interpolation.h:34
T yintercept_
y-axis intercept of the linear interpolation.
Definition: interpolation.h:39
T operator()(T x) const
Calculate spline interpolation at x.
Definition: interpolation.h:99
T slope_
Slope of the linear interpolation.
Definition: interpolation.h:37
InterpolateLinear(T x0, T y0, T x1, T y1)
Linear interpolation given two points (x0, y0) and (x1, y1).
Definition: interpolation.h:92
constexpr int p
Proton.
constexpr int n
Neutron.
Definition: action.h:24
size_t find_index(const std::vector< T > &v, T x)
Find the index in v that corresponds to the last value strictly smaller than x.
std::vector< T > apply_permutation(const std::vector< T > &v, const Permutation &p)
Apply a permutation to a vector.
void check_duplicates(const std::vector< T > &x, const std::string &error_position)
Check whether two components have the same value in a sorted vector x.
T interpolate_trilinear(T ax, T ay, T az, T f1, T f2, T f3, T f4, T f5, T f6, T f7, T f8)
Perform a trilinear 1st order interpolation.
Permutation generate_sort_permutation(std::vector< T > const &v, Cmp compare)
Calculate the permutations necessary for sorting a vector.
std::vector< size_t > Permutation
Represent a permutation.