/******************************************************************************* * * 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 . * ******************************************************************************/ #pragma once #include "./tools.hpp" #include "./gf.hpp" #include "./meshes/product.hpp" #include "./evaluators.hpp" namespace triqs { namespace gfs { template struct cartesian_product { using type = std::tuple; static constexpr size_t size = sizeof...(Ms); }; template constexpr int get_n_variables(cartesian_product) { return sizeof...(Ms);} // use alias template struct cartesian_product> : cartesian_product {}; /// TODO : Put inheriting constructor, simpler... // the mesh is simply a cartesian product template struct gf_mesh, Opt> : mesh_product...> { // using mesh_product< gf_mesh ... >::mesh_product< gf_mesh ... > ; using B = mesh_product...>; gf_mesh() = default; gf_mesh(gf_mesh... ms) : B{std::move(ms)...} {} }; namespace gfs_implementation { /// --------------------------- data access --------------------------------- template struct data_proxy, scalar_valued, Opt> : data_proxy_array_multivar, sizeof...(Ms)> {}; template struct data_proxy, matrix_valued, Opt> : data_proxy_array_multivar_matrix_valued, 2 + sizeof...(Ms)> {}; template struct data_proxy, tensor_valued, Opt> : data_proxy_array_multivar, R + sizeof...(Ms)> {}; // special case ? Or make a specific container.... template struct data_proxy, matrix_valued, Opt> : data_proxy_array_multivar_matrix_valued { }; /// --------------------------- hdf5 --------------------------------- // h5 name : name1_x_name2_..... template struct h5_name, 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; }, reverse(std::make_tuple(h5_name::invoke()...)), std::string()); } }; template struct h5_name, tensor_valued, S, Opt> : h5_name, matrix_valued, S, Opt> {}; /// --------------------------- evaluator --------------------------------- /** * 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 {g, std::move(tn), ev}; } template struct binder { G const *g; Tn tn; Ev const &evals; template decltype(auto) impl(size_t p, std14::index_sequence) const { return std::get(evals)(make_binder(g, std::make_tuple(p, std::get(tn)...), evals)); } decltype(auto) operator()(size_t p) const { return impl(p, std14::make_index_sequence::value>()); } }; template struct binder { G const *g; Tn tn; Ev const &evals; template decltype(auto) impl(size_t p, std14::index_sequence) const { return g->get_from_linear_index(p, std::get(tn)...); } decltype(auto) operator()(size_t p) const { return impl(p, std14::make_index_sequence::value>()); } }; // now the multi d evaluator itself. template struct evaluator, Target, nothing, Opt> { static constexpr int arity = sizeof...(Ms); mutable std::tuple...> evals; template decltype(auto) operator()(G const *g, Args &&... args) const { static constexpr int R = sizeof...(Args); // build the evaluators, as a tuple of ( evaluator ( mesh_component, args)) auto l = [](auto &a, auto &b, auto &c) { a = std14::decay_t{b, c}; }; triqs::tuple::for_each_zip(l, evals, g->mesh().components(), std::make_tuple(args...)); return std::get(evals)(make_binder(g, std::make_tuple(), evals)); } }; } // gf_implementation } }