1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
10 // Cynthia Gu, zg1@ornl.gov, Oak Ridge National Laboratory
11 // Paul R. C. Kent, kentpr@ornl.gov, Oak Ridge National Laboratory
12 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
13 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
14 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
15 //
16 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
17 //////////////////////////////////////////////////////////////////////////////////////
18
19
20 #include "DMC.h"
21 #include "QMCDrivers/DMC/DMCUpdatePbyP.h"
22 #include "QMCDrivers/DMC/DMCUpdatePbyPL2.h"
23 #include "QMCDrivers/DMC/SODMCUpdatePbyP.h"
24 #include "QMCDrivers/DMC/DMCUpdateAll.h"
25 #include "QMCHamiltonians/HamiltonianPool.h"
26 #include "Message/Communicate.h"
27 #include "Message/CommOperators.h"
28 #include "Message/OpenMP.h"
29 #include "Utilities/Timer.h"
30 #include "Utilities/RunTimeManager.h"
31 #include "OhmmsApp/RandomNumberControl.h"
32 #include "Utilities/ProgressReportEngine.h"
33 #include "Utilities/qmc_common.h"
34 #include "Utilities/FairDivide.h"
35 #if !defined(REMOVE_TRACEMANAGER)
36 #include "Estimators/TraceManager.h"
37 #else
38 typedef int TraceManager;
39 #endif
40
41 namespace qmcplusplus
42 {
43 /// Constructor.
DMC(MCWalkerConfiguration & w,TrialWaveFunction & psi,QMCHamiltonian & h,Communicate * comm,bool enable_profiling)44 DMC::DMC(MCWalkerConfiguration& w, TrialWaveFunction& psi, QMCHamiltonian& h, Communicate* comm, bool enable_profiling)
45 : QMCDriver(w, psi, h, comm, "DMC", enable_profiling),
46 KillNodeCrossing(0),
47 BranchInterval(-1),
48 L2("no"),
49 Reconfiguration("no"),
50 mover_MaxAge(-1)
51 {
52 RootName = "dmc";
53 qmc_driver_mode.set(QMC_UPDATE_MODE, 1);
54 m_param.add(KillWalker, "killnode");
55 m_param.add(Reconfiguration, "reconfiguration");
56 //m_param.add(BranchInterval,"branchInterval");
57 m_param.add(NonLocalMove, "nonlocalmove");
58 m_param.add(NonLocalMove, "nonlocalmoves");
59 m_param.add(mover_MaxAge, "MaxAge");
60 m_param.add(L2, "L2_diffusion");
61 }
62
resetUpdateEngines()63 void DMC::resetUpdateEngines()
64 {
65 ReportEngine PRE("DMC", "resetUpdateEngines");
66 bool fixW = (Reconfiguration == "runwhileincorrect");
67 if (Reconfiguration != "no" && Reconfiguration != "runwhileincorrect")
68 APP_ABORT("Reconfiguration is currently broken and gives incorrect results. Set reconfiguration=\"no\" or remove "
69 "the reconfiguration option from the DMC input section. To run performance tests, please set "
70 "reconfiguration to \"runwhileincorrect\" instead of \"yes\" to restore consistent behaviour.")
71 makeClones(W, Psi, H);
72 Timer init_timer;
73 if (Movers.empty())
74 {
75 W.loadEnsemble(wClones);
76 setWalkerOffsets();
77 int nw_multi = branchEngine->initWalkerController(W, fixW, false);
78 if (nw_multi > 1)
79 {
80 W.createWalkers((nw_multi - 1) * W.getActiveWalkers());
81 setWalkerOffsets();
82 }
83 //if(qmc_driver_mode[QMC_UPDATE_MODE]) W.clearAuxDataSet();
84 Movers.resize(NumThreads, 0);
85 Rng.resize(NumThreads, 0);
86 estimatorClones.resize(NumThreads, 0);
87 traceClones.resize(NumThreads, 0);
88 FairDivideLow(W.getActiveWalkers(), NumThreads, wPerRank);
89
90 {
91 //log file
92 std::ostringstream o;
93 o << " Initial partition of walkers on a node: ";
94 copy(wPerRank.begin(), wPerRank.end(), std::ostream_iterator<int>(o, " "));
95 o << "\n";
96 if (qmc_driver_mode[QMC_UPDATE_MODE])
97 {
98 o << " Updates by particle-by-particle moves";
99 if (L2 == "yes")
100 app_log() << "Using DMCUpdatePbyPL2" << std::endl;
101 else
102 app_log() << "Using DMCUpdatePbyPWithRejectionFast" << std::endl;
103 }
104 else
105 o << " Updates by walker moves";
106 // Appears to be set in constructor reported here and used nowhere
107 if (KillNodeCrossing)
108 o << "\n Walkers are killed when a node crossing is detected";
109 else
110 o << "\n DMC moves are rejected when a node crossing is detected";
111 if (SpinMoves == "yes")
112 o << "\n Spins treated as dynamic variable with SpinMass: " << SpinMass;
113 app_log() << o.str() << std::endl;
114 }
115 #pragma omp parallel for
116 for (int ip = 0; ip < NumThreads; ++ip)
117 {
118 estimatorClones[ip] = new EstimatorManagerBase(*Estimators);
119 estimatorClones[ip]->setCollectionMode(false);
120 #if !defined(REMOVE_TRACEMANAGER)
121 traceClones[ip] = Traces->makeClone();
122 #endif
123 #ifdef USE_FAKE_RNG
124 Rng[ip] = new FakeRandom();
125 #else
126 Rng[ip] = new RandomGenerator_t(*RandomNumberControl::Children[ip]);
127 hClones[ip]->setRandomGenerator(Rng[ip]);
128 #endif
129 if (SpinMoves == "yes")
130 {
131 if (qmc_driver_mode[QMC_UPDATE_MODE])
132 {
133 Movers[ip] = new SODMCUpdatePbyPWithRejectionFast(*wClones[ip], *psiClones[ip], *hClones[ip], *Rng[ip]);
134 Movers[ip]->setSpinMass(SpinMass);
135 Movers[ip]->put(qmcNode);
136 Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier);
137 Movers[ip]->initWalkersForPbyP(W.begin() + wPerRank[ip], W.begin() + wPerRank[ip + 1]);
138 }
139 else
140 {
141 APP_ABORT("SODMC Driver Mode must be PbyP\n");
142 }
143 }
144 else
145 {
146 if (qmc_driver_mode[QMC_UPDATE_MODE])
147 {
148 if (L2 == "yes")
149 Movers[ip] = new DMCUpdatePbyPL2(*wClones[ip], *psiClones[ip], *hClones[ip], *Rng[ip]);
150 else
151 Movers[ip] = new DMCUpdatePbyPWithRejectionFast(*wClones[ip], *psiClones[ip], *hClones[ip], *Rng[ip]);
152
153 Movers[ip]->put(qmcNode);
154 Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier);
155 Movers[ip]->initWalkersForPbyP(W.begin() + wPerRank[ip], W.begin() + wPerRank[ip + 1]);
156 }
157 else
158 {
159 if (KillNodeCrossing)
160 Movers[ip] = new DMCUpdateAllWithKill(*wClones[ip], *psiClones[ip], *hClones[ip], *Rng[ip]);
161 else
162 Movers[ip] = new DMCUpdateAllWithRejection(*wClones[ip], *psiClones[ip], *hClones[ip], *Rng[ip]);
163 Movers[ip]->put(qmcNode);
164 Movers[ip]->resetRun(branchEngine.get(), estimatorClones[ip], traceClones[ip], DriftModifier);
165 Movers[ip]->initWalkers(W.begin() + wPerRank[ip], W.begin() + wPerRank[ip + 1]);
166 }
167 }
168 }
169 }
170 #if !defined(REMOVE_TRACEMANAGER)
171 else
172 {
173 #pragma omp parallel for
174 for (int ip = 0; ip < NumThreads; ++ip)
175 {
176 traceClones[ip]->transfer_state_from(*Traces);
177 }
178 }
179 #endif
180 branchEngine->checkParameters(W);
181 int mxage = mover_MaxAge;
182 if (fixW)
183 {
184 if (BranchInterval < 0)
185 BranchInterval = 1;
186 mxage = (mover_MaxAge < 0) ? 0 : mover_MaxAge;
187 for (int ip = 0; ip < Movers.size(); ++ip)
188 Movers[ip]->MaxAge = mxage;
189 }
190 else
191 {
192 if (BranchInterval < 0)
193 BranchInterval = 1;
194 int miage = (qmc_driver_mode[QMC_UPDATE_MODE]) ? 1 : 5;
195 mxage = (mover_MaxAge < 0) ? miage : mover_MaxAge;
196 for (int i = 0; i < NumThreads; ++i)
197 Movers[i]->MaxAge = mxage;
198 }
199 {
200 std::ostringstream o;
201 if (fixW)
202 o << " Fixed population using reconfiguration method\n";
203 else
204 o << " Fluctuating population\n";
205 o << " Persistent walkers are killed after " << mxage << " MC sweeps\n";
206 o << " BranchInterval = " << BranchInterval << "\n";
207 o << " Steps per block = " << nSteps << "\n";
208 o << " Number of blocks = " << nBlocks << "\n";
209 app_log() << o.str() << std::endl;
210 }
211 app_log() << " DMC Engine Initialization = " << init_timer.elapsed() << " secs" << std::endl;
212 }
213
run()214 bool DMC::run()
215 {
216 LoopTimer<> dmc_loop;
217
218 bool variablePop = (Reconfiguration == "no");
219 resetUpdateEngines();
220 //estimator does not need to collect data
221 Estimators->setCollectionMode(true);
222 Estimators->start(nBlocks);
223 for (int ip = 0; ip < NumThreads; ip++)
224 Movers[ip]->startRun(nBlocks, false);
225 #if !defined(REMOVE_TRACEMANAGER)
226 Traces->startRun(nBlocks, traceClones);
227 #endif
228 IndexType block = 0;
229 IndexType updatePeriod = (qmc_driver_mode[QMC_UPDATE_MODE]) ? Period4CheckProperties : (nBlocks + 1) * nSteps;
230 int sample = 0;
231
232 RunTimeControl<> runtimeControl(run_time_manager, MaxCPUSecs, myComm->getName(), myComm->rank() == 0);
233
234 do // block
235 {
236 dmc_loop.start();
237 Estimators->startBlock(nSteps);
238 for (int ip = 0; ip < NumThreads; ip++)
239 Movers[ip]->startBlock(nSteps);
240
241 for (IndexType step = 0; step < nSteps; ++step, CurrentStep += BranchInterval)
242 {
243 // if(storeConfigs && (CurrentStep%storeConfigs == 0)) {
244 // ForwardWalkingHistory.storeConfigsForForwardWalking(W);
245 // W.resetWalkerParents();
246 // }
247
248 #pragma omp parallel
249 {
250 int ip = omp_get_thread_num();
251 Movers[ip]->set_step(sample);
252 bool recompute = (step + 1 == nSteps && nBlocksBetweenRecompute && (1 + block) % nBlocksBetweenRecompute == 0 &&
253 qmc_driver_mode[QMC_UPDATE_MODE]);
254 wClones[ip]->resetCollectables();
255 const size_t nw = W.getActiveWalkers();
256 #pragma omp for nowait
257 for (size_t iw = 0; iw < nw; ++iw)
258 {
259 Walker_t& thisWalker(*W[iw]);
260 Movers[ip]->advanceWalker(thisWalker, recompute);
261 }
262 }
263
264 //Collectables are weighted but not yet normalized
265 if (W.Collectables.size())
266 {
267 // only when collectable is not empty, need to generalize for W != wClones[0]
268 for (int ip = 1; ip < NumThreads; ++ip)
269 W.Collectables += wClones[ip]->Collectables;
270 }
271 branchEngine->branch(CurrentStep, W);
272 // if(storeConfigs && (CurrentStep%storeConfigs == 0)) {
273 // ForwardWalkingHistory.storeConfigsForForwardWalking(W);
274 // W.resetWalkerParents();
275 // }
276 if (variablePop)
277 FairDivideLow(W.getActiveWalkers(), NumThreads, wPerRank);
278 sample++;
279 }
280 // branchEngine->debugFWconfig();
281 Estimators->stopBlock(acceptRatio());
282 #if !defined(REMOVE_TRACEMANAGER)
283 Traces->write_buffers(traceClones, block);
284 #endif
285 block++;
286 if (DumpConfig && block % Period4CheckPoint == 0)
287 {
288 #ifndef USE_FAKE_RNG
289 for (int ip = 0; ip < NumThreads; ip++)
290 *(RandomNumberControl::Children[ip]) = *(Rng[ip]);
291 #endif
292 }
293 recordBlock(block);
294 dmc_loop.stop();
295
296 bool stop_requested = false;
297 // Rank 0 decides whether the time limit was reached
298 if (!myComm->rank())
299 stop_requested = runtimeControl.checkStop(dmc_loop);
300 myComm->bcast(stop_requested);
301
302 if (stop_requested)
303 {
304 if (!myComm->rank())
305 app_log() << runtimeControl.generateStopMessage("DMC", block - 1);
306 run_time_manager.markStop();
307 break;
308 }
309
310 } while (block < nBlocks);
311
312 #ifndef USE_FAKE_RNG
313 for (int ip = 0; ip < NumThreads; ip++)
314 *(RandomNumberControl::Children[ip]) = *(Rng[ip]);
315 #endif
316 Estimators->stop();
317 for (int ip = 0; ip < NumThreads; ++ip)
318 Movers[ip]->stopRun2();
319 #if !defined(REMOVE_TRACEMANAGER)
320 Traces->stopRun();
321 #endif
322 return finalize(nBlocks);
323 }
324
325
put(xmlNodePtr q)326 bool DMC::put(xmlNodePtr q)
327 {
328 BranchInterval = -1;
329 ParameterSet p;
330 p.add(BranchInterval, "branchInterval");
331 p.add(BranchInterval, "branchinterval");
332 p.add(BranchInterval, "substeps");
333 p.add(BranchInterval, "subSteps");
334 p.add(BranchInterval, "sub_steps");
335 p.put(q);
336
337 //app_log() << "\n DMC::put qmc_counter=" << qmc_common.qmc_counter << " my_counter=" << MyCounter<< std::endl;
338 //app_log() << " timestep = " << Tau << std::endl;
339 //app_log() << " blocks = " << nBlocks << std::endl;
340 //app_log() << " steps = " << nSteps << std::endl;
341 //app_log() << " current = " << CurrentStep << std::endl;
342 //app_log() << " walkers/mpi = " << W.getActiveWalkers() << std::endl << std::endl;
343 //app_log().flush();
344 return true;
345 }
346 } // namespace qmcplusplus
347