Skip to content

Commit bcccd70

Browse files
committed
[som_core] Moved all kernel-specific code out of some_core.cpp
* TODO file has been updated. * Python tests now compare also the tail of g_w.
1 parent d355778 commit bcccd70

6 files changed

Lines changed: 97 additions & 82 deletions

File tree

TODO.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
* Test all kernels and close #3 accordingly
2-
* Add automatic Python tests chi_* and chi_auto_*
3-
* Make adding new kernels more straightforward
2+
* Add automatic Python tests chi_*, chi_auto_* and zerotemp_*
3+
* Fix tests to compare tails of g_w
4+
* Make sure all tests run successfully with versions 0.9 and 0.95
5+
* Update year in copyright headers (2016-2017)

c++/kernels/base.hpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@
2020
******************************************************************************/
2121
#pragma once
2222

23+
#include <utility>
2324
#include <string>
2425
#include <vector>
2526
#include <iostream>
27+
#include <boost/preprocessor/seq/size.hpp>
28+
#include <boost/preprocessor/seq/enum.hpp>
2629

2730
#include "../rectangle.hpp"
2831
#include "../configuration.hpp"
@@ -31,7 +34,15 @@
3134
namespace som {
3235

3336
// Kinds of observables
34-
enum observable_kind {FermionGf, BosonCorr, BosonAutoCorr, ZeroTemp};
37+
#define ALL_OBSERVABLES (FermionGf)(BosonCorr)(BosonAutoCorr)(ZeroTemp)
38+
39+
enum observable_kind : unsigned int {BOOST_PP_SEQ_ENUM(ALL_OBSERVABLES)};
40+
constexpr const unsigned int n_observable_kinds = BOOST_PP_SEQ_SIZE(ALL_OBSERVABLES);
41+
42+
// Is statistics defined for this observable?
43+
bool is_stat_relevant(observable_kind kind) {
44+
return kind != ZeroTemp;
45+
}
3546

3647
// Statistics of observables
3748
triqs::gfs::statistic_enum observable_statistics(observable_kind kind) {
@@ -54,6 +65,47 @@ std::string observable_name(observable_kind kind) {
5465
}
5566
}
5667

68+
// Widest energy windows for observables
69+
std::pair<double,double> max_energy_window(observable_kind kind) {
70+
switch(kind) {
71+
case FermionGf: return std::make_pair(-HUGE_VAL,HUGE_VAL);
72+
case BosonCorr: return std::make_pair(-HUGE_VAL,HUGE_VAL);
73+
case BosonAutoCorr: return std::make_pair(0,HUGE_VAL);
74+
case ZeroTemp: return std::make_pair(0,HUGE_VAL);
75+
}
76+
}
77+
78+
// Construct a real-frequency GF from a configuration
79+
void back_transform(observable_kind kind,
80+
configuration const& conf,
81+
cache_index & ci,
82+
triqs::gfs::gf_view<triqs::gfs::refreq,triqs::gfs::scalar_valued> g_w) {
83+
bool bosoncorr = kind == BosonCorr || kind == BosonAutoCorr;
84+
85+
g_w() = 0;
86+
auto & tail = g_w.singularity();
87+
88+
for(auto const& rect : conf) {
89+
for(auto e : g_w.mesh()) g_w.data()(e.index()) += rect.hilbert_transform(double(e), bosoncorr);
90+
tail.data()(range(),0,0) += rect.tail_coefficients(tail.order_min(),tail.order_max(), bosoncorr);
91+
92+
if(kind == BosonAutoCorr) {
93+
// Add a reflected rectangle
94+
rectangle reflected_rect(-rect.center, rect.width, rect.height, ci);
95+
for(auto e : g_w.mesh()) g_w.data()(e.index()) += reflected_rect.hilbert_transform(double(e), true);
96+
tail.data()(range(),0,0) += reflected_rect.tail_coefficients(tail.order_min(),tail.order_max(), true);
97+
}
98+
99+
if(bosoncorr) {
100+
g_w.data() *= -1.0/M_PI;
101+
tail.data() *= -1.0/M_PI;
102+
}
103+
}
104+
}
105+
106+
// All meshes used with input data containers
107+
#define ALL_INPUT_MESHES (imtime)(imfreq)(legendre)
108+
57109
// Mesh traits
58110
template<typename MeshType> struct mesh_traits;
59111

c++/som_core.cpp

Lines changed: 37 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
*
2020
******************************************************************************/
2121
#include <limits>
22+
#include <boost/preprocessor/seq/for_each.hpp>
23+
#include <boost/preprocessor/seq/for_each_product.hpp>
2224

2325
#include "som_core.hpp"
2426
#include "kernels/fermiongf_imtime.hpp"
@@ -119,10 +121,7 @@ som_core::som_core(gf_const_view<imtime> g_tau, gf_const_view<imtime> S_tau,
119121
mesh(g_tau.mesh()), kind(kind), norms(make_default_norms(norms,get_target_shape(g_tau)[0])),
120122
rhs(input_data_r_t()), error_bars(input_data_r_t()) {
121123

122-
if(kind != FermionGf && kind != BosonCorr && kind != BosonAutoCorr && kind != ZeroTemp)
123-
fatal_error("unknown observable kind " + to_string(kind));
124-
125-
if(kind != ZeroTemp) check_gf_stat(g_tau, observable_statistics(kind));
124+
if(is_stat_relevant(kind)) check_gf_stat(g_tau, observable_statistics(kind));
126125

127126
check_input_gf(g_tau,S_tau);
128127
if(!is_gf_real(g_tau) || !is_gf_real(S_tau))
@@ -137,10 +136,7 @@ som_core::som_core(gf_const_view<imfreq> g_iw, gf_const_view<imfreq> S_iw,
137136
mesh(g_iw.mesh()), kind(kind), norms(make_default_norms(norms,get_target_shape(g_iw)[0])),
138137
rhs(input_data_c_t()), error_bars(input_data_c_t()) {
139138

140-
if(kind != FermionGf && kind != BosonCorr && kind != BosonAutoCorr && kind != ZeroTemp)
141-
fatal_error("unknown observable kind " + to_string(kind));
142-
143-
if(kind != ZeroTemp) check_gf_stat(g_iw, observable_statistics(kind));
139+
if(is_stat_relevant(kind)) check_gf_stat(g_iw, observable_statistics(kind));
144140

145141
check_input_gf(g_iw,S_iw);
146142
if(!is_gf_real_in_tau(g_iw) || !is_gf_real_in_tau(S_iw))
@@ -157,10 +153,7 @@ som_core::som_core(gf_const_view<legendre> g_l, gf_const_view<legendre> S_l,
157153
mesh(g_l.mesh()), kind(kind), norms(make_default_norms(norms,get_target_shape(g_l)[0])),
158154
rhs(input_data_r_t()), error_bars(input_data_r_t()) {
159155

160-
if(kind != FermionGf && kind != BosonCorr && kind != BosonAutoCorr && kind != ZeroTemp)
161-
fatal_error("unknown observable kind " + to_string(kind));
162-
163-
if(kind != ZeroTemp) check_gf_stat(g_l, observable_statistics(kind));
156+
if(is_stat_relevant(kind)) check_gf_stat(g_l, observable_statistics(kind));
164157

165158
check_input_gf(g_l,S_l);
166159
if(!is_gf_real(g_l) || !is_gf_real(S_l))
@@ -177,9 +170,17 @@ void som_core::run(run_parameters_t const& p) {
177170

178171
params = p;
179172

180-
if((kind == BosonAutoCorr || kind == ZeroTemp) && params.energy_window.first < 0) {
181-
params.energy_window.first = 0;
182-
if(params.verbosity > 0) warning("left boundary of the energy window is reset to 0");
173+
double e_min, e_max;
174+
std::tie(e_min,e_max) = max_energy_window(kind);
175+
if(params.energy_window.first < e_min) {
176+
params.energy_window.first = e_min;
177+
if(params.verbosity > 0)
178+
warning("left boundary of the energy window is reset to " + std::to_string(e_min));
179+
}
180+
if(params.energy_window.second > e_max) {
181+
params.energy_window.second = e_max;
182+
if(params.verbosity > 0)
183+
warning("right boundary of the energy window is reset to " + std::to_string(e_max));
183184
}
184185

185186
if(params.energy_window.first >= params.energy_window.second)
@@ -202,20 +203,12 @@ void som_core::run(run_parameters_t const& p) {
202203
triqs::signal_handler::start();
203204
run_status = 0;
204205
try {
205-
#define RUN_IMPL_CASE(ok, mk) case (int(ok) + 4 * mesh_traits<mk>::index): run_impl<kernel<ok,mk>>(); break;
206-
switch(int(kind) + 4 * mesh.index()) {
207-
RUN_IMPL_CASE(FermionGf,imtime);
208-
RUN_IMPL_CASE(FermionGf,imfreq);
209-
RUN_IMPL_CASE(FermionGf,legendre);
210-
RUN_IMPL_CASE(BosonCorr,imtime);
211-
RUN_IMPL_CASE(BosonCorr,imfreq);
212-
RUN_IMPL_CASE(BosonCorr,legendre);
213-
RUN_IMPL_CASE(BosonAutoCorr,imtime);
214-
RUN_IMPL_CASE(BosonAutoCorr,imfreq);
215-
RUN_IMPL_CASE(BosonAutoCorr,legendre);
216-
RUN_IMPL_CASE(ZeroTemp,imtime);
217-
RUN_IMPL_CASE(ZeroTemp,imfreq);
218-
RUN_IMPL_CASE(ZeroTemp,legendre);
206+
#define RUN_IMPL_CASE(r, okmk) \
207+
case (int(BOOST_PP_SEQ_ELEM(0,okmk)) + \
208+
n_observable_kinds * mesh_traits<BOOST_PP_SEQ_ELEM(1,okmk)>::index): \
209+
run_impl<kernel<BOOST_PP_SEQ_ENUM(okmk)>>(); break;
210+
switch(int(kind) + n_observable_kinds * mesh.index()) {
211+
BOOST_PP_SEQ_FOR_EACH_PRODUCT(RUN_IMPL_CASE, (ALL_OBSERVABLES)(ALL_INPUT_MESHES))
219212
}
220213
#undef RUN_IMPL_CASE
221214
} catch(stopped & e) {
@@ -461,65 +454,30 @@ template<typename MeshType>
461454
void triqs_gf_view_assign_delegation(gf_view<MeshType> g, som_core const& cont) {
462455
auto gf_dim = cont.results.size();
463456
check_gf_dim(g, gf_dim);
464-
if(cont.kind != ZeroTemp) check_gf_stat(g, observable_statistics(cont.kind));
457+
if(is_stat_relevant(cont.kind)) check_gf_stat(g, observable_statistics(cont.kind));
465458

466459
g() = 0;
460+
#define FILL_DATA_CASE(r, data, ok) \
461+
case ok: { \
462+
kernel<ok,MeshType> kern(g.mesh()); \
463+
for(int i : range(gf_dim)) fill_data(g, i, kern(cont.results[i])); \
464+
return; \
465+
}
467466
switch(cont.kind) {
468-
case FermionGf: {
469-
kernel<FermionGf,MeshType> kern(g.mesh());
470-
for(int i : range(gf_dim)) fill_data(g, i, kern(cont.results[i]));
471-
return;
472-
}
473-
case BosonCorr: {
474-
kernel<BosonCorr,MeshType> kern(g.mesh());
475-
for(int i : range(gf_dim)) fill_data(g, i, kern(cont.results[i]));
476-
return;
477-
}
478-
case BosonAutoCorr: {
479-
kernel<BosonAutoCorr,MeshType> kern(g.mesh());
480-
for(int i : range(gf_dim)) fill_data(g, i, kern(cont.results[i]));
481-
return;
482-
}
483-
case ZeroTemp: {
484-
kernel<ZeroTemp,MeshType> kern(g.mesh());
485-
for(int i : range(gf_dim)) fill_data(g, i, kern(cont.results[i]));
486-
return;
487-
}
488-
default:
489-
fatal_error("unknown observable kind " + to_string(cont.kind));
467+
BOOST_PP_SEQ_FOR_EACH(FILL_DATA_CASE, _, ALL_OBSERVABLES)
468+
default: fatal_error("unknown observable kind " + to_string(cont.kind));
490469
}
470+
#undef FILL_DATA_CASE
491471
}
492472

493473
template<> void triqs_gf_view_assign_delegation<refreq>(gf_view<refreq> g_w, som_core const& cont) {
494-
495-
bool bosoncorr = cont.kind == BosonCorr || cont.kind == BosonAutoCorr;
496-
if(cont.kind != FermionGf && !bosoncorr && cont.kind != ZeroTemp)
497-
fatal_error("unknown observable kind " + to_string(cont.kind));
498474
auto gf_dim = cont.results.size();
499475
check_gf_dim(g_w, gf_dim);
500-
501-
g_w() = 0;
502-
auto & tail = g_w.singularity();
503-
504-
for(int i : range(gf_dim)) {
505-
auto const& conf = cont.results[i];
506-
for(auto const& rect : conf) {
507-
for(auto e : g_w.mesh()) g_w.data()(e.index(),i,i) += rect.hilbert_transform(double(e), bosoncorr);
508-
tail.data()(range(),i,i) += rect.tail_coefficients(tail.order_min(),tail.order_max(), bosoncorr);
509-
510-
if(cont.kind == BosonAutoCorr) {
511-
// Add a reflected rectangle
512-
rectangle reflected_rect(-rect.center, rect.width, rect.height, const_cast<som_core&>(cont).ci);
513-
for(auto e : g_w.mesh()) g_w.data()(e.index(),i,i) += reflected_rect.hilbert_transform(double(e), true);
514-
tail.data()(range(),i,i) += reflected_rect.tail_coefficients(tail.order_min(),tail.order_max(), true);
515-
}
516-
}
517-
518-
if(bosoncorr) {
519-
g_w.data()(range(),i,i) *= -1.0/M_PI;
520-
tail.data()(range(),i,i) *= -1.0/M_PI;
521-
}
522-
}
476+
for(int i : range(gf_dim))
477+
back_transform(cont.kind,
478+
cont.results[i],
479+
const_cast<som_core&>(cont).ci,
480+
slice_target_to_scalar(g_w, i, i));
523481
}
524482

525483
template void triqs_gf_view_assign_delegation<imtime>(gf_view<imtime>, som_core const&);

test/python/gf_imfreq.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,6 @@
5757
# arch['histograms'] = cont.histograms
5858
assert_gfs_are_close(g_rec_iw, arch['g_rec_iw'])
5959
assert_gfs_are_close(g_w, arch['g_w'], 6e-4)
60+
assert_arrays_are_close(g_w.tail.data, arch['g_w'].tail.data, 6e-4)
6061
assert_arrays_are_close(cont.histograms[0].data, arch['histograms'][0].data)
6162
assert_arrays_are_close(cont.histograms[1].data, arch['histograms'][1].data)

test/python/gf_imtime.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,6 @@
5757
# arch['histograms'] = cont.histograms
5858
assert_gfs_are_close(g_rec_tau, arch['g_rec_tau'])
5959
assert_gfs_are_close(g_w, arch['g_w'], 1e-5)
60+
assert_arrays_are_close(g_w.tail.data, arch['g_w'].tail.data, 1e-5)
6061
assert_arrays_are_close(cont.histograms[0].data, arch['histograms'][0].data)
6162
assert_arrays_are_close(cont.histograms[1].data, arch['histograms'][1].data)

test/python/gf_legendre.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,6 @@
5757
# arch['histograms'] = cont.histograms
5858
assert_gfs_are_close(g_rec_l, arch['g_rec_l'])
5959
assert_gfs_are_close(g_w, arch['g_w'], 1e-5)
60+
assert_arrays_are_close(g_w.tail.data, arch['g_w'].tail.data, 1e-5)
6061
assert_arrays_are_close(cont.histograms[0].data, arch['histograms'][0].data)
6162
assert_arrays_are_close(cont.histograms[1].data, arch['histograms'][1].data)

0 commit comments

Comments
 (0)