|
Quantum 3xplorer (Q3)
An AI-native quantum simulation engine
|
#include <linear.hpp>
Inheritance diagram for q3::LinearMixer:Public Member Functions | |
| LinearMixer (Real mixing_parameter=0.4) | |
| void | mix_in_reciprocal_space (std::vector< std::vector< Complex > > &rho_in_g, const std::vector< std::vector< Complex > > &rho_out_g, int number_of_spin_components) override |
| std::string | name () const override |
Public Member Functions inherited from q3::ReciprocalSpaceMixer | |
| void | initialize (const MixerEnvironment &environment) override |
| Supply the representation context the mixer needs before the first mix(). | |
| void | mix (const std::vector< std::vector< Real > > &input_density, std::vector< std::vector< Real > > &output_density, int number_of_spin_components) override |
| Mixer (Real mixing_parameter, int history_depth) | |
Public Member Functions inherited from q3::Mixer | |
| Mixer (Real mixing_parameter, int history_depth) | |
| virtual | ~Mixer ()=default |
| int | history_depth () const |
| Real | last_residual_norm () const |
| Real | mixing_parameter () const |
| virtual void | reset () |
Additional Inherited Members | |
Static Public Member Functions inherited from q3::ReciprocalSpaceMixer | |
| static void | convert_total_magnetization_to_up_down (std::vector< std::vector< Complex > > &density_g) |
| In-place (ρ↑+ρ↓, ρ↑−ρ↓) → (ρ↑, ρ↓). | |
| static void | convert_up_down_to_total_magnetization (std::vector< std::vector< Complex > > &density_g) |
| In-place (ρ↑, ρ↓) → (ρ↑+ρ↓, ρ↑−ρ↓). | |
| static std::vector< Real > | sum_over_spin_channels (const std::vector< std::vector< Real > > &density_real, int number_of_spin_components) |
| Total real-space density ρ↑+ρ↓ (a copy of channel 0 when unpolarized). | |
Protected Member Functions inherited from q3::ReciprocalSpaceMixer | |
| Real | compute_metric_dot_product (const std::vector< std::vector< Complex > > &rho_a, const std::vector< std::vector< Complex > > &rho_b, int number_of_spin_components, int g_vector_count=-1) const |
Protected Attributes inherited from q3::ReciprocalSpaceMixer | |
| std::vector< Real > | charge_metric_weights_ |
| int | first_nonzero_g_index_ {0} |
| bool | is_gamma_only_ {false} |
| Real | magnetization_metric_weight_ {0.0} |
| int | number_of_smooth_g_vectors_ {0} |
| std::shared_ptr< Preconditioner > | preconditioner_ |
| std::function< void(const std::vector< Complex > &, std::vector< Real > &)> | to_real_space_ |
| std::function< void(const std::vector< Real > &, std::vector< Complex > &)> | to_reciprocal_space_ |
Protected Attributes inherited from q3::Mixer | |
| int | history_depth_ |
| Real | last_residual_norm_ {-1.0} |
| Real | mixing_parameter_ |
Simple linear density mixer operating in G-space with optional Kerker preconditioning.
Convergence is guaranteed for sufficiently small alpha, unlike Broyden which can diverge for difficult metallic systems.
Not to be confused with mixing_mode='plain' in a Quantum ESPRESSO input: there, 'plain' only turns the preconditioner off and the Broyden history still runs, which is why io/input/parser/qe.hpp maps it to this code's Broyden mixer rather than to this class.
Definition at line 37 of file linear.hpp.
|
inlineexplicit |
Definition at line 39 of file linear.hpp.
|
inlineoverridevirtual |
Perform one linear mixing step in G-space.
ρ_new = ρ_in + α · K(G) · (ρ_out - ρ_in)
where K is the configured residual preconditioner (Kerker or local-TF if enabled, the identity otherwise).
Compute last_residual_norm_ BEFORE mixing using the pre-mix residual, in the same shared two-channel metric Broyden reports – see ReciprocalSpaceMixer::compute_metric_dot_product().
Apply linear mixing: ρ_new = ρ_in + α · K(G) · (ρ_out - ρ_in) K(G) = G²/(G²+q0²) for Kerker, 1 otherwise. Only mix smooth G here. Hard G above smooth_g_vector_count are mixed separately, by the hard-G loop in ReciprocalSpaceMixer::mix().
Charge channel: G=0 is fixed by charge conservation, and the preconditioner screens the Coulomb response. Magnetization channel (spin 1 in the (total, m) representation): the moment is not conserved, so its G=0 component must be mixed, and no screening applies (no Coulomb kernel for m).
The preconditioner is an operator, so the residual is formed first and preconditioned as a whole rather than scaled per G on the fly. It is built over the full G range even though only the smooth range is mixed here – a non-diagonal preconditioner couples G components, and truncating its input to the smooth range would solve a different problem. For a diagonal preconditioner this is exactly the previous per-G multiply.
Implements q3::ReciprocalSpaceMixer.
Definition at line 49 of file linear.hpp.
References q3::ReciprocalSpaceMixer::compute_metric_dot_product(), q3::ReciprocalSpaceMixer::first_nonzero_g_index_, q3::Mixer::last_residual_norm_, q3::Mixer::mixing_parameter_, q3::ReciprocalSpaceMixer::number_of_smooth_g_vectors_, and q3::ReciprocalSpaceMixer::preconditioner_.
|
inlineoverridevirtual |
Implements q3::Mixer.
Definition at line 114 of file linear.hpp.