Loading...
Searching...
No Matches
q3::paw_one_center Namespace Reference

Classes

struct  AngularPoint
 One direction on the unit sphere with its quadrature weight. More...
 
struct  ChannelAngularLayout
 
struct  ChannelExpansion
 
struct  GradientAtRadius
 ∇n at one radius, for every angular point: radial part, tangential part, σ. More...
 
struct  OneCenterBranch
 One branch (all-electron or pseudo) of the one-center terms. More...
 
struct  OneCenterDensities
 lm-decomposed one-center densities, r-weighted, for one spin channel. More...
 
struct  OneCenterEnergy
 Both branches, kept separate so a gate failure can be localized. More...
 
struct  OneCenterOptions
 
struct  OnSiteOccupancies
 
class  OnSiteOccupationSymmetrizer
 
class  PawOneCenterConvention
 
class  PawOneCenterTerms
 
struct  ReferenceStateInputs
 Everything the engine needs to rebuild a dataset's own reference state. More...
 
struct  SpeciesOneCenterContext
 Everything reusable across SCF steps for one species. More...
 

Functions

int angular_momentum_of_lm (int lm_index)
 The L of a flat lm index.
 
std::vector< AngularPoint > build_angular_grid (int maximum_angular_momentum)
 
ChannelAngularLayout build_channel_angular_layout (const std::vector< int > &beta_index_per_channel, const std::vector< int > &angular_momentum_per_channel)
 
GradientAtRadius build_gradient_at_radius (const std::vector< Real > &channel_values, const std::vector< Real > &channel_derivatives, Real radius, const std::vector< std::vector< Real > > &harmonics, const std::vector< std::vector< std::array< Real, 3 > > > &harmonic_gradients)
 
OneCenterDensities build_one_center_densities (const PawPseudopotential &pseudopotential, const ChannelExpansion &expansion, const OnSiteOccupancies &occupancies, const GauntCoefficientTable &gaunt, int spin)
 
bool channel_expansion_matches_projectors (const PawPseudopotential &pseudopotential)
 
std::vector< Real > compute_one_center_d_matrix (const PawPseudopotential &pseudopotential, const ChannelExpansion &expansion, const GauntCoefficientTable &gaunt, const OneCenterEnergy &energy)
 
OneCenterEnergy compute_one_center_energy (const PawPseudopotential &pseudopotential, const OneCenterDensities &densities, const std::vector< AngularPoint > &angular_grid, const std::vector< std::vector< Real > > &harmonics, const XCFunctional &functional, const std::vector< std::vector< std::array< Real, 3 > > > *harmonic_gradients=nullptr, const OneCenterOptions &options={})
 
OneCenterEnergy compute_one_center_energy_either_mode (const PawPseudopotential &pseudopotential, const OneCenterDensities &densities, const std::vector< AngularPoint > &angular_grid, const std::vector< std::vector< Real > > &harmonics, const XCFunctional &functional, const std::vector< std::vector< std::array< Real, 3 > > > *harmonic_gradients=nullptr, const OneCenterOptions &options={})
 
std::vector< OneCenterEnergy > compute_one_center_energy_spin (const PawPseudopotential &pseudopotential, const std::vector< OneCenterDensities > &densities_by_spin, const std::vector< AngularPoint > &angular_grid, const std::vector< std::vector< Real > > &harmonics, const XCFunctional &functional, const std::vector< std::vector< std::array< Real, 3 > > > *harmonic_gradients=nullptr, const OneCenterOptions &options={})
 
void compute_one_center_xc (const std::vector< std::vector< Real > > &density_channels, const std::vector< Real > &core_density, const std::vector< Real > &radial_grid, const std::vector< Real > &radial_grid_derivative, int mesh_size, const std::vector< AngularPoint > &angular_grid, const std::vector< std::vector< Real > > &harmonics, const XCFunctional &functional, Real &energy, std::vector< std::vector< Real > > &potential_lm)
 
