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

#include <init.hpp>

+ Inheritance diagram for q3::PlanewavePseudopotentialKohnShamSCFIterator:

Public Member Functions

 PlanewavePseudopotentialKohnShamSCFIterator (KohnShamSCFIteratorConfig config)
 
 ~PlanewavePseudopotentialKohnShamSCFIterator () override=default
 
const NormConservingPlanewaveKohnShamEnergies & energies () const override
 
NormConservingPlanewaveKohnShamEnergies & energies_mutable () override
 
const std::vector< std::vector< Real > > & hubbard_occupation_traces () const
 
virtual void load_one_center_occupations (const std::vector< Matrix< Real > > &occupations_by_spin)
 
const NormConservingPlanewaveKohnShamQuantumSystem & norm_conserving_quantum_system () const
 
void offer_starting_wavefunctions (std::string save_directory)
 
virtual std::vector< Matrix< Real > > one_center_occupations () const
 
virtual const Matrix< Real > & projector_overlap_coefficients () const
 
const PseudopotentialSet & pseudopotential_set () const
 
void refresh_quantum_system_snapshot ()
 
void release_scf_workspace () override
 
virtual bool requires_one_center_occupations () const
 
NormConservingPlanewaveKohnShamSCFState result () const override
 
void set_diagonalizer_maximum_iterations_for_nscf (int maximum_iterations)
 
void set_diagonalizer_tolerance_for_nscf (Real tolerance)
 
void set_owned_pseudopotential_set (PseudopotentialSet pseudopotential_set)
 Transfer ownership of a PseudopotentialSet into this iterator.
 
std::vector< Complex > valence_exchange_correlation_potential_g_of (const std::vector< std::vector< Real > > &charge_density_real)
 
void write_checkpoints (const std::string &output_directory, const std::string &prefix) const override
 
- Public Member Functions inherited from q3::PlanewaveKohnShamSCFIterator
 PlanewaveKohnShamSCFIterator (KohnShamSCFIteratorConfig config)
 
 ~PlanewaveKohnShamSCFIterator () override=default
 
Real eigenvalue (int kpoint_index, int band_index) const
 
Matrix< Real > eigenvalues () const
 
const execution::PlanewaveExecutionPolicy & execution_policy () const
 
const std::vector< std::vector< int > > & g_vector_indices () const
 
const std::vector< int > & g_vector_indices (int kpoint_index) const
 
Matrix< Real > global_eigenvalues () const
 
const std::vector< std::vector< Real > > & kinetic_energy_squared () const
 
const KPointsGrid & kpoint_grid () const
 
void load_quantum_system (const PlanewaveKohnShamQuantumSystem &system)
 
bool loaded_charge_density_fits_grid () const
 
const std::optional< Magnetization > & magnetization () const
 
int number_of_bands () const override
 
Real number_of_electrons () const override
 
int number_of_kpoint_states () const override
 
int number_of_occupied_bands_per_spin () const
 
const std::vector< int > & number_of_plane_waves () const
 
int number_of_plane_waves (int kpoint_index) const
 
Real occupation (int kpoint_index, int band_index) const
 
const PlanewaveBasis & planewave_basis () const
 
void preload_charge_density ()
 
void preload_single_particle_states ()
 
const PlanewaveKohnShamQuantumSystem & quantum_system () const
 
void scale_loaded_charge_density_to_electron_count ()
 Rescale the loaded density so it integrates to this system's electron count.
 
void set_diagonalizer (std::unique_ptr< PlanewaveDiagonalizer > diagonalizer)
 
void set_owned_execution_policy (std::unique_ptr< execution::PlanewaveExecutionPolicy > policy)
 
void set_owned_kpoint_grid (KPointsGrid kpoint_grid)
 Transfer ownership of a KPointsGrid into this iterator.
 
Real spin_degeneracy () const
 
Complex wavefunction (int kpoint_index, int band_index, int g_vector_index) const
 
- Public Member Functions inherited from q3::KohnShamSCFIterator
 KohnShamSCFIterator (KohnShamSCFIteratorConfig config)
 
 ~KohnShamSCFIterator () override=default
 
const std::vector< Real > & charge_density_for_spin (int spin_index) const
 
const std::vector< Complex > & charge_density_g () const
 
const std::vector< Real > & charge_density_real () const
 
Crystal & crystal_structure () const
 
const XCFunctional & exchange_correlation () const
 
const std::vector< Complex > & exchange_correlation_potential_g () const
 
void load_charge_density (std::vector< std::vector< Real > > charge_density)
 
void load_effective_potential (std::vector< std::vector< Real > > effective_potential)
 
void offer_starting_charge_density (std::vector< std::vector< Real > > charge_density)
 
const std::vector< Real > & potential_for_spin (int spin_index) const
 
const std::vector< Real > & real_space_potential () const
 
const std::vector< ScfIterationRecord > & scf_history () const
 
Real total_energy () const override
 
const std::vector< Complex > & total_potential_g () const
 
- Public Member Functions inherited from q3::SCFIterator
 SCFIterator (SCFIteratorConfig config)
 
virtual ~SCFIterator ()=default
 
bool is_converged () const
 
int iteration () const
 
int number_of_spin_components () const
 
void run ()
 
void set_convergence_threshold (Real threshold)
 Set the SCF convergence threshold (in Ry).
 
void set_maximum_iterations (int maximum_iterations)
 Set the maximum number of SCF iterations.
 
void set_owned_crystal (Crystal crystal)
 Transfer ownership of a Crystal into this iterator.
 
const std::vector< Real > & total_energy_history_in_ry () const
 

Protected Member Functions

void accumulate_hubbard_occupation_and_potential ()
 
const std::vector< SymmetryOperation > & cached_symmetry_operations () const
 
Real compute_double_counting_correction () const override
 
void compute_effective_potential_from_density () override
 
void construct_density_from_states () override
 
const std::vector< Complex > & core_charge_density_g () const override
 
void create_norm_conserving_quantum_system_snapshot ()
 
NormConservingPlanewaveEffectivePotentialCalculator & effective_potential_calculator ()
 
std::vector< Real > effective_species_magnetizations () const
 
void fix_edge_kpoints_with_backward_propagation (int number_of_kpoints, int number_of_kpoint_states)
 
Real hubbard_potential_energy () const
 
void initialize_charge_density () override
 
void initialize_charge_density_from_atomic_superposition ()
 
void initialize_representation () override
 
void initialize_single_particle_states () override
 
bool is_at_band_path_segment_boundary (int kpoint_index) const
 
bool is_iteration_converged () const override
 
const std::vector< Complex > & local_ionic_potential_g () const override
 
void log_pseudopotential_summary (int number_of_atomic_wavefunctions) const
 
void propagate_wavefunctions_backward (int source_kpoint_state_index, int target_kpoint_state_index)
 
void propagate_wavefunctions_to_next_kpoint (int current_kpoint_state_index, int total_kpoint_states)
 
std::vector< std::vector< Complex > > read_saved_bands (int kpoint_index) const
 
void report_memory_estimate (int number_of_atomic_wavefunctions) const
 
void report_unconverged_solve (int kpoint_index_state) const
 
void setup_hubbard ()
 
void solve_single_particle_states () override
 
bool take_saved_starting_wavefunctions (int kpoint_index, std::vector< std::vector< Complex > > &starting_wavefunctions) const
 
- Protected Member Functions inherited from q3::PlanewaveKohnShamSCFIterator
void allocate_electronic_states ()
 
void build_kpoint_plane_wave_data ()
 
Real compute_delta_escf_correction () const override
 
Real compute_density_residual (const std::vector< std::vector< Real > > &input_density_for_mixing) const override
 
void compute_energy_components () override
 
Real compute_local_residual_between (const std::vector< std::vector< Real > > &density_in, const std::vector< std::vector< Real > > &density_out) const
 
Real compute_number_of_electrons () const
 
Real compute_residual_between (const std::vector< std::vector< Real > > &density_in, const std::vector< std::vector< Real > > &density_out) const
 
Real effective_charge_density_energy_cutoff () const
 
Real hartree_metric_prefactor () const
 
void initiate_mixer () override
 
std::vector< std::vector< Real > > input_density_for_mixing () const override
 
void log_representation_summary () const
 
Real magnetization_metric_weight () const
 
void mix_density (const std::vector< std::vector< Real > > &input_density_for_mixing) override
 
virtual void on_charge_density_initialized ()
 
const PlanewaveKohnShamEnergies & planewave_energies () const
 
PlanewaveKohnShamEnergies & planewave_energies_mutable ()
 
void report_convergence_details () override
 
void report_first_iteration_details () override
 
int resolve_number_of_bands () const
 
void restore_density_at_convergence () override
 
void set_diagonalization_tolerance (int iteration) override
 
void set_diagonalizer_tolerance (Real tolerance) override
 
void snapshot_output_density () override
 
