ampsci
c++ program for high-precision atomic structure calculations of single-valence systems
meTable.hpp
1 #pragma once
2 #include "Physics/AtomData.hpp"
3 #include "QkTable.hpp"
4 #include "Wavefunction/DiracSpinor.hpp"
5 #include <cstdint>
6 #include <unordered_map>
7 
8 namespace Coulomb {
9 
11 using nk2Index = uint32_t;
12 
16 template <typename T = double>
17 class meTable {
18 
19 private:
20  std::unordered_map<nk2Index, T> m_data{};
21 
22 public:
23  auto operator->() { return &m_data; }
24 
27  void add(const DiracSpinor &a, const DiracSpinor &b, T value) {
28  m_data.insert({FormIndex(a.nk_index(), b.nk_index()), std::move(value)});
29  }
32  void add(DiracSpinor::Index a, DiracSpinor::Index b, T value) {
33  m_data.insert({FormIndex(a, b), std::move(value)});
34  }
35 
37  void add(const meTable<T> &other) {
38  m_data.insert(other.cbegin(), other.cend());
39  }
40 
42  void update(const DiracSpinor &a, const DiracSpinor &b, T value) {
43  m_data.insert_or_assign(FormIndex(a.nk_index(), b.nk_index()),
44  std::move(value));
45  }
47  void update(DiracSpinor::Index a, DiracSpinor::Index b, T value) {
48  m_data.insert_or_assign(FormIndex(a, b), std::move(value));
49  }
50 
52  [[nodiscard]] bool contains(const DiracSpinor &a,
53  const DiracSpinor &b) const {
54  return m_data.find(FormIndex(a.nk_index(), b.nk_index())) != m_data.cend();
55  }
57  [[nodiscard]] bool contains(DiracSpinor::Index a,
58  DiracSpinor::Index b) const {
59  return m_data.find(FormIndex(a, b)) != m_data.cend();
60  }
61 
64  [[nodiscard]] const T *get(const DiracSpinor &a, const DiracSpinor &b) const {
65  const auto map_it = m_data.find(FormIndex(a.nk_index(), b.nk_index()));
66  return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
67  }
70  [[nodiscard]] const T *get(DiracSpinor::Index a, DiracSpinor::Index b) const {
71  const auto map_it = m_data.find(FormIndex(a, b));
72  return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
73  }
74 
77  [[nodiscard]] T *get(const DiracSpinor &a, const DiracSpinor &b) {
78  const auto map_it = m_data.find(FormIndex(a.nk_index(), b.nk_index()));
79  return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
80  }
83  [[nodiscard]] T *get(DiracSpinor::Index a, DiracSpinor::Index b) {
84  const auto map_it = m_data.find(FormIndex(a, b));
85  return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
86  }
87 
90  [[nodiscard]] T getv(const DiracSpinor &a, const DiracSpinor &b) const {
91  const auto ptr = get(a, b);
92  return ptr ? *ptr : T{};
93  }
96  [[nodiscard]] T getv(DiracSpinor::Index a, DiracSpinor::Index b) const {
97  const auto ptr = get(a, b);
98  return ptr ? *ptr : T{};
99  }
100 
103  [[nodiscard]] const T *get(const std::string &a, const std::string &b) const {
104  const auto [na, ka] = AtomData::parse_symbol(a);
105  const auto [nb, kb] = AtomData::parse_symbol(b);
106  const auto a_index =
107  static_cast<Coulomb::nkIndex>(Angular::nk_to_index(na, ka));
108  const auto b_index =
109  static_cast<Coulomb::nkIndex>(Angular::nk_to_index(nb, kb));
110  const auto map_it = m_data.find(FormIndex(a_index, b_index));
111  return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
112  }
113 
115  auto begin() { return m_data.begin(); }
116  auto end() { return m_data.end(); }
117  auto cbegin() const { return m_data.cbegin(); }
118  auto cend() const { return m_data.cend(); }
119 
120  static std::pair<std::string, std::string> index_to_symbols(nk2Index index) {
121  const auto [a, b] = unFormIndex(index);
122  const auto [na, ka] = Angular::index_to_nk(int(a));
123  const auto [nb, kb] = Angular::index_to_nk(int(b));
124  return {AtomData::shortSymbol(na, ka), AtomData::shortSymbol(nb, kb)};
125  }
126 
127  // private:
128  // Converts given set of nkIndex's (in any order) to nk4Index
129  [[nodiscard]] static nk2Index FormIndex(nkIndex a, nkIndex b) {
130  static_assert(sizeof(nk2Index) == 2 * sizeof(nkIndex));
131  static_assert(sizeof(nkIndex) * 8 == 16);
132  return (nk2Index)b + ((nk2Index)a << 16);
133  }
134 
135  [[nodiscard]] static std::pair<nkIndex, nkIndex> unFormIndex(nk2Index index) {
136  std::pair<nkIndex, nkIndex> out;
137  auto &[a, b] = out;
138  b = static_cast<nkIndex>(index);
139  // nb: this relies on specific encoding, and may fail?
140  a = static_cast<nkIndex>((index - static_cast<nk2Index>(b)) >> 16);
141  assert(FormIndex(a, b) == index);
142  return out;
143  }
144 };
145 
146 } // namespace Coulomb
Look-up table for matrix elements. Note: does not assume any symmetry: (a,b) is stored independantly ...
Definition: meTable.hpp:17
void add(DiracSpinor::Index a, DiracSpinor::Index b, T value)
Adds new element to table. If already exists, does nothing (does not update)
Definition: meTable.hpp:32
T * get(DiracSpinor::Index a, DiracSpinor::Index b)
Gets pointer to mutable requested element. If element not present, returns nullptr.
Definition: meTable.hpp:83
const T * get(DiracSpinor::Index a, DiracSpinor::Index b) const
Gets pointer to const requested element. If element not present, returns nullptr.
Definition: meTable.hpp:70
void update(const DiracSpinor &a, const DiracSpinor &b, T value)
Updates given element in table. If element not yet present, adds it.
Definition: meTable.hpp:42
auto begin()
Provide iterators.
Definition: meTable.hpp:115
bool contains(DiracSpinor::Index a, DiracSpinor::Index b) const
Checks if given element is in the table.
Definition: meTable.hpp:57
bool contains(const DiracSpinor &a, const DiracSpinor &b) const
Checks if given element is in the table.
Definition: meTable.hpp:52
T getv(const DiracSpinor &a, const DiracSpinor &b) const
Gets value of requested element. If element not present, returns zero (or default constructed T)
Definition: meTable.hpp:90
void add(const meTable< T > &other)
Adds elements from one Table into another (by copy)
Definition: meTable.hpp:37
const T * get(const DiracSpinor &a, const DiracSpinor &b) const
Gets pointer to const requested element. If element not present, returns nullptr.
Definition: meTable.hpp:64
void update(DiracSpinor::Index a, DiracSpinor::Index b, T value)
Updates given element in table. If element not yet present, adds it.
Definition: meTable.hpp:47
T getv(DiracSpinor::Index a, DiracSpinor::Index b) const
Gets value of requested element. If element not present, returns zero (or default constructed T)
Definition: meTable.hpp:96
const T * get(const std::string &a, const std::string &b) const
Gets pointer to const requested element. If element not present, returns nullptr. Overload for string...
Definition: meTable.hpp:103
void add(const DiracSpinor &a, const DiracSpinor &b, T value)
Adds new element to table. If already exists, does nothing (does not update)
Definition: meTable.hpp:27
T * get(const DiracSpinor &a, const DiracSpinor &b)
Gets pointer to mutable requested element. If element not present, returns nullptr.
Definition: meTable.hpp:77
Stores radial Dirac spinor: F_nk = (f, g)
Definition: DiracSpinor.hpp:41
Index nk_index() const
(n,kappa) index (see AtomData)
Definition: DiracSpinor.hpp:97
constexpr int nk_to_index(int n, int k)
return nk_index given {n, kappa}: nk_index(n,k) := n^2 - 2n + 1 + kappa_index
Definition: Wigner369j.hpp:73
std::pair< int, int > index_to_nk(int index)
return {n, kappa} given nk_index:
Definition: Wigner369j.hpp:78
std::pair< int, int > parse_symbol(std::string_view symbol)
Parses electron 'symbol' or 'shortSymbol' to {n,kappa}, e.g., "6s+" -> {6,-1}; "6p-" -> {6,...
Definition: AtomData.cpp:148
std::string shortSymbol(int n, int kappa)
Returns shortSymbol, given n and kappa: (6,-1)->"6s+".
Definition: AtomData.cpp:128
Functions (+classes) for computing Coulomb integrals.
Definition: Coulomb.hpp:8
uint32_t nk2Index
index type for set of 2 orbitals {nk,nk} -> nk4Index
Definition: meTable.hpp:11
uint16_t nkIndex
index type for each {nk} (orbital)
Definition: QkTable.hpp:19