Simpatico  v1.10
mcMd/analyzers/system/StructureFactorGrid.cpp
1 /*
2 * Simpatico - Simulation Package for Polymeric and Molecular Liquids
3 *
4 * Copyright 2010, The Regents of the University of Minnesota
5 * Distributed under the terms of the GNU General Public License.
6 */
7 
8 #include "StructureFactorGrid.h"
9 #include <mcMd/simulation/Simulation.h>
10 #include <mcMd/simulation/McMd_mpi.h>
11 #include <util/crystal/PointGroup.h>
12 #include <util/crystal/PointSymmetry.h>
13 #include <util/archives/Serializable_includes.h>
14 #include <util/format/Int.h>
15 #include <util/format/Dbl.h>
16 
17 namespace McMd
18 {
19 
20  using namespace Util;
21 
22  /*
23  * Constructor.
24  */
26  : StructureFactor(system),
27  hMax_(0),
28  nStar_(0),
29  lattice_(Triclinic),
30  isInitialized_(false)
31  { setClassName("StructureFactorGrid"); }
32 
33  /*
34  * Read parameters from file, and allocate data array.
35  */
36  void StructureFactorGrid::readParameters(std::istream& in)
37  {
38  readInterval(in);
40  read<int>(in, "nMode", nMode_);
42  modes_.allocate(nMode_, nAtomType_);
43  readDMatrix<double>(in, "modes", modes_, nMode_, nAtomType_);
44  read<int>(in, "hMax", hMax_);
45  read<Util::LatticeSystem>(in, "lattice", lattice_);
46 
47  // Allocate wavevectors arrays
48  nWave_ = (2*hMax_ + 1)*(2*hMax_ + 1)*(2*hMax_ + 1);
49  waveIntVectors_.allocate(nWave_);
50  waveVectors_.allocate(nWave_);
51  fourierModes_.allocate(nWave_, nMode_);
52  structureFactors_.allocate(nWave_, nMode_);
53 
54  int i, j, h, k, l, m;
55  IntVector g;
56 
57  // Cubic Symmetry
58  if (lattice_ == Cubic) {
59 
60  nStar_ = (hMax_ + 1 )*(hMax_ + 2)*(hMax_ + 3)/6;
61  starIds_.allocate(nStar_);
62  starSizes_.allocate(nStar_);
63 
64  // Create cubic point group
65  PointGroup group;
66  PointSymmetry a, b, c;
67 
68  a.R(0,1) = 1;
69  a.R(1,0) = 1;
70  a.R(2,2) = 1;
71 
72  b.R(0,0) = -1;
73  b.R(1,1) = 1;
74  b.R(2,2) = 1;
75 
76  c.R(0,1) = 1;
77  c.R(1,2) = 1;
78  c.R(2,0) = 1;
79 
80  group.add(c);
81  group.add(b);
82  group.add(a);
83  group.makeCompleteGroup();
84 
85  // Create grid of wavevectors
87  i = 0;
88  j = 0;
89  for (h = 0; h <= hMax_; ++h) {
90  g[0] = h;
91  for (k = 0; k <= h; ++k) {
92  g[1] = k;
93  for (l = 0; l <= k; ++l) {
94  g[2] = l;
95  starIds_[i] = j;
96  group.makeStar(g, star);
97  starSizes_[i] = star.size();
98  for (m = 0; m < star.size(); ++m) {
99  waveIntVectors_[j] = star[m];
100  ++j;
101  }
102  ++i;
103  }
104  }
105  }
106  if (i != nStar_) {
107  UTIL_THROW("Error");
108  }
109  if (j != nWave_) {
110  UTIL_THROW("Error");
111  }
112  } else if (lattice_ == Tetragonal) {
113 
114  nStar_ = (hMax_ + 1 )*(hMax_ + 1)*(hMax_ + 2)/2;
115  starIds_.allocate(nStar_);
116  starSizes_.allocate(nStar_);
117  // Create tetragonal point group
118  PointGroup group;
119  PointSymmetry a, b, c;
120 
121  a.R(0,0) = 1;
122  a.R(1,2) = 1;
123  a.R(2,1) = 1;
124 
125  b.R(0,0) = -1;
126  b.R(1,1) = 1;
127  b.R(2,2) = 1;
128 
129  c.R(0,0) = 1;
130  c.R(1,1) = -1;
131  c.R(2,2) = 1;
132 
133  group.add(c);
134  group.add(b);
135  group.add(a);
136  group.makeCompleteGroup();
137 
138  // Create grid of wavevectors
140  i = 0;
141  j = 0;
142  for (h = 0; h <= hMax_; ++h) {
143  g[0] = h;
144  for (k = 0; k <= hMax_; ++k) {
145  g[1] = k;
146  for (l = 0; l <= k; ++l) {
147  g[2] = l;
148  starIds_[i] = j;
149  group.makeStar(g, star);
150  starSizes_[i] = star.size();
151  for (m = 0; m < star.size(); ++m) {
152  waveIntVectors_[j] = star[m];
153  ++j;
154  }
155  ++i;
156  }
157  }
158  }
159  if (i != nStar_) {
160  UTIL_THROW("Error");
161  }
162  if (j != nWave_) {
163  UTIL_THROW("Error");
164  }
165  } else if (lattice_ == Orthorhombic) {
166 
167  nStar_ = (hMax_ + 1 )*(hMax_ + 1)*(hMax_ + 1);
168  starIds_.allocate(nStar_);
169  starSizes_.allocate(nStar_);
170  // Create orthorhombic point group
171  PointGroup group;
172  PointSymmetry a, b, c;
173 
174  a.R(0,0) = -1;
175  a.R(1,1) = 1;
176  a.R(2,2) = 1;
177 
178  b.R(0,0) = 1;
179  b.R(1,1) = -1;
180  b.R(2,2) = 1;
181 
182  c.R(0,0) = 1;
183  c.R(1,1) = 1;
184  c.R(2,2) = -1;
185 
186  group.add(c);
187  group.add(b);
188  group.add(a);
189  group.makeCompleteGroup();
190 
191  // Create grid of wavevectors
193  i = 0;
194  j = 0;
195  for (h = 0; h <= hMax_; ++h) {
196  g[0] = h;
197  for (k = 0; k <= hMax_; ++k) {
198  g[1] = k;
199  for (l = 0; l <= hMax_; ++l) {
200  g[2] = l;
201  starIds_[i] = j;
202  group.makeStar(g, star);
203  starSizes_[i] = star.size();
204  for (m = 0; m < star.size(); ++m) {
205  waveIntVectors_[j] = star[m];
206  ++j;
207  }
208  ++i;
209  }
210  }
211  }
212  if (i != nStar_) {
213  UTIL_THROW("Error");
214  }
215  if (j != nWave_) {
216  UTIL_THROW("Error");
217  }
218  }
219 
220  // Clear accumulators
221  for (i = 0; i < nWave_; ++i) {
222  for (j = 0; j < nMode_; ++j) {
223  structureFactors_(i, j) = 0.0;
224  }
225  }
226 
227  nSample_ = 0;
228 
229  isInitialized_ = true;
230  }
231 
232  /*
233  * Load state from an archive.
234  */
236  {
237  // Load from StructureFactor::serialize
239  ar & nAtomType_;
240  loadParameter<int>(ar, "nMode", nMode_);
241  modes_.allocate(nMode_, nAtomType_);
242  loadDMatrix<double>(ar, "modes", modes_, nMode_, nAtomType_);
243  ar & nWave_;
244  waveIntVectors_.allocate(nWave_);
245  structureFactors_.allocate(nWave_, nMode_);
246  ar & waveIntVectors_;
247  ar & structureFactors_;
248  ar & nSample_;
249 
250  // Load additional from StructureFactorGrid::serialize
251  loadParameter<int>(ar, "hMax", hMax_);
252  loadParameter<Util::LatticeSystem>(ar, "lattice", lattice_);
253  ar & nStar_;
254  starIds_.allocate(nStar_);
255  starSizes_.allocate(nStar_);
256  ar & starIds_;
257  ar & starSizes_;
258 
259  // Validate
260  if (nWave_ != (2*hMax_ + 1)*(2*hMax_ + 1)*(2*hMax_ + 1)) {
261  UTIL_THROW("Inconsistent value of nWave_");
262  }
263  if (nAtomType_ != system().simulation().nAtomType()) {
264  UTIL_THROW("Inconsistent values of nAtomType_");
265  }
266  if (modes_.capacity1() != nMode_) {
267  UTIL_THROW("Inconsistent capacity1 for modes array");
268  }
269  if (modes_.capacity2() != nAtomType_) {
270  UTIL_THROW("Inconsistent capacity2 for modes array");
271  }
272  if (waveIntVectors_.capacity() != nWave_) {
273  UTIL_THROW("Inconsistent capacity for waveIntVector");
274  }
275 
276  // Allocate temporary data structures (defined in StructureFactor)
277  waveVectors_.allocate(nWave_);
278  fourierModes_.allocate(nWave_, nMode_);
279 
280  isInitialized_ = true;
281  }
282 
283  /*
284  * Save state to archive.
285  */
287  { ar & *this; }
288 
290  {}
291 
293  {
294 
295  std::ios_base::openmode mode = std::ios_base::out;
296  if (!isFirstStep_) {
297  mode = std::ios_base::out | std::ios_base::app;
298  }
299  fileMaster().openOutputFile(outputFileName(".dat"), logFile_, mode);
300 
301  // fileMaster().openOutputFile(outputFileName(".dat"), logFile_, !isFirstStep_);
302 
304 
305  // Log structure factors
306  double volume = system().boundary().volume();
307  double norm;
308  for (int i = 0; i < nStar_; ++i) {
309  int size = starSizes_[i];
310 
311  int k = starIds_[i];
312  for (int n = 0; n < Dimension; ++n) {
313  logFile_ << Int(waveIntVectors_[k][n], 5);
314  }
315  logFile_ << Dbl(waveVectors_[k].abs(), 20, 8);
316 
317 
318  for (int j = 0; j < nMode_; ++j) {
319  double average = 0.0;
320  double value = 0.0;
321  k = starIds_[i];
322  for (int m = 0; m < size; ++m) {
323  norm = std::norm(fourierModes_(k, j));
324  value = norm/volume;
325  average += value;
326  ++k;
327  }
328  average = average/double(size);
329  logFile_ << Dbl(average, 20, 8);
330  }
331  logFile_ << std::endl;
332  }
333  logFile_ << std::endl;
334  logFile_.close();
335  }
336 
337 
339  {
340  double value, average, size;
341  int i, j, k, m, n;
342 
343  // Echo parameters to a log file
346  outputFile_.close();
347 
348  // Output structure factors to one file
350 
351  // Loop over waves to output structure factor
352  for (i = 0; i < nStar_; ++i) {
353  size = starSizes_[i];
354 
355  #if 0
356  // Output individual waves in star
357  k = starIds_[i];
358  for (m = 0; m < size; ++m) {
359  for (n = 0; n < Dimension; ++n) {
360  outputFile_ << Int(waveIntVectors_[k][n], 5);
361  }
362  outputFile_ << Dbl(waveVectors_[k].abs(), 20, 8);
363  for (j = 0; j < nMode_; ++j) {
364  value = structureFactors_(k, j)/double(nSample_);
365  outputFile_ << Dbl(value, 20, 8);
366  }
367  outputFile_ << std::endl;
368  ++k;
369  }
370  outputFile_ << std::endl;
371  #endif
372 
373  k = starIds_[i];
374  for (n = 0; n < Dimension; ++n) {
375  outputFile_ << Int(waveIntVectors_[k][n], 5);
376  }
377  outputFile_ << Dbl(waveVectors_[k].abs(), 20, 8);
378  for (j = 0; j < nMode_; ++j) {
379  k = starIds_[i];
380  average = 0.0;
381  for (m = 0; m < size; ++m) {
382  value = structureFactors_(k, j)/double(nSample_);
383  average += value;
384  ++k;
385  }
386  average = average/double(size);
387  outputFile_ << Dbl(average, 20, 8);
388  }
389  outputFile_ << std::endl;
390 
391  }
392  outputFile_.close();
393 
394  }
395 
396 }
virtual void setup()
Set up before a simulation.
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
int nSample_
Number of samples thus far.
DArray< Vector > waveVectors_
Array of floating point wave vectors (temporary).
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
Definition: DMatrix.h:170
double volume() const
Return unit cell volume.
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 loadParameters(Serializable::IArchive &ar)
Load parameters from archive.
DMatrix< std::complex< double > > fourierModes_
Instantaneous Fourier amplitudes (temporary)
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
bool add(Symmetry &symmetry)
Add a new element to the group.
void readOutputFileName(std::istream &in)
Read outputFileName from file.
virtual void readParameters(std::istream &in)
Read parameters from file.
DMatrix< double > modes_
Array of mode vectors.
Saving / output archive for binary ostream.
A fixed capacity (static) contiguous array with a variable logical size.
Definition: FSArray.h:37
#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 loadParameters(Serializable::IArchive &ar)
Load state from an archive.
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.
int nAtomType_
Number of atom types, copied from Simulation::nAtomType().
DMatrix< double > structureFactors_
Structure factor accumulators.
Utility classes for scientific computation.
Definition: accumulators.mod:1
int & R(int i, int j)
Return an element of the matrix by reference.
DArray< IntVector > waveIntVectors_
Array of Miller index IntVectors for wavevectors.
Wrapper for an int, for formatted ostream output.
Definition: Int.h:36
void makeStar(const IntVector &root, FSArray< IntVector, N > &star)
Generate a set of reciprocal vectors that are related by symmetry.
Definition: PointGroup.h:47
Group of crystal symmetries with no translations.
Definition: PointGroup.h:18
std::ofstream outputFile_
Output file stream.
virtual void sample(long iStep)
Add particles to StructureFactor accumulators.
StructureFactor evaluates structure factors in Fourier space.
Boundary & boundary() const
Get the Boundary by reference.
Definition: System.h:1064
bool isFirstStep_
Is this the first step?
Saving archive for binary istream.
Single-processor Monte Carlo (MC) and molecular dynamics (MD).
void setClassName(const char *className)
Set class name string.
An IntVector is an integer Cartesian vector.
Definition: IntVector.h:73
FileMaster & fileMaster()
Get the FileMaster by reference.
const std::string & outputFileName() const
Return outputFileName string.
void allocate(int capacity)
Allocate the underlying C array.
Definition: DArray.h:191
virtual void sample(long iStep)
Add particles to StructureFactor accumulators.
int nAtomType() const
Get the number of atom types.
virtual void save(Serializable::OArchive &ar)
Save state to archive.
void makeCompleteGroup()
Generate a complete group from the current elements.
int size() const
Return logical size of this array (i.e., number of elements).
Definition: FSArray.h:207
A PointSymmetry represents a crystallographic point group symmetry.
Definition: PointSymmetry.h:22
virtual void output()
Output structure factors, averaged over stars.