ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
core/system/System.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2014-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 "ResourceCleanup.hpp"
25
28
29#include "ek/Solver.hpp"
30#include "lb/Solver.hpp"
31
33
34#include <utils/Vector.hpp>
35
36#include <memory>
37#include <optional>
38#include <vector>
39
40class BoxGeometry;
41class LocalBox;
42class CellStructure;
43class Propagation;
46namespace Thermostat {
47class Thermostat;
48}
49class ComFixed;
50class Galilei;
51class Observable_stat;
52class OifGlobal;
54namespace CollisionDetection {
56}
57namespace BondBreakage {
58class BondBreakage;
59}
60namespace LeesEdwards {
61class LeesEdwards;
62}
63namespace Accumulators {
64class AutoUpdateAccumulators;
65}
66namespace Constraints {
67class Constraints;
68}
69struct SteepestDescent;
71struct NptIsoParameters;
73#ifdef ESPRESSO_CUDA
74class GpuParticleData;
75#endif
76
77namespace System {
78
79/**
80 * @brief Main system class.
81 *
82 * Most components follow the composite pattern and the opaque pointer pattern.
83 * See @ref SystemClassDesign for more details.
84 */
85class System : public std::enable_shared_from_this<System> {
86private:
87 struct Private {};
88 void initialize();
89
90public:
91 System(Private);
92
93 static std::shared_ptr<System> create();
94
95#ifdef ESPRESSO_CUDA
96 std::shared_ptr<GpuParticleData> gpu;
97#endif
99
100 /** @brief Get @ref time_step. */
101 auto get_time_step() const { return time_step; }
102
103 /** @brief Set @ref time_step. */
104 void set_time_step(double value);
105
106 /** @brief Get @ref sim_time. */
107 auto get_sim_time() const { return sim_time; }
108
109 /** @brief Set @ref sim_time. */
110 void set_sim_time(double value);
111
112 /** @brief Get @ref force_cap. */
113 auto get_force_cap() const { return force_cap; }
114
115 /** @brief Set @ref force_cap. */
116 void set_force_cap(double value);
117
118 /** @brief Get @ref min_global_cut. */
119 auto get_min_global_cut() const { return min_global_cut; }
120
121 /** @brief Set @ref min_global_cut. */
122 void set_min_global_cut(double value);
123
124 /** @brief Change the box dimensions. */
125 void set_box_l(Utils::Vector3d const &box_l);
126
127 /**
128 * @brief Tune the Verlet skin.
129 * Choose the optimal Verlet list skin between @p min_skin and @p max_skin
130 * by bisection to tolerance @p tol.
131 */
132 void tune_verlet_skin(double min_skin, double max_skin, double tol,
133 int int_steps, bool adjust_max_skin);
134
135 /** @brief Change cell structure topology. */
136 void set_cell_structure_topology(CellStructureType topology);
137
138 /** @brief Rebuild cell lists. Use e.g. after a skin change. */
139 void rebuild_cell_structure();
140#ifdef ESPRESSO_SHARED_MEMORY_PARALLELISM
141 void rebuild_aosoa();
142#endif
143
144 /** @brief Calculate the maximal cutoff of all interactions. */
145 double maximal_cutoff() const;
146
147 /** @brief Get the interaction range. */
148 double get_interaction_range() const;
149
150 unsigned get_global_ghost_flags() const;
151
152 /** Check electrostatic and magnetostatic methods are properly initialized.
153 * @return true if sanity checks failed.
154 */
155 bool long_range_interactions_sanity_checks() const;
156
157 /** @brief Calculate the total energy. */
158 std::shared_ptr<Observable_stat> calculate_energy();
159
160 /** @brief Calculate the pressure from a virial expansion. */
161 std::shared_ptr<Observable_stat> calculate_pressure();
162
163#ifdef ESPRESSO_NPT
164 /** @brief get the instantaneous pressure with (q(t+dt), p(t+dt/2))*/
166
167 /** @brief get the instantaneous virial pressure with q(t+dt)*/
169
170 /** @brief Synchronize NpT state such as instantaneous and average pressure */
171 void synchronize_npt_state();
172 /** @brief Reinitialize the NpT state. */
173 void npt_ensemble_init(bool recalc_forces);
174 void npt_add_virial_contribution(double energy);
175 bool has_npt_enabled() const;
176#endif // ESPRESSO_NPT
177 Utils::Vector3d *get_npt_virial() const;
178
179 /** @brief Calculate all forces. */
180 void calculate_forces();
181
182#ifdef ESPRESSO_DIPOLE_FIELD_TRACKING
183 /** @brief Calculate dipole fields. */
185#endif
186
187#ifdef ESPRESSO_COLLISION_DETECTION
188 bool has_collision_detection_enabled() const;
189#endif
190
191 /**
192 * @brief Compute the short-range energy of a particle.
193 *
194 * Iterate through particles inside cell and neighboring cells and compute
195 * energy contribution for a specific particle.
196 *
197 * @param pid Particle id
198 * @return Non-bonded energy of the particle.
199 */
200 double particle_short_range_energy_contribution(int pid);
201 /**
202 * @brief Compute the energy of a given bond which has to exist on the given
203 * particle.
204 *
205 * Requires that bond partners are visible on the same MPI rank as the
206 * primary particle.
207 * Returns nothing if the primary particle is not owned by this MPI rank.
208 *
209 * @param pid Particle id
210 * @param bond_id Bond id
211 * @param partners Particle ids of the bond partners
212 *
213 * @return energy of the bond given the primary particle and bond partners
214 */
215 std::optional<double> particle_bond_energy(int pid, int bond_id,
216 std::vector<int> partners);
217
218 /** Integrate equations of motion
219 * @param n_steps Number of integration steps, can be zero
220 * @param reuse_forces Decide when to re-calculate forces
221 *
222 * @details This function calls two hooks for propagation kernels such as
223 * velocity Verlet, velocity Verlet + NpT, or steepest descent.
224 * One hook is called before and one after the force calculation.
225 * It is up to the propagation kernels to increment the simulation time.
226 *
227 * This function propagates the system according to the choice of integrator
228 * stored in @ref Propagation::integ_switch. The general structure is:
229 * - if reuse_forces is zero, recalculate the forces based on the current
230 * state of the system
231 * - Loop over the number of simulation steps:
232 * -# initialization (e.g., RATTLE)
233 * -# First hook for propagation kernels
234 * -# Update dependent particles and properties (RATTLE, virtual sites)
235 * -# Calculate forces for the current state of the system. This includes
236 * forces added by the Langevin thermostat and the
237 * Lattice-Boltzmann-particle coupling
238 * -# Second hook for propagation kernels
239 * -# Update dependent properties (Virtual sites, RATTLE)
240 * -# Run single step algorithms (Lattice-Boltzmann propagation, collision
241 * detection, NpT update)
242 * - Final update of dependent properties and statistics/counters
243 *
244 * High-level documentation of the integration and thermostatting schemes
245 * can be found in doc/sphinx/system_setup.rst and /doc/sphinx/running.rst
246 *
247 * @return number of steps that have been integrated, or a negative error
248 * code
249 */
250 int integrate(int n_steps, int reuse_forces);
251
252 int integrate_with_signal_handler(int n_steps, int reuse_forces,
253 bool update_accumulators);
254
255 /** @brief Calculate particle-lattice interactions. */
256 void lb_couple_particles();
257
258 /** \name Hook procedures
259 * These procedures are called if several significant changes to
260 * the system happen which may make a reinitialization of subsystems
261 * necessary.
262 */
263 /**@{*/
264 /**
265 * @brief Called when the box length has changed. This routine is relatively
266 * fast, and changing the box length every time step as for example necessary
267 * for NpT is more or less ok.
268 *
269 * @param skip_method_adaption skip the long-range methods adaptions
270 */
271 void on_boxl_change(bool skip_method_adaption = false);
272 void on_node_grid_change();
273 void on_periodicity_change();
274 void on_cell_structure_change();
275 void on_thermostat_param_change();
276 void on_temperature_change();
277 void on_verlet_skin_change();
278 void on_timestep_change();
279 void on_integration_start();
280 void on_short_range_ia_change();
281 void on_non_bonded_ia_change();
282 void on_coulomb_change();
283 void on_dipoles_change();
284 /** @brief Called every time a constraint is changed. */
285 void on_constraint_change();
286 /** @brief Called when the LB boundary conditions change
287 * (geometry, slip velocity, or both).
288 */
289 void on_lb_boundary_conditions_change();
290 /** @brief Called every time a particle local property changes. */
291 void on_particle_local_change();
292 /** @brief Called every time a particle property changes. */
293 void on_particle_change();
294 /** @brief Called every time a particle charge changes. */
295 void on_particle_charge_change();
296 /** called before calculating observables, i.e. energy, pressure or
297 * the integrator (forces). Initialize any methods here which are not
298 * initialized immediately (P3M etc.).
299 */
300 void on_observable_calc();
301 void on_lees_edwards_change();
302 void veto_boxl_change(bool skip_particle_checks = false) const;
303 /**@}*/
304
305 /**
306 * @brief Update particles with properties depending on other particles,
307 * namely virtual sites and ICC charges.
308 */
309 void update_dependent_particles();
310 /**
311 * @brief Update the global propagation bitmask.
312 */
313 void update_used_propagations();
314 /**
315 * @brief Veto temperature change.
316 */
317 void check_kT(double value) const;
318
323 std::shared_ptr<BoxGeometry> box_geo;
324 std::shared_ptr<LocalBox> local_geo;
325 std::shared_ptr<CellStructure> cell_structure;
326 std::shared_ptr<Propagation> propagation;
327 std::shared_ptr<BondedInteractionsMap> bonded_ias;
328 std::shared_ptr<InteractionsNonBonded> nonbonded_ias;
329 std::shared_ptr<Thermostat::Thermostat> thermostat;
330 std::shared_ptr<ComFixed> comfixed;
331 std::shared_ptr<Galilei> galilei;
332 std::shared_ptr<OifGlobal> oif_global;
333 std::shared_ptr<ImmersedBoundaries> immersed_boundaries;
334#ifdef ESPRESSO_COLLISION_DETECTION
335 std::shared_ptr<CollisionDetection::CollisionDetection> collision_detection;
336#endif
337 std::shared_ptr<BondBreakage::BondBreakage> bond_breakage;
338 std::shared_ptr<LeesEdwards::LeesEdwards> lees_edwards;
339 std::shared_ptr<Accumulators::AutoUpdateAccumulators>
341 std::shared_ptr<Constraints::Constraints> constraints;
342 std::shared_ptr<SteepestDescent> steepest_descent;
343#ifdef ESPRESSO_STOKESIAN_DYNAMICS
344 std::shared_ptr<StokesianDynamics> stokesian_dynamics;
345#endif
346#ifdef ESPRESSO_NPT
347 std::shared_ptr<NptIsoParameters> nptiso;
348 std::shared_ptr<InstantaneousPressure> npt_inst_pressure;
349#endif
350
351protected:
352 /** @brief Whether the thermostat has to be reinitialized before integration.
353 */
355 /** @brief Molecular dynamics integrator time step. */
356 double time_step;
357 /** @brief Molecular dynamics integrator simulation time. */
358 double sim_time;
359 /** @brief Molecular dynamics integrator force capping. */
360 double force_cap;
361 /**
362 * @brief Minimal global interaction cutoff.
363 * Particles with a distance smaller than this are guaranteed
364 * to be available on the same node (through ghosts).
365 */
367
368 void update_local_geo();
369#ifdef ESPRESSO_ELECTROSTATICS
370 void update_icc_particles();
371 bool has_icc_enabled() const;
372#endif // ESPRESSO_ELECTROSTATICS
373#ifdef ESPRESSO_THERMAL_STONER_WOHLFARTH
374 void integrate_magnetodynamics();
375#endif
376
377private:
378 /**
379 * @brief Check integrator parameters and incompatibilities between
380 * the integrator and the currently active thermostat(s).
381 */
382 void integrator_sanity_checks() const;
383};
384
386void set_system(std::shared_ptr<System> new_instance);
387void reset_system();
388
389} // namespace System
CellStructureType
Cell structure topology.
Vector implementation and trait types for boost qvm interoperability.
container for bonded interactions.
Describes a cell structure / cell system.
Particle data communication manager for the GPU.
Observable for the pressure and energy.
Queue to deallocate resources before normal program termination.
double get_instantaneous_pressure_virial()
get the instantaneous virial pressure with q(t+dt)
auto get_time_step() const
Get time_step.
std::shared_ptr< StokesianDynamics > stokesian_dynamics
std::shared_ptr< LeesEdwards::LeesEdwards > lees_edwards
double sim_time
Molecular dynamics integrator simulation time.
std::shared_ptr< LocalBox > local_geo
std::shared_ptr< BondedInteractionsMap > bonded_ias
double min_global_cut
Minimal global interaction cutoff.
auto get_min_global_cut() const
Get min_global_cut.
bool reinit_thermo
Whether the thermostat has to be reinitialized before integration.
std::shared_ptr< ImmersedBoundaries > immersed_boundaries
std::shared_ptr< Accumulators::AutoUpdateAccumulators > auto_update_accumulators
std::shared_ptr< ComFixed > comfixed
std::shared_ptr< BondBreakage::BondBreakage > bond_breakage
Dipoles::Solver dipoles
std::shared_ptr< CollisionDetection::CollisionDetection > collision_detection
double get_instantaneous_pressure()
get the instantaneous pressure with (q(t+dt), p(t+dt/2))
std::shared_ptr< InstantaneousPressure > npt_inst_pressure
std::shared_ptr< OifGlobal > oif_global
std::shared_ptr< NptIsoParameters > nptiso
double force_cap
Molecular dynamics integrator force capping.
ResourceCleanup cleanup_queue
std::shared_ptr< Propagation > propagation
double time_step
Molecular dynamics integrator time step.
void calculate_long_range_fields()
Calculate dipole fields.
std::shared_ptr< SteepestDescent > steepest_descent
std::shared_ptr< GpuParticleData > gpu
std::shared_ptr< Thermostat::Thermostat > thermostat
std::shared_ptr< CellStructure > cell_structure
std::shared_ptr< Constraints::Constraints > constraints
auto get_force_cap() const
Get force_cap.
auto get_sim_time() const
Get sim_time.
Coulomb::Solver coulomb
std::shared_ptr< BoxGeometry > box_geo
std::shared_ptr< Galilei > galilei
std::shared_ptr< InteractionsNonBonded > nonbonded_ias
System & get_system()
void set_system(std::shared_ptr< System > new_instance)
Instantaneous pressure during force calculation for NPT integration.
Definition npt.hpp:92
Parameters of the isotropic NpT-integration scheme.
Definition npt.hpp:42
Steepest descent algorithm.