/******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2016 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 . * ******************************************************************************/ #ifndef SWIFT_ROW_MAJOR_ID_H #define SWIFT_ROW_MAJOR_ID_H /* Config parameters. */ #include /* Includes. */ #include "inline.h" /** * @brief Returns 1D index of a 3D NxNxN array using row-major style. * * Wraps around in the corresponding dimension if any of the 3 indices is >= N * or < 0. * * @param i Index along x. * @param j Index along y. * @param k Index along z. * @param N Size of the array along one axis. */ __attribute__((always_inline, const)) INLINE static int row_major_id_periodic( const int i, const int j, const int k, const int N) { return (((i + N) % N) * N * N + ((j + N) % N) * N + ((k + N) % N)); } /** * @brief Returns 1D index of a 3D NxNxN array using row-major style. * * Wraps around in the corresponding dimension if any of the 3 indices is >= N * or < 0. * * Padding is added along the x axis. * * @param i Index along x. * @param j Index along y. * @param k Index along z. * @param N Size of the array along one axis. */ __attribute__((always_inline, const)) INLINE static int row_major_id_periodic_with_padding(const int i, const int j, const int k, const int N, const int pad) { return ((((i + N) % N) * N + ((j + N) % N)) * (N + pad) + ((k + N) % N)); } /** * @brief Returns 1D index of a FFTW-padded 3D NxNxN array using row-major * style. * * Wraps around in the corresponding dimension if any of the 3 indices is >= N * or < 0. Note that indexes are of type size_t in this version and the array * is assumed to be padded to size 2*(N/2+1) in the last dimension as required * by FFTW MPI routines. * * @param i Index along x. * @param j Index along y. * @param k Index along z. * @param N Size of the array along one axis. */ __attribute__((always_inline, const)) INLINE static size_t row_major_id_periodic_size_t_padded(const int i, const int j, const int k, const int N) { /* Find last two dimensions of the padded array */ const size_t Nj = N; const size_t Nk = 2 * (N / 2 + 1); /* Get box-wrapped coordinates (note that we don't use the padded size here) */ const size_t i_wrap = (size_t)((i + N) % N); const size_t j_wrap = (size_t)((j + N) % N); const size_t k_wrap = (size_t)((k + N) % N); /* Compute index in the padded array */ return (i_wrap * Nj * Nk) + (j_wrap * Nk) + k_wrap; } /** * @brief Return a unique ID for a mesh cell in a local patch. * * We use the first 28 bits for the patch id then 3 lots * of 12 bits for each of i, j, and k. * * @param patch_id The local ID of patch. * @param i The i-index of the mesh cell in the patch. * @param j The j-index of the mesh cell in the patch. * @param k The k-index of the mesh cell in the patch. */ __attribute__((always_inline, const)) INLINE static size_t cell_index_from_patch_index(const int patch_id, const int i, const int j, const int k) { size_t ret = patch_id; ret <<= 12; ret += (size_t)i; ret <<= 12; ret += (size_t)j; ret <<= 12; ret += (size_t)k; return ret; } /** * @brief Return the patch index from the mesh cell unique ID. */ __attribute__((always_inline, const)) INLINE static int cell_index_extract_patch_index(const size_t index) { return (int)(index >> 36); } /** * @brief Returns a size_t containing the last n bits of a give size_t */ __attribute__((always_inline, const)) INLINE static size_t get_last_n_bits( const size_t x, const int n) { return x & ~(~((size_t)0) << n); } /** * @brief Extract the patch index, i, j and k from a cell_index. * * Performs the opposite operation to cell_index_from_patch_index(). */ __attribute__((always_inline)) INLINE static void patch_index_from_cell_index( size_t cell_index, int *restrict patch_index, int *restrict i, int *restrict j, int *restrict k) { const size_t kk = get_last_n_bits(cell_index, 12); cell_index >>= 12; const size_t jj = get_last_n_bits(cell_index, 12); cell_index >>= 12; const size_t ii = get_last_n_bits(cell_index, 12); cell_index >>= 12; *k = (int)kk; *j = (int)jj; *i = (int)ii; *patch_index = (int)cell_index; } /** * @brief Return i coordinate from an id returned by * row_major_id_periodic_size_t_padded * * This extracts the index in the first dimension from a row major id * returned by row_major_id_periodic_size_t_padded. I.e. it finds the * 'i' input parameter that was used to generate the id. * * @param id The padded row major ID. * @param N Size of the array along one axis. */ __attribute__((always_inline, const)) INLINE static int get_xcoord_from_padded_row_major_id(const size_t id, const int N) { const size_t Nj = N; const size_t Nk = 2 * (N / 2 + 1); return (int)(id / (Nj * Nk)); } /** * @brief Convert a global mesh array index to local slice index * * Given an index into the padded N*N*2*(N/2+1) array, compute * the corresponding index in the slice of the array stored * on the local MPI rank. * * @param id The padded row major ID. * @param N Size of the array along one axis. * @param slice_offset Index of the first slice on this rank */ __attribute__((always_inline, const)) INLINE static size_t get_index_in_local_slice(const size_t id, const int N, const int slice_offset) { const size_t Nj = N; const size_t Nk = 2 * (N / 2 + 1); return id - ((size_t)slice_offset) * Nj * Nk; } #endif /* SWIFT_ROW_MAJOR_ID_H */