mirror of
https://github.com/triqs/dft_tools
synced 2024-12-25 05:43:40 +01:00
[gfs] Lattice fourier, multivar G, curry, tail
- Add Fourier for lattice. - Add regular_bz_mesh, cyclic_lattice, and their FFT. - rm freq_infty. - The gf can now be evaluated on a tail_view, which result in composing the tail. - Fix the following issue : g(om_) << g(om_ +1) will recompose the tail correctly. - TODO : TEST THIS NEW FEATURE IN DETAIL. - Work on singularity for G(x, omega) - Separate the factory for singularity from the data factory in gf. - overload assign_from_functoin (renamed). - Fix singularity_t and co in the gf (const issue). - Clean tail, add tail_const_view - add m_tail for x -> tail on any mesh - test curry + fourier works on k
This commit is contained in:
parent
47cb8a03f7
commit
0a1285405c
@ -174,11 +174,7 @@ if(CMAKE_COMPILER_IS_ICC)
|
||||
else()
|
||||
set(BOOST_VERSION 1.46)
|
||||
endif()
|
||||
if (PythonSupport)
|
||||
find_package(Boost ${BOOST_VERSION} REQUIRED COMPONENTS mpi python serialization system )
|
||||
else()
|
||||
find_package(Boost ${BOOST_VERSION} REQUIRED COMPONENTS mpi serialization system )
|
||||
endif()
|
||||
if (NOT Boost_FOUND)
|
||||
message(FATAL_ERROR "Boost not found")
|
||||
endif()
|
||||
|
@ -8,7 +8,6 @@ module.add_include("<triqs/gfs/local/pade.hpp>")
|
||||
module.add_include("<triqs/gfs/local/legendre_matsubara.hpp>")
|
||||
module.add_using("namespace triqs::arrays")
|
||||
module.add_using("namespace triqs::gfs")
|
||||
module.add_using("namespace triqs::gfs::local")
|
||||
module.add_using("triqs::utility::mini_vector")
|
||||
|
||||
########################
|
||||
@ -16,8 +15,8 @@ module.add_using("triqs::utility::mini_vector")
|
||||
########################
|
||||
|
||||
t = class_( py_type = "TailGf",
|
||||
c_type = "local::tail_view",
|
||||
c_type_absolute = "triqs::gfs::local::tail_view",
|
||||
c_type = "tail_view",
|
||||
c_type_absolute = "triqs::gfs::tail_view",
|
||||
serializable= "tuple",
|
||||
is_printable= True,
|
||||
arithmetic = ("algebra","double")
|
||||
@ -41,7 +40,7 @@ t.add_property(getter = cfunction("int order_max()"),
|
||||
doc = "Max order of the expansion")
|
||||
|
||||
t.add_property(name = "mask",
|
||||
getter = cfunction("array_view<long,2> mask_view()"),
|
||||
getter = cfunction("array_view<int,2> mask()"),
|
||||
doc = "Access to the mask")
|
||||
|
||||
t.add_method(name = "has_coef",
|
||||
@ -51,7 +50,7 @@ t.add_method(name = "has_coef",
|
||||
|
||||
# strange, I should not quality : ADL ??
|
||||
t.add_method(name = "invert",
|
||||
calling_pattern = "self_c = local::inverse(self_c)",
|
||||
calling_pattern = "self_c = inverse(self_c)",
|
||||
signature = "void()",
|
||||
doc = "Invert")
|
||||
|
||||
@ -63,7 +62,7 @@ t.add_method(name = "zero",
|
||||
t.add_method_copy()
|
||||
t.add_method_copy_from()
|
||||
|
||||
t.add_call(calling_pattern = "auto result = self_c.evaluate(u)",
|
||||
t.add_call(calling_pattern = "auto result = evaluate(self_c,u)",
|
||||
signature = "dcomplex(dcomplex u)",
|
||||
doc = "")
|
||||
|
||||
@ -252,7 +251,7 @@ def make_gf( py_type, c_tag, is_complex_data = True, is_im = False, has_tail = T
|
||||
|
||||
if has_tail:
|
||||
g.add_property(name = "tail",
|
||||
getter = cfunction(c_name="singularity", signature = "local::tail_view()"),
|
||||
getter = cfunction(c_name="singularity", signature = "tail_view()"),
|
||||
doc ="The high frequency tail")
|
||||
|
||||
g.add_property(name = "indices",
|
||||
@ -332,7 +331,7 @@ def make_gf( py_type, c_tag, is_complex_data = True, is_im = False, has_tail = T
|
||||
g.number_protocol['multiply'].add_overload(calling_pattern = "*", signature = "gf<%s>(gf<%s> x,matrix<%s> y)"%(c_tag,c_tag,data_type))
|
||||
|
||||
g.add_method(name = "from_L_G_R",
|
||||
calling_pattern = "self_c = L_G_R(l,g,r)",
|
||||
calling_pattern = "self_c = L_G_R(l,g(),r)",
|
||||
signature = "void(matrix<%s> l,gf<%s> g,matrix<%s> r)"%(data_type,c_tag,data_type),
|
||||
doc = "self <<= l * g * r")
|
||||
|
||||
|
57
test/triqs/gfs/g_r_k.cpp
Normal file
57
test/triqs/gfs/g_r_k.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
#include <triqs/gfs.hpp>
|
||||
#include <triqs/gfs/bz.hpp>
|
||||
#include <triqs/gfs/cyclic_lattice.hpp>
|
||||
#include <triqs/gfs/local/fourier_lattice.hpp>
|
||||
|
||||
namespace h5 = triqs::h5;
|
||||
using namespace triqs::gfs;
|
||||
using namespace triqs::clef;
|
||||
using namespace triqs::arrays;
|
||||
using namespace triqs::lattice;
|
||||
|
||||
#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> " << (X) << std::endl << std::endl;
|
||||
|
||||
int main() {
|
||||
try {
|
||||
double beta = 1;
|
||||
int N = 10;
|
||||
int S = 2;
|
||||
placeholder<0> k_;
|
||||
placeholder<1> r_;
|
||||
|
||||
auto bz_ = brillouin_zone{bravais_lattice{make_unit_matrix<double>(2)}};
|
||||
auto gk = gf<bz>{{bz_, N}, {S, S}};
|
||||
|
||||
gk(k_) << -2 * (cos(k_(0)) + cos(k_(1)));
|
||||
|
||||
auto gr = gf<cyclic_lattice>{{N, N}, {S, S}};
|
||||
|
||||
gr() = inverse_fourier(gk); // ADD Security if gf =
|
||||
|
||||
// for (auto k : gk.mesh()) if (max_element(abs(gk[k])) > 1.e-10) std::cout << k << gk[k] << std::endl;
|
||||
|
||||
for (auto r : gr.mesh())
|
||||
if (max_element(abs(gr[r])) > 1.e-10) std::cout << r << gr[r] << std::endl;
|
||||
|
||||
// reverse transfo
|
||||
auto gk2 = gk;
|
||||
gk2() = fourier(gr);
|
||||
if (max_element(abs(gk.data() - gk2.data())) > 1.e-13) TRIQS_RUNTIME_ERROR << "fourier pb";
|
||||
|
||||
// check gr
|
||||
auto gr_test = gf<cyclic_lattice>{{N, N}, {S, S}};
|
||||
gr_test[{1,0,0}] = -1;
|
||||
gr_test[{-1,0,0}] = -1;
|
||||
gr_test[{0,1,0}] = -1;
|
||||
gr_test[{0,-1,0}] = -1;
|
||||
|
||||
if (max_element(abs(gr.data() - gr_test.data())) > 1.e-13) TRIQS_RUNTIME_ERROR << "fourier inverse pb"; // << gr.data() << gr_test.data();
|
||||
|
||||
// hdf5
|
||||
h5::file file("ess_g_r_k.h5", H5F_ACC_TRUNC);
|
||||
h5_write(file, "gr", gr);
|
||||
h5_write(file, "gk", gk);
|
||||
}
|
||||
TRIQS_CATCH_AND_ABORT;
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
(G1( 0)) ---> empty
|
||||
|
||||
(G( 0)) --->
|
||||
[[(0,0),(0,0)]
|
||||
[(0,0),(0,0)]]
|
||||
|
||||
(Gv2( 0)) --->
|
||||
[[(0,0)]]
|
||||
|
||||
(Gv2( 0)) --->
|
||||
[[(10,0)]]
|
||||
|
||||
(G( 0)) --->
|
||||
[[(10,0),(0,0)]
|
||||
[(0,0),(0,0)]]
|
||||
|
||||
(G(om_)) ---> gf_view(x0,)
|
||||
|
||||
(tql::eval(G(om_), om_=0)) --->
|
||||
[[(10,0),(0,0)]
|
||||
[(0,0),(0,0)]]
|
||||
|
||||
(Gv(om_)) ---> gf_view(x0,)
|
||||
|
||||
(tql::eval(Gv(om_), om_=0)) --->
|
||||
[[(10,0),(0,0)]
|
||||
[(0,0),(0,0)]]
|
||||
|
||||
-------------lazy assign ------------------
|
||||
(G(0)) --->
|
||||
[[(2.3,3.14159),(0,0)]
|
||||
[(0,0),(2.3,3.14159)]]
|
||||
|
||||
(G(inf)) ---> tail/tail_view : Ordermin/max = -1 3
|
||||
... Order -1 =
|
||||
[[(1,0),(0,0)]
|
||||
[(0,0),(1,0)]]
|
||||
... Order 0 =
|
||||
[[(2.3,0),(0,0)]
|
||||
[(0,0),(2.3,0)]]
|
||||
... Order 1 =
|
||||
[[(0,0),(0,0)]
|
||||
[(0,0),(0,0)]]
|
||||
... Order 2 =
|
||||
[[(0,0),(0,0)]
|
||||
[(0,0),(0,0)]]
|
||||
... Order 3 =
|
||||
[[(0,0),(0,0)]
|
||||
[(0,0),(0,0)]]
|
||||
|
||||
-------------lazy assign ------------------
|
||||
(G(0)) --->
|
||||
[[(0.151719,-0.207234),(0,0)]
|
||||
[(0,0),(0.151719,-0.207234)]]
|
||||
|
||||
(G(inf)) ---> tail/tail_view : Ordermin/max = -1 3
|
||||
... Order -1 =
|
||||
[[(1,0),(0,0)]
|
||||
[(0,0),(1,0)]]
|
||||
... Order 0 =
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]]
|
||||
... Order 1 =
|
||||
[[(5.29,0),(0,0)]
|
||||
[(0,0),(5.29,0)]]
|
||||
... Order 2 =
|
||||
[[(-12.167,0),(0,0)]
|
||||
[(0,0),(-12.167,0)]]
|
||||
... Order 3 =
|
||||
[[(27.9841,0),(0,0)]
|
||||
[(0,0),(27.9841,0)]]
|
||||
|
||||
(inverse(G(inf))) ---> tail_inv_lazy
|
||||
|
||||
-------------------------------------
|
||||
(Gv(om_)) ---> gf_view(x0,)
|
||||
|
||||
(tql::eval(Gv(om_), om_=0)) --->
|
||||
[[(0.151719,-0.207234),(0,0)]
|
||||
[(0,0),(0.151719,-0.207234)]]
|
||||
|
||||
(t.order_min()) ---> -1
|
||||
|
||||
(t( 0)) --->
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]]
|
||||
|
||||
(Gv2(inf)( 0)) --->
|
||||
[[(-2.3,0)]]
|
||||
|
||||
(G( 0)) --->
|
||||
[[(0.151719,-0.207234),(0,0)]
|
||||
[(0,0),(0.151719,-0.207234)]]
|
||||
|
||||
(Gc( 0)) --->
|
||||
[[(0.151719,-0.207234),(0,0)]
|
||||
[(0,0),(0.151719,-0.207234)]]
|
||||
|
||||
(G( 0)) --->
|
||||
[[(0.151719,-0.207234),(0,0)]
|
||||
[(0,0),(0.151719,-0.207234)]]
|
||||
|
||||
(G(inf)(0)) --->
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]]
|
||||
|
||||
(( G(inf) + G(inf) ) (0)) ---> (
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]] +
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]])
|
||||
|
||||
(( G(inf) * G(inf) ) (0)) --->
|
||||
[[(15.87,0),(0,0)]
|
||||
[(0,0),(15.87,0)]]
|
||||
|
||||
((G + Gc)( inf)) ---> ( tail/tail_view : Ordermin/max = -1 3
|
||||
... Order -1 =
|
||||
[[(1,0),(0,0)]
|
||||
[(0,0),(1,0)]]
|
||||
... Order 0 =
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]]
|
||||
... Order 1 =
|
||||
[[(5.29,0),(0,0)]
|
||||
[(0,0),(5.29,0)]]
|
||||
... Order 2 =
|
||||
[[(-12.167,0),(0,0)]
|
||||
[(0,0),(-12.167,0)]]
|
||||
... Order 3 =
|
||||
[[(27.9841,0),(0,0)]
|
||||
[(0,0),(27.9841,0)]] + tail/tail_view : Ordermin/max = -1 3
|
||||
... Order -1 =
|
||||
[[(1,0),(0,0)]
|
||||
[(0,0),(1,0)]]
|
||||
... Order 0 =
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]]
|
||||
... Order 1 =
|
||||
[[(5.29,0),(0,0)]
|
||||
[(0,0),(5.29,0)]]
|
||||
... Order 2 =
|
||||
[[(-12.167,0),(0,0)]
|
||||
[(0,0),(-12.167,0)]]
|
||||
... Order 3 =
|
||||
[[(27.9841,0),(0,0)]
|
||||
[(0,0),(27.9841,0)]])
|
||||
|
||||
((t + 2.3)(0)) ---> (
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]] + (2.3,0))
|
||||
|
||||
(t(-1)) --->
|
||||
[[(1,0),(0,0)]
|
||||
[(0,0),(1,0)]]
|
||||
|
@ -48,7 +48,7 @@ int main() {
|
||||
gw_n (tau_) << 1/(tau_-1.);
|
||||
auto gt_with_full_tail = make_gf_from_inverse_fourier(make_gf_from_g_and_tail(gw_n, gw.singularity()));
|
||||
TEST(gt_with_full_tail(.5));
|
||||
triqs::gfs::local::tail t(2,2);
|
||||
triqs::gfs::tail t(2,2);
|
||||
t(1)=1;
|
||||
TEST(t);
|
||||
auto gt_tail_with_one_term = make_gf_from_inverse_fourier(make_gf_from_g_and_tail(gw_n, t));
|
||||
|
@ -14,7 +14,6 @@ namespace h5 = triqs::h5;
|
||||
|
||||
int main() {
|
||||
try {
|
||||
triqs::gfs::freq_infty inf;
|
||||
|
||||
double beta =1;
|
||||
|
||||
@ -48,15 +47,15 @@ int main() {
|
||||
|
||||
Gv(om_) << (0.2 + om_ + 2.1);
|
||||
TEST(G(0));
|
||||
TEST(G(inf));
|
||||
TEST(G.singularity());
|
||||
|
||||
std::cout <<"-------------lazy assign 2 ------------------"<<std::endl;
|
||||
|
||||
G(om_) << 1/(om_ + 2.3);
|
||||
|
||||
TEST(G(0));
|
||||
TEST(G(inf));
|
||||
TEST(inverse(G(inf)));
|
||||
TEST(G.singularity());
|
||||
TEST(inverse(G.singularity()));
|
||||
|
||||
std::cout <<"----------------- 3 --------------------"<<std::endl;
|
||||
|
||||
@ -64,12 +63,12 @@ int main() {
|
||||
TEST( eval(Gv(om_), om_=0) ) ;
|
||||
|
||||
// tail
|
||||
auto t = G(inf);
|
||||
auto t = G.singularity();
|
||||
|
||||
TEST(t.order_min());
|
||||
TEST( t( 2) ) ;
|
||||
|
||||
TEST( Gv2(inf)( 2) ) ;
|
||||
TEST( Gv2.singularity()( 2) ) ;
|
||||
|
||||
// copy
|
||||
Gc = G;
|
||||
@ -110,10 +109,10 @@ int main() {
|
||||
}
|
||||
#endif
|
||||
TEST( G( 0) ) ;
|
||||
TEST(G(inf)(2));
|
||||
TEST(G.singularity()(2));
|
||||
|
||||
TEST( ( G(inf) + G(inf) ) (2));
|
||||
TEST( ( G(inf) * G(inf) ) (4));
|
||||
TEST( ( G.singularity() + G.singularity() ) (2));
|
||||
TEST( ( G.singularity() * G.singularity() ) (4));
|
||||
|
||||
TEST( t(1));
|
||||
|
||||
|
@ -37,7 +37,7 @@
|
||||
[[(2.3,3.14159),(0,0)]
|
||||
[(0,0),(2.3,3.14159)]]
|
||||
|
||||
(G(inf)) ---> tail/tail_view: min/smallest/max = -1 -1 8
|
||||
(G.singularity()) ---> tail/tail_view: min/smallest/max = -1 -1 8
|
||||
... Order -1 =
|
||||
[[(1,0),(0,0)]
|
||||
[(0,0),(1,0)]]
|
||||
@ -74,7 +74,7 @@
|
||||
[[(0.151719,-0.207234),(0,0)]
|
||||
[(0,0),(0.151719,-0.207234)]]
|
||||
|
||||
(G(inf)) ---> tail/tail_view: min/smallest/max = -1 1 8
|
||||
(G.singularity()) ---> tail/tail_view: min/smallest/max = -1 1 8
|
||||
... Order -1 =
|
||||
[[(0,0),(0,0)]
|
||||
[(0,0),(0,0)]]
|
||||
@ -106,7 +106,7 @@
|
||||
[[(-340.483,0),(0,0)]
|
||||
[(0,0),(-340.483,0)]]
|
||||
|
||||
(inverse(G(inf))) ---> tail/tail_view: min/smallest/max = -1 -1 6
|
||||
(inverse(G.singularity())) ---> tail/tail_view: min/smallest/max = -1 -1 6
|
||||
... Order -1 =
|
||||
[[(1,0),(0,0)]
|
||||
[(0,0),(1,0)]]
|
||||
@ -145,7 +145,7 @@
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]]
|
||||
|
||||
(Gv2(inf)( 2)) --->
|
||||
(Gv2.singularity()( 2)) --->
|
||||
[[(-2.3,0)]]
|
||||
|
||||
(G( 0)) --->
|
||||
@ -165,15 +165,15 @@
|
||||
[[(0.151719,-0.207234),(0,0)]
|
||||
[(0,0),(0.151719,-0.207234)]]
|
||||
|
||||
(G(inf)(2)) --->
|
||||
(G.singularity()(2)) --->
|
||||
[[(-2.3,0),(0,0)]
|
||||
[(0,0),(-2.3,0)]]
|
||||
|
||||
(( G(inf) + G(inf) ) (2)) --->
|
||||
(( G.singularity() + G.singularity() ) (2)) --->
|
||||
[[(-4.6,0),(0,0)]
|
||||
[(0,0),(-4.6,0)]]
|
||||
|
||||
(( G(inf) * G(inf) ) (4)) --->
|
||||
(( G.singularity() * G.singularity() ) (4)) --->
|
||||
[[(15.87,0),(0,0)]
|
||||
[(0,0),(15.87,0)]]
|
||||
|
||||
|
@ -1,43 +1,71 @@
|
||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
|
||||
#include <triqs/gfs.hpp>
|
||||
#include <triqs/gfs/product.hpp>
|
||||
#include <triqs/gfs/curry.hpp>
|
||||
#include <triqs/gfs/bz.hpp>
|
||||
#include <triqs/gfs/m_tail.hpp>
|
||||
|
||||
#include <triqs/gfs/local/fourier_real.hpp>
|
||||
#include <triqs/gfs/local/fourier_matsubara.hpp>
|
||||
#include <triqs/arrays.hpp>
|
||||
|
||||
using namespace triqs::gfs;
|
||||
namespace h5 = triqs::h5;
|
||||
using namespace triqs::gfs;
|
||||
using namespace triqs::clef;
|
||||
using namespace triqs::arrays;
|
||||
using namespace triqs::lattice;
|
||||
|
||||
template<typename T>
|
||||
void assert_equal(T const& x, T const& y, std::string mess) {
|
||||
if (std::abs(x - y) > 1.e-13) TRIQS_RUNTIME_ERROR << mess;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2>
|
||||
void assert_equal_array(T1 const& x, T2 const& y, std::string mess) {
|
||||
if (max_element(abs(x - y)) > 1.e-13) TRIQS_RUNTIME_ERROR << mess << "\n" << x << "\n" << y << "\n" << max_element(abs(x - y));
|
||||
}
|
||||
|
||||
#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> " << (X) << std::endl << std::endl;
|
||||
|
||||
int main() {
|
||||
|
||||
try {
|
||||
double tmax=10;
|
||||
double wmin=0.;
|
||||
double wmax=1.0;
|
||||
int n_re_freq=100;
|
||||
int Nt=100;
|
||||
double beta = 1;
|
||||
auto bz_ = brillouin_zone{bravais_lattice{make_unit_matrix<double>(2)}};
|
||||
|
||||
triqs::clef::placeholder<0> w_;
|
||||
triqs::clef::placeholder<1> wn_;
|
||||
triqs::clef::placeholder<2> tau_;
|
||||
int n_freq = 100;
|
||||
int n_times = n_freq * 2;
|
||||
int n_bz = 50;
|
||||
auto gkw = gf<cartesian_product<bz, imfreq>>{{{bz_, n_bz}, {beta, Fermion, n_freq}}, {1, 1}};
|
||||
auto gkt = gf<cartesian_product<bz, imtime>>{{{bz_, n_bz}, {beta, Fermion, n_times}}, {1, 1}};
|
||||
|
||||
auto G_w_wn = gf<cartesian_product<refreq,refreq>, scalar_valued>( {gf_mesh<refreq>(wmin, wmax, n_re_freq), gf_mesh<refreq>(wmin, wmax, n_re_freq)});
|
||||
auto G_w_tau = gf<cartesian_product<refreq,retime>, scalar_valued>( {gf_mesh<refreq>(wmin, wmax, n_re_freq), gf_mesh<retime>(-tmax, tmax, Nt)});
|
||||
placeholder<0> k_;
|
||||
placeholder<1> w_;
|
||||
placeholder<2> wn_;
|
||||
placeholder<3> tau_;
|
||||
|
||||
G_w_wn(w_,wn_)<<1/(wn_-1)/( pow(w_,3) );
|
||||
G_w_tau(w_,tau_)<< exp( -2*tau_ ) / (w_*w_ + 1 );
|
||||
auto eps_k = -2 * (cos(k_(0)) + cos(k_(1)));
|
||||
gkw(k_, w_) << 1 / (w_ - eps_k - 1 / (w_ + 2));
|
||||
|
||||
auto G_w_wn_curry0 = curry<0>(G_w_wn);
|
||||
auto G_w_tau_curry0 = curry<0>(G_w_tau);
|
||||
auto gk_w = curry<0>(gkw);
|
||||
auto gk_t = curry<0>(gkt);
|
||||
|
||||
//for (auto const & w : G_w_wn_curry0.mesh()) G_w_wn_curry0[w] = fourier(G_w_tau_curry0[w]);
|
||||
//G_w_wn_curry0[w_] << fourier(G_w_tau_curry0[w_]);
|
||||
//curry<0>(G_w_wn) [w_] << fourier(curry<0>(G_w_tau)[w_]);
|
||||
gk_t[k_] << inverse_fourier(gk_w[k_]);
|
||||
|
||||
// works also, but uses the evaluator which return to the same point
|
||||
// gk_t(k_) << inverse_fourier(gk_w(k_));
|
||||
// check last assertion
|
||||
for (auto k : gk_t.mesh()) assert_equal(k.linear_index(), gk_t.mesh().locate_neighbours(k).linear_index(), "k location point");
|
||||
|
||||
/// Testing the result
|
||||
auto gk_w_test = gf<imfreq>{{beta, Fermion, n_freq}, {1, 1}};
|
||||
auto gk_t_test = gf<imtime>{{beta, Fermion, n_times}, {1, 1}};
|
||||
assert_equal_array(gkt.singularity().data().data, gkw.singularity().data().data, "Error 05");
|
||||
for (auto & k : std::get<0>(gkw.mesh().components())) {
|
||||
gk_w_test(w_) << 1 / (w_ - eval(eps_k, k_ = k) - 1 / (w_ + 2));
|
||||
gk_t_test() = inverse_fourier(gk_w_test);
|
||||
assert_equal_array(gk_w_test.singularity().data(), gk_w[k].singularity().data(), "Error 0");
|
||||
assert_equal_array(gk_t_test.singularity().data(), gk_t[k].singularity().data(), "Error 0s");
|
||||
assert_equal_array(gk_w_test.data(), gk_w[k].data(), "Error 1");
|
||||
assert_equal_array(gk_t_test.data(), gk_t[k].data(), "Error 2");
|
||||
}
|
||||
// temp fix : THE TEST DOES NOT RUN !!
|
||||
//TRIQS_CATCH_AND_ABORT;
|
||||
catch(std::exception const & e ) { std::cout << "error "<< e.what()<< std::endl;}
|
||||
|
||||
// hdf5
|
||||
h5::file file("ess_g_k_om.h5", H5F_ACC_TRUNC);
|
||||
h5_write(file, "g", gkw);
|
||||
}
|
||||
TRIQS_CATCH_AND_ABORT;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#define TRIQS_ARRAYS_ENFORCE_BOUNDCHECK
|
||||
#include <triqs/gfs.hpp>
|
||||
#include <triqs/gfs/bz.hpp>
|
||||
#include <triqs/gfs/m_tail.hpp>
|
||||
|
||||
namespace h5 = triqs::h5;
|
||||
using namespace triqs::gfs;
|
||||
@ -8,34 +9,79 @@ using namespace triqs::clef;
|
||||
using namespace triqs::arrays;
|
||||
using namespace triqs::lattice;
|
||||
|
||||
template<typename T1, typename T2>
|
||||
void assert_equal(T1 const& x, T2 const& y, std::string mess) {
|
||||
if (std::abs(x - y) > 1.e-13) TRIQS_RUNTIME_ERROR << mess;
|
||||
}
|
||||
|
||||
#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> " << (X) << std::endl << std::endl;
|
||||
|
||||
int main() {
|
||||
try {
|
||||
double beta = 1;
|
||||
|
||||
auto bz_ = brillouin_zone{bravais_lattice{make_unit_matrix<double>(2)}};
|
||||
auto bz_ = brillouin_zone{bravais_lattice{{{1, 0}, {0, 1}}}};
|
||||
|
||||
auto g_eps = gf<bz>{{bz_, 100}, {1, 1}};
|
||||
|
||||
// Default, with a tail.
|
||||
auto G = gf<cartesian_product<bz, imfreq>>{{{bz_, 100}, {beta, Fermion, 100}}, {1, 1}};
|
||||
|
||||
// Same : the gf_default_singularity is the same
|
||||
static_assert(std::is_same<std14::decay_t<decltype(G.singularity())>, gf<bz, tail>>::value, "!!");
|
||||
|
||||
// auto G = gf<cartesian_product<bz, imfreq>, matrix_valued, gf<bz, tail>>{{{bz_, 100}, {beta, Fermion, 100}}, {1, 1}};
|
||||
|
||||
// The variant without tail
|
||||
auto G_no_tail = gf<cartesian_product<bz, imfreq>, matrix_valued, no_tail>{{{bz_, 100}, {beta, Fermion, 100}}, {1, 1}};
|
||||
|
||||
// try to assign to expression
|
||||
placeholder<0> k_;
|
||||
placeholder<1> w_;
|
||||
|
||||
/// The calculation is 3x longer with the tail !!
|
||||
auto eps_k = -2 * (cos(k_(0)) + cos(k_(1)));
|
||||
G(k_, w_) << 1 / (w_ - eps_k - 1 / (w_ + 2));
|
||||
|
||||
// same
|
||||
// auto eps = make_expr( [](k_t const& k) { return -2 * (cos(k(0)) + cos(k(1))); }) ;
|
||||
// G(k_, w_) << 1 / (w_ - eps(k_) - 1 / (w_ + 2));
|
||||
//G_no_tail(k_, w_) << 1 / (w_ - eps_k - 1 / (w_ + 2));
|
||||
//return 0;
|
||||
|
||||
if (0) { // to check speed of computation, which is long due to tail (inversion ?)
|
||||
auto t = tail_omega(1, 1);
|
||||
auto t2 = t;
|
||||
for (int u = 0; u < 10000; ++u) {
|
||||
t2 = (t + u - inverse(t - u));
|
||||
//t2 = inverse(t + u - inverse(t - u));
|
||||
}
|
||||
}
|
||||
|
||||
for (auto k : std::get<0>(G.mesh().components())) {
|
||||
assert_equal(G.singularity()[k](1)(0, 0), 1, "should be 1/omega");
|
||||
assert_equal(G.singularity()[k](2)(0, 0), eval(eps_k, k_ = k), "should be eps_k/omega^2");
|
||||
}
|
||||
|
||||
auto gk = curry<0>(G);
|
||||
|
||||
std::cerr << G.singularity()[{0, 0, 0}] << std::endl;
|
||||
std::cerr << gk[{0, 0, 0}].singularity() << std::endl;
|
||||
|
||||
if (1) {
|
||||
|
||||
for (auto k : gk.mesh()) {
|
||||
// std::cout << k << std::endl;
|
||||
auto p = gk[k];
|
||||
assert_equal(gk[k].singularity()(1)(0, 0), 1, "should be 1/omega");
|
||||
assert_equal(gk[k].singularity()(2)(0, 0), eval(eps_k, k_ = k), "should be eps_k/omega^2");
|
||||
}
|
||||
|
||||
for (auto k : gk.mesh()) {
|
||||
auto p = partial_eval<0>(G, 0);
|
||||
assert_equal(gk[k].singularity()(1)(0, 0), 1, "should be 1/omega");
|
||||
assert_equal(gk[k].singularity()(2)(0, 0), eval(eps_k, k_ = k), "should be eps_k/omega^2");
|
||||
}
|
||||
}
|
||||
// hdf5
|
||||
h5::file file("ess_g_k_om.h5", H5F_ACC_TRUNC);
|
||||
h5_write(file, "g", G);
|
||||
|
||||
|
||||
}
|
||||
TRIQS_CATCH_AND_ABORT;
|
||||
}
|
||||
|
@ -44,10 +44,9 @@ int main() {
|
||||
|
||||
G_k_iom(k_, w_) << 1 / (w_ - eps(k_));
|
||||
|
||||
|
||||
auto G_loc = gf<imfreq, matrix_valued, no_tail>{{beta, Fermion, 100}, {1, 1}};
|
||||
|
||||
auto r = G_k_iom(k_t{0, 0}, matsubara_freq{0, beta, Fermion});
|
||||
auto r = G_k_iom(k_t{0, 0, 0}, matsubara_freq{0, beta, Fermion});
|
||||
|
||||
auto r5 = sum_gf(k_ >> G_k_iom(k_,0), g_eps.mesh());
|
||||
G_loc(w_) << sum_gf(k_ >> G_k_iom(k_,w_), g_eps.mesh());
|
||||
|
@ -8,7 +8,6 @@ using namespace triqs::gfs;
|
||||
using namespace triqs::clef;
|
||||
using namespace triqs::arrays;
|
||||
using namespace triqs::lattice;
|
||||
using local::tail;
|
||||
|
||||
#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> " << (X) << std::endl << std::endl;
|
||||
|
||||
@ -17,24 +16,17 @@ using local::tail;
|
||||
int main() {
|
||||
try {
|
||||
double beta = 1;
|
||||
|
||||
auto bz_ = brillouin_zone{bravais_lattice{make_unit_matrix<double>(2)}};
|
||||
|
||||
auto t = tail{1,1};
|
||||
auto G = gf<bz, tail>{{bz_, 100}};
|
||||
auto G = gf<bz, tail>{{bz_, 100}, {1,1}};
|
||||
|
||||
// try to assign to expression
|
||||
placeholder<0> k_;
|
||||
placeholder<1> w_;
|
||||
auto eps = make_expr( [](k_t const& k) { return -2 * (cos(k(0)) + cos(k(1))); }) ;
|
||||
G(k_) << -2 * (cos(k_(0)) + cos(k_(1))) * t;
|
||||
|
||||
G(k_) << eps(k_) * t;
|
||||
|
||||
// hdf5
|
||||
h5::file file("ess_g_k_tail.h5", H5F_ACC_TRUNC );
|
||||
h5_write(file, "g", G);
|
||||
|
||||
|
||||
}
|
||||
TRIQS_CATCH_AND_ABORT;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
using triqs::arrays::make_shape;
|
||||
using namespace triqs::gfs;
|
||||
using triqs::gfs::local::tail;
|
||||
using triqs::gfs::tail;
|
||||
#define TEST(X) std::cout << BOOST_PP_STRINGIZE((X)) << " ---> "<< (X) <<std::endl<<std::endl;
|
||||
void test_0(){
|
||||
|
||||
|
@ -1,23 +0,0 @@
|
||||
#include <iostream>
|
||||
|
||||
struct infty {};
|
||||
|
||||
template<typename T> struct wrap {
|
||||
T x;
|
||||
wrap(T const & x_): x(x_) {}
|
||||
operator infty() const { return infty();}
|
||||
operator T () const { return x;}
|
||||
};
|
||||
|
||||
|
||||
double g(infty) { return 3;}
|
||||
double f(double) { return 30;}
|
||||
|
||||
int main() {
|
||||
|
||||
wrap<double> w(2);
|
||||
std::cout << w +1 <<std::endl;
|
||||
std::cout << g(w) <<std::endl;
|
||||
std::cout << f(w) <<std::endl;
|
||||
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
3
|
||||
3
|
||||
30
|
@ -18,9 +18,9 @@
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_ARRAYS_ALL_H
|
||||
#define TRIQS_ARRAYS_ALL_H
|
||||
#pragma once
|
||||
|
||||
// for python code generator, we need to know what to include...
|
||||
#define TRIQS_ARRAYS_INCLUDED
|
||||
|
||||
// The basic classes
|
||||
@ -31,6 +31,7 @@
|
||||
//
|
||||
#include <triqs/arrays/functional/map.hpp>
|
||||
#include <triqs/arrays/mapped_functions.hpp>
|
||||
#include <triqs/arrays/algorithms.hpp>
|
||||
|
||||
#include <triqs/arrays/functional/fold.hpp>
|
||||
#include <triqs/arrays/algorithms.hpp>
|
||||
@ -42,7 +43,6 @@
|
||||
#include <triqs/arrays/group_indices.hpp>
|
||||
|
||||
// Linear algebra ?? Keep here ?
|
||||
//#include <triqs/arrays/linalg/det_and_inverse.hpp>
|
||||
#include <triqs/arrays/linalg/det_and_inverse.hpp>
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -69,18 +69,14 @@ namespace gfs {
|
||||
|
||||
// ------------------------------- Factories --------------------------------------------------
|
||||
|
||||
template <typename Target> struct factories<block_index, Target, nothing, void> {
|
||||
template <typename Target> struct data_factory<block_index, Target, nothing, void> {
|
||||
using mesh_t = gf_mesh<block_index>;
|
||||
using gf_t = gf<block_index, Target>;
|
||||
using gf_view_t = gf_view<block_index, Target>;
|
||||
using aux_t = nothing;
|
||||
|
||||
struct target_shape_t {};
|
||||
|
||||
static typename gf_t::data_t make_data(mesh_t const &m, target_shape_t, aux_t) { return std::vector<Target>(m.size()); }
|
||||
static typename gf_t::singularity_t make_singularity(mesh_t const &m, target_shape_t) {
|
||||
return {};
|
||||
}
|
||||
static typename gf_t::data_t make(mesh_t const &m, target_shape_t, aux_t) { return std::vector<Target>(m.size()); }
|
||||
};
|
||||
|
||||
} // gfs_implementation
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2012-2013 by O. Parcollet
|
||||
* Copyright (C) 2014 by O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
@ -22,7 +22,8 @@
|
||||
#include "./tools.hpp"
|
||||
#include "./gf.hpp"
|
||||
#include "./local/tail.hpp"
|
||||
#include "../lattice/bz_mesh.hpp"
|
||||
#include "./domains/R.hpp"
|
||||
#include "../lattice/regular_bz_mesh.hpp"
|
||||
#include "./evaluators.hpp"
|
||||
|
||||
namespace triqs {
|
||||
@ -30,8 +31,8 @@ namespace gfs {
|
||||
|
||||
struct bz {};
|
||||
|
||||
template <typename Opt> struct gf_mesh<bz, Opt> : lattice::bz_mesh {
|
||||
template <typename... T> gf_mesh(T &&... x) : lattice::bz_mesh(std::forward<T>(x)...) {}
|
||||
template <typename Opt> struct gf_mesh<bz, Opt> : lattice::regular_bz_mesh {
|
||||
template <typename... T> gf_mesh(T &&... x) : lattice::regular_bz_mesh(std::forward<T>(x)...) {}
|
||||
};
|
||||
|
||||
namespace gfs_implementation {
|
||||
@ -49,25 +50,23 @@ namespace gfs {
|
||||
|
||||
// simple evaluation : take the point on the grid...
|
||||
template <> struct evaluator_fnt_on_mesh<bz> {
|
||||
// lattice::regular_bz_mesh::index_t n;
|
||||
size_t n;
|
||||
evaluator_fnt_on_mesh() = default;
|
||||
template <typename MeshType> evaluator_fnt_on_mesh(MeshType const &m, lattice::k_t const &k) {
|
||||
n = m.locate_neighbours(k); // TO BE IMPROVED
|
||||
// n = m.locate_neighbours(k).index();
|
||||
n = m.locate_neighbours(k).linear_index();
|
||||
}
|
||||
template <typename F> auto operator()(F const &f) const DECL_AND_RETURN(f(n));
|
||||
template <typename F> AUTO_DECL operator()(F const &f) const RETURN(f(n));
|
||||
// template <typename F> decltype(auto) operator()(F const &f) const { return f(n); }
|
||||
};
|
||||
|
||||
// ------------- evaluator -------------------
|
||||
// handle the case where the matsu. freq is out of grid...
|
||||
// --------------------------------------------------------------
|
||||
template <typename Target, typename Singularity, typename Opt> struct evaluator<bz, Target, Singularity, Opt> {
|
||||
static constexpr int arity = 1;
|
||||
|
||||
template <typename G>
|
||||
std::c14::conditional_t<std::is_same<Target, matrix_valued>::value, arrays::matrix_const_view<std::complex<double>>,
|
||||
std::complex<double>>
|
||||
operator()(G const *g, lattice::k_t const &k) const {
|
||||
auto n = g->mesh().locate_neighbours(k); // TO BE IMPROVED
|
||||
template <typename G> auto operator()(G const *g, lattice::k_t const &k) const {
|
||||
auto n = g->mesh().locate_neighbours(k);
|
||||
return (*g)[n];
|
||||
}
|
||||
};
|
||||
|
78
triqs/gfs/bz1.hpp
Normal file
78
triqs/gfs/bz1.hpp
Normal file
@ -0,0 +1,78 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2012-2013 by O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "./tools.hpp"
|
||||
#include "./gf.hpp"
|
||||
#include "./local/tail.hpp"
|
||||
#include "./domains/R.hpp"
|
||||
#include "../lattice/bz_mesh.hpp"
|
||||
#include "./evaluators.hpp"
|
||||
|
||||
namespace triqs {
|
||||
namespace gfs {
|
||||
|
||||
struct bz {};
|
||||
|
||||
template <typename Opt> struct gf_mesh<bz, Opt> : lattice::bz_mesh {
|
||||
template <typename... T> gf_mesh(T &&... x) : lattice::bz_mesh(std::forward<T>(x)...) {}
|
||||
};
|
||||
|
||||
namespace gfs_implementation {
|
||||
|
||||
// h5 name
|
||||
template <typename Singularity, typename Opt> struct h5_name<bz, matrix_valued, Singularity, Opt> {
|
||||
static std::string invoke() { return "BZ"; }
|
||||
};
|
||||
|
||||
/// --------------------------- data access ---------------------------------
|
||||
template <typename Opt> struct data_proxy<bz, matrix_valued, Opt> : data_proxy_array<std::complex<double>, 3> {};
|
||||
template <typename Opt> struct data_proxy<bz, scalar_valued, Opt> : data_proxy_array<std::complex<double>, 1> {};
|
||||
|
||||
/// --------------------------- evaluator ---------------------------------
|
||||
|
||||
// simple evaluation : take the point on the grid...
|
||||
template <> struct evaluator_fnt_on_mesh<bz> {
|
||||
size_t n;
|
||||
evaluator_fnt_on_mesh() = default;
|
||||
template <typename MeshType> evaluator_fnt_on_mesh(MeshType const &m, lattice::k_t const &k) {
|
||||
n = m.locate_neighbours(k); // TO BE IMPROVED
|
||||
}
|
||||
template <typename F> auto operator()(F const &f) const DECL_AND_RETURN(f(n));
|
||||
//template <typename F> decltype(auto) operator()(F const &f) const { return f(n); }
|
||||
};
|
||||
|
||||
// ------------- evaluator -------------------
|
||||
// handle the case where the matsu. freq is out of grid...
|
||||
template <typename Target, typename Singularity, typename Opt> struct evaluator<bz, Target, Singularity, Opt> {
|
||||
static constexpr int arity = 1;
|
||||
|
||||
template <typename G>
|
||||
std::c14::conditional_t<std::is_same<Target, matrix_valued>::value, arrays::matrix_const_view<std::complex<double>>,
|
||||
std::complex<double>>
|
||||
operator()(G const *g, lattice::k_t const &k) const {
|
||||
auto n = g->mesh().locate_neighbours(k); // TO BE IMPROVED
|
||||
return (*g)[n];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ namespace triqs { namespace gfs {
|
||||
/// --------------------------- Factories ---------------------------------
|
||||
|
||||
template<typename F, typename Opt, typename ... Ms>
|
||||
struct factories<cartesian_product<Ms...>, lambda_valued<F>, nothing, Opt> {};
|
||||
struct data_factory<cartesian_product<Ms...>, lambda_valued<F>, nothing, Opt> {};
|
||||
|
||||
/// --------------------------- partial_eval ---------------------------------
|
||||
// partial_eval<0> (g, 1) returns : x -> g(1,x)
|
||||
|
74
triqs/gfs/cyclic_lattice.hpp
Normal file
74
triqs/gfs/cyclic_lattice.hpp
Normal file
@ -0,0 +1,74 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2014 by O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "./tools.hpp"
|
||||
#include "./gf.hpp"
|
||||
#include "./local/tail.hpp"
|
||||
#include "./domains/R.hpp"
|
||||
#include "../lattice/cyclic_lattice.hpp"
|
||||
#include "./evaluators.hpp"
|
||||
|
||||
namespace triqs {
|
||||
namespace gfs {
|
||||
|
||||
struct cyclic_lattice {};
|
||||
|
||||
template <typename Opt> struct gf_mesh<cyclic_lattice, Opt> : lattice::cyclic_lattice_mesh {
|
||||
template <typename... T> gf_mesh(T &&... x) : lattice::cyclic_lattice_mesh(std::forward<T>(x)...) {}
|
||||
};
|
||||
|
||||
namespace gfs_implementation {
|
||||
|
||||
// h5 name
|
||||
template <typename Singularity, typename Opt> struct h5_name<cyclic_lattice, matrix_valued, Singularity, Opt> {
|
||||
static std::string invoke() { return "R"; }
|
||||
};
|
||||
|
||||
/// --------------------------- data access ---------------------------------
|
||||
template <typename Opt> struct data_proxy<cyclic_lattice, matrix_valued, Opt> : data_proxy_array<std::complex<double>, 3> {};
|
||||
template <typename Opt> struct data_proxy<cyclic_lattice, scalar_valued, Opt> : data_proxy_array<std::complex<double>, 1> {};
|
||||
|
||||
/// --------------------------- evaluator ---------------------------------
|
||||
|
||||
// simple evaluation : take the point on the grid...
|
||||
template <> struct evaluator_fnt_on_mesh<cyclic_lattice> {
|
||||
size_t n;
|
||||
evaluator_fnt_on_mesh() = default;
|
||||
template <typename MeshType, typename R> evaluator_fnt_on_mesh(MeshType const &m, R const &r) {
|
||||
n = m.modulo_reduce(r).linear_index();
|
||||
}
|
||||
template <typename F> AUTO_DECL operator()(F const &f) const RETURN(f(n));
|
||||
//template <typename F> decltype(auto) operator()(F const &f) const { return f(n); }
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------
|
||||
template <typename Target, typename Singularity, typename Opt> struct evaluator<cyclic_lattice, Target, Singularity, Opt> {
|
||||
static constexpr int arity = 1;
|
||||
|
||||
template <typename G, typename R> auto operator()(G const *g, R const &r) const {
|
||||
auto n = g->mesh().modulo_reduce(r);
|
||||
return (*g)[n];
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,8 +70,9 @@ namespace gfs {
|
||||
evaluator_one_var() = default;
|
||||
template <typename G>
|
||||
auto operator()(G const *g, double x) const DECL_AND_RETURN(evaluator_fnt_on_mesh<Variable>(g -> mesh(), x)(on_mesh(*g)));
|
||||
template <typename G> typename G::singularity_t const &operator()(G const *g, freq_infty const &) const {
|
||||
return g->singularity();
|
||||
|
||||
template <typename G> typename G::singularity_t operator()(G const *g, tail_view t) const {
|
||||
return compose(g->singularity(), t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ namespace gfs {
|
||||
using arrays::array_view;
|
||||
using arrays::matrix;
|
||||
using arrays::matrix_view;
|
||||
using arrays::matrix_const_view;
|
||||
using triqs::make_clone;
|
||||
|
||||
// The default target, for each Variable.
|
||||
@ -111,8 +112,9 @@ namespace gfs {
|
||||
template <typename Variable, typename Target, typename Singularity, typename Opt> struct h5_name; // value is a const char
|
||||
template <typename Variable, typename Target, typename Singularity, typename Opt> struct h5_rw;
|
||||
|
||||
// factories regroup all factories (constructors..) for all types of gf. Defaults implemented below.
|
||||
template <typename Variable, typename Target, typename Singularity, typename Opt> struct factories;
|
||||
// factories (constructors..) for all types of gf. Defaults implemented below.
|
||||
template <typename Variable, typename Target, typename Singularity, typename Opt> struct data_factory;
|
||||
template <typename Variable, typename Target, typename Singularity, typename Opt> struct singularity_factory;
|
||||
|
||||
} // gfs_implementation
|
||||
|
||||
@ -156,6 +158,7 @@ namespace gfs {
|
||||
using domain_t = typename mesh_t::domain_t;
|
||||
using mesh_point_t = typename mesh_t::mesh_point_t;
|
||||
using mesh_index_t = typename mesh_t::index_t;
|
||||
using linear_mesh_index_t = typename mesh_t::linear_index_t;
|
||||
using symmetry_t = typename gfs_implementation::symmetry<Variable, Target, Singularity, Opt>::type;
|
||||
using indices_t = typename gfs_implementation::indices<Target, Opt>::type;
|
||||
using evaluator_t = gfs_implementation::evaluator<Variable, Target, Singularity, Opt>;
|
||||
@ -166,12 +169,11 @@ namespace gfs {
|
||||
using data_const_view_t = typename data_proxy_t::storage_const_view_t;
|
||||
using data_t = std14::conditional_t<IsView, std14::conditional_t<IsConst, data_const_view_t, data_view_t>, data_regular_t>;
|
||||
|
||||
//using singularity_non_view_t = typename gfs_implementation::singularity<Variable, Target, Opt>::type;
|
||||
using singularity_non_view_t = Singularity;
|
||||
using singularity_view_t = typename view_type_if_exists_else_type<singularity_non_view_t>::type;
|
||||
using singularity_t = std14::conditional_t<IsView, singularity_view_t, singularity_non_view_t>;
|
||||
|
||||
//using is_container_t = void; // a tag to recognize the container
|
||||
using singularity_regular_t = typename Singularity::regular_type;
|
||||
using singularity_view_t = typename Singularity::view_type;
|
||||
using singularity_const_view_t = typename Singularity::const_view_type;
|
||||
using singularity_t = std14::conditional_t<IsView, std14::conditional_t<IsConst, singularity_const_view_t, singularity_view_t>,
|
||||
singularity_regular_t>;
|
||||
|
||||
mesh_t const &mesh() const { return _mesh; }
|
||||
domain_t const &domain() const { return _mesh.domain(); }
|
||||
@ -314,6 +316,15 @@ namespace gfs {
|
||||
}
|
||||
|
||||
/// --------------------- A direct access to the grid point --------------------------
|
||||
|
||||
template <typename... Args> r_type get_from_linear_index(Args &&... args) {
|
||||
return _data_proxy(_data, linear_mesh_index_t(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <typename... Args> cr_type get_from_linear_index(Args &&... args) const {
|
||||
return _data_proxy(_data, linear_mesh_index_t(std::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
template <typename... Args> r_type on_mesh(Args &&... args) {
|
||||
return _data_proxy(_data, _mesh.index_to_linear(mesh_index_t(std::forward<Args>(args)...)));
|
||||
}
|
||||
@ -391,10 +402,9 @@ namespace gfs {
|
||||
template <typename RHS, typename Variable, typename Target, typename Singularity, typename Opt, bool IsView>
|
||||
void triqs_clef_auto_assign(gf_impl<Variable, Target, Singularity, Opt, IsView, false> &g, RHS const &rhs) {
|
||||
triqs_clef_auto_assign_impl(g, rhs, typename std::is_base_of<tag::composite, gf_mesh<Variable, Opt>>::type());
|
||||
assign_from_expression(g.singularity(), rhs);
|
||||
assign_singularity_from_function(g.singularity(), rhs);
|
||||
// access to the data . Beware, we view it as a *matrix* NOT an array... (crucial for assignment to scalars !)
|
||||
// if f is an expression, replace the placeholder with a simple tail. If f is a function callable on freq_infty,
|
||||
// it uses the fact that tail_non_view_t can be casted into freq_infty
|
||||
// if f is an expression, replace the placeholder with a simple tail.
|
||||
}
|
||||
|
||||
// enable the writing g[om_] << .... also
|
||||
@ -436,7 +446,8 @@ namespace gfs {
|
||||
|
||||
template <typename Variable, typename Target, typename Singularity, typename Opt> class gf : public gf_impl<Variable, Target, Singularity, Opt, false, false> {
|
||||
using B = gf_impl<Variable, Target, Singularity, Opt, false, false>;
|
||||
using factory = gfs_implementation::factories<Variable, Target, Singularity, Opt>;
|
||||
using data_factory = gfs_implementation::data_factory<Variable, Target, Singularity, Opt>;
|
||||
using singularity_factory = gfs_implementation::singularity_factory<Variable, Target, Singularity, Opt>;
|
||||
|
||||
public:
|
||||
gf() : B() {}
|
||||
@ -458,12 +469,12 @@ namespace gfs {
|
||||
typename B::indices_t const &ind, std::string name = "")
|
||||
: B(std::move(m), std::move(dat), si, s, ind, name, typename B::evaluator_t{}) {}
|
||||
|
||||
using target_shape_t = typename factory::target_shape_t;
|
||||
using target_shape_t = typename data_factory::target_shape_t;
|
||||
|
||||
// with aux, and indices
|
||||
gf(typename B::mesh_t m, target_shape_t shape, typename factory::aux_t aux,
|
||||
gf(typename B::mesh_t m, target_shape_t shape, typename data_factory::aux_t aux,
|
||||
typename B::indices_t const &ind = typename B::indices_t{}, std::string name = "")
|
||||
: B(std::move(m), factory::make_data(m, shape, aux), factory::make_singularity(m, shape), typename B::symmetry_t{}, ind,
|
||||
: B(std::move(m), data_factory::make(m, shape, aux), singularity_factory::make(m, shape), typename B::symmetry_t{}, ind,
|
||||
name, // clean unncessary types
|
||||
typename B::evaluator_t{}) {
|
||||
if (this->_indices.is_empty()) this->_indices = typename B::indices_t(shape);
|
||||
@ -472,7 +483,7 @@ namespace gfs {
|
||||
// without the aux (defaulted)
|
||||
gf(typename B::mesh_t m, target_shape_t shape = target_shape_t{}, typename B::indices_t const &ind = typename B::indices_t{},
|
||||
std::string name = "")
|
||||
: B(std::move(m), factory::make_data(m, shape, typename factory::aux_t{}), factory::make_singularity(m, shape),
|
||||
: B(std::move(m), data_factory::make(m, shape, typename data_factory::aux_t{}), singularity_factory::make(m, shape),
|
||||
typename B::symmetry_t{}, ind, name, // clean unncessary types
|
||||
typename B::evaluator_t{}) {
|
||||
if (this->_indices.is_empty()) this->_indices = typename B::indices_t(shape);
|
||||
@ -800,7 +811,7 @@ namespace gfs {
|
||||
}
|
||||
|
||||
template <typename Variable, typename Singularity, typename Opt, typename T>
|
||||
gf<Variable, matrix_valued, Singularity, Opt> L_G_R(matrix<T> l, gf<Variable, matrix_valued, Singularity, Opt> g, matrix<T> r) {
|
||||
gf<Variable, matrix_valued, Singularity, Opt> L_G_R(matrix<T> l, gf_view<Variable, matrix_valued, Singularity, Opt> g, matrix<T> r) {
|
||||
auto res = gf<Variable, matrix_valued, Singularity, Opt>{g.mesh(), {int(first_dim(l)), int(second_dim(r))}};
|
||||
res.data() = _gf_data_mul_LR(l, g.data(), r);
|
||||
res.singularity() = l * g.singularity() * r;
|
||||
@ -811,31 +822,35 @@ namespace gfs {
|
||||
|
||||
// ------------------------- default factories ---------------------
|
||||
|
||||
template <typename Var, typename Target, int VarDim, typename Singularity, typename Opt> struct factories_default_impl {
|
||||
// Factory for the data
|
||||
template <typename Var, typename Target, int VarDim, typename Singularity, typename Opt> struct data_factory_default_impl {
|
||||
using gf_t = gf<Var, Target, Singularity, Opt>;
|
||||
using target_shape_t = arrays::mini_vector<int, VarDim>;
|
||||
using mesh_t = typename gf_t::mesh_t;
|
||||
using aux_t = arrays::memory_layout< get_n_variables(Var{}) + VarDim>;
|
||||
//
|
||||
static typename gf_t::data_t make_data(mesh_t const &m, target_shape_t shape, aux_t ml) {
|
||||
static typename gf_t::data_t make(mesh_t const &m, target_shape_t shape, aux_t ml) {
|
||||
typename gf_t::data_t A(gf_t::data_proxy_t::join_shape(m.size_of_components(), shape), ml);
|
||||
A() = 0;
|
||||
return A;
|
||||
}
|
||||
//
|
||||
static typename gf_t::singularity_t make_singularity(mesh_t const &m, target_shape_t shape) {
|
||||
return typename gf_t::singularity_t{shape};
|
||||
}
|
||||
};
|
||||
|
||||
template <int R, typename Var, typename Singularity, typename Opt>
|
||||
struct factories<Var, tensor_valued<R>, Singularity, Opt> : factories_default_impl<Var, tensor_valued<R>, R, Singularity, Opt> {};
|
||||
struct data_factory<Var, tensor_valued<R>, Singularity, Opt> : data_factory_default_impl<Var, tensor_valued<R>, R, Singularity, Opt> {};
|
||||
|
||||
template <typename Var, typename Singularity, typename Opt>
|
||||
struct factories<Var, matrix_valued, Singularity, Opt> : factories_default_impl<Var, matrix_valued, 2, Singularity, Opt> {};
|
||||
struct data_factory<Var, matrix_valued, Singularity, Opt> : data_factory_default_impl<Var, matrix_valued, 2, Singularity, Opt> {};
|
||||
|
||||
template <typename Var, typename Singularity, typename Opt>
|
||||
struct factories<Var, scalar_valued, Singularity, Opt> : factories_default_impl<Var, scalar_valued, 0, Singularity, Opt> {};
|
||||
struct data_factory<Var, scalar_valued, Singularity, Opt> : data_factory_default_impl<Var, scalar_valued, 0, Singularity, Opt> {};
|
||||
|
||||
// Factory for the singularity
|
||||
template <typename Var, typename Target, typename Singularity, typename Opt> struct singularity_factory {
|
||||
template <typename TargetShape> static Singularity make(gf_mesh<Var, Opt> const &m, TargetShape shape) {
|
||||
return Singularity{shape};
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------- hdf5 ---------------------------------------
|
||||
// scalar function : just add a _s
|
||||
|
@ -37,10 +37,10 @@ namespace gfs {
|
||||
|
||||
// singularity
|
||||
template <> struct gf_default_singularity<imfreq, matrix_valued> {
|
||||
using type = local::tail;
|
||||
using type = tail;
|
||||
};
|
||||
template <> struct gf_default_singularity<imfreq, scalar_valued> {
|
||||
using type = local::tail;
|
||||
using type = tail;
|
||||
};
|
||||
|
||||
namespace gfs_implementation {
|
||||
@ -68,7 +68,7 @@ namespace gfs {
|
||||
if ((p.n >= m.first_index()) && (p.n < m.size()+m.first_index())) {w=1; n =p.n;}
|
||||
else {w=0; n=0;}
|
||||
}
|
||||
template <typename F> auto operator()(F const &f) const DECL_AND_RETURN(w*f(n));
|
||||
template <typename F> AUTO_DECL operator()(F const &f) const RETURN(w*f(n));
|
||||
};
|
||||
|
||||
// ------------- evaluator -------------------
|
||||
@ -83,14 +83,15 @@ namespace gfs {
|
||||
AUTO_DECL operator()(G const *g, int n) const
|
||||
RETURN((*g)(matsubara_freq(n, g->mesh().domain().beta, g->mesh().domain().statistic)));
|
||||
|
||||
template <typename G> typename G::singularity_t const &operator()(G const *g, freq_infty const &) const {
|
||||
return g->singularity();
|
||||
template <typename G> typename G::singularity_t operator()(G const *g, tail_view t) const {
|
||||
return compose(g->singularity(),t);
|
||||
//return g->singularity();
|
||||
}
|
||||
};
|
||||
// --- various 4 specializations
|
||||
|
||||
// scalar_valued, tail
|
||||
template <typename Opt> struct evaluator<imfreq, scalar_valued, local::tail, Opt> : _eval_imfreq_base_impl {
|
||||
template <typename Opt> struct evaluator<imfreq, scalar_valued, tail, Opt> : _eval_imfreq_base_impl {
|
||||
|
||||
using _eval_imfreq_base_impl::operator();
|
||||
|
||||
@ -101,7 +102,7 @@ namespace gfs {
|
||||
} else {
|
||||
if ((f.n >= g->mesh().first_index()) && (f.n < g->mesh().size() + g->mesh().first_index())) return (*g)[f.n];
|
||||
}
|
||||
return g->singularity().evaluate(f)(0, 0);
|
||||
return evaluate(g->singularity(),f)(0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
@ -122,7 +123,7 @@ namespace gfs {
|
||||
};
|
||||
|
||||
// matrix_valued, tail
|
||||
template <typename Opt> struct evaluator<imfreq, matrix_valued, local::tail, Opt> : _eval_imfreq_base_impl {
|
||||
template <typename Opt> struct evaluator<imfreq, matrix_valued, tail, Opt> : _eval_imfreq_base_impl {
|
||||
|
||||
using _eval_imfreq_base_impl::operator();
|
||||
|
||||
@ -134,7 +135,7 @@ namespace gfs {
|
||||
} else {
|
||||
if ((f.n >= g->mesh().first_index()) && (f.n < g->mesh().size() + g->mesh().first_index())) return (*g)[f.n];
|
||||
}
|
||||
return g->singularity().evaluate(f);
|
||||
return evaluate(g->singularity(), f);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -39,10 +39,10 @@ namespace gfs {
|
||||
|
||||
// singularity
|
||||
template <> struct gf_default_singularity<imtime, matrix_valued> {
|
||||
using type = local::tail;
|
||||
using type = tail;
|
||||
};
|
||||
template <> struct gf_default_singularity<imtime, scalar_valued> {
|
||||
using type = local::tail;
|
||||
using type = tail;
|
||||
};
|
||||
|
||||
namespace gfs_implementation {
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include "./fit_tail.hpp"
|
||||
namespace triqs { namespace gfs { namespace local {
|
||||
namespace triqs { namespace gfs {
|
||||
|
||||
tail fit_tail_impl(gf_view<imfreq> gf, const tail_view known_moments, int n_moments, int n_min, int n_max) {
|
||||
|
||||
@ -44,7 +44,7 @@ namespace triqs { namespace gfs { namespace local {
|
||||
B(k, 0) = imag(gf.data()(gf.mesh().index_to_linear(n), i, j));
|
||||
// subtract known tail if present
|
||||
if (known_moments.size() > 0)
|
||||
B(k, 0) -= imag(slice_target(known_moments, arrays::range(i, i + 1), arrays::range(j, j + 1)).evaluate(iw)(0, 0));
|
||||
B(k, 0) -= imag(evaluate(slice_target(known_moments, arrays::range(i, i + 1), arrays::range(j, j + 1)), iw)(0, 0));
|
||||
|
||||
for (int l = 0; l < size_odd; l++) {
|
||||
int order = omin_odd + 2 * l;
|
||||
@ -67,7 +67,7 @@ namespace triqs { namespace gfs { namespace local {
|
||||
B(k, 0) = real(gf.data()(gf.mesh().index_to_linear(n), i, j));
|
||||
// subtract known tail if present
|
||||
if (known_moments.size() > 0)
|
||||
B(k, 0) -= real(slice_target(known_moments, arrays::range(i, i + 1), arrays::range(j, j + 1)).evaluate(iw)(0, 0));
|
||||
B(k, 0) -= real(evaluate(slice_target(known_moments, arrays::range(i, i + 1), arrays::range(j, j + 1)), iw)(0, 0));
|
||||
|
||||
for (int l = 0; l < size_even; l++) {
|
||||
int order = omin_even + 2 * l;
|
||||
@ -81,7 +81,7 @@ namespace triqs { namespace gfs { namespace local {
|
||||
}
|
||||
}
|
||||
}
|
||||
res.mask_view()=n_moments;
|
||||
res.mask()()=n_moments;
|
||||
return res; // return tail
|
||||
}
|
||||
|
||||
@ -92,7 +92,7 @@ namespace triqs { namespace gfs { namespace local {
|
||||
if (replace_by_fit) { // replace data in the fitting range by the values from the fitted tail
|
||||
int i = 0;
|
||||
for (auto iw : gf.mesh()) { // (arrays::range(n_min,n_max+1)) {
|
||||
if (i >= n_min) gf[iw] = gf.singularity().evaluate(iw);
|
||||
if (i >= n_min) gf[iw] = evaluate(gf.singularity(),iw);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
@ -109,4 +109,4 @@ namespace triqs { namespace gfs { namespace local {
|
||||
fit_tail(reinterpret_scalar_valued_gf_as_matrix_valued(gf), known_moments, n_moments, n_min, n_max, replace_by_fit );
|
||||
}
|
||||
|
||||
}}} // namespace
|
||||
}} // namespace
|
||||
|
@ -24,14 +24,12 @@
|
||||
#include <triqs/gfs/local/tail.hpp>
|
||||
#include <triqs/arrays/blas_lapack/gelss.hpp>
|
||||
|
||||
namespace triqs { namespace gfs { namespace local {
|
||||
namespace triqs { namespace gfs {
|
||||
|
||||
using triqs::gfs::imfreq;
|
||||
using triqs::gfs::block_index;
|
||||
using triqs::gfs::block_index;
|
||||
|
||||
namespace tgl = triqs::gfs::local;
|
||||
|
||||
// routine for fitting the tail (singularity) of a Matsubara Green's function
|
||||
// this is a *linear* least squares problem (with non-linear basis functions)
|
||||
// which is solved by singular value decomposition of the design matrix
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2011 by M. Ferrero, O. Parcollet
|
||||
* Copyright (C) 2011-2014 by M. Ferrero, O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
@ -18,28 +18,42 @@
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#ifndef TRIQS_GF_LOCAL_FOURIER_BASE_H
|
||||
#define TRIQS_GF_LOCAL_FOURIER_BASE_H
|
||||
#pragma once
|
||||
#include <triqs/arrays/vector.hpp>
|
||||
#include <triqs/gfs/gf.hpp>
|
||||
|
||||
namespace triqs { namespace gfs {
|
||||
|
||||
namespace details {
|
||||
|
||||
namespace tqa = triqs::arrays;
|
||||
typedef std::complex<double> dcomplex;
|
||||
using dcomplex = std::complex<double>;
|
||||
|
||||
void fourier_base(const tqa::vector<dcomplex> &in, tqa::vector<dcomplex> &out, size_t L, bool direct);
|
||||
void fourier_base(const tqa::vector<dcomplex> &in, tqa::vector<dcomplex> &out, size_t L1, size_t L2, bool direct);
|
||||
|
||||
}
|
||||
|
||||
namespace tags { struct fourier{}; }
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
// TO BE REPLACED BY A DIRECT CALL to many_fft in fftw, like for lattice case.
|
||||
// The implementation of the Fourier transformation
|
||||
// Reduce Matrix case to the scalar case.
|
||||
template <typename X, typename Y, typename S>
|
||||
void _fourier_impl(gf_view<X, matrix_valued, S> gw, gf_const_view<Y, matrix_valued, S> gt) {
|
||||
if (gt.data().shape().front_pop() != gw.data().shape().front_pop())
|
||||
TRIQS_RUNTIME_ERROR << "Fourier : matrix size of target mismatch";
|
||||
for (size_t n1 = 0; n1 < gt.data().shape()[1]; n1++)
|
||||
for (size_t n2 = 0; n2 < gt.data().shape()[2]; n2++) {
|
||||
auto gw_sl = slice_target_to_scalar(gw, n1, n2);
|
||||
auto gt_sl = slice_target_to_scalar(gt, n1, n2);
|
||||
_fourier_impl(gw_sl, gt_sl);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename X, typename Y, typename T, typename S>
|
||||
void triqs_gf_view_assign_delegation(gf_view<X, T, S> g, gf_keeper<tags::fourier, Y, T, S> const &L) {
|
||||
_fourier_impl(g, L.g);
|
||||
}
|
||||
}}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
89
triqs/gfs/local/fourier_lattice.cpp
Normal file
89
triqs/gfs/local/fourier_lattice.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2014 by O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "./fourier_lattice.hpp"
|
||||
#include <fftw3.h>
|
||||
|
||||
#define ASSERT_EQUAL(X,Y,MESS) if (X!=Y) TRIQS_RUNTIME_ERROR << MESS;
|
||||
|
||||
namespace triqs {
|
||||
namespace gfs {
|
||||
|
||||
// We rewrite the scalar in term of the matrix
|
||||
// We will change this for other FFT later when this FFT on lattice is checked.
|
||||
void _fourier_impl(gf_view<bz, scalar_valued> gk, gf_const_view<cyclic_lattice, scalar_valued> gr) {
|
||||
_fourier_impl(reinterpret_scalar_valued_gf_as_matrix_valued(gk), reinterpret_scalar_valued_gf_as_matrix_valued(gr));
|
||||
}
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
void _fourier_impl(gf_view<cyclic_lattice, scalar_valued> gr, gf_const_view<bz, scalar_valued> gk) {
|
||||
_fourier_impl(reinterpret_scalar_valued_gf_as_matrix_valued(gr), reinterpret_scalar_valued_gf_as_matrix_valued(gk));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
// The implementation is almost the same in both cases...
|
||||
template <typename V1, typename V2>
|
||||
void __impl(int sign, gf_view<V1, matrix_valued> g_out, gf_const_view<V2, matrix_valued> g_in) {
|
||||
|
||||
ASSERT_EQUAL(g_out.data().shape(), g_in.data().shape(), "Meshes are different");
|
||||
ASSERT_EQUAL(g_out.data().indexmap().strides()[1], g_out.data().shape()[1], "Unexpected strides in fourier implementation");
|
||||
ASSERT_EQUAL(g_out.data().indexmap().strides()[2], 1, "Unexpected strides in fourier implementation");
|
||||
ASSERT_EQUAL(g_in.data().indexmap().strides()[1], g_in.data().shape()[1], "Unexpected strides in fourier implementation");
|
||||
ASSERT_EQUAL(g_in.data().indexmap().strides()[2], 1, "Unexpected strides in fourier implementation");
|
||||
|
||||
auto L = g_in.mesh().get_dimensions();
|
||||
auto rank = g_in.mesh().rank();
|
||||
auto in_FFT = reinterpret_cast<fftw_complex*>(g_in.data().data_start());
|
||||
auto outFFT = reinterpret_cast<fftw_complex*>(g_out.data().data_start());
|
||||
// auto p = fftw_plan_dft(rank, L.ptr(), in_FFT, outFFT, FFTW_BACKWARD, FFTW_ESTIMATE);
|
||||
|
||||
// use the general routine that can do all the matrices at once.
|
||||
auto p = fftw_plan_many_dft(rank, // rank
|
||||
L.ptr(), // the dimension
|
||||
g_in.data().shape()[1] * g_in.data().shape()[2], // how many FFT : here 1
|
||||
in_FFT, // in data
|
||||
NULL, // embed : unused. Doc unclear ?
|
||||
g_in.data().indexmap().strides()[0], // stride of the in data
|
||||
1, // in : shift for multi fft.
|
||||
outFFT, // out data
|
||||
NULL, // embed : unused. Doc unclear ?
|
||||
g_out.data().indexmap().strides()[0], // stride of the out data
|
||||
1, // out : shift for multi fft.
|
||||
sign, FFTW_ESTIMATE);
|
||||
|
||||
|
||||
fftw_execute(p);
|
||||
fftw_destroy_plan(p);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
void _fourier_impl(gf_view<bz, matrix_valued> gk, gf_const_view<cyclic_lattice, matrix_valued> gr) {
|
||||
__impl(FFTW_BACKWARD, gk, gr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
void _fourier_impl(gf_view<cyclic_lattice, matrix_valued> gr, gf_const_view<bz, matrix_valued> gk) {
|
||||
__impl(FFTW_FORWARD, gr, gk);
|
||||
gr.data() /= gk.mesh().size();
|
||||
}
|
||||
}
|
||||
}
|
48
triqs/gfs/local/fourier_lattice.hpp
Normal file
48
triqs/gfs/local/fourier_lattice.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2014 by O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "fourier_base.hpp"
|
||||
#include <triqs/gfs/bz.hpp>
|
||||
#include <triqs/gfs/cyclic_lattice.hpp>
|
||||
|
||||
namespace triqs {
|
||||
namespace gfs {
|
||||
|
||||
template <typename Target, typename Singularity, typename Opt, bool V, bool C>
|
||||
gf_keeper<tags::fourier, cyclic_lattice, Target, Singularity>
|
||||
fourier(gf_impl<cyclic_lattice, Target, Singularity, Opt, V, C> const& g) {
|
||||
return {g};
|
||||
}
|
||||
|
||||
template <typename Target, typename Singularity, typename Opt, bool V, bool C>
|
||||
gf_keeper<tags::fourier, bz, Target, Singularity> inverse_fourier(gf_impl<bz, Target, Singularity, Opt, V, C> const& g) {
|
||||
return {g};
|
||||
}
|
||||
|
||||
// implementation
|
||||
void _fourier_impl(gf_view<bz, scalar_valued> gk, gf_const_view<cyclic_lattice, scalar_valued> gr);
|
||||
void _fourier_impl(gf_view<bz, matrix_valued> gk, gf_const_view<cyclic_lattice, matrix_valued> gr);
|
||||
|
||||
void _fourier_impl(gf_view<cyclic_lattice, scalar_valued> gr, gf_const_view<bz, scalar_valued> gk);
|
||||
void _fourier_impl(gf_view<cyclic_lattice, matrix_valued> gr, gf_const_view<bz, matrix_valued> gk);
|
||||
|
||||
}}
|
||||
|
@ -18,7 +18,6 @@
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "fourier_base.hpp"
|
||||
#include "fourier_matsubara.hpp"
|
||||
#include <fftw3.h>
|
||||
|
||||
@ -45,13 +44,13 @@ namespace gfs {
|
||||
//-------------------------------------
|
||||
|
||||
void direct(gf_view<imfreq, scalar_valued> gw, gf_const_view<imtime, scalar_valued> gt) {
|
||||
auto ta = gt(freq_infty());
|
||||
auto ta = gt.singularity();
|
||||
direct_impl(make_gf_view_without_tail(gw), make_gf_view_without_tail(gt), ta);
|
||||
gw.singularity() = gt.singularity(); // set tail
|
||||
}
|
||||
|
||||
void direct(gf_view<imfreq, scalar_valued, no_tail> gw, gf_const_view<imtime, scalar_valued, no_tail> gt) {
|
||||
auto ta = local::tail{1,1};
|
||||
auto ta = tail{1,1};
|
||||
direct_impl(gw, gt, ta);
|
||||
}
|
||||
|
||||
@ -59,7 +58,7 @@ namespace gfs {
|
||||
|
||||
private:
|
||||
void direct_impl(gf_view<imfreq, scalar_valued, no_tail> gw, gf_const_view<imtime, scalar_valued, no_tail> gt,
|
||||
local::tail const& ta) {
|
||||
tail const& ta) {
|
||||
// TO BE MODIFIED AFTER SCALAR IMPLEMENTATION TODO
|
||||
dcomplex d = ta(1)(0, 0), A = ta.get_or_zero(2)(0, 0), B = ta.get_or_zero(3)(0, 0);
|
||||
double b1 = 0, b2 = 0, b3 = 0;
|
||||
@ -112,7 +111,7 @@ namespace gfs {
|
||||
static bool Green_Function_Are_Complex_in_time = false;
|
||||
// If the Green function are NOT complex, then one use the symmetry property
|
||||
// fold the sum and get a factor 2
|
||||
auto ta = gw(freq_infty());
|
||||
auto ta = gw.singularity();
|
||||
// TO BE MODIFIED AFTER SCALAR IMPLEMENTATION TODO
|
||||
dcomplex d = ta(1)(0, 0), A = ta.get_or_zero(2)(0, 0), B = ta.get_or_zero(3)(0, 0);
|
||||
double b1, b2, b3;
|
||||
@ -180,65 +179,22 @@ namespace gfs {
|
||||
|
||||
//--------------------------------------------
|
||||
|
||||
template <typename Opt>
|
||||
void fourier_impl(gf_view<imfreq, scalar_valued, Opt> gw, gf_const_view<imtime, scalar_valued, Opt> gt) {
|
||||
// Direct transformation imtime -> imfreq, with a tail
|
||||
void _fourier_impl(gf_view<imfreq, scalar_valued, tail> gw, gf_const_view<imtime, scalar_valued, tail> gt) {
|
||||
impl_worker w;
|
||||
w.direct(gw, gt);
|
||||
}
|
||||
|
||||
template <typename Opt>
|
||||
void fourier_impl(gf_view<imfreq, matrix_valued, Opt> gw, gf_const_view<imtime, matrix_valued, Opt> gt) {
|
||||
void _fourier_impl(gf_view<imfreq, scalar_valued, no_tail> gw, gf_const_view<imtime, scalar_valued, no_tail> gt) {
|
||||
impl_worker w;
|
||||
for (size_t n1 = 0; n1 < gt.data().shape()[1]; n1++)
|
||||
for (size_t n2 = 0; n2 < gt.data().shape()[2]; n2++) {
|
||||
auto gw_sl = slice_target_to_scalar(gw, n1, n2);
|
||||
auto gt_sl = slice_target_to_scalar(gt, n1, n2);
|
||||
w.direct(gw_sl, gt_sl);
|
||||
}
|
||||
w.direct(gw, gt);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void inverse_fourier_impl(gf_view<imtime, scalar_valued> gt, gf_const_view<imfreq, scalar_valued> gw) {
|
||||
// Inverse transformation imfreq -> imtime: tail is mandatory
|
||||
void _fourier_impl(gf_view<imtime, scalar_valued, tail> gt, gf_const_view<imfreq, scalar_valued, tail> gw) {
|
||||
impl_worker w;
|
||||
w.inverse(gt, gw);
|
||||
}
|
||||
|
||||
void inverse_fourier_impl(gf_view<imtime, matrix_valued> gt, gf_const_view<imfreq, matrix_valued> gw) {
|
||||
impl_worker w;
|
||||
for (size_t n1 = 0; n1 < gw.data().shape()[1]; n1++)
|
||||
for (size_t n2 = 0; n2 < gw.data().shape()[2]; n2++) {
|
||||
auto gt_sl = slice_target_to_scalar(gt, n1, n2);
|
||||
auto gw_sl = slice_target_to_scalar(gw, n1, n2);
|
||||
w.inverse(gt_sl, gw_sl);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
void triqs_gf_view_assign_delegation(gf_view<imfreq, scalar_valued> g,
|
||||
gf_keeper<tags::fourier, imtime, scalar_valued> const& L) {
|
||||
fourier_impl(g, L.g);
|
||||
}
|
||||
void triqs_gf_view_assign_delegation(gf_view<imfreq, matrix_valued> g,
|
||||
gf_keeper<tags::fourier, imtime, matrix_valued> const& L) {
|
||||
fourier_impl(g, L.g);
|
||||
}
|
||||
void triqs_gf_view_assign_delegation(gf_view<imtime, scalar_valued> g,
|
||||
gf_keeper<tags::fourier, imfreq, scalar_valued> const& L) {
|
||||
inverse_fourier_impl(g, L.g);
|
||||
}
|
||||
void triqs_gf_view_assign_delegation(gf_view<imtime, matrix_valued> g,
|
||||
gf_keeper<tags::fourier, imfreq, matrix_valued> const& L) {
|
||||
inverse_fourier_impl(g, L.g);
|
||||
}
|
||||
void triqs_gf_view_assign_delegation(gf_view<imfreq, scalar_valued, no_tail> g,
|
||||
gf_keeper<tags::fourier, imtime, scalar_valued, no_tail> const& L) {
|
||||
fourier_impl(g, L.g);
|
||||
}
|
||||
void triqs_gf_view_assign_delegation(gf_view<imfreq, matrix_valued, no_tail> g,
|
||||
gf_keeper<tags::fourier, imtime, matrix_valued, no_tail> const& L) {
|
||||
fourier_impl(g, L.g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,8 @@
|
||||
namespace triqs {
|
||||
namespace gfs {
|
||||
|
||||
// only a few functions allowed:
|
||||
|
||||
template <typename Target, typename Singularity, typename Opt, bool V, bool C>
|
||||
gf_keeper<tags::fourier, imtime, Target, Singularity, Opt> fourier(gf_impl<imtime, Target, Singularity, Opt, V, C> const& g) {
|
||||
return {g};
|
||||
@ -36,18 +38,12 @@ namespace gfs {
|
||||
return {g};
|
||||
}
|
||||
|
||||
// The fourier transform with the tail
|
||||
void triqs_gf_view_assign_delegation(gf_view<imfreq, scalar_valued> g, gf_keeper<tags::fourier, imtime, scalar_valued> const& L);
|
||||
void triqs_gf_view_assign_delegation(gf_view<imfreq, matrix_valued> g, gf_keeper<tags::fourier, imtime, matrix_valued> const& L);
|
||||
void triqs_gf_view_assign_delegation(gf_view<imtime, scalar_valued> g, gf_keeper<tags::fourier, imfreq, scalar_valued> const& L);
|
||||
void triqs_gf_view_assign_delegation(gf_view<imtime, matrix_valued> g, gf_keeper<tags::fourier, imfreq, matrix_valued> const& L);
|
||||
|
||||
// The version without tail : only possible in one direction
|
||||
void triqs_gf_view_assign_delegation(gf_view<imfreq, scalar_valued, no_tail> g,
|
||||
gf_keeper<tags::fourier, imtime, scalar_valued, no_tail> const& L);
|
||||
void triqs_gf_view_assign_delegation(gf_view<imfreq, matrix_valued, no_tail> g,
|
||||
gf_keeper<tags::fourier, imtime, matrix_valued, no_tail> const& L);
|
||||
///
|
||||
void _fourier_impl(gf_view<imfreq, scalar_valued, tail> gw, gf_const_view<imtime, scalar_valued, tail> gt);
|
||||
void _fourier_impl(gf_view<imfreq, scalar_valued, no_tail> gw, gf_const_view<imtime, scalar_valued, no_tail> gt);
|
||||
void _fourier_impl(gf_view<imtime, scalar_valued, tail> gt, gf_const_view<imfreq, scalar_valued, tail> gw);
|
||||
|
||||
/// A few helper functions
|
||||
template <typename Target, typename Singularity, typename Opt, bool V, bool C>
|
||||
gf<imfreq, Target, Singularity, Opt> make_gf_from_fourier(gf_impl<imtime, Target, Singularity, Opt, V, C> const& gt, int n_iw) {
|
||||
auto m = gf_mesh<imfreq, Opt>{gt.mesh().domain(), n_iw};
|
||||
|
@ -49,7 +49,7 @@ namespace triqs { namespace gfs {
|
||||
//a is a number very larger than delta_w and very smaller than wmax-wmin, used in the tail computation
|
||||
const double a = gw.mesh().delta() * sqrt( double(L) );
|
||||
|
||||
auto ta = gt(freq_infty());
|
||||
auto ta = gt.singularity();
|
||||
g_in.resize(L);
|
||||
g_in() = 0;
|
||||
g_out.resize(L);
|
||||
@ -82,7 +82,7 @@ namespace triqs { namespace gfs {
|
||||
//a is a number very larger than delta_w and very smaller than wmax-wmin, used in the tail computation
|
||||
const double a = gw.mesh().delta() * sqrt( double(L) );
|
||||
|
||||
auto ta = gw(freq_infty());
|
||||
auto ta = gw.singularity();
|
||||
arrays::vector<dcomplex> g_in(L), g_out(L);
|
||||
|
||||
dcomplex t1 = ta(1)(0,0), t2 = ta.get_or_zero(2)(0,0);
|
||||
@ -105,46 +105,16 @@ namespace triqs { namespace gfs {
|
||||
|
||||
};
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------------
|
||||
|
||||
void fourier_impl(gf_view<refreq,scalar_valued> gw, gf_const_view<retime,scalar_valued> gt, scalar_valued){
|
||||
void _fourier_impl(gf_view<refreq, scalar_valued> gw, gf_const_view<retime, scalar_valued> gt) {
|
||||
impl_worker w;
|
||||
w.direct(gw, gt);
|
||||
}
|
||||
|
||||
void fourier_impl(gf_view<refreq,matrix_valued> gw, gf_const_view<retime,matrix_valued> gt, matrix_valued){
|
||||
impl_worker w;
|
||||
for (size_t n1=0; n1<gw.data().shape()[1];n1++)
|
||||
for (size_t n2=0; n2<gw.data().shape()[2];n2++) {
|
||||
auto gw_sl=slice_target_to_scalar(gw, n1, n2);
|
||||
auto gt_sl=slice_target_to_scalar(gt, n1, n2);
|
||||
w.direct(gw_sl, gt_sl);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void inverse_fourier_impl (gf_view<retime,scalar_valued> gt, gf_const_view<refreq,scalar_valued> gw, scalar_valued){
|
||||
void _fourier_impl(gf_view<retime, scalar_valued> gt, gf_const_view<refreq, scalar_valued> gw) {
|
||||
impl_worker w;
|
||||
w.inverse(gt, gw);
|
||||
}
|
||||
|
||||
void inverse_fourier_impl (gf_view<retime,matrix_valued> gt, gf_const_view<refreq,matrix_valued> gw, matrix_valued){
|
||||
impl_worker w;
|
||||
for (size_t n1=0; n1<gt.data().shape()[1];n1++)
|
||||
for (size_t n2=0; n2<gt.data().shape()[2];n2++) {
|
||||
auto gt_sl=slice_target_to_scalar(gt, n1, n2);
|
||||
auto gw_sl=slice_target_to_scalar(gw, n1, n2);
|
||||
w.inverse(gt_sl, gw_sl);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
void triqs_gf_view_assign_delegation( gf_view<refreq,matrix_valued> g, gf_keeper<tags::fourier,retime,matrix_valued> const & L) { fourier_impl (g,L.g, matrix_valued());}
|
||||
void triqs_gf_view_assign_delegation( gf_view<refreq,scalar_valued> g, gf_keeper<tags::fourier,retime,scalar_valued> const & L) { fourier_impl (g,L.g, scalar_valued());}
|
||||
void triqs_gf_view_assign_delegation( gf_view<retime,matrix_valued> g, gf_keeper<tags::fourier,refreq,matrix_valued> const & L) { inverse_fourier_impl(g,L.g, matrix_valued());}
|
||||
void triqs_gf_view_assign_delegation( gf_view<retime,scalar_valued> g, gf_keeper<tags::fourier,refreq,scalar_valued> const & L) { inverse_fourier_impl(g,L.g, scalar_valued());}
|
||||
|
||||
}}
|
||||
|
@ -34,11 +34,10 @@ namespace triqs { namespace gfs {
|
||||
return {g};
|
||||
}
|
||||
|
||||
void triqs_gf_view_assign_delegation(gf_view<refreq, scalar_valued> g, gf_keeper<tags::fourier, retime, scalar_valued> const& L);
|
||||
void triqs_gf_view_assign_delegation(gf_view<refreq, matrix_valued> g, gf_keeper<tags::fourier, retime, matrix_valued> const& L);
|
||||
void triqs_gf_view_assign_delegation(gf_view<retime, scalar_valued> g, gf_keeper<tags::fourier, refreq, scalar_valued> const& L);
|
||||
void triqs_gf_view_assign_delegation(gf_view<retime, matrix_valued> g, gf_keeper<tags::fourier, refreq, matrix_valued> const& L);
|
||||
void _fourier_impl(gf_view<refreq, scalar_valued> gw, gf_const_view<retime, scalar_valued> gt);
|
||||
void _fourier_impl(gf_view<retime, scalar_valued> gt, gf_const_view<refreq, scalar_valued> gw);
|
||||
|
||||
// helper functions
|
||||
template <typename Opt> gf_mesh<refreq, Opt> make_mesh_fourier_compatible(gf_mesh<retime, Opt> const& m) {
|
||||
int L = m.size();
|
||||
double pi = std::acos(-1);
|
||||
|
@ -33,7 +33,7 @@ namespace triqs { namespace gfs {
|
||||
dcomplex I(0,1);
|
||||
auto sh = G.data().shape().front_pop();
|
||||
auto Beta = G.domain().beta;
|
||||
local::tail_view t = G(freq_infty());
|
||||
tail_view t = G.singularity();
|
||||
if (!t.is_decreasing_at_infinity()) TRIQS_RUNTIME_ERROR<<" density computation : Green Function is not as 1/omega or less !!!";
|
||||
const size_t N1=sh[0], N2 = sh[1];
|
||||
arrays::array<dcomplex,2> dens_part(sh), dens_tail(sh), dens(sh);
|
||||
@ -89,11 +89,11 @@ namespace triqs { namespace gfs {
|
||||
|
||||
// compute a tail from the Legendre GF
|
||||
// this is Eq. 8 of our paper
|
||||
local::tail_view get_tail(gf_const_view<legendre> gl, int size = 10, int omin = -1) {
|
||||
tail_view get_tail(gf_const_view<legendre> gl, int size = 10, int omin = -1) {
|
||||
|
||||
auto sh = gl.data().shape().front_pop();
|
||||
local::tail t(sh, size, omin);
|
||||
t.data() = 0.0;
|
||||
tail t(sh, size, omin);
|
||||
t.data()() = 0.0;
|
||||
|
||||
for (int p=1; p<=t.order_max(); p++)
|
||||
for (auto l : gl.mesh())
|
||||
|
@ -37,7 +37,7 @@ namespace triqs {
|
||||
|
||||
arrays::matrix<double> density(gf_view<legendre> const & g);
|
||||
|
||||
local::tail_view get_tail(gf_const_view<legendre> gl, int size, int omin);
|
||||
tail_view get_tail(gf_const_view<legendre> gl, int size, int omin);
|
||||
|
||||
void enforce_discontinuity(gf_view<legendre> & gl, triqs::arrays::array_view<double,2> disc);
|
||||
|
||||
|
@ -48,15 +48,15 @@ namespace gfs {
|
||||
}
|
||||
|
||||
template <typename Variable, typename Target, typename S, typename Opt, bool V, bool C>
|
||||
gf_view<Variable, Target> make_gf_from_g_and_tail(gf_impl<Variable, Target, S, Opt, V, C> const &g, local::tail t) {
|
||||
gf_view<Variable, Target> make_gf_from_g_and_tail(gf_impl<Variable, Target, S, Opt, V, C> const &g, tail t) {
|
||||
details::_equal_or_throw(t.shape(), get_target_shape(g));
|
||||
auto g2 = gf<Variable, Target, no_tail>{g}; // copy the function without tail
|
||||
return {std::move(g2.mesh()), std::move(g2.data()), std::move(t), g2.symmetry()};
|
||||
}
|
||||
|
||||
template <typename Variable, typename Target, typename S, typename Opt, bool V, bool C>
|
||||
gf_view<Variable, Target, local::tail, Opt, C> make_gf_view_from_g_and_tail(gf_impl<Variable, Target, no_tail, Opt, V, C> const &g,
|
||||
local::tail_view t) {
|
||||
gf_view<Variable, Target, tail, Opt, C> make_gf_view_from_g_and_tail(gf_impl<Variable, Target, no_tail, Opt, V, C> const &g,
|
||||
tail_view t) {
|
||||
details::_equal_or_throw(t.shape(), get_target_shape(g));
|
||||
return {g.mesh(), g.data(), t, g.symmetry()};
|
||||
}
|
||||
|
214
triqs/gfs/local/tail.cpp
Normal file
214
triqs/gfs/local/tail.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2012 by M. Ferrero, O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#include "./tail.hpp"
|
||||
|
||||
namespace triqs {
|
||||
namespace gfs {
|
||||
|
||||
// tail_const_view class
|
||||
void tail_const_view::rebind(tail_const_view const &X) {
|
||||
omin = X.omin;
|
||||
_mask.rebind(X._mask);
|
||||
_data.rebind(X._data);
|
||||
}
|
||||
|
||||
// tail_view class
|
||||
void tail_view::rebind(tail_view const &X) {
|
||||
omin = X.omin;
|
||||
_mask.rebind(X._mask);
|
||||
_data.rebind(X._data);
|
||||
}
|
||||
|
||||
tail_view &tail_view::operator=(std::complex<double> x) {
|
||||
_data() = 0.0;
|
||||
mv_type(_data(-omin, ellipsis())) = x;
|
||||
mask() = omin + size() - 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// --- functions
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, tail_const_view x) {
|
||||
if (x.data().is_empty()) return out << "empty tail" << std::endl;
|
||||
out << "tail/tail_view: min/smallest/max = " << x.order_min() << " " << x.smallest_nonzero() << " " << x.order_max();
|
||||
for (int u = x.order_min(); u <= x.order_max(); ++u) out << "\n ... Order " << u << " = " << x(u);
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Evaluate the tail to sum_{n=order_min}^ordermax M_n/omega^n
|
||||
matrix<dcomplex> evaluate(tail_const_view t, dcomplex const &omega) {
|
||||
auto r = arrays::matrix<dcomplex>{t.shape()};
|
||||
r() = 0;
|
||||
auto omin = t.order_min();
|
||||
auto omax = t.order_max(); // precompute since long to do...
|
||||
auto _ = arrays::range{};
|
||||
for (int u = omax; u >= omin; --u)
|
||||
r = r / omega + matrix_view<dcomplex>{t.data()(u - omin, ellipsis())}; // need to make a matrix view because otherwise + is not defined
|
||||
r /= pow(omega, omin);
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Evaluate the tail to sum_{n=order_min}^ordermax M_n/omega^n
|
||||
tail compose(tail_const_view x, tail_const_view t) {
|
||||
auto r = tail(x.shape(), x.size(), x.order_min()); // a new tail of same size, init to 0
|
||||
auto t_inv = inverse(t);
|
||||
auto omin = x.order_min();
|
||||
auto omax = x.order_max(); // precompute since long to do...
|
||||
if ((omin<=0) && (omax>=0)) r = t * x(0);
|
||||
tail z = t;
|
||||
for (int u = -1; u >= omin; --u) {
|
||||
r += x(u) * z;
|
||||
z = z * t;
|
||||
}
|
||||
z = t_inv;
|
||||
for (int u = 1; u <= omax; ++u) {
|
||||
r += x(u) * z;
|
||||
z = z * t_inv;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Factories
|
||||
tail tail_omega(int N1, int N2, int size_, int order_min) {
|
||||
tail t(N1, N2, size_, order_min);
|
||||
t(-1) = 1;
|
||||
return t;
|
||||
}
|
||||
tail_view tail_omega(tail::shape_type const &sh, int size_, int order_min) { return tail_omega(sh[0], sh[1], size_, order_min); }
|
||||
tail_view tail_omega(tail_view t) { return tail_omega(t.shape(), t.size(), t.order_min()); }
|
||||
|
||||
// Ops
|
||||
tail conj(tail_const_view const &t) {
|
||||
return {conj(t.data()), t.mask(), t.order_min()};
|
||||
}
|
||||
|
||||
tail transpose(tail_const_view const &t) {
|
||||
return {transposed_view(t.data(), 0, 2, 1), transposed_view(t.mask(), 1, 0), t.order_min()};
|
||||
}
|
||||
|
||||
/// Slice in orbital space
|
||||
tail_view slice_target(tail_view t, range R1, range R2) {
|
||||
return {t.data()(range(), R1, R2), t.mask()(R1, R2), t.order_min()};
|
||||
}
|
||||
|
||||
tail_const_view slice_target(tail_const_view const &t, range R1, range R2) {
|
||||
return {t.data()(range(), R1, R2), t.mask()(R1, R2), t.order_min()};
|
||||
}
|
||||
|
||||
// inverse
|
||||
tail inverse(tail_const_view const &t) {
|
||||
int omin1 = -t.smallest_nonzero();
|
||||
int omax1 = std::min(t.order_max() + 2 * omin1, t.order_min() + int(t.size()) - 1);
|
||||
int si = omax1 - omin1 + 1;
|
||||
|
||||
tail res(t.shape(), t.size(), t.order_min());
|
||||
res.mask()() = omax1;
|
||||
|
||||
res(omin1) = inverse(t(-omin1));
|
||||
|
||||
// optimize for the case 1x1
|
||||
if (1 && (t.shape()==make_shape(1,1))) {
|
||||
for (int n = 1; n < si; n++) {
|
||||
for (int p = 0; p < n; p++) {
|
||||
res(omin1 + n)(0,0) -= t(n - omin1 - p)(0,0) * res(omin1 + p)(0,0);
|
||||
}
|
||||
res(omin1 + n)(0,0) = res(omin1)(0,0) * res(omin1 + n)(0,0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int n = 1; n < si; n++) {
|
||||
for (int p = 0; p < n; p++) {
|
||||
res(omin1 + n) -= t(n - omin1 - p) * res(omin1 + p);
|
||||
}
|
||||
res(omin1 + n) = res(omin1) * res(omin1 + n);
|
||||
//res(omin1 + n) = res(omin1) * make_clone(res(omin1 + n));
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// Arithmetic ops
|
||||
|
||||
tail operator*(matrix<dcomplex> const &a, tail_const_view const &b) {
|
||||
auto res = tail(first_dim(a), b.shape()[1], b.size(), b.order_min()); // no {} constructor to avoid narrowing:...
|
||||
for (int n = res.order_min(); n <= res.order_max(); ++n) res(n) = a * b(n);
|
||||
return res;
|
||||
}
|
||||
|
||||
tail operator*(tail_const_view const &a, matrix<dcomplex> const &b) {
|
||||
auto res = tail(a.shape()[0], second_dim(b), a.size(), a.order_min());
|
||||
for (int n = res.order_min(); n <= res.order_max(); ++n) res(n) = a(n) * b;
|
||||
return res;
|
||||
}
|
||||
|
||||
tail operator*(tail_const_view const &l, tail_const_view const &r) {
|
||||
if (l.shape()[1] != r.shape()[0] || l.order_min() != r.order_min() || l.size() != r.size())
|
||||
TRIQS_RUNTIME_ERROR << "tail multiplication: shape mismatch";
|
||||
// int omin1 = l.smallest_nonzero() + r.smallest_nonzero();
|
||||
int omax1 = std::min(std::min(r.order_max() + l.smallest_nonzero(), l.order_max() + r.smallest_nonzero()),
|
||||
r.order_min() + int(r.size()) - 1);
|
||||
// int si = omax1-omin1+1;
|
||||
tail res(l.shape(), l.size(), l.order_min());
|
||||
res.mask()() = omax1;
|
||||
for (int n = res.order_min(); n <= res.order_max(); ++n) {
|
||||
// sum_{p}^n a_p b_{n-p}. p <= a.n_max, p >= a.n_min and n-p <=b.n_max and n-p >= b.n_min
|
||||
// hence p <= min ( a.n_max, n-b.n_min ) and p >= max ( a.n_min, n- b.n_max)
|
||||
const int pmin = std::max(l.smallest_nonzero(), n - r.order_max());
|
||||
const int pmax = std::min(l.order_max(), n - r.smallest_nonzero());
|
||||
for (int p = pmin; p <= pmax; ++p) {
|
||||
res(n) += l(p) * r(n - p);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
tail operator*(dcomplex a, tail_const_view const &r) {
|
||||
tail res(r);
|
||||
res.data() *= a;
|
||||
return res;
|
||||
}
|
||||
|
||||
tail operator/(tail_const_view const &r, dcomplex a) {
|
||||
tail res(r);
|
||||
res.data() /= a;
|
||||
return res;
|
||||
}
|
||||
|
||||
tail operator+(tail_const_view const &l, tail_const_view const &r) {
|
||||
if (l.shape() != r.shape() || l.order_min() != r.order_min() || (l.size() != r.size()))
|
||||
TRIQS_RUNTIME_ERROR << "tail addition: shape mismatch" << l << r;
|
||||
tail res(l.shape(), l.size(), l.order_min());
|
||||
res.mask()() = std::min(l.order_max(), r.order_max());
|
||||
for (int i = res.order_min(); i <= res.order_max(); ++i) res(i) = l(i) + r(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
tail operator-(tail_const_view const &l, tail_const_view const &r) {
|
||||
if (l.shape() != r.shape() || l.order_min() != r.order_min() || (l.size() != r.size()))
|
||||
TRIQS_RUNTIME_ERROR << "tail addition: shape mismatch" << l << r;
|
||||
tail res(l.shape(), l.size(), l.order_min());
|
||||
res.mask()() = std::min(l.order_max(), r.order_max());
|
||||
for (int i = res.order_min(); i <= res.order_max(); ++i) res(i) = l(i) - r(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2012 by M. Ferrero, O. Parcollet
|
||||
* Copyright (C) 2012-2014 by M. Ferrero, O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
@ -25,127 +25,124 @@
|
||||
#include <triqs/mpi/boost.hpp>
|
||||
#include <boost/serialization/complex.hpp>
|
||||
|
||||
namespace triqs { namespace gfs { namespace local {
|
||||
|
||||
namespace details {
|
||||
static constexpr double small = 1.e-10;
|
||||
}
|
||||
namespace triqs {
|
||||
namespace gfs {
|
||||
|
||||
using dcomplex = std::complex<double>;
|
||||
using arrays::array;
|
||||
using arrays::array_view;
|
||||
using arrays::matrix_view;
|
||||
using arrays::matrix;
|
||||
namespace tqa= triqs::arrays; //namespace tql= triqs::clef; namespace mpl= boost::mpl;
|
||||
typedef std::complex<double> dcomplex;
|
||||
using arrays::make_shape;
|
||||
using arrays::range;
|
||||
using arrays::ellipsis;
|
||||
using arrays::mini_vector;
|
||||
|
||||
class tail; // the value class
|
||||
class tail_view; // the view class
|
||||
|
||||
template<typename G> struct LocalTail : mpl::false_{}; // a boolean trait to identify the objects modelling the concept LocalTail
|
||||
template<> struct LocalTail<tail > : mpl::true_{};
|
||||
template<> struct LocalTail<tail_view >: mpl::true_{};
|
||||
|
||||
// a trait to find the scalar of the algebra i.e. the true scalar and the matrix ...
|
||||
template <typename T> struct is_scalar_or_element : mpl::or_< tqa::ImmutableMatrix<T>, utility::is_in_ZRC<T> > {};
|
||||
class tail_const_view; // the const view class
|
||||
|
||||
// ---------------------- implementation --------------------------------
|
||||
|
||||
/// A common implementation class. Idiom: ValueView
|
||||
template<bool IsView> class tail_impl {
|
||||
enum rvc_enum {
|
||||
Regular,
|
||||
View,
|
||||
ConstView
|
||||
};
|
||||
|
||||
template <rvc_enum RVC, typename T> struct __get_rvc;
|
||||
template <rvc_enum RVC, typename T> using get_rvc = typename __get_rvc<RVC, T>::type;
|
||||
template <typename T> struct __get_rvc<Regular, T> {
|
||||
using type = T;
|
||||
};
|
||||
template <typename T> struct __get_rvc<View, T> {
|
||||
using type = typename T::view_type;
|
||||
};
|
||||
template <typename T> struct __get_rvc<ConstView, T> {
|
||||
using type = typename T::const_view_type;
|
||||
};
|
||||
|
||||
/// A common implementation class.
|
||||
template <rvc_enum RVC> class tail_impl {
|
||||
public:
|
||||
TRIQS_MPI_IMPLEMENTED_VIA_BOOST;
|
||||
typedef tail_view view_type;
|
||||
typedef tail_view const_view_type; // not nice
|
||||
typedef tail regular_type;
|
||||
using view_type = tail_view;
|
||||
using const_view_type = tail_view;
|
||||
using regular_type = tail;
|
||||
|
||||
typedef arrays::array <dcomplex,3> data_regular_type;
|
||||
typedef arrays::array_view <dcomplex,3> data_view_type;
|
||||
typedef typename mpl::if_c<IsView, data_view_type, data_regular_type>::type data_type;
|
||||
using data_type = get_rvc<RVC, array<dcomplex, 3>>;
|
||||
using mask_type = get_rvc<RVC, array<int, 2>>;
|
||||
|
||||
typedef arrays::array<long,2> mask_regular_type;
|
||||
typedef arrays::array_view<long,2> mask_view_type;
|
||||
typedef typename mpl::if_c<IsView, mask_view_type, mask_regular_type>::type mask_type;
|
||||
using mv_type = matrix_view<dcomplex>;
|
||||
using const_mv_type = matrix_view<dcomplex>;
|
||||
|
||||
typedef arrays::matrix_view<dcomplex> mv_type;
|
||||
typedef arrays::matrix_view<dcomplex> const_mv_type;
|
||||
data_type & data() { return _data; }
|
||||
data_type const & data() const { return _data; }
|
||||
mask_type & mask() { return _mask; }
|
||||
mask_type const & mask() const { return _mask; }
|
||||
|
||||
data_view_type data() { return _data;}
|
||||
const data_view_type data() const { return _data;}
|
||||
mask_view_type mask_view() { return mask;}
|
||||
const mask_view_type mask_view() const { return mask;}
|
||||
|
||||
long order_min() const {return omin;}
|
||||
long order_max() const {return min_element(mask);}
|
||||
int order_min() const { return omin; }
|
||||
int order_max() const { return min_element(_mask); }
|
||||
size_t size() const { return _data.shape()[0]; }
|
||||
long smallest_nonzero() const {
|
||||
long om = omin;
|
||||
while ((om < this->order_max()) && (max_element(abs(_data(om-omin,tqa::range(),tqa::range()))) < details::small)) om++;
|
||||
int smallest_nonzero() const {
|
||||
int om = omin;
|
||||
while ((om < order_max()) && (max_element(abs(_data(om - omin, ellipsis()))) < 1.e-10)) om++;
|
||||
return om;
|
||||
}
|
||||
|
||||
typedef tqa::mini_vector<size_t,2> shape_type;
|
||||
using shape_type = mini_vector<size_t, 2>;
|
||||
shape_type shape() const { return shape_type(_data.shape()[1], _data.shape()[2]); }
|
||||
bool is_decreasing_at_infinity() const { return (smallest_nonzero() >= 1); }
|
||||
|
||||
protected:
|
||||
|
||||
long omin;
|
||||
mask_type mask;
|
||||
int omin = -1;
|
||||
mask_type _mask;
|
||||
data_type _data;
|
||||
|
||||
// All constructors
|
||||
tail_impl(): omin(0), mask(), _data() {} // all arrays of zero size (empty)
|
||||
tail_impl(size_t N1, size_t N2, size_t size_, long order_min):
|
||||
omin(order_min), mask(tqa::make_shape(N1,N2)), _data(tqa::make_shape(size_,N1,N2)) {
|
||||
mask() = order_min+size_-1;
|
||||
tail_impl() = default;
|
||||
tail_impl(int N1, int N2, int size_, int order_min)
|
||||
: omin(order_min), _mask(arrays::make_shape(N1, N2)), _data(make_shape(size_, N1, N2)) {
|
||||
_mask() = order_min + size_ - 1;
|
||||
_data() = 0;
|
||||
}
|
||||
tail_impl(data_type const &d, mask_type const &m, long omin_) : omin(omin_), mask(m), _data(d) {}
|
||||
tail_impl(tail_impl<!IsView> const & x): omin(x.omin), mask(x.mask), _data(x._data) {}
|
||||
tail_impl(tail_impl const &) = default;
|
||||
tail_impl(tail_impl &&) = default;
|
||||
tail_impl(data_type const &d, mask_type const &m, int omin_) : omin(omin_), _mask(m), _data(d) {}
|
||||
template <rvc_enum RVC2> tail_impl(tail_impl<RVC2> const &x) : omin(x.order_min()), _mask(x.mask()), _data(x.data()) {}
|
||||
|
||||
friend class tail_impl<!IsView>;
|
||||
friend class tail;
|
||||
friend class tail_view;
|
||||
friend class tail_const_view;
|
||||
friend tail compose(tail_const_view x, tail_const_view omega);
|
||||
|
||||
// operator = for views
|
||||
void operator=(tail_const_view const &rhs); // implemented later
|
||||
|
||||
public:
|
||||
|
||||
mv_type operator()(int n) {
|
||||
if (n>this->order_max()) TRIQS_RUNTIME_ERROR<<" n > Max Order. n= "<<n <<", Max Order = "<<order_max() ;
|
||||
if (n<this->order_min()) TRIQS_RUNTIME_ERROR<<" n < Min Order. n= "<<n <<", Min Order = "<<order_min() ;
|
||||
return this->_data(n-omin, tqa::range(), tqa::range());
|
||||
if (n > order_max()) TRIQS_RUNTIME_ERROR << " n > Max Order. n= " << n << ", Max Order = " << order_max();
|
||||
if (n < order_min()) TRIQS_RUNTIME_ERROR << " n < Min Order. n= " << n << ", Min Order = " << order_min();
|
||||
return _data(n - omin, ellipsis());
|
||||
}
|
||||
|
||||
const_mv_type operator()(int n) const {
|
||||
if (n>this->order_max()) TRIQS_RUNTIME_ERROR<<" n > Max Order. n= "<<n <<", Max Order = "<<order_max() ;
|
||||
if (n<this->order_min()) { mv_type::regular_type r(this->shape()); r()=0; return r;}
|
||||
return this->_data(n-omin, tqa::range(), tqa::range());
|
||||
if (n > order_max()) TRIQS_RUNTIME_ERROR << " n > Max Order. n= " << n << ", Max Order = " << order_max();
|
||||
if (n < order_min()) {
|
||||
mv_type::regular_type r(shape());
|
||||
r() = 0;
|
||||
return r;
|
||||
}
|
||||
return _data(n - omin, ellipsis());
|
||||
}
|
||||
|
||||
/// same as (), but if n is too large, then returns 0 instead of raising an exception
|
||||
const_mv_type get_or_zero(int n) const {
|
||||
if ( (n>this->order_max()) || (n<this->order_min()) ) { mv_type::regular_type r(this->shape()); r()=0; return r; }
|
||||
return this->_data(n-omin, tqa::range(), tqa::range());
|
||||
}
|
||||
|
||||
operator freq_infty() const { return freq_infty(); }
|
||||
|
||||
/// Evaluate the tail to sum_{n=order_min}^ordermax M_n/omega^n
|
||||
arrays::matrix<dcomplex> evaluate(dcomplex const &omega) const {
|
||||
auto r = arrays::matrix<dcomplex>{this->shape()};
|
||||
if ((n > order_max()) || (n < order_min())) {
|
||||
mv_type::regular_type r(shape());
|
||||
r() = 0;
|
||||
auto omin = this->order_min();
|
||||
auto omax = this->order_max(); // precompute since long to do...
|
||||
auto _ = arrays::range{};
|
||||
for (int u = omax; u >= omin; --u)
|
||||
r = r / omega +
|
||||
const_mv_type{this->_data(u - omin, _, _)}; // need to make a matrix view because otherwise + is not defined
|
||||
r /= pow(omega, omin);
|
||||
return r;
|
||||
}
|
||||
|
||||
/// Save in txt file: doc the format ? ---> prefer serialization or hdf5 !
|
||||
void save(std::string file, bool accumulate=false) const {}
|
||||
|
||||
/// Load from txt file: doc the format ?
|
||||
//void load(std::string file){}
|
||||
return _data(n - omin, ellipsis());
|
||||
}
|
||||
|
||||
friend std::string get_triqs_hdf5_data_scheme(tail_impl const &g) { return "TailGf"; }
|
||||
|
||||
@ -153,252 +150,177 @@ namespace triqs { namespace gfs { namespace local {
|
||||
friend void h5_write(h5::group fg, std::string subgroup_name, tail_impl const &t) {
|
||||
auto gr = fg.create_group(subgroup_name);
|
||||
h5_write(gr, "omin", t.omin);
|
||||
h5_write(gr,"mask",t.mask);
|
||||
h5_write(gr, "mask", t._mask);
|
||||
h5_write(gr, "data", t._data);
|
||||
}
|
||||
|
||||
friend void h5_read(h5::group fg, std::string subgroup_name, tail_impl &t) {
|
||||
auto gr = fg.open_group(subgroup_name);
|
||||
h5_read(gr, "omin", t.omin);
|
||||
h5_read(gr,"mask",t.mask);
|
||||
h5_read(gr, "mask", t._mask);
|
||||
h5_read(gr, "data", t._data);
|
||||
}
|
||||
|
||||
// BOOST Serialization
|
||||
friend class boost::serialization::access;
|
||||
template<class Archive>
|
||||
void serialize(Archive & ar, const unsigned int version) {
|
||||
template <class Archive> void serialize(Archive &ar, const unsigned int version) {
|
||||
ar &TRIQS_MAKE_NVP("omin", omin);
|
||||
ar & TRIQS_MAKE_NVP("mask",mask);
|
||||
ar &TRIQS_MAKE_NVP("mask", _mask);
|
||||
ar &TRIQS_MAKE_NVP("data", _data);
|
||||
}
|
||||
|
||||
friend std::ostream & operator << (std::ostream & out, tail_impl const & x) {
|
||||
if (x.data().is_empty()) return out << "empty tail"<<std::endl;
|
||||
out <<"tail/tail_view: min/smallest/max = "<< x.order_min() << " " << x.smallest_nonzero() << " "<< x.order_max();
|
||||
for (long u = x.order_min(); u <= x.order_max(); ++u) out <<"\n ... Order "<<u << " = " << x(u);
|
||||
return out;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// -----------------------------
|
||||
// the view class
|
||||
class tail_view: public tail_impl <true> {
|
||||
typedef tail_impl <true> B;
|
||||
friend class tail;
|
||||
class tail_const_view : public tail_impl<ConstView> {
|
||||
using B = tail_impl<ConstView>;
|
||||
// friend class tail;
|
||||
|
||||
public:
|
||||
template<bool V> tail_view(tail_impl<V> const & t): B(t){}
|
||||
tail_view(B::data_type const &d, B::mask_type const &m, long order_min): B(d, m, order_min) {}
|
||||
tail_const_view(B::data_type d, B::mask_type m, int order_min) : B(std::move(d), std::move(m), order_min) {}
|
||||
tail_const_view(tail_const_view const &) = default;
|
||||
tail_const_view(tail_const_view &&) = default;
|
||||
tail_const_view(tail_impl<Regular> const &t) : B(t) {}
|
||||
tail_const_view(tail_impl<View> const &t) : B(t) {}
|
||||
|
||||
void rebind(tail_const_view const &X);
|
||||
};
|
||||
|
||||
// -----------------------------
|
||||
class tail_view : public tail_impl<View> {
|
||||
using B = tail_impl<View>;
|
||||
// friend class tail;
|
||||
|
||||
public:
|
||||
tail_view(B::data_type d, B::mask_type m, int order_min) : B(std::move(d), std::move(m), order_min) {}
|
||||
tail_view(tail_view const &) = default;
|
||||
tail_view(tail_view &&) = default;
|
||||
tail_view(tail_impl<Regular> const &t) : B(t) {}
|
||||
|
||||
void rebind(tail_view const &X) {
|
||||
omin = X.omin;
|
||||
mask.rebind(X.mask);
|
||||
_data.rebind(X._data);
|
||||
}
|
||||
inline void rebind(tail const &X);
|
||||
|
||||
// operator = for views
|
||||
tail_view & operator = (const tail_view & rhs) {
|
||||
if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2]) || (omin != rhs.omin))
|
||||
TRIQS_RUNTIME_ERROR<<"tails are incompatible";
|
||||
mask = rhs.mask;
|
||||
_data = rhs._data;
|
||||
return *this;
|
||||
}
|
||||
inline tail_view & operator=(const tail & rhs);
|
||||
|
||||
tail_view & operator = (std::complex<double> const & x) {
|
||||
_data() = 0.0;
|
||||
mv_type(_data(-omin, tqa::range(), tqa::range())) = x;
|
||||
mask() = omin+size()-1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
using B::operator(); // import all previously defined operator() for overloading
|
||||
friend std::ostream & triqs_nvl_formal_print(std::ostream & out, tail_view const & x) { return out<<"tail_view"; }
|
||||
void rebind(tail_view const &X);
|
||||
|
||||
tail_view &operator=(tail_view const &x) { return B::operator=(tail_const_view(x)), *this; }
|
||||
template <rvc_enum RVC> tail_view &operator=(tail_impl<RVC> const &x) { return B::operator=(tail_const_view(x)), *this; }
|
||||
tail_view &operator=(dcomplex);
|
||||
};
|
||||
|
||||
// -----------------------------
|
||||
// the regular class
|
||||
class tail: public tail_impl <false> {
|
||||
typedef tail_impl <false> B;
|
||||
friend class tail_view;
|
||||
class tail : public tail_impl<Regular> {
|
||||
using B = tail_impl<Regular>;
|
||||
// friend class tail_view;
|
||||
|
||||
public:
|
||||
tail():B() {}
|
||||
typedef tqa::mini_vector<size_t,2> shape_type;
|
||||
tail(size_t N1, size_t N2, size_t size_=10, long order_min=-1): B(N1,N2,size_,order_min) {}
|
||||
tail(shape_type const & sh, size_t size_=10, long order_min=-1): B(sh[0],sh[1],size_,order_min) {}
|
||||
tail(tqa::mini_vector<int,0>) : tail(1,1) {}
|
||||
tail(B::data_type const &d, B::mask_type const &m, long order_min): B(d, m, order_min) {}
|
||||
using shape_type = mini_vector<int, 2>;
|
||||
|
||||
tail() = default;
|
||||
tail(int N1, int N2, int size_ = 10, int order_min = -1) : B(N1, N2, size_, order_min) {}
|
||||
tail(shape_type const &sh, int size_ = 10, int order_min = -1) : B(sh[0], sh[1], size_, order_min) {}
|
||||
tail(mini_vector<int, 0>) : tail(1, 1) {}
|
||||
tail(B::data_type const &d, B::mask_type const &m, int order_min) : B(d, m, order_min) {}
|
||||
tail(tail const &g) : B(g) {}
|
||||
tail(tail_view const &g) : B(g) {}
|
||||
tail(tail_const_view const &g) : B(g) {}
|
||||
tail(tail &&) = default;
|
||||
|
||||
// operator = for values
|
||||
tail & operator = (tail_view const & rhs) {
|
||||
omin = rhs.omin;
|
||||
mask = rhs.mask;
|
||||
_data = rhs._data;
|
||||
return *this;
|
||||
}
|
||||
tail & operator = (tail const & rhs) {
|
||||
omin = rhs.omin;
|
||||
mask = rhs.mask;
|
||||
_data = rhs._data;
|
||||
return *this;
|
||||
}
|
||||
|
||||
using B::operator();
|
||||
|
||||
/// The simplest tail corresponding to omega
|
||||
static tail_view omega(size_t N1, size_t N2, size_t size_, long order_min) {
|
||||
tail t(N1, N2, size_, order_min);
|
||||
t(-1) = 1;
|
||||
return t;
|
||||
}
|
||||
|
||||
/// The simplest tail corresponding to omega, constructed from a shape for convenience
|
||||
static tail_view omega(tail::shape_type const & sh, size_t size_, long order_min) { return omega(sh[0],sh[1],size_,order_min); }
|
||||
|
||||
tail &operator=(tail const &x) { return B::operator=(tail_const_view(x)), *this; }
|
||||
template <rvc_enum RVC> tail &operator=(tail_impl<RVC> const &x) { return B::operator=(tail_const_view(x)), *this; }
|
||||
};
|
||||
|
||||
template<typename RHS> void assign_from_expression(tail_view t,RHS const & rhs) { t = rhs( tail::omega(t.shape(),t.size(),t.order_min()) ); }
|
||||
|
||||
inline void tail_view::rebind(tail const &X) {
|
||||
omin = X.omin;
|
||||
mask.rebind(X.mask);
|
||||
_data.rebind(X._data);
|
||||
}
|
||||
|
||||
inline tail_view & tail_view::operator = (const tail & rhs) {
|
||||
if ((_data.shape()[1] != rhs._data.shape()[1]) || (_data.shape()[2] != rhs._data.shape()[2]) || (omin != rhs.omin))
|
||||
// ---- impl. of = for base class -------------
|
||||
template <rvc_enum RVC> void tail_impl<RVC>::operator=(tail_const_view const &rhs) {
|
||||
if (RVC == Regular) {
|
||||
omin = rhs.order_min();
|
||||
} else {
|
||||
if ((_data.shape()[1] != rhs.data().shape()[1]) || (_data.shape()[2] != rhs.data().shape()[2]) || (omin != rhs.order_min()))
|
||||
TRIQS_RUNTIME_ERROR << "tails are incompatible";
|
||||
mask = rhs.mask;
|
||||
_data = rhs._data;
|
||||
return *this;
|
||||
}
|
||||
_mask = rhs.mask();
|
||||
_data = rhs.data();
|
||||
}
|
||||
|
||||
inline tail conj(tail_view t) { return {conj(t.data()), t.mask_view(),t.order_min()};}
|
||||
// ---- Factories -------------
|
||||
|
||||
inline tail transpose(tail_view t) { return {transposed_view(t.data(),0,2,1), transposed_view(t.mask_view(),1,0),t.order_min()};}
|
||||
/// The simplest tail corresponding to omega
|
||||
tail tail_omega(int N1, int N2, int size_ = 10, int order_min = -1);
|
||||
|
||||
/// The simplest tail corresponding to omega, constructed from a shape for convenience
|
||||
tail_view tail_omega(tail::shape_type const &sh, int size_, int order_min);
|
||||
|
||||
/// The simplest tail corresponding to omega, built from the shape, size, ordermin of t
|
||||
tail_view tail_omega(tail_view t);
|
||||
|
||||
// ---- IO -------------
|
||||
|
||||
std::ostream &operator<<(std::ostream &out, tail_const_view);
|
||||
|
||||
// ---- -------------
|
||||
|
||||
//
|
||||
template <typename RHS> void assign_singularity_from_function(tail_view t, RHS const &rhs) {
|
||||
t = rhs(tail_omega(t.shape(), t.size(), t.order_min()));
|
||||
}
|
||||
|
||||
// ---- Evaluate and compose -------------
|
||||
|
||||
/// Evaluate the tail to sum_{n=order_min}^ordermax M_n/omega^n
|
||||
matrix<dcomplex> evaluate(tail_const_view t, dcomplex const &omega);
|
||||
|
||||
tail compose(tail_const_view x, tail_const_view t);
|
||||
|
||||
// ---- Ops -------------
|
||||
|
||||
tail conj(tail_const_view const &t);
|
||||
tail transpose(tail_const_view const &t);
|
||||
|
||||
/// Slice in orbital space
|
||||
//template<bool V> tail_view slice_target(tail_impl<V> const & t, tqa::range R1, tqa::range R2)
|
||||
inline tail_view slice_target(tail_view t, tqa::range R1, tqa::range R2) {
|
||||
return tail_view(t.data()(tqa::range(),R1,R2), t.mask_view()(R1,R2), t.order_min());
|
||||
}
|
||||
tail_const_view slice_target(tail_const_view const &t, range R1, range R2);
|
||||
tail_view slice_target(tail_view t, range R1, range R2);
|
||||
inline tail_view slice_target(tail &t, range R1, range R2) { return slice_target(tail_view{t}, R1, R2);}
|
||||
inline tail_const_view slice_target(tail const &t, range R1, range R2) { return slice_target(tail_const_view{t}, R1, R2);}
|
||||
|
||||
inline tail inverse(tail_view const & t) {
|
||||
long omin1 = - t.smallest_nonzero();
|
||||
long omax1 = std::min(t.order_max() + 2*omin1, t.order_min()+long(t.size())-1);
|
||||
size_t si = omax1-omin1+1;
|
||||
tail inverse(tail_const_view const &t);
|
||||
|
||||
tail res(t.shape(), t.size(), t.order_min());
|
||||
res.mask_view() = omax1;
|
||||
/// ------------------- Arithmetic operations ------------------------------
|
||||
|
||||
res(omin1) = inverse(t(-omin1));
|
||||
tail operator+(tail_const_view const &l, tail_const_view const &r);
|
||||
tail operator-(tail_const_view const &l, tail_const_view const &r);
|
||||
|
||||
for (size_t n=1; n<si; n++) {
|
||||
for (size_t p=0; p<n; p++) {
|
||||
res(omin1 + n) -= t(n-omin1-p) * res(omin1+p);
|
||||
}
|
||||
res(omin1 + n) = res(omin1) * make_clone(res(omin1 + n));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// +/- with scalar or matrix.
|
||||
template <typename T>
|
||||
struct is_scalar_or_matrix : std::integral_constant<bool, arrays::ImmutableMatrix<std14::decay_t<T>>::value || utility::is_in_ZRC<T>::value> {};
|
||||
|
||||
inline tail inverse(tail const & t) { return inverse(tail_view(t));}
|
||||
|
||||
inline tail mult_impl(tail_view const & l, tail_view const& r) {
|
||||
if (l.shape()[1] != r.shape()[0] || l.order_min() != r.order_min() || l.size() != r.size())
|
||||
TRIQS_RUNTIME_ERROR<< "tail multiplication: shape mismatch";
|
||||
//long omin1 = l.smallest_nonzero() + r.smallest_nonzero();
|
||||
long omax1 = std::min(std::min(r.order_max()+l.smallest_nonzero(), l.order_max()+r.smallest_nonzero()), r.order_min()+long(r.size())-1);
|
||||
//size_t si = omax1-omin1+1;
|
||||
|
||||
tail res(l.shape(), l.size(), l.order_min());
|
||||
res.mask_view() = omax1;
|
||||
|
||||
for (long n=res.order_min(); n<=res.order_max(); ++n) {
|
||||
// sum_{p}^n a_p b_{n-p}. p <= a.n_max, p >= a.n_min and n-p <=b.n_max and n-p >= b.n_min
|
||||
// hence p <= min ( a.n_max, n-b.n_min ) and p >= max ( a.n_min, n- b.n_max)
|
||||
const long pmin = std::max(l.smallest_nonzero(), n - r.order_max() );
|
||||
const long pmax = std::min(l.order_max(), n - r.smallest_nonzero() );
|
||||
for (long p = pmin; p <= pmax; ++p) { res(n) += l(p) * r(n-p);}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
TYPE_ENABLE_IF(tail, mpl::and_<LocalTail<T1>, LocalTail<T2>>) operator*(T1 const &a, T2 const &b) {
|
||||
return mult_impl(a, b);
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
TYPE_ENABLE_IF(tail, mpl::and_<tqa::ImmutableMatrix<T1>, LocalTail<T2>>) operator*(T1 const &a, T2 const &b) {
|
||||
auto res = tail{first_dim(a), b.shape()[1], b.size(), b.order_min()};
|
||||
res.mask_view() = b.order_max();
|
||||
for (int n = res.order_min(); n <= res.order_max(); ++n) res(n) = a * b(n);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
TYPE_ENABLE_IF(tail, mpl::and_<LocalTail<T1>, tqa::ImmutableMatrix<T2>>) operator*(T1 const &a, T2 const &b) {
|
||||
auto res = tail{a.shape()[0], second_dim(b), a.size(), a.order_min()};
|
||||
res.mask_view() = a.order_max();
|
||||
for (int n = res.order_min(); n <= res.order_max(); ++n) res(n) = a(n) * b;
|
||||
return res;
|
||||
}
|
||||
|
||||
inline tail operator * (dcomplex a, tail_view const & r) { tail res(r); res.data()*=a; return res;}
|
||||
inline tail operator * (tail_view const & r, dcomplex a) { return a*r; }
|
||||
|
||||
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, LocalTail<T2>>)
|
||||
operator/ (T1 const & a, T2 const & b) { return a * inverse(b); }
|
||||
|
||||
inline tail operator / (tail_view const & r, dcomplex a) { tail res(r); res.data() /=a; return res;}
|
||||
inline tail operator / (dcomplex a, tail_view const & r) { return a * inverse(r); }
|
||||
|
||||
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, LocalTail<T2>>)
|
||||
operator + (T1 const & l, T2 const& r) {
|
||||
if (l.shape() != r.shape() || l.order_min() != r.order_min() || (l.size() != r.size()))
|
||||
TRIQS_RUNTIME_ERROR<< "tail addition: shape mismatch";
|
||||
tail res(l.shape(), l.size(), l.order_min());
|
||||
res.mask_view() = std::min(l.order_max(), r.order_max());
|
||||
for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) + r(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, LocalTail<T2>>)
|
||||
operator - (T1 const & l, T2 const& r) {
|
||||
if (l.shape() != r.shape() || l.order_min() != r.order_min() || (l.size() != r.size()))
|
||||
TRIQS_RUNTIME_ERROR<< "tail addition: shape mismatch";
|
||||
tail res(l.shape(), l.size(), l.order_min());
|
||||
res.mask_view() = std::min(l.order_max(), r.order_max());
|
||||
for (long i = res.order_min(); i<=res.order_max(); ++i) res(i) = l(i) - r(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<is_scalar_or_element<T1>, LocalTail<T2>>)
|
||||
operator + (T1 const & a, T2 const & t) {
|
||||
template <typename T> std14::enable_if_t<is_scalar_or_matrix<T>::value, tail> operator+(T const &a, tail_const_view const &t) {
|
||||
tail res(t);
|
||||
res(0) += a;
|
||||
return res;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, is_scalar_or_element<T2>>)
|
||||
operator + (T1 const & t, T2 const & a) { return a+t;}
|
||||
template <typename T> std14::enable_if_t<is_scalar_or_matrix<T>::value, tail> operator+(tail_const_view const &t, T const &a) {
|
||||
return a + t;
|
||||
}
|
||||
|
||||
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<is_scalar_or_element<T1>, LocalTail<T2>>)
|
||||
operator - (T1 const & a, T2 const & t) { return (-a) + t;}
|
||||
template <typename T> std14::enable_if_t<is_scalar_or_matrix<T>::value, tail> operator-(T const &a, tail_const_view const &t) {
|
||||
return (-a) + t;
|
||||
}
|
||||
|
||||
template <typename T> std14::enable_if_t<is_scalar_or_matrix<T>::value, tail> operator-(tail_const_view const &t, T const &a) {
|
||||
return (-a) + t;
|
||||
}
|
||||
|
||||
tail operator*(tail_const_view const &l, tail_const_view const &r);
|
||||
|
||||
tail operator*(matrix<dcomplex> const &a, tail_const_view const &b);
|
||||
tail operator*(tail_const_view const &a, matrix<dcomplex> const &b);
|
||||
template <typename T> tail operator*(matrix_view<T> const &a, tail_const_view const &b) { return matrix<dcomplex>(a) * b; }
|
||||
template <typename T> tail operator*(tail_const_view const &a, matrix_view<T> const &b) { return a * matrix<dcomplex>(b); }
|
||||
|
||||
tail operator*(dcomplex a, tail_const_view const &r);
|
||||
inline tail operator*(tail_const_view const &r, dcomplex a) { return a * r; }
|
||||
|
||||
inline tail operator/(tail_const_view const &a, tail_const_view const &b) { return a * inverse(b); }
|
||||
tail operator/(tail_const_view const &r, dcomplex a);
|
||||
inline tail operator/(dcomplex a, tail_view r) { return a * inverse(r); }
|
||||
|
||||
template<typename T1, typename T2> TYPE_ENABLE_IF(tail,mpl::and_<LocalTail<T1>, is_scalar_or_element<T2>>)
|
||||
operator - (T1 const & t, T2 const & a) { return (-a) + t;}
|
||||
|
||||
// inplace operators
|
||||
#define DEFINE_OPERATOR(OP1, OP2) \
|
||||
@ -411,6 +333,6 @@ namespace triqs { namespace gfs { namespace local {
|
||||
DEFINE_OPERATOR(/=, / );
|
||||
|
||||
#undef DEFINE_OPERATOR
|
||||
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,37 +22,47 @@
|
||||
#include "./tools.hpp"
|
||||
#include "./gf.hpp"
|
||||
#include "./local/tail.hpp"
|
||||
#include "./meshes/discrete.hpp"
|
||||
|
||||
namespace triqs {
|
||||
namespace gfs {
|
||||
|
||||
namespace gfs_implementation {
|
||||
|
||||
/*template <typename T> constexpr bool has_a_singularity() {
|
||||
return std::is_same<typename singularity<V1, Target>::type, local::tail>::value;
|
||||
template <typename Var, typename RHS, bool IsView>
|
||||
void assign_singularity_from_function(gf_impl<Var, tail, nothing, void, IsView, false> &s, RHS const &rhs) {
|
||||
auto t = tail_omega(s.get_from_linear_index(0));
|
||||
// a bit faster to first replace (some part of expression are precomputed).
|
||||
clef::placeholder<0> x_;
|
||||
//auto expr = rhs(x_, t);
|
||||
//for (auto x : s.mesh()) s[x] = eval(expr, x_ = x);
|
||||
for (auto x : s.mesh()) s[x] = rhs(x, t);
|
||||
}
|
||||
|
||||
/// --------------------------- singularity ---------------------------------
|
||||
|
||||
template <typename V1, typename V2, typename Target, typename Opt> struct singularity<cartesian_product<V1,V2>, Target, Opt> {
|
||||
using type = std14::conditional_t < (!has_a_singularity<V1>()) && has_a_singularity<V2>(), gf<V1, local::tail>, nothing > ;
|
||||
template <typename V1, typename V2, typename Target> struct gf_default_singularity<cartesian_product<V1, V2>, Target> {
|
||||
using S1 = typename gf_default_singularity<V1, Target>::type;
|
||||
using S2 = typename gf_default_singularity<V2, Target>::type;
|
||||
// type is nothing unless S1 is nothing and S2 is not, or 1 <-> 2
|
||||
using type = std14::conditional_t < is_nothing<S1>() && (!is_nothing<S2>()), gf<V1, S2>,
|
||||
std14::conditional_t < is_nothing<S2>() && (!is_nothing<S1>()), gf<V2, S1>, nothing >>
|
||||
;
|
||||
};
|
||||
*/
|
||||
|
||||
namespace gfs_implementation {
|
||||
|
||||
/// --------------------------- hdf5 ---------------------------------
|
||||
|
||||
template <typename Variable, typename Opt> struct h5_name<Variable, local::tail, nothing, Opt> {
|
||||
template <typename Variable, typename Opt> struct h5_name<Variable, tail, nothing, Opt> {
|
||||
static std::string invoke() { return "xxxxx"; }
|
||||
};
|
||||
|
||||
template <typename Variable, typename Opt> struct h5_rw<Variable, local::tail, nothing, Opt> {
|
||||
template <typename Variable, typename Opt> struct h5_rw<Variable, tail, nothing, Opt> {
|
||||
|
||||
static void write(h5::group gr, gf_const_view<Variable, local::tail, nothing, Opt> g) {
|
||||
for (size_t i = 0; i < g.mesh().size(); ++i) h5_write(gr, std::to_string(i), g._data[i]);
|
||||
static void write(h5::group gr, gf_const_view<Variable, tail, nothing, Opt> g) {
|
||||
// for (size_t i = 0; i < g.mesh().size(); ++i) h5_write(gr, std::to_string(i), g._data[i]);
|
||||
// h5_write(gr,"symmetry",g._symmetry);
|
||||
}
|
||||
|
||||
template <bool IsView> static void read(h5::group gr, gf_impl<Variable, local::tail, nothing, Opt, IsView, false> &g) {
|
||||
template <bool IsView> static void read(h5::group gr, gf_impl<Variable, tail, nothing, Opt, IsView, false> &g) {
|
||||
// does not work : need to read the block name and remake the mesh...
|
||||
// g._mesh = gf_mesh<block_index, Opt>(gr.get_all_subgroup_names());
|
||||
// g._data.resize(g._mesh.size());
|
||||
@ -62,43 +72,91 @@ namespace gfs {
|
||||
}
|
||||
};
|
||||
|
||||
/// --------------------------- data access ---------------------------------
|
||||
// --------------------------- data access ---------------------------------
|
||||
|
||||
template <typename Variable, typename Opt> struct data_proxy<Variable, local::tail, Opt> : data_proxy_vector<local::tail> {};
|
||||
template <typename Variable, typename Opt> struct data_proxy<Variable, tail, Opt> {
|
||||
|
||||
// ------------------------------- Factories --------------------------------------------------
|
||||
struct storage_t {
|
||||
arrays::array<dcomplex, 4> data;
|
||||
arrays::array<int, 2> mask;
|
||||
int omin;
|
||||
};
|
||||
|
||||
template <typename Variable, typename Opt> struct factories<Variable, local::tail, nothing, Opt> {
|
||||
using mesh_t=gf_mesh<Variable, Opt> ;
|
||||
using gf_t=gf<Variable, local::tail> ;
|
||||
//using gf_view_t=gf_view<block_index, Target> ;
|
||||
struct target_shape_t {};
|
||||
using aux_t = nothing;
|
||||
struct storage_view_t {
|
||||
arrays::array_view<dcomplex, 4> data;
|
||||
arrays::array_view<int, 2> mask;
|
||||
int omin;
|
||||
template<typename S> storage_view_t(S &s): data(s.data), mask(s.mask), omin(s.omin){}
|
||||
};
|
||||
|
||||
static typename gf_t::data_t make_data(mesh_t const &m, target_shape_t, aux_t) { return std::vector<local::tail>(m.size()); }
|
||||
static nothing make_singularity(mesh_t const &m, target_shape_t) {
|
||||
return {};
|
||||
struct storage_const_view_t {
|
||||
arrays::array_const_view<dcomplex, 4> data;
|
||||
arrays::array_const_view<int, 2> mask;
|
||||
int omin;
|
||||
template<typename S> storage_const_view_t(S &s): data(s.data), mask(s.mask), omin(s.omin){}
|
||||
};
|
||||
|
||||
// from the shape of the mesh and the target, make the shape of the array. default is to glue them
|
||||
// template <typename S1, typename S2> static auto join_shape(S1 const &s1, S2 const &s2) { return make_shape(join(s1, s2); }
|
||||
|
||||
template <typename S, typename RHS> static void assign_to_scalar(S &data, RHS &&rhs) { data() = std::forward<RHS>(rhs); }
|
||||
template <typename ST, typename RHS> static void rebind(ST &data, RHS &&rhs) { data.rebind(rhs.data()); }
|
||||
|
||||
template <typename S> tail_view operator()(S &data, int i) const {
|
||||
return {data.data(i, arrays::ellipsis()), data.mask, data.omin};
|
||||
}
|
||||
|
||||
template <typename S> tail_const_view operator()(S const &data, int i) const {
|
||||
return {data.data(i, arrays::ellipsis()), data.mask, data.omin};
|
||||
}
|
||||
};
|
||||
|
||||
// partial_eval
|
||||
template <typename Variable, typename Opt, bool IsConst> struct partial_eval_impl<Variable, local::tail, nothing, Opt, IsConst> {
|
||||
// ------------------------------- Factory for data --------------------------------------------------
|
||||
|
||||
using gv_t = gf_view<Variable, local::tail, nothing, Opt, IsConst>;
|
||||
template <typename Variable, typename Opt> struct data_factory<Variable, tail, nothing, Opt> {
|
||||
using mesh_t = gf_mesh<Variable, Opt>;
|
||||
using gf_t = gf<Variable, tail>;
|
||||
using target_shape_t = arrays::mini_vector<int, 2>;
|
||||
// struct target_shape_t {};
|
||||
using aux_t = nothing;
|
||||
|
||||
static typename gf_t::data_t make(mesh_t const &m, target_shape_t sh, aux_t) {
|
||||
auto t = tail(sh); // build a defaut tail
|
||||
// and duplicate it over the mesh size
|
||||
return {arrays::array<dcomplex, 4>{t.data().shape().front_append(m.size())}, arrays::array<int, 2>{t.shape()},
|
||||
t.order_min()};
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------- Factory for singularity --------------------------------------------------
|
||||
|
||||
template <typename V1, typename V2, typename Target, typename Opt>
|
||||
struct singularity_factory<cartesian_product<V1, V2>, Target, gf<V1, tail, nothing, void>, Opt> {
|
||||
template <typename TargetShape>
|
||||
static gf<V1, tail> make(gf_mesh<cartesian_product<V1, V2>, Opt> const &m, TargetShape shape) {
|
||||
return {std::get<0>(m.components()), shape};
|
||||
}
|
||||
};
|
||||
|
||||
// ------------------------------- partial_eval --------------------------------------------------
|
||||
|
||||
template <typename Variable, typename Opt, bool IsConst>
|
||||
struct partial_eval_impl<Variable, tail, nothing, Opt, IsConst> {
|
||||
|
||||
using gv_t = gf_view<Variable, tail, nothing, Opt, IsConst>;
|
||||
template <int... pos, typename... T> static auto invoke(gv_t g, T const &... x) {
|
||||
return invoke_impl(g, std14::index_sequence<pos...>(), x...);
|
||||
}
|
||||
|
||||
template <typename T> static local::tail_view invoke_impl(gv_t g, std14::index_sequence<0>, T const &x) {
|
||||
return g[g.mesh().index_to_linear(x)];
|
||||
template <typename T> static tail_view invoke_impl(gv_t g, std14::index_sequence<0>, T const &x) {
|
||||
return g.get_from_linear_index(x);
|
||||
}
|
||||
|
||||
template <typename T> static nothing invoke_impl(gv_t g, std14::index_sequence<1>, T const &x) {
|
||||
return {};
|
||||
template <typename T> static gv_t invoke_impl(gv_t g, std14::index_sequence<1>, T const &x) {
|
||||
return g;
|
||||
}
|
||||
};
|
||||
|
||||
} // gfs_implementation
|
||||
|
||||
|
||||
}}
|
||||
|
@ -65,10 +65,10 @@ namespace gfs {
|
||||
}
|
||||
|
||||
domain_t const &domain() const { return _dom; }
|
||||
size_t size() const { return L; }
|
||||
long size() const { return L; }
|
||||
|
||||
utility::mini_vector<size_t, 1> size_of_components() const {
|
||||
return {size()};
|
||||
return {size_t(size())};
|
||||
}
|
||||
|
||||
double delta() const { return del; }
|
||||
@ -79,7 +79,6 @@ namespace gfs {
|
||||
/// Conversions point <-> index <-> linear_index
|
||||
domain_pt_t index_to_point(index_t ind) const { return xmin + ind * del; }
|
||||
|
||||
public:
|
||||
long index_to_linear(index_t ind) const { return ind; }
|
||||
|
||||
/// The wrapper for the mesh point
|
||||
|
@ -150,7 +150,7 @@ namespace gfs {
|
||||
const_iterator cend() const { return const_iterator(this, true); }
|
||||
|
||||
bool operator==(matsubara_freq_mesh const &M) const {
|
||||
return (std::make_tuple(_dom, _n_pts, _positive_only) == std::make_tuple(M._dom, M._n_pts, M._positive_only));
|
||||
return (std::tie(_dom, _n_pts, _positive_only) == std::tie(M._dom, M._n_pts, M._positive_only));
|
||||
}
|
||||
bool operator!=(matsubara_freq_mesh const &M) const { return !(operator==(M)); }
|
||||
|
||||
|
@ -70,14 +70,14 @@ namespace gfs {
|
||||
/// --------------------------- hdf5 ---------------------------------
|
||||
|
||||
// h5 name : name1_x_name2_.....
|
||||
template <typename Opt, typename... Ms> struct h5_name<cartesian_product<Ms...>, matrix_valued, nothing, Opt> {
|
||||
template <typename Opt, typename S, typename... Ms> struct h5_name<cartesian_product<Ms...>, matrix_valued, S, Opt> {
|
||||
static std::string invoke() {
|
||||
return triqs::tuple::fold([](std::string a, std::string b) { return a + std::string(b.empty() ? "" : "_x_") + b; },
|
||||
std::make_tuple(h5_name<Ms, matrix_valued, nothing, Opt>::invoke()...), std::string());
|
||||
reverse(std::make_tuple(h5_name<Ms, matrix_valued, nothing, Opt>::invoke()...)), std::string());
|
||||
}
|
||||
};
|
||||
template <typename Opt, int R, typename... Ms>
|
||||
struct h5_name<cartesian_product<Ms...>, tensor_valued<R>, nothing, Opt> : h5_name<cartesian_product<Ms...>, matrix_valued, nothing, Opt> {};
|
||||
template <typename Opt, typename S, int R, typename... Ms>
|
||||
struct h5_name<cartesian_product<Ms...>, tensor_valued<R>, S, Opt> : h5_name<cartesian_product<Ms...>, matrix_valued, S, Opt> {};
|
||||
|
||||
/// --------------------------- evaluator ---------------------------------
|
||||
|
||||
@ -110,22 +110,27 @@ namespace gfs {
|
||||
template <typename G, typename Tn, typename Ev, int pos> struct binder;
|
||||
|
||||
template <int pos, typename G, typename Tn, typename Ev> binder<G, Tn, Ev, pos> make_binder(G const *g, Tn tn, Ev const &ev) {
|
||||
return binder<G, Tn, Ev, pos>{g, std::move(tn), ev};
|
||||
return {g, std::move(tn), ev};
|
||||
}
|
||||
|
||||
template <typename G, typename Tn, typename Ev, int pos> struct binder {
|
||||
G const *g;
|
||||
Tn tn;
|
||||
Ev const &evals;
|
||||
auto operator()(size_t p) const
|
||||
DECL_AND_RETURN(std::get<pos>(evals)(make_binder<pos - 1>(g, triqs::tuple::push_front(tn, p), evals)));
|
||||
template <size_t... Is> decltype(auto) impl(size_t p, std14::index_sequence<Is...>) const {
|
||||
return std::get<pos>(evals)(make_binder<pos - 1>(g, std::make_tuple(p, std::get<Is>(tn)...), evals));
|
||||
}
|
||||
decltype(auto) operator()(size_t p) const { return impl(p, std14::make_index_sequence<std::tuple_size<Tn>::value>()); }
|
||||
};
|
||||
|
||||
template <typename G, typename Tn, typename Ev> struct binder<G, Tn, Ev, -1> {
|
||||
G const *g;
|
||||
Tn tn;
|
||||
Ev const &evals;
|
||||
auto operator()(size_t p) const DECL_AND_RETURN(triqs::tuple::apply(on_mesh(*g), triqs::tuple::push_front(tn, p)));
|
||||
template <size_t... Is> decltype(auto) impl(size_t p, std14::index_sequence<Is...>) const {
|
||||
return g->get_from_linear_index(p, std::get<Is>(tn)...);
|
||||
}
|
||||
decltype(auto) operator()(size_t p) const { return impl(p, std14::make_index_sequence<std::tuple_size<Tn>::value>()); }
|
||||
};
|
||||
|
||||
// now the multi d evaluator itself.
|
||||
@ -133,21 +138,11 @@ namespace gfs {
|
||||
static constexpr int arity = sizeof...(Ms);
|
||||
mutable std::tuple<evaluator_fnt_on_mesh<Ms>...> evals;
|
||||
|
||||
struct _poly_lambda { // replace by a polymorphic lambda in C++14
|
||||
template <typename A, typename B, typename C> void operator()(A &a, B const &b, C const &c) const {
|
||||
a = A{b, c};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename G, typename... Args>
|
||||
// std::complex<double> operator() (G const * g, Args && ... args) const {
|
||||
auto operator()(G const *g, Args &&... args)
|
||||
const -> decltype(std::get<sizeof...(Args) - 1>(evals)(make_binder<sizeof...(Args) - 2>(g, std::make_tuple(), evals)))
|
||||
// when do we get C++14 decltype(auto) ...!?
|
||||
{
|
||||
template <typename G, typename... Args> decltype(auto) operator()(G const *g, Args &&... args) const {
|
||||
static constexpr int R = sizeof...(Args);
|
||||
// build the evaluators, as a tuple of ( evaluator<Ms> ( mesh_component, args))
|
||||
triqs::tuple::for_each_zip(_poly_lambda(), evals, g->mesh().components(), std::make_tuple(args...));
|
||||
auto l = [](auto &a, auto &b, auto &c) { a = std14::decay_t<decltype(a)>{b, c}; };
|
||||
triqs::tuple::for_each_zip(l, evals, g->mesh().components(), std::make_tuple(args...));
|
||||
return std::get<R - 1>(evals)(make_binder<R - 2>(g, std::make_tuple(), evals));
|
||||
}
|
||||
};
|
||||
|
@ -37,10 +37,10 @@ namespace gfs {
|
||||
|
||||
// singularity
|
||||
template <> struct gf_default_singularity<refreq, matrix_valued> {
|
||||
using type = local::tail;
|
||||
using type = tail;
|
||||
};
|
||||
template <> struct gf_default_singularity<refreq, scalar_valued> {
|
||||
using type = local::tail;
|
||||
using type = tail;
|
||||
};
|
||||
|
||||
namespace gfs_implementation {
|
||||
|
@ -37,10 +37,10 @@ namespace gfs {
|
||||
|
||||
// singularity
|
||||
template <> struct gf_default_singularity<retime, matrix_valued> {
|
||||
using type = local::tail;
|
||||
using type = tail;
|
||||
};
|
||||
template <> struct gf_default_singularity<retime, scalar_valued> {
|
||||
using type = local::tail;
|
||||
using type = tail;
|
||||
};
|
||||
|
||||
namespace gfs_implementation {
|
||||
|
@ -55,8 +55,6 @@ namespace gfs {
|
||||
Fermion
|
||||
};
|
||||
|
||||
struct freq_infty {}; // the point at infinity
|
||||
|
||||
//------------------------------------------------------
|
||||
|
||||
template <typename... T> struct closest_pt_wrap;
|
||||
@ -171,6 +169,7 @@ namespace gfs {
|
||||
struct nothing {
|
||||
template <typename... Args> explicit nothing(Args &&...) {} // takes anything, do nothing..
|
||||
nothing() {}
|
||||
using const_view_type = nothing;
|
||||
using view_type = nothing;
|
||||
using regular_type = nothing;
|
||||
void rebind(nothing) {}
|
||||
@ -181,15 +180,19 @@ namespace gfs {
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive> void serialize(Archive &ar, const unsigned int version) {}
|
||||
friend nothing operator+(nothing, nothing) { return nothing(); }
|
||||
template <typename RHS> friend void assign_from_expression(nothing &, RHS) {}
|
||||
template <typename RHS> friend void assign_singularity_from_function(nothing &, RHS) {}
|
||||
template<typename A> bool check_size(A) {return true;}
|
||||
bool is_empty() const { return false;}
|
||||
};
|
||||
|
||||
// Check if T is nothing
|
||||
template <typename T> constexpr bool is_nothing() { return std::is_same<nothing, T>::value; }
|
||||
|
||||
template<int ... pos, typename ...T> nothing partial_eval(nothing, T&&...) { return {};}
|
||||
inline nothing transpose(nothing) { return {};}
|
||||
inline nothing inverse(nothing) { return {};}
|
||||
inline nothing conj(nothing) { return {};}
|
||||
template <typename T> nothing compose(nothing,T&) { return {};}
|
||||
template <typename... T> nothing slice_target(nothing, T...) { return nothing(); }
|
||||
template <typename T> nothing operator+(nothing, T const &) { return nothing(); }
|
||||
template <typename T> nothing operator-(nothing, T const &) { return nothing(); }
|
||||
|
@ -40,6 +40,13 @@ namespace h5 {
|
||||
template <typename T>
|
||||
struct has_h5_write<T, decltype(h5_write(std::declval<h5::group>(), std::string(), std::declval<const T>()))> : std::true_type {
|
||||
};
|
||||
|
||||
// A generic read
|
||||
template <typename T> T h5_read(group gr, std::string const& name) {
|
||||
T x;
|
||||
h5_read(gr, name, x);
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,11 @@ namespace h5 {
|
||||
} // impl namespace
|
||||
|
||||
|
||||
void h5_write(group f, std::string const &name, std::vector<int> const &V) { h5_write_vector_impl(f, name, V); }
|
||||
void h5_write(group f, std::string const &name, std::vector<double> const &V) { h5_write_vector_impl(f, name, V); }
|
||||
void h5_write(group f, std::string const &name, std::vector<std::complex<double>> const &V) { h5_write_vector_impl(f, name, V); }
|
||||
|
||||
void h5_read(group f, std::string const &name, std::vector<int> &V) { h5_read_impl(f, name, V); }
|
||||
void h5_read(group f, std::string const &name, std::vector<double> &V) { h5_read_impl(f, name, V); }
|
||||
void h5_read(group f, std::string const &name, std::vector<std::complex<double>> &V) { h5_read_impl(f, name, V); }
|
||||
}
|
||||
|
@ -38,9 +38,11 @@ namespace triqs {
|
||||
void h5_write (group f, std::string const & name, std::vector<std::string> const & V);
|
||||
void h5_read (group f, std::string const & name, std::vector<std::string> & V);
|
||||
|
||||
void h5_write (group f, std::string const & name, std::vector<int> const & V);
|
||||
void h5_write (group f, std::string const & name, std::vector<double> const & V);
|
||||
void h5_write (group f, std::string const & name, std::vector<std::complex<double>> const & V);
|
||||
|
||||
void h5_read (group f, std::string const & name, std::vector<int> & V);
|
||||
void h5_read (group f, std::string const & name, std::vector<double> & V);
|
||||
void h5_read (group f, std::string const & name, std::vector<std::complex<double>> & V);
|
||||
|
||||
|
@ -60,6 +60,7 @@ namespace lattice {
|
||||
|
||||
/// The wrapper for the mesh point
|
||||
class mesh_point_t : gfs::tag::mesh_point, public utility::arithmetic_ops_by_cast<mesh_point_t, domain_pt_t> {
|
||||
public :
|
||||
bz_mesh const *m;
|
||||
index_t _index;
|
||||
|
||||
|
135
triqs/lattice/cyclic_lattice.hpp
Normal file
135
triqs/lattice/cyclic_lattice.hpp
Normal file
@ -0,0 +1,135 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2014 by O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <triqs/arrays.hpp>
|
||||
#include <triqs/utility/index_generator.hpp>
|
||||
//#include <string>
|
||||
//#include <vector>
|
||||
|
||||
namespace triqs {
|
||||
namespace lattice {
|
||||
|
||||
class cyclic_lattice_mesh {
|
||||
|
||||
utility::mini_vector<int, 3> dims; // the size in each dimension
|
||||
size_t _size = dims[0] * dims[1] * dims[2]; // total size
|
||||
long s1 = dims[0]; // stride
|
||||
long s2 = dims[0] * dims[1]; // stride
|
||||
|
||||
long _modulo(long r, int i) const {
|
||||
long res = r % dims[i];
|
||||
return (res >= 0 ? res : res + dims[i]);
|
||||
}
|
||||
|
||||
public:
|
||||
cyclic_lattice_mesh(int L1 = 1, int L2 = 1, int L3 = 1) : dims{L1, L2, L3} {}
|
||||
|
||||
int rank() const { return (dims[2] > 1 ? 3 : (dims[1] > 1 ? 2 : 1)); }
|
||||
|
||||
utility::mini_vector<int, 3> get_dimensions() const { return dims; }
|
||||
|
||||
/// ---------- Model the domain concept ---------------------
|
||||
using point_t = arrays::vector<int>; // domain concept. PUT on STACK
|
||||
|
||||
/// ----------- Model the mesh concept ----------------------
|
||||
using domain_t = cyclic_lattice_mesh;
|
||||
domain_t const& domain() const { return *this; }
|
||||
|
||||
using index_t = utility::mini_vector<long, 3>;
|
||||
using linear_index_t = long;
|
||||
|
||||
size_t size() const { return _size; }
|
||||
|
||||
utility::mini_vector<size_t, 1> size_of_components() const {
|
||||
return {size()};
|
||||
}
|
||||
|
||||
point_t index_to_point(index_t const& i) const {
|
||||
return {i[0], i[1], i[2]}; // not very good.
|
||||
}
|
||||
|
||||
/// flatten the index
|
||||
linear_index_t index_to_linear(index_t const& i) const {
|
||||
return _modulo(i[0], 0) + _modulo(i[1], 1) * s1 + _modulo(i[2], 2) * s2;
|
||||
}
|
||||
// linear_index_t index_to_linear(index_t const& i) const { return i[0] + i[1] * s1 + i[2] * s2; }
|
||||
|
||||
/// The wrapper for the mesh point
|
||||
class mesh_point_t : public utility::index3_generator, public utility::arithmetic_ops_by_cast<mesh_point_t, point_t> {
|
||||
cyclic_lattice_mesh const* m = nullptr;
|
||||
|
||||
public:
|
||||
mesh_point_t() = default;
|
||||
// explicit is important for g[ {1,2}] to disambiguate the mesh_point_t and the mesh_index_t
|
||||
explicit mesh_point_t(cyclic_lattice_mesh const& mesh, index_t const& index)
|
||||
: index3_generator(mesh.get_dimensions(), index), m(&mesh) {}
|
||||
mesh_point_t(cyclic_lattice_mesh const& mesh) : mesh_point_t(mesh, {0, 0, 0}) {}
|
||||
operator point_t() const { return m->index_to_point(index()); }
|
||||
// linear_index_t linear_index() const { return m->index_to_linear(index()); }
|
||||
// The mesh point behaves like a vector
|
||||
long operator()(int i) const { return index()[i]; }
|
||||
long operator[](int i) const { return operator()(i); }
|
||||
friend std::ostream& operator<<(std::ostream& out, mesh_point_t const& x) { return out << x.index(); }
|
||||
};
|
||||
|
||||
/// Accessing a point of the mesh
|
||||
mesh_point_t operator[](index_t i) const {
|
||||
return mesh_point_t{*this, i};
|
||||
}
|
||||
|
||||
/// Iterating on all the points...
|
||||
using const_iterator = gfs::mesh_pt_generator<cyclic_lattice_mesh>;
|
||||
const_iterator begin() const { return const_iterator(this); }
|
||||
const_iterator end() const { return const_iterator(this, true); }
|
||||
const_iterator cbegin() const { return const_iterator(this); }
|
||||
const_iterator cend() const { return const_iterator(this, true); }
|
||||
|
||||
/// ----------- End mesh concept ----------------------
|
||||
|
||||
/// Reduce point modulo to the lattice.
|
||||
mesh_point_t modulo_reduce(index_t const& r) const {
|
||||
return mesh_point_t{*this, {_modulo(r[0], 0), _modulo(r[1], 1), _modulo(r[2], 2)}};
|
||||
}
|
||||
|
||||
/// Write into HDF5
|
||||
friend void h5_write(h5::group fg, std::string subgroup_name, cyclic_lattice_mesh const& m) {
|
||||
h5::group gr = fg.create_group(subgroup_name);
|
||||
h5_write(gr, "dims", m.dims.to_vector());
|
||||
}
|
||||
|
||||
/// Read from HDF5
|
||||
friend void h5_read(h5::group fg, std::string subgroup_name, cyclic_lattice_mesh& m) {
|
||||
h5::group gr = fg.open_group(subgroup_name);
|
||||
auto dims = h5::h5_read<std::vector<int>>(gr, "dims");
|
||||
m = cyclic_lattice_mesh(dims[0], dims[1], dims[2]);
|
||||
}
|
||||
|
||||
// BOOST Serialization
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive> void serialize(Archive& ar, const unsigned int version) {
|
||||
ar& TRIQS_MAKE_NVP("dims", dims);
|
||||
ar& TRIQS_MAKE_NVP("_size", _size);
|
||||
ar& TRIQS_MAKE_NVP("s2", s2);
|
||||
ar& TRIQS_MAKE_NVP("s1", s1);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
150
triqs/lattice/regular_bz_mesh.hpp
Normal file
150
triqs/lattice/regular_bz_mesh.hpp
Normal file
@ -0,0 +1,150 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2014 by O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include <triqs/utility/index_generator.hpp>
|
||||
#include <triqs/h5/vector.hpp>
|
||||
#include "./brillouin_zone.hpp"
|
||||
#include "../gfs/tools.hpp"
|
||||
#include "../gfs/meshes/mesh_tools.hpp"
|
||||
|
||||
namespace triqs {
|
||||
namespace lattice {
|
||||
|
||||
class regular_bz_mesh {
|
||||
|
||||
brillouin_zone bz; //
|
||||
utility::mini_vector<int, 3> dims = {1, 1, 1}; // the size in each dimension
|
||||
size_t _size = dims[0] * dims[1] * dims[2]; // total size
|
||||
long s1 = dims[0]; // stride
|
||||
long s2 = dims[0] * dims[1]; // stride
|
||||
utility::mini_vector<double, 3> step = {2 * M_PI / dims[0], 2 * M_PI / dims[1], 2 * M_PI / dims[2]};
|
||||
|
||||
public:
|
||||
regular_bz_mesh() = default;
|
||||
|
||||
regular_bz_mesh(brillouin_zone const& bz, int n_l)
|
||||
: bz(bz), dims{n_l, (bz.lattice().dim() >= 2 ? n_l : 1), (bz.lattice().dim() >= 3 ? n_l : 1)} {}
|
||||
|
||||
int rank() const { return (dims[2] > 1 ? 3 : (dims[1] > 1 ? 2 : 1)); }
|
||||
|
||||
utility::mini_vector<int, 3> get_dimensions() const { return dims; }
|
||||
|
||||
/// ----------- Model the mesh concept ----------------------
|
||||
using domain_t = brillouin_zone;
|
||||
using domain_pt_t = typename domain_t::point_t;
|
||||
domain_t const& domain() const { return bz; }
|
||||
|
||||
using index_t = utility::mini_vector<long, 3>;
|
||||
using linear_index_t = long;
|
||||
|
||||
size_t size() const { return _size; }
|
||||
|
||||
utility::mini_vector<size_t, 1> size_of_components() const {
|
||||
return {size()};
|
||||
}
|
||||
|
||||
k_t index_to_point(index_t const& i) const {
|
||||
return {i[0] * step[0], i[1] * step[1], i[2] * step[2]};
|
||||
//return {(i[0] + 0.5) * step[0], (i[1] + 0.5) * step[1], (i[2] + 0.5) * step[2]};
|
||||
}
|
||||
|
||||
// flatten the index
|
||||
linear_index_t index_to_linear(index_t const& i) const { return i[0] + i[1] * s1 + i[2] * s2; }
|
||||
|
||||
// f (k) -> void where k is a k_t, a point in the BZ
|
||||
template <typename F> friend void foreach(regular_bz_mesh const& m, F f) {
|
||||
k_t k = {0,0,0}; //{0.5 * m.step[0], 0.5 * m.step[1], 0.5 * m.step[2]};
|
||||
for (long i2 = 0; i2 < m.dims[2]; ++i2, k(2) += m.step[2])
|
||||
for (long i1 = 0; i1 < m.dims[1]; ++i1, k(1) += m.step[1])
|
||||
for (long i0 = 0; i0 < m.dims[0]; ++i0, k(0) += m.step[0]) f(k);
|
||||
}
|
||||
|
||||
/// The wrapper for the mesh point
|
||||
class mesh_point_t : public utility::index3_generator, public utility::arithmetic_ops_by_cast<mesh_point_t, domain_pt_t> {
|
||||
regular_bz_mesh const* m = nullptr;
|
||||
|
||||
public:
|
||||
mesh_point_t() = default;
|
||||
mesh_point_t(regular_bz_mesh const& mesh, index_t const& index) : index3_generator(mesh.get_dimensions(), index), m(&mesh) {}
|
||||
mesh_point_t(regular_bz_mesh const& mesh) : mesh_point_t(mesh, {0,0,0}) {}
|
||||
operator domain_pt_t() const { return m->index_to_point(index()); }
|
||||
linear_index_t linear_index() const { return m->index_to_linear(index()); }
|
||||
// The mesh point behaves like a vector // NOT GOOD : take the ith componenet, this is SLOW
|
||||
double operator()(int i) const { return index()[i] * m->step[i]; }
|
||||
//double operator()(int i) const { return (index()[i] + 0.5) * m->step[i]; }
|
||||
double operator[](int i) const { return operator()(i);}
|
||||
friend std::ostream& operator<<(std::ostream& out, mesh_point_t const& x) { return out << (domain_pt_t)x; }
|
||||
};
|
||||
|
||||
/// Accessing a point of the mesh
|
||||
mesh_point_t operator[](index_t i) const {
|
||||
return {*this, i};
|
||||
}
|
||||
|
||||
/// Iterating on all the points...
|
||||
using const_iterator = gfs::mesh_pt_generator<regular_bz_mesh>;
|
||||
const_iterator begin() const { return const_iterator(this); }
|
||||
const_iterator end() const { return const_iterator(this, true); }
|
||||
const_iterator cbegin() const { return const_iterator(this); }
|
||||
const_iterator cend() const { return const_iterator(this, true); }
|
||||
|
||||
/// ----------- End mesh concept ----------------------
|
||||
|
||||
/// locate the closest point
|
||||
mesh_point_t locate_neighbours(k_t const& k) const {
|
||||
auto l = [&](int i) {
|
||||
long r = std::lround(k(i) / step[i]) % dims[i];
|
||||
return (r >= 0 ? r : r + dims[i]);
|
||||
};
|
||||
return {*this, {l(0), l(1), l(2)}};
|
||||
}
|
||||
|
||||
/// Write into HDF5
|
||||
friend void h5_write(h5::group fg, std::string subgroup_name, regular_bz_mesh const& m) {
|
||||
h5::group gr = fg.create_group(subgroup_name);
|
||||
h5_write(gr, "domain", m.domain());
|
||||
h5_write(gr, "n_pts", m.dims[2]);
|
||||
//h5_write(gr, "dims", m.dims.to_vector());
|
||||
}
|
||||
|
||||
/// Read from HDF5
|
||||
friend void h5_read(h5::group fg, std::string subgroup_name, regular_bz_mesh& m) {
|
||||
h5::group gr = fg.open_group(subgroup_name);
|
||||
auto bz = h5::h5_read<brillouin_zone>(gr, "domain");
|
||||
auto dims = h5::h5_read<int>(gr, "n_pts");
|
||||
m = regular_bz_mesh(bz, dims);
|
||||
//auto dims = h5::h5_read<std::vector<int>>(gr, "dims");
|
||||
//m = regular_bz_mesh(bz, {dims[0], dims[1], dims[2]}); // NOT CORRECT IN GENERAL
|
||||
}
|
||||
|
||||
// BOOST Serialization
|
||||
friend class boost::serialization::access;
|
||||
template <class Archive> void serialize(Archive& ar, const unsigned int version) {
|
||||
ar& TRIQS_MAKE_NVP("dims", dims);
|
||||
ar& TRIQS_MAKE_NVP("_size", _size);
|
||||
ar& TRIQS_MAKE_NVP("s2", s2);
|
||||
ar& TRIQS_MAKE_NVP("s1", s1);
|
||||
ar& TRIQS_MAKE_NVP("step", step);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
61
triqs/utility/index_generator.hpp
Normal file
61
triqs/utility/index_generator.hpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*******************************************************************************
|
||||
*
|
||||
* TRIQS: a Toolbox for Research in Interacting Quantum Systems
|
||||
*
|
||||
* Copyright (C) 2014 by O. Parcollet
|
||||
*
|
||||
* TRIQS is free software: you can redistribute it and/or modify it under the
|
||||
* terms of the GNU General Public License as published by the Free Software
|
||||
* Foundation, either version 3 of the License, or (at your option) any later
|
||||
* version.
|
||||
*
|
||||
* TRIQS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* TRIQS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
******************************************************************************/
|
||||
#pragma once
|
||||
#include "./mini_vector.hpp"
|
||||
|
||||
namespace triqs {
|
||||
namespace utility {
|
||||
|
||||
class index3_generator {
|
||||
mini_vector<long, 3> i, d; // rely on mini_vector initialization
|
||||
long i_flat =0;
|
||||
bool _at_end = false;
|
||||
|
||||
public:
|
||||
index3_generator() = default;
|
||||
index3_generator(mini_vector<long, 3> const& dims, mini_vector<long, 3> const &i) : d(dims),i(i) {}
|
||||
void advance() {
|
||||
++i_flat;
|
||||
++i[2];
|
||||
if (i[2] < d[2]) return;
|
||||
i[2] = 0;
|
||||
++i[1];
|
||||
if (i[1] < d[1]) return;
|
||||
i[1] = 0;
|
||||
++i[0];
|
||||
if (i[0] < d[0]) return;
|
||||
// i[0]=0;
|
||||
_at_end = true;
|
||||
}
|
||||
AUTO_DECL index() const { return i; }
|
||||
long linear_index() const { return i_flat;}
|
||||
bool at_end() const { return _at_end; }
|
||||
void reset() {
|
||||
_at_end = false;
|
||||
i_flat =0;
|
||||
i[0] = 0;
|
||||
i[1] = 0;
|
||||
i[2] = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user