/******************************************************************************* * * TRIQS: a Toolbox for Research in Interacting Quantum Systems * * Copyright (C) 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 . * ******************************************************************************/ #ifndef TRIQS_GF_PRODUCT_H #define TRIQS_GF_PRODUCT_H #include "./tools.hpp" #include "./gf.hpp" #include "./meshes/product.hpp" namespace triqs { namespace gfs { template struct cartesian_product{ typedef std::tuple type; static constexpr size_t size = sizeof...(Ms); }; // use alias template struct cartesian_product > : cartesian_product{}; // the mesh is simply a cartesian product template struct gf_mesh,Opt> : mesh_product< gf_mesh ... > { typedef mesh_product< gf_mesh ... > B; typedef std::tuple mesh_name_t; gf_mesh (gf_mesh ... ms) : B {std::move(ms)...} {} }; namespace gfs_implementation { // h5 name : name1_x_name2_..... template struct h5_name,matrix_valued,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::invoke()...), std::string()); } }; /// --------------------------- data access --------------------------------- template struct data_proxy,matrix_valued,Opt> : data_proxy_array,3> {}; template struct data_proxy,scalar_valued,Opt> : data_proxy_array,1> {}; /// --------------------------- evaluator --------------------------------- struct evaluator_grid_simple { size_t n; evaluator_grid_simple() = default; template evaluator_grid_simple (MeshType const & m, PointType const & p) { n=p; } template auto operator()(F const & f) const DECL_AND_RETURN(f (n)); }; struct evaluator_grid_linear_interpolation { double w1, w2; size_t n1, n2; evaluator_grid_linear_interpolation() = default; template evaluator_grid_linear_interpolation (MeshType const & m, PointType const & p, double prefactor=1) { // delegate ! bool in; double w; std::tie(in, n1, w) = windowing(m,p); //std::cout << in << " "<< n1 << " "<< w << " " << p << std::endl; if (!in) TRIQS_RUNTIME_ERROR <<" Evaluation out of bounds"; w1 = prefactor * w; w2 = prefactor *(1-w); n2 = n1 +1; } template auto operator()(F const & f) const DECL_AND_RETURN(w1 * f(n1) + w2 * f (n2)); }; template struct evaluator_fnt_on_mesh; // can not use inherited constructors, too recent... #define TRIQS_INHERIT_AND_FORWARD_CONSTRUCTOR(NEWCLASS,CLASS) : CLASS { template NEWCLASS(T &&... t) : CLASS(std::forward(t)...){};}; template<> struct evaluator_fnt_on_mesh TRIQS_INHERIT_AND_FORWARD_CONSTRUCTOR(evaluator_fnt_on_mesh, evaluator_grid_simple); template<> struct evaluator_fnt_on_mesh TRIQS_INHERIT_AND_FORWARD_CONSTRUCTOR(evaluator_fnt_on_mesh, evaluator_grid_linear_interpolation); template<> struct evaluator_fnt_on_mesh TRIQS_INHERIT_AND_FORWARD_CONSTRUCTOR(evaluator_fnt_on_mesh, evaluator_grid_linear_interpolation); template<> struct evaluator_fnt_on_mesh TRIQS_INHERIT_AND_FORWARD_CONSTRUCTOR(evaluator_fnt_on_mesh, evaluator_grid_linear_interpolation); /** * This the multi-dimensional evaluator. * It combine the evaluator of each components, as long as they are a linear form * eval(g, x) = \sum_i w_i g( n_i(x)) , with w some weight and n_i some points on the grid. * Mathematically, it is written as (example of evaluating g(x1,x2,x3,x4)). * Notation : eval(X) : g -> g(X) * eval(x1,x2,x3,x4) (g) = eval (x1) ( binder ( g, (), (x2,x3,x4)) ) * binder( g, (), (x2,x3,x4)) (p1) = eval(x2)(binder (g,(p1),(x3,x4))) * binder( g, (p1), (x3,x4)) (p2) = eval(x3)(binder (g,(p1,p2),(x4))) * binder( g, (p1,p2), (x4)) (p3) = eval(x4)(binder (g,(p1,p2,p3),())) * binder( g, (p1,p2,p3),()) (p4) = g[p1,p2,p3,p4] * * p_i are points on the grids, x_i points in the domain. * * Unrolling the formula gives (for 2 variables, with 2 points interpolation) * eval(xa,xb) (g) = eval (xa) ( binder ( g, (), (xb)) ) = w_1(xa) binder ( g, (), (xb))( n_1(xa)) + w_2(xa) binder ( g, (), (xb))( n_2(xa)) * = w_1(xa) ( eval(xb)( binder ( g, (n_1(xa) ), ()))) + 1 <-> 2 * = w_1(xa) ( W_1(xb) * binder ( g, (n_1(xa) ), ())(N_1(xb)) + 1<->2 ) + 1 <-> 2 * = w_1(xa) ( W_1(xb) * g[n_1(xa), N_1(xb)] + 1<->2 ) + 1 <-> 2 * = w_1(xa) ( W_1(xb) * g[n_1(xa), N_1(xb)] + W_2(xb) * g[n_1(xa), N_2(xb)] ) + 1 <-> 2 * which is the expected formula */ // implementation : G = gf, Tn : tuple of n points, Ev : tuple of evaluators (the evals functions), pos = counter from #args-1 =>0 // NB : the tuple is build in reverse with respect to the previous comment. template struct binder; template binder make_binder(G const * g, Tn tn, Ev const & ev) { return binder{g, std::move(tn), ev}; } template struct binder { G const * g; Tn tn; Ev const & evals; auto operator()(size_t p) const DECL_AND_RETURN( std::get(evals) ( make_binder(g, triqs::tuple::push_front(tn,p), evals) )); }; template struct binder { 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))); }; // now the multi d evaluator itself. template struct evaluator,Target,Opt> { static constexpr int arity = sizeof...(Ms); mutable std::tuple< evaluator_fnt_on_mesh ... > evals; struct _poly_lambda {// replace by a polymorphic lambda in C++14 template void operator()(A & a, B const & b, C const & c) const { a = A{b,c};} }; template std::complex operator() (G const * g, Args && ... args) const { static constexpr int R = sizeof...(Args); // build the evaluators, as a tuple of ( evaluator ( mesh_component, args)) triqs::tuple::call_on_zip(_poly_lambda(), evals, g->mesh().components(), std::make_tuple(args...)); return std::get(evals) (make_binder (g, std::make_tuple(), evals) ); } }; // ------------------------------- Factories -------------------------------------------------- template struct factories, scalar_valued,Opt> { typedef gf, scalar_valued,Opt> gf_t; template static gf_t make_gf(Meshes && ... meshes) { auto m = gf_mesh,Opt>(meshes...); typename gf_t::data_regular_t A(m.size()); A() =0; return gf_t (m, std::move(A), nothing(), nothing()); } }; } // gf_implementation }} #endif