PSCF v1.3.2
rpg/fts/brownian/BdSimulator.tpp
1#ifndef RPG_BD_SIMULATOR_TPP
2#define RPG_BD_SIMULATOR_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 "BdSimulator.h"
12
13#include <rpg/fts/brownian/BdStep.h>
14#include <rpg/fts/brownian/BdStepFactory.h>
15#include <rpg/fts/analyzer/AnalyzerFactory.h>
16#include <rpg/fts/trajectory/TrajectoryReader.h>
17#include <rpg/fts/trajectory/TrajectoryReaderFactory.h>
18#include <rpg/fts/perturbation/PerturbationFactory.h>
19#include <rpg/fts/perturbation/Perturbation.h>
20#include <rpg/fts/ramp/RampFactory.h>
21#include <rpg/fts/ramp/Ramp.h>
22#include <rpg/fts/compressor/Compressor.h>
23#include <rpg/system/System.h>
24
25#include <pscf/cuda/CudaRandom.h>
26#include <util/misc/Timer.h>
27#include <util/global.h>
28
29namespace Pscf {
30namespace Rpg {
31
32 using namespace Util;
33
34 /*
35 * Constructor.
36 */
37 template <int D>
39 : Simulator<D>(system),
40 analyzerManager_(*this, system),
41 bdStepPtr_(0),
42 bdStepFactoryPtr_(0),
43 trajectoryReaderFactoryPtr_(0),
44 seed_(0)
45 {
46 setClassName("BdSimulator");
47 bdStepFactoryPtr_ = new BdStepFactory<D>(*this);
48 trajectoryReaderFactoryPtr_
50 }
51
52 /*
53 * Destructor.
54 */
55 template <int D>
57 {
58 if (bdStepFactoryPtr_) {
59 delete bdStepFactoryPtr_;
60 }
61 if (bdStepPtr_) {
62 delete bdStepPtr_;
63 }
64 if (trajectoryReaderFactoryPtr_) {
65 delete trajectoryReaderFactoryPtr_;
66 }
67 }
68
69 /*
70 * Read instructions for creating objects from file.
71 */
72 template <int D>
73 void BdSimulator<D>::readParameters(std::istream &in)
74 {
75 // Optionally read random seed, initialize random number generators
77
78 // Optionally read and instantiate a BdStep object
79 bool isEnd = false;
80 std::string className;
82 UTIL_CHECK(bdStepFactoryPtr_);
83 bdStepPtr_
84 = bdStepFactoryPtr_->readObjectOptional(in, *this,
85 className, isEnd);
86
87 // Optionally read a Compressor block.
88 readCompressor(in, isEnd);
89 if (hasBdStep()) {
91 }
92
93 // Optionally read a Perturbation block.
94 readPerturbation(in, isEnd);
95
96 // Optionally read a Ramp block.
97 if (hasBdStep()) {
98 readRamp(in, isEnd);
99 }
100
101 // Compressor is required if a BdStep exists
102 // A Ramp is allowed only if a BdStep exists
103
104 // Read AnalyzerManager block
105 Analyzer<D>::baseInterval = 0; // default value
106 readParamCompositeOptional(in, analyzerManager_);
107
108 // Figure out what variables need to be saved in stored state
109 state_.needsCc = false;
110 state_.needsDc = false;
111 state_.needsHamiltonian = false;
112 if (hasBdStep()) {
113 if (stepper().needsCc()){
114 state_.needsCc = true;
115 }
116 if (stepper().needsDc()){
117 state_.needsDc = true;
118 }
119 }
120
121 // Initialize Simulator<D> base class
122 allocate();
123 }
124
125 /*
126 * Setup before the main loop of a simulate or analyze command.
127 */
128 template <int D>
129 void BdSimulator<D>::setup(int nStep)
130 {
131 UTIL_CHECK(system().w().hasData());
132
133 // Eigenanalysis of the projected chi matrix.
134 analyzeChi();
135
136 if (hasPerturbation()) {
137 perturbation().setup();
138 }
139
140 if (hasRamp()) {
141 ramp().setup(nStep);
142 }
143
144 // Solve MDE and compute c-fields for the intial state
145 system().compute();
146
147 // Compress the initial state (adjust pressure-like field)
148 if (hasCompressor()) {
149 compressor().compress();
150 compressor().clearTimers();
151 }
152
153 // Compute field components and Hamiltonian for initial state.
154 computeWc();
155 computeCc();
156 computeDc();
157 computeHamiltonian();
158
159 if (hasBdStep()) {
160 stepper().setup();
161 }
162
163 if (analyzerManager_.size() > 0){
164 analyzerManager_.setup();
165 }
166
167 }
168
169 /*
170 * Perform a field theoretic MC simulation of nStep steps.
171 */
172 template <int D>
174 {
175 UTIL_CHECK(system().w().hasData());
178
179 // Initial setup
180 setup(nStep);
181
182 // Main simulation loop
183 Timer timer;
184 Timer analyzerTimer;
185 timer.start();
186 iStep_ = 0;
187 if (hasRamp()) {
188 ramp().setParameters(iStep_);
189 }
190
191 // Analysis initial step (if any)
192 analyzerTimer.start();
193 analyzerManager_.sample(iStep_);
194 analyzerTimer.stop();
195
196 for (iTotalStep_ = 0; iTotalStep_ < nStep; ++iTotalStep_) {
197
198 // Take a step (modifies W fields)
199 bool converged;
200 converged = stepper().step();
201
202 if (converged){
203 iStep_++;
204
205 if (hasRamp()) {
206 ramp().setParameters(iStep_);
207 }
208
209 // Analysis (if any)
210 analyzerTimer.start();
211 if (Analyzer<D>::baseInterval != 0) {
213 if (analyzerManager_.size() > 0) {
214 analyzerManager_.sample(iStep_);
215 }
216 }
217 }
218 analyzerTimer.stop();
219
220 } else{
221 Log::file() << "Step: "<< iTotalStep_<< " fail to converge" << "\n";
222 }
223
224 }
225
226 timer.stop();
227 double time = timer.time();
228 double analyzerTime = analyzerTimer.time();
229
230 // Output results analyzers to files
232 analyzerManager_.output();
233 }
234
235 // Output results of ramp
236 if (hasRamp()){
237 Log::file() << std::endl;
238 ramp().output();
239 }
240
241 // Output times for the simulation run
242 Log::file() << std::endl;
243 Log::file() << "nStep " << nStep << std::endl;
244 if (iStep_ != nStep){
245 Log::file() << "nFail Step " << (nStep - iStep_)
246 << std::endl;
247 }
248 Log::file() << "Total run time " << time
249 << " sec" << std::endl;
250 double rStep = double(nStep);
251 Log::file() << "time / nStep " << time / rStep
252 << " sec" << std::endl;
253 Log::file() << "Analyzer run time " << analyzerTime
254 << " sec" << std::endl;
255 Log::file() << std::endl;
256
257 // Output number of times MDE has been solved for the simulation run
258 Log::file() << "MDE counter "
259 << compressor().mdeCounter() << std::endl;
260 Log::file() << std::endl;
261
262 }
263
264 /*
265 * Open, read and analyze a trajectory file
266 */
267 template <int D>
268 void BdSimulator<D>::analyze(int min, int max,
269 std::string classname,
270 std::string filename)
271 {
272 // Preconditions
273 UTIL_CHECK(min >= 0);
274 UTIL_CHECK(max >= min);
276 UTIL_CHECK(analyzerManager_.size() > 0);
277
278 // Construct TrajectoryReader
279 TrajectoryReader<D>* trajectoryReaderPtr;
280 trajectoryReaderPtr = trajectoryReaderFactory().factory(classname);
281 if (!trajectoryReaderPtr) {
282 std::string message;
283 message = "Invalid TrajectoryReader class name " + classname;
284 UTIL_THROW(message.c_str());
285 }
286
287 // Open trajectory file
288 trajectoryReaderPtr->open(filename);
289 trajectoryReaderPtr->readHeader();
290
291 // Main loop over trajectory frames
292 Timer timer;
293 bool hasFrame;
294 timer.start();
295 hasFrame = trajectoryReaderPtr->readFrame();
296
297 for (iStep_ = 0; iStep_ <= max && hasFrame; ++iStep_) {
298 if (hasFrame) {
299 clearData();
300
301 // Initialize analyzers
302 if (iStep_ == min) {
303 setup(iStep_);
304 }
305
306 // Sample property values only for iStep >= min
307 if (iStep_ >= min) {
308 analyzerManager_.sample(iStep_);
309 }
310 }
311
312 hasFrame = trajectoryReaderPtr->readFrame();
313 }
314 timer.stop();
315 Log::file() << "end main loop" << std::endl;
316 int nFrames = iStep_ - min;
317 trajectoryReaderPtr->close();
318 delete trajectoryReaderPtr;
319
320 // Output results of all analyzers to output files
321 analyzerManager_.output();
322
323 // Output number of frames and times
324 Log::file() << std::endl;
325 Log::file() << "# of frames " << nFrames << std::endl;
326 Log::file() << "run time " << timer.time()
327 << " sec" << std::endl;
328 Log::file() << "time / frame " << timer.time()/double(nFrames)
329 << " sec" << std::endl;
330 Log::file() << std::endl;
331
332 }
333
334 /*
335 * Output timer results.
336 */
337 template<int D>
338 void BdSimulator<D>::outputTimers(std::ostream& out) const
339 {
340 compressor().outputTimers(out);
341 }
342
343}
344}
345#endif
static long baseInterval
The interval for every Analyzer must be a multiple of baseInterval.
virtual void outputTimers(std::ostream &out) const
Output timing results.
void simulate(int nStep)
Perform a field theoretic Monte-Carlo simulation.
virtual void analyze(int min, int max, std::string classname, std::string filename)
Read and analyze a trajectory file.
void setClassName(const char *className)
Set class name string.
Factory< TrajectoryReader< D > > & trajectoryReaderFactory()
Get the trajectory reader factory by reference.
BdStep< D > & stepper()
Get BdStep.
bool hasBdStep() const
Does this BdSimulator have an associated BdStep?
void readParamCompositeOptional(std::istream &in, ParamComposite &child, bool next=true)
Add and attempt to read an optional child ParamComposite.
BdSimulator(System< D > &system)
Constructor.
virtual void readParameters(std::istream &in)
Read parameters for a MC simulation.
Factory for subclasses of BdStep.
void readRandomSeed(std::istream &in)
Read random seed and initialize random number generators.
System< D > & system()
Get parent system by reference.
void readRamp(std::istream &in, bool &isEnd)
Optionally read a Ramp parameter file block.
void clearData()
Clear field eigen-components and hamiltonian components.
SimState< D > state_
State saved during fts simulation.
long iTotalStep_
Simulation step counter.
void allocate()
Allocate required memory.
void readPerturbation(std::istream &in, bool &isEnd)
Optionally read a Perturbation parameter file block.
void readCompressor(std::istream &in, bool &isEnd)
Optionally read a Compressor parameter file block.
Ramp< D > const & ramp() const
Get the associated Ramp by const reference.
bool hasRamp() const
Does this Simulator have a Ramp?
Simulator(System< D > &system)
Constructor.
Compressor< D > & compressor()
Get the compressor by non-const reference.
bool hasCompressor() const
Does this Simulator have a Compressor object?
long iStep_
Simulation step counter.
Main class, representing a complete physical system.
Factory for subclasses of TrajectoryReader.
virtual bool readFrame()=0
Read a single frame.
virtual void close()=0
Close the trajectory file.
virtual void open(std::string filename)=0
Open trajectory file and read header, if any.
static std::ostream & file()
Get log ostream by reference.
Definition Log.cpp:59
std::string className() const
Get class name string.
Wall clock timer.
Definition Timer.h:35
void start(TimePoint begin)
Start timing from an externally supplied time.
Definition Timer.cpp:49
double time() const
Return the accumulated time, in seconds.
Definition Timer.cpp:37
void stop(TimePoint end)
Stop the clock at an externally supplied time.
Definition Timer.cpp:73
File containing preprocessor macros for error handling.
#define UTIL_CHECK(condition)
Assertion macro suitable for serial or parallel production code.
Definition global.h:68
#define UTIL_THROW(msg)
Macro for throwing an Exception, reporting function, file and line number.
Definition global.h:49
SCFT and PS-FTS with real periodic fields (GPU)
PSCF package top-level namespace.