PSCF v1.3
rpc/fts/analyzer/FourthOrderParameter.tpp
1#ifndef RPC_FOURTH_ORDER_PARAMETER_TPP
2#define RPC_FOURTH_ORDER_PARAMETER_TPP
3
4#include "FourthOrderParameter.h"
5
6#include <rpc/system/System.h>
7#include <rpc/fts/simulator/Simulator.h>
8#include <rpc/solvers/Mixture.h>
9#include <rpc/field/Domain.h>
10
11#include <prdc/cpu/RField.h>
12#include <prdc/cpu/FFT.h>
13#include <prdc/crystal/shiftToMinimum.h>
14
15#include <pscf/inter/Interaction.h>
16#include <pscf/mesh/MeshIterator.h>
17#include <pscf/math/IntVec.h>
18
19#include <util/containers/DArray.h>
20#include <util/param/ParamComposite.h>
21#include <util/misc/FileMaster.h>
22#include <util/misc/ioUtil.h>
23#include <util/format/Int.h>
24#include <util/format/Dbl.h>
25#include <util/global.h>
26
27#include <iostream>
28#include <complex>
29#include <vector>
30#include <numeric>
31#include <cmath>
32#include <set>
33
34namespace Pscf {
35namespace Rpc {
36
37 using namespace Util;
38 using namespace Pscf::Prdc;
39
40 /*
41 * Constructor.
42 */
43 template <int D>
47 kSize_(1),
48 isInitialized_(false)
49 { setClassName("FourthOrderParameter"); }
50
51 /*
52 * Destructor.
53 */
54 template <int D>
57
58 /*
59 * FourthOrderParameter setup
60 */
61 template <int D>
63 {
65
66 // Precondition: Require that the system has two monomer types
67 const int nMonomer = system().mixture().nMonomer();
68 UTIL_CHECK(nMonomer == 2);
69
70 IntVec<D> const & dimensions = system().domain().mesh().dimensions();
71
72 FFT<D>::computeKMesh(dimensions, kMeshDimensions_, kSize_);
73
74 // Allocate variables
75 if (!isInitialized_){
76 wK_.allocate(dimensions);
77 prefactor_.allocate(kSize_);
78 for (int i = 0; i < kSize_; ++i){
79 prefactor_[i] = 0.0;
80 }
81 }
82
83 isInitialized_ = true;
84
86 }
87
88 template <int D>
90 {
91 UTIL_CHECK(system().w().hasData());
92
93 if (!simulator().hasWc()){
94 simulator().computeWc();
95 }
96
98 itr.setDimensions(kMeshDimensions_);
99 std::vector<double> psi(kSize_);
100
101 // Conver W_(r) to fourier mode W_(k)
102 system().domain().fft().forwardTransform(simulator().wc(0), wK_);
103
104 for (itr.begin(); !itr.atEnd(); ++itr) {
105 std::complex<double> wK(wK_[itr.rank()][0], wK_[itr.rank()][1]);
106 psi[itr.rank()] = std::norm(wK) * std::norm(wK);
107 psi[itr.rank()] *= prefactor_[itr.rank()];
108 }
109
110 FourthOrderParameter_ = 0.0;
111
112 // Get sum over all wavevectors
113 for (int i = 1; i < kSize_; ++i){
114 FourthOrderParameter_ += psi[i];
115 }
116
117 FourthOrderParameter_ = std::pow(FourthOrderParameter_, 0.25);
118
119 return FourthOrderParameter_;
120
121 #if 0
122 // Debugging output
123 IntVec<D> meshDimensions = system().domain().mesh().dimensions();
124 UnitCell<D> const & unitCell = system().domain().unitCell();
125 IntVec<D> G;
126 IntVec<D> Gmin;
127 IntVec<D> nGmin;
128 double kSq;
129 std::vector<double> k(kSize_);
130
131 // Calculate GminList
132 for (itr.begin(); !itr.atEnd(); ++itr){
133 G = itr.position();
134 Gmin = shiftToMinimum(G, meshDimensions, unitCell);
135 kSq = unitCell.ksq(Gmin);
136 k[itr.rank()] = kSq;
137 }
138
139 auto maxIt = std::max_element(psi.begin(), psi.end());
140
141 // Calculate the index of the maximum element
142 size_t maxIndex = std::distance(psi.begin(), maxIt);
143 double kmax = k[maxIndex];
144
145 Log::file() << std::endl;
146 for (itr.begin(); !itr.atEnd(); ++itr){
147 if (k[itr.rank()] == kmax){
148 G = itr.position();
149 Gmin = shiftToMinimum(G, meshDimensions, unitCell);
150 Log::file() << "ksq: " << k[itr.rank()] << std::endl;
151 Log::file() << " G: " << G<< std::endl;
152 Log::file() << " Gmin: " << Gmin<< std::endl;
153 Log::file() << " prefactor: " << prefactor_[itr.rank()]<< std::endl;
154 Log::file() << " psi: " << psi[itr.rank()]<< std::endl;
155 }
156
157 }
158 #endif
159
160 }
161
162 template <int D>
163 void FourthOrderParameter<D>::outputValue(int step, double value)
164 {
165 if (simulator().hasRamp() && nSamplePerOutput() == 1) {
166 double chi= system().interaction().chi(0,1);
167
168 UTIL_CHECK(outputFile_.is_open());
169 outputFile_ << Int(step);
170 outputFile_ << Dbl(chi);
171 outputFile_ << Dbl(value);
172 outputFile_ << "\n";
173 } else {
175 }
176 }
177
178 template <int D>
180 {
181 IntVec<D> meshDimensions = system().domain().mesh().dimensions();
182 UnitCell<D> const & unitCell = system().domain().unitCell();
183 IntVec<D> G;
184 IntVec<D> Gmin;
185 IntVec<D> nGmin;
186 DArray<IntVec<D>> GminList;
187 GminList.allocate(kSize_);
188 MeshIterator<D> itr(kMeshDimensions_);
189 MeshIterator<D> searchItr(kMeshDimensions_);
190
191 // Calculate GminList
192 for (itr.begin(); !itr.atEnd(); ++itr){
193 G = itr.position();
194 Gmin = shiftToMinimum(G, meshDimensions, unitCell);
195 GminList[itr.rank()] = Gmin;
196 }
197
198 // Compute prefactor for each G wavevector
199 for (itr.begin(); !itr.atEnd(); ++itr){
200 bool inverseFound = false;
201
202 // If prefactor of current wavevector has not been assigned
203 if (prefactor_[itr.rank()] == 0){
204 Gmin = GminList[itr.rank()];
205
206 // Compute inverse of wavevector
207 nGmin.negate(Gmin);
208
209 // Search for inverse of wavevector
210 searchItr = itr;
211 for (; !searchItr.atEnd(); ++searchItr){
212 if (nGmin == GminList[searchItr.rank()]){
213 prefactor_[itr.rank()] = 1.0/2.0;
214 prefactor_[searchItr.rank()] = 1.0/2.0;
215 inverseFound = true;
216 }
217 }
218
219 if (inverseFound == false){
220 prefactor_[itr.rank()] = 1.0;
221 }
222
223 }
224
225 }
226 }
227
228}
229}
230#endif
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.
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
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.
Definition UnitCell.h:56
AverageAnalyzer(Simulator< D > &simulator, System< D > &system)
Constructor.
virtual void setup()
Setup before loop.
int nSamplePerOutput() const
Get value of nSamplePerOutput.
virtual void outputValue(int step, double value)
Output a sampled or block average value.
Simulator< D > & simulator()
Return reference to parent simulator.
System< D > & system()
Return reference to parent system.
void setClassName(const char *className)
Set class name string.
FourthOrderParameter(Simulator< D > &simulator, System< D > &system)
Constructor.
void computePrefactor()
Compute prefactor for each Fourier wavevector.
virtual void setup()
Setup before simulation loop.
virtual void outputValue(int step, double value)
Output a sampled or block average value.
virtual double compute()
Compute and return the derivative of H w/ respect to chi.
Field theoretic simulator (base class).
Main class, representing one complete 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
static std::ostream & file()
Get log ostream by reference.
Definition Log.cpp:59
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
Periodic fields and crystallography.
Definition CField.cpp:11
Real periodic fields, SCFT and PS-FTS (CPU).
Definition param_pc.dox:2
PSCF package top-level namespace.
Definition param_pc.dox:1