Loading...
Searching...
No Matches
q3::ReciprocalSpaceMixer Class Referenceabstract

#include <init.hpp>

+ Inheritance diagram for q3::ReciprocalSpaceMixer:

Public Member Functions

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
 
virtual void mix_in_reciprocal_space (std::vector< std::vector< Complex > > &input_density_g, const std::vector< std::vector< Complex > > &output_density_g, int number_of_spin_components)=0
 
 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 std::string name () const =0
 
virtual void reset ()
 

Static Public Member Functions

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

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

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_
 

Detailed Description

Mixer operating on G-space charge density vectors with a precomputed metric.

The unified real-space mix() transforms densities to reciprocal space, defers to the concrete mix_in_reciprocal_space() update, and transforms back, so the caller never has to know the mixer works in G-space.

Definition at line 26 of file init.hpp.

Member Function Documentation

◆ compute_metric_dot_product()

Real q3::ReciprocalSpaceMixer::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
inlineprotected

Weighted inner product ⟨ρ_a|ρ_b⟩ in the two-channel mixing metric – the same metric the SCF reports its convergence estimate in, so that a conv_thr value carried in from a plane-wave input means the same thing here as there:

channel 0 (total charge): Σ_{G≠0} w_charge(G) ρ_a*(G) ρ_b(G), w_charge = Hartree kernel ∝ 1/G² channel 1 (magnetization): Σ_{all G, incl. G=0} w_m ρ_a*(G) ρ_b(G), w_m = flat metric (no Coulomb kernel)

On gamma-only half-sphere grids every G≠0 term is doubled (ρ(-G) = ρ*(G)); the G=0 magnetization term is stored once and is not doubled.

Parameters
g_vector_countLimit the G range (e.g. smooth-only mixing); pass a negative value to use the full vectors.

Total charge channel: Hartree 1/G² metric, G=0 excluded (fixed by charge conservation, and the kernel diverges there).

Magnetization channels: flat metric including G=0 (the total moment is not conserved and must contribute to the metric).

Definition at line 168 of file init.hpp.

References charge_metric_weights_, first_nonzero_g_index_, is_gamma_only_, and magnetization_metric_weight_.

Referenced by q3::BroydenMixer::mix_in_reciprocal_space(), and q3::LinearMixer::mix_in_reciprocal_space().

◆ convert_total_magnetization_to_up_down()

static void q3::ReciprocalSpaceMixer::convert_total_magnetization_to_up_down ( std::vector< std::vector< Complex > > &  density_g)
inlinestatic

In-place (ρ↑+ρ↓, ρ↑−ρ↓) → (ρ↑, ρ↓).

Definition at line 132 of file init.hpp.

Referenced by mix().

◆ convert_up_down_to_total_magnetization()

static void q3::ReciprocalSpaceMixer::convert_up_down_to_total_magnetization ( std::vector< std::vector< Complex > > &  density_g)
inlinestatic

In-place (ρ↑, ρ↓) → (ρ↑+ρ↓, ρ↑−ρ↓).

Definition at line 121 of file init.hpp.

Referenced by mix().

◆ initialize()

◆ mix()

void q3::ReciprocalSpaceMixer::mix ( const std::vector< std::vector< Real > > &  input_density,
std::vector< std::vector< Real > > &  output_density,
int  number_of_spin_components 
)
inlineoverridevirtual

Mix one self-consistent field step using real-space densities.

Parameters
input_densitydensity used to build the potential (rho_in), per spin.
output_densitydensity from the bands (rho_out) on entry; overwritten with the mixed next-iteration density on exit, per spin.
number_of_spin_componentsnumber of spin channels.

Each mixer performs whatever internal transforms it needs (e.g. FFT to reciprocal space) so callers never branch on the mixer's space.

A density-dependent preconditioner needs the TOTAL real-space density, and it needs it here: mix() receives (ρ↑, ρ↓), and the rotation to (total, magnetization) happens further down in G-space, so the sum over spin channels has to be done explicitly before the transforms.

