diff --git a/dumux/assembly/partialreassembler.hh b/dumux/assembly/partialreassembler.hh index 6eff09375e9741ed7021de353dd13d051faf98b7..1ee55a31b241a64e7a205532aaf312be71dd53bc 100644 --- a/dumux/assembly/partialreassembler.hh +++ b/dumux/assembly/partialreassembler.hh @@ -380,6 +380,13 @@ public: using ParentType::ParentType; }; +//! helper function to determine whether the an engine class has vertex colors +template<class Engine> +auto hasVertexColor() +{ + return isValid([](auto&& a) -> decltype(a.vertexColor(0)) {}).template check<Engine>(); +} + /*! * \ingroup Assembly * \brief detects which entries in the Jacobian have to be recomputed @@ -396,9 +403,6 @@ class PartialReassembler static constexpr DiscretizationMethod discMethod = FVGridGeometry::discMethod; using Engine = PartialReassemblerEngine<Assembler, discMethod>; - static constexpr auto hasVertexColor = Dumux::isValid([](auto&& a) -> decltype(a.vertexColor(0)) {}); - static constexpr bool engineHasVertexColor = decltype(hasVertexColor(std::declval<Engine>()))::value; - public: /*! @@ -465,7 +469,8 @@ public: EntityColor dofColor(size_t idx) const { return engine_.dofColor(idx); } - template<bool enable = engineHasVertexColor, typename std::enable_if_t<enable, int> = 0> + template<bool enable = decltype(hasVertexColor<Engine>())::value, + typename std::enable_if_t<enable, int> = 0> EntityColor vertexColor(size_t idx) const { return engine_.vertexColor(idx); } diff --git a/dumux/common/typetraits/isvalid.hh b/dumux/common/typetraits/isvalid.hh index 4be5daa17fd4137c9ef3d9a6a6ec09cbdde8c997..0faa98375bc3177fd2529767e7cbb15434486d1c 100644 --- a/dumux/common/typetraits/isvalid.hh +++ b/dumux/common/typetraits/isvalid.hh @@ -80,8 +80,9 @@ public: * Usage: * If you want to test if a class has the member function resize(std::size_t) create a test functor * \code - * constexpr auto hasResize = isValid([](auto&& c) -> decltype(c.resize(std::size_t(1))) {}; }); + * auto hasResize = isValid([](auto&& c) -> decltype(c.resize(std::size_t(1))) {}; }); * \endcode + * \note hasResize can be constexpr in C++17 which allows lambdas in constexpr functions * The you can use the test in compile time expressions * \code * template<class T> diff --git a/dumux/nonlinear/newtonsolver.hh b/dumux/nonlinear/newtonsolver.hh index ee493a2b21049f24e0759e716d30e9f6d388afdb..51ada10fba9195f663d781860862049ad4af1f89 100644 --- a/dumux/nonlinear/newtonsolver.hh +++ b/dumux/nonlinear/newtonsolver.hh @@ -49,6 +49,20 @@ namespace Dumux { +//! helper function detecting if an assembler supports partial reassembly +template<class Assembler> +auto supportsPartialReassembly(const Assembler& assembler) noexcept +{ + using SolutionVector = typename Assembler::ResidualType; + using Reassembler = PartialReassembler<Assembler>; + + return isValid([](auto&& a) -> decltype( + a.assembleJacobianAndResidual(std::declval<Assembler>(), + std::declval<const SolutionVector&>(), + std::declval<const Reassembler*>()) + ){})(assembler); +} + /*! * \ingroup Nonlinear * \brief An implementation of a Newton controller @@ -68,13 +82,6 @@ class NewtonSolver using ConvergenceWriter = ConvergenceWriterInterface<SolutionVector>; using Reassembler = PartialReassembler<Assembler>; - // TODO: Require Reassembler argument from the standard interface - static constexpr auto supportsPartialReassembly = - Dumux::isValid([](auto&& a) -> decltype( - a.assembleJacobianAndResidual(std::declval<Assembler>(), - std::declval<const SolutionVector&>(), - std::declval<const Reassembler*>()) - ){}); public: using Communication = Comm; @@ -282,7 +289,7 @@ public: */ virtual void assembleLinearSystem(const SolutionVector& uCurrentIter) { - assembleLinearSystem_(uCurrentIter); + assembleLinearSystem_(*assembler_, uCurrentIter); if (enablePartialReassembly_) partialReassembler_->report(comm_, endIterMsgStream_); @@ -750,17 +757,17 @@ private: } //! assembleLinearSystem_ for assemblers that support partial reassembly - template<class A = Assembler> - auto assembleLinearSystem_(const SolutionVector& uCurrentIter) - -> typename std::enable_if_t<decltype(supportsPartialReassembly(std::declval<A>()))::value, void> + template<class A> + auto assembleLinearSystem_(const A& assembler, const SolutionVector& uCurrentIter) + -> typename std::enable_if_t<decltype(supportsPartialReassembly(assembler))::value, void> { assembler_->assembleJacobianAndResidual(uCurrentIter, partialReassembler_.get()); } //! assembleLinearSystem_ for assemblers that don't support partial reassembly - template<class A = Assembler> - auto assembleLinearSystem_(const SolutionVector& uCurrentIter) - -> typename std::enable_if_t<!decltype(supportsPartialReassembly(std::declval<A>()))::value, void> + template<class A> + auto assembleLinearSystem_(const A& assembler, const SolutionVector& uCurrentIter) + -> typename std::enable_if_t<!decltype(supportsPartialReassembly(assembler))::value, void> { assembler_->assembleJacobianAndResidual(uCurrentIter); } diff --git a/test/common/typetraits/test_isvalid.cc b/test/common/typetraits/test_isvalid.cc index 996bfaa92246532566ea80479958b918d3636345..1786f8d438e424b6e10f27065dc2202f1303d273 100644 --- a/test/common/typetraits/test_isvalid.cc +++ b/test/common/typetraits/test_isvalid.cc @@ -19,7 +19,7 @@ struct MyOtherVector { double resize; }; -constexpr auto hasResize = Dumux::isValid([](auto&& a) -> decltype(a.resize(std::size_t(1))) { }); +const auto hasResize = isValid([](auto&& a) -> decltype(a.resize(std::size_t(1))) { }); // using the check function template<class Vector, typename std::enable_if_t<hasResize.template check<Vector>(), int> = 0>