/******************************************************************************* * This file is part of SWIFT. * Copyright (c) 2013 Pedro Gonnet (pedro.gonnet@durham.ac.uk) * 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_MULTI_SOFTENING_GRAVITY_IACT_H #define SWIFT_MULTI_SOFTENING_GRAVITY_IACT_H /* Includes. */ #include "kernel_gravity.h" #include "kernel_long_gravity.h" #include "multipole.h" /* Standard headers */ #include /** * @brief Computes the intensity of the force at a point generated by a * point-mass. * * The returned quantity needs to be multiplied by the distance vector to obtain * the force vector. * * @param r2 Square of the distance to the point-mass. * @param h2 Square of the softening length. * @param h_inv Inverse of the softening length. * @param h_inv3 Cube of the inverse of the softening length. * @param mass Mass of the point-mass. * @param f_ij (return) The force intensity. * @param pot_ij (return) The potential. */ __attribute__((always_inline, nonnull)) INLINE static void runner_iact_grav_pp_full(const float r2, const float h2, const float h_inv, const float h_inv3, const float mass, float *restrict f_ij, float *restrict pot_ij) { /* Get the inverse distance */ const float r_inv = 1.f / sqrtf(r2 + FLT_MIN); /* Should we soften ? */ if (r2 >= h2) { /* Get Newtonian gravity */ *f_ij = mass * r_inv * r_inv * r_inv; *pot_ij = -mass * r_inv; } else { const float r = r2 * r_inv; const float ui = r * h_inv; const float W_f_ij = kernel_grav_force_eval(ui); const float W_pot_ij = kernel_grav_pot_eval(ui); /* Get softened gravity */ *f_ij = mass * h_inv3 * W_f_ij; *pot_ij = mass * h_inv * W_pot_ij; } } /** * @brief Computes the intensity of the force at a point generated by a * point-mass truncated for long-distance periodicity. * * The returned quantity needs to be multiplied by the distance vector to obtain * the force vector. * * @param r2 Square of the distance to the point-mass. * @param h2 Square of the softening length. * @param h_inv Inverse of the softening length. * @param h_inv3 Cube of the inverse of the softening length. * @param mass Mass of the point-mass. * @param r_s_inv Inverse of the mesh smoothing scale. * @param f_ij (return) The force intensity. * @param pot_ij (return) The potential. */ __attribute__((always_inline, nonnull)) INLINE static void runner_iact_grav_pp_truncated(const float r2, const float h2, const float h_inv, const float h_inv3, const float mass, const float r_s_inv, float *restrict f_ij, float *restrict pot_ij) { /* Get the inverse distance */ const float r_inv = 1.f / sqrtf(r2 + FLT_MIN); const float r = r2 * r_inv; /* Should we soften ? */ if (r2 >= h2) { /* Get Newtonian gravity */ *f_ij = mass * r_inv * r_inv * r_inv; *pot_ij = -mass * r_inv; } else { const float ui = r * h_inv; const float W_f_ij = kernel_grav_force_eval(ui); const float W_pot_ij = kernel_grav_pot_eval(ui); /* Get softened gravity */ *f_ij = mass * h_inv3 * W_f_ij; *pot_ij = mass * h_inv * W_pot_ij; } /* Get long-range correction */ const float u_lr = r * r_s_inv; float corr_f_lr, corr_pot_lr; kernel_long_grav_eval(u_lr, &corr_f_lr, &corr_pot_lr); *f_ij *= corr_f_lr; *pot_ij *= corr_pot_lr; } /** * @brief Computes the forces at a point generated by a multipole. * * @param r_x x-component of the distance vector to the multipole. * @param r_y y-component of the distance vector to the multipole. * @param r_z z-component of the distance vector to the multipole. * @param r2 Square of the distance vector to the multipole. * @param h The softening length. * @param h_inv Inverse of the softening length. * @param m The multipole. * @param f_x (return) The x-component of the acceleration. * @param f_y (return) The y-component of the acceleration. * @param f_z (return) The z-component of the acceleration. * @param pot (return) The potential. */ __attribute__((always_inline, nonnull)) INLINE static void runner_iact_grav_pm_full(const float r_x, const float r_y, const float r_z, const float r2, const float h, const float h_inv, const struct multipole *m, float *restrict f_x, float *restrict f_y, float *restrict f_z, float *restrict pot) { /* Use the M2P kernel */ struct reduced_grav_tensor l; l.F_000 = 0.f; l.F_100 = 0.f; l.F_010 = 0.f; l.F_001 = 0.f; gravity_M2P(m, r_x, r_y, r_z, r2, h, /*periodic=*/0, /*rs_inv=*/0.f, &l); /* Write back */ *pot = l.F_000; *f_x = l.F_100; *f_y = l.F_010; *f_z = l.F_001; } /** * @brief Computes the forces at a point generated by a multipole, truncated for * long-range periodicity. * * @param r_x x-component of the distance vector to the multipole. * @param r_y y-component of the distance vector to the multipole. * @param r_z z-component of the distance vector to the multipole. * @param r2 Square of the distance vector to the multipole. * @param h The softening length. * @param h_inv Inverse of the softening length. * @param r_s_inv The inverse of the gravity mesh-smoothing scale. * @param m The multipole. * @param f_x (return) The x-component of the acceleration. * @param f_y (return) The y-component of the acceleration. * @param f_z (return) The z-component of the acceleration. * @param pot (return) The potential. */ __attribute__((always_inline, nonnull)) INLINE static void runner_iact_grav_pm_truncated(const float r_x, const float r_y, const float r_z, const float r2, const float h, const float h_inv, const float r_s_inv, const struct multipole *m, float *restrict f_x, float *restrict f_y, float *restrict f_z, float *restrict pot) { /* Use the M2P kernel */ struct reduced_grav_tensor l; l.F_000 = 0.f; l.F_100 = 0.f; l.F_010 = 0.f; l.F_001 = 0.f; gravity_M2P(m, r_x, r_y, r_z, r2, h, /*periodic=*/1, r_s_inv, &l); /* Write back */ *pot = l.F_000; *f_x = l.F_100; *f_y = l.F_010; *f_z = l.F_001; } #endif /* SWIFT_MULTI_SOFTENING_GRAVITY_IACT_H */