void compute_one_center_xc_gradient_corrected (const std::vector< std::vector< Real > > &density_channels, const std::vector< Real > &core_density, const std::vector< Real > &radial_grid, const std::vector< Real > &radial_grid_derivative, int mesh_size, const std::vector< AngularPoint > &angular_grid, const std::vector< std::vector< Real > > &harmonics, const std::vector< std::vector< std::array< Real, 3 > > > &harmonic_gradients, const XCFunctional &functional, Real &energy, std::vector< std::vector< Real > > &potential_lm, std::vector< std::vector< Real > > &radial_weight_lm, std::vector< std::vector< Real > > &angular_weight_lm)
 
void compute_one_center_xc_gradient_corrected_spin (const std::vector< std::vector< std::vector< Real > > > &density_channels_by_spin, const std::vector< Real > &core_density, const std::vector< Real > &radial_grid, const std::vector< Real > &radial_grid_derivative, int mesh_size, const std::vector< AngularPoint > &angular_grid, const std::vector< std::vector< Real > > &harmonics, const std::vector< std::vector< std::array< Real, 3 > > > &harmonic_gradients, const XCFunctional &functional, Real &energy, std::vector< std::vector< std::vector< Real > > > &potential_lm_by_spin, std::vector< std::vector< std::vector< Real > > > &radial_weight_lm_by_spin, std::vector< std::vector< std::vector< Real > > > &angular_weight_lm_by_spin)
 
void compute_one_center_xc_spin (const std::vector< std::vector< std::vector< Real > > > &density_channels_by_spin, const std::vector< Real > &core_density, const std::vector< Real > &radial_grid, const std::vector< Real > &radial_grid_derivative, int mesh_size, const std::vector< AngularPoint > &angular_grid, const std::vector< std::vector< Real > > &harmonics, const XCFunctional &functional, Real &energy, std::vector< std::vector< std::vector< Real > > > &potential_lm_by_spin)
 
std::unique_ptr< PawOneCenterConvention > create_one_center_convention (const PawPseudopotential &pseudopotential)
 
std::vector< Real > cumulative_integral (const std::vector< Real > &values, const std::vector< Real > &measures, int mesh_size)
 
Real density_channel_moment (const std::vector< Real > &density_channel, int angular_momentum, const std::vector< Real > &radial_grid, const std::vector< Real > &radial_grid_derivative, int mesh_size)
 
int density_lm_count (const PawPseudopotential &pseudopotential)
 Number of lm channels a density needs: products of two l_max harmonics.
 
ChannelExpansion expand_channels (const PawPseudopotential &pseudopotential)
 
void gauss_legendre_nodes (int number_of_points, std::vector< Real > &nodes, std::vector< Real > &weights)
 
Registry< NamedFactory< PawOneCenterConvention > > & one_center_convention_registry ()
 The registry create_one_center_convention() builds conventions from.
 
std::vector< Real > radial_derivative (const std::vector< Real > &values, const std::vector< Real > &measures, int mesh_size)
 
Real radial_hartree_energy (const std::vector< std::vector< Real > > &potential_channels, const std::vector< std::vector< Real > > &density_channels, const std::vector< Real > &radial_grid_derivative, int mesh_size)
 
void solve_radial_hartree (int angular_momentum, const std::vector< Real > &radial_grid, const std::vector< Real > &radial_grid_derivative, const std::vector< Real > &density_r_squared, int mesh_size, std::vector< Real > &potential)
 
std::vector< std::vector< std::array< Real, 3 > > > tabulate_harmonic_gradients (const std::vector< AngularPoint > &angular_grid, int number_of_lm)
 
std::vector< std::vector< Real > > tabulate_harmonics (const std::vector< AngularPoint > &angular_grid, int number_of_lm)
 Real spherical harmonics at every angular grid point, [point][lm].
 

Detailed Description

Symmetrizing the PAW on-site occupations ρ_ij.

ρ_ij is accumulated as a weighted sum over the irreducible wedge,

ρ^a_ij = Σ_{k∈IBZ} w_k Σ_v f_kv Re[⟨ψ_kv|β^a_i⟩⟨β^a_j|ψ_kv⟩],

