diff --git a/dumux/multidomain/newtonsolver.hh b/dumux/multidomain/newtonsolver.hh index 0028df82bc5541a2e9c290f9bc4ff5aea8de6fee..e63fb4fd77de82d57a772b13efeed42b53e6bc12 100644 --- a/dumux/multidomain/newtonsolver.hh +++ b/dumux/multidomain/newtonsolver.hh @@ -29,19 +29,15 @@ #include <dumux/nonlinear/newtonsolver.hh> namespace Dumux { +namespace Detail { -namespace MDDetail { - -template<class Assembler, class IdType> -using GridVariables = std::decay_t<decltype(std::declval<Assembler>().gridVariables(IdType()))>; - -template<class Assembler, class IdType> -using GetPVSwitch = typename GridVariables<Assembler, IdType>::VolumeVariables::PrimaryVariableSwitch; +template<class Assembler, class Index> +using DetectPVSwitchMultiDomain = typename Assembler::template GridVariables<Index::value>::VolumeVariables::PrimaryVariableSwitch; template<class Assembler, std::size_t i> -using PrimaryVariableSwitch = Dune::Std::detected_or<int, GetPVSwitch, Assembler, Dune::index_constant<i>>; +using GetPVSwitchMultiDomain = Dune::Std::detected_or<int, DetectPVSwitchMultiDomain, Assembler, Dune::index_constant<i>>; -} +} // end namespace Detail /*! * \ingroup Nonlinear @@ -57,15 +53,14 @@ class MultiDomainNewtonSolver: public NewtonSolver<Assembler, LinearSolver, Reas using SolutionVector = typename Assembler::ResidualType; template<std::size_t i> - using PrimaryVariableSwitch = typename MDDetail::PrimaryVariableSwitch<Assembler, i>::type; + using PrimaryVariableSwitch = typename Detail::GetPVSwitchMultiDomain<Assembler, i>::type; template<std::size_t i> - using PrivarSwitchPtr = std::unique_ptr<PrimaryVariableSwitch<i>>; - - using PriVarSwitchPtrTuple = typename Assembler::Traits::template MakeTuple<PrivarSwitchPtr>; + using HasPriVarsSwitch = typename Detail::GetPVSwitchMultiDomain<Assembler, i>::value_t; // std::true_type or std::false_type template<std::size_t i> - using HasPriVarsSwitch = typename MDDetail::PrimaryVariableSwitch<Assembler, i>::value_t; + using PrivarSwitchPtr = std::unique_ptr<PrimaryVariableSwitch<i>>; + using PriVarSwitchPtrTuple = typename Assembler::Traits::template MakeTuple<PrivarSwitchPtr>; public: @@ -114,7 +109,7 @@ public: using namespace Dune::Hybrid; forEach(std::make_index_sequence<Assembler::Traits::numSubDomains>{}, [&](auto&& id) { - resetPriVarSwitch_(u[id].size(), id, HasPriVarsSwitch<id>()); + resetPriVarSwitch_(u[id].size(), id, HasPriVarsSwitch<id>{}); }); } @@ -143,7 +138,7 @@ public: using namespace Dune::Hybrid; forEach(std::make_index_sequence<Assembler::Traits::numSubDomains>{}, [&](auto&& id) { - invokePriVarSwitch_(uCurrentIter[id], id, HasPriVarsSwitch<id>()); + invokePriVarSwitch_(uCurrentIter[id], id, HasPriVarsSwitch<id>{}); }); ParentType::newtonEndStep(uCurrentIter, uLastIter); @@ -152,11 +147,15 @@ public: private: - + /*! + * \brief Reset the privar switch state, noop if there is no priVarSwitch + */ template<std::size_t i> - void resetPriVarSwitch_(const std::size_t numDofs, Dune::index_constant<i> id, std::false_type) - {} + void resetPriVarSwitch_(const std::size_t numDofs, Dune::index_constant<i> id, std::false_type) {} + /*! + * \brief Switch primary variables if necessary + */ template<std::size_t i> void resetPriVarSwitch_(const std::size_t numDofs, Dune::index_constant<i> id, std::true_type) { @@ -165,10 +164,15 @@ private: priVarsSwitchedInLastIteration_[i] = false; } + /*! + * \brief Switch primary variables if necessary, noop if there is no priVarSwitch + */ template<class SubSol, std::size_t i> - void invokePriVarSwitch_(SubSol&, Dune::index_constant<i> id, std::false_type) - {} + void invokePriVarSwitch_(SubSol&, Dune::index_constant<i> id, std::false_type) {} + /*! + * \brief Switch primary variables if necessary + */ template<class SubSol, std::size_t i> void invokePriVarSwitch_(SubSol& uCurrentIter, Dune::index_constant<i> id, std::true_type) { @@ -198,7 +202,7 @@ private: } } - + //! the coupling manager std::shared_ptr<CouplingManager> couplingManager_; //! the class handling the primary variable switch diff --git a/dumux/nonlinear/newtonsolver.hh b/dumux/nonlinear/newtonsolver.hh index f81f87857010ccfc10dc881dcd343d8b65a6d360..50b124211369dafe9122865172438832ee2d3f73 100644 --- a/dumux/nonlinear/newtonsolver.hh +++ b/dumux/nonlinear/newtonsolver.hh @@ -29,6 +29,7 @@ #include <cmath> #include <memory> #include <iostream> +#include <type_traits> #include <dune/common/timer.hh> #include <dune/common/exceptions.hh> @@ -49,8 +50,8 @@ #include "newtonconvergencewriter.hh" namespace Dumux { - namespace Detail { + //! helper struct detecting if an assembler supports partial reassembly struct supportsPartialReassembly { @@ -63,13 +64,12 @@ struct supportsPartialReassembly //! helper aliases to extract a primary variable switch from the VolumeVariables (if defined, yields int otherwise) template<class Assembler> -using GetPVSwitch = typename Assembler::GridVariables::VolumeVariables::PrimaryVariableSwitch; +using DetectPVSwitch = typename Assembler::GridVariables::VolumeVariables::PrimaryVariableSwitch; template<class Assembler> -using PrimaryVariableSwitch = Dune::Std::detected_or<int, GetPVSwitch, Assembler>; - -} +using GetPVSwitch = Dune::Std::detected_or<int, DetectPVSwitch, Assembler>; +} // end namespace Detail /*! * \ingroup Nonlinear @@ -91,8 +91,9 @@ class NewtonSolver using SolutionVector = typename Assembler::ResidualType; using ConvergenceWriter = ConvergenceWriterInterface<SolutionVector>; - using PrimaryVariableSwitch = typename Detail::PrimaryVariableSwitch<Assembler>::type; - static constexpr bool hasPriVarsSwitch = Detail::PrimaryVariableSwitch<Assembler>::value_t::value; + using PrimaryVariableSwitch = typename Detail::GetPVSwitch<Assembler>::type; + using HasPriVarsSwitch = typename Detail::GetPVSwitch<Assembler>::value_t; // std::true_type or std::false_type + static constexpr bool hasPriVarsSwitch() { return HasPriVarsSwitch::value; }; public: @@ -124,7 +125,7 @@ public: if (enablePartialReassembly_) partialReassembler_ = std::make_unique<Reassembler>(*assembler_); - if (hasPriVarsSwitch) + if (hasPriVarsSwitch()) { const int priVarSwitchVerbosity = getParamFromGroup<int>(paramGroup, "PrimaryVariableSwitch.Verbosity", 1); priVarSwitch_ = std::make_unique<PrimaryVariableSwitch>(priVarSwitchVerbosity); @@ -254,7 +255,7 @@ public: virtual void newtonBegin(const SolutionVector& u) { numSteps_ = 0; - resetPriVarSwitch_(u.size()); + resetPriVarSwitch_(u.size(), HasPriVarsSwitch{}); } /*! @@ -467,7 +468,7 @@ public: virtual void newtonEndStep(SolutionVector &uCurrentIter, const SolutionVector &uLastIter) { - invokePriVarSwitch_(uCurrentIter); + invokePriVarSwitch_(uCurrentIter, HasPriVarsSwitch{}); ++numSteps_; @@ -650,23 +651,29 @@ protected: Assembler& assembler() { return *assembler_; } - template<bool enable = hasPriVarsSwitch, std::enable_if_t<!enable, int> = 0> - void resetPriVarSwitch_(const std::size_t numDofs) - {} + /*! + * \brief Reset the privar switch state, noop if there is no priVarSwitch + */ + void resetPriVarSwitch_(const std::size_t numDofs, std::false_type) {} - template<bool enable = hasPriVarsSwitch, std::enable_if_t<enable, int> = 0> - void resetPriVarSwitch_(const std::size_t numDofs) + /*! + * \brief Reset the privar switch state + */ + void resetPriVarSwitch_(const std::size_t numDofs, std::true_type) { priVarSwitch_->reset(numDofs); priVarsSwitchedInLastIteration_ = false; } - template<bool enable = hasPriVarsSwitch, std::enable_if_t<!enable, int> = 0> - void invokePriVarSwitch_(SolutionVector&) - {} + /*! + * \brief Switch primary variables if necessary, noop if there is no priVarSwitch + */ + void invokePriVarSwitch_(SolutionVector&, std::false_type) {} - template<bool enable = hasPriVarsSwitch, std::enable_if_t<enable, int> = 0> - void invokePriVarSwitch_(SolutionVector& uCurrentIter) + /*! + * \brief Switch primary variables if necessary + */ + void invokePriVarSwitch_(SolutionVector& uCurrentIter, std::true_type) { // update the variable switch (returns true if the pri vars at at least one dof were switched) // for disabled grid variable caching