QMCPACK
test_SkAllEstimator.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) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by: Mark Dewing, markdewing@gmail.com, University of Illinois at Urbana-Champaign
8 //
9 // File created by: Mark Dewing, markdewing@gmail.com, University of Illinois at Urbana-Champaign
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 
13 #include "catch.hpp"
14 #include "OhmmsData/Libxml2Doc.h"
15 #include "Lattice/CrystalLattice.h"
16 #include "LongRange/StructFact.h"
17 #include "Particle/ParticleSet.h"
18 #include "Particle/DistanceTable.h"
21 #include <stdio.h>
22 #include <string>
23 using std::string;
24 
25 
26 /*
27  -- jpt 25/03/2020 --
28  Deterministic unit test for the SkAllEstimator class.
29  Despite the plumbing, it seems that _for the moment_ (March 2020)
30  that only the e-e structure factor is computed and stored.
31 
32  This is the important piece, as we use it for finite size corrections.
33  However, it looks like one might be able to generalize it for e-i and i-i
34  at a later date. If that happens, this test should be updated!
35  */
36 
37 
38 namespace qmcplusplus
39 {
40 TEST_CASE("SkAll", "[hamiltonian]")
41 {
42  // Boiler plate setup
43  std::cout << std::fixed;
44  std::cout << std::setprecision(8);
46 
47  Communicate* c;
49 
50  // XML parser
52 
53 
54  /*
55  Minimal xml input blocks
56  */
57  // Lattice block
58  const char* lat_xml = R"(<simulationcell>
59  <parameter name="lattice" units="bohr">
60  2.0 0.0 0.0
61  0.0 2.0 0.0
62  0.0 0.0 2.0
63  </parameter>
64  <parameter name="bconds">
65  p p p
66  </parameter>
67  <parameter name="LR_dim_cutoff" > 6 </parameter>
68  <parameter name="rs" > 1.0 </parameter>
69  <parameter name="nparticles" > 8 </parameter>
70  </simulationcell>)";
71 
72  // Particleset block for the electrons
73  const char* elec_pset_xml = R"(<particleset name="e" random="yes">
74  <group name="u" size="4">
75  <parameter name="charge" > -1 </parameter>
76  <parameter name="mass" > 1.0 </parameter>
77  </group>
78  <group name="d" size="4">
79  <parameter name="charge" > -1 </parameter>
80  <parameter name="mass" > 1.0 </parameter>
81  </group>
82  </particleset>)";
83 
84  // Particleset block for the ions
85  const char* ion_pset_xml = R"(<particleset name="i" size="4">
86  <group name="He">
87  <parameter name="charge" > 2 </parameter>
88  <parameter name="valence" > 2 </parameter>
89  <parameter name="atomicnumber"> 2 </parameter>
90  </group>
91  <attrib name="position" datatype="posArray"
92  condition="1">
93  0.00 0.00 0.00
94  0.25 0.25 0.25
95  0.50 0.50 0.50
96  0.75 0.75 0.75
97  </attrib>
98  <attrib name="ionid" datatype="stringArray">
99  He He He He
100  </attrib>
101  </particleset>)";
102 
103  // SKAllEstimator block, seems that writeionion does nothing?
104  const char* skall_xml = R"(<estimator
105  name="Skall" type="skall"
106  source="i" target="e" hdf5="yes"
107  />)";
108 
109  // Read in xml, add to pset_builder below
110  bool lat_okay = doc.parseFromString(lat_xml);
111  REQUIRE(lat_okay);
112  xmlNodePtr lat_xml_root = doc.getRoot();
113 
114  std::cout << "\n\n\ntest_SkAllEstimator: START\n";
115 
116  // Build a ParticleSetPool - makes ParticleSets
117  ParticleSetPool pset_builder(c, "pset_builder");
118 
119  // First attach the Lattice defined above
120  pset_builder.readSimulationCellXML(lat_xml_root);
121 
122  // Now build the elec ParticleSet
123  bool elec_pset_okay = doc.parseFromString(elec_pset_xml);
124  REQUIRE(elec_pset_okay);
125  xmlNodePtr elec_pset_xml_root = doc.getRoot();
126  pset_builder.put(elec_pset_xml_root);
127 
128  // Get the (now assembled) elec ParticleSet, sanity check, report
129  ParticleSet* elec = pset_builder.getParticleSet("e");
130  REQUIRE(elec->isSameMass());
131  REQUIRE(elec->getName() == "e");
132 
133  // Move the particles manually onto B1 lattice
134  // NB: Spins are grouped contiguously
135  // Up spins
136  elec->R[0][0] = 0.0;
137  elec->R[0][1] = 0.0;
138  elec->R[0][2] = 0.0;
139  elec->R[1][0] = 1.0;
140  elec->R[1][1] = 1.0;
141  elec->R[1][2] = 0.0;
142  elec->R[2][0] = 1.0;
143  elec->R[2][1] = 0.0;
144  elec->R[2][2] = 1.0;
145  elec->R[3][0] = 0.0;
146  elec->R[3][1] = 1.0;
147  elec->R[3][2] = 1.0;
148 
149  // Down spins
150  elec->R[4][0] = 1.0;
151  elec->R[4][1] = 0.0;
152  elec->R[4][2] = 0.0;
153  elec->R[5][0] = 0.0;
154  elec->R[5][1] = 1.0;
155  elec->R[5][2] = 0.0;
156  elec->R[6][0] = 0.0;
157  elec->R[6][1] = 0.0;
158  elec->R[6][2] = 1.0;
159  elec->R[7][0] = 1.0;
160  elec->R[7][1] = 1.0;
161  elec->R[7][2] = 1.0;
162 
163  elec->get(std::cout); // print particleset info to stdout
164 
165 
166  // Get the (now assembled) ion ParticleSet, sanity check, report
167  bool ion_pset_okay = doc.parseFromString(ion_pset_xml);
168  REQUIRE(ion_pset_okay);
169  xmlNodePtr ion_pset_xml_root = doc.getRoot();
170  pset_builder.put(ion_pset_xml_root);
171 
172  // Finally, make the ion ParticleSet, sanity check, report
173  // It seems that we need this only to construct skall, but it
174  // is never used to evaluate the estimator in this test.
175  ParticleSet* ion = pset_builder.getParticleSet("i");
176  REQUIRE(ion->isSameMass());
177  REQUIRE(ion->getName() == "i");
178  ion->get(std::cout); // print particleset info to stdout
179 
180 
181  // Set up the distance table, match expected layout
182  const int ee_table_id = elec->addTable(*elec);
183 
184  const auto& dii(elec->getDistTable(ee_table_id));
185  elec->update(); // distance table evaluation here
186 
187  // Check that the skall xml block is valid
188  bool skall_okay = doc.parseFromString(skall_xml);
189  REQUIRE(skall_okay);
190  xmlNodePtr skall_xml_root = doc.getRoot();
191 
192  // Make a SkAllEstimator, call put() to set up internals
193  SkAllEstimator skall(*ion, *elec);
194  skall.put(skall_xml_root);
195  skall.addObservables(elec->PropertyList, elec->Collectables);
196  skall.get(app_log()); // pretty print settings
197 
198  // Hack to make a walker so that t_walker_ points to something
199  // Only used to set t_walker_->Weight = 1 so that skall->evaluate()
200  // doesn't segfault.
201  // NB: setHistories(dummy) attaches dummy to t_walker_
203  skall.setHistories(dummy);
204  skall.evaluate(*elec);
205 
206  // s(k) is computed by & held by the ParticleSet. SkAll just
207  // takes that pre-computed s(k) and pulls out rho(k)..
208  // In order to compare to analytic result, need the list
209  // of k-vectors in cartesian coordinates.
210  // Luckily, ParticleSet stores that in SK->getKLists().kpts_cart
211  int nkpts = elec->getSimulationCell().getKLists().numk;
212  std::cout << "\n";
213  std::cout << "SkAll results:\n";
214  std::cout << std::fixed;
215  std::cout << std::setprecision(6);
216  std::cout << std::setw(4) << "i"
217  << " " << std::setw(8) << "kx"
218  << " " << std::setw(8) << "ky"
219  << " " << std::setw(8) << "kz"
220  << " " << std::setw(8) << "rhok_r"
221  << " " << std::setw(8) << "rhok_i"
222  << " " << std::setw(8) << "c.c."
223  << "\n";
224  std::cout << "================================================================\n";
225 
226  // Extract rhok out of Collectables, print values
227  auto rhok = elec->Collectables;
228  std::cout << std::fixed;
229  std::cout << std::setprecision(5);
230  for (int k = 0; k < nkpts; k++)
231  {
232  auto kvec = elec->getSimulationCell().getKLists().kpts_cart[k];
233  RealType kx = kvec[0];
234  RealType ky = kvec[1];
235  RealType kz = kvec[2];
236  RealType rk_r = rhok[nkpts + k];
237  RealType rk_i = rhok[2 * nkpts + k];
238  RealType rk_cc = rhok[k];
239  std::cout << std::setw(4) << k << " " << std::setw(8) << kx << " " << std::setw(8) << ky << " " << std::setw(8)
240  << kz << " " << std::setw(8) << rk_r << " " << std::setw(8) << rk_i << " " << std::setw(8) << rk_cc
241  << "\n";
242  }
243 
244  /*
245  Verify against analytic result:
246  NB: MUST match xml input!!!
247  rho(-1.94889, 0.00000, 0.00000)= 2.52341 + -3.71748i
248  rho( 0.00000, -1.94889, 0.00000)= 2.52341 + -3.71748i
249  rho( 0.00000, 0.00000, -1.94889)= 2.52341 + -3.71748i
250  rho( 0.00000, 0.00000, 1.94889)= 2.52341 + 3.71748i
251  rho( 0.00000, 1.94889, 0.00000)= 2.52341 + 3.71748i
252  rho( 1.94889, 0.00000, 0.00000)= 2.52341 + 3.71748i
253  rho(-1.94889, -1.94889, 0.00000)= -0.93151 + -2.34518i
254  rho(-1.94889, 0.00000, -1.94889)= -0.93151 + -2.34518i
255  rho(-1.94889, 0.00000, 1.94889)= 2.52341 + 0.00000i
256  rho(-1.94889, 1.94889, 0.00000)= 2.52341 + 0.00000i
257  rho( 0.00000, -1.94889, -1.94889)= -0.93151 + -2.34518i
258  rho( 0.00000, -1.94889, 1.94889)= 2.52341 + 0.00000i
259  rho( 0.00000, 1.94889, -1.94889)= 2.52341 + 0.00000i
260  rho( 0.00000, 1.94889, 1.94889)= -0.93151 + 2.34518i
261  rho( 1.94889, -1.94889, 0.00000)= 2.52341 + 0.00000i
262  rho( 1.94889, 0.00000, -1.94889)= 2.52341 + 0.00000i
263  rho( 1.94889, 0.00000, 1.94889)= -0.93151 + 2.34518i
264  rho( 1.94889, 1.94889, 0.00000)= -0.93151 + 2.34518i
265  rho(-1.94889, -1.94889, -1.94889)= -1.38359 + -0.30687i
266  rho(-1.94889, -1.94889, 1.94889)= 0.79595 + -1.17259i
267  rho(-1.94889, 1.94889, -1.94889)= 0.79595 + -1.17259i
268  rho(-1.94889, 1.94889, 1.94889)= 0.79595 + 1.17259i
269  rho( 1.94889, -1.94889, -1.94889)= 0.79595 + -1.17259i
270  rho( 1.94889, -1.94889, 1.94889)= 0.79595 + 1.17259i
271  rho( 1.94889, 1.94889, -1.94889)= 0.79595 + 1.17259i
272  rho( 1.94889, 1.94889, 1.94889)= -1.38359 + 0.30687i
273  */
274 
275  const RealType eps = 1E-04; // tolerance
276  REQUIRE(std::fabs(rhok[26] - 2.52341) < eps);
277  REQUIRE(std::fabs(rhok[52] + 3.71748) < eps);
278  REQUIRE(std::fabs(rhok[26 + 1] - 2.52341) < eps);
279  REQUIRE(std::fabs(rhok[52 + 1] + 3.71748) < eps);
280  REQUIRE(std::fabs(rhok[26 + 2] - 2.52341) < eps);
281  REQUIRE(std::fabs(rhok[52 + 2] + 3.71748) < eps);
282 
283  REQUIRE(std::fabs(rhok[26 + 3] - 2.52341) < eps);
284  REQUIRE(std::fabs(rhok[52 + 3] - 3.71748) < eps);
285  REQUIRE(std::fabs(rhok[26 + 4] - 2.52341) < eps);
286  REQUIRE(std::fabs(rhok[52 + 4] - 3.71748) < eps);
287  REQUIRE(std::fabs(rhok[26 + 5] - 2.52341) < eps);
288  REQUIRE(std::fabs(rhok[52 + 5] - 3.71748) < eps);
289 
290  REQUIRE(std::fabs(rhok[26 + 6] + 0.93151) < eps);
291  REQUIRE(std::fabs(rhok[52 + 6] + 2.34518) < eps);
292  REQUIRE(std::fabs(rhok[26 + 7] + 0.93151) < eps);
293  REQUIRE(std::fabs(rhok[52 + 7] + 2.34518) < eps);
294  REQUIRE(std::fabs(rhok[26 + 8] - 2.52341) < eps);
295  REQUIRE(std::fabs(rhok[52 + 8] - 0.00000) < eps);
296 
297  REQUIRE(std::fabs(rhok[26 + 9] - 2.52341) < eps);
298  REQUIRE(std::fabs(rhok[52 + 9] - 0.00000) < eps);
299  REQUIRE(std::fabs(rhok[26 + 10] + 0.93151) < eps);
300  REQUIRE(std::fabs(rhok[52 + 10] + 2.34518) < eps);
301  REQUIRE(std::fabs(rhok[26 + 11] - 2.52341) < eps);
302  REQUIRE(std::fabs(rhok[52 + 11] - 0.00000) < eps);
303 
304  REQUIRE(std::fabs(rhok[26 + 12] - 2.52341) < eps);
305  REQUIRE(std::fabs(rhok[52 + 12] - 0.00000) < eps);
306  REQUIRE(std::fabs(rhok[26 + 13] + 0.93151) < eps);
307  REQUIRE(std::fabs(rhok[52 + 13] - 2.34518) < eps);
308  REQUIRE(std::fabs(rhok[26 + 14] - 2.52341) < eps);
309  REQUIRE(std::fabs(rhok[52 + 14] - 0.00000) < eps);
310 
311  REQUIRE(std::fabs(rhok[26 + 15] - 2.52341) < eps);
312  REQUIRE(std::fabs(rhok[52 + 15] - 0.00000) < eps);
313  REQUIRE(std::fabs(rhok[26 + 16] + 0.93151) < eps);
314  REQUIRE(std::fabs(rhok[52 + 16] - 2.34518) < eps);
315  REQUIRE(std::fabs(rhok[26 + 17] + 0.93151) < eps);
316  REQUIRE(std::fabs(rhok[52 + 17] - 2.34518) < eps);
317 
318  REQUIRE(std::fabs(rhok[26 + 18] + 1.38359) < eps);
319  REQUIRE(std::fabs(rhok[52 + 18] + 0.30687) < eps);
320  REQUIRE(std::fabs(rhok[26 + 19] - 0.79595) < eps);
321  REQUIRE(std::fabs(rhok[52 + 19] + 1.17259) < eps);
322  REQUIRE(std::fabs(rhok[26 + 20] - 0.79595) < eps);
323  REQUIRE(std::fabs(rhok[52 + 20] + 1.17259) < eps);
324 
325  REQUIRE(std::fabs(rhok[26 + 21] - 0.79595) < eps);
326  REQUIRE(std::fabs(rhok[52 + 21] - 1.17259) < eps);
327  REQUIRE(std::fabs(rhok[26 + 22] - 0.79595) < eps);
328  REQUIRE(std::fabs(rhok[52 + 22] + 1.17259) < eps);
329  REQUIRE(std::fabs(rhok[26 + 23] - 0.79595) < eps);
330  REQUIRE(std::fabs(rhok[52 + 23] - 1.17259) < eps);
331 
332  REQUIRE(std::fabs(rhok[26 + 24] - 0.79595) < eps);
333  REQUIRE(std::fabs(rhok[52 + 24] - 1.17259) < eps);
334  REQUIRE(std::fabs(rhok[26 + 25] + 1.38359) < eps);
335  REQUIRE(std::fabs(rhok[52 + 25] - 0.30687) < eps);
336 
337  std::cout << "test_SkAllEstimator:: STOP\n";
338 }
339 } // namespace qmcplusplus
Walker< QMCTraits, PtclOnLatticeTraits > Walker_t
walker type
Definition: ParticleSet.h:59
class that handles xmlDoc
Definition: Libxml2Doc.h:76
const std::string & getName() const
return the name
Return_t evaluate(ParticleSet &P) override
Evaluate the local energy contribution of this component.
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
QTBase::RealType RealType
Definition: Configuration.h:58
bool put(xmlNodePtr cur)
process an xml element
std::ostream & app_log()
Definition: OutputManager.h:65
TEST_CASE("complex_helper", "[type_traits]")
xmlNodePtr getRoot()
Definition: Libxml2Doc.h:88
Declare SkAllEstimator.
void update(bool skipSK=false)
update the internal data
Communicate * Controller
Global Communicator for a process.
Definition: Communicate.cpp:35
bool put(xmlNodePtr cur) override
Read the input parameter.
Declaration of CrystalLattice<T,D>
PropertySetType PropertyList
name-value map of Walker Properties
Definition: ParticleSet.h:112
Wrapping information on parallelism.
Definition: Communicate.h:68
const auto & getSimulationCell() const
Definition: ParticleSet.h:250
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 addObservables(PropertySetType &plist)
REQUIRE(std::filesystem::exists(filename))
ParticleSet * getParticleSet(const std::string &pname)
get a named ParticleSet
Manage a collection of ParticleSet objects.
ParticlePos R
Position.
Definition: ParticleSet.h:79
virtual void setHistories(Walker_t &ThisWalker)
bool get(std::ostream &os) const override
write about the class
auto & getDistTable(int table_ID) const
get a distance table by table_ID
Definition: ParticleSet.h:190
Buffer_t Collectables
observables in addition to those registered in Properties/PropertyList
Definition: ParticleSet.h:126
const char * lat_xml
bool readSimulationCellXML(xmlNodePtr cur)
initialize the supercell shared by all the particle sets
bool parseFromString(const std::string_view data)
Definition: Libxml2Doc.cpp:204
SkAllEstimator evaluate the structure factor of the target particleset.
bool get(std::ostream &os) const override
dummy. For satisfying OhmmsElementBase.
A container class to represent a walker.
Definition: Walker.h:49
Declaration of ParticleSetPool.