/******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2012 Pedro Gonnet (pedro.gonnet@durham.ac.uk) * Matthieu Schaller (schaller@strw.leidenuniv.nl) * 2015 Peter W. Draper (p.w.draper@durham.ac.uk) * 2024 Will J. Roper (w.roper@sussex.ac.uk) * * 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 . * ******************************************************************************/ /* Config parameters. */ #include /* Local headers. */ #include "cell.h" #include "engine.h" #include "gravity_properties.h" #include "scheduler.h" #include "space.h" #include "zoom.h" /** * @breif Check whether we need a regrid based on the zoom region. * * This function is called in space_regrid in space_regrid.c and provides * the zoom specific regrid check. * * TODO: In the future this check needs to take into account the particle * distribution to ensure that the zoom region is sufficiently placed given * any bulk motion. * * @param s The #space. * @param new_cdim The new top-level cell dimensions (based on current hmax). * * @return 1 if a zoom regrid is needed, 0 otherwise. */ int zoom_need_regrid(const struct space *s, const int new_cdim[3]) { /* If we are running a zoom do we need to regrid based on the new cdim? */ return (new_cdim[0] < s->zoom_props->cdim[0] || new_cdim[1] < s->zoom_props->cdim[1] || new_cdim[2] < s->zoom_props->cdim[2]); } /** * @brief Find an acceptable geometry given the required zoom cdim. * * Unlike a uniform box, we have options with a zoom region. We can either * increase the background cdim to better resolve the zoom region or we can * increase the depth of the zoom region. * * We'll first try to increase the background cdim a reasonable amount since * this will carry less of a performance penalty for small increases than * doubling the number of zoom cells. This is also most likely to produce a * valid set up in all but the most extreme cases. * * @param s The #space. * @param new_cdim The new top-level cell dimensions (based on current hmax). */ void zoom_regrid_find_acceptable_geometry(struct space *s, const int new_cdim[3]) { /* Loop until we've found an acceptable geometry. */ while (zoom_need_regrid(s, new_cdim)) { /* First try increasing the background cdim to a maximum increase of 50% its * current value. */ int old_bkg_cdim = s->cdim[0]; while (zoom_need_regrid(s, new_cdim) && s->cdim[0] < 1.5 * old_bkg_cdim) { /* Increment the background cdim. */ s->cdim[0]++; s->cdim[1]++; s->cdim[2]++; /* Recalculate the zoom region geometry. (silently) */ zoom_region_init(s, 0); } /* If this worked we can stop here. */ if (!zoom_need_regrid(s, new_cdim)) { break; } /* If it didn't work we'll try increasing the depth of the zoom region (with * the original background cdim). */ s->zoom_props->zoom_cell_depth++; zoom_region_init(s, 0); } } /** * @brief Prepare the cells for the zoom region. * * This function is called in space_regrid in space_regrid.c and provides * the zoom specific cell preparation, freeing only the zoom specific cell * pointer arrays and computing the new zoom region geometry if necessary. * * The cells are counted here and stored on the space. In the zoom case this * includes counts from each top-level cell grid (zoom, bkg, and buffer if * used). * * @param s The #space. * @param zoom_cdim The new top-level cell dimensions (based on current hmax). * @param verbose Whether to print verbose output. */ void zoom_prepare_cells(struct space *s, const int zoom_cdim[3], int verbose) { /* Free the old zoom specific cells, if they were allocated. */ if (s->cells_top != NULL) { swift_free("local_zoom_cells_top", s->zoom_props->local_zoom_cells_top); swift_free("local_bkg_cells_top", s->zoom_props->local_bkg_cells_top); swift_free("local_zoom_cells_with_particles_top", s->zoom_props->local_zoom_cells_with_particles_top); swift_free("local_bkg_cell_with_particless_top", s->zoom_props->local_bkg_cells_with_particles_top); swift_free("local_buffer_cell_with_particless_top", s->zoom_props->local_buffer_cells_with_particles_top); swift_free("void_cell_indices", s->zoom_props->void_cell_indices); swift_free("neighbour_cells_top", s->zoom_props->neighbour_cells_top); /* Find an acceptable geometry given the required zoom cdim. */ zoom_regrid_find_acceptable_geometry(s, zoom_cdim); /* The above function found the geometry silently, if we're running in * verbose mode print the cell properties report. */ if (verbose) { zoom_report_cell_properties(s); } } /* Count the number of top level cells. */ s->tot_cells = s->nr_cells = (s->cdim[0] * s->cdim[1] * s->cdim[2]) + (s->zoom_props->cdim[0] * s->zoom_props->cdim[1] * s->zoom_props->cdim[2]) + (s->zoom_props->buffer_cdim[0] * s->zoom_props->buffer_cdim[1] * s->zoom_props->buffer_cdim[2]); } /** * @brief Allocate the cell indices arrays used for the zoom region. * * @param s The #space. */ void zoom_allocate_cells(struct space *s) { /* Allocate the indices of local zoom cells */ if (swift_memalign("local_zoom_cells_top", (void **)&s->zoom_props->local_zoom_cells_top, SWIFT_STRUCT_ALIGNMENT, s->zoom_props->nr_zoom_cells * sizeof(int)) != 0) error("Failed to allocate indices of local top-level zoom cells."); bzero(s->zoom_props->local_zoom_cells_top, s->zoom_props->nr_zoom_cells * sizeof(int)); /* Allocate the indices of local bkg cells */ if (swift_memalign("local_bkg_cells_top", (void **)&s->zoom_props->local_bkg_cells_top, SWIFT_STRUCT_ALIGNMENT, s->zoom_props->nr_bkg_cells * sizeof(int)) != 0) error("Failed to allocate indices of local top-level background cells."); bzero(s->zoom_props->local_bkg_cells_top, s->zoom_props->nr_bkg_cells * sizeof(int)); /* Allocate the indices of local buffer cells */ if (s->zoom_props->with_buffer_cells) { if (swift_memalign("local_buffer_cells_top", (void **)&s->zoom_props->local_buffer_cells_top, SWIFT_STRUCT_ALIGNMENT, s->zoom_props->nr_buffer_cells * sizeof(int)) != 0) error("Failed to allocate indices of local top-level background cells."); bzero(s->zoom_props->local_buffer_cells_top, s->zoom_props->nr_buffer_cells * sizeof(int)); } /* Allocate the indices of local zoom cells with particles */ if (swift_memalign( "local_zoom_cells_with_particles_top", (void **)&s->zoom_props->local_zoom_cells_with_particles_top, SWIFT_STRUCT_ALIGNMENT, s->zoom_props->nr_zoom_cells * sizeof(int)) != 0) error( "Failed to allocate indices of local top-level zoom cells with " "particles."); bzero(s->zoom_props->local_zoom_cells_with_particles_top, s->zoom_props->nr_zoom_cells * sizeof(int)); /* Allocate the indices of local bkg cells with particles */ if (swift_memalign( "local_bkg_cells_with_particles_top", (void **)&s->zoom_props->local_bkg_cells_with_particles_top, SWIFT_STRUCT_ALIGNMENT, s->zoom_props->nr_bkg_cells * sizeof(int)) != 0) error( "Failed to allocate indices of local top-level background cells with " "particles."); bzero(s->zoom_props->local_bkg_cells_with_particles_top, s->zoom_props->nr_bkg_cells * sizeof(int)); /* Allocate the indices of local buffer cells with particles */ if (s->zoom_props->with_buffer_cells) { if (swift_memalign( "local_buffer_cells_with_particles_top", (void **)&s->zoom_props->local_buffer_cells_with_particles_top, SWIFT_STRUCT_ALIGNMENT, s->zoom_props->nr_buffer_cells * sizeof(int)) != 0) error( "Failed to allocate indices of local top-level buffer cells with " "particles."); bzero(s->zoom_props->local_buffer_cells_with_particles_top, s->zoom_props->nr_buffer_cells * sizeof(int)); } }