PSCF v1.3.3
rpc/fts/compressor/IntraCorrelation.tpp
1#ifndef RPC_INTRACORRELATION_TPP
2#define RPC_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 <rpc/system/System.h>
14#include <rpc/solvers/Mixture.h>
15#include <rpc/solvers/Polymer.h>
16#include <rpc/solvers/Solvent.h>
17#include <rpc/field/Domain.h>
18
19#include <prdc/cpu/FFT.h>
20#include <prdc/cpu/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
32#include <util/global.h>
33
34namespace Pscf {
35namespace Rpc{
36
37 using namespace Util;
38
39 /*
40 * Constructor.
41 */
42 template <int D>
44 : systemPtr_(&system),
45 kSize_(1)
46 {}
47
48 /*
49 * Destructor.
50 */
51 template <int D>
54
55 /*
56 * Compute k-space array of intramolecular correlation functions.
57 */
58 template<int D>
59 void
61 {
62 // Local copies of system properties
63 Mixture<D> const & mixture = system().mixture();
64 UnitCell<D> const & unitCell = system().domain().unitCell();
65 IntVec<D> const & dimensions = system().domain().mesh().dimensions();
66 const int nPolymer = mixture.nPolymer();
67 const int nSolvent = mixture.nSolvent();
68 const double vMonomer = mixture.vMonomer();
69
70 // Compute Fourier space kMeshDimensions_ and kSize_
71 FFT<D>::computeKMesh(dimensions, kMeshDimensions_, kSize_);
72 UTIL_CHECK(correlations.capacity() == kSize_);
73
74 // Allocate Gsq (k-space array of square wavenumber values)
76 Gsq.allocate(kSize_);
77
78 // Compute Gsq
79 IntVec<D> G, Gmin;
80 MeshIterator<D> iter;
81 iter.setDimensions(kMeshDimensions_);
82 for (iter.begin(); !iter.atEnd(); ++iter) {
83 G = iter.position();
84 Gmin = shiftToMinimum(G, dimensions, unitCell);
85 Gsq[iter.rank()] = unitCell.ksq(Gmin);
86 }
87
88 // Initialize correlations to zero
89 for (int i = 0; i < correlations.capacity(); ++i){
90 correlations[i] = 0.0;
91 }
92
93 double phi, cPolymer, polymerLength, rsqAB;
94 double length, lengthA, lengthB, lengthC, ksq;
95 double kuhn, kuhnA, kuhnB, kuhnC, eA, eB;
96 int monomerId, monomerIdA, monomerIdB, monomerIdC;
97 int rank;
98
99 // Loop over polymer species
100 for (int i = 0; i < nPolymer; i++){
101
102 // Local copies of polymer properties
103 PolymerSpecies const & polymer = mixture.polymerSpecies(i);
104 const int nBlock = polymer.nBlock();
105 phi = polymer.phi();
106
107 // Compute polymerLength (sum of lengths of all blocks)
108 polymerLength = 0.0;
109 for (int j = 0; j < nBlock; j++) {
111 length = polymer.edge(j).length();
112 } else {
113 length = (double) polymer.edge(j).nBead();
114 }
115 polymerLength += length;
116 }
117
118 // Compute cPolymer (polymer number concentration)
119 cPolymer = phi/(polymerLength*vMonomer);
120
121 // Compute diagonal (j = k) contributions
122 for (int j = 0; j < nBlock; j++) {
123
124 monomerId = polymer.edge(j).monomerId();
125 kuhn = mixture.monomer(monomerId).kuhn();
126
127 // Loop over ksq to increment correlations
129 length = polymer.edge(j).length();
130 for (iter.begin(); !iter.atEnd(); ++iter) {
131 rank = iter.rank();
132 ksq = Gsq[rank];
133 correlations[rank] +=
134 cPolymer * Debye::dt(ksq, length, kuhn);
135 }
136 } else {
137 length = (double) polymer.edge(j).nBead();
138 for (iter.begin(); !iter.atEnd(); ++iter) {
139 rank = iter.rank();
140 ksq = Gsq[rank];
141 correlations[rank] +=
142 cPolymer * Debye::db(ksq, length, kuhn);
143 }
144 }
145
146 }
147
148 // Compute off-diagonal contributions
149 if (nBlock > 1) {
150 EdgeIterator edgeItr(polymer);
151
152 // Outer loop over blocks
153 for (int ia = 1; ia < nBlock; ++ia) {
154
155 // Block A properties
156 Edge const & edgeA = polymer.edge(ia);
158 lengthA = edgeA.length();
159 } else {
160 lengthA = (double) edgeA.nBead();
161 }
162 monomerIdA = edgeA.monomerId();
163 kuhnA = mixture.monomer(monomerIdA).kuhn();
164
165 // Inner loop over blocks
166 for (int ib = 0; ib < ia; ++ib) {
167
168 // Block B properties
169 Edge const & edgeB = polymer.edge(ib);
171 lengthB = edgeB.length();
172 } else {
173 lengthB = (double) edgeB.nBead();
174 }
175 monomerIdB = edgeB.monomerId();
176 kuhnB = mixture.monomer(monomerIdB).kuhn();
177
178 // Initialize rsqAB
180 rsqAB = 0.0;
181 } else {
182 rsqAB = 0.5*(kuhnA*kuhnA + kuhnB*kuhnB);
183 }
184
185 // Iterate over intermediate blocks, if any
186 int edgeId;
187 edgeItr.begin(ia, ib);
188 while (edgeItr.notEnd()) {
189 edgeId = edgeItr.currentEdgeId();
190 Edge const & edgeC = polymer.edge(edgeId);
191 monomerIdC = edgeC.monomerId();
192 kuhnC = mixture.monomer(monomerIdC).kuhn();
193 if (edgeId != ia && edgeId != ib) {
195 lengthC = edgeC.length();
196 } else {
197 lengthC = double(edgeC.nBead());
198 }
199 rsqAB += lengthC * kuhnC * kuhnC;
200 }
201 ++edgeItr;
202 }
203
204 // Loop over ksq to increment intra-block correlations
205 double x;
206 double prefactor = 2.0*cPolymer;
208 for (iter.begin(); !iter.atEnd(); ++iter) {
209 rank = iter.rank();
210 ksq = Gsq[rank];
211 x = std::exp( -rsqAB * ksq / 6.0);
212 eA = Debye::et(ksq, lengthA, kuhnA);
213 eB = Debye::et(ksq, lengthB, kuhnB);
214 correlations[rank] += prefactor * x * eA * eB;
215 }
216 } else {
217 for (iter.begin(); !iter.atEnd(); ++iter) {
218 rank = iter.rank();
219 ksq = Gsq[rank];
220 x = std::exp( -rsqAB * ksq / 6.0);
221 eA = Debye::eb(ksq, lengthA, kuhnA);
222 eB = Debye::eb(ksq, lengthB, kuhnB);
223 correlations[rank] += prefactor * x * eA * eB;
224 }
225 }
226
227 } // loop: block ib
228 } // loop: block ia
229 } // if (nBlock > 1)
230
231 } // loop over polymer species
232
233 // Loop over solvent species (if any)
234 if (nSolvent > 0) {
235 double size, dcorr;
236 for (int i = 0; i < nSolvent; i++){
237 SolventSpecies const & solvent = mixture.solventSpecies(i);
238 phi = solvent.phi();
239 size = solvent.size();
240 dcorr = phi*size/vMonomer;
241 for (iter.begin(); !iter.atEnd(); ++iter) {
242 correlations[iter.rank()] += dcorr;
243 }
244 }
245 }
246
247 }
248
249}
250}
251#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
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
void computeIntraCorrelations(RField< D > &correlations)
Compute and modify intramolecular correlations.
System< D > & system()
Return reference to parent system.
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
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 ?
Real periodic fields, SCFT and PS-FTS (CPU).
Definition param_pc.dox:2
PSCF package top-level namespace.