Simpatico  v1.10
ddMd/potentials/dihedral/DihedralPotentialImpl.h
1 #ifndef DDMD_DIHEDRAL_POTENTIAL_IMPL_H
2 #define DDMD_DIHEDRAL_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 "DihedralPotential.h" // base class
13 
14 namespace Util
15 {
16  class Vector;
17  class Tensor;
18 }
19 
20 namespace DdMd
21 {
22 
23  using namespace Util;
24 
25  class Simulation;
26  template <int N> class GroupStorage;
27 
33  template <class Interaction>
35  {
36 
37  public:
38 
46  DihedralPotentialImpl(Simulation& simulation);
47 
54 
58  virtual ~DihedralPotentialImpl();
59 
61 
62 
70  virtual void setNDihedralType(int nAtomType);
71 
81  virtual void readParameters(std::istream& in);
82 
89  virtual void loadParameters(Serializable::IArchive &ar);
90 
98  virtual void save(Serializable::OArchive &ar);
99 
101 
103 
111  void set(std::string name, int type, double value);
112 
119  double get(std::string name, int type) const;
120 
135  virtual double
136  dihedralEnergy(const Vector& R1, const Vector& R2, const Vector& R3,
137  int type) const;
138 
151  virtual void
152  dihedralForce(const Vector& R1, const Vector& R2, const Vector& R3,
153  Vector& F1, Vector& F2, Vector& F3, int type) const;
154 
158  virtual std::string interactionClassName() const;
159 
163  Interaction& interaction();
164 
168  const Interaction& interaction() const;
169 
171 
173 
177  virtual void computeForces();
178 
184  #ifdef UTIL_MPI
185  virtual void computeEnergy(MPI::Intracomm& communicator);
186  #else
187  virtual void computeEnergy();
188  #endif
189 
195  #ifdef UTIL_MPI
196  virtual void computeStress(MPI::Intracomm& communicator);
197  #else
198  virtual void computeStress();
199  #endif
200 
202 
203  private:
204 
208  Interaction* interactionPtr_;
209 
213  bool isInitialized_;
214 
215  };
216 
217 }
218 
219 #include "DihedralPotential.h"
220 #include <ddMd/simulation/Simulation.h>
221 #include <ddMd/storage/GroupStorage.h>
222 #include <ddMd/storage/GroupIterator.h>
223 #include <simp/boundary/Boundary.h>
224 #include <util/space/Vector.h>
225 #include <util/space/Dimension.h>
226 #include <util/space/Vector.h>
227 #include <util/space/Tensor.h>
228 //#include <util/accumulators/setToZero.h>
229 #include <util/global.h>
230 
231 #include <fstream>
232 
233 namespace DdMd
234 {
235 
236  using namespace Util;
237  using namespace Simp;
238 
239  /*
240  * Constructor.
241  */
242  template <class Interaction>
244  : DihedralPotential(simulation),
245  interactionPtr_(0),
246  isInitialized_(false)
247  {
248  interactionPtr_ = new Interaction();
249  setNDihedralType(simulation.nDihedralType());
250  }
251 
252  /*
253  * Default constructor.
254  */
255  template <class Interaction>
257  : DihedralPotential(),
258  interactionPtr_(0),
259  isInitialized_(false)
260  { interactionPtr_ = new Interaction(); }
261 
262  /*
263  * Destructor.
264  */
265  template <class Interaction>
267  {
268  if (interactionPtr_) {
269  delete interactionPtr_;
270  }
271  }
272 
273  /*
274  * Set the maximum number of dihedral types.
275  */
276  template <class Interaction>
278  { interaction().setNDihedralType(nDihedralType); }
279 
280  /*
281  * Read dihedral interaction parameters.
282  */
283  template <class Interaction>
285  {
286  UTIL_CHECK(!isInitialized_)
287  bool nextIndent = false;
288  addParamComposite(interaction(), nextIndent);
289  interaction().readParameters(in);
290  isInitialized_ = true;
291  }
292 
293  /*
294  * Load internal state from an archive.
295  */
296  template <class Interaction>
297  void
299  {
300  UTIL_CHECK(!isInitialized_)
301  bool nextIndent = false;
302  addParamComposite(interaction(), nextIndent);
303  interaction().loadParameters(ar);
304  isInitialized_ = true;
305  }
306 
307  /*
308  * Save internal state to an archive.
309  */
310  template <class Interaction>
312  { interaction().save(ar); }
313 
314  /*
315  * Modify an dihedral parameter, identified by a string.
316  */
317  template <class Interaction>
319  set(std::string name, int type, double value)
320  { interactionPtr_->set(name, type, value); }
321 
322  /*
323  * Get a parameter value, identified by a string.
324  */
325  template <class Interaction>
327  get(std::string name, int type) const
328  { return interactionPtr_->get(name, type); }
329 
330  /*
331  * Return energy for a single dihedral.
332  */
333  template <class Interaction>
335  dihedralEnergy(const Vector& R1, const Vector& R2, const Vector& R3,
336  int typeId) const
337  { return interaction().energy(R1, R2, R3, typeId); }
338 
339  /*
340  * Return forces for a single dihedral.
341  */
342  template <class Interaction>
344  dihedralForce(const Vector& R1, const Vector& R2, const Vector& R3,
345  Vector& F1, Vector& F2, Vector& F3, int typeId) const
346  { interaction().force(R1, R2, R3, F1, F2, F3, typeId); }
347 
348  /*
349  * Return dihedral potential interaction class name.
350  */
351  template <class Interaction>
353  { return interaction().className(); }
354 
355  /*
356  * Get Interaction by reference.
357  */
358  template <class Interaction>
360  { return *interactionPtr_; }
361 
362  /*
363  * Get Interaction by const reference.
364  */
365  template <class Interaction>
366  inline const Interaction& DihedralPotentialImpl<Interaction>::interaction() const
367  { return *interactionPtr_; }
368 
369  /*
370  * Increment atomic forces, without calculating energy.
371  */
372  template <class Interaction>
374  {
375  UTIL_CHECK(isInitialized_);
376 
377  Vector dr1; // R[1] - R[0]
378  Vector dr2; // R[2] - R[1]
379  Vector dr3; // R[3] - R[2]
380  Vector f1, f2, f3;
381  GroupIterator<4> iter;
382  Atom* atom0Ptr;
383  Atom* atom1Ptr;
384  Atom* atom2Ptr;
385  Atom* atom3Ptr;
386  int type;
387 
388  // Loop over dihedral groups
389  for (storage().begin(iter); iter.notEnd(); ++iter) {
390  type = iter->typeId();
391  atom0Ptr = iter->atomPtr(0);
392  atom1Ptr = iter->atomPtr(1);
393  atom2Ptr = iter->atomPtr(2);
394  atom3Ptr = iter->atomPtr(3);
395  // Calculate minimimum image separations dr1, dr2, dr3
396  boundary().distanceSq(atom1Ptr->position(),
397  atom0Ptr->position(), dr1);
398  boundary().distanceSq(atom2Ptr->position(),
399  atom1Ptr->position(), dr2);
400  boundary().distanceSq(atom3Ptr->position(),
401  atom2Ptr->position(), dr3);
402 
403  // Calculate derivatives of energy with respect to r1, r2, r3
404  interaction().force(dr1, dr2, dr3, f1, f2, f3, type);
405 
406  if (!atom0Ptr->isGhost()) {
407  atom0Ptr->force() += f1;
408  }
409  if (!atom1Ptr->isGhost()) {
410  atom1Ptr->force() -= f1;
411  atom1Ptr->force() += f2;
412  }
413  if (!atom2Ptr->isGhost()) {
414  atom2Ptr->force() -= f2;
415  atom2Ptr->force() += f3;
416  }
417  if (!atom3Ptr->isGhost()) {
418  atom3Ptr->force() -= f3;
419  }
420  }
421  }
422 
423  /*
424  * Compute total dihedral energy on all processors.
425  */
426  template <class Interaction>
427  #ifdef UTIL_MPI
428  void
430  #else
432  #endif
433  {
434  UTIL_CHECK(isInitialized_);
435 
436  // If energy is already set, do nothing and return.
437  if (isEnergySet()) return;
438 
439  Vector dr1; // R[1] - R[0]
440  Vector dr2; // R[2] - R[1]
441  Vector dr3; // R[3] - R[2]
442  double dihedralEnergy;
443  double localEnergy;
444  double fraction;
445  GroupIterator<4> iter;
446  Atom* atom0Ptr;
447  Atom* atom1Ptr;
448  Atom* atom2Ptr;
449  Atom* atom3Ptr;
450  int type, isLocal0, isLocal1, isLocal2, isLocal3;
451 
452  // Loop over dihedral groups
453  localEnergy = 0.0;
454  for (storage().begin(iter) ; iter.notEnd(); ++iter) {
455  type = iter->typeId();
456  atom0Ptr = iter->atomPtr(0);
457  atom1Ptr = iter->atomPtr(1);
458  atom2Ptr = iter->atomPtr(2);
459  atom3Ptr = iter->atomPtr(3);
460 
461  // Calculate minimimum image separation vectors
462  boundary().distanceSq(atom1Ptr->position(),
463  atom0Ptr->position(), dr1);
464  boundary().distanceSq(atom2Ptr->position(),
465  atom1Ptr->position(), dr2);
466  boundary().distanceSq(atom3Ptr->position(),
467  atom2Ptr->position(), dr3);
468 
469  // Calculate energy for one dihedral
470  dihedralEnergy = interaction().energy(dr1, dr2, dr3, type);
471 
472  isLocal0 = !(atom0Ptr->isGhost());
473  isLocal1 = !(atom1Ptr->isGhost());
474  isLocal2 = !(atom2Ptr->isGhost());
475  isLocal3 = !(atom3Ptr->isGhost());
476  fraction = (isLocal0 + isLocal1 + isLocal2 + isLocal3)*0.25;
477  localEnergy += fraction*dihedralEnergy;
478  }
479 
480  // Add localEnergy from all nodes, set sum on master
481  reduceEnergy(localEnergy, communicator);
482  }
483 
484  /*
485  * Compute total pair stress (Call on all processors).
486  */
487  template <class Interaction>
488  #ifdef UTIL_MPI
489  void
491  #else
493  #endif
494  {
495  // If stress is already set, do nothing and return.
496  if (isStressSet()) return;
497 
498  Tensor localStress;
499  Vector dr1, dr2, dr3;
500  Vector f1, f2, f3;
501  double factor;
502  double prefactor = -0.25;
503  GroupIterator<4> iter;
504  Atom* atom0Ptr;
505  Atom* atom1Ptr;
506  Atom* atom2Ptr;
507  Atom* atom3Ptr;
508  int type;
509  int isLocal0, isLocal1, isLocal2, isLocal3;
510 
511  // Iterate over dihedrals
512  localStress.zero();
513  for (storage().begin(iter); iter.notEnd(); ++iter) {
514  type = iter->typeId();
515  atom0Ptr = iter->atomPtr(0);
516  atom1Ptr = iter->atomPtr(1);
517  atom2Ptr = iter->atomPtr(2);
518  atom3Ptr = iter->atomPtr(3);
519 
520  // Calculate stress here
521  boundary().distanceSq(atom1Ptr->position(),
522  atom0Ptr->position(), dr1);
523  boundary().distanceSq(atom2Ptr->position(),
524  atom1Ptr->position(), dr2);
525  boundary().distanceSq(atom3Ptr->position(),
526  atom2Ptr->position(), dr3);
527 
528  // Calculate derivatives of energy with respect to dr1, dr2, dr3
529  interaction().force(dr1, dr2, dr2, f1, f2, f3, type);
530 
531  isLocal0 = !(atom0Ptr->isGhost());
532  isLocal1 = !(atom1Ptr->isGhost());
533  isLocal2 = !(atom2Ptr->isGhost());
534  isLocal3 = !(atom3Ptr->isGhost());
535  factor = prefactor*(isLocal0 + isLocal1 + isLocal2 + isLocal3);
536 
537  // Increment localStress tensor
538  dr1 *= factor;
539  dr2 *= factor;
540  dr3 *= factor;
541  incrementPairStress(f1, dr1, localStress);
542  incrementPairStress(f2, dr2, localStress);
543  incrementPairStress(f3, dr3, localStress);
544  }
545 
546  // Normalize by volume
547  localStress /= boundary().volume();
548 
549  // Add localStress from all nodes, set sum on master
550  reduceStress(localStress, communicator);
551  }
552 
553 }
554 #endif
void set(std::string name, int type, double value)
Modify an dihedral parameter, identified by a string.
Boundary & boundary() const
Return boundary by reference.
A Vector is a Cartesian vector.
Definition: Vector.h:75
virtual void dihedralForce(const Vector &R1, const Vector &R2, const Vector &R3, Vector &F1, Vector &F2, Vector &F3, int type) const
Returns derivatives of energy with respect to bond vectors forming the dihedral group.
virtual void setNDihedralType(int nAtomType)
Set the maximum number of atom types.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
double distanceSq(const Vector &r1, const Vector &r2) const
Return square distance between positions r1 and r2.
bool isStressSet() const
Is the stress set (known)?
Definition: Potential.cpp:94
GroupStorage< 4 > & storage() const
Return bond storage by reference.
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.
virtual void readParameters(std::istream &in)
Read potential energy parameters.
Vector & position()
Get position Vector by reference.
virtual void computeForces()
Add the dihedral forces for all atoms.
Tensor & zero()
Set all elements of this tensor to zero.
Definition: Tensor.h:441
File containing preprocessor macros for error handling.
A point particle in an MD simulation.
Parallel domain decomposition (DD) MD simulation.
Classes used by all simpatico molecular simulations.
Main object for a domain-decomposition MD simulation.
A Tensor represents a Cartesian tensor.
Definition: Tensor.h:32
Saving / output archive for binary ostream.
int nDihedralType()
Get maximum number of dihedral types.
Interaction & interaction()
Return dihedral interaction by reference.
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?
virtual double dihedralEnergy(const Vector &R1, const Vector &R2, const Vector &R3, int type) const
Returns potential energy for one dihedral.
Utility classes for scientific computation.
Definition: accumulators.mod:1
Abstract base class for computing dihedral forces and energies.
void incrementPairStress(const Vector &f, const Vector &dr, Tensor &stress) const
Add a pair contribution to the stress tensor.
Definition: Potential.h:235
virtual std::string interactionClassName() const
Return pair interaction class name (e.g., "CosineDihedral").
virtual void computeEnergy(MPI::Intracomm &communicator)
Compute the total dihedral energy for all processors.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
Saving archive for binary istream.
Vector & force()
Get force Vector by reference.
Implementation template for a DihedralPotential.
void addParamComposite(ParamComposite &child, bool next=true)
Add a child ParamComposite object to the format array.
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
double get(std::string name, int type) const
Get a parameter value, identified by a string.
bool isEnergySet() const
Is the energy set (known)?
Definition: Potential.cpp:57
virtual void computeStress(MPI::Intracomm &communicator)
Compute the covalent dihedral stress.