Simpatico  v1.10
ddMd/analyzers/scattering/StructureFactorGrid.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 "StructureFactorGrid.h"
9 #include <ddMd/simulation/Simulation.h>
10 #include <util/crystal/PointGroup.h>
11 #include <util/crystal/PointSymmetry.h>
12 #include <util/archives/Serializable_includes.h>
13 #include <util/mpi/MpiLoader.h>
14 #include <util/format/Int.h>
15 #include <util/format/Dbl.h>
16 
17 #include <iostream>
18 #include <fstream>
19 namespace DdMd
20 {
21 
22  using namespace Util;
23 
24  /*
25  * Constructor.
26  */
28  : StructureFactor(simulation),
29  hMax_(0),
30  nStar_(0),
31  lattice_(Triclinic),
32  isInitialized_(false)
33  { setClassName("StructureFactorGrid"); }
34 
35  /*
36  * Read parameters from file, and allocate data array.
37  */
38  void StructureFactorGrid::readParameters(std::istream& in)
39  {
41 
42  // Read parameters
43  readInterval(in);
45  read<int>(in, "nMode", nMode_);
47  readDMatrix<double>(in, "modes", modes_, nMode_, nAtomType_);
48  read<int>(in, "hMax", hMax_);
49  read<LatticeSystem>(in, "lattice", lattice_);
50 
51  // Allocate wavevectors arrays
52  nWave_ = (2*hMax_ +1 )*(2*hMax_ + 1)*(2*hMax_ + 1);
53  waveIntVectors_.allocate(nWave_);
54  waveVectors_.allocate(nWave_);
55  fourierModes_.allocate(nWave_, nMode_);
56  totalFourierModes_.allocate(nWave_, nMode_);
57 
58  int i, j, h, k, l, m;
59  IntVector g;
60 
61  // Cubic Symmetry
62  if (lattice_ == Cubic) {
63  nStar_ = (hMax_ +1 )*(hMax_ + 2)*(hMax_ + 3)/6;
64  starIds_.allocate(nStar_);
65  starSizes_.allocate(nStar_);
66 
67  // Create cubic point group
68  PointGroup group;
69  PointSymmetry a, b, c;
70 
71  a.R(0,1) = 1;
72  a.R(1,0) = 1;
73  a.R(2,2) = 1;
74 
75  b.R(0,0) = -1;
76  b.R(1,1) = 1;
77  b.R(2,2) = 1;
78 
79  c.R(0,1) = 1;
80  c.R(1,2) = 1;
81  c.R(2,0) = 1;
82 
83  group.add(c);
84  group.add(b);
85  group.add(a);
86  group.makeCompleteGroup();
87 
88  // Create grid of wavevectors
90  i = 0;
91  j = 0;
92  for (h = 0; h <= hMax_; ++h) {
93  g[0] = h;
94  for (k = 0; k <= h; ++k) {
95  g[1] = k;
96  for (l = 0; l <= k; ++l) {
97  g[2] = l;
98  starIds_[i] = j;
99  group.makeStar(g, star);
100  starSizes_[i] = star.size();
101  for (m = 0; m < star.size(); ++m) {
102  waveIntVectors_[j] = star[m];
103  ++j;
104  }
105  ++i;
106  }
107  }
108  }
109  if (i != nStar_) {
110  UTIL_THROW("Error");
111  }
112  if (j != nWave_) {
113  UTIL_THROW("Error");
114  }
115  } else if (lattice_ == Tetragonal) {
116 
117  nStar_ = (hMax_ + 1 )*(hMax_ + 1)*(hMax_ + 2)/2;
118  starIds_.allocate(nStar_);
119  starSizes_.allocate(nStar_);
120  // Create tetragonal point group
121  PointGroup group;
122  PointSymmetry a, b, c;
123 
124  a.R(0,0) = 1;
125  a.R(1,2) = 1;
126  a.R(2,1) = 1;
127 
128  b.R(0,0) = -1;
129  b.R(1,1) = 1;
130  b.R(2,2) = 1;
131 
132  c.R(0,0) = 1;
133  c.R(1,1) = -1;
134  c.R(2,2) = 1;
135 
136  group.add(c);
137  group.add(b);
138  group.add(a);
139  group.makeCompleteGroup();
140 
141  // Create grid of wavevectors
143  i = 0;
144  j = 0;
145  for (h = 0; h <= hMax_; ++h) {
146  g[0] = h;
147  for (k = 0; k <= hMax_; ++k) {
148  g[1] = k;
149  for (l = 0; l <= k; ++l) {
150  g[2] = l;
151  starIds_[i] = j;
152  group.makeStar(g, star);
153  starSizes_[i] = star.size();
154  for (m = 0; m < star.size(); ++m) {
155  waveIntVectors_[j] = star[m];
156  ++j;
157  }
158  ++i;
159  }
160  }
161  }
162  if (i != nStar_) {
163  UTIL_THROW("Error");
164  }
165  if (j != nWave_) {
166  UTIL_THROW("Error");
167  }
168  } else if (lattice_ == Orthorhombic) {
169 
170  nStar_ = (hMax_ + 1 )*(hMax_ + 1)*(hMax_ + 1);
171  starIds_.allocate(nStar_);
172  starSizes_.allocate(nStar_);
173  // Create tetragonal point group
174  PointGroup group;
175  PointSymmetry a, b, c;
176 
177  a.R(0,0) = -1;
178  a.R(1,1) = 1;
179  a.R(2,2) = 1;
180 
181  b.R(0,0) = 1;
182  b.R(1,1) = -1;
183  b.R(2,2) = 1;
184 
185  c.R(0,0) = 1;
186  c.R(1,1) = 1;
187  c.R(2,2) = -1;
188 
189  group.add(c);
190  group.add(b);
191  group.add(a);
192  group.makeCompleteGroup();
193 
194  // Create grid of wavevectors
196  i = 0;
197  j = 0;
198  for (h = 0; h <= hMax_; ++h) {
199  g[0] = h;
200  for (k = 0; k <= hMax_; ++k) {
201  g[1] = k;
202  for (l = 0; l <= hMax_; ++l) {
203  g[2] = l;
204  starIds_[i] = j;
205  group.makeStar(g, star);
206  starSizes_[i] = star.size();
207  for (m = 0; m < star.size(); ++m) {
208  waveIntVectors_[j] = star[m];
209  ++j;
210  }
211  ++i;
212  }
213  }
214  }
215  if (i != nStar_) {
216  UTIL_THROW("Error");
217  }
218  if (j != nWave_) {
219  UTIL_THROW("Error");
220  }
221  }
222 
223  if (simulation().domain().isMaster()) {
224 
225  structureFactors_.allocate(nWave_, nMode_);
226  int i, j;
227  for (i = 0; i < nWave_; ++i) {
228  for (j = 0; j < nMode_; ++j) {
229  structureFactors_(i, j) = 0.0;
230  }
231  }
232 
233  }
234  nSample_ = 0;
235 
236  isInitialized_ = true;
237  }
238 
239  /*
240  * Load internal state from an archive.
241  */
243  {
245 
246  // Load parameter file parameters
247  loadInterval(ar);
248  loadOutputFileName(ar);
249  loadParameter<int>(ar, "nMode", nMode_);
251  loadDMatrix<double>(ar, "modes", modes_, nMode_, nAtomType_);
252  loadParameter<int>(ar, "hMax", hMax_);
253  loadParameter<LatticeSystem>(ar, "lattice", lattice_);
254 
255  // Load and broadcast other distributed members
256  MpiLoader<Serializable::IArchive> loader(*this, ar);
257  loader.load(nWave_);
258  waveIntVectors_.allocate(nWave_);
259  loader.load(waveIntVectors_, nWave_);
260  loader.load(nStar_);
261  starIds_.allocate(nStar_);
262  loader.load(starIds_, nStar_);
263  starSizes_.allocate(nStar_);
264  loader.load(starSizes_, nStar_);
265  loader.load(nSample_);
266 
267  if (simulation().domain().isMaster()) {
269  ar >> structureFactors_;
270  }
271 
272  // Allocate work space
273  waveVectors_.allocate(nWave_);
274  fourierModes_.allocate(nWave_, nMode_);
276 
277  isInitialized_ = true;
278  }
279 
280  /*
281  * Save internal state to an archive.
282  */
284  {
285  saveInterval(ar);
286  saveOutputFileName(ar);
287  ar << nMode_;
288  ar << modes_;
289  ar << hMax_;
290  ar << lattice_;
291 
292  ar << nWave_;
293  ar << waveIntVectors_;
294  ar << nStar_;
295  ar << starIds_;
296  ar << starSizes_;
297  ar << nSample_;
298 
299  ar << structureFactors_;
300  }
301 
303  {}
304 
306  {
307  if (!isAtInterval(iStep)) {
308  UTIL_THROW("Time step index is not a multiple of interval");
309  }
310 
311  if (simulation().domain().isMaster()) {
312  // simulation().fileMaster().openOutputFile(outputFileName(".dat"), logFile_, !isFirstStep_);
313  std::ios_base::openmode mode = std::ios_base::out;
314  if (!isFirstStep_) {
315  mode = std::ios_base::out | std::ios_base::app;
316  }
317  std::string name = outputFileName(".dat");
318  simulation().fileMaster().openOutputFile(name, logFile_, mode);
319  }
320 
322 
323  // Log structure factors
324  if (simulation().domain().isMaster()) {
325  double volume = simulation().boundary().volume();
326  double norm;
327  for (int i = 0; i < nStar_; ++i) {
328  int size = starSizes_[i];
329 
330  int k = starIds_[i];
331  for (int n = 0; n < Dimension; ++n) {
332  logFile_ << Int(waveIntVectors_[k][n], 5);
333  }
334  logFile_ << Dbl(waveVectors_[k].abs(), 20, 8);
335 
336  for (int j = 0; j < nMode_; ++j) {
337  double average = 0.0;
338  double value = 0.0;
339  k = starIds_[i];
340  for (int m = 0; m < size; ++m) {
341  norm = std::norm(totalFourierModes_(k, j));
342  value = norm/volume;
343  average += value;
344  ++k;
345  }
346  average = average/double(size);
347  logFile_ << Dbl(average, 20, 8);
348  }
349  logFile_ << std::endl;
350  }
351  logFile_ << std::endl;
352  logFile_.close();
353  }
354 
355  }
356 
358  {
359  if (simulation().domain().isMaster()) {
360 
361  double value, average, size;
362  int i, j, k, m, n;
363 
364  // Write parameters to a *.prm file
367  outputFile_.close();
368 
369  // Output all structure factors to one file
371  for (i = 0; i < nStar_; ++i) {
372  size = starSizes_[i];
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  outputFile_.close();
392 
393  }
394  }
395 
396 }
virtual void clear()
Clear all accumulators and counters.
const int Dimension
Dimensionality of space.
Definition: Dimension.h:19
Simulation & simulation()
Get the parent Simulation by reference.
DArray< IntVector > waveIntVectors_
Array of Miller index IntVectors for wavevectors.
void readOutputFileName(std::istream &in)
Read outputFileName from file.
void saveInterval(Serializable::OArchive &ar)
Save interval parameter to an archive.
void allocate(int capacity1, int capacity2)
Allocate memory for a matrix.
Definition: DMatrix.h:170
StructureFactorGrid(Simulation &simulation)
Constructor.
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
DMatrix< double > structureFactors_
Structure factor accumulators.
int nAtomType_
Number of atom types, copied from Simulation::nAtomType().
void readInterval(std::istream &in)
Read parameter interval from file.
Wrapper for a double precision number, for formatted ostream output.
Definition: Dbl.h:39
DArray< Vector > waveVectors_
Array of floating point wave vectors.
bool add(Symmetry &symmetry)
Add a new element to the group.
Parallel domain decomposition (DD) MD simulation.
Main object for a domain-decomposition MD simulation.
Saving / output archive for binary ostream.
void loadOutputFileName(Serializable::IArchive &ar)
Load output file name to an archive.
A fixed capacity (static) contiguous array with a variable logical size.
Definition: FSArray.h:37
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 writeParam(std::ostream &out)
Write all parameters to an output stream.
bool isAtInterval(long counter) const
Return true iff counter is a multiple of the interval.
Utility classes for scientific computation.
Definition: accumulators.mod:1
std::ofstream outputFile_
Output file stream.
virtual void save(Serializable::OArchive &ar)
Save internal state to an archive.
int & R(int i, int j)
Return an element of the matrix by reference.
Wrapper for an int, for formatted ostream output.
Definition: Int.h:36
DMatrix< std::complex< double > > totalFourierModes_
Total fourier modes of concentration.
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
const std::string & outputFileName() const
Return outputFileName string.
virtual void loadParameters(Serializable::IArchive &ar)
Load internal state from an archive.
StructureFactor evaluates structure factors in Fourier space.
Saving archive for binary istream.
DMatrix< std::complex< double > > fourierModes_
Fourier modes of concentration.
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.
An IntVector is an integer Cartesian vector.
Definition: IntVector.h:73
int nAtomType()
Get maximum number of atom types.
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.
virtual void output()
Output structure factors, averaged over stars.
virtual void readParameters(std::istream &in)
Read parameters from file.
void makeCompleteGroup()
Generate a complete group from the current elements.
int nSample_
Number of samples thus far.
int size() const
Return logical size of this array (i.e., number of elements).
Definition: FSArray.h:207
void sample(long iStep)
Add particles to StructureFactor accumulators.
DMatrix< double > modes_
Array of mode vectors.
virtual void sample(long iStep)
Add particles to StructureFactor accumulators.
A PointSymmetry represents a crystallographic point group symmetry.
Definition: PointSymmetry.h:22