From 01aefb507a185dffcab51b14d8922f576861d508 Mon Sep 17 00:00:00 2001 From: Simon Praetorius <simon.praetorius@tu-dresden.de> Date: Mon, 2 Jul 2018 14:37:17 +0200 Subject: [PATCH] Removed tuple implementation and used wrapper instead --- src/amdis/Assembler.hpp | 6 +- src/amdis/FiniteElementSpaces.hpp | 133 ---------- src/amdis/GridFunctionOperator.hpp | 25 +- src/amdis/LocalAssemblerBase.hpp | 85 +----- src/amdis/LocalAssemblerList.hpp | 96 +++++++ src/amdis/LocalOperator.hpp | 23 +- .../gridfunctions/AnalyticGridFunction.hpp | 9 +- src/amdis/gridfunctions/DOFVectorView.hpp | 7 + .../gridfunctions/DerivativeGridFunction.hpp | 15 +- .../gridfunctions/FunctorGridFunction.hpp | 95 ++++--- src/amdis/utility/Tuple.hpp | 247 ------------------ test/CMakeLists.txt | 3 - test/TupleTest.cpp | 51 ---- 13 files changed, 207 insertions(+), 588 deletions(-) delete mode 100644 src/amdis/FiniteElementSpaces.hpp create mode 100644 src/amdis/LocalAssemblerList.hpp delete mode 100644 src/amdis/utility/Tuple.hpp delete mode 100644 test/TupleTest.cpp diff --git a/src/amdis/Assembler.hpp b/src/amdis/Assembler.hpp index c5f6ab4e..be425fc9 100644 --- a/src/amdis/Assembler.hpp +++ b/src/amdis/Assembler.hpp @@ -54,6 +54,8 @@ namespace AMDiS SystemVectorType& rhs, bool asmMatrix, bool asmVector) const; + /// Assemble operators on an element, by passing the element/intersection to + /// `elementAssembler` functor. template <class Element, class Operators, class ElementAssembler> void assembleElementOperators( Element const& element, @@ -70,14 +72,14 @@ namespace AMDiS bool asmMatrix, bool asmVector) const; - /// Return whether the matrix-block needs to be assembled + /// Return the element the LocalViews are bound to template <class LocalView0, class... LovalViews> auto const& getElement(LocalView0 const& localView, LovalViews const&...) const { return localView.element(); } - /// Return whether the matrix-block needs to be assembled + /// Return the gridView the localViews are bound to template <class LocalView0, class... LovalViews> auto const& getGridView(LocalView0 const& localView, LovalViews const&...) const { diff --git a/src/amdis/FiniteElementSpaces.hpp b/src/amdis/FiniteElementSpaces.hpp deleted file mode 100644 index 10775960..00000000 --- a/src/amdis/FiniteElementSpaces.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#pragma once - -#include <amdis/common/TupleUtility.hpp> -#include <amdis/common/IndexSeq.hpp> -#include <amdis/common/Loops.hpp> - -namespace AMDiS -{ - template <class FeSpace> - struct LocalView - { - using type = typename FeSpace::LocalView; - }; - - template <class FeSpace> - struct LocalIndexSet - { - using type = typename FeSpace::LocalIndexSet; - }; - - - template <class FeSpaces> - class FiniteElementSpaces - { - template <std::size_t I> - using FeSpace = std::tuple_element_t<I, FeSpaces>; - - static constexpr int nComponents = std::tuple_size<FeSpaces>::value; - - static_assert( nComponents > 0, "" ); - - using LocalViews = MapTuple_t<LocalView, FeSpaces>; - using LocalIndexSets = MapTuple_t<LocalIndexSet, FeSpaces>; - - /// The grid view the global FE basis lives on - using GridView = typename FeSpace<0>::GridView; - - /// Type of the grid element we are bound to - using Element = typename GridView::template Codim<0>::Entity; - - public: - explicit FiniteElementSpaces(std::shared_ptr<FeSpaces> const& feSpaces) - : feSpaces_(feSpaces) - , localViews_(mapTuple([](auto const& basis) { return basis.localView(); }, *feSpaces)) - , localIndexSets_(mapTuple([](auto const& basis) { return basis.localIndexSet(); }, *feSpaces)) - {} - - /// Update all global bases. This will update the indexing information of the global basis. - /// NOTE: It must be called if the grid has changed. - void update(GridView const& gv) - { - forEach(range_<0, nComponents>, [&,this](auto const _i) - { - static const int I = decltype(_i)::value; - std::get<I>(*feSpaces_).update(gv); - }); - } - - /// Bind the \ref localViews and \ref localIndexSets to a grid element - void bind(Element const& element) - { - forEach(range_<0, nComponents>, [&,this](auto const _i) - { - static const int I = decltype(_i)::value; - - auto& localView = std::get<I>(localViews_); - localView.bind(element); - - auto& localIndexSet = std::get<I>(localIndexSets_); - localIndexSet.bind(localView); - }); - // NOTE: maybe create element-geometry here - bound_ = true; - } - - /// Unbind from the current element - void unbind() - { - forEach(range_<0, nComponents>, [&,this](auto const _i) - { - static const int I = decltype(_i)::value; - std::get<I>(localIndexSets_).unbind(); - std::get<I>(localViews_).unbind(); - }); - bound_ = false; - } - - template <std::size_t I> - auto const& feSpace(const index_t<I> _i = {}) const - { - return std::get<I>(*feSpaces_); - } - - template <std::size_t I> - auto const& localView(const index_t<I> _i = {}) const - { - assert( bound_ && "localViews must be bound to an element." ); - return std::get<I>(localViews_); - } - - template <std::size_t I> - auto const& localIndexSet(const index_t<I> _i = {}) const - { - assert( bound_ && "localIndexSets must be bound to a localView." ); - return std::get<I>(localIndexSets_); - } - - auto const& element() const - { - assert( bound_ && "localViews must be bound to an element." ); - return std::get<0>(localViews_).element(); - } - - auto const& gridView() const - { - return std::get<0>(*feSpaces_).gridView(); - } - - private: - /// Tuple of global functionspace bases - std::shared_ptr<FeSpaces> feSpaces_; - - /// Tuple of localView objects, obtained from the tuple of global bases - LocalViews localViews_; - - /// Tuple of localIndexSet objects, obtained from the tuple of global bases - LocalIndexSets localIndexSets_; - - /// True, if localViews and localIndexSets are bound to an element - bool bound_ = false; - }; - -} // end namespace AMDiS diff --git a/src/amdis/GridFunctionOperator.hpp b/src/amdis/GridFunctionOperator.hpp index 1cda525f..70a12642 100644 --- a/src/amdis/GridFunctionOperator.hpp +++ b/src/amdis/GridFunctionOperator.hpp @@ -16,7 +16,8 @@ namespace AMDiS * @{ **/ - /// \brief The main implementation of an operator to be used in a \ref LocalAssembler. + /// \brief The main implementation of an CRTP-base class for operators using a grid-function + /// coefficient to be used in a \ref LocalAssembler. /** * An Operator that takes a GridFunction as coefficient. * Provides quadrature rules and handles the evaluation of the GridFunction at @@ -24,6 +25,7 @@ namespace AMDiS * * The class is specialized, by deriving from it, in \ref GridFunctionOperator. * + * \tparam Derived The class derived from GridFunctionOperatorBase * \tparam LocalContext The Element or Intersection type * \tparam GridFunction The GridFunction, a LocalFunction is created from, and * that is evaluated at quadrature points. @@ -36,21 +38,26 @@ namespace AMDiS class GridFunctionOperatorBase : public LocalOperator<Derived, LocalContext> { + /// The type of the localFunction associated with the GridFunction using LocalFunction = decltype(localFunction(std::declval<GridFunction>())); + /// The Codim=0 entity of the grid, the localFunction can be bound to using Element = typename Impl::ContextTypes<LocalContext>::Entity; + /// The geometry-type of the grid element using Geometry = typename Element::Geometry; + /// The type of the local coordinates in the \ref Element using LocalCoordinate = typename GridFunction::EntitySet::LocalCoordinate; + /// A factory for QuadratureRules that incooperate the order of the LocalFunction using QuadFactory = QuadratureFactory<typename Geometry::ctype, LocalContext::mydimension, LocalFunction>; public: /// \brief Constructor. Stores a copy of `gridFct`. /** - * An expression operator takes an expression, following the interface of - * \ref ExpressionBase, and stores a copy. Additionally, it gets the - * differentiation order, to calculate the quadrature degree in \ref getDegree. + * A GridFunctionOperator takes a gridFunction and the + * differentiation order of the operator, to calculate the + * quadrature degree in \ref getDegree. **/ GridFunctionOperatorBase(GridFunction const& gridFct, int termOrder) : gridFct_(gridFct) @@ -78,7 +85,8 @@ namespace AMDiS * Since all operators need geometry information, the `Element::Geometry` * object `geometry` is created once, during grid traversal, and passed in. * - * By default, it binds the \ref localFct_ to the `element`. + * By default, it binds the \ref localFct_ to the `element` and the Quadrature + * factory to the localFunction. **/ void bind_impl(Element const& element, Geometry const& geometry) { @@ -93,6 +101,7 @@ namespace AMDiS localFct_.unbind(); } + /// Create a quadrature factory from a PreQuadratureFactory, e.g. class derived from \ref QuadratureFactory template <class PreQuadFactory> void setQuadFactory(PreQuadFactory const& pre) { @@ -107,7 +116,7 @@ namespace AMDiS return localFct_(local); } - /// Create a quadrature rule using the \ref QuadratureCreator by calculating the + /// Create a quadrature rule using the \ref QuadratureFactory by calculating the /// quadrature order necessary to integrate the (bi)linear-form accurately. template <class... Nodes> auto const& getQuadratureRule(Dune::GeometryType type, Nodes const&... nodes) const @@ -148,23 +157,27 @@ namespace AMDiS : transposedOp_(std::forward<Args>(args)...) {} + /// Redirects the bind call top the transposed operator template <class Element, class Geometry> void bind_impl(Element const& element, Geometry const& geometry) { transposedOp_.bind_impl(element, geometry); } + /// Redirects the unbind call top the transposed operator void unbind_impl() { transposedOp_.unbind_impl(); } + /// Redirects the setQuadFactory call top the transposed operator template <class PreQuadFactory> void setQuadFactory(PreQuadFactory const& pre) { transposedOp_.setQuadFactory(pre); } + /// Apply the assembling to the transposed elementMatrix with interchanged row-/colNode template <class Context, class RowNode, class ColNode, class ElementMatrix> void getElementMatrix(Context const& context, RowNode const& rowNode, diff --git a/src/amdis/LocalAssemblerBase.hpp b/src/amdis/LocalAssemblerBase.hpp index 50892963..f6320729 100644 --- a/src/amdis/LocalAssemblerBase.hpp +++ b/src/amdis/LocalAssemblerBase.hpp @@ -1,13 +1,10 @@ #pragma once -#include <list> -#include <memory> #include <type_traits> #include <amdis/ContextGeometry.hpp> -#include <amdis/common/ConceptsBase.hpp> +// #include <amdis/common/ConceptsBase.hpp> #include <amdis/common/TypeDefs.hpp> -#include <amdis/utility/TreeData.hpp> namespace AMDiS { @@ -16,24 +13,28 @@ namespace AMDiS class LocalAssemblerBase { public: - + /// The codim=0 grid entity using Element = typename Impl::ContextTypes<LocalContext>::Entity; + /// The geometry of the \ref Element using Geometry = typename Element::Geometry; static constexpr int numNodes = sizeof...(Nodes); static_assert( numNodes == 1 || numNodes == 2, "VectorAssembler gets 1 Node, MatrixAssembler gets 2 Nodes!"); + /// Either an ElementVector or an ElementMatrix (depending on the number of nodes) using ElementMatrixVector = std::conditional_t< (sizeof...(Nodes)==1), Impl::ElementVector, std::conditional_t< (sizeof...(Nodes)==2), Impl::ElementMatrix, void>>; - public: - + /// Virtual destructor virtual ~LocalAssemblerBase() {} + /// Bind the local-assembler to the grid-element with its corresponding geometry virtual void bind(Element const& element, Geometry const& geometry) = 0; + + /// Unbind from the element virtual void unbind() = 0; /// Assemble an element matrix or element vector on the test- (and trial-) function node(s) @@ -42,74 +43,4 @@ namespace AMDiS ElementMatrixVector& elementMatrixVector) = 0; }; - - template <class GridView> - class OperatorLists - { - using Element = typename GridView::template Codim<0>::Entity; - - template <class OperatorType> - struct Scaled - { - std::shared_ptr<OperatorType> op; - double* factor = nullptr; - double* estFactor = nullptr; - BoundaryType b = {0}; - }; - - template <class... Nodes> - struct Data - { - using ElementOperator = LocalAssemblerBase<Element, Nodes...>; - using IntersectionOperator = LocalAssemblerBase<typename GridView::Intersection, Nodes...>; - - std::list<Scaled<ElementOperator>> element; - std::list<Scaled<IntersectionOperator>> boundary; - std::list<Scaled<IntersectionOperator>> intersection; - - bool assembled = false; // if false, do reassemble - bool changing = false; // if true, or assembled false, do reassemble - - bool empty() const - { - return element.empty() && boundary.empty() && intersection.empty(); - } - - bool doAssemble(bool flag) const - { - return flag && (!assembled || changing); - } - - template <class Geo> - void bind(Element const& elem, Geo const& geo) - { - for (auto& scaled : element) scaled.op->bind(elem,geo); - for (auto& scaled : boundary) scaled.op->bind(elem,geo); - for (auto& scaled : intersection) scaled.op->bind(elem,geo); - } - - void unbind() - { - for (auto& scaled : element) scaled.op->unbind(); - for (auto& scaled : boundary) scaled.op->unbind(); - for (auto& scaled : intersection) scaled.op->unbind(); - } - }; - - public: - - template <class RowNode, class ColNode> - using MatData = Data<RowNode, ColNode>; - - template <class Node> - using VecData = Data<Node>; - }; - - - template <class GlobalBasis> - using MatrixOperators = MatrixData<GlobalBasis, OperatorLists<typename GlobalBasis::GridView>::template MatData>; - - template <class GlobalBasis> - using VectorOperators = VectorData<GlobalBasis, OperatorLists<typename GlobalBasis::GridView>::template VecData>; - } // end namespace AMDiS diff --git a/src/amdis/LocalAssemblerList.hpp b/src/amdis/LocalAssemblerList.hpp new file mode 100644 index 00000000..e4b1dc79 --- /dev/null +++ b/src/amdis/LocalAssemblerList.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include <list> +#include <memory> + +#include <amdis/LocalAssemblerBase.hpp> +#include <amdis/utility/TreeData.hpp> + +namespace AMDiS +{ + template <class GridView> + class OperatorLists + { + using Element = typename GridView::template Codim<0>::Entity; + using Intersection = typename GridView::Intersection; + + template <class OperatorType> + struct DataElement + { + std::shared_ptr<OperatorType> op; + double* factor = nullptr; + double* estFactor = nullptr; + BoundaryType b = {0}; + }; + + /// Lists of \ref DataElement on the Element, BoundaryIntersction, and InteriorIntersections + template <class... Nodes> + struct Data + { + /// The type of local operators associated with grid elements + using ElementOperator = LocalAssemblerBase<Element, Nodes...>; + /// The type of local operators associated with grid intersections + using IntersectionOperator = LocalAssemblerBase<Intersection, Nodes...>; + + /// Return whether any operators are stored on the node + bool empty() const + { + return element.empty() && boundary.empty() && intersection.empty(); + } + + /// Test whether to assemble on the node + bool doAssemble(bool flag) const + { + return flag && (!assembled || changing); + } + + /// Bind all operators to the grid element and geometry + template <class Geo> + void bind(Element const& elem, Geo const& geo) + { + for (auto& scaled : element) scaled.op->bind(elem,geo); + for (auto& scaled : boundary) scaled.op->bind(elem,geo); + for (auto& scaled : intersection) scaled.op->bind(elem,geo); + } + + /// Unbind all operators from the element + void unbind() + { + for (auto& scaled : element) scaled.op->unbind(); + for (auto& scaled : boundary) scaled.op->unbind(); + for (auto& scaled : intersection) scaled.op->unbind(); + } + + /// List of operators to be assembled on grid elements + std::list<DataElement<ElementOperator>> element; + /// List of operators to be assembled on boundary intersections + std::list<DataElement<IntersectionOperator>> boundary; + /// List of operators to be assembled on interior intersections + std::list<DataElement<IntersectionOperator>> intersection; + + /// if false, do reassemble of all operators + bool assembled = false; + + /// if true, or \ref assembled false, do reassemble of all operators + bool changing = false; + }; + + public: + + /// List of operators associated with matrix blocks (RowNode, ColNode) + template <class RowNode, class ColNode> + using MatData = Data<RowNode, ColNode>; + + /// List of operators associated with vector blocks [Node] + template <class Node> + using VecData = Data<Node>; + }; + + + template <class GlobalBasis> + using MatrixOperators = MatrixData<GlobalBasis, OperatorLists<typename GlobalBasis::GridView>::template MatData>; + + template <class GlobalBasis> + using VectorOperators = VectorData<GlobalBasis, OperatorLists<typename GlobalBasis::GridView>::template VecData>; + +} // end namespace AMDiS diff --git a/src/amdis/LocalOperator.hpp b/src/amdis/LocalOperator.hpp index 87d2f3d3..5509510a 100644 --- a/src/amdis/LocalOperator.hpp +++ b/src/amdis/LocalOperator.hpp @@ -18,15 +18,18 @@ namespace AMDiS /** * The CRTP Base class for local operators. * - * \tparam Derived The class that derives from this base class + * \tparam Derived The class that derives from this base class * \tparam LocalContextType The type of the element or intersection the operator is evaluated on **/ template <class Derived, class LocalContextType> class LocalOperator { public: + /// The element or intersection the operator is assembled on using LocalContext = LocalContextType; + /// The codim=0 grid entity using Element = typename Impl::ContextTypes<LocalContext>::Entity; + /// The geometry of the \ref Element using Geometry = typename Element::Geometry; /// Initialize the local operator on the current gridView @@ -112,19 +115,19 @@ namespace AMDiS // default implementation called by \ref calculateElementMatrix template <class Context, class RowNode, class ColNode, class ElementMatrix> - void getElementMatrix(Context const& context, - RowNode const& rowNode, - ColNode const& colNode, - ElementMatrix& elementMatrix) + void getElementMatrix(Context const& /*context*/, + RowNode const& /*rowNode*/, + ColNode const& /*colNode*/, + ElementMatrix& /*elementMatrix*/) { error_exit("Needs to be implemented by derived class!"); } // default implementation called by \ref calculateElementVector template <class Context, class Node, class ElementVector> - void getElementVector(Context const& context, - Node const& node, - ElementVector& elementVector) + void getElementVector(Context const& /*context*/, + Node const& /*node*/, + ElementVector& /*elementVector*/) { error_exit("Needs to be implemented by derived class!"); } @@ -186,14 +189,14 @@ namespace AMDiS }; - /// Generate an \ref GridFunctionOperator from a PreOperator. + /// Generate a \ref LocalOperator from a PreOperator. template <class Derived, class LocalContext, class GridView> auto makeLocalOperator(LocalOperator<Derived, LocalContext> const& localOp, GridView const& /*gridView*/) { return localOp.derived(); } - /// Generate a shared_ptr to \ref GridFunctionOperator from a PreOperator. + /// Generate a shared_ptr to a \ref LocalOperator from a PreOperator. template <class Derived, class LocalContext, class GridView> auto makeLocalOperatorPtr(LocalOperator<Derived, LocalContext> const& localOp, GridView const& /*gridView*/) { diff --git a/src/amdis/gridfunctions/AnalyticGridFunction.hpp b/src/amdis/gridfunctions/AnalyticGridFunction.hpp index 055bfff1..40bd3918 100644 --- a/src/amdis/gridfunctions/AnalyticGridFunction.hpp +++ b/src/amdis/gridfunctions/AnalyticGridFunction.hpp @@ -27,7 +27,7 @@ namespace AMDiS public: AnalyticLocalFunction(Function const& fct) - : fct_(fct) + : fct_{fct} {} void bind(LocalContext const& element) @@ -42,7 +42,7 @@ namespace AMDiS Range operator()(Domain const& local) const { - assert(geometry_.has_value()); + assert( bool(geometry_) ); return fct_(geometry_.value().global(local)); } @@ -108,8 +108,8 @@ namespace AMDiS public: /// \brief Constructor. Stores the function `fct` and creates an `EntitySet`. AnalyticGridFunction(Function const& fct, GridView const& gridView) - : fct_(fct) - , entitySet_(gridView) + : fct_{fct} + , entitySet_{gridView} {} /// \brief Return the evaluated functor at global coordinates @@ -124,7 +124,6 @@ namespace AMDiS return {fct_}; } - EntitySet const& entitySet() const { return entitySet_; diff --git a/src/amdis/gridfunctions/DOFVectorView.hpp b/src/amdis/gridfunctions/DOFVectorView.hpp index f0a5f937..91ddcb18 100644 --- a/src/amdis/gridfunctions/DOFVectorView.hpp +++ b/src/amdis/gridfunctions/DOFVectorView.hpp @@ -297,6 +297,13 @@ namespace AMDiS return *this; } + template <class Expr> + DOFVectorMutableView& operator<<(Expr&& expr) + { + return interpolate(expr); + } + + /// Return the mutable DOFVector DOFVector<Traits>& coefficients() { return *mutableDofVector_; } diff --git a/src/amdis/gridfunctions/DerivativeGridFunction.hpp b/src/amdis/gridfunctions/DerivativeGridFunction.hpp index 5a7e621f..87fccfb8 100644 --- a/src/amdis/gridfunctions/DerivativeGridFunction.hpp +++ b/src/amdis/gridfunctions/DerivativeGridFunction.hpp @@ -45,7 +45,7 @@ namespace AMDiS public: /// Constructor. Stores a copy of gridFct. explicit DerivativeGridFunction(GridFunction const& gridFct) - : gridFct_(gridFct) + : gridFct_{gridFct} { static_assert(isValidRange<DerivativeTraits>(), "Derivative of GridFunction not defined"); } @@ -58,9 +58,9 @@ namespace AMDiS } /// Return the derivative-localFunction of the GridFunction. - friend LocalFunction localFunction(DerivativeGridFunction const& gf) + LocalFunction localFunction() const { - return derivative(localFunction(gf.gridFct_)); + return derivative(localFunction(gridFct_)); } /// Return the \ref EntitySet of the \ref GridFunction. @@ -74,7 +74,13 @@ namespace AMDiS }; -#ifndef DOXYGEN + template <class GF> + auto localFunction(DerivativeGridFunction<GF> const& gf) + { + return gf.localFunction(); + } + + template <class GridFct, class LocalFct = decltype(localFunction(std::declval<GridFct>())), REQUIRES(not Concepts::HasDerivative<GridFct>)> @@ -85,6 +91,7 @@ namespace AMDiS } +#ifndef DOXYGEN template <class Expr> struct DerivativePreGridFunction { diff --git a/src/amdis/gridfunctions/FunctorGridFunction.hpp b/src/amdis/gridfunctions/FunctorGridFunction.hpp index 26653e29..f3158053 100644 --- a/src/amdis/gridfunctions/FunctorGridFunction.hpp +++ b/src/amdis/gridfunctions/FunctorGridFunction.hpp @@ -47,12 +47,26 @@ namespace AMDiS using Range = R; using Domain = D; + template <class LocalFct> + struct LocalFunctionWrapper + { + template <class GridFct> + LocalFunctionWrapper(GridFct const& gridFct) + : localFct_{localFunction(gridFct)} + {} + + LocalFct const& operator*() const { return localFct_; } + LocalFct & operator*() { return localFct_; } + + LocalFct localFct_; + }; + public: /// Constructor. Stores copies of the functor and localFunction(gridfunction)s. template <class... GridFcts> FunctorLocalFunction(Functor const& fct, GridFcts&&... gridFcts) - : fct_(fct) - , localFcts_{tag::mapped_arg{}, [](auto const& gf) { return localFunction(gf); }, std::forward<GridFcts>(gridFcts)...} + : fct_{fct} + , localFcts_{std::forward<GridFcts>(gridFcts)...} {} /// Calls \ref bind for all localFunctions @@ -60,7 +74,7 @@ namespace AMDiS void bind(Element const& element) { forEach(localFcts_, [&](auto& localFct) { - localFct.bind(element); + (*localFct).bind(element); }); } @@ -68,22 +82,15 @@ namespace AMDiS void unbind() { forEach(localFcts_, [&](auto& localFct) { - localFct.unbind(); + (*localFct).unbind(); }); } /// Applies the functor \ref fct_ to the evaluated localFunctions Range operator()(Domain const& x) const { - return eval([&x](auto const& localFct) { return localFct(x); }, - MakeSeq_t<sizeof...(LocalFunctions)>{}); - } - - private: - template <class Op, std::size_t... I> - auto eval(Op op, Indices<I...>) const - { - return fct_(op(get<I>(localFcts_))...); + using Dune::Std::apply; + return apply([&](auto&&... localFct) { return fct_(localFct(x)...); }, localFcts_); } public: @@ -93,14 +100,14 @@ namespace AMDiS return fct_; } - Tuple<LocalFunctions...> const& localFcts() const + auto const& localFcts() const { return localFcts_; } private: Functor fct_; - Tuple<LocalFunctions...> localFcts_; + std::tuple<LocalFunctionWrapper<LocalFunctions>...> localFcts_; }; // Derivative of the LocalFunction of a FunctorGridFunction, utilizing @@ -119,11 +126,11 @@ namespace AMDiS { using Dune::Std::apply; auto di_f = apply([&](auto const&... lgfs) { - return makeFunctorGridFunction(partial(lf.fct(), _i), lgfs...); + return makeFunctorGridFunction(partial(lf.fct(), _i), (*lgfs)...); }, lf.localFcts()); using std::get; - auto const& lgfs_i = get<decltype(_i)::value>(lf.localFcts()); + auto const& lgfs_i = *get<decltype(_i)::value>(lf.localFcts()); return makeFunctorGridFunction(Operation::Multiplies{}, di_f, derivative(lgfs_i)); }; @@ -146,7 +153,7 @@ namespace AMDiS int order(FunctorLocalFunction<Sig,F,LFs...> const& lf) { using Dune::Std::apply; - return apply([&lf](auto const&... lgfs) { return order(lf.fct(), order(lgfs)...); }, + return apply([&lf](auto const&... lgfs) { return order(lf.fct(), order(*lgfs)...); }, lf.localFcts()); } @@ -193,15 +200,15 @@ namespace AMDiS /// Constructor. Stores copies of the functor and gridfunctions. template <class... GridFcts> explicit FunctorGridFunction(Functor const& fct, GridFcts&&... gridFcts) - : fct_(fct) - , gridFcts_(std::forward<GridFcts>(gridFcts)...) + : fct_{fct} + , gridFcts_{std::forward<GridFcts>(gridFcts)...} {} /// Applies the functor to the evaluated gridfunctions Range operator()(Domain const& x) const { - return eval(fct_, [&x](auto const& gridFct) { return gridFct(x); }, - MakeSeq_t<sizeof...(GridFunctions)>{}); + using Dune::Std::apply; + return apply([&](auto&&... gridFct) { return fct_(gridFct(x)...); }, gridFcts_); } /// Return the stored \ref EntitySet of the first GridFunction @@ -211,15 +218,10 @@ namespace AMDiS return get<0>(gridFcts_).entitySet(); } - auto const& fct() const { return fct_; } - auto const& gridFcts() const { return gridFcts_; } - - private: - template <class Outer, class Inner, std::size_t... I> - auto eval(Outer outer, Inner inner, Indices<I...>) const + LocalFunction localFunction() const { - using std::get; - return outer(inner(get<I>(gridFcts_))...); + using Dune::Std::apply; + return apply([&](auto const&... gridFcts) { return LocalFunction{fct_, gridFcts...}; }, gridFcts_); } private: @@ -232,16 +234,10 @@ namespace AMDiS template <class F, class... GFs> auto localFunction(FunctorGridFunction<F,GFs...> const& gf) { - return Dune::Std::apply([&gf](auto const&... gridFcts) - { - using LocalFunction = typename FunctorGridFunction<F,GFs...>::LocalFunction; - return LocalFunction{gf.fct(), gridFcts...}; - }, - gf.gridFcts()); + return gt.localFunction(); } -#ifndef DOXYGEN // Generator function for FunctorGridFunction expressions template <class Functor, class... GridFcts> auto makeFunctorGridFunction(Functor const& f, GridFcts const&... gridFcts) @@ -254,7 +250,7 @@ namespace AMDiS } // PreGridFunction related to FunctorGridFunction. - template <class Functor, class... GridFunctions> + template <class Functor, class... PreGridFunctions> struct FunctorPreGridFunction { using Self = FunctorPreGridFunction; @@ -267,28 +263,27 @@ namespace AMDiS return Dune::Std::apply([&](auto const&... pgf) { return makeFunctorGridFunction(self.fct_, makeGridFunction(pgf, gridView)...); - }, self.gridFcts_); + }, self.preGridFcts_); } }; - template <class... GridFcts> - explicit FunctorPreGridFunction(Functor const& fct, GridFcts&&... gridFcts) - : fct_(fct) - , gridFcts_(std::forward<GridFcts>(gridFcts)...) + template <class... PreGridFcts> + explicit FunctorPreGridFunction(Functor const& fct, PreGridFcts&&... pgfs) + : fct_{fct} + , preGridFcts_{std::forward<PreGridFcts>(pgfs)...} {} private: Functor fct_; - std::tuple<GridFunctions...> gridFcts_; + std::tuple<PreGridFunctions...> preGridFcts_; }; namespace Traits { - template <class Functor, class... GridFunctions> - struct IsPreGridFunction<FunctorPreGridFunction<Functor, GridFunctions...>> + template <class Functor, class... PreGridFcts> + struct IsPreGridFunction<FunctorPreGridFunction<Functor, PreGridFcts...>> : std::true_type {}; } -#endif /// \brief Generator function for FunctorGridFunction. \relates FunctorGridFunction @@ -300,10 +295,10 @@ namespace AMDiS * - `invokeAtQP([](double u, auto const& x) { return u + x[0]; }, 1.0, X());` * - `invokeAtQP(Operation::Plus{}, X(0), X(1));` **/ - template <class Functor, class... GridFcts> - auto invokeAtQP(Functor const& f, GridFcts&&... gridFcts) + template <class Functor, class... PreGridFcts> + auto invokeAtQP(Functor const& f, PreGridFcts&&... gridFcts) { - return FunctorPreGridFunction<Functor, std::decay_t<GridFcts>...>{f, std::forward<GridFcts>(gridFcts)...}; + return FunctorPreGridFunction<Functor, std::decay_t<PreGridFcts>...>{f, std::forward<PreGridFcts>(gridFcts)...}; } /** @} **/ diff --git a/src/amdis/utility/Tuple.hpp b/src/amdis/utility/Tuple.hpp deleted file mode 100644 index e6b946de..00000000 --- a/src/amdis/utility/Tuple.hpp +++ /dev/null @@ -1,247 +0,0 @@ -#pragma once - -#include <utility> - -#include <amdis/common/Mpl.hpp> -#include <amdis/common/Utility.hpp> - -#include <dune/common/typetraits.hh> - -namespace AMDiS -{ - // inspired by Sasha Goldshtein's implementation, - // see http://blogs.microsoft.co.il/sasha/2015/01/12/implementing-tuple-part-1 - - namespace tag - { - struct mapped_arg {}; - } - - namespace Impl - { - template <std::size_t, class T> - struct TupleEntry - { - TupleEntry() = default; - - explicit TupleEntry(T const& value) : value_(value) {} - explicit TupleEntry(T&& value) : value_(std::move(value)) {} - - // create value through a map of arguments - template <class Map, class... Args> - TupleEntry(tag::mapped_arg, Map&& map, Args&&... args) - : value_(map(std::forward<Args>(args)...)) - {} - - T value_; - }; - - template <class Sequences, class... Types> - struct TupleImpl; - - template <class T> - struct IsTupleImpl : std::false_type {}; - - template <class Sequences, class... Types> - struct IsTupleImpl<TupleImpl<Sequences,Types...>> : std::true_type {}; - - - template <std::size_t... Indices, class... Types> - struct TupleImpl<std::index_sequence<Indices...>, Types...> - : TupleEntry<Indices, Types>... - { - TupleImpl() = default; - - // constructor from sequence of types, disabling this for copy and move constructor - template <class... OtherTypes, - std::enable_if_t<(sizeof...(OtherTypes) == sizeof...(Types)), int> = 0, - std::enable_if_t<none_of_v<IsTupleImpl<std::decay_t<OtherTypes>>::value...>, int> = 0> - explicit TupleImpl(OtherTypes&&... other) - : TupleEntry<Indices, Types>{std::forward<OtherTypes>(other)}... - {} - - // constructor using a map to build the elements - template <class Map, class... OtherTypes, - std::enable_if_t<(sizeof...(OtherTypes) == sizeof...(Types)), int> = 0> - TupleImpl(tag::mapped_arg, Map&& map, OtherTypes&&... other) - : TupleEntry<Indices, Types>{tag::mapped_arg{}, std::forward<Map>(map), std::forward<OtherTypes>(other)}... - {} - }; - - } // end namespace Impl - - /// \brief Implementation of tuple, that allows mapped construction - template <class... Types> - class Tuple - : public Impl::TupleImpl<std::index_sequence_for<Types...>, Types...> - { - using Super = Impl::TupleImpl<std::index_sequence_for<Types...>, Types...>; - - public: - // some default constructors - Tuple() = default; - Tuple(Tuple const&) = default; - Tuple(Tuple&&) = default; - Tuple& operator=(Tuple const&) = default; - Tuple& operator=(Tuple&&) = default; - - /// Construct from types different from Types, but convertible - template <class... OtherTypes, - std::enable_if_t<(sizeof...(OtherTypes) == sizeof...(Types)), int> = 0> - explicit Tuple(OtherTypes&&... other) - : Super{std::forward<OtherTypes>(other)...} - {} - - /// Constructor from tuple of possibly other types - template <class... OtherTypes, - std::enable_if_t<(sizeof...(OtherTypes) == sizeof...(Types)), int> = 0> - explicit Tuple(Tuple<OtherTypes...> const& that) - : Super{that} - {} - - /// Constructor from tuple of possibly other types - template <class... OtherTypes, - std::enable_if_t<(sizeof...(OtherTypes) == sizeof...(Types)), int> = 0> - explicit Tuple(Tuple<OtherTypes...>&& that) - : Super{std::move(that)} - {} - - /// Constructor using a map to build the elements - template <class Map, class... OtherTypes, - std::enable_if_t<(sizeof...(OtherTypes) == sizeof...(Types)), int> = 0> - Tuple(tag::mapped_arg, Map&& map, OtherTypes&&... other) - : Super{tag::mapped_arg{}, std::forward<Map>(map), std::forward<OtherTypes>(other)...} - {} - - /// Get the I'th tuple element by reference - template <std::size_t I> - auto& operator[](std::integral_constant<std::size_t,I>) - { - Impl::TupleEntry<I, TupleElement_t<I, AMDiS::Types<Types...>>>& base = *this; - return base.value_; - } - - /// Get the I'th tuple element by const reference - template <std::size_t I> - auto const& operator[](std::integral_constant<std::size_t,I>) const - { - Impl::TupleEntry<I, TupleElement_t<I, AMDiS::Types<Types...>>> const& base = *this; - return base.value_; - } - - /// Return the number of elements in this tuple - constexpr std::size_t size() const - { - return sizeof...(Types); - } - }; - - - /// Get the I'th tuple element type - template <std::size_t I, class... T> - struct TupleElement<I, Tuple<T...>> - : TupleElement<I, Types<T...>> {}; - - - /// Get the size of the tuple - template <class... T> - struct TupleSize<Tuple<T...>> - : std::integral_constant<std::size_t, sizeof...(T)> {}; - - - namespace Impl - { - /// Get the I'th tuple element by reference - template <std::size_t I, class... T> - auto& get(Tuple<T...>& tuple) - { - Impl::TupleEntry<I, TupleElement_t<I, Types<T...>>>& base = tuple; - return base.value_; - } - - /// Get the I'th tuple element by const reference - template <std::size_t I, class... T> - auto const& get(Tuple<T...> const& tuple) - { - Impl::TupleEntry<I, TupleElement_t<I, Types<T...>>> const& base = tuple; - return base.value_; - } - - /// Get the I'th tuple element by rvalue reference - template <std::size_t I, class... T> - auto&& get(Tuple<T...>&& tuple) - { - Impl::TupleEntry<I, TupleElement_t<I, Types<T...>>>&& base = tuple; - return std::move(base.value_); - } - - template<class F, class TupleType, std::size_t... i> - decltype(auto) applyImpl(F&& f, TupleType&& args, std::index_sequence<i...>) - { - return f(get<i>(args)...); - } - - template <class F, class... T> - decltype(auto) apply(F&& f, Tuple<T...> const& args) - { - auto indices = std::index_sequence_for<T...>{}; - return applyImpl(std::forward<F>(f), args, indices); - } - - template <class F, class... T> - decltype(auto) apply(F&& f, Tuple<T...>& args) - { - auto indices = std::index_sequence_for<T...>{}; - return applyImpl(std::forward<F>(f), args, indices); - } - - } // end namespace Impl - - // inject get(Tuple) into namespace AMDiS by `using` directive - using Impl::get; - - // inject apply(F,Tuple) into namespace AMDiS by `using` directive - using Impl::apply; - - - template <class... Types> - Tuple<Types&&...> forwardAsTuple(Types&&... elements) - { - return Tuple<Types&&...>{std::forward<Types>(elements)...}; - } - - template <class... Types> - Tuple<Types&...> tie(Types&... elements) - { - return Tuple<Types&...>{elements...}; - } - -} // end namespace AMDiS - -namespace std -{ - template <class... T> - struct tuple_size<AMDiS::Tuple<T...>> - : AMDiS::TupleSize<AMDiS::Tuple<T...>> {}; - - template <std::size_t I, class... T> - struct tuple_element<I, AMDiS::Tuple<T...>> - : AMDiS::TupleElement<I, AMDiS::Tuple<T...>> {}; - - // inject get(AMDiS::Tuple) into namespace std by `using` directive - using AMDiS::Impl::get; - - // inject apply(F,AMDiS::Tuple) into namespace std by `using` directive - using AMDiS::Impl::apply; - -} // end namespace std - - -namespace Dune -{ - namespace Std - { - using AMDiS::Impl::apply; - - } // end namespace Std -} // end namespace Dune diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d17857e7..b5eb3aab 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -38,6 +38,3 @@ dune_add_test(SOURCES TreeDataTest.cpp dune_add_test(SOURCES TupleUtilityTest.cpp LINK_LIBRARIES amdis) - -dune_add_test(SOURCES TupleTest.cpp - LINK_LIBRARIES amdis) diff --git a/test/TupleTest.cpp b/test/TupleTest.cpp deleted file mode 100644 index 10c39b28..00000000 --- a/test/TupleTest.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include <tuple> -#include <iostream> - -#include <amdis/utility/Tuple.hpp> -#include <dune/common/hybridutilities.hh> -#include <dune/common/std/apply.hh> - -#include "Tests.hpp" - -using namespace AMDiS; - -struct B {}; - -struct A -{ - A() = delete; - A(A const&) = delete; - A(A&&) = delete; - - A(B,B) {}; -}; - -struct MakeA -{ - A operator()(B const& b) const - { - return {b,b}; - } -}; - - -int main() -{ - Tuple<double,int> u{1.3, 2}; - Tuple<double,int> v{1, 2}; - - Tuple<int, double> t1; - get<0>(t1) = 42; - - Tuple<int> t2(3); - Tuple<int> t3(t1); - - // construct a tuple of non-copyable and non-movable types - Tuple<A> t4(tag::mapped_arg{}, MakeA{}, B{}); - - Dune::Hybrid::forEach(u, [](auto value) { std::cout << value << "\n"; }); - - Dune::Std::apply([](auto... values) { return std::make_tuple(values...); }, u); - - return report_errors(); -} \ No newline at end of file -- GitLab