Loading...
Searching...
No Matches
q3::PlanewaveBlochOverlapCalculator Class Reference

#include <overlaps.hpp>

Public Member Functions

 PlanewaveBlochOverlapCalculator (const PlanewaveBasis &planewave_basis, const MillerIndexLookup &global_miller_lookup)
 
template<typename WavefunctionAtKpoint , typename WavefunctionAtNeighbor >
void add_augmentation_contribution (BlochOverlapResult &result, const Crystal &crystal_structure, const UltrasoftPlanewaveBasis &ultrasoft_basis, const Matrix< Complex > &projectors_at_kpoint, int number_of_plane_waves_at_kpoint, int number_of_bands_at_kpoint, WavefunctionAtKpoint wavefunction_at_kpoint, const Matrix< Complex > &projectors_at_neighbor, int number_of_plane_waves_at_neighbor, int number_of_bands_at_neighbor, WavefunctionAtNeighbor wavefunction_at_neighbor, const Vector3D &b_cartesian) const
 
template<typename WavefunctionAtKpoint , typename WavefunctionAtNeighbor >
BlochOverlapResult compute (const std::vector< int > &g_vector_indices_at_kpoint, int number_of_bands_at_kpoint, WavefunctionAtKpoint wavefunction_at_kpoint, const std::vector< int > &g_vector_indices_at_neighbor, int number_of_bands_at_neighbor, WavefunctionAtNeighbor wavefunction_at_neighbor, const IntegerVector3D &periodic_image_shift) const
 

Detailed Description

Definition at line 88 of file overlaps.hpp.

Constructor & Destructor Documentation

◆ PlanewaveBlochOverlapCalculator()

q3::PlanewaveBlochOverlapCalculator::PlanewaveBlochOverlapCalculator ( const PlanewaveBasis &  planewave_basis,
const MillerIndexLookup &  global_miller_lookup 
)
inlineexplicit

global_miller_lookup must already be built over planewave_basis.g_vectors() – the same lookup is reused across every (k,b) pair in a calculation, so building it is the caller's responsibility, not this calculator's.

Definition at line 96 of file overlaps.hpp.

Member Function Documentation

◆ add_augmentation_contribution()

template<typename WavefunctionAtKpoint , typename WavefunctionAtNeighbor >
void q3::PlanewaveBlochOverlapCalculator::add_augmentation_contribution ( BlochOverlapResult &  result,
const Crystal &  crystal_structure,
const UltrasoftPlanewaveBasis &  ultrasoft_basis,
const Matrix< Complex > &  projectors_at_kpoint,
int  number_of_plane_waves_at_kpoint,
int  number_of_bands_at_kpoint,
WavefunctionAtKpoint  wavefunction_at_kpoint,
const Matrix< Complex > &  projectors_at_neighbor,
int  number_of_plane_waves_at_neighbor,
int  number_of_bands_at_neighbor,
WavefunctionAtNeighbor  wavefunction_at_neighbor,
const Vector3D &  b_cartesian 
) const
inline

Add the ultrasoft/PAW augmentation contribution to an already-computed NC-only result, in place:

M_mn(k,b) += sum_I sum_ij <psi_mk|beta_i^I(k)> * Q_ij^I(b) * e^{-i*b.tau_I} * <beta_j^I(k+b)|psi_n,k+b>

projectors_at_kpoint/projectors_at_neighbor are compute_kleinman_bylander_projectors()'s output at k and at the neighbor k' – already carry each their own atomic structure factor e^{-i(k+G).tau_I}, so only the translation phase for Q_ij (which is defined atom-origin-centred, like compute_q_g_single itself) needs to be applied here. b_cartesian is the unwrapped translation (i.e. KPointNeighborDirection::reciprocal_lattice_translation, not folded by the periodic-image shift used for the plane-wave G-matching in compute() above), a physical wavevector in Bohr^-1 (tpiba-scaled – built from Crystal::reciprocal_vectors_bohr(), NOT the same convention as the raw GVector::g_cart field: g_cart is left unscaled by tpiba precisely so that structure-factor code elsewhere in this codebase can multiply it by an explicit 2*pi against a dimensionless alat-fraction position; b_cartesian already carries that 2*pi, so its own translation phase below multiplies the position by the plain lattice parameter instead, not by 2*pi again – doing both would double the factor). See atomic_position_alat's own definition below for the matching position-side convention.

b_cartesian must not be exactly (0,0,0) – see the cell-volume scaling note below; every real Wannier neighbor direction (KPointNeighborShells::neighbor_directions()) already satisfies this, since the origin is never itself a shell member.

