pairinteraction
A Rydberg Interaction Calculator
BasisAtomCreator.test.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2024 Pairinteraction Developers
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
5
15
16#include <doctest/doctest.h>
17
18namespace pairinteraction {
19
20constexpr double VOLT_PER_CM_IN_ATOMIC_UNITS = 1 / 5.14220675112e9;
21
22DOCTEST_TEST_CASE("create a basis for strontium 88") {
24 auto basis = BasisAtomCreator<double>()
25 .set_species("Sr88_singlet")
26 .restrict_quantum_number_n(60, 60)
27 .restrict_quantum_number_l(0, 2)
28 .create(database);
29 for (const auto &ket : *basis) {
30 DOCTEST_CHECK(ket->get_species() == "Sr88_singlet");
31 DOCTEST_MESSAGE("Ket: ", *ket);
32 }
33}
34
35DOCTEST_TEST_CASE("create a basis for strontium 87") {
37 auto basis = BasisAtomCreator<double>()
38 .set_species("Sr87_mqdt")
39 .restrict_quantum_number_nu(59, 61)
40 .restrict_quantum_number_l(0, 0)
41 .create(database);
42 for (const auto &ket : *basis) {
43 DOCTEST_CHECK(ket->get_species() == "Sr87_mqdt");
44 DOCTEST_MESSAGE("Ket: ", *ket);
45 }
46}
47
48DOCTEST_TEST_CASE("create a basis from kets") {
50 auto ket1 = KetAtomCreator("Sr88_singlet", 59, 0, 0, 0).create(database);
51 auto ket2 = KetAtomCreator("Sr88_singlet", 60, 0, 0, 0).create(database);
52 auto ket3 = KetAtomCreator("Sr88_singlet", 61, 0, 0, 0).create(database);
53 auto basis =
54 BasisAtomCreator<double>().append_ket(ket1).append_ket(ket2).append_ket(ket3).create(
55 database);
56 for (const auto &ket : *basis) {
57 DOCTEST_CHECK(ket->get_species() == "Sr88_singlet");
58 DOCTEST_MESSAGE("Ket: ", *ket);
59 }
60}
61
62DOCTEST_TEST_CASE("create a basis and sort it according to parity and m") {
64 auto basis_unsorted = BasisAtomCreator<double>()
65 .set_species("Rb")
66 .restrict_quantum_number_n(60, 60)
67 .restrict_quantum_number_l(0, 3)
68 .restrict_quantum_number_m(-0.5, 0.5)
69 .create(database);
70
71 // Sort the basis by parity and the m quantum number
72 auto sorter = basis_unsorted->get_sorter(
74 auto basis = basis_unsorted->transformed(sorter);
75
76 // Check if the basis is properly sorted
77 auto parity = Parity::ODD;
78 auto quantum_number_m = std::numeric_limits<double>::lowest();
79 for (size_t i = 0; i < basis->get_number_of_states(); ++i) {
80 DOCTEST_MESSAGE("State ", i, ": Parity = ", basis->get_parity(i),
81 ", M = ", basis->get_quantum_number_m(i));
82 DOCTEST_CHECK(basis->get_parity(i) >= parity);
83 if (basis->get_parity(i) != parity) {
84 parity = basis->get_parity(i);
85 quantum_number_m = std::numeric_limits<double>::lowest();
86 }
87 DOCTEST_CHECK(basis->get_quantum_number_m(i) >= quantum_number_m);
88 quantum_number_m = basis->get_quantum_number_m(i);
89 }
90
91 // Check that the blocks are correctly determined
92 auto blocks = basis->get_indices_of_blocks(
94 std::vector<size_t> expected_start = {0, 4, 8, 11};
95
96 DOCTEST_CHECK(blocks.size() == expected_start.size());
97
98 size_t idx = 0;
99 for (const auto &block : blocks) {
100 DOCTEST_MESSAGE("Block ", idx, " starts at ", block.start);
101 DOCTEST_CHECK(block.start == expected_start[idx]);
102 idx++;
103 }
104
105 // Test implicit conversion of an eigen matrix to a transformator
106 size_t dim = basis->get_number_of_states();
107 Eigen::SparseMatrix<double, Eigen::RowMajor> matrix(static_cast<long>(dim),
108 static_cast<long>(dim));
109 matrix.setIdentity();
110 auto transformed = basis->transformed(matrix);
111 auto transformation = transformed->get_transformation();
112 DOCTEST_CHECK(transformation.transformation_type.back() == TransformationType::ARBITRARY);
113}
114
115DOCTEST_TEST_CASE("calculation of matrix elements") {
116 auto &database = Database::get_global_instance();
117
118 auto ket_s = KetAtomCreator()
119 .set_species("Rb")
124 .create(database);
125
126 auto ket_p = KetAtomCreator()
127 .set_species("Rb")
132 .create(database);
133
134 auto basis = BasisAtomCreator<double>()
135 .set_species("Rb")
136 .restrict_quantum_number_n(59, 61)
137 .restrict_quantum_number_l(0, 1)
138 .restrict_quantum_number_m(0.5, 0.5)
139 .create(database);
140
141 SystemAtom<double> system(basis);
142
143 DOCTEST_SUBCASE("calculate energy") {
144 auto m1 = basis->get_canonical_state_from_ket(ket_s)->get_matrix_elements(
145 ket_s, OperatorType::ENERGY, 0);
146 DOCTEST_CHECK(m1.size() == 1);
147 double energy1 = m1[0];
148
149 auto m2 = basis->get_matrix_elements(ket_s, OperatorType::ENERGY, 0);
150 DOCTEST_CHECK(m2.size() == basis->get_number_of_states());
151 double energy2 = m2[static_cast<int>(basis->get_corresponding_state_index(ket_s))];
152
153 double reference = ket_s->get_energy();
154 DOCTEST_CHECK(std::abs(energy1 - reference) < 1e-11);
155 DOCTEST_CHECK(std::abs(energy2 - reference) < 1e-11);
156 }
157
158 DOCTEST_SUBCASE("calculate electric dipole matrix element") {
159 auto m = basis->get_matrix_elements(ket_p, OperatorType::ELECTRIC_DIPOLE, 0);
160 DOCTEST_CHECK(m.size() == basis->get_number_of_states());
161 double dipole = m[static_cast<int>(basis->get_corresponding_state_index(ket_s))];
162
163 DOCTEST_CHECK(std::abs(dipole - 1247.5985544327215848) < 1e-6);
164 }
165
166 DOCTEST_SUBCASE("calculate electric dipole matrix element with and without an induced dipole") {
167 {
168 auto state = basis->get_corresponding_state(ket_s);
169
170 auto m = state->get_matrix_elements(state, OperatorType::ELECTRIC_DIPOLE, 0);
171 DOCTEST_CHECK(m.rows() == 1);
172 DOCTEST_CHECK(m.cols() == 1);
173 double dipole = m.coeff(0, 0);
174
175 DOCTEST_CHECK(std::abs(dipole - 0) < 1e-6);
176 }
177
178 {
181 auto state = system.get_eigenbasis()->get_corresponding_state(ket_s);
182
183 auto m = state->get_matrix_elements(state, OperatorType::ELECTRIC_DIPOLE, 0);
184 DOCTEST_CHECK(m.rows() == 1);
185 DOCTEST_CHECK(m.cols() == 1);
186 double dipole = m.coeff(0, 0);
187
188 DOCTEST_CHECK(std::abs(dipole - 135.01903532588247003) < 1e-6);
189 }
190 }
191}
192
193} // namespace pairinteraction
Builder class for creating BasisAtom objects.
BasisAtomCreator< Scalar > & append_ket(const std::shared_ptr< const ket_t > &ket)
BasisAtomCreator< Scalar > & set_species(const std::string &value)
static Database & get_global_instance()
Definition: Database.cpp:1068
Builder class for creating KetAtom objects.
KetAtomCreator & set_quantum_number_n(int value)
std::shared_ptr< const KetAtom > create(Database &database) const
KetAtomCreator & set_quantum_number_j(double value)
KetAtomCreator & set_quantum_number_l(double value)
KetAtomCreator & set_species(const std::string &value)
KetAtomCreator & set_quantum_number_m(double value)
Type & set_electric_field(const std::array< real_t, 3 > &field)
Definition: SystemAtom.cpp:26
System< Derived > & diagonalize(const DiagonalizerInterface< scalar_t > &diagonalizer, std::optional< real_t > min_eigenenergy={}, std::optional< real_t > max_eigenenergy={}, double rtol=1e-6)
Definition: System.cpp:184
std::shared_ptr< const basis_t > get_eigenbasis() const
Definition: System.cpp:85
DOCTEST_TEST_CASE("create a basis for strontium 88")
constexpr double VOLT_PER_CM_IN_ATOMIC_UNITS