Simpatico  v1.10
mcMd/potentials/angle/AnglePotentialImpl.h
1 #ifndef MCMD_ANGLE_POTENTIAL_IMPL_H
2 #define MCMD_ANGLE_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 <mcMd/potentials/angle/AnglePotential.h> // base class
12 #include <mcMd/simulation/SystemInterface.h> // base class
13 #include <util/global.h>
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  {
36 
37  public:
38 
42  AnglePotentialImpl(System& system);
43 
48 
52  virtual ~AnglePotentialImpl();
53 
63  virtual void readParameters(std::istream& in);
64 
70  virtual void loadParameters(Serializable::IArchive &ar);
71 
77  virtual void save(Serializable::OArchive &ar);
78 
80 
81 
88  double energy(double cosTheta, int type) const;
89 
100  void force(const Vector& R1, const Vector& R2,
101  Vector& F1, Vector& F2, int type) const;
102 
110  virtual
111  double randomAngle(Random* random, double beta, int type)
112  const;
113 
121  virtual
122  double randomCosineAngle(Random *random, double beta, int type) const;
123 
131  void set(std::string name, int type, double value)
132  { interactionPtr_->set(name, type, value); }
133 
141  double get(std::string name, int type) const
142  { return interactionPtr_->get(name, type); }
143 
147  virtual std::string interactionClassName() const;
148 
152  Interaction& interaction();
153 
157  const Interaction& interaction() const;
158 
160 
162 
169  virtual double atomEnergy(const Atom& atom) const;
170 
174  virtual void addForces();
175 
179  virtual void computeEnergy();
180 
184  virtual void computeStress();
185 
187 
188  private:
189 
190  Interaction* interactionPtr_;
191 
192  bool isCopy_;
193 
197  template <typename T>
198  void computeStressImpl(T& stress) const;
199 
200  };
201 
202 }
203 
204 #include <mcMd/simulation/System.h>
205 #include <mcMd/simulation/Simulation.h>
206 #include <mcMd/simulation/stress.h>
207 #include <mcMd/chemistry/getAtomGroups.h>
208 #include <simp/boundary/Boundary.h>
209 #include <util/space/Dimension.h>
210 #include <util/space/Vector.h>
211 #include <util/space/Tensor.h>
212 #include <util/accumulators/setToZero.h>
213 
214 #include <fstream>
215 
216 namespace McMd
217 {
218 
219  using namespace Util;
220  using namespace Simp;
221 
222  /*
223  * Default constructor.
224  */
225  template <class Interaction>
227  : AnglePotential(),
228  SystemInterface(system),
229  interactionPtr_(0),
230  isCopy_(false)
231  { interactionPtr_ = new Interaction(); }
232 
233  /*
234  * Constructor, copy from AnglePotentialImpl<Interaction>.
235  */
236  template <class Interaction>
239  : AnglePotential(),
240  SystemInterface(other.system()),
241  interactionPtr_(&other.interaction()),
242  isCopy_(true)
243  {}
244 
245  /*
246  * Destructor.
247  */
248  template <class Interaction>
250  {
251  if (interactionPtr_ && !isCopy_) {
252  delete interactionPtr_;
253  interactionPtr_ = 0;
254  }
255  }
256 
257  /*
258  * Read parameters from file.
259  */
260  template <class Interaction>
262  {
263  if (!isCopy_) {
264  interaction().setNAngleType(simulation().nAngleType());
265  bool nextIndent = false;
266  addParamComposite(interaction(), nextIndent);
267  interaction().readParameters(in);
268  }
269  }
270 
271  /*
272  * Load internal state from an archive.
273  */
274  template <class Interaction>
275  void
277  {
278  ar >> isCopy_;
279  if (!isCopy_) {
280  interaction().setNAngleType(simulation().nAngleType());
281  bool nextIndent = false;
282  addParamComposite(interaction(), nextIndent);
283  interaction().loadParameters(ar);
284  }
285  }
286 
287  /*
288  * Save internal state to an archive.
289  */
290  template <class Interaction>
292  {
293  ar << isCopy_;
294  if (!isCopy_) {
295  interaction().save(ar);
296  }
297  }
298 
299  /*
300  * Return energy for a single angle.
301  */
302  template <class Interaction>
303  double AnglePotentialImpl<Interaction>::energy(double cosTheta, int type)
304  const
305  { return interaction().energy(cosTheta, type); }
306 
307  /*
308  * Return forces for a single angle.
309  */
310  template <class Interaction>
312  Vector& F1, Vector& F2, int type) const
313  { interaction().force(R1, R2, F1, F2, type); }
314 
315  /*
316  * Returns a random angle.
317  */
318  template <class Interaction>
320  double beta, int type) const
321  { return interaction().randomAngle(random, beta, type); }
322 
323  /*
324  * Returns Cosine of a random angle.
325  */
326  template <class Interaction>
328  double beta, int type) const
329  { return interaction().randomCosineAngle(random, beta, type); }
330 
331  /*
332  * Return angle energy for one Atom.
333  */
334  template <class Interaction>
336  {
337  AtomAngleArray angles;
338  const Angle* anglePtr;
339  int iAngle;
340  Vector dr1; // R[1] - R[0]
341  Vector dr2; // R[2] - R[1]
342  double rsq1, rsq2, cosTheta;
343  double energy = 0.0;
344 
345  getAtomAngles(atom, angles);
346  for (iAngle = 0; iAngle < angles.size(); ++iAngle) {
347  anglePtr = angles[iAngle];
348  rsq1 = boundary().distanceSq(anglePtr->atom(1).position(),
349  anglePtr->atom(0).position(), dr1);
350  rsq2 = boundary().distanceSq(anglePtr->atom(2).position(),
351  anglePtr->atom(1).position(), dr2);
352  cosTheta = dr1.dot(dr2) / sqrt(rsq1 * rsq2);
353  energy += interaction().energy(cosTheta, anglePtr->typeId());
354  }
355 
356  return energy;
357  }
358 
359  /*
360  * Compute and store angle energy.
361  */
362  template <class Interaction>
364  {
365  Vector dr1; // R[1] - R[0]
366  Vector dr2; // R[2] - R[1]
367  double rsq1, rsq2, cosTheta;
368  double energy = 0.0;
371 
372  for (int iSpec=0; iSpec < simulation().nSpecies(); ++iSpec) {
373  if (simulation().species(iSpec).nAngle() > 0) {
374  for (begin(iSpec, molIter); molIter.notEnd(); ++molIter) {
375  for (molIter->begin(angleIter); angleIter.notEnd(); ++angleIter){
376  rsq1 = boundary().distanceSq(angleIter->atom(1).position(),
377  angleIter->atom(0).position(), dr1);
378  rsq2 = boundary().distanceSq(angleIter->atom(2).position(),
379  angleIter->atom(1).position(), dr2);
380  cosTheta = dr1.dot(dr2) / sqrt(rsq1 * rsq2);
381  energy += interaction().energy(cosTheta, angleIter->typeId());
382  }
383  }
384  }
385  }
386 
387  // return energy;
388  energy_.set(energy);
389  }
390 
391  /*
392  * Add angle forces to forces array.
393  */
394  template <class Interaction>
396  {
397  Vector dr1, dr2, force1, force2;
398  System::MoleculeIterator molIter;
399  Molecule::AngleIterator angleIter;
400  Atom *atom0Ptr, *atom1Ptr, *atom2Ptr;
401  int iSpec;
402 
403  for (iSpec=0; iSpec < simulation().nSpecies(); ++iSpec) {
404  if (simulation().species(iSpec).nAngle() > 0) {
405  for (begin(iSpec, molIter); molIter.notEnd(); ++molIter) {
406  for (molIter->begin(angleIter); angleIter.notEnd(); ++angleIter){
407  atom0Ptr = &(angleIter->atom(0));
408  atom1Ptr = &(angleIter->atom(1));
409  atom2Ptr = &(angleIter->atom(2));
410  boundary().distanceSq(atom1Ptr->position(),
411  atom0Ptr->position(), dr1);
412  boundary().distanceSq(atom2Ptr->position(),
413  atom1Ptr->position(), dr2);
414  interaction().force(dr1, dr2, force1, force2,
415  angleIter->typeId());
416  atom0Ptr->force() += force1;
417  atom1Ptr->force() -= force1;
418  atom1Ptr->force() += force2;
419  atom2Ptr->force() -= force2;
420  }
421  }
422  }
423  }
424  }
425 
426  /*
427  * Generic stress / pressure computation.
428  *
429  * Allowed types:
430  * T == Tensor -> compute stress tensor
431  * T == Vector -> compute xx, yy, zz diagonal components
432  * T == double -> compute pressure (P_xx + P_yy + P_zz)/3
433  */
434  template <class Interaction>
435  template <typename T>
437  {
438  Vector dr1, dr2, force1, force2;
439  const Atom *atom0Ptr, *atom1Ptr, *atom2Ptr;
440 
441  setToZero(stress);
442 
443  // Iterate over all angles in System.
446  for (int iSpec = 0; iSpec < simulation().nSpecies(); ++iSpec) {
447  if (simulation().species(iSpec).nAngle() > 0) {
448  for (begin(iSpec, molIter); molIter.notEnd(); ++molIter) {
449  for (molIter->begin(angleIter); angleIter.notEnd(); ++angleIter){
450  atom0Ptr = &(angleIter->atom(0));
451  atom1Ptr = &(angleIter->atom(1));
452  atom2Ptr = &(angleIter->atom(2));
453 
454  boundary().distanceSq(atom1Ptr->position(),
455  atom0Ptr->position(), dr1);
456  boundary().distanceSq(atom2Ptr->position(),
457  atom1Ptr->position(), dr2);
458 
459  // force1 -- along dr1; force2 -- along dr2.
460  interaction().force(dr1, dr2,
461  force1, force2, angleIter->typeId());
462 
463  dr1 *= -1.0;
464  dr2 *= -1.0;
465  incrementPairStress(force1, dr1, stress);
466  incrementPairStress(force2, dr2, stress);
467  }
468  }
469  }
470  }
471 
472  stress /= boundary().volume();
473  normalizeStress(stress);
474  }
475 
476  /*
477  * Compute total angle stress.
478  */
479  template <class Interaction>
481  {
482  Tensor stress;
483  computeStressImpl(stress);
484 
485  // Set value of Setable<double> energy_
486  stress_.set(stress);
487  }
488 
489  template <class Interaction>
491  { return *interactionPtr_; }
492 
493  template <class Interaction>
494  inline const Interaction& AnglePotentialImpl<Interaction>::interaction() const
495  { return *interactionPtr_; }
496 
497  /*
498  * Return angle potential interaction class name.
499  */
500  template <class Interaction>
502  { return interaction().className(); }
503 
504 }
505 #endif
virtual void readParameters(std::istream &in)
Read angle potential parameters.
A Vector is a Cartesian vector.
Definition: Vector.h:75
Interface for a Angle Interaction.
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
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
Vector & force()
Get atomic force Vector by reference.
double volume() const
Return unit cell volume.
double dot(const Vector &v) const
Return dot product of this vector and vector v.
Definition: Vector.h:632
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.
virtual double randomAngle(Random *random, double beta, int type) const
Returns a random bond Angle.
Forward iterator for a PArray.
File containing preprocessor macros for error handling.
Classes used by all simpatico molecular simulations.
virtual double atomEnergy(const Atom &atom) const
Calculate the angle energy for one Atom.
A Tensor represents a Cartesian tensor.
Definition: Tensor.h:32
Forward const iterator for an Array or a C array.
virtual std::string interactionClassName() const
Return pair interaction class name (e.g., "CosineAngle").
Saving / output archive for binary ostream.
void force(const Vector &R1, const Vector &R2, Vector &F1, Vector &F2, int type) const
Returns forces along two bonds at the angle, for use in MD and stress calculation.
A fixed capacity (static) contiguous array with a variable logical size.
Definition: FSArray.h:37
void getAtomAngles(const Atom &atom, AtomAngleArray &groups)
Fill an array of pointers to Angles that contain an Atom.
virtual double randomCosineAngle(Random *random, double beta, int type) const
Returns Cosine a random bond Angle.
Implementation template for an AnglePotential.
virtual void computeStress()
Compute and store the total angle pressure.
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.
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.
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 computeEnergy()
Calculate and store total angle energy.
Boundary & boundary() const
Get the Boundary by reference.
Random number generator.
Definition: Random.h:46
const Vector & position() const
Get the position Vector by const reference.
bool notEnd() const
Is this not the end of the array?
int nAngle() const
Get number of angles per molecule for this Species.
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.
Interaction & interaction()
Return angle interaction by reference.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
virtual void addForces()
Calculate the angle energy for one Atom.
double energy()
Return the energy contribution, compute if necessary.