FML
Public Member Functions
FML::INTERPOLATION::SPLINE::GSLSpline Class Reference

This is a wrapper class for easy use of GSL splines It is (OpenMP) thread safe as long as splines are not created by a subthread and later tried to be used by more than that thread! More...

#include <Spline.h>

Public Member Functions

 GSLSpline ()=default
 
 GSLSpline (std::string name)
 Construct giving the spline a name (useful for error/warning messages) More...
 
 GSLSpline (double *x, double *y, int nx, std::string splinename="NoName", const gsl_interp_type *interpoltype=SPLINE_FIDUCIAL_INTERPOL_TYPE)
 Construct a spline from pointers to x and y. Both must have nx elements. More...
 
 GSLSpline (const DVector &x, const DVector &y, std::string splinename="NoName", const gsl_interp_type *interpoltype=SPLINE_FIDUCIAL_INTERPOL_TYPE)
 Construct a spline from vectors x and y. Both must have the same size. More...
 
 GSLSpline (const GSLSpline &rhs)
 
GSLSpline & operator= (const GSLSpline &rhs)
 
 ~GSLSpline ()
 
 operator bool () const
 Is the spline created or not? More...
 
void create (const double *x, const double *y, int nx, std::string splinename="NoName", const gsl_interp_type *interpoltype=SPLINE_FIDUCIAL_INTERPOL_TYPE)
 Create a spline from pointers to x and y. Both must have nx elements. More...
 
void create (const DVector &x, const DVector &y, std::string splinename="NoName", const gsl_interp_type *interpoltype=SPLINE_FIDUCIAL_INTERPOL_TYPE)
 Create a spline from vectors x and y. Both must have the same size. More...
 
double operator() (double x) const
 Overload of the () operator for easy evaluation of the spline. More...
 
double eval (double x) const
 Get the value of the spline (if out of bounds we use the closest value) More...
 
double eval_deriv (double x, int deriv) const
 
double deriv_x (double x) const
 Get the value of the first derivative of the spline. More...
 
double deriv_xx (double x) const
 Get the value of the second derivative of the spline. More...
 
std::pair< double, double > get_xrange () const
 Get the range the spline was created on. More...
 
std::string get_name () const
 Get the name of the spline. More...
 
void set_out_of_bounds_warning (bool v)
 Turn on/off warnings if we try to evaluate out of bounds (we use closest value in that case) More...
 
DVector get_x_data ()
 Get the raw GSL data for x used to create the spline. More...
 
DVector get_y_data ()
 Get the raw GSL data for y=f(x) used to create the spline. More...
 
void free ()
 Free up memory associated with the spline. More...
 

Detailed Description

This is a wrapper class for easy use of GSL splines It is (OpenMP) thread safe as long as splines are not created by a subthread and later tried to be used by more than that thread!

The fiducial splines are cubic splines for 1D and bicubic for 2D assuming natural (y''=0) boundary conditions at the end-points

The fiducial choice allows to get the function value and up to second order derivatives. NB: if you change the fiducial choice to a lower order spline, e.g to gsl_interp_linear, then the second derivative deriv_xx etc. will not work

If evaluating out of bounds it will return the closest value. To get a warning when this happens call set_out_of_bounds_warning(true) before using the spline or set the define SPLINE_FIDUCIAL_SPLINE_WARNING to be true

Errors are handled via the throw_error function

Compile time defines:

USE_MPI : Use MPI (only effect is in on how errors are handled)

USE_OMP : Use OpenMP

SPLINE_FIDUCIAL_INTERPOL_TYPE : Cubic spline is the fiducial choice

SPLINE_FIDUCIAL_INTERPOL_TYPE_2D : Bicubic is the fiducial choice

SPLINE_FIDUCIAL_SPLINE_WARNING : Show warnings if we evaluate out of bounds

Definition at line 80 of file Spline.h.

Constructor & Destructor Documentation

◆ GSLSpline() [1/5]

FML::INTERPOLATION::SPLINE::GSLSpline::GSLSpline ( )
default

◆ GSLSpline() [2/5]

FML::INTERPOLATION::SPLINE::GSLSpline::GSLSpline ( std::string  name)

