Line data Source code
1 : // SPDX-FileCopyrightText: 2024 Pairinteraction Developers
2 : // SPDX-License-Identifier: LGPL-3.0-or-later
3 :
4 : #include "pairinteraction/ket/KetAtom.hpp"
5 :
6 : #include "pairinteraction/enums/Parity.hpp"
7 : #include "pairinteraction/utils/hash.hpp"
8 :
9 : #include <array>
10 : #include <cctype>
11 : #include <cmath>
12 : #include <fmt/core.h>
13 : #include <string>
14 : #include <string_view>
15 : #include <vector>
16 :
17 : namespace pairinteraction {
18 :
19 : constexpr std::array<std::string_view, 6> quantum_number_l_labels = {"S", "P", "D", "F", "G", "H"};
20 :
21 1217 : KetAtom::KetAtom(Private /*unused*/, double energy, double f, double m, Parity p,
22 : std::string species, int n, double nu, double nui_exp, double nui_std,
23 : double l_exp, double l_std, double s_exp, double s_std, double j_exp, double j_std,
24 : double l_ryd_exp, double l_ryd_std, double j_ryd_exp, double j_ryd_std,
25 : bool is_j_total_momentum, bool is_calculated_with_mqdt,
26 : double underspecified_channel_contribution, Database &database,
27 1217 : size_t id_in_database)
28 1217 : : Ket(energy, f, m, p), species(std::move(species)), quantum_number_n(n), quantum_number_nu(nu),
29 1217 : quantum_number_nui_exp(nui_exp), quantum_number_nui_std(nui_std), quantum_number_l_exp(l_exp),
30 1217 : quantum_number_l_std(l_std), quantum_number_s_exp(s_exp), quantum_number_s_std(s_std),
31 1217 : quantum_number_j_exp(j_exp), quantum_number_j_std(j_std), quantum_number_l_ryd_exp(l_ryd_exp),
32 1217 : quantum_number_l_ryd_std(l_ryd_std), quantum_number_j_ryd_exp(j_ryd_exp),
33 1217 : quantum_number_j_ryd_std(j_ryd_std), is_j_total_momentum_(is_j_total_momentum),
34 1217 : is_calculated_with_mqdt_(is_calculated_with_mqdt),
35 1217 : underspecified_channel_contribution(underspecified_channel_contribution), database(database),
36 1217 : id_in_database(id_in_database) {}
37 :
38 0 : Database &KetAtom::get_database() const { return database; }
39 :
40 1194 : size_t KetAtom::get_id_in_database() const { return id_in_database; }
41 :
42 209 : std::string KetAtom::get_label() const {
43 209 : size_t pos = species.find('_');
44 209 : std::string label = (pos != std::string::npos) ? species.substr(0, pos) : species;
45 209 : label[0] = static_cast<char>(std::toupper(label[0]));
46 :
47 209 : if (!is_calculated_with_mqdt_) {
48 153 : if (quantum_number_s_exp == 0) {
49 13 : label += "_singlet";
50 140 : } else if (quantum_number_s_exp == 1) {
51 0 : label += "_triplet";
52 140 : } else if (quantum_number_s_exp != 0.5) {
53 0 : throw std::runtime_error(
54 0 : "Invalid value for quantum number s in the single-channel description.");
55 : }
56 : }
57 :
58 209 : label += ":";
59 :
60 209 : if (is_calculated_with_mqdt_) {
61 56 : label += fmt::format("S={:.1f},nu={:.1f},L={:.1f},", quantum_number_s_exp,
62 112 : quantum_number_nu, quantum_number_l_exp);
63 56 : label += this->is_j_total_momentum_ ? "J=" : "F=";
64 : } else {
65 306 : label += fmt::format("{:d},", quantum_number_n);
66 153 : if (quantum_number_l_exp == std::rint(quantum_number_l_exp) &&
67 153 : quantum_number_l_exp < quantum_number_l_labels.size()) {
68 153 : label += quantum_number_l_labels.at(static_cast<size_t>(quantum_number_l_exp));
69 : } else {
70 0 : label += fmt::format("{:.0f}", quantum_number_l_exp);
71 : }
72 153 : label += "_";
73 : }
74 :
75 209 : double total_momentum =
76 209 : this->is_j_total_momentum_ ? this->quantum_number_j_exp : this->quantum_number_f;
77 209 : if (total_momentum == std::rint(total_momentum)) {
78 13 : label += fmt::format("{:.0f}", total_momentum);
79 196 : } else if (2 * total_momentum == std::rint(2 * total_momentum)) {
80 392 : label += fmt::format("{:.0f}/2", 2 * total_momentum);
81 : } else {
82 0 : std::abort(); // can't happen because the total momentum is validated to be an integer
83 : // or half-integer
84 : }
85 :
86 209 : if (this->quantum_number_m == std::rint(this->quantum_number_m)) {
87 26 : label += fmt::format(",{:.0f}", this->quantum_number_m);
88 196 : } else if (2 * this->quantum_number_m == std::rint(2 * this->quantum_number_m)) {
89 392 : label += fmt::format(",{:.0f}/2", 2 * this->quantum_number_m);
90 : } else {
91 0 : std::abort(); // can't happen because the quantum number m is validated to be an integer
92 : // or half-integer
93 : }
94 :
95 418 : return label;
96 0 : }
97 :
98 : std::shared_ptr<KetAtom>
99 0 : KetAtom::get_ket_for_different_quantum_number_m(double new_quantum_number_m) const {
100 0 : auto ket = *this;
101 0 : ket.quantum_number_m = new_quantum_number_m;
102 0 : return std::make_shared<KetAtom>(ket);
103 0 : }
104 :
105 137 : const std::string &KetAtom::get_species() const { return species; }
106 :
107 4 : int KetAtom::get_quantum_number_n() const { return quantum_number_n; }
108 :
109 0 : double KetAtom::get_quantum_number_nu() const { return quantum_number_nu; }
110 :
111 0 : double KetAtom::get_quantum_number_nui() const { return quantum_number_nui_exp; }
112 :
113 3 : double KetAtom::get_quantum_number_l() const { return quantum_number_l_exp; }
114 :
115 1 : double KetAtom::get_quantum_number_s() const { return quantum_number_s_exp; }
116 :
117 1 : double KetAtom::get_quantum_number_j() const { return quantum_number_j_exp; }
118 :
119 0 : double KetAtom::get_quantum_number_l_ryd() const { return quantum_number_l_ryd_exp; }
120 :
121 0 : double KetAtom::get_quantum_number_j_ryd() const { return quantum_number_j_ryd_exp; }
122 :
123 0 : double KetAtom::get_quantum_number_nui_std() const { return quantum_number_nui_std; }
124 :
125 0 : double KetAtom::get_quantum_number_l_std() const { return quantum_number_l_std; }
126 :
127 0 : double KetAtom::get_quantum_number_s_std() const { return quantum_number_s_std; }
128 :
129 0 : double KetAtom::get_quantum_number_j_std() const { return quantum_number_j_std; }
130 :
131 0 : double KetAtom::get_quantum_number_l_ryd_std() const { return quantum_number_l_ryd_std; }
132 :
133 0 : double KetAtom::get_quantum_number_j_ryd_std() const { return quantum_number_j_ryd_std; }
134 :
135 0 : bool KetAtom::is_j_total_momentum() const { return is_j_total_momentum_; }
136 :
137 0 : bool KetAtom::is_calculated_with_mqdt() const { return is_calculated_with_mqdt_; }
138 :
139 0 : double KetAtom::get_underspecified_channel_contribution() const {
140 0 : return underspecified_channel_contribution;
141 : }
142 :
143 68 : bool KetAtom::operator==(const KetAtom &other) const {
144 135 : return Ket::operator==(other) && species == other.species &&
145 67 : quantum_number_n == other.quantum_number_n &&
146 67 : quantum_number_nu == other.quantum_number_nu &&
147 67 : quantum_number_nui_exp == other.quantum_number_nui_exp &&
148 67 : quantum_number_nui_std == other.quantum_number_nui_std &&
149 67 : quantum_number_l_exp == other.quantum_number_l_exp &&
150 67 : quantum_number_l_std == other.quantum_number_l_std &&
151 67 : quantum_number_s_exp == other.quantum_number_s_exp &&
152 67 : quantum_number_s_std == other.quantum_number_s_std &&
153 202 : quantum_number_j_exp == other.quantum_number_j_exp &&
154 135 : quantum_number_j_std == other.quantum_number_j_std;
155 : }
156 :
157 1 : bool KetAtom::operator!=(const KetAtom &other) const { return !(*this == other); }
158 :
159 1253 : size_t KetAtom::hash::operator()(const KetAtom &k) const {
160 1253 : size_t seed = typename Ket::hash()(k);
161 1253 : utils::hash_combine(seed, k.species);
162 1253 : utils::hash_combine(seed, k.quantum_number_n);
163 1253 : utils::hash_combine(seed, k.quantum_number_nu);
164 1253 : utils::hash_combine(seed, k.quantum_number_nui_exp);
165 1253 : utils::hash_combine(seed, k.quantum_number_nui_std);
166 1253 : utils::hash_combine(seed, k.quantum_number_l_exp);
167 1253 : utils::hash_combine(seed, k.quantum_number_l_std);
168 1253 : utils::hash_combine(seed, k.quantum_number_s_exp);
169 1253 : utils::hash_combine(seed, k.quantum_number_s_std);
170 1253 : utils::hash_combine(seed, k.quantum_number_j_exp);
171 1253 : utils::hash_combine(seed, k.quantum_number_j_std);
172 1253 : return seed;
173 : }
174 :
175 : } // namespace pairinteraction
|