TRIQS/triqs_tprf 4.0.0
A TRIQS application
Loading...
Searching...
No Matches
lindhard_chi00.cpp
1/*******************************************************************************
2 *
3 * TRIQS: a Toolbox for Research in Interacting Quantum Systems
4 *
5 * Copyright (C) 2022, H. U.R. Strand, Y. in 't Veld, M. Rösner
6 *
7 * TRIQS is free software: you can redistribute it and/or modify it under the
8 * terms of the GNU General Public License as published by the Free Software
9 * Foundation, either version 3 of the License, or (at your option) any later
10 * version.
11 *
12 * TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
13 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
15 * details.
16 *
17 * You should have received a copy of the GNU General Public License along with
18 * TRIQS. If not, see <http://www.gnu.org/licenses/>.
19 *
20 ******************************************************************************/
21
22#include <nda/linalg.hpp>
23
24#include "common.hpp"
25#include "lindhard_chi00.hpp"
26#include "lattice_utility.hpp"
27#include "../mpi.hpp"
28
29namespace triqs_tprf {
30
31 // ----------------------------------------------------
32 // chi00 bubble in analytic form
33
34 template<typename chi_t, typename mesh_t>
35 chi_t lindhard_chi00_template(e_k_cvt e_k, mesh_t mesh, double beta, double mu, double delta=0.) {
36
37 auto wmesh = mesh;
38 auto kmesh = e_k.mesh();
39 int nb = e_k.target().shape()[0];
40 std::complex<double> idelta(0.0, delta);
41
42 chi_t chi_wk{{wmesh, kmesh}, {nb, nb, nb, nb}};
43 for (auto [w, k] : chi_wk.mesh()) chi_wk[w, k] = 0.;
44
45 auto arr = mpi_view(kmesh);
46
47#pragma omp parallel for
48 for (unsigned int qidx = 0; qidx < kmesh.size(); qidx++) {
49 auto q = *std::next(kmesh.begin(), qidx);
50
51 for (auto k : arr) {
52
53 // -- If this is moved out to the k-loop the threading breaks?!?
54 matrix<std::complex<double>> e_k_mat(e_k[k] - mu);
55 auto [ek, Uk] = linalg::eigh(e_k_mat);
56
57 matrix<std::complex<double>> e_kq_mat(e_k(k + q) - mu);
58 auto [ekq, Ukq] = linalg::eigh(e_kq_mat);
59
60 for (int i : range(nb)) {
61 for (int j : range(nb)) {
62
63 double de = ekq(j) - ek(i);
64 double dn = fermi(ek(i) * beta) - fermi(ekq(j) * beta);
65
66 for (auto w : wmesh) {
67
68 std::complex<double> total_factor;
69
70 double tol = 1e-10;
71 if (abs(std::complex<double>(w) + idelta) < tol && abs(de) < tol) {
72 // w=0, de=0, 2nd order pole
73
74 // -- analytic first derivative of the fermi distribution function
75 // -- evaluated at ek(i)
76
77 double cosh_be = cosh(0.5 * beta * ek(i));
78 total_factor = beta / (4. * cosh_be * cosh_be);
79 } else {
80 total_factor = dn / (w + idelta + de);
81 }
82
83 chi_wk[w, q](a, b, c, d) << chi_wk[w, q](a, b, c, d) + Uk(a, i) * dagger(Uk)(i, d) * Ukq(c, j) * dagger(Ukq)(j, b) * total_factor;
84 } // w
85 } // j
86 } // i
87 } // q
88 } // k
89
90 chi_wk = mpi::all_reduce(chi_wk);
91 chi_wk /= kmesh.size();
92
93 return chi_wk;
94 }
95
96 chi_wk_t lindhard_chi00(e_k_cvt e_k, mesh::imfreq mesh, double mu) {
97 if (mesh.statistic() != Boson) TRIQS_RUNTIME_ERROR << "lindhard_chi00: statistic is incorrect.\n";
98 return lindhard_chi00_template<chi_wk_t, mesh::imfreq>(e_k, mesh, mesh.beta(), mu);
99 }
100
101 chi_Dwk_t lindhard_chi00(e_k_cvt e_k, mesh::dlr_imfreq mesh, double mu) {
102 if (mesh.statistic() != Boson) TRIQS_RUNTIME_ERROR << "lindhard_chi00: statistic is incorrect.\n";
103 return lindhard_chi00_template<chi_Dwk_t, mesh::dlr_imfreq>(e_k, mesh, mesh.beta(), mu);
104 }
105
106 chi_fk_t lindhard_chi00(e_k_cvt e_k, mesh::refreq mesh, double beta, double mu, double delta) {
107 return lindhard_chi00_template<chi_fk_t, mesh::refreq>(e_k, mesh, beta, mu, delta);
108 }
109
110} // namespace triqs_tprf