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