Line data Source code
1 : // SPDX-FileCopyrightText: 2024 PairInteraction Developers 2 : // SPDX-License-Identifier: LGPL-3.0-or-later 3 : 4 : #include "pairinteraction/ket/KetPair.hpp" 5 : 6 : #include "pairinteraction/basis/BasisAtom.hpp" 7 : #include "pairinteraction/ket/KetAtom.hpp" 8 : #include "pairinteraction/utils/hash.hpp" 9 : 10 : #include <limits> 11 : #include <string> 12 : 13 : namespace pairinteraction { 14 : template <typename Scalar> 15 2900412 : KetPair<Scalar>::KetPair( 16 : Private /*unused*/, std::initializer_list<size_t> atomic_indices, 17 : std::initializer_list<std::shared_ptr<const BasisAtom<Scalar>>> atomic_bases, real_t energy) 18 2900412 : : Ket(energy), quantum_number_m(calculate_quantum_number_m(atomic_indices, atomic_bases)), 19 5800824 : atomic_indices(atomic_indices), atomic_bases(atomic_bases) { 20 2900412 : if (atomic_indices.size() != atomic_bases.size()) { 21 0 : throw std::invalid_argument( 22 : "The number of atomic indices, and atomic bases must be the same."); 23 : } 24 2900412 : } 25 : 26 : template <typename Scalar> 27 2900412 : bool KetPair<Scalar>::has_quantum_number_m() const { 28 2900412 : return quantum_number_m != std::numeric_limits<real_t>::max(); 29 : } 30 : 31 : template <typename Scalar> 32 3033000 : typename KetPair<Scalar>::real_t KetPair<Scalar>::get_quantum_number_m() const { 33 3033000 : return quantum_number_m; 34 : } 35 : 36 : template <typename Scalar> 37 118 : std::string KetPair<Scalar>::get_label() const { 38 118 : constexpr real_t numerical_precision = 100 * std::numeric_limits<real_t>::epsilon(); 39 : 40 118 : std::string label; 41 118 : std::string separator; 42 354 : for (size_t atom_index = 0; atom_index < atomic_indices.size(); ++atom_index) { 43 236 : const auto &basis = atomic_bases[atom_index]; 44 236 : size_t idx = atomic_indices[atom_index]; 45 : Scalar coefficient = 46 236 : basis->get_coefficients().coeff(basis->get_corresponding_ket_index(idx), idx); 47 236 : std::string optional_tilde = (std::abs(coefficient - 1.0) > numerical_precision) ? "~" : ""; 48 236 : label += separator + optional_tilde + basis->get_corresponding_ket(idx)->get_label(); 49 236 : separator = "; "; 50 : } 51 236 : return label; 52 118 : } 53 : 54 : template <typename Scalar> 55 : std::shared_ptr<KetPair<Scalar>> 56 0 : KetPair<Scalar>::get_ket_for_different_quantum_number_m(real_t /*new_quantum_number_m*/) const { 57 : // If we use symmetrized states so that the quantum_number_f is the total 58 : // angular quantum number, the quantum_number_m is the magnetic quantum number 59 : // corresponding to the total angular quantum number and we can implement this 60 : // method. 61 0 : throw std::runtime_error("Not implemented."); 62 : } 63 : 64 : template <typename Scalar> 65 270 : std::vector<std::shared_ptr<const BasisAtom<Scalar>>> KetPair<Scalar>::get_atomic_states() const { 66 270 : std::vector<std::shared_ptr<const BasisAtom<Scalar>>> atomic_states; 67 270 : atomic_states.reserve(atomic_indices.size()); 68 810 : for (size_t atom_index = 0; atom_index < atomic_indices.size(); ++atom_index) { 69 540 : atomic_states.push_back(atomic_bases[atom_index]->get_state(atomic_indices[atom_index])); 70 : } 71 270 : return atomic_states; 72 0 : } 73 : 74 : template <typename Scalar> 75 6 : bool KetPair<Scalar>::operator==(const KetPair<Scalar> &other) const { 76 10 : return Ket::operator==(other) && quantum_number_m == other.quantum_number_m && 77 10 : atomic_indices == other.atomic_indices && atomic_bases == other.atomic_bases; 78 : } 79 : 80 : template <typename Scalar> 81 4 : bool KetPair<Scalar>::operator!=(const KetPair<Scalar> &other) const { 82 4 : return !(*this == other); 83 : } 84 : 85 : template <typename Scalar> 86 2833091 : size_t KetPair<Scalar>::hash::operator()(const KetPair<Scalar> &k) const { 87 2833091 : size_t seed = typename Ket::hash()(k); 88 2833091 : utils::hash_combine(seed, k.quantum_number_m); 89 8499273 : for (const auto &index : k.atomic_indices) { 90 5666182 : utils::hash_combine(seed, index); 91 : } 92 8499273 : for (const auto &basis : k.atomic_bases) { 93 5666182 : utils::hash_combine(seed, reinterpret_cast<std::uintptr_t>(basis.get())); 94 : } 95 2833091 : return seed; 96 : } 97 : 98 : template <typename Scalar> 99 2900412 : typename KetPair<Scalar>::real_t KetPair<Scalar>::calculate_quantum_number_m( 100 : const std::vector<size_t> &indices, 101 : const std::vector<std::shared_ptr<const BasisAtom<Scalar>>> &bases) { 102 8701236 : for (const auto &basis : bases) { 103 5800824 : if (!basis->has_quantum_number_m()) { 104 0 : return std::numeric_limits<real_t>::max(); 105 : } 106 : } 107 2900412 : real_t total_quantum_number_m = 0; 108 8701236 : for (size_t i = 0; i < indices.size(); ++i) { 109 5800824 : total_quantum_number_m += bases[i]->get_quantum_number_m(indices[i]); 110 : } 111 2900412 : return total_quantum_number_m; 112 : } 113 : 114 : // Explicit instantiations 115 : template class KetPair<double>; 116 : template class KetPair<std::complex<double>>; 117 : } // namespace pairinteraction