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) 2020 QMCPACK developers.
6 //
7 // File developed by: Bryan Clark, bclark@Princeton.edu, Princeton University
8 // Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
9 // Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
10 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
11 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
12 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
13 // Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore 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 #include <stdexcept>
20
21 #include "TrialWaveFunction.h"
22 #include "ResourceCollection.h"
23 #include "Utilities/IteratorUtility.h"
24 #include "Concurrency/Info.hpp"
25
26 namespace qmcplusplus
27 {
28 typedef enum
29 {
30 V_TIMER = 0,
31 VGL_TIMER,
32 ACCEPT_TIMER,
33 NL_TIMER,
34 RECOMPUTE_TIMER,
35 BUFFER_TIMER,
36 DERIVS_TIMER,
37 PREPAREGROUP_TIMER,
38 TIMER_SKIP
39 } TimerEnum;
40
41 static const std::vector<std::string> suffixes{"V", "VGL", "accept", "NLratio",
42 "recompute", "buffer", "derivs", "preparegroup"};
43
TrialWaveFunction(const std::string & aname,bool tasking,bool create_local_resource)44 TrialWaveFunction::TrialWaveFunction(const std::string& aname, bool tasking, bool create_local_resource)
45 : myName(aname),
46 BufferCursor(0),
47 BufferCursor_scalar(0),
48 PhaseValue(0.0),
49 PhaseDiff(0.0),
50 LogValue(0.0),
51 OneOverM(1.0),
52 use_tasking_(tasking)
53 {
54 if (suffixes.size() != TIMER_SKIP)
55 throw std::runtime_error("TrialWaveFunction::TrialWaveFunction mismatched timer enums and suffixes");
56
57 for (auto& suffix : suffixes)
58 {
59 std::string timer_name = "WaveFunction:" + myName + "::" + suffix;
60 TWF_timers_.push_back(*timer_manager.createTimer(timer_name, timer_level_medium));
61 }
62 }
63
64 /** Destructor
65 *
66 *@warning Have not decided whether Z is cleaned up by TrialWaveFunction
67 * or not. It will depend on I/O implementation.
68 */
~TrialWaveFunction()69 TrialWaveFunction::~TrialWaveFunction() { delete_iter(Z.begin(), Z.end()); }
70
startOptimization()71 void TrialWaveFunction::startOptimization()
72 {
73 for (int i = 0; i < Z.size(); i++)
74 Z[i]->IsOptimizing = true;
75 }
76
stopOptimization()77 void TrialWaveFunction::stopOptimization()
78 {
79 for (int i = 0; i < Z.size(); i++)
80 {
81 Z[i]->finalizeOptimization();
82 Z[i]->IsOptimizing = false;
83 }
84 }
85
86 /** Takes owndership of aterm
87 */
addComponent(WaveFunctionComponent * aterm)88 void TrialWaveFunction::addComponent(WaveFunctionComponent* aterm)
89 {
90 Z.push_back(aterm);
91
92 std::string aname = aterm->ClassName;
93 if (!aterm->myName.empty())
94 aname += ":" + aterm->myName;
95
96 if (aterm->is_fermionic)
97 app_log() << " Added a fermionic WaveFunctionComponent " << aname << std::endl;
98
99 for (auto& suffix : suffixes)
100 WFC_timers_.push_back(*timer_manager.createTimer(aname + "::" + suffix));
101 }
102
103
104 /** return log(|psi|)
105 *
106 * PhaseValue is the phase for the complex wave function
107 */
evaluateLog(ParticleSet & P)108 TrialWaveFunction::RealType TrialWaveFunction::evaluateLog(ParticleSet& P)
109 {
110 ScopedTimer local_timer(TWF_timers_[RECOMPUTE_TIMER]);
111 P.G = 0.0;
112 P.L = 0.0;
113 LogValueType logpsi(0.0);
114 for (int i = 0; i < Z.size(); ++i)
115 {
116 ScopedTimer z_timer(WFC_timers_[RECOMPUTE_TIMER + TIMER_SKIP * i]);
117 #ifndef NDEBUG
118 // Best way I've found yet to quickly see if WFC made it over the wire successfully
119 auto subterm = Z[i]->evaluateLog(P, P.G, P.L);
120 // std::cerr << "evaluate log Z element:" << i << " value: " << subterm << '\n';
121 logpsi += subterm;
122 #else
123 logpsi += Z[i]->evaluateLog(P, P.G, P.L);
124 #endif
125 }
126
127 G = P.G;
128 L = P.L;
129
130 LogValue = std::real(logpsi);
131 PhaseValue = std::imag(logpsi);
132 return LogValue;
133 }
134
mw_evaluateLog(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list)135 void TrialWaveFunction::mw_evaluateLog(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
136 const RefVectorWithLeader<ParticleSet>& p_list)
137 {
138 auto& wf_leader = wf_list.getLeader();
139 auto& p_leader = p_list.getLeader();
140 ScopedTimer local_timer(wf_leader.TWF_timers_[RECOMPUTE_TIMER]);
141
142 constexpr RealType czero(0);
143 const auto g_list(TrialWaveFunction::extractGRefList(wf_list));
144 const auto l_list(TrialWaveFunction::extractLRefList(wf_list));
145
146 // due to historic design issue, ParticleSet holds G and L instead of TrialWaveFunction.
147 // TrialWaveFunction now also holds G and L to move forward but they need to be copied to P.G and P.L
148 // to be compatiable with legacy use pattern.
149 const int num_particles = p_leader.getTotalNum();
150 auto initGandL = [num_particles, czero](TrialWaveFunction& twf, ParticleSet::ParticleGradient_t& grad,
151 ParticleSet::ParticleLaplacian_t& lapl) {
152 grad.resize(num_particles);
153 lapl.resize(num_particles);
154 grad = czero;
155 lapl = czero;
156 twf.LogValue = czero;
157 twf.PhaseValue = czero;
158 };
159 for (int iw = 0; iw < wf_list.size(); iw++)
160 initGandL(wf_list[iw], g_list[iw], l_list[iw]);
161
162 auto& wavefunction_components = wf_leader.Z;
163 const int num_wfc = wf_leader.Z.size();
164 for (int i = 0; i < num_wfc; ++i)
165 {
166 ScopedTimer z_timer(wf_leader.WFC_timers_[RECOMPUTE_TIMER + TIMER_SKIP * i]);
167 const auto wfc_list(extractWFCRefList(wf_list, i));
168 wavefunction_components[i]->mw_evaluateLog(wfc_list, p_list, g_list, l_list);
169 }
170
171 for (int iw = 0; iw < wf_list.size(); iw++)
172 {
173 ParticleSet& pset = p_list[iw];
174 TrialWaveFunction& twf = wf_list[iw];
175
176 for (int i = 0; i < num_wfc; ++i)
177 {
178 twf.LogValue += std::real(twf.Z[i]->LogValue);
179 twf.PhaseValue += std::imag(twf.Z[i]->LogValue);
180 }
181
182 // Ye: temporal workaround to have P.G/L always defined.
183 // remove when KineticEnergy use WF.G/L instead of P.G/L
184 pset.G = twf.G;
185 pset.L = twf.L;
186 }
187 }
188
recompute(const ParticleSet & P)189 void TrialWaveFunction::recompute(const ParticleSet& P)
190 {
191 ScopedTimer local_timer(TWF_timers_[RECOMPUTE_TIMER]);
192 for (int i = 0; i < Z.size(); ++i)
193 {
194 ScopedTimer z_timer(WFC_timers_[RECOMPUTE_TIMER + TIMER_SKIP * i]);
195 Z[i]->recompute(P);
196 }
197 }
198
mw_recompute(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,const std::vector<bool> & recompute)199 void TrialWaveFunction::mw_recompute(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
200 const RefVectorWithLeader<ParticleSet>& p_list,
201 const std::vector<bool>& recompute)
202 {
203 auto& wf_leader = wf_list.getLeader();
204 auto& p_leader = p_list.getLeader();
205 ScopedTimer local_timer(wf_leader.TWF_timers_[RECOMPUTE_TIMER]);
206
207 auto& wavefunction_components = wf_leader.Z;
208 const int num_wfc = wf_leader.Z.size();
209 for (int i = 0; i < num_wfc; ++i)
210 {
211 ScopedTimer z_timer(wf_leader.WFC_timers_[RECOMPUTE_TIMER + TIMER_SKIP * i]);
212 const auto wfc_list(extractWFCRefList(wf_list, i));
213 wavefunction_components[i]->mw_recompute(wfc_list, p_list, recompute);
214 }
215 }
216
evaluateDeltaLog(ParticleSet & P,bool recomputeall)217 TrialWaveFunction::RealType TrialWaveFunction::evaluateDeltaLog(ParticleSet& P, bool recomputeall)
218 {
219 ScopedTimer local_timer(TWF_timers_[RECOMPUTE_TIMER]);
220 P.G = 0.0;
221 P.L = 0.0;
222 LogValueType logpsi(0.0);
223 for (int i = 0; i < Z.size(); ++i)
224 {
225 ScopedTimer z_timer(WFC_timers_[RECOMPUTE_TIMER + TIMER_SKIP * i]);
226 if (Z[i]->Optimizable)
227 logpsi += Z[i]->evaluateLog(P, P.G, P.L);
228 }
229 LogValue = std::real(logpsi);
230 PhaseValue = std::imag(logpsi);
231
232 //In case we need to recompute orbitals, initialize dummy vectors for G and L.
233 //evaluateLog dumps into these variables, and logPsi contribution is discarded.
234 //Only called for non-optimizable orbitals.
235 if (recomputeall)
236 {
237 ParticleSet::ParticleGradient_t dummyG(P.G);
238 ParticleSet::ParticleLaplacian_t dummyL(P.L);
239
240 for (int i = 0; i < Z.size(); ++i)
241 {
242 //update orbitals if its not flagged optimizable, AND recomputeall is true
243 if (!Z[i]->Optimizable)
244 Z[i]->evaluateLog(P, dummyG, dummyL);
245 }
246 }
247 return LogValue;
248 }
249
evaluateDeltaLog(ParticleSet & P,RealType & logpsi_fixed_r,RealType & logpsi_opt_r,ParticleSet::ParticleGradient_t & fixedG,ParticleSet::ParticleLaplacian_t & fixedL)250 void TrialWaveFunction::evaluateDeltaLog(ParticleSet& P,
251 RealType& logpsi_fixed_r,
252 RealType& logpsi_opt_r,
253 ParticleSet::ParticleGradient_t& fixedG,
254 ParticleSet::ParticleLaplacian_t& fixedL)
255 {
256 ScopedTimer local_timer(TWF_timers_[RECOMPUTE_TIMER]);
257 P.G = 0.0;
258 P.L = 0.0;
259 fixedL = 0.0;
260 fixedG = 0.0;
261 LogValueType logpsi_fixed(0.0);
262 LogValueType logpsi_opt(0.0);
263
264 for (int i = 0; i < Z.size(); ++i)
265 {
266 ScopedTimer z_timer(WFC_timers_[RECOMPUTE_TIMER + TIMER_SKIP * i]);
267 if (Z[i]->Optimizable)
268 logpsi_opt += Z[i]->evaluateLog(P, P.G, P.L);
269 else
270 logpsi_fixed += Z[i]->evaluateLog(P, fixedG, fixedL);
271 }
272 P.G += fixedG;
273 P.L += fixedL;
274 convert(logpsi_fixed, logpsi_fixed_r);
275 convert(logpsi_opt, logpsi_opt_r);
276 }
277
278
mw_evaluateDeltaLogSetup(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,std::vector<RealType> & logpsi_fixed_list,std::vector<RealType> & logpsi_opt_list,RefVector<ParticleSet::ParticleGradient_t> & fixedG_list,RefVector<ParticleSet::ParticleLaplacian_t> & fixedL_list)279 void TrialWaveFunction::mw_evaluateDeltaLogSetup(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
280 const RefVectorWithLeader<ParticleSet>& p_list,
281 std::vector<RealType>& logpsi_fixed_list,
282 std::vector<RealType>& logpsi_opt_list,
283 RefVector<ParticleSet::ParticleGradient_t>& fixedG_list,
284 RefVector<ParticleSet::ParticleLaplacian_t>& fixedL_list)
285 {
286 auto& wf_leader = wf_list.getLeader();
287 auto& p_leader = p_list.getLeader();
288 ScopedTimer local_timer(wf_leader.TWF_timers_[RECOMPUTE_TIMER]);
289 constexpr RealType czero(0);
290 const int num_particles = p_leader.getTotalNum();
291 const auto g_list(TrialWaveFunction::extractGRefList(wf_list));
292 const auto l_list(TrialWaveFunction::extractLRefList(wf_list));
293
294 auto initGandL = [num_particles, czero](TrialWaveFunction& twf, ParticleSet::ParticleGradient_t& grad,
295 ParticleSet::ParticleLaplacian_t& lapl) {
296 grad.resize(num_particles);
297 lapl.resize(num_particles);
298 grad = czero;
299 lapl = czero;
300 twf.LogValue = czero;
301 twf.PhaseValue = czero;
302 };
303 for (int iw = 0; iw < wf_list.size(); iw++)
304 initGandL(wf_list[iw], g_list[iw], l_list[iw]);
305 auto& wavefunction_components = wf_leader.Z;
306 const int num_wfc = wf_leader.Z.size();
307 for (int i = 0; i < num_wfc; ++i)
308 {
309 ScopedTimer z_timer(wf_leader.WFC_timers_[RECOMPUTE_TIMER + TIMER_SKIP * i]);
310 const auto wfc_list(extractWFCRefList(wf_list, i));
311 if (wavefunction_components[i]->Optimizable)
312 {
313 wavefunction_components[i]->mw_evaluateLog(wfc_list, p_list, g_list, l_list);
314 for (int iw = 0; iw < wf_list.size(); iw++)
315 logpsi_opt_list[iw] += std::real(wfc_list[iw].LogValue);
316 }
317 else
318 {
319 wavefunction_components[i]->mw_evaluateLog(wfc_list, p_list, fixedG_list, fixedL_list);
320 for (int iw = 0; iw < wf_list.size(); iw++)
321 logpsi_fixed_list[iw] += std::real(wfc_list[iw].LogValue);
322 }
323 }
324
325 // Temporary workaround to have P.G/L always defined.
326 // remove when KineticEnergy use WF.G/L instead of P.G/L
327 auto addAndCopyToP = [](ParticleSet& pset, TrialWaveFunction& twf, ParticleSet::ParticleGradient_t& grad,
328 ParticleSet::ParticleLaplacian_t& lapl) {
329 pset.G = twf.G + grad;
330 pset.L = twf.L + lapl;
331 };
332 for (int iw = 0; iw < wf_list.size(); iw++)
333 addAndCopyToP(p_list[iw], wf_list[iw], fixedG_list[iw], fixedL_list[iw]);
334 }
335
336
mw_evaluateDeltaLog(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,std::vector<RealType> & logpsi_list,RefVector<ParticleSet::ParticleGradient_t> & dummyG_list,RefVector<ParticleSet::ParticleLaplacian_t> & dummyL_list,bool recompute)337 void TrialWaveFunction::mw_evaluateDeltaLog(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
338 const RefVectorWithLeader<ParticleSet>& p_list,
339 std::vector<RealType>& logpsi_list,
340 RefVector<ParticleSet::ParticleGradient_t>& dummyG_list,
341 RefVector<ParticleSet::ParticleLaplacian_t>& dummyL_list,
342 bool recompute)
343 {
344 auto& p_leader = p_list.getLeader();
345 auto& wf_leader = wf_list.getLeader();
346 ScopedTimer local_timer(wf_leader.TWF_timers_[RECOMPUTE_TIMER]);
347 constexpr RealType czero(0);
348 int num_particles = p_leader.getTotalNum();
349 const auto g_list(TrialWaveFunction::extractGRefList(wf_list));
350 const auto l_list(TrialWaveFunction::extractLRefList(wf_list));
351
352 // Initialize various members of the wavefunction, grad, and laplacian
353 auto initGandL = [num_particles, czero](TrialWaveFunction& twf, ParticleSet::ParticleGradient_t& grad,
354 ParticleSet::ParticleLaplacian_t& lapl) {
355 grad.resize(num_particles);
356 lapl.resize(num_particles);
357 grad = czero;
358 lapl = czero;
359 twf.LogValue = czero;
360 twf.PhaseValue = czero;
361 };
362 for (int iw = 0; iw < wf_list.size(); iw++)
363 initGandL(wf_list[iw], g_list[iw], l_list[iw]);
364
365 // Get wavefunction components (assumed the same for every WF in the list)
366 auto& wavefunction_components = wf_leader.Z;
367 const int num_wfc = wf_leader.Z.size();
368
369 // Loop over the wavefunction components
370 for (int i = 0; i < num_wfc; ++i)
371 if (wavefunction_components[i]->Optimizable)
372 {
373 ScopedTimer z_timer(wf_leader.WFC_timers_[RECOMPUTE_TIMER + TIMER_SKIP * i]);
374 const auto wfc_list(extractWFCRefList(wf_list, i));
375 wavefunction_components[i]->mw_evaluateLog(wfc_list, p_list, g_list, l_list);
376 for (int iw = 0; iw < wf_list.size(); iw++)
377 logpsi_list[iw] += std::real(wfc_list[iw].LogValue);
378 }
379
380 // Temporary workaround to have P.G/L always defined.
381 // remove when KineticEnergy use WF.G/L instead of P.G/L
382 auto copyToP = [](ParticleSet& pset, TrialWaveFunction& twf) {
383 pset.G = twf.G;
384 pset.L = twf.L;
385 };
386 for (int iw = 0; iw < wf_list.size(); iw++)
387 copyToP(p_list[iw], wf_list[iw]);
388
389 // Recompute is usually used to prepare the wavefunction for NLPP derivatives.
390 // (e.g compute the matrix inverse for determinants)
391 // Call mw_evaluateLog for the wavefunction components that were skipped previously.
392 // Ignore logPsi, G and L.
393 if (recompute)
394 for (int i = 0; i < num_wfc; ++i)
395 if (!wavefunction_components[i]->Optimizable)
396 {
397 ScopedTimer z_timer(wf_leader.WFC_timers_[RECOMPUTE_TIMER + TIMER_SKIP * i]);
398 const auto wfc_list(extractWFCRefList(wf_list, i));
399 wavefunction_components[i]->mw_evaluateLog(wfc_list, p_list, dummyG_list, dummyL_list);
400 }
401 }
402
403
404 /*void TrialWaveFunction::evaluateHessian(ParticleSet & P, int iat, HessType& grad_grad_psi)
405 {
406 std::vector<WaveFunctionComponent*>::iterator it(Z.begin());
407 std::vector<WaveFunctionComponent*>::iterator it_end(Z.end());
408
409 grad_grad_psi=0.0;
410
411 for (; it!=it_end; ++it)
412 {
413 HessType tmp_hess;
414 (*it)->evaluateHessian(P, iat, tmp_hess);
415 grad_grad_psi+=tmp_hess;
416 }
417 }*/
418
evaluateHessian(ParticleSet & P,HessVector_t & grad_grad_psi)419 void TrialWaveFunction::evaluateHessian(ParticleSet& P, HessVector_t& grad_grad_psi)
420 {
421 std::vector<WaveFunctionComponent*>::iterator it(Z.begin());
422 std::vector<WaveFunctionComponent*>::iterator it_end(Z.end());
423
424 grad_grad_psi.resize(P.getTotalNum());
425
426 for (int i = 0; i < Z.size(); i++)
427 {
428 HessVector_t tmp_hess(grad_grad_psi);
429 tmp_hess = 0.0;
430 Z[i]->evaluateHessian(P, tmp_hess);
431 grad_grad_psi += tmp_hess;
432 // app_log()<<"TrialWavefunction::tmp_hess = "<<tmp_hess<< std::endl;
433 // app_log()<< std::endl<< std::endl;
434 }
435 // app_log()<<" TrialWavefunction::Hessian = "<<grad_grad_psi<< std::endl;
436 }
437
calcRatio(ParticleSet & P,int iat,ComputeType ct)438 TrialWaveFunction::ValueType TrialWaveFunction::calcRatio(ParticleSet& P, int iat, ComputeType ct)
439 {
440 ScopedTimer local_timer(TWF_timers_[V_TIMER]);
441 PsiValueType r(1.0);
442 for (int i = 0; i < Z.size(); i++)
443 if (ct == ComputeType::ALL || (Z[i]->is_fermionic && ct == ComputeType::FERMIONIC) ||
444 (!Z[i]->is_fermionic && ct == ComputeType::NONFERMIONIC))
445 {
446 ScopedTimer z_timer(WFC_timers_[V_TIMER + TIMER_SKIP * i]);
447 r *= Z[i]->ratio(P, iat);
448 }
449 return static_cast<ValueType>(r);
450 }
451
mw_calcRatio(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,int iat,std::vector<PsiValueType> & ratios,ComputeType ct)452 void TrialWaveFunction::mw_calcRatio(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
453 const RefVectorWithLeader<ParticleSet>& p_list,
454 int iat,
455 std::vector<PsiValueType>& ratios,
456 ComputeType ct)
457 {
458 const int num_wf = wf_list.size();
459 ratios.resize(num_wf);
460 std::fill(ratios.begin(), ratios.end(), PsiValueType(1));
461
462 auto& wf_leader = wf_list.getLeader();
463 ScopedTimer local_timer(wf_leader.TWF_timers_[V_TIMER]);
464 const int num_wfc = wf_leader.Z.size();
465 auto& wavefunction_components = wf_leader.Z;
466
467 std::vector<PsiValueType> ratios_z(num_wf);
468 for (int i = 0; i < num_wfc; i++)
469 {
470 if (ct == ComputeType::ALL || (wavefunction_components[i]->is_fermionic && ct == ComputeType::FERMIONIC) ||
471 (!wavefunction_components[i]->is_fermionic && ct == ComputeType::NONFERMIONIC))
472 {
473 ScopedTimer z_timer(wf_leader.WFC_timers_[V_TIMER + TIMER_SKIP * i]);
474 const auto wfc_list(extractWFCRefList(wf_list, i));
475 wavefunction_components[i]->mw_calcRatio(wfc_list, p_list, iat, ratios_z);
476 for (int iw = 0; iw < wf_list.size(); iw++)
477 ratios[iw] *= ratios_z[iw];
478 }
479 }
480 for (int iw = 0; iw < wf_list.size(); iw++)
481 wf_list[iw].PhaseDiff = std::imag(std::arg(ratios[iw]));
482 }
483
prepareGroup(ParticleSet & P,int ig)484 void TrialWaveFunction::prepareGroup(ParticleSet& P, int ig)
485 {
486 for (int i = 0; i < Z.size(); ++i)
487 Z[i]->prepareGroup(P, ig);
488 }
489
mw_prepareGroup(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,int ig)490 void TrialWaveFunction::mw_prepareGroup(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
491 const RefVectorWithLeader<ParticleSet>& p_list,
492 int ig)
493 {
494 auto& wf_leader = wf_list.getLeader();
495 ScopedTimer local_timer(wf_leader.TWF_timers_[PREPAREGROUP_TIMER]);
496 const int num_wfc = wf_leader.Z.size();
497 auto& wavefunction_components = wf_leader.Z;
498
499 for (int i = 0; i < num_wfc; i++)
500 {
501 ScopedTimer z_timer(wf_leader.WFC_timers_[PREPAREGROUP_TIMER + TIMER_SKIP * i]);
502 const auto wfc_list(extractWFCRefList(wf_list, i));
503 wavefunction_components[i]->mw_prepareGroup(wfc_list, p_list, ig);
504 }
505 }
506
evalGrad(ParticleSet & P,int iat)507 TrialWaveFunction::GradType TrialWaveFunction::evalGrad(ParticleSet& P, int iat)
508 {
509 ScopedTimer local_timer(TWF_timers_[VGL_TIMER]);
510 GradType grad_iat;
511 for (int i = 0; i < Z.size(); ++i)
512 {
513 ScopedTimer z_timer(WFC_timers_[VGL_TIMER + TIMER_SKIP * i]);
514 grad_iat += Z[i]->evalGrad(P, iat);
515 }
516 return grad_iat;
517 }
518
evalGradWithSpin(ParticleSet & P,int iat,ComplexType & spingrad)519 TrialWaveFunction::GradType TrialWaveFunction::evalGradWithSpin(ParticleSet& P, int iat, ComplexType& spingrad)
520 {
521 ScopedTimer local_timer(TWF_timers_[VGL_TIMER]);
522 GradType grad_iat;
523 spingrad = 0;
524 for (int i = 0; i < Z.size(); ++i)
525 {
526 ScopedTimer z_timer(WFC_timers_[VGL_TIMER + TIMER_SKIP * i]);
527 grad_iat += Z[i]->evalGradWithSpin(P, iat, spingrad);
528 }
529 return grad_iat;
530 }
531
mw_evalGrad(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,int iat,std::vector<GradType> & grad_now)532 void TrialWaveFunction::mw_evalGrad(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
533 const RefVectorWithLeader<ParticleSet>& p_list,
534 int iat,
535 std::vector<GradType>& grad_now)
536 {
537 const int num_wf = wf_list.size();
538 grad_now.resize(num_wf);
539 std::fill(grad_now.begin(), grad_now.end(), GradType(0));
540
541 auto& wf_leader = wf_list.getLeader();
542 ScopedTimer local_timer(wf_leader.TWF_timers_[VGL_TIMER]);
543 // Right now mw_evalGrad can only be called through an concrete instance of a wavefunctioncomponent
544 const int num_wfc = wf_leader.Z.size();
545 auto& wavefunction_components = wf_leader.Z;
546
547 std::vector<GradType> grad_now_z(num_wf);
548 for (int i = 0; i < num_wfc; ++i)
549 {
550 ScopedTimer localtimer(wf_leader.WFC_timers_[VGL_TIMER + TIMER_SKIP * i]);
551 const auto wfc_list(extractWFCRefList(wf_list, i));
552 wavefunction_components[i]->mw_evalGrad(wfc_list, p_list, iat, grad_now_z);
553 for (int iw = 0; iw < wf_list.size(); iw++)
554 grad_now[iw] += grad_now_z[iw];
555 }
556 }
557
558
559 // Evaluates the gradient w.r.t. to the source of the Laplacian
560 // w.r.t. to the electrons of the wave function.
evalGradSource(ParticleSet & P,ParticleSet & source,int iat)561 TrialWaveFunction::GradType TrialWaveFunction::evalGradSource(ParticleSet& P, ParticleSet& source, int iat)
562 {
563 GradType grad_iat = GradType();
564 for (int i = 0; i < Z.size(); ++i)
565 grad_iat += Z[i]->evalGradSource(P, source, iat);
566 return grad_iat;
567 }
568
evalGradSource(ParticleSet & P,ParticleSet & source,int iat,TinyVector<ParticleSet::ParticleGradient_t,OHMMS_DIM> & grad_grad,TinyVector<ParticleSet::ParticleLaplacian_t,OHMMS_DIM> & lapl_grad)569 TrialWaveFunction::GradType TrialWaveFunction::evalGradSource(
570 ParticleSet& P,
571 ParticleSet& source,
572 int iat,
573 TinyVector<ParticleSet::ParticleGradient_t, OHMMS_DIM>& grad_grad,
574 TinyVector<ParticleSet::ParticleLaplacian_t, OHMMS_DIM>& lapl_grad)
575 {
576 GradType grad_iat = GradType();
577 for (int dim = 0; dim < OHMMS_DIM; dim++)
578 for (int i = 0; i < grad_grad[0].size(); i++)
579 {
580 grad_grad[dim][i] = GradType();
581 lapl_grad[dim][i] = 0.0;
582 }
583 for (int i = 0; i < Z.size(); ++i)
584 grad_iat += Z[i]->evalGradSource(P, source, iat, grad_grad, lapl_grad);
585 return grad_iat;
586 }
587
calcRatioGrad(ParticleSet & P,int iat,GradType & grad_iat)588 TrialWaveFunction::ValueType TrialWaveFunction::calcRatioGrad(ParticleSet& P, int iat, GradType& grad_iat)
589 {
590 ScopedTimer local_timer(TWF_timers_[VGL_TIMER]);
591 grad_iat = 0.0;
592 PsiValueType r(1.0);
593 if (use_tasking_)
594 {
595 std::vector<GradType> grad_components(Z.size(), GradType(0.0));
596 std::vector<PsiValueType> ratio_components(Z.size(), 0.0);
597 #pragma omp taskloop default(shared)
598 for (int i = 0; i < Z.size(); ++i)
599 {
600 ScopedTimer z_timer(WFC_timers_[VGL_TIMER + TIMER_SKIP * i]);
601 ratio_components[i] = Z[i]->ratioGrad(P, iat, grad_components[i]);
602 }
603
604 for (int i = 0; i < Z.size(); ++i)
605 {
606 grad_iat += grad_components[i];
607 r *= ratio_components[i];
608 }
609 }
610 else
611 for (int i = 0; i < Z.size(); ++i)
612 {
613 ScopedTimer z_timer(WFC_timers_[VGL_TIMER + TIMER_SKIP * i]);
614 r *= Z[i]->ratioGrad(P, iat, grad_iat);
615 }
616 LogValueType logratio = convertValueToLog(r);
617 PhaseDiff = std::imag(logratio);
618 return static_cast<ValueType>(r);
619 }
620
calcRatioGradWithSpin(ParticleSet & P,int iat,GradType & grad_iat,ComplexType & spingrad_iat)621 TrialWaveFunction::ValueType TrialWaveFunction::calcRatioGradWithSpin(ParticleSet& P,
622 int iat,
623 GradType& grad_iat,
624 ComplexType& spingrad_iat)
625 {
626 ScopedTimer local_timer(TWF_timers_[VGL_TIMER]);
627 grad_iat = 0.0;
628 spingrad_iat = 0.0;
629 PsiValueType r(1.0);
630 for (int i = 0; i < Z.size(); ++i)
631 {
632 ScopedTimer z_timer(WFC_timers_[VGL_TIMER + TIMER_SKIP * i]);
633 r *= Z[i]->ratioGradWithSpin(P, iat, grad_iat, spingrad_iat);
634 }
635
636 LogValueType logratio = convertValueToLog(r);
637 PhaseDiff = std::imag(logratio);
638 return static_cast<ValueType>(r);
639 }
640
mw_calcRatioGrad(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,int iat,std::vector<PsiValueType> & ratios,std::vector<GradType> & grad_new)641 void TrialWaveFunction::mw_calcRatioGrad(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
642 const RefVectorWithLeader<ParticleSet>& p_list,
643 int iat,
644 std::vector<PsiValueType>& ratios,
645 std::vector<GradType>& grad_new)
646 {
647 const int num_wf = wf_list.size();
648 grad_new.resize(num_wf);
649 std::fill(grad_new.begin(), grad_new.end(), GradType(0));
650 ratios.resize(num_wf);
651 std::fill(ratios.begin(), ratios.end(), PsiValueType(1));
652
653 auto& wf_leader = wf_list.getLeader();
654 ScopedTimer local_timer(wf_leader.TWF_timers_[VGL_TIMER]);
655 const int num_wfc = wf_leader.Z.size();
656 auto& wavefunction_components = wf_leader.Z;
657
658 if (wf_leader.use_tasking_)
659 {
660 std::vector<std::vector<PsiValueType>> ratios_components(num_wfc, std::vector<PsiValueType>(wf_list.size()));
661 std::vector<std::vector<GradType>> grads_components(num_wfc, std::vector<GradType>(wf_list.size()));
662 #pragma omp taskloop default(shared)
663 for (int i = 0; i < num_wfc; ++i)
664 {
665 ScopedTimer z_timer(wf_leader.WFC_timers_[VGL_TIMER + TIMER_SKIP * i]);
666 const auto wfc_list(extractWFCRefList(wf_list, i));
667 wavefunction_components[i]->mw_ratioGrad(wfc_list, p_list, iat, ratios_components[i], grads_components[i]);
668 }
669
670 for (int i = 0; i < num_wfc; ++i)
671 for (int iw = 0; iw < wf_list.size(); iw++)
672 {
673 ratios[iw] *= ratios_components[i][iw];
674 grad_new[iw] += grads_components[i][iw];
675 }
676 }
677 else
678 {
679 std::vector<PsiValueType> ratios_z(wf_list.size());
680 for (int i = 0; i < num_wfc; ++i)
681 {
682 ScopedTimer z_timer(wf_leader.WFC_timers_[VGL_TIMER + TIMER_SKIP * i]);
683 const auto wfc_list(extractWFCRefList(wf_list, i));
684 wavefunction_components[i]->mw_ratioGrad(wfc_list, p_list, iat, ratios_z, grad_new);
685 for (int iw = 0; iw < wf_list.size(); iw++)
686 ratios[iw] *= ratios_z[iw];
687 }
688 }
689 for (int iw = 0; iw < wf_list.size(); iw++)
690 wf_list[iw].PhaseDiff = std::imag(std::arg(ratios[iw]));
691 }
692
printGL(ParticleSet::ParticleGradient_t & G,ParticleSet::ParticleLaplacian_t & L,std::string tag)693 void TrialWaveFunction::printGL(ParticleSet::ParticleGradient_t& G,
694 ParticleSet::ParticleLaplacian_t& L,
695 std::string tag)
696 {
697 std::ostringstream o;
698 o << "--- reporting " << tag << std::endl << " ---" << std::endl;
699 for (int iat = 0; iat < L.size(); iat++)
700 o << "index: " << std::fixed << iat << std::scientific << " G: " << G[iat][0] << " " << G[iat][1] << " "
701 << G[iat][2] << " L: " << L[iat] << std::endl;
702 o << "--- end ---" << std::endl;
703 std::cout << o.str();
704 }
705
706 /** restore to the original state
707 * @param iat index of the particle with a trial move
708 *
709 * The proposed move of the iath particle is rejected.
710 * All the temporary data should be restored to the state prior to the move.
711 */
rejectMove(int iat)712 void TrialWaveFunction::rejectMove(int iat)
713 {
714 for (int i = 0; i < Z.size(); i++)
715 Z[i]->restore(iat);
716 PhaseDiff = 0;
717 }
718
719 /** update the state with the new data
720 * @param P ParticleSet
721 * @param iat index of the particle with a trial move
722 *
723 * The proposed move of the iath particle is accepted.
724 * All the temporary data should be incorporated so that the next move is valid.
725 */
acceptMove(ParticleSet & P,int iat,bool safe_to_delay)726 void TrialWaveFunction::acceptMove(ParticleSet& P, int iat, bool safe_to_delay)
727 {
728 ScopedTimer local_timer(TWF_timers_[ACCEPT_TIMER]);
729 #pragma omp taskloop default(shared) if (use_tasking_)
730 for (int i = 0; i < Z.size(); i++)
731 {
732 ScopedTimer z_timer(WFC_timers_[ACCEPT_TIMER + TIMER_SKIP * i]);
733 Z[i]->acceptMove(P, iat, safe_to_delay);
734 }
735 PhaseValue += PhaseDiff;
736 PhaseDiff = 0.0;
737 LogValue = 0;
738 for (int i = 0; i < Z.size(); i++)
739 LogValue += std::real(Z[i]->LogValue);
740 }
741
mw_accept_rejectMove(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,int iat,const std::vector<bool> & isAccepted,bool safe_to_delay)742 void TrialWaveFunction::mw_accept_rejectMove(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
743 const RefVectorWithLeader<ParticleSet>& p_list,
744 int iat,
745 const std::vector<bool>& isAccepted,
746 bool safe_to_delay)
747 {
748 auto& wf_leader = wf_list.getLeader();
749 ScopedTimer local_timer(wf_leader.TWF_timers_[ACCEPT_TIMER]);
750 const int num_wfc = wf_leader.Z.size();
751 auto& wavefunction_components = wf_leader.Z;
752
753 for (int iw = 0; iw < wf_list.size(); iw++)
754 if (isAccepted[iw])
755 {
756 wf_list[iw].LogValue = 0;
757 wf_list[iw].PhaseValue = 0;
758 }
759
760 #pragma omp taskloop default(shared) if (wf_leader.use_tasking_)
761 for (int i = 0; i < num_wfc; i++)
762 {
763 ScopedTimer z_timer(wf_leader.WFC_timers_[ACCEPT_TIMER + TIMER_SKIP * i]);
764 const auto wfc_list(extractWFCRefList(wf_list, i));
765 wavefunction_components[i]->mw_accept_rejectMove(wfc_list, p_list, iat, isAccepted, safe_to_delay);
766 for (int iw = 0; iw < wf_list.size(); iw++)
767 if (isAccepted[iw])
768 {
769 wf_list[iw].LogValue += std::real(wfc_list[iw].LogValue);
770 wf_list[iw].PhaseValue += std::imag(wfc_list[iw].LogValue);
771 }
772 }
773 }
774
completeUpdates()775 void TrialWaveFunction::completeUpdates()
776 {
777 ScopedTimer local_timer(TWF_timers_[ACCEPT_TIMER]);
778 for (int i = 0; i < Z.size(); i++)
779 {
780 ScopedTimer z_timer(WFC_timers_[ACCEPT_TIMER + TIMER_SKIP * i]);
781 Z[i]->completeUpdates();
782 }
783 }
784
mw_completeUpdates(const RefVectorWithLeader<TrialWaveFunction> & wf_list)785 void TrialWaveFunction::mw_completeUpdates(const RefVectorWithLeader<TrialWaveFunction>& wf_list)
786 {
787 auto& wf_leader = wf_list.getLeader();
788 ScopedTimer local_timer(wf_leader.TWF_timers_[ACCEPT_TIMER]);
789 const int num_wfc = wf_leader.Z.size();
790 auto& wavefunction_components = wf_leader.Z;
791
792 for (int i = 0; i < num_wfc; i++)
793 {
794 ScopedTimer z_timer(wf_leader.WFC_timers_[ACCEPT_TIMER + TIMER_SKIP * i]);
795 const auto wfc_list(extractWFCRefList(wf_list, i));
796 wavefunction_components[i]->mw_completeUpdates(wfc_list);
797 }
798 }
799
evaluateGL(ParticleSet & P,bool fromscratch)800 TrialWaveFunction::LogValueType TrialWaveFunction::evaluateGL(ParticleSet& P, bool fromscratch)
801 {
802 ScopedTimer local_timer(TWF_timers_[BUFFER_TIMER]);
803 P.G = 0.0;
804 P.L = 0.0;
805 LogValueType logpsi(0.0);
806 for (int i = 0; i < Z.size(); ++i)
807 {
808 ScopedTimer z_timer(WFC_timers_[BUFFER_TIMER + TIMER_SKIP * i]);
809 logpsi += Z[i]->evaluateGL(P, P.G, P.L, fromscratch);
810 }
811
812 // Ye: temporal workaround to have WF.G/L always defined.
813 // remove when KineticEnergy use WF.G/L instead of P.G/L
814 G = P.G;
815 L = P.L;
816 LogValue = std::real(logpsi);
817 PhaseValue = std::imag(logpsi);
818 return logpsi;
819 }
820
mw_evaluateGL(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,bool fromscratch)821 void TrialWaveFunction::mw_evaluateGL(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
822 const RefVectorWithLeader<ParticleSet>& p_list,
823 bool fromscratch)
824 {
825 auto& p_leader = p_list.getLeader();
826 auto& wf_leader = wf_list.getLeader();
827 ScopedTimer local_timer(wf_leader.TWF_timers_[BUFFER_TIMER]);
828
829 constexpr RealType czero(0);
830 const auto g_list(TrialWaveFunction::extractGRefList(wf_list));
831 const auto l_list(TrialWaveFunction::extractLRefList(wf_list));
832
833 const int num_particles = p_leader.getTotalNum();
834 for (TrialWaveFunction& wfs : wf_list)
835 {
836 wfs.G.resize(num_particles);
837 wfs.L.resize(num_particles);
838 wfs.G = czero;
839 wfs.L = czero;
840 wfs.LogValue = czero;
841 wfs.PhaseValue = czero;
842 }
843
844 auto& wavefunction_components = wf_leader.Z;
845 const int num_wfc = wf_leader.Z.size();
846
847 for (int i = 0; i < num_wfc; ++i)
848 {
849 ScopedTimer z_timer(wf_leader.WFC_timers_[BUFFER_TIMER + TIMER_SKIP * i]);
850 const auto wfc_list(extractWFCRefList(wf_list, i));
851 wavefunction_components[i]->mw_evaluateGL(wfc_list, p_list, g_list, l_list, fromscratch);
852 }
853
854 for (int iw = 0; iw < wf_list.size(); iw++)
855 {
856 ParticleSet& pset = p_list[iw];
857 TrialWaveFunction& twf = wf_list[iw];
858
859 for (int i = 0; i < num_wfc; ++i)
860 {
861 twf.LogValue += std::real(twf.Z[i]->LogValue);
862 twf.PhaseValue += std::imag(twf.Z[i]->LogValue);
863 }
864
865 // Ye: temporal workaround to have P.G/L always defined.
866 // remove when KineticEnergy use WF.G/L instead of P.G/L
867 pset.G = twf.G;
868 pset.L = twf.L;
869 }
870 }
871
872
checkInVariables(opt_variables_type & active)873 void TrialWaveFunction::checkInVariables(opt_variables_type& active)
874 {
875 for (int i = 0; i < Z.size(); i++)
876 Z[i]->checkInVariables(active);
877 }
878
checkOutVariables(const opt_variables_type & active)879 void TrialWaveFunction::checkOutVariables(const opt_variables_type& active)
880 {
881 for (int i = 0; i < Z.size(); i++)
882 Z[i]->checkOutVariables(active);
883 }
884
resetParameters(const opt_variables_type & active)885 void TrialWaveFunction::resetParameters(const opt_variables_type& active)
886 {
887 for (int i = 0; i < Z.size(); i++)
888 Z[i]->resetParameters(active);
889 }
890
reportStatus(std::ostream & os)891 void TrialWaveFunction::reportStatus(std::ostream& os)
892 {
893 for (int i = 0; i < Z.size(); i++)
894 Z[i]->reportStatus(os);
895 }
896
getLogs(std::vector<RealType> & lvals)897 void TrialWaveFunction::getLogs(std::vector<RealType>& lvals)
898 {
899 lvals.resize(Z.size(), 0);
900 for (int i = 0; i < Z.size(); i++)
901 {
902 lvals[i] = std::real(Z[i]->LogValue);
903 }
904 }
905
getPhases(std::vector<RealType> & pvals)906 void TrialWaveFunction::getPhases(std::vector<RealType>& pvals)
907 {
908 pvals.resize(Z.size(), 0);
909 for (int i = 0; i < Z.size(); i++)
910 {
911 pvals[i] = std::imag(Z[i]->LogValue);
912 }
913 }
914
registerData(ParticleSet & P,WFBufferType & buf)915 void TrialWaveFunction::registerData(ParticleSet& P, WFBufferType& buf)
916 {
917 ScopedTimer local_timer(TWF_timers_[BUFFER_TIMER]);
918 //save the current position
919 BufferCursor = buf.current();
920 BufferCursor_scalar = buf.current_scalar();
921 for (int i = 0; i < Z.size(); ++i)
922 {
923 ScopedTimer z_timer(WFC_timers_[BUFFER_TIMER + TIMER_SKIP * i]);
924 Z[i]->registerData(P, buf);
925 }
926 buf.add(PhaseValue);
927 buf.add(LogValue);
928 }
929
debugOnlyCheckBuffer(WFBufferType & buffer)930 void TrialWaveFunction::debugOnlyCheckBuffer(WFBufferType& buffer)
931 {
932 #ifndef NDEBUG
933 if (buffer.size() < buffer.current() + buffer.current_scalar() * sizeof(FullPrecRealType))
934 {
935 std::ostringstream assert_message;
936 assert_message << "On thread:" << Concurrency::getWorkerId<>() << " buf_list[iw].get().size():" << buffer.size()
937 << " < buf_list[iw].get().current():" << buffer.current()
938 << " + buf.current_scalar():" << buffer.current_scalar()
939 << " * sizeof(FullPrecRealType):" << sizeof(FullPrecRealType) << '\n';
940 throw std::runtime_error(assert_message.str());
941 }
942 #endif
943 }
944
updateBuffer(ParticleSet & P,WFBufferType & buf,bool fromscratch)945 TrialWaveFunction::RealType TrialWaveFunction::updateBuffer(ParticleSet& P, WFBufferType& buf, bool fromscratch)
946 {
947 ScopedTimer local_timer(TWF_timers_[BUFFER_TIMER]);
948 P.G = 0.0;
949 P.L = 0.0;
950 buf.rewind(BufferCursor, BufferCursor_scalar);
951 LogValueType logpsi(0.0);
952 for (int i = 0; i < Z.size(); ++i)
953 {
954 ScopedTimer z_timer(WFC_timers_[BUFFER_TIMER + TIMER_SKIP * i]);
955 logpsi += Z[i]->updateBuffer(P, buf, fromscratch);
956 }
957
958 G = P.G;
959 L = P.L;
960
961 LogValue = std::real(logpsi);
962 PhaseValue = std::imag(logpsi);
963 //printGL(P.G,P.L);
964 buf.put(PhaseValue);
965 buf.put(LogValue);
966 // Ye: temperal added check, to be removed
967 debugOnlyCheckBuffer(buf);
968 return LogValue;
969 }
970
copyFromBuffer(ParticleSet & P,WFBufferType & buf)971 void TrialWaveFunction::copyFromBuffer(ParticleSet& P, WFBufferType& buf)
972 {
973 ScopedTimer local_timer(TWF_timers_[BUFFER_TIMER]);
974 buf.rewind(BufferCursor, BufferCursor_scalar);
975 for (int i = 0; i < Z.size(); ++i)
976 {
977 ScopedTimer z_timer(WFC_timers_[BUFFER_TIMER + TIMER_SKIP * i]);
978 Z[i]->copyFromBuffer(P, buf);
979 }
980 //get the gradients and laplacians from the buffer
981 buf.get(PhaseValue);
982 buf.get(LogValue);
983 debugOnlyCheckBuffer(buf);
984 }
985
evaluateRatios(const VirtualParticleSet & VP,std::vector<ValueType> & ratios,ComputeType ct)986 void TrialWaveFunction::evaluateRatios(const VirtualParticleSet& VP, std::vector<ValueType>& ratios, ComputeType ct)
987 {
988 ScopedTimer local_timer(TWF_timers_[NL_TIMER]);
989 assert(VP.getTotalNum() == ratios.size());
990 std::vector<ValueType> t(ratios.size());
991 std::fill(ratios.begin(), ratios.end(), 1.0);
992 for (int i = 0; i < Z.size(); ++i)
993 if (ct == ComputeType::ALL || (Z[i]->is_fermionic && ct == ComputeType::FERMIONIC) ||
994 (!Z[i]->is_fermionic && ct == ComputeType::NONFERMIONIC))
995 {
996 ScopedTimer z_timer(WFC_timers_[NL_TIMER + TIMER_SKIP * i]);
997 Z[i]->evaluateRatios(VP, t);
998 for (int j = 0; j < ratios.size(); ++j)
999 ratios[j] *= t[j];
1000 }
1001 }
1002
mw_evaluateRatios(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVector<const VirtualParticleSet> & vp_list,const RefVector<std::vector<ValueType>> & ratios_list,ComputeType ct)1003 void TrialWaveFunction::mw_evaluateRatios(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
1004 const RefVector<const VirtualParticleSet>& vp_list,
1005 const RefVector<std::vector<ValueType>>& ratios_list,
1006 ComputeType ct)
1007 {
1008 auto& wf_leader = wf_list.getLeader();
1009 ScopedTimer local_timer(wf_leader.TWF_timers_[NL_TIMER]);
1010 auto& wavefunction_components = wf_leader.Z;
1011 std::vector<std::vector<ValueType>> t(ratios_list.size());
1012 for (int iw = 0; iw < wf_list.size(); iw++)
1013 {
1014 std::vector<ValueType>& ratios = ratios_list[iw];
1015 assert(vp_list[iw].get().getTotalNum() == ratios.size());
1016 std::fill(ratios.begin(), ratios.end(), 1.0);
1017 t[iw].resize(ratios.size());
1018 }
1019
1020 for (int i = 0; i < wavefunction_components.size(); i++)
1021 if (ct == ComputeType::ALL || (wavefunction_components[i]->is_fermionic && ct == ComputeType::FERMIONIC) ||
1022 (!wavefunction_components[i]->is_fermionic && ct == ComputeType::NONFERMIONIC))
1023 {
1024 ScopedTimer z_timer(wf_leader.WFC_timers_[NL_TIMER + TIMER_SKIP * i]);
1025 const auto wfc_list(extractWFCRefList(wf_list, i));
1026 wavefunction_components[i]->mw_evaluateRatios(wfc_list, vp_list, t);
1027 for (int iw = 0; iw < wf_list.size(); iw++)
1028 {
1029 std::vector<ValueType>& ratios = ratios_list[iw];
1030 for (int j = 0; j < ratios.size(); ++j)
1031 ratios[j] *= t[iw][j];
1032 }
1033 }
1034 }
1035
evaluateDerivRatios(VirtualParticleSet & VP,const opt_variables_type & optvars,std::vector<ValueType> & ratios,Matrix<ValueType> & dratio)1036 void TrialWaveFunction::evaluateDerivRatios(VirtualParticleSet& VP,
1037 const opt_variables_type& optvars,
1038 std::vector<ValueType>& ratios,
1039 Matrix<ValueType>& dratio)
1040 {
1041 #if defined(QMC_COMPLEX)
1042 APP_ABORT("TrialWaveFunction::evaluateDerivRatios not available for complex wavefunctions");
1043 #else
1044 std::fill(ratios.begin(), ratios.end(), 1.0);
1045 std::vector<ValueType> t(ratios.size());
1046 for (int i = 0; i < Z.size(); ++i)
1047 {
1048 Z[i]->evaluateDerivRatios(VP, optvars, t, dratio);
1049 for (int j = 0; j < ratios.size(); ++j)
1050 ratios[j] *= t[j];
1051 }
1052 #endif
1053 }
1054
put(xmlNodePtr cur)1055 bool TrialWaveFunction::put(xmlNodePtr cur) { return true; }
1056
reset()1057 void TrialWaveFunction::reset() {}
1058
makeClone(ParticleSet & tqp) const1059 TrialWaveFunction* TrialWaveFunction::makeClone(ParticleSet& tqp) const
1060 {
1061 TrialWaveFunction* myclone = new TrialWaveFunction(myName, use_tasking_, false);
1062 myclone->BufferCursor = BufferCursor;
1063 myclone->BufferCursor_scalar = BufferCursor_scalar;
1064 for (int i = 0; i < Z.size(); ++i)
1065 myclone->addComponent(Z[i]->makeClone(tqp));
1066 myclone->OneOverM = OneOverM;
1067 return myclone;
1068 }
1069
1070 /** evaluate derivatives of KE wrt optimizable varibles
1071 *
1072 * @todo WaveFunctionComponent objects should take the mass into account.
1073 */
evaluateDerivatives(ParticleSet & P,const opt_variables_type & optvars,std::vector<ValueType> & dlogpsi,std::vector<ValueType> & dhpsioverpsi,bool project)1074 void TrialWaveFunction::evaluateDerivatives(ParticleSet& P,
1075 const opt_variables_type& optvars,
1076 std::vector<ValueType>& dlogpsi,
1077 std::vector<ValueType>& dhpsioverpsi,
1078 bool project)
1079 {
1080 // // First, zero out derivatives
1081 // This should only be done for some variables.
1082 // for (int j=0; j<dlogpsi.size(); j++)
1083 // dlogpsi[j] = dhpsioverpsi[j] = 0.0;
1084 for (int i = 0; i < Z.size(); i++)
1085 {
1086 if (Z[i]->dPsi)
1087 (Z[i]->dPsi)->evaluateDerivatives(P, optvars, dlogpsi, dhpsioverpsi);
1088 else
1089 Z[i]->evaluateDerivatives(P, optvars, dlogpsi, dhpsioverpsi);
1090 }
1091 //orbitals do not know about mass of particle.
1092 for (int i = 0; i < dhpsioverpsi.size(); i++)
1093 dhpsioverpsi[i] *= OneOverM;
1094
1095 if (project)
1096 {
1097 for (int i = 0; i < Z.size(); i++)
1098 {
1099 if (Z[i]->dPsi)
1100 (Z[i]->dPsi)->multiplyDerivsByOrbR(dlogpsi);
1101 else
1102 Z[i]->multiplyDerivsByOrbR(dlogpsi);
1103 }
1104 RealType psiValue = std::exp(-LogValue) * std::cos(PhaseValue);
1105 for (int i = 0; i < dlogpsi.size(); i++)
1106 dlogpsi[i] *= psiValue;
1107 }
1108 }
1109
mw_evaluateParameterDerivatives(const RefVectorWithLeader<TrialWaveFunction> & wf_list,const RefVectorWithLeader<ParticleSet> & p_list,const opt_variables_type & optvars,RecordArray<ValueType> & dlogpsi,RecordArray<ValueType> & dhpsioverpsi)1110 void TrialWaveFunction::mw_evaluateParameterDerivatives(const RefVectorWithLeader<TrialWaveFunction>& wf_list,
1111 const RefVectorWithLeader<ParticleSet>& p_list,
1112 const opt_variables_type& optvars,
1113 RecordArray<ValueType>& dlogpsi,
1114 RecordArray<ValueType>& dhpsioverpsi)
1115 {
1116 const int nparam = dlogpsi.nparam();
1117 for (int iw = 0; iw < wf_list.size(); iw++)
1118 {
1119 std::vector<ValueType> tmp_dlogpsi(nparam);
1120 std::vector<ValueType> tmp_dhpsioverpsi(nparam);
1121 TrialWaveFunction& twf = wf_list[iw];
1122 for (int i = 0; i < twf.Z.size(); i++)
1123 {
1124 if (twf.Z[i]->dPsi)
1125 (twf.Z[i]->dPsi)->evaluateDerivatives(p_list[iw], optvars, tmp_dlogpsi, tmp_dhpsioverpsi);
1126 else
1127 twf.Z[i]->evaluateDerivatives(p_list[iw], optvars, tmp_dlogpsi, tmp_dhpsioverpsi);
1128 }
1129
1130 RealType OneOverM = twf.getReciprocalMass();
1131 for (int i = 0; i < nparam; i++)
1132 {
1133 dlogpsi.setValue(i, iw, tmp_dlogpsi[i]);
1134 //orbitals do not know about mass of particle.
1135 dhpsioverpsi.setValue(i, iw, tmp_dhpsioverpsi[i] * OneOverM);
1136 }
1137 }
1138 }
1139
1140
evaluateDerivativesWF(ParticleSet & P,const opt_variables_type & optvars,std::vector<ValueType> & dlogpsi)1141 void TrialWaveFunction::evaluateDerivativesWF(ParticleSet& P,
1142 const opt_variables_type& optvars,
1143 std::vector<ValueType>& dlogpsi)
1144 {
1145 for (int i = 0; i < Z.size(); i++)
1146 {
1147 if (Z[i]->dPsi)
1148 (Z[i]->dPsi)->evaluateDerivativesWF(P, optvars, dlogpsi);
1149 else
1150 Z[i]->evaluateDerivativesWF(P, optvars, dlogpsi);
1151 }
1152 }
1153
evaluateGradDerivatives(const ParticleSet::ParticleGradient_t & G_in,std::vector<ValueType> & dgradlogpsi)1154 void TrialWaveFunction::evaluateGradDerivatives(const ParticleSet::ParticleGradient_t& G_in,
1155 std::vector<ValueType>& dgradlogpsi)
1156 {
1157 for (int i = 0; i < Z.size(); i++)
1158 {
1159 Z[i]->evaluateGradDerivatives(G_in, dgradlogpsi);
1160 }
1161 }
1162
KECorrection() const1163 TrialWaveFunction::RealType TrialWaveFunction::KECorrection() const
1164 {
1165 RealType sum = 0.0;
1166 for (int i = 0; i < Z.size(); ++i)
1167 sum += Z[i]->KECorrection();
1168 return sum;
1169 }
1170
evaluateRatiosAlltoOne(ParticleSet & P,std::vector<ValueType> & ratios)1171 void TrialWaveFunction::evaluateRatiosAlltoOne(ParticleSet& P, std::vector<ValueType>& ratios)
1172 {
1173 ScopedTimer local_timer(TWF_timers_[V_TIMER]);
1174 std::fill(ratios.begin(), ratios.end(), 1.0);
1175 std::vector<ValueType> t(ratios.size());
1176 for (int i = 0; i < Z.size(); ++i)
1177 {
1178 ScopedTimer local_timer(WFC_timers_[V_TIMER + TIMER_SKIP * i]);
1179 Z[i]->evaluateRatiosAlltoOne(P, t);
1180 for (int j = 0; j < t.size(); ++j)
1181 ratios[j] *= t[j];
1182 }
1183 }
1184
createResource(ResourceCollection & collection) const1185 void TrialWaveFunction::createResource(ResourceCollection& collection) const
1186 {
1187 for (int i = 0; i < Z.size(); ++i)
1188 Z[i]->createResource(collection);
1189 }
1190
acquireResource(ResourceCollection & collection)1191 void TrialWaveFunction::acquireResource(ResourceCollection& collection)
1192 {
1193 for (int i = 0; i < Z.size(); ++i)
1194 Z[i]->acquireResource(collection);
1195 }
1196
releaseResource(ResourceCollection & collection)1197 void TrialWaveFunction::releaseResource(ResourceCollection& collection)
1198 {
1199 for (int i = 0; i < Z.size(); ++i)
1200 Z[i]->releaseResource(collection);
1201 }
1202
extractWFCRefList(const RefVectorWithLeader<TrialWaveFunction> & wf_list,int id)1203 RefVectorWithLeader<WaveFunctionComponent> TrialWaveFunction::extractWFCRefList(
1204 const RefVectorWithLeader<TrialWaveFunction>& wf_list,
1205 int id)
1206 {
1207 RefVectorWithLeader<WaveFunctionComponent> wfc_list(*wf_list.getLeader().Z[id]);
1208 wfc_list.reserve(wf_list.size());
1209 for (TrialWaveFunction& wf : wf_list)
1210 wfc_list.push_back(*wf.Z[id]);
1211 return wfc_list;
1212 }
1213
extractWFCPtrList(const UPtrVector<TrialWaveFunction> & g,int id)1214 std::vector<WaveFunctionComponent*> TrialWaveFunction::extractWFCPtrList(const UPtrVector<TrialWaveFunction>& g, int id)
1215 {
1216 std::vector<WaveFunctionComponent*> WFC_list;
1217 WFC_list.reserve(g.size());
1218 for (auto& WF : g)
1219 WFC_list.push_back(WF->Z[id]);
1220 return WFC_list;
1221 }
1222
extractGRefList(const RefVectorWithLeader<TrialWaveFunction> & wf_list)1223 RefVector<ParticleSet::ParticleGradient_t> TrialWaveFunction::extractGRefList(
1224 const RefVectorWithLeader<TrialWaveFunction>& wf_list)
1225 {
1226 RefVector<ParticleSet::ParticleGradient_t> g_list;
1227 for (TrialWaveFunction& wf : wf_list)
1228 g_list.push_back(wf.G);
1229 return g_list;
1230 }
1231
extractLRefList(const RefVectorWithLeader<TrialWaveFunction> & wf_list)1232 RefVector<ParticleSet::ParticleLaplacian_t> TrialWaveFunction::extractLRefList(
1233 const RefVectorWithLeader<TrialWaveFunction>& wf_list)
1234 {
1235 RefVector<ParticleSet::ParticleLaplacian_t> l_list;
1236 for (TrialWaveFunction& wf : wf_list)
1237 l_list.push_back(wf.L);
1238 return l_list;
1239 }
1240
1241
1242 } // namespace qmcplusplus
1243