PSCF v1.3.3
rpg/fts/analyzer/BinaryStructureFactorGrid.tpp
1#ifndef RPG_BINARY_STRUCTURE_FACTOR_GRID_TPP
2#define RPG_BINARY_STRUCTURE_FACTOR_GRID_TPP
3
4#include "BinaryStructureFactorGrid.h"
5
6#include <rpg/fts/simulator/Simulator.h>
7#include <rpg/system/System.h>
8#include <rpg/solvers/Mixture.h>
9#include <rpg/field/Domain.h>
10
11#include <prdc/crystal/shiftToMinimum.h>
12#include <prdc/cuda/WaveList.h>
13#include <prdc/cuda/FFT.h>
14#include <prdc/cuda/resources.h>
15#include <prdc/cuda/complex.h>
16
17#include <pscf/inter/Interaction.h>
18#include <pscf/mesh/MeshIterator.h>
19
20#include <util/misc/FileMaster.h>
21#include <util/misc/ioUtil.h>
22#include <util/format/Dbl.h>
23#include <util/format/Int.h>
24
25#include <fftw3.h>
26
27#include <vector>
28#include <unordered_map>
29#include <algorithm>
30
31namespace Pscf {
32namespace Rpg {
33
34 using namespace Util;
35 using namespace Pscf::Prdc;
36 using namespace Pscf::Prdc::Cuda;
37
38 /*
39 * Constructor.
40 */
41 template <int D>
43 : Analyzer<D>(),
46 isInitialized_(false),
47 nSamplePerBlock_(1)
48 { setClassName("BinaryStructureFactorGrid"); }
49
50 /*
51 * Read parameters from file, and allocate memory.
52 */
53 template <int D>
55 {
56 // Precondition: Require that the system has two monomer types
57 UTIL_CHECK(system().mixture().nMonomer() == 2);
58
59 readInterval(in);
61 readOptional(in,"nSamplePerBlock", nSamplePerBlock_);
62 }
63
64 /*
65 * BinaryStructureFactorGrid setup
66 */
67 template <int D>
69 {
70 // Copies of system properties
71 const int nMonomer = system().mixture().nMonomer();
72 IntVec<D> const & dimensions = system().domain().mesh().dimensions();
73
74 FFT<D>::computeKMesh(dimensions, kMeshDimensions_, kSize_);
75
76 #if 0
77 // Compute Fourier space kMeshDimensions_
78 for (int i = 0; i < D; ++i) {
79 if (i < D - 1) {
80 kMeshDimensions_[i] = dimensions[i];
81 } else {
82 kMeshDimensions_[i] = dimensions[i]/2 + 1;
83 }
84 }
85 kSize_ = 1;
86 for(int i = 0; i < D; ++i) {
87 kSize_ *= kMeshDimensions_[i];
88 }
89 #endif
90
91 nWave_ = kSize_;
92
93 if (!isInitialized_){
94 wm_.allocate(dimensions);
95 wk_.allocate(dimensions);
96 }
97
98 structureFactors_.allocate(nWave_);
99 accumulators_.allocate(nWave_);
100
101 // Convert real grid to KGrid format
102 qList_.resize(kSize_);
103 RField<D> const & kSq = system().domain().waveList().kSq();
104 HostDArray<cudaReal> kSqHost(kSize_);
105 kSqHost = kSq;
106 MeshIterator<D> itr;
107 itr.setDimensions(kMeshDimensions_);
108 for (itr.begin(); !itr.atEnd(); ++itr){
109 qList_[itr.rank()] = sqrt(double(kSqHost[itr.rank()]));
110 }
111
112 // Clear accumulators
113 for (int i = 0; i < nWave_; ++i) {
114 structureFactors_[i] = 0.0;
115 accumulators_[i].setNSamplePerBlock(nSamplePerBlock_);
116 accumulators_[i].clear();
117 }
118
119 isInitialized_ = true;
120
121 }
122
123 /*
124 * Increment structure factors for all wavevectors and modes.
125 */
126 template <int D>
128 {
129 UTIL_CHECK(system().w().hasData());
130
131 if (isAtInterval(iStep)) {
132 //IntVec<D> const & dimensions
133 // = system().domain().mesh().dimensions();
134
135 // Compute W: (rgrid(0) - rgrid(1)) / 2
136 VecOp::addVcVc(wm_, system().w().rgrid(0), 0.5,
137 system().w().rgrid(1), -0.5);
138
139 // Convert real grid to KGrid format
140 system().domain().fft().forwardTransform(wm_, wk_);
141
142 HostDArray<cudaComplex> wkCpu(kSize_);
143 wkCpu = wk_; // copy from device to host
144 for (int k = 0; k < wk_.capacity(); k++) {
145 accumulators_[k].sample(absSq<cudaComplex, cudaReal>(wkCpu[k]));
146 }
147 }
148
149 }
150
151 template <int D>
153 {
154 const double vSystem = system().domain().unitCell().volume();
155 const double vMonomer = system().mixture().vMonomer();
156 double n = vSystem / vMonomer;
157 double chi= system().interaction().chi(0,1);
158 MeshIterator<D> itr;
159 itr.setDimensions(kMeshDimensions_);
160 for (itr.begin(); !itr.atEnd(); ++itr) {
161 // Compute vS(q)
162 structureFactors_[itr.rank()] = n / (chi * chi) * accumulators_[itr.rank()].average() - 1.0/(2.0*chi);
163
164 // Compute S(q)
165 structureFactors_[itr.rank()] /= vMonomer;
166 }
167 }
168
169 // Average S(k) over k of equal magnitude
170 template <int D>
172 {
173 UTIL_CHECK(qList_.capacity() == structureFactors_.capacity());
174
175 std::map<double, double> SMap;
176 for (int i = 0; i < qList_.capacity(); ++i) {
177 double q = qList_[i];
178 double s = structureFactors_[i];
179 SMap[q] += s;
180 }
181
182 // Average structure factor with same magnitude value of q
183 for (auto& i : SMap) {
184 double q = i.first;
185 double sum = i.second;
186 int count = std::count(qList_.begin(), qList_.end(), q);
187 i.second = sum / count;
188 }
189
190 // Average structure factor for q in range of +-tolerance
191 double tolerance = 1e-5;
192 auto it = SMap.begin();
193 double currentq = it->first;
194 double sumS = it->second;
195 int count = 1;
196 for (++it; it != SMap.end(); ++it) {
197 double key = it->first;
198 double s = it->second;
199 if (std::abs(key - currentq) <= tolerance) {
200 sumS += s;
201 count++;
202 } else {
203 averageSMap_[currentq] = sumS / count;
204 currentq = key;
205 sumS = s;
206 count = 1;
207 }
208 }
209
210 // Add last batch of data (last number within tolerance)
211 averageSMap_[currentq] = sumS / count;
212 }
213
214
215
216
217 /*
218 * Output final results to output file.
219 */
220 template <int D>
222 {
225
226 // Output structure factors to one file
227 system().fileMaster().openOutputFile(outputFileName(), outputFile_);
228 outputFile_ << "\t" << "q";
229 outputFile_ << "\t" <<"\t" <<"S(q)";
230 outputFile_<< std::endl;
231 for (const auto& i : averageSMap_) {
232 double q = i.first;
233 double averageS = i.second;
234 outputFile_ << Dbl(q, 18, 8);
235 outputFile_ << Dbl(averageS, 18, 8);
236 outputFile_ << std::endl;
237 }
238 outputFile_.close();
239 }
240
241}
242}
243#endif
Template for dynamic array stored in host CPU memory.
Definition HostDArray.h:43
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
Iterator over points in a Mesh<D>.
int rank() const
Get the rank of current element.
void begin()
Set iterator to the first point in the mesh.
bool atEnd() const
Is this the end (i.e., one past the last point)?
void setDimensions(const IntVec< D > &dimensions)
Set the grid dimensions in all directions.
static void computeKMesh(IntVec< D > const &rMeshDimensions, IntVec< D > &kMeshDimensions, int &kSize)
Compute dimensions and size of k-space mesh for DFT of real data.
Definition cpu/FFT.tpp:262
Field of real double precision values on an FFT mesh.
Definition cpu/RField.h:29
const std::string & outputFileName() const
Return outputFileName string.
Analyzer()
Default constructor.
void readOutputFileName(std::istream &in)
Read outputFileName from file.
void readInterval(std::istream &in)
Read interval from file, with error checking.
bool isAtInterval(long counter) const
Return true iff counter is a multiple of the interval.
void sample(long iStep)
Add particles to BinaryStructureFactor accumulators.
void setClassName(const char *className)
Set class name string.
ScalarParam< Type > & readOptional(std::istream &in, const char *label, Type &value)
Add and read a new optional ScalarParam < Type > object.
void averageStructureFactor()
Compute average S(k) over k of equal magnitude.
System< D > * systemPtr_
Pointer to the parent system.
void output()
Output results to predefined output file.
Simulator< D > & simulator()
Return reference to parent Simulator.
void readParameters(std::istream &in)
Read parameters from file.
System< D > & system()
Return reference to parent system.
Simulator< D > * simulatorPtr_
Pointer to parent Simulator.
BinaryStructureFactorGrid(Simulator< D > &simulator, System< D > &system)
Constructor.
Field theoretic simulator (base class).
Main class, representing a complete physical system.
Wrapper for a double precision number, for formatted ostream output.
Definition Dbl.h:40
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
RT absSq(CT const &a)
Return square of absolute magnitude of a complex number.
void addVcVc(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, cudaReal const c, DeviceArray< cudaReal > const &d, cudaReal const e)
Vector addition w/ coefficient, a[i] = (b[i]*c) + (d[i]*e), kernel wrapper.
Definition VecOpMisc.cu:304
Fields, FFTs, and utilities for periodic boundary conditions (CUDA)
Definition CField.cu:12
Periodic fields and crystallography.
Definition CField.cpp:11
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.