and a weighted wedge sum reproduces the full-zone sum only for quantities the point group leaves alone. ρ_ij is not one: each projector channel carries an angular index (β_i is a radial function times Y_{l_i m_i}), and every operation mixes those indices and permutes equivalent atoms. Summing the wedge and stopping leaves an array that is not symmetry-adapted — its trace is right, its structure is not.

The restoration is the group average, with the same pairing SymmetryAnalyzer::symmetrize_vector uses for forces and for the same reason — it is the one combination that leaves an already-symmetric array unchanged:

ρ^a  ←  (1/N_R) Σ_R  D(R)ᵀ · ρ^{R(a)} · D(R)

with R(a) = atom_map[a] the atom a is carried to, and D(R) the real-harmonic rotation of the channel's l. Read the other way round, it is the statement the crystal makes: ρ^{R(a)} = D(R) ρ^a D(R)ᵀ. The radial index of a channel is untouched — a rotation does not mix β's of different radial shape — so the average acts only inside each (β_i, β_j) block, on the (2l_i+1)×(2l_j+1) angular indices.

Why ultrasoft never needed this. The same array builds the augmentation charge, and that reaches the grid, where the density symmetrizer repairs it. PAW's one-centre Hartree and XC terms read ρ_ij directly and never pass through a grid, so nothing downstream repairs them. Measured at 30 Ry, 2×2×2 Γ-centred (3 irreducible k-points against the full 8): diamond PAW split its Γ valence maximum 13.7274 / 13.7427 / 13.7465 eV where the full mesh gives 13.7393 three times, and sat 0.19 mRy above it; silicon PAW 0.25 mRy; the same silicon cell with ultrasoft or norm-conserving datasets agreed with its full mesh to 1e-7 Ry.

Time reversal needs no separate step here, unlike the DFT+U occupation matrix. ρ_ij is accumulated as Re[conj(⟨β_i|ψ⟩)⟨β_j|ψ⟩], which is already the average over the ±k pair the wedge folded together — the real part is the Θ projection. Quantum ESPRESSO's collinear becsum is real by the same construction.

Spin. Each channel is averaged over the crystal's spatial operations separately, exactly as PlanewaveChargeDensitySymmetrizer treats each spin component of the density; the assumption that the chemical cell's operations are symmetries of each spin channel is the one Q3 already makes on the grid, not a new one taken here.

Function Documentation

◆ angular_momentum_of_lm()

int q3::paw_one_center::angular_momentum_of_lm ( int  lm_index)
inline

The L of a flat lm index.

Definition at line 235 of file densities.hpp.

Referenced by compute_one_center_d_matrix().

◆ build_angular_grid()

std::vector< AngularPoint > q3::paw_one_center::build_angular_grid ( int  maximum_angular_momentum)
inline

Build the θ × φ product grid.

Parameters
maximum_angular_momentuml_max the grid must integrate products of

Definition at line 85 of file angular_grid.hpp.

References gauss_legendre_nodes(), q3::constants::pi, and q3::paw_one_center::AngularPoint::x.

Referenced by q3::paw_one_center::PawOneCenterTerms::build(), and q3::build_real_harmonic_rotation_matrix().

◆ build_channel_angular_layout()

ChannelAngularLayout q3::paw_one_center::build_channel_angular_layout ( const std::vector< int > &  beta_index_per_channel,
const std::vector< int > &  angular_momentum_per_channel 
)
inline

Derive the layout from the per-channel radial index and l that the projector mapping table already publishes, rather than re-deriving the expansion rule.

Definition at line 86 of file occupation_symmetrization.hpp.

References q3::paw_one_center::ChannelAngularLayout::angular_momentum, q3::paw_one_center::ChannelAngularLayout::manifold_base, q3::paw_one_center::ChannelAngularLayout::manifold_position, and q3::paw_one_center::ChannelAngularLayout::number_of_channels.

◆ build_gradient_at_radius()

