QMCPACK
test_multi_slater_determinant.cpp
Go to the documentation of this file.
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: Ye Luo, yeluo@anl.gov, Argonne National Laboratory
8 //
9 // File created by: Ye Luo, yeluo@anl.gov, Argonne National Laboratory
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 
13 #include "catch.hpp"
14 
15 #include <cstdio>
16 #include <string>
17 #include <limits>
18 #include "OhmmsData/Libxml2Doc.h"
19 #include "OhmmsPETE/OhmmsMatrix.h"
20 #include "Particle/ParticleSet.h"
22 #include "WaveFunctionFactory.h"
23 #include "LCAO/LCAOrbitalSet.h"
24 #include "TWFGrads.hpp"
26 #include <ResourceCollection.h>
28 
29 using std::string;
30 
31 namespace qmcplusplus
32 {
39 
40 void test_LiH_msd(const std::string& spo_xml_string,
41  const std::string& check_sponame,
42  int check_spo_size,
43  int check_basisset_size,
44  int test_nlpp_algorithm_batched,
45  int test_batched_api)
46 {
48 
50  auto ions_uptr = std::make_unique<ParticleSet>(ptcl.getSimulationCell());
51  auto elec_uptr = std::make_unique<ParticleSet>(ptcl.getSimulationCell());
52  ParticleSet& ions_(*ions_uptr);
53  ParticleSet& elec_(*elec_uptr);
54 
55  ions_.setName("ion0");
56  ptcl.addParticleSet(std::move(ions_uptr));
57  ions_.create({1, 1});
58  ions_.R[0] = {0.0, 0.0, 0.0};
59  ions_.R[1] = {0.0, 0.0, 3.0139239693};
60  SpeciesSet& ispecies = ions_.getSpeciesSet();
61  int LiIdx = ispecies.addSpecies("Li");
62  int HIdx = ispecies.addSpecies("H");
63 
64  elec_.setName("elec");
65  ptcl.addParticleSet(std::move(elec_uptr));
66  elec_.create({2, 2});
67  elec_.R[0] = {0.5, 0.5, 0.5};
68  elec_.R[1] = {0.1, 0.1, 1.1};
69  elec_.R[2] = {-0.5, -0.5, -0.5};
70  elec_.R[3] = {-0.1, -0.1, 1.5};
71 
72  SpeciesSet& tspecies = elec_.getSpeciesSet();
73  int upIdx = tspecies.addSpecies("u");
74  int downIdx = tspecies.addSpecies("d");
75  int massIdx = tspecies.addAttribute("mass");
76  tspecies(massIdx, upIdx) = 1.0;
77  tspecies(massIdx, downIdx) = 1.0;
78  // Necessary to set mass
79  elec_.resetGroups();
80 
82  bool okay = doc.parseFromString(spo_xml_string);
83  REQUIRE(okay);
84 
85  xmlNodePtr ein_xml = doc.getRoot();
86 
87  WaveFunctionFactory wf_factory(elec_, ptcl.getPool(), c);
88  RuntimeOptions runtime_options;
89  auto twf_ptr = wf_factory.buildTWF(ein_xml, runtime_options);
90 
91  auto& spo = dynamic_cast<const LCAOrbitalSet&>(twf_ptr->getSPOSet(check_sponame));
92  CHECK(spo.getOrbitalSetSize() == check_spo_size);
93  CHECK(spo.getBasisSetSize() == check_basisset_size);
94 
95  ions_.update();
96  elec_.update();
97 
98  auto& twf(*twf_ptr);
99  auto msd_refvec = twf.findMSD();
100  CHECK(msd_refvec.size() == 1);
101  MultiSlaterDetTableMethod& msd = msd_refvec[0];
102 
103  twf.setMassTerm(elec_);
104  twf.evaluateLog(elec_);
105 
106  app_log() << "twf.evaluateLog logpsi " << std::setprecision(16) << twf.getLogPsi() << " " << twf.getPhase()
107  << std::endl;
108  CHECK(std::complex<double>(twf.getLogPsi(), twf.getPhase()) ==
109  LogComplexApprox(std::complex<double>(-7.646027846242066, 3.141592653589793)));
110  CHECK(elec_.G[0][0] == ValueApprox(-2.181896934));
111  CHECK(elec_.G[1][1] == ValueApprox(0.120821033));
112  CHECK(elec_.G[2][2] == ValueApprox(1.2765987657));
113  CHECK(elec_.L[0] == ValueApprox(-15.460736911));
114  CHECK(elec_.L[3] == ValueApprox(-0.328013327566));
115 
116  Vector<ValueType> individual_det_ratios;
117  msd.calcIndividualDetRatios(individual_det_ratios);
118  CHECK(individual_det_ratios[0] == ValueApprox(-1.4357837882));
119  CHECK(individual_det_ratios[3] == ValueApprox(-0.013650987));
120 
121  twf.prepareGroup(elec_, 0);
122  auto grad_old = twf.evalGrad(elec_, 1);
123  app_log() << "twf.evalGrad grad_old " << std::setprecision(16) << grad_old << std::endl;
124  CHECK(grad_old[0] == ValueApprox(0.1204183219));
125  CHECK(grad_old[1] == ValueApprox(0.120821033));
126  CHECK(grad_old[2] == ValueApprox(2.05904174));
127 
128  PosType delta(0.1, 0.1, 0.2);
129  elec_.makeMove(1, delta);
130 
131  ParticleSet::GradType grad_new;
132  auto ratio = twf.calcRatioGrad(elec_, 1, grad_new);
133  app_log() << "twf.calcRatioGrad ratio " << ratio << " grad_new " << grad_new << std::endl;
134  CHECK(ratio == ValueApprox(1.374307585));
135  CHECK(grad_new[0] == ValueApprox(0.05732804333));
136  CHECK(grad_new[1] == ValueApprox(0.05747775029));
137  CHECK(grad_new[2] == ValueApprox(1.126889742));
138 
139  ratio = twf.calcRatio(elec_, 1);
140  app_log() << "twf.calcRatio ratio " << ratio << std::endl;
141  CHECK(ratio == ValueApprox(1.374307585));
142 
143 
144  opt_variables_type active;
145  twf.checkInVariables(active);
146 
147  const int nparam = active.size_of_active();
148  REQUIRE(nparam == 1486);
149 
151  Vector<ValueType> dlogpsi(nparam);
152  Vector<ValueType> dhpsioverpsi(nparam);
153  twf.evaluateDerivatives(elec_, active, dlogpsi, dhpsioverpsi);
154 
155  // Numbers not validated
156  CHECK(dlogpsi[0] == ValueApprox(0.006449058893092842));
157  CHECK(dlogpsi[1] == ValueApprox(-0.01365690177395768));
158  CHECK(dlogpsi[nparam - 1] == ValueApprox(0.1641910574099575));
159 
160  CHECK(dhpsioverpsi[0] == ValueApprox(0.2207480131794138));
161  CHECK(dhpsioverpsi[1] == ValueApprox(0.009316665149067847));
162  CHECK(dhpsioverpsi[nparam - 1] == ValueApprox(0.982665984797896));
163 
164  if (test_nlpp_algorithm_batched)
165  {
166  // set virtutal particle position
167  PosType newpos(0.3, 0.2, 0.5);
168 
169  //elec_.makeVirtualMoves(newpos);
170  //std::vector<ValueType> ratios(elec_.getTotalNum());
171  //twf.evaluateRatiosAlltoOne(elec_, ratios);
172 
173  //CHECK(std::real(ratios[0]) == Approx());
174  //CHECK(std::real(ratios[1]) == Approx());
175  //CHECK(std::real(ratios[2]) == Approx());
176 
177  elec_.makeMove(0, newpos - elec_.R[0]);
178  ValueType ratio_0 = twf.calcRatio(elec_, 0);
179  elec_.rejectMove(0);
180 
181  CHECK(std::real(ratio_0) == Approx(2.350046921));
182 
183  VirtualParticleSet VP(elec_, 2);
184  std::vector<PosType> newpos2(2);
185  std::vector<ValueType> ratios2(2);
186  newpos2[0] = newpos - elec_.R[1];
187  newpos2[1] = PosType(0.2, 0.5, 0.3) - elec_.R[1];
188  VP.makeMoves(elec_, 1, newpos2);
189  twf.evaluateRatios(VP, ratios2);
190 
191  CHECK(std::real(ratios2[0]) == Approx(-0.8544310407));
192  CHECK(std::real(ratios2[1]) == Approx(-1.0830708458));
193 
194  std::fill(ratios2.begin(), ratios2.end(), 0);
195  Matrix<ValueType> dratio(2, nparam);
196  twf.evaluateDerivRatios(VP, active, ratios2, dratio);
197 
198  CHECK(std::real(ratios2[0]) == Approx(-0.8544310407));
199  CHECK(std::real(ratios2[1]) == Approx(-1.0830708458));
200 
201  CHECK(std::real(dratio[0][0]) == Approx(0.248887465));
202  CHECK(std::real(dratio[0][1]) == Approx(0.135021218));
203  }
204 
205  //test acceptMove
206  {
207  PosType newpos(0.3, 0.2, 0.5);
208  elec_.makeMove(1, newpos - elec_.R[1]);
209  ValueType ratio_1 = twf.calcRatio(elec_, 1);
210  twf.acceptMove(elec_, 1);
211  elec_.acceptMove(1);
212 
213  CHECK(std::real(ratio_1) == Approx(-0.8544310407));
214  CHECK(twf.getLogPsi() == Approx(-7.8033473273));
215 
216  twf.evaluateLog(elec_);
217 
218  app_log() << "twf.evaluateLog logpsi " << std::setprecision(16) << twf.getLogPsi() << " " << twf.getPhase()
219  << std::endl;
220  CHECK(std::complex<double>(twf.getLogPsi(), twf.getPhase()) ==
221  LogComplexApprox(std::complex<double>(-7.803347327300154, 0.0)));
222  CHECK(elec_.G[0][0] == ValueApprox(1.63020975849953));
223  CHECK(elec_.G[1][1] == ValueApprox(-1.795375999646262));
224  CHECK(elec_.G[2][2] == ValueApprox(1.215768958589418));
225  CHECK(elec_.L[0] == ValueApprox(-21.84021387509693));
226  CHECK(elec_.L[3] == ValueApprox(-1.332448295858972));
227  }
228 
229  // testing batched interfaces
230  if (test_batched_api)
231  {
232  ParticleSet elec_clone(elec_);
233  elec_clone.update();
234 
235  std::unique_ptr<TrialWaveFunction> twf_clone(twf.makeClone(elec_clone));
236 
237  std::vector<PosType> displ(2);
238  displ[0] = {0.1, 0.2, 0.3};
239  displ[1] = {-0.2, -0.3, 0.0};
240 
241  // testing batched interfaces
242  ResourceCollection pset_res("test_pset_res");
243  ResourceCollection twf_res("test_twf_res");
244 
245  elec_.createResource(pset_res);
246  twf.createResource(twf_res);
247 
248  // testing batched interfaces
249  RefVectorWithLeader<ParticleSet> p_ref_list(elec_, {elec_, elec_clone});
250  RefVectorWithLeader<TrialWaveFunction> wf_ref_list(twf, {twf, *twf_clone});
251 
252  ResourceCollectionTeamLock<ParticleSet> mw_pset_lock(pset_res, p_ref_list);
253  ResourceCollectionTeamLock<TrialWaveFunction> mw_twf_lock(twf_res, wf_ref_list);
254 
255  ParticleSet::mw_update(p_ref_list);
256  TrialWaveFunction::mw_evaluateLog(wf_ref_list, p_ref_list);
257  app_log() << "before YYY [0] getLogPsi getPhase " << std::setprecision(16) << wf_ref_list[0].getLogPsi() << " "
258  << wf_ref_list[0].getPhase() << std::endl;
259  app_log() << "before YYY [1] getLogPsi getPhase " << std::setprecision(16) << wf_ref_list[1].getLogPsi() << " "
260  << wf_ref_list[1].getPhase() << std::endl;
261  CHECK(std::complex<RealType>(wf_ref_list[0].getLogPsi(), wf_ref_list[0].getPhase()) ==
262  LogComplexApprox(std::complex<RealType>(-7.803347327300153, 0.0)));
263  CHECK(std::complex<RealType>(wf_ref_list[1].getLogPsi(), wf_ref_list[1].getPhase()) ==
264  LogComplexApprox(std::complex<RealType>(-7.803347327300153, 0.0)));
265 
266  TrialWaveFunction::mw_prepareGroup(wf_ref_list, p_ref_list, 0);
267 
268  TWFGrads<CoordsType::POS> grad_old(2);
269 
270  const int moved_elec_id = 1;
271  TrialWaveFunction::mw_evalGrad(wf_ref_list, p_ref_list, moved_elec_id, grad_old);
272 
273  CHECK(grad_old.grads_positions[0][0] == ValueApprox(-2.6785305398));
274  CHECK(grad_old.grads_positions[0][1] == ValueApprox(-1.7953759996));
275  CHECK(grad_old.grads_positions[0][2] == ValueApprox(-5.8209379274));
276  CHECK(grad_old.grads_positions[1][0] == ValueApprox(-2.6785305398));
277  CHECK(grad_old.grads_positions[1][1] == ValueApprox(-1.7953759996));
278  CHECK(grad_old.grads_positions[1][2] == ValueApprox(-5.8209379274));
279 
280  TWFGrads<CoordsType::POS> grad_new(2);
281  std::vector<PsiValue> ratios(2);
282 
283  ParticleSet::mw_makeMove(p_ref_list, moved_elec_id, displ);
284  TrialWaveFunction::mw_calcRatio(wf_ref_list, p_ref_list, moved_elec_id, ratios);
285 
286  CHECK(ratios[0] == ValueApprox(PsiValue(-0.6181619459)));
287  CHECK(ratios[1] == ValueApprox(PsiValue(1.6186330488)));
288 
289  TrialWaveFunction::mw_calcRatioGrad(wf_ref_list, p_ref_list, moved_elec_id, ratios, grad_new);
290 
291  CHECK(ratios[0] == ValueApprox(PsiValue(-0.6181619459)));
292  CHECK(ratios[1] == ValueApprox(PsiValue(1.6186330488)));
293 
294  CHECK(grad_new.grads_positions[0][0] == ValueApprox(1.2418467899));
295  CHECK(grad_new.grads_positions[0][1] == ValueApprox(1.2425653495));
296  CHECK(grad_new.grads_positions[0][2] == ValueApprox(4.4273237873));
297  CHECK(grad_new.grads_positions[1][0] == ValueApprox(-0.8633778143));
298  CHECK(grad_new.grads_positions[1][1] == ValueApprox(0.8245347691));
299  CHECK(grad_new.grads_positions[1][2] == ValueApprox(-5.1513380151));
300 
301  std::vector<bool> isAccepted{false, true};
302  TrialWaveFunction::mw_accept_rejectMove(wf_ref_list, p_ref_list, moved_elec_id, isAccepted);
303  ParticleSet::mw_accept_rejectMove(p_ref_list, moved_elec_id, isAccepted);
304 
305  CHECK(wf_ref_list[0].getLogPsi() == Approx(-7.803347327300152));
306  CHECK(wf_ref_list[1].getLogPsi() == Approx(-7.321765331299484));
307 
308  // move the next electron
309  TrialWaveFunction::mw_prepareGroup(wf_ref_list, p_ref_list, 1);
310  const int moved_elec_id_next = 2;
311  TrialWaveFunction::mw_evalGrad(wf_ref_list, p_ref_list, moved_elec_id_next, grad_old);
312 
313  CHECK(grad_old.grads_positions[0][0] == ValueApprox(1.3325558736));
314  CHECK(grad_old.grads_positions[0][1] == ValueApprox(1.3327966725));
315  CHECK(grad_old.grads_positions[0][2] == ValueApprox(1.2157689586));
316  CHECK(grad_old.grads_positions[1][0] == ValueApprox(1.3222514142));
317  CHECK(grad_old.grads_positions[1][1] == ValueApprox(1.3230108868));
318  CHECK(grad_old.grads_positions[1][2] == ValueApprox(1.2035047435));
319 
320  ParticleSet::mw_makeMove(p_ref_list, moved_elec_id_next, displ);
321  TrialWaveFunction::mw_calcRatio(wf_ref_list, p_ref_list, moved_elec_id_next, ratios);
322 
323  CHECK(ratios[0] == ValueApprox(PsiValue(2.1080036144)));
324  CHECK(ratios[1] == ValueApprox(PsiValue(0.4947158435)));
325 
326  TrialWaveFunction::mw_calcRatioGrad(wf_ref_list, p_ref_list, moved_elec_id_next, ratios, grad_new);
327 
328  CHECK(ratios[0] == ValueApprox(PsiValue(2.1080036144)));
329  CHECK(ratios[1] == ValueApprox(PsiValue(0.4947158435)));
330 
331  CHECK(grad_new.grads_positions[0][0] == ValueApprox(1.8412365668));
332  CHECK(grad_new.grads_positions[0][1] == ValueApprox(1.3736370007));
333  CHECK(grad_new.grads_positions[0][2] == ValueApprox(0.8043818454));
334  CHECK(grad_new.grads_positions[1][0] == ValueApprox(1.3553132105));
335  CHECK(grad_new.grads_positions[1][1] == ValueApprox(1.5552132255));
336  CHECK(grad_new.grads_positions[1][2] == ValueApprox(0.804301246));
337  }
338 }
339 
340 TEST_CASE("LiH multi Slater dets table_method", "[wavefunction]")
341 {
342  app_log() << "-----------------------------------------------------------------" << std::endl;
343  app_log() << "LiH_msd using the table method no precomputation" << std::endl;
344  app_log() << "-----------------------------------------------------------------" << std::endl;
345  const char* spo_xml_string1 = R"(<wavefunction name="psi0" target="e">
346  <sposet_collection type="MolecularOrbital" name="LCAOBSet" source="ion0" cuspCorrection="no" href="LiH.orbs.h5">
347  <basisset name="LCAOBSet" key="GTO" transform="yes">
348  <grid type="log" ri="1.e-6" rf="1.e2" npts="1001"/>
349  </basisset>
350  <sposet basisset="LCAOBSet" name="spo-up" size="85">
351  <occupation mode="ground"/>
352  <coefficient size="85" spindataset="0"/>
353  </sposet>
354  <sposet basisset="LCAOBSet" name="spo-dn" size="85">
355  <occupation mode="ground"/>
356  <coefficient size="85" spindataset="0"/>
357  </sposet>
358  </sposet_collection>
359  <determinantset>
360  <multideterminant optimize="yes" spo_up="spo-up" spo_dn="spo-dn" algorithm="table_method">
361  <detlist size="1487" type="DETS" cutoff="1e-20" href="LiH.orbs.h5"/>
362  </multideterminant>
363  </determinantset>
364 </wavefunction>
365 )";
366  test_LiH_msd(spo_xml_string1, "spo-up", 85, 105, true, true);
367 }
368 
369 TEST_CASE("LiH multi Slater dets precomputed_table_method", "[wavefunction]")
370 {
371  app_log() << "-----------------------------------------------------------------" << std::endl;
372  app_log() << "LiH_msd using the table method with new optimization" << std::endl;
373  app_log() << "-----------------------------------------------------------------" << std::endl;
374  const char* spo_xml_string1_new = R"(<wavefunction name="psi0" target="e">
375  <sposet_collection type="MolecularOrbital" name="LCAOBSet" source="ion0" cuspCorrection="no" href="LiH.orbs.h5">
376  <basisset name="LCAOBSet" key="GTO" transform="yes">
377  <grid type="log" ri="1.e-6" rf="1.e2" npts="1001"/>
378  </basisset>
379  <sposet basisset="LCAOBSet" name="spo-up" size="85">
380  <occupation mode="ground"/>
381  <coefficient size="85" spindataset="0"/>
382  </sposet>
383  <sposet basisset="LCAOBSet" name="spo-dn" size="85">
384  <occupation mode="ground"/>
385  <coefficient size="85" spindataset="0"/>
386  </sposet>
387  </sposet_collection>
388  <determinantset>
389  <multideterminant optimize="yes" spo_up="spo-up" spo_dn="spo-dn" algorithm="precomputed_table_method">
390  <detlist size="1487" type="DETS" cutoff="1e-20" href="LiH.orbs.h5"/>
391  </multideterminant>
392  </determinantset>
393 </wavefunction>
394 )";
395  test_LiH_msd(spo_xml_string1_new, "spo-up", 85, 105, true, true);
396 }
397 
398 #ifdef QMC_COMPLEX
399 void test_Bi_msd(const std::string& spo_xml_string,
400  const std::string& check_sponame,
401  int check_spo_size,
402  int check_basisset_size)
403 {
405 
406  ParticleSetPool ptcl = ParticleSetPool(c);
407  auto ions_uptr = std::make_unique<ParticleSet>(ptcl.getSimulationCell());
408  auto elec_uptr = std::make_unique<ParticleSet>(ptcl.getSimulationCell());
409  ParticleSet& ions_(*ions_uptr);
410  ParticleSet& elec_(*elec_uptr);
411 
412  ions_.setName("ion0");
413  ptcl.addParticleSet(std::move(ions_uptr));
414  ions_.create(std::vector<int>{1});
415  ions_.R[0] = {0.0, 0.0, 0.0};
416  SpeciesSet& ispecies = ions_.getSpeciesSet();
417  int LiIdx = ispecies.addSpecies("Bi");
418 
419  elec_.setName("elec");
420  ptcl.addParticleSet(std::move(elec_uptr));
421  elec_.create(std::vector<int>{5});
422  elec_.R[0] = {1.592992772, -2.241313928, -0.7315193518};
423  elec_.R[1] = {0.07621077199, 0.8497557547, 1.604678718};
424  elec_.R[2] = {2.077473445, 0.680621113, -0.5251243321};
425  elec_.R[3] = {-1.488849594, 0.7470552741, 0.6659555498};
426  elec_.R[4] = {-1.448485879, 0.7337274141, 0.02687190951};
427 
428  elec_.spins[0] = 4.882003828;
429  elec_.spins[1] = 0.06469299507;
430  elec_.spins[2] = 5.392168887;
431  elec_.spins[3] = 5.33941214;
432  elec_.spins[4] = 3.127416326;
433  elec_.setSpinor(true);
434 
435  SpeciesSet& tspecies = elec_.getSpeciesSet();
436  int upIdx = tspecies.addSpecies("u");
437  int massIdx = tspecies.addAttribute("mass");
438  tspecies(massIdx, upIdx) = 1.0;
439  // Necessary to set mass
440  elec_.resetGroups();
441 
443  bool okay = doc.parseFromString(spo_xml_string);
444  REQUIRE(okay);
445 
446  xmlNodePtr ein_xml = doc.getRoot();
447 
448  RuntimeOptions runtime_options;
449  WaveFunctionFactory wf_factory(elec_, ptcl.getPool(), c);
450  auto twf_ptr = wf_factory.buildTWF(ein_xml, runtime_options);
451 
452  auto& spo = twf_ptr->getSPOSet(check_sponame);
453  CHECK(spo.getOrbitalSetSize() == check_spo_size);
454 
455  ions_.update();
456  elec_.update();
457 
458  auto& twf(*twf_ptr);
459  twf.setMassTerm(elec_);
460  twf.evaluateLog(elec_);
461 
462  //Reference values from QWalk with SOC
463 
464  app_log() << "twf.evaluateLog logpsi " << std::setprecision(16) << twf.getLogPsi() << " " << twf.getPhase()
465  << std::endl;
466  CHECK(std::complex<double>(twf.getLogPsi(), twf.getPhase()) ==
467  LogComplexApprox(std::complex<double>(-9.653087, 3.311467)));
468 
469  twf.prepareGroup(elec_, 0);
470  ParticleSet::ComplexType spingrad_old;
471  auto grad_old = twf.evalGradWithSpin(elec_, 1, spingrad_old);
472  app_log() << "twf.evalGrad grad_old " << std::setprecision(16) << grad_old << std::endl;
473  CHECK(grad_old[0] == ComplexApprox(ValueType(0.060932, -0.285244)).epsilon(1e-4));
474  CHECK(grad_old[1] == ComplexApprox(ValueType(-0.401769, 0.180544)).epsilon(1e-4));
475  CHECK(grad_old[2] == ComplexApprox(ValueType(0.174010, 0.140642)).epsilon(1e-4));
476  CHECK(spingrad_old == ComplexApprox(ValueType(0.6766137, -0.8366186)).epsilon(1e-4));
477 
478  PosType delta(0.464586, 0.75017, 1.184383);
479  double ds = 0.12;
480  elec_.makeMoveWithSpin(0, delta, ds);
481 
482  ParticleSet::GradType grad_new;
483  ParticleSet::ComplexType spingrad_new;
484  auto ratio = twf.calcRatioGradWithSpin(elec_, 0, grad_new, spingrad_new);
485  app_log() << "twf.calcRatioGrad ratio " << ratio << " grad_new " << grad_new << std::endl;
486  CHECK(ValueType(std::abs(ratio)) == ValueApprox(0.991503).epsilon(1e-4));
487  CHECK(grad_new[0] == ComplexApprox(ValueType(-0.631184, -0.136918)).epsilon(1e-4));
488  CHECK(grad_new[1] == ComplexApprox(ValueType(0.074214, -0.080204)).epsilon(1e-4));
489  CHECK(grad_new[2] == ComplexApprox(ValueType(-0.073180, -0.133539)).epsilon(1e-4));
490  CHECK(spingrad_new == ComplexApprox(ValueType(-0.135438, -0.6085006)).epsilon(1e-4));
491 
492  ratio = twf.calcRatio(elec_, 0);
493  app_log() << "twf.calcRatio ratio " << ratio << std::endl;
494  CHECK(ValueType(std::abs(ratio)) == ValueApprox(0.991503).epsilon(1e-4));
495 
496  elec_.accept_rejectMove(0, false);
497 
498  //now lets test batched interface
499  const int num_walkers = 2;
500  ResourceCollection pset_res("test_pset_res");
501  elec_.createResource(pset_res);
502  ParticleSet elec_clone(elec_);
503  RefVectorWithLeader<ParticleSet> p_list(elec_, {elec_, elec_clone});
504  ResourceCollectionTeamLock<ParticleSet> mw_pset_lock(pset_res, p_list);
505 
506  ResourceCollection twf_res("test_twf_res");
507  twf.createResource(twf_res);
508  auto twf_clone = twf.makeClone(elec_clone);
509  RefVectorWithLeader<TrialWaveFunction> twf_list(twf, {twf, *twf_clone});
510  ResourceCollectionTeamLock<TrialWaveFunction> mw_twf_lock(twf_res, twf_list);
511 
512  ParticleSet::mw_update(p_list);
513  TrialWaveFunction::mw_evaluateLog(twf_list, p_list);
514 
515  for (int iw = 0; iw < num_walkers; iw++)
516  {
517  CHECK(std::complex<double>(twf_list[iw].getLogPsi(), twf_list[iw].getPhase()) ==
518  LogComplexApprox(std::complex<double>(-9.653087, 3.311467)));
519  }
520 
521  TrialWaveFunction::mw_prepareGroup(twf_list, p_list, 0);
522 
523  int moved_elec_id = 1;
524  TWFGrads<CoordsType::POS_SPIN> grads_old(num_walkers);
525  TrialWaveFunction::mw_evalGrad(twf_list, p_list, moved_elec_id, grads_old);
526  for (int iw = 0; iw < num_walkers; iw++)
527  {
528  CHECK(grads_old.grads_positions[iw][0] == ComplexApprox(ValueType(0.060932, -0.285244)).epsilon(1e-4));
529  CHECK(grads_old.grads_positions[iw][1] == ComplexApprox(ValueType(-0.401769, 0.180544)).epsilon(1e-4));
530  CHECK(grads_old.grads_positions[iw][2] == ComplexApprox(ValueType(0.174010, 0.140642)).epsilon(1e-4));
531  CHECK(grads_old.grads_spins[iw] == ComplexApprox(ValueType(0.6766137, -0.8366186)).epsilon(1e-4));
532  }
533 
534  moved_elec_id = 0;
535  MCCoords<CoordsType::POS_SPIN> displs(num_walkers);
536  displs.positions = {delta, delta};
537  displs.spins = {ds, ds};
538  ParticleSet::mw_makeMove(p_list, moved_elec_id, displs);
539 
540  std::vector<PsiValue> ratios(num_walkers);
541  TrialWaveFunction::mw_calcRatio(twf_list, p_list, moved_elec_id, ratios);
542  for (int iw = 0; iw < num_walkers; iw++)
543  CHECK(ValueType(std::abs(ratios[iw])) == ValueApprox(0.991503).epsilon(1e-4));
544  std::fill(ratios.begin(), ratios.end(), ValueType(0));
545 
546  TWFGrads<CoordsType::POS_SPIN> grads_new(num_walkers);
547  TrialWaveFunction::mw_calcRatioGrad(twf_list, p_list, moved_elec_id, ratios, grads_new);
548  for (int iw = 0; iw < num_walkers; iw++)
549  {
550  CHECK(ValueType(std::abs(ratios[iw])) == ValueApprox(0.991503).epsilon(1e-4));
551  CHECK(grads_new.grads_positions[iw][0] == ComplexApprox(ValueType(-0.631184, -0.136918)).epsilon(1e-4));
552  CHECK(grads_new.grads_positions[iw][1] == ComplexApprox(ValueType(0.074214, -0.080204)).epsilon(1e-4));
553  CHECK(grads_new.grads_positions[iw][2] == ComplexApprox(ValueType(-0.073180, -0.133539)).epsilon(1e-4));
554  CHECK(grads_new.grads_spins[iw] == ComplexApprox(ValueType(-0.135438, -0.6085006)).epsilon(1e-4));
555  }
556 }
557 
558 TEST_CASE("Bi-spinor multi Slater dets", "[wavefunction]")
559 {
560  app_log() << "-----------------------------------------------------------------" << std::endl;
561  app_log() << "Bi using the table method no precomputation" << std::endl;
562  app_log() << "-----------------------------------------------------------------" << std::endl;
563  const char* spo_xml_string1 = R"(<wavefunction name="psi0" target="e">
564  <sposet_builder name="spinorbuilder" type="molecularorbital" source="ion0" transform="yes" href="Bi.orbs.h5" precision="double">
565  <sposet name="myspo" size="16">
566  <occupation mode="ground"/>
567  </sposet>
568  </sposet_builder>
569  <determinantset>
570  <multideterminant optimize="no" spo_0="myspo" algorithm="table_method">
571  <detlist size="4" type="DETS" nc0="0" ne0="5" nstates="16" cutoff="1e-20">
572  <ci coeff=" 0.8586" occ0="1110110000000000"/>
573  <ci coeff="-0.2040" occ0="1101110000000000"/>
574  <ci coeff=" 0.4081" occ0="1110101000000000"/>
575  <ci coeff="-0.2340" occ0="1101101000000000"/>
576  </detlist>
577  </multideterminant>
578  </determinantset>
579 </wavefunction>)";
580  test_Bi_msd(spo_xml_string1, "myspo", 16, 123);
581 
582  app_log() << "-----------------------------------------------------------------" << std::endl;
583  app_log() << "Bi using the table method with new optimization" << std::endl;
584  app_log() << "-----------------------------------------------------------------" << std::endl;
585  const char* spo_xml_string1_new = R"(<wavefunction name="psi0" target="e">
586  <sposet_builder name="spinorbuilder" type="molecularorbital" source="ion0" transform="yes" href="Bi.orbs.h5" precision="double">
587  <sposet name="myspo" size="16">
588  <occupation mode="ground"/>
589  </sposet>
590  </sposet_builder>
591  <determinantset>
592  <multideterminant optimize="no" spo_0="myspo" algorithm="precomputed_table_method">
593  <detlist size="4" type="DETS" nc0="0" ne0="5" nstates="16" cutoff="1e-20">
594  <ci coeff=" 0.8586" occ0="1110110000000000"/>
595  <ci coeff="-0.2040" occ0="1101110000000000"/>
596  <ci coeff=" 0.4081" occ0="1110101000000000"/>
597  <ci coeff="-0.2340" occ0="1101101000000000"/>
598  </detlist>
599  </multideterminant>
600  </determinantset>
601 </wavefunction>)";
602  test_Bi_msd(spo_xml_string1_new, "myspo", 16, 123);
603 
604  app_log() << "-----------------------------------------------------------------" << std::endl;
605  app_log() << "Bi using the table method with new optimization, read from hdf5" << std::endl;
606  app_log() << "-----------------------------------------------------------------" << std::endl;
607  const char* spo_xml_string2_new = R"(<wavefunction name="psi0" target="e">
608  <sposet_builder name="spinorbuilder" type="molecularorbital" source="ion0" transform="yes" href="Bi.orbs.h5" precision="double">
609  <sposet name="myspo" size="16">
610  <occupation mode="ground"/>
611  </sposet>
612  </sposet_builder>
613  <determinantset>
614  <multideterminant optimize="no" spo_0="myspo" algorithm="precomputed_table_method">
615  <detlist size="4" type="DETS" nc0="0" ne0="5" nstates="16" cutoff="1e-20" href="Bi.orbs.h5"/>
616  </multideterminant>
617  </determinantset>
618 </wavefunction>)";
619  test_Bi_msd(spo_xml_string2_new, "myspo", 16, 123);
620 }
621 #endif
622 } // namespace qmcplusplus
void setName(const std::string &aname)
Definition: ParticleSet.h:237
class that handles xmlDoc
Definition: Libxml2Doc.h:76
static void mw_makeMove(const RefVectorWithLeader< ParticleSet > &p_list, int iat, const MCCoords< CT > &displs)
batched version of makeMove
WaveFunctionComponent::PsiValue PsiValue
Definition: SlaterDet.cpp:25
int addSpecies(const std::string &aname)
When a name species does not exist, add a new species.
Definition: SpeciesSet.cpp:33
QMCTraits::RealType real
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
QTBase::GradType GradType
Definition: Configuration.h:62
QTBase::RealType RealType
Definition: Configuration.h:58
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
static void mw_prepareGroup(const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, int ig)
batched version of prepareGroup
std::ostream & app_log()
Definition: OutputManager.h:65
const char num_walkers[]
Definition: HDFVersion.h:37
TEST_CASE("complex_helper", "[type_traits]")
void test_LiH_msd(const std::string &spo_xml_string, const std::string &check_sponame, int check_spo_size, int check_basisset_size, int test_nlpp_algorithm_batched, int test_batched_api)
static void mw_calcRatioGrad(const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< PsiValue > &ratios, TWFGrads< CT > &grads)
batched version of ratioGrad
A ParticleSet that handles virtual moves of a selected particle of a given physical ParticleSet Virtu...
void makeMoves(const ParticleSet &refp, int jel, const std::vector< PosType > &deltaV, bool sphere=false, int iat=-1)
move virtual particles to new postions and update distance tables
void addParticleSet(std::unique_ptr< ParticleSet > &&p)
add a ParticleSet* to the pool with its ownership transferred ParticleSet built outside the ParticleS...
xmlNodePtr getRoot()
Definition: Libxml2Doc.h:88
LatticeGaussianProduct::GradType GradType
void createResource(ResourceCollection &collection) const
initialize a shared resource and hand it to a collection
QTBase::ComplexType ComplexType
Definition: Configuration.h:59
void update(bool skipSK=false)
update the internal data
Communicate * Controller
Global Communicator for a process.
Definition: Communicate.cpp:35
ParticleLaplacian L
laplacians of the particles
Definition: ParticleSet.h:85
static void mw_accept_rejectMove(const RefVectorWithLeader< ParticleSet > &p_list, Index_t iat, const std::vector< bool > &isAccepted, bool forward_mode=true)
batched version of acceptMove and rejectMove fused, templated on CoordsType
static void mw_accept_rejectMove(const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, const std::vector< bool > &isAccepted, bool safe_to_delay=false)
int addAttribute(const std::string &aname)
for a new attribute, allocate the data, !More often used to get the index of a species ...
Definition: SpeciesSet.cpp:45
Catch::Detail::LogComplexApprox LogComplexApprox
std::complex< QTFull::RealType > LogValue
QMCTraits::PosType PosType
Wrapping information on parallelism.
Definition: Communicate.h:68
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
std::vector< QMCTraits::GradType > grads_positions
Definition: TWFGrads.hpp:31
QTBase::ValueType ValueType
Definition: Configuration.h:60
REQUIRE(std::filesystem::exists(filename))
void rejectMove(Index_t iat)
reject a proposed move in regular mode
Manage a collection of ParticleSet objects.
ParticleGradient G
gradients of the particles
Definition: ParticleSet.h:83
Factory class to build a many-body wavefunction.
static void mw_calcRatio(const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< PsiValue > &ratios, ComputeType ct=ComputeType::ALL)
batched version of calcRatio
class to handle a set of variables that can be modified during optimizations
Definition: VariableSet.h:49
ParticlePos R
Position.
Definition: ParticleSet.h:79
QTBase::PosType PosType
Definition: Configuration.h:61
int size_of_active() const
return the number of active variables
Definition: VariableSet.h:78
static void mw_evalGrad(const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, TWFGrads< CT > &grads)
batched version of evalGrad
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
void create(const std::vector< int > &agroup)
create grouped particles
QMCTraits::RealType RealType
void makeMove(Index_t iat, const SingleParticlePos &displ, bool maybe_accept=true)
move the iat-th particle to active_pos_
bool parseFromString(const std::string_view data)
Definition: Libxml2Doc.cpp:204
static void mw_update(const RefVectorWithLeader< ParticleSet > &p_list, bool skipSK=false)
batched version of update
CHECK(log_values[0]==ComplexApprox(std::complex< double >{ 5.603777579195571, -6.1586603331188225 }))
TinyVector< double, 3 > PosType
handles acquire/release resource by the consumer (RefVectorWithLeader type).
LatticeGaussianProduct::ValueType ValueType
Declaration of a WaveFunctionFactory.
class to handle linear combinations of basis orbitals used to evaluate the Dirac determinants.
Definition: LCAOrbitalSet.h:30
std::complex< double > LogValue
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
const PoolType & getPool() const
get the Pool object
void acceptMove(Index_t iat)
accept the move and update the particle attribute by the proposed move in regular mode ...
const auto & getSimulationCell() const
get simulation cell
An AntiSymmetric WaveFunctionComponent composed of a linear combination of SlaterDeterminants.
static void mw_evaluateLog(const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list)
batched version of evaluateLog.
Declaration of ParticleSetPool.