Skip to content
Snippets Groups Projects
Commit 5739a5db authored by Matthieu Schaller's avatar Matthieu Schaller
Browse files

Merge branch 'gravity_order2_mac' into 'master'

Add Gadget-4 MAC

See merge request !1679
parents 356a55da a2648334
No related branches found
No related tags found
3 merge requests!1715Update planetary strength after planetary plus's master rebase,!1693More threapool plotting tweaks,!1679Add Gadget-4 MAC
...@@ -259,14 +259,16 @@ The accuracy of the gravity calculation is governed by the following four parame ...@@ -259,14 +259,16 @@ The accuracy of the gravity calculation is governed by the following four parame
* The accuracy criterion used in the adaptive MAC: :math:`\epsilon_{\rm fmm}`: ``epsilon_fmm``, * The accuracy criterion used in the adaptive MAC: :math:`\epsilon_{\rm fmm}`: ``epsilon_fmm``,
* The time-step size pre-factor :math:`\eta`: ``eta``, * The time-step size pre-factor :math:`\eta`: ``eta``,
The first three parameters govern the way the Fast-Multipole method The first three parameters govern the way the Fast-Multipole method tree-walk is
tree-walk is done (see the theory documents for full details). The ``MAC`` done (see the theory documents for full details). The ``MAC`` parameter can
parameter can take two values: ``adaptive`` or ``geometric``. In the first take three values: ``adaptive``, ``geometric``, or ``gadget``. In the first
case, the tree recursion decision is based on the estimated accelerations case, the tree recursion decision is based on the estimated accelerations that a
that a given tree node will produce, trying to recurse to levels where the given tree node will produce, trying to recurse to levels where the fractional
fractional contribution of the accelerations to the cell is less than contribution of the accelerations to the cell is less than :math:`\epsilon_{\rm
:math:`\epsilon_{\rm fmm}`. In the second case, a fixed Barnes-Hut-like fmm}`. In the second case, a fixed Barnes-Hut-like opening angle
opening angle :math:`\theta_{\rm cr}` is used. :math:`\theta_{\rm cr}` is used. The final case corresponds to the choice made
in the Gadget-4 code. It is an implementation using eq. 36 of `Springel et
al. (2021) <https://adsabs.harvard.edu/abs/2021MNRAS.506.2871S>`_.
The time-step of a given particle is given by :math:`\Delta t = The time-step of a given particle is given by :math:`\Delta t =
\sqrt{2\eta\epsilon_i/|\overrightarrow{a}_i|}`, where \sqrt{2\eta\epsilon_i/|\overrightarrow{a}_i|}`, where
......
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
#define gravity_props_default_a_smooth 1.25f #define gravity_props_default_a_smooth 1.25f
#define gravity_props_default_r_cut_max 4.5f #define gravity_props_default_r_cut_max 4.5f
#define gravity_props_default_r_cut_min 0.1f #define gravity_props_default_r_cut_min 0.0f
#define gravity_props_default_rebuild_frequency 0.01f #define gravity_props_default_rebuild_frequency 0.01f
#define gravity_props_default_rebuild_active_fraction 1.01f // > 1 means never #define gravity_props_default_rebuild_active_fraction 1.01f // > 1 means never
#define gravity_props_default_distributed_mesh 0 #define gravity_props_default_distributed_mesh 0
...@@ -124,12 +124,16 @@ void gravity_props_init(struct gravity_props *p, struct swift_params *params, ...@@ -124,12 +124,16 @@ void gravity_props_init(struct gravity_props *p, struct swift_params *params,
if (strcmp(buffer, "adaptive") == 0) { if (strcmp(buffer, "adaptive") == 0) {
p->use_adaptive_tolerance = 1; p->use_adaptive_tolerance = 1;
p->use_gadget_tolerance = 0;
} else if (strcmp(buffer, "gadget") == 0) {
p->use_adaptive_tolerance = 1;
p->use_gadget_tolerance = 1;
} else if (strcmp(buffer, "geometric") == 0) { } else if (strcmp(buffer, "geometric") == 0) {
p->use_adaptive_tolerance = 0; p->use_adaptive_tolerance = 0;
} else { } else {
error( error(
"Invalid choice of multipole acceptance criterion: '%s'. Should be " "Invalid choice of multipole acceptance criterion: '%s'. Should be "
"'adaptive' or 'geometric'", "'adaptive', 'gadget', or 'geometric'",
buffer); buffer);
} }
...@@ -295,9 +299,15 @@ void gravity_props_print(const struct gravity_props *p) { ...@@ -295,9 +299,15 @@ void gravity_props_print(const struct gravity_props *p) {
message("Self-gravity time integration: eta=%.4f", p->eta); message("Self-gravity time integration: eta=%.4f", p->eta);
if (p->use_adaptive_tolerance) { if (p->use_adaptive_tolerance) {
message("Self-gravity opening angle scheme: adaptive"); if (p->use_gadget_tolerance) {
message("Self-gravity opening angle: epsilon_fmm=%.6f", message("Self-gravity opening angle scheme: Gadget");
p->adaptive_tolerance); message("Self-gravity opening angle: epsilon_fmm=%.6f",
p->adaptive_tolerance);
} else {
message("Self-gravity opening angle scheme: adaptive");
message("Self-gravity opening angle: epsilon_fmm=%.6f",
p->adaptive_tolerance);
}
} else { } else {
message("Self-gravity opening angle scheme: fixed"); message("Self-gravity opening angle scheme: fixed");
message("Self-gravity opening angle: theta_cr=%.4f", p->theta_crit); message("Self-gravity opening angle: theta_cr=%.4f", p->theta_crit);
......
...@@ -66,6 +66,10 @@ struct gravity_props { ...@@ -66,6 +66,10 @@ struct gravity_props {
/*! Are we using the adaptive opening angle? (as read from param file) */ /*! Are we using the adaptive opening angle? (as read from param file) */
int use_adaptive_tolerance; int use_adaptive_tolerance;
/*! Are we using the Gadget adaptive opening angle? (as read from param file)
*/
int use_gadget_tolerance;
/*! Accuracy parameter of the advanced MAC */ /*! Accuracy parameter of the advanced MAC */
float adaptive_tolerance; float adaptive_tolerance;
......
...@@ -84,12 +84,15 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2L_accept( ...@@ -84,12 +84,15 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2L_accept(
const int use_rebuild_sizes, const int periodic) { const int use_rebuild_sizes, const int periodic) {
/* Order of the expansion */ /* Order of the expansion */
const int p = SELF_GRAVITY_MULTIPOLE_ORDER; const int p = 2;
/* Sizes of the multipoles */ /* Sizes of the multipoles */
const float rho_A = use_rebuild_sizes ? A->r_max_rebuild : A->r_max; const float rho_A = use_rebuild_sizes ? A->r_max_rebuild : A->r_max;
const float rho_B = use_rebuild_sizes ? B->r_max_rebuild : B->r_max; const float rho_B = use_rebuild_sizes ? B->r_max_rebuild : B->r_max;
/* Max size of both multipoles */
const float rho_max = max(rho_A, rho_B);
/* Get the softening */ /* Get the softening */
const float max_softening = const float max_softening =
max(A->m_pole.max_softening, B->m_pole.max_softening); max(A->m_pole.max_softening, B->m_pole.max_softening);
...@@ -102,19 +105,16 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2L_accept( ...@@ -102,19 +105,16 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2L_accept(
} }
E_BA_term *= 8.f; E_BA_term *= 8.f;
if (rho_A + rho_B > 0.f) { if (rho_A + rho_B > 0.f) {
E_BA_term *= max(rho_A, rho_B); E_BA_term *= rho_max;
;
E_BA_term /= (rho_A + rho_B); E_BA_term /= (rho_A + rho_B);
} }
/* Compute r^p */ /* Compute r^p = (r^2)^(p/2) */
#if SELF_GRAVITY_MULTIPOLE_ORDER % 2 == 1
const float r_to_p = integer_powf(sqrtf(r2), p);
#else
const float r_to_p = integer_powf(r2, (p / 2)); const float r_to_p = integer_powf(r2, (p / 2));
#endif
float f_MAC_inv; float f_MAC_inv;
if (props->consider_truncation_in_MAC) { if (periodic && props->consider_truncation_in_MAC) {
f_MAC_inv = gravity_f_MAC_inverse(max_softening, props->r_s_inv, r2); f_MAC_inv = gravity_f_MAC_inverse(max_softening, props->r_s_inv, r2);
} else { } else {
f_MAC_inv = r2; f_MAC_inv = r2;
...@@ -123,6 +123,9 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2L_accept( ...@@ -123,6 +123,9 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2L_accept(
/* Get the mimimal acceleration in A */ /* Get the mimimal acceleration in A */
const float min_a_grav = A->m_pole.min_old_a_grav_norm; const float min_a_grav = A->m_pole.min_old_a_grav_norm;
/* Maximal mass */
const float M_max = max(A->m_pole.M_000, B->m_pole.M_000);
/* Get the relative tolerance */ /* Get the relative tolerance */
const float eps = props->adaptive_tolerance; const float eps = props->adaptive_tolerance;
...@@ -133,7 +136,19 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2L_accept( ...@@ -133,7 +136,19 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2L_accept(
/* Get the sum of the multipole sizes */ /* Get the sum of the multipole sizes */
const float rho_sum = rho_A + rho_B; const float rho_sum = rho_A + rho_B;
if (props->use_advanced_MAC) { if (props->use_advanced_MAC && props->use_gadget_tolerance) {
/* Gadget 4 paper -- eq. 36 */
const int power = SELF_GRAVITY_MULTIPOLE_ORDER - 1;
const float ratio = integer_powf(rho_max / sqrtf(r2), power);
const int cond_1 = M_max * ratio < eps * min_a_grav * f_MAC_inv;
const int cond_2 =
props->use_tree_below_softening || max_softening * max_softening < r2;
return cond_1 && cond_2;
} else if (props->use_advanced_MAC && !props->use_gadget_tolerance) {
#ifdef SWIFT_DEBUG_CHECKS #ifdef SWIFT_DEBUG_CHECKS
if (min_a_grav == 0.) error("Acceleration is 0"); if (min_a_grav == 0.) error("Acceleration is 0");
...@@ -277,7 +292,7 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2P_accept( ...@@ -277,7 +292,7 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2P_accept(
const struct gravity_tensors *B, const float r2, const int periodic) { const struct gravity_tensors *B, const float r2, const int periodic) {
/* Order of the expansion */ /* Order of the expansion */
const int p = SELF_GRAVITY_MULTIPOLE_ORDER; const int p = 2;
/* Sizes of the multipoles */ /* Sizes of the multipoles */
const float rho_B = B->r_max; const float rho_B = B->r_max;
...@@ -293,15 +308,11 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2P_accept( ...@@ -293,15 +308,11 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2P_accept(
/* Compute the error estimator (without the 1/M_B term that cancels out) */ /* Compute the error estimator (without the 1/M_B term that cancels out) */
const float E_BA_term = 8.f * B->m_pole.power[p]; const float E_BA_term = 8.f * B->m_pole.power[p];
/* Compute r^p */ /* Compute r^p = (r^2)^(p/2) */
#if SELF_GRAVITY_MULTIPOLE_ORDER % 2 == 1
const float r_to_p = integer_powf(sqrtf(r2), p);
#else
const float r_to_p = integer_powf(r2, (p / 2)); const float r_to_p = integer_powf(r2, (p / 2));
#endif
float f_MAC_inv; float f_MAC_inv;
if (props->consider_truncation_in_MAC) { if (periodic && props->consider_truncation_in_MAC) {
f_MAC_inv = gravity_f_MAC_inverse(max_softening, props->r_s_inv, r2); f_MAC_inv = gravity_f_MAC_inverse(max_softening, props->r_s_inv, r2);
} else { } else {
f_MAC_inv = r2; f_MAC_inv = r2;
...@@ -317,7 +328,19 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2P_accept( ...@@ -317,7 +328,19 @@ __attribute__((nonnull, pure)) INLINE static int gravity_M2P_accept(
const float theta_crit = props->theta_crit; const float theta_crit = props->theta_crit;
const float theta_crit2 = theta_crit * theta_crit; const float theta_crit2 = theta_crit * theta_crit;
if (props->use_advanced_MAC) { if (props->use_advanced_MAC && props->use_gadget_tolerance) {
/* Gadget 4 paper -- eq. 12 */
const int power = SELF_GRAVITY_MULTIPOLE_ORDER;
const float ratio = integer_powf(rho_B / sqrtf(r2), power);
const int cond_1 = B->m_pole.M_000 * ratio < eps * old_a_grav * f_MAC_inv;
const int cond_2 =
props->use_tree_below_softening || max_softening * max_softening < r2;
return cond_1 && cond_2;
} else if (props->use_advanced_MAC && !props->use_gadget_tolerance) {
#ifdef SWIFT_DEBUG_CHECKS #ifdef SWIFT_DEBUG_CHECKS
if (old_a_grav == 0.) error("Acceleration is 0"); if (old_a_grav == 0.) error("Acceleration is 0");
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment