QMCPACK
test_RotatedSPOs_NLPP.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) 2022 QMCPACK developers.
6 //
7 // File developed by: Joshua Townsend, jptowns@sandia.gov, Sandia National Laboratories
8 // Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
9 //
10 // File created by: Joshua Townsend, jptowns@sandia.gov, Sandia National Laboratories
11 //////////////////////////////////////////////////////////////////////////////////////
12 
13 #include "catch.hpp"
14 
17 #include "OhmmsData/Libxml2Doc.h"
18 #include "OhmmsPETE/OhmmsMatrix.h"
19 #include "Particle/ParticleSet.h"
25 #include "Utilities/ProjectData.h"
26 
27 #include <stdio.h>
28 #include <string>
29 #include <limits>
30 
31 using std::string;
32 
33 namespace qmcplusplus
34 {
35 // Copied and extended from QMCWaveFunctions/tests/test_RotatedSPOs.cpp
36 
37 
38 void test_hcpBe_rotation(bool use_single_det, bool use_nlpp_batched)
39 {
41 
42  /*
43  BEGIN Boilerplate stuff to make a simple SPOSet. Copied from test_einset.cpp
44  */
47 
48  ParticleSetPool pp(c);
49 
51  lattice.R(0, 0) = 4.32747284;
52  lattice.R(0, 1) = 0.00000000;
53  lattice.R(0, 2) = 0.00000000;
54  lattice.R(1, 0) = -2.16373642;
55  lattice.R(1, 1) = 3.74770142;
56  lattice.R(1, 2) = 0.00000000;
57  lattice.R(2, 0) = 0.00000000;
58  lattice.R(2, 1) = 0.00000000;
59  lattice.R(2, 2) = 6.78114995;
60 
61 
62  const SimulationCell simulation_cell(lattice);
63  pp.setSimulationCell(simulation_cell);
64  auto elec_ptr = std::make_unique<ParticleSet>(pp.getSimulationCell());
65  auto& elec(*elec_ptr);
66  auto ions_uptr = std::make_unique<ParticleSet>(pp.getSimulationCell());
67  ParticleSet& ions(*ions_uptr);
68 
69  elec.setName("e");
70  elec.create({1, 1});
71  elec.R[0] = {0.1, 0.2, 0.3};
72  elec.R[1] = {1.0, 1.0, 1.0};
73 
74  SpeciesSet& especies = elec.getSpeciesSet();
75  int upIdx = especies.addSpecies("u");
76  int chargeIdx = especies.addAttribute("charge");
77  int massIdx = especies.addAttribute("mass");
78  especies(chargeIdx, upIdx) = -1;
79  especies(massIdx, upIdx) = 1.0;
80  int dnIdx = especies.addSpecies("d");
81  especies(chargeIdx, dnIdx) = -1;
82  especies(massIdx, dnIdx) = 1.0;
83  elec.resetGroups(); // need to set Mass so
84 
85 
86  pp.addParticleSet(std::move(elec_ptr));
87 
88  ions.setName("ion0");
89  ions.create({1});
90  ions.R[0] = {0.0, 0.0, 0.0};
91  SpeciesSet& tspecies = ions.getSpeciesSet();
92  int CIdx = tspecies.addSpecies("Be");
93  int CchargeIdx = tspecies.addAttribute("charge");
94  int CatomicnumberIdx = tspecies.addAttribute("atomicnumber");
95  tspecies(CchargeIdx, CIdx) = 2;
96  tspecies(CatomicnumberIdx, CIdx) = 4;
97 
98 
99  pp.addParticleSet(std::move(ions_uptr));
100 
102  REQUIRE(wp.empty() == true);
103 
104  const char* wf_input_multi_det = R"(
105  <wavefunction name="psi0" target="e">
106  <sposet_builder type="bspline" href="hcpBe.pwscf.h5" tilematrix="1 0 0 0 1 0 0 0 1" twistnum="0" source="ion0" version="0.10" meshfactor="1.0" precision="double" truncate="no" save_coefs="no">
107  <sposet type="bspline" name="spo_up" size="2" spindataset="0" optimize="yes">
108  </sposet>
109  <sposet type="bspline" name="spo_down" size="2" spindataset="0" optimize="yes">
110  </sposet>
111  </sposet_builder>
112  <determinantset>
113  <multideterminant optimize="no" spo_0="spo_up" spo_1="spo_down" algorithm="precomputed_table_method">
114  <detlist size="1" type="DETS" nc0="0" ne0="1" nc1="0" ne1="1" nstates="2" cutoff="1e-20">
115  <ci coeff="1.0" occ0="10" occ1="10"/>
116  </detlist>
117  </multideterminant>
118  </determinantset>
119  </wavefunction>)";
120 
121  const char* wf_input_single_det = R"(
122  <wavefunction name="psi0" target="e">
123  <sposet_builder type="bspline" href="hcpBe.pwscf.h5" tilematrix="1 0 0 0 1 0 0 0 1" twistnum="0" source="ion0" version="0.10" meshfactor="1.0" precision="double" truncate="no" save_coefs="no">
124  <sposet type="bspline" name="spo_up" size="2" spindataset="0" optimize="yes">
125  </sposet>
126  <sposet type="bspline" name="spo_down" size="2" spindataset="0" optimize="yes">
127  </sposet>
128  </sposet_builder>
129  <determinantset>
130  <slaterdeterminant>
131  <determinant id="spo_up" size="1">
132  <occupation mode="ground" spindataset="0"/>
133  </determinant>
134  <determinant id="spo_down" size="1">
135  <occupation mode="ground" spindataset="0"/>
136  </determinant>
137  </slaterdeterminant>
138  </determinantset>
139  </wavefunction>)";
140 
141  const char* wf_input = wf_input_multi_det;
142  if (use_single_det)
143  wf_input = wf_input_single_det;
144 
146  bool okay = doc.parseFromString(wf_input);
147  REQUIRE(okay);
148 
149  xmlNodePtr root = doc.getRoot();
150 
151  wp.put(root);
152  TrialWaveFunction* psi = wp.getWaveFunction("psi0");
153  REQUIRE(psi != nullptr);
154  REQUIRE(psi->getOrbitals().size() == 1);
155 
156 
157  // Note the pbc="no" setting to turn off long-range summation.
158  const char* ham_input_nlpp_nonbatched = R"(
159  <hamiltonian name="h0" type="generic" target="e">
160  <pairpot type="pseudo" name="PseudoPot" source="ion0" wavefunction="psi0" format="xml" algorithm="non-batched" pbc="no">
161  <pseudo elementType="Be" href="Be.BFD.xml" nrule="2" disable_randomize_grid="yes"/>
162  </pairpot>
163  </hamiltonian>)";
164 
165  const char* ham_input_nlpp_batched = R"(
166  <hamiltonian name="h0" type="generic" target="e">
167  <pairpot type="pseudo" name="PseudoPot" source="ion0" wavefunction="psi0" format="xml" algorithm="batched" pbc="no">
168  <pseudo elementType="Be" href="Be.BFD.xml" nrule="2" disable_randomize_grid="yes"/>
169  </pairpot>
170  </hamiltonian>)";
171 
172  const char* ham_input = ham_input_nlpp_nonbatched;
173  if (use_nlpp_batched)
174  ham_input = ham_input_nlpp_batched;
175 
176  HamiltonianFactory hf("h0", elec, pp.getPool(), wp.getPool(), c);
177 
178  Libxml2Document doc2;
179  bool okay2 = doc2.parseFromString(ham_input);
180  REQUIRE(okay2);
181 
182  xmlNodePtr root2 = doc2.getRoot();
183  hf.put(root2);
184 
185  opt_variables_type opt_vars;
186  psi->checkInVariables(opt_vars);
187  opt_vars.resetIndex();
188  psi->checkOutVariables(opt_vars);
189  psi->resetParameters(opt_vars);
190 
191  elec.update();
192 
193  double logval = psi->evaluateLog(elec);
194  CHECK(logval == Approx(-1.2865633501081344));
195 
196  CHECK(elec.G[0][0] == ValueApprox(0.54752651));
197  CHECK(elec.L[0] == ValueApprox(11.066512459947848));
198 #if defined(MIXED_PRECISION)
199  CHECK(elec.L[1] == ValueApprox(-0.4830868071).epsilon(1e-3));
200 #else
201  CHECK(elec.L[1] == ValueApprox(-0.4831061477045371));
202 #endif
203 
204  // Parameter derivatives of just the wavefunction
205  // Values come from QMCWaveFunctions/tests/eval_bspline_spo.py
207  Vector<ValueType> dlogpsi(2);
208  Vector<ValueType> dhpsioverpsi(2);
209  psi->evaluateDerivatives(elec, opt_vars, dlogpsi, dhpsioverpsi);
210 
211  CHECK(dlogpsi[0] == ValueApprox(-2.97750823));
212  CHECK(dlogpsi[1] == ValueApprox(-1.06146356));
213  CHECK(dhpsioverpsi[0] == ValueApprox(-36.71707483));
214  CHECK(dhpsioverpsi[1] == ValueApprox(-0.35274333));
215 
216  RefVectorWithLeader<TrialWaveFunction> wf_list(*psi, {*psi});
217  RefVectorWithLeader<ParticleSet> p_list(elec, {elec});
218 
219  // Test list with one wavefunction
220 
221  int nparam = 2;
222  int nentry = 1;
223  RecordArray<ValueType> dlogpsi_list(nentry, nparam);
224  RecordArray<ValueType> dhpsi_over_psi_list(nentry, nparam);
225 
226  TrialWaveFunction::mw_evaluateParameterDerivatives(wf_list, p_list, opt_vars, dlogpsi_list, dhpsi_over_psi_list);
227 
228  CHECK(dlogpsi_list[0][0] == Approx(dlogpsi[0]));
229  CHECK(dlogpsi_list[0][1] == Approx(dlogpsi[1]));
230  CHECK(dhpsi_over_psi_list[0][0] == Approx(dhpsioverpsi[0]));
231  CHECK(dhpsi_over_psi_list[0][1] == Approx(dhpsioverpsi[1]));
232 
233 
234  QMCHamiltonian* h = hf.getH();
235  RandomGenerator myrng;
236  h->setRandomGenerator(&myrng);
237 
238  h->evaluate(elec);
239  double loc_e = h->getLocalEnergy();
240  double ke = h->getKineticEnergy();
241  CHECK(ke == Approx(-6.818620576308302));
242  CHECK(loc_e == Approx(-3.562354739253797));
243 
244  auto* localECP_H = h->getHamiltonian("LocalECP");
245  double local_pp = localECP_H->evaluate(elec);
246 
247  Vector<ValueType> dlogpsi2(2);
248  Vector<ValueType> dhpsioverpsi2(2);
249 
250  h->evaluateValueAndDerivatives(elec, opt_vars, dlogpsi2, dhpsioverpsi2);
251  // Derivative the wavefunction is unchanged by NLPP
252  CHECK(dlogpsi2[0] == Approx(dlogpsi[0]));
253  CHECK(dlogpsi2[1] == Approx(dlogpsi[1]));
254 
255  // Derivative of H is different with NLPP included
256  CHECK(dhpsioverpsi2[0] == ValueApprox(-5.45054261));
257  CHECK(dhpsioverpsi2[1] == ValueApprox(-0.34818307));
258 
259  // batched interface
260  RefVectorWithLeader<QMCHamiltonian> h_list(*h, {*h});
261 
262  RecordArray<ValueType> dlogpsi_list2(nentry, nparam);
263  RecordArray<ValueType> dhpsi_over_psi_list2(nentry, nparam);
264 
265  h->mw_evaluateValueAndDerivatives(h_list, wf_list, p_list, opt_vars, dlogpsi_list2, dhpsi_over_psi_list2);
266 
267  CHECK(dlogpsi_list2[0][0] == Approx(dlogpsi2[0]));
268  CHECK(dlogpsi_list2[0][1] == Approx(dlogpsi2[1]));
269 
270  CHECK(dhpsi_over_psi_list2[0][0] == Approx(dhpsioverpsi2[0]));
271  CHECK(dhpsi_over_psi_list2[0][1] == Approx(dhpsioverpsi2[1]));
272 }
273 
274 TEST_CASE("RotatedSPOs SplineR2R hcpBe values", "[wavefunction]")
275 {
276  SECTION("nlpp non-batched")
277  {
278  bool use_single_det = GENERATE(true, false);
279  bool use_nlpp_batched = false;
280  test_hcpBe_rotation(use_single_det, use_nlpp_batched);
281  }
282 
283  SECTION("nlpp batched")
284  {
285  bool use_single_det = true;
286  bool use_nlpp_batched = true;
287  test_hcpBe_rotation(use_single_det, use_nlpp_batched);
288  }
289 }
290 
291 } // namespace qmcplusplus
a class that defines a supercell in D-dimensional Euclean space.
RealType evaluateLog(ParticleSet &P)
evalaute the log (internally gradients and laplacian) of the trial wavefunction.
void setSimulationCell(const SimulationCell &simulation_cell)
set simulation cell
class that handles xmlDoc
Definition: Libxml2Doc.h:76
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
void evaluateDerivatives(ParticleSet &P, const opt_variables_type &optvars, Vector< ValueType > &dlogpsi, Vector< ValueType > &dhpsioverpsi)
evaluate derivatives of KE wrt optimizable varibles
QTBase::RealType RealType
Definition: Configuration.h:58
OperatorBase * getHamiltonian(const std::string &aname)
return OperatorBase with the name aname
class ProjectData
Definition: ProjectData.h:36
FullPrecRealType evaluateValueAndDerivatives(ParticleSet &P, const opt_variables_type &optvars, Vector< ValueType > &dlogpsi, Vector< ValueType > &dhpsioverpsi)
evaluate energy and derivatives wrt to the variables
TEST_CASE("complex_helper", "[type_traits]")
void resetParameters(const opt_variables_type &active)
Set values of parameters in each component from the global list.
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
void test_hcpBe_rotation(bool use_single_det, bool use_nlpp_batched)
Builder class for einspline-based SPOSet objects.
Collection of Local Energy Operators.
ProjectData test_project("test", ProjectData::DriverVersion::BATCH)
void resetIndex()
reset Index
Communicate * Controller
Global Communicator for a process.
Definition: Communicate.cpp:35
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
const RuntimeOptions & getRuntimeOptions() const noexcept
static std::vector< QMCHamiltonian::FullPrecRealType > mw_evaluateValueAndDerivatives(const RefVectorWithLeader< QMCHamiltonian > &ham_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, const opt_variables_type &optvars, RecordArray< ValueType > &dlogpsi, RecordArray< ValueType > &dhpsioverpsi)
Wrapping information on parallelism.
Definition: Communicate.h:68
CrystalLattice< OHMMS_PRECISION, OHMMS_DIM > lattice
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
QTBase::ValueType ValueType
Definition: Configuration.h:60
REQUIRE(std::filesystem::exists(filename))
static void mw_evaluateParameterDerivatives(const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, const opt_variables_type &optvars, RecordArray< ValueType > &dlogpsi, RecordArray< ValueType > &dhpsioverpsi)
Declaration of WaveFunctionPool.
Factory class to build a many-body wavefunction.
Manage a collection of ParticleSet objects.
class to handle a set of variables that can be modified during optimizations
Definition: VariableSet.h:49
std::vector< std::unique_ptr< WaveFunctionComponent > > const & getOrbitals()
Declaration of a HamiltonianFactory.
FullPrecRealType getLocalEnergy()
void checkOutVariables(const opt_variables_type &o)
Check out optimizable variables Assign index mappings from global list (o) to local values in each co...
Class to represent a many-body trial wave function.
bool parseFromString(const std::string_view data)
Definition: Libxml2Doc.cpp:204
FullPrecRealType evaluate(ParticleSet &P)
evaluate Local Energy
CHECK(log_values[0]==ComplexApprox(std::complex< double >{ 5.603777579195571, -6.1586603331188225 }))
virtual Return_t evaluate(ParticleSet &P)=0
Evaluate the local energy contribution of this component.
LatticeGaussianProduct::ValueType ValueType
Declaration of WaveFunctionComponent.
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
const PoolType & getPool() const
get the Pool object
void setRandomGenerator(RandomBase< FullPrecRealType > *rng)
FullPrecRealType getKineticEnergy()
const auto & getSimulationCell() const
get simulation cell
Manage a collection of TrialWaveFunction objects.
Declaration of ParticleSetPool.
void checkInVariables(opt_variables_type &o)
Check in an optimizable parameter.