QMCPACK
test_SlaterDet.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) 2024 QMCPACK developers.
6 //
7 // File developed by: Cody A. Melton, cmelton@sandia.gov, Sandia National Laboratories
8 //
9 // File created by: Cody A. Melton, cmelton@sandia.gov, Sandia National Laboratories
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 #include "catch.hpp"
13 
18 #include <ResourceCollection.h>
19 #include <algorithm>
20 
21 namespace qmcplusplus
22 {
23 
25 {
26 public:
27  DummyDiracDetWithoutMW(const std::string& class_name, std::unique_ptr<SPOSet>&& spos, int first, int last)
28  : DiracDeterminantBase(getClassName(), std::move(spos), first, last)
29  {}
30  std::string getClassName() const override { return "DummyDiracDetWithoutMW"; }
34  {
35  G = 0.0;
36  L = 0.0;
37  return 0.0;
38  }
39  void acceptMove(ParticleSet& P, int iat, bool safe_to_delay = false) override {}
40  void restore(int iat) override {}
41  PsiValue ratio(ParticleSet& P, int iat) override { return 1.0; }
42  GradType evalGrad(ParticleSet& P, int iat) override
43  {
44  GradType grad;
45  grad[0] = 123.;
46  grad[1] = 456.;
47  grad[2] = 789.;
48  return grad;
49  }
50  GradType evalGradWithSpin(ParticleSet& P, int iat, ComplexType& spingrad) override
51  {
52  GradType grad;
53  grad[0] = 0.123;
54  grad[1] = 0.456;
55  grad[2] = 0.789;
56  spingrad = ComplexType(0.1, 0.2);
57  return grad;
58  }
59  PsiValue ratioGrad(ParticleSet& P, int iat, GradType& grad_iat) override
60  {
61  grad_iat[0] = 123.;
62  grad_iat[1] = 456.;
63  grad_iat[2] = 789.;
64  return 1;
65  }
66  PsiValue ratioGradWithSpin(ParticleSet& P, int iat, GradType& grad_iat, ComplexType& spingrad_iat) override
67  {
68  grad_iat[0] = 0.123;
69  grad_iat[1] = 0.456;
70  grad_iat[2] = 0.789;
71  spingrad_iat = ComplexType(0.1, 0.2);
72  return 1;
73  }
74  void registerData(ParticleSet& P, WFBufferType& buf) override {}
75  LogValue updateBuffer(ParticleSet& P, WFBufferType& buf, bool fromscratch = false) override { return 0.0; }
76  void copyFromBuffer(ParticleSet& P, WFBufferType& buf) override {}
78  const opt_variables_type& optvars,
79  Vector<ValueType>& dlogpsi,
80  Vector<ValueType>& dhpsioverpsi) override
81  {}
82  std::unique_ptr<DiracDeterminantBase> makeCopy(std::unique_ptr<SPOSet>&& spo) const override
83  {
84  return std::make_unique<DummyDiracDetWithoutMW>(getClassName(), std::move(spo), FirstIndex, LastIndex);
85  }
86 };
87 
89 {
90 public:
91  DummyDiracDetWithMW(const std::string& class_name, std::unique_ptr<SPOSet>&& spos, int first, int last)
92  : DummyDiracDetWithoutMW(getClassName(), std::move(spos), first, last)
93  {}
94 
97  const int iat,
98  std::vector<GradType>& grad_now) const override
99  {
100  for (auto& grad : grad_now)
101  {
102  grad[0] = 321.;
103  grad[1] = 654.;
104  grad[2] = 987.;
105  }
106  }
108  const RefVectorWithLeader<ParticleSet>& p_list,
109  const int iat,
110  std::vector<GradType>& grad_now,
111  std::vector<ComplexType>& spingrad_now) const override
112  {
113  for (auto& grad : grad_now)
114  {
115  grad[0] = 0.321;
116  grad[1] = 0.654;
117  grad[2] = 0.987;
118  }
119  for (auto& spingrad : spingrad_now)
120  spingrad = ComplexType(0.2, 0.1);
121  }
123  const RefVectorWithLeader<ParticleSet>& p_list,
124  int iat,
125  std::vector<PsiValue>& ratios,
126  std::vector<GradType>& grad_new) const override
127  {
128  for (auto& grad : grad_new)
129  {
130  grad[0] = 321.;
131  grad[1] = 654.;
132  grad[2] = 987.;
133  }
134  }
136  const RefVectorWithLeader<ParticleSet>& p_list,
137  int iat,
138  std::vector<PsiValue>& ratios,
139  std::vector<GradType>& grad_new,
140  std::vector<ComplexType>& spingrad_new) const override
141  {
142  for (auto& grad : grad_new)
143  {
144  grad[0] = 0.321;
145  grad[1] = 0.654;
146  grad[2] = 0.987;
147  }
148  for (auto& spingrad : spingrad_new)
149  spingrad = ComplexType(0.2, 0.1);
150  }
151 };
152 
153 TEST_CASE("SlaterDet mw_ APIs", "[wavefunction]")
154 {
156 
158  auto& elec0 = *(particle_pool).getParticleSet("e");
159  auto& elec1 = *(particle_pool).getParticleSet("e");
160  RefVectorWithLeader<ParticleSet> p_list(elec0, {elec0, elec1});
161 
162  std::unique_ptr<ConstantSPOSet> spo_ptr0 = std::make_unique<ConstantSPOSet>("dummySPO", 3, 3);
163  std::unique_ptr<ConstantSPOSet> spo_ptr1 = std::make_unique<ConstantSPOSet>("dummySPO", 3, 3);
164  //Right now, DiracDeterminantBatched has mw_ WithSpin APIs but DiracDeterminant does not.
165  //We want to add a test to make sure Slater determinant chooses the mw_ implementation if it has it.
166 
167  // First, do without mw_ APIs
168  {
169  std::unique_ptr<DiracDeterminantBase> det_ptr0 =
170  std::make_unique<DummyDiracDetWithoutMW>("dummy", std::move(spo_ptr0), 0, 12);
171  std::unique_ptr<DiracDeterminantBase> det_ptr1 =
172  std::make_unique<DummyDiracDetWithoutMW>("dummy", std::move(spo_ptr1), 0, 12);
173 
174  std::vector<std::unique_ptr<DiracDeterminantBase>> dirac_dets0;
175  dirac_dets0.push_back(std::move(det_ptr0));
176  std::vector<std::unique_ptr<DiracDeterminantBase>> dirac_dets1;
177  dirac_dets1.push_back(std::move(det_ptr1));
178 
179  SlaterDet slaterdet0(elec0, std::move(dirac_dets0));
180  SlaterDet slaterdet1(elec0, std::move(dirac_dets1));
181 
182  RefVectorWithLeader<WaveFunctionComponent> sd_list(slaterdet0, {slaterdet0, slaterdet1});
183  ResourceCollection sd_res("test_sd_res");
184  slaterdet0.createResource(sd_res);
185  ResourceCollectionTeamLock<WaveFunctionComponent> mw_sd_lock(sd_res, sd_list);
186 
187  std::vector<SPOSet::GradType> grads(2);
188  std::vector<WaveFunctionComponent::PsiValue> ratios(2);
189  std::vector<SPOSet::ComplexType> spingrads(2);
190  slaterdet0.mw_evalGrad(sd_list, p_list, 0, grads);
191  for (auto grad : grads)
192  {
193  CHECK(grad[0] == ValueApprox(123.));
194  CHECK(grad[1] == ValueApprox(456.));
195  CHECK(grad[2] == ValueApprox(789.));
196  }
197 
198  slaterdet0.mw_evalGradWithSpin(sd_list, p_list, 0, grads, spingrads);
199  for (auto grad : grads)
200  {
201  CHECK(grad[0] == ValueApprox(0.123));
202  CHECK(grad[1] == ValueApprox(0.456));
203  CHECK(grad[2] == ValueApprox(0.789));
204  }
205  for (auto sgrad : spingrads)
206  CHECK(sgrad == ComplexApprox(SPOSet::ComplexType(0.1, 0.2)));
207 
208  slaterdet0.mw_ratioGrad(sd_list, p_list, 0, ratios, grads);
209  for (auto grad : grads)
210  {
211  CHECK(grad[0] == ValueApprox(123.));
212  CHECK(grad[1] == ValueApprox(456.));
213  CHECK(grad[2] == ValueApprox(789.));
214  }
215 
216  slaterdet0.mw_ratioGradWithSpin(sd_list, p_list, 0, ratios, grads, spingrads);
217  for (auto grad : grads)
218  {
219  CHECK(grad[0] == ValueApprox(0.123));
220  CHECK(grad[1] == ValueApprox(0.456));
221  CHECK(grad[2] == ValueApprox(0.789));
222  }
223  for (auto sgrad : spingrads)
224  CHECK(sgrad == ComplexApprox(SPOSet::ComplexType(0.1, 0.2)));
225  }
226  //Now do with MW
227  {
228  std::unique_ptr<DiracDeterminantBase> det_ptr0 =
229  std::make_unique<DummyDiracDetWithMW>("dummy", std::move(spo_ptr0), 0, 12);
230  std::unique_ptr<DiracDeterminantBase> det_ptr1 =
231  std::make_unique<DummyDiracDetWithMW>("dummy", std::move(spo_ptr1), 0, 12);
232 
233  std::vector<std::unique_ptr<DiracDeterminantBase>> dirac_dets0;
234  dirac_dets0.push_back(std::move(det_ptr0));
235  std::vector<std::unique_ptr<DiracDeterminantBase>> dirac_dets1;
236  dirac_dets1.push_back(std::move(det_ptr1));
237 
238  SlaterDet slaterdet0(elec0, std::move(dirac_dets0));
239  SlaterDet slaterdet1(elec1, std::move(dirac_dets1));
240 
241  RefVectorWithLeader<WaveFunctionComponent> sd_list(slaterdet0, {slaterdet0, slaterdet1});
242 
243  ResourceCollection sd_res("test_sd_res");
244  slaterdet0.createResource(sd_res);
245  ResourceCollectionTeamLock<WaveFunctionComponent> mw_sd_lock(sd_res, sd_list);
246 
247  std::vector<SPOSet::GradType> grads(2);
248  std::vector<WaveFunctionComponent::PsiValue> ratios(2);
249  std::vector<SPOSet::ComplexType> spingrads(2);
250  slaterdet0.mw_evalGrad(sd_list, p_list, 0, grads);
251  for (auto grad : grads)
252  {
253  CHECK(grad[0] == ValueApprox(321.));
254  CHECK(grad[1] == ValueApprox(654.));
255  CHECK(grad[2] == ValueApprox(987.));
256  }
257 
258  slaterdet0.mw_evalGradWithSpin(sd_list, p_list, 0, grads, spingrads);
259  for (auto grad : grads)
260  {
261  CHECK(grad[0] == ValueApprox(0.321));
262  CHECK(grad[1] == ValueApprox(0.654));
263  CHECK(grad[2] == ValueApprox(0.987));
264  }
265  for (auto sgrad : spingrads)
266  CHECK(sgrad == ComplexApprox(SPOSet::ComplexType(0.2, 0.1)));
267 
268  slaterdet0.mw_ratioGrad(sd_list, p_list, 0, ratios, grads);
269  for (auto grad : grads)
270  {
271  CHECK(grad[0] == ValueApprox(321.));
272  CHECK(grad[1] == ValueApprox(654.));
273  CHECK(grad[2] == ValueApprox(987.));
274  }
275 
276  slaterdet0.mw_ratioGradWithSpin(sd_list, p_list, 0, ratios, grads, spingrads);
277  for (auto grad : grads)
278  {
279  CHECK(grad[0] == ValueApprox(0.321));
280  CHECK(grad[1] == ValueApprox(0.654));
281  CHECK(grad[2] == ValueApprox(0.987));
282  }
283  for (auto sgrad : spingrads)
284  CHECK(sgrad == ComplexApprox(SPOSet::ComplexType(0.2, 0.1)));
285  }
286 }
287 
288 } // namespace qmcplusplus
Declaration of DiracDeterminantBase with a S(ingle)P(article)O(rbital)Set.
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
void evaluateDerivatives(ParticleSet &P, const opt_variables_type &optvars, Vector< ValueType > &dlogpsi, Vector< ValueType > &dhpsioverpsi) override
Compute the derivatives of both the log of the wavefunction and kinetic energy with respect to optimi...
void acceptMove(ParticleSet &P, int iat, bool safe_to_delay=false) override
a move for iat-th particle is accepted.
TEST_CASE("complex_helper", "[type_traits]")
void mw_ratioGradWithSpin(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< PsiValue > &ratios, std::vector< GradType > &grad_now, std::vector< ComplexType > &spingrad_now) const override
compute the ratio of the new to old WaveFunctionComponent value and the new gradient/spingradient of ...
Definition: SlaterDet.cpp:85
GradType evalGrad(ParticleSet &P, int iat) override
return the current gradient for the iat-th particle
DummyDiracDetWithoutMW(const std::string &class_name, std::unique_ptr< SPOSet > &&spos, int first, int last)
QTBase::ComplexType ComplexType
Definition: Configuration.h:59
void mw_evalGradWithSpin(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, const int iat, std::vector< GradType > &grad_now, std::vector< ComplexType > &spingrad_now) const override
compute the current gradients and spin gradients for the iat-th particle of multiple walkers ...
void createResource(ResourceCollection &collection) const override
initialize a shared resource and hand it to a collection
Definition: SlaterDet.cpp:215
Attaches a unit to a Vector for IO.
Communicate * Controller
Global Communicator for a process.
Definition: Communicate.cpp:35
const int FirstIndex
index of the first particle with respect to the particle set
void mw_evalGrad(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, const int iat, std::vector< GradType > &grad_now) const override
compute the current gradients for the iat-th particle of multiple walkers
void mw_ratioGrad(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< PsiValue > &ratios, std::vector< GradType > &grad_new) const override
compute the ratio of the new to old WaveFunctionComponent value and the new gradient of multiple walk...
PsiValue ratioGradWithSpin(ParticleSet &P, int iat, GradType &grad_iat, ComplexType &spingrad_iat) override
evaluate the ratio of the new to old WaveFunctionComponent value and the new spin gradient Default im...
std::complex< QTFull::RealType > LogValue
Wrapping information on parallelism.
Definition: Communicate.h:68
void registerData(ParticleSet &P, WFBufferType &buf) override
For particle-by-particle move.
static ParticleSetPool make_O2_spinor(Communicate *c)
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
void restore(int iat) override
If a move for iat-th particle is rejected, restore to the content.
LogValue evaluateLog(const ParticleSet &P, ParticleSet::ParticleGradient &G, ParticleSet::ParticleLaplacian &L) override
evaluate the value of the WaveFunctionComponent from scratch
void mw_ratioGrad(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< PsiValue > &ratios, std::vector< GradType > &grad_now) const override
compute the ratio of the new to old WaveFunctionComponent value and the new gradient of multiple walk...
Definition: SlaterDet.cpp:75
PsiValue ratio(ParticleSet &P, int iat) override
evaluate the ratio of the new to old WaveFunctionComponent value
class to handle a set of variables that can be modified during optimizations
Definition: VariableSet.h:49
const int LastIndex
index of the last particle with respect to the particle set
DummyDiracDetWithMW(const std::string &class_name, std::unique_ptr< SPOSet > &&spos, int first, int last)
CHECK(log_values[0]==ComplexApprox(std::complex< double >{ 5.603777579195571, -6.1586603331188225 }))
void mw_evalGradWithSpin(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< GradType > &grad_now, std::vector< ComplexType > &spingrad_now) const override
compute the current gradients and spin gradients for the iat-th particle of multiple walkers ...
Definition: SlaterDet.cpp:98
void copyFromBuffer(ParticleSet &P, WFBufferType &buf) override
For particle-by-particle move.
handles acquire/release resource by the consumer (RefVectorWithLeader type).
LogValue updateBuffer(ParticleSet &P, WFBufferType &buf, bool fromscratch=false) override
For particle-by-particle move.
PsiValue ratioGrad(ParticleSet &P, int iat, GradType &grad_iat) override
evaluate the ratio of the new to old WaveFunctionComponent value and the new gradient ...
void mw_ratioGradWithSpin(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< PsiValue > &ratios, std::vector< GradType > &grad_new, std::vector< ComplexType > &spingrad_new) const override
compute the ratio of the new to old WaveFunctionComponent value and the new gradient/spingradient of ...
GradType evalGradWithSpin(ParticleSet &P, int iat, ComplexType &spingrad) override
return the current spin gradient for the iat-th particle Default implementation assumes that WaveFunc...
std::unique_ptr< DiracDeterminantBase > makeCopy(std::unique_ptr< SPOSet > &&spo) const override
cloning function
void mw_evalGrad(const RefVectorWithLeader< WaveFunctionComponent > &wfc_list, const RefVectorWithLeader< ParticleSet > &p_list, int iat, std::vector< GradType > &grad_now) const override
compute the current gradients for the iat-th particle of multiple walkers
Definition: SlaterDet.h:152
std::string getClassName() const override
return class name