PSCF v1.4.0
ForceBiasMove.tpp
1#ifndef RP_FORCE_BIAS_MOVE_TPP
2#define RP_FORCE_BIAS_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 "ForceBiasMove.h"
12#include <util/param/ParamComposite.h>
13#include <pscf/mesh/Mesh.h>
14#include <pscf/math/IntVec.h>
15#include <util/random/Random.h>
16
17namespace Pscf {
18namespace Rp {
19
20 using namespace Util;
21
22 /*
23 * Constructor.
24 */
25 template <int D, class T>
26 ForceBiasMove<D,T>::ForceBiasMove(typename T::McSimulator& simulator)
27 : McMoveT(simulator),
28 w_(),
29 dwc_(),
30 mobility_(0.0)
31 { ParamComposite::setClassName("ForceBiasMove"); }
32
33 /*
34 * Read body of parameter file block and allocate memory.
35 */
36 template <int D, class T>
38 {
39 McMoveT::readProbability(in);
40 ParamComposite::read(in, "mobility", mobility_);
41
42 // Allocate memory for private containers
43 int nMonomer = system().mixture().nMonomer();
44 IntVec<D> meshDimensions = system().domain().mesh().dimensions();
45 w_.allocate(nMonomer);
46 for (int i=0; i < nMonomer; ++i) {
47 w_[i].allocate(meshDimensions);
48 }
49 dc_.allocate(nMonomer-1);
50 dwc_.allocate(nMonomer-1);
51 for (int i=0; i < nMonomer - 1; ++i) {
52 dc_[i].allocate(meshDimensions);
53 dwc_[i].allocate(meshDimensions);
54 }
55 biasField_.allocate(meshDimensions);
56 eta_.allocate(meshDimensions);
57 }
58
59 /*
60 * Setup before entering main simulation loop.
61 */
62 template <int D, class T>
64 {
65 // Check array capacities
66 int meshSize = system().domain().mesh().size();
67 int nMonomer = system().mixture().nMonomer();
68 UTIL_CHECK(w_.capacity() == nMonomer);
69 for (int i=0; i < nMonomer; ++i) {
70 UTIL_CHECK(w_[i].capacity() == meshSize);
71 }
72 UTIL_CHECK(dc_.capacity() == nMonomer-1);
73 UTIL_CHECK(dwc_.capacity() == nMonomer-1);
74 for (int i = 0; i < nMonomer - 1; ++i) {
75 UTIL_CHECK(dc_[i].capacity() == meshSize);
76 UTIL_CHECK(dwc_[i].capacity() == meshSize);
77 }
78
79 McMoveT::setup();
80 }
81
82 /*
83 * Attempt and accept or reject MC move
84 */
85 template <int D, class T>
87 {
88 McMoveT::totalTimer_.start();
89 McMoveT::incrementNAttempt();
90
91 // Preconditions
92 UTIL_CHECK(simulator().hasWc());
93 UTIL_CHECK(simulator().hasDc());
94 UTIL_CHECK(simulator().hasHamiltonian());
95
96 // Array sizes and index variables
97 const int nMonomer = system().mixture().nMonomer();
98 const int meshSize = system().domain().mesh().size();
99 int i, j;
100
101 // Get current Hamiltonian
102 double oldHamiltonian = simulator().hamiltonian();
103
104 // Save current state
105 simulator().saveState();
106
107 // Clear eigen-components of the fields and Hamiltonian
108 simulator().clearData();
109
110 McMoveT::attemptMoveTimer_.start();
111
112 // Copy current W fields from parent system into wc_
113 for (i = 0; i < nMonomer; ++i) {
114 VecOp::eqV(w_[i], system().w().rgrid(i));
115 }
116
117 // Copy derivative fields into dc_
118 for (i = 0; i < nMonomer - 1; ++i) {
119 VecOp::eqV(dc_[i], simulator().dc(i));
120 }
121
122 // Constants for dynamics
123 const double vSystem = system().domain().unitCell().volume();
124 const double vNode = vSystem/double(meshSize);
125 const double a = -1.0*mobility_;
126 const double b = sqrt(2.0*mobility_/vNode);
127 const double stddev = 1.0;
128 const double mean = 0.0;
129
130 // Modify local variables dwc_ and w_
131 // Loop over composition eigenvectors of projected chi matrix
132 for (j = 0; j < nMonomer - 1; ++j) {
133
134 // Generate vector of normal distributed random numbers
135 McMoveT::vecRandom().normal(eta_, stddev, mean);
136
137 // Compute vector dwc_[j] of field component changes
138 VecOp::addVcVc(dwc_[j], dc_[j], a, eta_, b);
139
140 // Loop over monomer types to add to w_
141 for (i = 0; i < nMonomer; ++i) {
142 double evec = simulator().chiEvecs(j,i);
143 VecOp::addEqVc(w_[i], dwc_[j], evec);
144 }
145
146 }
147
148 // Set modified fields in parent system
149 system().w().setRGrid(w_);
150 simulator().clearData();
151
152 McMoveT::attemptMoveTimer_.stop();
153
154 // Call compressor
155 McMoveT::compressorTimer_.start();
156 int compress = simulator().compressor().compress();
157 UTIL_CHECK(system().c().hasData());
158 McMoveT::compressorTimer_.stop();
159
160 bool isConverged = false;
161 if (compress != 0){
162 McMoveT::incrementNFail();
163 simulator().restoreState();
164 } else {
165 isConverged = true;
166
167 // Compute eigenvector components of current fields
168 McMoveT::componentTimer_.start();
169 simulator().computeWc();
170 UTIL_CHECK(system().c().hasData());
171 simulator().computeCc();
172 simulator().computeDc();
173 McMoveT::componentTimer_.stop();
174
175 // Evaluate new Hamiltonian
176 McMoveT::hamiltonianTimer_.start();
177 simulator().computeHamiltonian();
178 double newHamiltonian = simulator().hamiltonian();
179 double dH = newHamiltonian - oldHamiltonian;
180
181 // Compute force bias used in acceptance criterion
182 double bias = 0.0;
183 for (j = 0; j < nMonomer - 1; ++j) {
184 RFieldT const & di = dc_[j];
185 RFieldT const & df = simulator().dc(j);
186 computeForceBias(biasField_, di, df, dwc_[j], mobility_);
187 bias += Reduce::sum(biasField_);
188 }
189 bias *= vNode;
190 McMoveT::hamiltonianTimer_.stop();
191
192 // Accept or reject move
193 McMoveT::decisionTimer_.start();
194 bool accept = false;
195 double weight = exp(bias - dH);
196 accept = McMoveT::random().metropolis(weight);
197 if (accept) {
198 McMoveT::incrementNAccept();
199 simulator().clearState();
200 } else {
201 simulator().restoreState();
202 }
203 McMoveT::decisionTimer_.stop();
204 }
205 McMoveT::totalTimer_.stop();
206
207 return isConverged;
208 }
209
210 /*
211 * Output data to log file (do-nothing implementation).
212 */
213 template <int D, class T>
216
217}
218}
219#endif
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
bool move() override
Attempt and accept or reject a force bias Monte-Carlo move.
void setup() override
Setup before the beginning of each simulation run.
ForceBiasMove(typename T::McSimulator &simulator)
Constructor.
void output() override
Output statistics for this move (at the end of simulation)
typename T::McMove McMoveT
Alias for McMove base class.
void readParameters(std::istream &in) override
Read body of parameter file block and allocate memory.
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
double sum(Array< double > const &in)
Compute sum of array elements (real).
Definition Reduce.cpp:20
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 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
PSCF package top-level namespace.