ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
core/thermostat.hpp
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#pragma once
23
24/** \file
25 * Implementation in \ref thermostat.cpp.
26 */
27
28#include <config/config.hpp>
29
30#include "Particle.hpp"
31#include "PropagationMode.hpp"
32#include "rotation.hpp"
33#include "system/Leaf.hpp"
34
35#include <utils/Counter.hpp>
36#include <utils/Vector.hpp>
37#include <utils/matrix.hpp>
38
39#include <cassert>
40#include <cmath>
41#include <cstdint>
42#include <memory>
43#include <unordered_map>
44#include <vector>
45
46namespace Thermostat {
47#ifdef ESPRESSO_PARTICLE_ANISOTROPY
49#else
50using GammaType = double;
51#endif
52/**
53 * @brief Value for unset friction coefficient.
54 * Sentinel value for the Langevin/Brownian parameters,
55 * indicating that they have not been set yet.
56 */
57#ifdef ESPRESSO_PARTICLE_ANISOTROPY
58constexpr GammaType gamma_sentinel{{-1.0, -1.0, -1.0}};
59#else
60constexpr GammaType gamma_sentinel{-1.0};
61#endif
62/**
63 * @brief Value for a null friction coefficient.
64 */
65#ifdef ESPRESSO_PARTICLE_ANISOTROPY
66constexpr GammaType gamma_null{{0.0, 0.0, 0.0}};
67#else
68constexpr GammaType gamma_null{0.0};
69#endif
70
71#ifdef ESPRESSO_THERMOSTAT_PER_PARTICLE
76#endif
77
79 GammaType const &gamma_body) {
80#ifdef ESPRESSO_PARTICLE_ANISOTROPY
81 auto const aniso_flag =
82 (gamma_body[0] != gamma_body[1]) || (gamma_body[1] != gamma_body[2]);
84 boost::qvm::diag_mat(gamma_body);
85 auto const gamma_space =
87 return gamma_space;
88#else
89 return gamma_body;
90#endif
91}
92
93/** @brief Check that two kT values are close up to a small tolerance. */
94inline bool are_kT_equal(double old_kT, double new_kT) {
95 constexpr auto relative_tolerance = 1e-6;
96 if (old_kT == 0. and new_kT == 0.) {
97 return true;
98 }
99 if ((old_kT < 0. and new_kT >= 0.) or (old_kT >= 0. and new_kT < 0.)) {
100 return false;
101 }
102 auto const large_kT = (old_kT > new_kT) ? old_kT : new_kT;
103 auto const small_kT = (old_kT > new_kT) ? new_kT : old_kT;
104 if (small_kT == 0.) {
105 return false;
106 }
107 return (large_kT / small_kT - 1. < relative_tolerance);
108}
109} // namespace Thermostat
110
112public:
113 /** Initialize or re-initialize the RNG counter with a seed. */
114 void rng_initialize(uint32_t const seed) {
115 m_rng_seed = seed;
116 m_initialized = true;
117 }
118 /** Increment the RNG counter */
119 void rng_increment() { m_rng_counter.increment(); }
120 /** Get current value of the RNG */
121 uint64_t rng_counter() const { return m_rng_counter.value(); }
123 m_rng_counter = Utils::Counter<uint64_t>(uint64_t{0u}, value);
124 }
125 /** Is the RNG seed required */
126 bool is_seed_required() const { return not m_initialized; }
127 uint32_t rng_seed() const { return m_rng_seed; }
128
129private:
130 /** @brief RNG counter. */
131 Utils::Counter<uint64_t> m_rng_counter{uint64_t{0u}, uint64_t{0u}};
132 /** @brief RNG seed. */
133 uint32_t m_rng_seed{0u};
134 bool m_initialized{false};
135};
136
137/** Thermostat for Langevin dynamics. */
139private:
141
142public:
143 /** Recalculate prefactors.
144 * Needs to be called every time the parameters are changed.
145 */
146 void recalc_prefactors(double kT, double time_step) {
148 pref_noise = sigma(kT, time_step, gamma);
149#ifdef ESPRESSO_ROTATION
150 pref_noise_rotation = sigma(kT, time_step, gamma_rotation);
151#endif // ESPRESSO_ROTATION
152 }
153 /** Calculate the noise prefactor.
154 * Evaluates the quantity @f$ \sqrt{2 k_B T \gamma / dt} / \sigma_\eta @f$
155 * with @f$ \sigma_\eta @f$ the standard deviation of the random uniform
156 * process @f$ \eta(t) @f$.
157 */
158 static GammaType sigma(double kT, double time_step, GammaType const &gamma) {
159 // random uniform noise has variance 1/12
160 constexpr auto const temp_coeff = 2.0 * 12.0;
161 return sqrt((temp_coeff * kT / time_step) * gamma);
162 }
163 /** @name Parameters */
164 /**@{*/
165 /** Translational friction coefficient @f$ \gamma_{\text{trans}} @f$. */
167#ifdef ESPRESSO_ROTATION
168 /** Rotational friction coefficient @f$ \gamma_{\text{rot}} @f$. */
170#endif // ESPRESSO_ROTATION
171 /**@}*/
172 /** @name Prefactors */
173 /**@{*/
174 /** Prefactor for the friction.
175 * Stores @f$ \gamma_{\text{trans}} @f$.
176 */
178 /** Prefactor for the translational velocity noise.
179 * Stores @f$ \sqrt{2 k_B T \gamma_{\text{trans}} / dt} / \sigma_\eta @f$.
180 */
182#ifdef ESPRESSO_ROTATION
183 /** Prefactor for the angular velocity noise.
184 * Stores @f$ \sqrt{2 k_B T \gamma_{\text{rot}} / dt} / \sigma_\eta @f$.
185 */
187#endif // ESPRESSO_ROTATION
188 /**@}*/
189};
190
191/** Thermostat for Brownian dynamics.
192 * Default particle mass is assumed to be unitary in these global parameters.
193 */
195private:
197
198public:
199 /** Recalculate prefactors.
200 * Needs to be called every time the parameters are changed.
201 */
202 void recalc_prefactors(double kT) {
203 /** The heat velocity dispersion corresponds to the Gaussian noise only,
204 * which is only valid for the BD. Just a square root of kT, see (10.2.17)
205 * and comments in 2 paragraphs afterwards, @cite pottier10a.
206 */
207 sigma_vel = sigma(kT);
208 /** The random walk position dispersion is defined by the second eq. (14.38)
209 * of @cite schlick10a. Its time interval factor will be added in the
210 * Brownian Dynamics functions. Its square root is the standard deviation.
211 */
212 sigma_pos = sigma(kT, gamma);
213#ifdef ESPRESSO_ROTATION
214 /** Note: the BD thermostat assigns the Brownian viscous parameters as well.
215 * They correspond to the friction tensor Z from the eq. (14.31) of
216 * @cite schlick10a.
217 */
220#endif // ESPRESSO_ROTATION
221 }
222 /** Calculate the noise prefactor.
223 * Evaluates the quantity @f$ \sqrt{2 k_B T / \gamma} / \sigma_\eta @f$
224 * with @f$ \sigma_\eta @f$ the standard deviation of the random Gaussian
225 * process @f$ \eta(t) @f$.
226 */
227 static GammaType sigma(double kT, GammaType const &gamma) {
228 constexpr auto const temp_coeff = 2.0;
229 return sqrt(Utils::hadamard_division(temp_coeff * kT, gamma));
230 }
231 /** Calculate the noise prefactor.
232 * Evaluates the quantity @f$ \sqrt{k_B T} / \sigma_\eta @f$
233 * with @f$ \sigma_\eta @f$ the standard deviation of the random Gaussian
234 * process @f$ \eta(t) @f$.
235 */
236 static double sigma(double kT) {
237 constexpr auto const temp_coeff = 1.0;
238 return sqrt(temp_coeff * kT);
239 }
240 /** @name Parameters */
241 /**@{*/
242 /** Translational friction coefficient @f$ \gamma_{\text{trans}} @f$. */
244 /** Rotational friction coefficient @f$ \gamma_{\text{rot}} @f$. */
246 /**@}*/
247 /** @name Prefactors */
248 /**@{*/
249 /** Translational noise standard deviation.
250 * Stores @f$ \sqrt{2D_{\text{trans}}} @f$ with
251 * @f$ D_{\text{trans}} = k_B T/\gamma_{\text{trans}} @f$
252 * the translational diffusion coefficient.
253 */
255#ifdef ESPRESSO_ROTATION
256 /** Rotational noise standard deviation.
257 * Stores @f$ \sqrt{2D_{\text{rot}}} @f$ with
258 * @f$ D_{\text{rot}} = k_B T/\gamma_{\text{rot}} @f$
259 * the rotational diffusion coefficient.
260 */
262#endif // ESPRESSO_ROTATION
263 /** Translational velocity noise standard deviation.
264 * Stores @f$ \sqrt{k_B T} @f$.
265 */
266 double sigma_vel = 0.;
267#ifdef ESPRESSO_ROTATION
268 /** Angular velocity noise standard deviation.
269 * Stores @f$ \sqrt{k_B T} @f$.
270 */
272#endif // ESPRESSO_ROTATION
273 /**@}*/
274};
275
276#ifdef ESPRESSO_NPT
277/** Thermostat for isotropic NPT dynamics. */
279private:
281
282public:
283 /** Recalculate prefactors.
284 * Needs to be called every time the parameters are changed.
285 */
286 void recalc_prefactors(double kT, double piston,
287 std::vector<double> const &mass_list,
288 double time_step) {
289 assert(piston > 0.0);
290
291 for (const auto &mass : mass_list) {
292 pref_rescale_0[mass] = std::exp(-gamma0 * time_step / mass);
293 pref_noise_0[mass] =
294 sigma_OU(kT, gamma0 / mass, time_step) / std::sqrt(mass);
295 }
296 pref_rescale_V = std::exp(-gammav * time_step / piston);
297 pref_noise_V = sigma_OU(kT, gammav / piston, time_step) * std::sqrt(piston);
298 }
299 /** Calculate the noise prefactor.
300 * Evaluates the quantity @f$ \sqrt{2 k_B T \gamma dt / 2} / \sigma_\eta @f$
301 * with @f$ \sigma_\eta @f$ the standard deviation of the random uniform
302 * process @f$ \eta(t) @f$.
303 */
304 static double sigma(double kT, double gamma, double time_step) {
305 // random uniform noise has variance 1/12; the temperature
306 // coefficient of 2 is canceled out by the half time step
307 constexpr auto const temp_coeff = 12.0;
308 return sqrt(temp_coeff * kT * gamma * time_step);
309 }
310 /** Calculate the noise prefactor for the exact solution
311 * of Orstein-Uhlenbeck equation.
312 * Evaluates the quantity @f$ \sqrt{k_B T (1 - \exp(-2 \gamma dt)} @f$
313 */
314 static double sigma_OU(double kT, double gamma, double time_step) {
315 return std::sqrt(kT * (1.0 - std::exp(-2. * gamma * time_step)));
316 }
317 /** @name Parameters */
318 /**@{*/
319 /** Friction coefficient of the particles @f$ \gamma^0 @f$ */
320 double gamma0 = 0.;
321 /** Friction coefficient for the box @f$ \gamma^V @f$ */
322 double gammav = 0.;
323 /**@}*/
324 /** @name Prefactors */
325 /**@{*/
326 /** Particle velocity rescaling at the time step for
327 * Orstein-Uhlenbeck equation.
328 * Stores @f$ \exp(-\frac{\gamma^{0}}{m} \cdot dt) @f$.
329 */
330 std::unordered_map<double, double> pref_rescale_0;
331 /** Particle velocity rescaling noise standard deviation for
332 * Orstein-Uhlenbeck equation.
333 * Stores @f$ \sqrt{k_B T ( 1 - \exp( -2 \frac{\gamma^{0}}{m} dt}) @f$
334 */
335 std::unordered_map<double, double> pref_noise_0;
336 /** Volume rescaling at half the time step.
337 * Stores @f$ \exp(-\frac{\gamma^{V}}{W} \cdot dt) @f$.
338 */
339 double pref_rescale_V = 0.;
340 /** Volume rescaling noise standard deviation for
341 * Orstein-Uhlenbeck equation
342 * Stores @f$ \sqrt{k_B T ( 1 - \exp( -2 \frac{\gamma^{0}}{W} dt}) @f$
343 */
344 double pref_noise_V = 0.;
345 /**@}*/
346};
347#endif
348
349/** Thermostat for lattice-Boltzmann particle coupling. */
351 /** @name Parameters */
352 /**@{*/
353 /** Friction coefficient. */
354 double gamma = -1.;
355 /** Internal flag to disable particle coupling during force recalculation. */
356 bool couple_to_md = false;
357 /**@}*/
358};
359
361
362/** Thermostat for thermalized bonds. */
364 void recalc_prefactors(double time_step, BondedInteractionsMap &bonded_ias);
365};
366
367#ifdef ESPRESSO_DPD
368/** Thermostat for dissipative particle dynamics. */
369struct DPDThermostat : public BaseThermostat {};
370#endif
371
372#ifdef ESPRESSO_STOKESIAN_DYNAMICS
373/** Thermostat for Stokesian dynamics. */
377#endif
378
379namespace Thermostat {
380class Thermostat : public System::Leaf<Thermostat> {
381public:
382 /** @brief Thermal energy of the simulated heat bath. */
383 double kT = -1.;
384 /** @brief Bitmask of currently active thermostats. */
385 int thermo_switch = THERMO_OFF;
386 std::shared_ptr<LangevinThermostat> langevin;
387 std::shared_ptr<BrownianThermostat> brownian;
388#ifdef ESPRESSO_NPT
389 std::shared_ptr<IsotropicNptThermostat> npt_iso;
390#endif
391 std::shared_ptr<LBThermostat> lb;
392#ifdef ESPRESSO_DPD
393 std::shared_ptr<DPDThermostat> dpd;
394#endif
395#ifdef ESPRESSO_STOKESIAN_DYNAMICS
396 std::shared_ptr<StokesianThermostat> stokesian;
397#endif
398 std::shared_ptr<ThermalizedBondThermostat> thermalized_bond;
399
400 /** Increment RNG counters */
401 void philox_counter_increment();
402
403 /** Initialize constants of all thermostats. */
404 void recalc_prefactors(double time_step);
405
407 if (lb) {
408 lb->couple_to_md = true;
409 }
410 }
411 void lb_coupling_deactivate();
412};
413} // namespace Thermostat
@ THERMO_OFF
Vector implementation and trait types for boost qvm interoperability.
container for bonded interactions.
Abstract class that represents a component of the system.
std::shared_ptr< BrownianThermostat > brownian
std::shared_ptr< ThermalizedBondThermostat > thermalized_bond
std::shared_ptr< LangevinThermostat > langevin
std::shared_ptr< DPDThermostat > dpd
std::shared_ptr< LBThermostat > lb
std::shared_ptr< IsotropicNptThermostat > npt_iso
std::shared_ptr< StokesianThermostat > stokesian
T value() const
Definition Counter.hpp:43
void increment()
Definition Counter.hpp:41
cudaStream_t stream[1]
CUDA streams for parallel computing on CPU and GPU.
Matrix implementation and trait types for boost qvm interoperability.
bool are_kT_equal(double old_kT, double new_kT)
Check that two kT values are close up to a small tolerance.
Utils::Vector3d GammaType
constexpr GammaType gamma_sentinel
Value for unset friction coefficient.
constexpr GammaType gamma_null
Value for a null friction coefficient.
auto handle_particle_anisotropy(Particle const &p, GammaType const &gamma_body)
auto const & handle_particle_gamma(GammaType const &particle_gamma, GammaType const &default_gamma)
VectorXd< 3 > Vector3d
Definition Vector.hpp:184
auto hadamard_division(Vector< T, N > const &a, Vector< U, N > const &b)
Definition Vector.hpp:394
This file contains all subroutines required to process rotational motion.
auto convert_body_to_space(const Utils::Quaternion< double > &quat, const Utils::Matrix< T, 3, 3 > &A)
Transform matrix from body- to space-fixed frame.
Definition rotation.hpp:87
uint64_t rng_counter() const
Get current value of the RNG.
uint32_t rng_seed() const
void rng_increment()
Increment the RNG counter.
bool is_seed_required() const
Is the RNG seed required.
void rng_initialize(uint32_t const seed)
Initialize or re-initialize the RNG counter with a seed.
void set_rng_counter(uint64_t value)
Thermostat for Brownian dynamics.
GammaType gamma
Translational friction coefficient .
GammaType gamma_rotation
Rotational friction coefficient .
void recalc_prefactors(double kT)
Recalculate prefactors.
GammaType sigma_pos
Translational noise standard deviation.
double sigma_vel_rotation
Angular velocity noise standard deviation.
double sigma_vel
Translational velocity noise standard deviation.
GammaType sigma_pos_rotation
Rotational noise standard deviation.
static GammaType sigma(double kT, GammaType const &gamma)
Calculate the noise prefactor.
static double sigma(double kT)
Calculate the noise prefactor.
Thermostat for dissipative particle dynamics.
Thermostat for isotropic NPT dynamics.
std::unordered_map< double, double > pref_noise_0
Particle velocity rescaling noise standard deviation for Orstein-Uhlenbeck equation.
static double sigma_OU(double kT, double gamma, double time_step)
Calculate the noise prefactor for the exact solution of Orstein-Uhlenbeck equation.
double pref_rescale_V
Volume rescaling at half the time step.
void recalc_prefactors(double kT, double piston, std::vector< double > const &mass_list, double time_step)
Recalculate prefactors.
double gamma0
Friction coefficient of the particles .
double gammav
Friction coefficient for the box .
double pref_noise_V
Volume rescaling noise standard deviation for Orstein-Uhlenbeck equation Stores .
std::unordered_map< double, double > pref_rescale_0
Particle velocity rescaling at the time step for Orstein-Uhlenbeck equation.
static double sigma(double kT, double gamma, double time_step)
Calculate the noise prefactor.
Thermostat for lattice-Boltzmann particle coupling.
bool couple_to_md
Internal flag to disable particle coupling during force recalculation.
double gamma
Friction coefficient.
Thermostat for Langevin dynamics.
GammaType pref_friction
Prefactor for the friction.
static GammaType sigma(double kT, double time_step, GammaType const &gamma)
Calculate the noise prefactor.
GammaType gamma_rotation
Rotational friction coefficient .
GammaType gamma
Translational friction coefficient .
void recalc_prefactors(double kT, double time_step)
Recalculate prefactors.
GammaType pref_noise
Prefactor for the translational velocity noise.
GammaType pref_noise_rotation
Prefactor for the angular velocity noise.
Struct holding all information for one particle.
Definition Particle.hpp:435
Thermostat for Stokesian dynamics.
Thermostat for thermalized bonds.
void recalc_prefactors(double time_step, BondedInteractionsMap &bonded_ias)
Matrix representation with static size.
Definition matrix.hpp:65