PSCF v1.4.0
BdMove.tpp
1#ifndef RP_BD_MOVE_TPP
2#define RP_BD_MOVE_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 "BdMove.h"
12
13#include <pscf/math/IntVec.h>
14
15namespace Pscf {
16namespace Rp {
17
18 using namespace Util;
19 using namespace Prdc;
20
21 /*
22 * Constructor.
23 */
24 template <int D, class T>
25 BdMove<D,T>::BdMove(typename T::McSimulator& simulator)
26 : McMoveT(simulator),
27 w_(),
28 etaA_(),
29 etaB_(),
30 dwc_(),
31 etaNewPtr_(nullptr),
32 etaOldPtr_(nullptr),
33 mobility_(0.0)
34 { ParamComposite::setClassName("BdMove"); }
35
36 /*
37 * Read body of parameter file block and allocate memory.
38 */
39 template <int D, class T>
40 void BdMove<D,T>::readParameters(std::istream &in)
41 {
42 McMoveT::readProbability(in);
43 ParamComposite::read(in, "mobility", mobility_);
44 ParamComposite::read(in, "nStep", nStep_);
45
46 // Allocate memory
47 int nMonomer = system().mixture().nMonomer();
48 IntVec<D> meshDimensions = system().domain().mesh().dimensions();
49 w_.allocate(nMonomer);
50 for (int i=0; i < nMonomer; ++i) {
51 w_[i].allocate(meshDimensions);
52 }
53 etaA_.allocate(nMonomer-1);
54 etaB_.allocate(nMonomer-1);
55 for (int i=0; i < nMonomer - 1; ++i) {
56 etaA_[i].allocate(meshDimensions);
57 etaB_[i].allocate(meshDimensions);
58 }
59 dwc_.allocate(meshDimensions);
60 }
61
62 template <int D, class T>
64 {
65 // Start total timer
66 McMoveT::totalTimer_.start();
67
68 // Preconditions
69 UTIL_CHECK(simulator().hasWc());
70 UTIL_CHECK(simulator().hasCc());
71 UTIL_CHECK(simulator().hasDc());
72 UTIL_CHECK(simulator().hasHamiltonian());
73
74 // Run BD simulation of nStep steps
75 McMoveT::attemptMoveTimer_.start();
76 McMoveT::incrementNAttempt();
77 bdSetup();
78
79 for (int i=0; i < nStep_; ++i) {
80 bdStep();
81 }
82 McMoveT::attemptMoveTimer_.stop();
83
84 UTIL_CHECK(simulator().hasWc());
85 UTIL_CHECK(simulator().hasCc());
86 UTIL_CHECK(simulator().hasDc());
87 simulator().computeHamiltonian();
88
89 simulator().clearState();
90 McMoveT::incrementNAccept();
91 McMoveT::totalTimer_.stop();
92
93 return true; // isConverged
94 }
95
96 /*
97 * Setup before main simulation loop.
98 */
99 template <int D, class T>
101 {
102 UTIL_CHECK(system().w().hasData());
103
104 // Compute field components as needed
105 if (!simulator().hasWc()) {
106 simulator().computeWc();
107 }
108 if (!simulator().hasCc()) {
109 if (!system().c().hasData()){
110 system().compute();
111 }
112 simulator().computeCc();
113 }
114 if (!simulator().hasDc()) {
115 if (!system().c().hasData()){
116 system().compute();
117 }
118 simulator().computeDc();
119 }
120
121 // Check array capacities
122 int nMonomer = system().mixture().nMonomer();
123 int meshSize = system().domain().mesh().size();
124 UTIL_CHECK(etaA_.capacity() == nMonomer-1);
125 UTIL_CHECK(etaB_.capacity() == nMonomer-1);
126 for (int i=0; i < nMonomer - 1; ++i) {
127 UTIL_CHECK(etaA_[i].capacity() == meshSize);
128 UTIL_CHECK(etaB_[i].capacity() == meshSize);
129 }
130 UTIL_CHECK(dwc_.capacity() == meshSize);
131
132 // Initialize pointers
133 etaOldPtr_ = &etaA_;
134 etaNewPtr_ = &etaB_;
135
136 generateEtaNew();
137 exchangeOldNew();
138 }
139
140 /*
141 * One step of Leimkuhler-Matthews BD algorithm.
142 */
143 template <int D, class T>
145 {
146 // Preconditions
147 UTIL_CHECK(system().w().hasData());
148 UTIL_CHECK(simulator().hasWc());
149 UTIL_CHECK(simulator().hasCc());
150 UTIL_CHECK(simulator().hasDc());
151 UTIL_CHECK(simulator().hasHamiltonian());
152
153 // Save current state
154 simulator().saveState();
155
156 // Copy current W fields from parent system into w_
157 const int nMonomer = system().mixture().nMonomer();
158 for (int i = 0; i < nMonomer; ++i) {
159 VecOp::eqV(w_[i], system().w().rgrid(i));
160 }
161
162 // Generate new random displacement values
163 generateEtaNew();
164
165 // Take LM step
166 const double a = -1.0*mobility_;
167 double evec;
168 // Loop over eigenvectors of projected chi matrix
169 for (int j = 0; j < nMonomer - 1; ++j) {
170 RFieldT const & etaN = etaNew(j);
171 RFieldT const & etaO = etaOld(j);
172 RFieldT const & dc = simulator().dc(j);
173 VecOp::addVV(dwc_, etaN, etaO);
174 VecOp::addEqVc(dwc_, dc, a);
175 // Loop over monomer types
176 for (int i = 0; i < nMonomer; ++i) {
177 evec = simulator().chiEvecs(j,i);
178 VecOp::addEqVc(w_[i], dwc_, evec);
179 }
180 }
181
182 // Set modified fields in parent system
183 system().w().setRGrid(w_);
184
185 // Enforce incompressibility (also solves MDE repeatedly)
186 bool isConverged = false;
187 int compress = simulator().compressor().compress();
188 if (compress != 0){
189 simulator().restoreState();
190 } else {
191 isConverged = true;
192 UTIL_CHECK(system().c().hasData());
193
194 // Compute components and derivatives at wp_
195 simulator().clearState();
196 simulator().clearData();
197 simulator().computeWc();
198 simulator().computeCc();
199 simulator().computeDc();
200
201 // Compute new Hamiltonian
202 simulator().computeHamiltonian();
203
204 // Exchange old and new random fields
205 exchangeOldNew();
206 }
207
208 return isConverged;
209 }
210
211 /*
212 * Generate new random displacement values.
213 */
214 template <int D, class T>
215 void BdMove<D,T>::generateEtaNew()
216 {
217 // Constants
218 const int nMonomer = system().mixture().nMonomer();
219 const int meshSize = system().domain().mesh().size();
220 const double vSystem = system().domain().unitCell().volume();
221 const double stddev = sqrt(0.5*mobility_*double(meshSize)/vSystem);
222 const double mean = 0.0;
223
224 for (int j = 0; j < nMonomer - 1; ++j) {
225 vecRandom().normal(etaNew(j), stddev, mean);
226 }
227 }
228
229 /*
230 * Exchange pointers to old and new random fields.
231 */
232 template <int D, class T>
233 void BdMove<D,T>::exchangeOldNew()
234 {
235 DArray< RFieldT >* temp;
236 temp = etaOldPtr_;
237 etaOldPtr_ = etaNewPtr_;
238 etaNewPtr_ = temp;
239 }
240
241}
242}
243#endif
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
void readParameters(std::istream &in) override
Read body of parameter file block.
Definition BdMove.tpp:40
BdMove(typename T::McSimulator &simulator)
Constructor.
Definition BdMove.tpp:25
bool move() override
Generate a short BD simulation.
Definition BdMove.tpp:63
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 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 addVV(Array< double > &a, Array< double > const &b, Array< double > const &c)
Vector-vector addition, a[i] = b[i] + c[i] (real)
Definition VecOp.cpp:64
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
Periodic fields and crystallography.
Definition complex.cpp:11
Class templates for real-valued periodic fields.
PSCF package top-level namespace.