TRIQS/TRIQS 4.0.0
Researching Interacting Quantum Systems
Loading...
Searching...
No Matches
functions2.hpp
Go to the documentation of this file.
1// Copyright (c) 2016-2018 Commissariat à l'énergie atomique et aux énergies alternatives (CEA)
2// Copyright (c) 2016-2018 Centre national de la recherche scientifique (CNRS)
3// Copyright (c) 2018-2023 Simons Foundation
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You may obtain a copy of the License at
16// https://www.gnu.org/licenses/gpl-3.0.txt
17//
18// Authors: Michel Ferrero, Olivier Parcollet, Nils Wentzell
19
24
25#pragma once
26
27#include "../gf/gf.hpp"
28#include "../gf/gf_view.hpp"
29#include "../block/block_gf.hpp"
30#include "../block/map.hpp"
32
33#include <itertools/itertools.hpp>
34
35#include <algorithm>
36#include <optional>
37#include <utility>
38#include <type_traits>
39#include <vector>
40
41namespace triqs::gfs {
42
51 template <typename Gf>
52 requires(is_gf_v<Gf>)
53 auto make_const_view(Gf const &g) {
54 return gf_const_view{g};
55 }
56
57 // Name elevated from nda for the declarations below.
58 using nda::array_const_view;
59
60 /*------------------------------------------------------------------------------------------------------
61 * Fitting the tail
62 *-----------------------------------------------------------------------------------------------------*/
63
78 template <int N = 0, typename G, typename A = typename G::const_view_type::data_t>
79 std::pair<typename A::regular_type, double> fit_tail(G const &g, A const &known_moments = {})
80 requires(is_gf_v<G>)
81 {
82 auto const &m = get_mesh<N>(g);
83 return m.get_tail_fitter().template fit<N>(m, make_array_const_view(g.data()), true, make_array_const_view(known_moments));
84 }
85
99 template <int N = 0, typename BG, typename BA = std::vector<typename BG::g_t::data_t::regular_type>>
100 std::pair<std::vector<typename BG::g_t::data_t::regular_type>, double> fit_tail(BG const &bg, BA const &known_moments = {})
101 requires(is_block_gf_v<BG, 1>)
102 {
103 double max_err = 0.0;
104 std::vector<typename BG::g_t::data_t::regular_type> tail_vec;
105 for (auto [i, g_bl] : itertools::enumerate(bg)) {
106 auto [tail, err] = known_moments.empty() ? fit_tail<N, typename BG::g_t>(g_bl) : fit_tail<N, typename BG::g_t>(g_bl, known_moments[i]);
107 tail_vec.emplace_back(std::move(tail));
108 max_err = std::max(err, max_err);
109 }
110 return std::make_pair(tail_vec, max_err);
111 }
112
126 template <int N = 0, typename G, typename A = typename G::data_t>
127 std::pair<typename A::regular_type, double> fit_hermitian_tail(G const &g, A const &known_moments = {})
128 requires(is_gf_v<G>)
129 {
130 std::optional<long> inner_matrix_dim;
131 constexpr int rank = G::target_t::rank;
132 if (rank == 0)
133 inner_matrix_dim = 1;
134 else if (rank == 2 && g.target_shape()[0] == g.target_shape()[1]) {
135 inner_matrix_dim = g.target_shape()[0];
136 } else
137 TRIQS_RUNTIME_ERROR << "Incompatible target_shape for fit_hermitian_tail\n";
138
139 auto const &m = get_mesh<N>(g);
140 return m.get_tail_fitter().template fit_hermitian<N>(m, make_array_const_view(g.data()), true, make_array_const_view(known_moments),
141 inner_matrix_dim);
142 }
143
160 template <int N = 0, typename BG, typename A = std::vector<typename BG::g_t::data_t::regular_type>>
161 std::pair<std::vector<typename BG::g_t::data_t::regular_type>, double> fit_hermitian_tail(BG const &bg, A const &known_moments = {})
162 requires(is_block_gf_v<BG, 1>)
163 {
164 double max_err = 0.0;
165 std::vector<typename BG::g_t::data_t::regular_type> tail_vec;
166 for (auto [i, g_bl] : itertools::enumerate(bg)) {
167 auto [tail, err] =
168 known_moments.empty() ? fit_hermitian_tail<N, typename BG::g_t>(g_bl) : fit_hermitian_tail<N, typename BG::g_t>(g_bl, known_moments[i]);
169 tail_vec.emplace_back(std::move(tail));
170 max_err = std::max(err, max_err);
171 }
172 return std::make_pair(tail_vec, max_err);
173 }
174
175 // Tail-fit without normalization, returns moments rescaled by maximum frequency: a_n * omega_max^n
176 template <template <typename, typename, typename...> typename G, typename V, typename T, typename... U>
177 auto fit_tail_no_normalize(G<V, T, U...> const &g) {
178 return g.mesh().get_tail_fitter().template fit<0>(g.mesh(), make_array_const_view(g.data()), false,
179 array_const_view<dcomplex, G<V, T, U...>::data_rank>{});
180 }
181
191 template <int N = 0, typename G> auto make_zero_tail(G const &g, int n_moments = 10) {
192 if constexpr (is_gf_v<G>) { // gf[_const][_view]<V, T>
193 auto sh = nda::rotate_index_view<N>(make_const_view(g.data())).shape();
194 sh[0] = n_moments;
195 return nda::zeros<dcomplex>(sh);
196 } else if constexpr (is_block_gf_v<G>) { // block[2]_gf[_const][_view]<V, T>
197 return map_block_gf([&](auto const &g_bl) { return make_zero_tail<N>(g_bl, n_moments); }, g);
198 }
199 }
200
201 /*------------------------------------------------------------------------------------------------------
202 * Slicing the matrix_valued/matrix_real_valued into a matrix
203 *-----------------------------------------------------------------------------------------------------*/
204
216 template <typename G, typename... Args> auto slice_target(G &&g, Args &&...args) {
217 return std::forward<G>(g).apply_on_data([&args...](auto &&d) { return d(nda::ellipsis(), std::forward<Args>(args)...); });
218 }
219
220 /*------------------------------------------------------------------------------------------------------
221 * Slicing the matrix valued into a scalar
222 *-----------------------------------------------------------------------------------------------------*/
223
235 template <typename G, typename... Args> auto slice_target_to_scalar(G &&g, Args &&...args) {
236 auto r = std::forward<G>(g).apply_on_data([&args...](auto &&d) { return d(nda::ellipsis(), std::forward<Args>(args)...); });
237 return r;
238 }
239
240 /*------------------------------------------------------------------------------------------------------
241 * Target reinterpretation
242 * A scalar valued gf can be viewed as a 1x1 matrix
243 *-----------------------------------------------------------------------------------------------------*/
244
254 template <typename G, typename... Args> auto reinterpret_scalar_valued_gf_as_matrix_valued(G &&g) {
255 static_assert(std::is_same_v<typename std::decay_t<G>::target_t, scalar_valued>,
256 "slice_target_to_scalar : the result is not a scalar valued function");
257 return std::forward<G>(g).apply_on_data([](auto &&d) { return nda::reinterpret_add_fast_dims_of_size_one<2>(d); });
258 }
259
260 /*------------------------------------------------------------------------------------------------------
261 * Inversion
262 *-----------------------------------------------------------------------------------------------------*/
263
271 template <typename M> void invert_in_place(gf_view<M, matrix_valued> g) {
272 auto &a = g.data();
273 auto mesh_lengths = stdutil::mpop<2>(a.indexmap().lengths());
274 nda::for_each(mesh_lengths, [&a](auto &&...i) { nda::linalg::inv_in_place(make_matrix_view(a(i..., range::all, range::all))); });
275 }
276
286 invert_in_place(g());
287 return g;
288 }
289
292 template <typename M> gf<M, matrix_valued> inverse(gf_view<M, matrix_valued> g) { return inverse(gf{g}); }
293
297
298 /*------------------------------------------------------------------------------------------------------
299 * is_gf_real : true iif the gf is real
300 *-----------------------------------------------------------------------------------------------------*/
301
311 template <typename G>
312 bool is_gf_real(G const &g, double tolerance = 1.e-13)
313 requires(is_gf_v<G>)
314 {
315 return max_element(abs(imag(g.data()))) <= tolerance;
316 }
317
320 template <typename G>
321 bool is_gf_real(G const &bg, double tolerance = 1.e-13)
322 requires(is_block_gf_v<G>)
323 {
324 return std::all_of(bg.begin(), bg.end(), [&](auto &g) { return is_gf_real(g, tolerance); });
325 }
326
335 template <typename G>
336 typename G::regular_type::real_t real(G const &g)
337 requires(is_gf_v<G> or is_block_gf_v<G>)
338 {
339 if constexpr (is_gf_v<G>)
340 return {g.mesh(), real(g.data())};
341 else
342 return map_block_gf([](auto &&g_bl) { return real(g_bl); }, g);
343 }
344
354 template <typename G>
355 typename G::regular_type::real_t imag(G const &g)
356 requires(is_gf_v<G> or is_block_gf_v<G>)
357 {
358 if constexpr (is_gf_v<G>)
359 return {g.mesh(), imag(g.data())};
360 else
361 return map_block_gf([](auto &&g_bl) { return imag(g_bl); }, g);
362 }
363
364 /*------------------------------------------------------------------------------------------------------
365 * Transpose. Create a NEW gf
366 *-----------------------------------------------------------------------------------------------------*/
367
376 template <typename M> gf<M, matrix_valued> transpose(gf_view<M, matrix_valued> g) { return {g.mesh(), transposed_view(g.data(), 0, 2, 1)}; }
377
378 /*------------------------------------------------------------------------------------------------------
379 * Conjugate
380 *-----------------------------------------------------------------------------------------------------*/
381
390 template <typename G>
391 typename G::regular_type conj(G const &g)
392 requires(is_gf_v<G>)
393 {
394 return {g.mesh(), conj(g.data())};
395 }
396
397 /*------------------------------------------------------------------------------------------------------
398 * Multiply by matrices left or right
399 *-----------------------------------------------------------------------------------------------------*/
400
401 // Right-multiply the target matrix at each mesh point of the data array by r.
402 // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward): a is indexed per mesh point in the loop, not forwarded
403 template <typename A3, typename T> void _gf_data_mul_R(A3 &&a, matrix<T> const &r) {
404 for (int i = 0; i < first_dim(a); ++i) { // Rely on the ordering
405 matrix_view<T> v = a(i, nda::range::all, nda::range::all);
406 v = v * r;
407 }
408 }
409
410 // Left-multiply the target matrix at each mesh point of the data array by l.
411 // NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward): a is indexed per mesh point in the loop, not forwarded
412 template <typename A3, typename T> void _gf_data_mul_L(matrix<T> const &l, A3 &&a) {
413 for (int i = 0; i < first_dim(a); ++i) { // Rely on the ordering
414 matrix_view<T> v = a(i, nda::range::all, nda::range::all);
415 v = l * v;
416 }
417 }
418
429 template <typename M, typename T> gf<M, matrix_valued> operator*(gf<M, matrix_valued> g, matrix<T> r) {
430 _gf_data_mul_R(g.data(), r);
431 return g;
432 }
433
444 template <typename M, typename T> gf<M, matrix_valued> operator*(matrix<T> l, gf<M, matrix_valued> g) {
445 _gf_data_mul_L(l, g.data());
446 return g;
447 }
448
449 /*------------------------------------------------------------------------------------------------------
450 * Multiply by matrices left and right, in place.
451 * Optimized for speed.
452 *-----------------------------------------------------------------------------------------------------*/
453
454 // Set a = l * b * r for the target matrix at each mesh point of the data arrays (optimized via gemm).
455 template <typename A, typename B, typename M> void set_from_gf_data_mul_LR(A &a, M const &l, B const &b, M const &r) {
456 auto tmp = matrix<typename M::value_type>(second_dim(b), second_dim(r));
457 auto _ = nda::range::all;
458 for (int i = 0; i < first_dim(a); ++i) { // Rely on the ordering
459 auto rhs_v = make_matrix_view(b(i, _, _));
460 auto lhs_v = make_matrix_view(a(i, _, _));
461 nda::blas::gemm(1, rhs_v, r, 0, tmp);
462 nda::blas::gemm(1, l, tmp, 0, lhs_v);
463 }
464 }
465
478 template <typename G1, typename G2, typename M> void set_from_L_G_R(G1 &g1, M const &l, G2 const &g2, M const &r) {
479 set_from_gf_data_mul_LR(g1.data(), l, g2.data(), r);
480 }
481} // namespace triqs::gfs
Provides the block Green's function container.
A read-only, non-owning view of a Green's function.
A mutable, non-owning view of a Green's function.
Definition gf_view.hpp:48
data_t & data() &
Get the data array view.
Definition gf_view.hpp:131
mesh_t const & mesh() const
Get the mesh of the Green's function.
Definition gf_view.hpp:125
The owning Green's function container.
Definition gf.hpp:194
data_t & data() &
Get the data array.
Definition gf.hpp:280
TRIQS exception hierarchy and related macros.
Provides a mutable non-owning view of a Green's function.
Provides the Green's function class.
void set_from_L_G_R(G1 &g1, M const &l, G2 const &g2, M const &r)
Set g1 = l * g2 * r at every mesh point (in place, optimized for speed).
void invert_in_place(gf_view< M, matrix_valued > g)
Invert, in place, the target matrix at each mesh point of a matrix-valued Green's function.
auto inverse(block_gf< M, T, L, A > &g)
Apply inverse block-wise to each block of the block Green's function.
auto reinterpret_scalar_valued_gf_as_matrix_valued(block_gf< M, T, L, A > &g)
Apply reinterpret_scalar_valued_gf_as_matrix_valued block-wise to each block of the block Green's fun...
auto map_block_gf(F &&f, G &&g)
Apply a callable to each block of a block Green's function.
Definition map.hpp:131
G::regular_type::real_t real(G const &g)
Take the real part of a Green's function (no check), returning a new Green's function with a real tar...
bool is_gf_real(G const &g, double tolerance=1.e-13)
Test whether a Green's function is real up to a tolerance.
G::regular_type::real_t imag(G const &g)
Take the imaginary part of a Green's function (no check), returning a new Green's function with a rea...
G::regular_type conj(G const &g)
Complex-conjugate a Green's function, returning a new Green's function.
gf< M, matrix_valued > transpose(gf_view< M, matrix_valued > g)
Transpose the target matrix of a matrix-valued Green's function, returning a new Green's function.
auto slice_target(G &&g, Args &&...1)
Slice the target of a Green's function, keeping the result matrix- (or tensor-) valued.
auto make_const_view(Gf const &g)
Make a const view of a Green's function.
auto slice_target_to_scalar(G &&g, Args &&...1)
Slice the target of a matrix-valued Green's function down to a scalar-valued one.
std::pair< typename A::regular_type, double > fit_hermitian_tail(G const &g, A const &known_moments={})
Fit the high-frequency tail of a Green's function, imposing hermitian symmetry on the fitted moments.
auto make_zero_tail(G const &g, int n_moments=10)
Create a zero-initialized tail object for a given Green function object.
std::pair< typename A::regular_type, double > fit_tail(G const &g, A const &known_moments={})
Fit the high-frequency tail of a Green's function using a least-squares procedure.
constexpr bool is_block_gf_v
Trait to check whether a type is a block Green's function.
Definition block_gf.hpp:119
constexpr bool is_gf_v
Trait to check whether a type models the Green's function concept.
Definition gf.hpp:101
auto const & get_mesh(BG const &bg)
Get the mesh of a block Green's function, or its N-th component for a product mesh.
Definition block_gf.hpp:158
#define TRIQS_RUNTIME_ERROR
Throw a triqs::runtime_error with the current source location.
Provides the function applying a callable block by block to a block Green's function.
Target type for a complex scalar-valued Green's function.
Definition targets.hpp:188