Simpatico  v1.10
IntraStructureFactor.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 "IntraStructureFactor.h"
9 #include <mcMd/simulation/Simulation.h>
10 #include <mcMd/simulation/McMd_mpi.h>
11 #include <mcMd/chemistry/Molecule.h>
12 #include <mcMd/chemistry/Atom.h>
13 #include <simp/boundary/Boundary.h>
14 #include <util/math/Constants.h>
15 #include <util/space/Dimension.h>
16 #include <util/misc/FileMaster.h>
17 #include <util/archives/Serializable_includes.h>
18 #include <util/misc/ioUtil.h>
19 #include <util/format/Int.h>
20 #include <util/format/Dbl.h>
21 
22 namespace McMd
23 {
24 
25  using namespace Util;
26  using namespace Simp;
27 
28  /*
29  * Constructor.
30  */
32  : SystemAnalyzer<System>(system),
33  isInitialized_(false)
34  { setClassName("IntraStructureFactor"); }
35 
36  /*
37  * Destructor.
38  */
40  {}
41 
42  /*
43  * Read parameters from file, and allocate data array.
44  */
45  void IntraStructureFactor::readParameters(std::istream& in)
46  {
47  readInterval(in);
49 
50  read<int>(in, "speciesId", speciesId_);
51  read<int>(in, "nAtomTypeIdPair", nAtomTypeIdPair_);
52  atomTypeIdPairs_.allocate(nAtomTypeIdPair_);
53  readDArray< Pair<int> >(in, "atomTypeIdPairs", atomTypeIdPairs_,
55  read<int>(in, "nWave", nWave_);
56 
57  waveIntVectors_.allocate(nWave_);
58  readDArray<IntVector>(in, "waveIntVectors", waveIntVectors_, nWave_);
60 
61  waveVectors_.allocate(nWave_);
62  fourierModes_.allocate(nWave_, nAtomType_ + 1);
65 
66  isInitialized_ = true;
67  }
68 
69  /*
70  * Load state from an archive.
71  */
73  {
74  loadInterval(ar);
76 
77  loadParameter<int>(ar, "speciesId", speciesId_);
78  loadParameter<int>(ar, "nAtomTypeIdPair", nAtomTypeIdPair_);
79  atomTypeIdPairs_.allocate(nAtomTypeIdPair_);
80  loadDArray< Pair<int> >(ar, "atomTypeIdPairs", atomTypeIdPairs_,
82  loadParameter<int>(ar, "nWave", nWave_);
83 
84  //waveIntVectors_.allocate(nWave_);
85  loadDArray<IntVector>(ar, "waveIntVectors", waveIntVectors_, nWave_);
86 
87  ar & nAtomType_;
88  if (nAtomType_ != system().simulation().nAtomType()) {
89  UTIL_THROW("Inconsistent nAtomType");
90  }
91  // structureFactors_.allocate(nWave_, nAtomTypeIdPair_);
92  ar & structureFactors_;
93  //fourierModes_.allocate(nWave_, nAtomType_ + 1);
94  ar & fourierModes_;
95  ar & nSample_;
96 
97  waveVectors_.allocate(nWave_);
98  isInitialized_ = true;
99  }
100 
101 
102  /*
103  * Save state to archive.
104  */
106  { ar & *this; }
107 
108  /*
109  * Set up before simulation.
110  */
112  {
113  // Preconditions
114  if (!isInitialized_) {
115  UTIL_THROW("Object is not initialized");
116  }
117  assert (nWave_ > 0);
118  assert (nAtomTypeIdPair_ > 0);
119 
120  // Clear accumulators
121  int i, j;
122  for (i = 0; i < nWave_; ++i) {
123  for (j = 0; j < nAtomTypeIdPair_; ++j) {
124  structureFactors_(i, j) = 0.0;
125  }
126  }
127  nSample_ = 0;
128  }
129 
130  /*
131  * Increment Structure Factor
132  */
134  {
135  if (isAtInterval(iStep)) {
136 
137  Vector position;
138  std::complex<double> rho[2];
139  std::complex<double> expFactor;
140  double volume = system().boundary().volume();
141  double product, dS;
144  int typeId, i, j, k;
145 
146  makeWaveVectors();
147 
148  // Set all Deltas to zero
149  for (i = 0; i < nWave_; ++i) {
150  for (int pairId = 0; pairId < nAtomTypeIdPair_; ++pairId) {
151  structureFactorDelta_(i, pairId) = 0;
152  }
153  }
154 
155  // Loop over molecules in species
156  system().begin(speciesId_, molIter);
157  for ( ; molIter.notEnd(); ++molIter) {
158 
159  // Set all Fourier modes to zero
160  for (i = 0; i < nWave_; ++i) {
161  for (typeId = 0; typeId <= nAtomType_; ++typeId) {
162  fourierModes_(i, typeId) = 0;
163  }
164  }
165 
166  // Loop over all atoms in one molecule
167  molIter->begin(atomIter);
168  for ( ; atomIter.notEnd(); ++atomIter) {
169  position = atomIter->position();
170  typeId = atomIter->typeId();
171 
172  // Loop over wavevectors
173  for (i = 0; i < nWave_; ++i) {
174  product = position.dot(waveVectors_[i]);
175  expFactor = exp( product*Constants::Im );
176  fourierModes_(i, typeId) += expFactor;
177  fourierModes_(i, nAtomType_) += expFactor;
178  }
179 
180  }
181 
182  // Increment structure factors
183  for (i = 0; i < nWave_; ++i) {
184  for (j = 0; j < nAtomTypeIdPair_; ++j) {
185  for (k = 0; k < 2; ++k) {
186  typeId = atomTypeIdPairs_[j][k];
187  if (typeId >= 0) {
188  rho[k] = fourierModes_(i, typeId);
189  } else {
190  rho[k] = fourierModes_(i, nAtomType_);
191  }
192  }
193  rho[0] = std::conj(rho[0]);
194  dS = std::real(rho[0]*rho[1])/volume;
195  structureFactors_(i, j) += dS;
196  structureFactorDelta_(i,j) += dS;
197  }
198  }
199 
200  }
201 
202  ++nSample_;
203  }
204 
205  }
206 
210  void IntraStructureFactor::makeWaveVectors()
211  {
212  Vector dWave;
213  Boundary* boundaryPtr = &system().boundary();
214  int i, j;
215 
216  // Calculate wavevectors
217  for (i = 0; i < nWave_; ++i) {
218  waveVectors_[i] = Vector::Zero;
219  for (j = 0; j < Dimension; ++j) {
220  dWave = boundaryPtr->reciprocalBasisVector(j);
221  dWave *= waveIntVectors_[i][j];
222  waveVectors_[i] += dWave;
223  //std::cout << waveVectors_[i] << std::endl;
224  }
225  }
226  }
227 
229  {
230  double value;
231  int i, j, k;
232 
233  // Echo parameters to a log file
236  outputFile_.close();
237 
238  // Output structure factors to one file
240  for (i = 0; i < nWave_; ++i) {
241  for (k = 0; k < Dimension; ++k) {
242  outputFile_ << Int(waveIntVectors_[i][k], 5);
243  }
244  outputFile_ << Dbl(waveVectors_[i].abs(), 20, 8);
245  for (j = 0; j < nAtomTypeIdPair_; ++j) {
246  value = structureFactors_(i, j)/double(nSample_);
247  outputFile_ << Dbl(value, 18, 8);
248  }
249  outputFile_ << std::endl;
250  }
251  outputFile_.close();
252 
253  }
254 
255 }
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
A Vector is a Cartesian vector.
Definition: Vector.h:75
float product(float a, float b)
Product for float Data.
Definition: product.h:22
int nAtomTypeIdPair_
Number of selected atom type pairs.
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
Definition: DMatrix.h:170
void begin(int speciesId, MoleculeIterator &iterator)
Initialize an iterator for molecules of one species in this System.
Definition: System.h:1147
DMatrix< std::complex< double > > fourierModes_
Fourier modes.
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
IntraStructureFactor(System &system)
Constructor.
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
DMatrix< double > structureFactorDelta_
Contribution of current time step to structure factor average.
A set of interacting Molecules enclosed by a Boundary.
Definition: System.h:115
System & system()
Return reference to parent system.
Wrapper for a double precision number, for formatted ostream output.
Definition: Dbl.h:39
Forward iterator for a PArray.
Classes used by all simpatico molecular simulations.
void readOutputFileName(std::istream &in)
Read outputFileName from file.
virtual void loadParameters(Serializable::IArchive &ar)
Load state from archive.
Forward const iterator for an Array or a C array.
Saving / output archive for binary ostream.
int nSample_
Number of samples thus far.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition: global.h:51
virtual void readParameters(std::istream &in)
Read parameters from file.
Simulation & simulation() const
Get the parent Simulation by reference.
Definition: System.h:1055
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.
void readInterval(std::istream &in)
Read interval from file, with error checking.
Utility classes for scientific computation.
Definition: accumulators.mod:1
virtual void setup()
Clear accumulators.
Wrapper for an int, for formatted ostream output.
Definition: Int.h:36
void sample(long iStep)
Add particle pairs to IntraStructureFactor histogram.
int nWave_
Number of wavevectors.
Template for Analyzer associated with one System.
int speciesId_
Index for molecular species.
int nAtomType_
Number of atom types, copied from Simulation::nAtomType().
bool notEnd() const
Is the current pointer not at the end of the array?
Boundary & boundary() const
Get the Boundary by reference.
Definition: System.h:1064
Saving archive for binary istream.
std::ofstream outputFile_
Output file stream.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
void setClassName(const char *className)
Set class name string.
DMatrix< double > structureFactors_
Structure factor accumulators.
FileMaster & fileMaster()
Get the FileMaster by reference.
void loadInterval(Serializable::IArchive &ar)
Load interval from archive, with error checking.
bool isAtInterval(long counter) const
Return true iff counter is a multiple of the interval.
const std::string & outputFileName() const
Return outputFileName string.
void loadOutputFileName(Serializable::IArchive &ar)
Load output file name from archive.
int nAtomType() const
Get the number of atom types.
bool notEnd() const
Is this not the end of the array?
static const std::complex< double > Im
Square root of -1.
Definition: Constants.h:40
virtual void output()
Output results to predefined output file.
virtual void save(Serializable::OArchive &ar)
Save state to archive.