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/enums/Parity.hpp" 8 : #include "pairinteraction/ket/KetAtom.hpp" 9 : #include "pairinteraction/utils/hash.hpp" 10 : 11 : #include <limits> 12 : #include <string> 13 : 14 : namespace pairinteraction { 15 : template <typename Scalar> 16 9101 : KetPair<Scalar>::KetPair( 17 : Private /*unused*/, std::initializer_list<size_t> atomic_indices, 18 : std::initializer_list<std::shared_ptr<const BasisAtom<Scalar>>> atomic_bases, real_t energy) 19 : : Ket(energy, calculate_quantum_number_f(atomic_indices, atomic_bases), 20 : calculate_quantum_number_m(atomic_indices, atomic_bases), 21 : calculate_parity(atomic_indices, atomic_bases)), 22 9101 : atomic_indices(atomic_indices), atomic_bases(atomic_bases) { 23 9101 : if (atomic_indices.size() != atomic_bases.size()) { 24 0 : throw std::invalid_argument( 25 : "The number of atomic indices, and atomic bases must be the same."); 26 : } 27 9101 : } 28 : 29 : template <typename Scalar> 30 19 : std::string KetPair<Scalar>::get_label() const { 31 19 : std::string label; 32 19 : std::string separator; 33 57 : for (size_t atom_index = 0; atom_index < atomic_indices.size(); ++atom_index) { 34 38 : label += separator + 35 114 : atomic_bases[atom_index] 36 38 : ->get_corresponding_ket(atomic_indices[atom_index]) 37 38 : ->get_label(); 38 38 : separator = "; "; 39 : } 40 38 : return label; 41 19 : } 42 : 43 : template <typename Scalar> 44 : std::shared_ptr<KetPair<Scalar>> 45 0 : KetPair<Scalar>::get_ket_for_different_quantum_number_m(real_t /*new_quantum_number_m*/) const { 46 : // If we use symmetrized states so that the quantum_number_f is the total 47 : // angular quantum number, the quantum_number_m is the magnetic quantum number 48 : // corresponding to the total angular quantum number and we can implement this 49 : // method. 50 0 : throw std::runtime_error("Not implemented."); 51 : } 52 : 53 : template <typename Scalar> 54 1 : std::vector<std::shared_ptr<const BasisAtom<Scalar>>> KetPair<Scalar>::get_atomic_states() const { 55 1 : std::vector<std::shared_ptr<const BasisAtom<Scalar>>> atomic_states; 56 1 : atomic_states.reserve(atomic_indices.size()); 57 3 : for (size_t atom_index = 0; atom_index < atomic_indices.size(); ++atom_index) { 58 2 : atomic_states.push_back(atomic_bases[atom_index]->get_state(atomic_indices[atom_index])); 59 : } 60 1 : return atomic_states; 61 0 : } 62 : 63 : template <typename Scalar> 64 8 : bool KetPair<Scalar>::operator==(const KetPair<Scalar> &other) const { 65 14 : return Ket::operator==(other) && atomic_indices == other.atomic_indices && 66 14 : atomic_bases == other.atomic_bases; 67 : } 68 : 69 : template <typename Scalar> 70 4 : bool KetPair<Scalar>::operator!=(const KetPair<Scalar> &other) const { 71 4 : return !(*this == other); 72 : } 73 : 74 : template <typename Scalar> 75 8496 : size_t KetPair<Scalar>::hash::operator()(const KetPair<Scalar> &k) const { 76 8496 : size_t seed = typename Ket::hash()(k); 77 25488 : for (const auto &index : k.atomic_indices) { 78 16992 : utils::hash_combine(seed, index); 79 : } 80 25488 : for (const auto &basis : k.atomic_bases) { 81 16992 : utils::hash_combine(seed, reinterpret_cast<std::uintptr_t>(basis.get())); 82 : } 83 8496 : return seed; 84 : } 85 : 86 : template <typename Scalar> 87 9101 : typename KetPair<Scalar>::real_t KetPair<Scalar>::calculate_quantum_number_f( 88 : const std::vector<size_t> & /*indices*/, 89 : const std::vector<std::shared_ptr<const BasisAtom<Scalar>>> & /*bases*/) { 90 : // Because this ket state is not symmetrized, the quantum_number_f is not well-defined. 91 9101 : return std::numeric_limits<real_t>::max(); 92 : } 93 : 94 : template <typename Scalar> 95 9101 : typename KetPair<Scalar>::real_t KetPair<Scalar>::calculate_quantum_number_m( 96 : const std::vector<size_t> &indices, 97 : const std::vector<std::shared_ptr<const BasisAtom<Scalar>>> &bases) { 98 27303 : for (const auto &basis : bases) { 99 18202 : if (!basis->has_quantum_number_m()) { 100 0 : return std::numeric_limits<real_t>::max(); 101 : } 102 : } 103 9101 : real_t total_quantum_number_m = 0; 104 27303 : for (size_t i = 0; i < indices.size(); ++i) { 105 18202 : total_quantum_number_m += bases[i]->get_quantum_number_m(indices[i]); 106 : } 107 9101 : return total_quantum_number_m; 108 : } 109 : 110 : template <typename Scalar> 111 9101 : Parity KetPair<Scalar>::calculate_parity( 112 : const std::vector<size_t> & /*indices*/, 113 : const std::vector<std::shared_ptr<const BasisAtom<Scalar>>> & /*bases*/) { 114 : // Because this ket state is not symmetrized, the parity is not well-defined. 115 9101 : return Parity::UNKNOWN; 116 : } 117 : 118 : // Explicit instantiations 119 : template class KetPair<double>; 120 : template class KetPair<std::complex<double>>; 121 : } // namespace pairinteraction