1#ifndef RPC_BINARY_STRUCTURE_FACTOR_GRID_TPP
2#define RPC_BINARY_STRUCTURE_FACTOR_GRID_TPP
4#include "BinaryStructureFactorGrid.h"
6#include <rpc/fts/simulator/Simulator.h>
9#include <prdc/cpu/RField.h>
10#include <prdc/crystal/shiftToMinimum.h>
12#include <pscf/mesh/MeshIterator.h>
13#include <pscf/math/IntVec.h>
14#include <pscf/math/RealVec.h>
16#include <util/param/ParamComposite.h>
17#include <util/misc/FileMaster.h>
18#include <util/misc/ioUtil.h>
19#include <util/format/Int.h>
20#include <util/format/Dbl.h>
46 simulatorPtr_(&simulator),
47 systemPtr_(&(simulator.system())),
48 isInitialized_(false),
62 UTIL_CHECK(2 == system().mixture().nMonomer());
65 readOutputFileName(in);
66 readOptional(in,
"nSamplePerBlock", nSamplePerBlock_);
76 const int nMonomer = system().mixture().nMonomer();
78 UTIL_THROW(
"nMonomer != 2 in BinaryStructureFactorGrid");
82 IntVec<D> const & dimensions = system().domain().mesh().dimensions();
86 for (
int i = 0; i < D; ++i) {
88 kMeshDimensions_[i] = dimensions[i];
90 kMeshDimensions_[i] = dimensions[i]/2 + 1;
92 kSize_ *= kMeshDimensions_[i];
96 wKGrid_.allocate(nMonomer);
97 wm_.allocate(dimensions);
98 wk_.allocate(dimensions);
99 for (
int i = 0; i < nMonomer; ++i) {
100 wKGrid_[i].allocate(dimensions);
104 qList_.resize(kSize_);
107 UnitCell<D> const & unitCell = system().domain().unitCell();
113 Gmin = shiftToMinimum(G, dimensions, unitCell);
114 Gsq = unitCell.
ksq(Gmin);
115 qList_[itr.
rank()] = sqrt(Gsq);
121 structureFactors_.allocate(nWave_);
122 accumulators_.allocate(nWave_);
123 isInitialized_ =
true;
126 for (
int i = 0; i < nWave_; ++i) {
127 structureFactors_[i] = 0.0;
128 accumulators_[i].setNSamplePerBlock(nSamplePerBlock_);
129 accumulators_[i].clear();
131 if (!isInitialized_) {
132 UTIL_THROW(
"Error: object is not initialized");
144 if (isAtInterval(iStep)) {
147 for (
int i = 0; i < wm_.capacity(); ++i) {
148 wm_[i] = (system().w().rgrid(0)[i] - system().w().rgrid(1)[i])/2;
152 system().domain().fft().forwardTransform(wm_, wk_);
155 for (
int k=0; k< wk_.capacity(); k++) {
156 std::complex<double> wmKGrid(wk_[k][0], wk_[k][1]);
157 double squared_magnitude = std::norm(wmKGrid);
158 accumulators_[k].sample(squared_magnitude);
167 const double vSystem = system().domain().unitCell().volume();
168 const double vMonomer = system().mixture().vMonomer();
169 double n = vSystem / vMonomer;
170 double chi= system().interaction().chi(0,1);
175 structureFactors_[itr.
rank()] = n / (chi * chi) * accumulators_[itr.
rank()].average() - 1.0/(2.0*chi);
178 structureFactors_[itr.
rank()] /= vMonomer;
187 const int nMonomer = system().mixture().nMonomer();
188 for (
int i = 0; i < nMonomer; ++i) {
189 system().domain().fft().forwardTransform(system().w().rgrid()[i],
193 std::map<double, double> SMap;
195 int qListcapacity = (int)qList_.capacity();
197 UTIL_CHECK(qListcapacity == structureFactors_.capacity());
198 for (
int i = 0; i < qListcapacity; ++i) {
200 s = structureFactors_[i];
206 for (
auto& i : SMap) {
208 double sum = i.second;
209 int count = std::count(qList_.begin(), qList_.end(), q);
210 i.second = sum / count;
214 double tolerance = 1e-5;
215 auto it = SMap.begin();
216 double currentq = it->first;
217 double sumS = it->second;
219 for (++it; it != SMap.end(); ++it) {
220 double key = it->first;
221 double s = it->second;
222 if (std::abs(key - currentq) <= tolerance) {
226 averageSMap_[currentq] = sumS / count;
234 averageSMap_[currentq] = sumS / count;
243 computeStructureFactor();
244 averageStructureFactor();
247 system().fileMaster().openOutputFile(outputFileName(), outputFile_);
248 outputFile_ <<
"\t" <<
"q";
249 outputFile_ <<
"\t" <<
"\t" <<
"S(q)/(\u03C1 N)";
250 outputFile_<< std::endl;
251 for (
const auto& i : averageSMap_) {
253 double averageS = i.second;
254 outputFile_ <<
Dbl(q, 18, 8);
255 outputFile_ <<
Dbl(averageS, 18, 8);
256 outputFile_ << std::endl;
An IntVec<D, T> is a D-component vector of elements of integer type T.
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.
IntVec< D > position() const
Get current position in the grid, as integer vector.
virtual double ksq(IntVec< D > const &k) const
Compute square magnitude of reciprocal lattice vector.
Base template for UnitCell<D> classes, D=1, 2 or 3.
Abstract base for periodic output and/or analysis actions.
void setup()
Clear accumulators.
void setClassName(const char *className)
Set class name string.
void readParameters(std::istream &in)
Read parameters from file.
BinaryStructureFactorGrid(Simulator< D > &simulator, System< D > &system)
Constructor.
void sample(long iStep)
Add particles to BinaryStructureFactor accumulators.
void averageStructureFactor()
Compute average S(k) over k of equal magnitude.
void computeStructureFactor()
Compute structure factor.
void output()
Output results to predefined output file.
Field theoretic simulator (base class).
Main class for SCFT or PS-FTS simulation of one system.
Wrapper for a double precision number, for formatted ostream output.
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Periodic fields and crystallography.
PSCF package top-level namespace.
Utility classes for scientific computation.