1#ifndef RP_BINARY_STRUCTURE_FACTOR_TPP
2#define RP_BINARY_STRUCTURE_FACTOR_TPP
4#include "BinaryStructureFactor.h"
6#include <pscf/interaction/Interaction.h>
7#include <pscf/mesh/MeshIterator.h>
8#include <pscf/mesh/Mesh.h>
9#include <pscf/math/IntVec.h>
11#include <util/param/ParamComposite.h>
12#include <util/containers/Array.h>
13#include <util/misc/FileMaster.h>
14#include <util/format/Dbl.h>
15#include <util/format/Int.h>
30 template <
int D,
class T>
32 typename T::Simulator& simulator,
33 typename T::System& system)
34 : AnalyzerT(simulator, system),
38 writeWaveData_(false),
42 AnalyzerT::setFileMaster(system.fileMaster());
48 template <
int D,
class T>
52 UTIL_CHECK(system().mixture().nMonomer() == 2);
54 AnalyzerT::readInterval(in);
55 AnalyzerT::readOutputFileName(in);
56 writeWaveData_ =
false;
58 isInitialized_ =
true;
64 template <
int D,
class T>
70 Mesh<D> const & mesh = system().domain().mesh();
72 FFTT::computeKMesh(rMeshDimensions, kMeshDimensions_, nWave_);
75 if (!wm_.isAllocated()){
79 wm_.allocate(rMeshDimensions);
80 wk_.allocate(rMeshDimensions);
81 waveBunchIds_.allocate(nWave_);
82 waveWeights_.allocate(nWave_);
85 waveAccumulators_.allocate(nWave_);
93 UTIL_CHECK(waveAccumulators_.capacity() == nWave_);
100 template <
int D,
class T>
109 typename T::WaveList& waveList = system().waveList();
111 if (!waveList.hasKSq()) {
112 waveList.computeKSq();
115 waveList.sortWaves();
116 nBunch_ = waveList.nBunch();
120 if (bunchAccumulators_.isAllocated()) {
121 int const m = bunchAccumulators_.capacity();
122 UTIL_CHECK(bunchWavenumbers_.capacity() == m);
125 bunchAccumulators_.deallocate();
126 bunchWavenumbers_.deallocate();
127 bunchValues_.deallocate();
130 if (!bunchAccumulators_.isAllocated()) {
133 bunchAccumulators_.allocate(nBunch_);
134 bunchWavenumbers_.allocate(nBunch_);
135 bunchValues_.allocate(nBunch_);
137 int m = bunchAccumulators_.capacity();
139 UTIL_CHECK(bunchWavenumbers_.capacity() == m);
143 for (
int ib = 0; ib < m; ++ib) {
144 bunchAccumulators_[ib].clear();
145 bunchWavenumbers_[ib] = 0.0;
146 bunchValues_[ib] = 0.0;
148 for (
int iw = 0; iw < nWave_; ++iw) {
149 waveBunchIds_[iw] = -1;
150 waveWeights_[iw] = 0.0;
152 if (writeWaveData_) {
153 for (
int iw = 0; iw < nWave_; ++iw) {
154 waveAccumulators_[iw].clear();
165 double wavenumberSq, newWavenumber, oldWavenumber;
166 double count,
sum, tot;
167 int begin, end, k, iw;
169 for (
int ib = 0; ib < nBunch_; ++ib) {
170 begin = bunches[ib][0];
171 end = bunches[ib][1];
174 iw = sortedIds[begin];
175 wavenumberSq = kSq[iw];
177 newWavenumber = std::sqrt(wavenumberSq);
178 bunchWavenumbers_[ib] = newWavenumber;
180 UTIL_CHECK(newWavenumber - oldWavenumber > 1.0E-8);
182 oldWavenumber = newWavenumber;
186 for (k = begin; k < end; ++k) {
190 UTIL_CHECK(std::abs(waveWeights_[iw]) < 1.0E-8);
191 waveBunchIds_[iw] = ib;
198 waveWeights_[iw] = count;
200 UTIL_CHECK(std::abs(kSq[iw] - wavenumberSq) < 1.0E-8);
205 for (k = begin; k < end; ++k) {
207 waveWeights_[iw] /=
sum;
208 tot += waveWeights_[iw];
221 template <
int D,
class T>
230 typename T::RField
const & wa = system().w().rgrid(0);
231 typename T::RField
const & wb = system().w().rgrid(1);
236 system().domain().fft().forwardTransform(wm_,
wk_);
242 template <
int D,
class T>
250 int m = bunchAccumulators_.capacity();
252 UTIL_CHECK(bunchWavenumbers_.capacity() >= m);
254 UTIL_CHECK(waveBunchIds_.capacity() == nWave_);
255 UTIL_CHECK(waveWeights_.capacity() == nWave_);
259 for (
int ib = 0; ib < nBunch_; ++ib) {
260 bunchValues_[ib] = 0.0;
264 double const vSystem = system().domain().unitCell().volume();
265 double const vMonomer = system().mixture().vMonomer();
266 double const chi = system().interaction().chi(0,1);
267 double a_ = vSystem / (chi * chi * vMonomer * vMonomer);
268 double b_ = 0.5 / (chi * vMonomer);
273 for (
int iw = 0; iw < nWave_; ++iw) {
274 value = a_ *
absSq( wk[iw] );
276 if (writeWaveData_) {
277 waveAccumulators_[iw].sample(value);
279 ib = waveBunchIds_[iw];
280 bunchValues_[ib] += waveWeights_[iw] * value;
284 for (ib = 0; ib < nBunch_; ++ib) {
285 bunchAccumulators_[ib].sample(bunchValues_[ib]);
293 template <
int D,
class T>
296 std::string filename;
300 filename = AnalyzerT::outputFileName();
301 if (writeWaveData_) {
304 AnalyzerT::fileMaster().openOutputFile(filename, file);
305 for (
int i = 0; i < nBunch_; ++i) {
306 file <<
Dbl(bunchWavenumbers_[i], 18, 8);
307 file <<
Dbl(bunchAccumulators_[i].average(), 18, 8);
313 if (writeWaveData_) {
314 filename = AnalyzerT::outputFileName();
316 AnalyzerT::fileMaster().openOutputFile(filename, file);
323 for (j = 0; j < D; ++j) {
324 file <<
Int(p[j], 5);
326 file <<
Dbl(waveAccumulators_[iw].average(), 18, 8);
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)?
IntVec< D > position() const
Get current position in the grid, as integer vector.
Description of a regular grid of points in a periodic domain.
IntVec< D > dimensions() const
Get an IntVec<D> of the grid dimensions.
int size() const
Get total number of grid points.
void readParameters(std::istream &in) override
Read parameters from file.
void output() override
Output results to predefined output file.
BinaryStructureFactor(typename T::Simulator &simulator, typename T::System &system)
Constructor.
void allocate()
Allocate member arrays with dimensions that depend only on mesh.
void computeS(Array< typename T::Complex > const &wk)
Complete calculation of current structure factors.
Types< D >::RFieldDft wk_
void findWaveBunches(Array< double > const &kSq, Array< bool > const &implicit)
Allocate and initialize data structures involving wave bunches.
void computeW()
Compute member variables wm_ and wk_.
Array container class template.
int capacity() const
Return allocated size.
Wrapper for a double precision number, for formatted ostream output.
An automatically growable array, analogous to a std::vector.
int size() const
Return logical size of this array (i.e., current number of elements).
Wrapper for an int, for formatted ostream output.
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.
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
double absSq(fftw_complex const &a)
Return square of absolute magnitude of an fftw_complex number.
double sum(Array< double > const &in)
Compute sum of array elements (real).
void mulEqS(Array< double > &a, double b)
Vector-scalar in-place multiplication, a[i] *= b (real).
void subVV(Array< double > &a, Array< double > const &b, Array< double > const &c)
Vector-vector subtraction, a[i] = b[i] - c[i] (real)
Periodic fields and crystallography.
Class templates for real-valued periodic fields.
PSCF package top-level namespace.