Version: SMASH-3.4
interpolation2D.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020,2022,2026
3  * SMASH Team
4  *
5  * GNU General Public License (GPLv3 or later)
6  */
7 
9 
10 #include <algorithm>
11 #include <initializer_list>
12 #include <iostream>
13 #include <sstream>
14 #include <stdexcept>
15 
16 namespace smash {
17 
19  const std::vector<double>& x, const std::vector<double>& y,
20  const std::vector<double>& z, const ExtrapolationType extrapolation_type)
21  : extrapolation_type_{extrapolation_type} {
22  switch (extrapolation_type_) {
26  break;
27  default:
28  throw std::invalid_argument(
29  "The provided extrapolation type is not supported. Valid types are "
30  "'None', 'Zero', and 'Constant'.");
31  }
32 
33  const size_t M = x.size();
34  const size_t N = y.size();
35 
36  if (z.size() != N * M) {
37  throw std::invalid_argument(
38  "Dimensions not suitable for 2D interpolation. DIM(z) != DIM(x) * "
39  "DIM(y).");
40  }
41 
42  if (M < 4 || N < 4) {
43  throw std::invalid_argument(
44  "Need at least 4 data points in each dimension for bicubic spline "
45  "interpolation.");
46  }
47 
48  if (!std::is_sorted(x.begin(), x.end()) ||
49  !std::is_sorted(y.begin(), y.end())) {
50  throw std::invalid_argument(
51  "x and y values must be strictly increasing, i.e. the vectors have to "
52  "be sorted by size of their values. This is required by GSL.");
53  }
54 
55  // Assign lower and upper bounds for constant extrapolation
56  first_x_ = x.front();
57  last_x_ = x.back();
58  first_y_ = y.front();
59  last_y_ = y.back();
60 
61  // cast vectors into arrays, as GSL functions can only handle arrays
62  const double* xa = &x[0];
63  const double* ya = &y[0];
64  const double* za = &z[0];
65 
66  // Create accelerator objects (interpolation lookups)
67  xacc_ = gsl_interp_accel_alloc();
68  yacc_ = gsl_interp_accel_alloc();
69 
70  // Initialize bicubic spline interpolation
71  spline_ = gsl_spline2d_alloc(gsl_interp2d_bicubic, M, N);
72  gsl_spline2d_init(spline_, xa, ya, za, M, N);
73 }
74 
76  gsl_spline2d_free(spline_);
77  gsl_interp_accel_free(xacc_);
78  gsl_interp_accel_free(yacc_);
79 }
80 
81 double InterpolateData2DSpline::operator()(double xi, double yi) const {
82  if ((xi < first_x_ || xi > last_x_) || (yi < first_y_ || yi > last_y_)) {
84  std::ostringstream error_msg{
85  "InterpolateData2DSpline only accepts x and y values within the "
86  "range of the underlying data\nwhen extrapolation is not specified. ",
87  std::ios::ate};
88  error_msg << "x value " << xi << " or y value " << yi
89  << " are out of bounds.";
90  throw std::out_of_range(error_msg.str());
92  return 0.;
94  // constant extrapolation at the edges
95  xi = (xi < first_x_) ? first_x_ : xi;
96  xi = (xi > last_x_) ? last_x_ : xi;
97  yi = (yi < first_y_) ? first_y_ : yi;
98  yi = (yi > last_y_) ? last_y_ : yi;
99  }
100  }
101 
102  // bicubic spline interpolation
103  return gsl_spline2d_eval(spline_, xi, yi, xacc_, yacc_);
104 }
105 
106 } // namespace smash
ExtrapolationType extrapolation_type_
Extrapolation type.
double first_y_
First y value of underlying data.
double last_y_
Last y value of underlying data.
double last_x_
Last x value of underlying data.
double operator()(double xi, double yi) const
Calculate bicubic interpolation for given x and y.
gsl_interp_accel * xacc_
GSL iterator for interpolation lookups in x direction.
InterpolateData2DSpline(const std::vector< double > &x, const std::vector< double > &y, const std::vector< double > &z, ExtrapolationType extrapolation_type=ExtrapolationType::None)
Interpolate function f given discrete samples f(x_i, y_i) = z_i.
gsl_spline2d * spline_
GSL spline in 2D.
double first_x_
First x value of underlying data.
gsl_interp_accel * yacc_
GSL iterator for interpolation lookupin y direction.
ExtrapolationType
Allows to specify the desired extrapolation type.
@ None
No extrapolation is done.
@ Constant
Extrapolate using a constant value.
@ Zero
Extrapolate with zero.
Definition: action.h:24