void symmetrize_density () override
 
void update_effective_potential () override
 
void update_occupations () override
 
void warn_if_total_charge_deviates () const
 
- Protected Member Functions inherited from q3::KohnShamSCFIterator
const KohnShamSCFIteratorConfig & config () const
 
Real diagonalization_threshold () const
 
void finalize () override
 
void initialize () override
 Base implementation prints the SCF banner. Children call SCFIterator::initialize() last.
 
void log_iteration_energy (Real delta_energy)
 Single source of truth for the per-iteration energy/convergence log line.
 
void perform_iteration () override
 
virtual void prepare_hamiltonian ()
 
void report_convergence () override
 
void report_iteration () override
 
void report_non_convergence () override
 
virtual void synchronize_smooth_density_from_mixed ()
 
- Protected Member Functions inherited from q3::SCFIterator
virtual void iterate ()
 Main iteration loop.
 
virtual void report ()
 Report convergence or non-convergence after iterate() finishes.
 

Protected Attributes

std::vector< Real > atomic_starting_magnetization_
 
std::vector< std::pair< std::string, Vector3D > > band_path_
 
int band_path_points_per_segment_ = 20
 
std::vector< q3::Matrix< Complex > > cached_hubbard_projectors_
 
std::vector< q3::Matrix< Complex > > cached_kleinman_bylander_projectors_
 Cached KB projectors per k-point (reused by the projector overlap accumulation).
 
std::vector< SymmetryOperation > cached_symmetry_operations_
 
std::string calculation_ = "self_consistent_field"
 
NormConservingPlanewaveKohnShamEnergies energies_
 
std::vector< std::vector< Complex > > hubbard_d_matrix_per_spin_
 
std::vector< HubbardManifold > hubbard_manifolds_
 DFT+U (Hubbard): resolved atom/shell manifolds; empty means no correction is active.
 
HubbardOccupationMixer hubbard_occupation_mixer_
 Owns the damping/Anderson state; see HubbardOccupationMixer.
 
Real hubbard_occupation_residual_ {std::numeric_limits<Real>::max()}
 
std::vector< std::vector< Real > > hubbard_occupation_traces_
 
Real hubbard_potential_energy_ {0.0}
 Σ_σ Tr[V_U^σ n^σ]; see hubbard_potential_energy().
 
int hubbard_seed_iterations_remaining_ = 0
 
const PseudopotentialSet * pseudopotential_set_ = nullptr
 
std::shared_ptr< NormConservingPlanewaveKohnShamQuantumSystem > quantum_system_snapshot_
 
std::vector< Real > starting_magnetization_
 
bool symmetry_operations_cached_ {false}
 
int total_hubbard_orbitals_ = 0
 
- Protected Attributes inherited from q3::PlanewaveKohnShamSCFIterator
std::vector< Real > cached_local_ionic_potential_real_
 Cached real-space ionic local potential (constant during SCF, avoids repeated FFTs).
 
std::unique_ptr< PlanewaveChargeDensityAccumulator > charge_density_accumulator_
 Accumulates real-space charge density from wavefunctions each SCF iteration.
 
Real charge_density_energy_cutoff_ = 0.0
 
std::vector< std::vector< Real > > convergence_output_density_
 Converged output density snapshot, restored once self-consistency is reached.
 
PlanewaveChargeDensitySymmetrizer density_symmetrizer_
 
std::string diagonalization_method_ = "davidson"
 
std::unique_ptr< PlanewaveDiagonalizer > diagonalizer_
 
std::unique_ptr< PlanewaveKohnShamEnergyCalculator > energy_calculator_
 Computes band energy and smearing entropy from the occupied Kohn-Sham states.
 
execution::PlanewaveExecutionPolicy * execution_policy_ = nullptr
 
PlanewaveFermiEnergyCalculator fermi_energy_calculator_
 
const KPointsGrid * kpoint_grid_ = nullptr
 
std::optional< Magnetization > magnetization_
 Set by report_convergence_details(); see magnetization() above.
 
std::optional< int > nscf_override_maximum_iterations_
 
std::optional< Real > nscf_override_tolerance_
 
int number_of_bands_ {0}
 
Real number_of_electrons_ {0.0}
 
int number_of_smooth_g_vectors_ {0}
 
std::unique_ptr< execution::PlanewaveExecutionPolicy > owned_execution_policy_
 
PlanewaveBasis planewave_basis_
 
PlanewaveKohnShamQuantumSystem quantum_system_
 
bool replicated_plane_wave_fallback_active_ = false
 
bool report_unconverged_bands_ = false
 
Real wavefunction_energy_cutoff_ = 30.0
 
- Protected Attributes inherited from q3::KohnShamSCFIterator
std::vector< Complex > charge_density_g_
 
std::vector< std::vector< Real > > charge_density_real_
 
Real density_residual_ {0.0}
 
Real diagonalizer_tolerance_ {0.0}
 
std::unique_ptr< XCFunctional > exchange_correlation_
 
std::vector< Complex > exchange_correlation_potential_g_
 
bool first_iteration_rediag_done_ {false}
 
bool has_preloaded_charge_density_ {false}
 
bool has_preloaded_effective_potential_ {false}
 
std::unique_ptr< Mixer > mixer_
 
bool preloaded_charge_density_is_a_starting_guess_ {false}
 Set by offer_starting_charge_density(): a density that need not fit.
 
std::vector< std::vector< Real > > real_space_potential_
 
std::vector< ScfIterationRecord > scf_history_
 
std::unique_ptr< SmearingScheme > smearing_scheme_
 
Real total_energy_previous_ {0.0}
 
std::vector< Complex > total_potential_g_
 
std::vector< std::vector< Complex > > total_potential_g_by_spin_
 
- Protected Attributes inherited from q3::SCFIterator
Real convergence_threshold_
 
Crystal * crystal_structure_
 
bool is_converged_ {false}
 
int iteration_ {0}
 
int maximum_iterations_
 

Additional Inherited Members

- Public Attributes inherited from q3::KohnShamSCFIterator
KohnShamSCFIteratorConfig config_
 
std::string exchange_correlation_functional_
 
int methfessel_paxton_order_
 
Real mixing_beta_
 
int mixing_history_size_
 
std::string mixing_mode_
 
std::string mixing_preconditioning_
 
Real mixing_q0_
 
std::string smearing_
 
Real smearing_width_
 

Detailed Description

Definition at line 59 of file init.hpp.

Constructor & Destructor Documentation

◆ PlanewavePseudopotentialKohnShamSCFIterator()

q3::PlanewavePseudopotentialKohnShamSCFIterator::PlanewavePseudopotentialKohnShamSCFIterator ( KohnShamSCFIteratorConfig  config)
inlineexplicit

Definition at line 61 of file init.hpp.

◆ ~PlanewavePseudopotentialKohnShamSCFIterator()

q3::PlanewavePseudopotentialKohnShamSCFIterator::~PlanewavePseudopotentialKohnShamSCFIterator ( )
overridedefault

Member Function Documentation

◆ accumulate_hubbard_occupation_and_potential()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::accumulate_hubbard_occupation_and_potential ( )
inlineprotected

Recompute the DFT+U occupation matrix from this iteration's converged wavefunctions, then the Dudarev energy and D-matrix for each spin channel. Called once per SCF iteration (after all k-points/spins are solved), mirroring UltrasoftPlanewavePseudopotentialKohnShamSCFIterator::accumulate_projector_overlaps()'s k-point-state loop and pool-reduction pattern. No-op if hubbard_manifolds_ is empty.

All <phi_j|psi_b> for this k-point in one ZGEMM – see compute_hubbard_projector_overlaps()'s docstring for why this is batched over every Hubbard orbital rather than looped per manifold. Only occupied bands are contracted, as the scalar loop this replaced also skipped the rest.

Gamma-only sums over half the G sphere, so <phi_m|psi> comes out at half its full-sphere value plus an Im-Im cross term. Completing it here rather than inside the occupation kernel keeps n_mm' = conj(O_m) O_m' exactly as written, and makes n real symmetric – which in turn makes the Dudarev D matrix real, so the Hamiltonian term it feeds preserves the half sphere's reality condition.

Scatter this manifold's row block; unoccupied bands stay zero, exactly as the scalar loop's continue left them.

Under MPI band-parallelism (G-vector distribution within a k-point pool), each rank's g_index loop above only covers its LOCAL plane-wave subset, so overlaps here is only a partial <phi_m|psi> sum – reduce across the band-parallel group before use, mirroring the applicator's identical <phi_m|psi> reduction for the H|psi> Hubbard term (hamiltonian_applicator/serial.hpp's reduce_within_group(hubbard_overlaps, ...)). A no-op when band_size == 1 (serial ExecutionPolicy's reduce_within_group()).

Each pool computed the occupation matrix only for its subset of k-points. Flatten (Complex has no reduce_vector overload) -> reduce across pools -> unflatten.

