PSCF v1.4.0
PredCorrBdStep.tpp
1#ifndef RP_PRED_CORR_BD_STEP_TPP
2#define RP_PRED_CORR_BD_STEP_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 "PredCorrBdStep.h"
12#include <pscf/math/IntVec.h>
13
14namespace Pscf {
15namespace Rp {
16
17 using namespace Util;
18
19 /*
20 * Constructor.
21 */
22 template <int D, class T>
23 PredCorrBdStep<D,T>::PredCorrBdStep(typename T::BdSimulator& simulator)
24 : BdStepT(simulator),
25 wf_(),
26 dci_(),
27 eta_(),
28 dwc_(),
29 dwp_(),
30 mobility_(0.0)
31 { ParamComposite::setClassName("PredCorrBdStep"); }
32
33 /*
34 * Read body of parameter file block and allocate memory.
35 */
36 template <int D, class T>
38 {
39 ParamComposite::read(in, "mobility", mobility_);
40
41 // Allocate memory for private containers
42 int nMonomer = system().mixture().nMonomer();
43 IntVec<D> meshDimensions = system().domain().mesh().dimensions();
44 wp_.allocate(nMonomer);
45 wf_.allocate(nMonomer);
46 for (int i = 0; i < nMonomer; ++i) {
47 wp_[i].allocate(meshDimensions);
48 wf_[i].allocate(meshDimensions);
49 }
50 dci_.allocate(nMonomer-1);
51 eta_.allocate(nMonomer-1);
52 for (int i = 0; i < nMonomer - 1; ++i) {
53 dci_[i].allocate(meshDimensions);
54 eta_[i].allocate(meshDimensions);
55 }
56 dwc_.allocate(meshDimensions);
57 dwp_.allocate(meshDimensions);
58 }
59
60 /*
61 * Setup before entering main simulation loop.
62 */
63 template <int D, class T>
65 {
66 // Check array capacities
67 const int meshSize = system().domain().mesh().size();
68 const int nMonomer = system().mixture().nMonomer();
69 UTIL_CHECK(wp_.capacity() == nMonomer);
70 UTIL_CHECK(wf_.capacity() == nMonomer);
71 for (int i = 0; i < nMonomer; ++i) {
72 UTIL_CHECK(wp_[i].capacity() == meshSize);
73 UTIL_CHECK(wf_[i].capacity() == meshSize);
74 }
75 UTIL_CHECK(dci_.capacity() == nMonomer - 1);
76 UTIL_CHECK(eta_.capacity() == nMonomer - 1);
77 for (int i=0; i < nMonomer - 1; ++i) {
78 UTIL_CHECK(dci_[i].capacity() == meshSize);
79 UTIL_CHECK(eta_[i].capacity() == meshSize);
80 }
81 UTIL_CHECK(dwc_.capacity() == meshSize);
82 UTIL_CHECK(dwp_.capacity() == meshSize);
83 }
84
85 /*
86 * Take one BD step.
87 */
88 template <int D, class T>
90 {
91 // Save initial state
92 simulator().saveState();
93
94 // Array sizes and indices
95 const int nMonomer = system().mixture().nMonomer();
96 const int meshSize = system().domain().mesh().size();
97 int i, j;
98
99 // Copy initial w monomer fields into wp_ and wf_
100 for (i = 0; i < nMonomer; ++i) {
101 wp_[i] = system().w().rgrid(i);
102 wf_[i] = wp_[i];
103 }
104
105 // Copy initial value of pressure field as dwp_
106 dwp_ = simulator().wc(nMonomer-1);
107
108 // Constants used for step
109 const double vSystem = system().domain().unitCell().volume();
110 const double a = -1.0 * mobility_;
111 const double stddev = sqrt(2.0*mobility_*double(meshSize)/vSystem);
112 const double mean = 0.0;
113
114 // Generate all random displacement components
115 for (j = 0; j < nMonomer - 1; ++j) {
116 BdStepT::vecRandom().normal(eta_[j], stddev, mean);
117 }
118
119 // Compute predicted state wp_, and store initial force as dci_
120
121 // Loop over composition eigenvectors of projected chi matrix
122 for (j = 0; j < nMonomer - 1; ++j) {
123 RFieldT const & dc = simulator().dc(j);
124 VecOp::addVcVc(dwc_, dc, a, eta_[j], 1.0);
125 VecOp::eqV(dci_[j], dc);
126 // Loop over monomer types
127 for (i = 0; i < nMonomer; ++i) {
128 double evec = simulator().chiEvecs(j,i);
129 VecOp::addEqVc(wp_[i], dwc_, evec);
130 }
131 }
132
133 // Set system fields to predicted state wp_
134 system().w().setRGrid(wp_);
135
136 // Apply compressor after predictor step
137 int compress = simulator().compressor().compress();
138 if (compress != 0){
139 simulator().restoreState();
140 bool isConverged = false;
141 return isConverged;
142 }
143
144 // Compute components and derivatives at wp_
145 UTIL_CHECK(system().c().hasData());
146 simulator().clearData();
147 simulator().computeWc();
148 simulator().computeCc();
149 simulator().computeDc();
150
151 // Compute change dwp_ in pressure field
152 // Note: On entry, dwp_ is the old pressure field
153 RFieldT const & wp = simulator().wc(nMonomer-1);
154 VecOp::subVV(dwp_, wp, dwp_);
155
156 // Adjust predicted pressure field
157 for (i = 0; i < nMonomer; ++i) {
158 VecOp::addEqV(wf_[i], dwp_);
159 }
160
161 // Compute corrected state wf_
162 const double ha = 0.5*a;
163 for (j = 0; j < nMonomer - 1; ++j) {
164 RFieldT const & dcp = simulator().dc(j);
165 VecOp::addVcVcVc(dwc_, dci_[j], ha, dcp, ha, eta_[j], 1.0);
166 for (i = 0; i < nMonomer; ++i) {
167 double evec = simulator().chiEvecs(j,i);
168 VecOp::addEqVc(wf_[i], dwc_, evec);
169 }
170 }
171
172 // Set system fields after corrector step
173 system().w().setRGrid(wf_);
174
175 // Apply compressor to final state
176 int compress2 = simulator().compressor().compress();
177 if (compress2 != 0){
178 simulator().restoreState();
179 bool isConverged = false;
180 return isConverged;
181 }
182
183 // Compute components and derivatives in final state
184 UTIL_CHECK(system().c().hasData());
185 simulator().clearState();
186 simulator().clearData();
187 simulator().computeWc();
188 simulator().computeCc();
189 simulator().computeDc();
190
191 // Success
192 bool isConverged = true;
193 return isConverged;
194 }
195
196}
197}
198#endif
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
PredCorrBdStep(typename T::BdSimulator &simulator)
Constructor.
void readParameters(std::istream &in) override
Read body of parameter file block and allocate memory.
void setup() override
Setup before simulation.
bool step() override
Take a single Brownian dynamics step.
ScalarParam< Type > & read(std::istream &in, const char *label, Type &value)
Add and read a new required ScalarParam < Type > object.
void setClassName(const char *className)
Set class name string.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
void addEqV(Array< double > &a, Array< double > const &b)
Vector-vector in-place addition, a[i] += b[i] (real).
Definition VecOp.cpp:198
void eqV(Array< double > &a, Array< double > const &b, const int beginIdA, const int beginIdB, const int n)
Vector assignment, a[i] = b[i] (real, slice).
Definition VecOp.cpp:21
void subVV(Array< double > &a, Array< double > const &b, Array< double > const &c)
Vector-vector subtraction, a[i] = b[i] - c[i] (real)
Definition VecOp.cpp:95
void addEqVc(Array< double > &a, Array< double > const &b, const double c)
Add scaled vector in-place, a[i] += b[i]*c (real).
Definition VecOp.cpp:395
Class templates for real-valued periodic fields.
void addVcVc(Array< double > &a, Array< double > const &b1, const double c1, Array< double > const &b2, const double c2)
Add two scaled vectors, a[i] = b1[i]*c1 + b2[2]*c2 (real).
Definition VecOp.cpp:364
void addVcVcVc(Array< double > &a, Array< double > const &b1, const double c1, Array< double > const &b2, const double c2, Array< double > const &b3, const double c3)
Add scaled vectors, a[i] = b1[i]*c1 + b2[i]*c2 + b3[i]*c3 (real).
Definition VecOp.cpp:426
PSCF package top-level namespace.