High-precision calculations for one- and two-valence atomic systems
RadialMatrix.hpp
1#pragma once
2#include "LinAlg/Matrix.hpp"
3#include "Maths/Grid.hpp"
4#include "Maths/Interpolator.hpp"
5#include "Wavefunction/DiracSpinor.hpp"
6#include <cassert>
7#include <complex>
8#include <iostream>
9#include <type_traits>
10#include <vector>
11
12namespace MBPT {
13
14/*!
15 @brief Radial matrix: stored on a sub-grid (defined by i0, stride, size).
16
17 @details
18 - i0 : the first grid-point included in subgrid
19 - stride: stride between grid-points used in subgrid
20 - size: total number of points used in subgrid
21 - rgrid: pointer to full grid
22 - T: type. Should usually be double or complex<double>
23
24*/
25template <typename T>
27
28 std::size_t m_i0, m_stride;
29 std::size_t m_size;
30 LinAlg::Matrix<T> m_Rmatrix;
31 std::shared_ptr<const Grid> m_rgrid; // "full" grid
32 std::vector<double> sub_r{}; // sub grid (required for interpolation)
33
34public:
35 //============================================================================
36
37 /*!
38 @brief Constructs a zero (size x size) matrix on the given sub-grid.
39
40 @details
41 Sub-grid point i corresponds to full-grid point i0 + i*stride.
42
43 @param i0 First full-grid point included in the sub-grid
44 @param stride Stride between full-grid points used in the sub-grid
45 @param size Number of sub-grid points
46 @param rgrid Full radial grid
47
48 @warning The last sub-grid point, i0 + stride*(size-1), must lie on the
49 full grid; this is checked by assert only (not in release
50 builds).
51 */
52 RadialMatrix(std::size_t i0, std::size_t stride, std::size_t size,
53 std::shared_ptr<const Grid> rgrid)
54 : m_i0(i0),
55 m_stride(stride),
56 m_size(size),
57 m_Rmatrix(m_size),
58 m_rgrid(rgrid) {
59 //------------------
60 // create vector of r on sub-grid, used to interpolate values onto full
61 const auto &r = m_rgrid->r();
62 sub_r.reserve(m_size);
63 // last sub-grid point, i0 + stride*(size-1), must lie on the full grid
64 assert(m_size > 0 && index_to_fullgrid(m_size - 1) < r.size());
65 for (std::size_t i = 0; i < m_size; ++i) {
66 sub_r.push_back(r[index_to_fullgrid(i)]);
67 }
68 assert(m_size < 2 || sub_r[1] == r[index_to_fullgrid(1)]);
69 assert(sub_r[m_size - 1] == r[index_to_fullgrid(m_size - 1)]);
70 //------------------
71 }
72
73 //============================================================================
74 //! direct access to matrix elements
75
76 T &at(std::size_t i, std::size_t j) { return m_Rmatrix(i, j); }
77 T at(std::size_t i, std::size_t j) const { return m_Rmatrix(i, j); }
78
79 T &operator()(std::size_t i, std::size_t j) { return at(i, j); }
80 T operator()(std::size_t i, std::size_t j) const { return at(i, j); }
81
82 //! direct access to radial matrix
83 const LinAlg::Matrix<T> &Rmatrix() const { return m_Rmatrix; }
84 LinAlg::Matrix<T> &Rmatrix() { return m_Rmatrix; }
85
86 std::size_t size() const { return m_size; }
87 std::size_t i0() const { return m_i0; }
88 std::size_t stride() const { return m_stride; }
89
90 //! First point along full grid for which subgrid is defined
91 double r0() const { return sub_r.front(); }
92 //! Last point along full grid for which subgrid is defined
93 double rmax() const { return sub_r.back(); }
94
95 //! returns r at position sub_i along sub grid
96 double r(std::size_t sub_i) const { return sub_r.at(sub_i); }
97
98 //! returns dr at position along sub grid
99 double dr(std::size_t sub_i) const {
100 const auto full_index = index_to_fullgrid(sub_i);
101 return m_rgrid->drdu(full_index) * m_rgrid->du() * double(m_stride);
102 }
103
104 //! Converts an index on the sub-grid to the full grid.
105 std::size_t index_to_fullgrid(std::size_t i) const {
106 return m_i0 + i * m_stride;
107 }
108
109 //============================================================================
110 //! Sets the radial matrix to have all zero's
111 void zero() { m_Rmatrix.zero(); }
112
113 //============================================================================
114 //! Matrix addition +,-
116 m_Rmatrix += rhs.m_Rmatrix;
117 return *this;
118 }
119 //! Matrix addition +,-
121 m_Rmatrix -= rhs.m_Rmatrix;
122 return *this;
123 }
124 //! Scalar multiplication
126 m_Rmatrix *= x;
127 return *this;
128 }
129
130 //! Matrix addition +,-
131 [[nodiscard]] friend RadialMatrix<T> operator+(RadialMatrix<T> lhs,
132 const RadialMatrix<T> &rhs) {
133 return lhs += rhs;
134 }
135 //! Matrix addition +,-
136 [[nodiscard]] friend RadialMatrix<T> operator-(RadialMatrix<T> lhs,
137 const RadialMatrix<T> &rhs) {
138 return lhs -= rhs;
139 }
140 //! Scalar multiplication
141 [[nodiscard]] friend RadialMatrix<T> operator*(const T x,
142 RadialMatrix<T> rhs) {
143 return rhs *= x;
144 }
145
146 //! Addition of identity: Matrix<T> += T : T assumed to be *Identity!
148 m_Rmatrix += aI;
149 return *this;
150 }
151 //! Addition of identity: Matrix<T> -= T : T assumed to be *Identity!
153 m_Rmatrix -= aI;
154 return *this;
155 }
156
157 //! Addition of identity: Matrix<T> + T : T assumed to be *Identity!
158 [[nodiscard]] friend RadialMatrix<T> operator+(RadialMatrix<T> M, T aI) {
159 return (M += aI);
160 }
161 //! Addition of identity: Matrix<T> - T : T assumed to be *Identity!
162 [[nodiscard]] friend RadialMatrix<T> operator-(RadialMatrix<T> M, T aI) {
163 return (M -= aI);
164 }
165
166 //============================================================================
167 //! Multiply coordinate elements (in place): Gij -> Gij*Bij
169 m_Rmatrix.mult_elements_by(rhs.m_Rmatrix);
170 return *this;
171 }
172
173 //! Multiply elements (new matrix): Gij = Aij*Bij
174 [[nodiscard]] friend RadialMatrix<T>
176 lhs.mult_elements_by(rhs);
177 return lhs;
178 }
179
180 /*!
181 @brief Matrix multiplication: Gij = Aik*Bkj
182
183 @details
184 Result is on the sub-grid of @p a.
185
186 @note Integration measure not included: call .drj() first to include it!
187 */
188 [[nodiscard]] friend RadialMatrix<T>
190 RadialMatrix<T> out(a.m_i0, a.m_stride, a.m_size, a.m_rgrid);
191 out.Rmatrix() = a.Rmatrix() * b.Rmatrix();
192 return out;
193 }
194
195 //! Matrix multiplication: Gij = Aik*Bkj
196 [[nodiscard]] friend RadialMatrix<T> operator*(const RadialMatrix<T> &a,
197 const RadialMatrix<T> &b) {
198 return matrix_multiply(a, b);
199 }
200
201 //============================================================================
202
203 //! Returns conjugate of matrix
204 [[nodiscard]] RadialMatrix<T> conj() const {
205 auto out = *this;
206 out.Rmatrix().conj_in_place();
207 return out;
208 }
209
210 //! Conjugates current matrix, in place
212 m_Rmatrix.conj_in_place();
213 return *this;
214 }
215
216 //! Returns real part of complex matrix (changes type; returns a real matrix)
217 [[nodiscard]] RadialMatrix<double> real() const {
218 RadialMatrix<double> out(m_i0, m_stride, m_size, m_rgrid);
219 out.Rmatrix() = m_Rmatrix.real();
220 return out;
221 }
222
223 //! Returns imag part of complex matrix (changes type; returns a real matrix)
224 [[nodiscard]] RadialMatrix<double> imag() const {
225 RadialMatrix<double> out(m_i0, m_stride, m_size, m_rgrid);
226 out.Rmatrix() = m_Rmatrix.imag();
227 return out;
228 }
229
230 //! Converts a real to complex matrix (changes type; returns a complex matrix)
232 RadialMatrix<std::complex<double>> out(m_i0, m_stride, m_size, m_rgrid);
233 out.Rmatrix() = m_Rmatrix.complex();
234 return out;
235 }
236
237 //============================================================================
238 //! Inversion (in place)
240 m_Rmatrix.invert_in_place();
241 return *this;
242 }
243 //! Returns inverse of matrix; original matrix unchanged
244 [[nodiscard]] RadialMatrix<T> inverse() const {
245 auto out = *this; //
246 return out.invert_in_place();
247 }
248
249 //============================================================================
250 //! Returns transpose of matrix; original matrix unchanged
251 [[nodiscard]] RadialMatrix<T> transpose() const {
252 RadialMatrix<T> out(m_i0, m_stride, m_size, m_rgrid);
253 out.m_Rmatrix = m_Rmatrix.transpose();
254 return out;
255 }
256
257 //============================================================================
258 //! Multiplies by drj: Q_ij -> Q_ij*dr_j, in place
260 const auto dus = m_rgrid->du() * double(m_stride);
261 for (auto i = 0ul; i < m_size; ++i) {
262 for (auto j = 0ul; j < m_size; ++j) {
263 const auto sj = index_to_fullgrid(j);
264 const auto dr = m_rgrid->drdu(sj) * dus;
265 m_Rmatrix[i][j] *= dr;
266 }
267 }
268 return *this;
269 }
270
271 //! Multiplies by dri: Q_ij -> Q_ij*dr_i, in place
273 const auto dus = m_rgrid->du() * double(m_stride);
274 for (auto i = 0ul; i < m_size; ++i) {
275 const auto si = index_to_fullgrid(i);
276 const auto dr = m_rgrid->drdu(si) * dus;
277 for (auto j = 0ul; j < m_size; ++j) {
278 m_Rmatrix[i][j] *= dr;
279 }
280 }
281 return *this;
282 }
283
284 //! Multiplies by drj: Q_ij -> Q_ij*dr_j. Returns new matrix (orig unchanged)
285 [[nodiscard]] RadialMatrix<T> drj() const {
286 auto out = *this;
287 return out.drj_in_place();
288 }
289
290 //! Multiplies by dri: Q_ij -> Q_ij*dr_i. Returns new matrix (orig unchanged)
291 [[nodiscard]] RadialMatrix<T> dri() const {
292 auto out = *this;
293 return out.dri_in_place();
294 }
295};
296
297//==============================================================================
298
299//! Checks if two matrices are equal (to within parts in 10^12)
300template <typename T>
301bool equal(const RadialMatrix<T> &lhs, const RadialMatrix<T> &rhs) {
302 return LinAlg::equal(lhs.Rmatrix(), rhs.Rmatrix());
303}
304
305//! returns maximum element (by abs)
306template <typename T>
307double max_element(const RadialMatrix<T> &a) {
308 double xmax = 0.0;
309 for (auto i = 0ul; i < a.size(); ++i) {
310 for (auto j = 0ul; j < a.size(); ++j) {
311 if (std::abs(a(i, j)) > xmax) {
312 xmax = std::abs(a(i, j));
313 }
314 }
315 }
316 return xmax;
317}
318
319//! returns maximum difference (abs) between two matrices
320template <typename T>
321double max_delta(const RadialMatrix<T> &a, const RadialMatrix<T> &b) {
322 double delta = 0.0;
323 for (auto i = 0ul; i < a.size(); ++i) {
324 for (auto j = 0ul; j < a.size(); ++j) {
325 if (std::abs(a(i, j) - b(i, j)) > delta) {
326 delta = std::abs(a(i, j) - b(i, j));
327 }
328 }
329 }
330 return delta;
331}
332
333//! returns maximum relative difference, |(aij-bij)/(aij+bij)|, of two matrices
334template <typename T>
335double max_epsilon(const RadialMatrix<T> &a, const RadialMatrix<T> &b) {
336 double eps = 0.0;
337 for (auto i = 0ul; i < a.size(); ++i) {
338 for (auto j = 0ul; j < a.size(); ++j) {
339 const auto eps_temp = std::abs((a(i, j) - b(i, j)) / (a(i, j) + b(i, j)));
340 if (eps_temp > eps)
341 eps = eps_temp;
342 }
343 }
344 return eps;
345}
346
347//==============================================================================
348
349using RMatrix = RadialMatrix<double>;
350using ComplexRMatrix = RadialMatrix<std::complex<double>>;
351
352} // namespace MBPT
Row-major dense matrix with arithmetic and linear algebra support.
Definition Matrix.hpp:208
Matrix< T > & invert_in_place()
Inverts the matrix in place.
Definition Matrix.ipp:54
auto complex() const
Converts a real to complex matrix (changes type; returns a complex matrix)
Definition Matrix.ipp:188
auto imag() const
Returns imag part of complex matrix (changes type; returns a real matrix)
Definition Matrix.ipp:177
Matrix< T > & conj_in_place()
Conjugates matrix, in place.
Definition Matrix.ipp:157
Matrix< T > transpose() const
Returns the transpose of the matrix.
Definition Matrix.ipp:94
Matrix< T > & zero()
Sets all elements to zero, in place.
Definition Matrix.ipp:137
Matrix< T > & mult_elements_by(const Matrix< T > &a)
Elementwise multiply in place: M_ij *= a_ij.
Definition Matrix.ipp:268
auto real() const
Returns real part of complex matrix (changes type; returns a real matrix)
Definition Matrix.ipp:166
Radial matrix: stored on a sub-grid (defined by i0, stride, size).
Definition RadialMatrix.hpp:26
RadialMatrix< T > transpose() const
Returns transpose of matrix; original matrix unchanged.
Definition RadialMatrix.hpp:251
RadialMatrix< T > & operator-=(const RadialMatrix< T > &rhs)
Matrix addition +,-.
Definition RadialMatrix.hpp:120
friend RadialMatrix< T > operator*(const RadialMatrix< T > &a, const RadialMatrix< T > &b)
Matrix multiplication: Gij = Aik*Bkj.
Definition RadialMatrix.hpp:196
friend RadialMatrix< T > mult_elements(RadialMatrix< T > lhs, const RadialMatrix< T > &rhs)
Multiply elements (new matrix): Gij = Aij*Bij.
Definition RadialMatrix.hpp:175
RadialMatrix< double > real() const
Returns real part of complex matrix (changes type; returns a real matrix)
Definition RadialMatrix.hpp:217
friend RadialMatrix< T > operator+(RadialMatrix< T > lhs, const RadialMatrix< T > &rhs)
Matrix addition +,-.
Definition RadialMatrix.hpp:131
RadialMatrix(std::size_t i0, std::size_t stride, std::size_t size, std::shared_ptr< const Grid > rgrid)
Constructs a zero (size x size) matrix on the given sub-grid.
Definition RadialMatrix.hpp:52
friend RadialMatrix< T > matrix_multiply(const RadialMatrix< T > &a, const RadialMatrix< T > &b)
Matrix multiplication: Gij = Aik*Bkj.
Definition RadialMatrix.hpp:189
RadialMatrix< std::complex< double > > complex() const
Converts a real to complex matrix (changes type; returns a complex matrix)
Definition RadialMatrix.hpp:231
RadialMatrix< T > & operator+=(const RadialMatrix< T > &rhs)
Matrix addition +,-.
Definition RadialMatrix.hpp:115
RadialMatrix< T > & mult_elements_by(const RadialMatrix< T > &rhs)
Multiply coordinate elements (in place): Gij -> Gij*Bij.
Definition RadialMatrix.hpp:168
RadialMatrix< double > imag() const
Returns imag part of complex matrix (changes type; returns a real matrix)
Definition RadialMatrix.hpp:224
friend RadialMatrix< T > operator*(const T x, RadialMatrix< T > rhs)
Scalar multiplication.
Definition RadialMatrix.hpp:141
RadialMatrix< T > dri() const
Multiplies by dri: Q_ij -> Q_ij*dr_i. Returns new matrix (orig unchanged)
Definition RadialMatrix.hpp:291
RadialMatrix< T > & conj_in_place()
Conjugates current matrix, in place.
Definition RadialMatrix.hpp:211
double r0() const
First point along full grid for which subgrid is defined.
Definition RadialMatrix.hpp:91
double r(std::size_t sub_i) const
returns r at position sub_i along sub grid
Definition RadialMatrix.hpp:96
friend RadialMatrix< T > operator-(RadialMatrix< T > M, T aI)
Addition of identity: Matrix<T> - T : T assumed to be *Identity!
Definition RadialMatrix.hpp:162
double dr(std::size_t sub_i) const
returns dr at position along sub grid
Definition RadialMatrix.hpp:99
RadialMatrix< T > & operator*=(const T x)
Scalar multiplication.
Definition RadialMatrix.hpp:125
friend RadialMatrix< T > operator+(RadialMatrix< T > M, T aI)
Addition of identity: Matrix<T> + T : T assumed to be *Identity!
Definition RadialMatrix.hpp:158
double rmax() const
Last point along full grid for which subgrid is defined.
Definition RadialMatrix.hpp:93
std::size_t index_to_fullgrid(std::size_t i) const
Converts an index on the sub-grid to the full grid.
Definition RadialMatrix.hpp:105
void zero()
Sets the radial matrix to have all zero's.
Definition RadialMatrix.hpp:111
T & at(std::size_t i, std::size_t j)
direct access to matrix elements
Definition RadialMatrix.hpp:76
friend RadialMatrix< T > operator-(RadialMatrix< T > lhs, const RadialMatrix< T > &rhs)
Matrix addition +,-.
Definition RadialMatrix.hpp:136
RadialMatrix< T > & operator+=(T aI)
Addition of identity: Matrix<T> += T : T assumed to be *Identity!
Definition RadialMatrix.hpp:147
const LinAlg::Matrix< T > & Rmatrix() const
direct access to radial matrix
Definition RadialMatrix.hpp:83
RadialMatrix< T > & operator-=(T aI)
Addition of identity: Matrix<T> -= T : T assumed to be *Identity!
Definition RadialMatrix.hpp:152
RadialMatrix< T > & invert_in_place()
Inversion (in place)
Definition RadialMatrix.hpp:239
RadialMatrix< T > & drj_in_place()
Multiplies by drj: Q_ij -> Q_ij*dr_j, in place.
Definition RadialMatrix.hpp:259
RadialMatrix< T > conj() const
Returns conjugate of matrix.
Definition RadialMatrix.hpp:204
RadialMatrix< T > & dri_in_place()
Multiplies by dri: Q_ij -> Q_ij*dr_i, in place.
Definition RadialMatrix.hpp:272
RadialMatrix< T > drj() const
Multiplies by drj: Q_ij -> Q_ij*dr_j. Returns new matrix (orig unchanged)
Definition RadialMatrix.hpp:285
RadialMatrix< T > inverse() const
Returns inverse of matrix; original matrix unchanged.
Definition RadialMatrix.hpp:244
bool equal(const Matrix< T > &lhs, const Matrix< T > &rhs, T eps=myEps< T >())
Compares two matrices element-wise to within a relative tolerance.
Definition Matrix.ipp:505
Many-body perturbation theory.
Definition MatrixElements.hpp:12
double max_element(const RadialMatrix< T > &a)
returns maximum element (by abs)
Definition RadialMatrix.hpp:307
bool equal(const RadialMatrix< T > &lhs, const RadialMatrix< T > &rhs)
Checks if two matrices are equal (to within parts in 10^12)
Definition RadialMatrix.hpp:301
double max_delta(const RadialMatrix< T > &a, const RadialMatrix< T > &b)
returns maximum difference (abs) between two matrices
Definition RadialMatrix.hpp:321
double max_epsilon(const RadialMatrix< T > &a, const RadialMatrix< T > &b)
returns maximum relative difference, |(aij-bij)/(aij+bij)|, of two matrices
Definition RadialMatrix.hpp:335