ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
velocity_verlet_npt_MTK.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-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#include <config/config.hpp>
21
22#ifdef ESPRESSO_NPT
24
25#include "BoxGeometry.hpp"
26#include "Particle.hpp"
28#include "communication.hpp"
29#include "errorhandling.hpp"
30#include "system/System.hpp"
32
33#include <utils/Vector.hpp>
34
35#include <boost/mpi/collectives.hpp>
36
37#include <cmath>
38#include <functional>
39
40/**
41 * @brief Scale and communicate instantaneous NpT pressure and
42 * propagate the conjugate momentum for volume.
43 * @f$ p_{\epsilon}(t+dt) = p_{\epsilon}(t)
44 * + 3 V (P_{\text{inst}} - P_{\text{ext}}) dt / 2 @f$
45 */
46static void
48 InstantaneousPressure &npt_inst_pressure,
49 double time_step) {
50 /* finalize derivation of p_inst */
51 npt_inst_pressure.p_inst = {0., 0.};
52
53 for (auto i = 0u; i < 3u; ++i) {
55 npt_inst_pressure.p_inst[0] +=
56 npt_inst_pressure.p_vir[i] + npt_inst_pressure.p_vel[i];
57 npt_inst_pressure.p_inst[1] += npt_inst_pressure.p_vir[i];
58 }
59 }
60
61 Utils::Vector2d p_sum = {0., 0.};
62 boost::mpi::reduce(::comm_cart, npt_inst_pressure.p_inst, p_sum,
63 std::plus<Utils::Vector2d>(), 0);
64
65 /* propagate p_epsilon */
66 if (::this_node == 0) {
67 npt_inst_pressure.p_inst = p_sum / (nptiso.dimension * nptiso.volume);
68 nptiso.p_epsilon += nptiso.volume *
69 (npt_inst_pressure.p_inst[0] - nptiso.p_ext) * 1.5 *
70 time_step;
71 if (nptiso.particle_number > 1) {
72 nptiso.p_epsilon +=
73 (p_sum[0] - p_sum[1]) *
74 (0.5 / static_cast<double>(nptiso.particle_number - 1)) * time_step;
75 }
76 }
77 boost::mpi::broadcast(::comm_cart, nptiso.p_epsilon, 0);
78}
79
80/* propagate positions with dt/2;
81 * @f$ pos[t+0.5*dt] = pos[t] + vel[t+0.5*dt] * 0.5 * dt @f$
82 */
84 double time_step) {
85 for (auto &p : particles) {
86 for (auto j = 0u; j < 3u; ++j) {
87 if (!p.is_fixed_along(j)) {
88 p.pos()[j] = p.pos()[j] + p.v()[j] * 0.5 * time_step;
89 }
90 }
91 }
92}
93
94/* rescaling positions based on MTK equation;
95 * @f$ pos[t] = \exp(0.5 * dt * p_{\epsilon} / W) * pos[t] @f$
96 */
97static void
99 ParticleRangeNPT const &particles) {
100 auto const propagator =
101 std::exp(nptiso.half_dt_inv_piston * nptiso.p_epsilon);
102
103 for (auto &p : particles) {
104 for (auto j = 0u; j < 3u; ++j) {
105 if (!p.is_fixed_along(j)) {
106 if (nptiso.geometry & NptIsoParameters::nptgeom_dir[j]) {
107 p.pos()[j] *= propagator;
108 }
109 }
110 }
111 }
112}
113
114/**
115 * @brief propagate positions and the volume and add thermal fluctuation.
116 * A and V are the position and volume propagators for half-time step.
117 * O is the propagator corresponding to Ornstein-Uhlenbeck process
118 * representing the stochastic thermostat.
119 * The time evolution follows the sequence A-V-O-V-A in this function,
120 * with propagators applied right to left.
121 */
123 ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso,
124 double time_step, System::System &system) {
125
126 auto &box_geo = *system.box_geo;
127 auto &cell_structure = *system.cell_structure;
128 auto &nptiso = *system.nptiso;
129 double L_new = 0.0;
130
131 /* 1st propagation pos_MTK and pos*/
132 velocity_verlet_npt_propagate_pos_MTK(nptiso, particles);
133 velocity_verlet_npt_propagate_pos(particles, time_step);
134
135 /* stochastic reservoirs for conjugate momentum for particles
136 * @f$ p(t+0.5*dt) = p(t+0.5*dt) \exp(- \gamma_0 dt / m)
137 * + \sqrt{k_B T (1 - \exp(-2 \gamma_0 dt)}N(0,1) @f$
138 */
139 for (auto &p : particles) {
140 auto const v_therm =
141 propagate_therm0_nptiso(npt_iso, p.v(), p.mass(), p.id());
142 for (unsigned int j = 0; j < 3; j++) {
143 if (!p.is_fixed_along(j)) {
144 if (nptiso.geometry & NptIsoParameters::nptgeom_dir[j]) {
145 p.v()[j] = v_therm[j];
146 }
147 }
148 }
149 }
150
151 /* 1st propagation: volume with dt/2
152 * @f$ V(t+0.5*dt) = \exp(0.5 * dt * 3 * p_{\epsilon} / W) * V(t) @f$,
153 * stochastic reservoirs for conjugate momentum for V
154 * @f$ p_{\epsilon} = p_{epsilon}(t) \exp(- \gamma_V dt / W)
155 * + \sqrt{k_B T (1 - \exp(-2 \gamma_V dt / W)}N(0,1) @f$,
156 * 2nd propagation: volume with dt/2
157 * @f$ V(t+dt) = \exp(0.5 * dt * 3 * p_{\epsilon} / W) * V(t+0.5*dt) @f$,
158 */
159 if (::this_node == 0) {
160 nptiso.volume *=
161 std::exp(1.5 * nptiso.inv_piston * nptiso.p_epsilon * time_step);
162 nptiso.p_epsilon = propagate_thermV_nptiso(npt_iso, nptiso.p_epsilon);
163 nptiso.volume *=
164 std::exp(1.5 * nptiso.inv_piston * nptiso.p_epsilon * time_step);
165 L_new = std::pow(nptiso.volume, 1.0 / nptiso.dimension);
166 }
167
168 /* 2nd propagation pos and pos_MTK*/
169 velocity_verlet_npt_propagate_pos(particles, time_step);
170 velocity_verlet_npt_propagate_pos_MTK(nptiso, particles);
171
172 cell_structure.set_resort_particles(Cells::RESORT_LOCAL);
173
174 /* Apply new volume to the box-length, communicate it, and account for
175 * necessary adjustments to the cell geometry */
176 Utils::Vector3d new_box;
177
178 if (::this_node == 0) {
179 new_box = box_geo.length();
180 for (auto i = 0u; i < 3u; ++i) {
181 if (nptiso.cubic_box ||
182 nptiso.geometry & NptIsoParameters::nptgeom_dir[i]) {
183 new_box[i] = L_new;
184 }
185 }
186 }
187
188 boost::mpi::broadcast(::comm_cart, new_box, 0);
189
190 box_geo.set_length(new_box);
191 // fast box length update
192 system.on_boxl_change(true);
193}
194
195/* rescaling momentum based on MTK equation;
196 * @f$ vel[t] = \exp(-0.5 * dt * p_{\epsilon} * (1 + 1 / (N - 1)) / W) * vel[t]
197 * @f$
198 */
199static void
201 InstantaneousPressure &npt_inst_pressure,
202 ParticleRangeNPT const &particles) {
203 npt_inst_pressure.p_vel = {};
204 auto const propagater =
205 std::exp(nptiso.half_dt_inv_piston_and_Nf * nptiso.p_epsilon);
206
207 for (auto &p : particles) {
208 for (auto j = 0u; j < 3u; ++j) {
209 if (!p.is_fixed_along(j)) {
210 if (nptiso.geometry & NptIsoParameters::nptgeom_dir[j]) {
211 p.v()[j] *= propagater;
212 npt_inst_pressure.p_vel[j] += Utils::sqr(p.v()[j]) * p.mass();
213 }
214 }
215 }
216 }
217}
218
220 IsotropicNptThermostat const &npt_iso,
221 double time_step, System::System &system) {
222 auto &nptiso = *system.nptiso;
223 auto &npt_inst_pressure = *system.npt_inst_pressure;
224 velocity_verlet_npt_propagate_vel_MTK(nptiso, npt_inst_pressure, particles);
225 velocity_verlet_npt_propagate_p_eps(nptiso, npt_inst_pressure, time_step);
226 velocity_verlet_npt_propagate_vel(nptiso, npt_inst_pressure, particles,
227 time_step);
228 velocity_verlet_npt_propagate_AVOVA_MTK(particles, npt_iso, time_step,
229 system);
230}
231
233 double time_step, System::System &system) {
234 auto &nptiso = *system.nptiso;
235 auto &npt_inst_pressure = *system.npt_inst_pressure;
236 velocity_verlet_npt_propagate_vel(nptiso, npt_inst_pressure, particles,
237 time_step);
238 velocity_verlet_npt_propagate_p_eps(nptiso, npt_inst_pressure, time_step);
239 velocity_verlet_npt_propagate_vel_MTK(nptiso, npt_inst_pressure, particles);
240}
241
242#endif // ESPRESSO_NPT
Vector implementation and trait types for boost qvm interoperability.
Main system class.
void on_boxl_change(bool skip_method_adaption=false)
Called when the box length has changed.
std::shared_ptr< InstantaneousPressure > npt_inst_pressure
std::shared_ptr< NptIsoParameters > nptiso
std::shared_ptr< CellStructure > cell_structure
std::shared_ptr< BoxGeometry > box_geo
boost::mpi::communicator comm_cart
The communicator.
int this_node
The number of this node.
This file contains the errorhandling code for severe errors, like a broken bond or illegal parameter ...
DEVICE_QUALIFIER constexpr T sqr(T x)
Calculates the SQuaRe of x.
Definition sqr.hpp:28
double propagate_thermV_nptiso(IsotropicNptThermostat const &npt_iso, double p_epsilon)
Added noise and friction for NpT-sims to NptIsoParameters::p_epsilon; .
Utils::Vector3d propagate_therm0_nptiso(IsotropicNptThermostat const &npt_iso, Utils::Vector3d const &vel, double mass, int p_identity)
Add velocity-dependent noise and friction for NpT-sims to the particle's velocity; .
Instantaneous pressure during force calculation for NPT integration.
Definition npt.hpp:92
Utils::Vector3d p_vel
ideal gas components of p_inst, derived from the velocities
Definition npt.hpp:99
Utils::Vector3d p_vir
virial (short-range) components of p_inst
Definition npt.hpp:97
Utils::Vector2d p_inst
instantaneous pressure for p_inst[0] and virial pressure for p_inst[1] the system currently has
Definition npt.hpp:95
Thermostat for isotropic NPT dynamics.
Parameters of the isotropic NpT-integration scheme.
Definition npt.hpp:42
std::size_t particle_number
number of particles
Definition npt.hpp:57
int geometry
geometry information for the NpT integrator.
Definition npt.hpp:72
static constexpr std::array< int, 3 > nptgeom_dir
Definition npt.hpp:88
double half_dt_inv_piston_and_Nf
the coefficient of propagation of momentum for MTK equation
Definition npt.hpp:65
double half_dt_inv_piston
the coefficient of propagation of position for MTK equation
Definition npt.hpp:63
double p_ext
desired pressure to which the algorithm strives to
Definition npt.hpp:59
int dimension
The number of dimensions in which NpT boxlength motion is coupled to particles.
Definition npt.hpp:75
double p_epsilon
conjugate momentum of volume
Definition npt.hpp:61
double volume
isotropic volume.
Definition npt.hpp:53
void velocity_verlet_npt_propagate_vel(NptIsoParameters const &nptiso, InstantaneousPressure &npt_inst_pressure, ParticleRangeNPT const &particles, double time_step)
Propagate the particle's velocity.
void velocity_verlet_npt_MTK_step_1(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step, System::System &system)
Special propagator for velocity Verlet NpT with the Andersen method.
static void velocity_verlet_npt_propagate_vel_MTK(NptIsoParameters const &nptiso, InstantaneousPressure &npt_inst_pressure, ParticleRangeNPT const &particles)
static void velocity_verlet_npt_propagate_p_eps(NptIsoParameters &nptiso, InstantaneousPressure &npt_inst_pressure, double time_step)
Scale and communicate instantaneous NpT pressure and propagate the conjugate momentum for volume.
static void velocity_verlet_npt_propagate_AVOVA_MTK(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step, System::System &system)
propagate positions and the volume and add thermal fluctuation.
static void velocity_verlet_npt_propagate_pos_MTK(NptIsoParameters &nptiso, ParticleRangeNPT const &particles)
void velocity_verlet_npt_MTK_step_2(ParticleRangeNPT const &particles, double time_step, System::System &system)
Final integration step of the velocity Verlet NpT integrator with the MTK method.
static void velocity_verlet_npt_propagate_pos(ParticleRangeNPT const &particles, double time_step)