53 if (!matches_layout(damped_, fresh)) {
61 residual_ = std::numeric_limits<Real>::max();
72 for_each_element(fresh, [&](
size_t manifold,
size_t spin,
size_t element) {
74 std::norm(fresh[manifold][spin][element] - damped_[manifold][spin][element]);
86 if (!damping_active_) {
95 if (mismatch >= previous_mismatch_)
96 ++nonmonotone_iterations_;
98 damping_active_ =
true;
100 previous_mismatch_ = mismatch;
101 residual_ = mismatch;
103 Real damping = damping_active_ ? mixing_beta : 1.0;
114 bool use_anderson = damping_active_ && matches_layout(residuals_, fresh) &&
115 mismatch > convergence_threshold;
117 Real anderson_theta = 0.0;
126 Real numerator = 0.0;
127 Real denominator = 0.0;
128 for_each_element(fresh, [&](
size_t manifold,
size_t spin,
size_t element) {
130 fresh[manifold][spin][element] - damped_[manifold][spin][element];
131 Complex residual_change =
residual - residuals_[manifold][spin][element];
132 numerator += (std::conj(
residual) * residual_change).real();
133 denominator += std::norm(residual_change);
136 ? numerator / denominator
144 residuals_.resize(fresh.size());
145 for (
size_t manifold = 0; manifold < fresh.size(); ++manifold) {
146 residuals_[manifold].resize(fresh[manifold].size());
147 for (
size_t spin = 0; spin < fresh[manifold].size(); ++spin) {
148 std::vector<Complex>
residual(fresh[manifold][spin].size());
149 for (
size_t element = 0; element <
residual.size(); ++element)
151 fresh[manifold][spin][element] - damped_[manifold][spin][element];
152 for (
size_t element = 0; element <
residual.size(); ++element) {
155 step *= (1.0 - anderson_theta);
156 damped_[manifold][spin][element] += step;
158 residuals_[manifold][spin] = std::move(
residual);