ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
rattle.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2026 The ESPResSo project
3 * Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010
4 * Max-Planck-Institute for Polymer Research, Theory Group
5 *
6 * This file is part of ESPResSo.
7 *
8 * ESPResSo is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * ESPResSo is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#include "rattle.hpp"
23
24#ifdef ESPRESSO_BOND_CONSTRAINT
25
26#include "BoxGeometry.hpp"
27#include "Particle.hpp"
28#include "ParticleRange.hpp"
32#include "communication.hpp"
33#include "errorhandling.hpp"
34
35#include <utils/Vector.hpp>
37#include <utils/matrix.hpp>
38
39#include <boost/mpi/collectives/all_reduce.hpp>
40#include <boost/range/algorithm.hpp>
41
42#include <cmath>
43#include <cstddef>
44#include <functional>
45#include <span>
46#include <variant>
47#include <vector>
48
49/** Maximal number of iterations before the RATTLE algorithm bails out. */
50static constexpr auto shake_max_iterations = 1000;
51
52static void check_convergence(int cnt, char const *const name) {
53 static constexpr char const *const msg = " failed to converge after ";
55 runtimeErrorMsg() << name << msg << cnt << " iterations";
56 }
57}
58
59/**
60 * @brief copy current position
61 *
62 * @param particles particle range
63 * @param ghost_particles ghost particle range
64 */
65void save_old_position(const ParticleRange &particles,
66 const ParticleRange &ghost_particles) {
67 auto save_pos = [](Particle &p) { p.pos_last_time_step() = p.pos(); };
68
69 boost::for_each(particles, save_pos);
70 boost::for_each(ghost_particles, save_pos);
71}
72
73/**
74 * @brief reset correction vectors to zero
75 *
76 * @param particles particle range
77 * @param ghost_particles ghost particle range
78 */
79static void init_correction_vector(const ParticleRange &particles,
80 const ParticleRange &ghost_particles) {
81 auto reset_force = [](Particle &p) { p.rattle_params().correction.fill(0); };
82
83 boost::for_each(particles, reset_force);
84 boost::for_each(ghost_particles, reset_force);
85}
86
87/**
88 * @brief Calculate the positional correction for the particles.
89 *
90 * @param ia_params Parameters
91 * @param box_geo Box geometry.
92 * @param p1 First particle.
93 * @param p2 Second particle.
94 * @param bond_id Bonded interaction id of this specific bond.
95 * @param rigid_bond_virial Per-bond-type RATTLE constraint virial
96 * accumulator, indexed by @p bond_id.
97 * @return True if there was a correction.
98 */
100 RigidBond const &ia_params, BoxGeometry const &box_geo, Particle &p1,
101 Particle &p2, int bond_id,
102 std::vector<Utils::Vector9d> &rigid_bond_virial) {
103 auto const r_ij = box_geo.get_mi_vector(p1.pos(), p2.pos());
104 auto const r_ij2 = r_ij.norm2();
105
106 if (std::abs(1.0 - r_ij2 / ia_params.d2) > ia_params.p_tol) {
107 auto const r_ij_t =
108 box_geo.get_mi_vector(p1.pos_last_time_step(), p2.pos_last_time_step());
109 auto const r_ij_dot = r_ij_t * r_ij;
110 auto const G =
111 0.50 * (ia_params.d2 - r_ij2) / r_ij_dot / (p1.mass() + p2.mass());
112
113 auto const pos_corr = G * r_ij_t;
114 p1.rattle_params().correction += pos_corr * p2.mass();
115 p2.rattle_params().correction -= pos_corr * p1.mass();
116
117 // Constraint force implied by this bond alone during this iteration:
118 // the correction just applied to p1 is
119 // @f$ \Delta r1 = pos_corr*m2 = (1/2)*a1*dt^2 @f$,
120 // so @f$ F1 = m1*a1 = 2*m1*\Delta r1/dt^2 = 2*m1*m2*pos_corr/dt^2 @f$.
121 // Division by dt^2 is deferred to @ref System::calculate_pressure(),
122 // where the timestep is available. This uses r_ij_t, the bond vector
123 // at the start of the MD step (fixed across all SHAKE iterations of this
124 // step), so the contribution is exact for this bond alone, regardless of
125 // how many other rigid bonds p1 or p2 participate in.
126 rigid_bond_virial[static_cast<std::size_t>(bond_id)] += Utils::flatten(
127 Utils::tensor_product(2.0 * p1.mass() * p2.mass() * pos_corr, r_ij_t));
128
129 return true;
130 }
131
132 return false;
133}
134
135/**
136 * @brief Compute the correction vectors using given kernel.
137 *
138 * @param cs cell structure
139 * @param box_geo Box geometry
140 * @param bonded_ias Bonded interactions
141 * @param kernel kernel function
142 * @return True if correction is necessary
143 */
144template <typename Kernel>
146 BoxGeometry const &box_geo,
147 BondedInteractionsMap const &bonded_ias,
148 Kernel kernel) {
149 bool correction = false;
150 cs.bond_loop([&correction, &kernel, &box_geo, &bonded_ias](
151 Particle &p1, int bond_id, std::span<Particle *> partners) {
152 auto const &iaparams = *bonded_ias.at(bond_id);
153
154 if (auto const *bond = std::get_if<RigidBond>(&iaparams)) {
155 auto const corrected = kernel(*bond, box_geo, p1, *partners[0], bond_id);
156 if (corrected)
157 correction = true;
158 }
159
160 /* Rigid bonds cannot break */
161 return false;
162 });
163
164 return correction;
165}
166
167/**
168 * @brief Apply positional corrections
169 *
170 * @param particles particle range
171 */
172static void apply_positional_correction(const ParticleRange &particles) {
173 boost::for_each(particles, [](Particle &p) {
174 p.pos() += p.rattle_params().correction;
175 p.v() += p.rattle_params().correction;
176 });
177}
178
180 BondedInteractionsMap &bonded_ias) {
183
184 auto particles = cs.local_particles();
185 auto ghost_particles = cs.ghost_particles();
186
187 // Reset the per-bond-type constraint virial for this timestep
188 bonded_ias.rigid_bond_virial.assign(
189 static_cast<std::size_t>(bonded_ias.get_next_key()),
191
192 int cnt;
193 for (cnt = 0; cnt < shake_max_iterations; ++cnt) {
194 init_correction_vector(particles, ghost_particles);
196 cs, box_geo, bonded_ias,
197 [&bonded_ias](RigidBond const &bond, BoxGeometry const &box_geo_,
198 Particle &p1, Particle &p2, int bond_id) {
200 bond, box_geo_, p1, p2, bond_id, bonded_ias.rigid_bond_virial);
201 });
202 bool const repeat =
203 boost::mpi::all_reduce(comm_cart, repeat_, std::logical_or<bool>());
204
205 // no correction is necessary, skip communication and bail out
206 if (!repeat)
207 break;
208
210
213 }
214 check_convergence(cnt, "RATTLE");
215
216 auto const resort_level =
219}
220
221/**
222 * @brief Calculate the velocity correction for the particles.
223 *
224 * @param ia_params Parameters
225 * @param box_geo Box geometry.
226 * @param p1 First particle.
227 * @param p2 Second particle.
228 * @return True if there was a correction.
229 */
231 BoxGeometry const &box_geo,
232 Particle &p1, Particle &p2) {
233 auto const v_ij = p1.v() - p2.v();
234 auto const r_ij = box_geo.get_mi_vector(p1.pos(), p2.pos());
235
236 auto const v_proj = v_ij * r_ij;
237 if (std::abs(v_proj) > ia_params.v_tol) {
238 auto const K = v_proj / ia_params.d2 / (p1.mass() + p2.mass());
239
240 auto const vel_corr = K * r_ij;
241
242 p1.rattle_params().correction -= vel_corr * p2.mass();
243 p2.rattle_params().correction += vel_corr * p1.mass();
244
245 return true;
246 }
247
248 return false;
249}
250
251/**
252 * @brief Apply velocity corrections
253 *
254 * @param particles particle range
255 */
256static void apply_velocity_correction(ParticleRange const &particles) {
257 boost::for_each(particles,
258 [](Particle &p) { p.v() += p.rattle_params().correction; });
259}
260
262 BondedInteractionsMap const &bonded_ias) {
264
265 auto particles = cs.local_particles();
266 auto ghost_particles = cs.ghost_particles();
267
268 int cnt;
269 for (cnt = 0; cnt < shake_max_iterations; ++cnt) {
270 init_correction_vector(particles, ghost_particles);
272 cs, box_geo, bonded_ias,
273 [](RigidBond const &bond, BoxGeometry const &box_geo_, Particle &p1,
274 Particle &p2, int /* bond_id */) {
276 });
277 bool const repeat =
278 boost::mpi::all_reduce(comm_cart, repeat_, std::logical_or<bool>());
279
280 // no correction is necessary, skip communication and bail out
281 if (!repeat)
282 break;
283
285
286 apply_velocity_correction(particles);
288 }
289 check_convergence(cnt, "VEL RATTLE");
290}
291
292#endif
Vector implementation and trait types for boost qvm interoperability.
Data structures for bonded interactions.
container for bonded interactions.
mapped_type const & at(key_type const &key) const
std::vector< Utils::Vector9d > rigid_bond_virial
Per-bond-type RATTLE constraint virial.
DEVICE_QUALIFIER auto get_next_key() const
ESPRESSO_ATTR_ALWAYS_INLINE Utils::Vector3< T > get_mi_vector(Utils::Vector3< T > const &a, Utils::Vector3< T > const &b) const
Get the minimum-image vector between two coordinates.
Describes a cell structure / cell system.
ParticleRange ghost_particles() const
void update_ghosts_and_resort_particle(unsigned data_parts)
Update ghost particles, with particle resort if needed.
void ghosts_update(unsigned data_parts)
Update ghost particles.
bool check_resort_required(Utils::Vector3d const &additional_offset={}) const
Check whether a particle has moved further than half the skin since the last Verlet list update,...
void bond_loop(BondKernel const &bond_kernel)
Bonded pair loop.
void set_resort_particles(Cells::Resort level)
Increase the local resort level at least to level.
ParticleRange local_particles() const
void ghosts_reduce_rattle_correction()
Add rattle corrections from ghost particles to real particles.
A range of particles.
static DEVICE_QUALIFIER constexpr Vector< T, N > broadcast(typename Base::value_type const &value) noexcept
Create a vector that has all entries set to the same value.
Definition Vector.hpp:131
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
boost::mpi::communicator comm_cart
The communicator.
This file contains the errorhandling code for severe errors, like a broken bond or illegal parameter ...
#define runtimeErrorMsg()
Matrix implementation and trait types for boost qvm interoperability.
@ DATA_PART_MOMENTUM
Particle::m.
@ DATA_PART_PROPERTIES
Particle::p.
@ DATA_PART_POSITION
Particle::r.
void flatten(Range const &v, OutputIterator out)
Flatten a range of ranges.
Definition flatten.hpp:56
Matrix< T, N, M > tensor_product(const Vector< T, N > &x, const Vector< T, M > &y)
void correct_velocity_shake(CellStructure &cs, BoxGeometry const &box_geo, BondedInteractionsMap const &bonded_ias)
Correction of current velocities using RATTLE algorithm.
Definition rattle.cpp:261
void save_old_position(const ParticleRange &particles, const ParticleRange &ghost_particles)
copy current position
Definition rattle.cpp:65
static constexpr auto shake_max_iterations
Maximal number of iterations before the RATTLE algorithm bails out.
Definition rattle.cpp:50
static void init_correction_vector(const ParticleRange &particles, const ParticleRange &ghost_particles)
reset correction vectors to zero
Definition rattle.cpp:79
static void apply_positional_correction(const ParticleRange &particles)
Apply positional corrections.
Definition rattle.cpp:172
static bool calculate_velocity_correction(RigidBond const &ia_params, BoxGeometry const &box_geo, Particle &p1, Particle &p2)
Calculate the velocity correction for the particles.
Definition rattle.cpp:230
void correct_position_shake(CellStructure &cs, BoxGeometry const &box_geo, BondedInteractionsMap &bonded_ias)
Propagate velocity and position while using SHAKE algorithm for bond constraint.
Definition rattle.cpp:179
static bool calculate_positional_correction(RigidBond const &ia_params, BoxGeometry const &box_geo, Particle &p1, Particle &p2, int bond_id, std::vector< Utils::Vector9d > &rigid_bond_virial)
Calculate the positional correction for the particles.
Definition rattle.cpp:99
static void check_convergence(int cnt, char const *const name)
Definition rattle.cpp:52
static void apply_velocity_correction(ParticleRange const &particles)
Apply velocity corrections.
Definition rattle.cpp:256
static bool compute_correction_vector(CellStructure &cs, BoxGeometry const &box_geo, BondedInteractionsMap const &bonded_ias, Kernel kernel)
Compute the correction vectors using given kernel.
Definition rattle.cpp:145
RATTLE algorithm ().
Definition of the rigid bond data type for the Rattle algorithm.
Struct holding all information for one particle.
Definition Particle.hpp:436
constexpr auto const & pos() const
Definition Particle.hpp:476
constexpr auto const & rattle_params() const
Definition Particle.hpp:659
constexpr auto const & v() const
Definition Particle.hpp:478
Parameters for the rigid_bond/SHAKE/RATTLE ALGORITHM.