GradientAtRadius q3::paw_one_center::build_gradient_at_radius ( const std::vector< Real > &  channel_values,
const std::vector< Real > &  channel_derivatives,
Real  radius,
const std::vector< std::vector< Real > > &  harmonics,
const std::vector< std::vector< std::array< Real, 3 > > > &  harmonic_gradients 
)
inline

Assemble ∇n and σ at one radius from the density channels and their radial derivatives.

Parameters
channel_valuesf_lm(r) — the true density channels, not r-weighted
channel_derivativesf'_lm(r)

Definition at line 140 of file gradient.hpp.

References q3::paw_one_center::GradientAtRadius::gradient_squared, q3::paw_one_center::GradientAtRadius::radial_component, and q3::paw_one_center::GradientAtRadius::tangential.

Referenced by compute_one_center_xc_gradient_corrected(), and compute_one_center_xc_gradient_corrected_spin().

◆ build_one_center_densities()

◆ channel_expansion_matches_projectors()

bool q3::paw_one_center::channel_expansion_matches_projectors ( const PawPseudopotential &  pseudopotential)
inline

Whether a dataset's one-center channel expansion agrees with the order the plane-wave side accumulates projector overlaps in.

The two are built independently — expand_channels from the partial waves, the projector mapping table from the β projectors — so their agreement is a property of the dataset, not of the code. A PAW file that paired them differently would make every ρ_ij element land in the wrong place while still producing a symmetric, plausible matrix.

Definition at line 68 of file scf_terms.hpp.

References q3::Pseudopotential::number_of_projectors, q3::PawPseudopotential::partial_waves_pseudo, and q3::Pseudopotential::projectors.

Referenced by q3::paw_one_center::PawOneCenterTerms::build().

◆ compute_one_center_d_matrix()

std::vector< Real > q3::paw_one_center::compute_one_center_d_matrix ( const PawPseudopotential &  pseudopotential,
const ChannelExpansion &  expansion,
const GauntCoefficientTable &  gaunt,
const OneCenterEnergy &  energy 
)
inline

One-center D_ij correction, as a dense (nh × nh) matrix for one spin.

Parameters
energythe branches produced by compute_one_center_energy, whose potential_lm are integrated against

For a gradient-corrected functional the perturbation's own channels are needed, not just their values: g_lm(r) = G·p(r)/r² and its radial derivative, paired with the by-parts weights the energy routine produced.

Definition at line 57 of file d_matrix.hpp.

References angular_momentum_of_lm(), q3::UltrasoftPseudopotential::augmentation_function_by_angular_momentum, q3::GauntCoefficientTable::coefficients, cumulative_integral(), density_lm_count(), q3::energy(), q3::paw_one_center::ChannelExpansion::lm_index, q3::Pseudopotential::mesh_size, q3::Pseudopotential::number_of_projectors, q3::PawPseudopotential::partial_waves_all_electron, q3::PawPseudopotential::partial_waves_pseudo, q3::paw_one_center::ChannelExpansion::radial_channel, radial_derivative(), q3::Pseudopotential::radial_grid, q3::Pseudopotential::radial_grid_derivative, and q3::paw_one_center::ChannelExpansion::size().

◆ compute_one_center_energy()

OneCenterEnergy q3::paw_one_center::compute_one_center_energy ( const PawPseudopotential &  pseudopotential,
const OneCenterDensities &  densities,
const std::vector< AngularPoint > &  angular_grid,
const std::vector< std::vector< Real > > &  harmonics,
const XCFunctional &  functional,
const std::vector< std::vector< std::array< Real, 3 > > > *  harmonic_gradients = nullptr,
const OneCenterOptions &  options = {} 
)
inline

Assemble both branches: Hartree and XC energies, and the summed potential each branch's D_ij contribution integrates against.

Only the energy is corrected here, never potential_lm: E_xc[n_core] does not depend on the valence occupancies, so its derivative — which is what D_ij is — is identically zero, and removing it from the potential too would break D ≡ ∂E/∂ρ_ij.

