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