Restore the symmetry the IBZ sum does not carry: time reversal, then the spatial operations.

n has angular indices, so a weighted irreducible-wedge sum does not reproduce the full-zone result the way an invariant scalar does — the trace comes out right and the structure does not. Averaging over the group is what QE does too; without it silicon's 3p manifold, which symmetry forces to be isotropic, came out anisotropic enough to move E_U from 0.1918 to 0.1204 Ry.

The wedge was reduced by the spatial operations and time reversal, so both have to come back; the first call is the Θ half and is described where it is defined. It is a separate call rather than another operation inside the group loop because Θ is antiunitary — it conjugates n instead of rotating its indices, and no real D(R) can express that. The two commute (a real D preserves realness), so the order is only a matter of which one gets to run on the smaller job.

Must run after both reductions: the matrix has to be complete before it is averaged.

Unconditional, with no "was symmetry used?" flag to thread through: a full-zone sum already produces an invariant matrix, and averaging an invariant over the group returns it unchanged. Gamma-only is the one exclusion for the spatial half — its half-sphere basis breaks the point group by construction, the same reason the density symmetrizer stands down there. Θ needs no such exclusion: a Γ-only n is real already.

First iteration only, after the matrix is complete (reduced and symmetrized) and before anything reads it: replace the named eigenvalues. The damping cache bootstraps from these seeded matrices below, and the first Hubbard potential is built from them, which is the entire mechanism – V_U starts in the wanted basin and self-consistency takes over from there.

The user value is per-spin ([0, 1]); the raw matrix carries the k-weight spin factor, so scale by spin_degeneracy() on the way in (a factor of 1 for a spin-polarized run).

Tr[n] per manifold, per spin — the first thing to look at when a DFT+U result looks wrong.

It is the number of electrons the manifold's projectors actually see, so it says immediately whether the projection is capturing the shell. For ultrasoft and PAW that depends on the overlap operator: the pseudo orbital alone misses the on-site charge the augmentation carries. Measured on fcc nickel with a PAW dataset: Tr[n] = 8.83 with the overlap operator and 2.71 without it, so the bare pseudo projection sees under a third of the d shell. Logged rather than left to a debugger, because the failure it diagnoses is a converged, plausible, wrong answer.

Kept at full precision alongside the four-decimal line, and recorded here rather than recomputed for the results file, so the two can never name different numbers – the same reason the SCF history is recorded where its line is printed.

Damp the occupation matrix before it drives V_U. The mixer decides whether damping is warranted at all and whether to accelerate; see HubbardOccupationMixer for why each of those is conditional.

Dudarev energy + per-spin D-matrix, assembled into the block-diagonal buffers the applicator expects (column-major, one buffer per spin).

Normalization: kpoint_grid() weights already carry the spin factor (they sum to 2 for spin-unpolarized runs, matching the electron-counting convention documented in fermi_energy/planewave/init.hpp), so the n_mm' accumulated above has eigenvalues up to spin_degeneracy(), not the [0,1] the Dudarev formula (E_U = (U/2) Tr[n(1-n)]) is defined for. Rescale n by 1/spin_degeneracy() before the formula, then scale the resulting per-channel energy back up by spin_degeneracy() – physically, an unpolarized run has two identical, degenerate spin channels each contributing this same per-spin energy. The D-matrix is used as computed (already expressed per spin channel, matching how it is applied to a single, spin-independent wavefunction solve at nspin=1).

A scaled copy, not a reference: this is the mixer's retained damped state, carried into the next iteration, and it must survive this rescale untouched.

Tr[V_U n] for this manifold and channel, accumulated from the same matrices the energy used so the two cannot drift apart. compute_double_counting_correction() subtracts it; see the note there for why it is mandatory.

V is indexed (m, m') and pairs with n_{m'm} — the transpose convention compute_hubbard_energy_and_potential already documents for the D matrix itself.

A spin-unpolarized calculation double-counts each manifold's occupation across the (non-existent) second spin channel; number_of_spin_components() == 1 already accounts for this since the loop above only ran once per manifold in that case.

Definition at line 1090 of file init.hpp.

References q3::accumulate_hubbard_occupation_matrix(), cached_hubbard_projectors_, cached_symmetry_operations(), q3::compute_hubbard_projector_overlaps(), q3::convert_gamma_only_projector_overlaps_to_full_sphere(), q3::KohnShamSCFIterator::crystal_structure(), q3::Matrix< T >::data(), q3::PlanewaveKohnShamSCFIterator::execution_policy_, q3::find_g_zero_plane_wave_index(), q3::PlanewaveKohnShamSCFIterator::g_vector_indices(), hubbard_manifolds_, q3::PlanewaveBasis::is_gamma_only(), q3::PlanewaveKohnShamSCFIterator::kpoint_grid(), q3::PlanewaveKohnShamSCFIterator::number_of_bands_, q3::PlanewaveKohnShamSCFIterator::number_of_kpoint_states(), q3::KPointsGrid::number_of_kpoints(), q3::PlanewaveKohnShamSCFIterator::number_of_plane_waves(), q3::SCFIterator::number_of_spin_components(), q3::PlanewaveKohnShamQuantumSystem::occupation_by_kpoint_state_index_and_band_index(), q3::math::tolerances::occupation_threshold, q3::PlanewaveKohnShamSCFIterator::planewave_basis_, q3::PlanewaveKohnShamSCFIterator::quantum_system_, q3::execution::PlanewaveExecutionPolicy::reduce_vector(), q3::execution::ExecutionPolicy::reduce_within_group(), q3::symmetrize_hubbard_occupation_matrices(), q3::symmetrize_hubbard_occupation_matrices_under_time_reversal(), and q3::PlanewaveKohnShamQuantumSystem::wavefunction().

Referenced by construct_density_from_states().

◆ cached_symmetry_operations()

const std::vector< SymmetryOperation > & q3::PlanewavePseudopotentialKohnShamSCFIterator::cached_symmetry_operations ( ) const
inlineprotected

The cell's symmetry operations, built once.

Only DFT+U needs them at this level, and only per SCF step, so they are cached lazily rather than computed in initialize() where every run would pay for them.

Definition at line 430 of file init.hpp.

References cached_symmetry_operations_, q3::KohnShamSCFIterator::crystal_structure(), q3::SymmetryAnalyzer::get_symmetry_operations(), and symmetry_operations_cached_.

Referenced by accumulate_hubbard_occupation_and_potential().

◆ compute_double_counting_correction()

Real q3::PlanewavePseudopotentialKohnShamSCFIterator::compute_double_counting_correction ( ) const
inlineoverrideprotectedvirtual

The base correction, plus DFT+U's own.

Structurally identical to what the PAW iterator does for its one-center term: a potential that entered the band energy has to be removed from it here, and the corresponding energy is added back separately. The two additions compose — a PAW + DFT+U run subtracts both.

Reimplemented from q3::PlanewaveKohnShamSCFIterator.

Definition at line 1509 of file init.hpp.

References q3::PlanewaveKohnShamSCFIterator::compute_double_counting_correction().

◆ compute_effective_potential_from_density()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::compute_effective_potential_from_density ( )
inlineoverrideprotectedvirtual

Compute the effective potential from the current charge density. Must set charge_density_g_, real_space_potential_, total_potential_g_, exchange_correlation_potential_g_, and energy components (hartree, xc).

Dispersion depends only on the (fixed) geometry, so compute it once per iterator lifetime. An explicit flag — not a zero-energy sentinel — marks it done: a legitimately zero dispersion energy must not trigger recomputation, and a stale nonzero value must not survive a rebuild. The factory resolves the configured scheme ("none" contributes an exact zero), so no per-scheme branching happens here.

Implements q3::PlanewaveKohnShamSCFIterator.

Definition at line 1783 of file init.hpp.

References q3::EffectivePotentialResult::charge_density_g, q3::compute_ewald(), q3::create_dispersion_calculator(), q3::PlanewaveKohnShamEnergies::ewald_energy, q3::EffectivePotentialResult::exchange_correlation_energy, q3::KohnShamEnergies::exchange_correlation_energy, q3::EffectivePotentialResult::exchange_correlation_potential_energy, q3::KohnShamEnergies::exchange_correlation_potential_energy, q3::EffectivePotentialResult::exchange_correlation_potential_g, q3::EffectivePotentialResult::hartree_energy, q3::KohnShamEnergies::hartree_energy, q3::math::tolerances::numerical_zero_threshold, q3::EffectivePotentialResult::real_space_potential, q3::EffectivePotentialResult::total_potential_g, q3::EffectivePotentialResult::total_potential_g_by_spin, and q3::NormConservingPlanewaveKohnShamEnergies::van_der_waals_energy.

◆ construct_density_from_states()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::construct_density_from_states ( )
inlineoverrideprotectedvirtual

