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 39507 : 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 39507 : atomic_indices(atomic_indices), atomic_bases(atomic_bases) { 23 39507 : 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 39507 : } 28 : 29 : template <typename Scalar> 30 27 : std::string KetPair<Scalar>::get_label() const { 31 27 : std::string label; 32 27 : std::string separator; 33 81 : for (size_t atom_index = 0; atom_index < atomic_indices.size(); ++atom_index) { 34 54 : label += separator + 35 162 : atomic_bases[atom_index] 36 54 : ->get_corresponding_ket(atomic_indices[atom_index]) 37 54 : ->get_label(); 38 54 : separator = "; "; 39 : } 40 54 : return label; 41 27 : } 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 34624 : size_t KetPair<Scalar>::hash::operator()(const KetPair<Scalar> &k) const { 76 34624 : size_t seed = typename Ket::hash()(k); 77 103872 : for (const auto &index : k.atomic_indices) { 78 69248 : utils::hash_combine(seed, index); 79 : } 80 103872 : for (const auto &basis : k.atomic_bases) { 81 69248 : utils::hash_combine(seed, reinterpret_cast<std::uintptr_t>(basis.get())); 82 : } 83 34624 : return seed; 84 : } 85 : 86 : template <typename Scalar> 87 39507 : 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 39507 : return std::numeric_limits<real_t>::max(); 92 : } 93 : 94 : template <typename Scalar> 95 39507 : 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 118521 : for (const auto &basis : bases) { 99 79014 : if (!basis->has_quantum_number_m()) { 100 0 : return std::numeric_limits<real_t>::max(); 101 : } 102 : } 103 39507 : real_t total_quantum_number_m = 0; 104 118521 : for (size_t i = 0; i < indices.size(); ++i) { 105 79014 : total_quantum_number_m += bases[i]->get_quantum_number_m(indices[i]); 106 : } 107 39507 : return total_quantum_number_m; 108 : } 109 : 110 : template <typename Scalar> 111 39507 : 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 39507 : return Parity::UNKNOWN; 116 : } 117 : 118 : // Explicit instantiations 119 : template class KetPair<double>; 120 : template class KetPair<std::complex<double>>; 121 : } // namespace pairinteraction