The pseudo branch keeps its core-core term: its "core" is the shallow pseudized partial core, and an atomic-referenced convention removes the core self-interaction from the all-electron branch alone.

Definition at line 607 of file energy.hpp.

◆ compute_one_center_energy_either_mode()

OneCenterEnergy q3::paw_one_center::compute_one_center_energy_either_mode ( const PawPseudopotential &  pseudopotential,
const OneCenterDensities &  densities,
const std::vector< AngularPoint > &  angular_grid,
const std::vector< std::vector< Real > > &  harmonics,
const XCFunctional &  functional,
const std::vector< std::vector< std::array< Real, 3 > > > *  harmonic_gradients = nullptr,
const OneCenterOptions &  options = {} 
)
inline

One-center energy for an unpolarized occupancy, with either functional mode.

The atomic reference state and every non-magnetic SCF step are unpolarized, but the functional handle they are evaluated with belongs to the calculation, which may be spin-polarized. Driving a polarized LibXC handle through the unpolarized routines does not fail — it misreads the interleaved density array and returns a plausible wrong number. For nickel that put the atomic reference at −24.12 Ry instead of −1.58 Ry, and the SCF total 113 Ry low while the magnetic moment still looked right.

So the branch is on the functional, not on the caller's density count: a polarized handle gets the density split evenly and the spin routines, which OneCenterEnergySpinTest gates as identical to the unpolarized answer.

Channel 0 already carries the whole energy — Hartree comes from the total density and channel 1's energies are left at zero — and both channels' potentials are equal here, so channel 0 is the complete answer.

Definition at line 902 of file energy.hpp.

Referenced by q3::paw_one_center::PawOneCenterTerms::update_by_spin().

◆ compute_one_center_energy_spin()

std::vector< OneCenterEnergy > q3::paw_one_center::compute_one_center_energy_spin ( const PawPseudopotential &  pseudopotential,
const std::vector< OneCenterDensities > &  densities_by_spin,
const std::vector< AngularPoint > &  angular_grid,
const std::vector< std::vector< Real > > &  harmonics,
const XCFunctional &  functional,
const std::vector< std::vector< std::array< Real, 3 > > > *  harmonic_gradients = nullptr,
const OneCenterOptions &  options = {} 
)
inline

Both branches, spin-polarized: one OneCenterEnergy per spin channel.

Hartree is a functional of the total density alone, so it is computed once from n↑ + n↓ and its potential handed to both channels — that is the physics, not an approximation. Only XC splits. To keep total() summable over the returned vector without double counting, the Hartree energy is recorded on channel 0 and left at zero on channel 1, while both channels' potential_lm carry the full Hartree potential because each channel's D_ij needs it.

Parameters
densities_by_spinone OneCenterDensities per channel, same lm and mesh

The core-only term goes through the spin routines as well.

The frozen core carries no moment, so this is the same number the unpolarized routine would give — but only if it is evaluated with an unpolarized handle, and the handle here is polarized. Nickel's core exchange-correlation is about 106 Ry, so taking the wrong branch put the atomic reference at −107.95 Ry instead of −1.58 Ry, which then appeared as a 113 Ry error in the SCF total.

Definition at line 741 of file energy.hpp.

Referenced by q3::paw_one_center::PawOneCenterTerms::update_by_spin().

◆ compute_one_center_xc()

void q3::paw_one_center::compute_one_center_xc ( const std::vector< std::vector< Real > > &  density_channels,
const std::vector< Real > &  core_density,
const std::vector< Real > &  radial_grid,
const std::vector< Real > &  radial_grid_derivative,
int  mesh_size,
const std::vector< AngularPoint > &  angular_grid,
const std::vector< std::vector< Real > > &  harmonics,
const XCFunctional &  functional,
Real &  energy,
std::vector< std::vector< Real > > &  potential_lm 
)
inline

Exchange-correlation for one branch on the radial × angular grid.

Parameters
density_channelsu_lm(r) = r² ρ_lm(r)
core_densityspherical ρ_core(r), added to the total before the functional is evaluated (never to the Hartree term)