◆ core_charge_density_g()

const std::vector< Complex > & q3::PlanewavePseudopotentialKohnShamSCFIterator::core_charge_density_g ( ) const
inlineoverrideprotectedvirtual

Return the core charge density in reciprocal space.

Implements q3::PlanewaveKohnShamSCFIterator.

Definition at line 1778 of file init.hpp.

◆ create_norm_conserving_quantum_system_snapshot()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::create_norm_conserving_quantum_system_snapshot ( )
inlineprotected

◆ effective_potential_calculator()

NormConservingPlanewaveEffectivePotentialCalculator & q3::PlanewavePseudopotentialKohnShamSCFIterator::effective_potential_calculator ( )
inlineprotected

The effective potential calculator, created on first use and kept, since it caches the real-space core charge density.

Definition at line 1827 of file init.hpp.

◆ effective_species_magnetizations()

std::vector< Real > q3::PlanewavePseudopotentialKohnShamSCFIterator::effective_species_magnetizations ( ) const
inlineprotected

Per-species initial magnetization, normalized to the species count.

An EMPTY config vector means the input gave no starting_magnetization at all; every species then defaults to constants::default_starting_magnetization so a spin-polarized run can break spin symmetry. Explicit values — including explicit zeros — are honored as given.

Definition at line 2008 of file init.hpp.

References q3::constants::default_starting_magnetization.

◆ energies()

const NormConservingPlanewaveKohnShamEnergies & q3::PlanewavePseudopotentialKohnShamSCFIterator::energies ( ) const
inlineoverridevirtual

Implements q3::KohnShamSCFIterator.

Definition at line 71 of file init.hpp.

References energies_.

◆ energies_mutable()

NormConservingPlanewaveKohnShamEnergies & q3::PlanewavePseudopotentialKohnShamSCFIterator::energies_mutable ( )
inlineoverridevirtual

Implements q3::KohnShamSCFIterator.

Definition at line 74 of file init.hpp.

References energies_.

◆ fix_edge_kpoints_with_backward_propagation()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::fix_edge_kpoints_with_backward_propagation ( int  number_of_kpoints,
int  number_of_kpoint_states 
)
inlineprotected

Re-solve edge k-points that lacked proper propagation seeds.

After the forward pass, two types of k-points may have suboptimal eigenvalues for high conduction bands:

(a) k[0] — the very first k-point, solved with only atomic-orbital seeds because no predecessor exists.

(b) The first k-point of each new segment after a direction change — these were solved without propagation seeds because we intentionally skipped propagation across the segment boundary.

For each such edge, we propagate backwards from a correctly converged neighbor (2 steps into the segment) and re-solve. The neighbor at offset +2 was itself seeded by propagation within the segment (from offset +1) and so has correct eigenstates for this path direction.

Collect all k-point indices that need re-solving. Always include k[0]. If a band path is defined, also include the first k-point of each segment after the first.

Number of k-points to re-solve at each edge (the boundary itself plus this many into the segment). More points improves accuracy for high conduction bands at the cost of extra diagonalizations.

Find the seed: the first k-point beyond the sweep region that was correctly solved during the forward pass.

Sweep backwards from the seed toward the edge point. Each re-solved k-point then serves as the seed for the next.

Definition at line 1678 of file init.hpp.

Referenced by solve_single_particle_states().

◆ hubbard_occupation_traces()

const std::vector< std::vector< Real > > & q3::PlanewavePseudopotentialKohnShamSCFIterator::hubbard_occupation_traces ( ) const
inline

Tr[n] per Hubbard manifold, per spin, from the converged occupation matrices – the diagnostic the DFT+U line prints, in full precision and indexed the same way as the manifolds the SCF state carries.

Empty when the run has no Hubbard manifolds.

Definition at line 219 of file init.hpp.

References hubbard_occupation_traces_.

◆ hubbard_potential_energy()

Real q3::PlanewavePseudopotentialKohnShamSCFIterator::hubbard_potential_energy ( ) const
inlineprotected

Σ_σ Tr[V_U^σ n^σ] — the DFT+U potential's own contribution to the band energy, which the double-counting correction has to remove.

The Hubbard potential is applied inside the Hamiltonian, so every eigenvalue already contains it. Adding E_U on top without removing Tr[V_U n] counts the on-site interaction twice, and because Tr[V_U n] = U(½Tr n − Tr n²) is negative for a partially filled shell, the error lowers the total energy — which is how this presented: switching U on made Q3's energy fall by ~1 Ry where E_U is positive definite and QE's rises. The PAW one-center term has exactly this counterpart and always did (compute_double_counting_correction() in the PAW iterator); DFT+U simply never grew one.

Definition at line 1528 of file init.hpp.

◆ initialize_charge_density()

◆ initialize_charge_density_from_atomic_superposition()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::initialize_charge_density_from_atomic_superposition ( )
inlineprotected

Magnetization density m(G): each atom contributes its starting magnetization – its own when given per atom, else its species' – times its atomic charge density.

Definition at line 2023 of file init.hpp.

References q3::compute_phase_factor(), q3::constants::two_pi, and q3::math::tolerances::zero_vector_magnitude_threshold.

Referenced by initialize_charge_density().

◆ initialize_representation()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::initialize_representation ( )
inlineoverrideprotectedvirtual

Read pseudopotential config before calling parent (which reads PW config). Skip fields already set by owned-data setters (InputData factory path).

Fixed occupations fill N/2 electrons per spin channel, so the TOTAL moment is pinned to zero regardless of the starting magnetization (QE rejects this input combination outright; see number_of_occupied_bands_per_spin). Warn rather than silently discarding the user's requested moment.

Reimplemented from q3::PlanewaveKohnShamSCFIterator.

Definition at line 472 of file init.hpp.

References q3::KohnShamSCFIteratorConfig::atomic_starting_magnetization, atomic_starting_magnetization_, q3::KohnShamSCFIteratorConfig::band_path, band_path_, q3::KohnShamSCFIteratorConfig::band_path_points_per_segment, band_path_points_per_segment_, q3::KohnShamSCFIteratorConfig::calculation, calculation_, q3::KohnShamSCFIterator::config(), q3::PlanewaveKohnShamSCFIterator::initialize_representation(), q3::PlanewaveKohnShamSCFIterator::magnetization(), q3::SCFIterator::number_of_spin_components(), q3::KohnShamSCFIteratorConfig::pseudopotential_set, pseudopotential_set(), pseudopotential_set_, q3::KohnShamSCFIteratorConfig::starting_magnetization, starting_magnetization_, and q3::log::warn().

◆ initialize_single_particle_states()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::initialize_single_particle_states ( )
inlineoverrideprotectedvirtual

The starting-guess Hamiltonian multiplies by the local potential on the wavefunction grid, pre-scaled by 1/N the way the Hamiltonian application holds it: restricted from the density grid through G space, completed within the pool, transformed back. The initializer took that conversion out of its own hands when the grids were first distributed, and this call went on passing the density-grid potential unconverted – read on the wrong grid, N times too large and different on every topology. Wherever there were more atomic orbitals than bands, the bands kept were chosen with it.

A previous geometry's bands, when offered, replace the atomic guess as the starting set the Rayleigh-Ritz step below rotates. The checkpoint writer stores one spin channel only, so a spin-polarized run keeps the atomic guess.

Implements q3::KohnShamSCFIterator.

Definition at line 774 of file init.hpp.

References cached_kleinman_bylander_projectors_, q3::NormConservingPlanewaveWavefunctionInitializer::compute_atomic_wavefunctions(), q3::compute_kleinman_bylander_projectors(), q3::compute_smooth_grid_potential_from_dense(), q3::count_atomic_orbitals(), q3::KohnShamSCFIterator::crystal_structure(), q3::log::debug(), q3::PlanewaveKohnShamSCFIterator::diagonalizer_, q3::PlanewaveKohnShamSCFIterator::execution_policy_, q3::PlanewaveBasis::fft_wave(), q3::PlanewaveKohnShamSCFIterator::g_vector_indices(), q3::log::info(), q3::NormConservingPlanewaveWavefunctionInitializer::initialize_interpolation_table(), q3::ProfilingCounters::instance(), q3::inverse_fft_smooth_potential(), q3::PlanewaveKohnShamSCFIterator::kinetic_energy_squared(), q3::PlanewaveKohnShamSCFIterator::kpoint_grid(), log_pseudopotential_summary(), q3::ProfilingCounters::log_resident_checkpoint(), q3::ProfilingCounters::log_resident_checkpoint_debug(), q3::PlanewaveKohnShamSCFIterator::number_of_bands_, q3::PlanewaveKohnShamSCFIterator::number_of_kpoint_states(), q3::KPointsGrid::number_of_kpoints(), q3::PlanewaveKohnShamSCFIterator::number_of_plane_waves(), q3::SCFIterator::number_of_spin_components(), q3::PlanewaveKohnShamSCFIterator::planewave_basis_, q3::PlanewaveKohnShamSCFIterator::preload_single_particle_states(), q3::QuantumSystem< QuantumStateType >::preloaded_quantum_system_, q3::KohnShamSCFIterator::prepare_hamiltonian(), q3::PlanewaveKohnShamSCFIterator::quantum_system_, quantum_system_snapshot_, q3::KohnShamSCFIterator::real_space_potential_, q3::execution::ExecutionPolicy::reduce_group_distributed_result(), q3::execution::PlanewaveExecutionPolicy::reduce_scalar(), q3::ProfilingCounters::release_unused_heap(), report_memory_estimate(), q3::NormConservingPlanewaveWavefunctionInitializer::rotate_wavefunctions(), setup_hubbard(), take_saved_starting_wavefunctions(), q3::FFTGrid::total_grid_points(), and q3::PlanewaveKohnShamSCFIterator::update_effective_potential().

