From 17422c49aa9eedbb5ef254f7662e19db10aaf436 Mon Sep 17 00:00:00 2001 From: Anna Mareike Kostelecky <anmako96@web.de> Date: Wed, 2 Oct 2024 14:18:51 +0200 Subject: [PATCH] [multidomain][freeflow] add init function with prevSol, when used as binary coupling manager Co-authored-by: Timo Koch <timokoch@uio.no> --- .../freeflowporenetwork/couplingmanager.hh | 87 +++++++++++++------ .../couplingmanager_base.hh | 70 +++++++++++---- .../freeflow/couplingmanager_staggered.hh | 53 ++++++++--- 3 files changed, 155 insertions(+), 55 deletions(-) diff --git a/dumux/multidomain/boundary/freeflowporenetwork/couplingmanager.hh b/dumux/multidomain/boundary/freeflowporenetwork/couplingmanager.hh index 2386f22da2..2b4f338e09 100644 --- a/dumux/multidomain/boundary/freeflowporenetwork/couplingmanager.hh +++ b/dumux/multidomain/boundary/freeflowporenetwork/couplingmanager.hh @@ -173,6 +173,10 @@ class FreeFlowPoreNetworkCouplingManager template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity; using SolutionVector = typename MDTraits::SolutionVector; + template<std::size_t id> + using SubSolutionVector + = std::decay_t<decltype(std::declval<SolutionVector>()[Dune::index_constant<id>()])>; + using CouplingConditions = FreeFlowPoreNetworkCouplingConditions<MDTraits, FreeFlowPoreNetworkCouplingManager<MDTraits>>; using CouplingMapper = StaggeredFreeFlowPoreNetworkCouplingMapper; @@ -195,38 +199,36 @@ public: GridVarsTuple&& gridVarsTuple, const SolutionVector& curSol) { - this->updateSolution(curSol); // generic coupling manager stores tuple of shared_ptr - - auto couplingMapper = std::make_shared<CouplingMapper>(); - couplingMapper->update(freeFlowMomentumProblem->gridGeometry(), - freeFlowMassProblem->gridGeometry(), - poreNetworkProblem->gridGeometry() - ); + // initialize sub coupling manager that are not stationary or transient problem specific + this->init_(freeFlowMomentumProblem, freeFlowMassProblem, poreNetworkProblem, std::forward<GridVarsTuple>(gridVarsTuple), curSol); - // initialize the binary sub coupling managers - typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage ffSolVecTuple; - std::get<0>(ffSolVecTuple) = std::get<freeFlowMomentumIndex>(this->curSol()); - std::get<1>(ffSolVecTuple) = std::get<freeFlowMassIndex>(this->curSol()); + // initialize stationary-specific sub coupling manager for free-flow + using FFSol = typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage; this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).init( freeFlowMomentumProblem, freeFlowMassProblem, std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<freeFlowMassIndex>(gridVarsTuple)), - ffSolVecTuple + FFSol{ std::get<freeFlowMomentumIndex>(this->curSol()), std::get<freeFlowMassIndex>(this->curSol()) } ); + } - typename SubCouplingManager<freeFlowMassIndex, poreNetworkIndex>::SolutionVectorStorage ffMassPmSolVecTuple; - std::get<0>(ffMassPmSolVecTuple) = std::get<freeFlowMassIndex>(this->curSol()); - std::get<1>(ffMassPmSolVecTuple) = std::get<poreNetworkIndex>(this->curSol()); - this->subCouplingManager(freeFlowMassIndex, poreNetworkIndex).init( - freeFlowMassProblem, poreNetworkProblem, couplingMapper, ffMassPmSolVecTuple - ); + template<class GridVarsTuple> + void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem, + std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem, + std::shared_ptr<Problem<poreNetworkIndex>> poreNetworkProblem, + GridVarsTuple&& gridVarsTuple, + const SolutionVector& curSol, + const SolutionVector& prevSol) + { + // initialize sub coupling manager that are not stationary or transient problem specific + this->init_(freeFlowMomentumProblem, freeFlowMassProblem, poreNetworkProblem, std::forward<GridVarsTuple>(gridVarsTuple), curSol); - typename SubCouplingManager<freeFlowMomentumIndex, poreNetworkIndex>::SolutionVectorStorage ffMomentumPmSolVecTuple; - std::get<0>(ffMomentumPmSolVecTuple) = std::get<freeFlowMomentumIndex>(this->curSol()); - std::get<1>(ffMomentumPmSolVecTuple) = std::get<poreNetworkIndex>(this->curSol()); - this->subCouplingManager(freeFlowMomentumIndex, poreNetworkIndex).init( - freeFlowMomentumProblem, poreNetworkProblem, - std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<poreNetworkIndex>(gridVarsTuple)), - couplingMapper, ffMomentumPmSolVecTuple + using FFSol = typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage; + using FFPrevSol = std::tuple<const SubSolutionVector<freeFlowMomentumIndex>*, const SubSolutionVector<freeFlowMassIndex>*>; + this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).init( + freeFlowMomentumProblem, freeFlowMassProblem, + std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<freeFlowMassIndex>(gridVarsTuple)), + FFSol{ std::get<freeFlowMomentumIndex>(this->curSol()), std::get<freeFlowMassIndex>(this->curSol()) }, + FFPrevSol{ &prevSol[freeFlowMomentumIndex], &prevSol[freeFlowMassIndex] } ); } @@ -476,6 +478,41 @@ public: return cm.couplingStencil(ii, elementI, scvI, jj); }); } + +private: + /* + * \brief Initializes sub-coupling managers for stationary and transient problems + */ + template<class GridVarsTuple> + void init_(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem, + std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem, + std::shared_ptr<Problem<poreNetworkIndex>> poreNetworkProblem, + GridVarsTuple&& gridVarsTuple, + const SolutionVector& curSol) + { + this->updateSolution(curSol); // generic coupling manager stores tuple of shared_ptr + + auto couplingMapper = std::make_shared<CouplingMapper>(); + couplingMapper->update(freeFlowMomentumProblem->gridGeometry(), + freeFlowMassProblem->gridGeometry(), + poreNetworkProblem->gridGeometry() + ); + + // initialize the binary sub coupling managers for stationary and transient problems + using FFMassPNMSol = typename SubCouplingManager<freeFlowMassIndex, poreNetworkIndex>::SolutionVectorStorage; + this->subCouplingManager(freeFlowMassIndex, poreNetworkIndex).init( + freeFlowMassProblem, poreNetworkProblem, couplingMapper, + FFMassPNMSol{ std::get<freeFlowMassIndex>(this->curSol()), std::get<poreNetworkIndex>(this->curSol()) } + ); + + using FFMomPNMSol = typename SubCouplingManager<freeFlowMomentumIndex, poreNetworkIndex>::SolutionVectorStorage; + this->subCouplingManager(freeFlowMomentumIndex, poreNetworkIndex).init( + freeFlowMomentumProblem, poreNetworkProblem, + std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<poreNetworkIndex>(gridVarsTuple)), + couplingMapper, FFMomPNMSol{ std::get<freeFlowMomentumIndex>(this->curSol()), std::get<poreNetworkIndex>(this->curSol()) } + ); + } + }; } // end namespace Dumux diff --git a/dumux/multidomain/boundary/freeflowporousmedium/couplingmanager_base.hh b/dumux/multidomain/boundary/freeflowporousmedium/couplingmanager_base.hh index 664d051fcc..2c469b314f 100644 --- a/dumux/multidomain/boundary/freeflowporousmedium/couplingmanager_base.hh +++ b/dumux/multidomain/boundary/freeflowporousmedium/couplingmanager_base.hh @@ -170,6 +170,10 @@ class FreeFlowPorousMediumCouplingManagerBase template<std::size_t id> using Element = typename GridView<id>::template Codim<0>::Entity; using SolutionVector = typename MDTraits::SolutionVector; + template<std::size_t id> + using SubSolutionVector + = std::decay_t<decltype(std::declval<SolutionVector>()[Dune::index_constant<id>()])>; + public: template<std::size_t i, std::size_t j> @@ -189,30 +193,36 @@ public: GridVarsTuple&& gridVarsTuple, const SolutionVector& curSol) { - this->updateSolution(curSol); // generic coupling manager stores tuple of shared_ptr + // initialize sub coupling manager that are not stationary or transient problem specific + this->init_(freeFlowMomentumProblem, freeFlowMassProblem, porousMediumProblem, std::forward<GridVarsTuple>(gridVarsTuple), curSol); - // initialize the binary sub coupling managers - typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage ffSolVecTuple; - std::get<0>(ffSolVecTuple) = std::get<freeFlowMomentumIndex>(this->curSol()); - std::get<1>(ffSolVecTuple) = std::get<freeFlowMassIndex>(this->curSol()); + // initialize stationary-specific sub coupling manager for free-flow + using FFSol = typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage; this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).init( freeFlowMomentumProblem, freeFlowMassProblem, std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<freeFlowMassIndex>(gridVarsTuple)), - ffSolVecTuple + FFSol{ std::get<freeFlowMomentumIndex>(this->curSol()), std::get<freeFlowMassIndex>(this->curSol()) } ); + } - typename SubCouplingManager<freeFlowMassIndex, porousMediumIndex>::SolutionVectorStorage ffMassPmSolVecTuple; - std::get<0>(ffMassPmSolVecTuple) = std::get<freeFlowMassIndex>(this->curSol()); - std::get<1>(ffMassPmSolVecTuple) = std::get<porousMediumIndex>(this->curSol()); - this->subCouplingManager(freeFlowMassIndex, porousMediumIndex).init( - freeFlowMassProblem, porousMediumProblem, ffMassPmSolVecTuple - ); + template<class GridVarsTuple> + void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem, + std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem, + std::shared_ptr<Problem<porousMediumIndex>> porousMediumProblem, + GridVarsTuple&& gridVarsTuple, + const SolutionVector& curSol, + const SolutionVector& prevSol) + { + // initialize sub coupling manager that are not stationary or transient problem specific + this->init_(freeFlowMomentumProblem, freeFlowMassProblem, porousMediumProblem, std::forward<GridVarsTuple>(gridVarsTuple), curSol); - typename SubCouplingManager<freeFlowMomentumIndex, porousMediumIndex>::SolutionVectorStorage ffMomentumPmSolVecTuple; - std::get<0>(ffMomentumPmSolVecTuple) = std::get<freeFlowMomentumIndex>(this->curSol()); - std::get<1>(ffMomentumPmSolVecTuple) = std::get<porousMediumIndex>(this->curSol()); - this->subCouplingManager(freeFlowMomentumIndex, porousMediumIndex).init( - freeFlowMomentumProblem, porousMediumProblem, ffMomentumPmSolVecTuple + using FFSol = typename SubCouplingManager<freeFlowMomentumIndex, freeFlowMassIndex>::SolutionVectorStorage; + using FFPrevSol = std::tuple<const SubSolutionVector<freeFlowMomentumIndex>*, const SubSolutionVector<freeFlowMassIndex>*>; + this->subCouplingManager(freeFlowMomentumIndex, freeFlowMassIndex).init( + freeFlowMomentumProblem, freeFlowMassProblem, + std::make_tuple(std::get<freeFlowMomentumIndex>(gridVarsTuple), std::get<freeFlowMassIndex>(gridVarsTuple)), + FFSol{ std::get<freeFlowMomentumIndex>(this->curSol()), std::get<freeFlowMassIndex>(this->curSol()) }, + FFPrevSol{ &prevSol[freeFlowMomentumIndex], &prevSol[freeFlowMassIndex] } ); } @@ -271,6 +281,32 @@ public: return cm.couplingStencil(ii, elementI, scvI, jj); }); } +private: + /* + * \brief Initializes sub-coupling managers for stationary and transient problems + */ + template<class GridVarsTuple> + void init_(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem, + std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem, + std::shared_ptr<Problem<porousMediumIndex>> porousMediumProblem, + GridVarsTuple&& gridVarsTuple, + const SolutionVector& curSol) + { + this->updateSolution(curSol); // generic coupling manager stores tuple of shared_ptr + + // initialize the binary sub coupling managers + using FFMassPMSol = typename SubCouplingManager<freeFlowMassIndex, porousMediumIndex>::SolutionVectorStorage; + this->subCouplingManager(freeFlowMassIndex, porousMediumIndex).init( + freeFlowMassProblem, porousMediumProblem, + FFMassPMSol{ std::get<freeFlowMassIndex>(this->curSol()), std::get<porousMediumIndex>(this->curSol()) } + ); + + using FFMomPMSol = typename SubCouplingManager<freeFlowMomentumIndex, porousMediumIndex>::SolutionVectorStorage; + this->subCouplingManager(freeFlowMomentumIndex, porousMediumIndex).init( + freeFlowMomentumProblem, porousMediumProblem, + FFMomPMSol{ std::get<freeFlowMomentumIndex>(this->curSol()), std::get<porousMediumIndex>(this->curSol()) } + ); + } }; } // end namespace Dumux diff --git a/dumux/multidomain/freeflow/couplingmanager_staggered.hh b/dumux/multidomain/freeflow/couplingmanager_staggered.hh index d80e34c868..f2d03395dc 100644 --- a/dumux/multidomain/freeflow/couplingmanager_staggered.hh +++ b/dumux/multidomain/freeflow/couplingmanager_staggered.hh @@ -73,6 +73,15 @@ private: using Scalar = typename Traits::Scalar; using SolutionVector = typename Traits::SolutionVector; + template<std::size_t id> + using SubSolutionVector + = std::decay_t<decltype(std::declval<SolutionVector>()[Dune::index_constant<id>()])>; + + template<std::size_t id> + using ConstSubSolutionVectorPtr = const SubSolutionVector<id>*; + + using PrevSolutionVectorStorage = typename Traits::template Tuple<ConstSubSolutionVectorPtr>; + using CouplingStencilType = std::vector<std::size_t>; using GridVariablesTuple = typename Traits::template TupleOfSharedPtr<GridVariables>; @@ -131,8 +140,9 @@ public: const SolutionVector& prevSol) { init(momentumProblem, massProblem, std::forward<GridVariablesTuple>(gridVariables), curSol); - prevSol_ = &prevSol; - isTransient_ = true; + + Dune::Hybrid::forEach(std::make_index_sequence<Traits::numSubDomains>{}, [&](auto i) + { std::get<i>(prevSolutions_) = &prevSol[i]; }); } //! use as binary coupling manager in multi model context @@ -148,6 +158,17 @@ public: computeCouplingStencils_(); } + //! use as binary coupling manager in multi model context and for transient problems + void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> momentumProblem, + std::shared_ptr<Problem<freeFlowMassIndex>> massProblem, + GridVariablesTuple&& gridVariables, + const typename ParentType::SolutionVectorStorage& curSol, + const PrevSolutionVectorStorage& prevSol) + { + init(momentumProblem, massProblem, std::forward<GridVariablesTuple>(gridVariables), curSol); + prevSolutions_ = prevSol; + } + // \} using CouplingManager<Traits>::evalCouplingResidual; @@ -191,7 +212,7 @@ public: if (!localAssemblerI.assembler().isStationaryProblem()) { - assert(isTransient_); + assert(isTransient_()); localResidual.evalStorage(residual, problem, element, fvGeometry, prevElemVolVars, curElemVolVars, scvI); } @@ -234,7 +255,7 @@ public: const SubControlVolumeFace<freeFlowMomentumIndex>& scvf, const bool considerPreviousTimeStep = false) const { - assert(!(considerPreviousTimeStep && !isTransient_)); + assert(!(considerPreviousTimeStep && !isTransient_())); bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex()); const auto& insideMomentumScv = fvGeometry.scv(scvf.insideScvIdx()); const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(insideMomentumScv.elementIndex()); @@ -261,7 +282,7 @@ public: const SubControlVolumeFace<freeFlowMomentumIndex>& scvf, const bool considerPreviousTimeStep = false) const { - assert(!(considerPreviousTimeStep && !isTransient_)); + assert(!(considerPreviousTimeStep && !isTransient_())); bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, fvGeometry.elementIndex()); const auto& insideMomentumScv = fvGeometry.scv(scvf.insideScvIdx()); const auto& insideMassScv = momentumCouplingContext_()[0].fvGeometry.scv(insideMomentumScv.elementIndex()); @@ -289,7 +310,7 @@ public: const SubControlVolume<freeFlowMomentumIndex>& scv, const bool considerPreviousTimeStep = false) const { - assert(!(considerPreviousTimeStep && !isTransient_)); + assert(!(considerPreviousTimeStep && !isTransient_())); bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex>(), element, scv.elementIndex()); const auto& massScv = (*scvs(momentumCouplingContext_()[0].fvGeometry).begin()); @@ -508,11 +529,11 @@ private: auto curElemVolVars = localView(gridVars_(freeFlowMassIndex).curGridVolVars()); curElemVolVars.bind(elementI, fvGeometry, this->curSol(freeFlowMassIndex)); - auto prevElemVolVars = isTransient_ ? localView(gridVars_(freeFlowMassIndex).prevGridVolVars()) + auto prevElemVolVars = isTransient_() ? localView(gridVars_(freeFlowMassIndex).prevGridVolVars()) : localView(gridVars_(freeFlowMassIndex).curGridVolVars()); - if (isTransient_) - prevElemVolVars.bindElement(elementI, fvGeometry, (*prevSol_)[freeFlowMassIndex]); + if (isTransient_()) + prevElemVolVars.bindElement(elementI, fvGeometry, prevSol_(freeFlowMassIndex)); momentumCouplingContext_().emplace_back(MomentumCouplingContext{std::move(fvGeometry), std::move(curElemVolVars), std::move(prevElemVolVars), eIdx}); } @@ -522,8 +543,8 @@ private: momentumCouplingContext_()[0].fvGeometry.bind(elementI); momentumCouplingContext_()[0].curElemVolVars.bind(elementI, momentumCouplingContext_()[0].fvGeometry, this->curSol(freeFlowMassIndex)); - if (isTransient_) - momentumCouplingContext_()[0].prevElemVolVars.bindElement(elementI, momentumCouplingContext_()[0].fvGeometry, (*prevSol_)[freeFlowMassIndex]); + if (isTransient_()) + momentumCouplingContext_()[0].prevElemVolVars.bindElement(elementI, momentumCouplingContext_()[0].fvGeometry, prevSol_(freeFlowMassIndex)); } } @@ -661,8 +682,14 @@ private: //! A tuple of std::shared_ptrs to the grid variables of the sub problems GridVariablesTuple gridVariables_; - const SolutionVector* prevSol_; - bool isTransient_; + bool isTransient_() const + { return std::get<0>(prevSolutions_) != nullptr; } + + template<std::size_t i> + const SubSolutionVector<i>& prevSol_(Dune::index_constant<i>) const + { return *std::get<i>(prevSolutions_); } + + PrevSolutionVectorStorage prevSolutions_; std::deque<std::vector<ElementSeed<freeFlowMomentumIndex>>> elementSets_; }; -- GitLab