ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
pressure_cabana.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2026 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#include "BoxGeometry.hpp"
25#include "Observable_stat.hpp"
26#include "Particle.hpp"
27#include "aosoa_pack.hpp"
30#include "exclusions.hpp"
31#include "forces_inline.hpp"
33#include "pressure_inline.hpp"
35
36#ifdef ESPRESSO_DPD
37#include "dpd.hpp"
38#endif
39
40#include <utils/Vector.hpp>
42
43#include <Cabana_Core.hpp>
44
45#include <omp.h>
46
47#include <cstddef>
48#include <span>
49#include <vector>
50
52 std::size_t n_bonded;
53 std::size_t n_types;
54 std::size_t off_bonded = 0;
55 std::size_t off_nb_inter;
56 std::size_t off_nb_intra;
57 std::size_t off_coulomb;
58 std::size_t off_dipolar;
59 std::size_t off_dpd;
60 std::size_t total;
61
62 PressureBinLayout(std::size_t n_bonded_, std::size_t n_types_)
63 : n_bonded(n_bonded_), n_types(n_types_) {
64 auto const n_nb = n_types * (n_types + 1) / 2;
69 off_dpd = off_dipolar + 1;
70 total = off_dpd + 1;
71 }
72
73 KOKKOS_INLINE_FUNCTION
74 std::size_t tensor_offset(std::size_t bin, std::size_t k) const {
75 return bin * 9 + k;
76 }
77
78 KOKKOS_INLINE_FUNCTION
79 std::size_t nb_inter_idx(int t1, int t2) const {
80 return off_nb_inter +
81 Utils::lower_triangular(std::max(t1, t2), std::min(t1, t2));
82 }
83
84 KOKKOS_INLINE_FUNCTION
85 std::size_t nb_intra_idx(int t1, int t2) const {
86 return off_nb_intra +
87 Utils::lower_triangular(std::max(t1, t2), std::min(t1, t2));
88 }
89
90 KOKKOS_INLINE_FUNCTION std::size_t coulomb_idx() const { return off_coulomb; }
91 KOKKOS_INLINE_FUNCTION std::size_t dipolar_idx() const { return off_dipolar; }
92 KOKKOS_INLINE_FUNCTION std::size_t dpd_idx() const { return off_dpd; }
93 KOKKOS_INLINE_FUNCTION std::size_t bonded_idx(int b) const {
94 return off_bonded + static_cast<std::size_t>(b);
95 }
96};
97
105 std::vector<Particle *> const &unique_particles;
106 Kokkos::View<double **, Kokkos::LayoutRight> local_pressure;
109 Kokkos::View<int *> mol_id_view;
112
114 BondedInteractionsMap const &bonded_ias_,
115 InteractionsNonBonded const &nonbonded_ias_,
116 Coulomb::Solver const &coulomb_,
117 Coulomb::ShortRangeForceKernel::kernel_type const *coulomb_f_kernel_,
118 Coulomb::ShortRangePressureKernel::kernel_type const *coulomb_p_kernel_,
119 BoxGeometry const &box_geo_,
120 std::vector<Particle *> const &unique_particles_,
121 Kokkos::View<double **, Kokkos::LayoutRight> const &local_pressure_,
122 PressureBinLayout layout_, CellStructure::AoSoA_pack const &aosoa_,
123 Kokkos::View<int *> mol_id_view_, double system_max_cutoff_,
124 int thermo_switch_)
125 : bonded_ias(bonded_ias_), nonbonded_ias(nonbonded_ias_),
126 coulomb(coulomb_), coulomb_f_kernel(coulomb_f_kernel_),
127 coulomb_p_kernel(coulomb_p_kernel_), box_geo(box_geo_),
128 unique_particles(unique_particles_), local_pressure(local_pressure_),
129 layout(layout_), aosoa(aosoa_), mol_id_view(std::move(mol_id_view_)),
130 system_max_cutoff(system_max_cutoff_), thermo_switch(thermo_switch_) {}
131
132 KOKKOS_INLINE_FUNCTION
133 void operator()(std::size_t i, std::size_t j) const {
134 auto const pos1 = aosoa.get_vector_at(aosoa.position, i);
135 auto const pos2 = aosoa.get_vector_at(aosoa.position, j);
136 auto const d = box_geo.get_mi_vector(pos1, pos2);
137 auto const dist = d.norm();
138 if (dist > system_max_cutoff)
139 return;
140
141 auto const t1 = aosoa.type(i);
142 auto const t2 = aosoa.type(j);
143 auto const &ia_params = nonbonded_ias.get_ia_param(t1, t2);
144 auto const tid = omp_get_thread_num();
145
146 // --- Non-bonded virial ---
147 if (dist <= ia_params.max_cut) {
148 bool skip = false;
149#ifdef ESPRESSO_EXCLUSIONS
150 if (aosoa.has_exclusion(i) or aosoa.has_exclusion(j)) {
151 skip =
153 }
154#endif
155 if (not skip) {
156 Utils::Vector3d f = calc_central_radial_force(ia_params, d, dist);
157
158#ifdef ESPRESSO_GAY_BERNE
159 if (gay_berne_active(dist, ia_params)) {
160 auto const dir1 = aosoa.get_vector_at(aosoa.director, i);
161 auto const dir2 = aosoa.get_vector_at(aosoa.director, j);
162 f += calc_non_central_force(dir1, dir2, ia_params, d, dist);
163 }
164#endif
165#ifdef ESPRESSO_THOLE
166 if (thole_active(ia_params, coulomb_f_kernel != nullptr)) {
168 *unique_particles.at(j), ia_params, d, dist,
170 }
171#endif
172
173 auto const stress = Utils::flatten(Utils::tensor_product(d, f));
174 auto const bin = (mol_id_view(i) == mol_id_view(j))
175 ? layout.nb_intra_idx(t1, t2)
176 : layout.nb_inter_idx(t1, t2);
177 for (std::size_t k = 0; k < 9; ++k)
178 local_pressure(tid, layout.tensor_offset(bin, k)) += stress[k];
179
180#ifdef ESPRESSO_DPD
181 if (dpd_active(ia_params, thermo_switch)) {
182 auto const vel1 = aosoa.get_vector_at(aosoa.velocity, i);
183 auto const vel2 = aosoa.get_vector_at(aosoa.velocity, j);
184 auto const v21 = box_geo.velocity_difference(pos1, pos2, vel1, vel2);
185 auto const dist2 = d.norm2();
186 // f_r/f_t: dissipative force from radial/transverse DPD channel
187 auto const f_r = dpd_pair_force(ia_params.dpd.radial, v21, dist, {});
188 auto const f_t = dpd_pair_force(ia_params.dpd.trans, v21, dist, {});
189 auto const P = Utils::tensor_product(d / dist2, d);
190 auto const f_d = P * (f_r - f_t) + f_t;
191 auto const s = Utils::flatten(Utils::tensor_product(d, f_d));
192 for (std::size_t k = 0; k < 9; ++k)
194 s[k];
195 }
196#endif
197 }
198 }
199
200#ifdef ESPRESSO_ELECTROSTATICS
201 if (coulomb_p_kernel != nullptr) {
202 auto const q1 = aosoa.charge(i), q2 = aosoa.charge(j);
203 if (q1 != 0. and q2 != 0.) {
204 auto const p_c = Utils::flatten((*coulomb_p_kernel)(q1 * q2, d, dist));
205 for (std::size_t k = 0; k < 9; ++k)
207 p_c[k];
208 }
209 }
210#endif
211 }
212};
213
215 Kokkos::View<double **, Kokkos::LayoutRight> const &local_pressure,
216 PressureBinLayout const &layout, Observable_stat &obs,
217 [[maybe_unused]] BondedInteractionsMap const &bonded_ias, int n_types) {
218 auto const nthreads = local_pressure.extent(0);
219 auto host =
220 Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, local_pressure);
221
222 auto sum_tensor = [&](std::size_t bin, std::span<double> dest) {
223 for (std::size_t k = 0; k < 9; ++k) {
224 double s = 0.;
225 for (std::size_t t = 0; t < nthreads; ++t)
226 s += host(t, layout.tensor_offset(bin, k));
227 dest[k] += s;
228 }
229 };
230
231 for (int b = 0; b < int(layout.n_bonded); ++b)
232 sum_tensor(layout.bonded_idx(b), obs.bonded_contribution(b));
233
234 for (int t1 = 0; t1 < n_types; ++t1)
235 for (int t2 = 0; t2 <= t1; ++t2)
236 sum_tensor(layout.nb_inter_idx(t1, t2),
238
239 for (int t1 = 0; t1 < n_types; ++t1)
240 for (int t2 = 0; t2 <= t1; ++t2)
241 sum_tensor(layout.nb_intra_idx(t1, t2),
243
244 if (!obs.coulomb.empty())
245 sum_tensor(layout.coulomb_idx(), obs.coulomb.subspan(0, 9));
246 if (!obs.dipolar.empty())
247 sum_tensor(layout.dipolar_idx(), obs.dipolar.subspan(0, 9));
248 if (!obs.dpd.empty())
249 sum_tensor(layout.dpd_idx(), obs.dpd);
250}
Vector implementation and trait types for boost qvm interoperability.
Data structures for bonded interactions.
container for bonded interactions.
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.
Utils::Vector3d velocity_difference(Utils::Vector3d const &x, Utils::Vector3d const &y, Utils::Vector3d const &u, Utils::Vector3d const &v) const
Calculate the velocity difference including the Lees-Edwards velocity.
auto & get_ia_param(int i, int j)
Get interaction parameters between particle types i and j.
Observable for the pressure and energy.
auto non_bonded_intra_contribution(int type1, int type2) const
Get contribution from a non-bonded intramolecular interaction.
std::span< double > coulomb
Contribution(s) from Coulomb interactions.
std::span< double > dpd
Contribution from DPD.
auto non_bonded_inter_contribution(int type1, int type2) const
Get contribution from a non-bonded intermolecular interaction.
std::span< double > bonded_contribution(int bond_id) const
Get contribution from a bonded interaction.
std::span< double > dipolar
Contribution(s) from dipolar interactions.
constexpr T norm2() const
Definition Vector.hpp:158
Utils::Vector3d dpd_pair_force(Utils::Vector3d const &p1_position, Utils::Vector3d const &p1_velocity, int p1_id, Utils::Vector3d const &p2_position, Utils::Vector3d const &p2_velocity, int p2_id, DPDThermostat const &dpd, BoxGeometry const &box_geo, IA_parameters const &ia_params, Utils::Vector3d const &d, double dist, double dist2)
Definition dpd.cpp:75
Routines to use DPD as thermostat or pair force .
bool do_nonbonded(Particle const &p1, Particle const &p2)
Determine if the non-bonded interactions between p1 and p2 should be calculated.
Force calculation.
ParticleForce calc_non_central_force(Particle const &p1, Particle const &p2, IA_parameters const &ia_params, Utils::Vector3d const &d, double const dist)
ESPRESSO_ATTR_ALWAYS_INLINE Utils::Vector3d calc_central_radial_force(IA_parameters const &ia_params, Utils::Vector3d const &d, double const dist)
void flatten(Range const &v, OutputIterator out)
Flatten a range of ranges.
Definition flatten.hpp:56
T lower_triangular(T i, T j)
Linear index into a lower triangular matrix.
Definition index.hpp:83
Matrix< T, N, M > tensor_product(const Vector< T, N > &x, const Vector< T, M > &y)
STL namespace.
Various procedures concerning interactions between particles.
static void reduce_cabana_pressure(Kokkos::View< double **, Kokkos::LayoutRight > const &local_pressure, PressureBinLayout const &layout, Observable_stat &obs, BondedInteractionsMap const &bonded_ias, int n_types)
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool gay_berne_active(double dist, IA_parameters const &ia_params)
KOKKOS_INLINE_FUNCTION bool thole_active(IA_parameters const &ia_params, bool has_coulomb_kernel)
ESPRESSO_ATTR_ALWAYS_INLINE KOKKOS_INLINE_FUNCTION bool dpd_active(IA_parameters const &ia_params, int thermo_switch)
bool has_exclusion(std::size_t i) const
PositionViewType position
Utils::Vector< T, N > get_vector_at(Kokkos::View< T *[N], array_layout, Kokkos::HostSpace > const &view, std::size_t i) const
DirectorViewType director
VelocityViewType velocity
Solver::ShortRangeForceKernel kernel_type
Solver::ShortRangePressureKernel kernel_type
KOKKOS_INLINE_FUNCTION std::size_t dpd_idx() const
KOKKOS_INLINE_FUNCTION std::size_t tensor_offset(std::size_t bin, std::size_t k) const
KOKKOS_INLINE_FUNCTION std::size_t coulomb_idx() const
KOKKOS_INLINE_FUNCTION std::size_t nb_intra_idx(int t1, int t2) const
KOKKOS_INLINE_FUNCTION std::size_t bonded_idx(int b) const
PressureBinLayout(std::size_t n_bonded_, std::size_t n_types_)
KOKKOS_INLINE_FUNCTION std::size_t dipolar_idx() const
KOKKOS_INLINE_FUNCTION std::size_t nb_inter_idx(int t1, int t2) const
Coulomb::ShortRangePressureKernel::kernel_type const * coulomb_p_kernel
Coulomb::Solver const & coulomb
Kokkos::View< int * > mol_id_view
InteractionsNonBonded const & nonbonded_ias
Kokkos::View< double **, Kokkos::LayoutRight > local_pressure
PressureBinLayout layout
KOKKOS_INLINE_FUNCTION void operator()(std::size_t i, std::size_t j) const
std::vector< Particle * > const & unique_particles
BondedInteractionsMap const & bonded_ias
Coulomb::ShortRangeForceKernel::kernel_type const * coulomb_f_kernel
PressureKernel(BondedInteractionsMap const &bonded_ias_, InteractionsNonBonded const &nonbonded_ias_, Coulomb::Solver const &coulomb_, Coulomb::ShortRangeForceKernel::kernel_type const *coulomb_f_kernel_, Coulomb::ShortRangePressureKernel::kernel_type const *coulomb_p_kernel_, BoxGeometry const &box_geo_, std::vector< Particle * > const &unique_particles_, Kokkos::View< double **, Kokkos::LayoutRight > const &local_pressure_, PressureBinLayout layout_, CellStructure::AoSoA_pack const &aosoa_, Kokkos::View< int * > mol_id_view_, double system_max_cutoff_, int thermo_switch_)
CellStructure::AoSoA_pack const & aosoa
BoxGeometry const & box_geo
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:45