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>
8#include <vector>
9class DiracSpinor;
10class Wavefunction;
11class Grid;
12namespace MBPT {
13class CorrelationPotential;
14}
15namespace IO {
16class InputBlock;
17}
18
19/*!
20 @brief Constructs spinor/orbital basis using B-splines
21
22 @details
23 Uses Bsplines to form a set of B-spline orbitals (using method from [1]
24 "Derevianko", [2] "Shabaev", [3] "Johnson", or [4] "Fischer", or the
25 "Hybrid" of [1] and [3]; see SplineType).
26 Diagonalises B-splines over Hamiltonian to produce a set of basis orbitals.
27
28 * [1] K. Beloy, A. Derevianko, Comput. Phys. Commun. 179, 310 (2008).
29 * [2] V. M. Shabaev, I. I. Tupitsyn, V. A. Yerokhin, G. Plunien, and G. Soff,
30 Phys. Rev. Lett. 93, 130405 (2004).
31 * [3] W. Johnson, S. Blundell, J. Sapirstein, Phys. Rev. A 37, 307 (1988).
32 * [4] C. F. Fischer and F. A. Parpia, Phys. Lett. A 179, 198 (1993).
33 * See also:
34 * Bachau et al., Reports Prog. Phys. 64, 1815 (2001).
35
36 By default, uses the Derevianko Dual Kinetic Balance (DKB) basis.
37
38 If \f$\{|i\rangle\}\f$ are the set of spline orbitals (of a given angular
39 symmetry; \f$2N\f$ of them, except Fischer with \f$\kappa>0\f$, see
40 spline_params), and
41 \f[
42 H_{ij} = \langle{S_i}|\hat H_{\rm HF}|{S_j}\rangle \,
43 , \qquad S_{ij} = \langle{S_i|S_j}\rangle.
44 \f]
45 The eigenvalue problem:
46 \f[
47 H_{ij}p_j = \epsilon S_{ij}p_j,
48 \f]
49 is solved, yielding one eigenvalue \f$\epsilon\f$ (with eigenvector
50 \f$p\f$) for each spline orbital: roughly half are positive-energy
51 solutions, and half negative-energy solutions.
52
53 Note: form_basis() does not store the eigenvectors, instead, it expands the
54 basis orbitals and stores them on the regular grid (coordinate space).
55 i.e., for each eigenvalue, n, the corresponding basis orbital is:
56 \f[
57 |{n}\rangle = \sum_i p_i |i\rangle\,
58 \f]
59*/
60namespace SplineBasis {
61
62/*!
63 @brief B-spline construction method (see details).
64
65 @details
66 - Derevianko (Reno): dual kinetic balance (DKB) splines; the first |kappa|
67 and the last spline are dropped, so the B-spline parts vanish at both
68 ends of the cavity (the kinetic-balance parts need not).
69 K. Beloy, A. Derevianko, Comput. Phys. Commun. 179, 310 (2008).
70 - Shabaev: DKB splines; the first and last spline are dropped, for all
71 kappa, with no boundary terms (as published: dropping more at r = 0 for
72 |kappa| >= 2 was found to make practically no difference).
73 V. M. Shabaev, I. I. Tupitsyn, V. A. Yerokhin, G. Plunien, and G. Soff,
74 Phys. Rev. Lett. 93, 130405 (2004).
75 - Johnson (Notre Dame): plain splines for f and g (no kinetic balance),
76 all kept; the boundary conditions f(0) = 0 and f(R) = -g(R) (MIT bag)
77 are imposed through boundary terms in the Hamiltonian matrix.
78 W. R. Johnson, S. A. Blundell, J. Sapirstein, Phys. Rev. A 37, 307
79 (1988).
80 - Fischer: plain splines (no kinetic balance); the first and
81 last spline are dropped (f = g = 0 at both ends), with no boundary
82 terms. For kappa > 0, the second spline is also dropped from f
83 (f'(0) = 0), which removes the spurious state found by Fischer and
84 Parpia for kappa = 1.
85 C. F. Fischer and F. A. Parpia, Phys. Lett. A 179, 198 (1993).
86 - Hybrid: DKB splines; the first |kappa| are dropped (as for
87 Derevianko), but the last is kept, and the Johnson rmax (MIT bag)
88 boundary term f(R) = -g(R) is imposed (see add_rmaxBoundary). Differs
89 from Derevianko only in the boundary condition at rmax.
90
91 See parseSplineType for the input strings.
92
93 @warning Fischer: bound states are accurate, but the pseudo-continuum
94 (cavity) states are not reliable: they disagree with those of the other
95 types, and for kappa > 0 some lie below the corresponding free-atom
96 energies. May not be suitable for MBPT; intended for testing only.
97*/
98enum class SplineType { Derevianko, Shabaev, Johnson, Fischer, Hybrid };
99
100//! Returns the canonical name string for a SplineType.
101inline std::string_view parseSplineType(SplineType type) {
102 switch (type) {
103 case SplineType::Johnson:
104 return "Johnson";
105 case SplineType::Fischer:
106 return "Fischer";
107 case SplineType::Hybrid:
108 return "Hybrid";
109 case SplineType::Shabaev:
110 return "Shabaev";
111 case SplineType::Derevianko:
112 return "Derevianko";
113 }
114 return "UnknownSplineType";
115}
116
117/*!
118 @brief Parses a string to SplineType (case-insensitive).
119
120 @details
121 - Derevianko (default; aliases: reno, dkb)
122 - Shabaev
123 - Johnson (aliases: nd, notredame, notre-dame)
124 - Fischer
125 - Hybrid
126
127 See SplineType for a description of each.
128
129 @return The SplineType; Derevianko if @p type is empty.
130
131 @warning An unrecognised @p type prints a warning and returns Derevianko.
132*/
133inline auto parseSplineType(std::string_view type) {
134 using qip::ci_compare;
135 if (ci_compare(type, "Johnson") || ci_compare(type, "nd") ||
136 ci_compare(type, "NotreDame") || ci_compare(type, "Notre-Dame"))
137 return SplineType::Johnson;
138 if (ci_compare(type, "Fischer"))
139 return SplineType::Fischer;
140 if (ci_compare(type, "Hybrid"))
141 return SplineType::Hybrid;
142 if (ci_compare(type, "Shabaev"))
143 return SplineType::Shabaev;
144 if (ci_compare(type, "Derevianko") || ci_compare(type, "Reno") ||
145 ci_compare(type, "DKB") || type.empty())
146 return SplineType::Derevianko;
147 std::cout << "Warning: unknown SplineType '" << type
148 << "'. Defaulting to Derevianko.\n";
149 return SplineType::Derevianko;
150}
151
152/*!
153 @brief Default first internal knot, r0, for each l, for the given type.
154
155 @details
156 Element l is the first knot for orbital angular momentum l; the last
157 element is used for all higher l (see form_basis).
158 - Dual-kinetic-balance types (Derevianko, Shabaev, Hybrid): 1e-4 for all l
159 - Types without kinetic balance (Johnson, Fischer): 3e-4 for s, 1e-4 for
160 p, 1e-3 for d and f, 1e-2 for higher l. As in Johnson et al. (Table
161 III), the first knot is moved out for higher l, since these orbitals are
162 negligible close to the nucleus, which improves the knot distribution.
163 The s and p values give the most accurate hyperfine constants and
164 Drake-Goldman sum rules for Cs (see the basis tests); in particular, a
165 first s knot at 1e-4 degrades the s-state hyperfine constants.
166*/
167std::vector<double> default_r0(SplineType type);
168
169//! Input parameters for B-spline basis construction (see form_basis).
171 //! Default: all parameters empty/zero
173 //! Sets each parameter directly (see form_basis); empty r0: default_r0
174 Parameters(const std::string &states, std::size_t n, std::size_t k,
175 std::vector<double> r0, double rmax,
176 const std::string &positron = "",
177 SplineType itype = SplineType::Derevianko,
178 bool in_orthogonalise = false, bool in_verbose = true);
179 /*!
180 @brief Reads parameters from an input block.
181
182 @details
183 Input keys [defaults]: states [""], number (n) [30], order (k) [7],
184 r0 [default_r0(type); comma-separated list, one for each l], rmax [40.0],
185 positron [""], type [Derevianko], orthogonalise [false], verbose [true].
186 */
188
189 //! Electron states to keep, e.g., "25spd10f"
190 std::string states{};
191 //! Number of splines (n), and order of the B-splines (k)
192 std::size_t n{}, k{};
193 //! First internal knot for each l (last entry for higher l); empty: default
194 std::vector<double> r0{};
195 //! Last knot (rmax)
196 double rmax{};
197 //! Negative-energy states to keep, e.g., "9spdf" (empty: none)
198 std::string positron{};
199 //! B-spline construction method
200 SplineType type{SplineType::Derevianko};
201 //! Force orthogonal to core (spectrum: to valence); done by Wavefunction
202 bool orthogonalise{false};
203 //! Print construction details to screen
204 bool verbose{true};
205};
206
207/*!
208 @brief Forms and returns the basis orbitals (expanded in terms of splines).
209
210 @details
211 Members of @p params:
212 - states = which states to keep e.g., "25spd10f" (up to n=25 for
213 s,p,d-states, and up to n=10 for f states)
214 - n: Number of splines (the underlying spline set may be larger; see
215 spline_params)
216 - k: k order of the B-splines. NB: must have \f$k\geq l_{\rm max}+3\f$ [1]
217 - r0: first internal knot, for each l: r0[l] is used for orbital angular
218 momentum l, and the last entry for all higher l (so a single value
219 applies to all l). Empty: default_r0(type). Values below the first grid
220 point are replaced by it.
221 - rmax: last knot (basis orbitals only non-zero before this point)
222 - positron: basis string giving the number of negative-energy states to
223 keep for each kappa (e.g., "9spdf" keeps 9 of each). Those closest to
224 -2mc^2 are kept. They are labelled with n continuing on from the
225 positive-energy solutions (so {n,kappa} stays unique), are flagged
226 (DiracSpinor::negativeEnergyStateQ), and are appended to the end of the
227 basis std::vector. Empty string discards them. Must be a subset of states.
228 A warning is also printed if any label is too large for DiracSpinor::nk_index (n > 256;
229 e.g., many splines with many negative-energy states kept).
230 - type: B-spline construction method (see SplineType)
231 - verbose: print construction details to screen
232 - orthogonalise: not used here (see Wavefunction::formBasis)
233
234 @param params Basis parameters (see above)
235 @param wf Wavefunction object: needed to form Hartree-Fock
236 Hamiltonian
237 @param correlationsQ If true, includes the correlation potential (Sigma)
238 of @p wf in the Hamiltonian (if it exists)
239
240 @return Basis orbitals: electron states for each kappa (in the order of
241 @p params.states, increasing n), followed by any negative-energy
242 states.
243
244 @note This function calls the below functions, they rarely need to be
245 called explicitly, unless you are trying to do something different
246 to usual.
247*/
248std::vector<DiracSpinor> form_basis(const Parameters &params,
249 const Wavefunction &wf,
250 const bool correlationsQ = false);
251
252/*!
253 @brief Checks basis against orbitals: normality, orthogonality, and energies.
254
255 @details
256 For each orbital in @p orbs with a matching basis state (same n and kappa),
257 finds the worst \f$ ||\langle a|b\rangle| - 1| \f$ and relative energy
258 difference, \f$ |(\varepsilon_b - \varepsilon_a)/\varepsilon_b| \f$. Also
259 finds the worst orthonormality between @p orbs and @p basis states of the
260 same kappa (see DiracSpinor::check_ortho). Prints each, and lists basis
261 states with opposite sign to the matching orbital.
262
263 @param basis Basis orbitals
264 @param orbs Reference orbitals (e.g., core or valence)
265 @param print_warning Flag printed results worse than 1e-3
266
267 @return Largest of the three deviations; 0 (prints nothing) if @p orbs is
268 empty.
269*/
270double check(const std::vector<DiracSpinor> &basis,
271 const std::vector<DiracSpinor> &orbs, bool print_warning = true);
272
273//! Type-dependent spline selection for a given kappa (see spline_params).
275 //! total number of underlying B-splines
276 std::size_t n_spl;
277 //! f-like splines kept: indices [imin_f, imax_f)
278 std::size_t imin_f, imax_f;
279 //! g-like splines kept: indices [imin_g, imax_g)
280 std::size_t imin_g, imax_g;
281 //! kinetic balance prefactor (1 for DKB types, 0 for Johnson, Fischer)
283 //! number of f-like splines kept
284 std::size_t num_f() const { return imax_f - imin_f; }
285 //! number of g-like splines kept
286 std::size_t num_g() const { return imax_g - imin_g; }
287};
288
289/*!
290 @brief Returns SplineParams for the given type, kappa, and number of states.
291
292 @details
293 Of the n_spl underlying B-splines, @p n_states are kept for each of f and
294 g (indices [imin_f, imax_f) and [imin_g, imax_g)):
295 - Johnson : all; no kinetic balance
296 - Fischer : drops the first and the last; no kinetic balance. For
297 kappa > 0, the second is also dropped from f (f'(0) = 0),
298 which removes the spurious kappa = 1 state found by Fischer
299 and Parpia; f then has @p n_states - 1 splines
300 - Hybrid : drops the first |kappa|; kinetic balance
301 - Shabaev : drops the first and the last; kinetic balance
302 - Derevianko : drops the first |kappa| and the last; kinetic balance
303*/
304SplineParams spline_params(SplineType type, int kappa, std::size_t n_states);
305
306//! Values at r of the two spline spinors built from one B-spline B_i
308 //! f-like spinor (f = B_i): f, g, and their radial derivatives
309 double f_f, g_f, df_f, dg_f;
310 //! g-like spinor (g = B_i): f, g, and their radial derivatives
311 double f_g, g_g, df_g, dg_g;
312};
313
314/*!
315 @brief Values at r of the f-like and g-like spline spinors built from B_i.
316
317 @details
318 See form_spline_basis: the f-like spinor has f = B_i and
319 g = kb (B_i' + kappa B_i/r); the g-like spinor has g = B_i and
320 f = kb (B_i' - kappa B_i/r), where kb = lambda alpha/2 is the kinetic
321 balance factor (zero without kinetic balance).
322
323 @param B B_i(r)
324 @param dB B_i'(r)
325 @param d2B B_i''(r)
326 @param kappa Dirac quantum number
327 @param r Radius (> 0)
328 @param kb Kinetic balance factor, lambda alpha/2
329*/
330SplineSpinorValues spline_spinor_values(double B, double dB, double d2B,
331 int kappa, double r, double kb);
332
333//! The spline spinors for one kappa (see form_spline_basis)
335 //! Spline spinors on the radial grid: f-like, then g-like
336 std::vector<DiracSpinor> basis{};
337 //! Radial derivatives (d/dr of both f and g) of the spline spinors
338 std::vector<DiracSpinor> d_basis{};
339 //! f and g of each spline spinor exactly at rmax (for boundary terms)
340 std::vector<double> f_rmax{}, g_rmax{};
341};
342
343/*!
344 @brief Forms the underlying spline basis (which is not kept).
345
346 @details
347 Forms the spline spinors for given kappa from the B-splines \f$B_i\f$
348 selected by spline_params: \f$N_f\f$ "f-like" followed by \f$N_g\f$
349 "g-like" (both equal to @p n_states, except Fischer with kappa > 0),
350 \f[
351 S_i = \begin{pmatrix} B_i \\
352 \frac{\lambda\alpha}{2}\left(B_i' + \frac{\kappa}{r}B_i\right)
353 \end{pmatrix},
354 \qquad
355 S_{N_f+i} = \begin{pmatrix}
356 \frac{\lambda\alpha}{2}\left(B_i' - \frac{\kappa}{r}B_i\right) \\ B_i
357 \end{pmatrix},
358 \f]
359 where \f$\lambda\f$ is the kinetic balance prefactor (SplineParams). Knots
360 are distributed log-linearly between @p r0_spl and @p rmax_spl, with the
361 end points (0 and rmax) repeated k times: only the first spline is
362 non-zero at r = 0, and only the last at r = rmax.
363
364 @param kappa Dirac quantum number
365 @param n_states Number of splines, N, of each type (f-like and g-like;
366 N-1 f-like for Fischer with kappa > 0)
367 @param k_spl Order of the B-splines
368 @param r0_spl First internal knot
369 @param rmax_spl Last knot (splines are zero beyond this point)
370 @param rgrid Radial grid the splines are stored on
371 @param alpha Fine-structure constant
372 @param itype B-spline construction method
373
374 @return The N_f + N_g spline spinors, their radial derivatives (d/dr of
375 both f and g), and the values of f and g of each exactly at rmax
376 (which is generally between grid points).
377*/
378SplineSpinors form_spline_basis(const int kappa, const std::size_t n_states,
379 const std::size_t k_spl, const double r0_spl,
380 const double rmax_spl,
381 std::shared_ptr<const Grid> rgrid,
382 const double alpha,
383 SplineType itype = SplineType::Derevianko);
384
385/*!
386 @brief Calculates and returns the Hamiltonian matrix H_ij and overlap S_ij.
387
388 @details
389 \f$ H_{ij} = \langle S_i|\hat H|S_j\rangle \f$ and
390 \f$ S_{ij} = \langle S_i|S_j\rangle \f$, over the spline basis. The
391 Hamiltonian is that of @p wf: the local part (see Wavefunction::H0ab),
392 plus Hartree-Fock exchange (if non-local), Breit (if included in @p wf),
393 and Sigma (if @p correlationsQ and @p wf has Sigma). For Johnson and
394 Hybrid types, also adds the boundary terms (see add_JohnsonBoundary and
395 add_rmaxBoundary).
396
397 @param splines Spline spinors (see form_spline_basis)
398 @param wf Wavefunction: provides the Hamiltonian
399 @param correlationsQ Include the correlation potential (Sigma) of @p wf
400 @param itype B-spline construction method (sets boundary terms)
401
402 @return Pair {H_ij, S_ij}.
403*/
404std::pair<LinAlg::Matrix<double>, LinAlg::Matrix<double>>
405fill_Hamiltonian_matrix(const SplineSpinors &splines, const Wavefunction &wf,
406 const bool correlationsQ = false,
407 SplineType itype = SplineType::Derevianko);
408
409/*!
410 @brief Applies Johnson/Notre-Dame boundary conditions to Hamiltonian matrix.
411
412 @details
413 Adds the boundary term of the action, S' [Eq. (10) of Johnson et al.],
414 together with the surface term \f$\frac{c}{2}[fg]_0^R\f$ by which the
415 symmetric kinetic matrix (Wavefunction::H0ab) differs from the
416 antisymmetrised form of Johnson et al. [Eq. (7)], so that f(0) = 0 and
417 f(R) = -g(R) [MIT bag, P(R) = Q(R); g = -Q here] become the natural
418 boundary conditions. Only the first spline is non-zero at r = 0
419 (B_1(0) = 1), and f(R), g(R) are those of the spline spinors at rmax (see
420 add_rmaxBoundary):
421 \f[
422 S' + \frac{c}{2}[fg]_0^R =
423 \frac{c}{2} f(0)^2 \ [\kappa<0] \ {\rm or}\ c^2 f(0)^2 \ [\kappa>0]
424 + \frac{c}{4}\left[f(R)^2 - g(R)^2\right] + \frac{c}{2} f(R) g(R),
425 \f]
426 (the f(0)g(0) terms cancel). The matrix gets its second derivatives. The
427 cancellation is exact analytically; on the radial grid it holds only to the
428 accuracy of the quadrature at the cavity ends.
429 W. R. Johnson, S. A. Blundell, J. Sapirstein, Phys. Rev. A 37, 307 (1988).
430
431 @param Aij Hamiltonian matrix, 2N x 2N (N f-like splines, then N
432 g-like); updated in place
433 @param kappa Dirac quantum number
434 @param alpha Fine-structure constant
435 @param f_rmax f(rmax) of each spline spinor (see SplineSpinors)
436 @param g_rmax g(rmax) of each spline spinor
437*/
438void add_JohnsonBoundary(LinAlg::Matrix<double> *Aij, const int kappa,
439 const double alpha, const std::vector<double> &f_rmax,
440 const std::vector<double> &g_rmax);
441
442/*!
443 @brief Applies the rmax (MIT bag) boundary term only: f(R) = -g(R).
444
445 @details
446 The r = R part of add_JohnsonBoundary (no r = 0 term); also used alone for
447 the Hybrid type. With \f$f(R) = \sum_i p_i u_i\f$ and
448 \f$g(R) = \sum_i p_i w_i\f$, where \f$u_i\f$, \f$w_i\f$ are f and g of
449 spline spinor i at R, adds the second derivatives of
450 \f[
451 \frac{c}{4}\left[f(R)^2 - g(R)^2\right] + \frac{c}{2} f(R) g(R):
452 \quad
453 \frac{c}{2}\left(u_iu_j - w_iw_j + u_iw_j + w_iu_j\right).
454 \f]
455 Without kinetic balance (Johnson), only the last f-like (u = 1) and last
456 g-like (w = 1) spinors are non-zero at R. With kinetic balance (Hybrid),
457 the kinetic-balance parts of the last two splines of each set also
458 contribute, so these are included.
459
460 @param Aij Hamiltonian matrix (f-like spinors, then g-like); updated in
461 place
462 @param alpha Fine-structure constant
463 @param f_rmax f(rmax) of each spline spinor (see SplineSpinors)
464 @param g_rmax g(rmax) of each spline spinor
465*/
466void add_rmaxBoundary(LinAlg::Matrix<double> *Aij, const double alpha,
467 const std::vector<double> &f_rmax,
468 const std::vector<double> &g_rmax);
469
470/*!
471 @brief Expands basis orbitals in terms of spline orbitals.
472
473 @details
474 Basis orbitals are formed from the eigenvectors of the Hamiltonian.
475 Keeps the electron states up to n = @p max_n (labelled n = l+1, l+2, ...,
476 from the bottom of the positive-energy branch up), and the
477 @p max_n_positron negative-energy states closest to the gap (labelled with
478 n continuing on from the positive-energy solutions, and flagged).
479
480 Each orbital is normalised, with sign chosen so that f is positive at
481 small r.
482
483 @param basis Electron states are appended to this
484 @param basis_positron Negative-energy states are appended to this
485 @param spl_basis Spline basis the eigenvectors are expressed in
486 @param kappa Dirac quantum number
487 @param max_n Maximum n of electron states kept
488 @param max_n_positron Number of negative-energy states kept
489 @param e_values Eigenvalues (ascending)
490 @param e_vectors Eigenvectors: e_vectors[i] corresponds to e_values[i]
491 @param wf Wavefunction: provides grid and alpha
492
493 @note States whose norm differs from 1 by more than 1e-4 are treated as
494 spurious: a warning is printed, and the orbital is set to zero (but
495 is still kept).
496*/
497void expand_basis_orbitals(std::vector<DiracSpinor> *basis,
498 std::vector<DiracSpinor> *basis_positron,
499 const std::vector<DiracSpinor> &spl_basis,
500 const int kappa, const int max_n, int max_n_positron,
501 const LinAlg::Vector<double> &e_values,
502 const LinAlg::Matrix<double> &e_vectors,
503 const Wavefunction &wf);
504
505/*!
506 @brief TKR sum rule (basis test); should be zero (needs -ve energy states).
507
508 @details
509 Thomas-Kuhn-Reiche sum rule. With a the first state in @p basis, for each
510 l up to the maximum l in @p basis:
511 \f[
512 \sum_n \frac{w_n}{2l+1} (\varepsilon_n - \varepsilon_a)
513 \langle a|r|n\rangle^2 = 0,
514 \f]
515 summed over basis states with \f$\kappa_n = l\f$ (\f$w_n = l\f$) and
516 \f$\kappa_n = -l-1\f$ (\f$w_n = l+1\f$), where
517 \f$\langle a|r|n\rangle\f$ is the radial integral.
518
519 @param basis Basis orbitals (including negative-energy states)
520 @param r Radial grid points
521 @param print Print electron and negative-energy contributions, for each l
522
523 @return The sum, for each l; empty if @p basis is empty.
524*/
525std::vector<double> sumrule_TKR(const std::vector<DiracSpinor> &basis,
526 const std::vector<double> &r,
527 bool print = false);
528
529/*!
530 @brief Drake-Goldman sum rules (basis test); should be zero.
531
532 @details
533 Must include negative-energy states in @p basis.
534 For each kappa in @p basis (a: the first basis state with that kappa):
535 \f[
536 \frac{1}{2j_a+1}\sum_n (\varepsilon_n - \varepsilon_a)^{m}
537 |\langle a||r||n\rangle|^2
538 \f]
539 where m = @p nDG, compared with its exact value:
540 \f$\langle a|r^2|a\rangle\f$ (m=0) or 0 (m=1). For m=2, the sum is scaled
541 by \f$\alpha^2/3\f$, and compared with 1. Kappas with l equal to the
542 maximum l in @p basis are skipped (no l+1 states to sum over).
543
544 @param nDG Power of the energy difference, m: 0, 1, or 2
545 @param basis Basis orbitals (including negative-energy states)
546 @param gr Radial grid
547 @param alpha Fine-structure constant
548 @param print Print sum, exact value, and difference, for each kappa
549
550 @return Sum minus exact value, for each kappa included. Kappas not present
551 in @p basis (e.g., p states for "20s5d") are skipped.
552*/
553std::vector<double> sumrule_DG(int nDG, const std::vector<DiracSpinor> &basis,
554 const Grid &gr, double alpha, bool print);
555
556/*!
557 @brief Measures radial completeness of the basis for orbital Fv.
558
559 @details
560 Sums over basis states n with the same kappa as @p Fv:
561 \f[
562 \sum_n \langle v|r|n\rangle\langle n|r^{-1}|v\rangle = 1, \qquad
563 \sum_n \langle v|r|n\rangle\langle n|r|v\rangle = \langle v|r^2|v\rangle,
564 \f]
565 where the matrix elements are radial integrals.
566
567 @param Fv Orbital to test
568 @param basis Basis orbitals
569 @param gr Radial grid
570 @param print Print one line of results (see r_completeness_header)
571
572 @return Relative deviation of each sum from its exact value.
573*/
574std::pair<double, double> r_completeness(const DiracSpinor &Fv,
575 const std::vector<DiracSpinor> &basis,
576 const Grid &gr, bool print = false);
577
578//! Prints the title and column headers for r_completeness output.
580 std::printf("Completeness (radial sum rules):\n");
581 std::printf(" <a|a> = sum_n <a|r|n><n|1/r|a> [= 1]\n");
582 std::printf(" <a|r2|a> = sum_n <a|r|n><n|r|a> [= <a|r^2|a>_HF]\n");
583 std::printf("%-4s %7s [%7s] %6s | %10s [%10s] %6s\n", "St", "sum1", "1",
584 "eps", "sum_r2", "<r2>_HF", "eps");
585}
586} // namespace SplineBasis
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:55
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:208
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:48
In-out (timers, profilers, and read/write data)
Definition ChronoTimer.hpp:9
Many-body perturbation theory.
Definition MatrixElements.hpp:12
Constructs spinor/orbital basis using B-splines.
Definition BSplineBasis.cpp:21
std::vector< DiracSpinor > d_basis
Radial derivatives (d/dr of both f and g) of the spline spinors.
Definition BSplineBasis.hpp:338
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:639
std::vector< double > sumrule_DG(int nDG, const std::vector< DiracSpinor > &basis, const Grid &gr, double alpha, bool print)
Drake-Goldman sum rules (basis test); should be zero.
Definition BSplineBasis.cpp:586
SplineSpinorValues spline_spinor_values(double B, double dB, double d2B, int kappa, double r, double kb)
Values at r of the f-like and g-like spline spinors built from B_i.
Definition BSplineBasis.cpp:274
double f_g
g-like spinor (g = B_i): f, g, and their radial derivatives
Definition BSplineBasis.hpp:311
void add_JohnsonBoundary(LinAlg::Matrix< double > *pAij, const int kappa, const double alpha, const std::vector< double > &f_rmax, const std::vector< double > &g_rmax)
Applies Johnson/Notre-Dame boundary conditions to Hamiltonian matrix.
Definition BSplineBasis.cpp:426
std::vector< double > f_rmax
f and g of each spline spinor exactly at rmax (for boundary terms)
Definition BSplineBasis.hpp:340
std::vector< DiracSpinor > basis
Spline spinors on the radial grid: f-like, then g-like.
Definition BSplineBasis.hpp:336
void add_rmaxBoundary(LinAlg::Matrix< double > *pAij, const double alpha, const std::vector< double > &f_rmax, const std::vector< double > &g_rmax)
Applies the rmax (MIT bag) boundary term only: f(R) = -g(R).
Definition BSplineBasis.cpp:441
std::vector< double > sumrule_TKR(const std::vector< DiracSpinor > &basis, const std::vector< double > &r, bool print)
TKR sum rule (basis test); should be zero (needs -ve energy states).
Definition BSplineBasis.cpp:550
double check(const std::vector< DiracSpinor > &basis, const std::vector< DiracSpinor > &orbs, bool print_warning)
Checks basis against orbitals: normality, orthogonality, and energies.
Definition BSplineBasis.cpp:190
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:87
std::pair< LinAlg::Matrix< double >, LinAlg::Matrix< double > > fill_Hamiltonian_matrix(const SplineSpinors &splines, const Wavefunction &wf, const bool correlationsQ, SplineType type)
Calculates and returns the Hamiltonian matrix H_ij and overlap S_ij.
Definition BSplineBasis.cpp:368
SplineType
B-spline construction method (see details).
Definition BSplineBasis.hpp:98
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:247
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.
Definition BSplineBasis.cpp:467
SplineSpinors 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:292
std::vector< double > default_r0(SplineType type)
Default first internal knot, r0, for each l, for the given type.
Definition BSplineBasis.cpp:72
double f_f
f-like spinor (f = B_i): f, g, and their radial derivatives
Definition BSplineBasis.hpp:309
std::string_view parseSplineType(SplineType type)
Returns the canonical name string for a SplineType.
Definition BSplineBasis.hpp:101
void r_completeness_header()
Prints the title and column headers for r_completeness output.
Definition BSplineBasis.hpp:579
Values at r of the two spline spinors built from one B-spline B_i.
Definition BSplineBasis.hpp:307
The spline spinors for one kappa (see form_spline_basis)
Definition BSplineBasis.hpp:334
bool ci_compare(std::string_view s1, std::string_view s2)
Case-insensitive string comparison; equivalent to tolower(s1) == tolower(s2).
Definition String.hpp:144
Input parameters for B-spline basis construction (see form_basis).
Definition BSplineBasis.hpp:170
std::string states
Electron states to keep, e.g., "25spd10f".
Definition BSplineBasis.hpp:190
Parameters()
Default: all parameters empty/zero.
Definition BSplineBasis.hpp:172
bool verbose
Print construction details to screen.
Definition BSplineBasis.hpp:204
std::size_t n
Number of splines (n), and order of the B-splines (k)
Definition BSplineBasis.hpp:192
double rmax
Last knot (rmax)
Definition BSplineBasis.hpp:196
std::vector< double > r0
First internal knot for each l (last entry for higher l); empty: default.
Definition BSplineBasis.hpp:194
bool orthogonalise
Force orthogonal to core (spectrum: to valence); done by Wavefunction.
Definition BSplineBasis.hpp:202
SplineType type
B-spline construction method.
Definition BSplineBasis.hpp:200
std::string positron
Negative-energy states to keep, e.g., "9spdf" (empty: none)
Definition BSplineBasis.hpp:198
Type-dependent spline selection for a given kappa (see spline_params).
Definition BSplineBasis.hpp:274
std::size_t imin_f
f-like splines kept: indices [imin_f, imax_f)
Definition BSplineBasis.hpp:278
std::size_t num_f() const
number of f-like splines kept
Definition BSplineBasis.hpp:284
std::size_t n_spl
total number of underlying B-splines
Definition BSplineBasis.hpp:276
double lambda_DKB
kinetic balance prefactor (1 for DKB types, 0 for Johnson, Fischer)
Definition BSplineBasis.hpp:282
std::size_t num_g() const
number of g-like splines kept
Definition BSplineBasis.hpp:286
std::size_t imin_g
g-like splines kept: indices [imin_g, imax_g)
Definition BSplineBasis.hpp:280