Construct giving the spline a name (useful for error/warning messages)

Definition at line 37 of file Spline.cpp.

37: GSLSpline() { this->name = name; }

◆ GSLSpline() [3/5]

FML::INTERPOLATION::SPLINE::GSLSpline::GSLSpline ( double *  x,
double *  y,
int  nx,
std::string  splinename = "NoName",
const gsl_interp_type *  interpoltype = SPLINE_FIDUCIAL_INTERPOL_TYPE 
)

Construct a spline from pointers to x and y. Both must have nx elements.

Definition at line 39 of file Spline.cpp.

43 {
44 create(x, y, nx, splinename, interpoltype);
45 }
void create(const double *x, const double *y, int nx, std::string splinename="NoName", const gsl_interp_type *interpoltype=SPLINE_FIDUCIAL_INTERPOL_TYPE)
Create a spline from pointers to x and y. Both must have nx elements.
Definition: Spline.cpp:89
return y
Definition: Global.h:265
x
Definition: test.py:18

◆ GSLSpline() [4/5]

FML::INTERPOLATION::SPLINE::GSLSpline::GSLSpline ( const DVector &  x,
const DVector &  y,
std::string  splinename = "NoName",
const gsl_interp_type *  interpoltype = SPLINE_FIDUCIAL_INTERPOL_TYPE 
)

Construct a spline from vectors x and y. Both must have the same size.

Definition at line 47 of file Spline.cpp.

50 {
51 // Check that dimensions match
52 if(x.size() != y.size())
53 throw std::runtime_error("GSLSpline::create The input vectors x, y don't have incompatible lengths!");
54 create(x, y, splinename, interpoltype);
55 }

◆ GSLSpline() [5/5]

FML::INTERPOLATION::SPLINE::GSLSpline::GSLSpline ( const GSLSpline &  rhs)

Definition at line 75 of file Spline.cpp.

75 {
76 // We just create the spline from scratch instead of copying all the data
77 if (rhs.spline != nullptr) {
78 create(rhs.spline->x, rhs.spline->y, rhs.size_x, rhs.name, rhs.interpoltype_used);
79 } else {
80 free();
81 }
82 }
void free()
Free up memory associated with the spline.
Definition: Spline.cpp:240

◆ ~GSLSpline()

FML::INTERPOLATION::SPLINE::GSLSpline::~GSLSpline ( )

Definition at line 284 of file Spline.cpp.

284{ free(); }

Member Function Documentation

◆ create() [1/2]

void FML::INTERPOLATION::SPLINE::GSLSpline::create ( const double *  x,
const double *  y,
int  nx,
std::string  splinename = "NoName",
const gsl_interp_type *  interpoltype = SPLINE_FIDUCIAL_INTERPOL_TYPE 
)

Create a spline from pointers to x and y. Both must have nx elements.

Definition at line 89 of file Spline.cpp.

93 {
94 // Clean up if we already have a spline allocated
95 if (spline != nullptr) {
96 free();
97 }
98
99 // Check if array is increasing
100 int sign_one = x[1] > x[0] ? 1.0 : -1.0;
101 for (int i = 1; i < nx; i++) {
102 if ((x[i] - x[i - 1]) * sign_one <= 0) {
103 std::string errormessage =
104 "[GSLSpline::create] x-array for spline " + name + " is not monotone\n";
105 throw_error(errormessage);
106 }
107 }
108
109 // If array is reversed then reverse it since GSL
110 // requires a monotonely increasing array
111 DVector xx, yy;
112 if (sign_one < 0) {
113 xx = DVector(nx);
114 yy = DVector(nx);
115 for (int i = 0; i < nx; i++) {
116 xx[i] = x[nx - 1 - i];
117 yy[i] = y[nx - 1 - i];
118 }
119 x = xx.data();
120 y = yy.data();
121 }
122
123 // Set class variables
124 xmin = x[0];
125 xmax = x[nx - 1];
126 dx_min = (x[1] - x[0]) / 2.0;
127 dx_max = (x[nx - 1] - x[nx - 2]) / 2.0;
128 size_x = nx;
129 name = splinename;
130 interpoltype_used = interpoltype;
131
132 // Make the spline
133 spline = gsl_spline_alloc(interpoltype, nx);
134 gsl_spline_init(spline, x, y, nx);
135
136 // Make accelerators (one per thread if OpenMP)
137 // If nthreads = 1 we are likely trying to create a spline
138 // inside a OMP region. In that case allocate as many as we have
139 // threads availiable on the system
140#ifdef USE_OMP
141 int nthreads = 1;
142#pragma omp parallel
143 {
144 int id = omp_get_thread_num();
145 if (id == 0)
146 nthreads = omp_get_num_threads();
147 }
148 if(nthreads == 1)
149 nthreads = nmax_threads;
150
151 // If we make a spline inside a nested openmp then
152 // the stuff above does not work
153 // nthreads = std::max(16, nthreads);
154 xaccs = std::vector<gsl_interp_accel *>(nthreads);
155 for (auto & xa : xaccs) {
156 xa = gsl_interp_accel_alloc();
157 }
158#else
159 xacc = gsl_interp_accel_alloc();
160#endif
161 }
FML::INTERPOLATION::SPLINE::DVector DVector
Definition: Simulation.h:39
std::vector< double > DVector
Definition: Spline.h:29

