Simpatico  v1.10
McPairPotentialImpl.h
1 #ifndef MCMD_MC_PAIR_INTERACTION_IMPL_H
2 #define MCMD_MC_PAIR_INTERACTION_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/pair/McPairPotential.h>
12 #include <util/global.h>
13 
14 namespace Util
15 {
16  class Vector;
17  class Tensor;
18 }
19 
20 namespace McMd
21 {
22 
23  using namespace Util;
24 
25  class System;
26 
32  template <class Interaction>
34  {
35 
36  public:
37 
41  McPairPotentialImpl(System& system);
42 
46  virtual ~McPairPotentialImpl();
47 
56  virtual void readParameters(std::istream& in);
57 
63  virtual void loadParameters(Serializable::IArchive &ar);
64 
70  virtual void save(Serializable::OArchive &ar);
71 
73 
74 
78  virtual double energy(double rsq, int iAtomType, int jAtomType) const;
79 
83  virtual double forceOverR(double rsq, int iAtomType, int jAtomType) const;
84 
88  virtual double maxPairCutoff() const;
89 
98  void set(std::string name, int i, int j, double value)
99  { interaction_.set(name, i, j, value); }
100 
108  double get(std::string name, int i, int j) const
109  { return interaction_.get(name, i, j); }
110 
114  virtual std::string interactionClassName() const;
115 
119  Interaction& interaction();
120 
124  const Interaction& interaction() const;
125 
127 
129 
136  double atomEnergy(const Atom& atom) const;
137 
144  double moleculeEnergy(const Molecule& molecule) const;
145 
151  virtual void computeEnergy();
152 
158  virtual void computeStress();
159 
161 
162  private:
163 
167  Interaction interaction_;
168 
177  template <typename T>
178  void computeStressImpl(T& stress);
179 
180  };
181 
182 }
183 
184 #include <mcMd/simulation/System.h>
185 #include <mcMd/simulation/Simulation.h>
186 #include <mcMd/simulation/stress.h>
187 #include <mcMd/neighbor/PairIterator.h>
188 #include <simp/boundary/Boundary.h>
189 
190 #include <util/space/Dimension.h>
191 #include <util/space/Vector.h>
192 #include <util/space/Tensor.h>
193 #include <util/accumulators/setToZero.h>
194 
195 #include <fstream>
196 
197 namespace McMd
198 {
199 
200  using namespace Util;
201  using namespace Simp;
202 
203  /*
204  * Default constructor.
205  */
206  template <class Interaction>
208  : McPairPotential(system)
209  {}
210 
211  /*
212  * Destructor.
213  */
214  template <class Interaction>
216  {}
217 
218  /*
219  * Read parameters from file.
220  */
221  template <class Interaction>
223  {
224  interaction().setNAtomType(simulation().nAtomType());
225 
226  // Read potential energy parameters with no indent or brackets.
227  bool nextIndent = false;
228  addParamComposite(interaction(), nextIndent);
229  interaction().readParameters(in);
230 
231  // Set atom capacity and allocate memory in the CellList.
232  cellList_.setAtomCapacity(simulation().atomCapacity());
233  }
234 
235  /*
236  * Load internal state from an archive.
237  */
238  template <class Interaction>
239  void
241  {
242  interaction().setNAtomType(simulation().nAtomType());
243 
244  // Read potential energy parameters with no indent or brackets.
245  bool nextIndent = false;
246  addParamComposite(interaction(), nextIndent);
247  interaction().loadParameters(ar);
248 
249  // Allocate memory for the CellList.
250  cellList_.setAtomCapacity(simulation().atomCapacity());
251  }
252 
253  /*
254  * Save internal state to an archive.
255  */
256  template <class Interaction>
258  {
259  interaction().save(ar);
260  }
261 
262  /*
263  * Return pair energy for a single pair.
264  */
265  template <class Interaction>
266  double
267  McPairPotentialImpl<Interaction>::energy(double rsq, int iAtomType, int jAtomType)
268  const
269  { return interaction().energy(rsq, iAtomType, jAtomType); }
270 
271  /*
272  * Return force / separation for a single pair.
273  */
274  template <class Interaction>
275  double
276  McPairPotentialImpl<Interaction>::forceOverR(double rsq, int iAtomType, int jAtomType)
277  const
278  {
279  if (rsq < interaction().cutoffSq(iAtomType, jAtomType)) {
280  return interaction().forceOverR(rsq, iAtomType, jAtomType);
281  } else {
282  return 0.0;
283  }
284  }
285 
286  /*
287  * Return maximum cutoff.
288  */
289  template <class Interaction>
291  { return interaction().maxPairCutoff(); }
292 
293  /*
294  * Return nonbonded pair energy for one Atom.
295  */
296  template <class Interaction>
298  {
299  Atom *jAtomPtr;
300  double energy;
301  double rsq;
302  int j, jId, nNeighbor;
303  int id = atom.id();
304 
305  // Get array of neighbors
307  nNeighbor = neighbors_.size();
308 
309  // Loop over neighboring atoms
310  energy = 0.0;
311  for (j = 0; j < nNeighbor; ++j) {
312  jAtomPtr = neighbors_[j];
313  jId = jAtomPtr->id();
314 
315  // Check if atoms are the same
316  if (jId != id) {
317 
318  // Check if atoms are bonded
319  if (!atom.mask().isMasked(*jAtomPtr)) {
320  rsq = boundary().
321  distanceSq(atom.position(), jAtomPtr->position());
322  energy += interaction().
323  energy(rsq, atom.typeId(), jAtomPtr->typeId());
324  }
325  }
326  }
327  return energy;
328  }
329 
330  /*
331  * Return nonbonded pair potential energy for one Molecule.
332  */
333  template <class Interaction>
335  {
336  const Atom* iAtomPtr;
337  const Atom* jAtomPtr;
338  double energy;
339  double rsq;
340  int i, iId, j, jId, nNeighbor;
341 
342  energy = 0.0;
343  for (i = 0; i < molecule.nAtom(); ++i) {
344  iAtomPtr = &molecule.atom(i);
345  iId = iAtomPtr->id();
346 
347  // Get array of neighbors
349  nNeighbor = neighbors_.size();
350 
351  // Loop over neighboring atoms
352  for (j = 0; j < nNeighbor; ++j) {
353  jAtomPtr = neighbors_[j];
354  jId = jAtomPtr->id();
355 
356  // Check if atoms are the same
357  if (jId != iId) {
358 
359  // Check if atoms are bonded
360  if (!(iAtomPtr->mask().isMasked(*jAtomPtr))) {
361 
362  if ( (&iAtomPtr->molecule() != &jAtomPtr->molecule()) ||
363  (iId < jId) ) {
364  rsq = boundary().distanceSq(iAtomPtr->position(),
365  jAtomPtr->position());
366  energy += interaction().energy(rsq, iAtomPtr->typeId(),
367  jAtomPtr->typeId());
368  }
369  }
370  }
371  }
372  }
373  return energy;
374  }
375 
376  /*
377  * Compute and store total nonbonded pair potential energy for System.
378  */
379  template <class Interaction>
381  {
382  Atom *iAtomPtr, *jAtomPtr;
383  double energy;
384  double rsq;
385  int nNeighbor, nInCell;
386  int i, j, iId, jId, ic;
387 
388  // Loop over cells
389  energy = 0.0;
390  for (ic=0; ic < cellList_.totCells(); ++ic) {
391 
392  // Get array of neighbors
393  cellList_.getCellNeighbors(ic, neighbors_, nInCell);
394  nNeighbor = neighbors_.size();
395 
396  // Loop over primary atoms in this cell
397  for (i = 0; i < nInCell; ++i) {
398  iAtomPtr = neighbors_[i];
399  iId = iAtomPtr->id();
400 
401  // Loop over secondary atoms in this and neighboring cells
402  for (j = 0; j < nNeighbor; ++j) {
403  jAtomPtr = neighbors_[j];
404  jId = jAtomPtr->id();
405 
406  // Count each pair only once
407  if (jId > iId) {
408 
409  // Exclude masked pairs
410  if (!iAtomPtr->mask().isMasked(*jAtomPtr)) {
411 
412  rsq = boundary().distanceSq(iAtomPtr->position(),
413  jAtomPtr->position());
414  energy += interaction().energy(rsq, iAtomPtr->typeId(),
415  jAtomPtr->typeId());
416  }
417 
418  }
419 
420  } // secondary atoms
421 
422  } // primary atoms
423 
424  } // cells
425 
426  // Store local variable energy in Setable<double> class member energy_
427  energy_.set(energy);
428  }
429 
430  /*
431  * Compute nonbonded pair stress.
432  */
433  template <class Interaction>
434  template <typename T>
436  {
437  Vector dr;
438  Vector force;
439  double rsq;
440  const Atom *atom0Ptr, *atom1Ptr;
441  int nNeighbor, nInCell, ia, ja, type0, type1;
442 
443  setToZero(stress);
444 
445  // Loop over cells
446  for (int ic=0; ic < cellList_.totCells(); ++ic) {
447 
448  // Get array of neighbors
449  cellList_.getCellNeighbors(ic, neighbors_, nInCell);
450  nNeighbor = neighbors_.size();
451 
452  // Loop over primary atoms in this cell.
453  for (ia = 0; ia < nInCell; ++ia) {
454  atom0Ptr = neighbors_[ia];
455  type0 = atom0Ptr->typeId();
456 
457  // Loop over secondary atoms in the neighboring cells.
458  for (ja = 0; ja < nNeighbor; ++ja) {
459  atom1Ptr = neighbors_[ja];
460  type1 = atom1Ptr->typeId();
461 
462  // Count each pair only once.
463  if (atom1Ptr->id() > atom0Ptr->id()) {
464 
465  // Exclude masked pairs.
466  if (!atom0Ptr->mask().isMasked(*atom1Ptr)) {
467  rsq = boundary().distanceSq(atom0Ptr->position(),
468  atom1Ptr->position(), dr);
469  if (rsq < interaction().cutoffSq(type0, type1)) {
470  force = dr;
471  force *= interaction().forceOverR(rsq, type0, type1);
472  incrementPairStress(force, dr, stress);
473  }
474 
475  }
476 
477  }
478 
479  } // secondary atoms
480 
481  } // primary atoms
482 
483  } // cells
484 
485  // Normalize by volume.
486  stress /= boundary().volume();
487  normalizeStress(stress);
488  }
489 
490  /*
491  * Compute nonbonded pair stress.
492  */
493  template <class Interaction>
495  {
496  Tensor stress;
497  computeStressImpl(stress);
498 
499  stress_.set(stress);
500  }
501 
502  /*
503  * Get non-const reference to Interaction.
504  */
505  template <class Interaction>
507  { return interaction_; }
508 
509  /*
510  * Get const reference to Interaction.
511  */
512  template <class Interaction>
513  inline const Interaction& McPairPotentialImpl<Interaction>::interaction() const
514  { return interaction_; }
515 
516  /*
517  * Return pair interaction class name.
518  */
519  template <class Interaction>
521  { return interaction().className(); }
522 
523 }
524 #endif
Molecule & molecule() const
Get the parent Molecule by reference.
A Vector is a Cartesian vector.
Definition: Vector.h:75
virtual void readParameters(std::istream &in)
Reads the pair potential Interaction blocks.
void getNeighbors(const Vector &pos, NeighborArray &neighbors) const
Fill a NeighborArray with pointers to atoms near a specified position.
double atomEnergy(const Atom &atom) const
Calculate the nonbonded pair energy for one Atom.
double distanceSq(const Vector &r1, const Vector &r2) const
Return square distance between positions r1 and r2.
virtual double maxPairCutoff() const
Return maximum cutoff.
double volume() const
Return unit cell volume.
void set(const T &value)
Set the value and mark as set.
Definition: Setable.h:107
A PairPotential for MC simulations (abstract).
Mask & mask()
Get the associated Mask by reference.
A set of interacting Molecules enclosed by a Boundary.
Definition: System.h:115
File containing preprocessor macros for error handling.
Classes used by all simpatico molecular simulations.
A Tensor represents a Cartesian tensor.
Definition: Tensor.h:32
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
CellList::NeighborArray neighbors_
Array to hold neighbors returned by a CellList.
Saving / output archive for binary ostream.
CellList cellList_
Cell list for atom positions.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
bool isMasked(const Atom &atom) const
True if the atom is in the masked set for the target Atom.
virtual double forceOverR(double rsq, int iAtomType, int jAtomType) const
Return force / separation for a single pair.
Implementation template for an McPairPotential.
int typeId() const
Get type index for this Atom.
void getCellNeighbors(int ic, NeighborArray &neighbors, int &nInCell) const
Fill an array with pointers to atoms in a cell and neighboring cells.
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.
Utility classes for scientific computation.
Definition: accumulators.mod:1
int id() const
Get global index for this Atom within the Simulation.
Interaction & interaction()
Return reference to underlying pair interaction.
int totCells() const
Get total number of cells in this CellList.
virtual ~McPairPotentialImpl()
Destructor.
virtual void computeStress()
Compute and store total short-range pair stress.
virtual std::string interactionClassName() const
Return pair interaction class name (e.g., "LJPair").
Saving archive for binary istream.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
void addParamComposite(ParamComposite &child, bool next=true)
Add a child ParamComposite object to the format array.
double moleculeEnergy(const Molecule &molecule) const
Calculate the nonbonded pair energy for an entire Molecule.
const Atom & atom(int localId) const
Get a specific Atom in this Molecule.
Boundary & boundary() const
Get the Boundary by reference.
virtual void computeEnergy()
Compute and store nonbonded pair energy of this System.
void setAtomCapacity(int atomCapacity)
Set atom capacity.
A physical molecule (a set of covalently bonded Atoms).
const Vector & position() const
Get the position Vector by const reference.
int size() const
Return logical size of this array (i.e., number of elements).
Definition: FSArray.h:207
int nAtom() const
Get the number of Atoms in this Molecule.
double energy()
Return the energy contribution, compute if necessary.