QMCPACK
test_DiracDeterminant.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: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
8 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
9 //
10 // File created by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
11 //////////////////////////////////////////////////////////////////////////////////////
12 
13 
14 #include "catch.hpp"
15 
16 #include "OhmmsData/Libxml2Doc.h"
17 #include "OhmmsPETE/OhmmsMatrix.h"
23 
24 #include <stdio.h>
25 #include <string>
26 
27 using std::string;
28 
29 namespace qmcplusplus
30 {
35 using LogValue = std::complex<QMCTraits::QTFull::RealType>;
37 
38 template<typename T1, typename T2>
40 {
41  REQUIRE(a.size() == b.size());
42  for (int i = 0; i < a.rows(); i++)
43  {
44  for (int j = 0; j < a.cols(); j++)
45  {
46  CHECK(a(i, j) == ValueApprox(b(i, j)));
47  }
48  }
49 }
50 
51 template<typename DET>
53 {
54  auto spo_init = std::make_unique<FakeSPO>();
55  const int norb = 3;
56  spo_init->setOrbitalSetSize(norb);
57  DET ddb(std::move(spo_init), 0, norb, 1, inverter_kind);
58  auto spo = dynamic_cast<FakeSPO*>(ddb.getPhi());
59 
60  // occurs in call to registerData
61  ddb.dpsiV.resize(norb);
62  ddb.d2psiV.resize(norb);
63 
64  const SimulationCell simulation_cell;
65  ParticleSet elec(simulation_cell);
66 
67  elec.create({3});
68  ddb.recompute(elec);
69 
71  b.resize(3, 3);
72 
73  b(0, 0) = 0.6159749342;
74  b(0, 1) = -0.2408954682;
75  b(0, 2) = -0.1646081192;
76  b(1, 0) = 0.07923894288;
77  b(1, 1) = 0.1496231042;
78  b(1, 2) = -0.1428117337;
79  b(2, 0) = -0.2974298429;
80  b(2, 1) = -0.04586322768;
81  b(2, 2) = 0.3927890292;
82 
83  check_matrix(ddb.psiM, b);
84 
86  PsiValue det_ratio = ddb.ratioGrad(elec, 0, grad);
87  PsiValue det_ratio1 = 0.178276269185;
88  CHECK(det_ratio1 == ValueApprox(det_ratio));
89 
90  ddb.acceptMove(elec, 0);
91 
92  b(0, 0) = 3.455170657;
93  b(0, 1) = -1.35124809;
94  b(0, 2) = -0.9233316353;
95  b(1, 0) = 0.05476311768;
96  b(1, 1) = 0.1591951095;
97  b(1, 2) = -0.1362710138;
98  b(2, 0) = -2.235099338;
99  b(2, 1) = 0.7119205298;
100  b(2, 2) = 0.9105960265;
101 
102  check_matrix(ddb.psiM, b);
103 
104  // set virtutal particle position
105  PosType newpos(0.3, 0.2, 0.5);
106 
107  elec.makeVirtualMoves(newpos);
108  std::vector<ValueType> ratios(elec.getTotalNum());
109  ddb.evaluateRatiosAlltoOne(elec, ratios);
110 
111  CHECK(std::real(ratios[0]) == Approx(1.2070809985));
112  CHECK(std::real(ratios[1]) == Approx(0.2498726439));
113  CHECK(std::real(ratios[2]) == Approx(-1.3145695364));
114 
115  elec.makeMove(0, newpos - elec.R[0]);
116  PsiValue ratio_0 = ddb.ratio(elec, 0);
117  elec.rejectMove(0);
118 
119  CHECK(std::real(ratio_0) == Approx(-0.5343861437));
120 
121  VirtualParticleSet VP(elec, 2);
122  std::vector<PosType> newpos2(2);
123  std::vector<ValueType> ratios2(2);
124  newpos2[0] = newpos - elec.R[1];
125  newpos2[1] = PosType(0.2, 0.5, 0.3) - elec.R[1];
126  VP.makeMoves(elec, 1, newpos2);
127  ddb.evaluateRatios(VP, ratios2);
128 
129  CHECK(std::real(ratios2[0]) == Approx(0.4880285278));
130  CHECK(std::real(ratios2[1]) == Approx(0.9308456444));
131 
132  //test acceptMove
133  elec.makeMove(1, newpos - elec.R[1]);
134  PsiValue ratio_1 = ddb.ratio(elec, 1);
135  ddb.acceptMove(elec, 1);
136  elec.acceptMove(1);
137 
138  CHECK(std::real(ratio_1) == Approx(0.9308456444));
139  CHECK(std::real(ddb.get_log_value()) == Approx(1.9891064655));
140 }
141 
142 TEST_CASE("DiracDeterminant_first", "[wavefunction][fermion]")
143 {
144  test_DiracDeterminant_first<DiracDeterminant<>>(DetMatInvertor::HOST);
145  test_DiracDeterminant_first<DiracDeterminant<>>(DetMatInvertor::ACCEL);
146 #if defined(ENABLE_CUDA)
147  test_DiracDeterminant_first<DiracDeterminant<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>>(
149  test_DiracDeterminant_first<DiracDeterminant<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>>(
151 #elif defined(ENABLE_SYCL)
152  test_DiracDeterminant_first<DiracDeterminant<DelayedUpdateSYCL<ValueType, QMCTraits::QTFull::ValueType>>>(
154 #endif
155 }
156 
157 //#define DUMP_INFO
158 
159 template<typename DET>
161 {
162  auto spo_init = std::make_unique<FakeSPO>();
163  const int norb = 4;
164  spo_init->setOrbitalSetSize(norb);
165  DET ddb(std::move(spo_init), 0, norb, 1, inverter_kind);
166  auto spo = dynamic_cast<FakeSPO*>(ddb.getPhi());
167 
168  // occurs in call to registerData
169  ddb.dpsiV.resize(norb);
170  ddb.d2psiV.resize(norb);
171 
172  const SimulationCell simulation_cell;
173  ParticleSet elec(simulation_cell);
174 
175  elec.create({4});
176  ddb.recompute(elec);
177 
178  Matrix<ValueType> orig_a;
179  orig_a.resize(4, 4);
180  orig_a = spo->a2;
181 
182  for (int i = 0; i < 3; i++)
183  {
184  for (int j = 0; j < norb; j++)
185  {
186  orig_a(j, i) = spo->v2(i, j);
187  }
188  }
189 
190  //check_matrix(ddb.psiM, b);
192 
193  Matrix<ValueType> a_update1, scratchT;
194  a_update1.resize(4, 4);
195  scratchT.resize(4, 4);
196  a_update1 = spo->a2;
197  for (int j = 0; j < norb; j++)
198  {
199  a_update1(j, 0) = spo->v2(0, j);
200  }
201 
202  Matrix<ValueType> a_update2;
203  a_update2.resize(4, 4);
204  a_update2 = spo->a2;
205  for (int j = 0; j < norb; j++)
206  {
207  a_update2(j, 0) = spo->v2(0, j);
208  a_update2(j, 1) = spo->v2(1, j);
209  }
210 
211  Matrix<ValueType> a_update3;
212  a_update3.resize(4, 4);
213  a_update3 = spo->a2;
214  for (int j = 0; j < norb; j++)
215  {
216  a_update3(j, 0) = spo->v2(0, j);
217  a_update3(j, 1) = spo->v2(1, j);
218  a_update3(j, 2) = spo->v2(2, j);
219  }
220 
222  PsiValue det_ratio = ddb.ratioGrad(elec, 0, grad);
223 
224  simd::transpose(a_update1.data(), a_update1.rows(), a_update1.cols(), scratchT.data(), scratchT.rows(),
225  scratchT.cols());
226  LogValue det_update1;
227  dm.invert_transpose(scratchT, a_update1, det_update1);
228  PsiValue det_ratio1 = LogToValue<ValueType>::convert(det_update1 - ddb.get_log_value());
229 #ifdef DUMP_INFO
230  app_log() << "det 0 = " << std::exp(ddb.get_log_value()) << std::endl;
231  app_log() << "det 1 = " << std::exp(det_update1) << std::endl;
232  app_log() << "det ratio 1 = " << det_ratio1 << std::endl;
233 #endif
234  //double det_ratio1 = 0.178276269185;
235 
236  CHECK(det_ratio1 == ValueApprox(det_ratio));
237 
238  ddb.acceptMove(elec, 0);
239 
240  PsiValue det_ratio2 = ddb.ratioGrad(elec, 1, grad);
241  LogValue det_update2;
242  simd::transpose(a_update2.data(), a_update2.rows(), a_update2.cols(), scratchT.data(), scratchT.rows(),
243  scratchT.cols());
244  dm.invert_transpose(scratchT, a_update2, det_update2);
245  PsiValue det_ratio2_val = LogToValue<ValueType>::convert(det_update2 - det_update1);
246 #ifdef DUMP_INFO
247  app_log() << "det 1 = " << std::exp(ddb.get_log_value()) << std::endl;
248  app_log() << "det 2 = " << std::exp(det_update2) << std::endl;
249  app_log() << "det ratio 2 = " << det_ratio2 << std::endl;
250 #endif
251  //double det_ratio2_val = 0.178276269185;
252  CHECK(det_ratio2 == ValueApprox(det_ratio2_val));
253 
254  ddb.acceptMove(elec, 1);
255 
256  PsiValue det_ratio3 = ddb.ratioGrad(elec, 2, grad);
257  LogValue det_update3;
258  simd::transpose(a_update3.data(), a_update3.rows(), a_update3.cols(), scratchT.data(), scratchT.rows(),
259  scratchT.cols());
260  dm.invert_transpose(scratchT, a_update3, det_update3);
261  PsiValue det_ratio3_val = LogToValue<ValueType>::convert(det_update3 - det_update2);
262 #ifdef DUMP_INFO
263  app_log() << "det 2 = " << std::exp(ddb.get_log_value()) << std::endl;
264  app_log() << "det 3 = " << std::exp(det_update3) << std::endl;
265  app_log() << "det ratio 3 = " << det_ratio3 << std::endl;
266 #endif
267  CHECK(det_ratio3 == ValueApprox(det_ratio3_val));
268  //check_value(det_ratio3, det_ratio3_val);
269 
270  ddb.acceptMove(elec, 2);
271 
272  simd::transpose(orig_a.data(), orig_a.rows(), orig_a.cols(), scratchT.data(), scratchT.rows(), scratchT.cols());
273  dm.invert_transpose(scratchT, orig_a, det_update3);
274 
275 #ifdef DUMP_INFO
276  app_log() << "original " << std::endl;
277  app_log() << orig_a << std::endl;
278  app_log() << "block update " << std::endl;
279  app_log() << ddb.psiM << std::endl;
280 #endif
281 
282  check_matrix(orig_a, ddb.psiM);
283 }
284 
285 TEST_CASE("DiracDeterminant_second", "[wavefunction][fermion]")
286 {
287  test_DiracDeterminant_second<DiracDeterminant<>>(DetMatInvertor::HOST);
288  test_DiracDeterminant_second<DiracDeterminant<>>(DetMatInvertor::ACCEL);
289 #if defined(ENABLE_CUDA)
290  test_DiracDeterminant_second<DiracDeterminant<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>>(
292  test_DiracDeterminant_second<DiracDeterminant<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>>(
294 #elif defined(ENABLE_SYCL)
295  test_DiracDeterminant_second<DiracDeterminant<DelayedUpdateSYCL<ValueType, QMCTraits::QTFull::ValueType>>>(
297 #endif
298 }
299 
300 template<typename DET>
302 {
303  auto spo_init = std::make_unique<FakeSPO>();
304  const int norb = 4;
305  spo_init->setOrbitalSetSize(norb);
306  // maximum delay 2
307  DET ddc(std::move(spo_init), 0, norb, 2, inverter_kind);
308  auto spo = dynamic_cast<FakeSPO*>(ddc.getPhi());
309 
310  // occurs in call to registerData
311  ddc.dpsiV.resize(norb);
312  ddc.d2psiV.resize(norb);
313 
314  const SimulationCell simulation_cell;
315  ParticleSet elec(simulation_cell);
316 
317  elec.create({4});
318  ddc.recompute(elec);
319 
320  Matrix<ValueType> orig_a;
321  orig_a.resize(4, 4);
322  orig_a = spo->a2;
323 
324  for (int i = 0; i < 3; i++)
325  {
326  for (int j = 0; j < norb; j++)
327  {
328  orig_a(j, i) = spo->v2(i, j);
329  }
330  }
331 
332  //check_matrix(ddc.psiM, b);
334 
335  Matrix<ValueType> a_update1, scratchT;
336  scratchT.resize(4, 4);
337  a_update1.resize(4, 4);
338  a_update1 = spo->a2;
339  for (int j = 0; j < norb; j++)
340  {
341  a_update1(j, 0) = spo->v2(0, j);
342  }
343 
344  Matrix<ValueType> a_update2;
345  a_update2.resize(4, 4);
346  a_update2 = spo->a2;
347  for (int j = 0; j < norb; j++)
348  {
349  a_update2(j, 0) = spo->v2(0, j);
350  a_update2(j, 1) = spo->v2(1, j);
351  }
352 
353  Matrix<ValueType> a_update3;
354  a_update3.resize(4, 4);
355  a_update3 = spo->a2;
356  for (int j = 0; j < norb; j++)
357  {
358  a_update3(j, 0) = spo->v2(0, j);
359  a_update3(j, 1) = spo->v2(1, j);
360  a_update3(j, 2) = spo->v2(2, j);
361  }
362 
363 
365  PsiValue det_ratio = ddc.ratioGrad(elec, 0, grad);
366 
367  simd::transpose(a_update1.data(), a_update1.rows(), a_update1.cols(), scratchT.data(), scratchT.rows(),
368  scratchT.cols());
369  LogValue det_update1;
370  dm.invert_transpose(scratchT, a_update1, det_update1);
371  PsiValue det_ratio1 = LogToValue<ValueType>::convert(det_update1 - ddc.get_log_value());
372 #ifdef DUMP_INFO
373  app_log() << "det 0 = " << std::exp(ddc.get_log_value()) << std::endl;
374  app_log() << "det 1 = " << std::exp(det_update1) << std::endl;
375  app_log() << "det ratio 1 = " << det_ratio1 << std::endl;
376 #endif
377  //double det_ratio1 = 0.178276269185;
378 
379  CHECK(det_ratio1 == ValueApprox(det_ratio));
380 
381  // update of Ainv in ddc is delayed
382  ddc.acceptMove(elec, 0, true);
383  // force update Ainv in ddc using SM-1 code path
384  // also force population of dpsiM or you will have invalid grad below
385  ddc.completeUpdates();
386  check_matrix(a_update1, ddc.psiM);
387 
388  grad = ddc.evalGrad(elec, 1);
389 
390  PsiValue det_ratio2 = ddc.ratioGrad(elec, 1, grad);
391  simd::transpose(a_update2.data(), a_update2.rows(), a_update2.cols(), scratchT.data(), scratchT.rows(),
392  scratchT.cols());
393  LogValue det_update2;
394  dm.invert_transpose(scratchT, a_update2, det_update2);
395  PsiValue det_ratio2_val = LogToValue<ValueType>::convert(det_update2 - det_update1);
396 #ifdef DUMP_INFO
397  app_log() << "det 1 = " << std::exp(ddc.get_log_value()) << std::endl;
398  app_log() << "det 2 = " << std::exp(det_update2) << std::endl;
399  app_log() << "det ratio 2 = " << det_ratio2 << std::endl;
400 #endif
401  // check ratio computed directly and the one computed by ddc with no delay
402  //double det_ratio2_val = 0.178276269185;
403  CHECK(det_ratio2 == ValueApprox(det_ratio2_val));
404 
405  // update of Ainv in ddc is delayed
406  ddc.acceptMove(elec, 1, true);
407 
408  grad = ddc.evalGrad(elec, 2);
409 
410  PsiValue det_ratio3 = ddc.ratioGrad(elec, 2, grad);
411  simd::transpose(a_update3.data(), a_update3.rows(), a_update3.cols(), scratchT.data(), scratchT.rows(),
412  scratchT.cols());
413  LogValue det_update3;
414  dm.invert_transpose(scratchT, a_update3, det_update3);
415  PsiValue det_ratio3_val = LogToValue<ValueType>::convert(det_update3 - det_update2);
416 #ifdef DUMP_INFO
417  app_log() << "det 2 = " << std::exp(ddc.get_log_value()) << std::endl;
418  app_log() << "det 3 = " << std::exp(det_update3) << std::endl;
419  app_log() << "det ratio 3 = " << det_ratio3 << std::endl;
420 #endif
421  // check ratio computed directly and the one computed by ddc with 1 delay
422  CHECK(det_ratio3 == ValueApprox(det_ratio3_val));
423  //check_value(det_ratio3, det_ratio3_val);
424 
425  // maximal delay reached and Ainv is updated fully
426  ddc.acceptMove(elec, 2, true);
427  ddc.completeUpdates();
428 
429  // fresh invert orig_a
430  simd::transpose(orig_a.data(), orig_a.rows(), orig_a.cols(), scratchT.data(), scratchT.rows(), scratchT.cols());
431  dm.invert_transpose(scratchT, orig_a, det_update3);
432 
433 #ifdef DUMP_INFO
434  app_log() << "original " << std::endl;
435  app_log() << orig_a << std::endl;
436  app_log() << "delayed update " << std::endl;
437  app_log() << ddc.psiM << std::endl;
438 #endif
439 
440  // compare all the elements of psiM in ddc and orig_a
441  check_matrix(orig_a, ddc.psiM);
442 }
443 
444 TEST_CASE("DiracDeterminant_delayed_update", "[wavefunction][fermion]")
445 {
446  test_DiracDeterminant_delayed_update<DiracDeterminant<>>(DetMatInvertor::HOST);
447  test_DiracDeterminant_delayed_update<DiracDeterminant<>>(DetMatInvertor::ACCEL);
448 #if defined(ENABLE_CUDA)
449  test_DiracDeterminant_delayed_update<DiracDeterminant<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>>(
451  test_DiracDeterminant_delayed_update<DiracDeterminant<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>>(
453 #elif defined(ENABLE_SYCL)
454  test_DiracDeterminant_delayed_update<DiracDeterminant<DelayedUpdateSYCL<ValueType, QMCTraits::QTFull::ValueType>>>(
456 #endif
457 }
458 
459 #ifdef QMC_COMPLEX
460 template<typename DET>
461 void test_DiracDeterminant_spinor_update(const DetMatInvertor inverter_kind)
462 {
464  using PosType = QMCTraits::PosType;
467  using ParticlePos = ParticleSet::ParticlePos;
468  using ParticleGradient = ParticleSet::ParticleGradient;
469  using ParticleLaplacian = ParticleSet::ParticleLaplacian;
470 
471  // O2 test example from pwscf non-collinear calculation.
473  lattice.R = {5.10509515, -3.23993545, 0.00000000, 5.10509515, 3.23993545,
474  0.00000000, -6.49690625, 0.00000000, 7.08268015};
475 
476  //Shamelessly stealing this from test_einset.cpp. 3 particles though.
477  const SimulationCell simulation_cell(lattice);
478  ParticleSet ions_(simulation_cell);
479  ParticleSet elec_(simulation_cell);
480  ions_.setName("ion");
481  ions_.create({2});
482 
483  ions_.R[0] = {0.00000000, 0.00000000, 1.08659253};
484  ions_.R[1] = {0.00000000, 0.00000000, -1.08659253};
485  elec_.setName("elec");
486  elec_.create({3});
487  elec_.R[0] = {0.1, -0.3, 1.0};
488  elec_.R[1] = {-0.1, 0.3, 1.0};
489  elec_.R[2] = {0.1, 0.2, 0.3};
490  elec_.spins[0] = 0.0;
491  elec_.spins[1] = 0.2;
492  elec_.spins[2] = 0.4;
493  elec_.setSpinor(true);
494 
495  SpeciesSet& tspecies = elec_.getSpeciesSet();
496  int upIdx = tspecies.addSpecies("u");
497  int chargeIdx = tspecies.addAttribute("charge");
498  tspecies(chargeIdx, upIdx) = -1;
499 
500  elec_.addTable(ions_);
501  elec_.resetGroups();
502  elec_.update();
503  // </steal>
504 
505 
506  const auto nelec = elec_.R.size();
507  //Our test case is going to be three electron gas orbitals distinguished by 3 different kpoints.
508  //Independent SPO's for the up and down channels.
509  //
510  std::vector<PosType> kup, kdn;
511  std::vector<RealType> k2up, k2dn;
512 
513 
514  kup.resize(nelec);
515  kup[0] = PosType(0, 0, 0);
516  kup[1] = PosType(0.1, 0.2, 0.3);
517  kup[2] = PosType(0.4, 0.5, 0.6);
518 
519  kdn.resize(nelec);
520  kdn[0] = PosType(0, 0, 0);
521  kdn[1] = PosType(-0.1, 0.2, -0.3);
522  kdn[2] = PosType(0.4, -0.5, 0.6);
523 
524  auto spo_up = std::make_unique<FreeOrbital>("free_orb_up", kup);
525  auto spo_dn = std::make_unique<FreeOrbital>("free_orb_up", kdn);
526 
527  auto spinor_set = std::make_unique<SpinorSet>("free_orb_spinor");
528  spinor_set->set_spos(std::move(spo_up), std::move(spo_dn));
529 
530  DET dd(std::move(spinor_set), 0, nelec, 1, inverter_kind);
531  app_log() << " nelec=" << nelec << std::endl;
532 
533  ParticleGradient G;
534  ParticleLaplacian L;
535  ParticleAttrib<ComplexType> SG;
536 
537  G.resize(nelec);
538  L.resize(nelec);
539  SG.resize(nelec);
540 
541  G = 0.0;
542  L = 0.0;
543  SG = 0.0;
544 
545  PosType dr(0.1, -0.05, 0.2);
546  RealType ds = 0.3;
547 
548  app_log() << " BEFORE\n";
549  app_log() << " R = " << elec_.R << std::endl;
550  app_log() << " s = " << elec_.spins << std::endl;
551 
552  //In this section, we're going to test that values and various derivatives come out
553  //correctly at the reference configuration.
554 
555  LogValue logref = dd.evaluateLog(elec_, G, L);
556 
557  CHECK(logref == ComplexApprox(ValueType(-1.1619939279564413, 0.8794794652468605)));
558  CHECK(G[0][0] == ComplexApprox(ValueType(0.13416635, 0.2468612)));
559  CHECK(G[0][1] == ComplexApprox(ValueType(-1.1165475, 0.71497753)));
560  CHECK(G[0][2] == ComplexApprox(ValueType(0.0178403, 0.08212244)));
561  CHECK(G[1][0] == ComplexApprox(ValueType(1.00240841, 0.12371593)));
562  CHECK(G[1][1] == ComplexApprox(ValueType(1.62679698, -0.41080777)));
563  CHECK(G[1][2] == ComplexApprox(ValueType(1.81324632, 0.78589013)));
564  CHECK(G[2][0] == ComplexApprox(ValueType(-1.10994555, 0.15525902)));
565  CHECK(G[2][1] == ComplexApprox(ValueType(-0.46335602, -0.50809713)));
566  CHECK(G[2][2] == ComplexApprox(ValueType(-1.751199, 0.10949589)));
567  CHECK(L[0] == ComplexApprox(ValueType(-2.06554158, 1.18145239)));
568  CHECK(L[1] == ComplexApprox(ValueType(-5.06340536, 0.82126749)));
569  CHECK(L[2] == ComplexApprox(ValueType(-4.82375261, -1.97943258)));
570 
571  //This is a workaround for the fact that I haven't implemented
572  // evaluateLogWithSpin(). Shouldn't be needed unless we do drifted all-electron moves...
573  for (int iat = 0; iat < nelec; iat++)
574  dd.evalGradWithSpin(elec_, iat, SG[iat]);
575 
576  CHECK(SG[0] == ComplexApprox(ValueType(-1.05686704, -2.01802154)));
577  CHECK(SG[1] == ComplexApprox(ValueType(1.18922259, 2.80414598)));
578  CHECK(SG[2] == ComplexApprox(ValueType(-0.62617675, -0.51093984)));
579 
580  GradType g_singleeval(0.0);
581  g_singleeval = dd.evalGrad(elec_, 1);
582 
583  CHECK(g_singleeval[0] == ComplexApprox(G[1][0]));
584  CHECK(g_singleeval[1] == ComplexApprox(G[1][1]));
585  CHECK(g_singleeval[2] == ComplexApprox(G[1][2]));
586 
587 
588  //And now we're going to propose a trial spin+particle move and check the ratio and gradients at the
589  //new location.
590  //
591  elec_.makeMoveAndCheckWithSpin(1, dr, ds);
592 
593  ValueType ratio_new;
594  ValueType spingrad_new;
595  GradType grad_new;
596 
597  //This tests ratio only evaluation. Indirectly a call to evaluate(P,iat)
598  ratio_new = dd.ratio(elec_, 1);
599  CHECK(ratio_new == ComplexApprox(ValueType(1.7472917722050971, 1.1900872950904169)));
600 
601  ratio_new = dd.ratioGrad(elec_, 1, grad_new);
602  CHECK(ratio_new == ComplexApprox(ValueType(1.7472917722050971, 1.1900872950904169)));
603  CHECK(grad_new[0] == ComplexApprox(ValueType(0.5496675534224996, -0.07968022499097227)));
604  CHECK(grad_new[1] == ComplexApprox(ValueType(0.4927399293808675, -0.29971549854643653)));
605  CHECK(grad_new[2] == ComplexApprox(ValueType(1.2792642963632226, 0.12110307514989149)));
606 
607  grad_new = 0;
608  spingrad_new = 0;
609  ratio_new = dd.ratioGradWithSpin(elec_, 1, grad_new, spingrad_new);
610  CHECK(ratio_new == ComplexApprox(ValueType(1.7472917722050971, 1.1900872950904169)));
611  CHECK(grad_new[0] == ComplexApprox(ValueType(0.5496675534224996, -0.07968022499097227)));
612  CHECK(grad_new[1] == ComplexApprox(ValueType(0.4927399293808675, -0.29971549854643653)));
613  CHECK(grad_new[2] == ComplexApprox(ValueType(1.2792642963632226, 0.12110307514989149)));
614  CHECK(spingrad_new == ComplexApprox(ValueType(1.164708841479661, 0.9576425115390172)));
615 
616 
617  //Cool. Now we test the transition between rejecting a move and accepting a move.
618  //Reject the move first. We want to see if everything stays the same. evalGrad and evalSpinGrad for ease of use.
619 
620  elec_.rejectMove(1);
621  //Going to check evalGrad and evalGradWithSpin for simplicity.
622  g_singleeval = dd.evalGrad(elec_, 1);
623  CHECK(g_singleeval[0] == ComplexApprox(G[1][0]));
624  CHECK(g_singleeval[1] == ComplexApprox(G[1][1]));
625  CHECK(g_singleeval[2] == ComplexApprox(G[1][2]));
626 
627  ValueType spingrad_old_test;
628  g_singleeval = dd.evalGradWithSpin(elec_, 1, spingrad_old_test);
629 
630  CHECK(spingrad_old_test == ComplexApprox(SG[1]));
631  CHECK(g_singleeval[0] == ComplexApprox(G[1][0]));
632  CHECK(g_singleeval[1] == ComplexApprox(G[1][1]));
633  CHECK(g_singleeval[2] == ComplexApprox(G[1][2]));
634 
635  //Now we test what happens if we accept a move...
636  elec_.makeMoveAndCheckWithSpin(1, dr, ds);
637  elec_.acceptMove(1);
638 
639  LogValue lognew(0.0);
640  G = 0.0; //evalauteLog += onto the G and L arguments. So we zero them out.
641  L = 0.0;
642  SG = 0.0;
643  lognew = dd.evaluateLog(elec_, G, L);
644 
645  for (int iat = 0; iat < nelec; iat++)
646  dd.evalGradWithSpin(elec_, iat, SG[iat]);
647  //logval for the new configuration has been computed with python.
648  //The others reference values are computed earlier in this section. New values equal the previous
649  // "new values" associated with the previous trial moves.
650  CHECK(lognew == ComplexApprox(ValueType(-0.41337396772929913, 1.4774106123071726)));
651  CHECK(G[1][0] == ComplexApprox(grad_new[0]));
652  CHECK(G[1][1] == ComplexApprox(grad_new[1]));
653  CHECK(G[1][2] == ComplexApprox(grad_new[2]));
654  CHECK(SG[1] == ComplexApprox(spingrad_new));
655 }
656 
657 TEST_CASE("DiracDeterminant_spinor_update", "[wavefunction][fermion]")
658 {
659  test_DiracDeterminant_spinor_update<DiracDeterminant<>>(DetMatInvertor::HOST);
660  test_DiracDeterminant_spinor_update<DiracDeterminant<>>(DetMatInvertor::ACCEL);
661 #ifdef ENABLE_CUDA
662  test_DiracDeterminant_spinor_update<DiracDeterminant<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>>(
664  test_DiracDeterminant_spinor_update<DiracDeterminant<DelayedUpdateCUDA<ValueType, QMCTraits::QTFull::ValueType>>>(
666 #endif
667 }
668 #endif
669 
670 } // namespace qmcplusplus
WaveFunctionComponent::PsiValue PsiValue
Definition: SlaterDet.cpp:25
static T convert(const std::complex< T1 > &logpsi)
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
void test_DiracDeterminant_delayed_update(const DetMatInvertor inverter_kind)
size_t getTotalNum() const
Definition: ParticleSet.h:493
std::ostream & app_log()
Definition: OutputManager.h:65
CrystalLattice< OHMMS_PRECISION, OHMMS_DIM > ParticleLayout
Definition: Configuration.h:79
TEST_CASE("complex_helper", "[type_traits]")
RealType ValueType
Definition: QMCTypes.h:42
DetMatInvertor
determinant matrix inverter select
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
ParticleAttrib< QTFull::ValueType > ParticleLaplacian
Definition: Configuration.h:96
LatticeGaussianProduct::GradType GradType
void transpose(const T *restrict A, size_t m, size_t lda, TO *restrict B, size_t n, size_t ldb)
transpose of A(m,n) to B(n,m)
Definition: algorithm.hpp:97
QTBase::ComplexType ComplexType
Definition: Configuration.h:59
void resize(size_type n, size_type m)
Resize the container.
Definition: OhmmsMatrix.h:99
size_type cols() const
Definition: OhmmsMatrix.h:78
std::complex< QTFull::RealType > LogValue
QMCTraits::PosType PosType
void check_matrix(Matrix< T1 > &a, Matrix< T2 > &b)
CrystalLattice< OHMMS_PRECISION, OHMMS_DIM > lattice
void test_DiracDeterminant_first(const DetMatInvertor inverter_kind)
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
size_type size() const
Definition: OhmmsMatrix.h:76
QTBase::ValueType ValueType
Definition: Configuration.h:60
REQUIRE(std::filesystem::exists(filename))
void rejectMove(Index_t iat)
reject a proposed move in regular mode
helper class to compute matrix inversion and the log value of determinant
Definition: DiracMatrix.h:111
ParticlePos R
Position.
Definition: ParticleSet.h:79
QTBase::PosType PosType
Definition: Configuration.h:61
MakeReturn< UnaryNode< FnExp, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t exp(const Vector< T1, C1 > &l)
size_type rows() const
Definition: OhmmsMatrix.h:77
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_
CHECK(log_values[0]==ComplexApprox(std::complex< double >{ 5.603777579195571, -6.1586603331188225 }))
ParticleAttrib< SingleParticlePos > ParticlePos
Definition: Configuration.h:92
TinyVector< double, 3 > PosType
QMCTraits::ComplexType ComplexType
LatticeGaussianProduct::ValueType ValueType
ParticleAttrib< QTFull::GradType > ParticleGradient
Definition: Configuration.h:95
Declaration of DiracDeterminant with a S(ingle)P(article)O(rbital)Set.
Declaration of WaveFunctionComponent.
std::complex< double > LogValue
void acceptMove(Index_t iat)
accept the move and update the particle attribute by the proposed move in regular mode ...
std::enable_if_t< std::is_same< T_FP, TMAT >::value > invert_transpose(const Matrix< TMAT, ALLOC1 > &amat, Matrix< TMAT, ALLOC2 > &invMat, std::complex< TREAL > &LogDet)
compute the inverse of the transpose of matrix A and its determinant value in log when T_FP and TMAT ...
Definition: DiracMatrix.h:188
void makeVirtualMoves(const SingleParticlePos &newpos)
Handles virtual moves for all the particles to a single newpos.
void test_DiracDeterminant_second(const DetMatInvertor inverter_kind)