|
ampsci
High-precision calculations for one- and two-valence atomic systems
|
Base class template to store Coulomb integrals, and similar. 3 specific cases (by template instantiation), account for specific symmetrs.
Mostly, a wrapper for std::unordered_map. Stores data in a std::vector of maps, each element (map) for each k (multipolarity). The symmetry is taken into account by defining a "Normal Ordering" of set of orbitals {a,b,c,d}, which is defined as the "smallest" arrangment of equivilant indices. The details depend on the specific symmetry in question:
S: for Symmetry::Qk, we assume Coulomb angular selection rules, including parity rule, (via k_minmax_Q); for all other symmetries no explicit selection rule is assumed. The fill() and fill_if() functions also make this assumption; these functions are only available for the Symmetry::Qk symmetry, and in that case, assume the regular Coulomb selection rules. #include <QkTable.hpp>
Public Member Functions | |
| void | fill (const std::vector< DiracSpinor > &basis, const YkTable &yk, int k_cut=-1, bool print=true) |
| Fill table with all non-zero Coulomb Q integrals from a YkTable. | |
| void | fill_if (const std::vector< DiracSpinor > &basis, const YkTable &yk, const SelectionRules &SelectionFunction, int k_cut=-1, bool print=true) |
| Fill table with Coulomb Q integrals satisfying a selection rule. | |
| void | fill (const std::vector< DiracSpinor > &basis, const CoulombFunction &Fk, const SelectionRules &Fk_SR, int k_cut=-1, bool print=true) |
| Fill table using a general CoulombFunction and selection rules. | |
| void | update (const std::vector< DiracSpinor > &basis, const CoulombFunction &Fk, double damp, bool print=true) |
| Re-calculate all existing table entries using a CoulombFunction. | |
| auto | operator-> () |
| Gives arrow access to all underlying vector<unordered_map> functions. | |
| void | summary () const |
| For testing: prints details of coulomb integrals stored. | |
| std::size_t | count () const |
| Returns number of stored integrals. | |
| int | max_k () const |
| void | add (int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, Real value) |
| adds a new value. Note: does nothing if {k,a,b,c,d} already exists | |
| void | add (int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d, Real value) |
| adds a new value. Note: does nothing if {k,a,b,c,d} already exists | |
| void | add (int k, nk4Index index, Real value) |
| adds a new value. Note: does nothing if {k,a,b,c,d} already exists | |
| void | update (int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, Real value) |
| Updates value in table. If not present, adds new value. | |
| void | update (int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d, Real value) |
| Updates value in table. If not present, adds new value. | |
| void | update (int k, nk4Index index, Real value) |
| Updates value in table. If not present, adds new value. | |
| bool | contains (int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const |
| Checks if given {k,a,b,c,d} is in the table. | |
| bool | contains (int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d) const |
| Checks if given {k,a,b,c,d} is in the table. | |
| bool | contains (int k, nk4Index index) const |
| Checks if given {k,a,b,c,d} is in the table. | |
| bool | emptyQ () const |
| Returns true if table is empty. | |
| std::array< std::size_t, 4 > | count_non_zero_integrals (const std::vector< DiracSpinor > &basis, std::size_t max_k=99, double eF=0.0) const |
| Real | Q (int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const |
| Retrieve a stored Q. If not present, returns 0. (Returns exactly as stored in table.) | |
| Real | Q (int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d) const |
| Retrieve a stored Q. If not present, returns 0. (Returns exactly as stored in table.) | |
| Real | Q (int k, nk4Index index) const |
| Retrieve a stored Q. If not present, returns 0. (Returns exactly as stored in table.) | |
| Real | R (int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const |
| Returns 'R', defined via: R := Q / (angular_coef) | |
| Real | R (int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d) const |
| Returns 'R', defined via: R := Q / (angular_coef) | |
| Real | P (int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, const Angular::SixJTable *const sj=nullptr) const |
| Exchange integral P^k_abcd = (2k+1) sum_l {6j} Q^l_abdc. | |
| Real | P (int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d, const Angular::SixJTable *const sj=nullptr) const |
| Exchange integral P^k_abcd = (2k+1) sum_l {6j} Q^l_abdc. | |
| Real | P2 (int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, const Angular::SixJTable &sj, const std::vector< double > &fk) const |
| Exchange integral P^k_abcd with effective Coulomb screening. | |
| Real | W (int k, const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, const Angular::SixJTable *const sj=nullptr) const |
| Antisymmetrised integral W^k_abcd = Q^k_abcd + P^k_abcd. | |
| Real | W (int k, nkIndex a, nkIndex b, nkIndex c, nkIndex d, const Angular::SixJTable *const sj=nullptr) const |
| Antisymmetrised integral W^k_abcd = Q^k_abcd + P^k_abcd. | |
| Real | g (const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d, int tma, int tmb, int tmc, int tmd) const |
| Full matrix element g_abcd with explicit magnetic quantum numbers. | |
| nk4Index | NormalOrder (const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const |
| Creates single 'nk4Index' corresponding to 'NormalOrder' symmetry of {a,b,c,d}. | |
| nk4Index | NormalOrder (nkIndex a, nkIndex b, nkIndex c, nkIndex d) const |
| Creates single 'nk4Index' corresponding to 'NormalOrder' symmetry of {a,b,c,d}. | |
| bool | is_NormalOrdered (nkIndex a, nkIndex b, nkIndex c, nkIndex d) const |
| Checks if set {a,b,c,d} are already in NormalOrder. | |
| bool | is_NormalOrdered (const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const |
| Checks if set {a,b,c,d} are already in NormalOrder. | |
| void | write (const std::string &fname, bool verbose=true) const |
| Writes coulomb integrals to disk. | |
| bool | read (const std::string &fname, bool verbose=true) |
| Reads coulomb integrals to disk. Returns false if none read in. | |
| double * | get (int k, nk4Index index) |
| Directly gets one of the stored elements, given normal-ordered nk4Index. | |
| nk4Index | CurrentOrder (const DiracSpinor &a, const DiracSpinor &b, const DiracSpinor &c, const DiracSpinor &d) const |
| Creates single 'nk4Index', WITHOUT accounting for 'NormalOrder'. Can be used to check if {a,b,c,d} are already in 'NormalOrder'. | |
| nk4Index | CurrentOrder (nkIndex a, nkIndex b, nkIndex c, nkIndex d) const |
| Creates single 'nk4Index', WITHOUT accounting for 'NormalOrder'. Can be used to check if {a,b,c,d} are already in 'NormalOrder'. | |
| std::array< nkIndex, 4 > | UnFormIndex (const nk4Index &index) const |
| Breaks nk4Index back into {ia,ib,ic,id}. Not often used. | |
Static Public Member Functions | |
| static nk4Index | FormIndex (nkIndex a, nkIndex b, nkIndex c, nkIndex d) |
| Converts given set of nkIndex's (in any order) to nk4Index. | |
| void Coulomb::CoulombTable< S >::fill | ( | const std::vector< DiracSpinor > & | basis, |
| const YkTable & | yk, | ||
| int | k_cut = -1, |
||
| bool | print = true |
||
| ) |
Fill table with all non-zero Coulomb Q integrals from a YkTable.
Fills the table with Q^k_abcd for all orbitals in basis, exploiting the 8-fold Qk symmetry to avoid redundant calculations. Uses a precomputed yk for the radial integrals.
Filling proceeds in four stages:
| basis | Basis set of orbitals. |
| yk | Precomputed Yk table for radial integrals. |
| k_cut | Maximum multipolarity k. Set to <=0 for no cut-off. |
| If true, prints timing and summary. |
| void Coulomb::CoulombTable< S >::fill_if | ( | const std::vector< DiracSpinor > & | basis, |
| const YkTable & | yk, | ||
| const SelectionRules & | SelectionFunction, | ||
| int | k_cut = -1, |
||
| bool | print = true |
||
| ) |
Fill table with Coulomb Q integrals satisfying a selection rule.
Same as default fill(basis, yk, k_cut, print), but only computes and stores integrals for which SelectionFunction returns true. Useful for restricting to a particular subset of integrals (e.g., CI- or MBPT-relevant).
Uses the same four-stage filling strategy as fill(basis, yk, ...).
| basis | Basis set of orbitals. |
| yk | Precomputed Yk table for radial integrals. |
| SelectionFunction | Returns true for integrals to include. |
| k_cut | Maximum multipolarity k. Set to <=0 for no cut-off. |
| If true, prints timing and summary. |
| void Coulomb::CoulombTable< S >::fill | ( | const std::vector< DiracSpinor > & | basis, |
| const CoulombFunction & | Fk, | ||
| const SelectionRules & | Fk_SR, | ||
| int | k_cut = -1, |
||
| bool | print = true |
||
| ) |
Fill table using a general CoulombFunction and selection rules.
Fills the table with Fk(k,a,b,c,d) for all orbitals in basis, restricted to entries for which Fk_SR returns true, accounting for the symmetry of the table. Unlike the YkTable overloads, this version is general-purpose and does not assume Qk angular selection rules.
Uses the same four-stage filling strategy as fill(basis, yk, ...).
| basis | Basis set of orbitals. |
| Fk | Function to compute the integral value. |
| Fk_SR | Selection rule; only integrals passing this are stored. |
| k_cut | Maximum multipolarity k. Set to <=0 for no cut-off. |
| If true, prints timing and summary. |
| void Coulomb::CoulombTable< S >::update | ( | const std::vector< DiracSpinor > & | basis, |
| const CoulombFunction & | Fk, | ||
| double | damp, | ||
| bool | print = true |
||
| ) |
Re-calculate all existing table entries using a CoulombFunction.
Updates all integrals currently stored in the table by re-evaluating Fk(k,a,b,c,d) using the provided CoulombFunction() for each entry. Unlike fill(), this recalculates all existing entries and does not add new ones. Useful for iterating.
Damping: With \(\eta = \text{damp}\), integrals are updated as:
\[ Q^k_{abcd} \to \eta Q^k_{abcd} + (1-\eta) Fk(k,a,b,c,d) \]
where Fk is a CoulombFunction. \(\eta=0\) means no damping. Must be between 0 and 1 (0 is allowed, 1 is not).
| basis | Basis set of orbitals. |
| Fk | Function to compute the integral value. |
| damp | Damping factor, \(\eta \in [0,1)\). 0 means no damping. |
| If true, prints a progress bar. |
|
inline |
Gives arrow access to all underlying vector<unordered_map> functions.
| void Coulomb::CoulombTable< S >::summary | ( | ) | const |
For testing: prints details of coulomb integrals stored.
| std::size_t Coulomb::CoulombTable< S >::count | ( | ) | const |
Returns number of stored integrals.
|
inline |
Maximum k stored in table. If table is empty, returns '-1'
| void Coulomb::CoulombTable< S >::add | ( | int | k, |
| const DiracSpinor & | a, | ||
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d, | ||
| Real | value | ||
| ) |
adds a new value. Note: does nothing if {k,a,b,c,d} already exists
| void Coulomb::CoulombTable< S >::add | ( | int | k, |
| nkIndex | a, | ||
| nkIndex | b, | ||
| nkIndex | c, | ||
| nkIndex | d, | ||
| Real | value | ||
| ) |
adds a new value. Note: does nothing if {k,a,b,c,d} already exists
| void Coulomb::CoulombTable< S >::add | ( | int | k, |
| nk4Index | index, | ||
| Real | value | ||
| ) |
adds a new value. Note: does nothing if {k,a,b,c,d} already exists
| void Coulomb::CoulombTable< S >::update | ( | int | k, |
| const DiracSpinor & | a, | ||
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d, | ||
| Real | value | ||
| ) |
Updates value in table. If not present, adds new value.
| void Coulomb::CoulombTable< S >::update | ( | int | k, |
| nkIndex | a, | ||
| nkIndex | b, | ||
| nkIndex | c, | ||
| nkIndex | d, | ||
| Real | value | ||
| ) |
Updates value in table. If not present, adds new value.
| void Coulomb::CoulombTable< S >::update | ( | int | k, |
| nk4Index | index, | ||
| Real | value | ||
| ) |
Updates value in table. If not present, adds new value.
| bool Coulomb::CoulombTable< S >::contains | ( | int | k, |
| const DiracSpinor & | a, | ||
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d | ||
| ) | const |
Checks if given {k,a,b,c,d} is in the table.
| bool Coulomb::CoulombTable< S >::contains | ( | int | k, |
| nkIndex | a, | ||
| nkIndex | b, | ||
| nkIndex | c, | ||
| nkIndex | d | ||
| ) | const |
Checks if given {k,a,b,c,d} is in the table.
| bool Coulomb::CoulombTable< S >::contains | ( | int | k, |
| nk4Index | index | ||
| ) | const |
Checks if given {k,a,b,c,d} is in the table.
|
inline |
Returns true if table is empty.
| std::array< std::size_t, 4 > Coulomb::CoulombTable< S >::count_non_zero_integrals | ( | const std::vector< DiracSpinor > & | basis, |
| std::size_t | max_k = 99, |
||
| double | eF = 0.0 |
||
| ) | const |
Counts number of non-zero Coulomb integrals, accounting for symmetry
In theory, easily updated for general symmetry/selection rules, but this is usually the bottle-neck!
| double Coulomb::CoulombTable< S >::Q | ( | int | k, |
| const DiracSpinor & | a, | ||
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d | ||
| ) | const |
Retrieve a stored Q. If not present, returns 0. (Returns exactly as stored in table.)
| double Coulomb::CoulombTable< S >::Q | ( | int | k, |
| nkIndex | a, | ||
| nkIndex | b, | ||
| nkIndex | c, | ||
| nkIndex | d | ||
| ) | const |
Retrieve a stored Q. If not present, returns 0. (Returns exactly as stored in table.)
| double Coulomb::CoulombTable< S >::Q | ( | int | k, |
| nk4Index | index | ||
| ) | const |
Retrieve a stored Q. If not present, returns 0. (Returns exactly as stored in table.)
| double Coulomb::CoulombTable< S >::R | ( | int | k, |
| const DiracSpinor & | a, | ||
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d | ||
| ) | const |
Returns 'R', defined via: R := Q / (angular_coef)
| double Coulomb::CoulombTable< S >::R | ( | int | k, |
| nkIndex | a, | ||
| nkIndex | b, | ||
| nkIndex | c, | ||
| nkIndex | d | ||
| ) | const |
Returns 'R', defined via: R := Q / (angular_coef)
| double Coulomb::CoulombTable< S >::P | ( | int | k, |
| const DiracSpinor & | a, | ||
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d, | ||
| const Angular::SixJTable *const | sj = nullptr |
||
| ) | const |
Exchange integral P^k_abcd = (2k+1) sum_l {6j} Q^l_abdc.
Computes the exchange part of the antisymmetrised W = Q + P integral. Optionally uses a precomputed 6J table for faster evaluation.
| double Coulomb::CoulombTable< S >::P | ( | int | k, |
| nkIndex | a, | ||
| nkIndex | b, | ||
| nkIndex | c, | ||
| nkIndex | d, | ||
| const Angular::SixJTable *const | sj = nullptr |
||
| ) | const |
Exchange integral P^k_abcd = (2k+1) sum_l {6j} Q^l_abdc.
As P(int, const DiracSpinor&, ...) but takes nkIndex arguments.
| double Coulomb::CoulombTable< S >::P2 | ( | int | k, |
| const DiracSpinor & | a, | ||
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d, | ||
| const Angular::SixJTable & | sj, | ||
| const std::vector< double > & | fk | ||
| ) | const |
Exchange integral P^k_abcd with effective Coulomb screening.
As P(), but each l term is weighted by a screening factor fk[l].
| double Coulomb::CoulombTable< S >::W | ( | int | k, |
| const DiracSpinor & | a, | ||
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d, | ||
| const Angular::SixJTable *const | sj = nullptr |
||
| ) | const |
Antisymmetrised integral W^k_abcd = Q^k_abcd + P^k_abcd.
Returns Q + P. Optionally uses a precomputed 6J table.
| double Coulomb::CoulombTable< S >::W | ( | int | k, |
| nkIndex | a, | ||
| nkIndex | b, | ||
| nkIndex | c, | ||
| nkIndex | d, | ||
| const Angular::SixJTable *const | sj = nullptr |
||
| ) | const |
Antisymmetrised integral W^k_abcd = Q^k_abcd + P^k_abcd.
As W(int, const DiracSpinor&, ...) but takes nkIndex arguments.
| double Coulomb::CoulombTable< S >::g | ( | const DiracSpinor & | a, |
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d, | ||
| int | tma, | ||
| int | tmb, | ||
| int | tmc, | ||
| int | tmd | ||
| ) | const |
Full matrix element g_abcd with explicit magnetic quantum numbers.
Sums over k, weighted by 3j symbols, using the stored Q^k values.
| nk4Index Coulomb::CoulombTable< S >::NormalOrder | ( | const DiracSpinor & | a, |
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d | ||
| ) | const |
Creates single 'nk4Index' corresponding to 'NormalOrder' symmetry of {a,b,c,d}.
| nk4Index Coulomb::CoulombTable< S >::NormalOrder | ( | nkIndex | a, |
| nkIndex | b, | ||
| nkIndex | c, | ||
| nkIndex | d | ||
| ) | const |
Creates single 'nk4Index' corresponding to 'NormalOrder' symmetry of {a,b,c,d}.
|
inline |
Checks if set {a,b,c,d} are already in NormalOrder.
|
inline |
Checks if set {a,b,c,d} are already in NormalOrder.
| void Coulomb::CoulombTable< S >::write | ( | const std::string & | fname, |
| bool | verbose = true |
||
| ) | const |
Writes coulomb integrals to disk.
| bool Coulomb::CoulombTable< S >::read | ( | const std::string & | fname, |
| bool | verbose = true |
||
| ) |
Reads coulomb integrals to disk. Returns false if none read in.
| double * Coulomb::CoulombTable< S >::get | ( | int | k, |
| nk4Index | index | ||
| ) |
Directly gets one of the stored elements, given normal-ordered nk4Index.
| nk4Index Coulomb::CoulombTable< S >::CurrentOrder | ( | const DiracSpinor & | a, |
| const DiracSpinor & | b, | ||
| const DiracSpinor & | c, | ||
| const DiracSpinor & | d | ||
| ) | const |
Creates single 'nk4Index', WITHOUT accounting for 'NormalOrder'. Can be used to check if {a,b,c,d} are already in 'NormalOrder'.
| nk4Index Coulomb::CoulombTable< S >::CurrentOrder | ( | nkIndex | a, |
| nkIndex | b, | ||
| nkIndex | c, | ||
| nkIndex | d | ||
| ) | const |
Creates single 'nk4Index', WITHOUT accounting for 'NormalOrder'. Can be used to check if {a,b,c,d} are already in 'NormalOrder'.
|
static |
Converts given set of nkIndex's (in any order) to nk4Index.
| std::array< nkIndex, 4 > Coulomb::CoulombTable< S >::UnFormIndex | ( | const nk4Index & | index | ) | const |
Breaks nk4Index back into {ia,ib,ic,id}. Not often used.