Commit 7615cf61 authored by Matthieu Schaller's avatar Matthieu Schaller
Browse files

Use the multipole acceptance criterion to build the long-range interactions...

Use the multipole acceptance criterion to build the long-range interactions and not just the geometry of the mesh.
parent aff8fd2f
...@@ -1647,9 +1647,9 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts, ...@@ -1647,9 +1647,9 @@ void engine_exchange_strays(struct engine *e, size_t offset_parts,
* @brief Constructs the top-level tasks for the short-range gravity * @brief Constructs the top-level tasks for the short-range gravity
* interactions. * interactions.
* *
* All top-cells get a self task. * - All top-cells get a self task.
* All neighbouring pairs get a pair task. * - All pairs within range according to the multipole acceptance
* All non-neighbouring pairs within a range of 6 cells get a M-M task. * criterion get a pair task.
* *
* @param e The #engine. * @param e The #engine.
*/ */
...@@ -1658,6 +1658,7 @@ void engine_make_self_gravity_tasks(struct engine *e) { ...@@ -1658,6 +1658,7 @@ void engine_make_self_gravity_tasks(struct engine *e) {
struct space *s = e->s; struct space *s = e->s;
struct scheduler *sched = &e->sched; struct scheduler *sched = &e->sched;
const int nodeID = e->nodeID; const int nodeID = e->nodeID;
const double theta_crit_inv = e->gravity_properties->theta_crit_inv;
struct cell *cells = s->cells_top; struct cell *cells = s->cells_top;
const int nr_cells = s->nr_cells; const int nr_cells = s->nr_cells;
...@@ -1668,13 +1669,14 @@ void engine_make_self_gravity_tasks(struct engine *e) { ...@@ -1668,13 +1669,14 @@ void engine_make_self_gravity_tasks(struct engine *e) {
/* Skip cells without gravity particles */ /* Skip cells without gravity particles */
if (ci->gcount == 0) continue; if (ci->gcount == 0) continue;
/* Is that neighbour local ? */ /* Is that cell local ? */
if (ci->nodeID != nodeID) continue; if (ci->nodeID != nodeID) continue;
/* If the cells is local build a self-interaction */ /* If the cells is local build a self-interaction */
scheduler_addtask(sched, task_type_self, task_subtype_grav, 0, 0, ci, NULL, scheduler_addtask(sched, task_type_self, task_subtype_grav, 0, 0, ci, NULL,
0); 0);
/* Loop over every other cell */
for (int cjd = cid + 1; cjd < nr_cells; ++cjd) { for (int cjd = cid + 1; cjd < nr_cells; ++cjd) {
struct cell *cj = &cells[cjd]; struct cell *cj = &cells[cjd];
...@@ -1683,9 +1685,11 @@ void engine_make_self_gravity_tasks(struct engine *e) { ...@@ -1683,9 +1685,11 @@ void engine_make_self_gravity_tasks(struct engine *e) {
if (cj->gcount == 0) continue; if (cj->gcount == 0) continue;
/* Is that neighbour local ? */ /* Is that neighbour local ? */
if (cj->nodeID != nodeID) continue; if (cj->nodeID != nodeID) continue; // MATTHIEU
if (cell_are_neighbours(ci, cj)) /* Are the cells to close for a MM interaction ? */
if (!gravity_multipole_accept(ci->multipole, cj->multipole,
theta_crit_inv))
scheduler_addtask(sched, task_type_pair, task_subtype_grav, 0, 0, ci, scheduler_addtask(sched, task_type_pair, task_subtype_grav, 0, 0, ci,
cj, 1); cj, 1);
} }
......
...@@ -48,8 +48,8 @@ void gravity_props_init(struct gravity_props *p, ...@@ -48,8 +48,8 @@ void gravity_props_init(struct gravity_props *p,
p->eta = parser_get_param_float(params, "Gravity:eta"); p->eta = parser_get_param_float(params, "Gravity:eta");
/* Opening angle */ /* Opening angle */
p->theta = parser_get_param_double(params, "Gravity:theta"); p->theta_crit = parser_get_param_double(params, "Gravity:theta");
p->theta_inv = 1. / p->theta; p->theta_crit_inv = 1. / p->theta_crit;
/* Softening lengths */ /* Softening lengths */
p->epsilon = parser_get_param_double(params, "Gravity:epsilon"); p->epsilon = parser_get_param_double(params, "Gravity:epsilon");
...@@ -63,7 +63,7 @@ void gravity_props_print(const struct gravity_props *p) { ...@@ -63,7 +63,7 @@ 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);
message("Self-gravity opening angle: theta=%.4f", p->theta); message("Self-gravity opening angle: theta=%.4f", p->theta_crit);
message("Self-gravity softening: epsilon=%.4f", p->epsilon); message("Self-gravity softening: epsilon=%.4f", p->epsilon);
...@@ -80,7 +80,7 @@ void gravity_props_print_snapshot(hid_t h_grpgrav, ...@@ -80,7 +80,7 @@ void gravity_props_print_snapshot(hid_t h_grpgrav,
io_write_attribute_f(h_grpgrav, "Time integration eta", p->eta); io_write_attribute_f(h_grpgrav, "Time integration eta", p->eta);
io_write_attribute_f(h_grpgrav, "Softening length", p->epsilon); io_write_attribute_f(h_grpgrav, "Softening length", p->epsilon);
io_write_attribute_f(h_grpgrav, "Opening angle", p->theta); io_write_attribute_f(h_grpgrav, "Opening angle", p->theta_crit);
io_write_attribute_f(h_grpgrav, "MM a_smooth", p->a_smooth); io_write_attribute_f(h_grpgrav, "MM a_smooth", p->a_smooth);
io_write_attribute_f(h_grpgrav, "MM r_cut", p->r_cut); io_write_attribute_f(h_grpgrav, "MM r_cut", p->r_cut);
} }
......
...@@ -42,10 +42,10 @@ struct gravity_props { ...@@ -42,10 +42,10 @@ struct gravity_props {
float eta; float eta;
/*! Tree opening angle (Multipole acceptance criterion) */ /*! Tree opening angle (Multipole acceptance criterion) */
double theta; double theta_crit;
/*! Inverse of opening angle */ /*! Inverse of opening angle */
double theta_inv; double theta_crit_inv;
/*! Softening length */ /*! Softening length */
double epsilon; double epsilon;
......
...@@ -208,9 +208,9 @@ INLINE static void gravity_reset(struct gravity_tensors *m) { ...@@ -208,9 +208,9 @@ INLINE static void gravity_reset(struct gravity_tensors *m) {
INLINE static void gravity_drift(struct gravity_tensors *m, double dt) { INLINE static void gravity_drift(struct gravity_tensors *m, double dt) {
/* Move the whole thing according to bulk motion */ /* Move the whole thing according to bulk motion */
m->CoM[0] += m->m_pole.vel[0] * dt; m->CoM[0] += m->m_pole.vel[0] * dt * 0; // MATTHIEU
m->CoM[1] += m->m_pole.vel[1] * dt; m->CoM[1] += m->m_pole.vel[1] * dt * 0;
m->CoM[2] += m->m_pole.vel[2] * dt; m->CoM[2] += m->m_pole.vel[2] * dt * 0;
} }
/** /**
...@@ -2508,4 +2508,29 @@ INLINE static void gravity_L2P(const struct grav_tensor *lb, ...@@ -2508,4 +2508,29 @@ INLINE static void gravity_L2P(const struct grav_tensor *lb,
gp->a_grav[2] += a_grav[2]; gp->a_grav[2] += a_grav[2];
} }
/**
* @brief Checks whether a cell-cell interaction can be appromixated by a M-M
* interaction.
*
* @param ma The #multipole of the first #cell.
* @param mb The #multipole of the second #cell.
* @param theta_crit_inv The inverse of the critical opening angle.
*/
__attribute__((always_inline)) INLINE static int gravity_multipole_accept(
const struct gravity_tensors *ma, const struct gravity_tensors *mb,
double theta_crit_inv) {
const double r_crit_a = ma->r_max * theta_crit_inv;
const double r_crit_b = mb->r_max * theta_crit_inv;
const double dx = ma->CoM[0] - mb->CoM[0];
const double dy = ma->CoM[1] - mb->CoM[1];
const double dz = ma->CoM[2] - mb->CoM[2];
const double r2 = dx * dx + dy * dy + dz * dz;
/* Multipole acceptance criterion (Dehnen 2002, eq.10) */
return (r2 > (r_crit_a + r_crit_b) * (r_crit_a + r_crit_b));
}
#endif /* SWIFT_MULTIPOLE_H */ #endif /* SWIFT_MULTIPOLE_H */
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
/* Includes. */ /* Includes. */
#include "cell.h" #include "cell.h"
#include "gravity.h" #include "gravity.h"
#include "inline.h"
#include "part.h" #include "part.h"
/** /**
...@@ -379,14 +380,15 @@ void runner_dopair_grav(struct runner *r, struct cell *ci, struct cell *cj, ...@@ -379,14 +380,15 @@ void runner_dopair_grav(struct runner *r, struct cell *ci, struct cell *cj,
"The impossible has happened: pair interaction between a cell and " "The impossible has happened: pair interaction between a cell and "
"itself."); "itself.");
/* Are the cells direct neighbours? */ /* Are the cells direct neighbours? */
if (!cell_are_neighbours(ci, cj)) /* if (!cell_are_neighbours(ci, cj)) */
error( /* error( */
"Non-neighbouring cells ! ci->x=[%f %f %f] ci->width=%f cj->loc=[%f %f " /* "Non-neighbouring cells ! ci->x=[%f %f %f] ci->width=%f cj->loc=[%f %f
"%f] " * " */
"cj->width=%f", /* "%f] " */
ci->loc[0], ci->loc[1], ci->loc[2], ci->width[0], cj->loc[0], /* "cj->width=%f", */
cj->loc[1], cj->loc[2], cj->width[0]); /* ci->loc[0], ci->loc[1], ci->loc[2], ci->width[0], cj->loc[0], */
/* cj->loc[1], cj->loc[2], cj->width[0]); */
#endif #endif
...@@ -515,6 +517,14 @@ void runner_dosub_grav(struct runner *r, struct cell *ci, struct cell *cj, ...@@ -515,6 +517,14 @@ void runner_dosub_grav(struct runner *r, struct cell *ci, struct cell *cj,
} }
} }
/**
* @brief Performs all M-M interactions between a given top-level cell and all
* the other top-levels that are far enough.
*
* @param r The thread #runner.
* @param ci The #cell of interest.
* @param timer Are we timing this ?
*/
void runner_do_grav_long_range(struct runner *r, struct cell *ci, int timer) { void runner_do_grav_long_range(struct runner *r, struct cell *ci, int timer) {
#if ICHECK > 0 #if ICHECK > 0
...@@ -530,39 +540,40 @@ void runner_do_grav_long_range(struct runner *r, struct cell *ci, int timer) { ...@@ -530,39 +540,40 @@ void runner_do_grav_long_range(struct runner *r, struct cell *ci, int timer) {
} }
#endif #endif
/* Some constants */
const struct engine *e = r->e;
const struct gravity_props *props = e->gravity_properties;
const double theta_crit_inv = props->theta_crit_inv;
TIMER_TIC; TIMER_TIC;
/* Recover the list of top-level cells */ /* Recover the list of top-level cells */
const struct engine *e = r->e;
struct cell *cells = e->s->cells_top; struct cell *cells = e->s->cells_top;
const int nr_cells = e->s->nr_cells; const int nr_cells = e->s->nr_cells;
/* const double max_d = */
/* const_gravity_a_smooth * const_gravity_r_cut * ci->width[0]; */
/* const double max_d2 = max_d * max_d; */
// const double pos_i[3] = {ci->loc[0], ci->loc[1], ci->loc[2]};
/* Anything to do here? */ /* Anything to do here? */
if (!cell_is_active(ci, e)) return; if (!cell_is_active(ci, e)) return; // MATTHIEU (should never happen)
/* Drift our own multipole if need be */ /* Check multipole has been drifted */
if (ci->ti_old_multipole != e->ti_current) cell_drift_multipole(ci, e); if (ci->ti_old_multipole != e->ti_current)
error("Interacting un-drifted multipole");
/* Loop over all the cells and go for a p-m interaction if far enough but not /* Loop over all the top-level cells and go for a M-M interaction if
* too far */ * well-separated */
for (int i = 0; i < nr_cells; ++i) { for (int i = 0; i < nr_cells; ++i) {
/* Handle on the top-level cell */
struct cell *cj = &cells[i]; struct cell *cj = &cells[i];
if (ci == cj) continue; /* Avoid stupid cases */
if (cj->gcount == 0) continue; if (ci == cj || cj->gcount == 0) continue;
/* const double dx[3] = {cj->loc[0] - pos_i[0], // x */
/* cj->loc[1] - pos_i[1], // y */
/* cj->loc[2] - pos_i[2]}; // z */
/* const double r2 = dx[0] * dx[0] + dx[1] * dx[1] + dx[2] * dx[2]; */
/* if (r2 > max_d2) continue; */
if (!cell_are_neighbours(ci, cj)) runner_dopair_grav_mm(r, ci, cj); /* Check the multipole acceptance criterion */
if (gravity_multipole_accept(ci->multipole, cj->multipole,
theta_crit_inv)) {
/* Go for a (non-symmetric) M-M calculation */
runner_dopair_grav_mm(r, ci, cj);
}
} }
if (timer) TIMER_TOC(timer_dograv_long_range); if (timer) TIMER_TOC(timer_dograv_long_range);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment