32 const std::vector<Real>& output_density)
override {
33 int number_of_points =
static_cast<int>(input_density.size());
36 std::vector<Real> residual(number_of_points);
37 for (
int point_index = 0; point_index < number_of_points; point_index++) {
38 residual[point_index] = output_density[point_index] - input_density[point_index];
46 density_history_.push_back(input_density);
47 residual_history_.push_back(residual);
50 while (
static_cast<int>(density_history_.size()) >
history_depth_) {
51 density_history_.erase(density_history_.begin());
52 residual_history_.erase(residual_history_.begin());
55 int number_of_history_entries =
static_cast<int>(density_history_.size());
58 if (number_of_history_entries <= 1) {
59 std::vector<Real> mixed_density(number_of_points);
60 for (
int point_index = 0; point_index < number_of_points; point_index++) {
61 mixed_density[point_index] =
74 int number_of_differences = number_of_history_entries - 1;
75 std::vector<Real> overlap_matrix(number_of_differences * number_of_differences,
77 std::vector<Real> right_hand_side(number_of_differences, 0.0);
79 const auto& residual_last = residual_history_.back();
82 std::vector<std::vector<Real>> delta_residuals(number_of_differences,
83 std::vector<Real>(number_of_points));
84 for (
int difference_index = 0; difference_index < number_of_differences;
86 for (
int point_index = 0; point_index < number_of_points; point_index++) {
87 delta_residuals[difference_index][point_index] =
88 residual_history_[difference_index][point_index] - residual_last[point_index];
93 for (
int difference_index = 0; difference_index < number_of_differences;
95 const auto& delta_residual_i = delta_residuals[difference_index];
98 for (
int point_index = 0; point_index < number_of_points; point_index++) {
99 rhs_dot -= delta_residual_i[point_index] * residual_last[point_index];
101 right_hand_side[difference_index] = rhs_dot;
103 for (
int column_index = 0; column_index < number_of_differences; column_index++) {
105 const auto& delta_residual_j = delta_residuals[column_index];
106 for (
int point_index = 0; point_index < number_of_points; point_index++) {
107 dot += delta_residual_i[point_index] * delta_residual_j[point_index];
109 overlap_matrix[difference_index + column_index * number_of_differences] =
120 int overlap_size = number_of_differences * number_of_differences;
121 std::vector<Real> reduce_buffer(number_of_differences + overlap_size);
122 for (
int i = 0; i < number_of_differences; i++) {
123 reduce_buffer[i] = right_hand_side[i];
125 for (
int i = 0; i < overlap_size; i++) {
126 reduce_buffer[number_of_differences + i] = overlap_matrix[i];
130 for (
int i = 0; i < number_of_differences; i++) {
131 right_hand_side[i] = reduce_buffer[i];
133 for (
int i = 0; i < overlap_size; i++) {
134 overlap_matrix[i] = reduce_buffer[number_of_differences + i];
139 int number_of_right_hand_sides = 1;
140 int lapack_workspace_size = 4 * number_of_differences;
141 std::vector<Real> lapack_workspace(lapack_workspace_size);
144 &number_of_differences,
145 &number_of_differences,
146 &number_of_right_hand_sides,
147 overlap_matrix.data(),
148 &number_of_differences,
149 right_hand_side.data(),
150 &number_of_differences,
151 lapack_workspace.data(),
152 &lapack_workspace_size,
156 log::warn(
"Anderson mixing: LAPACK dgels failed (info={}), falling back to linear",
158 std::vector<Real> mixed_density(number_of_points);
159 for (
int point_index = 0; point_index < number_of_points; point_index++) {
160 mixed_density[point_index] =
163 return mixed_density;
171 std::vector<Real> density_optimal(number_of_points), residual_optimal(number_of_points);
172 const auto& density_last = density_history_.back();
174 for (
int point_index = 0; point_index < number_of_points; point_index++) {
175 density_optimal[point_index] = density_last[point_index];
176 residual_optimal[point_index] = residual_last[point_index];
179 for (
int difference_index = 0; difference_index < number_of_differences;
180 difference_index++) {
181 Real gamma_i = right_hand_side[difference_index];
182 for (
int point_index = 0; point_index < number_of_points; point_index++) {
183 density_optimal[point_index] +=
185 (density_history_[difference_index][point_index] - density_last[point_index]);
186 residual_optimal[point_index] +=
188 (residual_history_[difference_index][point_index] - residual_last[point_index]);
193 std::vector<Real> mixed_density(number_of_points);
194 for (
int point_index = 0; point_index < number_of_points; point_index++) {
195 mixed_density[point_index] =
196 density_optimal[point_index] +
mixing_parameter_ * residual_optimal[point_index];
199 return mixed_density;