Simpatico  v1.10
MdPairEnergyCoefficients.cpp
1 #ifndef SIMP_NOPAIR
2 /*
3 * Simpatico - Simulation Package for Polymeric and Molecular Liquids
4 *
5 * Copyright 2010 - 2017, The Regents of the University of Minnesota
6 * Distributed under the terms of the GNU General Public License.
7 */
8 
9 #include "MdPairEnergyCoefficients.h"
10 
11 #include <mcMd/simulation/Simulation.h>
12 #include <mcMd/potentials/pair/MdPairPotential.h>
13 #include <mcMd/neighbor/PairList.h>
14 #include <mcMd/neighbor/PairIterator.h>
15 #include <simp/species/Species.h>
16 #include <util/format/Dbl.h>
17 #include <util/format/Int.h>
18 #include <util/archives/Serializable_includes.h>
19 #include <util/misc/FileMaster.h>
20 
21 namespace McMd
22 {
23 
24  using namespace Util;
25 
26  /*
27  * Constructor.
28  */
30  : SystemAnalyzer<MdSystem>(system),
31  nAtomType_(system.simulation().nAtomType()),
32  nSpecies_(system.simulation().nSpecies()),
33  pairListPtr_(&system.pairPotential().pairList()),
34  pairPotentialPtr_(&system.pairPotential()),
35  boundaryPtr_(&system.boundary()),
36  maxMoleculeNeighbors_(0)
37  { setClassName("MdPairEnergyCoefficients"); }
38 
39  /*
40  * Destructor
41  */
43  {}
44 
45  /*
46  * Clear molecules' neighbor list arrays.
47  */
48  void MdPairEnergyCoefficients::clear()
49  {
50  int iSpecies1, iMolecule1;
51 
52  for (iSpecies1 = 0; iSpecies1 < nSpecies_; ++iSpecies1) {
53  Species *species1Ptr;
54 
55  species1Ptr = &system().simulation().species(iSpecies1);
56  for (iMolecule1 = 0; iMolecule1 < species1Ptr->capacity();
57  ++iMolecule1) {
58  moleculeNeighbors_[iSpecies1][iMolecule1].clear();
59  }
60  }
61  }
62 
63  /*
64  * Read input parameters.
65  */
67  {
68  readInterval(in);
70  read<PairSelector>(in, "selector", selector_);
71  read<int>(in, "maxMoleculeNeighbors", maxMoleculeNeighbors_);
72 
73  // Allocate
74  int iSpecies;
75  moleculeNeighbors_.allocate(nSpecies_);
76  twoMoleculePairEnergy_.allocate(nSpecies_);
77  for (iSpecies = 0; iSpecies < nSpecies_; ++iSpecies) {
78  Species *speciesPtr;
79  int nMolecule;
80  int iMolecule;
81 
82  speciesPtr = &system().simulation().species(iSpecies);
83  nMolecule = speciesPtr->capacity();
84 
85  moleculeNeighbors_[iSpecies].allocate(nMolecule);
86  twoMoleculePairEnergy_[iSpecies].allocate(nMolecule);
87  for (iMolecule = 0; iMolecule < nMolecule; ++iMolecule) {
88  moleculeNeighbors_[iSpecies][iMolecule].
89  allocate(maxMoleculeNeighbors_);
90  }
91  }
92  fileMaster().openOutputFile(outputFileName(".dat"), outputFile_);
93  isInitialized_ = true;
94  }
95 
96  /*
97  * Load state from an archive.
98  */
100  {
101  loadInterval(ar);
102  loadOutputFileName(ar);
103  fileMaster().openOutputFile(outputFileName(".dat"), outputFile_);
104 
105  loadParameter<PairSelector>(ar, "selector", selector_);
106  loadParameter<int>(ar, "maxMoleculeNeighbors", maxMoleculeNeighbors_);
107 
108  int nAtomType, nSpecies;
109  ar & nAtomType;
110  ar & nSpecies;
111 
112  if (nAtomType != nAtomType_) {
113  UTIL_THROW("Inconsistent values of nAtomType");
114  }
115  if (nSpecies != nSpecies_) {
116  UTIL_THROW("Inconsistent values of nSpecies");
117  }
118 
119  // Allocate moleculeNeighbors and twoMoleculePairEnergy.
120  int iSpecies;
121  moleculeNeighbors_.allocate(nSpecies_);
122  twoMoleculePairEnergy_.allocate(nSpecies_);
123 
124  for (iSpecies = 0; iSpecies < nSpecies_; ++iSpecies) {
125  Species *speciesPtr;
126  int nMolecule;
127  int iMolecule;
128 
129  speciesPtr = &system().simulation().species(iSpecies);
130  nMolecule = speciesPtr->capacity();
131 
132  moleculeNeighbors_[iSpecies].allocate(nMolecule);
133  twoMoleculePairEnergy_[iSpecies].allocate(nMolecule);
134  for (iMolecule = 0; iMolecule < nMolecule; ++iMolecule) {
135  moleculeNeighbors_[iSpecies][iMolecule].
136  allocate(maxMoleculeNeighbors_);
137  }
138  }
139 
140  ar & pairEnergyAccumulator_;
141  ar & moleculePESqAccumulator_;
142  ar & twoMoleculePESqAccumulator_;
143  ar & pESqAccumulator_;
144 
145  isInitialized_ = true;
146  }
147 
148  /*
149  * Save state to archive.
150  */
152  { ar & *this; }
153 
154  /*
155  * Evaluate contributions to accumulators.
156  */
158  {
159  if (isAtInterval(iStep)) {
160 
161 // if (!system().isPairListCurrent()) {
162 // system().buildPairList();
163 // }
164 
165  // First clear neighbor list
166  clear();
167 
168  // Loop over pairs and construct neighbor list per molecule
169  PairIterator iter;
170  Atom *atom0Ptr;
171  Atom *atom1Ptr;
172 
173  for (pairListPtr_->begin(iter); iter.notEnd(); ++iter) {
174  iter.getPair(atom0Ptr, atom1Ptr);
175  if (selector_.match(*atom0Ptr, *atom1Ptr)) {
176  Pair< Atom * > atomPair;
177  Molecule *moleculePtr;
178  Species *speciesPtr;
179  int speciesId, moleculeId;
180 
181  atomPair[0] = atom0Ptr;
182  atomPair[1] = atom1Ptr;
183 
184  // Store pair in neighbor list of boths atoms' molecules
185  // (do double counting, since pair list counts only unique
186  // pairs)
187  moleculePtr = & atom0Ptr->molecule();
188  speciesPtr = & moleculePtr->species();
189  speciesId = speciesPtr->id();
190  moleculeId = moleculePtr->id();
191 
192  moleculeNeighbors_[speciesId][moleculeId].
193  append(atomPair);
194 
195  moleculePtr = & atom1Ptr->molecule();
196  speciesPtr = & moleculePtr->species();
197  speciesId = speciesPtr->id();
198  moleculeId = moleculePtr->id();
199 
200  // store atomPair in reverse order
201  atomPair[0] = atom1Ptr;
202  atomPair[1] = atom0Ptr;
203 
204  moleculeNeighbors_[speciesId][moleculeId].
205  append(atomPair);
206  }
207  } // end pair loop
208 
209  // Now loop over all molecules
210  double moleculePESq = 0.0;
211  double pairEnergy=0.0;
212  double twoMoleculePESq=0.0;
213 
214  double rsq;
215  int iSpecies1, iMolecule1;
216 
217  for (iSpecies1 = 0; iSpecies1 < nSpecies_; ++iSpecies1) {
218  Species *species1Ptr;
219 
220  species1Ptr = &system().simulation().species(iSpecies1);
221  for (iMolecule1 = 0; iMolecule1 < species1Ptr->capacity();
222  ++iMolecule1) {
223  int iSpecies2, iMolecule2;
224 
225  double moleculePairEnergy=0.0;
226 
227  // clear array for pair energy with neighboring molecules
228  for (iSpecies2 = 0; iSpecies2 < nSpecies_; ++iSpecies2) {
229  Species *species2Ptr;
230 
231  species2Ptr = &system().simulation().species(iSpecies2);
232  for (iMolecule2 = 0; iMolecule2 < species2Ptr->capacity();
233  ++iMolecule2) {
234  twoMoleculePairEnergy_[iSpecies2][iMolecule2]=0.0;
235  }
236  }
237 
238  // Loop over this molecule's neighbors
239  DSArray< Pair< Atom *> > *neighborsPtr;
241 
242  neighborsPtr=&moleculeNeighbors_[iSpecies1][iMolecule1];
243  for (neighborsPtr->begin(it); it.notEnd(); ++it) {
244  Atom *atom0Ptr, *atom1Ptr;
245  atom0Ptr = (*it)[0];
246  atom1Ptr = (*it)[1];
247 
248  if (selector_.match(*atom0Ptr,*atom1Ptr)) {
249  double energy;
250  Species *species2Ptr;
251  Molecule *molecule2Ptr;
252  int species2Id,molecule2Id;
253 
254  // Load second atom's molecule and species
255  molecule2Ptr = &atom1Ptr->molecule();
256  species2Ptr = &atom1Ptr->molecule().species();
257  species2Id = species2Ptr->id();
258  molecule2Id = molecule2Ptr->id();
259 
260  rsq = boundaryPtr_->distanceSq(atom0Ptr->position(),
261  atom1Ptr->position());
262  energy = pairPotentialPtr_->energy(rsq,
263  atom0Ptr->typeId(), atom1Ptr->typeId());
264 
265  // increment pair energy of this molecule pair
266  twoMoleculePairEnergy_[species2Id][molecule2Id] +=
267  energy;
268  }
269  } // end neighbors loop
270 
271  // sum the molecular pair energies and their squares
272  for (iSpecies2 = 0; iSpecies2 < nSpecies_; ++iSpecies2) {
273  Species *species2Ptr;
274 
275  species2Ptr = &system().simulation().species(iSpecies2);
276  for (iMolecule2 = 0; iMolecule2 < species2Ptr->capacity();
277  ++iMolecule2) {
278  double energy =
279  twoMoleculePairEnergy_[iSpecies2][iMolecule2];
280  moleculePairEnergy += energy;
281  twoMoleculePESq += energy*energy;
282  }
283 
284  }
285 
286  // accumulate total molecular pair energy and its square
287  pairEnergy += moleculePairEnergy;
288  moleculePESq += moleculePairEnergy*moleculePairEnergy;
289 
290  } // end molecule loop
291 
292  } // end species loop
293 
294  // Sample sum of pair energies
295  pairEnergyAccumulator_.sample(pairEnergy);
296 
297  // Sample sum of squares of molecular pair energy
298  moleculePESqAccumulator_.sample(moleculePESq);
299 
300  // Sample sum of squares of two molecule pair energy
301  twoMoleculePESqAccumulator_.sample(twoMoleculePESq);
302 
303  // Sample square of total pair energy
304  pESqAccumulator_.sample(pairEnergy*pairEnergy);
305 
306  outputFile_ << Dbl(pairEnergy);
307  outputFile_ << Dbl(moleculePESq);
308  outputFile_ << Dbl(twoMoleculePESq);
309  outputFile_ << Dbl(pairEnergy*pairEnergy);
310 
311  outputFile_ << std::endl;
312  }
313  }
314 
315  /*
316  * Summary
317  */
319  {
320  // Close *.dat file
321  outputFile_.close();
322 
323  // Open and write summary file
324  fileMaster().openOutputFile(outputFileName(".prm"), outputFile_);
325  writeParam(outputFile_);
326  outputFile_ << std::endl;
327 
328  outputFile_ << "File format:" << std::endl;
329  outputFile_ << " ";
330  outputFile_ << "[pairE] ";
331  outputFile_ << "[moPairESq] ";
332  outputFile_ << "[twoMolPairESq]";
333  outputFile_ << "[pairESq] ";
334  outputFile_ << std::endl;
335 
336  outputFile_.close();
337 
338  // Write averages to separate files
339  fileMaster().openOutputFile(outputFileName(".pairE.ave"),
340  outputFile_);
341  pairEnergyAccumulator_.output(outputFile_);
342  outputFile_.close();
343 
344  fileMaster().openOutputFile(outputFileName(".molPairESq.ave"),
345  outputFile_);
346  moleculePESqAccumulator_.output(outputFile_);
347  outputFile_.close();
348 
349  fileMaster().openOutputFile(outputFileName(".twoMolPairESq.ave"),
350  outputFile_);
351  twoMoleculePESqAccumulator_.output(outputFile_);
352  outputFile_.close();
353 
354  fileMaster().openOutputFile(outputFileName(".pairESq.ave"),
355  outputFile_);
356  pESqAccumulator_.output(outputFile_);
357  outputFile_.close();
358  }
359 
360 }
361 #endif
Molecule & molecule() const
Get the parent Molecule by reference.
virtual double energy(double rsq, int iAtomType, int jAtomType) const =0
Return pair energy for a single pair.
virtual void loadParameters(Serializable::IArchive &ar)
Load state from an archive.
double distanceSq(const Vector &r1, const Vector &r2) const
Return square distance between positions r1 and r2.
void openOutputFile(const std::string &filename, std::ofstream &out, std::ios_base::openmode mode=std::ios_base::out) const
Open an output file.
Definition: FileMaster.cpp:290
virtual void readParameters(std::istream &in)
Read parameters and initialize.
Species & species() const
Get the molecular Species by reference.
MdSystem & system()
Return reference to parent system.
Wrapper for a double precision number, for formatted ostream output.
Definition: Dbl.h:39
void readOutputFileName(std::istream &in)
Read outputFileName from file.
int id() const
Get the index for this Molecule (unique in species).
void getPair(Atom *&atom1Ptr, Atom *&atom2Ptr) const
Get pointers for current pair of Atoms.
An array of exactly 2 objects.
Definition: Pair.h:23
Forward const iterator for an Array or a C array.
Saving / output archive for binary ostream.
bool match(const Atom &atom1, const Atom &atom2) const
Return true if pair of atoms matches the selector policy.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
Simulation & simulation() const
Get the parent Simulation by reference.
Definition: System.h:1055
int typeId() const
Get type index for this Atom.
virtual void writeParam(std::ostream &out)
Write all parameters to an output stream.
void readInterval(std::istream &in)
Read interval from file, with error checking.
A point particle within a Molecule.
virtual void output()
Output final summary and file format.
Utility classes for scientific computation.
Definition: accumulators.mod:1
Iterator for pairs in a PairList.
Template for Analyzer associated with one System.
void output(std::ostream &out) const
Output final statistical properties to file.
Definition: Average.cpp:178
virtual void save(Serializable::OArchive &ar)
Save state to archive.
void begin(PairIterator &iterator) const
Initialize a PairIterator.
int id() const
Get integer id of this Species.
Saving archive for binary istream.
void sample(double value)
Add a sampled value to the ensemble.
Definition: Average.cpp:94
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
virtual void sample(long iStep)
Evaluate energy and print.
void begin(ArrayIterator< Data > &iterator)
Set an ArrayIterator to the beginning of this Array.
Definition: DSArray.h:302
void setClassName(const char *className)
Set class name string.
int capacity() const
Maximum allowed number of molecules for this Species.
bool notEnd() const
Return true if not at end of PairList.
FileMaster & fileMaster()
Get the FileMaster by reference.
void loadInterval(Serializable::IArchive &ar)
Load interval from archive, with error checking.
A System for Molecular Dynamics simulation.
Definition: MdSystem.h:68
bool isAtInterval(long counter) const
Return true iff counter is a multiple of the interval.
Dynamically allocated array with variable logical size.
Definition: DSArray.h:30
const std::string & outputFileName() const
Return outputFileName string.
void loadOutputFileName(Serializable::IArchive &ar)
Load output file name from archive.
A physical molecule (a set of covalently bonded Atoms).
const Vector & position() const
Get the position Vector by const reference.
bool notEnd() const
Is this not the end of the array?
A Species represents a set of chemically similar molecules.
MdPairEnergyCoefficients(MdSystem &system)
Constructor.
Species & species(int i)
Get a specific Species by reference.