1+ #include < chrono>
2+ #include < nda/nda.hpp>
3+ #include < cppdlr/cppdlr.hpp>
4+ #include < triqs_xca/block_sparse.hpp>
5+ #include < triqs_xca/block_sparse_manual.hpp>
6+ #include < triqs_xca/block_sparse_backbone.hpp>
7+
8+ using namespace nda ;
9+ using namespace cppdlr ;
10+
11+ nda::array<dcomplex, 3 > Hmat_to_Gtmat (nda::array<dcomplex, 2 > Hmat, double beta, nda::array<double , 1 > dlr_it_abs) {
12+ // Helper function for computing the non-interacting Green's function from the Hamiltonian, both in dense storage
13+
14+ int N = Hmat.extent (0 );
15+ auto [H_loc_eval, H_loc_evec] = nda::linalg::eigenelements (Hmat);
16+ auto E0 = nda::min_element (H_loc_eval);
17+ H_loc_eval -= E0 ;
18+ auto tr_exp_minusbetaH = nda::sum (exp (-beta * H_loc_eval));
19+ auto eta_0 = nda::log (tr_exp_minusbetaH) / beta;
20+ H_loc_eval += eta_0;
21+ auto Gt_evals_t = nda::zeros<dcomplex>(N, N);
22+ int r = dlr_it_abs.extent (0 );
23+ auto Gt_mat = nda::zeros<dcomplex>(r, N, N);
24+ auto Gbeta = nda::zeros<dcomplex>(N, N);
25+ for (int t = 0 ; t < r; t++) {
26+ for (int i = 0 ; i < N; i++) { Gt_evals_t (i, i) = -exp (-beta * dlr_it_abs (t) * H_loc_eval (i)); }
27+ Gt_mat (t, _, _) = matmul (H_loc_evec, matmul (Gt_evals_t, nda::transpose (H_loc_evec)));
28+ }
29+ return Gt_mat;
30+ }
31+
32+ std::tuple<nda::array<dcomplex, 3 >, nda::array<dcomplex, 3 >> discrete_bath_helper (double beta, double Lambda, double eps) {
33+ // Helper function for setting up the discrete bath model
34+
35+ auto dlr_rf = build_dlr_rf (Lambda, eps);
36+ auto itops = imtime_ops (Lambda, dlr_rf);
37+ auto const &dlr_it = itops.get_itnodes ();
38+ auto dlr_it_abs = rel2abs (dlr_it);
39+ int r = itops.rank ();
40+
41+ // hybridization parameters
42+ double s = 0.5 ;
43+ double t = 1.0 ;
44+ nda::array<double , 1 > e{-2.3 * t, 2.3 * t};
45+
46+ // hybridization generation
47+ auto Jt = nda::array<dcomplex, 3 >(r, 1 , 1 );
48+ auto Jt_refl = nda::array<dcomplex, 3 >(r, 1 , 1 );
49+ for (int i = 0 ; i <= 1 ; i++) {
50+ for (int u = 0 ; u < r; u++) {
51+ Jt (u, 0 , 0 ) += k_it (dlr_it (u), e (i), beta);
52+ Jt_refl (u, 0 , 0 ) += k_it (-dlr_it (u), e (i), beta);
53+ }
54+ }
55+
56+ // orbital index order: do 0, do 1, up 0, up 1. same level <-> same parity index
57+ auto Deltat = nda::array<dcomplex, 3 >(r, 4 , 4 );
58+ auto Deltat_refl = nda::array<dcomplex, 3 >(r, 4 , 4 );
59+
60+ for (int i = 0 ; i < Deltat.extent (1 ); i++) {
61+ for (int j = 0 ; j < Deltat.extent (2 ); j++) {
62+ if (i == j) {
63+ Deltat (_, i, j) = Jt (_, 0 , 0 );
64+ Deltat_refl (_, i, j) = Jt_refl (_, 0 , 0 );
65+ } else if ((i == 0 && j == 1 ) || (i == 1 && j == 0 ) || (i == 2 && j == 3 ) || (i == 3 && j == 2 )) {
66+ Deltat (_, i, j) = s * Jt (_, 0 , 0 );
67+ Deltat_refl (_, i, j) = s * Jt_refl (_, 0 , 0 );
68+ }
69+ }
70+ }
71+ Deltat = t * t * Deltat;
72+ Deltat_refl = t * t * Deltat_refl;
73+
74+ return std::make_tuple (Deltat, Deltat_refl);
75+ }
76+
77+ std::tuple<nda::array<dcomplex, 3 >, nda::array<dcomplex, 3 >, nda::array<dcomplex, 3 >> two_band_dense_helper (double beta, double Lambda, double eps) {
78+
79+ auto dlr_rf = build_dlr_rf (Lambda, eps);
80+ auto itops = imtime_ops (Lambda, dlr_rf);
81+ auto const &dlr_it = itops.get_itnodes ();
82+ auto dlr_it_abs = cppdlr::rel2abs (dlr_it);
83+
84+ // Hamiltonian in dense storage
85+ auto H_dense = nda::zeros<dcomplex>(16 , 16 );
86+ H_dense (0 , 0 ) = -1 ;
87+ H_dense (1 , 1 ) = -1 ;
88+ H_dense (2 , 2 ) = -1 ;
89+ H_dense (3 , 3 ) = -1 ;
90+ H_dense (4 , 4 ) = -0.6 ;
91+ H_dense (5 , 8 ) = 0.2 ;
92+ H_dense (6 , 6 ) = -0.4 ;
93+ H_dense (6 , 7 ) = 0.2 ;
94+ H_dense (7 , 6 ) = 0.2 ;
95+ H_dense (7 , 7 ) = -0.4 ;
96+ H_dense (8 , 5 ) = 0.2 ;
97+ H_dense (9 , 9 ) = -0.6 ;
98+ H_dense (11 , 11 ) = 2 ;
99+ H_dense (12 , 12 ) = 2 ;
100+ H_dense (13 , 13 ) = 2 ;
101+ H_dense (14 , 14 ) = 2 ;
102+ H_dense (15 , 15 ) = 6 ;
103+
104+ // Green's function in dense storage
105+ auto Gt_dense = Hmat_to_Gtmat (H_dense, beta, dlr_it_abs);
106+
107+ // creation/annihilation operators in dense storage
108+ auto Fs_dense = nda::zeros<dcomplex>(4 , 16 , 16 );
109+ // copied from a text dump of an h5 file output from atom_diag
110+ Fs_dense = {{{0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
111+ {0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
112+ {0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 2.23711e-17 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
113+ {0 , 0 , 0 , 0 , 0 , 0 , 2.23711e-17 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
114+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
115+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2.23711e-17 , 0 , 0 , 0 },
116+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 },
117+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2.23711e-17 , 0 , 0 , 0 , 0 },
118+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 },
119+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 },
120+ {1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
121+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
122+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
123+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
124+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
125+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }},
126+ {{0 , 0 , 0 , 0 , -1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
127+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
128+ {0 , 0 , 0 , 0 , 0 , 0 , 1 , 2.23711e-17 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
129+ {0 , 0 , 0 , 0 , 0 , 2.23711e-17 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
130+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
131+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 , 0 , 0 , 0 , 0 },
132+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -2.23711e-17 , 0 , 0 , 0 },
133+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 , 0 , 0 , 0 },
134+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -2.23711e-17 , 0 , 0 , 0 , 0 },
135+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 },
136+ {0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
137+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
138+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
139+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 },
140+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
141+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }},
142+ {{0 , 0 , 0 , 0 , 0 , -1 , 0 , 0 , -2.23711e-17 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
143+ {0 , 0 , 0 , 0 , 0 , 0 , -1 , -2.23711e-17 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
144+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
145+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 },
146+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 },
147+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -2.23711e-17 , 0 },
148+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -2.23711e-17 , 0 , 0 },
149+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 , 0 , 0 },
150+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 , 0 },
151+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
152+ {0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
153+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
154+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 },
155+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
156+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
157+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }},
158+ {{0 , 0 , 0 , 0 , 0 , 0 , -2.23711e-17 , -1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
159+ {0 , 0 , 0 , 0 , 0 , -2.23711e-17 , 0 , 0 , -1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
160+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 , 0 , 0 , 0 , 0 , 0 , 0 },
161+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
162+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 , 0 },
163+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 , 0 },
164+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 0 },
165+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2.23711e-17 , 0 },
166+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2.23711e-17 , 0 , 0 },
167+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
168+ {0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
169+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , -1 },
170+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
171+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
172+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 },
173+ {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }}};
174+ auto F_dags_dense = nda::zeros<dcomplex>(4 , 16 , 16 );
175+ for (int i = 0 ; i < 4 ; i++) { F_dags_dense (i, _, _) = nda::transpose (nda::conj (Fs_dense (i, _, _))); }
176+
177+ return std::make_tuple (Gt_dense, Fs_dense, F_dags_dense);
178+ }
179+
180+ std::tuple<BlockDiagOpFun, BlockOpSymQuartet, nda::vector<int >> two_band_helper (double beta, double Lambda, double eps,
181+ nda::array_const_view<dcomplex, 3 > hyb_coeffs,
182+ nda::array_const_view<dcomplex, 3 > hyb_refl_coeffs) {
183+ auto dlr_rf = build_dlr_rf (Lambda, eps);
184+ auto itops = imtime_ops (Lambda, dlr_rf);
185+ auto const &dlr_it = itops.get_itnodes ();
186+ auto dlr_it_abs = cppdlr::rel2abs (dlr_it);
187+
188+ // get Hamiltonian, creation/annihilation operators in block-sparse storage
189+ int num_blocks = 5 ; // number of blocks of Hamiltonian
190+
191+ // Hamiltonian
192+ std::vector<nda::array<double , 2 >> H_blocks (num_blocks); // Hamiltonian in sparse storage
193+ H_blocks[0 ] = nda::make_regular (-1 * nda::eye<double >(4 ));
194+ H_blocks[1 ] = {{-0.6 , 0 , 0 , 0 , 0 , 0 }, {0 , 8.27955e-19 , 0 , 0 , 0.2 , 0 }, {0 , 0 , -0.4 , 0.2 , 0 , 0 },
195+ {0 , 0 , 0.2 , -0.4 , 0 , 0 }, {0 , 0.2 , 0 , 0 , 8.27955e-19 , 0 }, {0 , 0 , 0 , 0 , 0 , -0.6 }};
196+ H_blocks[2 ] = {{0 }};
197+ H_blocks[3 ] = nda::make_regular (2 * nda::eye<double >(4 ));
198+ H_blocks[4 ] = {{6 }};
199+ nda::vector<int > H_block_inds = {0 , 0 , -1 , 0 , 0 };
200+
201+ // Green's function
202+ auto Gt = nonint_gf_BDOF (H_blocks, H_block_inds, beta, dlr_it_abs);
203+
204+ // creation/annihilation operators
205+ nda::vector<int > ann_conn = {2 , 0 , -1 , 1 , 3 }; // block column indices of F operators
206+ nda::vector<int > cre_conn = {1 , 3 , 0 , 4 , -1 }; // block column indices of F^dag operators
207+ std::vector<nda::array<dcomplex, 3 >> F_blocks (num_blocks), Fdag_blocks (num_blocks);
208+
209+ F_blocks[0 ] = {{{1 , 0 , 0 , 0 }}, {{0 , 1 , 0 , 0 }}, {{0 , 0 , 1 , 0 }}, {{0 , 0 , 0 , 1 }}};
210+ F_blocks[1 ] = {{{0 , 0 , 0 , 0 , 0 , 0 }, {1 , 0 , 0 , 0 , 0 , 0 }, {0 , 1 , 0 , 0 , 0 , 0 }, {0 , 0 , 0 , 1 , 0 , 0 }},
211+ {{-1 , 0 , 0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 , 0 , 0 }, {0 , 0 , 1 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 , 1 , 0 }},
212+ {{0 , -1 , 0 , 0 , 0 , 0 }, {0 , 0 , -1 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 , 0 , 1 }},
213+ {{0 , 0 , 0 , -1 , 0 , 0 }, {0 , 0 , 0 , 0 , -1 , 0 }, {0 , 0 , 0 , 0 , 0 , -1 }, {0 , 0 , 0 , 0 , 0 , 0 }}};
214+ F_blocks[2 ] = {{{0 }}};
215+ F_blocks[3 ] = {{{0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {1 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 1 , 0 , 0 }, {0 , 0 , 1 , 0 }},
216+ {{0 , 0 , 0 , 0 }, {-1 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , -1 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 1 }},
217+ {{1 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , -1 , 0 }, {0 , 0 , 0 , -1 }, {0 , 0 , 0 , 0 }},
218+ {{0 , 1 , 0 , 0 }, {0 , 0 , 1 , 0 }, {0 , 0 , 0 , 1 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }}};
219+ F_blocks[4 ] = {{{0 }, {0 }, {0 }, {1 }}, {{0 }, {0 }, {-1 }, {0 }}, {{0 }, {1 }, {0 }, {0 }}, {{-1 }, {0 }, {0 }, {0 }}};
220+
221+ Fdag_blocks[0 ] = {{{0 , 1 , 0 , 0 }, {0 , 0 , 1 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 1 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }},
222+ {{-1 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 1 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 1 }, {0 , 0 , 0 , 0 }},
223+ {{0 , 0 , 0 , 0 }, {-1 , 0 , 0 , 0 }, {0 , -1 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 1 }},
224+ {{0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 }, {-1 , 0 , 0 , 0 }, {0 , -1 , 0 , 0 }, {0 , 0 , -1 , 0 }}};
225+ Fdag_blocks[1 ] = {{{0 , 0 , 1 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 , 1 , 0 }, {0 , 0 , 0 , 0 , 0 , 1 }, {0 , 0 , 0 , 0 , 0 , 0 }},
226+ {{0 , -1 , 0 , 0 , 0 , 0 }, {0 , 0 , 0 , -1 , 0 , 0 }, {0 , 0 , 0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 , 0 , 1 }},
227+ {{1 , 0 , 0 , 0 , 0 , 0 }, {0 , 0 , 0 , 0 , 0 , 0 }, {0 , 0 , 0 , -1 , 0 , 0 }, {0 , 0 , 0 , 0 , -1 , 0 }},
228+ {{0 , 0 , 0 , 0 , 0 , 0 }, {1 , 0 , 0 , 0 , 0 , 0 }, {0 , 1 , 0 , 0 , 0 , 0 }, {0 , 0 , 1 , 0 , 0 , 0 }}};
229+ Fdag_blocks[2 ] = {{{1 }, {0 }, {0 }, {0 }}, {{0 }, {1 }, {0 }, {0 }}, {{0 }, {0 }, {1 }, {0 }}, {{0 }, {0 }, {0 }, {1 }}};
230+ Fdag_blocks[3 ] = {{{0 , 0 , 0 , 1 }}, {{0 , 0 , -1 , 0 }}, {{0 , 1 , 0 , 0 }}, {{-1 , 0 , 0 , 0 }}};
231+ Fdag_blocks[4 ] = {{{0 }}};
232+
233+ BlockOpSymSet F_BOSS (ann_conn, F_blocks), Fdag_BOSS (cre_conn, Fdag_blocks);
234+ std::vector<BlockOpSymSet> F_sym_vec{F_BOSS }, F_dag_sym_vec{Fdag_BOSS};
235+ nda::vector<long > sym_set_labels (4 );
236+ sym_set_labels = 0 ; // all operators belong to the same symmetry set
237+ BlockOpSymQuartet Fq (F_sym_vec, F_dag_sym_vec, hyb_coeffs, hyb_refl_coeffs, sym_set_labels);
238+
239+ return std::make_tuple (Gt, Fq, sym_set_labels);
240+ }
241+
242+ int main () {
243+ nda::array<int , 3 > topologies = {{{0 , 2 }, {1 , 4 }, {3 , 5 }}, {{0 , 3 }, {1 , 5 }, {2 , 4 }}, {{0 , 4 }, {1 , 3 }, {2 , 5 }}, {{0 , 3 }, {1 , 4 }, {2 , 5 }}};
244+ nda::vector<int > topo_sign{1 , 1 , 1 , -1 }; // topo_sign(i) = (-1)^{# of line crossings in topology i}
245+
246+ nda::array<int , 2 > topology = {{0 , 2 }, {1 , 3 }};
247+ int n = 4 , N = 16 ;
248+ double beta = 2.0 ;
249+ double Lambda = 10.0 * beta;
250+ double eps = 1.0e-4 ;
251+
252+ // generate hybridization, noninteracting Green's function, creation/annihilation operators
253+ auto [Deltat, Deltat_refl] = discrete_bath_helper (beta, Lambda, eps);
254+ auto [Gt_dense, Fs_dense, F_dags_dense] = two_band_dense_helper (beta, Lambda, eps);
255+
256+ // DLR generation
257+ auto dlr_rf = build_dlr_rf (Lambda, eps);
258+ auto itops = imtime_ops (Lambda, dlr_rf);
259+ auto const &dlr_it = itops.get_itnodes ();
260+ auto dlr_it_abs = cppdlr::rel2abs (dlr_it);
261+ int r = itops.rank ();
262+
263+ // hybridization and DenseFSet
264+ auto hyb_coeffs = itops.vals2coefs (Deltat); // hybridization DLR coeffs
265+ auto hyb_refl = Deltat;
266+ auto hyb_refl_coeffs = hyb_coeffs;
267+ auto [Gt, Fq, sym_set_labels] = two_band_helper (beta, Lambda, eps, hyb_coeffs, hyb_refl_coeffs);
268+
269+ auto D = DiagramBlockSparseEvaluator (beta, itops, Deltat, hyb_refl, dlr_rf, Gt, Fq); // create DiagramEvaluator object
270+
271+ auto Deltadlr = itops.vals2coefs (Deltat); // obtain dlr coefficient of Delta(t)
272+ nda::vector<double > dlr_rf_reflect = -dlr_rf;
273+ nda::array<dcomplex, 3 > Deltadlr_reflect = Deltadlr * 1.0 ;
274+ for (int i = 0 ; i < Deltadlr.shape (0 ); ++i) Deltadlr_reflect (i, _, _) = transpose (Deltadlr (i, _, _));
275+ auto Delta_decomp = hyb_decomp (Deltadlr, dlr_rf, eps);
276+ auto Delta_decomp_reflect = hyb_decomp (Deltadlr_reflect, dlr_rf_reflect, eps);
277+ hyb_F Delta_F (N, r, n);
278+ hyb_F Delta_F_reflect (N, r, n);
279+ Delta_F.update_inplace (Delta_decomp, dlr_it, Fs_dense, F_dags_dense);
280+ Delta_F_reflect.update_inplace (Delta_decomp_reflect, dlr_it, F_dags_dense, Fs_dense);
281+ auto fb = nda::vector<int64_t >(3 );
282+ fb (0 ) = 0 ;
283+
284+ BlockDiagOpFun third_order_result (r, Gt.get_block_sizes ());
285+ for (int i = 0 ; i < 4 ; ++i) {
286+ std::cout << " Evaluating topology " << i << std::endl;
287+
288+ // Compute third-order contribution using DiagramEvaluator
289+ auto B = Backbone (topologies (i, _, _), n);
290+ D.eval_diagram_block_sparse (B);
291+ third_order_result = D.Sigma ;
292+ D.reset (); // reset the DiagramEvaluator for the next topology
293+
294+ // Compute third-order contribution using Zhen's code
295+ nda::array<dcomplex, 3 > TCA_Zhen (r, N, N);
296+ TCA_Zhen = 0 ;
297+ fb (1 ) = 0 ;
298+ fb (2 ) = 0 ;
299+ TCA_Zhen += Sigma_Diagram_calc (Delta_F, Delta_F_reflect, topologies (i, _, _), Deltat, Deltat_refl, Gt_dense, itops, beta, Fs_dense,
300+ F_dags_dense, fb, true );
301+ fb (1 ) = 1 ;
302+ TCA_Zhen += Sigma_Diagram_calc (Delta_F, Delta_F_reflect, topologies (i, _, _), Deltat, Deltat_refl, Gt_dense, itops, beta, Fs_dense,
303+ F_dags_dense, fb, true );
304+ fb (2 ) = 1 ;
305+ TCA_Zhen += Sigma_Diagram_calc (Delta_F, Delta_F_reflect, topologies (i, _, _), Deltat, Deltat_refl, Gt_dense, itops, beta, Fs_dense,
306+ F_dags_dense, fb, true );
307+ fb (1 ) = 0 ;
308+ TCA_Zhen += Sigma_Diagram_calc (Delta_F, Delta_F_reflect, topologies (i, _, _), Deltat, Deltat_refl, Gt_dense, itops, beta, Fs_dense,
309+ F_dags_dense, fb, true );
310+
311+ std::cout << " max error in block 0: " << nda::max_element (nda::abs (TCA_Zhen (_, range (0 , 4 ), range (0 , 4 )) - third_order_result.get_block (0 ))) << std::endl;
312+ std::cout << " max error in block 1: " << nda::max_element (nda::abs (TCA_Zhen (_, range (4 , 10 ), range (4 , 10 )) - third_order_result.get_block (1 ))) << std::endl;
313+ std::cout << " max error in block 2: " << nda::max_element (nda::abs (TCA_Zhen (_, range (10 , 11 ), range (10 , 11 )) - third_order_result.get_block (2 ))) << std::endl;
314+ std::cout << " max error in block 3: " << nda::max_element (nda::abs (TCA_Zhen (_, range (11 , 15 ), range (11 , 15 )) - third_order_result.get_block (3 ))) << std::endl;
315+ std::cout << " max error in block 4: " << nda::max_element (nda::abs (TCA_Zhen (_, range (15 , 16 ), range (15 , 16 )) - third_order_result.get_block (4 ))) << std::endl;
316+ std::cout << std::endl;
317+ }
318+ }
0 commit comments