High-precision calculations for one- and two-valence atomic systems
BSplineBasis.hpp
1#pragma once
2#include "IO/InputBlock.hpp"
3#include "LinAlg/include.hpp"
4#include "qip/String.hpp"
5#include <memory>
6#include <string>
7#include <utility>
8class DiracSpinor;
9class Wavefunction;
10class Grid;
11namespace MBPT {
12class CorrelationPotential;
13}
14namespace IO {
15class InputBlock;
16}
17
18/*!
19 @brief Constructs spinor/orbital basis using B-splines
20
21 @details
22 Uses Bsplines to form a set of B-spline orbitals (using method from [1]
23 "Derevianko", [2] "Johnson", or [3] "Fischer").
24 Diagonalises B-splines over Hamiltonian to produce a set of basis orbitals.
25
26 * [1] K. Beloy, A. Derevianko, Comput. Phys. Commun. 179, 310 (2008).
27 * [2] W. Johnson, S. Blundell, J. Sapirstein, Phys. Rev. A 37, 307 (1988).
28 * [3] C. F. Fischer and F. A. Parpia, Phys. Lett. A 179, 198 (1993).
29 * See also:
30 * Bachau et al., Reports Prog. Phys. 64, 1815 (2001).
31 * V. M. Shabaev, I. I. Tupitsyn, V. A. Yerokhin, G. Plunien, and G. Soff, Phys. Rev. Lett. 93, 130405 (2004).
32
33 By default, uses the Derevianko Dual Kintetic Balance (DKB) basis.
34
35 If \f$\{|i\rangle\}\f$ are the set of \f$2N\f$ DKB spline orbitals (of a given
36 angular symmetry), and
37 \f[
38 H_{ij} = \langle{S_i}|\hat H_{\rm HF}|{S_j}\rangle \,
39 , \qquad S_{ij} = \langle{S_i|S_j}\rangle.
40 \f]
41 The eigenvalue problem:
42 \f[
43 H_{ij}p_i = \epsilon S_{ij}p_i,
44 \f]
45 is solved, yielding \f$2N\f$ eigenvalues \f$\epsilon\f$ with corresponding
46 eigenvectors \f$p\f$ (half of these are positive energy solutions, half are
47 negative energy solutions).
48
49 Note: form_basis() does not store the eigenvectors, instead, it expands the
50 basis orbitals and stores them on the regular grid (coordinate space).
51 i.e., for each eigenvalue, n, the corresponding basis orbital is:
52 \f[
53 |{n}\rangle = \sum_i^{2N} p_i |i\rangle\,
54 \f]
55*/
56namespace SplineBasis {
57
58/*!
59 @brief B-spline construction method: Derevianko/Reno (DKB), Johnson/NotreDame, or Fischer.
60 @details
61 W. R. Johnson, S. A. Blundell, J. Sapirstein, Phys. Rev. A 37, 307 (1988).
62*/
63enum class SplineType { Derevianko, Johnson, Fischer };
64
65//! Returns the canonical name string for a SplineType.
66inline std::string_view parseSplineType(SplineType type) {
67 switch (type) {
68 case SplineType::Johnson:
69 return "Johnson";
70 case SplineType::Fischer:
71 return "Fischer";
72 case SplineType::Derevianko:
73 return "Derevianko";
74 }
75 return "UnknownSplineType";
76}
77
78/*!
79 @brief Parses a string to SplineType (case-insensitive).
80 @details
81 - Derevianko (default, aliases: reno): Dual Kinetic Balance method; K. Beloy, A. Derevianko, Comput. Phys. Commun. 179, 310 (2008).
82 - Johnson (aliases: nd, notredame, notre-dame): Notre-Dame method with explicit boundary conditions; W. R. Johnson, S. A. Blundell, J. Sapirstein, Phys. Rev. A 37, 307 (1988).
83 - Fischer (aliases: vanderbilt): rmax boundary only (no r=0 conditions); C. F. Fischer and F. A. Parpia, Phys. Lett. A 179, 198 (1993).
84*/
85inline auto parseSplineType(std::string_view type) {
86 using qip::ci_compare;
87 if (ci_compare(type, "Johnson") || ci_compare(type, "nd") ||
88 ci_compare(type, "NotreDame") || ci_compare(type, "Notre-Dame"))
89 return SplineType::Johnson;
90 if (ci_compare(type, "Fischer") || ci_compare(type, "Vanderbilt"))
91 return SplineType::Fischer;
92 if (ci_compare(type, "Derevianko") || ci_compare(type, "Reno") ||
93 type.empty())
94 return SplineType::Derevianko;
95 std::cout << "Warning: unknown SplineType '" << type
96 << "'. Defaulting to Derevianko.\n";
97 return SplineType::Derevianko;
98}
99
100//! Input parameters for B-spline basis construction.
102 Parameters() {}
103 Parameters(const std::string &states, std::size_t n, std::size_t k, double r0,
104 double reps, double rmax, const std::string &positron = "",
105 SplineType itype = SplineType::Derevianko,
106 bool in_orthogonalise = false, bool in_verbose = true);
108
109 std::string states{};
110 std::size_t n{}, k{};
111 double r0{}, reps{}, rmax{};
112 std::string positron{};
113 SplineType type{SplineType::Derevianko};
114 bool orthogonalise{false};
115 bool verbose{true};
116};
117
118//!
119/*!
120 @brief Forms and returns the basis orbitals (expanded in terms of splines).
121 @details
122 - states_str = which states to keep e.g., "25spd10f" (up to n=25 for
123 s,p,d-states, and up to n=10 for f states)
124 - n_spl: Number of splines (nb: underlying spline set is larger, see [1])
125 - k_spl: k order of the B-splines. NB: must have \f$k\geq l_{\rm max}+3\f$ [1]
126 - r0_spl: first internal knot
127 - r0_eps: sets r0_spl as r where relative core density larger than
128 r0_eps (updates r0 for each l). Typically ~1.0e-8. Set to zero to use r0_spl.
129 - rmax_spl: last internal knot (basis orbitals only non-zero before this
130 point)
131 - wf: Wavefunction object: needed to form Hartree-Fock Hamiltonian
132 - positronQ: =true will keep negative energy states (have -ve principal
133 quantum number, are appended to end of the basis std::vector). If false,
134 discards them.
135
136Note: This function calls the below functions, they rarely need to be called
137explicitely, unless you are trying to do something different to usual.
138*/
139std::vector<DiracSpinor> form_basis(const Parameters &params,
140 const Wavefunction &wf,
141 const bool correlationsQ = false);
142
143//! Compares basis to reference orbitals; checks normality, orthogonality, and energies.
144double check(const std::vector<DiracSpinor> &basis,
145 const std::vector<DiracSpinor> &orbs, bool print_warning = true);
146
147//! Type-dependent spline grid parameters for a given kappa.
149 //! first included spline index
150 std::size_t imin;
151 //! total number of splines (n_spl >= N, number of basis functions)
152 std::size_t n_spl;
153 //! one-past-last included spline index (exclusive upper bound)
154 std::size_t imax;
155 //! kinetic balance prefactor (1 for DKB, 0 for Johnson)
157};
158//! Returns SplineParams for the given type, kappa, and number of states.
159SplineParams spline_params(SplineType type, int kappa, std::size_t n_states);
160
161//! Forms the underlying spline basis (which is not kept)
162std::pair<std::vector<DiracSpinor>, std::vector<DiracSpinor>> form_spline_basis(
163 const int kappa, const std::size_t n_states, const std::size_t k_spl,
164 const double r0_spl, const double rmax_spl, std::shared_ptr<const Grid> rgrid,
165 const double alpha, SplineType itype = SplineType::Derevianko);
166
167//! Calculates and returns the Hamiltonian matrix H_ij and overlap matrix S_ij.
168std::pair<LinAlg::Matrix<double>, LinAlg::Matrix<double>>
169fill_Hamiltonian_matrix(const std::vector<DiracSpinor> &spl_basis,
170 const std::vector<DiracSpinor> &d_basis,
171 const Wavefunction &wf,
172 const bool correlationsQ = false,
173 SplineType itype = SplineType::Derevianko);
174
175/*!
176 @brief Applies Johnson/Notre-Dame boundary conditions to the Hamiltonian matrix.
177 @details
178 Adds r=0 and r=rmax boundary terms to enforce correct asymptotic behaviour.
179 W. R. Johnson, S. A. Blundell, J. Sapirstein, Phys. Rev. A 37, 307 (1988).
180*/
181void add_JohnsonBoundary(LinAlg::Matrix<double> *Aij, const int kappa,
182 const double alpha);
183
184/*!
185 @brief Applies Fischer/Vanderbilt rmax boundary: forces f(rmax)=g(rmax).
186 @details
187 Subset of add_JohnsonBoundary (rmax terms only; no r=0 conditions).
188*/
189void add_FischerBoundary(LinAlg::Matrix<double> *Aij, const double alpha);
190
191//! Expands basis orbitals in terms of spline orbitals by diagonalising Hamiltonian.
192void expand_basis_orbitals(std::vector<DiracSpinor> *basis,
193 std::vector<DiracSpinor> *basis_positron,
194 const std::vector<DiracSpinor> &spl_basis,
195 const int kappa, const int max_n, int max_n_positron,
196 const LinAlg::Vector<double> &e_values,
197 const LinAlg::Matrix<double> &e_vectors,
198 const Wavefunction &wf);
199
200//! TKR sum rule (basis test); should =0 (must include -ve energy states)
201std::vector<double> sumrule_TKR(const std::vector<DiracSpinor> &basis,
202 const std::vector<double> &r,
203 bool print = false);
204
205//! Drake-Gordon sum rule (basis test); should =0 (must incl -ve energy states)
206std::vector<double> sumrule_DG(int nDG, const std::vector<DiracSpinor> &basis,
207 const Grid &gr, double alpha, bool print);
208
209//! Measures radial completeness of the basis for orbital Fv.
210std::pair<double, double> r_completeness(const DiracSpinor &Fv,
211 const std::vector<DiracSpinor> &basis,
212 const Grid &gr, bool print = false);
213
214//! Prints the title and column headers for r_completeness output.
216 std::printf("Completeness (radial sum rules):\n");
217 std::printf(" <a|a> = sum_n <a|r|n><n|1/r|a> [= 1]\n");
218 std::printf(" <a|r2|a> = sum_n <a|r|n><n|r|a> [= <a|r^2|a>_HF]\n");
219 std::printf("%-4s %7s [%7s] %6s | %10s [%10s] %6s\n", "St", "sum1", "1",
220 "eps", "sum_r2", "<r2>_HF", "eps");
221}
222} // namespace SplineBasis
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:42
Non-uniform radial grid with Jacobian, suitable for atomic structure calculations.
Definition Grid.hpp:85
Holds a named list of key=value options and nested InputBlocks.
Definition InputBlock.hpp:154
Row-major dense matrix with arithmetic and linear algebra support.
Definition Matrix.hpp:209
Owning 1D array; inherits from Matrix<T> with a single column.
Definition Vector.hpp:25
Stores Wavefunction (set of valence orbitals, grid, HF etc.)
Definition Wavefunction.hpp:37
In-out (timers, profilers, and read/write data)
Definition ChronoTimer.hpp:9
Many-body perturbation theory.
Definition CI_Integrals.hpp:10
Constructs spinor/orbital basis using B-splines.
Definition BSplineBasis.cpp:20
std::pair< double, double > r_completeness(const DiracSpinor &Fa, const std::vector< DiracSpinor > &basis, const Grid &gr, bool print)
Measures radial completeness of the basis for orbital Fv.
Definition BSplineBasis.cpp:503
std::vector< double > sumrule_DG(int nDG, const std::vector< DiracSpinor > &basis, const Grid &gr, double alpha, bool print)
Drake-Gordon sum rule (basis test); should =0 (must incl -ve energy states)
Definition BSplineBasis.cpp:454
std::pair< std::vector< DiracSpinor >, std::vector< DiracSpinor > > form_spline_basis(const int kappa, const std::size_t N_states, const std::size_t k_spl, const double r0_spl, const double rmax_spl, std::shared_ptr< const Grid > rgrid, const double alpha, SplineType type)
Forms the underlying spline basis (which is not kept)
Definition BSplineBasis.cpp:206
std::size_t n_spl
total number of splines (n_spl >= N, number of basis functions)
Definition BSplineBasis.hpp:152
std::pair< LinAlg::Matrix< double >, LinAlg::Matrix< double > > fill_Hamiltonian_matrix(const std::vector< DiracSpinor > &spl_basis, const std::vector< DiracSpinor > &d_basis, const Wavefunction &wf, const bool correlationsQ, SplineType type)
Calculates and returns the Hamiltonian matrix H_ij and overlap matrix S_ij.
Definition BSplineBasis.cpp:269
std::vector< double > sumrule_TKR(const std::vector< DiracSpinor > &basis, const std::vector< double > &r, bool print)
TKR sum rule (basis test); should =0 (must include -ve energy states)
Definition BSplineBasis.cpp:418
double check(const std::vector< DiracSpinor > &basis, const std::vector< DiracSpinor > &orbs, bool print_warning)
Compares basis to reference orbitals; checks normality, orthogonality, and energies.
Definition BSplineBasis.cpp:132
std::vector< DiracSpinor > form_basis(const Parameters &params, const Wavefunction &wf, const bool correlationsQ)
Forms and returns the basis orbitals (expanded in terms of splines).
Definition BSplineBasis.cpp:51
double lambda_DKB
kinetic balance prefactor (1 for DKB, 0 for Johnson)
Definition BSplineBasis.hpp:156
std::size_t imax
one-past-last included spline index (exclusive upper bound)
Definition BSplineBasis.hpp:154
void add_FischerBoundary(LinAlg::Matrix< double > *pAij, const double alpha)
Applies Fischer/Vanderbilt rmax boundary: forces f(rmax)=g(rmax).
Definition BSplineBasis.cpp:345
SplineType
B-spline construction method: Derevianko/Reno (DKB), Johnson/NotreDame, or Fischer.
Definition BSplineBasis.hpp:63
void add_JohnsonBoundary(LinAlg::Matrix< double > *pAij, const int kappa, const double alpha)
Applies Johnson/Notre-Dame boundary conditions to the Hamiltonian matrix.
Definition BSplineBasis.cpp:326
SplineParams spline_params(SplineType type, int kappa, std::size_t N_states)
Returns SplineParams for the given type, kappa, and number of states.
Definition BSplineBasis.cpp:189
void expand_basis_orbitals(std::vector< DiracSpinor > *basis, std::vector< DiracSpinor > *basis_positron, const std::vector< DiracSpinor > &spl_basis, const int kappa, const int max_n, int max_n_positron, const LinAlg::Vector< double > &e_values, const LinAlg::Matrix< double > &e_vectors, const Wavefunction &wf)
Expands basis orbitals in terms of spline orbitals by diagonalising Hamiltonian.
Definition BSplineBasis.cpp:357
std::size_t imin
first included spline index
Definition BSplineBasis.hpp:150
std::string_view parseSplineType(SplineType type)
Returns the canonical name string for a SplineType.
Definition BSplineBasis.hpp:66
void r_completeness_header()
Prints the title and column headers for r_completeness output.
Definition BSplineBasis.hpp:215
Type-dependent spline grid parameters for a given kappa.
Definition BSplineBasis.hpp:148
bool ci_compare(std::string_view s1, std::string_view s2)
Case-insensitive string comparison; equivalent to tolower(s1) == tolower(s2).
Definition String.hpp:143
Input parameters for B-spline basis construction.
Definition BSplineBasis.hpp:101