QMCPACK
test_NonLocalECPotential.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: Peter Doak, doakpw@ornl.gov, Oak Ridge National Laboratory
8 //
9 // File created by: Peter Doak, doakpw@ornl.gov, Oak Ridge National Laboratory
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 #include "catch.hpp"
13 
14 #include "Configuration.h"
15 #include "Numerics/Quadrature.h"
16 #include "Particle/ParticleSet.h"
20 #include "TestListenerFunction.h"
23 
24 namespace qmcplusplus
25 {
26 namespace testing
27 {
28 /** class to violate access control because evaluation of NonLocalECPotential uses RNG
29  * which we may not be able to control.
30  */
32 {
34 
35 public:
37  {
38  nl_ecp.PPset[0]->rrotsgrid_m = nl_ecp.PPset[0]->sgridxyz_m;
39  }
40  static bool didGridChange(NonLocalECPotential& nl_ecp)
41  {
42  return nl_ecp.PPset[0]->rrotsgrid_m != nl_ecp.PPset[0]->sgridxyz_m;
43  }
44  static void mw_evaluateImpl(NonLocalECPotential& nl_ecp,
48  bool Tmove,
49  const std::optional<ListenerOption<Real>> listener_opt,
50  bool keep_grid)
51  {
52  nl_ecp.mw_evaluateImpl(o_list, twf_list, p_list, Tmove, listener_opt, keep_grid);
53  }
54 };
55 
56 } // namespace testing
57 
58 TEST_CASE("NonLocalECPotential", "[hamiltonian]")
59 {
60  using Real = QMCTraits::RealType;
62  using Position = QMCTraits::PosType;
64 
66  lattice.BoxBConds = true; // periodic
67  lattice.R.diagonal(20.0);
68  lattice.LR_dim_cutoff = 15;
69  lattice.reset();
70 
71  const SimulationCell simulation_cell(lattice);
72 
73  ParticleSet ions(simulation_cell);
74 
75  ions.setName("ion");
76  ions.create({2});
77  ions.R[0] = {0.0, 1.0, 0.0};
78  ions.R[1] = {0.0, -1.0, 0.0};
79 
80  SpeciesSet& ion_species = ions.getSpeciesSet();
81  int index_species = ion_species.addSpecies("Na");
82  int index_charge = ion_species.addAttribute("charge");
83  int index_atomic_number = ion_species.addAttribute("atomic_number");
84  ion_species(index_charge, index_species) = 1;
85  ion_species(index_atomic_number, index_species) = 1;
86  ions.createSK();
87  ions.resetGroups(); // test_ecp.cpp claims this is needed
88  ions.update(); // elsewhere its implied this is needed
89 
90  ParticleSet ions2(ions);
91  ions2.update();
92 
93  ParticleSet elec(simulation_cell);
94  elec.setName("elec");
95  elec.create({2, 1});
96  elec.R[0] = {0.4, 0.0, 0.0};
97  elec.R[1] = {1.0, 0.0, 0.0};
98 
99  SpeciesSet& tspecies = elec.getSpeciesSet();
100  int upIdx = tspecies.addSpecies("u");
101  int chargeIdx = tspecies.addAttribute("charge");
102  int massIdx = tspecies.addAttribute("mass");
103  tspecies(chargeIdx, upIdx) = -1;
104  tspecies(massIdx, upIdx) = 1.0;
105 
106  int dnIdx = tspecies.addSpecies("d");
107  chargeIdx = tspecies.addAttribute("charge");
108  massIdx = tspecies.addAttribute("mass");
109  tspecies(chargeIdx, dnIdx) = -1;
110  tspecies(massIdx, dnIdx) = 1.0;
111 
112  elec.createSK();
113  elec.resetGroups();
114  const int ei_table_index = elec.addTable(ions);
115  elec.update();
116 
117  ParticleSet elec2(elec);
118  elec2.update();
119 
120  RefVector<ParticleSet> ptcls{elec, elec2};
121  RefVectorWithLeader<ParticleSet> p_list(elec, ptcls);
122 
123  RuntimeOptions runtime_options;
124  TrialWaveFunction psi(runtime_options);
125  TrialWaveFunction psi2(runtime_options);
126  RefVectorWithLeader<TrialWaveFunction> twf_list(psi, {psi, psi2});
127 
128  bool doForces = false;
129  bool use_DLA = false;
130 
131  NonLocalECPotential nl_ecp(ions, elec, psi, doForces, use_DLA);
132 
133  int num_walkers = 2;
134  int max_values = 10;
135  Matrix<Real> local_pots(num_walkers, max_values);
136  Matrix<Real> local_pots2(num_walkers, max_values);
137 
138  ResourceCollection pset_res("test_pset_res");
139  elec.createResource(pset_res);
140  ResourceCollectionTeamLock<ParticleSet> pset_lock(pset_res, p_list);
141 
142  std::vector<ListenerVector<Real>> listeners;
143  listeners.emplace_back("nonlocalpotential", getParticularListener(local_pots));
144  listeners.emplace_back("nonlocalpotential", getParticularListener(local_pots2));
145 
146  Matrix<Real> ion_pots(num_walkers, max_values);
147  Matrix<Real> ion_pots2(num_walkers, max_values);
148 
149  std::vector<ListenerVector<Real>> ion_listeners;
150  ion_listeners.emplace_back("nonlocalpotential", getParticularListener(ion_pots));
151  ion_listeners.emplace_back("nonlocalpotential", getParticularListener(ion_pots2));
152 
153 
154  // This took some time to sort out from the multistage mess of put and clones
155  // but this accomplishes in a straight forward way what I interpret to be done by that code.
157  ECPComponentBuilder ecp_comp_builder("test_read_ecp", comm, 4, 1);
158 
159  bool okay = ecp_comp_builder.read_pp_file("Na.BFD.xml");
160  REQUIRE(okay);
161  UPtr<NonLocalECPComponent> nl_ecp_comp = std::move(ecp_comp_builder.pp_nonloc);
162  nl_ecp.addComponent(0, std::move(nl_ecp_comp));
163  UPtr<OperatorBase> nl_ecp2_ptr = nl_ecp.makeClone(elec2, psi2);
164  auto& nl_ecp2 = dynamic_cast<NonLocalECPotential&>(*nl_ecp2_ptr);
165 
166  StdRandom<FullPrecReal> rng(10101);
167  StdRandom<FullPrecReal> rng2(10201);
168  nl_ecp.setRandomGenerator(&rng);
169  nl_ecp2.setRandomGenerator(&rng2);
170 
171  RefVector<OperatorBase> nl_ecps{nl_ecp, nl_ecp2};
172  RefVectorWithLeader<OperatorBase> o_list(nl_ecp, nl_ecps);
173  ResourceCollection nl_ecp_res("test_nl_ecp_res");
174  nl_ecp.createResource(nl_ecp_res);
175  ResourceCollectionTeamLock<OperatorBase> nl_ecp_lock(nl_ecp_res, o_list);
176 
177  // Despite what test_ecp.cpp says this does not need to be done.
178  // I think because of the pp
181 
183 
184  ListenerOption<Real> listener_opt{listeners, ion_listeners};
185  testing::TestNonLocalECPotential::mw_evaluateImpl(nl_ecp, o_list, twf_list, p_list, false, listener_opt, true);
186 
187  // I'd like to see this gone when legacy drivers are dropped but for now we'll check against
188  // the single particle API
189  auto value = o_list[0].evaluateDeterministic(p_list[0]);
190 
191  CHECK(std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0) == Approx(value));
192  CHECK(std::accumulate(local_pots2.begin(), local_pots2.begin() + local_pots2.cols(), 0.0) == Approx(value));
193  CHECK(std::accumulate(ion_pots.begin(), ion_pots.begin() + ion_pots.cols(), 0.0) == Approx(-2.1047365665));
194  CHECK(std::accumulate(ion_pots2.begin(), ion_pots2.begin() + ion_pots2.cols(), 0.0) == Approx(-2.1047365665));
195 
197 
198  elec.R[0] = {0.5, 0.0, 2.0};
199  elec.update();
200 
201  testing::TestNonLocalECPotential::mw_evaluateImpl(nl_ecp, o_list, twf_list, p_list, false, listener_opt, true);
202 
204  auto value2 = o_list[0].evaluateDeterministic(elec);
205 
206  CHECK(std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0) == Approx(value2));
207  // check the second walker which will be unchanged.
208  CHECK(std::accumulate(local_pots2[1], local_pots2[1] + local_pots2.cols(), 0.0) == Approx(value));
209 
210  // Randomizing grid does nothing for Na pp
211  testing::TestNonLocalECPotential::mw_evaluateImpl(nl_ecp, o_list, twf_list, p_list, false, listener_opt, false);
212  auto value3 = o_list[0].evaluateDeterministic(p_list[0]);
213  CHECK(std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0) == Approx(value3));
214 }
215 
216 } // namespace qmcplusplus
a class that defines a supercell in D-dimensional Euclean space.
void setName(const std::string &aname)
Definition: ParticleSet.h:237
Container_t::iterator begin()
Definition: OhmmsMatrix.h:89
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
QTBase::RealType RealType
Definition: Configuration.h:58
class to violate access control because evaluation of NonLocalECPotential uses RNG which we may not b...
const char num_walkers[]
Definition: HDFVersion.h:37
TEST_CASE("complex_helper", "[type_traits]")
static void mw_evaluateImpl(NonLocalECPotential &nl_ecp, const RefVectorWithLeader< OperatorBase > &o_list, const RefVectorWithLeader< TrialWaveFunction > &twf_list, const RefVectorWithLeader< ParticleSet > &p_list, bool Tmove, const std::optional< ListenerOption< Real >> listener_opt, bool keep_grid)
void createResource(ResourceCollection &collection) const
initialize a shared resource and hand it to a collection
void update(bool skipSK=false)
update the internal data
Communicate * Controller
Global Communicator for a process.
Definition: Communicate.cpp:35
static bool didGridChange(NonLocalECPotential &nl_ecp)
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
std::unique_ptr< NonLocalECPComponent > pp_nonloc
ForceBase::Real Real
Definition: ForceBase.cpp:26
size_type cols() const
Definition: OhmmsMatrix.h:78
Wrapping information on parallelism.
Definition: Communicate.h:68
CrystalLattice< OHMMS_PRECISION, OHMMS_DIM > lattice
int addTable(const ParticleSet &psrc, DTModes modes=DTModes::ALL_OFF)
add a distance table
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
void createResource(ResourceCollection &collection) const override
initialize a shared resource and hand it to a collection
static void mw_evaluateImpl(const RefVectorWithLeader< OperatorBase > &o_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, bool Tmove, std::optional< ListenerOption< Real >> listeners, bool keepGrid=false)
the actual implementation for batched walkers, used by mw_evaluate, mw_evaluateWithToperator mw_evalu...
REQUIRE(std::filesystem::exists(filename))
Declaration of a builder class for an ECP component for an ionic type.
void addComponent(int groupID, std::unique_ptr< NonLocalECPComponent > &&pp)
ParticlePos R
Position.
Definition: ParticleSet.h:79
QTBase::PosType PosType
Definition: Configuration.h:61
std::unique_ptr< T > UPtr
auto getParticularListener(Matrix< T > &local_pots)
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
void create(const std::vector< int > &agroup)
create grouped particles
bool read_pp_file(const std::string &fname)
std::vector< std::reference_wrapper< T > > RefVector
void setRandomGenerator(RandomBase< FullPrecRealType > *rng) override
set the internal RNG pointer as the given pointer
Evaluate the semi local potentials.
Class to represent a many-body trial wave function.
CHECK(log_values[0]==ComplexApprox(std::complex< double >{ 5.603777579195571, -6.1586603331188225 }))
handles acquire/release resource by the consumer (RefVectorWithLeader type).
void createSK()
create Structure Factor with PBCs
QTFull::RealType FullPrecRealType
Definition: Configuration.h:66
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
std::unique_ptr< OperatorBase > makeClone(ParticleSet &qp, TrialWaveFunction &psi) override
std::vector< std::unique_ptr< NonLocalECPComponent > > PPset
unique NonLocalECPComponent to remove
DMCRefEnergy::FullPrecReal FullPrecReal
static void copyGridUnrotatedForTest(NonLocalECPotential &nl_ecp)
Convenience container for common optional element to mw_eval.._impl.
Definition: Listener.hpp:76