Simpatico  v1.10
ddMd/analyzers/scattering/VanHove.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 "VanHove.h"
9 #include <ddMd/simulation/Simulation.h>
10 #include <ddMd/simulation/SimulationAccess.h>
11 #include <ddMd/storage/AtomStorage.h>
12 #include <ddMd/storage/AtomIterator.h>
13 #include <ddMd/communicate/Exchanger.h>
14 #include <simp/boundary/Boundary.h>
15 #include <util/math/Constants.h>
16 #include <util/space/Dimension.h>
17 #include <util/space/IntVector.h>
18 #include <util/misc/ioUtil.h>
19 #include <util/mpi/MpiLoader.h>
20 #include <util/misc/FileMaster.h>
21 #include <util/archives/Serializable_includes.h>
22 #include <util/misc/ioUtil.h>
23 #include <util/format/Int.h>
24 #include <util/format/Dbl.h>
25 
26 namespace DdMd
27 {
28 
29  using namespace Util;
30  using namespace Simp;
31 
32  /*
33  * Constructor.
34  */
36  : Analyzer(simulation),
37  isInitialized_(false)
38  { setClassName("VanHove"); }
39 
40  /*
41  * Destructor
42  */
44  {}
45 
46  /*
47  * Read parameters from file, and allocate memory.
48  */
49  void VanHove::readParameters(std::istream& in)
50  {
51  readInterval(in);
53 
56  readDArray<double>(in, "atomTypeCoeffs", atomTypeCoeffs_, nAtomType_);
57 
58  read<int>(in, "nBuffer", nBuffer_);
59  read<int>(in, "nWave", nWave_);
60  waveIntVectors_.allocate(nWave_);
61  waveVectors_.allocate(nWave_);
63  totalFourierModes_.allocate(nWave_);
64 
65  if (simulation().domain().isMaster()) {
66  accumulators_.allocate(nWave_);
67  for (int i = 0; i < nWave_; ++i) {
68  accumulators_[i].setParam(nBuffer_);
69  }
70  }
71 
72  readDArray<IntVector>(in, "waveIntVectors", waveIntVectors_, nWave_);
73  isInitialized_ = true;
74  }
75 
76  /*
77  * Load state from an archive.
78  */
80  {
82  loadInterval(ar);
85  loadDArray<double>(ar, "atomTypeCoeffs", atomTypeCoeffs_, nAtomType_);
86  loadParameter<int>(ar, "nBuffer", nBuffer_);
87  loadParameter<int>(ar, "nWave", nWave_);
88  waveIntVectors_.allocate(nWave_);
89  loadDArray<IntVector>(ar, "waveIntVectors", waveIntVectors_, nWave_);
90 
91  // Load and broadcast nSample_
92  MpiLoader<Serializable::IArchive> loader(*this, ar);
93  loader.load(nSample_);
94 
95  if (simulation().domain().isMaster()) {
96  accumulators_.allocate(nWave_);
97  ar >> accumulators_;
98  }
99 
100  waveVectors_.allocate(nWave_);
102  totalFourierModes_.allocate(nWave_);
103 
104  isInitialized_ = true;
105  }
106 
107  /*
108  * Save state to an archive.
109  */
111  {
112  saveInterval(ar);
113  saveOutputFileName(ar);
114  ar << atomTypeCoeffs_;
115  ar << nBuffer_;
116  ar << nWave_;
117  ar << waveIntVectors_;
118 
119  ar << nSample_;
120 
121  if (simulation().domain().isMaster()) {
122  ar << accumulators_;
123  }
124  }
125 
126  /*
127  * Clear accumulators.
128  */
130  {
131  if (!isInitialized_) {
132  UTIL_THROW("Error: Object not initialized");
133  }
134  assert (nBuffer_ > 0);
135  assert (nWave_ > 0);
136  nSample_ = 0;
137  if (simulation().domain().isMaster()) {
138  for (int i = 0; i < nWave_; ++i) {
139  accumulators_[i].clear();
140  }
141  }
142  }
143 
145  void VanHove::sample(long iStep)
146  {
147  if (isAtInterval(iStep)) {
148 
149  Vector position;
150  std::complex<double> expFactor;
151  double product, coeff;
152  AtomIterator atomIter;
153  int i, typeId;
154 
155  makeWaveVectors();
156 
157  // Set all Fourier modes to zero
158  for (i = 0; i < nWave_; ++i) {
159  fourierModes_[i] = std::complex<double>(0.0, 0.0);
160  }
161 
162  simulation().atomStorage().begin(atomIter);
163  for ( ; atomIter.notEnd(); ++atomIter) {
164  position = atomIter->position();
165  typeId = atomIter->typeId();
166  coeff = atomTypeCoeffs_[typeId];
167 
168  // Loop over wavevectors
169  for (i = 0; i < nWave_; ++i) {
170 
171  product = position.dot(waveVectors_[i]);
172  expFactor = exp( product*Constants::Im );
173  fourierModes_[i] += coeff*expFactor;
174  }
175  }
176 
177  for (i = 0; i < nWave_; ++i) {
178  totalFourierModes_[i] = std::complex<double>(0.0, 0.0);
179  }
180 
181  #ifdef UTIL_MPI
182  // Loop over wavevectors
183  for (int i = 0; i < nWave_; ++i) {
184  //Sum values from all processors.
186  Reduce(&fourierModes_[i], &totalFourierModes_[i],
187  1, MPI::DOUBLE_COMPLEX, MPI::SUM, 0);
188  }
189  #else
190  for (int i = 0; i < nWave_; ++i) {
191  totalFourierModes_[i] = fourierModes_[i];
192  }
193  #endif
194 
195  if (simulation().domain().isMaster()) {
196  // Add Fourier modes to autocorrelation accumulators
197  double sqrtV = sqrt(simulation().boundary().volume());
198  for (int i = 0; i < nWave_; ++i) {
199  accumulators_[i].sample(totalFourierModes_[i]/sqrtV);
200  }
201  }
202  ++nSample_;
203  }
204 
205  }
206 
211  {
212  Vector dWave;
213  Boundary* boundaryPtr = &simulation().boundary();
214  int i, j;
215 
216  // Calculate wavevectors
217  for (i = 0; i < nWave_; ++i) {
219  for (j = 0; j < Dimension; ++j) {
220  dWave = boundaryPtr->reciprocalBasisVector(j);
221  dWave *= waveIntVectors_[i][j];
222  waveVectors_[i] += dWave;
223  }
224  }
225  }
226 
228  {
229  if (simulation().domain().isMaster()) {
230  // Write parameters to a *.prm file
233  outputFile_.close();
234 
235  // Output structure factors to one *.dat file
237 
238  int i, j;
239 
240  // Output autocorrelation functions to file
241  for (i = 0; i < nWave_; ++i) {
242 
243  for (j = 0; j < Dimension; ++j) {
244  outputFile_ << Int(waveIntVectors_[i][j], 5);
245  }
246  outputFile_ << Dbl(waveVectors_[i].abs(), 20, 8);
247  outputFile_ << std::endl;
248  accumulators_[i].output(outputFile_);
249  outputFile_ << std::endl;
250  outputFile_ << std::endl;
251  }
252  outputFile_.close();
253  }
254 
255  }
256 
257 }
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
Abstract base for periodic output and/or analysis actions.
Simulation & simulation()
Get the parent Simulation by reference.
VanHove(Simulation &simulation)
Constructor.
A Vector is a Cartesian vector.
Definition: Vector.h:75
int nBuffer_
Number of samples stored in history buffer.
float product(float a, float b)
Product for float Data.
Definition: product.h:22
virtual void loadParameters(Serializable::IArchive &ar)
Load state from an archive.
void readOutputFileName(std::istream &in)
Read outputFileName from file.
void saveInterval(Serializable::OArchive &ar)
Save interval parameter to an archive.
DArray< Vector > waveVectors_
Array of wave vectors.
AtomStorage & atomStorage()
Get the AtomStorage by reference.
double dot(const Vector &v) const
Return dot product of this vector and vector v.
Definition: Vector.h:632
DArray< AutoCorr< std::complex< double >, std::complex< double > > > accumulators_
Autocorrelation function accumulators.
virtual void readParameters(std::istream &in)
Read parameters from file.
An orthorhombic periodic unit cell.
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
static const Vector Zero
Zero Vector = {0.0, 0.0, 0.0}.
Definition: Vector.h:369
bool isInitialized_
Has readParam been called?
void readInterval(std::istream &in)
Read parameter interval from file.
Wrapper for a double precision number, for formatted ostream output.
Definition: Dbl.h:39
Parallel domain decomposition (DD) MD simulation.
Classes used by all simpatico molecular simulations.
Main object for a domain-decomposition MD simulation.
DArray< IntVector > waveIntVectors_
Array of miller index vectors for wavevectors.
MPI::Intracomm & communicator() const
Return Cartesian communicator by reference.
Definition: Domain.h:257
Saving / output archive for binary ostream.
void loadOutputFileName(Serializable::IArchive &ar)
Load output file name to an archive.
DArray< std::complex< double > > fourierModes_
Fourier modes. First index is wavevector, second is atom type.
FileMaster & fileMaster()
Get the associated FileMaster by reference.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
virtual void clear()
Clear accumulators.
virtual void writeParam(std::ostream &out)
Write all parameters to an output stream.
const Vector & reciprocalBasisVector(int i) const
Return reciprocal lattice basis vector i.
bool isAtInterval(long counter) const
Return true iff counter is a multiple of the interval.
bool notEnd() const
Is the current pointer not at the end of the PArray?
Utility classes for scientific computation.
Definition: accumulators.mod:1
int nWave_
Number of wavevectors.
Wrapper for an int, for formatted ostream output.
Definition: Int.h:36
int nSample_
Number of samples thus far.
const std::string & outputFileName() const
Return outputFileName string.
Saving archive for binary istream.
virtual void save(Serializable::OArchive &ar)
Save state to an archive.
void sample(long iStep)
Add particle pairs to VanHove histogram.
Provides methods for MPI-aware loading of data from input archive.
Definition: MpiLoader.h:43
void setClassName(const char *className)
Set class name string.
void loadInterval(Serializable::IArchive &ar)
Load parameter interval from input archive.
int nAtomType()
Get maximum number of atom types.
std::ofstream outputFile_
Output file stream.
Boundary & boundary()
Get the Boundary by reference.
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:191
void saveOutputFileName(Serializable::OArchive &ar)
Save output file name to an archive.
Domain & domain()
Get the Domain by reference.
Iterator for all atoms owned by an AtomStorage.
Definition: AtomIterator.h:24
static const std::complex< double > Im
Square root of -1.
Definition: Constants.h:40
virtual void output()
Output results to predefined output file.
void begin(AtomIterator &iterator)
Set iterator to beginning of the set of atoms.
void makeWaveVectors()
Update wavevectors.
DArray< double > atomTypeCoeffs_
Array of coefficients for atom types.
int nAtomType_
Number of atom types, copied from Simulation::nAtomType().