PSCF v1.3.3
rpg/fts/montecarlo/ForceBiasMove.tpp
1#ifndef RPG_FORCE_BIAS_MOVE_TPP
2#define RPG_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 "McMove.h"
13#include <rpg/fts/montecarlo/McSimulator.h>
14#include <rpg/fts/compressor/Compressor.h>
15#include <rpg/fts/VecOpFts.h>
16#include <rpg/system/System.h>
17#include <rpg/solvers/Mixture.h>
18#include <rpg/field/Domain.h>
19#include <prdc/cuda/resources.h>
20#include <pscf/cuda/CudaRandom.h>
21#include <util/param/ParamComposite.h>
22#include <util/random/Random.h>
23
24namespace Pscf {
25namespace Rpg {
26
27 using namespace Util;
28
29 /*
30 * Constructor.
31 */
32 template <int D>
34 : McMove<D>(simulator),
35 w_(),
36 dwc_(),
37 mobility_(0.0)
38 { setClassName("ForceBiasMove"); }
39
40 /*
41 * Destructor, empty default implementation.
42 */
43 template <int D>
46
47 /*
48 * ReadParameters, empty default implementation.
49 */
50 template <int D>
51 void ForceBiasMove<D>::readParameters(std::istream &in)
52 {
53 //Read the probability
55
56 // Read Brownian dynamics mobility parameter
57 read(in, "mobility", mobility_);
58
59 // Allocate memory for private containers
60 int nMonomer = system().mixture().nMonomer();
61 IntVec<D> meshDimensions = system().domain().mesh().dimensions();
62 w_.allocate(nMonomer);
63 for (int i=0; i < nMonomer; ++i) {
64 w_[i].allocate(meshDimensions);
65 }
66 dc_.allocate(nMonomer-1);
67 dwc_.allocate(nMonomer-1);
68 for (int i=0; i < nMonomer - 1; ++i) {
69 dc_[i].allocate(meshDimensions);
70 dwc_[i].allocate(meshDimensions);
71 }
72
73 }
74
75 template <int D>
77 {
78 // Check array capacities
79 int meshSize = system().domain().mesh().size();
80 IntVec<D> dimensions = system().domain().mesh().dimensions();
81 int nMonomer = system().mixture().nMonomer();
82 UTIL_CHECK(w_.capacity() == nMonomer);
83 for (int i=0; i < nMonomer; ++i) {
84 UTIL_CHECK(w_[i].capacity() == meshSize);
85 }
86 UTIL_CHECK(dc_.capacity() == nMonomer-1);
87 UTIL_CHECK(dwc_.capacity() == nMonomer-1);
88 for (int i=0; i < nMonomer - 1; ++i) {
89 UTIL_CHECK(dc_[i].capacity() == meshSize);
90 UTIL_CHECK(dwc_[i].capacity() == meshSize);
91 }
92
94 biasField_.allocate(dimensions);
95 gaussianField_.allocate(dimensions);
96 }
97
98 /*
99 * Attempt unconstrained move
100 */
101 template <int D>
103 {
104 totalTimer_.start();
106
107 // Preconditions
108 UTIL_CHECK(simulator().hasWc());
109 UTIL_CHECK(simulator().hasDc());
110 UTIL_CHECK(simulator().hasHamiltonian());
111
112 // Array sizes and indices
113 const int nMonomer = system().mixture().nMonomer();
114 const int meshSize = system().domain().mesh().size();
115 int i, j;
116
117
118 // Get current Hamiltonian
119 double oldHamiltonian = simulator().hamiltonian();
120
121 // Save current state
122 simulator().saveState();
123
124 // Clear both eigen-components of the fields and hamiltonian
125 simulator().clearData();
126
127 attemptMoveTimer_.start();
128
129 // Copy current W fields from parent system into wc_
130 for (i = 0; i < nMonomer; ++i) {
131 VecOp::eqV(w_[i], system().w().rgrid(i));
132 }
133
134 // Copy current derivative fields from into member variable dc_
135 for (i = 0; i < nMonomer - 1; ++i) {
136 VecOp::eqV(dc_[i], simulator().dc(i));
137 }
138
139 // Constants for dynamics
140 const double vSystem = system().domain().unitCell().volume();
141 const double vNode = vSystem/double(meshSize);
142 double a = -1.0*mobility_;
143 double b = sqrt(2.0*mobility_/vNode);
144
145 // Constants for normal distribution
146 double stddev = 1.0;
147 double mean = 0;
148
149 // Modify local variables dwc_ and wc_
150 // Loop over eigenvectors of projected chi matrix
151 double evec;
152 for (j = 0; j < nMonomer - 1; ++j) {
153 RField<D> & dwc = dwc_[j];
154
155 // Generate normal distributed random floating point numbers
156 cudaRandom().normal(gaussianField_, stddev, mean);
157
158 // dwc
159 VecOp::addVcVc(dwc, dc_[j], a, gaussianField_, b);
160
161 // Loop over monomer types
162 for (i = 0; i < nMonomer; ++i) {
163 RField<D> const & dwc = dwc_[j];
164 RField<D> & wn = w_[i];
165 evec = simulator().chiEvecs(j,i);
166 VecOp::addEqVc(wn, dwc, evec);
167 }
168
169 }
170
171 // Set modified fields in parent system
172 system().w().setRGrid(w_);
173 simulator().clearData();
174
175 attemptMoveTimer_.stop();
176
177 // Call compressor
178 compressorTimer_.start();
179 int compress = simulator().compressor().compress();
180 UTIL_CHECK(system().c().hasData());
181 compressorTimer_.stop();
182
183 bool isConverged = false;
184 if (compress != 0){
186 simulator().restoreState();
187 } else {
188 isConverged = true;
189
190 // Compute eigenvector components of current fields
191 componentTimer_.start();
192 simulator().computeWc();
193 UTIL_CHECK(system().c().hasData());
194 simulator().computeCc();
195 simulator().computeDc();
196 componentTimer_.stop();
197
198 // Evaluate new Hamiltonian
199 hamiltonianTimer_.start();
200 simulator().computeHamiltonian();
201 double newHamiltonian = simulator().hamiltonian();
202 double dH = newHamiltonian - oldHamiltonian;
203
204 // Compute force bias
205 double bias = 0.0;
206 for (j = 0; j < nMonomer - 1; ++j) {
207 RField<D> const & di = dc_[j];
208 RField<D> const & df = simulator().dc(j);
209 RField<D> const & dwc = dwc_[j];
210
211 VecOpFts::computeForceBias(biasField_, di, df, dwc, mobility_);
212 bias += Reduce::sum(biasField_);
213 }
214 bias *= vNode;
215 hamiltonianTimer_.stop();
216
217 // Accept or reject move
218 decisionTimer_.start();
219 bool accept = false;
220 double weight = exp(bias - dH);
221 accept = random().metropolis(weight);
222 if (accept) {
224 simulator().clearState();
225 } else {
226 simulator().restoreState();
227 }
228 decisionTimer_.stop();
229 }
230
231 totalTimer_.stop();
232 return isConverged;
233 }
234
235 /*
236 * Trivial default implementation - do nothing
237 */
238 template <int D>
241
242 template<int D>
243 void ForceBiasMove<D>::outputTimers(std::ostream& out)
244 {
245 // Output timing results, if requested.
246 out << "\n";
247 out << "ForceBiasMove time contributions:\n";
249 }
250
251}
252}
253#endif
An IntVec<D, T> is a D-component vector of elements of integer type T.
Definition IntVec.h:27
Field of real double precision values on an FFT mesh.
Definition cpu/RField.h:29
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.
void setup()
Setup before the beginning of each simulation run.
void output()
Output statistics for this move (at the end of simulation)
ForceBiasMove(McSimulator< D > &simulator)
Constructor.
void readParameters(std::istream &in)
Read required parameters from file.
bool move()
Attempt and accept or reject force bias Monte-Carlo move.
void outputTimers(std::ostream &out)
Return real move times contributions.
CudaRandom & cudaRandom()
Get cuda random number generator by reference.
void incrementNAttempt()
Increment the number of attempted moves.
Random & random()
Get Random number generator of parent System.
void readProbability(std::istream &in)
Read the probability from file.
McSimulator< D > & simulator()
Get parent McSimulator object.
System< D > & system()
Get parent System object.
void incrementNAccept()
Increment the number of accepted moves.
void incrementNFail()
Increment the number of failed moves.
virtual void outputTimers(std::ostream &out)
Log output timing results.
virtual void setup()
Setup before the beginning of each simulation run.
McMove(McSimulator< D > &simulator)
Constructor.
Timer attemptMoveTimer_
Timers for McMove.
Monte-Carlo simulation coordinator.
#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 .
Definition Reduce.cpp:80
void eqV(Array< double > &a, Array< double > const &b)
Vector assignment, a[i] = b[i].
Definition VecOp.cpp:23
void addVcVc(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, cudaReal const c, DeviceArray< cudaReal > const &d, cudaReal const e)
Vector addition w/ coefficient, a[i] = (b[i]*c) + (d[i]*e), kernel wrapper.
Definition VecOpMisc.cu:304
void addEqVc(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, cudaReal const c)
Vector addition in-place w/ coefficient, a[i] += b[i] * c, kernel wrapper.
Definition VecOpMisc.cu:343
void computeForceBias(DeviceArray< cudaReal > &result, DeviceArray< cudaReal > const &di, DeviceArray< cudaReal > const &df, DeviceArray< cudaReal > const &dwc, cudaReal mobility)
Compute force bias.
Definition VecOpFts.cu:133
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.