/****************************************************************************** * * AMDiS - Adaptive multidimensional simulations * * Copyright (C) 2013 Dresden University of Technology. All Rights Reserved. * Web: https://fusionforge.zih.tu-dresden.de/projects/amdis * * Authors: * Simon Vey, Thomas Witkowski, Andreas Naumann, Simon Praetorius, et al. * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * * This file is part of AMDiS * * See also license.opensource.txt in the distribution. * ******************************************************************************/ /** \file functorN_expr.h */ #ifndef AMDIS_FUNCTOR_N_EXPRESSION_HPP #define AMDIS_FUNCTOR_N_EXPRESSION_HPP #include "AMDiS_fwd.h" #include "LazyOperatorTerm.h" #include "Functors.h" // #include "expressions/functor_expr.hpp" #include "operations/functors.hpp" #include #include #include #include namespace AMDiS { /// for_each for std::tuple template inline typename std::enable_if::type for_each(std::tuple &, FuncT) { } template inline typename std::enable_if::type for_each(std::tuple& t, FuncT f) { f(std::get(t)); for_each(t, f); } template using int_ = std::integral_constant; namespace traits { /// get the degree of a functor by combining the degrees of the arguments template struct functor_degree { template static int eval(F f, Int... d) { return 0; } }; template struct functor_degree >::type > { template static int eval(F f, Int... d) { return f.getDegree(d...); } }; // specialization for abstract-functions template struct functor_degree > { template static int eval(AbstractFunction const& fct, Int... d) { return fct.getDegree(); } }; template struct functor_degree > { template static int eval(BinaryAbstractFunction const& fct, Int... d) { return fct.getDegree(); } }; template struct functor_degree > { template static int eval(TertiaryAbstractFunction const& fct, Int... d) { return fct.getDegree(); } }; } // end namespace traits namespace result_of { template struct void_{ typedef void type; }; /// extract result type from function pointers template struct Function; template struct Function { typedef R result_type; }; template struct Function { typedef R type; }; template typename Function::type function_helper(T); /// extract result type from functors template struct Functor { typedef decltype(function_helper(&F::operator())) type; }; template struct Functor > { typedef R type; }; template struct Functor::type> { typedef typename F::value_type type; }; template struct Functor::type> { typedef typename F::result_type type; }; } // end namespace result_of namespace detail { /// Functor that initializes the feSpace list template struct InsertFeSpaces { List& feSpaces; InsertFeSpaces(List& feSpaces_) : feSpaces(feSpaces_) {}; template void operator()(Term& term) { term.insertFeSpaces(feSpaces); } }; /// Functor that is called on each term to initialize it on an element template struct InitElement { OT* ot; const ElInfo *elInfo, *elInfo2; SubAssembler* subAssembler; Quadrature *quad; const BasisFunction *basisFct; InitElement(OT* ot_, const ElInfo* elInfo_, SubAssembler* subAssembler_, Quadrature *quad_, const BasisFunction *basisFct_) : ot(ot_), elInfo(elInfo_), elInfo2(NULL), subAssembler(subAssembler_), quad(quad_), basisFct(basisFct_) {} InitElement(OT* ot_, const ElInfo* smallElInfo_, const ElInfo* largeElInfo_, SubAssembler* subAssembler_, Quadrature *quad_, const BasisFunction *basisFct_) : ot(ot_), elInfo(smallElInfo_), elInfo2(largeElInfo_), subAssembler(subAssembler_), quad(quad_), basisFct(basisFct_) {} template void operator()(Term& term) { if (elInfo2) term.initElement(ot, elInfo, elInfo2, subAssembler, quad, basisFct); else term.initElement(ot, elInfo, subAssembler, quad, basisFct); } }; } // end namespace detail /// Operator term with arbitrary number of sub-term (expressions) template struct LazyOperatorTerms : public LazyOperatorTermBase { std::tuple term_tuple; template LazyOperatorTerms(Terms_... terms_) : term_tuple(terms_...) { } template inline void insertFeSpaces(List& feSpaces) { for_each(term_tuple, detail::InsertFeSpaces(feSpaces)); } template inline void initElement(OT* ot, const ElInfo* elInfo, SubAssembler* subAssembler, Quadrature *quad, const BasisFunction *basisFct = NULL) { for_each(term_tuple, detail::InitElement(ot, elInfo, subAssembler, quad, basisFct)); } template inline void initElement(OT* ot, const ElInfo* smallElInfo, const ElInfo* largeElInfo, SubAssembler* subAssembler, Quadrature *quad, const BasisFunction *basisFct = NULL) { for_each(term_tuple, detail::InitElement(ot, smallElInfo, largeElInfo, subAssembler, quad, basisFct)); } inline double operator()(const int& iq) const; }; // the expressions // _____________________________________________________________________________ namespace expressions { /// Functor that takes arbitrary number of arguments template struct FunctionN : public LazyOperatorTerms { typedef LazyOperatorTerms super; static const int N = sizeof...(Terms); typedef typename result_of::Functor::type value_type; BOOST_STATIC_ASSERT_MSG( (!boost::is_same::value), "********** ERROR: You have to define a result_type for your Functor **********" ); F f; ///< the functor template FunctionN(F&& f_, Terms_... terms_) : super(terms_...), f(f_) {} // call f.getDegree() function template int getDegree(int_, Terms_&&... terms) const { return getDegree(int_(), std::get(super::term_tuple), std::forward(terms)...); } template int getDegree(int_<0>, Terms_&&... terms) const { return traits::functor_degree::eval(f, terms.getDegree()...); } int getDegree() const { return getDegree(int_()); } // call f.operator()(...) template inline value_type eval(const int& iq, int_, Terms_&&... terms) const { return eval(iq, int_(), std::get(super::term_tuple), std::forward(terms)...); } template inline value_type eval(const int& iq, int_<0>, Terms_&&... terms) const { return f(terms(iq)...); // f(term1(iq), term2(iq), term3(iq),...) } inline value_type operator()(const int& iq) const { return eval(iq, int_()); } }; template using Function1 = FunctionN; template using Function2 = FunctionN; template using Function3 = FunctionN; template using Function4 = FunctionN; /// A wrapper functor for AMDiS::AbstractFunctions template struct Wrapper : public FunctorBase { typedef TOut result_type; Wrapper(AbstractFunction* fct_) : fct(fct_) {} int getDegree(int degree) const { return fct->getDegree(); } TOut operator()(const TIn& x) const { return (*fct)(x); } protected: AbstractFunction* fct; }; template struct DegreeWrapper : public FunctorBase { typedef typename result_of::Functor::type result_type; DegreeWrapper(F&& fct_) : fct(fct_) {} template int getDegree(Int... degrees) const { return D; } template result_type operator()(Ts&&... args) const { return fct(args...); } protected: F fct; }; template struct DegreeWrapper2 : public FunctorBase { typedef typename result_of::Functor::type result_type; DegreeWrapper2(F&& fct_, DegF&& degfct_) : fct(fct_), degfct(degfct_) {} template int getDegree(Int... degrees) const { return degfct(degrees...); } template result_type operator()(Ts&&... args) const { return fct(args...); } protected: F fct; DegF degfct; }; } // end namespace expressions namespace result_of { // result of generator-functions (used for enable_if constructs) template struct FunctionN : std::enable_if < and_< typename traits::is_valid_arg::type... >::value, expressions::FunctionN< F, typename traits::to_expr::type...> > {}; template struct FunctionN : std::enable_if < traits::is_valid_arg::value, expressions::FunctionN< F, typename traits::to_expr::type> > {}; } // end namespace result_of // generator-functions // _____________________________________________________________________________ template inline typename result_of::FunctionN::type function_(F&& f, Terms... ts) { return expressions::FunctionN::to::type...> (std::forward(f), traits::to_expr::to::get(ts)...); } template inline typename result_of::FunctionN::type func(F&& f, Terms... ts) { return expressions::FunctionN::to::type...> (std::forward(f), traits::to_expr::to::get(ts)...); } template inline typename result_of::FunctionN::type eval(F&& f, Term0 t0, Terms... ts) { return expressions::FunctionN::to::type, typename traits::to_expr::to::type...> (std::forward(f), traits::to_expr::to::get(t0), traits::to_expr::to::get(ts)...); } // function wrapper for abstract functions // _____________________________________________________________________________ template inline expressions::Wrapper wrap(AbstractFunction* fct) { return expressions::Wrapper(fct); } template inline expressions::DegreeWrapper deg(F&& fct) { return expressions::DegreeWrapper(std::forward(fct)); } template inline expressions::DegreeWrapper2 deg(F&& fct, DegF&& degfct) { return expressions::DegreeWrapper2(std::forward(fct), std::forward(degfct)); } } // end namespace AMDiS #endif // AMDIS_FUNCTOR_N_EXPRESSION_HPP