compute_q_g_single()'s general (nonzero-argument) branch is normalized for its existing charge-density consumer (add_augmentation_charges() / precompute_q_functions_g(), which use the identical interpolate_augmentation_function()-based formula with no volume factor of their own) – not for the S-operator/overlap convention this augmentation term needs, where Q_ij must be the cell-size-independent real-space integral augmentation_overlap_integrals(i,j) = integral Q_ij(r) d^3r (exactly what its own b=0 special branch returns, unscaled). Measured empirically (see this file's unit tests): the general branch is smaller than the special branch by exactly a factor of the cell volume, to 8 significant figures on a real Si ultrasoft pseudopotential – so the general branch must be multiplied by cell_volume() to convert it to the overlap convention. b is never exactly zero for a real Wannier neighbor direction (KPointNeighborShells never enumerates the origin), so this multiplication is applied unconditionally; it would be wrong at b = 0 exactly, where compute_q_g_single() takes its already-correctly-scaled special branch instead – callers must not invoke this method with b_cartesian = (0,0,0).

compute_q_g_single() takes its wavevector in the plane-wave basis's own 2*pi/alat units (it multiplies by two_pi_over_lattice_parameter internally before interpolating the radial table), while b_cartesian arrives in physical bohr^-1 from KPointNeighborShells. Convert once here; passing b_cartesian directly would sample Q_ij at |b| * tpiba instead of |b| – too small by tpiba (0.6 for silicon), so an over-estimated augmentation term that can push the overlap's singular values above 1.

convert_from_crystal_to_cartesian() returns a position in alat units (dimensionless, 1.0 = one lattice parameter), not Bohr – multiply by lattice_parameter() to get a physical Bohr position matching b_cartesian's own physical Bohr^-1 units, so the dot product is already a phase angle in radians with no separate 2*pi factor (unlike the g_cart-based structure factors elsewhere in this codebase, which multiply an explicit 2*pi against a dimensionless reduced G-vector instead – a different, not-tpiba-scaled convention).

amplitude_at_kpoint stores <beta_i|psi_mk>; the formula above needs <psi_mk|beta_i>, its conjugate.

Definition at line 237 of file overlaps.hpp.

References q3::Crystal::cell_volume(), q3::compute_phase_factor(), q3::UltrasoftPlanewaveBasis::compute_q_g_single(), q3::Crystal::convert_from_crystal_to_cartesian(), q3::Vector3D::dot(), q3::Crystal::lattice_parameter(), q3::Vector3D::norm(), q3::Crystal::number_of_atoms(), q3::NormConservingPlanewaveBasis::number_of_projector_channels(), q3::Matrix< T >::rows(), q3::Crystal::species_type_index(), q3::Crystal::two_pi_over_lattice_parameter(), q3::BlochOverlapResult::values, and q3::math::tolerances::zero_vector_magnitude_threshold.

◆ compute()

template<typename WavefunctionAtKpoint , typename WavefunctionAtNeighbor >
BlochOverlapResult q3::PlanewaveBlochOverlapCalculator::compute ( const std::vector< int > &  g_vector_indices_at_kpoint,
int  number_of_bands_at_kpoint,
WavefunctionAtKpoint  wavefunction_at_kpoint,
const std::vector< int > &  g_vector_indices_at_neighbor,
int  number_of_bands_at_neighbor,
WavefunctionAtNeighbor  wavefunction_at_neighbor,
const IntegerVector3D &  periodic_image_shift 
) const
inline

Compute M_mn(k,b) for one (k, neighbor) pair.

wavefunction_at_kpoint(band_index) and wavefunction_at_neighbor(band_index) return a pointer to that band's plane-wave coefficients, contiguous over its own g_vector_indices_* list (the PlanewaveKohnShamQuantumSystem convention) – passed as callables rather than a quantum system reference so this kernel stays independent of the SCF/NSCF state shape and is directly unit-testable against synthetic data.

Local position within the neighbor's own G-set, keyed by the GLOBAL charge-density-sphere index – built once per (k,b) pair here; a caller driving many pairs against the same neighbor may cache this externally, but correctness does not depend on it.

For every plane wave in k's own set, resolve which local position (if any) in the neighbor's set holds the same physical plane wave once the periodic-image shift is applied.

Definition at line 112 of file overlaps.hpp.

References q3::MillerIndexLookup::find(), q3::PlanewaveBasis::g_vectors(), q3::BlochOverlapResult::missing_g_vector_count, q3::BlochOverlapResult::number_of_bands_at_kpoint, q3::BlochOverlapResult::number_of_bands_at_neighbor, q3::BlochOverlapResult::values, q3::IntegerVector3D::x, q3::IntegerVector3D::y, and q3::IntegerVector3D::z.


The documentation for this class was generated from the following file: