1 #include "catch.hpp"
2 #include <libint2/atom.h>
3 
4 using libint2::Atom;
5 using libint2::constants::codata_2014;
6 using libint2::constants::codata_2018;
7 
8 TEST_CASE("XYZ reader", "[util]") {
9   { // fewer atoms than #atoms is not OK
10     std::stringstream sstr;
11     sstr << "2\n\nO 0 0 0\n";
12     REQUIRE_THROWS_AS(libint2::read_dotxyz(sstr), std::logic_error);
13   }
14   { // fewer atoms than #atoms+#axes is not OK
15     std::stringstream sstr;
16     sstr << "2\n\nO 0 0 0\nO 0 0 1\nAA 0 0 0\nBB 0 0 0\n";
17     REQUIRE_THROWS_AS(libint2::read_dotxyz_pbc(sstr), std::logic_error);
18   }
19   { // bad element symbol is not OK
20     std::stringstream sstr;
21     sstr << "2\n\nO 0 0 0\nZ 0 0 0\n";
22     REQUIRE_THROWS_AS(libint2::read_dotxyz(sstr), std::logic_error);
23   }
24   { // bad element symbol is not OK
25     std::stringstream sstr;
26     sstr << "2\n\n0 0 0 0\nO 0 0 0\n";
27     REQUIRE_THROWS_AS(libint2::read_dotxyz(sstr), std::logic_error);
28   }
29   { // duplicate cell parameters are not OK
30     std::stringstream sstr;
31     sstr << "2\n\nO 0 0 0\nO 0 0 1\nAA 2 0 0\nAA 0 2 0\nCC 0 0 2\n";
32     REQUIRE_THROWS_AS(libint2::read_dotxyz_pbc(sstr), std::logic_error);
33   }
34   { // missing cell parameters are not OK
35     // not enough entries
36     std::stringstream sstr1;
37     sstr1 << "2\n\nO 0 0 0\nO 0 0 1\nAA 2 0 0\nCC 0 0 2\n";
38     REQUIRE_THROWS_AS(libint2::read_dotxyz_pbc(sstr1), std::logic_error);
39     // or too many atoms
40     std::stringstream sstr2;
41     sstr2 << "2\n\nO 0 0 0\nO 0 0 1\nO 0 0 3\nAA 2 0 0\nCC 0 0 2\n";
42     REQUIRE_THROWS_AS(libint2::read_dotxyz_pbc(sstr2), std::logic_error);
43   }
44   { // more atoms than #atoms is OK
45     std::stringstream sstr;
46     sstr << "2\n\nO 0 0 0\nO 0 0 0\nO 0 0 0\n";
47     REQUIRE_NOTHROW(libint2::read_dotxyz(sstr));
48   }
49   { // PBC input is OK as molecular input
50     std::stringstream sstr;
51     sstr << "2\n\nO 0 0 0\nO 0 0 1\nAA 2 0 0\nBB 0 2 0\nCC 0 0 2\n";
52     REQUIRE_NOTHROW(libint2::read_dotxyz(sstr));
53   }
54   { // validate results
55     std::stringstream sstr;
56     sstr << "2\n\nO 0 0 0\nO 0 0 1\n";
57     auto atoms = libint2::read_dotxyz(sstr);
58     const auto angstrom_to_bohr = 1 / codata_2018::bohr_to_angstrom;
59     REQUIRE(atoms.size() == 2);
60     REQUIRE(atoms[0] == Atom{8, 0., 0., 0.});
61     REQUIRE(atoms[1] == Atom{8, 0., 0., 1. * angstrom_to_bohr});
62   }
63   { // validate use of conversion factor
64     std::stringstream sstr;
65     sstr << "2\n\nO 0 0 0\nO 0 0 1\n";
66     auto atoms = libint2::read_dotxyz(sstr, codata_2014::bohr_to_angstrom);
67     const auto angstrom_to_bohr = 1 / codata_2014::bohr_to_angstrom;
68     REQUIRE(atoms.size() == 2);
69     REQUIRE(atoms[0] == Atom{8, 0., 0., 0.});
70     REQUIRE(atoms[1] == Atom{8, 0., 0., 1. * angstrom_to_bohr});
71   }
72   { // validate PBS results
73     std::stringstream sstr;
74     sstr << "2\n\nO 0 0 0\nO 0 0 1\nCC 0 0 4\nBB 0 3 0\nAA 2 0 0\n"; // axes can be out of order
75     std::vector<Atom> atoms;
76     std::array<std::array<double, 3>, 3> cell;
77     std::tie(atoms, cell) = libint2::read_dotxyz_pbc(sstr);
78     const auto angstrom_to_bohr = 1 / codata_2018::bohr_to_angstrom;
79     REQUIRE(atoms.size() == 2);
80     REQUIRE(atoms[0] == Atom{8, 0., 0., 0.});
81     REQUIRE(atoms[1] == Atom{8, 0., 0., 1. * angstrom_to_bohr});
82     REQUIRE(cell[0] ==
83             std::array<double, 3>{2. * angstrom_to_bohr, 0., 0.});
84     REQUIRE(cell[1] ==
85             std::array<double, 3>{0., 3. * angstrom_to_bohr, 0.});
86     REQUIRE(cell[2] ==
87             std::array<double, 3>{0., 0., 4. * angstrom_to_bohr});
88   }
89 }
90