QMCPACK
test_coulomb_pbcAA.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: Mark Dewing, markdewing@gmail.com, University of Illinois at Urbana-Champaign
8 // Peter W. Doak, doakpw@ornl.gov, Oak Ridge National Laboratory
9 //
10 // File created by: Mark Dewing, markdewing@gmail.com, University of Illinois at Urbana-Champaign
11 //////////////////////////////////////////////////////////////////////////////////////
12 
13 
14 #include <catch.hpp>
15 
16 #include <CoulombPBCAA.h>
17 
18 #include <algorithm>
19 #include <numeric>
20 #include <string>
21 
22 #include <checkMatrix.hpp>
23 #include "Configuration.h"
24 #include <Listener.hpp>
25 #include <OhmmsData/Libxml2Doc.h>
26 #include <OhmmsPETE/OhmmsMatrix.h>
27 #include <ParticleSet.h>
28 #include <ResourceCollection.h>
29 #include "TestListenerFunction.h"
30 #include <TrialWaveFunction.h>
32 
33 using std::string;
34 
35 namespace qmcplusplus
36 {
37 
38 using QMCT = QMCTraits;
39 using Real = QMCT::RealType;
40 
41 TEST_CASE("Coulomb PBC A-A", "[hamiltonian]")
42 {
43  const double vmad_sc = -1.4186487397403098;
45 
47  lattice.BoxBConds = true; // periodic
48  lattice.R.diagonal(1.0);
49  lattice.reset();
50 
51  const SimulationCell simulation_cell(lattice);
52  ParticleSet ions(simulation_cell);
53 
54  ions.setName("ion");
55  ions.create({1});
56  ions.R[0] = {0.0, 0.0, 0.0};
57  SpeciesSet& ion_species = ions.getSpeciesSet();
58  int pIdx = ion_species.addSpecies("H");
59  int pChargeIdx = ion_species.addAttribute("charge");
60  ion_species(pChargeIdx, pIdx) = 1;
61  ions.createSK();
62 
63 
64  CoulombPBCAA caa(ions, false, false, false);
65 
66  // Background charge term
67  double consts = caa.evalConsts();
68  CHECK(consts == Approx(-3.1151210154));
69 
70  double val = caa.evaluate(ions);
71  //std::cout << "val = " << val << std::endl;
72  CHECK(val == Approx(vmad_sc));
73 
74  // supercell Madelung energy
75  val = caa.get_madelung_constant();
76  CHECK(val == Approx(vmad_sc));
77 }
78 
79 TEST_CASE("Coulomb PBC A-A BCC H", "[hamiltonian]")
80 {
81  const double alat = 3.77945227;
82  const double vmad_sc = -1.4186487397403098 / alat;
84 
86  lattice.BoxBConds = true; // periodic
87  lattice.R.diagonal(alat);
88  lattice.reset();
89 
90  const SimulationCell simulation_cell(lattice);
91  ParticleSet ions(simulation_cell);
92  ParticleSet elec(simulation_cell);
93 
94  ions.setName("ion");
95  ions.create({2});
96  ions.R[0] = {0.0, 0.0, 0.0};
97  ions.R[1] = {1.88972614, 1.88972614, 1.88972614};
98  SpeciesSet& ion_species = ions.getSpeciesSet();
99  int pIdx = ion_species.addSpecies("H");
100  int pChargeIdx = ion_species.addAttribute("charge");
101  ion_species(pChargeIdx, pIdx) = 1;
102  ions.createSK();
103 
104 
105  CoulombPBCAA caa(ions, false, false, false);
106 
107  // Background charge term
108  double consts = caa.evalConsts();
109  CHECK(consts == Approx(-1.675229452)); // not validated
110 
111  double val = caa.evaluate(elec);
112  CHECK(val == Approx(-0.9628996199)); // not validated
113 
114  // supercell Madelung energy
115  val = caa.get_madelung_constant();
116  CHECK(val == Approx(vmad_sc));
117 }
118 
119 TEST_CASE("Coulomb PBC A-A elec", "[hamiltonian]")
120 {
122 
124  lattice.BoxBConds = true; // periodic
125  lattice.R.diagonal(1.0);
126  lattice.reset();
127 
128  const SimulationCell simulation_cell(lattice);
129  ParticleSet elec(simulation_cell);
130 
131  elec.setName("elec");
132  elec.create({1});
133  elec.R[0] = {0.0, 0.5, 0.0};
134  SpeciesSet& tspecies = elec.getSpeciesSet();
135  int upIdx = tspecies.addSpecies("u");
136  int chargeIdx = tspecies.addAttribute("charge");
137  int massIdx = tspecies.addAttribute("mass");
138  tspecies(chargeIdx, upIdx) = -1;
139  tspecies(massIdx, upIdx) = 1.0;
140 
141  elec.createSK();
142  elec.update();
143 
144 
145  CoulombPBCAA caa(elec, true, false, false);
146 
147  // Self-energy correction, no background charge for e-e interaction
148  double consts = caa.evalConsts();
149  CHECK(consts == Approx(-3.1151210154));
150 
151  double val = caa.evaluate(elec);
152  CHECK(val == Approx(-1.418648723)); // not validated
153 }
154 
155 TEST_CASE("Coulomb PBC A-A BCC", "[hamiltonian]")
156 {
157  const double alat = 1.0;
158  const double vmad_bcc = -1.819616724754322 / alat;
160 
162  lattice.BoxBConds = true; // periodic
163  lattice.R = 0.5 * alat;
164  lattice.R(0, 0) = -0.5 * alat;
165  lattice.R(1, 1) = -0.5 * alat;
166  lattice.R(2, 2) = -0.5 * alat;
167  lattice.reset();
168 
169  const SimulationCell simulation_cell(lattice);
170  ParticleSet elec(simulation_cell);
171 
172  elec.setName("elec");
173  elec.create({1});
174  elec.R[0] = {0.0, 0.0, 0.0};
175 
176  SpeciesSet& tspecies = elec.getSpeciesSet();
177  int upIdx = tspecies.addSpecies("u");
178  int chargeIdx = tspecies.addAttribute("charge");
179  int massIdx = tspecies.addAttribute("mass");
180  tspecies(chargeIdx, upIdx) = -1;
181  tspecies(massIdx, upIdx) = 1.0;
182 
183  elec.createSK();
184  elec.update();
185 
186 
187  CoulombPBCAA caa(elec, true, false, false);
188 
189  double val = caa.evaluate(elec);
190  CHECK(val == Approx(vmad_bcc));
191 
192  val = caa.get_madelung_constant();
193  CHECK(val == Approx(vmad_bcc));
194 }
195 
197 {
198  const double alat = 1.0;
199  const double vmad_bcc = -1.819616724754322 / alat;
201 
203  lattice.BoxBConds = true; // periodic
204  lattice.R = 0.5 * alat;
205  lattice.R(0, 0) = -0.5 * alat;
206  lattice.R(1, 1) = -0.5 * alat;
207  lattice.R(2, 2) = -0.5 * alat;
208  lattice.reset();
209 
210  const SimulationCell simulation_cell(lattice);
211  ParticleSet elec(simulation_cell, kind);
212 
213  elec.setName("elec");
214  elec.create({1, 2});
215  elec.R[0] = {0.0, 0.0, 0.0};
216  elec.R[1] = {0.1, 0.2, 0.3};
217  elec.R[2] = {0.3, 0.1, 0.2};
218 
219  SpeciesSet& tspecies = elec.getSpeciesSet();
220  int upIdx = tspecies.addSpecies("u");
221  int dnIdx = tspecies.addSpecies("d");
222  int chargeIdx = tspecies.addAttribute("charge");
223  int massIdx = tspecies.addAttribute("mass");
224  tspecies(chargeIdx, upIdx) = -1;
225  tspecies(chargeIdx, dnIdx) = -1;
226  tspecies(massIdx, upIdx) = 1.0;
227  tspecies(massIdx, dnIdx) = 1.0;
228 
229  elec.createSK();
230 
231  CoulombPBCAA caa(elec, true, false, kind == DynamicCoordinateKind::DC_POS_OFFLOAD);
232 
233  ParticleSet elec_clone(elec);
234  CoulombPBCAA caa_clone(caa);
235 
236  elec_clone.R[2] = {0.2, 0.3, 0.0};
237 
238  // testing batched interfaces
239  ResourceCollection pset_res("test_pset_res");
240  ResourceCollection caa_res("test_caa_res");
241  elec.createResource(pset_res);
242  caa.createResource(caa_res);
243 
244  // testing batched interfaces
245  RefVectorWithLeader<ParticleSet> p_ref_list(elec, {elec, elec_clone});
246  RefVectorWithLeader<OperatorBase> caa_ref_list(caa, {caa, caa_clone});
247 
248  // dummy psi
249  RuntimeOptions runtime_options;
250  TrialWaveFunction psi(runtime_options);
251  TrialWaveFunction psi_clone(runtime_options);
252  RefVectorWithLeader<TrialWaveFunction> psi_ref_list(psi, {psi, psi_clone});
253 
254  ResourceCollectionTeamLock<ParticleSet> mw_pset_lock(pset_res, p_ref_list);
255  ResourceCollectionTeamLock<OperatorBase> mw_caa_lock(caa_res, caa_ref_list);
256 
257  ParticleSet::mw_update(p_ref_list);
258  caa.mw_evaluate(caa_ref_list, psi_ref_list, p_ref_list);
259 
260  CHECK(caa.getValue() == Approx(-5.4954533536));
261  CHECK(caa_clone.getValue() == Approx(-6.329373489));
262 
263  CHECK(caa.get_madelung_constant() == Approx(vmad_bcc));
264  CHECK(caa_clone.get_madelung_constant() == Approx(vmad_bcc));
265 }
266 
267 TEST_CASE("Coulomb PBC A-A BCC 3 particles", "[hamiltonian]")
268 {
271 }
272 
273 
274 TEST_CASE("CoulombAA::mw_evaluatePerParticle", "[hamiltonian]")
275 {
278 
279  // Constructing a mock "golden" set of walker elements
281  lattice.BoxBConds = true; // periodic
282  lattice.R.diagonal(1.0);
283  lattice.reset();
284 
285  const SimulationCell simulation_cell(lattice);
286  ParticleSet elec(simulation_cell);
287 
288  elec.setName("elec");
289  elec.create({2});
290  elec.R[0] = {0.0, 0.5, 0.0};
291  elec.R[1] = {0.0, 0.0, 0.0};
292  SpeciesSet& tspecies = elec.getSpeciesSet();
293  int upIdx = tspecies.addSpecies("u");
294  int chargeIdx = tspecies.addAttribute("charge");
295  int massIdx = tspecies.addAttribute("mass");
296  tspecies(chargeIdx, upIdx) = -1;
297  tspecies(massIdx, upIdx) = 1.0;
298 
299  // The XMLParticleParser always calls createSK on particle sets it creates.
300  // Since most code assumes a valid particle set is as created by XMLParticleParser,
301  // we must call createSK().
302  elec.createSK();
303  elec.update();
304  // golden particle set valid (enough for this test)
305 
307  // golden CoulombPBCAA
308  CoulombPBCAA caa(elec, true, false, kind == DynamicCoordinateKind::DC_POS_OFFLOAD);
309 
310  // mock golden wavefunction, only needed to satisfy APIs
311  RuntimeOptions runtime_options;
312  TrialWaveFunction psi(runtime_options);
313 
314  // informOfPerParticleListener should be called on the golden instance of this operator if there
315  // are listeners present for it. This would normally be done by QMCHamiltonian but this is a unit test.
317 
318  // Now we can make a clone of the mock walker
319  ParticleSet elec2(elec);
320 
321  elec2.R[0] = {0.0, 0.5, 0.1};
322  elec2.R[1] = {0.6, 0.05, -0.1};
323  elec2.update();
324 
325  CoulombPBCAA caa2(elec2, true, false, kind == DynamicCoordinateKind::DC_POS_OFFLOAD);
326  RefVector<OperatorBase> caas{caa, caa2};
327  RefVectorWithLeader<OperatorBase> o_list(caa, caas);
328 
329  TrialWaveFunction psi_clone(runtime_options);
330  RefVectorWithLeader<TrialWaveFunction> twf_list(psi, {psi, psi_clone});
331 
332  // Self-energy correction, no background charge for e-e interaction
333  double consts = caa.myConst;
334  CHECK(consts == Approx(-6.3314780332));
335  RefVector<ParticleSet> ptcls{elec, elec2};
336  RefVectorWithLeader<ParticleSet> p_list(elec, ptcls);
337 
338  ResourceCollection caa_res("test_caa_res");
339  caa.createResource(caa_res);
340  ResourceCollectionTeamLock<OperatorBase> caa_lock(caa_res, o_list);
341 
342  ResourceCollection pset_res("test_pset_res");
343  elec.createResource(pset_res);
344  ResourceCollectionTeamLock<ParticleSet> pset_lock(pset_res, p_list);
345 
346  // The test Listener emitted by getParticularListener binds a Matrix
347  // it will write the reported data into it with each walker's particle values
348  // in a row.
349  Matrix<Real> local_pots(2);
350  Matrix<Real> local_pots2(2);
351 
352  std::vector<ListenerVector<Real>> listeners;
353  listeners.emplace_back("localenergy", getParticularListener(local_pots));
354  listeners.emplace_back("localenergy", getParticularListener(local_pots2));
355  std::vector<ListenerVector<Real>> ion_listeners;
356 
357  ParticleSet::mw_update(p_list);
358 
359  caa.mw_evaluatePerParticle(o_list, twf_list, p_list, listeners, ion_listeners);
360  CHECK(caa.getValue() == Approx(-2.9332312765));
361  CHECK(caa2.getValue() == Approx(-3.4537460926));
362  // Check that the sum of the particle energies == the total
363  CHECK(std::accumulate(local_pots.begin(), local_pots.begin() + local_pots.cols(), 0.0) == Approx(-2.9332312765));
364  CHECK(std::accumulate(local_pots[1], local_pots[1] + local_pots.cols(), 0.0) == Approx(-3.4537460926));
365  // Check that the second listener received the same data
366  auto check_matrix_result = checkMatrix(local_pots, local_pots2);
367  CHECKED_ELSE(check_matrix_result.result) { FAIL(check_matrix_result.result_message); }
368 }
369 
370 } // namespace qmcplusplus
a class that defines a supercell in D-dimensional Euclean space.
DynamicCoordinateKind
enumerator for DynamicCoordinates kinds
void setName(const std::string &aname)
Definition: ParticleSet.h:237
Container_t::iterator begin()
Definition: OhmmsMatrix.h:89
Calculates the AA Coulomb potential using PBCs.
Definition: CoulombPBCAA.h:38
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
TEST_CASE("complex_helper", "[type_traits]")
CHECKED_ELSE(check_matrix_result.result)
void createResource(ResourceCollection &collection) const
initialize a shared resource and hand it to a collection
auto check_matrix_result
void update(bool skipSK=false)
update the internal data
static std::unique_ptr< LRHandlerType > CoulombHandler
Stores the energ optimized LR handler.
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
ForceBase::Real Real
Definition: ForceBase.cpp:26
size_type cols() const
Definition: OhmmsMatrix.h:78
void test_CoulombPBCAA_3p(DynamicCoordinateKind kind)
CrystalLattice< OHMMS_PRECISION, OHMMS_DIM > lattice
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
void mw_evaluate(const RefVectorWithLeader< OperatorBase > &o_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list) const override
Evaluate the contribution of this component of multiple walkers.
RealType get_madelung_constant() const
Definition: CoulombPBCAA.h:185
Return_t evalConsts(bool report=true)
ParticlePos R
Position.
Definition: ParticleSet.h:79
auto getParticularListener(Matrix< T > &local_pots)
Return_t getValue() const noexcept
get a copy of value_
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
void create(const std::vector< int > &agroup)
create grouped particles
Declaration of a TrialWaveFunction.
std::vector< std::reference_wrapper< T > > RefVector
Class to represent a many-body trial wave function.
CheckMatrixResult checkMatrix(M1 &a_mat, M2 &b_mat, const bool check_all=false, std::optional< const double > eps=std::nullopt)
This function checks equality a_mat and b_mat elements M1, M2 need to have their element type declare...
Definition: checkMatrix.hpp:63
static void mw_update(const RefVectorWithLeader< ParticleSet > &p_list, bool skipSK=false)
batched version of update
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
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
void mw_evaluatePerParticle(const RefVectorWithLeader< OperatorBase > &o_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, const std::vector< ListenerVector< RealType >> &listeners, const std::vector< ListenerVector< RealType >> &ion_listeners) const override
Evaluate the contribution of this component of multiple walkers per particle reporting to registered ...
void informOfPerParticleListener() override
Inform objects associated with this operator of per particle listeners.
Listener types that allow Estimators to register with QMCHamiltonian to have "trace" values from oper...
Return_t evaluate(ParticleSet &P) override
Evaluate the local energy contribution of this component.