◆ is_at_band_path_segment_boundary()

bool q3::PlanewavePseudopotentialKohnShamSCFIterator::is_at_band_path_segment_boundary ( int  kpoint_index) const
inlineprotected

Check whether a k-point index falls on a band-path segment boundary.

Segment boundaries are the high-symmetry points where the path direction changes (e.g., G, X, W, K in a G→X→W→K→G→L path). At these points, the eigenstates may reorder between segments, so forward propagation of wavefunctions across the boundary would bias the Davidson solver toward eigenstates from the wrong symmetry direction.

Returns false for SCF calculations (no band path defined) and for the endpoint of the last segment (which has no following segment to pollute).

The last k-point (endpoint of the final segment) is not a boundary because there is no following segment.

Definition at line 1640 of file init.hpp.

Referenced by solve_single_particle_states().

◆ is_iteration_converged()

bool q3::PlanewavePseudopotentialKohnShamSCFIterator::is_iteration_converged ( ) const
inlineoverrideprotectedvirtual

The base check alone lets a DFT+U run exit while the (now damped, see previous_hubbard_occupation_matrices_) occupation matrix is still visibly moving iteration to iteration: the density can be self-consistent while V_U, built from a still-relaxing n, is not. hubbard_occupation_residual_ is updated for this iteration inside construct_density_from_states(), which perform_iteration() always runs before this is checked (SCFIterator::iterate()), so it is never stale by an iteration. The hubbard_manifolds_.empty() short-circuit means non-Hubbard runs never consult the residual at all, so its "unconverged" default (see the member doc) never matters for them.

occupation_matrices going into the damping step is already pool- and band-reduced (accumulate_hubbard_occupation_and_potential's own MPI reduction, upstream of the damping block), and mixing_beta_ is the same scalar on every rank, so hubbard_occupation_residual_ is deterministic pure arithmetic on already-rank-consistent inputs — unlike density_residual_, it needs no reduce_scalar_max of its own (see that residual's docstring for why it needs one: per-rank FFTW plan noise, which nothing in the damping step re-introduces).

Reimplemented from q3::KohnShamSCFIterator.

Definition at line 1077 of file init.hpp.

References q3::SCFIterator::convergence_threshold_, q3::HubbardOccupationMixer::damping_active(), hubbard_manifolds_, hubbard_occupation_mixer_, hubbard_occupation_residual_, and q3::SCFIterator::is_iteration_converged().

◆ load_one_center_occupations()

virtual void q3::PlanewavePseudopotentialKohnShamSCFIterator::load_one_center_occupations ( const std::vector< Matrix< Real > > &  occupations_by_spin)
inlinevirtual

Hand over ρ_ij from a checkpoint, so D's one-centre term is built from the converged occupations before the first Hamiltonian and stays so for the whole run. Call after construction and before run(), like load_effective_potential(). Nothing to do where D has no such term.

Reimplemented in q3::PawPlanewavePseudopotentialKohnShamSCFIterator.

Definition at line 290 of file init.hpp.

◆ local_ionic_potential_g()

const std::vector< Complex > & q3::PlanewavePseudopotentialKohnShamSCFIterator::local_ionic_potential_g ( ) const
inlineoverrideprotectedvirtual

Return the local ionic potential in reciprocal space.

Implements q3::PlanewaveKohnShamSCFIterator.

Definition at line 1775 of file init.hpp.

Referenced by valence_exchange_correlation_potential_g_of().

◆ log_pseudopotential_summary()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::log_pseudopotential_summary ( int  number_of_atomic_wavefunctions) const
inlineprotected

Definition at line 1993 of file init.hpp.

References q3::log::info().

Referenced by initialize_single_particle_states().

◆ norm_conserving_quantum_system()

const NormConservingPlanewaveKohnShamQuantumSystem & q3::PlanewavePseudopotentialKohnShamSCFIterator::norm_conserving_quantum_system ( ) const
inline

Access the pseudopotential quantum-system snapshot built during initialization.

Definition at line 234 of file init.hpp.

References quantum_system_snapshot_.

Referenced by q3::internal::build_wannier_interface_record().

◆ offer_starting_wavefunctions()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::offer_starting_wavefunctions ( std::string  save_directory)
inline

Offer the bands a previous geometry saved in save_directory as this run's starting wavefunctions, as pw.x's next ionic step starts from the last one's. Each k-point whose wfc<k>.dat fits this run's basis starts from those bands, passed through the same Rayleigh-Ritz step as the atomic guess, so they are re-orthonormalized in this geometry's overlap and given eigenvalues before the eigensolver sees them. Any other k-point falls back to the atomic + random guess. Only the starting point changes, never what the SCF converges to.

Definition at line 356 of file init.hpp.

◆ one_center_occupations()

virtual std::vector< Matrix< Real > > q3::PlanewavePseudopotentialKohnShamSCFIterator::one_center_occupations ( ) const
inlinevirtual

The on-site occupations ρ_ij per spin channel, which the checkpoint stores: what D's one-centre term is built from. Empty wherever D has no such term; the PAW iterator overrides this.

Reimplemented in q3::PawPlanewavePseudopotentialKohnShamSCFIterator.

Definition at line 272 of file init.hpp.

Referenced by write_checkpoints().

◆ projector_overlap_coefficients()

virtual const Matrix< Real > & q3::PlanewavePseudopotentialKohnShamSCFIterator::projector_overlap_coefficients ( ) const
inlinevirtual

Overlap coefficients ⟨β_i|ψ_nk⟩ at convergence.

Returns an empty matrix for norm-conserving calculations. The ultrasoft iterator overrides this to return the accumulated coefficients.

Reimplemented in q3::UltrasoftPlanewavePseudopotentialKohnShamSCFIterator.

Definition at line 262 of file init.hpp.

◆ propagate_wavefunctions_backward()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::propagate_wavefunctions_backward ( int  source_kpoint_state_index,
int  target_kpoint_state_index 
)
inlineprotected

Copy converged wavefunctions from one k-point state to another (backward direction).

Unlike propagate_wavefunctions_to_next_kpoint which only moves forward, this copies from any source to any target state index. Used to seed k[0] from k[1]'s converged wavefunctions after the forward pass.

Definition at line 1596 of file init.hpp.

◆ propagate_wavefunctions_to_next_kpoint()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::propagate_wavefunctions_to_next_kpoint ( int  current_kpoint_state_index,
int  total_kpoint_states 
)
inlineprotected

Copy converged wavefunctions from the current k-point to the next k-point's slot in quantum_system_, providing a physically motivated initial guess for the Davidson solver.

When the two k-points have different numbers of plane waves (due to the |k+G|² cutoff sphere varying with k), the coefficients are truncated or zero-padded. This is valid because G-vectors are sorted by kinetic energy, so the leading coefficients correspond to the most important basis functions.

Definition at line 1542 of file init.hpp.

Referenced by solve_single_particle_states().

◆ pseudopotential_set()

const PseudopotentialSet & q3::PlanewavePseudopotentialKohnShamSCFIterator::pseudopotential_set ( ) const
inline

Access the pseudopotential set by const reference.

Definition at line 226 of file init.hpp.

References pseudopotential_set_.

Referenced by q3::internal::build_wannier_interface_record(), initialize_representation(), and set_owned_pseudopotential_set().

◆ read_saved_bands()

std::vector< std::vector< Complex > > q3::PlanewavePseudopotentialKohnShamSCFIterator::read_saved_bands ( int  kpoint_index) const
inlineprotected

The first number_of_bands_ bands of wfc<global k + 1>.dat in the offered directory, on this rank's plane waves, matched by Miller index. Empty when the file is missing or unreadable, or was written for a different basis: another gamma treatment, cell or k-point (a vc-relax step moves the cell), fewer bands, or a plane wave of this rank's it does not hold.

