From 232c202e87d4ebba68ac9e10558707a6b4504560 Mon Sep 17 00:00:00 2001 From: Timo Koch <timo.koch@iws.uni-stuttgart.de> Date: Tue, 26 Jul 2022 13:35:25 +0200 Subject: [PATCH] [fcdiamond][localresidual] Support time information in computeStorage This allows for an ad-hoc fix of the current known bug in multidomain, that does not correctly account for residual evaluations at different time levels in a time integration scheme. --- dumux/assembly/fcdiamondlocalresidual.hh | 78 +++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/dumux/assembly/fcdiamondlocalresidual.hh b/dumux/assembly/fcdiamondlocalresidual.hh index c122e09e63..3e6e1da4b6 100644 --- a/dumux/assembly/fcdiamondlocalresidual.hh +++ b/dumux/assembly/fcdiamondlocalresidual.hh @@ -25,6 +25,7 @@ #ifndef DUMUX_FC_DIAMOND_LOCAL_RESIDUAL_HH #define DUMUX_FC_DIAMOND_LOCAL_RESIDUAL_HH +#include <dune/common/std/type_traits.hh> #include <dune/geometry/type.hh> #include <dune/istl/matrix.hh> @@ -33,6 +34,22 @@ #include <dumux/assembly/fvlocalresidual.hh> #include <dumux/discretization/extrusion.hh> +namespace Dumux::Detail { + +template<class Imp, class P, class G, class S, class V> +using TimeInfoInterfaceDiamondDetector = decltype( + std::declval<Imp>().computeStorage( + std::declval<P>(), std::declval<G>(), std::declval<S>(), std::declval<V>(), true + ) +); + +template<class Imp, class P, class G, class S, class V> +constexpr inline bool hasTimeInfoInterfaceDiamond() +{ return Dune::Std::is_detected<TimeInfoInterfaceDiamondDetector, Imp, P, G, S, V>::value; } + +} // end namespace Dumux::Detail + + namespace Dumux { /*! @@ -45,6 +62,7 @@ template<class TypeTag> class FaceCenteredDiamondLocalResidual : public FVLocalResidual<TypeTag> { using ParentType = FVLocalResidual<TypeTag>; + using Implementation = GetPropType<TypeTag, Properties::LocalResidual>; using Scalar = GetPropType<TypeTag, Properties::Scalar>; using Problem = GetPropType<TypeTag, Properties::Problem>; using GridGeometry = GetPropType<TypeTag, Properties::GridGeometry>; @@ -52,7 +70,9 @@ class FaceCenteredDiamondLocalResidual : public FVLocalResidual<TypeTag> using Element = typename GridView::template Codim<0>::Entity; using ElementBoundaryTypes = GetPropType<TypeTag, Properties::ElementBoundaryTypes>; using FVElementGeometry = typename GridGeometry::LocalView; - using ElementVolumeVariables = typename GetPropType<TypeTag, Properties::GridVolumeVariables>::LocalView; + using GridVolumeVariables = GetPropType<TypeTag, Properties::GridVolumeVariables>; + using ElementVolumeVariables = typename GridVolumeVariables::LocalView; + using VolumeVariables = typename GridVolumeVariables::VolumeVariables; using SubControlVolume = typename FVElementGeometry::SubControlVolume; using SubControlVolumeFace = typename FVElementGeometry::SubControlVolumeFace; using ElementFluxVariablesCache = typename GetPropType<TypeTag, Properties::GridFluxVariablesCache>::LocalView; @@ -129,6 +149,62 @@ public: return flux; } + + using ParentType::evalStorage; + /*! + * \brief Compute the storage local residual, i.e. the deviation of the + * storage term from zero for instationary problems. + * + * \param residual The residual vector to fill + * \param problem The problem to solve + * \param element The DUNE Codim<0> entity for which the residual + * ought to be calculated + * \param fvGeometry The finite-volume geometry of the element + * \param prevElemVolVars The volume averaged variables for all + * sub-control volumes of the element at the previous time level + * \param curElemVolVars The volume averaged variables for all + * sub-control volumes of the element at the current time level + * \param scv The sub control volume the storage term is integrated over + */ + void evalStorage(ElementResidualVector& residual, + const Problem& problem, + const Element& element, + const FVElementGeometry& fvGeometry, + const ElementVolumeVariables& prevElemVolVars, + const ElementVolumeVariables& curElemVolVars, + const SubControlVolume& scv) const + { + const auto& curVolVars = curElemVolVars[scv]; + const auto& prevVolVars = prevElemVolVars[scv]; + + // Compute storage with the model specific storage residual + // This addresses issues #792/#940 in ad-hoc way by additionally providing crude time level information (previous or current) + // to the low-level interfaces if this is supported by the LocalResidual implementation + NumEqVector prevStorage = computeStorageImpl_(problem, fvGeometry, scv, prevVolVars, /*previous time level?*/true); + NumEqVector storage = computeStorageImpl_(problem, fvGeometry, scv, curVolVars, /*previous time level?*/false); + + prevStorage *= prevVolVars.extrusionFactor(); + storage *= curVolVars.extrusionFactor(); + + storage -= prevStorage; + storage *= Extrusion::volume(scv); + storage /= this->timeLoop().timeStepSize(); + + residual[scv.localDofIndex()] += storage; + } + +private: + NumEqVector computeStorageImpl_(const Problem& problem, + const FVElementGeometry& fvGeometry, + const SubControlVolume& scv, + const VolumeVariables& volVars, + [[maybe_unused]] bool isPreviousTimeStep) const + { + if constexpr (Detail::hasTimeInfoInterfaceDiamond<Implementation, Problem, FVElementGeometry, SubControlVolume, VolumeVariables>()) + return this->asImp().computeStorage(problem, fvGeometry, scv, volVars, isPreviousTimeStep); + else + return this->asImp().computeStorage(problem, scv, volVars); + } }; } // end namespace Dumux -- GitLab