High-precision calculations for one- and two-valence atomic systems
DiracODE Namespace Reference

Detailed Description

Functions and classes used to solve the Dirac equation.

Classes

class  AsymptoticSpinor
 Performs asymptotic expansion for f and g at large r, up to order Nx in (1/r). More...
 
class  AsymptoticSpinorContinuum
 Large-r Dirac-Coulomb oscillating tail spinors of a continuum (en > 0) state, energy-normalised. More...
 
struct  ContinuumTailSpinors
 Pair of oscillating continuum spinor values at one radius: the regular (F) and irregular (G) large-r Dirac-Coulomb solutions. More...
 
struct  DiracContinuumDerivative
 H-like Dirac derivative matrix for continuum states at large r. More...
 
struct  FreeDiracParameters
 Momentum, normalisation, and resolved extent of the free (V = 0) Dirac waves at one energy on a grid; see freeDirac(). More...
 
struct  GridRequirements
 Grid requirements returned by RequiredContinuumGrid. More...
 

Functions

void boundState (DiracSpinor &Fa, const double en0, const std::vector< double > &v, const std::vector< double > &H_off_diag={}, const double alpha=PhysConst::alpha, double eps=1.0e-14, const DiracSpinor *const VxFa=nullptr, const DiracSpinor *const Fa0=nullptr, double zion=1, double mass=1.0)
 Solves bound-state problem for local potential (en < 0).
 
void regularAtOrigin (DiracSpinor &Fa, const double en, const std::vector< double > &v, const std::vector< double > &H_off_diag, const double alpha, const DiracSpinor *const VxFa=nullptr, const DiracSpinor *const Fa0=nullptr, double zion=1, double mass=1.0)
 For given energy en, solves DE with correct boundary conditions at the origin.
 
void regularAtInfinity (DiracSpinor &Fa, const double en, const std::vector< double > &v, const std::vector< double > &H_off_diag, const double alpha, const DiracSpinor *const VxFa=nullptr, const DiracSpinor *const Fa0=nullptr, double zion=1, double mass=1.0)
 For given energy en, solves (local) DE with correct boundary conditions at infinity.
 
DiracSpinor boundState (int n, int kappa, const double en0, const std::shared_ptr< const Grid > &gr, const std::vector< double > &v, const std::vector< double > &H_off_diag={}, const double alpha=PhysConst::alpha, double eps=1.0e-14, const DiracSpinor *const VxFa=nullptr, const DiracSpinor *const Fa0=nullptr, double zion=1, double mass=1.0)
 Factory overload: constructs a DiracSpinor(n, kappa, gr) and calls boundState().
 
void regularAtOrigin_C (DiracSpinor &FaR, DiracSpinor &FaI, const std::complex< double > en, const std::vector< double > &v, const std::vector< double > &H_off_diag, const double alpha)
 For given complex energy en, solves Dirac equation with correct boundary conditions at the origin.
 
void regularAtInfinity_C (DiracSpinor &FaR, DiracSpinor &FaI, const std::complex< double > en, const std::vector< double > &v, const std::vector< double > &H_off_diag, const double alpha)
 For given complex energy en, solves Dirac equation with correct boundary conditions at infinity.
 
void solveContinuum (DiracSpinor &Fa, double en, const std::vector< double > &v, double alpha, const DiracSpinor *const VxFa=nullptr, const DiracSpinor *const Fa0=nullptr, bool average_tail=false)
 Solves Dirac equation for a continuum state (en > 0) with energy normalisation.
 
GridRequirements RequiredContinuumGrid (double en, const Grid &gr, double N_ppw=20.0, double alpha=PhysConst::alpha)
 Grid parameters required to safely store (pointwise) a continuum state of energy en on the entire grid.
 
std::size_t averageTail (DiracSpinor &Fa, const std::vector< double > &v, double alpha)
 Optionally fills the zeroed high-r tail of a continuum state with a locally-averaged solution, so radial integrals against smooth functions remain accurate.
 
void solveContinuumIrregular (DiracSpinor &Firr, const DiracSpinor &Freg, double en, const std::vector< double > &v, double alpha)
 Builds the irregular continuum partner F_irr of a regular continuum orbital F_reg.
 
