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 11453 : 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 11453 : size_t id_in_database)
28 11453 : : Ket(energy, f, m, p), species(std::move(species)), quantum_number_n(n), quantum_number_nu(nu),
29 11453 : quantum_number_nui_exp(nui_exp), quantum_number_nui_std(nui_std), quantum_number_l_exp(l_exp),
30 11453 : quantum_number_l_std(l_std), quantum_number_s_exp(s_exp), quantum_number_s_std(s_std),
31 11453 : quantum_number_j_exp(j_exp), quantum_number_j_std(j_std), quantum_number_l_ryd_exp(l_ryd_exp),
32 11453 : quantum_number_l_ryd_std(l_ryd_std), quantum_number_j_ryd_exp(j_ryd_exp),
33 11453 : quantum_number_j_ryd_std(j_ryd_std), is_j_total_momentum_(is_j_total_momentum),
34 11453 : is_calculated_with_mqdt_(is_calculated_with_mqdt),
35 11453 : underspecified_channel_contribution(underspecified_channel_contribution), database(database),
36 11453 : id_in_database(id_in_database) {}
37 :
38 0 : Database &KetAtom::get_database() const { return database; }
39 :
40 11332 : size_t KetAtom::get_id_in_database() const { return id_in_database; }
41 :
42 259 : std::string KetAtom::get_label() const {
43 259 : size_t pos = species.find('_');
44 259 : std::string label = (pos != std::string::npos) ? species.substr(0, pos) : species;
45 259 : label[0] = static_cast<char>(std::toupper(label[0]));
46 :
47 259 : if (!is_calculated_with_mqdt_) {
48 202 : if (quantum_number_s_exp == 0) {
49 13 : label += "_singlet";
50 189 : } else if (quantum_number_s_exp == 1) {
51 0 : label += "_triplet";
52 189 : } 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 259 : label += ":";
59 :
60 259 : if (is_calculated_with_mqdt_) {
61 57 : label += fmt::format("S={:.1f},nu={:.1f},L={:.1f},", quantum_number_s_exp,
62 114 : quantum_number_nu, quantum_number_l_exp);
63 57 : label += this->is_j_total_momentum_ ? "J=" : "F=";
64 : } else {
65 404 : label += fmt::format("{:d},", quantum_number_n);
66 202 : if (quantum_number_l_exp == std::rint(quantum_number_l_exp) &&
67 202 : quantum_number_l_exp < quantum_number_l_labels.size()) {
68 202 : 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 202 : label += "_";
73 : }
74 :
75 259 : if (this->quantum_number_f == std::rint(this->quantum_number_f)) {
76 28 : label += fmt::format("{:.0f}", this->quantum_number_f);
77 245 : } else if (2 * this->quantum_number_f == std::rint(2 * this->quantum_number_f)) {
78 490 : label += fmt::format("{:.0f}/2", 2 * this->quantum_number_f);
79 : } else {
80 0 : std::abort(); // can't happen because the total momentum is validated to be an integer
81 : // or half-integer
82 : }
83 :
84 259 : if (this->quantum_number_m == std::rint(this->quantum_number_m)) {
85 28 : label += fmt::format(",{:.0f}", this->quantum_number_m);
86 245 : } else if (2 * this->quantum_number_m == std::rint(2 * this->quantum_number_m)) {
87 490 : label += fmt::format(",{:.0f}/2", 2 * this->quantum_number_m);
88 : } else {
89 0 : std::abort(); // can't happen because the quantum number m is validated to be an integer
90 : // or half-integer
91 : }
92 :
93 259 : return label;
94 0 : }
95 :
96 : std::shared_ptr<KetAtom>
97 0 : KetAtom::get_ket_for_different_quantum_number_m(double new_quantum_number_m) const {
98 0 : auto ket = *this;
99 0 : ket.quantum_number_m = new_quantum_number_m;
100 0 : return std::make_shared<KetAtom>(ket);
101 0 : }
102 :
103 557 : const std::string &KetAtom::get_species() const { return species; }
104 :
105 62 : int KetAtom::get_quantum_number_n() const { return quantum_number_n; }
106 :
107 15 : double KetAtom::get_quantum_number_nu() const { return quantum_number_nu; }
108 :
109 0 : double KetAtom::get_quantum_number_nui() const { return quantum_number_nui_exp; }
110 :
111 73 : double KetAtom::get_quantum_number_l() const { return quantum_number_l_exp; }
112 :
113 11 : double KetAtom::get_quantum_number_s() const { return quantum_number_s_exp; }
114 :
115 3 : double KetAtom::get_quantum_number_j() const { return quantum_number_j_exp; }
116 :
117 0 : double KetAtom::get_quantum_number_l_ryd() const { return quantum_number_l_ryd_exp; }
118 :
119 0 : double KetAtom::get_quantum_number_j_ryd() const { return quantum_number_j_ryd_exp; }
120 :
121 0 : double KetAtom::get_quantum_number_nui_std() const { return quantum_number_nui_std; }
122 :
123 0 : double KetAtom::get_quantum_number_l_std() const { return quantum_number_l_std; }
124 :
125 0 : double KetAtom::get_quantum_number_s_std() const { return quantum_number_s_std; }
126 :
127 0 : double KetAtom::get_quantum_number_j_std() const { return quantum_number_j_std; }
128 :
129 0 : double KetAtom::get_quantum_number_l_ryd_std() const { return quantum_number_l_ryd_std; }
130 :
131 0 : double KetAtom::get_quantum_number_j_ryd_std() const { return quantum_number_j_ryd_std; }
132 :
133 0 : bool KetAtom::is_j_total_momentum() const { return is_j_total_momentum_; }
134 :
135 28 : bool KetAtom::is_calculated_with_mqdt() const { return is_calculated_with_mqdt_; }
136 :
137 0 : double KetAtom::get_underspecified_channel_contribution() const {
138 0 : return underspecified_channel_contribution;
139 : }
140 :
141 914 : bool KetAtom::operator==(const KetAtom &other) const {
142 1761 : return Ket::operator==(other) && species == other.species &&
143 847 : quantum_number_n == other.quantum_number_n &&
144 847 : quantum_number_nu == other.quantum_number_nu &&
145 847 : quantum_number_nui_exp == other.quantum_number_nui_exp &&
146 847 : quantum_number_nui_std == other.quantum_number_nui_std &&
147 847 : quantum_number_l_exp == other.quantum_number_l_exp &&
148 847 : quantum_number_l_std == other.quantum_number_l_std &&
149 847 : quantum_number_s_exp == other.quantum_number_s_exp &&
150 847 : quantum_number_s_std == other.quantum_number_s_std &&
151 2608 : quantum_number_j_exp == other.quantum_number_j_exp &&
152 1761 : quantum_number_j_std == other.quantum_number_j_std;
153 : }
154 :
155 1 : bool KetAtom::operator!=(const KetAtom &other) const { return !(*this == other); }
156 :
157 11903 : size_t KetAtom::hash::operator()(const KetAtom &k) const {
158 11903 : size_t seed = typename Ket::hash()(k);
159 11903 : utils::hash_combine(seed, k.species);
160 11903 : utils::hash_combine(seed, k.quantum_number_n);
161 11903 : utils::hash_combine(seed, k.quantum_number_nu);
162 11903 : utils::hash_combine(seed, k.quantum_number_nui_exp);
163 11903 : utils::hash_combine(seed, k.quantum_number_nui_std);
164 11903 : utils::hash_combine(seed, k.quantum_number_l_exp);
165 11903 : utils::hash_combine(seed, k.quantum_number_l_std);
166 11903 : utils::hash_combine(seed, k.quantum_number_s_exp);
167 11903 : utils::hash_combine(seed, k.quantum_number_s_std);
168 11903 : utils::hash_combine(seed, k.quantum_number_j_exp);
169 11903 : utils::hash_combine(seed, k.quantum_number_j_std);
170 11903 : return seed;
171 : }
172 :
173 : } // namespace pairinteraction
|