PSCF v1.3
rpg/fts/compressor/IntraCorrelation.tpp
1#ifndef RPG_INTRACORRELATION_TPP
2#define RPG_INTRACORRELATION_TPP
3
4/*
5* PSCF - Polymer Self-Consistent Field
6*
7* Copyright 2015 - 2025, The Regents of the University of Minnesota
8* Distributed under the terms of the GNU General Public License.
9*/
10
11#include "IntraCorrelation.h"
12
13#include <rpg/system/System.h>
14#include <rpg/field/Domain.h>
15#include <rpg/solvers/Mixture.h>
16
17#include <prdc/cuda/FFT.h>
18#include <prdc/crystal/UnitCell.h>
19#include <prdc/crystal/shiftToMinimum.h>
20
21#include <pscf/mesh/MeshIterator.h>
22#include <pscf/chem/Debye.h>
23#include <pscf/chem/EdgeIterator.h>
24#include <pscf/chem/PolymerType.h>
25#include <pscf/cuda/HostDArray.h>
26
27#include <util/global.h>
28
29namespace Pscf {
30namespace Rpg{
31
32 using namespace Util;
33
34 // Constructor
35 template <int D>
37 : systemPtr_(&system),
38 kSize_(1)
39 { setClassName("IntraCorrelation"); }
40
41 // Destructor
42 template <int D>
45
46 template<int D>
47 void
49 {
50 // Local copies of system properties
51 Mixture<D> const & mixture = system().mixture();
52 UnitCell<D> const & unitCell = system().domain().unitCell();
53 IntVec<D> const & dimensions = system().domain().mesh().dimensions();
54 const int nPolymer = mixture.nPolymer();
55 const int nSolvent = mixture.nSolvent();
56 const double vMonomer = mixture.vMonomer();
57
58 // Compute k-space mesh dimensions kMeshDimensions_ & size kSize_
59 FFT<D>::computeKMesh(dimensions, kMeshDimensions_, kSize_);
60 UTIL_CHECK(correlations.capacity() == kSize_);
61
62 // Allocate Gsq (k-space array of square wavenumber values)
64 Gsq.allocate(kSize_);
65
66 // Compute Gsq
67 IntVec<D> G, Gmin;
68 MeshIterator<D> iter;
69 iter.setDimensions(kMeshDimensions_);
70 for (iter.begin(); !iter.atEnd(); ++iter) {
71 G = iter.position();
72 Gmin = shiftToMinimum(G, dimensions, unitCell);
73 Gsq[iter.rank()] = unitCell.ksq(Gmin);
74 }
75
76 // Allocate local correlations_h array
77 HostDArray<cudaReal> correlations_h;
78 correlations_h.allocate(kSize_);
79
80 // Initialize correlations_h to zero
81 for (int i = 0; i < correlations_h.capacity(); ++i){
82 correlations_h[i] = 0.0;
83 }
84
85 double phi, cPolymer, polymerLength, rsqAB;
86 double length, lengthA, lengthB, lengthC, ksq;
87 double kuhn, kuhnA, kuhnB, kuhnC, eA, eB;
88 int monomerId, monomerIdA, monomerIdB, monomerIdC;
89 int rank;
90
91 // Loop over polymer species
92 for (int i = 0; i < nPolymer; i++){
93
94 // Local copies of polymer properties
95 PolymerSpecies const & polymer = mixture.polymerSpecies(i);
96 const int nBlock = polymer.nBlock();
97 phi = polymer.phi();
98
99 // Compute polymerLength (sum of lengths of all blocks)
100 polymerLength = 0.0;
101 for (int j = 0; j < nBlock; j++) {
103 length = polymer.edge(j).length();
104 } else {
105 length = (double) polymer.edge(j).nBead();
106 }
107 polymerLength += length;
108 }
109
110 // Compute cPolymer (polymer number concentration)
111 cPolymer = phi/(polymerLength*vMonomer);
112
113 // Compute diagonal (j = k) contributions
114 for (int j = 0; j < nBlock; j++) {
115
116 monomerId = polymer.edge(j).monomerId();
117 kuhn = mixture.monomer(monomerId).kuhn();
118
119 // Loop over ksq to increment correlations_h
121 length = polymer.edge(j).length();
122 for (iter.begin(); !iter.atEnd(); ++iter) {
123 rank = iter.rank();
124 ksq = Gsq[rank];
125 correlations_h[rank] +=
126 cPolymer * Debye::dt(ksq, length, kuhn);
127 }
128 } else {
129 length = (double) polymer.edge(j).nBead();
130 for (iter.begin(); !iter.atEnd(); ++iter) {
131 rank = iter.rank();
132 ksq = Gsq[rank];
133 correlations_h[rank] +=
134 cPolymer * Debye::db(ksq, length, kuhn);
135 }
136 }
137
138 }
139
140 // Compute off-diagonal contributions
141 if (nBlock > 1) {
142 EdgeIterator edgeItr(polymer);
143
144 // Outer loop over blocks
145 for (int ia = 1; ia < nBlock; ++ia) {
146
147 // Block A properties
148 Edge const & edgeA = polymer.edge(ia);
150 lengthA = edgeA.length();
151 } else {
152 lengthA = (double) edgeA.nBead();
153 }
154 monomerIdA = edgeA.monomerId();
155 kuhnA = mixture.monomer(monomerIdA).kuhn();
156
157 // Inner loop over blocks
158 for (int ib = 0; ib < ia; ++ib) {
159
160 // Block B properties
161 Edge const & edgeB = polymer.edge(ib);
163 lengthB = edgeB.length();
164 } else {
165 lengthB = (double) edgeB.nBead();
166 }
167 monomerIdB = edgeB.monomerId();
168 kuhnB = mixture.monomer(monomerIdB).kuhn();
169
170 // Initialize rsqAB
172 rsqAB = 0.0;
173 } else {
174 rsqAB = 0.5*(kuhnA*kuhnA + kuhnB*kuhnB);
175 }
176
177 // Iterate over intermediate blocks, if any
178 int edgeId;
179 edgeItr.begin(ia, ib);
180 while (edgeItr.notEnd()) {
181 edgeId = edgeItr.currentEdgeId();
182 Edge const & edgeC = polymer.edge(edgeId);
183 monomerIdC = edgeC.monomerId();
184 kuhnC = mixture.monomer(monomerIdC).kuhn();
185 if (edgeId != ia && edgeId != ib) {
187 lengthC = edgeC.length();
188 } else {
189 lengthC = double(edgeC.nBead());
190 }
191 rsqAB += lengthC * kuhnC * kuhnC;
192 }
193 ++edgeItr;
194 }
195
196 // Loop over ksq to increment intra-block correlations
197 double x;
198 double prefactor = 2.0*cPolymer;
200 for (iter.begin(); !iter.atEnd(); ++iter) {
201 rank = iter.rank();
202 ksq = Gsq[rank];
203 x = std::exp( -rsqAB * ksq / 6.0);
204 eA = Debye::et(ksq, lengthA, kuhnA);
205 eB = Debye::et(ksq, lengthB, kuhnB);
206 correlations_h[rank] += prefactor * x * eA * eB;
207 }
208 } else {
209 for (iter.begin(); !iter.atEnd(); ++iter) {
210 rank = iter.rank();
211 ksq = Gsq[rank];
212 x = std::exp( -rsqAB * ksq / 6.0);
213 eA = Debye::eb(ksq, lengthA, kuhnA);
214 eB = Debye::eb(ksq, lengthB, kuhnB);
215 correlations_h[rank] += prefactor * x * eA * eB;
216 }
217 }
218
219 } // loop: block ib
220 } // loop: block ia
221 } // if (nBlock > 1) - off diagonal elements
222
223 } // loop over polymer species
224
225 // Loop over solvent species (if any)
226 if (nSolvent > 0) {
227 double size, dcorr;
228 for (int i = 0; i < nSolvent; i++){
229 Solvent<D> const & solvent = mixture.solvent(i);
230 phi = solvent.phi();
231 size = solvent.size();
232 dcorr = phi*size/vMonomer;
233 for (iter.begin(); !iter.atEnd(); ++iter) {
234 correlations_h[iter.rank()] += dcorr;
235 }
236 }
237 }
238
239 // Copy local array correlations_h to device (gpu) memory
240 correlations = correlations_h;
241
242 }
243
244}
245}
246#endif
Edge iterator for graph associated with a polymer.
int currentEdgeId() const
Get index of the current edge.
bool notEnd() const
Return true iff currentId != targetId.
void begin(int sourceId, int targetId)
Initialize iterator.
Descriptor for a block within a block polymer.
Definition Edge.h:59
int nBead() const
Get the number of beads in this block, in the bead model.
Definition Edge.h:302
int monomerId() const
Get the monomer type id for this block.
Definition Edge.h:284
double length() const
Get the length of this block, in the thread model.
Definition Edge.h:311
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.
IntVec< D > position() const
Get current position in the grid, as integer vector.
double kuhn() const
Statistical segment length (random walk step size).
Definition Monomer.h:131
Descriptor for a linear or acyclic branched block polymer.
virtual Edge & edge(int id)=0
Get a specified Edge (block descriptor) by non-const reference.
int nBlock() const
Number of blocks.
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
SolventT & solvent(int id)
Get a solvent solver object.
PolymerSpecies const & polymerSpecies(int id) const final
Get a PolymerSpecies descriptor by const reference.
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
System< D > & system()
Return reference to parent system.
void computeIntraCorrelations(RField< D > &correlations)
Compute and return intramolecular correlations.
IntraCorrelation(System< D > &system)
Constructor.
Solver and descriptor for a mixture of polymers and solvents.
int nPolymer() const
Get number of polymer species.
Monomer const & monomer(int id) const
Get a Monomer type descriptor by const reference.
int nSolvent() const
Get number of solvent (point particle) species.
double vMonomer() const
Get monomer reference volume (set to 1.0 by default).
Solver and descriptor for a solvent species.
double phi() const
Get the overall volume fraction for this species.
Definition Species.h:149
double size() const
Get the size (number of monomers) in this solvent.
Main class, representing one complete system.
double phi() const
Get the overall volume fraction for this species.
Definition Species.h:149
int capacity() const
Return allocated size.
Definition Array.h:159
Dynamically allocatable contiguous array template.
Definition DArray.h:32
void allocate(int capacity)
Allocate the underlying C array.
Definition DArray.h:199
void setClassName(const char *className)
Set class name string.
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
double dt(double ksq, double length, double kuhn)
Compute and return intrablock correlation function (thread model)
Definition Debye.cpp:17
double et(double ksq, double length, double kuhn)
Compute and return one-sided factor for one block (thread model).
Definition Debye.cpp:53
double eb(double ksq, double nBead, double kuhn)
Compute and return one-sided factor for one block (thread model).
Definition Debye.cpp:69
double db(double ksq, double nBead, double kuhn)
Compute and return an intrablock correlation function (bead model)
Definition Debye.cpp:33
bool isThread()
Is the thread model in use ?
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.
Definition param_pc.dox:1