LCOV - code coverage report
Current view: top level - src/ket - KetPair.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 46 51 90.2 %
Date: 2025-09-29 10:27:57 Functions: 15 20 75.0 %

          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       74467 : 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       74467 :       atomic_indices(atomic_indices), atomic_bases(atomic_bases) {
      23       74467 :     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       74467 : }
      28             : 
      29             : template <typename Scalar>
      30          34 : std::string KetPair<Scalar>::get_label() const {
      31          34 :     constexpr real_t numerical_precision = 100 * std::numeric_limits<real_t>::epsilon();
      32             : 
      33          34 :     std::string label;
      34          34 :     std::string separator;
      35         102 :     for (size_t atom_index = 0; atom_index < atomic_indices.size(); ++atom_index) {
      36          68 :         const auto &basis = atomic_bases[atom_index];
      37          68 :         size_t idx = atomic_indices[atom_index];
      38             :         Scalar coefficient =
      39          68 :             basis->get_coefficients().coeff(idx, basis->get_corresponding_ket_index(idx));
      40          68 :         std::string optional_tilde = (std::abs(coefficient - 1.0) > numerical_precision) ? "~" : "";
      41          68 :         label += separator + optional_tilde + basis->get_corresponding_ket(idx)->get_label();
      42          68 :         separator = "; ";
      43             :     }
      44          68 :     return label;
      45          34 : }
      46             : 
      47             : template <typename Scalar>
      48             : std::shared_ptr<KetPair<Scalar>>
      49           0 : KetPair<Scalar>::get_ket_for_different_quantum_number_m(real_t /*new_quantum_number_m*/) const {
      50             :     // If we use symmetrized states so that the quantum_number_f is the total
      51             :     // angular quantum number, the quantum_number_m is the magnetic quantum number
      52             :     // corresponding to the total angular quantum number and we can implement this
      53             :     // method.
      54           0 :     throw std::runtime_error("Not implemented.");
      55             : }
      56             : 
      57             : template <typename Scalar>
      58           1 : std::vector<std::shared_ptr<const BasisAtom<Scalar>>> KetPair<Scalar>::get_atomic_states() const {
      59           1 :     std::vector<std::shared_ptr<const BasisAtom<Scalar>>> atomic_states;
      60           1 :     atomic_states.reserve(atomic_indices.size());
      61           3 :     for (size_t atom_index = 0; atom_index < atomic_indices.size(); ++atom_index) {
      62           2 :         atomic_states.push_back(atomic_bases[atom_index]->get_state(atomic_indices[atom_index]));
      63             :     }
      64           1 :     return atomic_states;
      65           0 : }
      66             : 
      67             : template <typename Scalar>
      68           8 : bool KetPair<Scalar>::operator==(const KetPair<Scalar> &other) const {
      69          14 :     return Ket::operator==(other) && atomic_indices == other.atomic_indices &&
      70          14 :         atomic_bases == other.atomic_bases;
      71             : }
      72             : 
      73             : template <typename Scalar>
      74           4 : bool KetPair<Scalar>::operator!=(const KetPair<Scalar> &other) const {
      75           4 :     return !(*this == other);
      76             : }
      77             : 
      78             : template <typename Scalar>
      79       69649 : size_t KetPair<Scalar>::hash::operator()(const KetPair<Scalar> &k) const {
      80       69649 :     size_t seed = typename Ket::hash()(k);
      81      208947 :     for (const auto &index : k.atomic_indices) {
      82      139298 :         utils::hash_combine(seed, index);
      83             :     }
      84      208947 :     for (const auto &basis : k.atomic_bases) {
      85      139298 :         utils::hash_combine(seed, reinterpret_cast<std::uintptr_t>(basis.get()));
      86             :     }
      87       69649 :     return seed;
      88             : }
      89             : 
      90             : template <typename Scalar>
      91       74467 : typename KetPair<Scalar>::real_t KetPair<Scalar>::calculate_quantum_number_f(
      92             :     const std::vector<size_t> & /*indices*/,
      93             :     const std::vector<std::shared_ptr<const BasisAtom<Scalar>>> & /*bases*/) {
      94             :     // Because this ket state is not symmetrized, the quantum_number_f is not well-defined.
      95       74467 :     return std::numeric_limits<real_t>::max();
      96             : }
      97             : 
      98             : template <typename Scalar>
      99       74467 : 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      223401 :     for (const auto &basis : bases) {
     103      148934 :         if (!basis->has_quantum_number_m()) {
     104           0 :             return std::numeric_limits<real_t>::max();
     105             :         }
     106             :     }
     107       74467 :     real_t total_quantum_number_m = 0;
     108      223401 :     for (size_t i = 0; i < indices.size(); ++i) {
     109      148934 :         total_quantum_number_m += bases[i]->get_quantum_number_m(indices[i]);
     110             :     }
     111       74467 :     return total_quantum_number_m;
     112             : }
     113             : 
     114             : template <typename Scalar>
     115       74467 : Parity KetPair<Scalar>::calculate_parity(
     116             :     const std::vector<size_t> & /*indices*/,
     117             :     const std::vector<std::shared_ptr<const BasisAtom<Scalar>>> & /*bases*/) {
     118             :     // Because this ket state is not symmetrized, the parity is not well-defined.
     119       74467 :     return Parity::UNKNOWN;
     120             : }
     121             : 
     122             : // Explicit instantiations
     123             : template class KetPair<double>;
     124             : template class KetPair<std::complex<double>>;
     125             : } // namespace pairinteraction

Generated by: LCOV version 1.16