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: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
8 // Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory
9 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
10 //
11 // File created by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
12 //////////////////////////////////////////////////////////////////////////////////////
13
14
15 #include "RMCUpdatePbyP.h"
16 #include "QMCDrivers/DriftOperators.h"
17 #include "Message/OpenMP.h"
18 #include "Configuration.h"
19 #include "Particle/Reptile.h"
20 #include <cmath>
21 //////////////////////////////////////////////////////////////////////////
22 // This driver is strongly based off the method used by Lucas Wagner in QWalk.
23 //
24 // This driver proposes an "all-electron" configuration by performing N single particle moves,
25 // accepting or rejecting at each step. Umrigar's scaled drift is used to generate the VMC configurations.
26 //
27 // The configuration is then accepted/rejected based only on the symmetrized DMC action, which
28 // amounts to Maroni/Baroni's method. Note that energy filtering (like in DMC) is used here as well.
29 //
30 // Until serious discrepencies are detected, it is strongly advised that this driver be used over the
31 // RMCUpdateAll, as the time step errors seem to be really reduced using this method.
32 //////////////////////////////////////////////////////////////////////////////
33
34
35 namespace qmcplusplus
36 {
37 using WP = WalkerProperties::Indexes;
38
39 /// Constructor.
RMCUpdatePbyPWithDrift(MCWalkerConfiguration & w,TrialWaveFunction & psi,QMCHamiltonian & h,RandomGenerator_t & rg,std::vector<int> act,std::vector<int> tp)40 RMCUpdatePbyPWithDrift::RMCUpdatePbyPWithDrift(MCWalkerConfiguration& w,
41 TrialWaveFunction& psi,
42 QMCHamiltonian& h,
43 RandomGenerator_t& rg,
44 std::vector<int> act,
45 std::vector<int> tp)
46 : QMCUpdateBase(w, psi, h, rg),
47 Action(act),
48 TransProb(tp),
49 advance_timer_(*timer_manager.createTimer("RMCUpdatePbyP::advance", timer_level_medium)),
50 movepbyp_timer_(*timer_manager.createTimer("RMCUpdatePbyP::movePbyP", timer_level_medium)),
51 update_mbo_timer_(*timer_manager.createTimer("RMCUpdatePbyP::updateMBO", timer_level_medium)),
52 energy_timer_(*timer_manager.createTimer("RMCUpdatePbyP::energy", timer_level_medium))
53 {
54 scaleDrift = false;
55 actionType = SYM_ACTION;
56 }
57
~RMCUpdatePbyPWithDrift()58 RMCUpdatePbyPWithDrift::~RMCUpdatePbyPWithDrift() {}
59
60
initWalkersForPbyP(WalkerIter_t it,WalkerIter_t it_end)61 void RMCUpdatePbyPWithDrift::initWalkersForPbyP(WalkerIter_t it, WalkerIter_t it_end)
62 {
63 UpdatePbyP = true;
64
65 for (; it != it_end; ++it)
66 {
67 Walker_t& awalker = **it; //W.reptile->getHead();
68 W.R = awalker.R;
69 W.update(true);
70 W.donePbyP();
71 if (awalker.DataSet.size())
72 awalker.DataSet.clear();
73 awalker.DataSet.rewind();
74 Psi.registerData(W, awalker.DataSet);
75 awalker.DataSet.allocate();
76 Psi.copyFromBuffer(W, awalker.DataSet);
77 Psi.evaluateLog(W);
78 RealType logpsi = Psi.updateBuffer(W, awalker.DataSet, false);
79 awalker.G = W.G;
80 awalker.L = W.L;
81 RealType eloc = H.evaluate(W);
82 awalker.resetProperty(logpsi, Psi.getPhase(), eloc);
83 }
84 }
85
put(xmlNodePtr cur)86 bool RMCUpdatePbyPWithDrift::put(xmlNodePtr cur)
87 {
88 QMCUpdateBase::put(cur);
89
90 ParameterSet m_param;
91 bool usedrift = true;
92 std::string action = "SLA";
93 m_param.add(usedrift, "useDrift");
94 m_param.add(action, "Action");
95 m_param.add(equilSteps, "equilsteps");
96 m_param.add(equilSteps, "equilSteps");
97 m_param.put(cur);
98
99 if (usedrift == true)
100 {
101 if (omp_get_thread_num() == 0)
102 app_log() << " Using Umrigar scaled drift\n";
103 }
104 else
105 {
106 if (omp_get_thread_num() == 0)
107 app_log() << " Using non-scaled drift\n";
108 }
109
110 if (action == "DMC")
111 {
112 actionType = DMC_ACTION;
113 if (omp_get_thread_num() == 0)
114 app_log() << " Using DMC link-action\n";
115 }
116 else
117 {
118 if (omp_get_thread_num() == 0)
119 app_log() << " Using Symmetrized Link-Action\n";
120 }
121
122 return true;
123 }
advanceWalkersVMC()124 void RMCUpdatePbyPWithDrift::advanceWalkersVMC()
125 {
126 advance_timer_.start();
127 Walker_t& curhead = W.reptile->getHead();
128 Walker_t prophead(curhead);
129 Walker_t::WFBuffer_t& w_buffer(prophead.DataSet);
130 W.loadWalker(prophead, true);
131 Psi.copyFromBuffer(W, w_buffer);
132 //create a 3N-Dimensional Gaussian with variance=1
133 makeGaussRandomWithEngine(deltaR, RandomGen);
134 int nAcceptTemp(0);
135 int nRejectTemp(0);
136 //copy the old energy and scale factor of drift
137 RealType eold(prophead.Properties(WP::LOCALENERGY));
138 RealType vqold(prophead.Properties(WP::DRIFTSCALE));
139 RealType enew(eold);
140 RealType rr_proposed = 0.0;
141 RealType rr_accepted = 0.0;
142 RealType gf_acc = 1.0;
143 movepbyp_timer_.start();
144 for (int ig = 0; ig < W.groups(); ++ig) //loop over species
145 {
146 RealType tauovermass = Tau * MassInvS[ig];
147 RealType oneover2tau = 0.5 / (tauovermass);
148 RealType sqrttau = std::sqrt(tauovermass);
149 for (int iat = W.first(ig); iat < W.last(ig); ++iat)
150 {
151 //get the displacement
152 GradType grad_iat = Psi.evalGrad(W, iat);
153 PosType dr;
154 DriftModifier->getDrift(tauovermass, grad_iat, dr);
155 dr += sqrttau * deltaR[iat];
156 bool is_valid = W.makeMoveAndCheck(iat, dr);
157 RealType rr = tauovermass * dot(deltaR[iat], deltaR[iat]);
158 rr_proposed += rr;
159 if (!is_valid || rr > m_r2max)
160 {
161 ++nRejectTemp;
162 W.accept_rejectMove(iat, false);
163 continue;
164 }
165 ValueType ratio = Psi.calcRatioGrad(W, iat, grad_iat);
166 //node is crossed reject the move
167 if (branchEngine->phaseChanged(Psi.getPhaseDiff()))
168 {
169 ++nRejectTemp;
170 ++nNodeCrossing;
171 W.accept_rejectMove(iat, false);
172 Psi.rejectMove(iat);
173 }
174 else
175 {
176 RealType logGf = -0.5 * dot(deltaR[iat], deltaR[iat]);
177 //Use the force of the particle iat
178 DriftModifier->getDrift(tauovermass, grad_iat, dr);
179 dr = W.R[iat] - W.activePos - dr;
180 RealType logGb = -oneover2tau * dot(dr, dr);
181 RealType prob = std::norm(ratio) * std::exp(logGb - logGf);
182 bool is_accepted = false;
183 if (RandomGen() < prob)
184 {
185 is_accepted = true;
186 ++nAcceptTemp;
187 Psi.acceptMove(W, iat, true);
188 rr_accepted += rr;
189 gf_acc *= prob; //accumulate the ratio
190 }
191 else
192 {
193 ++nRejectTemp;
194 Psi.rejectMove(iat);
195 }
196 W.accept_rejectMove(iat, is_accepted);
197 }
198 }
199 }
200 movepbyp_timer_.stop();
201 Psi.completeUpdates();
202 W.donePbyP();
203
204 if (nAcceptTemp > 0)
205 {
206 //need to overwrite the walker properties
207 MCWalkerConfiguration::Walker_t& newhead(W.reptile->getNewHead());
208 update_mbo_timer_.start();
209 prophead.Age = 0;
210 prophead.R = W.R;
211 RealType logpsi = Psi.updateBuffer(W, w_buffer, false);
212 W.saveWalker(prophead);
213 update_mbo_timer_.stop();
214 energy_timer_.start();
215 enew = H.evaluate(W);
216 energy_timer_.stop();
217 prophead.resetProperty(logpsi, Psi.getPhase(), enew, rr_accepted, rr_proposed, 0.0);
218 prophead.Weight = 1.0;
219 H.auxHevaluate(W, prophead, true, false); //evaluate properties but not collectables.
220 H.saveProperty(prophead.getPropertyBase());
221 newhead = prophead;
222 nAccept++;
223 }
224 else
225 {
226 //all moves are rejected: does not happen normally with reasonable wavefunctions
227 curhead.Age++;
228 curhead.Properties(WP::R2ACCEPTED) = 0.0;
229 //weight is set to 0 for traces
230 // consistent w/ no evaluate/auxHevaluate
231 RealType wtmp = prophead.Weight;
232 curhead.Weight = 0.0;
233 H.rejectedMove(W, curhead);
234 curhead.Weight = wtmp;
235 ++nAllRejected;
236 gf_acc = 1.0;
237 nReject++;
238 }
239 Walker_t& centerbead = W.reptile->getCenter();
240 W.loadWalker(centerbead, true);
241 W.update();
242 H.auxHevaluate(W, centerbead); //evaluate collectables but not properties.
243 // Traces->buffer_sample();
244 }
245
246
initWalkers(WalkerIter_t it,WalkerIter_t it_end)247 void RMCUpdatePbyPWithDrift::initWalkers(WalkerIter_t it, WalkerIter_t it_end)
248 {
249 IndexType initsteps = W.reptile->nbeads * 2;
250
251 vmcSteps = W.reptile->nbeads + 1;
252
253 for (int n = 0; n < initsteps; n++)
254 advanceWalkersVMC();
255 }
256
advanceWalkersRMC()257 void RMCUpdatePbyPWithDrift::advanceWalkersRMC()
258 {
259 Walker_t& curhead = W.reptile->getHead();
260 Walker_t prophead(curhead);
261 Walker_t::WFBuffer_t& w_buffer(prophead.DataSet);
262 W.loadWalker(prophead, true);
263 Psi.copyFromBuffer(W, w_buffer);
264
265 makeGaussRandomWithEngine(deltaR, RandomGen);
266 int nAcceptTemp(0);
267 int nRejectTemp(0);
268 //copy the old energy and scale factor of drift
269 RealType eold(prophead.Properties(WP::LOCALENERGY));
270 RealType vqold(prophead.Properties(WP::DRIFTSCALE));
271 RealType rr_proposed = 0.0;
272 RealType rr_accepted = 0.0;
273 RealType gf_acc = 1.0;
274 movepbyp_timer_.start();
275 for (int ig = 0; ig < W.groups(); ++ig) //loop over species
276 {
277 RealType tauovermass = Tau * MassInvS[ig];
278 RealType oneover2tau = 0.5 / (tauovermass);
279 RealType sqrttau = std::sqrt(tauovermass);
280 for (int iat = W.first(ig); iat < W.last(ig); ++iat)
281 {
282 //get the displacement
283 GradType grad_iat = Psi.evalGrad(W, iat);
284 PosType dr;
285 DriftModifier->getDrift(tauovermass, grad_iat, dr);
286 dr += sqrttau * deltaR[iat];
287 bool is_valid = W.makeMoveAndCheck(iat, dr);
288 RealType rr = tauovermass * dot(deltaR[iat], deltaR[iat]);
289 rr_proposed += rr;
290 if (!is_valid || rr > m_r2max)
291 {
292 ++nRejectTemp;
293 W.accept_rejectMove(iat, false);
294 continue;
295 }
296 ValueType ratio = Psi.calcRatioGrad(W, iat, grad_iat);
297 //node is crossed reject the move
298 if (branchEngine->phaseChanged(Psi.getPhaseDiff()))
299 {
300 ++nRejectTemp;
301 ++nNodeCrossing;
302 W.accept_rejectMove(iat, false);
303 Psi.rejectMove(iat);
304 }
305 else
306 {
307 RealType logGf = -0.5 * dot(deltaR[iat], deltaR[iat]);
308 //Use the force of the particle iat
309 DriftModifier->getDrift(tauovermass, grad_iat, dr);
310 dr = W.R[iat] - W.activePos - dr;
311 RealType logGb = -oneover2tau * dot(dr, dr);
312 RealType prob = std::norm(ratio) * std::exp(logGb - logGf);
313 bool is_accepted = false;
314 if (RandomGen() < prob)
315 {
316 is_accepted = true;
317 ++nAcceptTemp;
318 Psi.acceptMove(W, iat, true);
319 rr_accepted += rr;
320 gf_acc *= prob; //accumulate the ratio
321 }
322 else
323 {
324 ++nRejectTemp;
325 Psi.rejectMove(iat);
326 }
327 W.accept_rejectMove(iat, is_accepted);
328 }
329 }
330 }
331 movepbyp_timer_.stop();
332 Psi.completeUpdates();
333 W.donePbyP();
334 // In the rare case that all proposed moves fail, we bounce.
335 if (nAcceptTemp == 0)
336 {
337 ++nReject;
338 H.rejectedMove(W, prophead);
339 curhead.Age += 1;
340 W.reptile->flip();
341 }
342 prophead.R = W.R;
343 RealType logpsi = Psi.updateBuffer(W, w_buffer, false);
344 W.saveWalker(prophead);
345 Walker_t &lastbead(W.reptile->getTail()), nextlastbead(W.reptile->getNext());
346 RealType eloc = H.evaluate(W);
347 RealType dS = branchEngine->DMCLinkAction(eloc, curhead.Properties(WP::LOCALENERGY)) -
348 branchEngine->DMCLinkAction(lastbead.Properties(WP::LOCALENERGY), nextlastbead.Properties(WP::LOCALENERGY));
349 RealType acceptProb = std::min((RealType)1.0, std::exp(-dS));
350 if ((RandomGen() <= acceptProb) || (prophead.Age >= MaxAge || lastbead.Age >= MaxAge))
351 {
352 MCWalkerConfiguration::Walker_t& overwriteWalker(W.reptile->getNewHead());
353 if (curhead.Age >= MaxAge || lastbead.Age >= MaxAge)
354 app_log() << "\tForce Acceptance...\n";
355
356 prophead.Properties(WP::LOCALENERGY) = eloc;
357 prophead.Properties(WP::R2ACCEPTED) = rr_accepted;
358 prophead.Properties(WP::R2PROPOSED) = rr_proposed;
359 H.auxHevaluate(W, prophead, true, false); //evaluate properties? true. collectables? false.
360 H.saveProperty(prophead.getPropertyBase());
361 prophead.Age = 0;
362 overwriteWalker = prophead;
363 ++nAccept;
364 }
365 else
366 {
367 ++nReject;
368 H.rejectedMove(W, prophead);
369 curhead.Properties(WP::R2ACCEPTED) = 0;
370 curhead.Properties(WP::R2PROPOSED) = rr_proposed;
371 curhead.Age += 1;
372 W.reptile->flip();
373 // return;
374 }
375 //Collectables should be evaluated on center bead. Here we go.
376 Walker_t& centerbead = W.reptile->getCenter();
377 W.loadWalker(centerbead, true);
378 W.update(); //Called to recompute S(k) and distance tables.
379 H.auxHevaluate(W, centerbead, false, true); //evaluate properties? false. Collectables? true.
380 }
381
advanceWalker(Walker_t & thisWalker,bool recompute)382 void RMCUpdatePbyPWithDrift::advanceWalker(Walker_t& thisWalker, bool recompute)
383 {
384 //empty function to
385 }
386
advanceWalkers(WalkerIter_t it,WalkerIter_t it_end,bool init)387 void RMCUpdatePbyPWithDrift::advanceWalkers(WalkerIter_t it, WalkerIter_t it_end, bool init)
388 {
389 if (init == true)
390 advanceWalkersVMC();
391 else
392 advanceWalkersRMC();
393 }
394
accumulate(WalkerIter_t it,WalkerIter_t it_end)395 void RMCUpdatePbyPWithDrift::accumulate(WalkerIter_t it, WalkerIter_t it_end) { Estimators->accumulate(W, it, it_end); }
396
397 } // namespace qmcplusplus
398