23 int const history_size =
static_cast<int>(G.rows());
30 "Anderson acceleration: the mixing weights were requested for an "
31 "empty history (Gram matrix of size {:d}x{:d}).",
32 history_size,
static_cast<int>(G.cols()));
38 auto const newest_step_only = [history_size]()
40 Eigen::VectorXd theta = Eigen::VectorXd::Zero(history_size);
41 theta(history_size - 1) = 1.0;
45 double const g_scale = G.diagonal().maxCoeff();
50 return newest_step_only();
54 Eigen::MatrixXd M(history_size + 1, history_size + 1);
55 M.topLeftCorner(history_size, history_size) = G;
56 M.topRightCorner(history_size, 1).setOnes();
57 M.bottomLeftCorner(1, history_size).setOnes();
58 M(history_size, history_size) = 0.0;
60 Eigen::VectorXd rhs_aa(history_size + 1);
62 rhs_aa(history_size) = 1.0;
64 Eigen::VectorXd
const theta =
65 M.fullPivLu().solve(rhs_aa).head(history_size);
67 if (!theta.allFinite())
72 "Anderson acceleration: the mixing weights came out non-finite. "
73 "Falling back to the plain Picard step for this iteration.");
74 return newest_step_only();
92 double const mixed_residual_norm_2 = theta.dot(G * theta);
93 double const newest_step_norm_2 = G(history_size - 1, history_size - 1);
108 constexpr double max_weight = 1e2;
123 constexpr double numerically_zero = 1e-8;
124 bool const exact_cancellation_of_substantial_steps =
125 mixed_residual_norm_2 < numerically_zero &&
126 G.diagonal().minCoeff() > numerically_zero;
129 if (!(mixed_residual_norm_2 < newest_step_norm_2) ||
130 theta.cwiseAbs().maxCoeff() > max_weight ||
131 exact_cancellation_of_substantial_steps)
136 "Anderson acceleration: rejected the mixture of {:d} stored steps "
137 "(predicted residual {:g} vs. {:g} for the plain step, largest "
138 "weight {:g}). Falling back to the plain Picard step for this "
140 history_size, mixed_residual_norm_2, newest_step_norm_2,
141 theta.cwiseAbs().maxCoeff());
142 return newest_step_only();
198 std::size_t x_id = 0u;
199 std::size_t f_id = 0u;
210 auto const& newest =
_history.back();
218 int const history_size =
static_cast<int>(
_history.size());
230 _gram.topLeftCorner(history_size - 1, history_size - 1) =
231 _gram.block(1, 1, history_size - 1, history_size - 1).eval();
233 for (
int i = 0; i < history_size; ++i)
236 _gram(i, history_size - 1) = d;
237 _gram(history_size - 1, i) = d;
258 Eigen::MatrixXd
const G =
_gram.topLeftCorner(history_size, history_size);
267 for (
int i = 0; i < history_size; ++i)
274 DBUG(
"Picard/Anderson: history size {:d}, theta=[{:.4g}]", history_size,
275 fmt::join(theta.data(), theta.data() + history_size,
", "));