double solveContinuumForward (DiracSpinor &phi, const DiracSpinor &Freg, const DiracSpinor &Firr, double en, const std::vector< double > &v, double alpha, const DiracSpinor &Sr)
 Solves the inhomogeneous continuum equation (h_r - en) phi = S (en > 0) with the standing-wave boundary condition, by outward integration plus subtraction of the regular solution.
 
std::pair< double, double > numerical_f_amplitude (double en, int kappa, double alpha, double Zeff, double f_final, double g_final, double r_final, double dr)
 Finds the numerical amplitude of f(r) for a continuum Dirac solution at large r.
 
double analytic_f_amplitude (double en, double alpha)
 Analytic amplitude of f(r) at very large r for an H-like Dirac continuum state.
 
double fitQuadratic (double x1, double x2, double x3, double y1, double y2, double y3)
 Fits a quadratic to three points and returns the interpolated maximum.
 
std::vector< DiracSpinor > freeDirac (double en, int min_l, int max_l, std::shared_ptr< const Grid > grid, double alpha)
 Free (V = 0) Dirac spherical waves at energy en, for every kappa with l in [min_l, max_l]; energy normalised.
 
DiracSpinor freeDirac (double en, int kappa, std::shared_ptr< const Grid > grid, double alpha)
 Free (V = 0) Dirac spherical wave of a single kappa; see the all-l overload of freeDirac()
 
DiracSpinor solve_inhomog (const int kappa, const double en, const std::vector< double > &v, const std::vector< double > &H_mag, const double alpha, const DiracSpinor &source, const DiracSpinor *const VxFa=nullptr, const DiracSpinor *const Fa0=nullptr, double zion=1, double mass=1.0)
 Solves the inhomogeneous Dirac equation, returning the solution spinor.
 
void solve_inhomog (DiracSpinor &Fa, const double en, const std::vector< double > &v, const std::vector< double > &H_mag, const double alpha, const DiracSpinor &source, const DiracSpinor *const VxFa=nullptr, const DiracSpinor *const Fa0=nullptr, double zion=1, double mass=1.0)
 Solves the inhomogeneous Dirac equation, overwriting Fa.
 
void solve_inhomog (DiracSpinor &Fa, DiracSpinor &Fzero, DiracSpinor &Finf, const double en, const std::vector< double > &v, const std::vector< double > &H_mag, const double alpha, const DiracSpinor &source, const DiracSpinor *const VxFa=nullptr, const DiracSpinor *const Fa0=nullptr, double zion=1, double mass=1.0)
 Solves the inhomogeneous Dirac equation, overwriting Fa and exposing the homogeneous solutions.
 

Class Documentation

◆ DiracODE::ContinuumTailSpinors

struct DiracODE::ContinuumTailSpinors
Class Members
double fC F^C = {fC, gC}, large ~ cos.
double gC
double fG G^C = {fG, gG}, large ~ sin.
double gG

◆ DiracODE::GridRequirements

struct DiracODE::GridRequirements
Class Members
size_t num_points num_points required, keeping r0, rmax, and b unchanged
double b largest sufficient b, keeping num_points unchanged (clamped to >= 0.05)
size_t num_points_b num_points required at the returned b (== current num_points, unless b was clamped)

Function Documentation

◆ boundState() [1/2]

void DiracODE::boundState ( DiracSpinor &  Fa,
const double  en0,
const std::vector< double > &  v,
const std::vector< double > &  H_off_diag = {},
const double  alpha = PhysConst::alpha,
double  eps = 1.0e-14,
const DiracSpinor *const  VxFa = nullptr,
const DiracSpinor *const  Fa0 = nullptr,
double  zion = 1,
double  mass = 1.0 
)

Solves bound-state problem for local potential (en < 0).

Solves \( (H_0 + v - \epsilon_a)F_a = 0 \) for the bound state. en0 is the initial energy guess (must be reasonably good). eps is the convergence target for the energy.

  • v is the local potential (e.g., v = v_dir + v_nuc)
  • H_off_diag is an optional off-diagonal potential
  • alpha: \( \alpha = \lambda\alpha_0 \) is the effective fine-structure constant

◆ regularAtOrigin()

