QMCPACK
test_J2_derivatives.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) 2021 QMCPACK developers.
6 //
7 // File developed by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
8 //
9 // File created by: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 #include "catch.hpp"
13 
14 #include <memory>
15 #include "Jastrow/TwoBodyJastrow.h"
16 #include "Jastrow/FakeFunctor.h"
17 
18 namespace qmcplusplus
19 {
20 
22 
23 TEST_CASE("TwoBodyJastrow simple", "[wavefunction]")
24 {
25  const SimulationCell simulation_cell;
26  ParticleSet elec(simulation_cell);
27  elec.setName("e");
28  elec.create({1, 1});
29  TwoBodyJastrow<FakeJasFunctor> jorb("J2_fake", elec, false);
30 
31  opt_variables_type active;
32  jorb.checkOutVariables(active);
33 }
34 
35 TEST_CASE("TwoBodyJastrow one species and two variables", "[wavefunction]")
36 {
37  const SimulationCell simulation_cell;
38  ParticleSet elec(simulation_cell);
39  elec.setName("e");
40  elec.create({1, 1});
41  TwoBodyJastrow<FakeJasFunctor> jorb("J2_fake", elec, false);
42 
43  auto j2_uptr = std::make_unique<FakeJasFunctor>("test_fake");
44  auto& j2 = *j2_uptr;
45  j2.myVars.insert("opt1", 1.0);
46  j2.myVars.insert("opt2", 2.0);
47  // update num_active_vars
48  j2.myVars.resetIndex();
49  jorb.addFunc(0, 0, std::move(j2_uptr));
50 
51  opt_variables_type global_active;
52  global_active.insertFrom(j2.myVars);
53 
54  jorb.checkOutVariables(global_active);
55 
56  CHECK(global_active.size_of_active() == 2);
57 }
58 
60 {
61  ParticleSet elec(simulation_cell);
62  elec.setName("e");
63  elec.create({2, 2});
64 
65  elec.R[0] = {1.0, 0.0, 0.0};
66  elec.R[1] = {1.1, 1.0, 0.1};
67  elec.R[2] = {0.9, 0.8, 1.0};
68  elec.R[3] = {0.9, 0.5, 1.1};
69 
70  SpeciesSet& tspecies = elec.getSpeciesSet();
71  int upIdx = tspecies.addSpecies("u");
72  int downIdx = tspecies.addSpecies("d");
73  elec.resetGroups();
74 
75  elec.addTable(elec);
76  elec.update();
77 
78  return elec;
79 }
80 
81 // Two variables, both active
82 TEST_CASE("TwoBodyJastrow two variables", "[wavefunction]")
83 {
84  const SimulationCell simulation_cell;
85  ParticleSet elec = get_two_species_particleset(simulation_cell);
86 
87  TwoBodyJastrow<FakeJasFunctor> jorb("J2_fake", elec, false);
88 
89  auto j2a_uptr = std::make_unique<FakeJasFunctor>("test_fake_a");
90  auto& j2a = *j2a_uptr;
91  j2a.myVars.insert("opt1", 1.0);
92  // update num_active_vars
93  j2a.myVars.resetIndex();
94  jorb.addFunc(0, 0, std::move(j2a_uptr));
95 
96  auto j2b_uptr = std::make_unique<FakeJasFunctor>("test_fake_b");
97  auto& j2b = *j2b_uptr;
98  j2b.myVars.insert("opt2", 2.0);
99  // update num_active_vars
100  j2b.myVars.resetIndex();
101  jorb.addFunc(0, 1, std::move(j2b_uptr));
102 
103  opt_variables_type global_active;
104  global_active.insertFrom(j2a.myVars);
105  global_active.insertFrom(j2b.myVars);
106  global_active.resetIndex();
107 
108  jorb.checkOutVariables(global_active);
109 
110  // Formatted output of variables involved
111  //j2a.myVars.print(app_log(),0,true);
112  //j2b.myVars.print(app_log(),0,true);
113  //global_active.print(app_log(),0,true);
114  //jorb.getComponentVars().print(app_log(),0,true);
115 
116  CHECK(global_active.size_of_active() == 2);
117 
118  // Order is based on the function list F
119  // For two species (ia - index of first species, ib - index of second species)
120  // F[0] is (0,0)
121  // F[1] and F[2] are (0,1),(1,0) - use the same functions
122  // F[3] is (1,1) b-b (by default uses the same function as a-a)
123 
124  // Index into global_active
125  auto o1 = jorb.getComponentOffset(0);
126  CHECK(o1.first == 0);
127  CHECK(o1.second == 1);
128 
129  auto o2 = jorb.getComponentOffset(1);
130  CHECK(o2.first == 1);
131  CHECK(o2.second == 2);
132 
133  auto o3 = jorb.getComponentOffset(2);
134  CHECK(o3.first == 1);
135  CHECK(o3.second == 2);
136 
137  auto o4 = jorb.getComponentOffset(3);
138  CHECK(o4.first == 0);
139  CHECK(o4.second == 1);
140 
141  UniqueOptObjRefs opt_obj_refs;
142  jorb.extractOptimizableObjectRefs(opt_obj_refs);
143  REQUIRE(opt_obj_refs.size() == 2);
144 }
145 
146 // Reproduce 2814. If the variational parameter for the first Jastrow factor
147 // is not active, the offsets are not correct.
148 // "First" means the first in the function list F, which has species indices 0,0
149 TEST_CASE("TwoBodyJastrow variables fail", "[wavefunction]")
150 {
151  const SimulationCell simulation_cell;
152  ParticleSet elec = get_two_species_particleset(simulation_cell);
153 
154  TwoBodyJastrow<FakeJasFunctor> jorb("J2_fake", elec, false);
155 
156  auto j2a_uptr = std::make_unique<FakeJasFunctor>("test_fake_a");
157  auto& j2a = *j2a_uptr;
158  j2a.myVars.insert("opt1", 1.0);
159  // update num_active_vars
160  j2a.myVars.resetIndex();
161  jorb.addFunc(0, 0, std::move(j2a_uptr));
162 
163  auto j2b_uptr = std::make_unique<FakeJasFunctor>("test_fake_b");
164  auto& j2b = *j2b_uptr;
165  j2b.myVars.insert("opt2", 2.0);
166  // update num_active_vars
167  j2b.myVars.resetIndex();
168  jorb.addFunc(0, 1, std::move(j2b_uptr));
169 
170  opt_variables_type global_active;
171  global_active.insertFrom(j2b.myVars);
172  global_active.resetIndex();
173 
174 
175  jorb.checkOutVariables(global_active);
176 
177  CHECK(global_active.size_of_active() == 1);
178  // Not optimizing the parameter in this Jastrow factor, indicated by first index is -1
179  auto o1 = jorb.getComponentOffset(0);
180  CHECK(o1.first == -1);
181 
182  // Offset into set of active variables (global_active)
183  auto o2 = jorb.getComponentOffset(1);
184  CHECK(o2.first == 0);
185  CHECK(o2.second == 1);
186 
187  auto o3 = jorb.getComponentOffset(2);
188  CHECK(o3.first == 0);
189  CHECK(o3.second == 1);
190 
191  auto o4 = jorb.getComponentOffset(3);
192  CHECK(o4.first == -1);
193 
195 
196  // Check derivative indexing
197  int num_vars = 1;
198  j2b.derivs_.resize(num_vars);
199  // Elements are d/dp_i u(r), d/dp_i du/dr, d/dp_i d2u/dr2
200  j2b.derivs_[0] = {0.5, 1.3, 2.4};
201  Vector<ValueType> dlogpsi(num_vars);
202  jorb.evaluateDerivativesWF(elec, global_active, dlogpsi);
203 
204  CHECK(dlogpsi[0] == ValueApprox(-2.0)); // 4 * derivs_[0][0]
205 
206  Vector<ValueType> dlogpsi2(num_vars);
207  Vector<ValueType> dhpsioverpsi(num_vars);
208 
209  jorb.evaluateDerivatives(elec, global_active, dlogpsi2, dhpsioverpsi);
210  CHECK(dlogpsi2[0] == ValueApprox(-2.0));
211 }
212 
213 // Other variational parameters in the wavefunction (e.g. one-body Jastrow)
214 
215 TEST_CASE("TwoBodyJastrow other variables", "[wavefunction]")
216 {
217  const SimulationCell simulation_cell;
218  ParticleSet elec = get_two_species_particleset(simulation_cell);
219 
220  TwoBodyJastrow<FakeJasFunctor> jorb("J2_fake", elec, false);
221 
222  auto j2a_uptr = std::make_unique<FakeJasFunctor>("test_fake_a");
223  auto j2a = *j2a_uptr;
224  j2a.myVars.insert("opt1", 1.0);
225  // update num_active_vars
226  j2a.myVars.resetIndex();
227  jorb.addFunc(0, 0, std::move(j2a_uptr));
228 
229  auto j2b_uptr = std::make_unique<FakeJasFunctor>("test_fake_b");
230  auto& j2b = *j2b_uptr;
231  j2b.myVars.insert("opt2", 2.0);
232  // update num_active_vars
233  j2b.myVars.resetIndex();
234  jorb.addFunc(0, 1, std::move(j2b_uptr));
235 
236  opt_variables_type global_active;
237  // This is a parameter from another part of the wavefunction
238  global_active.insert("other_opt", 1.0);
239  global_active.insertFrom(j2b.myVars);
240  global_active.resetIndex();
241 
242 
243  jorb.checkOutVariables(global_active);
244 
245  //global_active.print(app_log(),0,true);
246  //jorb.getComponentVars().print(app_log(),0,true);
247 
248  CHECK(global_active.size_of_active() == 2);
249  // Not optimizing the parameter in this Jastrow factor, indicated by first index is -1
250  auto o1 = jorb.getComponentOffset(0);
251  CHECK(o1.first < 0);
252 
253  // Offset into set of active variables (global_active)
254  auto o2 = jorb.getComponentOffset(1);
255  CHECK(o2.first == 0);
256  CHECK(o2.second == 1);
257 
258  auto o3 = jorb.getComponentOffset(2);
259  CHECK(o3.first == 0);
260  CHECK(o3.second == 1);
261 
262  auto o4 = jorb.getComponentOffset(3);
263  CHECK(o4.first < 0);
264 
265 
267 
268  // Check derivative indexing
269  int num_vars = 2;
270  j2b.derivs_.resize(num_vars);
271  // Elements are d/dp_i u(r), d/dp_i du/dr, d/dp_i d2u/dr2
272  j2b.derivs_[0] = {0.5, 1.3, 2.4};
273  Vector<ValueType> dlogpsi(num_vars);
274  jorb.evaluateDerivativesWF(elec, global_active, dlogpsi);
275 
276  CHECK(dlogpsi[1] == ValueApprox(-2.0)); // 4 * derivs_[0][0]
277 
278  Vector<ValueType> dlogpsi2(num_vars);
279  Vector<ValueType> dhpsioverpsi(num_vars);
280 
281  jorb.evaluateDerivatives(elec, global_active, dlogpsi2, dhpsioverpsi);
282  CHECK(dlogpsi2[1] == ValueApprox(-2.0));
283 }
284 
285 // Reproduce 3137. If the number of particle types equals the number of particles
286 // the two body jastrow is not constructed correctly (except in the case of two
287 // particles).
288 TEST_CASE("TwoBodyJastrow Jastrow three particles of three types", "[wavefunction]")
289 {
290  const SimulationCell simulation_cell;
291  ParticleSet ions(simulation_cell);
292  ParticleSet elec(simulation_cell);
293 
294  ions.setName("ion");
295  ions.create({1});
296  ions.R[0] = {0.0, 0.0, 0.0};
297  elec.setName("elec");
298  elec.create({1, 1, 1});
299  elec.R[0] = {-0.28, 0.0225, -2.709};
300  elec.R[1] = {-1.08389, 1.9679, -0.0128914};
301  elec.R[2] = {-2.08389, 0.9679, 0.0128914};
302  TwoBodyJastrow<FakeJasFunctor> jorb("J2_fake", elec, false);
303 
304  // 0 uu (0,0)
305  // 1 ud (0,1)
306  // 2 up (0,2)
307  // 3 du (1,0)
308  // 4 dd (1,1)
309  // 5 dp (1,2)
310  // 6 pu (2,0)
311  // 7 pd (2,1)
312  // 8 pp (2,2)
313 
314  auto j2a_uptr = std::make_unique<FakeJasFunctor>("test_fake_a");
315  auto& j2a = *j2a_uptr;
316  j2a.myVars.insert("opt1", 1.0);
317  // update num_active_vars
318  j2a.myVars.resetIndex();
319  jorb.addFunc(0, 1, std::move(j2a_uptr));
320 
321  auto j2b_uptr = std::make_unique<FakeJasFunctor>("test_fake_b");
322  auto j2b = *j2b_uptr;
323  j2b.myVars.insert("opt2", 2.0);
324  // update num_active_vars
325  j2b.myVars.resetIndex();
326  jorb.addFunc(0, 2, std::make_unique<FakeJasFunctor>(*j2b_uptr));
327 
328  // currently opposite spins won't be set to be equivalent
329  // setting u,p doesn't set d,p
330  jorb.addFunc(1, 2, std::move(j2b_uptr));
331 
332  auto& F = jorb.getPairFunctions();
333  for (size_t i = 0; i < F.size(); ++i)
334  CHECK(F[i] != nullptr);
335 }
336 
337 } // namespace qmcplusplus
void setName(const std::string &aname)
Definition: ParticleSet.h:237
ParticleSet get_two_species_particleset(const SimulationCell &simulation_cell)
int addSpecies(const std::string &aname)
When a name species does not exist, add a new species.
Definition: SpeciesSet.cpp:33
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
FakeFunctor for testing purpose.
void addFunc(int ia, int ib, std::unique_ptr< FT > j)
add functor for (ia,ib) pair
TEST_CASE("complex_helper", "[type_traits]")
const std::vector< FT * > & getPairFunctions() const
void extractOptimizableObjectRefs(UniqueOptObjRefs &opt_obj_refs) override
extract underlying OptimizableObject references
void resetIndex()
reset Index
void update(bool skipSK=false)
update the internal data
void evaluateDerivativesWF(ParticleSet &P, const opt_variables_type &active, Vector< ValueType > &dlogpsi) override
int addTable(const ParticleSet &psrc, DTModes modes=DTModes::ALL_OFF)
add a distance table
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
QTBase::ValueType ValueType
Definition: Configuration.h:60
REQUIRE(std::filesystem::exists(filename))
void insert(const std::string &vname, real_type v, bool enable=true, int type=OTHER_P)
Definition: VariableSet.h:133
class to handle a set of variables that can be modified during optimizations
Definition: VariableSet.h:49
ParticlePos R
Position.
Definition: ParticleSet.h:79
int size_of_active() const
return the number of active variables
Definition: VariableSet.h:78
Specialization for two-body Jastrow function using multiple functors.
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
void create(const std::vector< int > &agroup)
create grouped particles
CHECK(log_values[0]==ComplexApprox(std::complex< double >{ 5.603777579195571, -6.1586603331188225 }))
std::pair< int, int > getComponentOffset(int index)
void evaluateDerivatives(ParticleSet &P, const opt_variables_type &active, Vector< ValueType > &dlogpsi, Vector< ValueType > &dhpsioverpsi) override
LatticeGaussianProduct::ValueType ValueType
void checkOutVariables(const opt_variables_type &active) override
check out optimizable variables
void insertFrom(const VariableSet &input)
insert a VariableSet to the list
Definition: VariableSet.cpp:37
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33