ε_xc is per particle, so the energy density is ε·n; the r² restores the volume element the r-weighted storage already carries elsewhere.

Definition at line 155 of file energy.hpp.

References q3::XCFunctional::compute(), cumulative_integral(), and q3::energy().

◆ compute_one_center_xc_gradient_corrected()

void q3::paw_one_center::compute_one_center_xc_gradient_corrected ( const std::vector< std::vector< Real > > &  density_channels,
const std::vector< Real > &  core_density,
const std::vector< Real > &  radial_grid,
const std::vector< Real > &  radial_grid_derivative,
int  mesh_size,
const std::vector< AngularPoint > &  angular_grid,
const std::vector< std::vector< Real > > &  harmonics,
const std::vector< std::vector< std::array< Real, 3 > > > &  harmonic_gradients,
const XCFunctional &  functional,
Real &  energy,
std::vector< std::vector< Real > > &  potential_lm,
std::vector< std::vector< Real > > &  radial_weight_lm,
std::vector< std::vector< Real > > &  angular_weight_lm 
)
inline

Gradient-corrected exchange-correlation on the radial × angular grid.

Same shape as the LDA routine, plus σ = |∇n|² and the by-parts weights the D_ij gradient term needs. The core density is spherical, so it contributes to the radial derivative through its own slope and nothing to the tangential part.

The true density channels f_lm = u_lm/r², and their radial derivatives. The core is spherical, so it enters only the L = 0 channel — through Y_00, hence the √(4π).

Bookkeeping worth spelling out, because getting it wrong is an error of r⁴. The stored tangential field is ∇_Ω n / r, and the perturbation's tangential field is (1/r) Σ g_lm ∇_Ω Y_lm, so their product carries 1/r; the volume element contributes r². Net, the weight paired with g_lm under ∫dr is r·S_lm, not S_lm/r.

Definition at line 226 of file energy.hpp.

References build_gradient_at_radius(), q3::XCFunctional::compute_gradient_corrected(), cumulative_integral(), q3::energy(), q3::constants::four_pi, and radial_derivative().

◆ compute_one_center_xc_gradient_corrected_spin()

void q3::paw_one_center::compute_one_center_xc_gradient_corrected_spin ( const std::vector< std::vector< std::vector< Real > > > &  density_channels_by_spin,
const std::vector< Real > &  core_density,
const std::vector< Real > &  radial_grid,
const std::vector< Real > &  radial_grid_derivative,
int  mesh_size,
const std::vector< AngularPoint > &  angular_grid,
const std::vector< std::vector< Real > > &  harmonics,
const std::vector< std::vector< std::array< Real, 3 > > > &  harmonic_gradients,
const XCFunctional &  functional,
Real &  energy,
std::vector< std::vector< std::vector< Real > > > &  potential_lm_by_spin,
std::vector< std::vector< std::vector< Real > > > &  radial_weight_lm_by_spin,
std::vector< std::vector< std::vector< Real > > > &  angular_weight_lm_by_spin 
)
inline

Spin-polarized gradient-corrected exchange-correlation for one branch.

The by-parts construction of the unpolarized routine carries over with one change: a GGA's dependence on ∇n_σ runs through both σ_σσ and the cross term σ_↑↓, so the field conjugate to ∇δn_σ is

