diff --git a/examples/EAGLE_12/eagle_12.yml b/examples/EAGLE_12/eagle_12.yml index 24c4876f90e5e6d9b68d1753fa1655c7797e4f58..3721d6690f41ac97148c297480d32018f94d09c0 100644 --- a/examples/EAGLE_12/eagle_12.yml +++ b/examples/EAGLE_12/eagle_12.yml @@ -24,7 +24,7 @@ TimeIntegration: Scheduler: max_top_level_cells: 8 - cell_split_size: 64 + cell_split_size: 50 # Parameters governing the snapshots Snapshots: @@ -56,5 +56,5 @@ SPH: # Parameters related to the initial conditions InitialConditions: - file_name: ./EAGLE_ICs_12.hdf5 # The file to read + file_name: ./EAGLE_ICs_12.hdf5 # The file to read cleanup_h_factors: 1 # Remove the h-factors inherited from Gadget diff --git a/src/Makefile.am b/src/Makefile.am index d1dc10048d01afb7b782421abdd0507ee9f868ea..33bcd78dfe4a1f846a297f47141c2e9914f97f50 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,7 +56,7 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \ units.c common_io.c single_io.c multipole.c version.c map.c \ kernel_hydro.c tools.c part.c partition.c clocks.c parser.c \ physical_constants.c potential.c hydro_properties.c \ - runner_doiact_fft.c threadpool.c cooling.c sourceterms.c \ + threadpool.c cooling.c sourceterms.c \ statistics.c runner_doiact_vec.c profiler.c dump.c logger.c \ part_type.c xmf.c gravity_properties.c gravity.c \ collectgroup.c hydro_space.c equation_of_state.c \ @@ -64,7 +64,7 @@ AM_SOURCES = space.c runner.c queue.c task.c cell.c engine.c \ # Include files for distribution, not installation. nobase_noinst_HEADERS = align.h approx_math.h atomic.h barrier.h cycle.h error.h inline.h kernel_hydro.h kernel_gravity.h \ - kernel_long_gravity.h vector.h cache.h runner_doiact.h runner_doiact_vec.h runner_doiact_grav.h runner_doiact_fft.h \ + kernel_long_gravity.h vector.h cache.h runner_doiact.h runner_doiact_vec.h runner_doiact_grav.h \ runner_doiact_nosort.h units.h intrinsics.h minmax.h kick.h timestep.h drift.h adiabatic_index.h io_properties.h \ dimension.h part_type.h periodic.h memswap.h dump.h logger.h sign.h \ gravity.h gravity_io.h gravity_cache.h \ diff --git a/src/engine.c b/src/engine.c index c53dc74a1af90691973ccac1e1dae79d8486ab13..0d0bbb9965a4c810633b7ece67aaa7effe5bcecb 100644 --- a/src/engine.c +++ b/src/engine.c @@ -339,9 +339,6 @@ void engine_make_hierarchical_tasks_gravity(struct engine *e, struct cell *c) { c->grav_mesh = scheduler_addtask(s, task_type_grav_mesh, task_subtype_none, 0, 0, c, NULL); - // if (periodic) scheduler_addunlock(s, c->init_grav, c->grav_ghost_in); - // if (periodic) scheduler_addunlock(s, c->grav_ghost_out, - // c->grav_down); if (periodic) scheduler_addunlock(s, c->drift_gpart, c->grav_mesh); if (periodic) scheduler_addunlock(s, c->grav_mesh, c->super->end_force); scheduler_addunlock(s, c->init_grav, c->grav_long_range); @@ -3556,13 +3553,6 @@ void engine_marktasks_mapper(void *map_data, int num_elements, if (cell_is_active_gravity(t->ci, e)) scheduler_activate(s, t); } - /* Periodic gravity stuff (Note this is not linked to a cell) ? */ - else if (t->type == task_type_grav_top_level || - t->type == task_type_grav_ghost_in || - t->type == task_type_grav_ghost_out) { - scheduler_activate(s, t); - } - /* Time-step? */ else if (t->type == task_type_timestep) { t->ci->updated = 0; @@ -4203,9 +4193,7 @@ void engine_skip_force_and_kick(struct engine *e) { t->type == task_type_timestep || t->subtype == task_subtype_force || t->subtype == task_subtype_grav || t->type == task_type_end_force || t->type == task_type_grav_long_range || - t->type == task_type_grav_ghost_in || - t->type == task_type_grav_ghost_out || - t->type == task_type_grav_top_level || t->type == task_type_grav_down || + t->type == task_type_grav_down || t->type == task_type_cooling || t->type == task_type_sourceterms) t->skip = 1; } diff --git a/src/mesh_gravity.c b/src/mesh_gravity.c index 5c0016bc51c5887867d81bfff1e4c7314f5929c6..4f5ff463543a0484229cde131de17cbc6a98405b 100644 --- a/src/mesh_gravity.c +++ b/src/mesh_gravity.c @@ -178,7 +178,7 @@ INLINE static void gpart_to_mesh_CIC(const struct gpart* gp, double* rho, int N, void mesh_to_gparts_CIC(struct gpart* gp, const double* pot, int N, double fac, const double dim[3]) { - /* Box wrap the multipole's position */ + /* Box wrap the gpart's position */ const double pos_x = box_wrap(gp->x[0], 0., dim[0]); const double pos_y = box_wrap(gp->x[1], 0., dim[1]); const double pos_z = box_wrap(gp->x[2], 0., dim[2]); diff --git a/src/runner.c b/src/runner.c index a4430988872ab0bb139cb64bf0e6809e209fd316..6af9cdb8d1db07f9e8919ea4cf2d93adb011a5e4 100644 --- a/src/runner.c +++ b/src/runner.c @@ -54,7 +54,6 @@ #include "hydro_properties.h" #include "kick.h" #include "minmax.h" -#include "runner_doiact_fft.h" #include "runner_doiact_vec.h" #include "scheduler.h" #include "sort_part.h" @@ -95,7 +94,6 @@ #undef FUNCTION_TASK_LOOP /* Import the gravity loop functions. */ -#include "runner_doiact_fft.h" #include "runner_doiact_grav.h" /** @@ -1750,27 +1748,27 @@ void runner_do_end_force(struct runner *r, struct cell *c, int timer) { /* Check that this gpart has interacted with all the other * particles (via direct or multipoles) in the box */ - /* if (gp->num_interacted != e->total_nr_gparts) { */ - - /* /\* Get the ID of the gpart *\/ */ - /* long long my_id = 0; */ - /* if (gp->type == swift_type_gas) */ - /* my_id = e->s->parts[-gp->id_or_neg_offset].id; */ - /* else if (gp->type == swift_type_star) */ - /* my_id = e->s->sparts[-gp->id_or_neg_offset].id; */ - /* else if (gp->type == swift_type_black_hole) */ - /* error("Unexisting type"); */ - /* else */ - /* my_id = gp->id_or_neg_offset; */ - - /* error( */ - /* "g-particle (id=%lld, type=%s) did not interact " */ - /* "gravitationally with all other gparts " */ - /* "gp->num_interacted=%lld, total_gparts=%lld (local " */ - /* "num_gparts=%zd)", */ - /* my_id, part_type_names[gp->type], gp->num_interacted, */ - /* e->total_nr_gparts, e->s->nr_gparts); */ - /* } */ + if (gp->num_interacted != e->total_nr_gparts) { + + /* Get the ID of the gpart */ + long long my_id = 0; + if (gp->type == swift_type_gas) + my_id = e->s->parts[-gp->id_or_neg_offset].id; + else if (gp->type == swift_type_star) + my_id = e->s->sparts[-gp->id_or_neg_offset].id; + else if (gp->type == swift_type_black_hole) + error("Unexisting type"); + else + my_id = gp->id_or_neg_offset; + + error( + "g-particle (id=%lld, type=%s) did not interact " + "gravitationally with all other gparts " + "gp->num_interacted=%lld, total_gparts=%lld (local " + "num_gparts=%zd)", + my_id, part_type_names[gp->type], gp->num_interacted, + e->total_nr_gparts, e->s->nr_gparts); + } } #endif } @@ -2224,9 +2222,6 @@ void *runner_main(void *data) { case task_type_grav_mesh: runner_do_grav_mesh(r, t->ci, 1); break; - case task_type_grav_top_level: - // runner_do_grav_fft(r, 1); - break; case task_type_grav_long_range: runner_do_grav_long_range(r, t->ci, 1); break; diff --git a/src/runner_doiact_fft.c b/src/runner_doiact_fft.c deleted file mode 100644 index 475e82900c0099003785220b4e77041633669f4f..0000000000000000000000000000000000000000 --- a/src/runner_doiact_fft.c +++ /dev/null @@ -1,601 +0,0 @@ -/******************************************************************************* - * This file is part of SWIFT. - * Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.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 <http://www.gnu.org/licenses/>. - * - ******************************************************************************/ - -/* Config parameters. */ -#include "../config.h" - -#ifdef HAVE_FFTW -#include <fftw3.h> -#endif - -/* This object's header. */ -#include "runner_doiact_fft.h" - -/* Local includes. */ -#include "debug.h" -#include "engine.h" -#include "error.h" -#include "kernel_long_gravity.h" -#include "part.h" -#include "runner.h" -#include "space.h" -#include "timers.h" - -#ifdef HAVE_FFTW2 - -/** - * @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)) INLINE static int row_major_id(int i, int j, - int k, int N) { - return (((i + N) % N) * N * N + ((j + N) % N) * N + ((k + N) % N)); -} - -/** - * @brief Interpolate values from a the mesh using CIC. - * - * @param mesh The mesh to read from. - * @param i The index of the cell along x - * @param j The index of the cell along y - * @param k The index of the cell along z - * @param tx First CIC coefficient along x - * @param ty First CIC coefficient along y - * @param tz First CIC coefficient along z - * @param dx Second CIC coefficient along x - * @param dy Second CIC coefficient along y - * @param dz Second CIC coefficient along z - */ -__attribute__((always_inline)) INLINE static double CIC_get( - double mesh[6][6][6], int i, int j, int k, double tx, double ty, double tz, - double dx, double dy, double dz) { - - double temp; - temp = mesh[i + 0][j + 0][k + 0] * tx * ty * tz; - temp += mesh[i + 0][j + 0][k + 1] * tx * ty * dz; - temp += mesh[i + 0][j + 1][k + 0] * tx * dy * tz; - temp += mesh[i + 0][j + 1][k + 1] * tx * dy * dz; - temp += mesh[i + 1][j + 0][k + 0] * dx * ty * tz; - temp += mesh[i + 1][j + 0][k + 1] * dx * ty * dz; - temp += mesh[i + 1][j + 1][k + 0] * dx * dy * tz; - temp += mesh[i + 1][j + 1][k + 1] * dx * dy * dz; - - return temp; -} - -/** - * @brief Assigns a given multipole to a density mesh using the CIC method. - * - * @param m The #multipole. - * @param rho The density mesh. - * @param N the size of the mesh along one axis. - * @param fac The width of a mesh cell. - * @param dim The dimensions of the simulation box. - */ -void multipole_to_mesh_CIC(const struct gravity_tensors* m, double* rho, int N, - double fac, const double dim[3]) { - - /* Box wrap the multipole's position */ - const double CoM_x = box_wrap(m->CoM[0], 0., dim[0]); - const double CoM_y = box_wrap(m->CoM[1], 0., dim[1]); - const double CoM_z = box_wrap(m->CoM[2], 0., dim[2]); - - int i = (int)(fac * CoM_x); - if (i >= N) i = N - 1; - const double dx = fac * CoM_x - i; - const double tx = 1. - dx; - - int j = (int)(fac * CoM_y); - if (j >= N) j = N - 1; - const double dy = fac * CoM_y - j; - const double ty = 1. - dy; - - int k = (int)(fac * CoM_z); - if (k >= N) k = N - 1; - const double dz = fac * CoM_z - k; - const double tz = 1. - dz; - -#ifdef SWIFT_DEBUG_CHECKS - if (i < 0 || i >= N) error("Invalid multipole position in x"); - if (j < 0 || j >= N) error("Invalid multipole position in y"); - if (k < 0 || k >= N) error("Invalid multipole position in z"); -#endif - - const double mass = m->m_pole.M_000; - - /* CIC ! */ - rho[row_major_id(i + 0, j + 0, k + 0, N)] += mass * tx * ty * tz; - rho[row_major_id(i + 0, j + 0, k + 1, N)] += mass * tx * ty * dz; - rho[row_major_id(i + 0, j + 1, k + 0, N)] += mass * tx * dy * tz; - rho[row_major_id(i + 0, j + 1, k + 1, N)] += mass * tx * dy * dz; - rho[row_major_id(i + 1, j + 0, k + 0, N)] += mass * dx * ty * tz; - rho[row_major_id(i + 1, j + 0, k + 1, N)] += mass * dx * ty * dz; - rho[row_major_id(i + 1, j + 1, k + 0, N)] += mass * dx * dy * tz; - rho[row_major_id(i + 1, j + 1, k + 1, N)] += mass * dx * dy * dz; -} - -/** - * @brief Computes the potential on a multipole from a given mesh using the CIC - * method. - * - * @param m The #multipole. - * @param pot The potential mesh. - * @param N the size of the mesh along one axis. - * @param fac width of a mesh cell. - * @param dim The dimensions of the simulation box. - */ -void mesh_to_multipole_CIC(struct gravity_tensors* m, const double* pot, int N, - double fac, const double dim[3]) { - - /* Box wrap the multipole's position */ - const double CoM_x = box_wrap(m->CoM[0], 0., dim[0]); - const double CoM_y = box_wrap(m->CoM[1], 0., dim[1]); - const double CoM_z = box_wrap(m->CoM[2], 0., dim[2]); - - int i = (int)(fac * CoM_x); - if (i >= N) i = N - 1; - const double dx = fac * CoM_x - i; - const double tx = 1. - dx; - - int j = (int)(fac * CoM_y); - if (j >= N) j = N - 1; - const double dy = fac * CoM_y - j; - const double ty = 1. - dy; - - int k = (int)(fac * CoM_z); - if (k >= N) k = N - 1; - const double dz = fac * CoM_z - k; - const double tz = 1. - dz; - -#ifdef SWIFT_DEBUG_CHECKS - if (i < 0 || i >= N) error("Invalid multipole position in x"); - if (j < 0 || j >= N) error("Invalid multipole position in y"); - if (k < 0 || k >= N) error("Invalid multipole position in z"); -#endif - - /* First, copy the necessary part of the mesh for stencil operations */ - /* This includes box-wrapping in all 3 dimensions. */ - double phi[6][6][6]; - for (int iii = -2; iii <= 3; ++iii) { - for (int jjj = -2; jjj <= 3; ++jjj) { - for (int kkk = -2; kkk <= 3; ++kkk) { - phi[iii + 2][jjj + 2][kkk + 2] = - pot[row_major_id(i + iii, j + jjj, k + kkk, N)]; - } - } - } - - /* Indices of (i,j,k) in the local copy of the mesh */ - const int ii = 2, jj = 2, kk = 2; - - /* Some local accumulators */ - double F_000 = 0.; - double F_100 = 0., F_010 = 0., F_001 = 0.; - double F_200 = 0., F_020 = 0., F_002 = 0.; - double F_110 = 0., F_101 = 0., F_011 = 0.; - double F_300 = 0., F_030 = 0., F_003 = 0.; - - /* Simple CIC for the potential itself */ - F_000 -= CIC_get(phi, ii, jj, kk, tx, ty, tz, dx, dy, dz); - - /* ---- */ - - /* 5-point stencil along each axis for the 1st derivatives */ - F_100 -= (1. / 12.) * CIC_get(phi, ii + 2, jj, kk, tx, ty, tz, dx, dy, dz); - F_100 += (2. / 3.) * CIC_get(phi, ii + 1, jj, kk, tx, ty, tz, dx, dy, dz); - F_100 -= (2. / 3.) * CIC_get(phi, ii - 1, jj, kk, tx, ty, tz, dx, dy, dz); - F_100 += (1. / 12.) * CIC_get(phi, ii - 2, jj, kk, tx, ty, tz, dx, dy, dz); - - F_010 -= (1. / 12.) * CIC_get(phi, ii, jj + 2, kk, tx, ty, tz, dx, dy, dz); - F_010 += (2. / 3.) * CIC_get(phi, ii, jj + 1, kk, tx, ty, tz, dx, dy, dz); - F_010 -= (2. / 3.) * CIC_get(phi, ii, jj - 1, kk, tx, ty, tz, dx, dy, dz); - F_010 += (1. / 12.) * CIC_get(phi, ii, jj - 2, kk, tx, ty, tz, dx, dy, dz); - - F_001 -= (1. / 12.) * CIC_get(phi, ii, jj, kk + 2, tx, ty, tz, dx, dy, dz); - F_001 += (2. / 3.) * CIC_get(phi, ii, jj, kk + 1, tx, ty, tz, dx, dy, dz); - F_001 -= (2. / 3.) * CIC_get(phi, ii, jj, kk - 1, tx, ty, tz, dx, dy, dz); - F_001 += (1. / 12.) * CIC_get(phi, ii, jj, kk - 2, tx, ty, tz, dx, dy, dz); - - /* ---- */ - - /* 5-point stencil along each axis for the 2nd derivatives (diagonal) */ - F_200 -= (1. / 12.) * CIC_get(phi, ii + 2, jj, kk, tx, ty, tz, dx, dy, dz); - F_200 += (4. / 3.) * CIC_get(phi, ii + 1, jj, kk, tx, ty, tz, dx, dy, dz); - F_200 -= (5. / 2.) * CIC_get(phi, ii + 0, jj, kk, tx, ty, tz, dx, dy, dz); - F_200 += (4. / 3.) * CIC_get(phi, ii - 1, jj, kk, tx, ty, tz, dx, dy, dz); - F_200 -= (1. / 12.) * CIC_get(phi, ii - 2, jj, kk, tx, ty, tz, dx, dy, dz); - - F_020 -= (1. / 12.) * CIC_get(phi, ii, jj + 2, kk, tx, ty, tz, dx, dy, dz); - F_020 += (4. / 3.) * CIC_get(phi, ii, jj + 1, kk, tx, ty, tz, dx, dy, dz); - F_020 -= (5. / 2.) * CIC_get(phi, ii, jj + 0, kk, tx, ty, tz, dx, dy, dz); - F_020 += (4. / 3.) * CIC_get(phi, ii, jj - 1, kk, tx, ty, tz, dx, dy, dz); - F_020 -= (1. / 12.) * CIC_get(phi, ii, jj - 2, kk, tx, ty, tz, dx, dy, dz); - - F_002 -= (1. / 12.) * CIC_get(phi, ii, jj, kk + 2, tx, ty, tz, dx, dy, dz); - F_002 += (4. / 3.) * CIC_get(phi, ii, jj, kk + 1, tx, ty, tz, dx, dy, dz); - F_002 -= (5. / 2.) * CIC_get(phi, ii, jj, kk + 0, tx, ty, tz, dx, dy, dz); - F_002 += (4. / 3.) * CIC_get(phi, ii, jj, kk - 1, tx, ty, tz, dx, dy, dz); - F_002 -= (1. / 12.) * CIC_get(phi, ii, jj, kk - 2, tx, ty, tz, dx, dy, dz); - - /* Regular stencil for the 2nd derivatives (non-diagonal) */ - F_110 += (1. / 4.) * CIC_get(phi, ii + 1, jj + 1, kk, tx, ty, tz, dx, dy, dz); - F_110 -= (1. / 4.) * CIC_get(phi, ii + 1, jj - 1, kk, tx, ty, tz, dx, dy, dz); - F_110 -= (1. / 4.) * CIC_get(phi, ii - 1, jj + 1, kk, tx, ty, tz, dx, dy, dz); - F_110 += (1. / 4.) * CIC_get(phi, ii - 1, jj - 1, kk, tx, ty, tz, dx, dy, dz); - - F_101 += (1. / 4.) * CIC_get(phi, ii + 1, jj, kk + 1, tx, ty, tz, dx, dy, dz); - F_101 -= (1. / 4.) * CIC_get(phi, ii + 1, jj, kk - 1, tx, ty, tz, dx, dy, dz); - F_101 -= (1. / 4.) * CIC_get(phi, ii - 1, jj, kk + 1, tx, ty, tz, dx, dy, dz); - F_101 += (1. / 4.) * CIC_get(phi, ii - 1, jj, kk - 1, tx, ty, tz, dx, dy, dz); - - F_011 += (1. / 4.) * CIC_get(phi, ii, jj + 1, kk + 1, tx, ty, tz, dx, dy, dz); - F_011 -= (1. / 4.) * CIC_get(phi, ii, jj + 1, kk - 1, tx, ty, tz, dx, dy, dz); - F_011 -= (1. / 4.) * CIC_get(phi, ii, jj - 1, kk + 1, tx, ty, tz, dx, dy, dz); - F_011 += (1. / 4.) * CIC_get(phi, ii, jj - 1, kk - 1, tx, ty, tz, dx, dy, dz); - - /* ---- */ - - /* 5-point stencil along each axis for the 3rd derivatives (diagonal) */ - F_300 -= (1. / 2.) * CIC_get(phi, ii + 2, jj, kk, tx, ty, tz, dx, dy, dz); - F_300 += 1. * CIC_get(phi, ii + 1, jj, kk, tx, ty, tz, dx, dy, dz); - F_300 -= 1. * CIC_get(phi, ii - 1, jj, kk, tx, ty, tz, dx, dy, dz); - F_300 += (1. / 2.) * CIC_get(phi, ii - 2, jj, kk, tx, ty, tz, dx, dy, dz); - - F_030 -= (1. / 2.) * CIC_get(phi, ii, jj + 2, kk, tx, ty, tz, dx, dy, dz); - F_030 += (2. / 3.) * CIC_get(phi, ii, jj + 1, kk, tx, ty, tz, dx, dy, dz); - F_030 -= (2. / 3.) * CIC_get(phi, ii, jj - 1, kk, tx, ty, tz, dx, dy, dz); - F_030 += (1. / 2.) * CIC_get(phi, ii, jj - 2, kk, tx, ty, tz, dx, dy, dz); - - F_003 -= (1. / 2.) * CIC_get(phi, ii, jj, kk + 2, tx, ty, tz, dx, dy, dz); - F_003 += 1. * CIC_get(phi, ii, jj, kk + 1, tx, ty, tz, dx, dy, dz); - F_003 -= 1. * CIC_get(phi, ii, jj, kk - 1, tx, ty, tz, dx, dy, dz); - F_003 += (1. / 2.) * CIC_get(phi, ii, jj, kk - 2, tx, ty, tz, dx, dy, dz); - - /* Store things back */ - m->pot.F_000 += F_000; - m->pot.F_100 -= F_100 * fac; - m->pot.F_010 -= F_010 * fac; - m->pot.F_001 -= F_001 * fac; - m->pot.F_200 += F_200 * fac * fac; - m->pot.F_020 += F_020 * fac * fac; - m->pot.F_002 += F_002 * fac * fac; - m->pot.F_110 -= F_110 * fac * fac; - m->pot.F_011 -= F_011 * fac * fac; - m->pot.F_101 -= F_101 * fac * fac; - m->pot.F_300 += F_300 * fac * fac * fac; - m->pot.F_030 += F_030 * fac * fac * fac; - m->pot.F_003 += F_003 * fac * fac * fac; - - m->pot.interacted = 1; -} - -#ifdef SWIFT_GRAVITY_FORCE_CHECKS - -/** - * @brief Computes the potential on a gpart from a given mesh using the CIC - * method. - * - * Debugging routine. - * - * @param gp The #gpart. - * @param pot The potential mesh. - * @param N the size of the mesh along one axis. - * @param fac width of a mesh cell. - * @param dim The dimensions of the simulation box. - */ -void mesh_to_gparts_CIC(struct gpart* gp, const double* pot, int N, double fac, - const double dim[3]) { - - /* Box wrap the multipole's position */ - const double pos_x = box_wrap(gp->x[0], 0., dim[0]); - const double pos_y = box_wrap(gp->x[1], 0., dim[1]); - const double pos_z = box_wrap(gp->x[2], 0., dim[2]); - - int i = (int)(fac * pos_x); - if (i >= N) i = N - 1; - const double dx = fac * pos_x - i; - const double tx = 1. - dx; - - int j = (int)(fac * pos_y); - if (j >= N) j = N - 1; - const double dy = fac * pos_y - j; - const double ty = 1. - dy; - - int k = (int)(fac * pos_z); - if (k >= N) k = N - 1; - const double dz = fac * pos_z - k; - const double tz = 1. - dz; - -#ifdef SWIFT_DEBUG_CHECKS - if (i < 0 || i >= N) error("Invalid multipole position in x"); - if (j < 0 || j >= N) error("Invalid multipole position in y"); - if (k < 0 || k >= N) error("Invalid multipole position in z"); -#endif - - if (gp->a_grav_PM[0] != 0. || gp->potential_PM != 0.) - error("Particle with non-initalised stuff"); - - /* First, copy the necessary part of the mesh for stencil operations */ - /* This includes box-wrapping in all 3 dimensions. */ - double phi[6][6][6]; - for (int iii = -2; iii <= 3; ++iii) { - for (int jjj = -2; jjj <= 3; ++jjj) { - for (int kkk = -2; kkk <= 3; ++kkk) { - phi[iii + 2][jjj + 2][kkk + 2] = - pot[row_major_id(i + iii, j + jjj, k + kkk, N)]; - } - } - } - - /* Some local accumulators */ - double p = 0.; - double a[3] = {0.}; - - /* Indices of (i,j,k) in the local copy of the mesh */ - const int ii = 2, jj = 2, kk = 2; - - /* Simple CIC for the potential itself */ - p += CIC_get(phi, ii, jj, kk, tx, ty, tz, dx, dy, dz); - - /* ---- */ - - /* 5-point stencil along each axis for the accelerations */ - a[0] += (1. / 12.) * CIC_get(phi, ii + 2, jj, kk, tx, ty, tz, dx, dy, dz); - a[0] -= (2. / 3.) * CIC_get(phi, ii + 1, jj, kk, tx, ty, tz, dx, dy, dz); - a[0] += (2. / 3.) * CIC_get(phi, ii - 1, jj, kk, tx, ty, tz, dx, dy, dz); - a[0] -= (1. / 12.) * CIC_get(phi, ii - 2, jj, kk, tx, ty, tz, dx, dy, dz); - - a[1] += (1. / 12.) * CIC_get(phi, ii, jj + 2, kk, tx, ty, tz, dx, dy, dz); - a[1] -= (2. / 3.) * CIC_get(phi, ii, jj + 1, kk, tx, ty, tz, dx, dy, dz); - a[1] += (2. / 3.) * CIC_get(phi, ii, jj - 1, kk, tx, ty, tz, dx, dy, dz); - a[1] -= (1. / 12.) * CIC_get(phi, ii, jj - 2, kk, tx, ty, tz, dx, dy, dz); - - a[2] += (1. / 12.) * CIC_get(phi, ii, jj, kk + 2, tx, ty, tz, dx, dy, dz); - a[2] -= (2. / 3.) * CIC_get(phi, ii, jj, kk + 1, tx, ty, tz, dx, dy, dz); - a[2] += (2. / 3.) * CIC_get(phi, ii, jj, kk - 1, tx, ty, tz, dx, dy, dz); - a[2] -= (1. / 12.) * CIC_get(phi, ii, jj, kk - 2, tx, ty, tz, dx, dy, dz); - - /* ---- */ - - /* Store things back */ - gp->potential_PM = p; - gp->a_grav_PM[0] = fac * a[0]; - gp->a_grav_PM[1] = fac * a[1]; - gp->a_grav_PM[2] = fac * a[2]; -} -#endif - -/** - * @brief Dump a real array of size NxNxN to stdout. - * - * Debugging routine. - * - * @param array The array to dump. - * @param N The side-length of the array to dump - */ -void print_array(double* array, int N) { - - for (int k = N - 1; k >= 0; --k) { - printf("--- z = %d ---------\n", k); - for (int j = N - 1; j >= 0; --j) { - for (int i = 0; i < N; ++i) { - printf("%f ", array[i * N * N + j * N + k]); - } - printf("\n"); - } - } -} - -/** - * @brief Dump a complex array of size NxNxN to stdout. - * - * Debugging routine. - * - * @param array The array to dump. - * @param N The side-length of the array to dump - */ -void print_carray(fftw_complex* array, int N) { - - for (int k = N - 1; k >= 0; --k) { - printf("--- z = %d ---------\n", k); - for (int j = N - 1; j >= 0; --j) { - for (int i = 0; i < N; ++i) { - printf("(%f %f) ", array[i * N * N + j * N + k][0], - array[i * N * N + j * N + k][1]); - } - printf("\n"); - } - } -} - -#endif /* HAVE_FFTW */ - -/** - * @brief Computes the potential on the top multipoles using a Fourier transform - * - * @param r The #runner task - * @param timer Are we timing this ? - */ -void runner_do_grav_fft(struct runner* r, int timer) { - -#ifdef HAVE_FFTW2 - - const struct engine* e = r->e; - const struct space* s = e->s; - const double a_smooth = e->gravity_properties->a_smooth; - const double box_size = s->dim[0]; - const int cdim[3] = {s->cdim[0], s->cdim[1], s->cdim[2]}; - const double dim[3] = {s->dim[0], s->dim[1], s->dim[2]}; - - TIMER_TIC; - - if (cdim[0] != cdim[1] || cdim[0] != cdim[2]) error("Non-square mesh"); - if (a_smooth <= 0.) error("Invalid value of a_smooth"); - - /* Some useful constants */ - const int N = cdim[0]; - const int N_half = N / 2; - const double cell_fac = N / box_size; - - /* Recover the list of top-level multipoles */ - const int nr_cells = s->nr_cells; - struct gravity_tensors* restrict multipoles = s->multipoles_top; - -#ifdef SWIFT_DEBUG_CHECKS - const struct cell* cells = s->cells_top; - const integertime_t ti_current = e->ti_current; - - /* Make sure everything has been drifted to the current point */ - for (int i = 0; i < nr_cells; ++i) - if (cells[i].ti_old_multipole != ti_current) - error("Top-level multipole %d not drifted", i); -#endif - - /* Allocates some memory for the density mesh */ - double* restrict rho = (double*)fftw_malloc(sizeof(double) * N * N * N); - if (rho == NULL) error("Error allocating memory for density mesh"); - - /* Allocates some memory for the mesh in Fourier space */ - fftw_complex* restrict frho = - (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * N * N * (N_half + 1)); - if (frho == NULL) - error("Error allocating memory for transform of density mesh"); - - /* Prepare the FFT library */ - fftw_plan forward_plan = fftw_plan_dft_r2c_3d( - N, N, N, rho, frho, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); - fftw_plan inverse_plan = fftw_plan_dft_c2r_3d( - N, N, N, frho, rho, FFTW_ESTIMATE | FFTW_DESTROY_INPUT); - - /* Do a CIC mesh assignment of the multipoles */ - bzero(rho, N * N * N * sizeof(double)); - for (int i = 0; i < nr_cells; ++i) - multipole_to_mesh_CIC(&multipoles[i], rho, N, cell_fac, dim); - - /* print_array(rho, N); */ - - /* Fourier transform to go to magic-land */ - fftw_execute(forward_plan); - - /* frho now contains the Fourier transform of the density field */ - /* frho contains NxNx(N/2+1) complex numbers */ - - /* Some common factors */ - const double green_fac = -1. / (M_PI * box_size); - const double a_smooth2 = - 4. * M_PI * M_PI * a_smooth * a_smooth / ((double)(N * N)); - const double k_fac = M_PI / (double)N; - - /* Now de-convolve the CIC kernel and apply the Green function */ - for (int i = 0; i < N; ++i) { - - /* kx component of vector in Fourier space and 1/sinc(kx) */ - const int kx = (i > N_half ? i - N : i); - const double kx_d = (double)kx; - const double fx = k_fac * kx_d; - const double sinc_kx_inv = (kx != 0) ? fx / sin(fx) : 1.; - - for (int j = 0; j < N; ++j) { - - /* ky component of vector in Fourier space and 1/sinc(ky) */ - const int ky = (j > N_half ? j - N : j); - const double ky_d = (double)ky; - const double fy = k_fac * ky_d; - const double sinc_ky_inv = (ky != 0) ? fy / sin(fy) : 1.; - - for (int k = 0; k < N_half + 1; ++k) { - - /* kz component of vector in Fourier space and 1/sinc(kz) */ - const int kz = (k > N_half ? k - N : k); - const double kz_d = (double)kz; - const double fz = k_fac * kz_d; - const double sinc_kz_inv = (kz != 0) ? fz / (sin(fz) + FLT_MIN) : 1.; - - /* Norm of vector in Fourier space */ - const double k2 = (kx_d * kx_d + ky_d * ky_d + kz_d * kz_d); - - /* Avoid FPEs... */ - if (k2 == 0.) continue; - - /* Green function */ - double W; - fourier_kernel_long_grav_eval(k2 * a_smooth2, &W); - const double green_cor = green_fac * W / (k2 + FLT_MIN); - - /* Deconvolution of CIC */ - const double CIC_cor = sinc_kx_inv * sinc_ky_inv * sinc_kz_inv; - const double CIC_cor2 = CIC_cor * CIC_cor; - const double CIC_cor4 = CIC_cor2 * CIC_cor2; - - /* Combined correction */ - const double total_cor = green_cor * CIC_cor4; - - /* Apply to the mesh */ - const int index = N * (N_half + 1) * i + (N_half + 1) * j + k; - frho[index][0] *= total_cor; - frho[index][1] *= total_cor; - } - } - } - - /* Correct singularity at (0,0,0) */ - frho[0][0] = 0.; - frho[0][1] = 0.; - - /* Fourier transform to come back from magic-land */ - fftw_execute(inverse_plan); - - /* rho now contains the potential */ - /* Let's create an alias to avoid confusion */ - /* This array is now again NxNxN real numbers */ - double* potential = rho; - - /* message("\n\n\n POTENTIAL"); */ - /* print_array(potential, N); */ - - /* Get the potential from the mesh to the gravity tensors using CIC */ - for (int i = 0; i < nr_cells; ++i) - mesh_to_multipole_CIC(&multipoles[i], potential, N, cell_fac, dim); - -#ifdef SWIFT_GRAVITY_FORCE_CHECKS - /* Get the potential from the mesh to the gparts using CIC */ - for (size_t i = 0; i < s->nr_gparts; ++i) - mesh_to_gparts_CIC(&s->gparts[i], potential, N, cell_fac, dim); -#endif - - /* Clean-up the mess */ - fftw_destroy_plan(forward_plan); - fftw_destroy_plan(inverse_plan); - fftw_free(rho); - fftw_free(frho); - - /* Time the whole thing */ - if (timer) TIMER_TOC(timer_dograv_top_level); - -#else - error("No FFTW library found. Cannot compute periodic long-range forces."); -#endif -} diff --git a/src/runner_doiact_fft.h b/src/runner_doiact_fft.h deleted file mode 100644 index 93fee635e11a9bf048a1ca7f59ded985bec952b7..0000000000000000000000000000000000000000 --- a/src/runner_doiact_fft.h +++ /dev/null @@ -1,33 +0,0 @@ -/******************************************************************************* - * This file is part of SWIFT. - * Copyright (c) 2016 Matthieu Schaller (matthieu.schaller@durham.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 <http://www.gnu.org/licenses/>. - * - ******************************************************************************/ -#ifndef SWIFT_RUNNER_DOIACT_FFT_H -#define SWIFT_RUNNER_DOIACT_FFT_H - -struct runner; -struct gravity_tensors; - -void runner_do_grav_fft(struct runner* r, int timer); - -void multipole_to_mesh_CIC(const struct gravity_tensors* m, double* rho, int N, - double fac, const double dim[3]); - -void mesh_to_multipole_CIC(struct gravity_tensors* m, const double* pot, int N, - double fac, const double dim[3]); - -#endif /* SWIFT_RUNNER_DOIACT_FFT_H */ diff --git a/src/scheduler.c b/src/scheduler.c index 187ad7093badc6c53ccbb95377969550f9bffc67..6bae7f2f3c4d75ea7c7e2b1b233ed96e54e9cae2 100644 --- a/src/scheduler.c +++ b/src/scheduler.c @@ -263,7 +263,7 @@ void scheduler_write_dependencies(struct scheduler *s, int verbose) { if (type == task_type_self + k && subtype == task_subtype_grav) gravity_cluster[k] = 1; } - if (type == task_type_grav_top_level) gravity_cluster[2] = 1; + if (type == task_type_grav_mesh) gravity_cluster[2] = 1; if (type == task_type_grav_long_range) gravity_cluster[3] = 1; } } @@ -304,7 +304,7 @@ void scheduler_write_dependencies(struct scheduler *s, int verbose) { fprintf(f, "\t\t \"%s %s\";\n", taskID_names[task_type_self + k], subtaskID_names[task_subtype_grav]); if (gravity_cluster[2]) - fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_top_level]); + fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_mesh]); if (gravity_cluster[3]) fprintf(f, "\t\t %s;\n", taskID_names[task_type_grav_long_range]); fprintf(f, "\t};\n"); @@ -901,9 +901,7 @@ void scheduler_splittasks_mapper(void *map_data, int num_elements, scheduler_splittask_gravity(t, s); } else if (t->subtype == task_subtype_grav) { scheduler_splittask_gravity(t, s); - } else if (t->type == task_type_grav_top_level || - t->type == task_type_grav_ghost_in || - t->type == task_type_grav_ghost_out) { + } else if (t->type == task_type_grav_mesh) { /* For future use */ } else { error("Unexpected task sub-type"); diff --git a/src/task.c b/src/task.c index e37da280bc57f9a75243c8db2eaf4ae794c53d1d..25e77da89f7ca937b29956458ce4d61026dd5bcc 100644 --- a/src/task.c +++ b/src/task.c @@ -54,8 +54,7 @@ const char *taskID_names[task_type_count] = { "ghost_out", "extra_ghost", "drift_part", "drift_gpart", "end_force", "kick1", "kick2", "timestep", "send", - "recv", "grav_top_level", "grav_long_range", - "grav_ghost_in", "grav_ghost_out", "grav_mm", + "recv", "grav_long_range","grav_mm", "grav_down", "grav_mesh", "cooling", "sourceterms"}; @@ -172,7 +171,6 @@ __attribute__((always_inline)) INLINE static enum task_actions task_acts_on( break; case task_type_init_grav: - case task_type_grav_top_level: case task_type_grav_mm: return task_action_multipole; break; diff --git a/src/task.h b/src/task.h index fdd679347f21ae83c8a388231859ee31c5a6135e..f6dcc652df41c5459fd19030387cd6ddbe9360fd 100644 --- a/src/task.h +++ b/src/task.h @@ -58,10 +58,7 @@ enum task_types { task_type_timestep, task_type_send, task_type_recv, - task_type_grav_top_level, task_type_grav_long_range, - task_type_grav_ghost_in, - task_type_grav_ghost_out, task_type_grav_mm, task_type_grav_down, task_type_grav_mesh,