PSCF v1.3.3
rpg/fts/brownian/LMBdStep.tpp
1#ifndef RPG_LM_BD_STEP_TPP
2#define RPG_LM_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 "LMBdStep.h"
12
13#include <rpg/fts/brownian/BdSimulator.h>
14#include <rpg/fts/compressor/Compressor.h>
15#include <rpg/system/System.h>
16#include <rpg/solvers/Mixture.h>
17#include <rpg/field/Domain.h>
18#include <prdc/cuda/VecOp.h>
19#include <pscf/math/IntVec.h>
20#include <pscf/cuda/CudaRandom.h>
21
22namespace Pscf {
23namespace Rpg {
24
25 using namespace Util;
26 using namespace Pscf::Prdc;
27 using namespace Pscf::Prdc::Cuda;
28
29 /*
30 * Constructor.
31 */
32 template <int D>
34 : BdStep<D>(simulator),
35 w_(),
36 etaA_(),
37 etaB_(),
38 dwc_(),
39 etaNewPtr_(0),
40 etaOldPtr_(0),
41 mobility_(0.0)
42 {}
43
44 /*
45 * Destructor, empty default implementation.
46 */
47 template <int D>
50
51 /*
52 * ReadParameters, empty default implementation.
53 */
54 template <int D>
55 void LMBdStep<D>::readParameters(std::istream &in)
56 {
57 read(in, "mobility", mobility_);
58
59 int nMonomer = system().mixture().nMonomer();
60 int meshSize = system().domain().mesh().size();
61 IntVec<D> meshDimensions = system().domain().mesh().dimensions();
62
63 // Allocate memory for private containers
64 w_.allocate(nMonomer);
65 for (int i=0; i < nMonomer; ++i) {
66 w_[i].allocate(meshDimensions);
67 }
68 etaA_.allocate(nMonomer-1);
69 etaB_.allocate(nMonomer-1);
70 for (int i=0; i < nMonomer - 1; ++i) {
71 etaA_[i].allocate(meshDimensions);
72 etaB_[i].allocate(meshDimensions);
73 }
74 dwc_.allocate(meshDimensions);
75 gaussianField_.allocate(meshDimensions);
76 }
77
78 /*
79 * Generate new random displacement values
80 */
81 template <int D>
82 void LMBdStep<D>::generateEtaNew()
83 {
84 const int nMonomer = system().mixture().nMonomer();
85 const int meshSize = system().domain().mesh().size();
86
87 // Prefactor b for displacements
88 const double vSystem = system().domain().unitCell().volume();
89 double b = sqrt(0.5*mobility_*double(meshSize)/vSystem);
90
91 // Constants for normal distribution
92 double stddev = 1.0;
93 double mean = 0;
94
95 int j;
96 for (j = 0; j < nMonomer - 1; ++j) {
97 RField<D>& eta = etaNew(j);
98
99 // Generate normal distributed random floating point numbers
100 cudaRandom().normal(gaussianField_, stddev, mean);
101 VecOp::mulVS(eta, gaussianField_, b);
102
103 }
104 }
105
106 template <int D>
107 void LMBdStep<D>::exchangeOldNew()
108 {
109 DArray< RField<D> >* temp;
110 temp = etaOldPtr_;
111 etaOldPtr_ = etaNewPtr_;
112 etaNewPtr_ = temp;
113 }
114
115 /*
116 * Initial setup before main simulation loop.
117 */
118 template <int D>
120 {
121 int nMonomer = system().mixture().nMonomer();
122 int meshSize = system().domain().mesh().size();
123
124 // Check array capacities
125 UTIL_CHECK(etaA_.capacity() == nMonomer-1);
126 UTIL_CHECK(etaB_.capacity() == nMonomer-1);
127 for (int i=0; i < nMonomer - 1; ++i) {
128 UTIL_CHECK(etaA_[i].capacity() == meshSize);
129 UTIL_CHECK(etaB_[i].capacity() == meshSize);
130 }
131 UTIL_CHECK(dwc_.capacity() == meshSize);
132
133 // Initialize pointers
134 etaOldPtr_ = &etaA_;
135 etaNewPtr_ = &etaB_;
136
137 generateEtaNew();
138 exchangeOldNew();
139 }
140
141 /*
142 * One step of Leimkuhler-Matthews BD algorithm.
143 */
144 template <int D>
146 {
147 // Array sizes and indices
148 const int nMonomer = system().mixture().nMonomer();
149 const int meshSize = system().domain().mesh().size();
150 int i, j;
151
152 // Save current state
153 simulator().saveState();
154
155 // Copy current W fields from parent system into w_
156 for (i = 0; i < nMonomer; ++i) {
157 VecOp::eqV(w_[i], system().w().rgrid(i));
158 }
159
160 // Generate new random displacement values
161 generateEtaNew();
162
163 // Take LM step:
164 double a = -1.0*mobility_;
165 double evec;
166
167 // Loop over composition eigenvectors of projected chi matrix
168 for (j = 0; j < nMonomer - 1; ++j) {
169 RField<D> const & etaN = etaNew(j);
170 RField<D> const & etaO = etaOld(j);
171 RField<D> const & dc = simulator().dc(j);
172 VecOp::addVcVcVc(dwc_, etaN, 1.0, etaO, 1.0, dc, a);
173 // Loop over monomer types
174 for (i = 0; i < nMonomer; ++i) {
175 RField<D> & w = w_[i];
176 evec = simulator().chiEvecs(j,i);
177 VecOp::addEqVc(w, dwc_, evec);
178 }
179 }
180
181 // Set modified fields
182 system().w().setRGrid(w_);
183
184 // Enforce incompressibility (also solves MDE repeatedly)
185 bool isConverged = false;
186 int compress = simulator().compressor().compress();
187 if (compress != 0){
188 simulator().restoreState();
189 } else{
190 isConverged = true;
191 UTIL_CHECK(system().c().hasData());
192
193 // Compute components and derivatives at wp_
194 simulator().clearState();
195 simulator().clearData();
196 simulator().computeWc();
197 simulator().computeCc();
198 simulator().computeDc();
199
200 // Exchange old and new random fields
201 exchangeOldNew();
202
203 }
204
205 return isConverged;
206
207 }
208
209}
210}
211#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
Brownian dynamics simulator.
BdStep(BdSimulator< D > &simulator)
Constructor.
System< D > & system()
Get parent System object.
BdSimulator< D > & simulator()
Get parent BdSimulator object.
virtual bool step()
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.
virtual void setup()
Setup before simulation.
virtual void readParameters(std::istream &in)
Read required parameters from file.
LMBdStep(BdSimulator< D > &simulator)
Constructor.
Dynamically allocatable contiguous array template.
Definition DArray.h:32
#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)
Vector assignment, a[i] = b[i].
Definition VecOp.cpp:23
void mulVS(Array< double > &a, Array< double > const &b, double c)
Vector multiplication, a[i] = b[i] * c.
Definition VecOp.cpp:126
void addVcVcVc(DeviceArray< cudaReal > &a, DeviceArray< cudaReal > const &b, cudaReal const c, DeviceArray< cudaReal > const &d, cudaReal const e, DeviceArray< cudaReal > const &f, cudaReal const g)
3-vec addition w coeff, a[i] = (b[i]*c) + (d[i]*e) + (f[i]*g), kernel wrapper.
Definition VecOpMisc.cu:322
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
Fields, FFTs, and utilities for periodic boundary conditions (CUDA)
Definition CField.cu:12
Periodic fields and crystallography.
Definition CField.cpp:11
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.