ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
velocity_verlet_npt.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 NPT
24
25#include "BoxGeometry.hpp"
26#include "Particle.hpp"
27#include "ParticleRange.hpp"
29#include "communication.hpp"
30#include "errorhandling.hpp"
31#include "npt.hpp"
32#include "system/System.hpp"
33#include "thermostat.hpp"
35
36#include <utils/Vector.hpp>
37#include <utils/math/sqr.hpp>
38
39#include <boost/mpi/collectives.hpp>
40
41#include <cmath>
42#include <functional>
43
44static constexpr Utils::Vector3i nptgeom_dir{{1, 2, 4}};
45
46static void
48 IsotropicNptThermostat const &npt_iso,
49 double time_step) {
50 nptiso.p_vel = {};
51
52 for (auto &p : particles) {
53 auto const noise = friction_therm0_nptiso<2>(npt_iso, p.v(), p.id());
54 for (unsigned int j = 0; j < 3; j++) {
55 if (!p.is_fixed_along(j)) {
56 if (nptiso.geometry & ::nptgeom_dir[j]) {
57 nptiso.p_vel[j] += Utils::sqr(p.v()[j] * time_step) * p.mass();
58 p.v()[j] += (p.force()[j] * time_step / 2.0 + noise[j]) / p.mass();
59 } else {
60 // Propagate velocity: v(t+dt) = v(t+0.5*dt) + 0.5*dt * a(t+dt)
61 p.v()[j] += p.force()[j] * time_step / 2.0 / p.mass();
62 }
63 }
64 }
65 }
66}
67
68/** Scale and communicate instantaneous NpT pressure */
69static void
71 double time_step) {
72 /* finalize derivation of p_inst */
73 nptiso.p_inst = 0.0;
74 for (unsigned int i = 0; i < 3; i++) {
75 if (nptiso.geometry & ::nptgeom_dir[i]) {
76 nptiso.p_vel[i] /= Utils::sqr(time_step);
78 }
79 }
80
81 double p_sum = 0.0;
82 boost::mpi::reduce(comm_cart, nptiso.p_inst, p_sum, std::plus<double>(), 0);
83 if (this_node == 0) {
85 nptiso.p_diff += (nptiso.p_inst - nptiso.p_ext) * 0.5 * time_step +
87 }
88}
89
90static void
92 IsotropicNptThermostat const &npt_iso,
93 double time_step, System::System &system) {
94
95 auto &box_geo = *system.box_geo;
96 auto &cell_structure = *system.cell_structure;
97 Utils::Vector3d scal{};
98 double L_new = 0.0;
99
100 /* finalize derivation of p_inst */
101 velocity_verlet_npt_finalize_p_inst(npt_iso, time_step);
102
103 /* adjust \ref NptIsoParameters::nptiso.volume; prepare pos- and
104 * vel-rescaling
105 */
106 if (this_node == 0) {
107 nptiso.volume += nptiso.inv_piston * nptiso.p_diff * 0.5 * time_step;
108 scal[2] = Utils::sqr(box_geo.length()[nptiso.non_const_dim]) /
109 pow(nptiso.volume, 2.0 / nptiso.dimension);
110 nptiso.volume += nptiso.inv_piston * nptiso.p_diff * 0.5 * time_step;
111 if (nptiso.volume < 0.0) {
113 << "your choice of piston= " << nptiso.piston << ", dt= " << time_step
114 << ", p_diff= " << nptiso.p_diff
115 << " just caused the volume to become negative, decrease dt";
116 nptiso.volume = box_geo.volume();
117 scal[2] = 1;
118 }
119
120 L_new = pow(nptiso.volume, 1.0 / nptiso.dimension);
121
122 scal[1] = L_new * box_geo.length_inv()[nptiso.non_const_dim];
123 scal[0] = 1. / scal[1];
124 }
125 boost::mpi::broadcast(comm_cart, scal, 0);
126
127 /* propagate positions while rescaling positions and velocities */
128 for (auto &p : particles) {
129 for (unsigned int j = 0; j < 3; j++) {
130 if (!p.is_fixed_along(j)) {
131 if (nptiso.geometry & ::nptgeom_dir[j]) {
132 p.pos()[j] = scal[1] * (p.pos()[j] + scal[2] * p.v()[j] * time_step);
133 p.pos_at_last_verlet_update()[j] *= scal[1];
134 p.v()[j] *= scal[0];
135 } else {
136 p.pos()[j] += p.v()[j] * time_step;
137 }
138 }
139 }
140 }
141
142 cell_structure.set_resort_particles(Cells::RESORT_LOCAL);
143
144 /* Apply new volume to the box-length, communicate it, and account for
145 * necessary adjustments to the cell geometry */
146 Utils::Vector3d new_box;
147
148 if (this_node == 0) {
149 new_box = box_geo.length();
150
151 for (unsigned int i = 0; i < 3; i++) {
153 new_box[i] = L_new;
154 }
155 }
156 }
157
158 boost::mpi::broadcast(comm_cart, new_box, 0);
159
160 box_geo.set_length(new_box);
161 // fast box length update
162 system.on_boxl_change(true);
163}
164
165static void
167 IsotropicNptThermostat const &npt_iso,
168 double time_step) {
169 nptiso.p_vel = {};
170
171 for (auto &p : particles) {
172 for (unsigned int j = 0; j < 3; j++) {
173 if (!p.is_fixed_along(j)) {
174 auto const noise = friction_therm0_nptiso<1>(npt_iso, p.v(), p.id());
175 if (nptiso.geometry & ::nptgeom_dir[j]) {
176 p.v()[j] += (p.force()[j] * time_step / 2.0 + noise[j]) / p.mass();
177 nptiso.p_vel[j] += Utils::sqr(p.v()[j] * time_step) * p.mass();
178 } else {
179 // Propagate velocities: v(t+0.5*dt) = v(t) + 0.5*dt * a(t)
180 p.v()[j] += p.force()[j] * time_step / 2.0 / p.mass();
181 }
182 }
183 }
184 }
185}
186
188 IsotropicNptThermostat const &npt_iso,
189 double time_step, System::System &system) {
190 velocity_verlet_npt_propagate_vel(particles, npt_iso, time_step);
191 velocity_verlet_npt_propagate_pos(particles, npt_iso, time_step, system);
192}
193
195 IsotropicNptThermostat const &npt_iso,
196 double time_step) {
197 velocity_verlet_npt_propagate_vel_final(particles, npt_iso, time_step);
198 velocity_verlet_npt_finalize_p_inst(npt_iso, time_step);
199}
200
201#endif // 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< 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 defaults for ESPResSo.
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
NptIsoParameters nptiso
Definition npt.cpp:42
Exports for the NpT code.
double friction_thermV_nptiso(IsotropicNptThermostat const &npt_iso, double p_diff)
Add p_diff-dependent noise and friction for NpT-sims to NptIsoParameters::p_diff.
Thermostat for isotropic NPT dynamics.
double inv_piston
inverse of piston
Definition npt.hpp:41
int geometry
geometry information for the NpT integrator.
Definition npt.hpp:62
Utils::Vector3d p_vir
virial (short-range) components of p_inst
Definition npt.hpp:53
double p_ext
desired pressure to which the algorithm strives to
Definition npt.hpp:47
bool cubic_box
Set this flag if you want all box dimensions to be identical.
Definition npt.hpp:71
int non_const_dim
An index to one of the non-constant dimensions.
Definition npt.hpp:75
double p_diff
difference between p_ext and p_inst
Definition npt.hpp:51
double p_inst
instantaneous pressure the system currently has
Definition npt.hpp:49
Utils::Vector3d p_vel
ideal gas components of p_inst, derived from the velocities
Definition npt.hpp:55
int dimension
The number of dimensions in which NpT boxlength motion is coupled to particles.
Definition npt.hpp:65
double piston
mass of a virtual piston representing the shaken box
Definition npt.hpp:39
double volume
isotropic volume.
Definition npt.hpp:45
void velocity_verlet_npt_step_2(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step)
Final integration step of the Velocity Verlet+NpT integrator.
void velocity_verlet_npt_step_1(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step, System::System &system)
Special propagator for NpT isotropic.
static constexpr Utils::Vector3i nptgeom_dir
static void velocity_verlet_npt_propagate_pos(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step, System::System &system)
static void velocity_verlet_npt_finalize_p_inst(IsotropicNptThermostat const &npt_iso, double time_step)
Scale and communicate instantaneous NpT pressure.
static void velocity_verlet_npt_propagate_vel(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step)
static void velocity_verlet_npt_propagate_vel_final(ParticleRangeNPT const &particles, IsotropicNptThermostat const &npt_iso, double time_step)