Files are matched by k-point index, and the k-point checked. Within a relaxation the symmetry is held fixed, so the irreducible k-points and their order are the same from step to step; a geometry whose symmetry changes them starts the k-points that moved from the atomic guess.

Definition at line 1910 of file init.hpp.

References q3::QEPlanewaveKohnShamWavefunctionReader::band_coefficients(), q3::log::debug(), q3::QEPlanewaveKohnShamWavefunctionReader::is_gamma_only(), q3::QEPlanewaveKohnShamWavefunctionReader::kpoint_coordinates(), q3::QEPlanewaveKohnShamWavefunctionReader::miller_indices(), q3::QEPlanewaveKohnShamWavefunctionReader::number_of_bands(), q3::QEPlanewaveKohnShamWavefunctionReader::read(), and q3::QEPlanewaveKohnShamWavefunctionReader::reciprocal_lattice_vectors().

◆ refresh_quantum_system_snapshot()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::refresh_quantum_system_snapshot ( )
inline

Give the snapshot the electronic state the iterator currently holds.

The snapshot is the only object carrying the pseudopotential data – beta tables, augmentation, the ultrasoft basis – because the factory built it as the right subclass. quantum_system_ is a by-value member of the base type and carries the wavefunctions and eigenvalues. Anything needing both at once (a Wannier capture on an ultrasoft or PAW dataset) has to bring them together first, which result() also does when it assembles the state to hand back.

Copies electronic state only; the pseudopotential data on the snapshot is untouched.

Definition at line 252 of file init.hpp.

References q3::PlanewaveKohnShamSCFIterator::quantum_system_, and quantum_system_snapshot_.

Referenced by q3::internal::build_wannier_interface_record().

◆ release_scf_workspace()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::release_scf_workspace ( )
inlineoverridevirtual

The projector cache is the SCF's too: the forces and stress build their own. The applicator holds pointers into it, so its view is cleared first and the storage freed after; the cache refills on demand.

Reimplemented from q3::PlanewaveKohnShamSCFIterator.

Definition at line 394 of file init.hpp.

References cached_kleinman_bylander_projectors_, q3::PlanewaveKohnShamSCFIterator::diagonalizer_, and q3::PlanewaveKohnShamSCFIterator::release_scf_workspace().

◆ report_memory_estimate()

◆ report_unconverged_solve()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::report_unconverged_solve ( int  kpoint_index_state) const
inlineprotected

Warn when a non-self-consistent solve kept bands short of the tolerance.

A self-consistent run finishes them on its next iteration, so only the NSCF pass reports: its eigenvectors are the answer, and a model built on them (a band structure, a Wannier capture) inherits the error silently.

Definition at line 1759 of file init.hpp.

References q3::log::warn().

Referenced by solve_single_particle_states().

◆ requires_one_center_occupations()

virtual bool q3::PlanewavePseudopotentialKohnShamSCFIterator::requires_one_center_occupations ( ) const
inlinevirtual

Whether a non-self-consistent pass must be handed those occupations before it diagonalizes – true exactly where D carries a one-centre term.

Reimplemented in q3::PawPlanewavePseudopotentialKohnShamSCFIterator.

Definition at line 280 of file init.hpp.

◆ result()

NormConservingPlanewaveKohnShamSCFState q3::PlanewavePseudopotentialKohnShamSCFIterator::result ( ) const
inlineoverridevirtual

Assemble and return a snapshot of the converged SCF state.

The ultrasoft subclass overrides this to inject the effective D-matrix into the snapshot.

Share the existing quantum system snapshot instead of creating a new one. The PP basis (beta tables, local potential, core charge) is expensive to initialize, and we only need a read-only view for forces/stress/IO.

Implements q3::PlanewaveKohnShamSCFIterator.

Reimplemented in q3::UltrasoftPlanewavePseudopotentialKohnShamSCFIterator.

Definition at line 83 of file init.hpp.

References q3::PlanewaveKohnShamSCFState::charge_density_g, q3::KohnShamSCFIterator::charge_density_g_, q3::PlanewaveKohnShamSCFState::charge_density_real, q3::KohnShamSCFIterator::charge_density_real_, q3::KohnShamSCFIterator::config(), q3::SCFState::converged, q3::KohnShamSCFIterator::crystal_structure(), q3::PlanewaveKohnShamSCFState::crystal_structure, energies_, q3::NormConservingPlanewaveKohnShamSCFState::energies_data_, q3::KohnShamSCFIterator::exchange_correlation(), q3::PlanewaveKohnShamSCFState::exchange_correlation, q3::KohnShamSCFIterator::exchange_correlation_potential_g(), q3::PlanewaveKohnShamSCFState::exchange_correlation_potential_g, q3::PlanewaveKohnShamSCFState::execution_policy, q3::PlanewaveKohnShamSCFIterator::execution_policy_, q3::NormConservingPlanewaveKohnShamSCFState::hubbard_d_matrix_per_spin, hubbard_d_matrix_per_spin_, q3::NormConservingPlanewaveKohnShamSCFState::hubbard_manifolds, hubbard_manifolds_, q3::KohnShamSCFIteratorConfig::hubbard_projector_type, q3::NormConservingPlanewaveKohnShamSCFState::hubbard_projector_type, q3::SCFIterator::is_converged(), q3::SCFIterator::iteration(), q3::PlanewaveKohnShamSCFIterator::kpoint_grid(), q3::PlanewaveKohnShamSCFState::kpoint_grid, q3::PlanewaveKohnShamSCFState::planewave_basis, q3::PlanewaveKohnShamSCFIterator::planewave_basis_, q3::PlanewaveKohnShamSCFIterator::quantum_system_, quantum_system_snapshot_, q3::NormConservingPlanewaveKohnShamSCFState::quantum_system_snapshot_, q3::PlanewaveKohnShamSCFState::real_space_potential, q3::KohnShamSCFIterator::real_space_potential_, q3::SCFState::scf_iterations, q3::PlanewaveKohnShamSCFState::total_potential_g, q3::KohnShamSCFIterator::total_potential_g_, q3::PlanewaveKohnShamSCFState::total_potential_g_by_spin, and q3::KohnShamSCFIterator::total_potential_g_by_spin_.

Referenced by q3::UltrasoftPlanewavePseudopotentialKohnShamSCFIterator::result(), and write_checkpoints().

◆ set_diagonalizer_maximum_iterations_for_nscf()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::set_diagonalizer_maximum_iterations_for_nscf ( int  maximum_iterations)
inline

Allow a fixed-potential pass enough Davidson iterations to converge every band.

Pending, like the tolerance above, until the diagonalizer exists. Also turns on the report of any k-point whose solve still ends with bands unconverged, since a single pass has no later iteration to finish them.

Definition at line 317 of file init.hpp.

References q3::PlanewaveKohnShamSCFIterator::nscf_override_maximum_iterations_.

◆ set_diagonalizer_tolerance_for_nscf()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::set_diagonalizer_tolerance_for_nscf ( Real  tolerance)
inline

Set the diagonalizer tolerance directly, bypassing the adaptive SCF scheme.

Intended for use by the NSCF flavor, which runs only a single diagonalization pass. The SCF adaptive scheme always starts at the loose initial threshold (1e-2 Ry) on iteration 1, which is far too loose for a fixed-potential NSCF calculation and causes Davidson to converge to wrong conduction-band eigenvalues at special high-symmetry k-points.

This method may be called before run() when the diagonalizer_ is not yet constructed. The requested tolerance is stored as a pending override and applied on the first call to set_diagonalization_tolerance() inside run().

Definition at line 306 of file init.hpp.

References q3::PlanewaveKohnShamSCFIterator::nscf_override_tolerance_.

◆ set_owned_pseudopotential_set()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::set_owned_pseudopotential_set ( PseudopotentialSet  pseudopotential_set)
inline

Transfer ownership of a PseudopotentialSet into this iterator.

Definition at line 66 of file init.hpp.

References pseudopotential_set(), and pseudopotential_set_.

◆ setup_hubbard()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::setup_hubbard ( )
inlineprotected

Resolve DFT+U (Hubbard) manifolds and cache their atomic-orbital projectors, once, for the whole SCF run (geometry-only, like KB projectors). No-op if config().hubbard is empty. The one remaining scope gate is the Davidson diagonalizer.

