Simpatico  v1.10
ddMd/potentials/bond/BondPotentialImpl.h
1 #ifndef DDMD_BOND_POTENTIAL_IMPL_H
2 #define DDMD_BOND_POTENTIAL_IMPL_H
3 
4 /*
5 * Simpatico - Simulation Package for Polymeric and Molecular Liquids
6 *
7 * Copyright 2010 - 2017, The Regents of the University of Minnesota
8 * Distributed under the terms of the GNU General Public License.
9 */
10 
11 #include <util/global.h>
12 #include "BondPotential.h" // base class
13 
14 namespace DdMd
15 {
16 
17  using namespace Util;
18 
19  class Simulation;
20  template <int N> class GroupStorage;
21 
27  template <class Interaction>
29  {
30 
31  public:
32 
40  BondPotentialImpl(Simulation& simulation);
41 
48 
52  virtual ~BondPotentialImpl();
53 
55 
56 
66  virtual void setNBondType(int nAtomType);
67 
77  virtual void readParameters(std::istream& in);
78 
86  virtual void loadParameters(Serializable::IArchive &ar);
87 
93  virtual void save(Serializable::OArchive &ar);
94 
96 
98 
102  virtual double bondEnergy(double rsq, int bondTypeId) const;
103 
107  virtual double bondForceOverR(double rsq, int bondTypeId) const;
108 
112  virtual
113  double randomBondLength(Random* random, double beta, int bondTypeId)
114  const;
115 
123  void set(std::string name, int bondTypeId, double value);
124 
131  double get(std::string name, int bondTypeId) const;
132 
136  virtual std::string interactionClassName() const;
137 
141  const Interaction& interaction() const;
142 
146  Interaction& interaction();
147 
149 
151 
155  virtual void computeForces();
156 
162  #ifdef UTIL_MPI
163  virtual void computeEnergy(MPI::Intracomm& communicator);
164  #else
165  virtual void computeEnergy();
166  #endif
167 
173  #ifdef UTIL_MPI
174  virtual void computeStress(MPI::Intracomm& communicator);
175  #else
176  virtual void computeStress();
177  #endif
178 
184  #ifdef UTIL_MPI
185  virtual void computeForcesAndStress(MPI::Intracomm& communicator);
186  #else
187  virtual void computeForcesAndStress();
188  #endif
189 
191 
192  private:
193 
197  double energy_;
198 
202  Interaction* interactionPtr_;
203 
204  /*
205  * Initialized false, reset true in (read|load)Parameters.
206  */
207  bool isInitialized_;
208 
209  };
210 
211 }
212 
213 #include "BondPotential.h"
214 #include <ddMd/simulation/Simulation.h>
215 #include <ddMd/storage/GroupStorage.h>
216 #include <ddMd/storage/GroupIterator.h>
217 #include <simp/boundary/Boundary.h>
218 #include <util/space/Vector.h>
219 #include <util/space/Dimension.h>
220 #include <util/space/Vector.h>
221 #include <util/space/Tensor.h>
222 //#include <util/accumulators/setToZero.h>
223 #include <util/global.h>
224 
225 #include <fstream>
226 
227 namespace DdMd
228 {
229 
230  using namespace Util;
231  using namespace Simp;
232 
233  /*
234  * Constructor.
235  */
236  template <class Interaction>
238  : BondPotential(simulation),
239  interactionPtr_(0),
240  isInitialized_(false)
241  {
242  interactionPtr_ = new Interaction();
243  setNBondType(simulation.nBondType());
244  }
245 
246  /*
247  * Default constructor.
248  */
249  template <class Interaction>
251  : BondPotential(),
252  interactionPtr_(0),
253  isInitialized_(false)
254  { interactionPtr_ = new Interaction(); }
255 
256  /*
257  * Destructor.
258  */
259  template <class Interaction>
261  {
262  if (interactionPtr_) {
263  delete interactionPtr_;
264  }
265  }
266 
267  /*
268  * Set the maximum number of atom types.
269  */
270  template <class Interaction>
272  { interaction().setNBondType(nBondType); }
273 
274  /*
275  * Read bond interaction parameters.
276  */
277  template <class Interaction>
279  {
280  UTIL_CHECK(!isInitialized_);
281  bool nextIndent = false;
282  addParamComposite(interaction(), nextIndent);
283  interaction().readParameters(in);
284  isInitialized_ = true;
285  }
286 
287  /*
288  * Load internal state from an archive.
289  */
290  template <class Interaction>
291  void
293  {
294  UTIL_CHECK(!isInitialized_);
295  bool nextIndent = false;
296  addParamComposite(interaction(), nextIndent);
297  interaction().loadParameters(ar);
298  isInitialized_ = true;
299  }
300 
301  /*
302  * Save internal state to an archive.
303  */
304  template <class Interaction>
306  { interaction().save(ar); }
307 
308  /*
309  * Return bond energy for a single pair.
310  */
311  template <class Interaction>
312  double
313  BondPotentialImpl<Interaction>::bondEnergy(double rsq, int bondTypeId) const
314  { return interaction().energy(rsq, bondTypeId); }
315 
316  /*
317  * Return force / separation for a single bonded pair.
318  */
319  template <class Interaction>
320  double
322  const
323  { return interaction().forceOverR(rsq, bondTypeId); }
324 
325  /*
326  * Return random bond length.
327  */
328  template <class Interaction> double
330  randomBondLength(Random* random, double beta, int bondTypeId) const
331  { return interaction().randomBondLength(random, beta, bondTypeId); }
332 
333  /*
334  * Return bond potential interaction class name.
335  */
336  template <class Interaction>
338  { return interaction().className(); }
339 
340  /*
341  * Modify a bond parameter, identified by a string.
342  */
343  template <class Interaction>
344  inline
345  void BondPotentialImpl<Interaction>::set(std::string name, int bondTypeId,
346  double value)
347  { interactionPtr_->set(name, bondTypeId, value); }
348 
349  /*
350  * Get a parameter value, identified by a string.
351  */
352  template <class Interaction>
353  inline
354  double BondPotentialImpl<Interaction>::get(std::string name, int bondTypeId) const
355  { return interactionPtr_->get(name, bondTypeId); }
356 
357  /*
358  * Get Interaction by reference.
359  */
360  template <class Interaction>
362  { return *interactionPtr_; }
363 
364  /*
365  * Get Interaction by const reference.
366  */
367  template <class Interaction>
368  inline const Interaction& BondPotentialImpl<Interaction>::interaction() const
369  { return *interactionPtr_; }
370 
371  /*
372  * Increment atomic forces, without calculating energy.
373  */
374  template <class Interaction>
376  {
377  Vector f;
378  double rsq;
379  GroupIterator<2> iter;
380  Atom* atom0Ptr;
381  Atom* atom1Ptr;
382  int type, isLocal0, isLocal1;
383 
384  storage().begin(iter);
385  for ( ; iter.notEnd(); ++iter) {
386  type = iter->typeId();
387  atom0Ptr = iter->atomPtr(0);
388  atom1Ptr = iter->atomPtr(1);
389  isLocal0 = !(atom0Ptr->isGhost());
390  isLocal1 = !(atom1Ptr->isGhost());
391  // Set f = r0 - r1, minimum image separation between atoms
392  rsq = boundary().distanceSq(atom0Ptr->position(),
393  atom1Ptr->position(), f);
394  // Set force = (r0-r1)*(forceOverR)
395  f *= interactionPtr_->forceOverR(rsq, type);
396  if (isLocal0) {
397  atom0Ptr->force() += f;
398  }
399  if (isLocal1) {
400  atom1Ptr->force() -= f;
401  }
402  }
403  }
404 
405  /*
406  * Compute total bond energy on all processors, store result on master.
407  */
408  template <class Interaction>
409  #ifdef UTIL_MPI
410  void
411  BondPotentialImpl<Interaction>::computeEnergy(MPI::Intracomm& communicator)
412  #else
414  #endif
415  {
416 
417  // If energy is already set, do nothing and return.
418  if (isEnergySet()) return;
419 
420  Vector f;
421  double rsq;
422  double bondEnergy;
423  double localEnergy = 0.0;
424  GroupIterator<2> iter;
425  Atom* atom0Ptr;
426  Atom* atom1Ptr;
427  int type, isLocal0, isLocal1;
428 
429  // Loop over bonds to compute localEnergy on this processor.
430  storage().begin(iter);
431  for ( ; iter.notEnd(); ++iter) {
432  type = iter->typeId();
433  atom0Ptr = iter->atomPtr(0);
434  atom1Ptr = iter->atomPtr(1);
435 
436  // Calculate minimum image square distance between atoms
437  rsq = boundary().distanceSq(atom0Ptr->position(),
438  atom1Ptr->position());
439  bondEnergy = interactionPtr_->energy(rsq, type);
440 
441  isLocal0 = !(atom0Ptr->isGhost());
442  isLocal1 = !(atom1Ptr->isGhost());
443  if (isLocal0 && isLocal1) {
444  localEnergy += bondEnergy;
445  } else {
446  assert(isLocal0 || isLocal1);
447  localEnergy += 0.5*bondEnergy;
448  }
449  }
450 
451  // Add localEnergy from all processors, set energy to sum on master.
452  reduceEnergy(localEnergy, communicator);
453  }
454 
455  /*
456  * Compute total pair stress (Call on all processors).
457  */
458  template <class Interaction>
459  #ifdef UTIL_MPI
460  void BondPotentialImpl<Interaction>::computeStress(MPI::Intracomm& communicator)
461  #else
463  #endif
464  {
465  // Do nothing and return if stress is already set.
466  if (isStressSet()) return;
467 
468  Tensor localStress;
469  Vector dr;
470  Vector f;
471  double rsq, forceOverR;
472  GroupIterator<2> iter;
473  Atom* atom0Ptr;
474  Atom* atom1Ptr;
475  int type;
476  int isLocal0, isLocal1;
477 
478  localStress.zero();
479 
480  // Iterate over bonds
481  storage().begin(iter);
482  for ( ; iter.notEnd(); ++iter) {
483  type = iter->typeId();
484  atom0Ptr = iter->atomPtr(0);
485  atom1Ptr = iter->atomPtr(1);
486  isLocal0 = !(atom0Ptr->isGhost());
487  isLocal1 = !(atom1Ptr->isGhost());
488  rsq = boundary().distanceSq(atom0Ptr->position(),
489  atom1Ptr->position(), dr);
490  f = dr;
491  assert(isLocal0 || isLocal1);
492  if (isLocal0 && isLocal1) {
493  forceOverR = interactionPtr_->forceOverR(rsq, type);
494  } else {
495  forceOverR = 0.5*interactionPtr_->forceOverR(rsq, type);
496  }
497  f *= forceOverR;
498  incrementPairStress(f, dr, localStress);
499  }
500 
501  // if (reverseUpdateFlag()) { } else { }
502 
503  // Normalize by volume
504  localStress /= boundary().volume();
505 
506  // Add localStress from all processors, set stress to sum on master
507  reduceStress(localStress, communicator);
508  }
509 
510  /*
511  * Compute total pair stress (Call on all processors).
512  */
513  template <class Interaction>
514  #ifdef UTIL_MPI
516  #else
518  #endif
519  {
520  // Do nothing and return if stress is already set.
521  if (isStressSet()) {
522  computeForces();
523  return;
524  }
525 
526  Tensor localStress;
527  Vector dr;
528  Vector f;
529  double rsq;
530  GroupIterator<2> iter;
531  Atom* atom0Ptr;
532  Atom* atom1Ptr;
533  int type;
534  int isLocal0, isLocal1;
535 
536  localStress.zero();
537 
538  // Iterate over bonds
539  storage().begin(iter);
540  for ( ; iter.notEnd(); ++iter) {
541  type = iter->typeId();
542  atom0Ptr = iter->atomPtr(0);
543  atom1Ptr = iter->atomPtr(1);
544  rsq = boundary().distanceSq(atom0Ptr->position(),
545  atom1Ptr->position(), dr);
546  f = dr;
547  f *= interactionPtr_->forceOverR(rsq, type);
548  isLocal0 = !(atom0Ptr->isGhost());
549  isLocal1 = !(atom1Ptr->isGhost());
550  assert(isLocal0 || isLocal1);
551  if (isLocal0) {
552  atom0Ptr->force() += f;
553  }
554  if (isLocal1) {
555  atom1Ptr->force() -= f;
556  }
557  if (!(isLocal0 && isLocal1)) {
558  f *= 0.5;
559  }
560  incrementPairStress(f, dr, localStress);
561  }
562 
563  // if (reverseUpdateFlag()) { } else { }
564 
565  // Normalize by volume
566  localStress /= boundary().volume();
567 
568  // Add localStress from all processors, set stress to sum on master
569  reduceStress(localStress, communicator);
570  }
571 
572 }
573 #endif
A Vector is a Cartesian vector.
Definition: Vector.h:75
double distanceSq(const Vector &r1, const Vector &r2) const
Return square distance between positions r1 and r2.
Implementation template for a BondPotential.
bool isStressSet() const
Is the stress set (known)?
Definition: Potential.cpp:94
void reduceStress(Tensor &localStress, MPI::Intracomm &communicator)
Add local stresses from all processors, set total on master.
Definition: Potential.cpp:142
double volume() const
Return unit cell volume.
Vector & position()
Get position Vector by reference.
Tensor & zero()
Set all elements of this tensor to zero.
Definition: Tensor.h:441
virtual double randomBondLength(Random *random, double beta, int bondTypeId) const
Return force / separation for a single pair.
Abstract base class for computing bond forces and energies.
virtual void computeStress(MPI::Intracomm &communicator)
Compute the covalent bond stress.
virtual void computeEnergy(MPI::Intracomm &communicator)
Compute the total bond energy for all processors.
File containing preprocessor macros for error handling.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
const Interaction & interaction() const
Return bond interaction by const reference.
int nBondType()
Get maximum number of bond types.
A point particle in an MD simulation.
Parallel domain decomposition (DD) MD simulation.
Classes used by all simpatico molecular simulations.
virtual void computeForces()
Add the bond forces for all atoms.
virtual void readParameters(std::istream &in)
Read potential energy parameters.
Main object for a domain-decomposition MD simulation.
A Tensor represents a Cartesian tensor.
Definition: Tensor.h:32
virtual double bondEnergy(double rsq, int bondTypeId) const
Return pair energy for a single pair.
Saving / output archive for binary ostream.
bool isGhost() const
Is this atom a ghost?
Iterator for all Group < N > objects owned by a GroupStorage< N >.
Definition: GroupIterator.h:25
bool notEnd() const
Is the current pointer not at the end of the PArray?
Utility classes for scientific computation.
Definition: accumulators.mod:1
void set(std::string name, int bondTypeId, double value)
Modify a bond parameter, identified by a string.
double get(std::string name, int bondTypeId) const
Get a parameter value, identified by a string.
virtual void setNBondType(int nAtomType)
Set the maximum number of atom types.
void begin(GroupIterator< N > &iterator)
Set iterator to beginning of the set of groups.
void incrementPairStress(const Vector &f, const Vector &dr, Tensor &stress) const
Add a pair contribution to the stress tensor.
Definition: Potential.h:235
virtual double bondForceOverR(double rsq, int bondTypeId) const
Return force / separation for a single pair.
GroupStorage< 2 > & storage() const
Return bond storage by reference.
Saving archive for binary istream.
Vector & force()
Get force Vector by reference.
void addParamComposite(ParamComposite &child, bool next=true)
Add a child ParamComposite object to the format array.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
virtual void computeForcesAndStress(MPI::Intracomm &communicator)
Compute bond forces and stress.
void reduceEnergy(double localEnergy, MPI::Intracomm &communicator)
Add local energies from all processors, set energy on master.
Definition: Potential.cpp:120
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition: global.h:68
virtual std::string interactionClassName() const
Return pair interaction class name (e.g., "HarmonicBond").
Boundary & boundary() const
Return boundary by reference.
Random number generator.
Definition: Random.h:46
bool isEnergySet() const
Is the energy set (known)?
Definition: Potential.cpp:57