W_σ = 2 v_{σσ} ∇n_σ + v_{↑↓} ∇n_{σ'}

rather than 2 v_σ ∇n.

It reduces exactly, not just numerically: at n↑ = n↓ = n/2 each channel's gradient is half the total, and the functional's own spin scaling supplies the rest — PBE exchange has no cross term (v_{↑↓} = 0) with v_{↑↑} = 2 v_σ^unpol, while PBE correlation has v_{↑↓} = 2 v_{↑↑}. Both land on 2 v_σ^unpol ∇n. OneCenterEnergySpinTest gates the resulting energy.

Same r-bookkeeping as the unpolarized routine: the stored tangential field carries 1/r and the perturbation's own carries another, against r² from the volume element, so the weight paired with g_lm under ∫dr is r·S_lm.

Definition at line 445 of file energy.hpp.

References build_gradient_at_radius(), q3::XCFunctional::compute_gradient_corrected_spin(), cumulative_integral(), q3::energy(), q3::constants::four_pi, and radial_derivative().

◆ compute_one_center_xc_spin()

void q3::paw_one_center::compute_one_center_xc_spin ( const std::vector< std::vector< std::vector< Real > > > &  density_channels_by_spin,
const std::vector< Real > &  core_density,
const std::vector< Real > &  radial_grid,
const std::vector< Real > &  radial_grid_derivative,
int  mesh_size,
const std::vector< AngularPoint > &  angular_grid,
const std::vector< std::vector< Real > > &  harmonics,
const XCFunctional &  functional,
Real &  energy,
std::vector< std::vector< std::vector< Real > > > &  potential_lm_by_spin 
)
inline

Spin-polarized exchange-correlation for one branch (LDA).

Same grid and same projection as the unpolarized routine; the difference is that the functional sees two densities and returns two potentials, so the D_ij of each channel integrates against its own v_xc. The frozen core is unpolarized and is split evenly between the channels, which is what makes n↑ + n↓ reproduce the unpolarized total exactly.

Parameters
density_channels_by_spin[spin][lm][radial point], r-weighted
potential_lm_by_spinout, [spin][lm][radial point]

The functional returns ε per particle of the total density, matching the unpolarized convention, so the energy weight is n↑ + n↓.

Definition at line 358 of file energy.hpp.

References q3::XCFunctional::compute_spin(), cumulative_integral(), and q3::energy().

◆ create_one_center_convention()

std::unique_ptr< PawOneCenterConvention > q3::paw_one_center::create_one_center_convention ( const PawPseudopotential &  pseudopotential)
inline

◆ cumulative_integral()

std::vector< Real > q3::paw_one_center::cumulative_integral ( const std::vector< Real > &  values,
const std::vector< Real > &  measures,
int  mesh_size 
)
inline

Cumulative integral ∫₀^{r_i} g(r) dr on a non-uniform grid.

Simpson over each pair of intervals, with a three-point half-step (5,8,−1)/12 rule for the odd points in between, so every grid point carries fourth-order accuracy rather than only the even ones. values are the integrand samples; measures are dr/di.

Definition at line 45 of file radial_poisson.hpp.

Referenced by compute_one_center_d_matrix(), compute_one_center_xc(), compute_one_center_xc_gradient_corrected(), compute_one_center_xc_gradient_corrected_spin(), compute_one_center_xc_spin(), radial_hartree_energy(), and solve_radial_hartree().

◆ density_channel_moment()

Real q3::paw_one_center::density_channel_moment ( const std::vector< Real > &  density_channel,
int  angular_momentum,
const std::vector< Real > &  radial_grid,
const std::vector< Real > &  radial_grid_derivative,
int  mesh_size 
)
inline

Multipole moment ∫ u_LM(r) r^L dr of one density channel.

The quantity the compensation charge exists to make equal between the all-electron and pseudo densities — outside the augmentation sphere the two then produce identical electrostatics, which is what lets a PAW calculation be split across two grids at all.

Definition at line 222 of file densities.hpp.

References q3::simpson_rule().

◆ density_lm_count()

int q3::paw_one_center::density_lm_count ( const PawPseudopotential &  pseudopotential)
inline

Number of lm channels a density needs: products of two l_max harmonics.

Definition at line 124 of file densities.hpp.

References q3::PawPseudopotential::partial_waves_pseudo.

Referenced by q3::paw_one_center::PawOneCenterTerms::build(), build_one_center_densities(), and compute_one_center_d_matrix().

◆ expand_channels()

◆ gauss_legendre_nodes()

void q3::paw_one_center::gauss_legendre_nodes ( int  number_of_points,
std::vector< Real > &  nodes,
std::vector< Real > &  weights 
)
inline

Gauss-Legendre nodes and weights on [-1, 1], by Newton iteration on the Legendre polynomial. Converges quadratically; the iteration is run to machine tolerance because the exactness gate leaves no room for a loose root.

Definition at line 52 of file angular_grid.hpp.

References q3::constants::pi.

Referenced by build_angular_grid().

◆ one_center_convention_registry()

Registry< NamedFactory< PawOneCenterConvention > > & q3::paw_one_center::one_center_convention_registry ( )
inline

The registry create_one_center_convention() builds conventions from.

Definition at line 25 of file registry.hpp.

References q3::Registry< Entry >::add().

Referenced by create_one_center_convention().

◆ radial_derivative()

std::vector< Real > q3::paw_one_center::radial_derivative ( const std::vector< Real > &  values,
const std::vector< Real > &  measures,
int  mesh_size 
)
inline

df/dr on a non-uniform grid, by five-point central differences in index space divided by dr/di.

Differentiating in index space is what makes this safe on a logarithmic mesh: a power law r^γ is an exponential in the index, so the stencil sees a smooth function even where the density itself has a cusp-like profile.

Definition at line 45 of file gradient.hpp.

Referenced by compute_one_center_d_matrix(), compute_one_center_xc_gradient_corrected(), and compute_one_center_xc_gradient_corrected_spin().

◆ radial_hartree_energy()

Real q3::paw_one_center::radial_hartree_energy ( const std::vector< std::vector< Real > > &  potential_channels,
const std::vector< std::vector< Real > > &  density_channels,
const std::vector< Real > &  radial_grid_derivative,
int  mesh_size 
)
inline

Hartree energy of a set of one-center density channels against their own potentials: E_H = ½ Σ_lm ∫ V_lm(r) u_lm(r) dr.

The one-half is the usual double-counting factor, applied once after the channels are summed rather than inside each integral — a scalar pulled out of a sum, so the two placements differ only in operation count.

Definition at line 127 of file radial_poisson.hpp.

References cumulative_integral(), and q3::energy().

◆ solve_radial_hartree()

void q3::paw_one_center::solve_radial_hartree ( int  angular_momentum,
const std::vector< Real > &  radial_grid,
const std::vector< Real > &  radial_grid_derivative,
const std::vector< Real > &  density_r_squared,
int  mesh_size,
std::vector< Real > &  potential 
)
inline

Solve for the Hartree potential of one (L, M) density channel.

Parameters
angular_momentumL of this channel
radial_gridr values
radial_grid_derivativedr/di
density_r_squaredu_L(r) = r² ρ_L(r)
mesh_sizepoints to use
potential[out] V_L(r), resized to mesh_size

Definition at line 84 of file radial_poisson.hpp.

References cumulative_integral(), and q3::constants::four_pi.

◆ tabulate_harmonic_gradients()

std::vector< std::vector< std::array< Real, 3 > > > q3::paw_one_center::tabulate_harmonic_gradients ( const std::vector< AngularPoint > &  angular_grid,
int  number_of_lm 
)
inline

Tangential gradients ∇_Ω Y_lm at every angular grid point, [point][lm][xyz].

Obtained by differentiating Y_lm along the unit sphere: perturbing the direction and renormalizing projects out the radial component automatically, which is exactly the tangential derivative wanted here.

Definition at line 84 of file gradient.hpp.

References q3::compute_real_spherical_harmonic(), q3::harmonic_combined_degree_order_index(), and q3::harmonic_order_sequence().

Referenced by q3::paw_one_center::PawOneCenterTerms::build().

◆ tabulate_harmonics()

std::vector< std::vector< Real > > q3::paw_one_center::tabulate_harmonics ( const std::vector< AngularPoint > &  angular_grid,
int  number_of_lm 
)
inline

Real spherical harmonics at every angular grid point, [point][lm].

Definition at line 55 of file energy.hpp.

References q3::compute_real_spherical_harmonic(), q3::harmonic_combined_degree_order_index(), q3::harmonic_order_sequence(), and q3::Vector3D::x.

Referenced by q3::paw_one_center::PawOneCenterTerms::build().