void DiracODE::regularAtOrigin ( DiracSpinor &  Fa,
const double  en,
const std::vector< double > &  v,
const std::vector< double > &  H_mag,
const double  alpha,
const DiracSpinor *const  VxFa,
const DiracSpinor *const  Fa0,
double  zion,
double  mass 
)

For given energy en, solves DE with correct boundary conditions at the origin.

◆ regularAtInfinity()

void DiracODE::regularAtInfinity ( DiracSpinor &  Fa,
const double  en,
const std::vector< double > &  v,
const std::vector< double > &  H_mag,
const double  alpha,
const DiracSpinor *const  VxFa,
const DiracSpinor *const  Fa0,
double  zion,
double  mass 
)

For given energy en, solves (local) DE with correct boundary conditions at infinity.

◆ boundState() [2/2]

DiracSpinor DiracODE::boundState ( int  n,
int  kappa,
const double  en0,
const std::shared_ptr< const Grid > &  gr,
const std::vector< double > &  v,
const std::vector< double > &  H_off_diag = {},
const double  alpha = PhysConst::alpha,
double  eps = 1.0e-14,
const DiracSpinor *const  VxFa = nullptr,
const DiracSpinor *const  Fa0 = nullptr,
double  zion = 1,
double  mass = 1.0 
)
inline

Factory overload: constructs a DiracSpinor(n, kappa, gr) and calls boundState().

◆ regularAtOrigin_C()

void DiracODE::regularAtOrigin_C ( DiracSpinor &  FaR,
DiracSpinor &  FaI,
const std::complex< double >  en,
const std::vector< double > &  v,
const std::vector< double > &  H_mag,
const double  alpha 
)

For given complex energy en, solves Dirac equation with correct boundary conditions at the origin.

◆ regularAtInfinity_C()

void DiracODE::regularAtInfinity_C ( DiracSpinor &  FaR,
DiracSpinor &  FaI,
const std::complex< double >  en,
const std::vector< double > &  v,
const std::vector< double > &  H_mag,
const double  alpha 
)

For given complex energy en, solves Dirac equation with correct boundary conditions at infinity.

◆ solveContinuum()

void DiracODE::solveContinuum ( DiracSpinor &  Fa,
double  en,
const std::vector< double > &  v,
double  alpha,
const DiracSpinor *const  VxFa = nullptr,
const DiracSpinor *const  Fa0 = nullptr,
bool  average_tail = false 
)

Solves Dirac equation for a continuum state (en > 0) with energy normalisation.

Normalisation is achieved by continuing the ODE integration to very large r and comparing the asymptotic amplitude to that of the analytic solution. Only the solution on the regular grid is kept; the extended part is discarded. The solution is solved and stored only up to the radius where the grid resolves the oscillations (at least ~10 points per wavelength); Fa.max_pt() is set accordingly and the tail is zeroed. For high energies this may be well inside the grid; for low energies it is the entire grid.

Parameters
FaOutput spinor (result stored here).
enContinuum energy (must be > 0).
vLocal potential v(r).
alphaFine-structure constant.
VxFaOptional exchange potential. If nullptr, ignored.
Fa0Optional inhomogeneous source spinor. If nullptr, ignored.
average_tailOptionally fill the unresolved (zeroed) tail with a local average (see averageTail()).

◆ RequiredContinuumGrid()

GridRequirements DiracODE::RequiredContinuumGrid ( double  en,
const Grid &  gr,
double  N_ppw = 20.0,
double  alpha = PhysConst::alpha 
)

Grid parameters required to safely store (pointwise) a continuum state of energy en on the entire grid.

A continuum state is stored pointwise only where the grid spacing gives at least N_ppw points per wavelength; beyond that solveContinuum() zeroes the solution (see Fa.max_pt()). This checks the grid against the largest spacing (the last point) - the constraint is always at large r, where the grid is coarsest. Each returned value assumes the other grid parameters are unchanged. The b formula assumes a loglinear grid; b is clamped from below at 0.05 (below that, even a nearly-linear grid is too coarse) - when clamped, num_points_b (the num_points required at the clamped b) will exceed the current num_points. Uses the relativistic wavelength, 2*pi/k with k^2 = en*(2 + alpha^2*en); at high energy this is much shorter than the non-relativistic estimate (e.g., 1.9x shorter at en = 1e5 au).

