QMCPACK
test_distance_table.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 
15 #include <stdio.h>
16 #include <string>
17 #include "OhmmsData/Libxml2Doc.h"
18 #include "OhmmsPETE/Tensor.h"
19 #include "Particle/ParticleSet.h"
21 #include "ParticleIO/LatticeIO.h"
22 #include "Particle/DistanceTable.h"
23 #include <ResourceCollection.h>
24 #include "MinimalParticlePool.h"
25 
26 using std::string;
27 
28 namespace qmcplusplus
29 {
30 TEST_CASE("distance_open_z", "[distance_table][xml]")
31 {
32  // test that particle distances are properly calculated
33 
34 
35  const char* particles = R"(<tmp>
36 <particleset name="e" random="yes">
37  <group name="u" size="1" mass="1.0">
38  <parameter name="charge" > -1 </parameter>
39  <parameter name="mass" > 1.0 </parameter>
40  <attrib name="position" datatype="posArray" condition="0">
41  0.00000000 0.00000000 0.20000000
42  </attrib>
43  </group>
44  <group name="d" size="1" mass="1.0">
45  <parameter name="charge" > -1 </parameter>
46  <parameter name="mass" > 1.0 </parameter>
47  <attrib name="position" datatype="posArray" condition="0">
48  0.00000000 0.00000000 -0.20000000
49  </attrib>
50  </group>
51 </particleset>
52 <particleset name="ion0">
53  <group name="H" size="2" mass="1836.15">
54  <parameter name="charge" > 1 </parameter>
55  <parameter name="valence" > 1 </parameter>
56  <parameter name="atomicnumber" > 1 </parameter>
57  <parameter name="mass" > 1836.15 </parameter>
58  <attrib name="position" datatype="posArray" condition="0">
59  0.00000000 0.00000000 0.00000000
60  0.00000000 0.00000000 0.50000000
61  </attrib>
62  </group>
63 </particleset>
64 </tmp>
65 )";
66 
68  bool okay = doc.parseFromString(particles);
69  REQUIRE(okay);
70 
71  xmlNodePtr root = doc.getRoot();
72  xmlNodePtr part1 = xmlFirstElementChild(root);
73  xmlNodePtr part2 = xmlNextElementSibling(part1);
74 
75  // read particle set
76  const SimulationCell simulation_cell;
77  ParticleSet ions(simulation_cell), electrons(simulation_cell);
78 
79  XMLParticleParser parse_electrons(electrons);
80  parse_electrons.readXML(part1);
81 
82  XMLParticleParser parse_ions(ions);
83  parse_ions.readXML(part2);
84 
85  REQUIRE(electrons.getName() == "e");
86  REQUIRE(ions.getName() == "ion0");
87  REQUIRE(ions.isSameMass());
88  REQUIRE(electrons.isSameMass());
89 
90  // calculate particle distances
91  const int tid = electrons.addTable(ions);
92  electrons.update();
93 
94  // get target particle set's distance table data
95  const auto& dtable = electrons.getDistTableAB(tid);
96  REQUIRE(dtable.getName() == "ion0_e");
97 
98  REQUIRE(dtable.sources() == ions.getTotalNum());
99  REQUIRE(dtable.targets() == electrons.getTotalNum());
100 
101  double expect[] = {0.2, 0.2, 0.3, 0.7};
102  int idx(0);
103  for (int iat = 0; iat < dtable.sources(); iat++)
104  {
105  for (int jat = 0; jat < dtable.targets(); jat++, idx++)
106  {
107  double dist = dtable.getDistRow(jat)[iat];
108  CHECK(dist == Approx(expect[idx]));
109  }
110  }
111 
112  TinyVector<double, 3> displ1 = dtable.getDisplacements()[0][0];
113  CHECK(displ1[0] == Approx(0.0));
114  CHECK(displ1[1] == Approx(0.0));
115  CHECK(displ1[2] == Approx(-0.2));
116 
117  TinyVector<double, 3> displ2 = dtable.getDisplacements()[0][1];
118  CHECK(displ2[0] == Approx(0.0));
119  CHECK(displ2[1] == Approx(0.0));
120  CHECK(displ2[2] == Approx(0.3));
121 
122  // get distance between target="e" group="u" iat=0 and source="ion0" group="H" jat=1
123 
124 } // TEST_CASE distance_open_z
125 
126 TEST_CASE("distance_open_xy", "[distance_table][xml]")
127 {
128  const char* particles = R"(<tmp>
129 <particleset name="e" random="yes">
130  <group name="u" size="2" mass="1.0">
131  <parameter name="charge" > -1 </parameter>
132  <parameter name="mass" > 1.0 </parameter>
133  <attrib name="position" datatype="posArray" condition="0">
134  0.70000000 0.00000000 0.00000000
135  0.00000000 1.00000000 0.00000000
136  </attrib>
137  </group>
138  <group name="d" size="1" mass="1.0">
139  <parameter name="charge" > -1 </parameter>
140  <parameter name="mass" > 1.0 </parameter>
141  <attrib name="position" datatype="posArray" condition="0">
142  -0.90000000 0.00000000 0.00000000
143  </attrib>
144  </group>
145 </particleset>
146 <particleset name="ion0">
147  <group name="H" size="2" mass="1836.15">
148  <parameter name="charge" > 1 </parameter>
149  <parameter name="valence" > 1 </parameter>
150  <parameter name="atomicnumber" > 1 </parameter>
151  <parameter name="mass" > 1836.15 </parameter>
152  <attrib name="position" datatype="posArray" condition="0">
153  0.00000000 0.00000000 0.00000000
154  1.00000000 0.00000000 0.00000000
155  </attrib>
156  </group>
157 </particleset>
158 </tmp>
159 )";
160 
162  bool okay = doc.parseFromString(particles);
163  REQUIRE(okay);
164 
165  xmlNodePtr root = doc.getRoot();
166  xmlNodePtr part1 = xmlFirstElementChild(root);
167  xmlNodePtr part2 = xmlNextElementSibling(part1);
168 
169  // read particle set
170  const SimulationCell simulation_cell;
171  ParticleSet ions(simulation_cell), electrons(simulation_cell);
172 
173  XMLParticleParser parse_electrons(electrons);
174  parse_electrons.readXML(part1);
175 
176  XMLParticleParser parse_ions(ions);
177  parse_ions.readXML(part2);
178 
179  REQUIRE(electrons.getName() == "e");
180  REQUIRE(ions.getName() == "ion0");
181  REQUIRE(ions.isSameMass());
182  REQUIRE(electrons.isSameMass());
183 
184  // calculate particle distances
185  const int tid = electrons.addTable(ions);
186  electrons.update();
187 
188  // get distance table attached to target particle set (electrons)
189  const auto& dtable = electrons.getDistTableAB(tid);
190  REQUIRE(dtable.getName() == "ion0_e");
191 
192  REQUIRE(dtable.sources() == ions.getTotalNum());
193  REQUIRE(dtable.targets() == electrons.getTotalNum());
194 
195  // calculate distance, one source particle at a time i.e.
196  // H0 - e0: 0.7
197  // H0 - e1: 1.0
198  // H0 - e2: 0.9
199  // H1 - e0: 0.3
200  // etc.
201  double expect[] = {0.7, 1.0, 0.9, 0.3, std::sqrt(2), 1.9};
202  int idx(0);
203  for (int iat = 0; iat < dtable.sources(); iat++)
204  {
205  for (int jat = 0; jat < dtable.targets(); jat++, idx++)
206  {
207  double dist = dtable.getDistRow(jat)[iat];
208  CHECK(dist == Approx(expect[idx]));
209  }
210  }
211 
212 } // TEST_CASE distance_open_xy
213 
214 TEST_CASE("distance_open_species_deviation", "[distance_table][xml]")
215 {
216  // pull out distances between specific species
217 
218 
219  const char* particles = R"(<tmp>
220 <particleset name="e" random="yes">
221  <group name="u" size="2" mass="1.0">
222  <parameter name="charge" > -1 </parameter>
223  <parameter name="mass" > 1.0 </parameter>
224  <attrib name="position" datatype="posArray" condition="0">
225  0.70000000 0.00000000 0.00000000
226  0.00000000 1.00000000 0.00000000
227  </attrib>
228  </group>
229  <group name="d" size="1" mass="1.0">
230  <parameter name="charge" > -1 </parameter>
231  <parameter name="mass" > 1.0 </parameter>
232  <attrib name="position" datatype="posArray" condition="0">
233  -0.90000000 0.00000000 0.00000000
234  </attrib>
235  </group>
236 </particleset>
237 <particleset name="ion0">
238  <group name="H" size="2" mass="1836.15">
239  <parameter name="charge" > 1 </parameter>
240  <parameter name="valence" > 1 </parameter>
241  <parameter name="atomicnumber" > 1 </parameter>
242  <parameter name="mass" > 1836.15 </parameter>
243  <attrib name="position" datatype="posArray" condition="0">
244  0.00000000 0.00000000 0.00000000
245  1.00000000 0.00000000 0.00000000
246  </attrib>
247  </group>
248 </particleset>
249 </tmp>
250 )";
251 
253  bool okay = doc.parseFromString(particles);
254  REQUIRE(okay);
255 
256  xmlNodePtr root = doc.getRoot();
257  xmlNodePtr part1 = xmlFirstElementChild(root);
258  xmlNodePtr part2 = xmlNextElementSibling(part1);
259 
260  // read particle set
261  const SimulationCell simulation_cell;
262  ParticleSet ions(simulation_cell), electrons(simulation_cell);
263 
264  XMLParticleParser parse_electrons(electrons);
265  parse_electrons.readXML(part1);
266 
267  XMLParticleParser parse_ions(ions);
268  parse_ions.readXML(part2);
269 
270  REQUIRE(electrons.getName() == "e");
271  REQUIRE(ions.getName() == "ion0");
272  REQUIRE(ions.isSameMass());
273  REQUIRE(electrons.isSameMass());
274 
275  // calculate particle distances
276  const int tid = electrons.addTable(ions);
277  electrons.update();
278 
279  // get distance table attached to target particle set (electrons)
280  const auto& dtable = electrons.getDistTableAB(tid);
281  REQUIRE(dtable.getName() == "ion0_e");
282 
283  // get the electron species set
284  SpeciesSet& especies(electrons.getSpeciesSet());
285 
286  REQUIRE(dtable.sources() == ions.getTotalNum());
287  REQUIRE(dtable.targets() == electrons.getTotalNum());
288 
289  // !! assume "u" and "H" groups have the same number of particles
290  double latdev2 = 0.0; // mean-squared deviation from lattice
291  int cur_jat(-1); // keep an index to the last found target particle
292  double expect[] = {0.7, std::sqrt(2)};
293  int idx(0);
294  for (int iat = 0; iat < dtable.sources(); iat++, idx++)
295  {
296  for (int jat = cur_jat + 1; jat < dtable.targets(); jat++, idx++)
297  {
298  // find next "u"
299  int species_id = electrons.GroupID[jat];
300  string species_name = especies.speciesName[species_id];
301  if (species_name != "u")
302  continue;
303 
304  // calculate distance from lattice site iat
305  double dist = dtable.getDistRow(jat)[iat];
306  latdev2 += std::pow(dist, 2); // !? pow(x,2) does what?
307  CHECK(dist == Approx(expect[idx]));
308  cur_jat = jat;
309  break;
310  }
311  }
312  CHECK(latdev2 / ions.getTotalNum() == Approx(1.245));
313 
314 } // TEST_CASE distance_open_species_deviation
315 
317 {
318  const char* particles = R"(<tmp>
319  <simulationcell>
320  <parameter name="lattice" units="bohr">
321  6.00000000 6.00000000 0.00000000
322  0.00000000 6.00000000 6.00000000
323  6.00000000 0.00000000 6.00000000
324  </parameter>
325  <parameter name="bconds">
326  p p p
327  </parameter>
328  <parameter name="LR_dim_cutoff" > 15 </parameter>
329  </simulationcell>
330 </tmp>
331 )";
332 
334  bool okay = doc.parseFromString(particles);
335  REQUIRE(okay);
336 
337  xmlNodePtr root = doc.getRoot();
338  xmlNodePtr part1 = xmlFirstElementChild(root);
339 
340  // read lattice
343  lp.put(part1);
344  lattice.print(app_log(), 0);
345 
346  return SimulationCell(lattice);
347 }
348 
350 {
351  const char* particles = R"(<tmp>
352  <simulationcell>
353  <parameter name="lattice" units="bohr">
354  6.00000000 0.00000000 0.00000000
355  0.00000000 6.00000000 0.00000000
356  0.00000000 0.00000000 6.00000000
357  </parameter>
358  <parameter name="bconds">
359  p p p
360  </parameter>
361  <parameter name="LR_dim_cutoff" > 15 </parameter>
362  </simulationcell>
363 </tmp>
364 )";
365 
367  bool okay = doc.parseFromString(particles);
368  REQUIRE(okay);
369 
370  xmlNodePtr root = doc.getRoot();
371  xmlNodePtr part1 = xmlFirstElementChild(root);
372 
373  // read lattice
376  lp.put(part1);
377  lattice.print(app_log(), 0);
378 
379  return SimulationCell(lattice);
380 }
381 
383 {
384  const char* particles = R"(<tmp>
385  <particleset name="e">
386  <group name="u" size="2" mass="1.0">
387  <parameter name="charge" > -1 </parameter>
388  <parameter name="mass" > 1.0 </parameter>
389  <attrib name="position" datatype="posArray" condition="0">
390  0.00000000 0.00000000 0.00000000
391  3.00000000 0.00000000 0.00000000
392  </attrib>
393  </group>
394  <group name="d" size="1" mass="1.0">
395  <parameter name="charge" > -1 </parameter>
396  <parameter name="mass" > 1.0 </parameter>
397  <attrib name="position" datatype="posArray" condition="0">
398  0.00000000 0.00000000 3.00000000
399  </attrib>
400  </group>
401  </particleset>
402  <particleset name="ion0">
403  <group name="H" size="8" mass="1836.15">
404  <parameter name="charge" > 1 </parameter>
405  <parameter name="valence" > 1 </parameter>
406  <parameter name="atomicnumber" > 1 </parameter>
407  <parameter name="mass" > 1836.15 </parameter>
408  <attrib name="position" datatype="posArray" condition="0">
409  0.00000000 0.00000000 0.00000000
410  3.00000000 0.00000000 0.00000000
411  0.00000000 3.00000000 0.00000000
412  3.00000000 3.00000000 0.00000000
413  0.00000000 0.00000000 3.00000000
414  3.00000000 0.00000000 3.00000000
415  0.00000000 3.00000000 3.00000000
416  3.00000000 3.00000000 3.00000000
417  </attrib>
418  </group>
419  </particleset>
420 </tmp>
421 )";
422 
424  bool okay = doc.parseFromString(particles);
425  REQUIRE(okay);
426 
427  xmlNodePtr root = doc.getRoot();
428  xmlNodePtr part1 = xmlFirstElementChild(root);
429  xmlNodePtr part2 = xmlNextElementSibling(part1);
430 
431  // read particle set
432  XMLParticleParser parse_electrons(electrons);
433  parse_electrons.readXML(part1);
434 
435  XMLParticleParser parse_ions(ions);
436  parse_ions.readXML(part2);
437 
438  REQUIRE(electrons.getName() == "e");
439  REQUIRE(ions.getName() == "ion0");
440  REQUIRE(ions.isSameMass());
441  REQUIRE(electrons.isSameMass());
442 }
443 
444 TEST_CASE("distance_pbc_z", "[distance_table][xml]")
445 {
446  // test that particle distances are properly calculated under periodic boundary condition
447  // There are many details in this example, but the main idea is simple: When a particle is moved by a full lattice vector, no distance should change.
448 
449  const SimulationCell simulation_cell(parse_pbc_lattice());
450  ParticleSet ions(simulation_cell), electrons(simulation_cell);
451  parse_electron_ion_pbc_z(ions, electrons);
452 
453  // calculate particle distances
454  const int ei_tid = electrons.addTable(ions);
455  electrons.update();
456  ions.update();
457 
458  // get target particle set's distance table data
459  const auto& ei_dtable = electrons.getDistTableAB(ei_tid);
460  CHECK(ei_dtable.getName() == "ion0_e");
461 
462  CHECK(ei_dtable.sources() == ions.getTotalNum());
463  CHECK(ei_dtable.targets() == electrons.getTotalNum());
464 
465  int num_src = ions.getTotalNum();
466  int num_tar = electrons.getTotalNum();
467  std::vector<double> expect;
468  expect.resize(num_src * num_tar);
469  int idx(0);
470  for (int iat = 0; iat < num_src; iat++)
471  {
472  for (int jat = 0; jat < num_tar; jat++, idx++)
473  {
474  double dist = ei_dtable.getDistRow(jat)[iat];
475  expect[idx] = dist;
476  }
477  }
478 
479  // move a particle by a lattice vector
480  ParticleSet::SingleParticlePos disp(6.0, 0, 0);
481  electrons.makeMove(0, disp); // temporary change written in distance table
482  electrons.acceptMove(0); // update distance table with temporary change
483 
484  // move some more
485  disp[1] = -6.0;
486  electrons.makeMove(1, disp);
487  electrons.acceptMove(1);
488 
489  idx = 0;
490  for (int iat = 0; iat < num_src; iat++)
491  {
492  for (int jat = 0; jat < num_tar; jat++, idx++)
493  {
494  double dist = ei_dtable.getDistRow(jat)[iat];
495  CHECK(expect[idx] == Approx(dist));
496  }
497  }
498 
499  const int ee_tid = electrons.addTable(electrons);
500  // get target particle set's distance table data
501  const auto& ee_dtable = electrons.getDistTableAA(ee_tid);
502  CHECK(ee_dtable.getName() == "e_e");
503  electrons.update();
504 
505  // shift electron 0 a bit to avoid box edges.
506  ParticleSet::SingleParticlePos shift(0.1, 0.2, -0.1);
507  electrons.makeMove(0, shift);
508  electrons.acceptMove(0);
509 
510  disp[0] = 0.2;
511  disp[1] = 0.1;
512  disp[2] = 0.3;
513 
514  electrons.makeMove(0, disp, false);
515  CHECK(ee_dtable.getTempDists()[1] == Approx(2.7239676944));
516  CHECK(ee_dtable.getTempDispls()[1][0] == Approx(2.7));
517  CHECK(ee_dtable.getTempDispls()[1][1] == Approx(-0.3));
518  CHECK(ee_dtable.getTempDispls()[1][2] == Approx(-0.2));
519  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.908607914));
520  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.9));
521  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.2));
522  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(-0.1));
523  electrons.rejectMove(0);
524 
525  electrons.makeMove(0, disp);
526  CHECK(ee_dtable.getTempDists()[1] == Approx(2.7239676944));
527  CHECK(ee_dtable.getTempDispls()[1][0] == Approx(2.7));
528  CHECK(ee_dtable.getTempDispls()[1][1] == Approx(-0.3));
529  CHECK(ee_dtable.getTempDispls()[1][2] == Approx(-0.2));
530  CHECK(ee_dtable.getOldDists()[1] == Approx(2.908607914));
531  CHECK(ee_dtable.getOldDispls()[1][0] == Approx(2.9));
532  CHECK(ee_dtable.getOldDispls()[1][1] == Approx(-0.2));
533  CHECK(ee_dtable.getOldDispls()[1][2] == Approx(0.1));
534  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.908607914));
535  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.9));
536  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.2));
537  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(-0.1));
538  electrons.acceptMove(0);
539 
540  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.7239676944));
541  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.7));
542  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.3));
543  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(0.2));
544 
545  // revert previous move
546  electrons.makeMove(0, -disp);
547  electrons.acceptMove(0);
548 
549  // test forward mode
550  electrons.makeMove(0, disp);
551  electrons.accept_rejectMove(0, true, true);
552 
553  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.908607914));
554  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.9));
555  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.2));
556  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(-0.1));
557 
558  electrons.makeMove(1, disp);
559  electrons.accept_rejectMove(1, false, true);
560  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.7239676944));
561  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.7));
562  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.3));
563  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(0.2));
564 } // TEST_CASE distance_pbc_z
565 
567 {
568  // test that particle distances are properly calculated under periodic boundary condition
569  // There are many details in this example, but the main idea is simple: When a particle is moved by a full lattice vector, no distance should change.
570 
571  const SimulationCell simulation_cell(parse_pbc_lattice());
572  ParticleSet ions(simulation_cell), electrons(simulation_cell, test_kind);
573  parse_electron_ion_pbc_z(ions, electrons);
574 
575  // calculate particle distances
576  ions.update();
577  const int ee_tid = electrons.addTable(electrons, DTModes::NEED_FULL_TABLE_ON_HOST_AFTER_DONEPBYP);
578  // get target particle set's distance table data
579  const auto& ee_dtable = electrons.getDistTableAA(ee_tid);
580  CHECK(ee_dtable.getName() == "e_e");
581  electrons.update();
582 
583  // shift electron 0 a bit to avoid box edges.
584  ParticleSet::SingleParticlePos shift(0.1, 0.2, -0.1);
585  electrons.makeMove(0, shift);
586  electrons.accept_rejectMove(0, true, false);
587  electrons.donePbyP();
588 
589  ParticleSet electrons_clone(electrons);
590  RefVectorWithLeader<ParticleSet> p_list(electrons);
591  p_list.push_back(electrons);
592  p_list.push_back(electrons_clone);
593 
594  ResourceCollection pset_res("test_pset_res");
595  electrons.createResource(pset_res);
596  ResourceCollectionTeamLock<ParticleSet> mw_pset_lock(pset_res, p_list);
597 
598  std::vector<ParticleSet::SingleParticlePos> disp{{0.2, 0.1, 0.3}, {0.2, 0.1, 0.3}};
599 
600  ParticleSet::mw_makeMove(p_list, 0, disp);
601  ParticleSet::mw_accept_rejectMove(p_list, 0, {true, true}, true);
602  ParticleSet::mw_makeMove(p_list, 1, disp);
603  ParticleSet::mw_accept_rejectMove(p_list, 1, {false, false}, true);
604 
605  ParticleSet::mw_donePbyP(p_list);
606  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.7239676944));
607  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.7));
608  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.3));
609  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(0.2));
610 } // test_distance_pbc_z_batched_APIs
611 
613 {
614  // test that particle distances are properly calculated under periodic boundary condition
615  // There are many details in this example, but the main idea is simple: When a particle is moved by a full lattice vector, no distance should change.
616 
617  const SimulationCell simulation_cell(parse_pbc_fcc_lattice());
618  ParticleSet ions(simulation_cell), electrons(simulation_cell, test_kind);
619  parse_electron_ion_pbc_z(ions, electrons);
620 
621  // calculate particle distances
622  ions.update();
623  const int ee_tid = electrons.addTable(electrons, DTModes::NEED_FULL_TABLE_ON_HOST_AFTER_DONEPBYP);
624  // get target particle set's distance table data
625  const auto& ee_dtable = electrons.getDistTableAA(ee_tid);
626  CHECK(ee_dtable.getName() == "e_e");
627  electrons.update();
628 
629  // shift electron 0 a bit to avoid box edges.
630  ParticleSet::SingleParticlePos shift(0.1, 0.2, -0.1);
631  electrons.makeMove(0, shift);
632  electrons.accept_rejectMove(0, true, false);
633  electrons.donePbyP();
634 
635  ParticleSet electrons_clone(electrons);
636  RefVectorWithLeader<ParticleSet> p_list(electrons);
637  p_list.push_back(electrons);
638  p_list.push_back(electrons_clone);
639 
640  ResourceCollection pset_res("test_pset_res");
641  electrons.createResource(pset_res);
642  ResourceCollectionTeamLock<ParticleSet> mw_pset_lock(pset_res, p_list);
643 
644  std::vector<ParticleSet::SingleParticlePos> disp{{0.2, 0.1, 0.3}, {0.2, 0.1, 0.3}};
645 
646  ParticleSet::mw_makeMove(p_list, 0, disp);
647  ParticleSet::mw_accept_rejectMove(p_list, 0, {true, true}, true);
648  ParticleSet::mw_makeMove(p_list, 1, disp);
649  ParticleSet::mw_accept_rejectMove(p_list, 1, {false, false}, true);
650 
651  ParticleSet::mw_donePbyP(p_list);
652  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.7239676944));
653  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.7));
654  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.3));
655  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(0.2));
656 } // test_distance_pbc_z_batched_APIs
657 
658 TEST_CASE("distance_pbc_z batched APIs", "[distance_table][xml]")
659 {
664 }
665 
667 {
668  // test that particle distances are properly calculated under periodic boundary condition
669  // There are many details in this example, but the main idea is simple: When a particle is moved by a full lattice vector, no distance should change.
670 
671  const SimulationCell simulation_cell(parse_pbc_lattice());
672  ParticleSet ions(simulation_cell), electrons(simulation_cell, test_kind);
673  parse_electron_ion_pbc_z(ions, electrons);
674 
675  // calculate particle distances
676  ions.update();
677  const int ee_tid = electrons.addTable(electrons, DTModes::NEED_TEMP_DATA_ON_HOST);
678  // get target particle set's distance table data
679  const auto& ee_dtable = electrons.getDistTableAA(ee_tid);
680  CHECK(ee_dtable.getName() == "e_e");
681  electrons.update();
682 
683  // shift electron 0 a bit to avoid box edges.
684  ParticleSet::SingleParticlePos shift(0.1, 0.2, -0.1);
685  electrons.makeMove(0, shift);
686  electrons.accept_rejectMove(0, true, false);
687  electrons.donePbyP();
688 
689  ParticleSet electrons_clone(electrons);
690  RefVectorWithLeader<ParticleSet> p_list(electrons);
691  p_list.push_back(electrons);
692  p_list.push_back(electrons_clone);
693 
694  ResourceCollection pset_res("test_pset_res");
695  electrons.createResource(pset_res);
696  ResourceCollectionTeamLock<ParticleSet> mw_pset_lock(pset_res, p_list);
697 
698  std::vector<ParticleSet::SingleParticlePos> disp{{0.2, 0.1, 0.3}, {0.2, 0.1, 0.3}};
699 
700  ParticleSet::mw_makeMove(p_list, 0, disp);
701  CHECK(ee_dtable.getTempDists()[1] == Approx(2.7239676944));
702  CHECK(ee_dtable.getTempDispls()[1][0] == Approx(2.7));
703  CHECK(ee_dtable.getTempDispls()[1][1] == Approx(-0.3));
704  CHECK(ee_dtable.getTempDispls()[1][2] == Approx(-0.2));
705  CHECK(ee_dtable.getOldDists()[1] == Approx(2.908607914));
706  CHECK(ee_dtable.getOldDispls()[1][0] == Approx(2.9));
707  CHECK(ee_dtable.getOldDispls()[1][1] == Approx(-0.2));
708  CHECK(ee_dtable.getOldDispls()[1][2] == Approx(0.1));
709  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.908607914));
710  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.9));
711  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.2));
712  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(-0.1));
713  ParticleSet::mw_accept_rejectMove(p_list, 0, {true, true}, true);
714 
715  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.908607914));
716  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.9));
717  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.2));
718  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(-0.1));
719 
720  ParticleSet::mw_makeMove(p_list, 1, disp);
721  ParticleSet::mw_accept_rejectMove(p_list, 1, {false, false}, true);
722  CHECK(ee_dtable.getDistRow(1)[0] == Approx(2.7239676944));
723  CHECK(ee_dtable.getDisplRow(1)[0][0] == Approx(-2.7));
724  CHECK(ee_dtable.getDisplRow(1)[0][1] == Approx(0.3));
725  CHECK(ee_dtable.getDisplRow(1)[0][2] == Approx(0.2));
726 } // test_distance_pbc_z_batched_APIs_ee_NEED_TEMP_DATA_ON_HOST
727 
728 TEST_CASE("distance_pbc_z batched APIs ee NEED_TEMP_DATA_ON_HOST", "[distance_table][xml]")
729 {
732 }
733 
734 TEST_CASE("test_distance_pbc_diamond", "[distance_table][xml]")
735 {
737 
738  auto& ions = *pset_pool.getParticleSet("ion");
739  auto& elecs = *pset_pool.getParticleSet("e");
740 
741  ions.addTable(ions);
742  ions.update();
743  elecs.addTable(ions);
744  elecs.addTable(elecs);
745  elecs.update();
746 }
747 } // namespace qmcplusplus
a class that defines a supercell in D-dimensional Euclean space.
void test_distance_pbc_z_batched_APIs(DynamicCoordinateKind test_kind)
DynamicCoordinateKind
enumerator for DynamicCoordinates kinds
class that handles xmlDoc
Definition: Libxml2Doc.h:76
const std::string & getName() const
return the name
static void mw_makeMove(const RefVectorWithLeader< ParticleSet > &p_list, int iat, const MCCoords< CT > &displs)
batched version of makeMove
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
const DistanceTableAA & getDistTableAA(int table_ID) const
get a distance table by table_ID and dyanmic_cast to DistanceTableAA
void test_distance_pbc_z_batched_APIs_ee_NEED_TEMP_DATA_ON_HOST(DynamicCoordinateKind test_kind)
size_t getTotalNum() const
Definition: ParticleSet.h:493
std::ostream & app_log()
Definition: OutputManager.h:65
bool put(xmlNodePtr cur)
Definition: LatticeIO.cpp:32
static ParticleSetPool make_diamondC_1x1x1(Communicate *c)
TEST_CASE("complex_helper", "[type_traits]")
xmlNodePtr getRoot()
Definition: Libxml2Doc.h:88
void createResource(ResourceCollection &collection) const
initialize a shared resource and hand it to a collection
SimulationCell parse_pbc_lattice()
void update(bool skipSK=false)
update the internal data
Communicate * Controller
Global Communicator for a process.
Definition: Communicate.cpp:35
static void mw_accept_rejectMove(const RefVectorWithLeader< ParticleSet > &p_list, Index_t iat, const std::vector< bool > &isAccepted, bool forward_mode=true)
batched version of acceptMove and rejectMove fused, templated on CoordsType
ParticleIndex GroupID
Species ID.
Definition: ParticleSet.h:77
const DistanceTableAB & getDistTableAB(int table_ID) const
get a distance table by table_ID and dyanmic_cast to DistanceTableAB
MakeReturn< BinaryNode< FnPow, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t, typename CreateLeaf< Vector< T2, C2 > >::Leaf_t > >::Expression_t pow(const Vector< T1, C1 > &l, const Vector< T2, C2 > &r)
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 test_distance_fcc_pbc_z_batched_APIs(DynamicCoordinateKind test_kind)
REQUIRE(std::filesystem::exists(filename))
void rejectMove(Index_t iat)
reject a proposed move in regular mode
void accept_rejectMove(Index_t iat, bool accepted, bool forward_mode=true)
accept or reject a proposed move Two operation modes: The using and updating distance tables via Part...
bool readXML(xmlNodePtr cur)
process xmlnode <particleset/> which contains everything about the particle set to initialize ...
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
SimulationCell parse_pbc_fcc_lattice()
MakeReturn< UnaryNode< FnSqrt, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sqrt(const Vector< T1, C1 > &l)
void makeMove(Index_t iat, const SingleParticlePos &displ, bool maybe_accept=true)
move the iat-th particle to active_pos_
bool parseFromString(const std::string_view data)
Definition: Libxml2Doc.cpp:204
CHECK(log_values[0]==ComplexApprox(std::complex< double >{ 5.603777579195571, -6.1586603331188225 }))
static void mw_donePbyP(const RefVectorWithLeader< ParticleSet > &p_list, bool skipSK=false)
batched version of donePbyP
handles acquire/release resource by the consumer (RefVectorWithLeader type).
void parse_electron_ion_pbc_z(ParticleSet &ions, ParticleSet &electrons)
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
void acceptMove(Index_t iat)
accept the move and update the particle attribute by the proposed move in regular mode ...
whether full table needs to be ready at anytime or not after donePbyP Optimization can be implemented...
void donePbyP(bool skipSK=false)
update structure factor and unmark active_ptcl_
whether temporary data set on the host is updated or not when a move is proposed. ...