8 #include "NphIntegrator.h" 9 #include <ddMd/simulation/Simulation.h> 10 #include <ddMd/storage/AtomStorage.h> 11 #include <ddMd/storage/AtomIterator.h> 12 #include <ddMd/communicate/Exchanger.h> 13 #include <ddMd/potentials/pair/PairPotential.h> 14 #include <simp/ensembles/EnergyEnsemble.h> 15 #include <simp/ensembles/BoundaryEnsemble.h> 16 #include <util/space/Vector.h> 17 #include <util/mpi/MpiLoader.h> 18 #include <util/format/Dbl.h> 47 read<double>(in,
"dt", dt_);
48 read<double>(in,
"W", W_);
49 read<LatticeSystem>(in,
"mode", mode_);
64 loadParameter<double>(ar,
"dt", dt_);
65 loadParameter<double>(ar,
"W", W_);
66 loadParameter<LatticeSystem>(ar,
"mode", mode_);
95 { nu_ =
Vector(0.0,0.0,0.0); }
109 double dtHalf = 0.5*dt_;
114 prefactors_[i] = dtHalf/mass;
121 if (
domain().isMaster()) {
149 P_curr_diag_ =
Vector(stress(0, 0), stress(1,1), stress(2,2));
150 double P_curr = (1.0/3.0)*stress.
trace();
152 double mtk_term = (1.0/2.0)*dt_*T_kinetic_/W_;
156 if (mode_ == Cubic) {
157 nu_[0] += (1.0/2.0)*dt_*V/W_*(P_curr - P_target_) + mtk_term;
158 nu_[1] = nu_[2] = nu_[0];
159 }
else if (mode_ == Tetragonal) {
160 nu_[0] += (1.0/2.0)*dt_*V/W_*(P_curr_diag_[0] - P_target_) + mtk_term;
161 nu_[1] += (1.0/2.0)*dt_*V/W_*((1.0/2.0)*(P_curr_diag_[1]+P_curr_diag_[2]) - P_target_) + mtk_term;
163 }
else if (mode_ == Orthorhombic) {
164 nu_[0] += (1.0/2.0)*dt_*V/W_*(P_curr_diag_[0] - P_target_) + mtk_term;
165 nu_[1] += (1.0/2.0)*dt_*V/W_*(P_curr_diag_[1] - P_target_) + mtk_term;
166 nu_[2] += (1.0/2.0)*dt_*V/W_*(P_curr_diag_[2] - P_target_) + mtk_term;
176 mtk_term_2_ = (nu_[0]+nu_[1]+nu_[2])/ndof_;
178 (1.0/4.0)*(nu_[1]+mtk_term_2_),
179 (1.0/4.0)*(nu_[2]+mtk_term_2_));
180 exp_v_fac_ =
Vector(exp(-v_fac[0]*dt_),
184 exp(-(2.0*v_fac[1])*dt_),
185 exp(-(2.0*v_fac[2])*dt_));
194 const double a[] = {double(1.0), double(1.0/6.0), double(1.0/120.0),
195 double(1.0/5040.0), double(1.0/362880.0), double(1.0/39916800.0)};
197 Vector arg_v =
Vector(v_fac[0]*dt_, v_fac[1]*dt_, v_fac[2]*dt_);
198 Vector arg_r =
Vector(r_fac[0]*dt_, r_fac[1]*dt_, r_fac[2]*dt_);
200 sinhx_fac_v_ =
Vector(0.0,0.0,0.0);
206 for (
unsigned int i = 0; i < 6; i++) {
207 sinhx_fac_v_ +=
Vector(a[i]*term_v[0],
210 sinhx_fac_r +=
Vector(a[i]*term_r[0],
213 term_v =
Vector(term_v[0] * arg_v[0] * arg_v[0],
214 term_v[1] * arg_v[1] * arg_v[1],
215 term_v[2] * arg_v[2] * arg_v[2]);
216 term_r =
Vector(term_r[0] * arg_r[0] * arg_r[0],
217 term_r[1] * arg_r[1] * arg_r[1],
218 term_r[2] * arg_r[2] * arg_r[2]);
225 for ( ; atomIter.
notEnd(); ++atomIter) {
226 prefactor = prefactors_[atomIter->typeId()];
228 dv.
multiply(atomIter->force(), prefactor);
229 dv[0] = dv[0] * exp_v_fac_[0]*sinhx_fac_v_[0];
230 dv[1] = dv[1] * exp_v_fac_[1]*sinhx_fac_v_[1];
231 dv[2] = dv[2] * exp_v_fac_[2]*sinhx_fac_v_[2];
233 Vector& v = atomIter->velocity();
234 v[0] = v[0] * exp_v_fac_2[0] + dv[0];
235 v[1] = v[1] * exp_v_fac_2[1] + dv[1];
236 v[2] = v[2] * exp_v_fac_2[2] + dv[2];
238 vtmp[0] = v[0]*exp_r_fac[0] *sinhx_fac_r[0];
239 vtmp[1] = v[1]*exp_r_fac[1] *sinhx_fac_r[1];
240 vtmp[2] = v[2]*exp_r_fac[2] *sinhx_fac_r[2];
242 Vector& r = atomIter->position();
243 r[0] = r[0]*exp_r_fac[0]*exp_r_fac[0] + vtmp[0]*dt_;
244 r[1] = r[1]*exp_r_fac[1]*exp_r_fac[1] + vtmp[1]*dt_;
245 r[2] = r[2]*exp_r_fac[2]*exp_r_fac[2] + vtmp[2]*dt_;
254 L[0] *= box_len_scale[0];
255 L[1] *= box_len_scale[1];
256 L[2] *= box_len_scale[2];
272 (1.0/2.0)*(nu_[1]+mtk_term_2_),
273 (1.0/2.0)*(nu_[2]+mtk_term_2_));
275 exp(-v_fac_2[1]*dt_),
276 exp(-v_fac_2[2]*dt_));
280 for ( ; atomIter.
notEnd(); ++atomIter) {
281 prefactor = prefactors_[atomIter->typeId()];
282 dv.
multiply(atomIter->force(), prefactor);
283 dv[0] = dv[0] * exp_v_fac_[0]*sinhx_fac_v_[0];
284 dv[1] = dv[1] * exp_v_fac_[1]*sinhx_fac_v_[1];
285 dv[2] = dv[2] * exp_v_fac_[2]*sinhx_fac_v_[2];
287 Vector& v = atomIter->velocity();
288 v[0] = v[0] * exp_v_fac_2[0] + dv[0];
289 v[1] = v[1] * exp_v_fac_2[1] + dv[1];
290 v[2] = v[2] * exp_v_fac_2[2] + dv[2];
305 P_curr_diag_ =
Vector(stress(0,0), stress(1,1), stress(2,2));
306 double P_curr = (1.0/3.0)*stress.
trace();
308 double mtk_term = (1.0/2.0)*dt_*T_kinetic_/W_;
311 if (mode_ == Cubic) {
312 nu_[0] += (1.0/2.0)*dt_*V/W_*(P_curr - P_target_) + mtk_term;
313 nu_[1] = nu_[2] = nu_[0];
314 }
else if (mode_ == Tetragonal) {
315 nu_[0] += (1.0/2.0)*dt_*V/W_*(P_curr_diag_[0] - P_target_) + mtk_term;
316 nu_[1] += (1.0/2.0)*dt_*V/W_*((1.0/2.0)*(P_curr_diag_[1]+P_curr_diag_[2]) - P_target_) + mtk_term;
318 }
else if (mode_ == Orthorhombic) {
319 nu_[0] += (1.0/2.0)*dt_*V/W_*(P_curr_diag_[0] - P_target_) + mtk_term;
320 nu_[1] += (1.0/2.0)*dt_*V/W_*(P_curr_diag_[1] - P_target_) + mtk_term;
321 nu_[2] += (1.0/2.0)*dt_*V/W_*(P_curr_diag_[2] - P_target_) + mtk_term;
330 file.open(
"NPH.log", std::ios::out | std::ios::app);
332 double barostat_energy = W_*(nu_[0]*nu_[0]+ nu_[1]*nu_[1] + nu_[2]*nu_[2]);
338 <<
Dbl(barostat_energy,20)
void loadParameters(Serializable::IArchive &ar)
Load saveInterval and saveFileName from restart archive.
Signal & velocitySignal()
Signal to indicate change in atomic velocities.
A Vector is a Cartesian vector.
void save(Serializable::OArchive &ar)
Save state to an input restart archive.
NphIntegrator(Simulation &simulation)
Constructor.
~NphIntegrator()
Destructor.
int nAtomTotal() const
Get total number of atoms on all processors.
double kineticEnergy()
Return precomputed total kinetic energy.
double pressure() const
Get the target pressure.
double volume() const
Return unit cell volume.
void setOrthorhombic(const Vector &lengths)
Set unit cell dimensions for orthorhombic boundary.
const Vector & lengths() const
Get Vector of unit cell lengths by const reference.
Vector & multiply(const Vector &v, double s)
Multiply a vector v by a scalar s.
void readParameters(std::istream &in)
Read saveInterval and saveFileName.
void readParameters(std::istream &in)
Read required parameters.
BoundaryEnsemble & boundaryEnsemble()
Get the BoundaryEnsemble by reference.
void setIsSetup()
Mark the integrator as having been setup at least once.
double mass() const
Get the mass.
Wrapper for a double precision number, for formatted ostream output.
File containing preprocessor macros for error handling.
Parallel domain decomposition (DD) MD simulation.
Classes used by all simpatico molecular simulations.
double trace() const
Return the trace of this tensor.
Main object for a domain-decomposition MD simulation.
A Tensor represents a Cartesian tensor.
AtomType & atomType(int i)
Get an AtomType descriptor by reference.
Saving / output archive for binary ostream.
void setupAtoms()
Setup state of atoms just before integration.
void bcast(MPI::Intracomm &comm, T &data, int root)
Broadcast a single T value.
void computePotentialEnergies()
Calculate and store total potential energy on all processors.
void notify(const T &t)
Notify all observers.
bool notEnd() const
Is the current pointer not at the end of the PArray?
Utility classes for scientific computation.
void load(Data &value)
Load and broadcast a single Data value.
Domain & domain()
Get the Domain.
Tensor kineticStress() const
Return total kinetic stress.
bool isAllocated() const
Return true if the DArray has been allocated, false otherwise.
virtual void integrateStep2()
Execute secodn step of two-step integrator.
bool isSetup() const
Has the setup() method been called at least once previously?
AtomStorage & atomStorage()
Get the AtomStorage.
void save(Serializable::OArchive &ar)
Save saveInterval and saveFileName from restart archive.
void computeNAtomTotal(MPI::Intracomm &communicator)
Compute the total number of local atoms on all processors.
void initDynamicalState()
Initialize Vector nu to zero.
bool isMaster() const
Is this the master processor (gridRank == 0) ?
void computeVirialStress()
Calculate and store all virial stress contributions.
Simulation & simulation()
Get the parent simulation.
double potentialEnergy() const
Return sum of precomputed total potential energies.
virtual void integrateStep1()
Execute first step of two-step integrator.
int nAtomType()
Get maximum number of atom types.
Saving archive for binary istream.
Provides methods for MPI-aware loading of data from input archive.
A two-step velocity-Verlet style integrator.
void setClassName(const char *className)
Set class name string.
int nAtomType()
Get maximum number of atom types.
Boundary & boundary()
Get the Boundary by reference.
int capacity() const
Return allocated size.
void allocate(int capacity)
Allocate the underlying C array.
void computeKineticEnergy()
Compute total kinetic energy.
Domain & domain()
Get the Domain by reference.
Tensor virialStress() const
Return total virial stress.
Iterator for all atoms owned by an AtomStorage.
void computeKineticStress()
Calculate and store kinetic stress.
void setup()
Setup state just before integration.
virtual void clear()
Set integrator to initial state and clears all statistics.
void begin(AtomIterator &iterator)
Set iterator to beginning of the set of atoms.
void loadParameters(Serializable::IArchive &ar)
Load parameters from an input restart archive.