Parameters
enContinuum energy (should be the largest energy required).
grThe radial grid.
N_ppwRequired points per wavelength (default 20, as used by solveContinuum).
alphaFine-structure constant.

◆ averageTail()

std::size_t DiracODE::averageTail ( DiracSpinor &  Fa,
const std::vector< double > &  v,
double  alpha 
)

Optionally fills the zeroed high-r tail of a continuum state with a locally-averaged solution, so radial integrals against smooth functions remain accurate.

solveContinuum() stores the solution only up to the radius where the grid resolves the oscillations (Fa.max_pt()), and zeroes the rest; radial integrals then silently omit any contribution from beyond that radius. This routine replaces the tail with the local Gaussian average of a finely-integrated solution. The average is smooth enough to store on the coarse grid, and preserves radial integrals against functions that are smooth on the oscillation scale (bound orbitals, r^k, ...), since Int[B f_avg] = Int[B_avg f] ~ Int[B f]. It does not preserve integrals against co-factors that oscillate on a comparable scale (e.g. jL(qr) with q ~ k), and the stored tail is a local average, not the pointwise wavefunction. Exchange is neglected in the tail. Sets Fa.max_pt() to num_points.

Parameters
FaContinuum state from solveContinuum() (modified in place).
vLocal potential v(r) (as used to solve Fa).
alphaFine-structure constant.
Returns
Index of the first averaged point; num_points if nothing was done.

◆ solveContinuumIrregular()

void DiracODE::solveContinuumIrregular ( DiracSpinor &  Firr,
const DiracSpinor &  Freg,
double  en,
const std::vector< double > &  v,
double  alpha 
)

Builds the irregular continuum partner F_irr of a regular continuum orbital F_reg.

Given the regular (energy-normalised) continuum orbital F_reg at energy en > 0 in the local potential v, constructs the linearly independent irregular solution F_irr of the same homogeneous equation: the quarter-wave phase-shifted partner (F_reg ~ sin, F_irr ~ -cos at large r), so that

\[ F_reg + i F_irr \]

is the outgoing wave.

It plays the role of the "regular at infinity" solution of the continuum Green's function, in place of the decaying bound solution.

The outermost grid points are seeded by projecting F_reg onto the energy-normalised asymptotic Dirac-Coulomb pair {F^C, G^C} ( AsymptoticSpinorContinuum ), F_reg = a F^C + b G^C, so

\[ F_irr = b F^C - a G^C \]

(the short-range phase shift is in a, b); the homogeneous equation is then integrated inwards to the origin. If the asymptotic series has not converged at the box edge (a barely-open channel, small p*r_max), F_reg is first continued outward on a fine grid with the Coulomb tail potential until it has; F_irr is seeded there and integrated back to the box. As a last resort (non-Coulomb tail) the seed is the leading-order component swap, f_irr = -g_reg/beta, g_irr = beta f_reg.

The result has the Wronskian f_reg g_irr - f_irr g_reg = alpha/pi (times a^2 + b^2, which is 1 when the projection is exact). It need not be normalised: the overall scale cancels in the Green's-function prefactor.

Parameters
FirrOutput: the irregular partner (kappa from Freg).
FregThe regular, energy-normalised continuum orbital.
enContinuum energy (> 0; should equal Freg.en()).
vLocal potential (as used to solve Freg); its tail sets the residual-ion charge of the Coulomb series.
alphaFine-structure constant.
Warning
Requires en > 0 and a grid dense enough at large r that F_reg is resolved there (same condition as solveContinuum).

◆ solveContinuumForward()

double DiracODE::solveContinuumForward ( DiracSpinor &  phi,
const DiracSpinor &  Freg,
const DiracSpinor &  Firr,
double  en,
const std::vector< double > &  v,
double  alpha,
const DiracSpinor &  Sr 
)

Solves the inhomogeneous continuum equation (h_r - en) phi = S (en > 0) with the standing-wave boundary condition, by outward integration plus subtraction of the regular solution.

Outward integration from the origin with regular initial conditions gives a particular solution, determined only up to an admixture of F_reg (itself regular at the origin). Beyond the (short-ranged) source it equals c F_reg + K F_irr exactly; c and K are read off pointwise over an outer window from the two spinor components (local Wronskian; no phase fit) and averaged, and then

