63 if (!g.
mesh().positive_only())
TRIQS_RUNTIME_ERROR <<
"gf imfreq is not for omega_n >0, real_to_complex does not apply";
64 auto const &dat = g.
data();
65 auto sh = dat.shape();
66 int is_boson = (g.
mesh().statistic() == Boson);
68 sh[0] = 2 * sh[0] - is_boson;
69 array<dcomplex, std::decay_t<
decltype(dat)>::rank> new_data(sh);
70 auto ell = nda::ellipsis{};
71 if (is_boson) new_data(L - 1, ell) = dat(0, ell);
72 long L1 = (is_boson ? L - 1 : L);
73 for (
long u = is_boson; u < L; ++u) {
74 new_data(L1 + u, ell) = dat(u, ell);
75 new_data(L - 1 - u, ell) =
conj(dat(u, ell));
93 static_assert(std::is_same_v<typename std::decay_t<G>::mesh_t,
mesh::imfreq>,
"positive_freq_view only makes senses for imfreq gf");
94 static_assert(std::decay_t<G>::is_view or std::is_lvalue_reference_v<G>,
"Cannot construct a positive_freq_view from a temporary gf");
95 if (g.mesh().positive_only())
return g;
96 long L = g.mesh().size();
97 long L1 = (L + 1) / 2;
98 int is_boson = (g.mesh().statistic() == Boson);
99 return {g.mesh().get_positive_freq(), g.data()(range(L1 - is_boson, L), nda::ellipsis())};
122 template <
typename G>
127 using target_t =
typename G::target_t;
128 using mesh_t =
typename std::decay_t<G>::mesh_t;
129 static_assert(std::is_same_v<mesh_t, mesh::imfreq> or std::is_same_v<mesh_t, mesh::imtime> or std::is_same_v<mesh_t, mesh::dlr_imfreq>
130 or std::is_same_v<mesh_t, mesh::dlr_imtime>,
131 "is_gf_hermitian requires an imfreq, imtime, dlr_imfreq or dlr_imtime Green function");
132 static_assert(target_t::rank == 0 or target_t::rank == 2 or target_t::rank == 4,
133 "is_gf_hermitian requires a Green function with a target rank of 0, 2 or 4.");
135 if constexpr (std::is_same_v<mesh_t, mesh::imfreq>) {
136 if (g.mesh().positive_only())
return true;
138 for (
auto w : g.mesh()) {
139 if constexpr (target_t::rank == 0) {
140 if (abs(
conj(g[-w]) - g[w]) > tolerance)
return false;
141 }
else if constexpr (target_t::rank == 2) {
142 if (max_element(abs(dagger(g[-w]) - g[w])) > tolerance)
return false;
144 for (
auto [i, j, k, l] : g.target_indices())
145 if (abs(
conj(g[-w](k, l, i, j)) - g[w](i, j, k, l)) > tolerance)
return false;
149 }
else if constexpr (std::is_same_v<mesh_t, mesh::dlr_imfreq>) {
152 long N = g.mesh().size();
153 for (
long d = 0; d < N / 2; ++d) {
154 long d_neg = N - 1 - d;
155 if constexpr (target_t::rank == 0) {
156 if (abs(
conj(g.data()(d_neg)) - g.data()(d)) > tolerance)
return false;
157 }
else if constexpr (target_t::rank == 2) {
158 if (max_element(abs(dagger(g.data()(d_neg, ellipsis())) - g.data()(d, ellipsis()))) > tolerance)
return false;
160 for (
auto [i, j, k, l] : g.target_indices())
161 if (abs(
conj(g.data()(d_neg, k, l, i, j)) - g.data()(d, i, j, k, l)) > tolerance)
return false;
165 }
else if constexpr (std::is_same_v<mesh_t, mesh::dlr_imtime>) {
166 for (
long d = 0; d < g.mesh().
size(); ++d) {
167 if constexpr (target_t::rank == 0) {
168 if (abs(
conj(g.data()(d)) - g.data()(d)) > tolerance)
return false;
169 }
else if constexpr (target_t::rank == 2) {
170 for (
auto [i, j] : g.target_indices())
171 if (abs(
conj(g.data()(d, j, i)) - g.data()(d, i, j)) > tolerance)
return false;
173 for (
auto [i, j, k, l] : g.target_indices())
174 if (abs(
conj(g.data()(d, k, l, i, j)) - g.data()(d, i, j, k, l)) > tolerance)
return false;
179 for (
auto t : g.mesh()) {
180 if constexpr (target_t::rank == 0) {
181 if (abs(
conj(g[t]) - g[t]) > tolerance)
return false;
182 }
else if constexpr (target_t::rank == 2) {
183 for (
auto [i, j] : g.target_indices())
184 if (abs(
conj(g[t](j, i)) - g[t](i, j)) > tolerance)
return false;
186 for (
auto [i, j, k, l] : g.target_indices())
187 if (abs(
conj(g[t](k, l, i, j)) - g[t](i, j, k, l)) > tolerance)
return false;
193 return std::all_of(g.begin(), g.end(), [&](
auto &g_bl) { return is_gf_hermitian<typename G::g_t>(g_bl, tolerance); });
213 using target_t =
typename G::target_t;
214 using mesh_t =
typename std::decay_t<G>::mesh_t;
215 static_assert(std::is_same_v<mesh_t, mesh::imfreq>,
"is_gf_hermitian requires an imfreq Green function");
217 if (g.mesh().positive_only())
return true;
218 for (
auto w : g.mesh()) {
219 if constexpr (target_t::rank == 0) {
220 if (abs(
conj(g[-w]) - g[w]) > tolerance)
return false;
222 if (max_element(abs(
conj(g[-w]) - g[w])) > tolerance)
return false;
227 return std::all_of(g.begin(), g.end(), [&](
auto &g_bl) { return is_gf_real_in_tau<typename G::g_t>(g_bl, tolerance); });
250 template <
typename G>
255 using target_t =
typename G::target_t;
256 using mesh_t =
typename std::decay_t<G>::mesh_t;
257 static_assert(std::is_same_v<mesh_t, mesh::imfreq> or std::is_same_v<mesh_t, mesh::imtime> or std::is_same_v<mesh_t, mesh::dlr_imfreq>
258 or std::is_same_v<mesh_t, mesh::dlr_imtime>,
259 "make_hermitian requires an imfreq, imtime, dlr_imfreq or dlr_imtime Green function");
260 static_assert(target_t::rank == 0 or target_t::rank == 2 or target_t::rank == 4,
261 "make_hermitian requires a Green function with a target rank of 0, 2 or 4.");
263 if constexpr (std::is_same_v<mesh_t, mesh::imfreq>) {
264 if (g.mesh().positive_only())
return typename G::regular_type{g};
265 auto g_sym =
typename G::regular_type{g};
266 for (
auto w : g.mesh()) {
267 if constexpr (target_t::rank == 0)
268 g_sym[w] = 0.5 * (g[w] +
conj(g[-w]));
269 else if constexpr (target_t::rank == 2)
270 g_sym[w] = 0.5 * (g[w] + dagger(g[-w]));
272 for (
auto [i, j, k, l] : g.target_indices()) g_sym[w](i, j, k, l) = 0.5 * (g[w](i, j, k, l) +
conj(g[-w](k, l, i, j)));
276 }
else if constexpr (std::is_same_v<mesh_t, mesh::dlr_imfreq>) {
278 auto g_sym =
typename G::regular_type{g};
279 long N = g.mesh().size();
280 for (
long d = 0; d < N; ++d) {
281 long d_neg = N - 1 - d;
282 if constexpr (target_t::rank == 0)
283 g_sym.data()(d) = 0.5 * (g.data()(d) +
conj(g.data()(d_neg)));
284 else if constexpr (target_t::rank == 2)
285 g_sym.data()(d, ellipsis()) = 0.5 * (g.data()(d, ellipsis()) + dagger(g.data()(d_neg, ellipsis())));
287 for (
auto [i, j, k, l] : g.target_indices())
288 g_sym.data()(d, i, j, k, l) = 0.5 * (g.data()(d, i, j, k, l) +
conj(g.data()(d_neg, k, l, i, j)));
292 auto g_sym =
typename G::regular_type{g};
293 for (
long d = 0; d < g.mesh().
size(); ++d) {
294 if constexpr (target_t::rank == 0)
295 g_sym.data()(d) = 0.5 * (g.data()(d) +
conj(g.data()(d)));
296 else if constexpr (target_t::rank == 2)
297 for (
auto [i, j] : g.target_indices()) g_sym.data()(d, i, j) = 0.5 * (g.data()(d, i, j) +
conj(g.data()(d, j, i)));
299 for (
auto [i, j, k, l] : g.target_indices())
300 g_sym.data()(d, i, j, k, l) = 0.5 * (g.data()(d, i, j, k, l) +
conj(g.data()(d, k, l, i, j)));
322 template <
typename G>
327 using mesh_t =
typename std::decay_t<G>::mesh_t;
328 static_assert(std::is_same_v<mesh_t, mesh::imfreq>,
"make_real_in_tau requires an imfreq Green function");
330 if (g.mesh().positive_only())
return typename G::regular_type{g};
331 auto g_sym =
typename G::regular_type{g};
332 for (
auto w : g.mesh()) { g_sym[w] = 0.5 * (g[w] +
conj(g[-w])); }
351 template <
template <
typename,
typename,
typename...>
typename G,
typename T>
auto restricted_view(G<mesh::imfreq, T>
const &g,
int n_max) {
352 auto iw_mesh =
mesh::imfreq{g.mesh().beta(), Fermion, n_max};
354 auto const &old_mesh = g.mesh();
356 int idx_max = old_mesh.to_data_index(iw_mesh.last_index());
357 auto data_view = g.data()(range(idx_min, idx_max + 1), ellipsis());
359 return typename G<mesh::imfreq, T>::const_view_type{iw_mesh, data_view};
375 for (
auto iw : g.
mesh())
391 int n_pts_in_fit_range = int(std::round(g.
mesh().get_tail_fitter().get_tail_fraction() * g.
mesh().size() / 2));
392 int n_min = g.
mesh().last_index() - n_pts_in_fit_range;
414 template <
template <
typename,
typename,
typename...>
typename G,
typename T>
415 auto fit_tail_on_window(G<mesh::imfreq, T>
const &g,
int n_min,
int n_max, array_const_view<dcomplex, 3> known_moments,
int n_tail_max,
416 int expansion_order) {
417 if (n_max == -1) n_max = g.mesh().last_index();
419 double tail_fraction =
static_cast<double>(n_max - n_min) / n_max;
420 g_rview.mesh().set_tail_fit_parameters(tail_fraction, n_tail_max, expansion_order);
421 return fit_tail(g_rview, known_moments);
441 template <
template <
typename,
typename...>
typename G,
typename T>
443 int expansion_order) {
444 if (n_max == -1) n_max = g.mesh().last_index();
446 double tail_fraction =
static_cast<double>(n_max - n_min) / n_max;
447 g_rview.mesh().set_tail_fit_parameters(tail_fraction, n_tail_max, expansion_order);
int size() const
Get the total number of blocks.
Provides the block Green's function container.
A read-only, non-owning view of a Green's function.
mesh_t const & mesh() const
Get the mesh of the Green's function.
data_t & data() &
Get the data array view.
A mutable, non-owning view of a Green's function.
mesh_t const & mesh() const
Get the mesh of the Green's function.
The owning Green's function container.
Imaginary frequency mesh type.
data_index_t to_data_index(index_t n) const noexcept
Map a Matsubara index to its corresponding data index .
Provides a mesh type for the discrete Lehmann representation in imaginary frequency space.
Provides a mesh type for the discrete Lehmann representation in imaginary time.
TRIQS exception hierarchy and related macros.
Provides tail fitting, slicing, inversion, reality and matrix-multiplication functions for Green's fu...
Provides a mutable non-owning view of a Green's function.
Provides the Green's function class.
auto map_block_gf(F &&f, G &&g)
Apply a callable to each block of a block Green's function.
G::regular_type make_real_in_tau(G const &g)
Symmetrize a Matsubara Green's function so that its imaginary-time partner is real-valued.
G::regular_type make_hermitian(G const &g)
Symmetrize a Green's function so that it satisfies the hermitian symmetry.
G::regular_type conj(G const &g)
Complex-conjugate a Green's function, returning a new Green's function.
bool is_gf_hermitian(G const &g, double tolerance=1.e-12)
Test whether a Green's function satisfies the hermitian symmetry up to a tolerance .
gf< mesh::imfreq, T > make_gf_from_real_gf(gf_const_view< mesh::imfreq, T, Layout > g)
Build a full-mesh Matsubara Green's function from one defined on positive frequencies only.
bool is_gf_real_in_tau(G const &g, double tolerance=1.e-12)
Test whether a Matsubara Green's function corresponds to a real imaginary-time Green's function.
view_or_type_t< std::decay_t< G > > positive_freq_view(G &&g)
Make a view of the positive-frequency part of a Matsubara Green's function.
auto restricted_view(G< mesh::imfreq, T > const &g, int n_max)
Make a const view of a Matsubara Green's function restricted to the first n_max frequency indices.
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.
void replace_by_tail_in_fit_window(gf_view< mesh::imfreq, T > g, array_const_view< dcomplex, 1+T::rank > tail)
Overwrite the high-frequency portion of a Matsubara Green's function with the tail expansion.
auto fit_hermitian_tail_on_window(G< mesh::imfreq, T > const &g, int n_min, int n_max, array_const_view< dcomplex, 3 > known_moments, int n_tail_max, int expansion_order)
Fit the high-frequency tail on a restricted window, imposing hermitian moment matrices.
void replace_by_tail(gf_view< mesh::imfreq, T > g, array_const_view< dcomplex, 1+T::rank > tail, int n_min)
Overwrite the high-frequency tail of a Matsubara Green's function.
auto fit_tail_on_window(G< mesh::imfreq, T > const &g, int n_min, int n_max, array_const_view< dcomplex, 3 > known_moments, int n_tail_max, int expansion_order)
Fit the high-frequency tail of a Matsubara Green's function on a restricted frequency window.
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.
constexpr bool is_gf_v
Trait to check whether a type models the Green's function concept.
auto tail_eval(nda::array_const_view< std::complex< double >, R > A, std::complex< double > z_0)
Evaluate the tail expansion of a function at a given point .
#define TRIQS_RUNTIME_ERROR
Throw a triqs::runtime_error with the current source location.
#define TRIQS_ASSERT(X)
Throw a triqs::runtime_error if the boolean expression X evaluates to false.
typename details::_view_or_type< T >::type view_or_type_t
Get the view type of a given type T if it exists.
Provides a mesh type on the imaginary frequency axis.
Provides a mesh type on the imaginary time axis.