PSCF v1.3.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#include <rpg/solvers/Solvent.h>
17#include <rpg/field/Domain.h>
18
19#include <prdc/cuda/FFT.h>
20#include <prdc/cuda/RField.h>
21#include <prdc/crystal/shiftToMinimum.h>
22#include <prdc/crystal/UnitCell.h>
23
24#include <pscf/mesh/Mesh.h>
25#include <pscf/mesh/MeshIterator.h>
26#include <pscf/chem/PolymerSpecies.h>
27#include <pscf/chem/SolventSpecies.h>
28#include <pscf/chem/Edge.h>
29#include <pscf/chem/Debye.h>
30#include <pscf/chem/EdgeIterator.h>
31//#include <pscf/chem/PolymerType.h>
32#include <pscf/cuda/HostDArray.h>
33
34#include <util/global.h>
35
36namespace Pscf {
37namespace Rpg{
38
39 using namespace Util;
40
41 // Constructor
42 template <int D>
44 : systemPtr_(&system),
45 kSize_(1)
46 { setClassName("IntraCorrelation"); }
47
48 // Destructor
49 template <int D>
52
53 template<int D>
54 void
56 {
57 // Local copies of system properties
58 Mixture<D> const & mixture = system().mixture();
59 UnitCell<D> const & unitCell = system().domain().unitCell();
60 IntVec<D> const & dimensions = system().domain().mesh().dimensions();
61 const int nPolymer = mixture.nPolymer();
62 const int nSolvent = mixture.nSolvent();
63 const double vMonomer = mixture.vMonomer();
64
65 // Compute k-space mesh dimensions kMeshDimensions_ & size kSize_
66 FFT<D>::computeKMesh(dimensions, kMeshDimensions_, kSize_);
67 UTIL_CHECK(correlations.capacity() == kSize_);
68
69 // Allocate Gsq (k-space array of square wavenumber values)
71 Gsq.allocate(kSize_);
72
73 // Compute Gsq
74 IntVec<D> G, Gmin;
75 MeshIterator<D> iter;
76 iter.setDimensions(kMeshDimensions_);
77 for (iter.begin(); !iter.atEnd(); ++iter) {
78 G = iter.position();
79 Gmin = shiftToMinimum(G, dimensions, unitCell);
80 Gsq[iter.rank()] = unitCell.ksq(Gmin);
81 }
82
83 // Allocate local correlations_h array
84 HostDArray<cudaReal> correlations_h;
85 correlations_h.allocate(kSize_);
86
87 // Initialize correlations_h to zero
88 for (int i = 0; i < correlations_h.capacity(); ++i){
89 correlations_h[i] = 0.0;
90 }
91
92 double phi, cPolymer, polymerLength, rsqAB;
93 double length, lengthA, lengthB, lengthC, ksq;
94 double kuhn, kuhnA, kuhnB, kuhnC, eA, eB;
95 int monomerId, monomerIdA, monomerIdB, monomerIdC;
96 int rank;
97
98 // Loop over polymer species
99 for (int i = 0; i < nPolymer; i++){
100
101 // Local copies of polymer properties
102 PolymerSpecies const & polymer = mixture.polymerSpecies(i);
103 const int nBlock = polymer.nBlock();
104 phi = polymer.phi();
105
106 // Compute polymerLength (sum of lengths of all blocks)
107 polymerLength = 0.0;
108 for (int j = 0; j < nBlock; j++) {
110 length = polymer.edge(j).length();
111 } else {
112 length = (double) polymer.edge(j).nBead();
113 }
114 polymerLength += length;
115 }
116
117 // Compute cPolymer (polymer number concentration)
118 cPolymer = phi/(polymerLength*vMonomer);
119
120 // Compute diagonal (j = k) contributions
121 for (int j = 0; j < nBlock; j++) {
122
123 monomerId = polymer.edge(j).monomerId();
124 kuhn = mixture.monomer(monomerId).kuhn();
125
126 // Loop over ksq to increment correlations_h
128 length = polymer.edge(j).length();
129 for (iter.begin(); !iter.atEnd(); ++iter) {
130 rank = iter.rank();
131 ksq = Gsq[rank];
132 correlations_h[rank] +=
133 cPolymer * Debye::dt(ksq, length, kuhn);
134 }
135 } else {
136 length = (double) polymer.edge(j).nBead();
137 for (iter.begin(); !iter.atEnd(); ++iter) {
138 rank = iter.rank();
139 ksq = Gsq[rank];
140 correlations_h[rank] +=
141 cPolymer * Debye::db(ksq, length, kuhn);
142 }
143 }
144
145 }
146
147 // Compute off-diagonal contributions
148 if (nBlock > 1) {
149 EdgeIterator edgeItr(polymer);
150
151 // Outer loop over blocks
152 for (int ia = 1; ia < nBlock; ++ia) {
153
154 // Block A properties
155 Edge const & edgeA = polymer.edge(ia);
157 lengthA = edgeA.length();
158 } else {
159 lengthA = (double) edgeA.nBead();
160 }
161 monomerIdA = edgeA.monomerId();
162 kuhnA = mixture.monomer(monomerIdA).kuhn();
163
164 // Inner loop over blocks
165 for (int ib = 0; ib < ia; ++ib) {
166
167 // Block B properties
168 Edge const & edgeB = polymer.edge(ib);
170 lengthB = edgeB.length();
171 } else {
172 lengthB = (double) edgeB.nBead();
173 }
174 monomerIdB = edgeB.monomerId();
175 kuhnB = mixture.monomer(monomerIdB).kuhn();
176
177 // Initialize rsqAB
179 rsqAB = 0.0;
180 } else {
181 rsqAB = 0.5*(kuhnA*kuhnA + kuhnB*kuhnB);
182 }
183
184 // Iterate over intermediate blocks, if any
185 int edgeId;
186 edgeItr.begin(ia, ib);
187 while (edgeItr.notEnd()) {
188 edgeId = edgeItr.currentEdgeId();
189 Edge const & edgeC = polymer.edge(edgeId);
190 monomerIdC = edgeC.monomerId();
191 kuhnC = mixture.monomer(monomerIdC).kuhn();
192 if (edgeId != ia && edgeId != ib) {
194 lengthC = edgeC.length();
195 } else {
196 lengthC = double(edgeC.nBead());
197 }
198 rsqAB += lengthC * kuhnC * kuhnC;
199 }
200 ++edgeItr;
201 }
202
203 // Loop over ksq to increment intra-block correlations
204 double x;
205 double prefactor = 2.0*cPolymer;
207 for (iter.begin(); !iter.atEnd(); ++iter) {
208 rank = iter.rank();
209 ksq = Gsq[rank];
210 x = std::exp( -rsqAB * ksq / 6.0);
211 eA = Debye::et(ksq, lengthA, kuhnA);
212 eB = Debye::et(ksq, lengthB, kuhnB);
213 correlations_h[rank] += prefactor * x * eA * eB;
214 }
215 } else {
216 for (iter.begin(); !iter.atEnd(); ++iter) {
217 rank = iter.rank();
218 ksq = Gsq[rank];
219 x = std::exp( -rsqAB * ksq / 6.0);
220 eA = Debye::eb(ksq, lengthA, kuhnA);
221 eB = Debye::eb(ksq, lengthB, kuhnB);
222 correlations_h[rank] += prefactor * x * eA * eB;
223 }
224 }
225
226 } // loop: block ib
227 } // loop: block ia
228 } // if (nBlock > 1) - off diagonal elements
229
230 } // loop over polymer species
231
232 // Loop over solvent species (if any)
233 if (nSolvent > 0) {
234 double size, dcorr;
235 for (int i = 0; i < nSolvent; i++){
236 SolventSpecies const & solvent = mixture.solventSpecies(i);
237 phi = solvent.phi();
238 size = solvent.size();
239 dcorr = phi*size/vMonomer;
240 for (iter.begin(); !iter.atEnd(); ++iter) {
241 correlations_h[iter.rank()] += dcorr;
242 }
243 }
244 }
245
246 // Copy local array correlations_h to device (gpu) memory
247 correlations = correlations_h;
248
249 }
250
251}
252}
253#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
PolymerSpecies const & polymerSpecies(int id) const final
Get a PolymerSpecies descriptor by const reference.
SolventSpecies const & solventSpecies(int id) const final
Set a SolventSpecies descriptor object 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).
Main class, representing a complete physical system.
Descriptor for a solvent species.
double size() const
Get the size (number of monomers) in this solvent.
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.