ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
forces.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 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/** \file
22 * Force calculation.
23 *
24 * The corresponding header file is forces.hpp.
25 */
26
27#include "BoxGeometry.hpp"
28#include "Particle.hpp"
29#include "ParticleRange.hpp"
30#include "PropagationMode.hpp"
33#include "cells.hpp"
34#include "collision.hpp"
35#include "communication.hpp"
36#include "constraints.hpp"
39#include "forces_inline.hpp"
40#include "galilei/ComFixed.hpp"
47#include "npt.hpp"
48#include "rotation.hpp"
49#include "short_range_loop.hpp"
50#include "system/System.hpp"
51#include "thermostat.hpp"
53
54#include <utils/math/sqr.hpp>
55
56#include <boost/variant.hpp>
57
58#ifdef CALIPER
59#include <caliper/cali.h>
60#endif
61
62#include <cassert>
63#include <cmath>
64#include <memory>
65#include <variant>
66
67/** External particle forces */
69 ParticleForce f = {};
70
71#ifdef EXTERNAL_FORCES
72 f.f += p.ext_force();
73#ifdef ROTATION
74 f.torque += p.ext_torque();
75#endif
76#endif
77
78#ifdef ENGINE
79 // apply a swimming force in the direction of
80 // the particle's orientation axis
81 if (p.swimming().swimming and !p.swimming().is_engine_force_on_fluid) {
82 f.f += p.swimming().f_swim * p.calc_director();
83 }
84#endif
85
86 return f;
87}
88
89static void init_forces(ParticleRange const &particles,
90 ParticleRange const &ghost_particles) {
91#ifdef CALIPER
92 CALI_CXX_MARK_FUNCTION;
93#endif
94
95 for (auto &p : particles) {
96 p.force_and_torque() = external_force(p);
97 }
98
99 init_forces_ghosts(ghost_particles);
100}
101
102void init_forces_ghosts(ParticleRange const &particles) {
103 for (auto &p : particles) {
104 p.force_and_torque() = {};
105 }
106}
107
108static void force_capping(ParticleRange const &particles, double force_cap) {
109 if (force_cap > 0.) {
110 auto const force_cap_sq = Utils::sqr(force_cap);
111 for (auto &p : particles) {
112 auto const force_sq = p.force().norm2();
113 if (force_sq > force_cap_sq) {
114 p.force() *= force_cap / std::sqrt(force_sq);
115 }
116 }
117 }
118}
119
121#ifdef CALIPER
122 CALI_CXX_MARK_FUNCTION;
123#endif
124#ifdef CUDA
125#ifdef CALIPER
126 CALI_MARK_BEGIN("copy_particles_to_GPU");
127#endif
128 gpu.update();
129#ifdef CALIPER
130 CALI_MARK_END("copy_particles_to_GPU");
131#endif
132#endif // CUDA
133
134#ifdef COLLISION_DETECTION
136#endif
137 bond_breakage->clear_queue();
138 auto particles = cell_structure->local_particles();
139 auto ghost_particles = cell_structure->ghost_particles();
140#ifdef ELECTROSTATICS
141 if (coulomb.impl->extension) {
142 if (auto icc = std::get_if<std::shared_ptr<ICCStar>>(
143 get_ptr(coulomb.impl->extension))) {
144 (**icc).iteration(*cell_structure, particles, ghost_particles);
145 }
146 }
147#endif // ELECTROSTATICS
148#ifdef NPT
150#endif
151 init_forces(particles, ghost_particles);
152 thermostat_force_init();
153
154 calc_long_range_forces(particles);
155
156 auto const elc_kernel = coulomb.pair_force_elc_kernel();
157 auto const coulomb_kernel = coulomb.pair_force_kernel();
158 auto const dipoles_kernel = dipoles.pair_force_kernel();
159
160#ifdef ELECTROSTATICS
161 auto const coulomb_cutoff = coulomb.cutoff();
162#else
163 auto const coulomb_cutoff = INACTIVE_CUTOFF;
164#endif
165
166#ifdef DIPOLES
167 auto const dipole_cutoff = dipoles.cutoff();
168#else
169 auto const dipole_cutoff = INACTIVE_CUTOFF;
170#endif
171
173 [coulomb_kernel_ptr = get_ptr(coulomb_kernel),
174 &bond_breakage = *bond_breakage, &box_geo = *box_geo](
175 Particle &p1, int bond_id, Utils::Span<Particle *> partners) {
176 return add_bonded_force(p1, bond_id, partners, bond_breakage, box_geo,
177 coulomb_kernel_ptr);
178 },
179 [coulomb_kernel_ptr = get_ptr(coulomb_kernel),
180 dipoles_kernel_ptr = get_ptr(dipoles_kernel),
181 elc_kernel_ptr = get_ptr(elc_kernel), &nonbonded_ias = *nonbonded_ias,
182 &thermostat = *thermostat,
183 &box_geo = *box_geo](Particle &p1, Particle &p2, Distance const &d) {
184 auto const &ia_params =
185 nonbonded_ias.get_ia_param(p1.type(), p2.type());
187 p1, p2, d.vec21, sqrt(d.dist2), d.dist2, ia_params, thermostat,
188 box_geo, coulomb_kernel_ptr, dipoles_kernel_ptr, elc_kernel_ptr);
189#ifdef COLLISION_DETECTION
191 detect_collision(p1, p2, d.dist2);
192#endif
193 },
194 *cell_structure, maximal_cutoff(), maximal_cutoff_bonded(),
195 VerletCriterion<>{*this, cell_structure->get_verlet_skin(),
196 get_interaction_range(), coulomb_cutoff, dipole_cutoff,
198
199 Constraints::constraints.add_forces(*box_geo, particles, get_sim_time());
200
201 for (int i = 0; i < max_oif_objects; i++) {
202 // There are two global quantities that need to be evaluated:
203 // object's surface and object's volume.
204 auto const area_volume = boost::mpi::all_reduce(
205 comm_cart, calc_oif_global(i, *box_geo, *cell_structure), std::plus());
206 auto const oif_part_area = std::abs(area_volume[0]);
207 auto const oif_part_vol = std::abs(area_volume[1]);
208 if (oif_part_area < 1e-100 and oif_part_vol < 1e-100) {
209 break;
210 }
211 add_oif_global_forces(area_volume, i, *box_geo, *cell_structure);
212 }
213
214 // Must be done here. Forces need to be ghost-communicated
216
217 if (thermostat->lb and (propagation->used_propagations &
219 lb_couple_particles();
220 }
221
222#ifdef CUDA
223#ifdef CALIPER
224 CALI_MARK_BEGIN("copy_forces_from_GPU");
225#endif
226 gpu.copy_forces_to_host(particles, this_node);
227#ifdef CALIPER
228 CALI_MARK_END("copy_forces_from_GPU");
229#endif
230#endif // CUDA
231
232#ifdef VIRTUAL_SITES_RELATIVE
233 if (propagation->used_propagations &
236 }
237#endif
238
239 // Communication step: ghost forces
240 cell_structure->ghosts_reduce_forces();
241
242 // should be pretty late, since it needs to zero out the total force
243 comfixed->apply(particles);
244
245 // Needs to be the last one to be effective
246 force_capping(particles, force_cap);
247
248 // mark that forces are now up-to-date
249 propagation->recalc_forces = false;
250}
251
252void calc_long_range_forces(const ParticleRange &particles) {
253#ifdef CALIPER
254 CALI_CXX_MARK_FUNCTION;
255#endif
256
257#ifdef ELECTROSTATICS
258 /* calculate k-space part of electrostatic interaction. */
260#endif // ELECTROSTATICS
261
262#ifdef DIPOLES
263 /* calculate k-space part of the magnetostatic interaction. */
265#endif // DIPOLES
266}
267
268#ifdef NPT
273#endif
float f[3]
__global__ float * force
double maximal_cutoff_bonded()
Calculate the maximal cutoff of bonded interactions, required to determine the cell size for communic...
This file contains everything related to the global cell structure / cell system.
CollisionModeType mode
collision protocol
Definition collision.hpp:55
void volume_conservation(CellStructure &cs)
Calculate volumes, volume force and add it to each virtual particle.
A range of particles.
void calculate_forces()
Calculate all forces.
Definition forces.cpp:120
A stripped-down version of std::span from C++17.
Definition Span.hpp:38
Returns true if the particles are to be considered for short range interactions.
void prepare_local_collision_queue()
Collision_parameters collision_params
Parameters for collision detection.
Definition collision.cpp:73
@ OFF
Deactivate collision detection.
double collision_detection_cutoff()
void detect_collision(Particle const &p1, Particle const &p2, double const dist2)
Detect (and queue) a collision between the given particles.
boost::mpi::communicator comm_cart
The communicator.
int this_node
The number of this node.
const T * get_ptr(std::optional< T > const &opt)
static void init_forces(ParticleRange const &particles, ParticleRange const &ghost_particles)
Definition forces.cpp:89
static void force_capping(ParticleRange const &particles, double force_cap)
Definition forces.cpp:108
void init_forces_ghosts(ParticleRange const &particles)
Set forces of all ghosts to zero.
Definition forces.cpp:102
static ParticleForce external_force(Particle const &p)
External particle forces.
Definition forces.cpp:68
void npt_add_virial_force_contribution(const Utils::Vector3d &force, const Utils::Vector3d &d)
Update the NpT virial.
Definition forces.cpp:269
void calc_long_range_forces(const ParticleRange &particles)
Calculate long range forces (P3M, ...).
Definition forces.cpp:252
Force calculation.
bool add_bonded_force(Particle &p1, int bond_id, Utils::Span< Particle * > partners, BondBreakage::BondBreakage &bond_breakage, BoxGeometry const &box_geo, Coulomb::ShortRangeForceKernel::kernel_type const *kernel)
void add_non_bonded_pair_force(Particle &p1, Particle &p2, Utils::Vector3d const &d, double dist, double dist2, IA_parameters const &ia_params, Thermostat::Thermostat const &thermostat, BoxGeometry const &box_geo, Coulomb::ShortRangeForceKernel::kernel_type const *coulomb_kernel, Dipoles::ShortRangeForceKernel::kernel_type const *dipoles_kernel, Coulomb::ShortRangeForceCorrectionsKernel::kernel_type const *elc_kernel)
Calculate non-bonded forces between a pair of particles and update their forces and torques.
ICC is a method that allows to take into account the influence of arbitrarily shaped dielectric inter...
ImmersedBoundaries immersed_boundaries
Constraints< ParticleRange, Constraint > constraints
Solver const & get_coulomb()
Definition coulomb.cpp:68
Solver const & get_dipoles()
Definition dipoles.cpp:51
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:26
Various procedures concerning interactions between particles.
constexpr double INACTIVE_CUTOFF
Cutoff for deactivated interactions.
void npt_add_virial_contribution(double energy)
Definition npt.cpp:141
void npt_reset_instantaneous_virials()
reset virial part of instantaneous pressure
Definition npt.cpp:134
Exports for the NpT code.
void add_oif_global_forces(Utils::Vector2d const &area_volume, int molType, BoxGeometry const &box_geo, CellStructure &cs)
Distribute the OIF global forces to all particles in the mesh.
int max_oif_objects
Utils::Vector2d calc_oif_global(int molType, BoxGeometry const &box_geo, CellStructure &cs)
Calculate the OIF global force.
P3M electrostatics on GPU.
void vs_relative_back_transfer_forces_and_torques(CellStructure &cell_structure)
Definition relative.cpp:166
This file contains all subroutines required to process rotational motion.
void short_range_loop(BondKernel bond_kernel, PairKernel pair_kernel, CellStructure &cell_structure, double pair_cutoff, double bond_cutoff, VerletCriterion const &verlet_criterion={})
void calc_long_range_force(ParticleRange const &particles) const
Definition coulomb.cpp:279
void calc_long_range_force(ParticleRange const &particles) const
Definition dipoles.cpp:212
Distance vector and length handed to pair kernels.
Force information on a particle.
Definition Particle.hpp:290
Utils::Vector3d f
force.
Definition Particle.hpp:314
Struct holding all information for one particle.
Definition Particle.hpp:393
auto const & swimming() const
Definition Particle.hpp:559
auto const & ext_force() const
Definition Particle.hpp:552
auto const & type() const
Definition Particle.hpp:416
auto const & ext_torque() const
Definition Particle.hpp:482
auto calc_director() const
Definition Particle.hpp:485