ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
forces_cabana.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2025 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include <config/config.hpp>
23
24#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
25
26#include "aosoa_pack.hpp"
27#include "forces_inline.hpp"
28
29#include <utils/Vector.hpp>
30
31#include <Cabana_Core.hpp>
32
33#include <omp.h>
34
35#include <cstddef>
36#include <vector>
37
38#if defined(__GNUG__) or defined(__clang__)
39#define ESPRESSO_ATTR_ALWAYS_INLINE [[gnu::always_inline]]
40#else
41#define ESPRESSO_ATTR_ALWAYS_INLINE
42#endif
43
53 std::vector<Particle *> const &unique_particles;
55#ifdef ESPRESSO_ROTATION
57#endif
58#ifdef ESPRESSO_NPT
61#endif
63
65 BondedInteractionsMap const &bonded_ias_,
66 InteractionsNonBonded const &nonbonded_ias_,
70 Coulomb::ShortRangeEnergyKernel::kernel_type const *coulomb_u_kernel_,
71 Thermostat::Thermostat const &thermostat_, BoxGeometry const &box_geo_,
72 std::vector<Particle *> const &unique_particles_,
73 CellStructure::ForceType const &local_force_,
74#ifdef ESPRESSO_ROTATION
75 CellStructure::ForceType const &local_torque_,
76#endif
77#ifdef ESPRESSO_NPT
78 Utils::Vector3d *const global_virial_,
79 CellStructure::VirialType const &local_virial_,
80#endif
81 CellStructure::AoSoA_pack const &aosoa_)
82 : bonded_ias(bonded_ias_), nonbonded_ias(nonbonded_ias_),
83 coulomb_kernel(coulomb_kernel_), dipoles_kernel(dipoles_kernel_),
84 elc_kernel(elc_kernel_), coulomb_u_kernel(coulomb_u_kernel_),
85 thermostat(thermostat_), box_geo(box_geo_),
86 unique_particles(unique_particles_), local_force(local_force_),
87#ifdef ESPRESSO_ROTATION
88 local_torque(local_torque_),
89#endif
90#ifdef ESPRESSO_NPT
91 global_virial(global_virial_), local_virial(local_virial_),
92#endif
93 aosoa(aosoa_) {
94 }
95
96 // Helper functions to check if specific algorithms are active
97 ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool
98 gay_berne_active(double dist, IA_parameters const &ia_params) const {
99#ifdef ESPRESSO_GAY_BERNE
100 return dist < ia_params.gay_berne.cut;
101#else
102 return false;
103#endif
104 }
105
106#ifdef ESPRESSO_NPT
107 ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool npt_active() const {
108 return global_virial != nullptr;
109 }
110#endif
111
112#ifdef ESPRESSO_THOLE
113 ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool
114 thole_active(IA_parameters const &ia_params) const {
115 return (ia_params.thole.scaling_coeff != 0. and
116 ia_params.thole.q1q2 != 0. and coulomb_kernel != nullptr);
117 }
118#endif
119
120#ifdef ESPRESSO_DIPOLES
121 ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool
123 return dipoles_kernel != nullptr;
124 }
125#endif
126
127 ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION void
128 operator()(std::size_t i, std::size_t j) const {
129
130 auto const &ia_params =
132
133 ParticleForce pf{};
134
135 // calc distance
136 auto const pos1 = aosoa.get_vector_at(aosoa.position, i);
137 auto const pos2 = aosoa.get_vector_at(aosoa.position, j);
138 auto const d = box_geo.get_mi_vector(pos1, pos2);
139 auto const dist = d.norm();
140
141 // Determine which data needs to be loaded based on active algorithms
142#if defined(ESPRESSO_DIPOLES) or defined(ESPRESSO_GAY_BERNE)
143 bool const need_directors =
144 gay_berne_active(dist, ia_params) or dipoles_active();
145#endif
146#if defined(ESPRESSO_EXCLUSIONS) or defined(ESPRESSO_THOLE)
147 bool const need_particle_pointers = aosoa.has_exclusion(i) or
148 aosoa.has_exclusion(j) or
149 thole_active(ia_params);
150 Particle const *p1_ptr = nullptr;
151 Particle const *p2_ptr = nullptr;
152 if (need_particle_pointers) {
153 p1_ptr = unique_particles.at(i);
154 p2_ptr = unique_particles.at(j);
155 }
156#endif
157
158 // Load directors only if needed
159#if defined(ESPRESSO_GAY_BERNE) or defined(ESPRESSO_DIPOLES)
160 Utils::Vector3d dir1{}, dir2{};
161 if (need_directors) {
164 }
165#endif
166
167 /***********************************************/
168 /* non-bonded pair potentials */
169 /***********************************************/
170
171 if (dist < ia_params.max_cut) {
172#ifdef ESPRESSO_EXCLUSIONS
173 bool skip_non_bonded = false;
174 if (aosoa.has_exclusion(i) or aosoa.has_exclusion(j)) {
175 skip_non_bonded = not do_nonbonded(*p1_ptr, *p2_ptr);
176 }
177#else
178 constexpr bool skip_non_bonded = false;
179#endif
180 if (not skip_non_bonded) {
181 pf.f += calc_central_radial_force(ia_params, d, dist);
182
183 // Only call Thole force kernel if active
184#ifdef ESPRESSO_THOLE
185 if (thole_active(ia_params)) {
186 pf.f += thole_pair_force(*p1_ptr, *p2_ptr, ia_params, d, dist,
188 }
189#endif
190 // Only call Gay-Berne force kernel if active
191#ifdef ESPRESSO_GAY_BERNE
192 if (gay_berne_active(dist, ia_params)) {
193 pf += gb_pair_force(dir1, dir2, ia_params, d, dist);
194 }
195#endif
196 } // not skip_non_bonded
197 }
198
199 /*********************************************************************/
200 /* everything before this contributes to the virial pressure in NpT, */
201 /* but nothing afterwards, since the contribution to pressure from */
202 /* electrostatic is calculated by energy */
203 /*********************************************************************/
204#ifdef ESPRESSO_NPT
205 Utils::Vector3d virial{};
206 if (npt_active()) {
207 virial = hadamard_product(pf.f, d);
208 }
209#endif // ESPRESSO_NPT
210
211 /***********************************************/
212 /* thermostat */
213 /***********************************************/
214
215 /* The inter dpd force should not be part of the virial */
216#ifdef ESPRESSO_DPD
218 auto const dist2 = dist * dist;
219 auto const vel1 = aosoa.get_vector_at(aosoa.velocity, i);
220 auto const vel2 = aosoa.get_vector_at(aosoa.velocity, j);
221 auto const force =
222 dpd_pair_force(pos1, vel1, aosoa.id(i), pos2, vel2, aosoa.id(j),
223 *thermostat.dpd, box_geo, ia_params, d, dist, dist2);
224 pf += force;
225 }
226#endif // ESPRESSO_DPD
227
228#ifdef ESPRESSO_ELECTROSTATICS
229 Utils::Vector3d f1_asym{};
230 Utils::Vector3d f2_asym{};
231 // real-space electrostatic charge-charge interaction
232 if (coulomb_kernel != nullptr) {
233 auto const q1q2 = aosoa.charge(i) * aosoa.charge(j);
234 if (q1q2 != 0) {
235 pf.f += (*coulomb_kernel)(q1q2, d, dist);
236 if (elc_kernel) {
237 (*elc_kernel)(pos1, pos2, f1_asym, f2_asym, q1q2);
238 }
239#ifdef ESPRESSO_NPT
240 if (npt_active()) {
241 virial[0] += (*coulomb_u_kernel)(pos1, pos2, q1q2, d, dist);
242 }
243#endif // ESPRESSO_NPT
244 }
245 }
246#endif // ESPRESSO_ELECTROSTATICS
247
248 // Only call dipole force kernel if active
249#ifdef ESPRESSO_DIPOLES
250 if (dipoles_active()) {
251 auto const d1d2 = aosoa.dipm(i) * aosoa.dipm(j);
252 if (d1d2 != 0.) {
253 pf += (*dipoles_kernel)(d1d2, aosoa.dipm(i) * dir1,
254 aosoa.dipm(j) * dir2, d, dist, dist * dist);
255 }
256 }
257#endif // ESPRESSO_DIPOLES
258
259 auto opf = calc_opposing_force(pf, d);
260#ifdef ESPRESSO_ELECTROSTATICS
261 pf.f += f1_asym;
262 opf.f += f2_asym;
263#endif // ESPRESSO_ELECTROSTATICS
264
265 auto const thread_id = omp_get_thread_num();
266
267 local_force(i, thread_id, 0) += pf.f[0];
268 local_force(i, thread_id, 1) += pf.f[1];
269 local_force(i, thread_id, 2) += pf.f[2];
270#ifdef ESPRESSO_ROTATION
271 local_torque(i, thread_id, 0) += pf.torque[0];
272 local_torque(i, thread_id, 1) += pf.torque[1];
273 local_torque(i, thread_id, 2) += pf.torque[2];
274#endif
275
276 local_force(j, thread_id, 0) += opf.f[0];
277 local_force(j, thread_id, 1) += opf.f[1];
278 local_force(j, thread_id, 2) += opf.f[2];
279#ifdef ESPRESSO_ROTATION
280 local_torque(j, thread_id, 0) += opf.torque[0];
281 local_torque(j, thread_id, 1) += opf.torque[1];
282 local_torque(j, thread_id, 2) += opf.torque[2];
283#endif
284#ifdef ESPRESSO_NPT
285 if (npt_active()) {
286 local_virial(thread_id, 0) += virial[0];
287 local_virial(thread_id, 1) += virial[1];
288 local_virial(thread_id, 2) += virial[2];
289 }
290#endif
291 }
292};
293
294#endif // ESPRESSO_SHARED_MEMORY_PARALLELISM
@ THERMO_DPD
Vector implementation and trait types for boost qvm interoperability.
container for bonded interactions.
ESPRESSO_ATTR_ALWAYS_INLINE Utils::Vector< T, 3 > get_mi_vector(const Utils::Vector< T, 3 > &a, const Utils::Vector< T, 3 > &b) const
Get the minimum-image vector between two coordinates.
auto & get_ia_param(int i, int j)
Get interaction parameters between particle types i and j.
std::shared_ptr< DPDThermostat > dpd
int thermo_switch
Bitmask of currently active thermostats.
Utils::Vector3d dpd_pair_force(DPDParameters const &params, Utils::Vector3d const &v, double dist, Utils::Vector3d const &noise)
Definition dpd.cpp:86
bool do_nonbonded(Particle const &p1, Particle const &p2)
Determine if the non-bonded interactions between p1 and p2 should be calculated.
#define ESPRESSO_ATTR_ALWAYS_INLINE
Force calculation.
ParticleForce calc_opposing_force(ParticleForce const &pf, Utils::Vector3d const &d)
ESPRESSO_ATTR_ALWAYS_INLINE Utils::Vector3d calc_central_radial_force(IA_parameters const &ia_params, Utils::Vector3d const &d, double const dist)
ParticleForce gb_pair_force(Utils::Vector3d const &ui, Utils::Vector3d const &uj, IA_parameters const &ia_params, Utils::Vector3d const &d, double dist)
Calculate Gay-Berne force and torques.
Definition gay_berne.hpp:49
Utils::Vector3d get_vector_at(Kokkos::View< double *[3], array_layout, Kokkos::HostSpace > const &view, std::size_t i) const
bool has_exclusion(std::size_t i) const
PositionViewType position
DirectorViewType director
VelocityViewType velocity
Solver::ShortRangeEnergyKernel kernel_type
Solver::ShortRangeForceCorrectionsKernel kernel_type
Solver::ShortRangeForceKernel kernel_type
Solver::ShortRangeForceKernel kernel_type
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool thole_active(IA_parameters const &ia_params) const
std::vector< Particle * > const & unique_particles
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool gay_berne_active(double dist, IA_parameters const &ia_params) const
Coulomb::ShortRangeEnergyKernel::kernel_type const *const coulomb_u_kernel
Coulomb::ShortRangeForceCorrectionsKernel::kernel_type const * elc_kernel
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool npt_active() const
BoxGeometry const & box_geo
ForcesKernel(BondedInteractionsMap const &bonded_ias_, InteractionsNonBonded const &nonbonded_ias_, Coulomb::ShortRangeForceKernel::kernel_type const *coulomb_kernel_, Dipoles::ShortRangeForceKernel::kernel_type const *dipoles_kernel_, Coulomb::ShortRangeForceCorrectionsKernel::kernel_type const *elc_kernel_, Coulomb::ShortRangeEnergyKernel::kernel_type const *coulomb_u_kernel_, Thermostat::Thermostat const &thermostat_, BoxGeometry const &box_geo_, std::vector< Particle * > const &unique_particles_, CellStructure::ForceType const &local_force_, CellStructure::ForceType const &local_torque_, Utils::Vector3d *const global_virial_, CellStructure::VirialType const &local_virial_, CellStructure::AoSoA_pack const &aosoa_)
CellStructure::VirialType const & local_virial
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool dipoles_active() const
Dipoles::ShortRangeForceKernel::kernel_type const *const dipoles_kernel
CellStructure::AoSoA_pack const & aosoa
CellStructure::ForceType const & local_torque
InteractionsNonBonded const & nonbonded_ias
Utils::Vector3d *const global_virial
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION void operator()(std::size_t i, std::size_t j) const
BondedInteractionsMap const & bonded_ias
CellStructure::ForceType const & local_force
Coulomb::ShortRangeForceKernel::kernel_type const *const coulomb_kernel
Thermostat::Thermostat const & thermostat
Parameters for non-bonded interactions.
GayBerne_Parameters gay_berne
Force information on a particle.
Definition Particle.hpp:345
Struct holding all information for one particle.
Definition Particle.hpp:450
Utils::Vector3d thole_pair_force(Particle const &p1, Particle const &p2, IA_parameters const &ia_params, Utils::Vector3d const &d, double dist, BondedInteractionsMap const &bonded_ias, Coulomb::ShortRangeForceKernel::kernel_type const *kernel)
Calculate Thole force.
Definition thole.hpp:44