ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
velocity_verlet_npt_Andersen.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 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"
27#include "ParticleRange.hpp"
29#include "communication.hpp"
30#include "errorhandling.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 * + (P_{\text{inst}} - P_{\text{ext}})*0.5*dt @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 for (auto i = 0u; i < 3u; ++i) {
54 npt_inst_pressure.p_inst[0] +=
55 npt_inst_pressure.p_vir[i] + npt_inst_pressure.p_vel[i];
56 npt_inst_pressure.p_inst[1] += npt_inst_pressure.p_vir[i];
57 }
58 }
59
60 Utils::Vector2d p_sum = {0., 0.};
61 boost::mpi::reduce(::comm_cart, npt_inst_pressure.p_inst, p_sum,
62 std::plus<Utils::Vector2d>(), 0);
63
64 /* propagate p_epsilon */
65 if (::this_node == 0) {
66 npt_inst_pressure.p_inst = p_sum / (nptiso.dimension * nptiso.volume);
67 nptiso.p_epsilon +=
68 (npt_inst_pressure.p_inst[0] - nptiso.p_ext) * 0.5 * time_step;
69 }
70}
71
72/**
73 * @brief propagete positions and the volume and add thermal fluctuation.
74 * A and V are the position and volume propagators for half-time step.
75 * O is the propagator corresponding to Ornstein-Uhlenbeck process
76 * representing the stochastic thermostat.
77 * The time evolution follows the sequence A-V-O-V-A in this function,
78 * with propagators applied right to left.
79 */
81 ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso,
82 double time_step, System::System &system) {
83
84 auto &box_geo = *system.box_geo;
85 auto &cell_structure = *system.cell_structure;
86 auto &npt_inst_pressure = *system.npt_inst_pressure;
87 auto &nptiso = *system.nptiso;
88 Utils::Vector3d scal{};
89 double L_halfdt = 0.0;
90 double L_dt = 0.0;
91
92 /* finalize derivation of p_inst and propagate p_epsilon;
93 * @f$ p_{\epsilon}(t+dt) = p_{\epsilon}(t)
94 * + (P_{\text{inst}} - P_{\text{ext}})*0.5*dt @f$
95 */
96 velocity_verlet_npt_finalize_p_inst(nptiso, npt_inst_pressure, time_step);
97
98 /* 1st adjust \ref NptIsoParameters::nptiso.volume with dt/2;
99 * @f$ V(t+0.5*dt) = V(t) + 0.5*p_{\epsilon}*dt @f$
100 * and prepare pos and vel-rescaling
101 */
102 if (::this_node == 0) {
103 nptiso.volume += nptiso.inv_piston * nptiso.p_epsilon * 0.5 * time_step;
104 // L(t)**2 / L(t+0.5*dt)**2, where the numerator follows time in position,
105 // and the denominator follows time in velocity
106 scal[2] = Utils::sqr(box_geo.length()[nptiso.non_const_dim]) /
107 pow(nptiso.volume, 2.0 / nptiso.dimension);
108 if (nptiso.volume < 0.0) {
110 << "your choice of piston= " << nptiso.piston << ", dt= " << time_step
111 << ", p_epsilon= " << nptiso.p_epsilon
112 << " just caused the volume to become negative, decrease dt";
113 nptiso.volume = box_geo.volume();
114 scal[2] = 1;
115 }
116
117 L_halfdt = pow(nptiso.volume, 1.0 / nptiso.dimension);
118
119 // L(t+0.5*dt) / L(t)
120 scal[1] = L_halfdt * box_geo.length_inv()[nptiso.non_const_dim];
121 // L(t) / L(t+0.5*dt)
122 scal[0] = 1. / scal[1];
123 }
124 boost::mpi::broadcast(::comm_cart, scal, 0);
125
126 /* 1st propagate positions with dt/2 and rescaling pos;
127 * @f$ pos[t+0.5*dt] = (L(t+0.5*dt) / L(t)) *
128 * (pos[t] + (L(t)**2 / L(t+0.5*dt)**2) * vel[t+0.5*dt] * 0.5 * dt) @f$
129 */
130 for (auto &p : particles) {
131 for (auto j = 0u; j < 3u; ++j) {
132 if (!p.is_fixed_along(j)) {
133 if (nptiso.geometry & NptIsoParameters::nptgeom_dir[j]) {
134 p.pos()[j] =
135 scal[1] * (p.pos()[j] + scal[2] * p.v()[j] * 0.5 * time_step);
136 p.pos_at_last_verlet_update()[j] *= scal[1];
137 p.v()[j] *= scal[0];
138 } else {
139 p.pos()[j] += p.v()[j] * 0.5 * time_step;
140 }
141 }
142 }
143 }
144
145 /* stochastic reservoirs for conjugate momentum for V;
146 * @f$ p_{\epsilon} = p_{epsilon}(t) \exp(- \gamma_V dt / W)
147 * + \sqrt{k_B T (1 - \exp(-2 \gamma_V dt / W)}N(0,1) @f$,
148 * 2nd adjust \ref NptIsoParameters::nptiso.volume with dt/2;
149 * @f$ V(t+dt) = V(t+0.5*dt) + 0.5*p_{\epsilon}*dt @f$,
150 * and prepare pos- and vel-rescaling
151 */
152 if (::this_node == 0) {
153 nptiso.p_epsilon = propagate_thermV_nptiso(npt_iso, nptiso.p_epsilon);
154 nptiso.volume += nptiso.inv_piston * nptiso.p_epsilon * 0.5 * time_step;
155 L_dt = pow(nptiso.volume, 1.0 / nptiso.dimension);
156
157 scal[2] = 1.0;
158 scal[1] = L_dt / L_halfdt;
159 scal[0] = 1. / scal[1];
160 }
161 boost::mpi::broadcast(::comm_cart, scal, 0);
162
163 /* stochastic reservoirs for velocities;
164 * @f$ p(t+0.5*dt) = p(t+0.5*dt) \exp(- \gamma_0 dt / m)
165 * + \sqrt{k_B T (1 - \exp(-2 \gamma_0 dt)}N(0,1) @f$
166 * and 2nd propagate positions with dt/2 while rescaling positions velocities
167 * @f$ pos[t+dt] = (L(t+dt) / L(t+0.5*dt)) *
168 * (pos[t+0.5*dt] + vel[t+0.5*dt]) @f$
169 */
170 for (auto &p : particles) {
171 auto const v_therm =
172 propagate_therm0_nptiso(npt_iso, p.v(), p.mass(), p.id());
173 for (auto j = 0u; j < 3u; ++j) {
174 if (!p.is_fixed_along(j)) {
175 if (nptiso.geometry & NptIsoParameters::nptgeom_dir[j]) {
176 p.v()[j] = v_therm[j];
177 p.pos()[j] =
178 scal[1] * (p.pos()[j] + scal[2] * p.v()[j] * 0.5 * time_step);
179 p.pos_at_last_verlet_update()[j] *= scal[1];
180 p.v()[j] *= scal[0];
181 } else {
182 p.pos()[j] += p.v()[j] * 0.5 * time_step;
183 }
184 }
185 }
186 }
187
188 cell_structure.set_resort_particles(Cells::RESORT_LOCAL);
189
190 /* Apply new volume to the box-length, communicate it, and account for
191 * necessary adjustments to the cell geometry */
192 Utils::Vector3d new_box;
193
194 if (::this_node == 0) {
195 new_box = box_geo.length();
196 for (auto i = 0u; i < 3u; ++i) {
197 if (nptiso.cubic_box ||
198 nptiso.geometry & NptIsoParameters::nptgeom_dir[i]) {
199 new_box[i] = L_dt;
200 }
201 }
202 }
203
204 boost::mpi::broadcast(::comm_cart, new_box, 0);
205
206 box_geo.set_length(new_box);
207 // fast box length update
208 system.on_boxl_change(true);
209}
210
212 IsotropicNptThermostat const &npt_iso,
213 double time_step,
214 System::System &system) {
215 auto &nptiso = *system.nptiso;
216 auto &npt_inst_pressure = *system.npt_inst_pressure;
217 velocity_verlet_npt_propagate_vel(nptiso, npt_inst_pressure, particles,
218 time_step);
219 velocity_verlet_npt_propagate_AVOVA_And(particles, npt_iso, time_step,
220 system);
221}
222
224 double time_step,
225 System::System &system) {
226 auto &nptiso = *system.nptiso;
227 auto &npt_inst_pressure = *system.npt_inst_pressure;
228 velocity_verlet_npt_propagate_vel_final(nptiso, npt_inst_pressure, particles,
229 time_step);
230 velocity_verlet_npt_finalize_p_inst(nptiso, npt_inst_pressure, time_step);
231}
232
233#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 ...
#define runtimeErrorMsg()
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
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 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_final(NptIsoParameters const &nptiso, InstantaneousPressure &npt_inst_pressure, ParticleRangeNPT const &particles, double time_step)
Propagate the particle's velocity.
void velocity_verlet_npt_propagate_vel(NptIsoParameters const &nptiso, InstantaneousPressure &npt_inst_pressure, ParticleRangeNPT const &particles, double time_step)
Propagate the particle's velocity.
static void velocity_verlet_npt_finalize_p_inst(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_And(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step, System::System &system)
propagete positions and the volume and add thermal fluctuation.
void velocity_verlet_npt_Andersen_step_1(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step, System::System &system)
Special propagator for NpT isotropic for Andersen method.
void velocity_verlet_npt_Andersen_step_2(ParticleRangeNPT const &particles, double time_step, System::System &system)
Final integration step of the Velocity Verlet+NpT integrator for Andersen method.