Simpatico  v1.10
mcMd/potentials/dihedral/DihedralPotentialImpl.h
1 #ifndef MCMD_DIHEDRAL_POTENTIAL_IMPL_H
2 #define MCMD_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 <mcMd/potentials/dihedral/DihedralPotential.h> // base class
13 #include <mcMd/simulation/SystemInterface.h> // base class
14 
15 namespace Util
16 {
17  class Vector;
18  class Tensor;
19 }
20 
21 namespace McMd
22 {
23 
24  class System;
25 
26  using namespace Util;
27 
33  template <class Interaction>
35  private SystemInterface
36  {
37 
38  public:
39 
44 
49 
53  virtual ~DihedralPotentialImpl();
54 
64  virtual void readParameters(std::istream& in);
65 
71  virtual void loadParameters(Serializable::IArchive &ar);
72 
78  virtual void save(Serializable::OArchive &ar);
79 
81 
82 
97  virtual
98  double energy(const Vector& R1, const Vector& R2, const Vector& R3,
99  int type) const;
100 
113  virtual
114  void force(const Vector& R1, const Vector& R2, const Vector& R3,
115  Vector& F1, Vector& F2, Vector& F3, int type) const;
116 
124  void set(std::string name, int type, double value)
125  { interactionPtr_->set(name, type, value); }
126 
134  double get(std::string name, int type) const
135  { return interactionPtr_->get(name, type); }
136 
140  virtual std::string interactionClassName() const;
141 
145  Interaction& interaction();
146 
150  const Interaction& interaction() const;
151 
153 
155 
162  virtual double atomEnergy(const Atom& atom) const;
163 
167  virtual void addForces();
168 
172  virtual void computeEnergy();
173 
177  virtual void computeStress();
178 
180 
181  private:
182 
183  Interaction* interactionPtr_;
184 
185  bool isCopy_;
186 
190  template <typename T>
191  void computeStressImpl(T& stress) const;
192 
193  };
194 
195 }
196 
197 #include <mcMd/simulation/System.h>
198 #include <mcMd/simulation/Simulation.h>
199 #include <mcMd/simulation/stress.h>
200 #include <mcMd/chemistry/getAtomGroups.h>
201 #include <simp/boundary/Boundary.h>
202 #include <util/space/Dimension.h>
203 #include <util/space/Vector.h>
204 #include <util/space/Tensor.h>
205 #include <util/accumulators/setToZero.h>
206 
207 #include <fstream>
208 
209 namespace McMd
210 {
211 
212  using namespace Util;
213  using namespace Simp;
214 
215  /*
216  * Default constructor.
217  */
218  template <class Interaction>
220  : DihedralPotential(),
221  SystemInterface(system),
222  interactionPtr_(0),
223  isCopy_(false)
224  { interactionPtr_ = new Interaction(); }
225 
226  /*
227  * Constructor, copy from DihedralPotentialImpl<Interaction>.
228  */
229  template <class Interaction>
232  : DihedralPotential(),
233  SystemInterface(other.system()),
234  interactionPtr_(&other.interaction()),
235  isCopy_(true)
236  {}
237 
238  /*
239  * Destructor.
240  */
241  template <class Interaction>
243  {}
244 
245  /*
246  * Read parameters from file.
247  */
248  template <class Interaction>
250  {
251  if (!isCopy_) {
252  interaction().setNDihedralType(simulation().nDihedralType());
253  bool nextIndent = false;
254  addParamComposite(interaction(), nextIndent);
255  interaction().readParameters(in);
256  }
257  }
258 
259  /*
260  * Load internal state from an archive.
261  */
262  template <class Interaction>
263  void
265  {
266  ar >> isCopy_;
267  if (!isCopy_) {
268  interaction().setNDihedralType(simulation().nDihedralType());
269  bool nextIndent = false;
270  addParamComposite(interaction(), nextIndent);
271  interaction().loadParameters(ar);
272  }
273  }
274 
275  /*
276  * Save internal state to an archive.
277  */
278  template <class Interaction>
280  {
281  ar << isCopy_;
282  if (!isCopy_) {
283  interaction().save(ar);
284  }
285  }
286 
287  /*
288  * Return energy for a single dihedral.
289  */
290  template <class Interaction>
292  energy(const Vector& R1, const Vector& R2, const Vector& R3, int typeId) const
293  { return interaction().energy(R1, R2, R3, typeId); }
294 
295  /*
296  * Return forces for a single dihedral.
297  */
298  template <class Interaction>
300  force(const Vector& R1, const Vector& R2, const Vector& R3,
301  Vector& F1, Vector& F2, Vector& F3, int typeId) const
302  { interaction().force(R1, R2, R3, F1, F2, F3, typeId); }
303 
304  /*
305  * Return dihedral energy for one Atom.
306  */
307  template <class Interaction>
309  const
310  {
311  Vector dr1; // R[1] - R[0]
312  Vector dr2; // R[2] - R[1]
313  Vector dr3; // R[3] - R[2]
314  double energy = 0.0;
315  AtomDihedralArray dihedrals;
316  const Dihedral* dihedralPtr;
317  int iDihedral;
318 
319  getAtomDihedrals(atom, dihedrals);
320  for (iDihedral = 0; iDihedral < dihedrals.size(); ++iDihedral) {
321  dihedralPtr = dihedrals[iDihedral];
322  boundary().distanceSq(dihedralPtr->atom(1).position(),
323  dihedralPtr->atom(0).position(), dr1);
324  boundary().distanceSq(dihedralPtr->atom(2).position(),
325  dihedralPtr->atom(1).position(), dr2);
326  boundary().distanceSq(dihedralPtr->atom(3).position(),
327  dihedralPtr->atom(2).position(), dr3);
328  energy += interaction().energy(dr1, dr2, dr3,
329  dihedralPtr->typeId());
330  }
331  return energy;
332  }
333 
334  /*
335  * Compute total dihedral energy for a System.
336  */
337  template <class Interaction>
339  {
340  Vector dr1; // R[1] - R[0]
341  Vector dr2; // R[2] - R[1]
342  Vector dr3; // R[3] - R[2]
343  double energy = 0.0;
345  Molecule::ConstDihedralIterator dihedralIter;
346 
347  for (int iSpec=0; iSpec < simulation().nSpecies(); ++iSpec) {
348  if (simulation().species(iSpec).nDihedral() > 0) {
349  for (begin(iSpec, molIter); molIter.notEnd(); ++molIter) {
350  molIter->begin(dihedralIter);
351  for ( ; dihedralIter.notEnd(); ++dihedralIter){
352  boundary().distanceSq(dihedralIter->atom(1).position(),
353  dihedralIter->atom(0).position(), dr1);
354  boundary().distanceSq(dihedralIter->atom(2).position(),
355  dihedralIter->atom(1).position(), dr2);
356  boundary().distanceSq(dihedralIter->atom(3).position(),
357  dihedralIter->atom(2).position(), dr3);
358  energy += interaction().
359  energy(dr1, dr2, dr3, dihedralIter->typeId());
360  }
361  }
362  }
363  }
364 
365  energy_.set(energy);
366  // return energy;
367  }
368 
369  /*
370  * Add dihedral forces to atomic forces.
371  */
372  template <class Interaction>
374  {
375  Vector dr1, dr2, dr3, force1, force2, force3;
376  Atom *atom0Ptr, *atom1Ptr, *atom2Ptr, *atom3Ptr;
377  int iSpec;
378 
379  System::MoleculeIterator molIter;
380  Molecule::DihedralIterator dihedralIter;
381  for (iSpec=0; iSpec < simulation().nSpecies(); ++iSpec) {
382  if (simulation().species(iSpec).nDihedral() > 0) {
383  for (begin(iSpec, molIter); molIter.notEnd(); ++molIter) {
384  molIter->begin(dihedralIter);
385  for ( ; dihedralIter.notEnd(); ++dihedralIter) {
386 
387  atom0Ptr = &(dihedralIter->atom(0));
388  atom1Ptr = &(dihedralIter->atom(1));
389  atom2Ptr = &(dihedralIter->atom(2));
390  atom3Ptr = &(dihedralIter->atom(3));
391 
392  boundary().distanceSq(atom1Ptr->position(),
393  atom0Ptr->position(), dr1);
394  boundary().distanceSq(atom2Ptr->position(),
395  atom1Ptr->position(), dr2);
396  boundary().distanceSq(atom3Ptr->position(),
397  atom2Ptr->position(), dr3);
398  interaction().force(dr1, dr2, dr3,
399  force1, force2, force3, dihedralIter->typeId());
400 
401  atom0Ptr->force() += force1;
402  atom1Ptr->force() -= force1;
403  atom1Ptr->force() += force2;
404  atom2Ptr->force() -= force2;
405  atom2Ptr->force() += force3;
406  atom3Ptr->force() -= force3;
407  }
408  }
409  }
410  }
411  }
412 
413  /*
414  * Generic stress / pressure computation.
415  *
416  * Allowed types:
417  * T == Tensor -> compute stress tensor
418  * T == Vector -> compute xx, yy, zz diagonal components
419  * T == double -> compute pressure (P_xx + P_yy + P_zz)/3
420  */
421  template <class Interaction>
422  template <typename T>
424  const
425  {
426  Vector dr1, dr2, dr3, force1, force2, force3;
427 
428  setToZero(stress);
429 
430  // Iterate over all dihedrals in System.
432  Molecule::ConstDihedralIterator dihedralIter;
433  for (int iSpec = 0; iSpec < simulation().nSpecies(); ++iSpec) {
434  if (simulation().species(iSpec).nDihedral() > 0) {
435  for (begin(iSpec, molIter); molIter.notEnd(); ++molIter) {
436  molIter->begin(dihedralIter);
437  for ( ; dihedralIter.notEnd(); ++dihedralIter){
438 
439  boundary().distanceSq(dihedralIter->atom(1).position(),
440  dihedralIter->atom(0).position(), dr1);
441  boundary().distanceSq(dihedralIter->atom(2).position(),
442  dihedralIter->atom(1).position(), dr2);
443  boundary().distanceSq(dihedralIter->atom(3).position(),
444  dihedralIter->atom(2).position(), dr3);
445 
446  interaction().force(dr1, dr2, dr3, force1, force2, force3,
447  dihedralIter->typeId());
448 
449  dr1 *= -1.0;
450  dr2 *= -1.0;
451  dr3 *= -1.0;
452  incrementPairStress(force1, dr1, stress);
453  incrementPairStress(force2, dr2, stress);
454  incrementPairStress(force3, dr3, stress);
455  }
456  }
457  }
458  }
459 
460  stress /= boundary().volume();
461  normalizeStress(stress);
462  }
463 
464  /*
465  * Compute dihedral stress.
466  */
467  template <class Interaction>
469  {
470  // Compute stress tensor
471  Tensor stress;
472  computeStressImpl(stress);
473 
474  // Set value of Setable<double> energy_
475  stress_.set(stress);
476  }
477 
478  template <class Interaction>
480  { return *interactionPtr_; }
481 
482  template <class Interaction>
483  inline const Interaction& DihedralPotentialImpl<Interaction>::interaction() const
484  { return *interactionPtr_; }
485 
486  /*
487  * Return dihedral potential interaction class name.
488  */
489  template <class Interaction>
491  { return interaction().className(); }
492 
493 }
494 #endif
A Vector is a Cartesian vector.
Definition: Vector.h:75
virtual void readParameters(std::istream &in)
Read dihedral potential parameters.
An interface to a System.
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
Vector & force()
Get atomic force Vector by reference.
double volume() const
Return unit cell volume.
void set(const T &value)
Set the value and mark as set.
Definition: Setable.h:107
A set of interacting Molecules enclosed by a Boundary.
Definition: System.h:115
int typeId() const
Get the typeId for this covalent group.
Forward iterator for a PArray.
File containing preprocessor macros for error handling.
Classes used by all simpatico molecular simulations.
void getAtomDihedrals(const Atom &atom, AtomDihedralArray &groups)
Fill an array of pointers to Dihedrals that contain an Atom.
A Tensor represents a Cartesian tensor.
Definition: Tensor.h:32
Interface for a Dihedral Potential.
Forward const iterator for an Array or a C array.
Saving / output archive for binary ostream.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
A fixed capacity (static) contiguous array with a variable logical size.
Definition: FSArray.h:37
int nDihedral() const
Get number of dihedrals per molecule for this Species.
virtual void force(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.
Simulation & simulation() const
Get the parent Simulation by reference.
void setToZero(int &value)
Set an int variable to zero.
Definition: setToZero.h:25
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
Forward iterator for an Array or a C array.
Definition: ArrayIterator.h:39
Forward iterator for a PArray.
Definition: ArraySet.h:19
Atom & atom(int i)
Get a specific Atom in the Group by reference.
virtual double atomEnergy(const Atom &atom) const
Compute and return the dihedral energy for one Atom.
bool notEnd() const
Is the current pointer not at the end of the array?
void begin(int speciesId, System::MoleculeIterator &iterator)
Initialize an iterator for molecules of one species in this SystemInterface.
virtual std::string interactionClassName() const
Return pair interaction class name (e.g., "CosineDihedral").
Interaction & interaction()
Return dihedral potential interaction by reference.
Saving archive for binary istream.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
int nSpecies() const
Get the number of Species in this Simulation.
void addParamComposite(ParamComposite &child, bool next=true)
Add a child ParamComposite object to the format array.
A sequence of NAtom covalently interacting atoms.
virtual void computeStress()
Compute and store the total dihedral pressure.
Boundary & boundary() const
Get the Boundary by reference.
Implementation template for an DihedralPotential.
virtual void addForces()
Add dihedral forces to all atomic forces.
const Vector & position() const
Get the position Vector by const reference.
bool notEnd() const
Is this not the end of the array?
virtual void computeEnergy()
Calculate and store dihedral energy for this System.
Species & species(int i)
Get a specific Species by reference.
int size() const
Return logical size of this array (i.e., number of elements).
Definition: FSArray.h:207
System & system() const
Get the parent System by reference.
double energy()
Return the energy contribution, compute if necessary.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.