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 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
10 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
11 //
12 // File created by: Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
13 //////////////////////////////////////////////////////////////////////////////////////
14
15
16 #include "QMCDrivers/DMC/DMCUpdatePbyPL2.h"
17 #include "Particle/MCWalkerConfiguration.h"
18 // #include "Particle/DistanceTable.h"
19 #include "Particle/HDFWalkerIO.h"
20 #include "ParticleBase/ParticleUtility.h"
21 #include "ParticleBase/RandomSeqGenerator.h"
22 #include "QMCDrivers/DriftOperators.h"
23 #if !defined(REMOVE_TRACEMANAGER)
24 #include "Estimators/TraceManager.h"
25 #else
26 typedef int TraceManager;
27 #endif
28 //#define TEST_INNERBRANCH
29 #include "QMCDrivers/DMC/DMCUpdatePbyP.h"
30
31 namespace qmcplusplus
32 {
33 using WP = WalkerProperties::Indexes;
34
35 /// Constructor.
DMCUpdatePbyPL2(MCWalkerConfiguration & w,TrialWaveFunction & psi,QMCHamiltonian & h,RandomGenerator_t & rg)36 DMCUpdatePbyPL2::DMCUpdatePbyPL2(MCWalkerConfiguration& w,
37 TrialWaveFunction& psi,
38 QMCHamiltonian& h,
39 RandomGenerator_t& rg)
40 : QMCUpdateBase(w, psi, h, rg)
41 {
42 setup_timers(myTimers, DMCTimerNames, timer_level_medium);
43 }
44
45 /// destructor
~DMCUpdatePbyPL2()46 DMCUpdatePbyPL2::~DMCUpdatePbyPL2() {}
47
advanceWalker(Walker_t & thisWalker,bool recompute)48 void DMCUpdatePbyPL2::advanceWalker(Walker_t& thisWalker, bool recompute)
49 {
50 Walker_t::WFBuffer_t& w_buffer(thisWalker.DataSet);
51 {
52 ScopedTimer local_timer(myTimers[DMC_buffer]);
53 W.loadWalker(thisWalker, true);
54 Psi.copyFromBuffer(W, w_buffer);
55 }
56 //create a 3N-Dimensional Gaussian with variance=1
57 makeGaussRandomWithEngine(deltaR, RandomGen);
58 int nAcceptTemp(0);
59 int nRejectTemp(0);
60 //copy the old energy and scale factor of drift
61 //EstimatorRealType eold(thisWalker.Properties(LOCALENERGY));
62 //EstimatorRealType enew(eold);
63 FullPrecRealType eold(thisWalker.Properties(WP::LOCALENERGY));
64 FullPrecRealType enew(eold);
65 RealType rr_proposed = 0.0;
66 RealType rr_accepted = 0.0;
67 RealType gf_acc = 1.0;
68 mPosType K;
69 mTensorType D;
70 mTensorType Dchol;
71 PosType Ktmp, drtmp;
72 TensorType Dtmp;
73 bool L2_proj = H.has_L2();
74 if (L2_proj)
75 {
76 Ktmp = 0.0;
77 Dtmp = 0.0;
78 for (int d = 0; d < DIM; d++)
79 Dtmp(d, d) = 1.0;
80 }
81 {
82 ScopedTimer local_timer(myTimers[DMC_movePbyP]);
83 for (int ig = 0; ig < W.groups(); ++ig) //loop over species
84 {
85 RealType tauovermass = Tau * MassInvS[ig];
86 RealType oneover2tau = 0.5 / (tauovermass);
87 RealType sqrttau = std::sqrt(tauovermass);
88 RealType rr;
89 for (int iat = W.first(ig); iat < W.last(ig); ++iat)
90 {
91 //W.setActive(iat);
92 //get the displacement
93 GradType grad_iat = Psi.evalGrad(W, iat);
94 mPosType dr;
95 mPosType dr_diff = deltaR[iat];
96 if (!L2_proj) // normal projector
97 {
98 getScaledDrift(tauovermass, grad_iat, dr);
99 dr += sqrttau * dr_diff;
100 rr = tauovermass * dot(dr_diff, dr_diff);
101 rr_proposed += rr;
102 if (rr > m_r2max)
103 {
104 ++nRejectTemp;
105 W.accept_rejectMove(iat, false);
106 continue;
107 }
108 if (!W.makeMoveAndCheck(iat, dr))
109 {
110 W.accept_rejectMove(iat, false);
111 continue;
112 }
113 }
114 else // projector including L2 potential
115 {
116 // do a fake move (zero distance)
117 // this ensures the temporary distance data is correct
118 // will need to remove this later, but requires reimplementation of computeL2DK
119 dr = 0.0;
120 if (!W.makeMoveAndCheck(iat, dr))
121 {
122 W.accept_rejectMove(iat, false);
123 continue;
124 }
125
126 H.computeL2DK(W, iat, Dtmp, Ktmp);
127 D = Dtmp; // upcast for mixed precision
128 K = Ktmp;
129 getScaledDriftL2(tauovermass, grad_iat, D, K, dr);
130
131 W.accept_rejectMove(iat, false);
132 rr = tauovermass * dot(dr_diff, dr_diff);
133 rr_proposed += rr;
134 if (rr > m_r2max)
135 {
136 ++nRejectTemp;
137 W.accept_rejectMove(iat, false);
138 continue;
139 }
140
141 // move with just drift to update distance tables
142 if (!W.makeMoveAndCheck(iat, dr))
143 {
144 W.accept_rejectMove(iat, false);
145 continue;
146 }
147
148 // compute diffusion step
149 H.computeL2D(W, iat, Dtmp);
150 D = Dtmp; // upcast for mixed precision
151 Dchol = cholesky(D);
152 dr_diff = dot(Dchol, dr_diff);
153 dr += sqrttau * dr_diff;
154
155 // reverse the intermediate drift move
156 W.accept_rejectMove(iat, false);
157 // move with drift and diffusion together
158 if (!W.makeMoveAndCheck(iat, dr))
159 {
160 W.accept_rejectMove(iat, false);
161 continue;
162 }
163 }
164 ValueType ratio = Psi.calcRatioGrad(W, iat, grad_iat);
165 //node is crossed reject the move
166 if (branchEngine->phaseChanged(Psi.getPhaseDiff()))
167 {
168 ++nRejectTemp;
169 ++nNodeCrossing;
170 W.accept_rejectMove(iat, false);
171 Psi.rejectMove(iat);
172 }
173 else
174 {
175 FullPrecRealType logGf = -0.5 * dot(deltaR[iat], deltaR[iat]);
176 //Use the force of the particle iat
177 DriftModifier->getDrift(tauovermass, grad_iat, drtmp);
178 dr = drtmp; // upcast for mixed precision
179 dr = W.R[iat] - W.activePos - dr;
180 FullPrecRealType logGb = -oneover2tau * dot(dr, dr);
181 RealType prob = std::norm(ratio) * std::exp(logGb - logGf);
182 bool is_accepted = false;
183
184 if (RandomGen() < prob)
185 {
186 is_accepted = true;
187
188 ++nAcceptTemp;
189 Psi.acceptMove(W, iat, true);
190 rr_accepted += rr;
191 gf_acc *= prob; //accumulate the ratio
192 }
193 else
194 {
195 ++nRejectTemp;
196 Psi.rejectMove(iat);
197 }
198 W.accept_rejectMove(iat, is_accepted);
199 }
200 }
201 }
202 Psi.completeUpdates();
203 W.donePbyP();
204 }
205
206 if (nAcceptTemp > 0)
207 {
208 //need to overwrite the walker properties
209 RealType logpsi(0);
210 {
211 ScopedTimer local_timer(myTimers[DMC_buffer]);
212 thisWalker.Age = 0;
213 logpsi = Psi.updateBuffer(W, w_buffer, recompute);
214 W.saveWalker(thisWalker);
215 }
216 {
217 ScopedTimer local_timer(myTimers[DMC_hamiltonian]);
218 enew = H.evaluateWithToperator(W);
219 }
220 thisWalker.resetProperty(logpsi, Psi.getPhase(), enew, rr_accepted, rr_proposed, 1.0);
221 thisWalker.Weight *= branchEngine->branchWeight(enew, eold);
222 {
223 ScopedTimer local_timer(myTimers[DMC_collectables]);
224 H.auxHevaluate(W, thisWalker);
225 H.saveProperty(thisWalker.getPropertyBase());
226 }
227 }
228 else
229 {
230 //all moves are rejected: does not happen normally with reasonable wavefunctions
231 thisWalker.Age++;
232 thisWalker.Properties(WP::R2ACCEPTED) = 0.0;
233 //weight is set to 0 for traces
234 // consistent w/ no evaluate/auxHevaluate
235 RealType wtmp = thisWalker.Weight;
236 thisWalker.Weight = 0.0;
237 H.rejectedMove(W, thisWalker);
238 thisWalker.Weight = wtmp;
239 ++nAllRejected;
240 enew = eold; //copy back old energy
241 gf_acc = 1.0;
242 thisWalker.Weight *= branchEngine->branchWeight(enew, eold);
243 }
244 #if !defined(REMOVE_TRACEMANAGER)
245 Traces->buffer_sample(W.current_step);
246 #endif
247 {
248 ScopedTimer local_timer(myTimers[DMC_tmoves]);
249 const int NonLocalMoveAcceptedTemp = H.makeNonLocalMoves(W);
250 if (NonLocalMoveAcceptedTemp > 0)
251 {
252 RealType logpsi = Psi.updateBuffer(W, w_buffer, false);
253 W.saveWalker(thisWalker);
254 NonLocalMoveAccepted += NonLocalMoveAcceptedTemp;
255 }
256 }
257 nAccept += nAcceptTemp;
258 nReject += nRejectTemp;
259
260 setMultiplicity(thisWalker);
261 }
262
263 } // namespace qmcplusplus
264