/******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2018 Matthieu Schaller (schaller@strw.leidenuniv.nl) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * ******************************************************************************/ #ifndef SWIFT_EAGLE_FEEDBACK_INTERPOLATE_H #define SWIFT_EAGLE_FEEDBACK_INTERPOLATE_H /* Local includes. */ #include "error.h" #include "inline.h" /** * @brief Returns the 1d index of element with 2d indices i,j * from a flattened 2d array in row major order * * @param i, j Indices of element of interest * @param Nx, Ny Sizes of array dimensions */ __attribute__((always_inline)) static INLINE int row_major_index_2d( const int i, const int j, const int Nx, const int Ny) { #ifdef SWIFT_DEBUG_CHECKS assert(i < Nx); assert(j < Ny); #endif return i * Ny + j; } /** * @brief Returns the 1d index of element with 3d indices i,j,k * from a flattened 3d array in row major order * * @param i, j, k Indices of element of interest * @param Nx, Ny, Nz Sizes of array dimensions */ __attribute__((always_inline)) static INLINE int row_major_index_3d( const int i, const int j, const int k, const int Nx, const int Ny, const int Nz) { #ifdef SWIFT_DEBUG_CHECKS assert(i < Nx); assert(j < Ny); assert(k < Nz); #endif return i * Ny * Nz + j * Nz + k; } /** * @brief linear interpolation of 1d table at bin i with offset dx * * @param table array to interpolate * @param i index of cell to interpolate * @param dx offset within cell to interpolate */ __attribute__((always_inline)) static INLINE double interpolate_1d( const double* const table, const int i, const double dx) { const double tx = 1. - dx; return tx * table[i] + dx * table[i + 1]; } /** * @brief linear interpolation of 2d table at bin i,j with offset dx, dy * * @param table array to interpolate * @param i row index of cell to interpolate * @param j column index of cell to interpolate * @param dx row offset within cell to interpolate * @param dy column offset within cell to interpolate */ __attribute__((always_inline)) static INLINE double interpolate_2d( double** table, const int i, const int j, const float dx, const float dy) { const float tx = 1.f - dx; const float ty = 1.f - dy; double result = tx * ty * table[i][j]; result += tx * dy * table[i][j + 1]; result += dx * ty * table[i + 1][j]; result += dx * dy * table[i + 1][j + 1]; return result; } /** * @brief linear interpolation of non-uniformly spaced 1d array, array_y, whose * positions are specified in array_x. The function takes an input value in the * range of array_x and returns a value interpolated from array_y with the same * offset in the corresponding bin. * * @param array_x array of values indicating positions of the array to be * interpolated * @param array_y array to interpolate * @param size length of array_x and array_y * @param x value within range of array_x indicating bin and offset within * array_y to interpolate */ static INLINE double interpolate_1D_non_uniform(const double* array_x, const double* array_y, const int size, const double x) { #ifdef SWIFT_DEBUG_CHECKS /* Check that x within range of array_x */ if (x < array_x[0]) error("interpolating value less than array min. value %.5e array min %.5e", x, array_x[0]); if (x > array_x[size - 1]) error( "interpolating value greater than array max. value %.5e array max %.5e", x, array_x[size - 1]); #endif /* Find bin index and offset of x within array_x */ int index = 0; while (array_x[index] <= x) index++; const double offset = (array_x[index] - x) / (array_x[index] - array_x[index - 1]); /* Interpolate array_y */ return offset * array_y[index - 1] + (1. - offset) * array_y[index]; } #endif /* SWIFT_EAGLE_FEEDBACK_INTERPOLATE_H */