diff --git a/amdis/Integrate.hpp b/amdis/Integrate.hpp index 69489397de103d5b79c9b13ec2e81f50f2cac678..6b8498ab35ea448f80e508b3b74200b1725a1851 100644 --- a/amdis/Integrate.hpp +++ b/amdis/Integrate.hpp @@ -32,15 +32,6 @@ namespace AMDiS return gridView.comm().sum(result); } - template - auto integrateImpl(GF&& gf, GV const& gv, QP makeQuad, std::true_type) - { - return integrateImpl(FWD(gf), gv, makeQuad); - } - - template - auto integrateImpl(GF&&, GV&&, QP&&, std::false_type) { return 0.0; } - } // end namespace Impl @@ -58,16 +49,9 @@ namespace AMDiS { auto&& gridFct = makeGridFunction(FWD(expr), gridView); - // test whether the gridFct model `Concepts::HasLocalFunctionOrder` - using GF = TYPEOF(gridFct); - static const bool expr_has_order = Concepts::HasLocalFunctionOrder; - static_assert(expr_has_order, - "Polynomial degree of expression can not be deduced. You need to provide an explicit value for the quadrature degree or a quadrature rule in `integrate()`."); - using Rules = Dune::QuadratureRules; - auto makeQuad = [](auto&& t, auto&& lf) { return Rules::rule(t, order(lf)); }; - - return Impl::integrateImpl(FWD(gridFct), gridView, makeQuad, bool_); + return Impl::integrateImpl(FWD(gridFct), gridView, + [](auto&& t, auto&& lf) { return Rules::rule(t, polynomialDegree(lf).value()); }); } @@ -84,7 +68,8 @@ namespace AMDiS auto integrate(Expr&& expr, GridView const& gridView, QuadratureRule const& quad) { auto&& gridFct = makeGridFunction(FWD(expr), gridView); - return Impl::integrateImpl(FWD(gridFct), gridView, [&](auto&&, auto&&) { return quad; }); + return Impl::integrateImpl(FWD(gridFct), gridView, + [&](auto&&, auto&&) { return quad; }); } diff --git a/amdis/LocalOperator.hpp b/amdis/LocalOperator.hpp index 5cf504149e979ffda8523465e7d92be4dfe1d59f..663bceecdce5617786391873bb18be299d64cc5a 100644 --- a/amdis/LocalOperator.hpp +++ b/amdis/LocalOperator.hpp @@ -132,8 +132,8 @@ namespace AMDiS test_warning(coeffDegree >= 0, "polynomial order of coefficient function not determined. Use order 4 by default."); - int psiDegree = polynomialDegree(rowNode); - int phiDegree = polynomialDegree(colNode); + int psiDegree = polynomialDegree(rowNode).value_or(1); + int phiDegree = polynomialDegree(colNode).value_or(1); int degree = psiDegree + phiDegree + (coeffDegree >= 0 ? coeffDegree : 4); if (isSimplex_) @@ -157,7 +157,7 @@ namespace AMDiS test_warning(coeffDegree >= 0, "polynomial order of coefficient function not determined. Use order 4 by default."); - int psiDegree = polynomialDegree(node); + int psiDegree = polynomialDegree(node).value_or(1); int degree = psiDegree + (coeffDegree >= 0 ? coeffDegree : 4); if (isSimplex_) diff --git a/amdis/common/CMakeLists.txt b/amdis/common/CMakeLists.txt index 1d6b5c22a02ed87241f77c007ee5e41a8f63e69d..bee9ae3fdd7bc55d6047472e9950e5d78c1cccd9 100644 --- a/amdis/common/CMakeLists.txt +++ b/amdis/common/CMakeLists.txt @@ -23,6 +23,7 @@ install(FILES Literals.hpp Logical.hpp Math.hpp + PolynomialDegree.hpp Range.hpp QuadMath.hpp SharedPtr.hpp diff --git a/amdis/common/PolynomialDegree.hpp b/amdis/common/PolynomialDegree.hpp new file mode 100644 index 0000000000000000000000000000000000000000..6caafb6260833c46bb2247cceaef5686ab4934dc --- /dev/null +++ b/amdis/common/PolynomialDegree.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +#include + +namespace AMDiS +{ + namespace Traits + { + template + using OrderFreeFunction = decltype(order(std::declval())); + + template + using OrderMemberFunction = decltype(std::declval().order()); + + } // end namespace Traits + + + /// Polynomial degree of a local function or a finite-element space or anything + /// else that defines an order function. + /** + * Return the derived or defined polynomial degree of a function `f` + * If no order is defined, return an empty optional. + **/ + template + std::optional polynomialDegree(F const& f) + { + if constexpr (Dune::Std::is_detected_v) + return order(f); + else if constexpr (Dune::Std::is_detected_v) + return f.order(); + else + return std::nullopt; + } + +} // end namespace AMDiS \ No newline at end of file diff --git a/amdis/functions/CMakeLists.txt b/amdis/functions/CMakeLists.txt index 73697b6352cfe82f81c4258f7bf7ecc4ea1ef8af..0491d5b0d970908248a5bc60afbf338c9be169a6 100644 --- a/amdis/functions/CMakeLists.txt +++ b/amdis/functions/CMakeLists.txt @@ -5,5 +5,6 @@ install(FILES Interpolate.hpp NodeIndices.hpp Nodes.hpp + Order.hpp ParallelGlobalBasis.hpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/functions) diff --git a/amdis/functions/Order.hpp b/amdis/functions/Order.hpp new file mode 100644 index 0000000000000000000000000000000000000000..e6a26ab743fe0acd708399c94b5d063d29c12d6d --- /dev/null +++ b/amdis/functions/Order.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include + +#include + +#include +#include + +namespace AMDiS +{ + template + auto order(Node const& node) + -> decltype(node.finiteElement().localBasis().order()) + { + return node.finiteElement().localBasis().order(); + } + + template )> + int order(Node const& node) + { + return order(node.child(0u)); + } + + template )> + int order(Node const& node) + { + int degree = 0; + Tools::for_range<0,Node::CHILDREN>([&](auto const _i) { + degree = std::max(degree, int(order(node.child(_i)))); + }); + return degree; + } + +} // end namespace AMDiS diff --git a/amdis/gridfunctions/DiscreteLocalFunction.inc.hpp b/amdis/gridfunctions/DiscreteLocalFunction.inc.hpp index 5e6140fe143c25311c70fd1eea7aa736fc41f6ae..a668a1103ae25996fd1e236f3e22426b4b3b4d62 100644 --- a/amdis/gridfunctions/DiscreteLocalFunction.inc.hpp +++ b/amdis/gridfunctions/DiscreteLocalFunction.inc.hpp @@ -3,7 +3,9 @@ #include #include #include +#include #include +#include #include #include @@ -130,11 +132,13 @@ public: return PartialLocalFunction{globalFunction_, type}; } - /// \brief The \ref polynomialDegree() of the LocalFunctions - int order() const + /// \brief The polynomial degree of the LocalFunctions basis-functions + auto order() const + -> decltype(order(std::declval())) { assert( bound_ ); - return polynomialDegree(*subTree_); + using AMDiS::order; + return order(*subTree_); } /// \brief Return the bound element @@ -207,10 +211,12 @@ public: bound_ = false; } - int order() const + auto order() const + -> decltype(order(std::declval())) { assert( bound_ ); - return std::max(0, polynomialDegree(*subTree_)-1); + using AMDiS::order; + return std::max(0, int(order(*subTree_))-1); } /// Return the bound element diff --git a/amdis/gridfunctions/FunctorGridFunction.hpp b/amdis/gridfunctions/FunctorGridFunction.hpp index 1d9b7b7ad2e83cf71d9e7550a030dc2b9985ee07..cd54c933eb3f3bb6db365ec610132104b651c4af 100644 --- a/amdis/gridfunctions/FunctorGridFunction.hpp +++ b/amdis/gridfunctions/FunctorGridFunction.hpp @@ -152,11 +152,11 @@ namespace AMDiS /** * **Requirements:** * - The functor `F` must model `Concepts::HasFunctorOrder` - * - All localFunctions `LFs...` must model `Concepts::HasOrder` + * - All localFunctions `LFs...` must model `Concepts::Polynomial` **/ template - && (Concepts::HasOrder &&...))> + && (Concepts::Polynomial &&...))> int order(FunctorLocalFunction const& lf) { return Tools::apply([&lf](auto const&... lgfs) { diff --git a/amdis/gridfunctions/Order.hpp b/amdis/gridfunctions/Order.hpp index e1950fe3655991627e8a7e274d4d839bf77c90df..4fe950bf22025d4aafbe5a4c096d843c3722c5c1 100644 --- a/amdis/gridfunctions/Order.hpp +++ b/amdis/gridfunctions/Order.hpp @@ -2,7 +2,7 @@ #include -#include +#include namespace AMDiS { @@ -14,7 +14,6 @@ namespace AMDiS return lf.order(); } - namespace Concepts { /** \addtogroup Concepts @@ -23,15 +22,7 @@ namespace AMDiS namespace Definition { - struct HasLocalFunctionOrder - { - template - auto require(F&& f) -> decltype( - order(localFunction(f)) - ); - }; - - struct HasOrder + struct Polynomial { template auto require(F&& f) -> decltype( @@ -41,24 +32,14 @@ namespace AMDiS } // end namespace Definition - - /// \brief GridFunction GF has free function `order(localFunction(F))` - template - constexpr bool HasLocalFunctionOrder = models; - - template - using HasLocalFunctionOrder_t = models_t; - - /// \brief LocalFuncion LF has free function `order(F)` template - constexpr bool HasOrder = models; + constexpr bool Polynomial = models; template - using HasOrder_t = models_t; + using Polynomial_t = models_t; /** @} **/ } // end namespace Concepts - } // end namespace AMDiS diff --git a/amdis/localoperators/ConvectionDiffusionOperator.hpp b/amdis/localoperators/ConvectionDiffusionOperator.hpp index 72ab1925c7fda35416362310ec23931cc0a72681..e11401f1c7b7e1843b7c53c90b4d9d90fba13b09 100644 --- a/amdis/localoperators/ConvectionDiffusionOperator.hpp +++ b/amdis/localoperators/ConvectionDiffusionOperator.hpp @@ -176,16 +176,10 @@ namespace AMDiS private: - template - using HasLocalFunctionOrder = decltype( order(std::declval()) ); - template int coeffOrder(LocalFct const& localFct) { - if constexpr (Dune::Std::is_detected::value) - return order(localFct); - else - return 0; + return polynomialDegree(localFct).value_or(0); } template diff --git a/amdis/typetree/FiniteElementType.hpp b/amdis/typetree/FiniteElementType.hpp index 682a74472f2912cbf7f3d169ce40c1fb8fa45474..3c6fcfb6664e34d6af8d97ef2326f7ae7e544188 100644 --- a/amdis/typetree/FiniteElementType.hpp +++ b/amdis/typetree/FiniteElementType.hpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -16,10 +17,8 @@ namespace AMDiS template struct FiniteElementTypeImpl { - static_assert( Dune::AlwaysFalse::value, "Unknown node-type for range definition" ); - - // polynomial degree of finite-element basis functions - static int order(Node const&) { return 0; } + static_assert(Dune::AlwaysFalse::value, + "Unknown node-type for range definition"); }; } @@ -30,12 +29,6 @@ namespace AMDiS template using FiniteElementType_t = typename FiniteElementType::type; - template - int polynomialDegree(Node const& node) - { - return FiniteElementType::order(node); - } - namespace Impl { @@ -44,11 +37,6 @@ namespace AMDiS struct FiniteElementTypeImpl { using type = typename Node::FiniteElement; - - static int order(Node const& node) - { - return node.finiteElement().localBasis().order(); - } }; // Power node @@ -57,11 +45,6 @@ namespace AMDiS { using ChildNode = typename Node::template Child<0>::type; using type = FiniteElementType_t; - - static int order(Node const& node) - { - return FiniteElementType::order(node.child(0)); - } }; // Composite node @@ -69,17 +52,7 @@ namespace AMDiS struct FiniteElementTypeImpl { using type = tag::unknown; // no common FiniteElement type - - static int order(Node const& node) - { - int degree = 0; - Tools::for_range<0,Node::CHILDREN>([&](auto const _i) { - degree = std::max(degree, polynomialDegree(node.child(_i))); - }); - return degree; - } }; } // end namespace Impl - } // end namespace AMDiS diff --git a/amdis/utility/QuadratureFactory.hpp b/amdis/utility/QuadratureFactory.hpp index c4fdf3bef95511e66347081528126482024b80af..6b53797c03f817e0ddbb28796f13beacb2c9bee0 100644 --- a/amdis/utility/QuadratureFactory.hpp +++ b/amdis/utility/QuadratureFactory.hpp @@ -5,6 +5,7 @@ #include #include +#include #include namespace AMDiS @@ -39,27 +40,16 @@ namespace AMDiS }; - template - using HasLocalFunctionOrder = decltype( order(std::declval()) ); - - /// \brief Factory for quadrature rule, that calculates the coefficient order from /// a localFunction passed to the bind method. template class QuadFactoryFromLocalFunction : public QuadratureFactory { - using Concept = Dune::Std::is_detected; - static_assert(Concept::value, - "Polynomial order of GridFunction can not be extracted. Provide an explicit order parameter instead."); - public: void bind(LocalFunction const& localFct) final { - if constexpr (Concept::value) - order_ = AMDiS::order(localFct); - else - order_ = -1; + order_ = polynomialDegree(localFct).value(); } int order() const final { return order_; } diff --git a/test/FiniteElementTypeTest.cpp b/test/FiniteElementTypeTest.cpp index f3d33522cf4a217cc40fb14333703f20f3b1dd6b..b9f67a0576f2c257e2d21a84a831ef5177c263e2 100644 --- a/test/FiniteElementTypeTest.cpp +++ b/test/FiniteElementTypeTest.cpp @@ -4,6 +4,8 @@ #include #include +#include +#include #include #include "Tests.hpp" @@ -36,14 +38,14 @@ int main() localView.bind(e); auto node = localView.tree(); - AMDIS_TEST_EQ( polynomialDegree(node), k+1 ); // maximum over all polynomial degrees + AMDIS_TEST_EQ( polynomialDegree(node).value(), k+1 ); // maximum over all polynomial degrees static_assert( std::is_same_v>, "" ); auto v_node = TypeTree::child(node, _0); - AMDIS_TEST_EQ( polynomialDegree(v_node), k+1 ); + AMDIS_TEST_EQ( polynomialDegree(v_node).value(), k+1 ); auto p_node = TypeTree::child(node, _1); - AMDIS_TEST_EQ( polynomialDegree(p_node), k ); + AMDIS_TEST_EQ( polynomialDegree(p_node).value(), k ); } return report_errors();