ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
pressure.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 <config/config.hpp>
23
24#include "BoxGeometry.hpp"
25#include "Observable_stat.hpp"
26#include "Particle.hpp"
32#include "kokkos_helpers.hpp"
37#include "pressure_cabana.hpp"
38#include "pressure_inline.hpp"
41#include "system/System.hpp"
43
44#include <utils/Vector.hpp>
45#include <utils/math/sqr.hpp>
46#include <utils/matrix.hpp>
47
48#include <algorithm>
49#include <cstddef>
50#include <memory>
51
53 using execution_space = Kokkos::DefaultHostExecutionSpace;
54 std::unique_ptr<Observable_stat> observable;
55 Kokkos::View<double **, Kokkos::LayoutRight, execution_space> local;
56};
57
58namespace System {
59
61
62 if (not m_obs_pressure) {
63 auto const n_threads = PressureObservable::execution_space{}.concurrency();
64 m_obs_pressure = std::make_shared<PressureObservable>();
65 m_obs_pressure->observable = std::make_unique<Observable_stat>(9ul, 0ul, 0);
66 m_obs_pressure->local =
67 decltype(m_obs_pressure->local)("local_pressure", n_threads, 9ul);
68 }
69
70 auto &local_pressure = m_obs_pressure->local;
71 auto &obs_pressure = *m_obs_pressure->observable;
72 obs_pressure.reset(static_cast<std::size_t>(bonded_ias->get_next_key()),
73 nonbonded_ias->get_max_seen_particle_type());
74
75 if (long_range_interactions_sanity_checks()) {
76 return obs_pressure;
77 }
78
79 on_observable_calc();
80
81 auto const volume = box_geo->volume();
82
83 // Kinetic virial — reduction over local particles
85 *cell_structure,
86 [](Utils::Matrix<double, 3, 3> &acc, Particle const &p) {
87 if (!p.is_virtual())
88 acc += Utils::tensor_product(p.v(), p.mass() * p.v());
89 },
90 [](auto &a, auto const &b) { a += b; });
91 std::ranges::copy(Utils::flatten(kinetic), obs_pressure.kinetic_lin.begin());
92
93 auto const coulomb_force_kernel = coulomb.pair_force_kernel();
94 auto const coulomb_pressure_kernel = coulomb.pair_pressure_kernel();
95 auto const dipoles_pressure_kernel = dipoles.pair_pressure_kernel();
96
97 // Factory instead of an eager criterion: construction fills an O(n_types^2)
98 // cutoff table, so it only runs on the link-cell fallback path.
99 auto const make_verlet_criterion = [&] {
100 return VerletCriterion<>{*this,
101 cell_structure->get_verlet_skin(),
102 get_interaction_range(),
103 coulomb.cutoff(),
104 dipoles.cutoff(),
106 };
108
109 PressureBinLayout layout{
110 static_cast<std::size_t>(bonded_ias->get_next_key()),
111 std::size_t(nonbonded_ias->get_max_seen_particle_type() + 1)};
112
113 using exec = Kokkos::DefaultHostExecutionSpace;
114 if (local_pressure.extent(1) != layout.total * 9ul) {
115 Kokkos::realloc(Kokkos::WithoutInitializing, local_pressure,
116 exec{}.concurrency(), layout.total * 9ul);
117 }
118 kokkos_deep_copy(exec{}, local_pressure, 0.);
119
120 auto const &unique_particles = cell_structure->get_unique_particles();
121 auto const n_particles = unique_particles.size();
122 Kokkos::View<int *, Kokkos::LayoutRight, exec> mol_id("mol_id", n_particles);
123 for (std::size_t i = 0; i < n_particles; ++i) {
124 mol_id(i) = unique_particles[i]->mol_id();
125 }
126
127 PressureKernel pair_p_kernel{*bonded_ias,
128 *nonbonded_ias,
129 coulomb,
133 *box_geo,
134#ifdef ESPRESSO_DPD
135 thermostat->dpd.get(),
136#endif
137 cell_structure->get_unique_particles(),
138 local_pressure,
139 layout,
140 cell_structure->get_aosoa(),
141 mol_id,
142 maximal_cutoff(),
143 thermostat->thermo_switch};
144
145 auto &bs = cell_structure->bond_state();
146 BondsPressureKernelData bonds_p_data{*bonded_ias, *box_geo, local_pressure,
147 layout, cell_structure->get_aosoa()};
149 bonds_p_data, bs.pair_list, bs.pair_ids, get_ptr(coulomb_force_kernel)};
151 bs.angle_ids};
153 bs.dihedral_ids};
154
156 pair_p_kernel, *cell_structure, get_interaction_range(),
157 bonded_ias->maximal_cutoff(), make_verlet_criterion,
158 propagation->integ_switch);
159
160 reduce_cabana_pressure(local_pressure, layout, obs_pressure, *bonded_ias,
161 nonbonded_ias->get_max_seen_particle_type() + 1);
162
163#ifdef ESPRESSO_ELECTROSTATICS
164 /* calculate k-space part of electrostatic interaction. */
165 auto const coulomb_pressure = coulomb.calc_pressure_long_range();
166 std::ranges::copy(coulomb_pressure, obs_pressure.coulomb.begin() + 9u);
167#endif
168#ifdef ESPRESSO_DIPOLES
169 /* calculate k-space part of magnetostatic interaction. */
170 auto const dipoles_pressure = dipoles.calc_pressure_long_range();
171 std::ranges::copy(dipoles_pressure, obs_pressure.dipolar.begin() + 9u);
172#endif
173
174#ifdef ESPRESSO_VIRTUAL_SITES_RELATIVE
175 if (!obs_pressure.virtual_sites.empty()) {
176 auto const vs_pressure = vs_relative_pressure_tensor(*cell_structure);
177 std::ranges::copy(Utils::flatten(vs_pressure),
178 obs_pressure.virtual_sites.begin());
179 }
180#endif
181
182#ifdef ESPRESSO_BOND_CONSTRAINT
183 if (propagation->is_inertial() and bonded_ias->get_n_rigid_bonds() >= 1) {
184 // rigid_bond_virial was accumulated bond-by-bond inside
185 // correct_position_shake() during the last integration step, so it is
186 // already correct regardless of how many rigid bonds a particle
187 // participates in; only the deferred 1/dt^2 factor is applied here.
188 auto const sq_dt = Utils::sqr(get_time_step());
189 auto const &rigid_bond_virial = bonded_ias->rigid_bond_virial;
190 for (std::size_t bond_id = 0; bond_id < rigid_bond_virial.size();
191 ++bond_id) {
192 auto const stress = rigid_bond_virial[bond_id] / sq_dt;
193 auto dest = obs_pressure.bonded_contribution(static_cast<int>(bond_id));
194 for (std::size_t k = 0; k < 9u; ++k)
195 dest[k] += stress[k];
196 }
197 }
198#endif // ESPRESSO_BOND_CONSTRAINT
199
200 obs_pressure.rescale(volume);
201
202 obs_pressure.mpi_reduce();
203 return obs_pressure;
204}
205
206} // namespace System
Vector implementation and trait types for boost qvm interoperability.
Data structures for bonded interactions.
Observable for the pressure and energy.
Observable_stat const & calculate_pressure()
Calculate the pressure from a virial expansion.
Definition pressure.cpp:60
Returns true if the particles are to be considered for short range interactions.
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
constexpr double inactive_cutoff
Special cutoff value for an inactive interaction.
Definition config.hpp:53
const T * get_ptr(std::optional< T > const &opt)
ESPRESSO_ATTR_ALWAYS_INLINE void kokkos_deep_copy(auto const &exec_space, auto const &view, auto const &value)
Wrapper for Kokkos::deep_copy that skips fork/join when the number of threads is 1.
Matrix implementation and trait types for boost qvm interoperability.
void flatten(Range const &v, OutputIterator out)
Flatten a range of ranges.
Definition flatten.hpp:56
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:28
Matrix< T, N, M > tensor_product(const Vector< T, N > &x, const Vector< T, M > &y)
Various procedures concerning interactions between particles.
static void reduce_cabana_pressure(Kokkos::View< double **, Kokkos::LayoutRight, Kokkos::HostSpace > const &local_pressure, PressureBinLayout const &layout, Observable_stat &obs, BondedInteractionsMap const &bonded_ias, int n_types)
Utils::Matrix< double, 3, 3 > vs_relative_pressure_tensor(CellStructure const &cell_structure)
Definition relative.cpp:194
void cabana_short_range(auto const &pair_bonds_kernel, auto const &angle_bonds_kernel, auto const &dihedral_bonds_kernel, auto const &nonbonded_kernel, CellStructure &cell_structure, double pair_cutoff, double bond_cutoff, auto const &make_verlet_criterion, auto const integ_switch, ShortRangeVerletPairLoop const &verlet_pair_loop={})
void update_verlet_state(System::System const &system, double const collision_cut)
Struct holding all information for one particle.
Definition Particle.hpp:436
DPDThermostat const * dpd
std::unique_ptr< Observable_stat > observable
Definition pressure.cpp:54
Kokkos::View< double **, Kokkos::LayoutRight, execution_space > local
Definition pressure.cpp:55
Kokkos::DefaultHostExecutionSpace execution_space
Definition pressure.cpp:53
Matrix representation with static size.
Definition matrix.hpp:65