\[ \varphi = \tilde\varphi - c\,F_{\rm reg} \to K\,F_{\rm irr} , \]

the Green's-function solution with the standing-wave Green's function. The outgoing solution is phi - i K F_reg.

Where the main grid no longer resolves the oscillations (high energy), phi is continued through that band by variation of parameters on the pair, phi = u F_reg + w F_irr, with the quadratures done on the grid; the extraction window lies inside the resolved region.

Parameters
phiOutput: the standing-wave particular solution (kappa from Freg).
FregRegular homogeneous solution at en (energy-normalised).
FirrIrregular partner (see solveContinuumIrregular).
enContinuum energy (> 0).
vLocal potential (as used for Freg and Firr).
alphaFine-structure constant.
SrSource spinor S.
Returns
K: phi -> K F_irr at large r (K = -pi <Freg|S> for the exact solution; +pi <Freg|S> in the TDHF convention (h - en) phi = -S). Returns 0 if no valid extraction window exists (the resolved region ends inside the source).

◆ numerical_f_amplitude()

std::pair< double, double > DiracODE::numerical_f_amplitude ( double  en,
int  kappa,
double  alpha,
double  Zeff,
double  f_final,
double  g_final,
double  r_final,
double  dr 
)

Finds the numerical amplitude of f(r) for a continuum Dirac solution at large r.

Continues ODE integration beyond the regular grid, assuming an H-like potential (-Zeff/r) and a linearly-spaced extension grid with step dr. The amplitude estimate sqrt(f^2 + c_g^2 g^2) is averaged over full oscillation cycles (delimited by zero-crossings of f, located to sub-step accuracy), and the cycle means are extrapolated to r -> infinity by fitting A_inf + c2/r^2 + c3/r^3 + c4/r^4. Converged when the extrapolated estimates from the full and half integration ranges agree.

Parameters
enContinuum energy.
kappaOrbital kappa quantum number.
alphaFine-structure constant.
ZeffEffective nuclear charge.
f_finalValue of f at the end of the regular grid.
g_finalValue of g at the end of the regular grid.
r_finalRadial position at the end of the regular grid.
drStep size for the extended linear grid.
Returns
{amplitude, eps} - extrapolated asymptotic amplitude of f(r), and relative difference between the last two estimates (convergence measure).

◆ analytic_f_amplitude()

double DiracODE::analytic_f_amplitude ( double  en,
double  alpha 
)

Analytic amplitude of f(r) at very large r for an H-like Dirac continuum state.

Parameters
enContinuum energy.
alphaFine-structure constant.
Returns
Analytic asymptotic amplitude.

◆ fitQuadratic()

double DiracODE::fitQuadratic ( double  x1,
double  x2,
double  x3,
double  y1,
double  y2,
double  y3 
)

Fits a quadratic to three points and returns the interpolated maximum.

Assumes |y2| = max(|y1|, |y2|, |y3|); used to find the amplitude of a sinusoidal oscillation. The three points must be close to the maximum.

Parameters
x1,x2,x3x-coordinates of the three points.
y1,y2,y3y-coordinates of the three points.
Returns
Interpolated maximum value.

◆ freeDirac() [1/2]

std::vector< DiracSpinor > DiracODE::freeDirac ( double  en,
int  min_l,
int  max_l,
std::shared_ptr< const Grid >  grid,
double  alpha 
)

Free (V = 0) Dirac spherical waves at energy en, for every kappa with l in [min_l, max_l]; energy normalised.

Exact solutions of the free Dirac equation, regular at the origin,

\[ \begin{align} f(r) &= N\, r\, j_l(kr), \\ g(r) &= \frac{\kappa}{|\kappa|}\, N\, \frac{k\alpha}{2 + \alpha^2\en}\, r\, j_{\tilde l}(kr), \end{align} \]

with

\[ \begin{align} k &= \sqrt{\en(2 + \alpha^2\en)}, \\ \tilde l &= l(-\kappa), \\ N &= k D = \sqrt{\frac{k\,(\en + 2mc^2)}{\pi c^2}}, \end{align} \]