hubbard_projector_type selects "atomic" (raw pseudo-atomic orbitals, the default) or "ortho-atomic" (the full system-wide atomic-orbital set Lowdin-orthogonalized jointly before the manifold's columns are selected out – see the call site below). HubbardForceCalculator carries the ortho-atomic gradient for norm-conserving datasets, including the term from every other orbital's own position-dependence through the joint S^-1/2 transform.

Occupation seeding directives are validated here, where the manifolds are known, so a typo'd species or an impossible spin dies at setup with a named cause instead of surfacing as a silently unseeded run converging into the wrong minimum – the exact failure mode seeding exists to prevent.

ortho-atomic: Lowdin-orthogonalize the FULL system-wide atomic-orbital set (all atoms, all shells) jointly – matching QE's convention, which orthogonalizes the system-wide atomic-orbital set first – before selecting out the Hubbard manifold's columns below. This must operate on the whole set, not a per-manifold subset: a manifold-only Lowdin transform would be a materially different (non-standard) definition.

Ultrasoft and PAW ortho-atomic projectors use the generalized <phi_i|S|phi_j> metric. Apply the same production overlap operator used by Davidson so its beta-projector ordering, q matrix, Gamma completion, and band-group reduction cannot drift from the eigenproblem definition.

The Lowdin metric is itself a physical G-space overlap. Gamma-only storage contains one member of each +/-G pair, so diagonalizing the raw half-sphere sum would define a different projector from the explicit full-sphere run. Complete the metric before the band-group reduction and eigendecomposition, using the same overlap rule as the Hubbard occupation path below.

For ultrasoft and PAW the Hubbard occupations are defined with the all-electron inner product, <phi_m|S|psi>, not <phi_m|psi>: the pseudo orbital misses the on-site charge the augmentation carries, which for a 3d manifold is most of it.

Rather than thread S through the occupation matrix, the Hamiltonian term and the projector overlaps separately, S is applied once here to the cached projectors. S is Hermitian, so <S phi_m|psi> = <phi_m|S|psi>, and every consumer downstream — the occupation matrix, the applicator's |phi> V <phi| term — becomes correct with no further change.

Definition at line 544 of file init.hpp.

References q3::build_atomic_orbitals_g_space(), cached_hubbard_projectors_, q3::compute_hubbard_projector_overlaps(), q3::compute_kleinman_bylander_projectors(), q3::KohnShamSCFIterator::config(), q3::convert_gamma_only_projector_overlaps_to_full_sphere(), q3::create_overlap_operator(), q3::KohnShamSCFIterator::crystal_structure(), q3::PlanewaveKohnShamSCFIterator::diagonalization_method_, q3::PlanewaveKohnShamSCFIterator::diagonalizer_, q3::enumerate_atomic_orbitals(), q3::PlanewaveKohnShamSCFIterator::execution_policy_, q3::find_g_zero_plane_wave_index(), q3::PlanewaveKohnShamSCFIterator::g_vector_indices(), hubbard_d_matrix_per_spin_, hubbard_manifolds_, hubbard_seed_iterations_remaining_, q3::KohnShamSCFIteratorConfig::hubbard_starting_eigenvalues, q3::log::info(), q3::PlanewaveBasis::is_gamma_only(), q3::PlanewaveKohnShamSCFIterator::kpoint_grid(), q3::lowdin_orthogonalize_orbitals(), q3::KPointsGrid::number_of_kpoints(), q3::PlanewaveKohnShamSCFIterator::number_of_plane_waves(), q3::SCFIterator::number_of_spin_components(), q3::PlanewaveKohnShamSCFIterator::planewave_basis_, quantum_system_snapshot_, q3::execution::ExecutionPolicy::reduce_within_group(), q3::resolve_hubbard_manifolds(), q3::tabulate_atomic_wavefunctions_in_q_space(), and total_hubbard_orbitals_.

Referenced by initialize_single_particle_states().

◆ solve_single_particle_states()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::solve_single_particle_states ( )
inlineoverrideprotectedvirtual

── Forward pass: solve k-points 0, 1, 2, ..., N-1 ── Each k-point's converged wavefunctions seed the next k-point. At band-path segment boundaries (high-symmetry points where the path direction changes), propagation is skipped to avoid biasing the Davidson solver with wavefunctions from the wrong symmetry direction.

Propagate converged wavefunctions to the next k-point, unless we are at a segment boundary where the path direction changes.

HARD RULE: Propagation by direct coefficient copying is only valid if the G-vector bases are identical. In Q3, k-points have different G-spheres and sortings. Direct propagation destroys the good starting guess from the previous SCF iteration. Disable for SCF.

── Backward fix: re-solve edge k-points using neighbor seeds ── This is only relevant for band-path calculations to fix symmetry-breaking at segment boundaries. Skip for SCF.

Implements q3::KohnShamSCFIterator.

Definition at line 964 of file init.hpp.

References cached_kleinman_bylander_projectors_, calculation_, q3::compute_kleinman_bylander_projectors(), q3::KohnShamSCFIterator::crystal_structure(), q3::PlanewaveKohnShamSCFIterator::diagonalizer_, fix_edge_kpoints_with_backward_propagation(), q3::PlanewaveKohnShamSCFIterator::g_vector_indices(), hubbard_d_matrix_per_spin_, hubbard_manifolds_, is_at_band_path_segment_boundary(), q3::SCFIterator::iteration_, q3::PlanewaveKohnShamSCFIterator::kinetic_energy_squared(), q3::PlanewaveKohnShamSCFIterator::kpoint_grid(), q3::PlanewaveKohnShamSCFIterator::number_of_bands_, q3::PlanewaveKohnShamSCFIterator::number_of_kpoint_states(), q3::KPointsGrid::number_of_kpoints(), q3::PlanewaveKohnShamSCFIterator::number_of_plane_waves(), q3::SCFIterator::number_of_spin_components(), q3::PlanewaveKohnShamSCFIterator::planewave_basis_, propagate_wavefunctions_to_next_kpoint(), q3::PlanewaveKohnShamSCFIterator::quantum_system_, quantum_system_snapshot_, q3::KohnShamSCFIterator::real_space_potential_, and report_unconverged_solve().

◆ take_saved_starting_wavefunctions()

bool q3::PlanewavePseudopotentialKohnShamSCFIterator::take_saved_starting_wavefunctions ( int  kpoint_index,
std::vector< std::vector< Complex > > &  starting_wavefunctions 
) const
inlineprotected

The saved bands of one local k-point as this run's starting set, decided the same way on every rank of the pool: the Rayleigh-Ritz step that follows sums its subspace matrices across the pool, so its ranks must agree on how many starting vectors there are. False, and the set left alone, when any rank of the pool cannot use its share of the file.

Definition at line 1886 of file init.hpp.

Referenced by initialize_single_particle_states().

◆ valence_exchange_correlation_potential_g_of()

std::vector< Complex > q3::PlanewavePseudopotentialKohnShamSCFIterator::valence_exchange_correlation_potential_g_of ( const std::vector< std::vector< Real > > &  charge_density_real)
inline

Vxc(G) of a given valence density alone – without the nonlinear core correction's core charge, which the Hamiltonian's own Vxc includes.

For the mean-field export, whose VXC and vxc.dat need Vxc of the converged SCF density: a GW self-energy is built from the valence electrons, so the Vxc it replaces is the valence one. pw2bgw computes its VXC and vxc.dat the same way unless told otherwise, and its manual warns that keeping the core charge "will produce incorrect results" (vxc_zero_rho_core, default .TRUE., INPUT_pw2bgw). Measured on silicon with an NLCC dataset at 25 Ry: with the core charge, V_xc(G = 0) was -0.6750 Ry against pw2bgw's -0.6524 Ry. The base calculator is the one that adds no core charge (see NormConservingPlanewaveEffectivePotentialCalculator); without NLCC the two coincide. Touches none of the iterator's own potentials or energies.

Definition at line 337 of file init.hpp.

References q3::KohnShamSCFIterator::charge_density_real(), q3::PlanewaveEffectivePotentialCalculator::compute(), q3::KohnShamSCFIterator::crystal_structure(), q3::KohnShamSCFIterator::exchange_correlation_, q3::EffectivePotentialResult::exchange_correlation_potential_g, q3::PlanewaveKohnShamSCFIterator::execution_policy(), local_ionic_potential_g(), q3::SCFIterator::number_of_spin_components(), and q3::PlanewaveKohnShamSCFIterator::planewave_basis_.

◆ write_checkpoints()

void q3::PlanewavePseudopotentialKohnShamSCFIterator::write_checkpoints ( const std::string &  output_directory,
const std::string &  prefix 
) const
inlineoverridevirtual

Write binary checkpoint files (charge density, wavefunctions, and effective potential).

Writes:

  • charge-density.dat — QE-compatible Fortran binary charge density
  • wfc*.dat — QE-compatible Fortran binary wavefunctions per k-point
  • effective-potential.q3cp — Q3-native v3 binary with V_eff in real space and, for PAW, the on-site occupations ρ_ij

The effective-potential file enables NSCF calculations to load V_eff directly instead of reconstructing it from charge density + input parameters, and to build a PAW dataset's one-centre term of D from the converged ρ_ij.

Under k-point pools of one rank each, every rank writes the wfc*.dat files of its own k-points, and the root writes the rest. Those it can write alone: the density, the potential built from it and the PAW ρ_ij are reduced across pools, so every rank already holds them whole. Only the eigenvalues are per pool, and are gathered first. The result is the same directory a serial run writes, which a serial NSCF restores.

Collective: every rank must call this.

Every rank creates the directory it writes into rather than waiting on the root. Ranks may race to create it, so success is judged by the directory existing afterwards, not by which call made it.

Write the effective potential (V_Hxc + V_loc) to the Q3-native checkpoint, along with how the run that produced it ended.

The header fields are not decoration. A checkpoint travels away from the run that wrote it – to an NSCF job, to a restart, to a third party verifying a published calculation – and a reader has no other way to learn whether the density it holds converged, or what energy it converged to. Leaving them zero makes the file assert that it came from an unconverged run at zero energy, which is worse than saying nothing.

Reimplemented from q3::SCFIterator.

Definition at line 134 of file init.hpp.

References q3::KohnShamQuantumSystemSnapshot::charge_density_real, q3::KohnShamSCFIterator::charge_density_real_, q3::Matrix< T >::cols(), q3::KohnShamQuantumSystemSnapshot::converged, q3::create_charge_density_checkpoint(), q3::create_wavefunction_checkpoint(), q3::execution::PlanewaveExecutionPolicy::each_process_owns_whole_kpoints(), q3::KohnShamQuantumSystemSnapshot::effective_potential_real, q3::KohnShamQuantumSystemSnapshot::eigenvalues, q3::PlanewaveKohnShamSCFIterator::execution_policy_, q3::PlanewaveKohnShamSCFIterator::global_eigenvalues(), q3::log::info(), q3::SCFIterator::is_converged(), q3::execution::ExecutionPolicy::is_root(), q3::KohnShamQuantumSystemSnapshot::iteration, q3::SCFIterator::iteration(), q3::KohnShamQuantumSystemSnapshot::number_of_bands, q3::KohnShamQuantumSystemSnapshot::number_of_kpoint_states, q3::execution::PlanewaveExecutionPolicy::number_of_pools(), q3::KohnShamQuantumSystemSnapshot::number_of_spin_components, q3::SCFIterator::number_of_spin_components(), q3::KohnShamQuantumSystemSnapshot::one_center_occupations, one_center_occupations(), q3::KohnShamSCFIterator::real_space_potential_, result(), q3::Matrix< T >::rows(), q3::Q3PlanewaveKohnShamQuantumSystemCheckpoint::save(), q3::KohnShamQuantumSystemSnapshot::total_energy, q3::KohnShamSCFIterator::total_energy(), and q3::log::warn().

Member Data Documentation

◆ atomic_starting_magnetization_

std::vector<Real> q3::PlanewavePseudopotentialKohnShamSCFIterator::atomic_starting_magnetization_
protected

Definition at line 366 of file init.hpp.

Referenced by initialize_representation().

◆ band_path_

std::vector<std::pair<std::string, Vector3D> > q3::PlanewavePseudopotentialKohnShamSCFIterator::band_path_
protected

Definition at line 367 of file init.hpp.

Referenced by initialize_representation().

◆ band_path_points_per_segment_

int q3::PlanewavePseudopotentialKohnShamSCFIterator::band_path_points_per_segment_ = 20
protected

Definition at line 368 of file init.hpp.

Referenced by initialize_representation().

◆ cached_hubbard_projectors_

std::vector<q3::Matrix<Complex> > q3::PlanewavePseudopotentialKohnShamSCFIterator::cached_hubbard_projectors_
protected

Cached Hubbard atomic-orbital projectors per k-point, all manifolds' orbitals concatenated in hubbard_manifolds_ order (geometry-only, set once at setup).

Definition at line 422 of file init.hpp.

Referenced by accumulate_hubbard_occupation_and_potential(), and setup_hubbard().

◆ cached_kleinman_bylander_projectors_

std::vector<q3::Matrix<Complex> > q3::PlanewavePseudopotentialKohnShamSCFIterator::cached_kleinman_bylander_projectors_
protected

Cached KB projectors per k-point (reused by the projector overlap accumulation).

Definition at line 408 of file init.hpp.

Referenced by q3::UltrasoftPlanewavePseudopotentialKohnShamSCFIterator::accumulate_projector_overlaps(), initialize_single_particle_states(), release_scf_workspace(), and solve_single_particle_states().

◆ cached_symmetry_operations_

std::vector<SymmetryOperation> q3::PlanewavePseudopotentialKohnShamSCFIterator::cached_symmetry_operations_
mutableprotected

Definition at line 438 of file init.hpp.

Referenced by cached_symmetry_operations().

◆ calculation_

std::string q3::PlanewavePseudopotentialKohnShamSCFIterator::calculation_ = "self_consistent_field"
protected

Definition at line 363 of file init.hpp.

Referenced by initialize_representation(), and solve_single_particle_states().

◆ energies_

NormConservingPlanewaveKohnShamEnergies q3::PlanewavePseudopotentialKohnShamSCFIterator::energies_
protected

◆ hubbard_d_matrix_per_spin_

std::vector<std::vector<Complex> > q3::PlanewavePseudopotentialKohnShamSCFIterator::hubbard_d_matrix_per_spin_
protected

Dense block-diagonal Hubbard D-matrix per spin channel (column-major, refreshed once per SCF iteration in construct_density_from_states()).

Definition at line 447 of file init.hpp.

Referenced by result(), setup_hubbard(), and solve_single_particle_states().

◆ hubbard_manifolds_

std::vector<HubbardManifold> q3::PlanewavePseudopotentialKohnShamSCFIterator::hubbard_manifolds_
protected

DFT+U (Hubbard): resolved atom/shell manifolds; empty means no correction is active.

Definition at line 411 of file init.hpp.

Referenced by accumulate_hubbard_occupation_and_potential(), is_iteration_converged(), result(), setup_hubbard(), and solve_single_particle_states().

◆ hubbard_occupation_mixer_

HubbardOccupationMixer q3::PlanewavePseudopotentialKohnShamSCFIterator::hubbard_occupation_mixer_
protected

Owns the damping/Anderson state; see HubbardOccupationMixer.

Definition at line 461 of file init.hpp.

Referenced by is_iteration_converged().

◆ hubbard_occupation_residual_

Real q3::PlanewavePseudopotentialKohnShamSCFIterator::hubbard_occupation_residual_ {std::numeric_limits<Real>::max()}
protected

‖n_fresh − n_damped‖² — how far the freshly accumulated occupation matrix is from the damped one driving V_U, not the step actually taken (which is this scaled by the damping factor). The distinction matters because this is the quantity gating SCF exit. Same squared-magnitude convention density_residual_ uses. Updated by accumulate_hubbard_occupation_and_potential(); consulted by is_iteration_converged(). A large sentinel (never a false "converged") until the damping cache has been through at least one real blend.

Definition at line 459 of file init.hpp.

Referenced by is_iteration_converged().

◆ hubbard_occupation_traces_

std::vector<std::vector<Real> > q3::PlanewavePseudopotentialKohnShamSCFIterator::hubbard_occupation_traces_
protected

Tr[n] for each manifold and spin channel, as of the last SCF step that built the occupation matrices. Indexed [manifold][spin], parallel to hubbard_manifolds_; empty when no correction is active.

Definition at line 417 of file init.hpp.

Referenced by hubbard_occupation_traces().

◆ hubbard_potential_energy_

Real q3::PlanewavePseudopotentialKohnShamSCFIterator::hubbard_potential_energy_ {0.0}
protected

Σ_σ Tr[V_U^σ n^σ]; see hubbard_potential_energy().

Definition at line 442 of file init.hpp.

◆ hubbard_seed_iterations_remaining_

int q3::PlanewavePseudopotentialKohnShamSCFIterator::hubbard_seed_iterations_remaining_ = 0
protected

Iterations of occupation seeding still owed. Starts at 1 + hubbard_fixed_occupation_iterations: the first application is the starting guess, any further ones hold that guess in place while the wavefunctions adapt to it.

Definition at line 468 of file init.hpp.

Referenced by setup_hubbard().

◆ pseudopotential_set_

const PseudopotentialSet* q3::PlanewavePseudopotentialKohnShamSCFIterator::pseudopotential_set_ = nullptr
protected

◆ quantum_system_snapshot_

◆ starting_magnetization_

std::vector<Real> q3::PlanewavePseudopotentialKohnShamSCFIterator::starting_magnetization_
protected

Definition at line 365 of file init.hpp.

Referenced by initialize_representation().

◆ symmetry_operations_cached_

bool q3::PlanewavePseudopotentialKohnShamSCFIterator::symmetry_operations_cached_ {false}
mutableprotected

Definition at line 439 of file init.hpp.

Referenced by cached_symmetry_operations().

◆ total_hubbard_orbitals_

int q3::PlanewavePseudopotentialKohnShamSCFIterator::total_hubbard_orbitals_ = 0
protected

Definition at line 448 of file init.hpp.

Referenced by setup_hubbard().


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