◆ create() [2/2]

void FML::INTERPOLATION::SPLINE::GSLSpline::create ( const DVector &  x,
const DVector &  y,
std::string  splinename = "NoName",
const gsl_interp_type *  interpoltype = SPLINE_FIDUCIAL_INTERPOL_TYPE 
)

Create a spline from vectors x and y. Both must have the same size.

Definition at line 163 of file Spline.cpp.

166 {
167 if (x.size() != y.size()) {
168 std::string errormessage =
169 "[GSLSpline::create] x and y array must have the same number of elements for spline " + name +
170 "\n";
171 throw_error(errormessage);
172 }
173 create(x.data(), y.data(), int(x.size()), splinename, interpoltype);
174 }

◆ deriv_x()

double FML::INTERPOLATION::SPLINE::GSLSpline::deriv_x ( double  x) const

Get the value of the first derivative of the spline.

Definition at line 275 of file Spline.cpp.

275{ return eval_deriv(x, 1); }
double eval_deriv(double x, int deriv) const
Definition: Spline.cpp:203

◆ deriv_xx()

double FML::INTERPOLATION::SPLINE::GSLSpline::deriv_xx ( double  x) const

Get the value of the second derivative of the spline.

Definition at line 276 of file Spline.cpp.

276{ return eval_deriv(x, 2); }

◆ eval()

double FML::INTERPOLATION::SPLINE::GSLSpline::eval ( double  x) const

Get the value of the spline (if out of bounds we use the closest value)

Definition at line 183 of file Spline.cpp.

183 {
184 if (spline == nullptr) {
185 std::string errormessage = "[GSLSpline::eval] Spline " + name + " has not been created!\n";
186 throw_error(errormessage);
187 }
188
189 // If out of bounds show a warning and set x to boundary value
190 out_of_bounds_check(x);
191 x = std::max(x, xmin);
192 x = std::min(x, xmax);
193
194 // Return f, f' or f'' depending on value of deriv
195#ifdef USE_OMP
196 gsl_interp_accel * xacc_thread = xaccs[omp_get_thread_num()];
197#else
198 gsl_interp_accel * xacc_thread = xacc;
199#endif
200 return gsl_spline_eval(spline, x, xacc_thread);
201 }

◆ eval_deriv()

double FML::INTERPOLATION::SPLINE::GSLSpline::eval_deriv ( double  x,
int  deriv 
) const

Definition at line 203 of file Spline.cpp.

