ampsci
High-precision calculations for one- and two-valence atomic 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
8namespace Coulomb {
9
10//! index type for set of 2 orbitals {nk,nk} -> nk4Index
11using nk2Index = uint32_t;
12
13//! Look-up table for matrix elements. Note: does not assume any symmetry: (a,b)
14//! is stored independantly of (b,a). In general, maps a pair of DiracSpinors to
15//! a single value (of any type, T).
16template <typename T = double>
17class meTable {
18
19private:
20 std::unordered_map<nk2Index, T> m_data{};
21
22public:
23 auto operator->() { return &m_data; }
24
25 //! Adds new element to table. If already exists, does nothing (does not
26 //! update)
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 }
30 //! Adds new element to table. If already exists, does nothing (does not
31 //! update)
32 void add(DiracSpinor::Index a, DiracSpinor::Index b, T value) {
33 m_data.insert({FormIndex(a, b), std::move(value)});
34 }
35
36 //! Adds elements from one Table into another (by copy)
37 void add(const meTable<T> &other) {
38 m_data.insert(other.cbegin(), other.cend());
39 }
40
41 //! Updates given element in table. If element not yet present, adds it
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 }
46 //! Updates given element in table. If element not yet present, adds it
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
51 //! Checks if given element is in the table
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 }
56 //! Checks if given element is in the table
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
62 //! Returns true in the meTable is empty
63 [[nodiscard]] bool empty() const { return m_data.empty(); }
64
65 //! Gets pointer to const requested element. If element not present,
66 //! returns nullptr
67 [[nodiscard]] const T *get(const DiracSpinor &a, const DiracSpinor &b) const {
68 const auto map_it = m_data.find(FormIndex(a.nk_index(), b.nk_index()));
69 return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
70 }
71 //! Gets pointer to const requested element. If element not present,
72 //! returns nullptr
73 [[nodiscard]] const T *get(DiracSpinor::Index a, DiracSpinor::Index b) const {
74 const auto map_it = m_data.find(FormIndex(a, b));
75 return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
76 }
77
78 //! Gets pointer to mutable requested element. If element not present, returns
79 //! nullptr
80 [[nodiscard]] T *get(const DiracSpinor &a, const DiracSpinor &b) {
81 const auto map_it = m_data.find(FormIndex(a.nk_index(), b.nk_index()));
82 return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
83 }
84 //! Gets pointer to mutable requested element. If element not present, returns
85 //! nullptr
86 [[nodiscard]] T *get(DiracSpinor::Index a, DiracSpinor::Index b) {
87 const auto map_it = m_data.find(FormIndex(a, b));
88 return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
89 }
90
91 //! Gets value of requested element. If element not present,
92 //! returns zero (or default constructed T)
93 [[nodiscard]] T getv(const DiracSpinor &a, const DiracSpinor &b) const {
94 const auto ptr = get(a, b);
95 return ptr ? *ptr : T{};
96 }
97 //! Gets value of requested element. If element not present,
98 //! returns zero (or default constructed T)
99 [[nodiscard]] T getv(DiracSpinor::Index a, DiracSpinor::Index b) const {
100 const auto ptr = get(a, b);
101 return ptr ? *ptr : T{};
102 }
103
104 //! Gets pointer to const requested element. If element not present,
105 //! returns nullptr. Overload for strings (parses symbol)
106 [[nodiscard]] const T *get(const std::string &a, const std::string &b) const {
107 const auto [na, ka] = AtomData::parse_symbol(a);
108 const auto [nb, kb] = AtomData::parse_symbol(b);
109 const auto a_index =
110 static_cast<Coulomb::nkIndex>(Angular::nk_to_index(na, ka));
111 const auto b_index =
112 static_cast<Coulomb::nkIndex>(Angular::nk_to_index(nb, kb));
113 const auto map_it = m_data.find(FormIndex(a_index, b_index));
114 return (map_it == m_data.cend()) ? nullptr : &(map_it->second);
115 }
116
117 //! Provide iterators
118 auto begin() { return m_data.begin(); }
119 auto end() { return m_data.end(); }
120 auto cbegin() const { return m_data.cbegin(); }
121 auto cend() const { return m_data.cend(); }
122
123 static std::pair<std::string, std::string> index_to_symbols(nk2Index index) {
124 const auto [a, b] = unFormIndex(index);
125 const auto [na, ka] = Angular::index_to_nk(a);
126 const auto [nb, kb] = Angular::index_to_nk(b);
127 return {AtomData::shortSymbol(na, ka), AtomData::shortSymbol(nb, kb)};
128 }
129
130 // private:
131 // Converts given set of nkIndex's (in any order) to nk4Index
132 [[nodiscard]] static nk2Index FormIndex(nkIndex a, nkIndex b) {
133 static_assert(sizeof(nk2Index) == 2 * sizeof(nkIndex));
134 static_assert(sizeof(nkIndex) * 8 == 16);
135 return (nk2Index)b + ((nk2Index)a << 16);
136 }
137
138 [[nodiscard]] static std::pair<nkIndex, nkIndex> unFormIndex(nk2Index index) {
139 std::pair<nkIndex, nkIndex> out;
140 auto &[a, b] = out;
141 b = static_cast<nkIndex>(index);
142 // nb: this relies on specific encoding, and may fail?
143 a = static_cast<nkIndex>((index - static_cast<nk2Index>(b)) >> 16);
144 assert(FormIndex(a, b) == index);
145 return out;
146 }
147};
148
149} // 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:86
T * get(const DiracSpinor &a, const DiracSpinor &b)
Gets pointer to mutable requested element. If element not present, returns nullptr.
Definition meTable.hpp:80
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:118
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:106
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:93
void add(const meTable< T > &other)
Adds elements from one Table into another (by copy)
Definition meTable.hpp:37
bool empty() const
Returns true in the meTable is empty.
Definition meTable.hpp:63
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
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:73
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:99
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
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:67
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:42
Index nk_index() const
(n,kappa) index (see AtomData)
Definition DiracSpinor.hpp:101
constexpr std::uint64_t nk_to_index(int n, int k)
Returns nk_index, given {n, kappa}.
Definition Wigner369j.hpp:172
std::pair< int, int > index_to_nk(std::uint64_t nk_index)
Returns {n, kappa} given nk_index.
Definition Wigner369j.hpp:178
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 CoulombIntegrals.cpp:13
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) [max n: 256]
Definition QkTable.hpp:23