Simpatico  v1.10
NvtDpdVvIntegrator.cpp
1 /*
2 * Simpatico - Simulation Package for Polymeric and Molecular Liquids
3 *
4 * Copyright 2010 - 2017, The Regents of the University of Minnesota
5 * Distributed under the terms of the GNU General Public License.
6 */
7 
8 #include "NvtDpdVvIntegrator.h"
9 #include <mcMd/mdSimulation/MdSystem.h>
10 #include <mcMd/simulation/Simulation.h>
11 #include <mcMd/potentials/pair/MdPairPotential.h>
12 #include <mcMd/neighbor/PairList.h>
13 #include <mcMd/neighbor/PairIterator.h>
14 #include <mcMd/chemistry/Molecule.h>
15 #include <mcMd/chemistry/Atom.h>
16 #include <simp/ensembles/EnergyEnsemble.h>
17 #include <simp/boundary/Boundary.h>
18 #include <util/archives/Serializable_includes.h>
19 #include <util/space/Vector.h>
20 
21 #define MCMD_DPD_TYPE 0
22 
23 namespace McMd
24 {
25 
26  using namespace Util;
27  using namespace Simp;
28 
29  /*
30  * Constructor.
31  */
33  : MdIntegrator(system),
34  dtMinvFactors_(),
35  cutoff_(-1.0),
36  gamma_(-1.0),
37  sigma_(-1.0),
38  temperature_(1.0),
39  cutoffSq_(-1.0),
40  #ifndef SIMP_NOPAIR
41  pairListPtr_(&system.pairPotential().pairList()),
42  #endif
43  boundaryPtr_(&system.boundary()),
44  randomPtr_(&system.simulation().random()),
45  energyEnsemblePtr_(&system.energyEnsemble()),
46  atomCapacity_(system.simulation().atomCapacity()),
47  isInitialized_(false)
48  {
49  // Note: Within the constructor, the method parameter "system"
50  // hides the MdIntegrator::system() method name.
51 
52  // Precondition
53  if (!system.energyEnsemble().isIsothermal() ) {
54  UTIL_THROW("System energy ensemble is not isothermal");
55  }
56  temperature_ = energyEnsemblePtr_->temperature();
57 
58  setClassName("NvtDpdVvIntegrator");
59  }
60 
61  /*
62  * Destructor.
63  */
65  {}
66 
67  /*
68  * Read parameter and configuration files, initialize system.
69  */
70  void NvtDpdVvIntegrator::readParameters(std::istream &in)
71  {
72  // Precondition
73  if (isInitialized_) {
74  UTIL_THROW("NvtDpdVvIntegrator already initialized");
75  }
76 
77  read<double>(in, "dt", dt_);
78  read<double>(in, "cutoff", cutoff_);
79  #ifndef SIMP_NOPAIR
80  if (cutoff_ > system().pairPotential().maxPairCutoff()) {
81  UTIL_THROW("Error: Dpd pair cutoff > maxCutoff of pair potential");
82  }
83  #endif
84  read<double>(in, "gamma", gamma_);
85 
86  // Allocate arrays for internal use
87  dissipativeForces_.allocate(atomCapacity_);
88  randomForces_.allocate(atomCapacity_);
89  dtMinvFactors_.allocate(simulation().nAtomType());
90 
91  isInitialized_ = true;
92  }
93 
94  /*
95  * Load the internal state to an archive.
96  */
98  {
99  // Precondition
100  if (isInitialized_) {
101  UTIL_THROW("NvtDpdVvIntegrator already initialized");
102  }
103 
104  loadParameter<double>(ar, "dt", dt_);
105  loadParameter<double>(ar, "cutoff", cutoff_);
106  #ifndef SIMP_NOPAIR
107  if (cutoff_ > system().pairPotential().maxPairCutoff()) {
108  UTIL_THROW("Error: Dpd pair cutoff > maxCutoff of pair potential");
109  }
110  #endif
111  loadParameter<double>(ar, "gamma", gamma_);
112  ar & temperature_;
113  ar & sigma_;
114  ar & cutoffSq_;
115  ar & atomCapacity_;
116  ar & dtMinvFactors_;
117  ar & dissipativeForces_;
118  ar & randomForces_;
119 
120  isInitialized_ = true;
121  }
122 
123  /*
124  * Save the internal state to an archive.
125  */
127  {
128  ar & dt_;
129  ar & cutoff_;
130  ar & gamma_;
131  ar & temperature_;
132  ar & sigma_;
133  ar & cutoffSq_;
134  ar & atomCapacity_;
135  ar & dtMinvFactors_;
136  ar & dissipativeForces_;
137  ar & randomForces_;
138  }
139 
140  /*
141  * Initialize constants and forces.
142  */
144  {
145  if (!isInitialized_) {
146  UTIL_THROW("Object must be initialized before use");
147  }
148 
149  // Calculate dtMinvFactors_ array.
150  double mass;
151  int nAtomType = simulation().nAtomType();
152  for (int i = 0; i < nAtomType; ++i) {
153  mass = simulation().atomType(i).mass();
154  dtMinvFactors_[i] = 0.5*dt_/mass;
155  }
156 
157  temperature_ = system().energyEnsemble().temperature();
158  sigma_ = sqrt(2.0*gamma_*temperature_/dt_);
159  cutoffSq_ = cutoff_*cutoff_;
160 
161  #ifndef SIMP_NOPAIR
164  #endif
165 
167  computeDpdForces(true);
168  }
169 
170  /*
171  * Compute new dissipative and (optionally) random forces.
172  *
173  * Dissipative and random forces are stored in separate arrays.
174  * If computeRandom == true, recompute random as well as dissipative
175  * forces.
176  */
177  void NvtDpdVvIntegrator::computeDpdForces(bool computeRandom)
178  {
179  Vector e; // unit vector (r0 - r1)/|r0 - r1|;
180  Vector f; // force vector
181  Vector dv; // difference in velocities v0 - v1;
182  double rsq; // square of distance between atoms.
183  double r; // distance between atoms.
184  double fr; // magnitude of random pair force.
185  double fd; // magnitude of dissipative pair force.
186  double wr; // weighting function for random forces.
187  Atom* atom0Ptr;
188  Atom* atom1Ptr;
189  PairIterator iter;
190  int i;
191 
192  // Set all dissipative forces to zero.
193  for (i=0; i < atomCapacity_; ++i) {
194  dissipativeForces_[i].zero();
195  }
196  if (computeRandom) {
197  for (i=0; i < atomCapacity_; ++i) {
198  randomForces_[i].zero();
199  }
200  }
201 
202  // Iterator over atom pairs
203  for (pairListPtr_->begin(iter); iter.notEnd(); ++iter) {
204  iter.getPair(atom0Ptr, atom1Ptr);
205  rsq = boundaryPtr_->distanceSq(atom0Ptr->position(),
206  atom1Ptr->position(), e);
207  if (rsq < cutoffSq_) {
208  r = sqrt(rsq);
209  e /= r;
210 
211  #if MCMD_DPD_TYPE == 0
212  wr = 1.0;
213  #endif
214  #if MCMD_DPD_TYPE == 1
215  wr = 1.0 - (r/cutoff_);
216  #endif
217  #if MCMD_DPD_TYPE == 2
218  wr = 1.0 - rsq/cutoffSq_;
219  #endif
220 
221  // Add random forces to atomic vectors.
222  if (computeRandom) {
223  fr = sigma_*wr*randomPtr_->gaussian();
224  f.multiply(e, fr);
225  randomForces_[atom0Ptr->id()] += f;
226  randomForces_[atom1Ptr->id()] -= f;
227  }
228 
229  // Add dissipative forces to array
230  dv.subtract(atom0Ptr->velocity(), atom1Ptr->velocity());
231  fd = -gamma_*wr*wr*dv.dot(e);
232  f.multiply(e, fd);
233  dissipativeForces_[atom0Ptr->id()] += f;
234  dissipativeForces_[atom1Ptr->id()] -= f;
235 
236  }
237 
238  }
241 
242  }
243 
244  /*
245  * DPD integrator time step.
246  */
248  {
249  Vector dv;
250  Vector dr;
251  Vector f;
252  System::MoleculeIterator molIter;
253  int iSpecies, nSpecies, atomId;
254 
255  nSpecies = simulation().nSpecies();
256 
257  // 1st half velocity Verlet, loop over atoms
258  Molecule::AtomIterator atomIter;
259  for (iSpecies=0; iSpecies < nSpecies; ++iSpecies) {
260  for (system().begin(iSpecies, molIter); molIter.notEnd(); ++molIter)
261  {
262  for (molIter->begin(atomIter); atomIter.notEnd(); ++atomIter) {
263  atomId = atomIter->id();
264 
265  // f = (conservative atomic) + random + dissipative force
266  f.add(atomIter->force(), dissipativeForces_[atomId]);
267  f += randomForces_[atomId];
268 
269  // Velocity increment dv = force*0.5*dt/mass
270  dv.multiply(f, dtMinvFactors_[atomIter->typeId()]);
271  atomIter->velocity() += dv;
272 
273  dr.multiply(atomIter->velocity(), dt_);
274  atomIter->position() += dr;
275 
276  }
277  }
278  }
281 
282  #if 0
283  #ifndef SIMP_NOPAIR
284  if (!system().pairPotential().isPairListCurrent()) {
286  }
287  #endif
288  #endif
289 
290  // Note: MdSystem().calculateForces() rebuilds the pair list as needed.
291 
292  // Calculate all new forces
294  computeDpdForces(true);
295 
296  // 2nd half velocity Verlet, loop over atoms
297  for (iSpecies=0; iSpecies < nSpecies; ++iSpecies) {
298  system().begin(iSpecies, molIter);
299  for ( ; molIter.notEnd(); ++molIter) {
300  for (molIter->begin(atomIter); atomIter.notEnd(); ++atomIter) {
301  atomId = atomIter->id();
302 
303  // f = conservative + random + dissipative force
304  f.add(atomIter->force(), dissipativeForces_[atomId]);
305  f += randomForces_[atomId];
306 
307  // Increment velocity by dv = f*0.5*dt/mass
308  dv.multiply(f, dtMinvFactors_[atomIter->typeId()]);
309  atomIter->velocity() += dv;
310 
311  }
312  }
313  }
315 
316  // Recompute disipative force (but not random forces).
317  computeDpdForces(false);
318 
319  }
320 
321 }
322 #undef MCMD_DPD_TYPE
virtual void save(Serializable::OArchive &ar)
Save the internal state to an archive.
A Vector is a Cartesian vector.
Definition: Vector.h:75
virtual double maxPairCutoff() const =0
Return maximum cutoff distance.
void calculateForces()
Compute all forces in this System.
Definition: MdSystem.cpp:857
void begin(int speciesId, MoleculeIterator &iterator)
Initialize an iterator for molecules of one species in this System.
Definition: System.h:1147
Vector & add(const Vector &v1, const Vector &v2)
Add vectors v1 and v2.
Definition: Vector.h:657
Vector & velocity()
Get atomic velocity Vector by reference.
double distanceSq(const Vector &r1, const Vector &r2) const
Return square distance between positions r1 and r2.
bool notEnd() const
Is the current pointer not at the end of the array?
Definition: ArrayIterator.h:83
Signal & positionSignal()
Signal to indicate change in atomic positions.
Definition: MdSystem.h:669
virtual void step()
Take a complete integration step.
double dot(const Vector &v) const
Return dot product of this vector and vector v.
Definition: Vector.h:632
Vector & multiply(const Vector &v, double s)
Multiply a vector v by a scalar s.
Definition: Vector.h:686
EnergyEnsemble & energyEnsemble() const
Get the EnergyEnsemble by reference.
Definition: System.h:1095
Classes used by all simpatico molecular simulations.
Simulation & simulation()
Get parent Simulation by reference.
Definition: MdIntegrator.h:111
void getPair(Atom *&atom1Ptr, Atom *&atom2Ptr) const
Get pointers for current pair of Atoms.
Abstract base for molecular dynamics integrators.
Definition: MdIntegrator.h:30
virtual void loadParameters(Serializable::IArchive &ar)
Load the internal state to an archive.
Saving / output archive for binary ostream.
MdPairPotential & pairPotential() const
Return MdPairPotential by reference.
Definition: MdSystem.h:520
const AtomType & atomType(int i) const
Get a single AtomType object by const reference.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
bool isIsothermal() const
Is this an Isothermal ensemble?
MdSystem & system()
Get parent MdSystem by reference.
Definition: MdIntegrator.h:105
void notify(const T &t)
Notify all observers.
Definition: Signal.cpp:22
A point particle within a Molecule.
bool notEnd() const
Is the current pointer not at the end of the PArray?
Utility classes for scientific computation.
Definition: accumulators.mod:1
double gaussian(void)
Return a Gaussian random number with zero average and unit variance.
Definition: Random.cpp:92
int id() const
Get global index for this Atom within the Simulation.
Forward iterator for an Array or a C array.
Definition: ArrayIterator.h:39
Forward iterator for a PArray.
Definition: ArraySet.h:19
Iterator for pairs in a PairList.
double dt_
Integrator time step.
Definition: MdIntegrator.h:79
void begin(PairIterator &iterator) const
Initialize a PairIterator.
Signal & velocitySignal()
Signal to indicate change in atomic velocities.
Definition: MdSystem.h:675
Saving archive for binary istream.
double mass() const
Get the mass.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
int nSpecies() const
Get the number of Species in this Simulation.
void buildPairList()
Build the internal PairList.
void clearPairListStatistics()
Clear all statistical accumulators stored in PairList.
virtual void setup()
Setup private variables before main loop.
Vector & subtract(const Vector &v1, const Vector &v2)
Subtract vector v2 from v1.
Definition: Vector.h:672
void setClassName(const char *className)
Set class name string.
bool notEnd() const
Return true if not at end of PairList.
A System for Molecular Dynamics simulation.
Definition: MdSystem.h:68
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:191
double temperature() const
Return the temperature.
const Vector & position() const
Get the position Vector by const reference.
int nAtomType() const
Get the number of atom types.
NvtDpdVvIntegrator(MdSystem &system)
Constructor.
virtual ~NvtDpdVvIntegrator()
Destructor.
virtual void readParameters(std::istream &in)
Read parameters from file and initialize this MdSystem.