( \( \tilde l \) is l+1 for kappa < 0, l-1 for kappa > 0), where D is the energy-normalised large-r amplitude (analytic_f_amplitude()),

\[ f \to D\sin(kr - l\pi/2), \]

so that

\[ \int (f_\en f_{\en'} + g_\en g_{\en'})\,dr = \delta(\en - \en'). \]

Same (f, g) convention as solveContinuum(); the non-relativistic limit of f is DiracContinuum::P_el with zero charge. Standing waves (not outgoing): only |amplitude|^2 summed over channels is meaningful.

As solveContinuum(), the solution is stored only where the grid resolves the oscillations (at least ~10 points per wavelength): max_pt() is set accordingly and the tail zeroed, so that free and distorted waves at the same energy are truncated alike (as required when completing a truncated multipole sum with plane waves).

j_l(kr) for l = 0..max_l+1 is evaluated once per grid point and shared by every kappa; for a single kappa use the (en, kappa) overload.

Parameters
enContinuum (kinetic) energy, > 0, in au.
min_lMinimum orbital l.
max_lMaximum orbital l.
gridRadial grid.
alphaFine-structure constant.
Returns
The waves, in kappa-index order (-1, 1, -2, 2, ...), with n = 0.
Note
Do not obtain free waves from solveContinuum() with a zero potential: its normalisation assumes a Coulomb tail.

◆ freeDirac() [2/2]

DiracSpinor DiracODE::freeDirac ( double  en,
int  kappa,
std::shared_ptr< const Grid >  grid,
double  alpha 
)

Free (V = 0) Dirac spherical wave of a single kappa; see the all-l overload of freeDirac()

◆ solve_inhomog() [1/3]

DiracSpinor DiracODE::solve_inhomog ( const int  kappa,
const double  en,
const std::vector< double > &  v,
const std::vector< double > &  H_mag,
const double  alpha,
const DiracSpinor &  source,
const DiracSpinor *const  VxFa = nullptr,
const DiracSpinor *const  Fa0 = nullptr,
double  zion = 1,
double  mass = 1.0 
)

Solves the inhomogeneous Dirac equation, returning the solution spinor.

Solves \( (H_0 + v - \epsilon_a) F_a = S \) for \( \psi_\kappa \) using Green's method (see Methods documentation). Note the sign convention for S.

Parameters
kappaAngular momentum kappa of the solution.
enOrbital energy \( \epsilon \).
vLocal potential v(r).
H_magOff-diagonal (magnetic) potential.
alphaFine-structure constant.
sourceInhomogeneous source term S.
VxFaOptional exchange potential. If nullptr, ignored.
Fa0Optional inhomogeneous source spinor. If nullptr, ignored.
zionEffective ionic charge (default 1).
massEffective particle mass in atomic units (default 1 = m_e).
Returns
Solution spinor Fa.

◆ solve_inhomog() [2/3]

void DiracODE::solve_inhomog ( DiracSpinor &  Fa,
const double  en,
const std::vector< double > &  v,
const std::vector< double > &  H_mag,
const double  alpha,
const DiracSpinor &  source,
const DiracSpinor *const  VxFa = nullptr,
const DiracSpinor *const  Fa0 = nullptr,
double  zion = 1,
double  mass = 1.0 
)

Solves the inhomogeneous Dirac equation, overwriting Fa.

As above; kappa is taken from Fa.

◆ solve_inhomog() [3/3]

void DiracODE::solve_inhomog ( DiracSpinor &  Fa,
DiracSpinor &  Fzero,
DiracSpinor &  Finf,
const double  en,
const std::vector< double > &  v,
const std::vector< double > &  H_mag,
const double  alpha,
const DiracSpinor &  source,
const DiracSpinor *const  VxFa = nullptr,
const DiracSpinor *const  Fa0 = nullptr,
double  zion = 1,
double  mass = 1.0 
)

Solves the inhomogeneous Dirac equation, overwriting Fa and exposing the homogeneous solutions.

As above, but also returns the homogeneous solutions Fzero (regular at origin) and Finf (regular at infinity), which satisfy \( (H_0 + v - \epsilon)F = 0 \). The first two overloads discard these; this one keeps them for potential reuse. Fzero and Finf are out parameters – they are overwritten internally and do not need to be initialised before calling.