PSCF v1.3.3
rpg/fts/analyzer/FourthOrderParameter.tpp
1#ifndef RPG_FOURTH_ORDER_PARAMETER_TPP
2#define RPG_FOURTH_ORDER_PARAMETER_TPP
3
4#include "FourthOrderParameter.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/cuda/FFT.h>
12#include <prdc/cuda/RField.h>
13#include <prdc/cuda/resources.h>
14#include <prdc/crystal/shiftToMinimum.h>
15
16#include <pscf/inter/Interaction.h>
17#include <pscf/mesh/MeshIterator.h>
18#include <pscf/math/IntVec.h>
19
20#include <util/misc/ioUtil.h>
21#include <util/format/Int.h>
22#include <util/format/Dbl.h>
23#include <util/global.h>
24
25namespace Pscf {
26namespace Rpg {
27
28 using namespace Util;
29 using namespace Pscf::Prdc;
30
31 /*
32 * Constructor.
33 */
34 template <int D>
38 kSize_(1),
39 isInitialized_(false)
40 { setClassName("FourthOrderParameter"); }
41
42 /*
43 * Destructor.
44 */
45 template <int D>
48
49 /*
50 * FourthOrderParameter setup
51 */
52 template <int D>
54 {
55 // Local copies of data
56 const int nMonomer = system().mixture().nMonomer();
57 IntVec<D> const & dimensions = system().domain().mesh().dimensions();
58
59 // Precondition: Require that the system has two monomer types
60 UTIL_CHECK(nMonomer == 2);
61
63
64 // Compute DFT k-space mesh kMeshDimensions_ and kSize_
65 FFT<D>::computeKMesh(dimensions, kMeshDimensions_, kSize_);
66
67 // Allocate variables
68 if (!isInitialized_){
69 wc0_.allocate(dimensions);
70 wK_.allocate(dimensions);
71 prefactor_.allocate(kMeshDimensions_);
72 VecOp::eqS(prefactor_, 0);
73 }
74
75 isInitialized_ = true;
76
78 }
79
80 template <int D>
82 {
83 UTIL_CHECK(system().w().hasData());
84
85 if (!simulator().hasWc()){
86 simulator().computeWc();
87 }
88
89 RField<D> psi;
90 psi.allocate(kMeshDimensions_);
91
92 // Convert W_(r) to fourier mode W_(k)
93 VecOp::eqV(wc0_, simulator().wc(0));
94 system().domain().fft().forwardTransform(wc0_, wK_);
95
96 // psi = |wK_|^4
97 VecOp::sqSqNormV(psi, wK_);
98
99 // W_(k)^4 * weight factor
100 VecOp::mulEqV(psi, prefactor_);
101
102 // Get sum over all wavevectors
103 HostDArray<cudaReal> psiHost(kSize_);
104 psiHost = psi;
105 FourthOrderParameter_ = 0.0;
106
107 for (int i = 1; i < kSize_; ++i){
108 FourthOrderParameter_ += psiHost[i];
109 }
110
111 FourthOrderParameter_ = std::pow(FourthOrderParameter_, 0.25);
112
113 return FourthOrderParameter_;
114 }
115
116 template <int D>
117 void FourthOrderParameter<D>::outputValue(int step, double value)
118 {
119 if (simulator().hasRamp() && nSamplePerOutput() == 1) {
120 double chi = system().interaction().chi(0,1);
121
122 UTIL_CHECK(outputFile_.is_open());
123 outputFile_ << Int(step);
124 outputFile_ << Dbl(chi);
125 outputFile_ << Dbl(value);
126 outputFile_ << "\n";
127 } else {
129 }
130 }
131
132 template <int D>
134 {
135 IntVec<D> meshDimensions = system().domain().mesh().dimensions();
136 UnitCell<D> const & unitCell = system().domain().unitCell();
137 HostDArray<cudaReal> prefactor_h(kSize_);
138 for (int i = 0; i < kSize_; ++i){
139 prefactor_h[i] = 0;
140 }
141 IntVec<D> G;
142 IntVec<D> Gmin;
143 IntVec<D> nGmin;
144 DArray<IntVec<D>> GminList;
145 GminList.allocate(kSize_);
146 MeshIterator<D> itr(kMeshDimensions_);
147 MeshIterator<D> searchItr(kMeshDimensions_);
148
149 // Calculate GminList
150 for (itr.begin(); !itr.atEnd(); ++itr){
151 G = itr.position();
152 Gmin = shiftToMinimum(G, meshDimensions, unitCell);
153 GminList[itr.rank()] = Gmin;
154 }
155
156 // Compute weight factor for each G wavevector
157 for (itr.begin(); !itr.atEnd(); ++itr){
158 bool inverseFound = false;
159
160 // If the weight factor of the current wavevector has not been assigned
161 if (prefactor_h[itr.rank()] == 0){
162 Gmin = GminList[itr.rank()];
163
164 // Compute inverse of wavevector
165 nGmin.negate(Gmin);
166
167 // Search for inverse of wavevector
168 searchItr = itr;
169 for (; !searchItr.atEnd(); ++searchItr){
170 if (nGmin == GminList[searchItr.rank()]){
171 prefactor_h[itr.rank()] = 1.0/2.0;
172 prefactor_h[searchItr.rank()] = 1.0/2.0;
173 inverseFound = true;
174 }
175 }
176
177 if (inverseFound == false){
178 prefactor_h[itr.rank()] = 1.0;
179 }
180
181 }
182
183 }
184
185 // Copy the weight factor from cpu(host) to gpu(device)
186 prefactor_ = prefactor_h;
187 }
188
189}
190}
191#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)?
IntVec< D > position() const
Get current position in the grid, as integer vector.
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
void allocate(IntVec< D > const &meshDimensions)
Allocate the underlying C array for an FFT grid.
Base template for UnitCell<D> classes, D=1, 2 or 3.
Definition UnitCell.h:56
AverageAnalyzer(Simulator< D > &simulator, System< D > &system)
Constructor.
virtual void setup()
Setup before loop.
virtual void outputValue(int step, double value)
Output a sampled or block average value.
int nSamplePerOutput() const
Get value of nSamplePerOutput.
Simulator< D > & simulator()
Return reference to parent simulator.
System< D > & system()
Return reference to parent system.
virtual double compute()
Compute and return the fourth order parameter.
void setClassName(const char *className)
Set class name string.
FourthOrderParameter(Simulator< D > &simulator, System< D > &system)
Constructor.
virtual void outputValue(int step, double value)
Output a sampled or block average value.
virtual void setup()
Setup before simulation loop.
void computePrefactor()
Compute prefactor for each Fourier wavevector.
Field theoretic simulator (base class).
Main class, representing a complete physical system.
Vec< D, T > & negate(const Vec< D, T > &v)
Return negative of vector v.
Definition Vec.h:520
Dynamically allocatable contiguous array template.
Definition DArray.h:32
void allocate(int capacity)
Allocate the underlying C array.
Definition DArray.h:199
Wrapper for a double precision number, for formatted ostream output.
Definition Dbl.h:40
Wrapper for an int, for formatted ostream output.
Definition Int.h:37
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
void mulEqV(Array< double > &a, Array< double > const &b)
Vector multiplication in-place, a[i] *= b[i].
Definition VecOp.cpp:254
void eqV(Array< double > &a, Array< double > const &b)
Vector assignment, a[i] = b[i].
Definition VecOp.cpp:23
void eqS(Array< double > &a, double b)
Vector assignment, a[i] = b.
Definition VecOp.cpp:36
void sqSqNormV(DeviceArray< cudaReal > &a, DeviceArray< cudaComplex > const &b)
Norm of complex number to the 4th power, a[i] = norm(b[i])^4, kernel wrapper.
Definition VecOpMisc.cu:600
Periodic fields and crystallography.
Definition CField.cpp:11
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.