High-precision calculations for one- and two-valence atomic systems
Anderson.hpp
1#pragma once
2#include "Wavefunction/DiracSpinor.hpp"
3#include <cassert>
4#include <cstddef>
5#include <vector>
6
7namespace ExternalField {
8
9/*!
10 @brief Anderson mixing coefficients for a fixed-point
11 iteration x -> G(x).
12 @details
13 Given the residuals \f$ r_k = G(x_k) - x_k \f$ of the stored iterates
14 (oldest first) through their Gram matrix \f$ B_{kl} = \braket{r_k}{r_l} \f$,
15 returns the \f$ c_k \f$ minimising
16 \f[ \Big\|\sum_k c_k r_k\Big\|^2 \quad\text{subject to}\quad \sum_k c_k = 1, \f]
17 via the bordered system [B 1; 1^T 0][c; lambda] = [0; 1]. The next iterate
18 is \f$ x = \sum_k c_k G(x_k) \f$. For a linear map this is equivalent to
19 (truncated) GMRES: it converges wherever the linear problem is
20 non-singular, where damped iteration may not.
21
22 A saturated history makes B ill-conditioned: the oldest entries are then
23 dropped, and the returned vector holds one coefficient per KEPT entry, the
24 last c.size() entries of the history (the caller drops the same entries
25 from its own history). Empty if no entry is usable (take a plain step).
26*/
27std::vector<double>
28anderson_coefficients(const std::vector<std::vector<double>> &gram);
29
30//! As above, from the residual spinors directly (Gram matrix of their inner
31//! products).
32std::vector<double>
33anderson_coefficients(const std::vector<DiracSpinor> &residuals);
34
35/*!
36 @brief Anderson mixing history of a fixed-point iteration x -> G(x) on
37 spinors, as used by the mixed-state solvers.
38 @details
39 Holds the map outputs \f$ g_k = G(x_k) \f$, the residuals
40 \f$ r_k = g_k - x_k \f$ and their Gram matrix, and a scalar carried with
41 each entry (an amplitude linear in the state, mixed with the same
42 coefficients; zero if unused). The Gram matrix is kept incrementally: a
43 new entry costs one inner product per kept entry, not a rebuild of the
44 whole matrix. At most @p depth entries are kept: the oldest is dropped
45 when the history is full, and (see @ref anderson_coefficients) while the
46 Gram matrix is ill-conditioned.
47*/
49public:
50 explicit AndersonHistory(std::size_t depth) : m_depth(depth) {
51 assert(depth > 0 && "AndersonHistory needs a depth of at least one");
52 }
53
54 //! Adds the entry (g, r), with |r|^2 = r2 (which the caller has from its
55 //! convergence test) and the carried scalar k; drops the oldest entry if
56 //! the history is full
57 void push(DiracSpinor g, DiracSpinor r, double r2, double k = 0.0);
58
59 /*!
60 @brief The Anderson extrapolation over the kept entries,
61 x = sum_k c_k g_k and (if @p k is non-null) k = sum_k c_k k_k, with the
62 coefficients of @ref anderson_coefficients; entries that had to be
63 dropped for conditioning are dropped from the history too.
64 @details If no entry is usable (the coefficients could not be solved
65 for), x is the plain step: the latest map output, and the history is
66 cleared.
67 */
68 void mix(DiracSpinor *x, double *k = nullptr);
69
70 //! Number of kept entries
71 std::size_t size() const { return m_g.size(); }
72
73private:
74 std::size_t m_depth;
75 std::vector<DiracSpinor> m_g{};
76 std::vector<DiracSpinor> m_r{};
77 std::vector<double> m_k{};
78 // Gram matrix of the residuals, <r_i|r_j>, over the kept entries
79 std::vector<std::vector<double>> m_gram{};
80
81 // Drops the n oldest entries (and their Gram rows and columns)
82 void drop_oldest(std::size_t n);
83};
84
85/*!
86 @brief Anderson mixing history of a fixed-point iteration x -> G(x) on a
87 state held as one real vector, as used by the TDHF solvers (the whole set
88 of core corrections, flattened).
89 @details
90 As @ref AndersonHistory: holds the map outputs \f$ g_k = G(x_k) \f$, the
91 residuals \f$ r_k = g_k - x_k \f$ and their Gram matrix (Euclidean inner
92 product), kept incrementally. At most @p depth entries are kept: the
93 oldest is dropped when the history is full, and (see
94 @ref anderson_coefficients) while the Gram matrix is ill-conditioned.
95*/
97public:
98 explicit AndersonVectorHistory(std::size_t depth) : m_depth(depth) {
99 assert(depth > 0 && "AndersonVectorHistory needs a depth of at least one");
100 }
101
102 //! Adds the entry for iterate x with map output g = G(x) (residual
103 //! g - x); drops the oldest entry if the history is full
104 void push(const std::vector<double> &x, std::vector<double> g);
105
106 /*!
107 @brief The Anderson extrapolation over the kept entries,
108 x = sum_k c_k g_k, with the coefficients of @ref anderson_coefficients;
109 entries that had to be dropped for conditioning are dropped from the
110 history too.
111 @details If no entry is usable (the coefficients could not be solved
112 for), returns the plain step: the latest map output, and the history is
113 cleared.
114 */
115 std::vector<double> mix();
116
117 //! Number of kept entries
118 std::size_t size() const { return m_g.size(); }
119
120private:
121 std::size_t m_depth;
122 std::vector<std::vector<double>> m_g{};
123 std::vector<std::vector<double>> m_r{};
124 // Gram matrix of the residuals, <r_i|r_j>, over the kept entries
125 std::vector<std::vector<double>> m_gram{};
126
127 // Drops the n oldest entries (and their Gram rows and columns)
128 void drop_oldest(std::size_t n);
129};
130
131} // namespace ExternalField
Stores radial Dirac spinor: F_nk = (f, g)
Definition DiracSpinor.hpp:55
Anderson mixing history of a fixed-point iteration x -> G(x) on spinors, as used by the mixed-state s...
Definition Anderson.hpp:48
void push(DiracSpinor g, DiracSpinor r, double r2, double k=0.0)
Adds the entry (g, r), with |r|^2 = r2 (which the caller has from its convergence test) and the carri...
Definition Anderson.cpp:71
void mix(DiracSpinor *x, double *k=nullptr)
The Anderson extrapolation over the kept entries, x = sum_k c_k g_k and (if k is non-null) k = sum_k ...
Definition Anderson.cpp:105
std::size_t size() const
Number of kept entries.
Definition Anderson.hpp:71
Anderson mixing history of a fixed-point iteration x -> G(x) on a state held as one real vector,...
Definition Anderson.hpp:96
std::size_t size() const
Number of kept entries.
Definition Anderson.hpp:118
std::vector< double > mix()
The Anderson extrapolation over the kept entries, x = sum_k c_k g_k, with the coefficients of anderso...
Definition Anderson.cpp:170
void push(const std::vector< double > &x, std::vector< double > g)
Adds the entry for iterate x with map output g = G(x) (residual g - x); drops the oldest entry if the...
Definition Anderson.cpp:131
Core-polarisation (RPA) corrections to matrix elements of an external field.
Definition MatrixElements.hpp:9
std::vector< double > anderson_coefficients(const std::vector< std::vector< double > > &gram)
Anderson mixing coefficients for a fixed-point iteration x -> G(x).
Definition Anderson.cpp:17