/******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2016 Bert Vandenbroucke (bert.vandenbroucke@gmail.com). * * 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_VORONOIXD_ALGORITHM_H #define SWIFT_VORONOIXD_ALGORITHM_H #include "error.h" #include "inline.h" #include "voronoi1d_cell.h" #include #include /** * @brief Store the extents of the simulation box in the global variables. * * @param anchor Corner of the simulation box with the lowest coordinate values. * @param side Side lengths of the simulation box. */ __attribute__((always_inline)) INLINE static void voronoi_set_box( const float *anchor, const float *side) {} /** * @brief Initialize a 1D Voronoi cell. * * Sets the positions of left and right neighbours to very large values, the * generator position to the given particle position, and all other quantities * to zero. * * @param cell 1D Voronoi cell to initialize. * @param x Position of the generator of the cell. * @param anchor Anchor of the simulation box. * @param side Side lengths of the simulation box. */ __attribute__((always_inline)) INLINE void voronoi_cell_init( struct voronoi_cell *cell, const double *x, const double *anchor, const double *side) { cell->x = x[0]; cell->xL = anchor[0] - cell->x; cell->xR = anchor[0] + side[0] - cell->x; cell->idL = 0; cell->idR = 0; cell->volume = 0.0f; cell->centroid = 0.0f; } /** * @brief Interact a 1D Voronoi cell with a particle with given relative * position and ID. * * This method checks if the given relative position is closer to the cell * generator than the current left or right neighbour and updates neighbours * accordingly. * * @param cell 1D Voronoi cell. * @param dx Relative position of the interacting generator w.r.t. the cell * generator (in fact: dx = generator - neighbour). * @param id ID of the interacting neighbour. */ __attribute__((always_inline)) INLINE void voronoi_cell_interact( struct voronoi_cell *cell, const float *dx, unsigned long long id) { /* Check for stupidity */ if (dx[0] == 0.0f) { error("Cannot interact a Voronoi cell generator with itself!"); } if (-dx[0] < 0.0f) { /* New left neighbour? */ if (-dx[0] > cell->xL) { cell->xL = -dx[0]; cell->idL = id; } } else { /* New right neighbour? */ if (-dx[0] < cell->xR) { cell->xR = -dx[0]; cell->idR = id; } } } /** * @brief Finalize a 1D Voronoi cell. * * Calculates the relative positions of the midpoints of the faces (which in * this case are just the midpoints of the segments connecting the generator * with the two neighbours) w.r.t. the generator, and the cell volume (length) * and centroid (midpoint of the segment connecting the midpoints of the faces). * This function returns the maximal radius at which a particle could still * change the structure of the cell, i.e. twice the largest distance between * the cell generator and one of its faces. If the cell has been interacted with * all neighbours within this radius, we know for sure that the cell is * complete. * * @param cell 1D Voronoi cell. * @return Maximal radius that could still change the structure of the cell. */ __attribute__((always_inline)) INLINE float voronoi_cell_finalize( struct voronoi_cell *cell) { float xL, xR; float max_radius; max_radius = fmax(-cell->xL, cell->xR); cell->xL = xL = 0.5f * cell->xL; cell->xR = xR = 0.5f * cell->xR; cell->volume = xR - xL; cell->centroid = cell->x + 0.5f * (xL + xR); return max_radius; } /** * @brief Get the oriented surface area and midpoint of the face between a * 1D Voronoi cell and the given neighbour. * * This function also checks if the given neighbour is in fact a neighbour of * this cell. Since we perform gradient and flux calculations for all neighbour * pairs within the smoothing length, which assumes the cell to be spherical, * it can happen that this is not the case. It is the responsibility of the * routine that calls this function to check for a zero return value and * deal with it appropriately. * * For this specific case, we simply check if the neighbour is the left or * right neighbour and set the surface area to 1. The midpoint is set to the * relative position vector of the appropriate face. * * @param cell 1D Voronoi cell. * @param ngb ID of a particle that is possibly a neighbour of this cell. * @param midpoint Array to store the relative position of the face in. * @return 0 if the given neighbour is not a neighbour, surface area 1.0f * otherwise. */ __attribute__((always_inline)) INLINE float voronoi_get_face( const struct voronoi_cell *cell, unsigned long long ngb, float *midpoint) { if (ngb != cell->idL && ngb != cell->idR) { /* this is perfectly possible: we interact with all particles within the smoothing length, and they do not need to be all neighbours. If this happens, we return 0, so that the flux method can return */ return 0.0f; } if (ngb == cell->idL) { /* Left face */ midpoint[0] = cell->xL; } else { /* Right face */ midpoint[0] = cell->xR; } /* The other components of midpoint are just zero */ midpoint[1] = 0.0f; midpoint[2] = 0.0f; return 1.0f; } /** * @brief Get the centroid of a 1D Voronoi cell. * * We store only the relevant coordinate of the centroid, but need to return * a 3D vector. * * @param cell 1D Voronoi cell. * @param centroid Array to store the centroid in. */ __attribute__((always_inline)) INLINE void voronoi_get_centroid( const struct voronoi_cell *cell, float *centroid) { centroid[0] = cell->centroid; centroid[1] = 0.0f; centroid[2] = 0.0f; } #endif // SWIFT_VORONOIXD_ALGORITHM_H