diff --git a/samples/electrophoresis.py b/samples/electrophoresis.py
index 907fa07bbe2..efecee935cb 100644
--- a/samples/electrophoresis.py
+++ b/samples/electrophoresis.py
@@ -33,9 +33,6 @@
logging.basicConfig(level=logging.INFO)
-# Use a fixed int for a deterministic behavior
-np.random.seed()
-
required_features = ["P3M", "EXTERNAL_FORCES", "WCA"]
espressomd.assert_features(required_features)
@@ -133,7 +130,8 @@
# activate electrostatics
#############################################################
-p3m = espressomd.electrostatics.P3M(prefactor=1.0, accuracy=1e-2)
+p3m_params = {"prefactor": 1., "accuracy": 1e-2}
+p3m = espressomd.electrostatics.P3M(**p3m_params)
system.electrostatics.solver = p3m
# apply external force (external electric field)
@@ -160,17 +158,15 @@
obs=obs_bond_length, delta_N=1)
system.auto_update_accumulators.add(acc_bond_length)
-# data storage for python analysis
-#############################################################
-pos = np.full((N_SAMPLES, N_MONOMERS, 3), np.nan)
+obs_pos = espressomd.observables.ParticlePositions(ids=range(N_MONOMERS))
+acc_pos = espressomd.accumulators.TimeSeries(obs=obs_pos, delta_N=100)
+system.auto_update_accumulators.add(acc_pos)
# sampling Loop
#############################################################
-for i in range(N_SAMPLES):
- if i % 100 == 0:
- logging.info(f"\rsampling: {i:4d}")
- system.integrator.run(N_INT_STEPS)
- pos[i] = system.part.by_ids(range(N_MONOMERS)).pos
+for i in range(N_SAMPLES // 100):
+ logging.info(f"\rsampling: {100 * i:4d}")
+ system.integrator.run(100 * N_INT_STEPS)
logging.info("\nsampling finished!\n")
@@ -179,6 +175,7 @@
# calculate center of mass (COM) and its velocity
#############################################################
+pos = acc_pos.time_series()
COM = pos.sum(axis=1) / N_MONOMERS
COM_v = (COM[1:] - COM[:-1]) / (N_INT_STEPS * system.time_step)
@@ -220,7 +217,7 @@ def exponential(x, lp):
# ...second by using observables
-def persistence_length_obs(
+def persistence_length_from_obs(
acc_bond_length, acc_persistence_angles, exponential):
bond_lengths_obs = np.array(acc_bond_length.mean())
sampling_positions_obs = np.insert(
@@ -233,7 +230,7 @@ def persistence_length_obs(
return sampling_positions_obs, cos_thetas_obs, opt_obs[0]
-sampling_positions_obs, cos_thetas_obs, persistence_length_obs = persistence_length_obs(
+sampling_positions_obs, cos_thetas_obs, persistence_length_obs = persistence_length_from_obs(
acc_bond_length, acc_persistence_angles, exponential)
logging.info(f"persistence length (observables): {persistence_length_obs}")
diff --git a/src/core/BoxGeometry.hpp b/src/core/BoxGeometry.hpp
index 7224ec4a2b7..6ba20e48e86 100644
--- a/src/core/BoxGeometry.hpp
+++ b/src/core/BoxGeometry.hpp
@@ -16,8 +16,8 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-#ifndef ESPRESSO_SRC_CORE_BOX_GEOMETRY_HPP
-#define ESPRESSO_SRC_CORE_BOX_GEOMETRY_HPP
+
+#pragma once
#include "algorithm/periodic_fold.hpp"
#include "lees_edwards/LeesEdwardsBC.hpp"
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#include
namespace detail {
@@ -68,6 +69,28 @@ template T get_mi_coord(T a, T b, T box_length, bool periodic) {
return get_mi_coord(a, b, box_length, 1. / box_length, 0.5 * box_length,
periodic);
}
+
+/** @brief Calculate image box shift vector.
+ * @param image_box image box offset
+ * @param box box length
+ * @return Image box coordinates.
+ */
+inline auto image_shift(Utils::Vector3i const &image_box,
+ Utils::Vector3d const &box) {
+ return hadamard_product(image_box, box);
+}
+
+/** @brief Unfold particle coordinates to image box.
+ * @param pos coordinate to unfold
+ * @param image_box image box offset
+ * @param box box length
+ * @return Unfolded coordinates.
+ */
+inline auto unfolded_position(Utils::Vector3d const &pos,
+ Utils::Vector3i const &image_box,
+ Utils::Vector3d const &box) {
+ return pos + image_shift(image_box, box);
+}
} // namespace detail
enum class BoxType { CUBOID = 0, LEES_EDWARDS = 1 };
@@ -120,7 +143,7 @@ class BoxGeometry {
* @return true iff periodic in direction.
*/
constexpr bool periodic(unsigned coord) const {
- assert(coord <= 2);
+ assert(coord <= 2u);
return m_periodic[coord];
}
@@ -192,11 +215,11 @@ class BoxGeometry {
auto a_tmp = a;
auto b_tmp = b;
a_tmp[shear_plane_normal] = Algorithm::periodic_fold(
- a_tmp[shear_plane_normal], length()[shear_plane_normal]);
+ a_tmp[shear_plane_normal], m_length[shear_plane_normal]);
b_tmp[shear_plane_normal] = Algorithm::periodic_fold(
- b_tmp[shear_plane_normal], length()[shear_plane_normal]);
- return lees_edwards_bc().distance(a_tmp - b_tmp, length(), length_half(),
- length_inv(), m_periodic);
+ b_tmp[shear_plane_normal], m_length[shear_plane_normal]);
+ return lees_edwards_bc().distance(a_tmp - b_tmp, m_length, m_length_half,
+ m_length_inv, m_periodic);
}
assert(type() == BoxType::CUBOID);
return {get_mi_coord(a[0], b[0], 0), get_mi_coord(a[1], b[1], 1),
@@ -238,61 +261,54 @@ class BoxGeometry {
}
return ret;
}
-};
-
-/** @brief Fold a coordinate to primary simulation box.
- * @param pos coordinate to fold
- * @param image_box image box offset
- * @param length box length
- */
-inline std::pair fold_coordinate(double pos, int image_box,
- double const &length) {
- std::tie(pos, image_box) = Algorithm::periodic_fold(pos, image_box, length);
-
- if ((image_box == std::numeric_limits::min()) ||
- (image_box == std::numeric_limits::max())) {
- throw std::runtime_error(
- "Overflow in the image box count while folding a particle coordinate "
- "into the primary simulation box. Maybe a particle experienced a "
- "huge force.");
- }
- return {pos, image_box};
-}
-
-/** @brief Fold particle coordinates to primary simulation box.
- * Lees-Edwards offset is ignored.
- * @param[in,out] pos coordinate to fold
- * @param[in,out] image_box image box offset
- * @param[in] box box parameters (side lengths, periodicity)
- */
-inline void fold_position(Utils::Vector3d &pos, Utils::Vector3i &image_box,
- const BoxGeometry &box) {
- for (unsigned int i = 0; i < 3; i++) {
- if (box.periodic(i)) {
- std::tie(pos[i], image_box[i]) =
- fold_coordinate(pos[i], image_box[i], box.length()[i]);
+ /** @brief Fold coordinates to primary simulation box in-place.
+ * Lees-Edwards offset is ignored.
+ * @param[in,out] pos coordinate to fold
+ * @param[in,out] image_box image box offset
+ */
+ void fold_position(Utils::Vector3d &pos, Utils::Vector3i &image_box) const {
+ for (unsigned int i = 0u; i < 3u; i++) {
+ if (m_periodic[i]) {
+ auto const result =
+ Algorithm::periodic_fold(pos[i], image_box[i], m_length[i]);
+ if (result.second == std::numeric_limits::min() or
+ result.second == std::numeric_limits::max()) {
+ throw std::runtime_error(
+ "Overflow in the image box count while folding a particle "
+ "coordinate into the primary simulation box. Maybe a particle "
+ "experienced a huge force.");
+ }
+ std::tie(pos[i], image_box[i]) = result;
+ }
}
}
-}
-/** @brief Fold particle coordinates to primary simulation box.
- * @param p coordinate to fold
- * @param box box parameters (side lengths, periodicity)
- * @return Folded coordinates.
- */
-inline Utils::Vector3d folded_position(const Utils::Vector3d &p,
- const BoxGeometry &box) {
- Utils::Vector3d p_folded;
- for (unsigned int i = 0; i < 3; i++) {
- if (box.periodic(i)) {
- p_folded[i] = Algorithm::periodic_fold(p[i], box.length()[i]);
- } else {
- p_folded[i] = p[i];
+ /** @brief Calculate coordinates folded to primary simulation box.
+ * @param p coordinate to fold
+ * @return Folded coordinates.
+ */
+ auto folded_position(Utils::Vector3d const &p) const {
+ Utils::Vector3d p_folded;
+ for (unsigned int i = 0u; i < 3u; i++) {
+ if (m_periodic[i]) {
+ p_folded[i] = Algorithm::periodic_fold(p[i], m_length[i]);
+ } else {
+ p_folded[i] = p[i];
+ }
}
+
+ return p_folded;
}
- return p_folded;
-}
+ /** @brief Calculate image box shift vector */
+ auto image_shift(Utils::Vector3i const &image_box) const {
+ return detail::image_shift(image_box, m_length);
+ }
-#endif
+ /** @brief Unfold particle coordinates to image box. */
+ auto unfolded_position(Utils::Vector3d const &pos,
+ Utils::Vector3i const &image_box) const {
+ return detail::unfolded_position(pos, image_box, m_length);
+ }
+};
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 6aa9c4aa872..5cd399788a4 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -33,7 +33,6 @@ add_library(
forcecap.cpp
forces.cpp
ghosts.cpp
- grid.cpp
immersed_boundaries.cpp
interactions.cpp
event.cpp
diff --git a/src/core/EspressoSystemStandAlone.cpp b/src/core/EspressoSystemStandAlone.cpp
index bc71ba4742f..694ec3200e6 100644
--- a/src/core/EspressoSystemStandAlone.cpp
+++ b/src/core/EspressoSystemStandAlone.cpp
@@ -19,10 +19,13 @@
#include "config/config.hpp"
+#include "BoxGeometry.hpp"
#include "EspressoSystemStandAlone.hpp"
+#include "cell_system/CellStructure.hpp"
+#include "cell_system/CellStructureType.hpp"
+#include "cells.hpp"
#include "communication.hpp"
#include "event.hpp"
-#include "grid.hpp"
#include "integrate.hpp"
#include "system/System.hpp"
#include "system/System.impl.hpp"
@@ -48,16 +51,20 @@ EspressoSystemStandAlone::EspressoSystemStandAlone(int argc, char **argv) {
#ifdef VIRTUAL_SITES
set_virtual_sites(std::make_shared());
#endif
- ::System::set_system(std::make_shared<::System::System>());
+ auto system = std::make_shared<::System::System>();
+ ::System::set_system(system);
+ auto &cell_structure = *system->cell_structure;
+ cells_re_init(cell_structure, CellStructureType::CELL_STRUCTURE_REGULAR);
}
void EspressoSystemStandAlone::set_box_l(Utils::Vector3d const &box_l) const {
- set_box_length(box_l);
+ System::get_system().box_geo->set_length(box_l);
+ on_boxl_change();
}
void EspressoSystemStandAlone::set_node_grid(
Utils::Vector3i const &node_grid) const {
- ::set_node_grid(node_grid);
+ ::communicator.set_node_grid(node_grid);
}
void EspressoSystemStandAlone::set_time_step(double time_step) const {
diff --git a/src/core/LocalBox.hpp b/src/core/LocalBox.hpp
index 432c52f2aee..f78e3f99123 100644
--- a/src/core/LocalBox.hpp
+++ b/src/core/LocalBox.hpp
@@ -16,25 +16,25 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-#ifndef ESPRESSO_SRC_CORE_LOCALBOX_HPP
-#define ESPRESSO_SRC_CORE_LOCALBOX_HPP
+
+#pragma once
#include "cell_system/CellStructureType.hpp"
#include
#include
-template class LocalBox {
- Utils::Vector m_local_box_l = {1, 1, 1};
- Utils::Vector m_lower_corner = {0, 0, 0};
- Utils::Vector m_upper_corner = {1, 1, 1};
+class LocalBox {
+ Utils::Vector3d m_local_box_l = {1., 1., 1.};
+ Utils::Vector3d m_lower_corner = {0., 0., 0.};
+ Utils::Vector3d m_upper_corner = {1., 1., 1.};
Utils::Array m_boundaries = {};
CellStructureType m_cell_structure_type;
public:
LocalBox() = default;
- LocalBox(Utils::Vector const &lower_corner,
- Utils::Vector const &local_box_length,
+ LocalBox(Utils::Vector3d const &lower_corner,
+ Utils::Vector3d const &local_box_length,
Utils::Array const &boundaries,
CellStructureType const cell_structure_type)
: m_local_box_l(local_box_length), m_lower_corner(lower_corner),
@@ -42,11 +42,11 @@ template class LocalBox {
m_boundaries(boundaries), m_cell_structure_type(cell_structure_type) {}
/** Left (bottom, front) corner of this nodes local box. */
- Utils::Vector const &my_left() const { return m_lower_corner; }
+ auto const &my_left() const { return m_lower_corner; }
/** Right (top, back) corner of this nodes local box. */
- Utils::Vector const &my_right() const { return m_upper_corner; }
+ auto const &my_right() const { return m_upper_corner; }
/** Dimensions of the box a single node is responsible for. */
- Utils::Vector const &length() const { return m_local_box_l; }
+ auto const &length() const { return m_local_box_l; }
/** @brief Boundary information for the local box.
*
* This returns for each of the faces of the local box if
@@ -56,17 +56,32 @@ template class LocalBox {
*
* @return Array with boundary information.
*/
- Utils::Array const &boundary() const { return m_boundaries; }
+ auto const &boundary() const { return m_boundaries; }
/** Return cell structure type. */
- CellStructureType const &cell_structure_type() const {
- return m_cell_structure_type;
- }
+ auto const &cell_structure_type() const { return m_cell_structure_type; }
/** Set cell structure type. */
void set_cell_structure_type(CellStructureType cell_structure_type) {
m_cell_structure_type = cell_structure_type;
}
-};
-#endif
+ static LocalBox make_regular_decomposition(Utils::Vector3d const &box_l,
+ Utils::Vector3i const &node_index,
+ Utils::Vector3i const &node_grid) {
+
+ auto const local_length = Utils::hadamard_division(box_l, node_grid);
+ auto const my_left = Utils::hadamard_product(node_index, local_length);
+
+ decltype(LocalBox::m_boundaries) boundaries;
+ for (unsigned int dir = 0u; dir < 3u; dir++) {
+ /* left boundary ? */
+ boundaries[2u * dir] = (node_index[dir] == 0);
+ /* right boundary ? */
+ boundaries[2u * dir + 1u] = -(node_index[dir] + 1 == node_grid[dir]);
+ }
+
+ return {my_left, local_length, boundaries,
+ CellStructureType::CELL_STRUCTURE_REGULAR};
+ }
+};
diff --git a/src/core/PartCfg.cpp b/src/core/PartCfg.cpp
index 55227795edb..53087faf9cc 100644
--- a/src/core/PartCfg.cpp
+++ b/src/core/PartCfg.cpp
@@ -19,8 +19,9 @@
#include "PartCfg.hpp"
-#include "grid.hpp"
+#include "BoxGeometry.hpp"
#include "particle_node.hpp"
+#include "system/System.hpp"
#include
@@ -31,6 +32,8 @@ void PartCfg::update() {
if (m_valid)
return;
+ auto const &box_geo = *System::get_system().box_geo;
+
m_parts.clear();
auto const ids = get_particle_ids();
@@ -48,7 +51,7 @@ void PartCfg::update() {
m_parts.push_back(get_particle_data(id));
auto &p = m_parts.back();
- p.pos() += image_shift(p.image_box(), box_geo.length());
+ p.pos() += box_geo.image_shift(p.image_box());
p.image_box() = {};
}
diff --git a/src/core/algorithm/periodic_fold.hpp b/src/core/algorithm/periodic_fold.hpp
index cb2278cc2ed..6e00e42a420 100644
--- a/src/core/algorithm/periodic_fold.hpp
+++ b/src/core/algorithm/periodic_fold.hpp
@@ -33,10 +33,10 @@ namespace Algorithm {
* @return x folded into [0, l) and number of folds.
*/
template
-std::pair periodic_fold(T x, I i, T const &l) {
+std::pair periodic_fold(T x, I i, T const l) {
using limits = std::numeric_limits;
- while ((x < 0) && (i > limits::min())) {
+ while ((x < T{0}) && (i > limits::min())) {
x += l;
--i;
}
@@ -56,7 +56,7 @@ std::pair periodic_fold(T x, I i, T const &l) {
* @param l Length of primary interval
* @return x folded into [0, l).
*/
-template T periodic_fold(T x, T const &l) {
+template T periodic_fold(T x, T const l) {
#ifndef __FAST_MATH__
/* Can't fold if either x or l is nan or inf. */
if (std::isnan(x) or std::isnan(l) or std::isinf(x) or (l == 0)) {
diff --git a/src/core/analysis/statistics.cpp b/src/core/analysis/statistics.cpp
index c8effaf24d9..38a0e9db61a 100644
--- a/src/core/analysis/statistics.cpp
+++ b/src/core/analysis/statistics.cpp
@@ -26,10 +26,10 @@
#include "analysis/statistics.hpp"
+#include "BoxGeometry.hpp"
#include "Particle.hpp"
-#include "cells.hpp"
+#include "cell_system/CellStructure.hpp"
#include "errorhandling.hpp"
-#include "grid.hpp"
#include "partCfg_global.hpp"
#include "system/System.hpp"
@@ -48,6 +48,7 @@ double mindist(PartCfg &partCfg, std::vector const &set1,
std::vector const &set2) {
using Utils::contains;
+ auto const &box_geo = *System::get_system().box_geo;
auto mindist_sq = std::numeric_limits::infinity();
for (auto jt = partCfg.begin(); jt != partCfg.end(); ++jt) {
@@ -75,6 +76,8 @@ double mindist(PartCfg &partCfg, std::vector const &set1,
Utils::Vector3d calc_linear_momentum(bool include_particles,
bool include_lbfluid) {
Utils::Vector3d momentum{};
+ auto const &system = System::get_system();
+ auto &cell_structure = *system.cell_structure;
if (include_particles) {
auto const particles = cell_structure.local_particles();
momentum =
@@ -83,7 +86,6 @@ Utils::Vector3d calc_linear_momentum(bool include_particles,
return m + p.mass() * p.v();
});
}
- auto const &system = System::get_system();
if (include_lbfluid and system.lb.is_solver_set()) {
momentum += system.lb.get_momentum() * system.lb.get_lattice_speed();
}
@@ -141,6 +143,7 @@ std::vector nbhood(PartCfg &partCfg, Utils::Vector3d const &pos,
double dist) {
std::vector ids;
auto const dist_sq = dist * dist;
+ auto const &box_geo = *System::get_system().box_geo;
for (auto const &p : partCfg) {
auto const r_sq = box_geo.get_mi_vector(pos, p.pos()).norm2();
@@ -157,6 +160,7 @@ calc_part_distribution(PartCfg &partCfg, std::vector const &p1_types,
std::vector const &p2_types, double r_min,
double r_max, int r_bins, bool log_flag, bool int_flag) {
+ auto const &box_geo = *System::get_system().box_geo;
auto const r_max2 = Utils::sqr(r_max);
auto const r_min2 = Utils::sqr(r_min);
auto const start_dist2 = Utils::sqr(r_max + 1.);
@@ -239,6 +243,7 @@ structure_factor(PartCfg &partCfg, std::vector const &p_types, int order) {
if (order < 1)
throw std::domain_error("order has to be a strictly positive number");
+ auto const &box_geo = *System::get_system().box_geo;
auto const order_sq = Utils::sqr(static_cast(order));
auto const twoPI_L = 2. * Utils::pi() * box_geo.length_inv()[0];
std::vector ff(2 * order_sq + 1);
diff --git a/src/core/analysis/statistics_chain.cpp b/src/core/analysis/statistics_chain.cpp
index 8787674c8f1..097781947e8 100644
--- a/src/core/analysis/statistics_chain.cpp
+++ b/src/core/analysis/statistics_chain.cpp
@@ -24,9 +24,10 @@
#include "analysis/statistics_chain.hpp"
+#include "BoxGeometry.hpp"
#include "Particle.hpp"
-#include "grid.hpp"
#include "particle_node.hpp"
+#include "system/System.hpp"
#include
#include
@@ -36,6 +37,7 @@
#include
std::array calc_re(int chain_start, int n_chains, int chain_length) {
+ auto const &box_geo = *System::get_system().box_geo;
double dist = 0.0, dist2 = 0.0, dist4 = 0.0;
std::array re;
@@ -44,9 +46,8 @@ std::array calc_re(int chain_start, int n_chains, int chain_length) {
get_particle_data(chain_start + i * chain_length + chain_length - 1);
auto const &p2 = get_particle_data(chain_start + i * chain_length);
- auto const d =
- unfolded_position(p1.pos(), p1.image_box(), box_geo.length()) -
- unfolded_position(p2.pos(), p2.image_box(), box_geo.length());
+ auto const d = box_geo.unfolded_position(p1.pos(), p1.image_box()) -
+ box_geo.unfolded_position(p2.pos(), p2.image_box());
auto const norm2 = d.norm2();
dist += sqrt(norm2);
dist2 += norm2;
@@ -61,6 +62,7 @@ std::array calc_re(int chain_start, int n_chains, int chain_length) {
}
std::array calc_rg(int chain_start, int n_chains, int chain_length) {
+ auto const &box_geo = *System::get_system().box_geo;
double r_G = 0.0, r_G2 = 0.0, r_G4 = 0.0;
std::array rg;
@@ -75,16 +77,14 @@ std::array calc_rg(int chain_start, int n_chains, int chain_length) {
"Gyration tensor is not well-defined for chains including virtual "
"sites. Virtual sites do not have a meaningful mass.");
}
- r_CM += unfolded_position(p.pos(), p.image_box(), box_geo.length()) *
- p.mass();
+ r_CM += box_geo.unfolded_position(p.pos(), p.image_box()) * p.mass();
M += p.mass();
}
r_CM /= M;
double tmp = 0.0;
for (int j = 0; j < chain_length; ++j) {
auto const &p = get_particle_data(chain_start + i * chain_length + j);
- Utils::Vector3d const d =
- unfolded_position(p.pos(), p.image_box(), box_geo.length()) - r_CM;
+ auto const d = box_geo.unfolded_position(p.pos(), p.image_box()) - r_CM;
tmp += d.norm2();
}
tmp /= static_cast(chain_length);
@@ -101,6 +101,7 @@ std::array calc_rg(int chain_start, int n_chains, int chain_length) {
}
std::array calc_rh(int chain_start, int n_chains, int chain_length) {
+ auto const &box_geo = *System::get_system().box_geo;
double r_H = 0.0, r_H2 = 0.0;
std::array rh;
@@ -113,9 +114,8 @@ std::array calc_rh(int chain_start, int n_chains, int chain_length) {
auto const &p1 = get_particle_data(i);
for (int j = i + 1; j < chain_start + chain_length * (p + 1); j++) {
auto const &p2 = get_particle_data(j);
- auto const d =
- unfolded_position(p1.pos(), p1.image_box(), box_geo.length()) -
- unfolded_position(p2.pos(), p2.image_box(), box_geo.length());
+ auto const d = box_geo.unfolded_position(p1.pos(), p1.image_box()) -
+ box_geo.unfolded_position(p2.pos(), p2.image_box());
ri += 1.0 / d.norm();
}
}
diff --git a/src/core/bond_breakage/bond_breakage.cpp b/src/core/bond_breakage/bond_breakage.cpp
index f50275f2344..efe151e4def 100644
--- a/src/core/bond_breakage/bond_breakage.cpp
+++ b/src/core/bond_breakage/bond_breakage.cpp
@@ -16,13 +16,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
+
#include "bond_breakage/bond_breakage.hpp"
#include "bond_breakage/actions.hpp"
-#include "cells.hpp"
+#include "cell_system/CellStructure.hpp"
#include "communication.hpp"
#include "errorhandling.hpp"
#include "event.hpp"
+#include "system/System.hpp"
#include
@@ -137,6 +139,8 @@ ActionSet actions_for_breakage(QueueEntry const &e) {
return {DeleteBond{e.particle_id, *(e.bond_partners[0]), e.bond_type}};
}
#ifdef VIRTUAL_SITES_RELATIVE
+ auto const &system = System::get_system();
+ auto const &cell_structure = *system.cell_structure;
// revert bind at point of collision for pair bonds
if ((*spec).action_type == ActionType::REVERT_BIND_AT_POINT_OF_COLLISION and
not is_angle_bond(e.bond_partners)) {
@@ -217,21 +221,25 @@ static void remove_pair_bonds_to(Particle &p, int other_pid) {
// Handler for the different delete events
class execute : public boost::static_visitor<> {
+ CellStructure &cell_structure;
+
public:
+ execute() : cell_structure{*System::get_system().cell_structure} {}
+
void operator()(DeleteBond const &d) const {
- if (auto p = ::cell_structure.get_local_particle(d.particle_id)) {
+ if (auto p = cell_structure.get_local_particle(d.particle_id)) {
remove_bond(*p, BondView(d.bond_type, {&d.bond_partner_id, 1}));
}
on_particle_change();
}
void operator()(DeleteAngleBond const &d) const {
- if (auto p = ::cell_structure.get_local_particle(d.particle_id)) {
+ if (auto p = cell_structure.get_local_particle(d.particle_id)) {
remove_bond(*p, BondView(d.bond_type, {&d.bond_partner_id[0], 2}));
}
on_particle_change();
}
void operator()(DeleteAllBonds const &d) const {
- if (auto p = ::cell_structure.get_local_particle(d.particle_id_1)) {
+ if (auto p = cell_structure.get_local_particle(d.particle_id_1)) {
remove_pair_bonds_to(*p, d.particle_id_2);
}
on_particle_change();
diff --git a/src/core/bonded_interactions/angle_common.hpp b/src/core/bonded_interactions/angle_common.hpp
index 3da4b2e7d45..8c12849be3f 100644
--- a/src/core/bonded_interactions/angle_common.hpp
+++ b/src/core/bonded_interactions/angle_common.hpp
@@ -25,49 +25,41 @@
*/
#include "config/config.hpp"
-#include "grid.hpp"
#include
+#include
#include
+namespace detail {
+inline double sanitize_cosine(double cosine) {
+ if (cosine > TINY_COS_VALUE)
+ cosine = TINY_COS_VALUE;
+ if (cosine < -TINY_COS_VALUE)
+ cosine = -TINY_COS_VALUE;
+ return cosine;
+}
+} // namespace detail
+
/** Compute the cosine of the angle between three particles.
*
- * Also return all intermediate quantities: normalized vectors
- * @f$ \vec{r_{ij}} @f$ (from particle @f$ j @f$ to particle @f$ i @f$)
- * and @f$ \vec{r_{kj}} @f$, and their normalization constants.
- *
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
* @param[in] sanitize_cosine Sanitize the cosine of the angle.
* @return @f$ \vec{r_{ij}} @f$, @f$ \vec{r_{kj}} @f$,
* @f$ \left\|\vec{r_{ij}}\right\|^{-1} @f$,
* @f$ \left\|\vec{r_{kj}}\right\|^{-1} @f$,
* @f$ \cos(\theta_{ijk}) @f$
*/
-inline std::tuple
-calc_vectors_and_cosine(Utils::Vector3d const &r_mid,
- Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right,
- bool sanitize_cosine = false) {
- /* normalized vector from p_mid to p_left */
- auto vec1 = box_geo.get_mi_vector(r_left, r_mid);
- auto const d1i = 1.0 / vec1.norm();
- vec1 *= d1i;
- /* normalized vector from p_mid to p_right */
- auto vec2 = box_geo.get_mi_vector(r_right, r_mid);
- auto const d2i = 1.0 / vec2.norm();
- vec2 *= d2i;
+inline double calc_cosine(Utils::Vector3d const &vec1,
+ Utils::Vector3d const &vec2,
+ bool sanitize_cosine = false) {
/* cosine of the angle between vec1 and vec2 */
- auto cosine = vec1 * vec2;
+ auto cos_phi = (vec1 * vec2) / std::sqrt(vec1.norm2() * vec2.norm2());
if (sanitize_cosine) {
- if (cosine > TINY_COS_VALUE)
- cosine = TINY_COS_VALUE;
- if (cosine < -TINY_COS_VALUE)
- cosine = -TINY_COS_VALUE;
+ cos_phi = detail::sanitize_cosine(cos_phi);
}
- return std::make_tuple(vec1, vec2, d1i, d2i, cosine);
+ return cos_phi;
}
/** Compute a three-body angle interaction force.
@@ -75,9 +67,8 @@ calc_vectors_and_cosine(Utils::Vector3d const &r_mid,
* See the details in @ref bondedIA_angle_force. The @f$ K(\theta_{ijk}) @f$
* term is provided as a lambda function in @p forceFactor.
*
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
* @param[in] forceFactor Angle force term.
* @param[in] sanitize_cosine Sanitize the cosine of the angle.
* @tparam ForceFactor Function evaluating the angle force term
@@ -86,16 +77,21 @@ calc_vectors_and_cosine(Utils::Vector3d const &r_mid,
*/
template
std::tuple
-angle_generic_force(Utils::Vector3d const &r_mid, Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right, ForceFactor forceFactor,
- bool sanitize_cosine) {
- auto const [vec1, vec2, d1i, d2i, cosine] =
- calc_vectors_and_cosine(r_mid, r_left, r_right, sanitize_cosine);
+angle_generic_force(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2,
+ ForceFactor forceFactor, bool sanitize_cosine) {
+ auto const d1 = vec1.norm();
+ auto const d2 = vec2.norm();
+ auto cos_phi = (vec1 * vec2) / (d1 * d2);
+ if (sanitize_cosine) {
+ cos_phi = detail::sanitize_cosine(cos_phi);
+ }
/* force factor */
- auto const fac = forceFactor(cosine);
+ auto const fac = forceFactor(cos_phi);
/* distribute forces */
- auto f_left = (fac * d1i) * (vec1 * cosine - vec2);
- auto f_right = (fac * d2i) * (vec2 * cosine - vec1);
+ auto const v1 = vec1 / d1;
+ auto const v2 = vec2 / d2;
+ auto f_left = (fac / d1) * (v1 * cos_phi - v2);
+ auto f_right = (fac / d2) * (v2 * cos_phi - v1);
auto f_mid = -(f_left + f_right);
return std::make_tuple(f_mid, f_left, f_right);
}
diff --git a/src/core/bonded_interactions/angle_cosine.hpp b/src/core/bonded_interactions/angle_cosine.hpp
index b9918fd102f..4e455b0b1fc 100644
--- a/src/core/bonded_interactions/angle_cosine.hpp
+++ b/src/core/bonded_interactions/angle_cosine.hpp
@@ -26,6 +26,7 @@
* @ref bondedIA_angle_cosine.
*/
+#include "BoxGeometry.hpp"
#include "angle_common.hpp"
#include
@@ -52,10 +53,8 @@ struct AngleCosineBond {
AngleCosineBond(double bend, double phi0);
std::tuple
- forces(Utils::Vector3d const &r_mid, Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const;
- double energy(Utils::Vector3d const &r_mid, Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const;
+ forces(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
+ double energy(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
private:
friend boost::serialization::access;
@@ -69,15 +68,13 @@ struct AngleCosineBond {
};
/** Compute the three-body angle interaction force.
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
* @return Forces on the second, first and third particles, in that order.
*/
inline std::tuple
-AngleCosineBond::forces(Utils::Vector3d const &r_mid,
- Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const {
+AngleCosineBond::forces(Utils::Vector3d const &vec1,
+ Utils::Vector3d const &vec2) const {
auto forceFactor = [this](double const cos_phi) {
auto const sin_phi = sqrt(1 - Utils::sqr(cos_phi));
@@ -86,19 +83,16 @@ AngleCosineBond::forces(Utils::Vector3d const &r_mid,
return -bend * (sin_phi * cos_phi0 - cos_phi * sin_phi0) / sin_phi;
};
- return angle_generic_force(r_mid, r_left, r_right, forceFactor, false);
+ return angle_generic_force(vec1, vec2, forceFactor, false);
}
/** Computes the three-body angle interaction energy.
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
*/
-inline double AngleCosineBond::energy(Utils::Vector3d const &r_mid,
- Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const {
- auto const vectors = calc_vectors_and_cosine(r_mid, r_left, r_right, true);
- auto const cos_phi = std::get<4>(vectors);
+inline double AngleCosineBond::energy(Utils::Vector3d const &vec1,
+ Utils::Vector3d const &vec2) const {
+ auto const cos_phi = calc_cosine(vec1, vec2, true);
auto const sin_phi = sqrt(1 - Utils::sqr(cos_phi));
// potential: U(phi) = k * [1 - cos(phi - phi0)]
// trig identity: cos(phi - phi0) = cos(phi)cos(phi0) + sin(phi)sin(phi0)
diff --git a/src/core/bonded_interactions/angle_cossquare.hpp b/src/core/bonded_interactions/angle_cossquare.hpp
index 473ea7817d2..b29d6c9cbeb 100644
--- a/src/core/bonded_interactions/angle_cossquare.hpp
+++ b/src/core/bonded_interactions/angle_cossquare.hpp
@@ -49,10 +49,8 @@ struct AngleCossquareBond {
AngleCossquareBond(double bend, double phi0);
std::tuple
- forces(Utils::Vector3d const &r_mid, Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const;
- double energy(Utils::Vector3d const &r_mid, Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const;
+ forces(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
+ double energy(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
private:
friend boost::serialization::access;
@@ -65,33 +63,28 @@ struct AngleCossquareBond {
};
/** Compute the three-body angle interaction force.
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
* @return Forces on the second, first and third particles, in that order.
*/
inline std::tuple
-AngleCossquareBond::forces(Utils::Vector3d const &r_mid,
- Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const {
+AngleCossquareBond::forces(Utils::Vector3d const &vec1,
+ Utils::Vector3d const &vec2) const {
auto forceFactor = [this](double const cos_phi) {
return bend * (cos_phi - cos_phi0);
};
- return angle_generic_force(r_mid, r_left, r_right, forceFactor, false);
+ return angle_generic_force(vec1, vec2, forceFactor, false);
}
/** Computes the three-body angle interaction energy.
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
*/
-inline double AngleCossquareBond::energy(Utils::Vector3d const &r_mid,
- Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const {
- auto const vectors = calc_vectors_and_cosine(r_mid, r_left, r_right, true);
- auto const cos_phi = std::get<4>(vectors);
+inline double AngleCossquareBond::energy(Utils::Vector3d const &vec1,
+ Utils::Vector3d const &vec2) const {
+ auto const cos_phi = calc_cosine(vec1, vec2, true);
return 0.5 * bend * Utils::sqr(cos_phi - cos_phi0);
}
diff --git a/src/core/bonded_interactions/angle_harmonic.hpp b/src/core/bonded_interactions/angle_harmonic.hpp
index a1f53d08da2..f0c813d3766 100644
--- a/src/core/bonded_interactions/angle_harmonic.hpp
+++ b/src/core/bonded_interactions/angle_harmonic.hpp
@@ -51,10 +51,8 @@ struct AngleHarmonicBond {
}
std::tuple
- forces(Utils::Vector3d const &r_mid, Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const;
- double energy(Utils::Vector3d const &r_mid, Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const;
+ forces(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
+ double energy(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
private:
friend boost::serialization::access;
@@ -66,15 +64,13 @@ struct AngleHarmonicBond {
};
/** Compute the three-body angle interaction force.
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
* @return Forces on the second, first and third particles, in that order.
*/
inline std::tuple
-AngleHarmonicBond::forces(Utils::Vector3d const &r_mid,
- Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const {
+AngleHarmonicBond::forces(Utils::Vector3d const &vec1,
+ Utils::Vector3d const &vec2) const {
auto forceFactor = [this](double const cos_phi) {
auto const sin_phi = sqrt(1 - Utils::sqr(cos_phi));
@@ -82,19 +78,16 @@ AngleHarmonicBond::forces(Utils::Vector3d const &r_mid,
return -bend * (phi - phi0) / sin_phi;
};
- return angle_generic_force(r_mid, r_left, r_right, forceFactor, true);
+ return angle_generic_force(vec1, vec2, forceFactor, true);
}
/** Compute the three-body angle interaction energy.
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
*/
-inline double AngleHarmonicBond::energy(Utils::Vector3d const &r_mid,
- Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const {
- auto const vectors = calc_vectors_and_cosine(r_mid, r_left, r_right, true);
- auto const cos_phi = std::get<4>(vectors);
+inline double AngleHarmonicBond::energy(Utils::Vector3d const &vec1,
+ Utils::Vector3d const &vec2) const {
+ auto const cos_phi = calc_cosine(vec1, vec2, true);
auto const phi = acos(cos_phi);
return 0.5 * bend * Utils::sqr(phi - phi0);
}
diff --git a/src/core/bonded_interactions/bonded_interactions.dox b/src/core/bonded_interactions/bonded_interactions.dox
index 314415a1378..b559a6c6996 100644
--- a/src/core/bonded_interactions/bonded_interactions.dox
+++ b/src/core/bonded_interactions/bonded_interactions.dox
@@ -134,8 +134,8 @@
* @code
* # enable boost::variant with more than 20 types
* target_compile_options(
- * EspressoCppFlags INTERFACE -DBOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
- * -DBOOST_MPL_LIMIT_LIST_SIZE=40)
+ * espresso_cpp_flags INTERFACE -DBOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
+ * -DBOOST_MPL_LIMIT_LIST_SIZE=40)
* @endcode
* * In forces_inline.hpp:
* - A call to the new bond's force calculation needs to be placed in either
diff --git a/src/core/bonded_interactions/bonded_tab.hpp b/src/core/bonded_interactions/bonded_tab.hpp
index 0725aad8fe1..70739fad20d 100644
--- a/src/core/bonded_interactions/bonded_tab.hpp
+++ b/src/core/bonded_interactions/bonded_tab.hpp
@@ -92,10 +92,8 @@ struct TabulatedAngleBond : public TabulatedBond {
TabulatedAngleBond(double min, double max, std::vector const &energy,
std::vector const &force);
std::tuple
- forces(Utils::Vector3d const &r_mid, Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const;
- double energy(Utils::Vector3d const &r_mid, Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const;
+ forces(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
+ double energy(Utils::Vector3d const &vec1, Utils::Vector3d const &vec2) const;
};
/** Parameters for 4-body tabulated potential. */
@@ -109,12 +107,11 @@ struct TabulatedDihedralBond : public TabulatedBond {
std::vector const &force);
boost::optional>
- forces(Utils::Vector3d const &r1, Utils::Vector3d const &r2,
- Utils::Vector3d const &r3, Utils::Vector3d const &r4) const;
- boost::optional energy(Utils::Vector3d const &r1,
- Utils::Vector3d const &r2,
- Utils::Vector3d const &r3,
- Utils::Vector3d const &r4) const;
+ forces(Utils::Vector3d const &v12, Utils::Vector3d const &v23,
+ Utils::Vector3d const &v34) const;
+ boost::optional energy(Utils::Vector3d const &v12,
+ Utils::Vector3d const &v23,
+ Utils::Vector3d const &v34) const;
};
/** Compute a tabulated bond length force.
@@ -155,15 +152,13 @@ TabulatedDistanceBond::energy(Utils::Vector3d const &dx) const {
}
/** Compute the three-body angle interaction force.
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
* @return Forces on the second, first and third particles, in that order.
*/
inline std::tuple
-TabulatedAngleBond::forces(Utils::Vector3d const &r_mid,
- Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const {
+TabulatedAngleBond::forces(Utils::Vector3d const &vec1,
+ Utils::Vector3d const &vec2) const {
auto forceFactor = [this](double const cos_phi) {
auto const sin_phi = sqrt(1 - Utils::sqr(cos_phi));
@@ -177,22 +172,19 @@ TabulatedAngleBond::forces(Utils::Vector3d const &r_mid,
return -gradient / sin_phi;
};
- return angle_generic_force(r_mid, r_left, r_right, forceFactor, true);
+ return angle_generic_force(vec1, vec2, forceFactor, true);
}
/** Compute the three-body angle interaction energy.
* It is assumed that the potential is tabulated
* for all angles between 0 and Pi.
*
- * @param[in] r_mid Position of second/middle particle.
- * @param[in] r_left Position of first/left particle.
- * @param[in] r_right Position of third/right particle.
+ * @param[in] vec1 Vector from central particle to left particle.
+ * @param[in] vec2 Vector from central particle to right particle.
*/
-inline double TabulatedAngleBond::energy(Utils::Vector3d const &r_mid,
- Utils::Vector3d const &r_left,
- Utils::Vector3d const &r_right) const {
- auto const vectors = calc_vectors_and_cosine(r_mid, r_left, r_right, true);
- auto const cos_phi = std::get<4>(vectors);
+inline double TabulatedAngleBond::energy(Utils::Vector3d const &vec1,
+ Utils::Vector3d const &vec2) const {
+ auto const cos_phi = calc_cosine(vec1, vec2, true);
/* calculate phi */
#ifdef TABANGLEMINUS
auto const phi = acos(-cos_phi);
@@ -206,28 +198,25 @@ inline double TabulatedAngleBond::energy(Utils::Vector3d const &r_mid,
* The forces have a singularity at @f$ \phi = 0 @f$ and @f$ \phi = \pi @f$
* (see @cite swope92a page 592).
*
- * @param[in] r1 Position of the first particle.
- * @param[in] r2 Position of the second particle.
- * @param[in] r3 Position of the third particle.
- * @param[in] r4 Position of the fourth particle.
+ * @param[in] v12 Vector from @p p1 to @p p2
+ * @param[in] v23 Vector from @p p2 to @p p3
+ * @param[in] v34 Vector from @p p3 to @p p4
* @return the forces on @p p2, @p p1, @p p3
*/
inline boost::optional>
-TabulatedDihedralBond::forces(Utils::Vector3d const &r1,
- Utils::Vector3d const &r2,
- Utils::Vector3d const &r3,
- Utils::Vector3d const &r4) const {
+TabulatedDihedralBond::forces(Utils::Vector3d const &v12,
+ Utils::Vector3d const &v23,
+ Utils::Vector3d const &v34) const {
/* vectors for dihedral angle calculation */
- Utils::Vector3d v12, v23, v34, v12Xv23, v23Xv34;
+ Utils::Vector3d v12Xv23, v23Xv34;
double l_v12Xv23, l_v23Xv34;
/* dihedral angle, cosine of the dihedral angle */
double phi, cos_phi;
/* dihedral angle */
- auto const angle_is_undefined =
- calc_dihedral_angle(r1, r2, r3, r4, v12, v23, v34, v12Xv23, l_v12Xv23,
- v23Xv34, l_v23Xv34, cos_phi, phi);
+ auto const angle_is_undefined = calc_dihedral_angle(
+ v12, v23, v34, v12Xv23, l_v12Xv23, v23Xv34, l_v23Xv34, cos_phi, phi);
/* dihedral angle not defined - force zero */
if (angle_is_undefined) {
return {};
@@ -255,22 +244,21 @@ TabulatedDihedralBond::forces(Utils::Vector3d const &r1,
/** Compute the four-body dihedral interaction energy.
* The energy doesn't have any singularity if the angle phi is well-defined.
*
- * @param[in] r1 Position of the first particle.
- * @param[in] r2 Position of the second particle.
- * @param[in] r3 Position of the third particle.
- * @param[in] r4 Position of the fourth particle.
+ * @param[in] v12 Vector from @p p1 to @p p2
+ * @param[in] v23 Vector from @p p2 to @p p3
+ * @param[in] v34 Vector from @p p3 to @p p4
*/
-inline boost::optional TabulatedDihedralBond::energy(
- Utils::Vector3d const &r1, Utils::Vector3d const &r2,
- Utils::Vector3d const &r3, Utils::Vector3d const &r4) const {
+inline boost::optional
+TabulatedDihedralBond::energy(Utils::Vector3d const &v12,
+ Utils::Vector3d const &v23,
+ Utils::Vector3d const &v34) const {
/* vectors for dihedral calculations. */
- Utils::Vector3d v12, v23, v34, v12Xv23, v23Xv34;
+ Utils::Vector3d v12Xv23, v23Xv34;
double l_v12Xv23, l_v23Xv34;
/* dihedral angle, cosine of the dihedral angle */
double phi, cos_phi;
- auto const angle_is_undefined =
- calc_dihedral_angle(r1, r2, r3, r4, v12, v23, v34, v12Xv23, l_v12Xv23,
- v23Xv34, l_v23Xv34, cos_phi, phi);
+ auto const angle_is_undefined = calc_dihedral_angle(
+ v12, v23, v34, v12Xv23, l_v12Xv23, v23Xv34, l_v23Xv34, cos_phi, phi);
/* dihedral angle not defined - energy zero */
if (angle_is_undefined) {
return {};
diff --git a/src/core/bonded_interactions/dihedral.hpp b/src/core/bonded_interactions/dihedral.hpp
index 63c28fef1cd..f5281dd0061 100644
--- a/src/core/bonded_interactions/dihedral.hpp
+++ b/src/core/bonded_interactions/dihedral.hpp
@@ -27,9 +27,7 @@
* the maximal bond length!
*/
-#include "BoxGeometry.hpp"
#include "config/config.hpp"
-#include "grid.hpp"
#include
#include
@@ -57,13 +55,12 @@ struct DihedralBond {
boost::optional>
- forces(Utils::Vector3d const &r1, Utils::Vector3d const &r2,
- Utils::Vector3d const &r3, Utils::Vector3d const &r4) const;
+ forces(Utils::Vector3d const &v12, Utils::Vector3d const &v23,
+ Utils::Vector3d const &v34) const;
- inline boost::optional energy(Utils::Vector3d const &r1,
- Utils::Vector3d const &r2,
- Utils::Vector3d const &r3,
- Utils::Vector3d const &r4) const;
+ boost::optional energy(Utils::Vector3d const &v12,
+ Utils::Vector3d const &v23,
+ Utils::Vector3d const &v34) const;
private:
friend boost::serialization::access;
@@ -85,10 +82,9 @@ struct DihedralBond {
* If the a,b or b,c are parallel the dihedral angle is not defined in which
* case the function returns true. Calling functions should check for that.
*
- * @param[in] r1 , r2 , r3 , r4 Positions of the particles forming the dihedral
- * @param[out] a Vector from @p p1 to @p p2
- * @param[out] b Vector from @p p2 to @p p3
- * @param[out] c Vector from @p p3 to @p p4
+ * @param[in] a Vector from @p p1 to @p p2
+ * @param[in] b Vector from @p p2 to @p p3
+ * @param[in] c Vector from @p p3 to @p p4
* @param[out] aXb Vector product of a and b
* @param[out] l_aXb |aXB|
* @param[out] bXc Vector product of b and c
@@ -97,15 +93,11 @@ struct DihedralBond {
* @param[out] phi Dihedral angle in the range [0, pi]
* @return Whether the angle is undefined.
*/
-inline bool
-calc_dihedral_angle(Utils::Vector3d const &r1, Utils::Vector3d const &r2,
- Utils::Vector3d const &r3, Utils::Vector3d const &r4,
- Utils::Vector3d &a, Utils::Vector3d &b, Utils::Vector3d &c,
- Utils::Vector3d &aXb, double &l_aXb, Utils::Vector3d &bXc,
- double &l_bXc, double &cosphi, double &phi) {
- a = box_geo.get_mi_vector(r2, r1);
- b = box_geo.get_mi_vector(r3, r2);
- c = box_geo.get_mi_vector(r4, r3);
+inline bool calc_dihedral_angle(Utils::Vector3d const &a,
+ Utils::Vector3d const &b,
+ Utils::Vector3d const &c, Utils::Vector3d &aXb,
+ double &l_aXb, Utils::Vector3d &bXc,
+ double &l_bXc, double &cosphi, double &phi) {
/* calculate vector product a X b and b X c */
aXb = vector_product(a, b);
@@ -141,27 +133,24 @@ calc_dihedral_angle(Utils::Vector3d const &r1, Utils::Vector3d const &r2,
* The forces have a singularity at @f$ \phi = 0 @f$ and @f$ \phi = \pi @f$
* (see @cite swope92a page 592).
*
- * @param[in] r1 Position of the first particle.
- * @param[in] r2 Position of the second particle.
- * @param[in] r3 Position of the third particle.
- * @param[in] r4 Position of the fourth particle.
+ * @param[in] v12 Vector from @p p1 to @p p2
+ * @param[in] v23 Vector from @p p2 to @p p3
+ * @param[in] v34 Vector from @p p3 to @p p4
* @return the forces on @p p2, @p p1, @p p3
*/
inline boost::optional>
-DihedralBond::forces(Utils::Vector3d const &r1, Utils::Vector3d const &r2,
- Utils::Vector3d const &r3,
- Utils::Vector3d const &r4) const {
+DihedralBond::forces(Utils::Vector3d const &v12, Utils::Vector3d const &v23,
+ Utils::Vector3d const &v34) const {
/* vectors for dihedral angle calculation */
- Utils::Vector3d v12, v23, v34, v12Xv23, v23Xv34;
+ Utils::Vector3d v12Xv23, v23Xv34;
double l_v12Xv23, l_v23Xv34;
/* dihedral angle, cosine of the dihedral angle */
double phi, cos_phi, sin_mphi_over_sin_phi;
/* dihedral angle */
- auto const angle_is_undefined =
- calc_dihedral_angle(r1, r2, r3, r4, v12, v23, v34, v12Xv23, l_v12Xv23,
- v23Xv34, l_v23Xv34, cos_phi, phi);
+ auto const angle_is_undefined = calc_dihedral_angle(
+ v12, v23, v34, v12Xv23, l_v12Xv23, v23Xv34, l_v23Xv34, cos_phi, phi);
/* dihedral angle not defined - force zero */
if (angle_is_undefined) {
return {};
@@ -199,24 +188,21 @@ DihedralBond::forces(Utils::Vector3d const &r1, Utils::Vector3d const &r2,
/** Compute the four-body dihedral interaction energy.
* The energy doesn't have any singularity if the angle phi is well-defined.
*
- * @param[in] r1 Position of the first particle.
- * @param[in] r2 Position of the second particle.
- * @param[in] r3 Position of the third particle.
- * @param[in] r4 Position of the fourth particle.
+ * @param[in] v12 Vector from @p p1 to @p p2
+ * @param[in] v23 Vector from @p p2 to @p p3
+ * @param[in] v34 Vector from @p p3 to @p p4
*/
inline boost::optional
-DihedralBond::energy(Utils::Vector3d const &r1, Utils::Vector3d const &r2,
- Utils::Vector3d const &r3,
- Utils::Vector3d const &r4) const {
+DihedralBond::energy(Utils::Vector3d const &v12, Utils::Vector3d const &v23,
+ Utils::Vector3d const &v34) const {
/* vectors for dihedral calculations. */
- Utils::Vector3d v12, v23, v34, v12Xv23, v23Xv34;
+ Utils::Vector3d v12Xv23, v23Xv34;
double l_v12Xv23, l_v23Xv34;
/* dihedral angle, cosine of the dihedral angle */
double phi, cos_phi;
- auto const angle_is_undefined =
- calc_dihedral_angle(r1, r2, r3, r4, v12, v23, v34, v12Xv23, l_v12Xv23,
- v23Xv34, l_v23Xv34, cos_phi, phi);
+ auto const angle_is_undefined = calc_dihedral_angle(
+ v12, v23, v34, v12Xv23, l_v12Xv23, v23Xv34, l_v23Xv34, cos_phi, phi);
/* dihedral angle not defined - energy zero */
if (angle_is_undefined) {
return {};
diff --git a/src/core/cell_system/AtomDecomposition.cpp b/src/core/cell_system/AtomDecomposition.cpp
index 66618d2a580..bd538039767 100644
--- a/src/core/cell_system/AtomDecomposition.cpp
+++ b/src/core/cell_system/AtomDecomposition.cpp
@@ -102,7 +102,7 @@ void AtomDecomposition::mark_cells() {
void AtomDecomposition::resort(bool global_flag,
std::vector &diff) {
for (auto &p : local().particles()) {
- fold_position(p.pos(), p.image_box(), m_box);
+ m_box.fold_position(p.pos(), p.image_box());
p.pos_at_last_verlet_update() = p.pos();
}
diff --git a/src/core/cell_system/CellStructure.cpp b/src/core/cell_system/CellStructure.cpp
index 0ecdcc00ce9..7eedbcd27ed 100644
--- a/src/core/cell_system/CellStructure.cpp
+++ b/src/core/cell_system/CellStructure.cpp
@@ -27,7 +27,6 @@
#include "cell_system/RegularDecomposition.hpp"
#include "cell_system/CellStructureType.hpp"
-#include "grid.hpp"
#include "lees_edwards/lees_edwards.hpp"
#include
@@ -256,7 +255,7 @@ void CellStructure::resort_particles(bool global_flag, BoxGeometry const &box) {
void CellStructure::set_atom_decomposition(boost::mpi::communicator const &comm,
BoxGeometry const &box,
- LocalBox &local_geo) {
+ LocalBox &local_geo) {
set_particle_decomposition(std::make_unique(comm, box));
m_type = CellStructureType::CELL_STRUCTURE_NSQUARE;
local_geo.set_cell_structure_type(m_type);
@@ -264,7 +263,7 @@ void CellStructure::set_atom_decomposition(boost::mpi::communicator const &comm,
void CellStructure::set_regular_decomposition(
boost::mpi::communicator const &comm, double range, BoxGeometry const &box,
- LocalBox &local_geo) {
+ LocalBox &local_geo) {
set_particle_decomposition(
std::make_unique(comm, range, box, local_geo));
m_type = CellStructureType::CELL_STRUCTURE_REGULAR;
@@ -273,8 +272,7 @@ void CellStructure::set_regular_decomposition(
void CellStructure::set_hybrid_decomposition(
boost::mpi::communicator const &comm, double cutoff_regular,
- BoxGeometry const &box, LocalBox &local_geo,
- std::set n_square_types) {
+ BoxGeometry const &box, LocalBox &local_geo, std::set n_square_types) {
set_particle_decomposition(std::make_unique(
comm, cutoff_regular, box, local_geo, n_square_types));
m_type = CellStructureType::CELL_STRUCTURE_HYBRID;
diff --git a/src/core/cell_system/CellStructure.hpp b/src/core/cell_system/CellStructure.hpp
index 27c487e9b3d..3b5b0b4e49d 100644
--- a/src/core/cell_system/CellStructure.hpp
+++ b/src/core/cell_system/CellStructure.hpp
@@ -19,8 +19,7 @@
* along with this program. If not, see .
*/
-#ifndef ESPRESSO_SRC_CORE_CELL_SYSTEM_CELL_STRUCTURE_HPP
-#define ESPRESSO_SRC_CORE_CELL_SYSTEM_CELL_STRUCTURE_HPP
+#pragma once
#include "cell_system/ParticleDecomposition.hpp"
@@ -40,8 +39,6 @@
#include
#include
-#include
-#include
#include
#include
@@ -53,6 +50,10 @@
#include
#include
+namespace boost::mpi {
+class communicator;
+}
+
namespace Cells {
enum Resort : unsigned {
RESORT_NONE = 0u,
@@ -517,8 +518,7 @@ struct CellStructure {
* @param local_geo Geometry of the local box (holds cell structure type).
*/
void set_atom_decomposition(boost::mpi::communicator const &comm,
- BoxGeometry const &box,
- LocalBox &local_geo);
+ BoxGeometry const &box, LocalBox &local_geo);
/**
* @brief Set the particle decomposition to @ref RegularDecomposition.
@@ -530,7 +530,7 @@ struct CellStructure {
*/
void set_regular_decomposition(boost::mpi::communicator const &comm,
double range, BoxGeometry const &box,
- LocalBox &local_geo);
+ LocalBox &local_geo);
/**
* @brief Set the particle decomposition to @ref HybridDecomposition.
@@ -543,7 +543,7 @@ struct CellStructure {
*/
void set_hybrid_decomposition(boost::mpi::communicator const &comm,
double cutoff_regular, BoxGeometry const &box,
- LocalBox &local_geo,
+ LocalBox &local_geo,
std::set n_square_types);
private:
@@ -744,5 +744,3 @@ struct CellStructure {
}
}
};
-
-#endif
diff --git a/src/core/cell_system/HybridDecomposition.cpp b/src/core/cell_system/HybridDecomposition.cpp
index 073c03b636e..a921eecde05 100644
--- a/src/core/cell_system/HybridDecomposition.cpp
+++ b/src/core/cell_system/HybridDecomposition.cpp
@@ -43,7 +43,7 @@
HybridDecomposition::HybridDecomposition(boost::mpi::communicator comm,
double cutoff_regular,
BoxGeometry const &box_geo,
- LocalBox const &local_box,
+ LocalBox const &local_box,
std::set n_square_types)
: m_comm(std::move(comm)), m_box(box_geo), m_cutoff_regular(cutoff_regular),
m_regular_decomposition(RegularDecomposition(
diff --git a/src/core/cell_system/HybridDecomposition.hpp b/src/core/cell_system/HybridDecomposition.hpp
index 6db52dbc5eb..d58ffbf326d 100644
--- a/src/core/cell_system/HybridDecomposition.hpp
+++ b/src/core/cell_system/HybridDecomposition.hpp
@@ -77,8 +77,7 @@ class HybridDecomposition : public ParticleDecomposition {
public:
HybridDecomposition(boost::mpi::communicator comm, double cutoff_regular,
- BoxGeometry const &box_geo,
- LocalBox const &local_box,
+ BoxGeometry const &box_geo, LocalBox const &local_box,
std::set n_square_types);
Utils::Vector3i get_cell_grid() const {
diff --git a/src/core/cell_system/RegularDecomposition.cpp b/src/core/cell_system/RegularDecomposition.cpp
index 6500a57a829..b3be169b98e 100644
--- a/src/core/cell_system/RegularDecomposition.cpp
+++ b/src/core/cell_system/RegularDecomposition.cpp
@@ -23,9 +23,10 @@
#include "cell_system/Cell.hpp"
+#include "communication.hpp"
#include "error_handling/RuntimeErrorStream.hpp"
#include "errorhandling.hpp"
-#include "grid.hpp"
+#include "system/System.hpp"
#include
#include
@@ -53,7 +54,7 @@
Cell *RegularDecomposition::position_to_cell(const Utils::Vector3d &pos) {
Utils::Vector3i cpos;
- for (unsigned int i = 0; i < 3; i++) {
+ for (unsigned int i = 0u; i < 3u; i++) {
cpos[i] = static_cast(std::floor(pos[i] * inv_cell_size[i])) + 1 -
cell_offset[i];
@@ -63,14 +64,14 @@ Cell *RegularDecomposition::position_to_cell(const Utils::Vector3d &pos) {
the particle belongs here and could otherwise potentially be dismissed
due to rounding errors. */
if (cpos[i] < 1) {
- if ((!m_box.periodic(i) or (pos[i] >= m_box.length()[i])) &&
- m_local_box.boundary()[2 * i])
+ if ((!m_box.periodic(i) or (pos[i] >= m_box.length()[i])) and
+ m_local_box.boundary()[2u * i])
cpos[i] = 1;
else
return nullptr;
} else if (cpos[i] > cell_grid[i]) {
- if ((!m_box.periodic(i) or (pos[i] < m_box.length()[i])) &&
- m_local_box.boundary()[2 * i + 1])
+ if ((!m_box.periodic(i) or (pos[i] < m_box.length()[i])) and
+ m_local_box.boundary()[2u * i + 1u])
cpos[i] = cell_grid[i];
else
return nullptr;
@@ -102,18 +103,20 @@ void RegularDecomposition::move_left_or_right(ParticleList &src,
ParticleList &left,
ParticleList &right,
int dir) const {
+ auto const is_open_boundary_left = m_local_box.boundary()[2 * dir] != 0;
+ auto const is_open_boundary_right = m_local_box.boundary()[2 * dir + 1] != 0;
+ auto const can_move_left = m_box.periodic(dir) or not is_open_boundary_left;
+ auto const can_move_right = m_box.periodic(dir) or not is_open_boundary_right;
+ auto const my_left = m_local_box.my_left()[dir];
+ auto const my_right = m_local_box.my_right()[dir];
for (auto it = src.begin(); it != src.end();) {
- if ((m_box.get_mi_coord(it->pos()[dir], m_local_box.my_left()[dir], dir) <
- 0.0) and
- (m_box.periodic(dir) || (m_local_box.boundary()[2 * dir] == 0))) {
- left.insert(std::move(*it));
- it = src.erase(it);
- } else if ((m_box.get_mi_coord(it->pos()[dir], m_local_box.my_right()[dir],
- dir) >= 0.0) and
- (m_box.periodic(dir) ||
- (m_local_box.boundary()[2 * dir + 1] == 0))) {
+ auto const pos = it->pos()[dir];
+ if (m_box.get_mi_coord(pos, my_right, dir) >= 0. and can_move_right) {
right.insert(std::move(*it));
it = src.erase(it);
+ } else if (m_box.get_mi_coord(pos, my_left, dir) < 0. and can_move_left) {
+ left.insert(std::move(*it));
+ it = src.erase(it);
} else {
++it;
}
@@ -162,16 +165,14 @@ void RegularDecomposition::exchange_neighbors(
}
}
-namespace {
/**
* @brief Fold coordinates to box and reset the old position.
*/
-void fold_and_reset(Particle &p, BoxGeometry const &box_geo) {
- fold_position(p.pos(), p.image_box(), box_geo);
+static void fold_and_reset(Particle &p, BoxGeometry const &box_geo) {
+ box_geo.fold_position(p.pos(), p.image_box());
p.pos_at_last_verlet_update() = p.pos();
}
-} // namespace
void RegularDecomposition::resort(bool global,
std::vector &diff) {
@@ -393,9 +394,11 @@ template auto make_flat_set(Comparator &&comp) {
void RegularDecomposition::init_cell_interactions() {
+ auto const &box_geo = *System::get_system().box_geo;
auto const halo = Utils::Vector3i{1, 1, 1};
auto const cart_info = Utils::Mpi::cart_get<3>(m_comm);
- auto const node_pos = cart_info.coords;
+ auto const &node_pos = cart_info.coords;
+ auto const &node_grid = ::communicator.node_grid;
auto const global_halo_offset = hadamard_product(node_pos, cell_grid) - halo;
auto const global_size = hadamard_product(node_grid, cell_grid);
@@ -633,7 +636,7 @@ GhostCommunicator RegularDecomposition::prepare_comm() {
RegularDecomposition::RegularDecomposition(boost::mpi::communicator comm,
double range,
BoxGeometry const &box_geo,
- LocalBox const &local_geo)
+ LocalBox const &local_geo)
: m_comm(std::move(comm)), m_box(box_geo), m_local_box(local_geo) {
/* set up new regular decomposition cell structure */
create_cell_grid(range);
diff --git a/src/core/cell_system/RegularDecomposition.hpp b/src/core/cell_system/RegularDecomposition.hpp
index 77ccc09aa3b..0072f4e1c7e 100644
--- a/src/core/cell_system/RegularDecomposition.hpp
+++ b/src/core/cell_system/RegularDecomposition.hpp
@@ -79,7 +79,7 @@ struct RegularDecomposition : public ParticleDecomposition {
boost::mpi::communicator m_comm;
BoxGeometry const &m_box;
- LocalBox m_local_box;
+ LocalBox m_local_box;
std::vector cells;
std::vector m_local_cells;
std::vector m_ghost_cells;
@@ -88,8 +88,7 @@ struct RegularDecomposition : public ParticleDecomposition {
public:
RegularDecomposition(boost::mpi::communicator comm, double range,
- BoxGeometry const &box_geo,
- LocalBox const &local_geo);
+ BoxGeometry const &box_geo, LocalBox const &local_geo);
GhostCommunicator const &exchange_ghosts_comm() const override {
return m_exchange_ghosts_comm;
diff --git a/src/core/cells.cpp b/src/core/cells.cpp
index 1272800b4a7..416980f4a13 100644
--- a/src/core/cells.cpp
+++ b/src/core/cells.cpp
@@ -36,9 +36,9 @@
#include "communication.hpp"
#include "errorhandling.hpp"
#include "event.hpp"
-#include "grid.hpp"
#include "integrate.hpp"
#include "particle_node.hpp"
+#include "system/System.hpp"
#include
#include
@@ -53,9 +53,6 @@
#include
#include
-/** Type of cell structure in use */
-CellStructure cell_structure{box_geo};
-
/**
* @brief Get pairs of particles that are closer than a distance and fulfill a
* filter criterion.
@@ -77,6 +74,7 @@ std::vector> get_pairs_filtered(double const distance,
ret.emplace_back(p1.id(), p2.id());
};
+ auto &cell_structure = *System::get_system().cell_structure;
cell_structure.non_bonded_loop(pair_kernel);
/* Sort pairs */
@@ -90,6 +88,8 @@ std::vector> get_pairs_filtered(double const distance,
namespace detail {
static auto get_max_neighbor_search_range() {
+ auto const &system = System::get_system();
+ auto const &cell_structure = *system.cell_structure;
return *boost::min_element(cell_structure.max_range());
}
static void search_distance_sanity_check_max_range(double const distance) {
@@ -104,6 +104,8 @@ static void search_distance_sanity_check_max_range(double const distance) {
}
}
static void search_distance_sanity_check_cell_structure(double const distance) {
+ auto const &system = System::get_system();
+ auto const &cell_structure = *system.cell_structure;
if (cell_structure.decomposition_type() ==
CellStructureType::CELL_STRUCTURE_HYBRID) {
throw std::runtime_error("Cannot search for neighbors in the hybrid "
@@ -127,9 +129,10 @@ get_short_range_neighbors(int const pid, double const distance) {
ret.emplace_back(p2.id());
}
};
- auto const p = ::cell_structure.get_local_particle(pid);
+ auto &cell_structure = *System::get_system().cell_structure;
+ auto const p = cell_structure.get_local_particle(pid);
if (p and not p->is_ghost()) {
- ::cell_structure.run_on_particle_short_range_neighbors(*p, kernel);
+ cell_structure.run_on_particle_short_range_neighbors(*p, kernel);
return {ret};
}
return {};
@@ -139,7 +142,8 @@ get_short_range_neighbors(int const pid, double const distance) {
* @brief Get pointers to all interacting neighbors of a central particle.
*/
static auto get_interacting_neighbors(Particle const &p) {
- auto const distance = *boost::min_element(::cell_structure.max_range());
+ auto &cell_structure = *System::get_system().cell_structure;
+ auto const distance = *boost::min_element(cell_structure.max_range());
detail::search_neighbors_sanity_checks(distance);
std::vector ret;
auto const cutoff2 = Utils::sqr(distance);
@@ -149,7 +153,7 @@ static auto get_interacting_neighbors(Particle const &p) {
ret.emplace_back(&p2);
}
};
- ::cell_structure.run_on_particle_short_range_neighbors(p, kernel);
+ cell_structure.run_on_particle_short_range_neighbors(p, kernel);
return ret;
}
@@ -175,6 +179,7 @@ std::vector non_bonded_loop_trace(int const rank) {
Distance const &d) {
pairs.emplace_back(p1.id(), p2.id(), p1.pos(), p2.pos(), d.vec21, rank);
};
+ auto &cell_structure = *System::get_system().cell_structure;
cell_structure.non_bonded_loop(pair_kernel);
return pairs;
}
@@ -190,7 +195,8 @@ std::vector get_neighbor_pids() {
}
ret.emplace_back(p.id(), neighbor_pids);
};
- for (auto const &p : ::cell_structure.local_particles()) {
+ auto &cell_structure = *System::get_system().cell_structure;
+ for (auto const &p : cell_structure.local_particles()) {
kernel(p, get_interacting_neighbors(p));
}
return ret;
@@ -198,12 +204,19 @@ std::vector get_neighbor_pids() {
void set_hybrid_decomposition(std::set n_square_types,
double cutoff_regular) {
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto &local_geo = *system.local_geo;
+ auto &cell_structure = *system.cell_structure;
cell_structure.set_hybrid_decomposition(comm_cart, cutoff_regular, box_geo,
local_geo, n_square_types);
on_cell_structure_change();
}
-void cells_re_init(CellStructureType new_cs) {
+void cells_re_init(CellStructure &cell_structure, CellStructureType new_cs) {
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto &local_geo = *system.local_geo;
switch (new_cs) {
case CellStructureType::CELL_STRUCTURE_REGULAR:
cell_structure.set_regular_decomposition(comm_cart, interaction_range(),
@@ -230,6 +243,8 @@ void cells_re_init(CellStructureType new_cs) {
}
void check_resort_particles() {
+ auto &cell_structure = *System::get_system().cell_structure;
+
auto const level = (cell_structure.check_resort_required(
cell_structure.local_particles(), skin))
? Cells::RESORT_LOCAL
@@ -239,6 +254,10 @@ void check_resort_particles() {
}
void cells_update_ghosts(unsigned data_parts) {
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto &cell_structure = *system.cell_structure;
+
/* data parts that are only updated on resort */
auto constexpr resort_only_parts =
Cells::DATA_PART_PROPERTIES | Cells::DATA_PART_BONDS;
@@ -272,7 +291,3 @@ void cells_update_ghosts(unsigned data_parts) {
cell_structure.ghosts_update(data_parts & ~resort_only_parts);
}
}
-
-Cell *find_current_cell(Particle const &p) {
- return cell_structure.find_current_cell(p);
-}
diff --git a/src/core/cells.hpp b/src/core/cells.hpp
index 0dbcd3004f6..704007e1f03 100644
--- a/src/core/cells.hpp
+++ b/src/core/cells.hpp
@@ -47,8 +47,7 @@
* should be treated using N-square.
*/
-#ifndef ESPRESSO_SRC_CORE_CELLS_HPP
-#define ESPRESSO_SRC_CORE_CELLS_HPP
+#pragma once
#include "cell_system/Cell.hpp"
#include "cell_system/CellStructure.hpp"
@@ -74,9 +73,6 @@ enum {
CELL_GLOBAL_EXCHANGE = 1
};
-/** Type of cell structure in use. */
-extern CellStructure cell_structure;
-
/** Initialize cell structure @ref HybridDecomposition
* @param n_square_types Types of particles to place in the N-square cells.
* @param cutoff_regular Cutoff for the regular decomposition.
@@ -85,9 +81,14 @@ void set_hybrid_decomposition(std::set n_square_types,
double cutoff_regular);
/** Reinitialize the cell structures.
+ * @param cell_structure The cell structure to modify
* @param new_cs The new topology to use afterwards.
*/
-void cells_re_init(CellStructureType new_cs);
+void cells_re_init(CellStructure &cell_structure, CellStructureType new_cs);
+
+inline void cells_re_init(CellStructure &cell_structure) {
+ cells_re_init(cell_structure, cell_structure.decomposition_type());
+}
/** Update ghost information. If needed,
* the particles are also resorted.
@@ -143,16 +144,6 @@ void serialize(Archive &ar, NeighborPIDs &n, unsigned int const /* version */) {
*/
std::vector get_neighbor_pids();
-/**
- * @brief Find the cell in which a particle is stored.
- *
- * Uses position_to_cell on p.pos(). If this is not on the node's domain,
- * uses position at last Verlet list rebuild (p.p_old()).
- *
- * @return pointer to the cell or nullptr if the particle is not on the node
- */
-Cell *find_current_cell(Particle const &p);
-
class PairInfo {
public:
PairInfo() = default;
@@ -187,5 +178,3 @@ void serialize(Archive &ar, PairInfo &p, unsigned int const /* version */) {
* non-bonded loop.
*/
std::vector non_bonded_loop_trace(int rank);
-
-#endif
diff --git a/src/core/cluster_analysis/Cluster.cpp b/src/core/cluster_analysis/Cluster.cpp
index b29d0340535..841b056f1d2 100644
--- a/src/core/cluster_analysis/Cluster.cpp
+++ b/src/core/cluster_analysis/Cluster.cpp
@@ -28,8 +28,8 @@
#include "BoxGeometry.hpp"
#include "Particle.hpp"
#include "errorhandling.hpp"
-#include "grid.hpp"
#include "particle_node.hpp"
+#include "system/System.hpp"
#include
@@ -52,6 +52,7 @@ Utils::Vector3d Cluster::center_of_mass() {
Utils::Vector3d
Cluster::center_of_mass_subcluster(std::vector const &particle_ids) {
sanity_checks();
+ auto const &box_geo = *System::get_system().box_geo;
Utils::Vector3d com{};
// The distances between the particles are "folded", such that all distances
@@ -59,11 +60,11 @@ Cluster::center_of_mass_subcluster(std::vector const &particle_ids) {
// of the cluster is arbitrarily chosen as reference.
auto const reference_position =
- folded_position(get_particle_data(particles[0]).pos(), box_geo);
+ box_geo.folded_position(get_particle_data(particles[0]).pos());
double total_mass = 0.;
for (int pid : particle_ids) {
auto const folded_pos =
- folded_position(get_particle_data(pid).pos(), box_geo);
+ box_geo.folded_position(get_particle_data(pid).pos());
auto const dist_to_reference =
box_geo.get_mi_vector(folded_pos, reference_position);
com += dist_to_reference * get_particle_data(pid).mass();
@@ -77,11 +78,12 @@ Cluster::center_of_mass_subcluster(std::vector const &particle_ids) {
com += reference_position;
// Fold into simulation box
- return folded_position(com, box_geo);
+ return box_geo.folded_position(com);
}
double Cluster::longest_distance() {
sanity_checks();
+ auto const &box_geo = *System::get_system().box_geo;
double ld = 0.;
for (auto a = particles.begin(); a != particles.end(); a++) {
for (auto b = a; ++b != particles.end();) {
@@ -105,6 +107,7 @@ double Cluster::radius_of_gyration() {
double
Cluster::radius_of_gyration_subcluster(std::vector const &particle_ids) {
sanity_checks();
+ auto const &box_geo = *System::get_system().box_geo;
// Center of mass
Utils::Vector3d com = center_of_mass_subcluster(particle_ids);
double sum_sq_dist = 0.;
@@ -133,6 +136,7 @@ std::vector sort_indices(const std::vector &v) {
std::pair Cluster::fractal_dimension(double dr) {
#ifdef GSL
sanity_checks();
+ auto const &box_geo = *System::get_system().box_geo;
Utils::Vector3d com = center_of_mass();
// calculate Df using linear regression on the logarithms of the radii of
// gyration against the number of particles in sub-clusters. Particles are
@@ -182,7 +186,8 @@ std::pair Cluster::fractal_dimension(double dr) {
}
void Cluster::sanity_checks() const {
- if (::box_geo.type() != BoxType::CUBOID) {
+ auto const &box_geo = *System::get_system().box_geo;
+ if (box_geo.type() != BoxType::CUBOID) {
throw std::runtime_error(
"Cluster analysis is not compatible with non-cuboid box types");
}
diff --git a/src/core/cluster_analysis/ClusterStructure.cpp b/src/core/cluster_analysis/ClusterStructure.cpp
index 6cd7a03cd3b..0f32c1a6519 100644
--- a/src/core/cluster_analysis/ClusterStructure.cpp
+++ b/src/core/cluster_analysis/ClusterStructure.cpp
@@ -22,9 +22,9 @@
#include "Cluster.hpp"
#include "PartCfg.hpp"
#include "errorhandling.hpp"
-#include "grid.hpp"
#include "partCfg_global.hpp"
#include "particle_node.hpp"
+#include "system/System.hpp"
#include
@@ -195,7 +195,7 @@ int ClusterStructure::get_next_free_cluster_id() {
}
void ClusterStructure::sanity_checks() const {
- if (::box_geo.type() != BoxType::CUBOID) {
+ if (System::get_system().box_geo->type() != BoxType::CUBOID) {
throw std::runtime_error(
"Cluster analysis is not compatible with non-cuboid box types");
}
diff --git a/src/core/collision.cpp b/src/core/collision.cpp
index a32dec37243..e85367f4b3d 100644
--- a/src/core/collision.cpp
+++ b/src/core/collision.cpp
@@ -20,15 +20,17 @@
#include "collision.hpp"
#ifdef COLLISION_DETECTION
+#include "BoxGeometry.hpp"
#include "Particle.hpp"
#include "bonded_interactions/bonded_interaction_data.hpp"
#include "cell_system/Cell.hpp"
+#include "cell_system/CellStructure.hpp"
#include "cells.hpp"
#include "communication.hpp"
#include "errorhandling.hpp"
#include "event.hpp"
-#include "grid.hpp"
#include "nonbonded_interactions/nonbonded_interaction_data.hpp"
+#include "system/System.hpp"
#include "virtual_sites.hpp"
#include
@@ -73,7 +75,7 @@ static std::vector local_collision_queue;
Collision_parameters collision_params;
namespace {
-Particle &get_part(int id) {
+Particle &get_part(CellStructure &cell_structure, int id) {
auto const p = cell_structure.get_local_particle(id);
if (not p) {
@@ -234,45 +236,46 @@ void queue_collision(const int part1, const int part2) {
/** @brief Calculate position of vs for GLUE_TO_SURFACE mode.
* Returns id of particle to bind vs to.
*/
-const Particle &glue_to_surface_calc_vs_pos(const Particle &p1,
- const Particle &p2,
- Utils::Vector3d &pos) {
+static auto const &glue_to_surface_calc_vs_pos(Particle const &p1,
+ Particle const &p2,
+ BoxGeometry const &box_geo,
+ Utils::Vector3d &pos) {
double c;
auto const vec21 = box_geo.get_mi_vector(p1.pos(), p2.pos());
- const double dist_betw_part = vec21.norm();
+ auto const dist = vec21.norm();
// Find out, which is the particle to be glued.
if ((p1.type() == collision_params.part_type_to_be_glued) and
(p2.type() == collision_params.part_type_to_attach_vs_to)) {
- c = 1 - collision_params.dist_glued_part_to_vs / dist_betw_part;
+ c = 1. - collision_params.dist_glued_part_to_vs / dist;
} else if ((p2.type() == collision_params.part_type_to_be_glued) and
(p1.type() == collision_params.part_type_to_attach_vs_to)) {
- c = collision_params.dist_glued_part_to_vs / dist_betw_part;
+ c = collision_params.dist_glued_part_to_vs / dist;
} else {
throw std::runtime_error("This should never be thrown. Bug.");
}
- for (int i = 0; i < 3; i++) {
- pos[i] = p2.pos()[i] + vec21[i] * c;
- }
+ pos = p2.pos() + vec21 * c;
if (p1.type() == collision_params.part_type_to_attach_vs_to)
return p1;
return p2;
}
-void bind_at_point_of_collision_calc_vs_pos(const Particle *const p1,
- const Particle *const p2,
- Utils::Vector3d &pos1,
- Utils::Vector3d &pos2) {
- auto const vec21 = box_geo.get_mi_vector(p1->pos(), p2->pos());
- pos1 = p1->pos() - vec21 * collision_params.vs_placement;
- pos2 = p1->pos() - vec21 * (1. - collision_params.vs_placement);
+static void bind_at_point_of_collision_calc_vs_pos(Particle const &p1,
+ Particle const &p2,
+ BoxGeometry const &box_geo,
+ Utils::Vector3d &pos1,
+ Utils::Vector3d &pos2) {
+ auto const vec21 = box_geo.get_mi_vector(p1.pos(), p2.pos());
+ pos1 = p1.pos() - vec21 * collision_params.vs_placement;
+ pos2 = p1.pos() - vec21 * (1. - collision_params.vs_placement);
}
// Considers three particles for three_particle_binding and performs
// the binding if the criteria are met
-void coldet_do_three_particle_bond(Particle &p, Particle const &p1,
- Particle const &p2) {
+static void coldet_do_three_particle_bond(Particle &p, Particle const &p1,
+ Particle const &p2,
+ BoxGeometry const &box_geo) {
// If p1 and p2 are not closer or equal to the cutoff distance, skip
// p1:
if (box_geo.get_mi_vector(p.pos(), p1.pos()).norm() >
@@ -337,63 +340,65 @@ void coldet_do_three_particle_bond(Particle &p, Particle const &p1,
}
#ifdef VIRTUAL_SITES_RELATIVE
-void place_vs_and_relate_to_particle(const int current_vs_pid,
- const Utils::Vector3d &pos,
- int relate_to) {
+static void place_vs_and_relate_to_particle(CellStructure &cell_structure,
+ BoxGeometry const &box_geo,
+ int const current_vs_pid,
+ Utils::Vector3d const &pos,
+ int const relate_to) {
Particle new_part;
new_part.id() = current_vs_pid;
new_part.pos() = pos;
auto p_vs = cell_structure.add_particle(std::move(new_part));
- vs_relate_to(*p_vs, get_part(relate_to));
+ vs_relate_to(*p_vs, get_part(cell_structure, relate_to), box_geo);
p_vs->set_virtual(true);
p_vs->type() = collision_params.vs_particle_type;
}
-void bind_at_poc_create_bond_between_vs(const int current_vs_pid,
- const CollisionPair &c) {
+static void bind_at_poc_create_bond_between_vs(CellStructure &cell_structure,
+ int const current_vs_pid,
+ CollisionPair const &c) {
switch (get_bond_num_partners(collision_params.bond_vs)) {
case 1: {
// Create bond between the virtual particles
const int bondG[] = {current_vs_pid - 2};
// Only add bond if vs was created on this node
- if (cell_structure.get_local_particle(current_vs_pid - 1))
- get_part(current_vs_pid - 1)
- .bonds()
- .insert({collision_params.bond_vs, bondG});
+ if (auto p = cell_structure.get_local_particle(current_vs_pid - 1))
+ p->bonds().insert({collision_params.bond_vs, bondG});
break;
}
case 2: {
// Create 1st bond between the virtual particles
const int bondG[] = {c.pp1, c.pp2};
// Only add bond if vs was created on this node
- if (cell_structure.get_local_particle(current_vs_pid - 1))
- get_part(current_vs_pid - 1)
- .bonds()
- .insert({collision_params.bond_vs, bondG});
- if (cell_structure.get_local_particle(current_vs_pid - 2))
- get_part(current_vs_pid - 2)
- .bonds()
- .insert({collision_params.bond_vs, bondG});
+ if (auto p = cell_structure.get_local_particle(current_vs_pid - 1))
+ p->bonds().insert({collision_params.bond_vs, bondG});
+ if (auto p = cell_structure.get_local_particle(current_vs_pid - 2))
+ p->bonds().insert({collision_params.bond_vs, bondG});
break;
}
}
}
-void glue_to_surface_bind_part_to_vs(const Particle *const p1,
- const Particle *const p2,
- const int vs_pid_plus_one,
- const CollisionPair &) {
+static void glue_to_surface_bind_part_to_vs(Particle const *const p1,
+ Particle const *const p2,
+ int const vs_pid_plus_one,
+ CollisionPair const &,
+ CellStructure &cell_structure) {
// Create bond between the virtual particles
const int bondG[] = {vs_pid_plus_one - 1};
if (p1->type() == collision_params.part_type_after_glueing) {
- get_part(p1->id()).bonds().insert({collision_params.bond_vs, bondG});
+ get_part(cell_structure, p1->id())
+ .bonds()
+ .insert({collision_params.bond_vs, bondG});
} else {
- get_part(p2->id()).bonds().insert({collision_params.bond_vs, bondG});
+ get_part(cell_structure, p2->id())
+ .bonds()
+ .insert({collision_params.bond_vs, bondG});
}
}
-#endif
+#endif // VIRTUAL_SITES_RELATIVE
std::vector gather_global_collision_queue() {
std::vector res = local_collision_queue;
@@ -405,29 +410,30 @@ std::vector gather_global_collision_queue() {
}
static void three_particle_binding_do_search(Cell *basecell, Particle &p1,
- Particle &p2) {
- auto handle_cell = [&p1, &p2](Cell *c) {
- for (auto &P : c->particles()) {
+ Particle &p2,
+ BoxGeometry const &box_geo) {
+ auto handle_cell = [&p1, &p2, &box_geo](Cell *c) {
+ for (auto &p : c->particles()) {
// Skip collided particles themselves
- if ((P.id() == p1.id()) || (P.id() == p2.id())) {
+ if ((p.id() == p1.id()) or (p.id() == p2.id())) {
continue;
}
// We need all cyclical permutations, here (bond is placed on 1st
// particle, order of bond partners does not matter, so we don't need
// non-cyclic permutations).
- // coldet_do_three_particle_bond checks the bonding criterion and if
+ // @ref coldet_do_three_particle_bond checks the bonding criterion and if
// the involved particles are not already bonded before it binds them.
- if (!P.is_ghost()) {
- coldet_do_three_particle_bond(P, p1, p2);
+ if (!p.is_ghost()) {
+ coldet_do_three_particle_bond(p, p1, p2, box_geo);
}
if (!p1.is_ghost()) {
- coldet_do_three_particle_bond(p1, P, p2);
+ coldet_do_three_particle_bond(p1, p, p2, box_geo);
}
if (!p2.is_ghost()) {
- coldet_do_three_particle_bond(p2, P, p1);
+ coldet_do_three_particle_bond(p2, p, p1, box_geo);
}
}
};
@@ -444,8 +450,9 @@ static void three_particle_binding_do_search(Cell *basecell, Particle &p1,
// Goes through the collision queue and for each pair in it
// looks for a third particle by using the domain decomposition
// cell system. If found, it performs three particle binding
-void three_particle_binding_domain_decomposition(
- const std::vector &gathered_queue) {
+static void three_particle_binding_domain_decomposition(
+ CellStructure &cell_structure, BoxGeometry const &box_geo,
+ std::vector const &gathered_queue) {
for (auto &c : gathered_queue) {
// If we have both particles, at least as ghosts, Get the corresponding cell
@@ -454,20 +461,21 @@ void three_particle_binding_domain_decomposition(
cell_structure.get_local_particle(c.pp2)) {
Particle &p1 = *cell_structure.get_local_particle(c.pp1);
Particle &p2 = *cell_structure.get_local_particle(c.pp2);
- auto cell1 = find_current_cell(p1);
- auto cell2 = find_current_cell(p2);
+ auto cell1 = cell_structure.find_current_cell(p1);
+ auto cell2 = cell_structure.find_current_cell(p2);
if (cell1)
- three_particle_binding_do_search(cell1, p1, p2);
+ three_particle_binding_do_search(cell1, p1, p2, box_geo);
if (cell2 and cell1 != cell2)
- three_particle_binding_do_search(cell2, p1, p2);
+ three_particle_binding_do_search(cell2, p1, p2, box_geo);
} // If local particles exist
} // Loop over total collisions
}
// Handle the collisions stored in the queue
-void handle_collisions() {
+void handle_collisions(CellStructure &cell_structure) {
+ auto const &box_geo = *System::get_system().box_geo;
// Note that the glue to surface mode adds bonds between the centers
// but does so later in the process. This is needed to guarantee that
// a particle can only be glued once, even if queued twice in a single
@@ -481,7 +489,9 @@ void handle_collisions() {
const int bondG[] = {c.pp2};
- get_part(c.pp1).bonds().insert({collision_params.bond_centers, bondG});
+ get_part(cell_structure, c.pp1)
+ .bonds()
+ .insert({collision_params.bond_centers, bondG});
}
}
@@ -546,11 +556,12 @@ void handle_collisions() {
p2->set_can_rotate_all_axes();
// Positions of the virtual sites
- bind_at_point_of_collision_calc_vs_pos(p1, p2, pos1, pos2);
+ bind_at_point_of_collision_calc_vs_pos(*p1, *p2, box_geo, pos1, pos2);
auto handle_particle = [&](Particle *p, Utils::Vector3d const &pos) {
if (not p->is_ghost()) {
- place_vs_and_relate_to_particle(current_vs_pid, pos, p->id());
+ place_vs_and_relate_to_particle(cell_structure, box_geo,
+ current_vs_pid, pos, p->id());
// Particle storage locations may have changed due to
// added particle
p1 = cell_structure.get_local_particle(c.pp1);
@@ -569,7 +580,7 @@ void handle_collisions() {
current_vs_pid++;
// Create bonds between the vs.
- bind_at_poc_create_bond_between_vs(current_vs_pid, c);
+ bind_at_poc_create_bond_between_vs(cell_structure, current_vs_pid, c);
} // mode VS
if (collision_params.mode == CollisionModeType::GLUE_TO_SURF) {
@@ -587,15 +598,16 @@ void handle_collisions() {
}
Utils::Vector3d pos;
- const Particle &attach_vs_to =
- glue_to_surface_calc_vs_pos(*p1, *p2, pos);
+ Particle const &attach_vs_to =
+ glue_to_surface_calc_vs_pos(*p1, *p2, box_geo, pos);
// Add a bond between the centers of the colliding particles
// The bond is placed on the node that has p1
if (!p1->is_ghost()) {
const int bondG[] = {c.pp2};
- get_part(c.pp1).bonds().insert(
- {collision_params.bond_centers, bondG});
+ get_part(cell_structure, c.pp1)
+ .bonds()
+ .insert({collision_params.bond_centers, bondG});
}
// Change type of particle being attached, to make it inert
@@ -608,7 +620,8 @@ void handle_collisions() {
// Vs placement happens on the node that has p1
if (!attach_vs_to.is_ghost()) {
- place_vs_and_relate_to_particle(current_vs_pid, pos,
+ place_vs_and_relate_to_particle(cell_structure, box_geo,
+ current_vs_pid, pos,
attach_vs_to.id());
// Particle storage locations may have changed due to
// added particle
@@ -618,7 +631,8 @@ void handle_collisions() {
} else { // Just update the books
current_vs_pid++;
}
- glue_to_surface_bind_part_to_vs(p1, p2, current_vs_pid, c);
+ glue_to_surface_bind_part_to_vs(p1, p2, current_vs_pid, c,
+ cell_structure);
}
} // we considered the pair
} // Loop over all collisions in the queue
@@ -639,10 +653,11 @@ void handle_collisions() {
// three-particle-binding part
if (collision_params.mode == CollisionModeType::BIND_THREE_PARTICLES) {
auto gathered_queue = gather_global_collision_queue();
- three_particle_binding_domain_decomposition(gathered_queue);
+ three_particle_binding_domain_decomposition(cell_structure, box_geo,
+ gathered_queue);
} // if TPB
local_collision_queue.clear();
}
-#endif
+#endif // COLLISION_DETECTION
diff --git a/src/core/collision.hpp b/src/core/collision.hpp
index e46a6d7baf2..339e47f81a8 100644
--- a/src/core/collision.hpp
+++ b/src/core/collision.hpp
@@ -16,11 +16,13 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-#ifndef CORE_COLLISION_HPP
-#define CORE_COLLISION_HPP
+
+#pragma once
#include "config/config.hpp"
+#include "cell_system/CellStructure.hpp"
+
#include "BondList.hpp"
#include "Particle.hpp"
@@ -99,7 +101,7 @@ extern Collision_parameters collision_params;
void prepare_local_collision_queue();
/// Handle the collisions recorded in the queue
-void handle_collisions();
+void handle_collisions(CellStructure &cell_structure);
/** @brief Add the collision between the given particle ids to the collision
* queue
@@ -156,5 +158,3 @@ inline double collision_detection_cutoff() {
#endif
return -1.;
}
-
-#endif
diff --git a/src/core/communication.cpp b/src/core/communication.cpp
index 7c4a430306a..4a8813610ba 100644
--- a/src/core/communication.cpp
+++ b/src/core/communication.cpp
@@ -25,23 +25,26 @@
#include "errorhandling.hpp"
#include "event.hpp"
-#include "grid.hpp"
#ifdef WALBERLA
#include
#endif
+#include
#include
#include
+#include
#include
#include
#include
+#include
#include
boost::mpi::communicator comm_cart;
+Communicator communicator{};
namespace Communication {
static auto const &mpi_datatype_cache =
@@ -60,19 +63,12 @@ MpiCallbacks &mpiCallbacks() {
using Communication::mpiCallbacks;
int this_node = -1;
-int n_nodes = -1;
namespace Communication {
void init(std::shared_ptr mpi_env) {
Communication::mpi_env = std::move(mpi_env);
- MPI_Comm_size(MPI_COMM_WORLD, &n_nodes);
- node_grid = Utils::Mpi::dims_create<3>(n_nodes);
-
- comm_cart =
- Utils::Mpi::cart_create(comm_cart, node_grid, /* reorder */ false);
-
- this_node = comm_cart.rank();
+ communicator.full_initialization();
Communication::m_callbacks =
std::make_unique(comm_cart);
@@ -87,6 +83,35 @@ void init(std::shared_ptr mpi_env) {
}
} // namespace Communication
+Communicator::Communicator()
+ : comm{::comm_cart}, node_grid{}, this_node{::this_node}, size{-1} {}
+
+void Communicator::init_comm_cart() {
+ auto constexpr reorder = false;
+ comm = Utils::Mpi::cart_create(comm, node_grid, reorder);
+ this_node = comm.rank();
+ // check topology validity
+ std::ignore = Utils::Mpi::cart_neighbors<3>(comm);
+}
+
+void Communicator::full_initialization() {
+ assert(this_node == -1);
+ assert(size == -1);
+ MPI_Comm_size(MPI_COMM_WORLD, &size);
+ node_grid = Utils::Mpi::dims_create<3>(size);
+ init_comm_cart();
+}
+
+void Communicator::set_node_grid(Utils::Vector3i const &value) {
+ node_grid = value;
+ init_comm_cart();
+ on_node_grid_change();
+}
+
+Utils::Vector3i Communicator::calc_node_index() const {
+ return Utils::Mpi::cart_coords<3>(comm, this_node);
+}
+
std::shared_ptr mpi_init(int argc, char **argv) {
return std::make_shared(argc, argv);
}
diff --git a/src/core/communication.hpp b/src/core/communication.hpp
index a7dbcf42800..7bf9178c100 100644
--- a/src/core/communication.hpp
+++ b/src/core/communication.hpp
@@ -46,6 +46,8 @@
#include "MpiCallbacks.hpp"
+#include
+
#include
#include
@@ -54,11 +56,28 @@
/** The number of this node. */
extern int this_node;
-/** The total number of nodes. */
-extern int n_nodes;
/** The communicator */
extern boost::mpi::communicator comm_cart;
+struct Communicator {
+ boost::mpi::communicator &comm;
+ Utils::Vector3i node_grid;
+ /** @brief The MPI rank. */
+ int &this_node;
+ /** @brief The MPI world size. */
+ int size;
+
+ Communicator();
+ void init_comm_cart();
+ void full_initialization();
+ /** @brief Calculate the node index in the Cartesian topology. */
+ Utils::Vector3i calc_node_index() const;
+ /** @brief Set new Cartesian topology. */
+ void set_node_grid(Utils::Vector3i const &value);
+};
+
+extern Communicator communicator;
+
namespace Communication {
/**
* @brief Returns a reference to the global callback class instance.
diff --git a/src/core/constraints/Constraints.hpp b/src/core/constraints/Constraints.hpp
index 8c19dbf6678..edc46cc20cc 100644
--- a/src/core/constraints/Constraints.hpp
+++ b/src/core/constraints/Constraints.hpp
@@ -19,8 +19,9 @@
#ifndef CORE_CONSTRAINTS_CONSTRAINTS_HPP
#define CORE_CONSTRAINTS_CONSTRAINTS_HPP
+#include "BoxGeometry.hpp"
#include "Observable_stat.hpp"
-#include "grid.hpp"
+#include "system/System.hpp"
#include
#include
@@ -53,6 +54,7 @@ template class Constraints {
return std::find(begin(), end(), constraint) != end();
}
void add(std::shared_ptr const &constraint) {
+ auto const &box_geo = *System::get_system().box_geo;
if (not constraint->fits_in_box(box_geo.length())) {
throw std::runtime_error("Constraint not compatible with box size.");
}
@@ -71,27 +73,28 @@ template class Constraints {
const_iterator begin() const { return m_constraints.begin(); }
const_iterator end() const { return m_constraints.end(); }
- void add_forces(ParticleRange &particles, double t) const {
+ void add_forces(BoxGeometry const &box_geo, ParticleRange &particles,
+ double time) const {
if (m_constraints.empty())
return;
reset_forces();
for (auto &p : particles) {
- auto const pos = folded_position(p.pos(), box_geo);
+ auto const pos = box_geo.folded_position(p.pos());
ParticleForce force{};
for (auto const &constraint : *this) {
- force += constraint->force(p, pos, t);
+ force += constraint->force(p, pos, time);
}
p.force_and_torque() += force;
}
}
- void add_energy(const ParticleRange &particles, double time,
- Observable_stat &obs_energy) const {
- for (auto &p : particles) {
- auto const pos = folded_position(p.pos(), box_geo);
+ void add_energy(BoxGeometry const &box_geo, ParticleRange const &particles,
+ double time, Observable_stat &obs_energy) const {
+ for (auto const &p : particles) {
+ auto const pos = box_geo.folded_position(p.pos());
for (auto const &constraint : *this) {
constraint->add_energy(p, pos, time, obs_energy);
diff --git a/src/core/constraints/ShapeBasedConstraint.cpp b/src/core/constraints/ShapeBasedConstraint.cpp
index 9b4e2fe2107..450544ef39e 100644
--- a/src/core/constraints/ShapeBasedConstraint.cpp
+++ b/src/core/constraints/ShapeBasedConstraint.cpp
@@ -27,7 +27,6 @@
#include "energy_inline.hpp"
#include "errorhandling.hpp"
#include "forces_inline.hpp"
-#include "grid.hpp"
#include "nonbonded_interactions/nonbonded_interaction_data.hpp"
#include "system/System.hpp"
#include "thermostat.hpp"
@@ -51,17 +50,18 @@ double ShapeBasedConstraint::total_normal_force() const {
}
double ShapeBasedConstraint::min_dist(const ParticleRange &particles) {
+ auto const &box_geo = *System::get_system().box_geo;
double global_mindist = std::numeric_limits::infinity();
auto const local_mindist = std::accumulate(
particles.begin(), particles.end(),
std::numeric_limits::infinity(),
- [this](double min, Particle const &p) {
+ [this, &box_geo](double min, Particle const &p) {
auto const &ia_params = get_ia_param(p.type(), part_rep.type());
if (checkIfInteraction(ia_params)) {
double dist;
Utils::Vector3d vec;
- m_shape->calculate_dist(folded_position(p.pos(), box_geo), dist, vec);
+ m_shape->calculate_dist(box_geo.folded_position(p.pos()), dist, vec);
return std::min(min, dist);
}
return min;
diff --git a/src/core/cuda/init.cpp b/src/core/cuda/init.cpp
index 5aca865c74d..13776e951e8 100644
--- a/src/core/cuda/init.cpp
+++ b/src/core/cuda/init.cpp
@@ -83,7 +83,8 @@ std::vector cuda_gather_gpus() {
}
}
- int const n_gpus = static_cast(devices_local.size());
+ auto const n_gpus = static_cast(devices_local.size());
+ auto const n_nodes = ::communicator.size;
if (this_node == 0) {
std::set device_set;
diff --git a/src/core/dpd.cpp b/src/core/dpd.cpp
index 369b513c19e..794b3119b51 100644
--- a/src/core/dpd.cpp
+++ b/src/core/dpd.cpp
@@ -27,13 +27,15 @@
#include "dpd.hpp"
+#include "BoxGeometry.hpp"
+#include "cell_system/CellStructure.hpp"
#include "cells.hpp"
#include "event.hpp"
-#include "grid.hpp"
#include "integrate.hpp"
#include "interactions.hpp"
#include "nonbonded_interactions/nonbonded_interaction_data.hpp"
#include "random.hpp"
+#include "system/System.hpp"
#include "thermostat.hpp"
#include
@@ -49,8 +51,6 @@
#include
#include
-using Utils::Vector3d;
-
/** Return a random uniform 3D vector with the Philox thermostat.
* Random numbers depend on
* 1. dpd_rng_counter (initialized by seed) which is increased on integration
@@ -58,7 +58,7 @@ using Utils::Vector3d;
* 3. Two particle IDs (order-independent, decorrelates particles, gets rid of
* seed-per-node)
*/
-Vector3d dpd_noise(int pid1, int pid2) {
+Utils::Vector3d dpd_noise(int pid1, int pid2) {
return Random::noise_uniform(
dpd.rng_counter(), dpd.rng_seed(), (pid1 < pid2) ? pid2 : pid1,
(pid1 < pid2) ? pid1 : pid2);
@@ -84,8 +84,9 @@ static double weight(int type, double r_cut, double k, double r) {
return 1. - pow((r / r_cut), k);
}
-Vector3d dpd_pair_force(DPDParameters const ¶ms, Vector3d const &v,
- double dist, Vector3d const &noise) {
+Utils::Vector3d dpd_pair_force(DPDParameters const ¶ms,
+ Utils::Vector3d const &v, double dist,
+ Utils::Vector3d const &noise) {
if (dist < params.cutoff) {
auto const omega = weight(params.wf, params.cutoff, params.k, dist);
auto const omega2 = Utils::sqr(omega);
@@ -107,12 +108,14 @@ Utils::Vector3d dpd_pair_force(Particle const &p1, Particle const &p2,
return {};
}
+ auto const &box_geo = *System::get_system().box_geo;
+
auto const v21 =
box_geo.velocity_difference(p1.pos(), p2.pos(), p1.v(), p2.v());
auto const noise_vec =
(ia_params.dpd.radial.pref > 0.0 || ia_params.dpd.trans.pref > 0.0)
? dpd_noise(p1.id(), p2.id())
- : Vector3d{};
+ : Utils::Vector3d{};
auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, noise_vec);
auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, noise_vec);
@@ -126,28 +129,32 @@ Utils::Vector3d dpd_pair_force(Particle const &p1, Particle const &p2,
}
static auto dpd_viscous_stress_local() {
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto &cell_structure = *system.cell_structure;
on_observable_calc();
Utils::Matrix stress{};
- cell_structure.non_bonded_loop(
- [&stress](const Particle &p1, const Particle &p2, Distance const &d) {
- auto const v21 =
- box_geo.velocity_difference(p1.pos(), p2.pos(), p1.v(), p2.v());
+ cell_structure.non_bonded_loop([&stress, &box_geo](Particle const &p1,
+ Particle const &p2,
+ Distance const &d) {
+ auto const v21 =
+ box_geo.velocity_difference(p1.pos(), p2.pos(), p1.v(), p2.v());
- auto const &ia_params = get_ia_param(p1.type(), p2.type());
- auto const dist = std::sqrt(d.dist2);
+ auto const &ia_params = get_ia_param(p1.type(), p2.type());
+ auto const dist = std::sqrt(d.dist2);
- auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, {});
- auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, {});
+ auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, {});
+ auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, {});
- /* Projection operator to radial direction */
- auto const P = tensor_product(d.vec21 / d.dist2, d.vec21);
- /* This is equivalent to P * f_r + (1 - P) * f_t, but with
- * doing only one matrix-vector multiplication */
- auto const f = P * (f_r - f_t) + f_t;
+ /* Projection operator to radial direction */
+ auto const P = tensor_product(d.vec21 / d.dist2, d.vec21);
+ /* This is equivalent to P * f_r + (1 - P) * f_t, but with
+ * doing only one matrix-vector multiplication */
+ auto const f = P * (f_r - f_t) + f_t;
- stress += tensor_product(d.vec21, f);
- });
+ stress += tensor_product(d.vec21, f);
+ });
return stress;
}
@@ -168,6 +175,7 @@ static auto dpd_viscous_stress_local() {
* @return Stress tensor contribution.
*/
Utils::Vector9d dpd_stress(boost::mpi::communicator const &comm) {
+ auto const &box_geo = *System::get_system().box_geo;
auto const local_stress = dpd_viscous_stress_local();
std::remove_const_t global_stress;
diff --git a/src/core/ek/EKWalberla.cpp b/src/core/ek/EKWalberla.cpp
index 2a23fd24348..a828440c5b8 100644
--- a/src/core/ek/EKWalberla.cpp
+++ b/src/core/ek/EKWalberla.cpp
@@ -21,10 +21,10 @@
#ifdef WALBERLA
+#include "BoxGeometry.hpp"
#include "ek/EKReactions.hpp"
#include "ek/EKWalberla.hpp"
#include "errorhandling.hpp"
-#include "grid.hpp"
#include "integrate.hpp"
#include "lb/Implementation.hpp"
#include "lb/LBWalberla.hpp"
@@ -110,8 +110,9 @@ void EKWalberla::veto_time_step(double time_step) const {
}
void EKWalberla::sanity_checks() const {
+ auto const &box_geo = *System::get_system().box_geo;
auto const &lattice = ek_container->get_lattice();
- auto const agrid = ::box_geo.length()[0] / lattice.get_grid_dimensions()[0];
+ auto const agrid = box_geo.length()[0] / lattice.get_grid_dimensions()[0];
auto [my_left, my_right] = lattice.get_local_domain();
my_left *= agrid;
my_right *= agrid;
diff --git a/src/core/electrostatics/coulomb.cpp b/src/core/electrostatics/coulomb.cpp
index afdaaf7e27d..036e558bc1a 100644
--- a/src/core/electrostatics/coulomb.cpp
+++ b/src/core/electrostatics/coulomb.cpp
@@ -28,7 +28,7 @@
#include "ParticleRange.hpp"
#include "actor/visit_try_catch.hpp"
#include "actor/visitors.hpp"
-#include "cells.hpp"
+#include "cell_system/CellStructure.hpp"
#include "communication.hpp"
#include "electrostatics/icc.hpp"
#include "errorhandling.hpp"
@@ -327,9 +327,9 @@ static auto calc_charge_excess_ratio(std::vector const &charges) {
void check_charge_neutrality(double relative_tolerance) {
// collect non-zero particle charges from all nodes
- auto const &local_particles = cell_structure.local_particles();
+ auto &cell_structure = *System::get_system().cell_structure;
std::vector local_charges;
- for (auto const &p : local_particles) {
+ for (auto const &p : cell_structure.local_particles()) {
local_charges.push_back(p.q());
}
std::vector> node_charges;
diff --git a/src/core/electrostatics/coulomb_inline.hpp b/src/core/electrostatics/coulomb_inline.hpp
index 81b6cecec67..e3365c9ba33 100644
--- a/src/core/electrostatics/coulomb_inline.hpp
+++ b/src/core/electrostatics/coulomb_inline.hpp
@@ -26,6 +26,7 @@
#include "electrostatics/solver.hpp"
#include "Particle.hpp"
+#include "system/System.hpp"
#include
#include
@@ -85,9 +86,11 @@ struct ShortRangeForceCorrectionsKernel {
result_type
operator()(std::shared_ptr const &ptr) const {
auto const &actor = *ptr;
- return kernel_type{[&actor](Particle &p1, Particle &p2, double q1q2) {
- actor.add_pair_force_corrections(p1, p2, q1q2);
- }};
+ auto const &box_geo = *System::get_system().box_geo;
+ return kernel_type{
+ [&actor, &box_geo](Particle &p1, Particle &p2, double q1q2) {
+ actor.add_pair_force_corrections(p1, p2, q1q2, box_geo);
+ }};
}
#endif // P3M
};
@@ -134,15 +137,16 @@ struct ShortRangeEnergyKernel {
result_type
operator()(std::shared_ptr const &ptr) const {
auto const &actor = *ptr;
+ auto const &box_geo = *System::get_system().box_geo;
auto const energy_kernel = std::visit(*this, actor.base_solver);
- return kernel_type{[&actor, energy_kernel](
+ return kernel_type{[&actor, &box_geo, energy_kernel](
Particle const &p1, Particle const &p2, double q1q2,
Utils::Vector3d const &d, double dist) {
auto energy = 0.;
if (energy_kernel) {
energy = (*energy_kernel)(p1, p2, q1q2, d, dist);
}
- return energy + actor.pair_energy_correction(q1q2, p1, p2);
+ return energy + actor.pair_energy_correction(p1, p2, q1q2, box_geo);
}};
}
#endif // P3M
diff --git a/src/core/electrostatics/elc.cpp b/src/core/electrostatics/elc.cpp
index 3ce90953a84..09ad631286e 100644
--- a/src/core/electrostatics/elc.cpp
+++ b/src/core/electrostatics/elc.cpp
@@ -30,13 +30,14 @@
#include "electrostatics/p3m.hpp"
#include "electrostatics/p3m_gpu.hpp"
+#include "BoxGeometry.hpp"
#include "Particle.hpp"
#include "ParticleRange.hpp"
-#include "cells.hpp"
+#include "cell_system/CellStructure.hpp"
#include "communication.hpp"
#include "errorhandling.hpp"
#include "event.hpp"
-#include "grid.hpp"
+#include "system/System.hpp"
#include
#include
@@ -124,7 +125,8 @@ static std::vector calc_sc_cache(ParticleRange const &particles,
}
static std::pair
-prepare_sc_cache(ParticleRange const &particles, double far_cut) {
+prepare_sc_cache(ParticleRange const &particles, BoxGeometry const &box_geo,
+ double far_cut) {
assert(far_cut >= 0.);
auto const n_freq_x =
static_cast(std::ceil(far_cut * box_geo.length()[0]) + 1.);
@@ -200,6 +202,7 @@ void ElectrostaticLayerCorrection::check_gap(Particle const &p) const {
void ElectrostaticLayerCorrection::add_dipole_force(
ParticleRange const &particles) const {
constexpr std::size_t size = 3;
+ auto const &box_geo = *System::get_system().box_geo;
auto const pref = prefactor * 4. * Utils::pi() / box_geo.volume();
/* for non-neutral systems, this shift gives the background contribution
@@ -265,6 +268,7 @@ void ElectrostaticLayerCorrection::add_dipole_force(
double ElectrostaticLayerCorrection::dipole_energy(
ParticleRange const &particles) const {
constexpr std::size_t size = 7;
+ auto const &box_geo = *System::get_system().box_geo;
auto const pref = prefactor * 2. * Utils::pi() / box_geo.volume();
auto const lz = box_geo.length()[2];
/* for nonneutral systems, this shift gives the background contribution
@@ -339,21 +343,30 @@ double ElectrostaticLayerCorrection::dipole_energy(
/*****************************************************************/
-static auto image_sum_b(double q, double z, double d) {
- auto const shift = box_geo.length_half()[2];
- auto const lz = box_geo.length()[2];
- return q / (1. - d) * (z - 2. * d * lz / (1. - d)) - q * shift / (1. - d);
-}
+struct ImageSum {
+ double delta;
+ double shift;
+ double lz;
+ double dci; // delta complement inverse
-static auto image_sum_t(double q, double z, double d) {
- auto const shift = box_geo.length_half()[2];
- auto const lz = box_geo.length()[2];
- return q / (1. - d) * (z + 2. * d * lz / (1. - d)) - q * shift / (1. - d);
-}
+ ImageSum(double delta, double shift, double lz)
+ : delta{delta}, shift{shift}, lz{lz}, dci{1. / (1. - delta)} {}
+
+ /** @brief Image sum from the bottom layer. */
+ double b(double q, double z) const {
+ return q * dci * (z - 2. * delta * lz * dci) - q * dci * shift;
+ }
+
+ /** @brief Image sum from the top layer. */
+ double t(double q, double z) const {
+ return q * dci * (z + 2. * delta * lz * dci) - q * dci * shift;
+ }
+};
double
ElectrostaticLayerCorrection::z_energy(ParticleRange const &particles) const {
constexpr std::size_t size = 4;
+ auto const &box_geo = *System::get_system().box_geo;
auto const xy_area_inv = box_geo.length_inv()[0] * box_geo.length_inv()[1];
auto const pref = prefactor * 2. * Utils::pi() * xy_area_inv;
auto const delta = elc.delta_mid_top * elc.delta_mid_bot;
@@ -363,7 +376,8 @@ ElectrostaticLayerCorrection::z_energy(ParticleRange const &particles) const {
/* for non-neutral systems, this shift gives the background contribution
* (rsp. for this shift, the DM of the background is zero) */
- double const shift = box_geo.length_half()[2];
+ auto const shift = box_geo.length_half()[2];
+ auto const lz = box_geo.length()[2];
if (elc.dielectric_contrast_on) {
if (elc.const_pot) {
@@ -386,6 +400,7 @@ ElectrostaticLayerCorrection::z_energy(ParticleRange const &particles) const {
// metallic boundaries
clear_vec(gblcblk, size);
auto const h = elc.box_h;
+ ImageSum const image_sum{delta, shift, lz};
for (auto const &p : particles) {
auto const z = p.pos()[2];
auto const q = p.q();
@@ -394,26 +409,25 @@ ElectrostaticLayerCorrection::z_energy(ParticleRange const &particles) const {
if (elc.dielectric_contrast_on) {
if (z < elc.space_layer) {
gblcblk[2] += fac_delta * (elc.delta_mid_bot + 1.) * q;
- gblcblk[3] += q * (image_sum_b(elc.delta_mid_bot * delta,
- -(2. * h + z), delta) +
- image_sum_b(delta, -(2. * h - z), delta));
+ gblcblk[3] +=
+ q * (image_sum.b(elc.delta_mid_bot * delta, -(2. * h + z)) +
+ image_sum.b(delta, -(2. * h - z)));
} else {
gblcblk[2] += fac_delta_mid_bot * (1. + elc.delta_mid_top) * q;
- gblcblk[3] += q * (image_sum_b(elc.delta_mid_bot, -z, delta) +
- image_sum_b(delta, -(2. * h - z), delta));
+ gblcblk[3] += q * (image_sum.b(elc.delta_mid_bot, -z) +
+ image_sum.b(delta, -(2. * h - z)));
}
if (z > (h - elc.space_layer)) {
// note the minus sign here which is required due to |z_i-z_j|
gblcblk[2] -= fac_delta * (elc.delta_mid_top + 1.) * q;
gblcblk[3] -=
- q * (image_sum_t(elc.delta_mid_top * delta, 4. * h - z, delta) +
- image_sum_t(delta, 2. * h + z, delta));
+ q * (image_sum.t(elc.delta_mid_top * delta, 4. * h - z) +
+ image_sum.t(delta, 2. * h + z));
} else {
// note the minus sign here which is required due to |z_i-z_j|
gblcblk[2] -= fac_delta_mid_top * (1. + elc.delta_mid_bot) * q;
- gblcblk[3] -=
- q * (image_sum_t(elc.delta_mid_top, 2. * h - z, delta) +
- image_sum_t(delta, 2. * h + z, delta));
+ gblcblk[3] -= q * (image_sum.t(elc.delta_mid_top, 2. * h - z) +
+ image_sum.t(delta, 2. * h + z));
}
}
}
@@ -428,6 +442,7 @@ ElectrostaticLayerCorrection::z_energy(ParticleRange const &particles) const {
void ElectrostaticLayerCorrection::add_z_force(
ParticleRange const &particles) const {
constexpr std::size_t size = 1;
+ auto const &box_geo = *System::get_system().box_geo;
auto const xy_area_inv = box_geo.length_inv()[0] * box_geo.length_inv()[1];
auto const pref = prefactor * 2. * Utils::pi() * xy_area_inv;
auto const delta = elc.delta_mid_top * elc.delta_mid_bot;
@@ -488,6 +503,7 @@ void setup_PoQ(elc_data const &elc, double prefactor, std::size_t index,
double omega, ParticleRange const &particles) {
assert(index >= 1);
constexpr std::size_t size = 4;
+ auto const &box_geo = *System::get_system().box_geo;
auto const xy_area_inv = box_geo.length_inv()[0] * box_geo.length_inv()[1];
auto const pref_di = prefactor * 4. * Utils::pi() * xy_area_inv;
auto const pref = -pref_di / expm1(omega * box_geo.length()[2]);
@@ -629,6 +645,7 @@ static void setup_PQ(elc_data const &elc, double prefactor, std::size_t index_p,
assert(index_p >= 1);
assert(index_q >= 1);
constexpr std::size_t size = 8;
+ auto const &box_geo = *System::get_system().box_geo;
auto const xy_area_inv = box_geo.length_inv()[0] * box_geo.length_inv()[1];
auto const pref_di = prefactor * 8 * Utils::pi() * xy_area_inv;
auto const pref = -pref_di / expm1(omega * box_geo.length()[2]);
@@ -753,7 +770,8 @@ static void setup_PQ(elc_data const &elc, double prefactor, std::size_t index_p,
}
static void add_PQ_force(std::size_t index_p, std::size_t index_q, double omega,
- const ParticleRange &particles) {
+ ParticleRange const &particles,
+ BoxGeometry const &box_geo) {
auto constexpr c_2pi = 2. * Utils::pi();
auto const pref_x =
c_2pi * box_geo.length_inv()[0] * static_cast(index_p) / omega;
@@ -813,7 +831,8 @@ static double PQ_energy(double omega, std::size_t n_part) {
void ElectrostaticLayerCorrection::add_force(
ParticleRange const &particles) const {
auto constexpr c_2pi = 2. * Utils::pi();
- auto const n_freqs = prepare_sc_cache(particles, elc.far_cut);
+ auto const &box_geo = *System::get_system().box_geo;
+ auto const n_freqs = prepare_sc_cache(particles, box_geo, elc.far_cut);
auto const n_scxcache = std::get<0>(n_freqs);
auto const n_scycache = std::get<1>(n_freqs);
partblk.resize(particles.size() * 8);
@@ -859,7 +878,7 @@ void ElectrostaticLayerCorrection::add_force(
Utils::sqr(box_geo.length_inv()[1] * static_cast(q)));
setup_PQ(elc, prefactor, p, q, omega, particles);
distribute(8);
- add_PQ_force(p, q, omega, particles);
+ add_PQ_force(p, q, omega, particles, box_geo);
}
}
}
@@ -867,8 +886,9 @@ void ElectrostaticLayerCorrection::add_force(
double ElectrostaticLayerCorrection::calc_energy(
ParticleRange const &particles) const {
auto constexpr c_2pi = 2. * Utils::pi();
+ auto const &box_geo = *System::get_system().box_geo;
auto energy = dipole_energy(particles) + z_energy(particles);
- auto const n_freqs = prepare_sc_cache(particles, elc.far_cut);
+ auto const n_freqs = prepare_sc_cache(particles, box_geo, elc.far_cut);
auto const n_scxcache = std::get<0>(n_freqs);
auto const n_scycache = std::get<1>(n_freqs);
@@ -923,6 +943,7 @@ double ElectrostaticLayerCorrection::calc_energy(
double ElectrostaticLayerCorrection::tune_far_cut() const {
// Largest reasonable cutoff for far formula
auto constexpr maximal_far_cut = 50.;
+ auto const &box_geo = *System::get_system().box_geo;
auto const box_l_x_inv = box_geo.length_inv()[0];
auto const box_l_y_inv = box_geo.length_inv()[1];
auto const min_inv_boxl = std::min(box_l_x_inv, box_l_y_inv);
@@ -953,6 +974,7 @@ double ElectrostaticLayerCorrection::tune_far_cut() const {
}
static auto calc_total_charge() {
+ auto &cell_structure = *System::get_system().cell_structure;
auto local_q = 0.;
for (auto const &p : cell_structure.local_particles()) {
local_q += p.q();
@@ -961,6 +983,7 @@ static auto calc_total_charge() {
}
void ElectrostaticLayerCorrection::sanity_checks_periodicity() const {
+ auto const &box_geo = *System::get_system().box_geo;
if (!box_geo.periodic(0) || !box_geo.periodic(1) || !box_geo.periodic(2)) {
throw std::runtime_error("ELC: requires periodicity (True, True, True)");
}
@@ -995,6 +1018,7 @@ void ElectrostaticLayerCorrection::adapt_solver() {
}
void ElectrostaticLayerCorrection::recalc_box_h() {
+ auto const &box_geo = *System::get_system().box_geo;
auto const new_box_h = box_geo.length()[2] - elc.gap_size;
if (new_box_h < 0.) {
throw std::runtime_error("ELC gap size (" + std::to_string(elc.gap_size) +
@@ -1032,9 +1056,9 @@ elc_data::elc_data(double maxPWerror, double gap_size, double far_cut,
bool neutralize, double delta_top, double delta_bot,
bool with_const_pot, double potential_diff)
: maxPWerror{maxPWerror}, gap_size{gap_size},
- box_h{box_geo.length()[2] - gap_size}, far_cut{far_cut}, far_cut2{-1.},
- far_calculated{far_cut == -1.}, dielectric_contrast_on{delta_top != 0. or
- delta_bot != 0.},
+ box_h{System::get_system().box_geo->length()[2] - gap_size},
+ far_cut{far_cut}, far_cut2{-1.}, far_calculated{far_cut == -1.},
+ dielectric_contrast_on{delta_top != 0. or delta_bot != 0.},
const_pot{with_const_pot and dielectric_contrast_on},
neutralize{neutralize and !dielectric_contrast_on},
delta_mid_top{std::clamp(delta_top, -1., +1.)}, delta_mid_bot{std::clamp(
@@ -1083,11 +1107,6 @@ ElectrostaticLayerCorrection::ElectrostaticLayerCorrection(
adapt_solver();
}
-Utils::Vector3d elc_data::get_mi_vector(Utils::Vector3d const &a,
- Utils::Vector3d const &b) const {
- return box_geo.get_mi_vector(a, b);
-}
-
static void p3m_assign_image_charge(elc_data const &elc, CoulombP3M &p3m,
double q, Utils::Vector3d const &pos) {
if (pos[2] < elc.space_layer) {
@@ -1170,6 +1189,7 @@ double ElectrostaticLayerCorrection::long_range_energy(
auto const energy = std::visit(
[this, &particles](auto const &solver_ptr) {
auto &solver = *solver_ptr;
+ auto const &box_geo = *System::get_system().box_geo;
// assign the original charges (they may not have been assigned yet)
solver.charge_assign(particles);
@@ -1180,7 +1200,8 @@ double ElectrostaticLayerCorrection::long_range_energy(
auto energy = 0.;
energy += 0.5 * solver.long_range_energy(particles);
- energy += 0.5 * elc.dielectric_layers_self_energy(solver, particles);
+ energy +=
+ 0.5 * elc.dielectric_layers_self_energy(solver, box_geo, particles);
// assign both original and image charges
charge_assign(elc, solver, particles);
@@ -1207,9 +1228,10 @@ void ElectrostaticLayerCorrection::add_long_range_forces(
[this, &particles](auto const &solver_ptr) {
auto &solver = *solver_ptr;
if (elc.dielectric_contrast_on) {
+ auto const &box_geo = *System::get_system().box_geo;
modify_p3m_sums(elc, solver, particles);
charge_assign(elc, solver, particles);
- elc.dielectric_layers_self_forces(solver, particles);
+ elc.dielectric_layers_self_forces(solver, box_geo, particles);
} else {
solver.charge_assign(particles);
}
diff --git a/src/core/electrostatics/elc.hpp b/src/core/electrostatics/elc.hpp
index 197aa5fe0f4..d0071881ea3 100644
--- a/src/core/electrostatics/elc.hpp
+++ b/src/core/electrostatics/elc.hpp
@@ -40,6 +40,7 @@
#include "electrostatics/p3m.hpp"
#include "electrostatics/p3m_gpu.hpp"
+#include "BoxGeometry.hpp"
#include "Particle.hpp"
#include "ParticleRange.hpp"
@@ -118,29 +119,31 @@ struct elc_data {
/// pairwise contributions from the lowest and top layers
template
void dielectric_layers_contribution(CoulombP3M const &p3m,
+ BoxGeometry const &box_geo,
Utils::Vector3d const &pos1,
Utils::Vector3d const &pos2, double q1q2,
Kernel &&kernel) const {
if (pos1[2] < space_layer) {
auto const q_eff = delta_mid_bot * q1q2;
- auto const d = get_mi_vector(pos2, {pos1[0], pos1[1], -pos1[2]});
+ auto const d = box_geo.get_mi_vector(pos2, {pos1[0], pos1[1], -pos1[2]});
kernel(q_eff, d);
}
if (pos1[2] > (box_h - space_layer)) {
auto const q_eff = delta_mid_top * q1q2;
- auto const l = 2. * box_h;
- auto const d = get_mi_vector(pos2, {pos1[0], pos1[1], l - pos1[2]});
+ auto const z = 2. * box_h - pos1[2];
+ auto const d = box_geo.get_mi_vector(pos2, {pos1[0], pos1[1], z});
kernel(q_eff, d);
}
}
/// self energies of top and bottom layers with their virtual images
double dielectric_layers_self_energy(CoulombP3M const &p3m,
+ BoxGeometry const &box_geo,
ParticleRange const &particles) const {
auto energy = 0.;
for (auto const &p : particles) {
dielectric_layers_contribution(
- p3m, p.pos(), p.pos(), Utils::sqr(p.q()),
+ p3m, box_geo, p.pos(), p.pos(), Utils::sqr(p.q()),
[&](double q1q2, Utils::Vector3d const &d) {
energy += p3m.pair_energy(q1q2, d.norm());
});
@@ -150,19 +153,16 @@ struct elc_data {
/// forces of particles in border layers with themselves
void dielectric_layers_self_forces(CoulombP3M const &p3m,
+ BoxGeometry const &box_geo,
ParticleRange const &particles) const {
for (auto &p : particles) {
dielectric_layers_contribution(
- p3m, p.pos(), p.pos(), Utils::sqr(p.q()),
+ p3m, box_geo, p.pos(), p.pos(), Utils::sqr(p.q()),
[&](double q1q2, Utils::Vector3d const &d) {
p.force() += p3m.pair_force(q1q2, d, d.norm());
});
}
}
-
-private:
- Utils::Vector3d get_mi_vector(Utils::Vector3d const &a,
- Utils::Vector3d const &b) const;
};
struct ElectrostaticLayerCorrection
@@ -252,23 +252,23 @@ struct ElectrostaticLayerCorrection
}
/** @brief Calculate short-range pair energy correction. */
- double pair_energy_correction(double q1q2, Particle const &p1,
- Particle const &p2) const {
+ double pair_energy_correction(Particle const &p1, Particle const &p2,
+ double q1q2, BoxGeometry const &box_geo) const {
double energy = 0.;
if (elc.dielectric_contrast_on) {
energy = std::visit(
- [this, &p1, &p2, q1q2](auto &p3m_ptr) {
+ [this, &p1, &p2, q1q2, &box_geo](auto &p3m_ptr) {
auto const &pos1 = p1.pos();
auto const &pos2 = p2.pos();
auto const &p3m = *p3m_ptr;
auto energy = 0.;
elc.dielectric_layers_contribution(
- p3m, pos1, pos2, q1q2,
+ p3m, box_geo, pos1, pos2, q1q2,
[&](double q_eff, Utils::Vector3d const &d) {
energy += p3m.pair_energy(q_eff, d.norm());
});
elc.dielectric_layers_contribution(
- p3m, pos2, pos1, q1q2,
+ p3m, box_geo, pos2, pos1, q1q2,
[&](double q_eff, Utils::Vector3d const &d) {
energy += p3m.pair_energy(q_eff, d.norm());
});
@@ -280,21 +280,21 @@ struct ElectrostaticLayerCorrection
}
/** @brief Add short-range pair force corrections. */
- void add_pair_force_corrections(Particle &p1, Particle &p2,
- double q1q2) const {
+ void add_pair_force_corrections(Particle &p1, Particle &p2, double q1q2,
+ BoxGeometry const &box_geo) const {
if (elc.dielectric_contrast_on) {
std::visit(
- [this, &p1, &p2, q1q2](auto &p3m_ptr) {
+ [this, &p1, &p2, q1q2, &box_geo](auto &p3m_ptr) {
auto const &pos1 = p1.pos();
auto const &pos2 = p2.pos();
auto const &p3m = *p3m_ptr;
elc.dielectric_layers_contribution(
- p3m, pos1, pos2, q1q2,
+ p3m, box_geo, pos1, pos2, q1q2,
[&](double q_eff, Utils::Vector3d const &d) {
p1.force() += p3m.pair_force(q_eff, d, d.norm());
});
elc.dielectric_layers_contribution(
- p3m, pos2, pos1, q1q2,
+ p3m, box_geo, pos2, pos1, q1q2,
[&](double q_eff, Utils::Vector3d const &d) {
p2.force() += p3m.pair_force(q_eff, d, d.norm());
});
diff --git a/src/core/electrostatics/icc.cpp b/src/core/electrostatics/icc.cpp
index 1a2590ba570..9b4ebf359b8 100644
--- a/src/core/electrostatics/icc.cpp
+++ b/src/core/electrostatics/icc.cpp
@@ -36,7 +36,6 @@
#include "ParticleRange.hpp"
#include "actor/visitors.hpp"
#include "cell_system/CellStructure.hpp"
-#include "cells.hpp"
#include "communication.hpp"
#include "electrostatics/coulomb.hpp"
#include "electrostatics/coulomb_inline.hpp"
@@ -289,6 +288,7 @@ void update_icc_particles() {
if (system.coulomb.impl->extension) {
if (auto icc = std::get_if>(
get_ptr(system.coulomb.impl->extension))) {
+ auto &cell_structure = *system.cell_structure;
(**icc).iteration(cell_structure, cell_structure.local_particles(),
cell_structure.ghost_particles());
}
diff --git a/src/core/electrostatics/mmm1d.cpp b/src/core/electrostatics/mmm1d.cpp
index 8bb7aa1782f..5a7b9962cf4 100644
--- a/src/core/electrostatics/mmm1d.cpp
+++ b/src/core/electrostatics/mmm1d.cpp
@@ -29,12 +29,14 @@
#include "electrostatics/mmm-common.hpp"
#include "electrostatics/mmm-modpsi.hpp"
+#include "BoxGeometry.hpp"
+#include "LocalBox.hpp"
#include "Particle.hpp"
#include "cell_system/CellStructureType.hpp"
#include "errorhandling.hpp"
#include "event.hpp"
-#include "grid.hpp"
#include "specfunc.hpp"
+#include "system/System.hpp"
#include "tuning.hpp"
#include
@@ -56,6 +58,7 @@
#endif
static double far_error(int P, double minrad) {
+ auto const &box_geo = *System::get_system().box_geo;
auto const wavenumber = 2. * Utils::pi() * box_geo.length_inv()[2];
// this uses an upper bound to all force components and the potential
auto const rhores = wavenumber * minrad;
@@ -67,6 +70,7 @@ static double far_error(int P, double minrad) {
static double determine_minrad(double maxPWerror, int P) {
// bisection to search for where the error is maxPWerror
auto constexpr min_rad = 0.01;
+ auto const &box_geo = *System::get_system().box_geo;
auto const rgranularity = min_rad * box_geo.length()[2];
auto rmin = rgranularity;
auto rmax = std::min(box_geo.length()[0], box_geo.length()[1]);
@@ -138,12 +142,14 @@ CoulombMMM1D::CoulombMMM1D(double prefactor, double maxPWerror,
}
void CoulombMMM1D::sanity_checks_periodicity() const {
+ auto const &box_geo = *System::get_system().box_geo;
if (box_geo.periodic(0) || box_geo.periodic(1) || !box_geo.periodic(2)) {
throw std::runtime_error("MMM1D requires periodicity (False, False, True)");
}
}
void CoulombMMM1D::sanity_checks_cell_structure() const {
+ auto const &local_geo = *System::get_system().local_geo;
if (local_geo.cell_structure_type() !=
CellStructureType::CELL_STRUCTURE_NSQUARE) {
throw std::runtime_error("MMM1D requires the N-square cellsystem");
@@ -151,6 +157,8 @@ void CoulombMMM1D::sanity_checks_cell_structure() const {
}
void CoulombMMM1D::recalc_boxl_parameters() {
+ auto const &box_geo = *System::get_system().box_geo;
+
if (far_switch_radius_sq >= Utils::sqr(box_geo.length()[2]))
far_switch_radius_sq = 0.8 * Utils::sqr(box_geo.length()[2]);
@@ -165,6 +173,7 @@ void CoulombMMM1D::recalc_boxl_parameters() {
Utils::Vector3d CoulombMMM1D::pair_force(double q1q2, Utils::Vector3d const &d,
double dist) const {
auto constexpr c_2pi = 2. * Utils::pi();
+ auto const &box_geo = *System::get_system().box_geo;
auto const n_modPsi = static_cast(modPsi.size()) >> 1;
auto const rxy2 = d[0] * d[0] + d[1] * d[1];
auto const rxy2_d = rxy2 * uz2;
@@ -258,6 +267,7 @@ double CoulombMMM1D::pair_energy(double const q1q2, Utils::Vector3d const &d,
return 0.;
auto constexpr c_2pi = 2. * Utils::pi();
+ auto const &box_geo = *System::get_system().box_geo;
auto const n_modPsi = static_cast(modPsi.size()) >> 1;
auto const rxy2 = d[0] * d[0] + d[1] * d[1];
auto const rxy2_d = rxy2 * uz2;
@@ -321,6 +331,7 @@ void CoulombMMM1D::tune() {
recalc_boxl_parameters();
if (far_switch_radius_sq < 0.) {
+ auto const &box_geo = *System::get_system().box_geo;
auto const maxrad = box_geo.length()[2];
auto min_time = std::numeric_limits::infinity();
auto min_rad = -1.;
diff --git a/src/core/electrostatics/mmm1d_gpu.cpp b/src/core/electrostatics/mmm1d_gpu.cpp
index 9d73f35c67e..fbe58285653 100644
--- a/src/core/electrostatics/mmm1d_gpu.cpp
+++ b/src/core/electrostatics/mmm1d_gpu.cpp
@@ -23,10 +23,11 @@
#include "electrostatics/mmm1d_gpu.hpp"
+#include "BoxGeometry.hpp"
+#include "LocalBox.hpp"
#include "cell_system/CellStructureType.hpp"
#include "communication.hpp"
#include "event.hpp"
-#include "grid.hpp"
#include "system/GpuParticleData.hpp"
#include "system/System.hpp"
@@ -38,6 +39,7 @@ CoulombMMM1DGpu::CoulombMMM1DGpu(double prefactor, double maxPWerror,
far_switch_radius_sq{-1.}, bessel_cutoff{bessel_cutoff}, m_is_tuned{
false} {
set_prefactor(prefactor);
+ auto const &box_geo = *System::get_system().box_geo;
if (maxPWerror <= 0.) {
throw std::domain_error("Parameter 'maxPWerror' must be > 0");
}
@@ -62,12 +64,14 @@ CoulombMMM1DGpu::CoulombMMM1DGpu(double prefactor, double maxPWerror,
}
void CoulombMMM1DGpu::sanity_checks_periodicity() const {
+ auto const &box_geo = *System::get_system().box_geo;
if (box_geo.periodic(0) || box_geo.periodic(1) || !box_geo.periodic(2)) {
throw std::runtime_error("MMM1D requires periodicity (False, False, True)");
}
}
void CoulombMMM1DGpu::sanity_checks_cell_structure() const {
+ auto const &local_geo = *System::get_system().local_geo;
if (local_geo.cell_structure_type() !=
CellStructureType::CELL_STRUCTURE_NSQUARE) {
throw std::runtime_error("MMM1D requires the N-square cellsystem");
diff --git a/src/core/electrostatics/p3m.cpp b/src/core/electrostatics/p3m.cpp
index 244faa27f8d..a5b01443c4f 100644
--- a/src/core/electrostatics/p3m.cpp
+++ b/src/core/electrostatics/p3m.cpp
@@ -38,15 +38,16 @@
#include "p3m/fft.hpp"
#include "p3m/influence_function.hpp"
+#include "BoxGeometry.hpp"
+#include "LocalBox.hpp"
#include "Particle.hpp"
#include "ParticleRange.hpp"
#include "actor/visitors.hpp"
+#include "cell_system/CellStructure.hpp"
#include "cell_system/CellStructureType.hpp"
-#include "cells.hpp"
#include "communication.hpp"
#include "errorhandling.hpp"
#include "event.hpp"
-#include "grid.hpp"
#include "integrate.hpp"
#include "system/System.hpp"
#include "tuning.hpp"
@@ -77,6 +78,7 @@
#include
void CoulombP3M::count_charged_particles() {
+ auto &cell_structure = *System::get_system().cell_structure;
auto local_n = 0;
auto local_q2 = 0.0;
auto local_q = 0.0;
@@ -106,6 +108,7 @@ void CoulombP3M::count_charged_particles() {
* @cite deserno98a @cite deserno98b.
*/
void CoulombP3M::calc_influence_function_force() {
+ auto const &box_geo = *System::get_system().box_geo;
auto const start = Utils::Vector3i{p3m.fft.plan[3].start};
auto const size = Utils::Vector3i{p3m.fft.plan[3].new_mesh};
@@ -117,6 +120,7 @@ void CoulombP3M::calc_influence_function_force() {
* self energy correction.
*/
void CoulombP3M::calc_influence_function_energy() {
+ auto const &box_geo = *System::get_system().box_geo;
auto const start = Utils::Vector3i{p3m.fft.plan[3].start};
auto const size = Utils::Vector3i{p3m.fft.plan[3].new_mesh};
@@ -169,6 +173,7 @@ static void p3m_tune_aliasing_sums(int nx, int ny, int nz,
*/
static double p3m_real_space_error(double pref, double r_cut_iL, int n_c_part,
double sum_q2, double alpha_L) {
+ auto const &box_geo = *System::get_system().box_geo;
return (2. * pref * sum_q2 * exp(-Utils::sqr(r_cut_iL * alpha_L))) /
sqrt(static_cast(n_c_part) * r_cut_iL * box_geo.length()[0] *
box_geo.volume());
@@ -189,6 +194,7 @@ static double p3m_real_space_error(double pref, double r_cut_iL, int n_c_part,
static double p3m_k_space_error(double pref, Utils::Vector3i const &mesh,
int cao, int n_c_part, double sum_q2,
double alpha_L) {
+ auto const &box_geo = *System::get_system().box_geo;
auto const mesh_i =
Utils::hadamard_division(Utils::Vector3d::broadcast(1.), mesh);
auto const alpha_L_i = 1. / alpha_L;
@@ -225,6 +231,7 @@ static double p3m_k_space_error(double pref, Utils::Vector3i const &mesh,
static double p3mgpu_k_space_error(double prefactor,
Utils::Vector3i const &mesh, int cao,
int npart, double sum_q2, double alpha_L) {
+ auto const &box_geo = *System::get_system().box_geo;
auto ks_err = 0.;
if (this_node == 0) {
ks_err = p3m_k_space_error_gpu(prefactor, mesh.data(), cao, npart, sum_q2,
@@ -240,12 +247,16 @@ void CoulombP3M::init() {
assert(p3m.params.cao >= 1 and p3m.params.cao <= 7);
assert(p3m.params.alpha > 0.);
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto const &local_geo = *system.local_geo;
+
p3m.params.cao3 = Utils::int_pow<3>(p3m.params.cao);
p3m.params.recalc_a_ai_cao_cut(box_geo.length());
sanity_checks();
- auto const &solver = System::get_system().coulomb.impl->solver;
+ auto const &solver = system.coulomb.impl->solver;
double elc_layer = 0.;
if (auto actor = get_actor_by_type(solver)) {
elc_layer = actor->elc.space_layer;
@@ -254,9 +265,9 @@ void CoulombP3M::init() {
p3m.local_mesh.calc_local_ca_mesh(p3m.params, local_geo, skin, elc_layer);
p3m.sm.resize(comm_cart, p3m.local_mesh);
- int ca_mesh_size =
- fft_init(p3m.local_mesh.dim, p3m.local_mesh.margin, p3m.params.mesh,
- p3m.params.mesh_off, p3m.ks_pnum, p3m.fft, node_grid, comm_cart);
+ int ca_mesh_size = fft_init(p3m.local_mesh.dim, p3m.local_mesh.margin,
+ p3m.params.mesh, p3m.params.mesh_off, p3m.ks_pnum,
+ p3m.fft, ::communicator.node_grid, comm_cart);
p3m.rs_mesh.resize(ca_mesh_size);
for (auto &e : p3m.E_mesh) {
@@ -342,7 +353,6 @@ void CoulombP3M::assign_charge(double q, Utils::Vector3d const &real_pos) {
real_pos);
}
-namespace {
template struct AssignForces {
void operator()(p3m_data_struct &p3m, double force_prefac,
ParticleRange const &particles) const {
@@ -373,21 +383,17 @@ template struct AssignForces {
}
};
-auto dipole_moment(Particle const &p, BoxGeometry const &box) {
- return p.q() * unfolded_position(p.pos(), p.image_box(), box.length());
-}
-
-auto calc_dipole_moment(boost::mpi::communicator const &comm,
- ParticleRange const &particles,
- BoxGeometry const &box) {
+static auto calc_dipole_moment(boost::mpi::communicator const &comm,
+ ParticleRange const &particles,
+ BoxGeometry const &box_geo) {
auto const local_dip = boost::accumulate(
- particles, Utils::Vector3d{}, [&box](Utils::Vector3d dip, auto const &p) {
- return dip + dipole_moment(p, box);
+ particles, Utils::Vector3d{},
+ [&box_geo](Utils::Vector3d const &dip, auto const &p) {
+ return dip + p.q() * box_geo.unfolded_position(p.pos(), p.image_box());
});
return boost::mpi::all_reduce(comm, local_dip, std::plus<>());
}
-} // namespace
/** @details Calculate the long range electrostatics part of the pressure
* tensor. This is part \f$\Pi_{\textrm{dir}, \alpha, \beta}\f$ eq. (2.6)
@@ -397,6 +403,8 @@ auto calc_dipole_moment(boost::mpi::communicator const &comm,
Utils::Vector9d CoulombP3M::p3m_calc_kspace_pressure_tensor() {
using namespace detail::FFT_indexing;
+ auto const &box_geo = *System::get_system().box_geo;
+
Utils::Vector9d node_k_space_pressure_tensor{};
if (p3m.sum_q2 > 0.) {
@@ -452,6 +460,8 @@ Utils::Vector9d CoulombP3M::p3m_calc_kspace_pressure_tensor() {
double CoulombP3M::long_range_kernel(bool force_flag, bool energy_flag,
ParticleRange const &particles) {
+ auto const &box_geo = *System::get_system().box_geo;
+
/* Gather information for FFT grid inside the nodes domain (inner local mesh)
* and perform forward 3D FFT (Charge Assignment Mesh). */
p3m.sm.gather_grid(p3m.rs_mesh.data(), comm_cart, p3m.local_mesh.dim);
@@ -567,8 +577,10 @@ class CoulombTuningAlgorithm : public TuningAlgorithm {
void on_solver_change() const override { on_coulomb_change(); }
void setup_logger(bool verbose) override {
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
#ifdef CUDA
- auto const &solver = System::get_system().coulomb.impl->solver;
+ auto const &solver = system.coulomb.impl->solver;
auto const on_gpu = has_actor_of_type(solver);
#else
auto const on_gpu = false;
@@ -628,6 +640,7 @@ class CoulombTuningAlgorithm : public TuningAlgorithm {
}
void determine_mesh_limits() override {
+ auto const &box_geo = *System::get_system().box_geo;
auto const mesh_density =
static_cast(p3m.params.mesh[0]) * box_geo.length_inv()[0];
@@ -660,10 +673,12 @@ class CoulombTuningAlgorithm : public TuningAlgorithm {
}
TuningAlgorithm::Parameters get_time() override {
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto const &solver = system.coulomb.impl->solver;
auto tuned_params = TuningAlgorithm::Parameters{};
auto time_best = time_sentinel;
auto mesh_density = m_mesh_density_min;
- auto const &solver = System::get_system().coulomb.impl->solver;
while (mesh_density <= m_mesh_density_max) {
auto trial_params = TuningAlgorithm::Parameters{};
if (m_tune_mesh) {
@@ -707,6 +722,7 @@ class CoulombTuningAlgorithm : public TuningAlgorithm {
};
void CoulombP3M::tune() {
+ auto const &box_geo = *System::get_system().box_geo;
if (p3m.params.alpha_L == 0. and p3m.params.alpha != 0.) {
p3m.params.alpha_L = p3m.params.alpha * box_geo.length()[0];
}
@@ -739,7 +755,10 @@ void CoulombP3M::tune() {
}
void CoulombP3M::sanity_checks_boxl() const {
- for (unsigned int i = 0; i < 3; i++) {
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto const &local_geo = *system.local_geo;
+ for (unsigned int i = 0u; i < 3u; i++) {
/* check k-space cutoff */
if (p3m.params.cao_cut[i] >= box_geo.length_half()[i]) {
std::stringstream msg;
@@ -767,6 +786,7 @@ void CoulombP3M::sanity_checks_boxl() const {
}
void CoulombP3M::sanity_checks_periodicity() const {
+ auto const &box_geo = *System::get_system().box_geo;
if (!box_geo.periodic(0) || !box_geo.periodic(1) || !box_geo.periodic(2)) {
throw std::runtime_error(
"CoulombP3M: requires periodicity (True, True, True)");
@@ -774,6 +794,7 @@ void CoulombP3M::sanity_checks_periodicity() const {
}
void CoulombP3M::sanity_checks_cell_structure() const {
+ auto const &local_geo = *System::get_system().local_geo;
if (local_geo.cell_structure_type() !=
CellStructureType::CELL_STRUCTURE_REGULAR &&
local_geo.cell_structure_type() !=
@@ -781,8 +802,8 @@ void CoulombP3M::sanity_checks_cell_structure() const {
throw std::runtime_error(
"CoulombP3M: requires the regular or hybrid decomposition cell system");
}
- if (n_nodes > 1 && local_geo.cell_structure_type() ==
- CellStructureType::CELL_STRUCTURE_HYBRID) {
+ if (::communicator.size > 1 && local_geo.cell_structure_type() ==
+ CellStructureType::CELL_STRUCTURE_HYBRID) {
throw std::runtime_error(
"CoulombP3M: does not work with the hybrid decomposition cell system, "
"if using more than one MPI node");
@@ -790,6 +811,7 @@ void CoulombP3M::sanity_checks_cell_structure() const {
}
void CoulombP3M::sanity_checks_node_grid() const {
+ auto const &node_grid = ::communicator.node_grid;
if (node_grid[0] < node_grid[1] || node_grid[1] < node_grid[2]) {
throw std::runtime_error(
"CoulombP3M: node grid must be sorted, largest first");
@@ -797,6 +819,7 @@ void CoulombP3M::sanity_checks_node_grid() const {
}
void CoulombP3M::scaleby_box_l() {
+ auto const &box_geo = *System::get_system().box_geo;
p3m.params.r_cut = p3m.params.r_cut_iL * box_geo.length()[0];
p3m.params.alpha = p3m.params.alpha_L * box_geo.length_inv()[0];
p3m.params.recalc_a_ai_cao_cut(box_geo.length());
diff --git a/src/core/electrostatics/scafacos_impl.cpp b/src/core/electrostatics/scafacos_impl.cpp
index 365eaeeb2a0..1a0895fa8fc 100644
--- a/src/core/electrostatics/scafacos_impl.cpp
+++ b/src/core/electrostatics/scafacos_impl.cpp
@@ -26,11 +26,13 @@
#include "electrostatics/scafacos.hpp"
#include "electrostatics/scafacos_impl.hpp"
-#include "cells.hpp"
+#include "BoxGeometry.hpp"
+#include "LocalBox.hpp"
+#include "cell_system/CellStructure.hpp"
#include "communication.hpp"
#include "event.hpp"
-#include "grid.hpp"
#include "integrate.hpp"
+#include "system/System.hpp"
#include "tuning.hpp"
#include
@@ -51,11 +53,15 @@ make_coulomb_scafacos(std::string const &method,
}
void CoulombScafacosImpl::update_particle_data() {
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto &cell_structure = *system.cell_structure;
+
positions.clear();
charges.clear();
for (auto const &p : cell_structure.local_particles()) {
- auto const pos = folded_position(p.pos(), box_geo);
+ auto const pos = box_geo.folded_position(p.pos());
positions.push_back(pos[0]);
positions.push_back(pos[1]);
positions.push_back(pos[2]);
@@ -67,6 +73,8 @@ void CoulombScafacosImpl::update_particle_forces() const {
if (positions.empty())
return;
+ auto &cell_structure = *System::get_system().cell_structure;
+
auto it_fields = fields.begin();
for (auto &p : cell_structure.local_particles()) {
p.force() += prefactor * p.q() *
@@ -85,6 +93,9 @@ double CoulombScafacosImpl::time_r_cut(double r_cut) {
void CoulombScafacosImpl::tune_r_cut() {
auto constexpr convergence_threshold = 1e-3;
+ auto const &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto const &local_geo = *system.local_geo;
auto const min_box_l = *boost::min_element(box_geo.length());
auto const min_local_box_l = *boost::min_element(local_geo.length());
diff --git a/src/core/energy.cpp b/src/core/energy.cpp
index 8b1645e2108..b91fcfa7645 100644
--- a/src/core/energy.cpp
+++ b/src/core/energy.cpp
@@ -22,7 +22,9 @@
* Energy calculation.
*/
+#include "BoxGeometry.hpp"
#include "Observable_stat.hpp"
+#include "cells.hpp"
#include "communication.hpp"
#include "constraints.hpp"
#include "energy_inline.hpp"
@@ -49,30 +51,33 @@ std::shared_ptr calculate_energy() {
return obs_energy_ptr;
}
+ auto &system = System::get_system();
+ auto &cell_structure = *system.cell_structure;
auto &obs_energy = *obs_energy_ptr;
#if defined(CUDA) and (defined(ELECTROSTATICS) or defined(DIPOLES))
- auto &gpu_particle_data = System::get_system().gpu;
+ auto &gpu_particle_data = system.gpu;
gpu_particle_data.clear_energy_on_device();
gpu_particle_data.update();
#endif
on_observable_calc();
+ auto const &box_geo = *system.box_geo;
auto const local_parts = cell_structure.local_particles();
+ auto const n_nodes = ::communicator.size;
for (auto const &p : local_parts) {
obs_energy.kinetic[0] += calc_kinetic_energy(p);
}
- auto const &system = System::get_system();
auto const coulomb_kernel = system.coulomb.pair_energy_kernel();
auto const dipoles_kernel = system.dipoles.pair_energy_kernel();
short_range_loop(
- [&obs_energy, coulomb_kernel_ptr = get_ptr(coulomb_kernel)](
+ [&obs_energy, coulomb_kernel_ptr = get_ptr(coulomb_kernel), &box_geo](
Particle const &p1, int bond_id, Utils::Span partners) {
auto const &iaparams = *bonded_ia_params.at(bond_id);
- auto const result =
- calc_bonded_energy(iaparams, p1, partners, coulomb_kernel_ptr);
+ auto const result = calc_bonded_energy(iaparams, p1, partners, box_geo,
+ coulomb_kernel_ptr);
if (result) {
obs_energy.bonded_contribution(bond_id)[0] += result.get();
return false;
@@ -86,7 +91,7 @@ std::shared_ptr calculate_energy() {
coulomb_kernel_ptr, dipoles_kernel_ptr,
obs_energy);
},
- maximal_cutoff(n_nodes), maximal_cutoff_bonded());
+ cell_structure, maximal_cutoff(n_nodes), maximal_cutoff_bonded());
#ifdef ELECTROSTATICS
/* calculate k-space part of electrostatic interaction. */
@@ -98,7 +103,8 @@ std::shared_ptr calculate_energy() {
obs_energy.dipolar[1] = system.dipoles.calc_energy_long_range(local_parts);
#endif
- Constraints::constraints.add_energy(local_parts, get_sim_time(), obs_energy);
+ Constraints::constraints.add_energy(box_geo, local_parts, get_sim_time(),
+ obs_energy);
#if defined(CUDA) and (defined(ELECTROSTATICS) or defined(DIPOLES))
auto const energy_host = gpu_particle_data.copy_energy_to_host();
@@ -114,6 +120,8 @@ std::shared_ptr calculate_energy() {
}
double particle_short_range_energy_contribution(int pid) {
+ auto const &system = System::get_system();
+ auto &cell_structure = *system.cell_structure;
double ret = 0.0;
if (cell_structure.get_resort_particles()) {
@@ -121,7 +129,7 @@ double particle_short_range_energy_contribution(int pid) {
}
if (auto const p = cell_structure.get_local_particle(pid)) {
- auto const &coulomb = System::get_system().coulomb;
+ auto const &coulomb = system.coulomb;
auto const coulomb_kernel = coulomb.pair_energy_kernel();
auto kernel = [&ret, coulomb_kernel_ptr = get_ptr(coulomb_kernel)](
Particle const &p, Particle const &p1,
@@ -142,8 +150,10 @@ double particle_short_range_energy_contribution(int pid) {
#ifdef DIPOLE_FIELD_TRACKING
void calc_long_range_fields() {
+ auto const &system = System::get_system();
+ auto const &dipoles = system.dipoles;
+ auto &cell_structure = *system.cell_structure;
auto particles = cell_structure.local_particles();
- auto const &dipoles = System::get_system().dipoles;
dipoles.calc_long_range_field(particles);
}
#endif
diff --git a/src/core/energy_inline.hpp b/src/core/energy_inline.hpp
index f4c09b93a7e..40cbe84dbc1 100644
--- a/src/core/energy_inline.hpp
+++ b/src/core/energy_inline.hpp
@@ -49,6 +49,7 @@
#include "nonbonded_interactions/thole.hpp"
#include "nonbonded_interactions/wca.hpp"
+#include "BoxGeometry.hpp"
#include "Observable_stat.hpp"
#include "Particle.hpp"
#include "bond_error.hpp"
@@ -202,7 +203,7 @@ inline void add_non_bonded_pair_energy(
inline boost::optional
calc_bonded_energy(Bonded_IA_Parameters const &iaparams, Particle const &p1,
- Utils::Span partners,
+ Utils::Span partners, BoxGeometry const &box_geo,
Coulomb::ShortRangeEnergyKernel::kernel_type const *kernel) {
auto const n_partners = static_cast(partners.size());
@@ -245,17 +246,19 @@ calc_bonded_energy(Bonded_IA_Parameters const &iaparams, Particle const &p1,
throw BondUnknownTypeError();
} // 1 partner
if (n_partners == 2) {
+ auto const vec1 = box_geo.get_mi_vector(p2->pos(), p1.pos());
+ auto const vec2 = box_geo.get_mi_vector(p3->pos(), p1.pos());
if (auto const *iap = boost::get(&iaparams)) {
- return iap->energy(p1.pos(), p2->pos(), p3->pos());
+ return iap->energy(vec1, vec2);
}
if (auto const *iap = boost::get(&iaparams)) {
- return iap->energy(p1.pos(), p2->pos(), p3->pos());
+ return iap->energy(vec1, vec2);
}
if (auto const *iap = boost::get(&iaparams)) {
- return iap->energy(p1.pos(), p2->pos(), p3->pos());
+ return iap->energy(vec1, vec2);
}
if (auto const *iap = boost::get(&iaparams)) {
- return iap->energy(p1.pos(), p2->pos(), p3->pos());
+ return iap->energy(vec1, vec2);
}
if (boost::get(&iaparams)) {
runtimeWarningMsg() << "Unsupported bond type " +
@@ -266,11 +269,15 @@ calc_bonded_energy(Bonded_IA_Parameters const &iaparams, Particle const &p1,
throw BondUnknownTypeError();
} // 2 partners
if (n_partners == 3) {
+ // note: particles in a dihedral bond are ordered as p2-p1-p3-p4
+ auto const v12 = box_geo.get_mi_vector(p1.pos(), p2->pos());
+ auto const v23 = box_geo.get_mi_vector(p3->pos(), p1.pos());
+ auto const v34 = box_geo.get_mi_vector(p4->pos(), p3->pos());
if (auto const *iap = boost::get(&iaparams)) {
- return iap->energy(p2->pos(), p1.pos(), p3->pos(), p4->pos());
+ return iap->energy(v12, v23, v34);
}
if (auto const *iap = boost::get(&iaparams)) {
- return iap->energy(p2->pos(), p1.pos(), p3->pos(), p4->pos());
+ return iap->energy(v12, v23, v34);
}
if (boost::get(&iaparams)) {
runtimeWarningMsg() << "Unsupported bond type " +
diff --git a/src/core/event.cpp b/src/core/event.cpp
index b78142796ac..7fa4acaf646 100644
--- a/src/core/event.cpp
+++ b/src/core/event.cpp
@@ -25,6 +25,8 @@
*/
#include "event.hpp"
+#include "BoxGeometry.hpp"
+#include "LocalBox.hpp"
#include "bonded_interactions/thermalized_bond.hpp"
#include "cell_system/CellStructureType.hpp"
#include "cells.hpp"
@@ -37,7 +39,6 @@
#include "electrostatics/coulomb.hpp"
#include "electrostatics/icc.hpp"
#include "errorhandling.hpp"
-#include "grid.hpp"
#include "immersed_boundaries.hpp"
#include "integrate.hpp"
#include "interactions.hpp"
@@ -68,11 +69,6 @@ void on_program_start() {
}
#endif
- init_node_grid();
-
- /* initially go for regular decomposition */
- cells_re_init(CellStructureType::CELL_STRUCTURE_REGULAR);
-
/* make sure interaction 0<->0 always exists */
make_particle_type_exist(0);
}
@@ -103,13 +99,14 @@ void on_integration_start(double time_step) {
}
#ifdef NPT
- npt_ensemble_init(box_geo);
+ npt_ensemble_init(*system.box_geo);
#endif
partCfg().invalidate();
invalidate_fetch_cache();
#ifdef ADDITIONAL_CHECKS
+ auto &cell_structure = *system.cell_structure;
if (!Utils::Mpi::all_compare(comm_cart, cell_structure.use_verlet_list)) {
runtimeErrorMsg() << "Nodes disagree about use of verlet lists.";
}
@@ -167,6 +164,9 @@ void on_particle_local_change() {
}
void on_particle_change() {
+ auto &system = System::get_system();
+ auto &cell_structure = *system.cell_structure;
+
if (cell_structure.decomposition_type() ==
CellStructureType::CELL_STRUCTURE_HYBRID) {
cell_structure.set_resort_particles(Cells::RESORT_GLOBAL);
@@ -174,14 +174,10 @@ void on_particle_change() {
cell_structure.set_resort_particles(Cells::RESORT_LOCAL);
}
#ifdef ELECTROSTATICS
- if (System::is_system_set()) {
- System::get_system().coulomb.on_particle_change();
- }
+ system.coulomb.on_particle_change();
#endif
#ifdef DIPOLES
- if (System::is_system_set()) {
- System::get_system().dipoles.on_particle_change();
- }
+ system.dipoles.on_particle_change();
#endif
recalc_forces = true;
@@ -222,7 +218,8 @@ void on_non_bonded_ia_change() {
}
void on_short_range_ia_change() {
- cells_re_init(cell_structure.decomposition_type());
+ auto const &system = System::get_system();
+ cells_re_init(*system.cell_structure);
recalc_forces = true;
}
@@ -230,15 +227,19 @@ void on_constraint_change() { recalc_forces = true; }
void on_lb_boundary_conditions_change() { recalc_forces = true; }
+static void update_local_geo(System::System &system) {
+ *system.local_geo = LocalBox::make_regular_decomposition(
+ system.box_geo->length(), ::communicator.calc_node_index(),
+ ::communicator.node_grid);
+}
+
void on_boxl_change(bool skip_method_adaption) {
- grid_changed_box_l(box_geo);
- /* Electrostatics cutoffs mostly depend on the system size,
- * therefore recalculate them. */
- cells_re_init(cell_structure.decomposition_type());
+ auto &system = System::get_system();
+ update_local_geo(system);
+ cells_re_init(*system.cell_structure);
/* Now give methods a chance to react to the change in box length */
if (not skip_method_adaption) {
- auto &system = System::get_system();
system.lb.on_boxl_change();
system.ek.on_boxl_change();
#ifdef ELECTROSTATICS
@@ -288,6 +289,7 @@ void on_periodicity_change() {
#ifdef STOKESIAN_DYNAMICS
if (integ_switch == INTEG_METHOD_SD) {
+ auto const &box_geo = *System::get_system().box_geo;
if (box_geo.periodic(0) || box_geo.periodic(1) || box_geo.periodic(2))
runtimeErrorMsg() << "Stokesian Dynamics requires periodicity "
<< "(False, False, False)\n";
@@ -297,7 +299,8 @@ void on_periodicity_change() {
}
void on_skin_change() {
- cells_re_init(cell_structure.decomposition_type());
+ auto const &system = System::get_system();
+ cells_re_init(*system.cell_structure);
on_coulomb_and_dipoles_change();
}
@@ -313,8 +316,9 @@ void on_timestep_change() {
void on_forcecap_change() { recalc_forces = true; }
void on_node_grid_change() {
- grid_changed_n_nodes();
auto &system = System::get_system();
+ auto &cell_structure = *system.cell_structure;
+ update_local_geo(system);
system.lb.on_node_grid_change();
system.ek.on_node_grid_change();
#ifdef ELECTROSTATICS
@@ -323,7 +327,7 @@ void on_node_grid_change() {
#ifdef DIPOLES
system.dipoles.on_node_grid_change();
#endif
- cells_re_init(cell_structure.decomposition_type());
+ cells_re_init(cell_structure);
}
/**
@@ -356,6 +360,8 @@ unsigned global_ghost_flags() {
}
void update_dependent_particles() {
+ auto &system = System::get_system();
+ auto &cell_structure = *system.cell_structure;
#ifdef VIRTUAL_SITES
virtual_sites()->update();
cells_update_ghosts(global_ghost_flags());
diff --git a/src/core/forces.cpp b/src/core/forces.cpp
index b83b55b4dc0..fa6a783ec13 100644
--- a/src/core/forces.cpp
+++ b/src/core/forces.cpp
@@ -24,6 +24,7 @@
* The corresponding header file is forces.hpp.
*/
+#include "BoxGeometry.hpp"
#include "bond_breakage/bond_breakage.hpp"
#include "cell_system/CellStructure.hpp"
#include "cells.hpp"
@@ -152,12 +153,14 @@ void force_calc(CellStructure &cell_structure, double time_step, double kT) {
CALI_CXX_MARK_FUNCTION;
#endif
- auto &espresso_system = System::get_system();
+ auto &system = System::get_system();
+ auto const &box_geo = *system.box_geo;
+ auto const n_nodes = ::communicator.size;
#ifdef CUDA
#ifdef CALIPER
CALI_MARK_BEGIN("copy_particles_to_GPU");
#endif
- espresso_system.gpu.update();
+ system.gpu.update();
#ifdef CALIPER
CALI_MARK_END("copy_particles_to_GPU");
#endif
@@ -170,9 +173,9 @@ void force_calc(CellStructure &cell_structure, double time_step, double kT) {
auto particles = cell_structure.local_particles();
auto ghost_particles = cell_structure.ghost_particles();
#ifdef ELECTROSTATICS
- if (espresso_system.coulomb.impl->extension) {
+ if (system.coulomb.impl->extension) {
if (auto icc = std::get_if>(
- get_ptr(espresso_system.coulomb.impl->extension))) {
+ get_ptr(system.coulomb.impl->extension))) {
(**icc).iteration(cell_structure, particles, ghost_particles);
}
}
@@ -181,26 +184,27 @@ void force_calc(CellStructure &cell_structure, double time_step, double kT) {
calc_long_range_forces(particles);
- auto const elc_kernel = espresso_system.coulomb.pair_force_elc_kernel();
- auto const coulomb_kernel = espresso_system.coulomb.pair_force_kernel();
- auto const dipoles_kernel = espresso_system.dipoles.pair_force_kernel();
+ auto const elc_kernel = system.coulomb.pair_force_elc_kernel();
+ auto const coulomb_kernel = system.coulomb.pair_force_kernel();
+ auto const dipoles_kernel = system.dipoles.pair_force_kernel();
#ifdef ELECTROSTATICS
- auto const coulomb_cutoff = espresso_system.coulomb.cutoff();
+ auto const coulomb_cutoff = system.coulomb.cutoff();
#else
auto const coulomb_cutoff = INACTIVE_CUTOFF;
#endif
#ifdef DIPOLES
- auto const dipole_cutoff = espresso_system.dipoles.cutoff();
+ auto const dipole_cutoff = system.dipoles.cutoff();
#else
auto const dipole_cutoff = INACTIVE_CUTOFF;
#endif
short_range_loop(
- [coulomb_kernel_ptr = get_ptr(coulomb_kernel)](
- Particle &p1, int bond_id, Utils::Span partners) {
- return add_bonded_force(p1, bond_id, partners, coulomb_kernel_ptr);
+ [coulomb_kernel_ptr = get_ptr(coulomb_kernel),
+ &box_geo](Particle &p1, int bond_id, Utils::Span partners) {
+ return add_bonded_force(p1, bond_id, partners, box_geo,
+ coulomb_kernel_ptr);
},
[coulomb_kernel_ptr = get_ptr(coulomb_kernel),
dipoles_kernel_ptr = get_ptr(dipoles_kernel),
@@ -214,31 +218,32 @@ void force_calc(CellStructure &cell_structure, double time_step, double kT) {
detect_collision(p1, p2, d.dist2);
#endif
},
- maximal_cutoff(n_nodes), maximal_cutoff_bonded(),
+ cell_structure, maximal_cutoff(n_nodes), maximal_cutoff_bonded(),
VerletCriterion<>{skin, interaction_range(), coulomb_cutoff,
dipole_cutoff, collision_detection_cutoff()});
- Constraints::constraints.add_forces(particles, get_sim_time());
+ Constraints::constraints.add_forces(box_geo, particles, get_sim_time());
if (max_oif_objects) {
// There are two global quantities that need to be evaluated:
// object's surface and object's volume.
for (int i = 0; i < max_oif_objects; i++) {
auto const area_volume = boost::mpi::all_reduce(
- comm_cart, calc_oif_global(i, cell_structure), std::plus<>());
+ comm_cart, calc_oif_global(i, box_geo, cell_structure),
+ std::plus<>());
auto const oif_part_area = std::abs(area_volume[0]);
auto const oif_part_vol = std::abs(area_volume[1]);
if (oif_part_area < 1e-100 and oif_part_vol < 1e-100) {
break;
}
- add_oif_global_forces(area_volume, i, cell_structure);
+ add_oif_global_forces(area_volume, i, box_geo, cell_structure);
}
}
// Must be done here. Forces need to be ghost-communicated
immersed_boundaries.volume_conservation(cell_structure);
- if (System::get_system().lb.is_solver_set()) {
+ if (system.lb.is_solver_set()) {
LB::couple_particles(thermo_virtual, particles, ghost_particles, time_step);
}
@@ -246,7 +251,7 @@ void force_calc(CellStructure &cell_structure, double time_step, double kT) {
#ifdef CALIPER
CALI_MARK_BEGIN("copy_forces_from_GPU");
#endif
- espresso_system.gpu.copy_forces_to_host(particles, this_node);
+ system.gpu.copy_forces_to_host(particles, this_node);
#ifdef CALIPER
CALI_MARK_END("copy_forces_from_GPU");
#endif
diff --git a/src/core/forces_inline.hpp b/src/core/forces_inline.hpp
index e18a18c7868..2d21f2483be 100644
--- a/src/core/forces_inline.hpp
+++ b/src/core/forces_inline.hpp
@@ -28,6 +28,7 @@
#include "forces.hpp"
+#include "BoxGeometry.hpp"
#include "actor/visitors.hpp"
#include "bond_breakage/bond_breakage.hpp"
#include "bonded_interactions/bonded_interaction_data.hpp"
@@ -324,6 +325,7 @@ inline boost::optional calc_bond_pair_force(
inline bool add_bonded_two_body_force(
Bonded_IA_Parameters const &iaparams, Particle &p1, Particle &p2,
+ BoxGeometry const &box_geo,
Coulomb::ShortRangeForceKernel::kernel_type const *kernel) {
auto const dx = box_geo.get_mi_vector(p1.pos(), p2.pos());
@@ -355,35 +357,39 @@ inline bool add_bonded_two_body_force(
inline boost::optional<
std::tuple>
calc_bonded_three_body_force(Bonded_IA_Parameters const &iaparams,
- Particle const &p1, Particle const &p2,
- Particle const &p3) {
+ BoxGeometry const &box_geo, Particle const &p1,
+ Particle const &p2, Particle const &p3) {
+ auto const vec1 = box_geo.get_mi_vector(p2.pos(), p1.pos());
+ auto const vec2 = box_geo.get_mi_vector(p3.pos(), p1.pos());
if (auto const *iap = boost::get(&iaparams)) {
- return iap->forces(p1.pos(), p2.pos(), p3.pos());
+ return iap->forces(vec1, vec2);
}
if (auto const *iap = boost::get(&iaparams)) {
- return iap->forces(p1.pos(), p2.pos(), p3.pos());
+ return iap->forces(vec1, vec2);
}
if (auto const *iap = boost::get(&iaparams)) {
- return iap->forces(p1.pos(), p2.pos(), p3.pos());
+ return iap->forces(vec1, vec2);
}
#ifdef TABULATED
if (auto const *iap = boost::get(&iaparams)) {
- return iap->forces(p1.pos(), p2.pos(), p3.pos());
+ return iap->forces(vec1, vec2);
}
#endif
if (auto const *iap = boost::get | | |