Simpatico  v1.10
EnergyAnalyzer.cpp
1 /*
2 * Simpatico - Simulation Package for Polymeric and Molecular Liquids
3 *
4 * Copyright 2010 - 2017, The Regents of the University of Minnesota
5 * Distributed under the terms of the GNU General Public License.
6 */
7 
8 #include "EnergyAnalyzer.h"
9 #include <ddMd/simulation/Simulation.h>
10 #include <ddMd/potentials/pair/PairPotential.h>
11 #ifdef SIMP_BOND
12 #include <ddMd/potentials/bond/BondPotential.h>
13 #endif
14 #ifdef SIMP_ANGLE
15 #include <ddMd/potentials/angle/AnglePotential.h>
16 #endif
17 #ifdef SIMP_DIHEDRAL
18 #include <ddMd/potentials/dihedral/DihedralPotential.h>
19 #endif
20 #ifdef SIMP_EXTERNAL
21 #include <ddMd/potentials/external/ExternalPotential.h>
22 #endif
23 #include <util/accumulators/Average.h>
24 #include <util/format/Int.h>
25 #include <util/format/Dbl.h>
26 #include <util/mpi/MpiLoader.h>
27 #include <util/misc/ioUtil.h>
28 
29 #include <sstream>
30 
31 namespace DdMd
32 {
33 
34  using namespace Util;
35 
36  /*
37  * Constructor.
38  */
40  : Analyzer(simulation),
41  totalAveragePtr_(0),
42  kineticAveragePtr_(0),
43  pairAveragePtr_(0),
44  #ifdef SIMP_BOND
45  bondAveragePtr_(0),
46  #endif
47  #ifdef SIMP_ANGLE
48  angleAveragePtr_(0),
49  #endif
50  #ifdef SIMP_DIHEDRAL
51  dihedralAveragePtr_(0),
52  #endif
53  #ifdef SIMP_EXTERNAL
54  externalAveragePtr_(0),
55  #endif
56  nSamplePerBlock_(0),
57  isInitialized_(false)
58  { setClassName("EnergyAnalyzer"); }
59 
60  /*
61  * Read interval and outputFileName.
62  */
63  void EnergyAnalyzer::readParameters(std::istream& in)
64  {
65  readInterval(in);
67  nSamplePerBlock_ = 0;
68  readOptional<int>(in, "nSamplePerBlock", nSamplePerBlock_);
69 
70  Simulation& sim = simulation();
71  if (sim.domain().isMaster()) {
72  totalAveragePtr_ = new Average;
73  totalAveragePtr_->setNSamplePerBlock(nSamplePerBlock_);
74  kineticAveragePtr_ = new Average;
75  kineticAveragePtr_->setNSamplePerBlock(nSamplePerBlock_);
76  pairAveragePtr_ = new Average;
77  pairAveragePtr_->setNSamplePerBlock(nSamplePerBlock_);
78  #ifdef SIMP_BOND
79  if (sim.nBondType()) {
80  bondAveragePtr_ = new Average;
81  bondAveragePtr_->setNSamplePerBlock(nSamplePerBlock_);
82  }
83  #endif
84  #ifdef SIMP_ANGLE
85  if (sim.nAngleType()) {
86  angleAveragePtr_ = new Average;
87  angleAveragePtr_->setNSamplePerBlock(nSamplePerBlock_);
88  }
89  #endif
90  #ifdef SIMP_EXTERNAL
91  if (sim.hasExternal()) {
92  externalAveragePtr_ = new Average;
93  externalAveragePtr_->setNSamplePerBlock(nSamplePerBlock_);
94  }
95  #endif
96  }
97 
98  isInitialized_ = true;
99  }
100 
101  /*
102  * Load internal state from an archive.
103  */
105  {
106  loadInterval(ar);
107  loadOutputFileName(ar);
108  nSamplePerBlock_ = 0; // default value
109  bool isRequired = false;
110  loadParameter<int>(ar, "nSamplePerBlock", nSamplePerBlock_,
111  isRequired);
112 
113  // Load Average accumulators
114  Simulation& sim = simulation();
115  if (sim.domain().isMaster()) {
116  totalAveragePtr_ = new Average;
117  ar >> *totalAveragePtr_;
118  kineticAveragePtr_ = new Average;
119  ar >> *kineticAveragePtr_;
120  pairAveragePtr_ = new Average;
121  ar >> *pairAveragePtr_;
122  #ifdef SIMP_BOND
123  if (sim.nBondType()) {
124  bondAveragePtr_ = new Average;
125  ar >> *bondAveragePtr_;
126  }
127  #endif
128  #ifdef SIMP_ANGLE
129  if (sim.nAngleType()) {
130  angleAveragePtr_ = new Average;
131  ar >> *angleAveragePtr_;
132  }
133  #endif
134  #ifdef SIMP_DIHEDRAL
135  if (sim.nDihedralType()) {
136  dihedralAveragePtr_ = new Average;
137  ar >> *dihedralAveragePtr_;
138  }
139  #endif
140  #ifdef SIMP_EXTERNAL
141  if (sim.hasExternal()) {
142  externalAveragePtr_ = new Average;
143  ar >> *externalAveragePtr_;
144  }
145  #endif
146  }
147 
148  isInitialized_ = true;
149  }
150 
151  /*
152  * Save internal state to an archive.
153  */
155  {
156  saveInterval(ar);
157  saveOutputFileName(ar);
158  bool isActive = bool(nSamplePerBlock_);
159  Parameter::saveOptional(ar, nSamplePerBlock_, isActive);
160 
161  // Save average accumulators
162  Simulation& sim = simulation();
163  ar << *totalAveragePtr_;
164  ar << *kineticAveragePtr_;
165  ar << *pairAveragePtr_;
166  #ifdef SIMP_BOND
167  if (sim.nBondType()) {
168  ar << *bondAveragePtr_;
169  }
170  #endif
171  #ifdef SIMP_ANGLE
172  if (sim.nAngleType()) {
173  ar << *angleAveragePtr_;
174  }
175  #endif
176  #ifdef SIMP_DIHEDRAL
177  if (sim.nDihedralType()) {
178  ar << *dihedralAveragePtr_;
179  }
180  #endif
181  #ifdef SIMP_EXTERNAL
182  if (sim.hasExternal()) {
183  ar << *externalAveragePtr_;
184  }
185  #endif
186  }
187 
188  /*
189  * Reset nSample.
190  */
192  {
193  Simulation& sim = simulation();
194  if (sim.domain().isMaster()) {
195  totalAveragePtr_->clear();
196  kineticAveragePtr_->clear();
197  pairAveragePtr_->clear();
198  #ifdef SIMP_BOND
199  if (sim.nBondType()) {
200  bondAveragePtr_->clear();
201  }
202  #endif
203  #ifdef SIMP_ANGLE
204  if (sim.nAngleType()) {
205  angleAveragePtr_->clear();
206  }
207  #endif
208  #ifdef SIMP_DIHEDRAL
209  if (sim.nDihedralType()) {
210  dihedralAveragePtr_->clear();
211  }
212  #endif
213  #ifdef SIMP_EXTERNAL
214  if (sim.hasExternal()) {
215  externalAveragePtr_->clear();
216  }
217  #endif
218  }
219  }
220 
221  /*
222  * Open outputfile
223  */
225  {
226  if (simulation().domain().isMaster()) {
227  if (outputFile_.is_open()) {
228  outputFile_.close();
229  }
230  std::string filename;
231  filename = outputFileName(".dat");
232  simulation().fileMaster().openOutputFile(filename, outputFile_);
233  }
234  }
235 
236  /*
237  * Output energy to file
238  */
239  void EnergyAnalyzer::sample(long iStep)
240  {
241  if (isAtInterval(iStep)) {
242  Simulation& sim = simulation();
243  sim.computeKineticEnergy();
245  if (sim.domain().isMaster()) {
246  //outputFile_ << Int(iStep, 10);
247  double kinetic = sim.kineticEnergy();
248  kineticAveragePtr_->sample(kinetic);
249  //outputFile_ << Dbl(kinetic, 15);
250  double potential = 0.0;
251  double pair = sim.pairPotential().energy();
252  potential += pair;
253  pairAveragePtr_->sample(pair);
254  //outputFile_ << Dbl(pair, 15);
255  #ifdef SIMP_BOND
256  if (sim.nBondType()) {
257  double bond = sim.bondPotential().energy();
258  potential += bond;
259  bondAveragePtr_->sample(bond);
260  //outputFile_ << Dbl(bond, 15);
261  }
262  #endif
263  #ifdef SIMP_ANGLE
264  if (sim.nAngleType()) {
265  double angle = sim.anglePotential().energy();
266  potential += angle;
267  angleAveragePtr_->sample(angle);
268  //outputFile_ << Dbl(angle, 15);
269  }
270  #endif
271  #ifdef SIMP_DIHEDRAL
272  if (sim.nDihedralType()) {
273  double dihedral = sim.dihedralPotential().energy();
274  potential += dihedral;
275  dihedralAveragePtr_->sample(dihedral);
276  // outputFile_ << Dbl(dihedral, 15);
277  }
278  #endif
279  #ifdef SIMP_EXTERNAL
280  if (sim.hasExternal()) {
281  double external = sim.externalPotential().energy();
282  potential += external;
283  externalAveragePtr_->sample(external);
284  // outputFile_ << Dbl(external, 15);
285  }
286  #endif
287  double total = kinetic + potential;
288  totalAveragePtr_->sample(total);
289  // outputFile_ << Dbl(total, 20)
290  // << std::endl;
291 
292  // Output block averages, if needed
293  if (nSamplePerBlock_ > 0 && totalAveragePtr_->isBlockComplete()) {
294  int beginStep = iStep - (nSamplePerBlock_ - 1)*interval();
295  outputFile_ << Int(beginStep, 12);
296  outputFile_ << Dbl(kineticAveragePtr_->blockAverage());
297  outputFile_ << Dbl(pairAveragePtr_->blockAverage());
298  #ifdef SIMP_BOND
299  if (sim.nBondType()) {
300  outputFile_ << Dbl(bondAveragePtr_->blockAverage());
301  }
302  #endif
303  #ifdef SIMP_ANGLE
304  if (sim.nAngleType()) {
305  outputFile_ << Dbl(angleAveragePtr_->blockAverage());
306  }
307  #endif
308  #ifdef SIMP_DIHEDRAL
309  if (sim.nDihedralType()) {
310  outputFile_ << Dbl(dihedralAveragePtr_->blockAverage());
311  }
312  #endif
313  #ifdef SIMP_EXTERNAL
314  if (sim.hasExternal()) {
315  outputFile_ << Dbl(externalAveragePtr_->blockAverage());
316  }
317  #endif
318  outputFile_ << Dbl(totalAveragePtr_->blockAverage());
319  outputFile_ << "\n";
320  }
321  }
322 
323  }
324  }
325 
326  /*
327  * Output results to file after simulation is completed.
328  */
330  {
331  Simulation& sim = simulation();
332  if (sim.domain().isMaster()) {
333 
334  // Close data (*.dat) file, if any
335  if (outputFile_.is_open()) {
336  outputFile_.close();
337  }
338 
339  // Write parameter (*.prm) file
340  sim.fileMaster().openOutputFile(outputFileName(".prm"), outputFile_);
341  ParamComposite::writeParam(outputFile_);
342  outputFile_.close();
343 
344  // Write average (*.ave) file
345  sim.fileMaster().openOutputFile(outputFileName(".ave"), outputFile_);
346  double ave, err;
347  ave = kineticAveragePtr_->average();
348  err = kineticAveragePtr_->blockingError();
349  outputFile_ << "Kinetic " << Dbl(ave) << " +- " << Dbl(err, 9, 2) << "\n";
350  ave = pairAveragePtr_->average();
351  err = pairAveragePtr_->blockingError();
352  outputFile_ << "Pair " << Dbl(ave) << " +- " << Dbl(err, 9, 2) << "\n";
353  #ifdef SIMP_BOND
354  if (sim.nBondType()) {
355  ave = bondAveragePtr_->average();
356  err = bondAveragePtr_->blockingError();
357  outputFile_ << "Bond " << Dbl(ave) << " +- " << Dbl(err, 9, 2) << "\n";
358  }
359  #endif
360  #ifdef SIMP_ANGLE
361  if (sim.nAngleType()) {
362  ave = angleAveragePtr_->average();
363  err = angleAveragePtr_->blockingError();
364  outputFile_ << "Angle " << Dbl(ave) << " +- " << Dbl(err, 9, 2) << "\n";
365  }
366  #endif
367  #ifdef SIMP_DIHEDRAL
368  if (sim.nDihedralType()) {
369  ave = dihedralAveragePtr_->average();
370  err = dihedralAveragePtr_->blockingError();
371  outputFile_ << "Dihedral " << Dbl(ave) << " +- " << Dbl(err, 9, 2) << "\n";
372  }
373  #endif
374  #ifdef SIMP_EXTERNAL
375  if (sim.hasExternal()) {
376  ave = externalAveragePtr_->average();
377  err = externalAveragePtr_->blockingError();
378  outputFile_ << "External " << Dbl(ave) << " +- " << Dbl(err, 9, 2) << "\n";
379  }
380  #endif
381  ave = totalAveragePtr_->average();
382  err = totalAveragePtr_->blockingError();
383  outputFile_ << "Total " << Dbl(ave) << " +- " << Dbl(err, 9, 2) << "\n";
384  outputFile_.close();
385 
386  // Write error analysis (*.aer) file
387  sim.fileMaster().openOutputFile(outputFileName(".aer"), outputFile_);
388  outputFile_ <<
389  "---------------------------------------------------------------------------------\n";
390  outputFile_ << "Kinetic:\n\n";
391  kineticAveragePtr_->output(outputFile_);
392  outputFile_ <<
393  "---------------------------------------------------------------------------------\n";
394  outputFile_ << "Pair:\n\n";
395  pairAveragePtr_->output(outputFile_);
396  #ifdef SIMP_BOND
397  if (sim.nBondType()) {
398  outputFile_ <<
399  "---------------------------------------------------------------------------------\n";
400  outputFile_ << "Bond:\n\n";
401  bondAveragePtr_->output(outputFile_);
402  }
403  #endif
404  #ifdef SIMP_ANGLE
405  if (sim.nAngleType()) {
406  outputFile_ <<
407  "---------------------------------------------------------------------------------\n";
408  outputFile_ << "Angle:\n\n";
409  angleAveragePtr_->output(outputFile_);
410  }
411  #endif
412  #ifdef SIMP_DIHEDRAL
413  if (sim.nDihedralType()) {
414  outputFile_ <<
415  "---------------------------------------------------------------------------------\n";
416  outputFile_ << "Dihedral:\n\n";
417  dihedralAveragePtr_->output(outputFile_);
418  }
419  #endif
420  #ifdef SIMP_EXTERNAL
421  if (sim.hasExternal()) {
422  outputFile_ <<
423  "---------------------------------------------------------------------------------\n";
424  outputFile_ << "External:\n\n";
425  externalAveragePtr_->output(outputFile_);
426  }
427  #endif
428  outputFile_ <<
429  "---------------------------------------------------------------------------------\n";
430  outputFile_ << "Total:\n\n";
431  totalAveragePtr_->output(outputFile_);
432  outputFile_.close();
433 
434  }
435  }
436 
437 
438 }
Abstract base for periodic output and/or analysis actions.
void clear()
Clear all accumulators, set to empty initial state.
Definition: Average.cpp:42
Simulation & simulation()
Get the parent Simulation by reference.
bool isBlockComplete() const
Is the current block average complete?
Definition: Average.h:232
const BondPotential & bondPotential() const
Get the PairPotential by const reference.
void readOutputFileName(std::istream &in)
Read outputFileName from file.
bool isRequired() const
Is this ParamComposite required in the input file?
void saveInterval(Serializable::OArchive &ar)
Save interval parameter to an archive.
Calculates the average and variance of a sampled property.
Definition: Average.h:43
double average() const
Return the average of all sampled values.
double kineticEnergy()
Return precomputed total kinetic energy.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an input archive.
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
void readInterval(std::istream &in)
Read parameter interval from file.
Wrapper for a double precision number, for formatted ostream output.
Definition: Dbl.h:39
EnergyAnalyzer(Simulation &simulation)
Constructor.
int nBondType()
Get maximum number of bond types.
double blockingError() const
Return estimated error on average from blocking analysis.
Definition: Average.cpp:133
Parallel domain decomposition (DD) MD simulation.
Main object for a domain-decomposition MD simulation.
const ExternalPotential & externalPotential() const
Get the ExternalPotential by reference.
bool isActive() const
Is this parameter active?
Saving / output archive for binary ostream.
void loadOutputFileName(Serializable::IArchive &ar)
Load output file name to an archive.
int nDihedralType()
Get maximum number of dihedral types.
FileMaster & fileMaster()
Get the associated FileMaster by reference.
const DihedralPotential & dihedralPotential() const
Get the DihedralPotential by const reference.
virtual void writeParam(std::ostream &out)
Write all parameters to an output stream.
void computePotentialEnergies()
Calculate and store total potential energy on all processors.
bool isAtInterval(long counter) const
Return true iff counter is a multiple of the interval.
Utility classes for scientific computation.
Definition: accumulators.mod:1
virtual void output()
Write file averages and error analysis to file.
Wrapper for an int, for formatted ostream output.
Definition: Int.h:36
const std::string & outputFileName() const
Return outputFileName string.
void output(std::ostream &out) const
Output final statistical properties to file.
Definition: Average.cpp:178
virtual void sample(long iStep)
Write energy to file.
bool isMaster() const
Is this the master processor (gridRank == 0) ?
Definition: Domain.h:313
const PairPotential & pairPotential() const
Get the PairPotential by const reference.
void setNSamplePerBlock(int nSamplePerBlock)
Set nSamplePerBlock.
Definition: Average.cpp:63
double energy() const
Return the total potential, from all processors.
Definition: Potential.cpp:39
Saving archive for binary istream.
void sample(double value)
Add a sampled value to the ensemble.
Definition: Average.cpp:94
virtual void readParameters(std::istream &in)
Read interval and output file name.
void setClassName(const char *className)
Set class name string.
void loadInterval(Serializable::IArchive &ar)
Load parameter interval from input archive.
const AnglePotential & anglePotential() const
Get the AnglePotential by const reference.
int nAngleType()
Get maximum number of angle types.
int interval() const
Get interval value.
void saveOutputFileName(Serializable::OArchive &ar)
Save output file name to an archive.
void computeKineticEnergy()
Compute total kinetic energy.
Domain & domain()
Get the Domain by reference.
virtual void save(Serializable::OArchive &ar)
Save internal state to an output archive.
static void saveOptional(Serializable::OArchive &ar, Type &value, bool isActive)
Save an optional parameter value to an output archive.
Definition: Parameter.h:224
virtual void clear()
Clear nSample counter and all accumulators.
virtual void setup()
Setup before main loop.
bool hasExternal()
Does this simulation have an external potential?