Skip to content

Commit 727e3a4

Browse files
committed
Added Python DiagramEvaluator test
1 parent f21b8b3 commit 727e3a4

9 files changed

Lines changed: 341 additions & 178 deletions

File tree

c++/triqs_xca/block_sparse_backbone.cpp

Lines changed: 130 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <nda/declarations.hpp>
88
#include <nda/mapped_functions.hxx>
99
#include <nda/nda.hpp>
10+
#include <triqs/mesh/dlr_imtime.hpp>
1011
#include <triqs/mesh/imtime.hpp>
1112
#include <triqs_xca/block_sparse.hpp>
1213
#include <triqs_xca/block_sparse_backbone.hpp>
@@ -78,6 +79,11 @@ void DiagramEvaluator::reset() {
7879
}
7980
}
8081

82+
int DiagramEvaluator::get_num_backbones(nda::array<int, 2> topology) {
83+
Backbone backbone(topology, n);
84+
return static_cast<int>(backbone.fb_ix_max * backbone.o_ix_max * pow(hyb_poles.size(), backbone.m - 1));
85+
}
86+
8187
void DiagramEvaluator::multiply_vertex_block(Backbone &backbone, int v_ix, nda::vector_const_view<int> ind_path,
8288
nda::vector_const_view<int> block_dims) {
8389
int o_ix = backbone.get_vertex_orb(v_ix); // orbital_index
@@ -219,103 +225,119 @@ void DiagramEvaluator::multiply_prefactor(Backbone &backbone, nda::vector_const_
219225

220226
BlockDiagOpFun &DiagramEvaluator::get_self_energy() { return Sigma; }
221227

222-
void DiagramEvaluator::eval_self_energy(Backbone &backbone) {
223-
228+
void DiagramEvaluator::find_path_self_energy(Backbone &backbone, int f_ix, nda::vector_view<int> ind_path, nda::vector_view<int> block_dims) {
224229
int m = backbone.m;
225-
nda::vector<int> ind_path(2 * m - 1); // tracks block indices of factors for computing a particular block of the self-energy
226-
nda::vector<int> block_dims(2 * m + 1); // tracks the dimensions of the blocks in these factors
227-
228-
// loop over all flat indices
229-
int f_ix_max = static_cast<int>(backbone.fb_ix_max * backbone.o_ix_max * pow(hyb_poles.size(), m - 1));
230-
for (int f_ix = 0; f_ix < f_ix_max; f_ix++) {
231-
backbone.set_flat_index(f_ix, hyb_poles); // set directions, pole indices, and orbital indices from a single integer index
232-
/* Example of block_dims for m = 2 (OCA): each number is an index of block_dims, and each square represents a block of a matrix
233-
3 3 2 2 1 1 0
234-
-------- -------- -------- -------- -------- -------- --------
235-
4 | F | 3 | G | 3 | F | 2 | G | 2 | F | 1 | G | 1 | F |
236-
| | | | | | | | | | | | | |
237-
-------- -------- -------- -------- -------- -------- --------
238-
*/
239-
// ind_path can diverge at the vertex connected to vertex 0
240-
for (int b_ix = 0; b_ix < Gt.get_num_block_cols(); b_ix++) { // loop over blocks of self-energy
241-
for (int p_kap = 0; p_kap < q; p_kap++) { // loop over symmetry sets on the zero vertex
242-
bool path_all_nonzero = true;
243-
int w = 0, ip = 0; // w loops over the vertices and edges, ip is the current block index
244-
245-
if (backbone.has_vertex_dag(0)) { // if line is connected to zero is backward
246-
ip = Fq.F_dags[p_kap].get_block_index(b_ix);
247-
if (ip != -1) {
248-
block_dims(0) = Fq.F_dags[p_kap].get_block_size(b_ix, 1);
249-
block_dims(1) = Fq.F_dags[p_kap].get_block_size(b_ix, 0);
250-
} else {
251-
path_all_nonzero = false;
252-
}
230+
backbone.set_flat_index(f_ix, hyb_poles); // set directions, pole indices, and orbital indices from a single integer index
231+
/* Example of block_dims for m = 2 (OCA): each number is an index of block_dims, and each square represents a block of a matrix
232+
3 3 2 2 1 1 0
233+
-------- -------- -------- -------- -------- -------- --------
234+
4 | F | 3 | G | 3 | F | 2 | G | 2 | F | 1 | G | 1 | F |
235+
| | | | | | | | | | | | | |
236+
-------- -------- -------- -------- -------- -------- --------
237+
*/
238+
// ind_path can diverge at the vertex connected to vertex 0
239+
for (int b_ix = 0; b_ix < Gt.get_num_block_cols(); b_ix++) { // loop over blocks of self-energy
240+
for (int p_kap = 0; p_kap < q; p_kap++) { // loop over symmetry sets on the zero vertex
241+
bool path_all_nonzero = true;
242+
int w = 0, ip = 0; // w loops over the vertices and edges, ip is the current block index
243+
244+
if (backbone.has_vertex_dag(0)) { // if line is connected to zero is backward
245+
ip = Fq.F_dags[p_kap].get_block_index(b_ix);
246+
if (ip != -1) {
247+
block_dims(0) = Fq.F_dags[p_kap].get_block_size(b_ix, 1);
248+
block_dims(1) = Fq.F_dags[p_kap].get_block_size(b_ix, 0);
253249
} else {
254-
ip = Fq.Fs[p_kap].get_block_index(b_ix);
255-
if (ip != -1) {
256-
block_dims(0) = Fq.Fs[p_kap].get_block_size(b_ix, 1);
257-
block_dims(1) = Fq.Fs[p_kap].get_block_size(b_ix, 0);
258-
} else {
259-
path_all_nonzero = false;
260-
}
250+
path_all_nonzero = false;
261251
}
262-
// traverse factors in two halves
263-
// first half: before vertex connected to zero
264-
while (w < backbone.get_topology(0, 1) && path_all_nonzero) { // only continue if we have not hit a zero block
265-
if (w != 0) {
266-
ip = (backbone.has_vertex_dag(w)) ? Fq.F_dags[Fq.sym_set_labels(backbone.get_orb_ind(w))].get_block_index(ip) :
267-
Fq.Fs[Fq.sym_set_labels(backbone.get_orb_ind(w))].get_block_index(ip); // update block index
268-
}
269-
if (ip == -1 || (w < 2 * m - 1 && Gt.get_zero_block_index(ip) == -1)) { // check if we hit a zero block in F or Gt
270-
path_all_nonzero = false;
271-
} else { // inner 'if' block unnecessary in first half
272-
ind_path(w) = ip; // store the block index for the current vertex/edge, unless we are at the last vertex
273-
if (w != backbone.get_topology(0, 1) - 1) { // if so, then orb_ind = -1, because w is the vertex connected to zero
274-
block_dims(w + 2) = (backbone.has_vertex_dag(w + 1)) ? Fq.F_dags[Fq.sym_set_labels(backbone.get_orb_ind(w + 1))].get_block_size(ip, 0) :
275-
Fq.Fs[Fq.sym_set_labels(backbone.get_orb_ind(w + 1))].get_block_size(ip, 0);
276-
}
252+
} else {
253+
ip = Fq.Fs[p_kap].get_block_index(b_ix);
254+
if (ip != -1) {
255+
block_dims(0) = Fq.Fs[p_kap].get_block_size(b_ix, 1);
256+
block_dims(1) = Fq.Fs[p_kap].get_block_size(b_ix, 0);
257+
} else {
258+
path_all_nonzero = false;
259+
}
260+
}
261+
// traverse factors in two halves
262+
// first half: before vertex connected to zero
263+
while (w < backbone.get_topology(0, 1) && path_all_nonzero) { // only continue if we have not hit a zero block
264+
if (w != 0) {
265+
ip = (backbone.has_vertex_dag(w)) ? Fq.F_dags[Fq.sym_set_labels(backbone.get_orb_ind(w))].get_block_index(ip) :
266+
Fq.Fs[Fq.sym_set_labels(backbone.get_orb_ind(w))].get_block_index(ip); // update block index
267+
}
268+
if (ip == -1 || (w < 2 * m - 1 && Gt.get_zero_block_index(ip) == -1)) { // check if we hit a zero block in F or Gt
269+
path_all_nonzero = false;
270+
} else { // inner 'if' block unnecessary in first half
271+
ind_path(w) = ip; // store the block index for the current vertex/edge, unless we are at the last vertex
272+
if (w != backbone.get_topology(0, 1) - 1) { // if so, then orb_ind = -1, because w is the vertex connected to zero
273+
block_dims(w + 2) = (backbone.has_vertex_dag(w + 1)) ? Fq.F_dags[Fq.sym_set_labels(backbone.get_orb_ind(w + 1))].get_block_size(ip, 0) :
274+
Fq.Fs[Fq.sym_set_labels(backbone.get_orb_ind(w + 1))].get_block_size(ip, 0);
277275
}
278-
w += 1;
279276
}
277+
w += 1;
278+
}
280279

281-
int ip1 = ip;
282-
// second half
283-
if (path_all_nonzero) {
284-
for (int p_mu = 0; p_mu < q; p_mu++) {
285-
bool fork_all_nonzero = true;
286-
w = backbone.get_topology(0, 1); // reset w to the vertex connected to vertex 0
287-
// save block_dims(backbone.get_topology(0, 1) + 1)
288-
block_dims(w + 1) = (backbone.has_vertex_dag(w)) ? Fq.F_dags[p_mu].get_block_size(ip1, 0) : Fq.Fs[p_mu].get_block_size(ip1, 0);
289-
ip = (backbone.has_vertex_dag(w)) ? Fq.F_dags[p_mu].get_block_index(ip1) :
290-
Fq.Fs[p_mu].get_block_index(ip1); // update block index for the vertex connected to zero
291-
while (w < 2 * m && fork_all_nonzero) {
292-
if (w != backbone.get_topology(0, 1)) {
293-
ip = (backbone.has_vertex_dag(w)) ? Fq.F_dags[Fq.sym_set_labels(backbone.get_orb_ind(w))].get_block_index(ip) :
294-
Fq.Fs[Fq.sym_set_labels(backbone.get_orb_ind(w))].get_block_index(ip); // update block index
295-
}
296-
if (ip == -1 || (w < 2 * m - 1 && Gt.get_zero_block_index(ip) == -1)) { // check if we hit a zero block in F or Gt
297-
fork_all_nonzero = false;
298-
} else {
299-
if (w < 2 * m - 1) { // only store the block index if we are not at the last vertex
300-
ind_path(w) = ip; // store the block index for the current vertex/edge
301-
block_dims(w + 2) = (backbone.has_vertex_dag(w + 1)) ?
302-
Fq.F_dags[Fq.sym_set_labels(backbone.get_orb_ind(w + 1))].get_block_size(ip, 0) :
303-
Fq.Fs[Fq.sym_set_labels(backbone.get_orb_ind(w + 1))].get_block_size(ip, 0);
304-
}
305-
}
306-
w += 1;
280+
int ip1 = ip;
281+
// second half
282+
if (path_all_nonzero) {
283+
for (int p_mu = 0; p_mu < q; p_mu++) {
284+
bool fork_all_nonzero = true;
285+
w = backbone.get_topology(0, 1); // reset w to the vertex connected to vertex 0
286+
// save block_dims(backbone.get_topology(0, 1) + 1)
287+
block_dims(w + 1) = (backbone.has_vertex_dag(w)) ? Fq.F_dags[p_mu].get_block_size(ip1, 0) : Fq.Fs[p_mu].get_block_size(ip1, 0);
288+
ip = (backbone.has_vertex_dag(w)) ? Fq.F_dags[p_mu].get_block_index(ip1) :
289+
Fq.Fs[p_mu].get_block_index(ip1); // update block index for the vertex connected to zero
290+
while (w < 2 * m && fork_all_nonzero) {
291+
if (w != backbone.get_topology(0, 1)) {
292+
ip = (backbone.has_vertex_dag(w)) ? Fq.F_dags[Fq.sym_set_labels(backbone.get_orb_ind(w))].get_block_index(ip) :
293+
Fq.Fs[Fq.sym_set_labels(backbone.get_orb_ind(w))].get_block_index(ip); // update block index
307294
}
308-
if (fork_all_nonzero) {
309-
// evaluate the diagram with these directions, poles, and orbital indices
310-
// b_ix is the block index for the first edge
311-
eval_self_energy_fixed_indices(backbone, b_ix, p_kap, p_mu, ind_path, block_dims);
295+
if (ip == -1 || (w < 2 * m - 1 && Gt.get_zero_block_index(ip) == -1)) { // check if we hit a zero block in F or Gt
296+
fork_all_nonzero = false;
297+
} else {
298+
if (w < 2 * m - 1) { // only store the block index if we are not at the last vertex
299+
ind_path(w) = ip; // store the block index for the current vertex/edge
300+
block_dims(w + 2) = (backbone.has_vertex_dag(w + 1)) ?
301+
Fq.F_dags[Fq.sym_set_labels(backbone.get_orb_ind(w + 1))].get_block_size(ip, 0) :
302+
Fq.Fs[Fq.sym_set_labels(backbone.get_orb_ind(w + 1))].get_block_size(ip, 0);
303+
}
312304
}
305+
w += 1;
306+
}
307+
if (fork_all_nonzero) {
308+
// evaluate the diagram with these directions, poles, and orbital indices
309+
// b_ix is the block index for the first edge
310+
eval_self_energy_fixed_indices(backbone, b_ix, p_kap, p_mu, ind_path, block_dims);
313311
}
314312
}
315313
}
316314
}
317-
backbone.reset_all_inds(); // reset directions, pole indices, and orbital indices for the next iteration
318315
}
316+
backbone.reset_all_inds(); // reset directions, pole indices, and orbital indices for the next iteration
317+
}
318+
319+
void DiagramEvaluator::eval_self_energy(Backbone &backbone, int f_ix) {
320+
int m = backbone.m;
321+
int f_ix_max = static_cast<int>(backbone.fb_ix_max * backbone.o_ix_max * pow(hyb_poles.size(), m - 1));
322+
if (f_ix < 0 || f_ix >= f_ix_max) {
323+
throw std::runtime_error("DiagramEvaluator::eval_self_energy: f_ix out of range");
324+
}
325+
326+
nda::vector<int> ind_path(2 * m - 1); // tracks block indices of factors for computing a particular block of the self-energy
327+
nda::vector<int> block_dims(2 * m + 1); // tracks the dimensions of the blocks in these factors
328+
329+
find_path_self_energy(backbone, f_ix, ind_path, block_dims);
330+
Sigma.set_zero_block_indices(); // set zero_block_indices according to current blocks
331+
}
332+
333+
void DiagramEvaluator::eval_self_energy(Backbone &backbone) {
334+
int m = backbone.m;
335+
nda::vector<int> ind_path(2 * m - 1); // tracks block indices of factors for computing a particular block of the self-energy
336+
nda::vector<int> block_dims(2 * m + 1); // tracks the dimensions of the blocks in these factors
337+
338+
// loop over all flat indices
339+
int f_ix_max = static_cast<int>(backbone.fb_ix_max * backbone.o_ix_max * pow(hyb_poles.size(), m - 1));
340+
for (int f_ix = 0; f_ix < f_ix_max; f_ix++) { find_path_self_energy(backbone, f_ix, ind_path, block_dims); }
319341
Sigma.set_zero_block_indices(); // set zero_block_indices according to current blocks
320342
}
321343

@@ -347,19 +369,35 @@ void DiagramEvaluator::eval_self_energy_fixed_indices(Backbone &backbone, int b_
347369
}
348370

349371
block_gf<dlr_imtime> DiagramEvaluator::compute_self_energy(nda::array<int, 2> topology) {
350-
int n = hyb.extent(1);
351372
Backbone backbone(topology, n);
352373
eval_self_energy(backbone);
353-
BlockDiagOpFun Sigma = get_self_energy();
354-
std::vector<gf<dlr_imtime>> Sigma_blocks(Sigma.get_num_block_cols());
355-
for (int i = 0; i < Sigma.get_num_block_cols(); ++i) {
356-
if (Sigma.get_zero_block_index(i) == -1) {
357-
Sigma_blocks[i] = gf<dlr_imtime>(tau_mesh); // zero block
374+
BlockDiagOpFun sig = get_self_energy();
375+
std::vector<gf<dlr_imtime>> sig_blocks(sig.get_num_block_cols());
376+
for (int i = 0; i < sig.get_num_block_cols(); ++i) {
377+
if (sig.get_zero_block_index(i) == -1) {
378+
sig_blocks[i] = gf<dlr_imtime>(tau_mesh, 0 * Gt.get_block(i)); // zero block
379+
} else {
380+
sig_blocks[i] = gf<dlr_imtime>(tau_mesh, sig.get_block(i));
381+
}
382+
}
383+
reset();
384+
return {sig_blocks};
385+
}
386+
387+
block_gf<dlr_imtime> DiagramEvaluator::compute_self_energy(nda::array<int, 2> topology, int f_ix) {
388+
Backbone backbone(topology, n);
389+
eval_self_energy(backbone, f_ix);
390+
BlockDiagOpFun sig = get_self_energy();
391+
std::vector<gf<dlr_imtime>> sig_blocks(sig.get_num_block_cols());
392+
for (int i = 0; i < sig.get_num_block_cols(); ++i) {
393+
if (sig.get_zero_block_index(i) == -1) {
394+
sig_blocks[i] = gf<dlr_imtime>(tau_mesh, 0 * Gt.get_block(i)); // zero block
358395
} else {
359-
Sigma_blocks[i] = gf<dlr_imtime>(tau_mesh, Sigma.get_block(i));
396+
sig_blocks[i] = gf<dlr_imtime>(tau_mesh, sig.get_block(i));
360397
}
361398
}
362-
return {Sigma_blocks};
399+
reset();
400+
return {sig_blocks};
363401
}
364402

365403
// ========== Correlator routines ==========

c++/triqs_xca/block_sparse_backbone.hpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ class DiagramEvaluator {
4242
void multiply_zero_vertex_block(Backbone &backbone, bool is_forward, int b_ix_0, int p_kap, int p_mu, nda::vector_const_view<int> ind_path,
4343
nda::vector_const_view<int> block_dims); // multiply by the zero vertex and the vertex connected to zero
4444
BlockDiagOpFun &get_self_energy(); // get the self-energy result
45-
void eval_self_energy(Backbone &backbone); // evaluate a diagram of a given order and topology in block-sparse storage
45+
void find_path_self_energy(Backbone &backbone, int f_ix, nda::vector_view<int> ind_path, nda::vector_view<int> block_dims);
46+
void eval_self_energy(Backbone &backbone, int f_ix); // evaluate a particular backbone diagram
47+
void eval_self_energy(Backbone &backbone); // evaluate a diagram of a given order and topology in block-sparse storage
4648
void eval_self_energy_fixed_indices(
4749
Backbone &backbone, int b_ix, int p_kap, int p_mu, nda::vector_const_view<int> ind_path,
4850
nda::vector_const_view<int>
@@ -75,10 +77,12 @@ class DiagramEvaluator {
7577
nda::array<dcomplex, 3> Tmu; // intermediate storage array
7678

7779
// routines for any diagram
78-
void reset(); // reset all arrays to zero
80+
void reset(); // reset all arrays to zero
81+
int get_num_backbones(nda::array<int, 2> topology); // get number of backbones for given topology
7982

8083
// routines for self-energy diagrams
81-
block_gf<dlr_imtime> compute_self_energy(nda::array<int, 2> topology); // compute self-energy for given topology
84+
block_gf<dlr_imtime> compute_self_energy(nda::array<int, 2> topology); // compute self-energy for given topology
85+
block_gf<dlr_imtime> compute_self_energy(nda::array<int, 2> topology, int f_ix); // compute self-energy for given topology and flat index
8286

8387
/**
8488
* @brief Constructor for DiagramEvaluator
@@ -90,9 +94,8 @@ class DiagramEvaluator {
9094
* @param[in] G_ppsc pseudo-particle Green's function at imaginary time nodes
9195
* @param[in] ad atom_diag object with Hamiltonian and field operators
9296
*/
93-
DiagramEvaluator(double beta, double Lambda, double eps, nda::vector_const_view<double> hyb_poles,
94-
nda::array_const_view<dcomplex, 3> hyb_coeffs, block_gf_view<dlr_imtime> G_ppsc,
95-
triqs::atom_diag::atom_diag<false> const &ad);
97+
DiagramEvaluator(double beta, double Lambda, double eps, nda::vector_const_view<double> hyb_poles, nda::array_const_view<dcomplex, 3> hyb_coeffs,
98+
block_gf_view<dlr_imtime> G_ppsc, triqs::atom_diag::atom_diag<false> const &ad);
9699

97100
/**
98101
* @brief Old constructor for DiagramEvaluator

0 commit comments

Comments
 (0)