Spin-polarized densities are mixed in the (total, magnetization) representation, the one that diagonalizes the mixing metric: channel 0 = ρ↑+ρ↓ carries the whole Coulomb response, so it gets the 1/G² metric and Kerker preconditioning; channel 1 = ρ↑−ρ↓ has no Coulomb kernel, so it gets the flat metric and no preconditioning. The per-channel metric code in the concrete mixers assumes this layout.

For dual-grid (ultrasoft/PAW) calculations, the hard G-vectors (above the smooth cutoff) carry the augmentation charges. They sit outside the Broyden subspace, so they need an update of their own; plain linear mixing at the configured mixing_beta is the cheapest stable one. Q3 was replacing them at 100% (beta=1.0), which caused augmentation oscillations and Broyden divergence. Fix: linear-mix hard G with the same mixing_parameter_ used for the smooth region.

Implements q3::Mixer.

Definition at line 41 of file init.hpp.

References convert_total_magnetization_to_up_down(), convert_up_down_to_total_magnetization(), mix_in_reciprocal_space(), q3::Mixer::mixing_parameter_, number_of_smooth_g_vectors_, preconditioner_, sum_over_spin_channels(), to_real_space_, and to_reciprocal_space_.

◆ mix_in_reciprocal_space()

virtual void q3::ReciprocalSpaceMixer::mix_in_reciprocal_space ( std::vector< std::vector< Complex > > &  input_density_g,
const std::vector< std::vector< Complex > > &  output_density_g,
int  number_of_spin_components 
)
pure virtual

Perform one mixing step in G-space.

Parameters
input_density_ginput density in G-space (modified in-place with the mixed result).
output_density_goutput density in G-space.
number_of_spin_componentsnumber of spin components.

Implemented in q3::BroydenMixer, and q3::LinearMixer.

Referenced by mix().

◆ Mixer()

q3::Mixer::Mixer ( Real  mixing_parameter,
int  history_depth 
)
inline

Definition at line 48 of file init.hpp.

◆ sum_over_spin_channels()

static std::vector< Real > q3::ReciprocalSpaceMixer::sum_over_spin_channels ( const std::vector< std::vector< Real > > &  density_real,
int  number_of_spin_components 
)
inlinestatic

Total real-space density ρ↑+ρ↓ (a copy of channel 0 when unpolarized).

Definition at line 108 of file init.hpp.

Referenced by mix().

Member Data Documentation

◆ charge_metric_weights_

std::vector<Real> q3::ReciprocalSpaceMixer::charge_metric_weights_
protected

Definition at line 205 of file init.hpp.

Referenced by compute_metric_dot_product(), and initialize().

◆ first_nonzero_g_index_

int q3::ReciprocalSpaceMixer::first_nonzero_g_index_ {0}
protected

◆ is_gamma_only_

bool q3::ReciprocalSpaceMixer::is_gamma_only_ {false}
protected

Definition at line 209 of file init.hpp.

Referenced by compute_metric_dot_product(), and initialize().

◆ magnetization_metric_weight_

Real q3::ReciprocalSpaceMixer::magnetization_metric_weight_ {0.0}
protected

Definition at line 207 of file init.hpp.

Referenced by compute_metric_dot_product(), and initialize().

◆ number_of_smooth_g_vectors_

int q3::ReciprocalSpaceMixer::number_of_smooth_g_vectors_ {0}
protected

◆ preconditioner_

std::shared_ptr<Preconditioner> q3::ReciprocalSpaceMixer::preconditioner_
protected

◆ to_real_space_

std::function<void(const std::vector<Complex>&, std::vector<Real>&)> q3::ReciprocalSpaceMixer::to_real_space_
protected

Definition at line 204 of file init.hpp.

Referenced by initialize(), and mix().

◆ to_reciprocal_space_

std::function<void(const std::vector<Real>&, std::vector<Complex>&)> q3::ReciprocalSpaceMixer::to_reciprocal_space_
protected

Definition at line 203 of file init.hpp.

Referenced by initialize(), and mix().


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