|
Quantum 3xplorer (Q3)
An AI-native quantum simulation engine
|
#include <occupation_mixer.hpp>
Public Member Functions | |
| const HubbardOccupationMatrices & | blend (const HubbardOccupationMatrices &fresh, Real mixing_beta, Real convergence_threshold) |
| const HubbardOccupationMatrices & | damped () const |
The retained damped state, for callers that need it after blend. | |
| bool | damping_active () const |
| Whether non-monotone progress has switched damping on for this run. | |
| Real | residual () const |
| ||n_fresh - n_damped||^2 from the last blend; huge until one has run. | |
Definition at line 42 of file occupation_mixer.hpp.
|
inline |
Blend fresh into the retained state and return what should drive V_U.
mixing_beta is the damping factor once damping is active; convergence_threshold gates both SCF exit (via residual()) and the point at which the Anderson step stands down.
First call, or a manifold layout change mid-run. Both caches are indexed the same way, so both are dropped rather than indexed into while mismatched.
How far n still is from its own fixed point, measured before anything is blended: ||n_fresh - n_damped||^2, zero exactly when the freshly accumulated matrix already agrees with the one driving V_U. Same squared-magnitude convention density_residual_ uses.
What earns the damping is non-monotone progress: an occupation matrix that moves further from its fixed point than it was the iteration before. Monotone runs record zero such events ever; FeO, which does not converge in 100 iterations undamped, trips the counter almost immediately. Counted cumulatively rather than consecutively, because an oscillation alternates rather than growing every step.
">=", not ">": while damping is off the mixer passes the fresh matrix straight through, so a clean period-2 oscillation produces a constant mismatch rather than a growing one. Firing only on strict growth would leave exactly the sustained oscillation this exists to break undetected forever. Anything that fails to improve counts.
Anderson accelerates the hard middle of the SCF and then steps aside. Its extrapolation changes the path n takes, and a path change moves where the run stops by the size of the convergence threshold – which is the scale cross-basis energies are compared at. Restricting it to iterations where n is still further out than that threshold keeps the acceleration where the cost is and leaves the approach to the fixed point on the plain damped path.
Two-point secant: <r, r - r_prev> / |r - r_prev|^2, the one-term quasi-Newton step. Clamped, because the secant is exact only where the residual map is locally linear and can otherwise ask for an arbitrarily long step; at the clamp the update is still a damped step in the descent direction rather than a leap.
Definition at line 52 of file occupation_mixer.hpp.
References q3::constants::hubbard_anderson_secant_minimum_denominator, q3::constants::hubbard_anderson_theta_limit, q3::constants::hubbard_damping_trigger_iterations, and residual().
|
inline |
The retained damped state, for callers that need it after blend.
Definition at line 175 of file occupation_mixer.hpp.
|
inline |
Whether non-monotone progress has switched damping on for this run.
Definition at line 170 of file occupation_mixer.hpp.
Referenced by q3::PlanewavePseudopotentialKohnShamSCFIterator::is_iteration_converged().
|
inline |
||n_fresh - n_damped||^2 from the last blend; huge until one has run.
Definition at line 165 of file occupation_mixer.hpp.
Referenced by blend().