criptic v1
Cosmic Ray Interstellar Propagation Tool using Itô Calculus
Loading...
Searching...
No Matches
Interp2D.H
Go to the documentation of this file.
1
8#ifndef _INTERP2D_H_
9#define _INTERP2D_H_
10
11#include <cmath>
12#include <gsl/gsl_interp2d.h>
13#include "ErrCodes.H"
14#include "Interp1D.H"
15#include "ThreadVec.H"
16#include "Types.H"
17
18namespace criptic {
19
31 class Interp2D {
32
33 public:
34
61 Interp2D(const double* x_, const double* y_, const double* z_,
62 const size_t nx_, const size_t ny_,
63 const extrapType extrapXLo_ = extrapError,
64 const extrapType extrapXHi_ = extrapError,
65 const extrapType extrapYLo_ = extrapError,
66 const extrapType extrapYHi_ = extrapError,
67 const bool xLog_ = false, const bool yLog_ = false,
68 const bool zLog_ = false,
69 const double zXLo_ = 0.0, const double zXHi_ = 0.0,
70 const double zYLo_ = 0.0, const double zYHi_ = 0.0) :
71 x(x_),
72 y(y_),
73 z(z_),
74 nx(nx_),
75 ny(ny_),
76 extrapXLo(extrapXLo_),
77 extrapXHi(extrapXHi_),
78 extrapYLo(extrapYLo_),
79 extrapYHi(extrapYHi_),
80 xLog(xLog_),
81 yLog(yLog_),
82 zLog(zLog_),
83 zXLo(zXLo_),
84 zXHi(zXHi_),
85 zYLo(zYLo_),
86 zYHi(zYHi_)
87 {
88
89 // Allocate and initialize GSL objects
90 interp = gsl_interp2d_alloc(gsl_interp2d_bilinear, nx, ny);
91 gsl_interp2d_init(interp, x, y, z, nx, ny);
92 for (IdxType i = 0; i < accX.size(); i++) {
93 accX[i] = gsl_interp_accel_alloc();
94 accY[i] = gsl_interp_accel_alloc();
95 }
96 }
97
102 // Free memory
103 gsl_interp2d_free(interp);
104 for (IdxType i = 0; i < accX.size(); i++) {
105 gsl_interp_accel_free(accX[i]);
106 gsl_interp_accel_free(accY[i]);
107 }
108 }
109
114 double xMin() const { return xLog ? std::pow(10., x[0]) : x[0]; }
115
120 double xMax() const { return xLog ? std::pow(10., x[nx-1]) : x[nx-1]; }
121
126 double yMin() const { return yLog ? std::pow(10., y[0]) : y[0]; }
127
132 double yMax() const { return yLog ? std::pow(10., y[ny-1]) : y[ny-1]; }
133
141 double operator()(const Real& x_, const Real& y_) const {
142
143 // Take log if requested
144 double x1 = xLog ? std::log10(x_) : x_;
145 double y1 = yLog ? std::log10(y_) : y_;
146
147 // Catch case where we are logging variables and we input a
148 // value that is at the top or bottom of the table, but taking
149 // the logarithm leads us to be off the table by a machine
150 // precision-level amount; this can cause an error if
151 // extrapolation is forbidden. To handle this, if xLog or yLog
152 // is set, we check for near-equality between x1 and y1 and the
153 // extrema of the table, and coerce the points back onto the
154 // table if they are off by a very small amount.
155 if (xLog) {
156 if (x1 < x[0] && x[0] - x1 < 1.0e-10) x1 = x[0];
157 else if (!(x1 < x[nx-1]) && x1 - x[nx-1] < tol) x1 = x[nx-1];
158 }
159 if (yLog) {
160 if (y1 < y[0] && y[0] - y1 < 1.0e-10) y1 = y[0];
161 else if (!(y1 < y[ny-1]) && y1 - y[ny-1] < tol) y1 = y[ny-1];
162 }
163
164 // Find out where we are relative to grid; note that there are 9
165 // possible regions, defined by being on the grid and in 8
166 // possible zones around it
167 double z1 = 0.0;
168 if (x1 < x[0]) {
169
170 // Off-table low in x direction; bail if this region is
171 // disallowed
172 if (extrapXLo == extrapError)
174
175 // Now check with region we are in in the y direction
176 if (y1 < y[0]) {
177
178 // Allowed combinations in this region are Const for both x
179 // and y, in which case we just return the (0,0) value,
180 // FixedVal for both *if the fixed values are the same*, and
181 // linear for both, in which case we linearly extrapolate in
182 // both directions; any other combination is an error
183 if (extrapXLo == extrapConst &&
185 z1 = z[0];
186 } else if (extrapXLo == extrapFixedVal &&
188 zXLo == zYLo) {
189 z1 = zXLo;
190 } else if (extrapXLo == extrapLinear &&
192 double mx = (z[1] - z[0]) / (x[1] - x[0]);
193 double my = (z[nx] - z[0]) / (y[1] - y[0]);
194 z1 = z[0] + mx * (x1 - x[0]) + my * (y1 - y[0]);
195 } else {
197 }
198
199 } else if (y1 < y[ny-1]) {
200
201 // On-table in y direction
202 switch (extrapXLo) {
203 case extrapLinear: {
204 double zx0 = gsl_interp2d_eval(interp, x, y, z,
205 x[0], y1, accX(), accY());
206 double zx1 = gsl_interp2d_eval(interp, x, y, z,
207 x[1], y1, accX(), accY());
208 double mx = (zx1 - zx0) / (x[1] - x[0]);
209 z1 = zx0 + mx * (x1 - x[0]);
210 break;
211 }
212 case extrapFixedVal:
213 return zXLo;
214 case extrapConst: {
215 z1 = gsl_interp2d_eval(interp, x, y, z,
216 x[0], y1, accX(), accY());
217 break;
218 }
219 case extrapError:
221 }
222
223 } else {
224
225 // Off-table high in y direction; bail if disallowed
226 if (extrapYHi == extrapError) {
228 }
229
230 // Allowed combinations in this region are Const for both x
231 // and y, in which case we just return the (0,ny-1) value,
232 // FixedVal for both *if the fixed values are the same*, and
233 // linear for both, in which case we linearly extrapolate in
234 // both directions; any other combination is an error
235 if (extrapXLo == extrapConst &&
237 z1 = z[(ny-1)*nx];
238 } else if (extrapXLo == extrapFixedVal &&
240 zXLo == zYHi) {
241 z1 = zXLo;
242 } else if (extrapXLo == extrapLinear &&
244 double mx = (z[ (ny-1) * nx + 1] - z[ (ny-1) * nx ]) /
245 (x[1] - x[0]);
246 double my = (z[ (ny-1) * nx ] - z[ (ny-2) * nx ])
247 / (y[ny-1] - y[ny-2]);
248 z1 = z[ (ny-1) * nx ] + mx * (x1 - x[0]) + my * (y1 - y[ny-1]);
249 } else {
251 }
252
253 }
254
255 } else if (x1 < x[nx-1]) {
256
257 // On-table in x direction; see where we are in y
258 if (y1 < y[0]) {
259
260 // Off-table low in y
261 switch (extrapYLo) {
262 case extrapLinear: {
263 double zy0 = gsl_interp2d_eval(interp, x, y, z,
264 x1, y[0], accX(), accY());
265 double zy1 = gsl_interp2d_eval(interp, x, y, z,
266 x1, y[1], accX(), accY());
267 double my = (zy1 - zy0) / (y[1] - y[0]);
268 z1 = zy0 + my * (y1 - y[0]);
269 break;
270 }
271 case extrapFixedVal:
272 return zYLo;
273 case extrapConst: {
274 z1 = gsl_interp2d_eval(interp, x, y, z,
275 x1, y[0], accX(), accY());
276 break;
277 }
278 case extrapError: {
280 }
281 }
282
283 } else if (y1 < y[ny-1]) {
284
285 // On table in both directions
286 z1 = gsl_interp2d_eval(interp, x, y, z,
287 x1, y1, accX(), accY());
288
289 } else {
290
291 // Off-table high in y direction
292 switch (extrapYHi) {
293 case extrapLinear: {
294 double zy0 = gsl_interp2d_eval(interp, x, y, z,
295 x1, y[ny-2], accX(), accY());
296 double zy1 = gsl_interp2d_eval(interp, x, y, z,
297 x1, y[ny-1], accX(), accY());
298 double my = (zy1 - zy0) / (y[ny-1] - y[ny-2]);
299 z1 = zy1 + my * (y1 - y[0]);
300 break;
301 }
302 case extrapFixedVal:
303 return zYHi;
304 case extrapConst: {
305 z1 = gsl_interp2d_eval(interp, x, y, z,
306 x1, y[ny-1], accX(), accY());
307 break;
308 }
309 case extrapError: {
311 }
312 }
313 }
314
315 } else {
316
317 // Off-table high in x direction; bail if this region is
318 // disallowed
319 if (extrapXHi == extrapError)
321
322 // Now check with region we are in in the y direction
323 if (y1 < y[0]) {
324
325 // Off-table low in y direction; bail if disallowed
326 if (extrapYLo == extrapError)
328
329 // Allowed combinations in this region are Const for both x
330 // and y, in which case we just return the (nx-1,0) value,
331 // FixedVal for both *if the fixed values are the same*, and
332 // linear for both, in which case we linearly extrapolate in
333 // both directions; any other combination is an error
334 if (extrapXHi == extrapConst &&
336 z1 = z[nx-1];
337 } else if (extrapXHi == extrapFixedVal &&
339 zXHi == zYLo) {
340 z1 = zXHi;
341 } else if (extrapXHi == extrapLinear &&
343 double mx = (z[nx-1] - z[nx-2]) / (x[nx-1] - x[nx-2]);
344 double my = (z[nx-1 + nx] - z[nx-1]) / (y[1] - y[0]);
345 z1 = z[nx-1] + mx * (x1 - x[nx-1]) + my * (y1 - y[0]);
346 } else {
348 }
349
350 } else if (y1 < y[ny-1]) {
351
352 // On-table in y direction
353 switch (extrapXHi) {
354 case extrapLinear: {
355 double zx0 = gsl_interp2d_eval(interp, x, y, z,
356 x[nx-2], y1, accX(), accY());
357 double zx1 = gsl_interp2d_eval(interp, x, y, z,
358 x[nx-1], y1, accX(), accY());
359 double mx = (zx1 - zx0) / (x[nx-1] - x[nx-2]);
360 z1 = zx1 + mx * (x1 - x[nx-1]);
361 break;
362 }
363 case extrapFixedVal:
364 return zXHi;
365 case extrapConst: {
366 z1 = gsl_interp2d_eval(interp, x, y, z,
367 x[nx-1], y1, accX(), accY());
368 break;
369 }
370 case extrapError:
372 }
373
374 } else {
375
376 // Off-table high in y direction; bail if disallowed
377 if (extrapYHi == extrapError) {
379 }
380
381 // Allowed combinations in this region are Const for both x
382 // and y, in which case we just return the (0,ny-1) value,
383 // FixedVal for both *if the fixed values are the same*, and
384 // linear for both, in which case we linearly extrapolate in
385 // both directions; any other combination is an error
386 if (extrapXHi == extrapConst &&
388 z1 = z[(ny-1)*nx + nx-1];
389 } else if (extrapXHi == extrapFixedVal &&
391 zXHi == zYHi) {
392 z1 = zXHi;
393 } else if (extrapXHi == extrapLinear &&
395 double mx = (z[ (ny-1) * nx + nx-2] - z[ (ny-1) * nx + nx-1 ]) /
396 (x[nx-1] - x[nx-2]);
397 double my = (z[ (ny-1) * nx + nx-1 ] - z[ (ny-2) * nx + nx-1])
398 / (y[ny-1] - y[ny-2]);
399 z1 = z[ (ny-1) * nx + nx-1] +
400 mx * (x1 - x[nx-1]) + my * (y1 - y[ny-1]);
401 } else {
403 }
404
405 }
406
407 }
408
409 // Return
410 if (zLog) {
411 return std::pow(10., z1);
412 } else {
413 return z1;
414 }
415 }
416
417 private:
418
419 const double *x;
420 const double *y;
421 const double *z;
422 const size_t nx;
423 const size_t ny;
428 const bool xLog;
429 const bool yLog;
430 const bool zLog;
431 const double zXLo;
432 const double zXHi;
433 const double zYLo;
434 const double zYHi;
435 static constexpr double tol = 1.0e-8;
438 // GSL machinery
439 gsl_interp2d *interp;
443 };
444
445}
446
447#endif
448// _INTERP2D_H_
A file containing a set of enumerated error codes.
A utility class to handle 1D interpolation.
A class to hold objects where one copy is required per thread.
Basic integer and real types.
A class to handle interpolation on 2D tables.
Definition Interp2D.H:31
~Interp2D()
Destructor.
Definition Interp2D.H:101
const bool zLog
Definition Interp2D.H:430
double operator()(const Real &x_, const Real &y_) const
Caclulate an interpolated value from the table.
Definition Interp2D.H:141
const double zYHi
Definition Interp2D.H:434
const extrapType extrapXHi
Definition Interp2D.H:425
const bool xLog
Definition Interp2D.H:428
const extrapType extrapYHi
Definition Interp2D.H:427
double xMax() const
Return upper limit of table x.
Definition Interp2D.H:120
const extrapType extrapXLo
Definition Interp2D.H:424
const size_t ny
Definition Interp2D.H:423
const size_t nx
Definition Interp2D.H:422
static constexpr double tol
Definition Interp2D.H:435
const double * z
Definition Interp2D.H:421
double xMin() const
Return lower limit of table in x.
Definition Interp2D.H:114
Interp2D(const double *x_, const double *y_, const double *z_, const size_t nx_, const size_t ny_, const extrapType extrapXLo_=extrapError, const extrapType extrapXHi_=extrapError, const extrapType extrapYLo_=extrapError, const extrapType extrapYHi_=extrapError, const bool xLog_=false, const bool yLog_=false, const bool zLog_=false, const double zXLo_=0.0, const double zXHi_=0.0, const double zYLo_=0.0, const double zYHi_=0.0)
Constructor.
Definition Interp2D.H:61
const double zYLo
Definition Interp2D.H:433
double yMax() const
Return upper limit of table y.
Definition Interp2D.H:132
const double * x
Definition Interp2D.H:419
const double * y
Definition Interp2D.H:420
gsl_interp2d * interp
Definition Interp2D.H:439
const double zXLo
Definition Interp2D.H:431
const extrapType extrapYLo
Definition Interp2D.H:426
ThreadVec< gsl_interp_accel * > accY
Definition Interp2D.H:441
const double zXHi
Definition Interp2D.H:432
double yMin() const
Return lower limit of table in y.
Definition Interp2D.H:126
ThreadVec< gsl_interp_accel * > accX
Definition Interp2D.H:440
const bool yLog
Definition Interp2D.H:429
A class to automate private thread copies of objects.
Definition ThreadVec.H:35
IdxType size() const
Return the number of distinct objects stored.
Definition ThreadVec.H:59
The primary namespace for criptic objects.
Definition AdvancePacket.H:25
extrapType
Enum describing different ways to handle extrapolation.
Definition Interp1D.H:22
@ extrapConst
Definition Interp1D.H:25
@ extrapLinear
Definition Interp1D.H:24
@ extrapError
Definition Interp1D.H:23
@ extrapFixedVal
Definition Interp1D.H:27
@ errBadYHiExtrapolation
Definition ErrCodes.H:34
@ errBadYLoExtrapolation
Definition ErrCodes.H:32
@ errBadXLoExtrapolation
Definition ErrCodes.H:28
@ errBadXYExtrapolation
Definition ErrCodes.H:36
@ errBadXHiExtrapolation
Definition ErrCodes.H:30
std::vector< Real >::size_type IdxType
Definition Types.H:45
double Real
Definition Types.H:38