203 {
204 if (spline == nullptr) {
205 std::string errormessage = "[GSLSpline::eval_deriv] Spline " + name + " has not been created!\n";
206 throw_error(errormessage);
207 }
208 if (deriv < 0 || deriv > 2) {
209 std::string errormessage = "[GSLSpline::eval_deriv] Got deriv = " + std::to_string(deriv) +
210 " for spline " + name + " Expected 0 = f, 1 = f' or 2 = f''\n";
211 throw_error(errormessage);
212 }
213
214 // If out of bounds show a warning and set x to boundary value
215 out_of_bounds_check(x);
216 x = std::max(x, xmin);
217 x = std::min(x, xmax);
218
219 // Return f, f' or f'' depending on value of deriv
220#ifdef USE_OMP
221 gsl_interp_accel * xacc_thread = xaccs[omp_get_thread_num()];
222#else
223 gsl_interp_accel * xacc_thread = xacc;
224#endif
225
226 double dydx = 0.0;
227 if (deriv == 0) {
228 dydx = gsl_spline_eval(spline, x, xacc_thread);
229 } else if (deriv == 1) {
230 dydx = gsl_spline_eval_deriv(spline, x, xacc_thread);
231 } else if (deriv == 2) {
232 dydx = gsl_spline_eval_deriv2(spline, x, xacc_thread);
233 }
234 return dydx;
235 }

◆ free()

void FML::INTERPOLATION::SPLINE::GSLSpline::free ( )

Free up memory associated with the spline.

Definition at line 240 of file Spline.cpp.

240 {
241 if (spline != nullptr) {
242 // Reset class variables
243 xmin = xmax = 0.0;
244 size_x = 0;
245 dx_min = dx_max = 0.0;
246
247 // Free the spline
248 gsl_spline_free(spline);
249 spline = nullptr;
250
251 // Free accelerators
252#ifdef USE_OMP
253 for (auto & xa : xaccs) {
254 gsl_interp_accel_free(xa);
255 }
256 std::vector<gsl_interp_accel *>().swap(xaccs);
257#else
258 gsl_interp_accel_free(xacc);
259 xacc = nullptr;
260#endif
261 }
262 }

◆ get_name()

std::string FML::INTERPOLATION::SPLINE::GSLSpline::get_name ( ) const

Get the name of the spline.

Definition at line 278 of file Spline.cpp.

278{ return name; }

◆ get_x_data()

DVector FML::INTERPOLATION::SPLINE::GSLSpline::get_x_data ( )
inline

Get the raw GSL data for x used to create the spline.

Definition at line 165 of file Spline.h.

165{ return DVector(spline->x, spline->x + spline->size); }

◆ get_xrange()

std::pair< double, double > FML::INTERPOLATION::SPLINE::GSLSpline::get_xrange ( ) const

Get the range the spline was created on.

Definition at line 277 of file Spline.cpp.

277{ return {xmin, xmax}; }

◆ get_y_data()

DVector FML::INTERPOLATION::SPLINE::GSLSpline::get_y_data ( )
inline

Get the raw GSL data for y=f(x) used to create the spline.

Definition at line 167 of file Spline.h.

167{ return DVector(spline->y, spline->y + spline->size); }

◆ operator bool()

FML::INTERPOLATION::SPLINE::GSLSpline::operator bool ( ) const
explicit

Is the spline created or not?

Definition at line 84 of file Spline.cpp.

84{ return (spline != nullptr); }

◆ operator()()

double FML::INTERPOLATION::SPLINE::GSLSpline::operator() ( double  x) const

Overload of the () operator for easy evaluation of the spline.

Definition at line 181 of file Spline.cpp.

181{ return eval(x); }
double eval(double x) const
Get the value of the spline (if out of bounds we use the closest value)
Definition: Spline.cpp:183

◆ operator=()

GSLSpline & FML::INTERPOLATION::SPLINE::GSLSpline::operator= ( const GSLSpline &  rhs)

Definition at line 60 of file Spline.cpp.

60 {
61 if (this != &rhs) {
62 // We just create the spline from scratch instead of copying all the data
63 if (rhs.spline != nullptr) {
64 create(rhs.spline->x, rhs.spline->y, rhs.size_x, rhs.name, rhs.interpoltype_used);
65 } else {
66 free();
67 }
68 }
69 return *this;
70 }

◆ set_out_of_bounds_warning()

void FML::INTERPOLATION::SPLINE::GSLSpline::set_out_of_bounds_warning ( bool  v)

Turn on/off warnings if we try to evaluate out of bounds (we use closest value in that case)

Definition at line 279 of file Spline.cpp.

279{ out_of_bounds_warning = v; }

The documentation for this class was generated from the following files: