Simpatico  v1.10
StructureFactorP.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 "StructureFactorP.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/misc/ioUtil.h>
18 #include <util/format/Int.h>
19 #include <util/format/Dbl.h>
20 
21 namespace McMd
22 {
23 
24  using namespace Util;
25  using namespace Simp;
26 
27  /*
28  * Constructor.
29  */
31  : SystemAnalyzer<System>(system)
32  { setClassName("StructureFactorP"); }
33 
34  /*
35  * Destructor.
36  */
38  {}
39 
40  /*
41  * Read parameters from file, and allocate memory.
42  */
43  void StructureFactorP::readParameters(std::istream& in)
44  {
45  readInterval(in);
47 
49 
50  read<int>(in, "nAtomTypeIdPair", nAtomTypeIdPair_);
52  readDArray< Pair<int> >(in, "atomTypeIdPairs", atomTypeIdPairs_,
54 
55  read<int>(in, "nWave", nWave_);
56  waveIntVectors_.allocate(nWave_);
57  readDArray<IntVector>(in, "waveIntVectors", waveIntVectors_, nWave_);
58 
59  waveVectors_.allocate(nWave_);
60  fourierModes_.allocate(nWave_, nAtomType_ + 1);
62 
63  isInitialized_ = true;
64  }
65 
66  /*
67  * Load state from archive.
68  */
70  {
72  ar & nAtomType_;
73  loadParameter<int>(ar, "nAtomTypeIdPair", nAtomTypeIdPair_);
74  loadDArray< Pair<int> >(ar, "atomTypeIdPairs", atomTypeIdPairs_,
76  loadParameter<int>(ar, "nWave", nWave_);
77  loadDArray<IntVector>(ar, "waveIntVectors", waveIntVectors_, nWave_);
78  ar & structureFactors_;
79  ar & nSample_;
80 
81  // Validate
82  if (nAtomType_ != system().simulation().nAtomType()) {
83  UTIL_THROW("Inconsistent values of nAtomType");
84  }
85  if (nAtomTypeIdPair_ != atomTypeIdPairs_.capacity()) {
86  UTIL_THROW("Inconsistent capacity for atomTypeIdPairs");
87  }
88  if (nWave_ != waveIntVectors_.capacity()) {
89  UTIL_THROW("Inconsistent capacity for waveIntVectors");
90  }
91  if (nWave_ != structureFactors_.capacity1()) {
92  UTIL_THROW("Inconsistent capacity1 for structureFactors");
93  }
94  if (nAtomTypeIdPair_ != structureFactors_.capacity2()) {
95  UTIL_THROW("Inconsistent capacity2 for structureFactors");
96  }
97 
98  // Allocate
99  waveVectors_.allocate(nWave_);
100  fourierModes_.allocate(nWave_, nAtomType_ + 1);
101 
102  isInitialized_ = true;
103  }
104 
105  /*
106  * Save state to archive.
107  */
109  { ar & *this; }
110 
111  /*
112  * Setup immediately before simulation.
113  */
115  {
116  if (!isInitialized_) {
117  UTIL_THROW("Object not initialized");
118  }
119  assert (nWave_ > 0);
120  assert (nAtomTypeIdPair_ > 0);
121 
122  // Clear accumulators
123  int i, j;
124  for (i = 0; i < nWave_; ++i) {
125  for (j = 0; j < nAtomTypeIdPair_; ++j) {
126  structureFactors_(i, j) = 0.0;
127  }
128  }
129  nSample_ = 0;
130  }
131 
133  void StructureFactorP::sample(long iStep)
134  {
135  if (isAtInterval(iStep)) {
136 
137  Vector position;
138  std::complex<double> expFactor;
139  double product;
142  int nSpecies, iSpecies, typeId, i;
143 
144  makeWaveVectors();
145 
146  // Set all Fourier modes to zero
147  for (i = 0; i < nWave_; ++i) {
148  for (typeId = 0; typeId <= nAtomType_; ++typeId) {
149  fourierModes_(i, typeId) = std::complex<double>(0.0, 0.0);
150  }
151  }
152 
153  // Loop over all atoms
154  nSpecies = system().simulation().nSpecies();
155  for (iSpecies = 0; iSpecies < nSpecies; ++iSpecies) {
156  system().begin(iSpecies, molIter);
157  for ( ; molIter.notEnd(); ++molIter) {
158  molIter->begin(atomIter);
159  for ( ; atomIter.notEnd(); ++atomIter) {
160  position = atomIter->position();
161  typeId = atomIter->typeId();
162 
163  // Loop over wavevectors
164  for (i = 0; i < nWave_; ++i) {
165 
166  product = position.dot(waveVectors_[i]);
167  expFactor = exp( product*Constants::Im );
168  fourierModes_(i, typeId) += expFactor;
169  fourierModes_(i, nAtomType_) += expFactor;
170 
171  }
172 
173  }
174  }
175 
176  }
177 
178  // Increment structure factors
179  std::complex<double> rho[2];
180  double volume = system().boundary().volume();
181  int j, k;
182  for (i = 0; i < nWave_; ++i) {
183  for (j = 0; j < nAtomTypeIdPair_; ++j) {
184  for (k = 0; k < 2; ++k) {
185  typeId = atomTypeIdPairs_[j][k];
186  if (typeId >= 0) {
187  rho[k] = fourierModes_(i, typeId);
188  } else {
189  rho[k] = fourierModes_(i, nAtomType_);
190  }
191  }
192  rho[0] = std::conj(rho[0]);
193  structureFactors_(i, j) += std::real(rho[0]*rho[1])/volume;
194  }
195  }
196 
197  ++nSample_;
198 
199  }
200 
201  }
202 
207  {
208  Vector dWave;
209  Boundary* boundaryPtr = &system().boundary();
210  int i, j;
211 
212  // Calculate wavevectors
213  for (i = 0; i < nWave_; ++i) {
215  for (j = 0; j < Dimension; ++j) {
216  dWave = boundaryPtr->reciprocalBasisVector(j);
217  dWave *= waveIntVectors_[i][j];
218  waveVectors_[i] += dWave;
219  //std::cout << waveVectors_[i] << std::endl;
220  }
221  }
222  }
223 
225  {
226  double value;
227  int i, j, k;
228 
229  // Echo parameters to a log file
232  outputFile_.close();
233 
234  // Output structure factors to one file
236  for (i = 0; i < nWave_; ++i) {
237  for (k = 0; k < Dimension; ++k) {
238  outputFile_ << Int(waveIntVectors_[i][k], 5);
239  }
240  outputFile_ << Dbl(waveVectors_[i].abs(), 20, 8);
241  for (j = 0; j < nAtomTypeIdPair_; ++j) {
242  value = structureFactors_(i, j)/double(nSample_);
243  outputFile_ << Dbl(value, 18, 8);
244  }
245  outputFile_ << std::endl;
246  }
247  outputFile_.close();
248 
249  #if 0
250  // Output each structure factor to a separate file
251  std::string suffix;
252  int typeId;
253  for (j = 0; j < nAtomTypeIdPair_; ++j) {
254 
255  // Construct file suffix for this structure factor
256  suffix = std::string(".");
257  for (k = 0; k < 2; k++) {
258  typeId = atomTypeIdPairs_[j][k];
259  if (typeId < 0) {
260  suffix += std::string("A");
261  } else {
262  suffix += toString(typeId);
263  }
264  }
265  suffix += std::string(".dat");
266 
268 
269  // Loop over waves to output structure factor
270  for (i = 0; i < nWave_; ++i) {
271  for (k = 0; k < Dimension; ++k) {
272  outputFile_ << Int(waveIntVectors_[i][k], 5);
273  }
274  outputFile_ << Dbl(waveVectors_[i].abs(), 20, 8);
275  value = structureFactors_(i, j)/double(nSample_);
276  outputFile_ << Dbl(value, 20, 8);
277  outputFile_ << std::endl;
278  }
279 
280  outputFile_.close();
281  }
282  #endif
283 
284  }
285 
286 }
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
int nAtomTypeIdPair_
Number of selected atom type pairs.
std::string toString(int n)
Return string representation of an integer.
Definition: ioUtil.cpp:52
A Vector is a Cartesian vector.
Definition: Vector.h:75
virtual void readParameters(std::istream &in)
Read parameters from file.
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 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
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
An orthorhombic periodic unit cell.
std::ofstream outputFile_
Output file stream.
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?
virtual void loadParameters(Serializable::IArchive &ar)
Load parameters from archive.
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
virtual void save(Serializable::OArchive &ar)
Save state to an archive.
Forward iterator for a PArray.
Classes used by all simpatico molecular simulations.
void readOutputFileName(std::istream &in)
Read outputFileName from file.
~StructureFactorP()
Destructor.
StructureFactorP(System &system)
Constructor.
Forward const iterator for an Array or a C array.
Saving / output archive for binary ostream.
DArray< IntVector > waveIntVectors_
Array of miller index IntVectors for wavevectors.
#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
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.
virtual void setup()
Clear accumulators.
void readInterval(std::istream &in)
Read interval from file, with error checking.
Utility classes for scientific computation.
Definition: accumulators.mod:1
int nAtomType_
Number of atom types, copied from Simulation::nAtomType().
Wrapper for an int, for formatted ostream output.
Definition: Int.h:36
virtual void output()
Output results to predefined output file.
void sample(long iStep)
Add particle pairs to StructureFactorP histogram.
Template for Analyzer associated with one System.
int nSample_
Number of samples thus far.
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.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
int nSpecies() const
Get the number of Species in this Simulation.
DMatrix< double > structureFactors_
Structure factor accumulators.
void setClassName(const char *className)
Set class name string.
FileMaster & fileMaster()
Get the FileMaster by reference.
bool isAtInterval(long counter) const
Return true iff counter is a multiple of the interval.
const std::string & outputFileName() const
Return outputFileName string.
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
DArray< Vector > waveVectors_
Array of wave vectors (temporary)
void makeWaveVectors()
Update wavevectors.
DArray< Pair< int > > atomTypeIdPairs_
Array of atom type indices (-1 indicates a sum of all types)
int nWave_
Number of wavevectors.