/*******************************************************************************
* This file is part of SWIFT.
* Copyright (C) 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
/* Standard headers. */
#include
#include
#include
/* Local headers. */
#include "cell.h"
#include "parser.h"
#include "space.h"
#include "swift.h"
#include "zoom_region/zoom.h"
void make_mock_space(struct space *s) {
/* Define the members we need for the test. */
s->dim[0] = 1000;
s->dim[1] = 1000;
s->dim[2] = 1000;
s->nr_gparts = 18;
/* We need the engine to be NULL for the logic. */
s->e = NULL;
/* Allocate memory for the gparts. */
struct gpart *gparts = NULL;
if (posix_memalign((void **)&gparts, gpart_align,
s->nr_gparts * sizeof(struct gpart)) != 0) {
error("Failed to allocate memory for gparts");
}
bzero(gparts, s->nr_gparts * sizeof(struct gpart));
/* We need the engine to be NULL for the logic. */
s->e = NULL;
/* Define the corners of the region */
double cube_corners[8][3] = {{487.5, 487.5, 487.5}, {487.5, 512.5, 487.5},
{512.5, 487.5, 487.5}, {512.5, 512.5, 487.5},
{487.5, 487.5, 512.5}, {487.5, 512.5, 512.5},
{512.5, 487.5, 512.5}, {512.5, 512.5, 512.5}};
/* Loop over the gparts and set up background and zoom particles. */
for (size_t i = 0; i < s->nr_gparts; i++) {
gparts[i].mass = 1.0;
/* Handle background and zoom region particles differently. */
if (i < 10) {
/* Set background particles to be evenly spaced. */
gparts[i].x[0] = s->dim[0] / s->nr_gparts * i;
gparts[i].x[1] = s->dim[1] / s->nr_gparts * i;
gparts[i].x[2] = s->dim[2] / s->nr_gparts * i;
gparts[i].type = swift_type_dark_matter_background;
} else {
/* Set zoom region particles to be at the corners of the region. */
gparts[i].x[0] = cube_corners[i - 10][0];
gparts[i].x[1] = cube_corners[i - 10][1];
gparts[i].x[2] = cube_corners[i - 10][2];
gparts[i].type = swift_type_dark_matter;
}
s->gparts = gparts;
}
}
void make_mock_cells(struct space *s) {
/* Get the zoom properties */
struct zoom_region_properties *zoom_props = s->zoom_props;
/* Calculate the number of cells. */
s->nr_cells =
s->cdim[0] * s->cdim[1] * s->cdim[2] +
zoom_props->cdim[0] * zoom_props->cdim[1] * zoom_props->cdim[2] +
zoom_props->buffer_cdim[0] * zoom_props->buffer_cdim[1] *
zoom_props->buffer_cdim[2];
/* Allocate cells. */
if (posix_memalign((void **)&s->cells_top, cell_align,
s->nr_cells * sizeof(struct cell)) != 0) {
error("Couldn't allocate the cell");
}
bzero(s->cells_top, s->nr_cells * sizeof(struct cell));
/* Get some zoom region properties */
const int bkg_cell_offset = zoom_props->bkg_cell_offset;
const double zoom_bounds[3] = {zoom_props->region_lower_bounds[0],
zoom_props->region_lower_bounds[1],
zoom_props->region_lower_bounds[2]};
/* Loop over zoom cells and set locations and initial values */
for (int i = 0; i < zoom_props->cdim[0]; i++) {
for (int j = 0; j < zoom_props->cdim[1]; j++) {
for (int k = 0; k < zoom_props->cdim[2]; k++) {
const size_t cid = cell_getid(zoom_props->cdim, i, j, k);
struct cell *c = &s->cells_top[cid];
c->loc[0] = (i * zoom_props->width[0]) + zoom_bounds[0];
c->loc[1] = (j * zoom_props->width[1]) + zoom_bounds[1];
c->loc[2] = (k * zoom_props->width[2]) + zoom_bounds[2];
c->width[0] = zoom_props->width[0];
c->width[1] = zoom_props->width[1];
c->width[2] = zoom_props->width[2];
c->type = cell_type_zoom;
c->subtype = cell_subtype_regular;
}
}
}
/* Loop over background cells and set locations and initial values */
for (int i = 0; i < s->cdim[0]; i++) {
for (int j = 0; j < s->cdim[1]; j++) {
for (int k = 0; k < s->cdim[2]; k++) {
const size_t cid = cell_getid_offset(s->cdim, bkg_cell_offset, i, j, k);
struct cell *c = &s->cells_top[cid];
c->loc[0] = i * s->width[0];
c->loc[1] = j * s->width[1];
c->loc[2] = k * s->width[2];
c->width[0] = s->width[0];
c->width[1] = s->width[1];
c->width[2] = s->width[2];
c->type = cell_type_bkg;
c->subtype = cell_subtype_regular;
}
}
}
/* Label void cells. */
for (int cid = zoom_props->bkg_cell_offset; cid < s->nr_cells; cid++) {
/* Get the cell */
struct cell *c = &s->cells_top[cid];
/* Get the middle of the cell. */
double mid[3] = {c->loc[0] + 0.5 * c->width[0],
c->loc[1] + 0.5 * c->width[1],
c->loc[2] + 0.5 * c->width[2]};
/* Label this cell if it contains the zoom region. */
if ((mid[0] > s->zoom_props->region_lower_bounds[0]) &&
(mid[0] < s->zoom_props->region_upper_bounds[0]) &&
(mid[1] > s->zoom_props->region_lower_bounds[1]) &&
(mid[1] < s->zoom_props->region_upper_bounds[1]) &&
(mid[2] > s->zoom_props->region_lower_bounds[2]) &&
(mid[2] < s->zoom_props->region_upper_bounds[2])) {
c->subtype = cell_subtype_void;
}
}
}
int main(int argc, char *argv[]) {
/* Initialise CPU frequency, this also starts time. */
unsigned long cpu_freq = 0;
clocks_set_cpufreq(cpu_freq);
/* Choke on FPEs */
#ifdef HAVE_FE_ENABLE_EXCEPT
feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW);
#endif
const char *input_file = argv[1];
/* Create a structure to read file into. */
struct swift_params param_file;
/* Read the parameter file. */
parser_read_file(input_file, ¶m_file);
/* Create a space structure. */
struct space s;
bzero(&s, sizeof(struct space));
make_mock_space(&s);
/* Flag that we are running a zoom. */
s.with_zoom_region = 1;
/* Run the zoom_init function. */
zoom_props_init(¶m_file, &s, 0);
zoom_region_init(&s, 0);
/* Make the cells. */
make_mock_cells(&s);
/* Define coordinates to test. */
const double zoom_coords[3] = {500.0, 500.0, 500.0};
const double bkg_coords[3] = {10.0, 990.0, 800.0};
/* Get a zoom, buffer and background cell using cell_getid functions. */
const size_t zoom_cell_id =
cell_getid_from_pos(&s, zoom_coords[0], zoom_coords[1], zoom_coords[2]);
const size_t bkg_cell_id =
cell_getid_from_pos(&s, bkg_coords[0], bkg_coords[1], bkg_coords[2]);
/* Get the cells. */
const struct cell *zoom_cell = &s.cells_top[zoom_cell_id];
const struct cell *bkg_cell = &s.cells_top[bkg_cell_id];
/* Test that the right type of cell was returned. */
assert(zoom_cell->type == cell_type_zoom);
assert(bkg_cell->type == cell_type_bkg);
/* Test that the coordinate is actually inside the returned cell. */
assert(zoom_coords[0] >= zoom_cell->loc[0] &&
zoom_coords[0] < zoom_cell->loc[0] + zoom_cell->width[0]);
assert(zoom_coords[1] >= zoom_cell->loc[1] &&
zoom_coords[1] < zoom_cell->loc[1] + zoom_cell->width[1]);
assert(zoom_coords[2] >= zoom_cell->loc[2] &&
zoom_coords[2] < zoom_cell->loc[2] + zoom_cell->width[2]);
assert(bkg_coords[0] >= bkg_cell->loc[0] &&
bkg_coords[0] < bkg_cell->loc[0] + bkg_cell->width[0]);
assert(bkg_coords[1] >= bkg_cell->loc[1] &&
bkg_coords[1] < bkg_cell->loc[1] + bkg_cell->width[1]);
assert(bkg_coords[2] >= bkg_cell->loc[2] &&
bkg_coords[2] < bkg_cell->loc[2] + bkg_cell->width[2]);
free(s.cells_top);
free(s.zoom_props);
return 0;
}