13#ifndef DUMUX_MULTIDOMAIN_BOUNDARY_FREEFLOWPORENETWORK_FFMASSPORENETWORK_COUPLINGMANAGER_HH
14#define DUMUX_MULTIDOMAIN_BOUNDARY_FREEFLOWPORENETWORK_FFMASSPORENETWORK_COUPLINGMANAGER_HH
19#include <dune/common/float_cmp.hh>
20#include <dune/common/exceptions.hh>
32template<
class MDTraits>
36 using Scalar =
typename MDTraits::Scalar;
40 static constexpr auto freeFlowMassIndex =
typename MDTraits::template SubDomain<0>::Index();
41 static constexpr auto poreNetworkIndex =
typename MDTraits::template SubDomain<1>::Index();
47 using FreeFlowMassTypeTag =
typename MDTraits::template SubDomain<freeFlowMassIndex>::TypeTag;
48 using PoreNetworkTypeTag =
typename MDTraits::template SubDomain<poreNetworkIndex>::TypeTag;
50 using CouplingStencils = std::unordered_map<std::size_t, std::vector<std::size_t> >;
51 using CouplingStencil = CouplingStencils::mapped_type;
54 template<std::
size_t id>
55 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
63 template<std::
size_t id>
using FVElementGeometry =
typename GridGeometry<id>::LocalView;
65 template<std::
size_t id>
using Element =
typename GridView<id>::template Codim<0>::Entity;
67 template<std::
size_t id>
using SubControlVolumeFace =
typename FVElementGeometry<id>::SubControlVolumeFace;
68 template<std::
size_t id>
using SubControlVolume =
typename FVElementGeometry<id>::SubControlVolume;
70 using VelocityVector =
typename Element<freeFlowMassIndex>::Geometry::GlobalCoordinate;
72 struct FreeFlowMassCouplingContext
74 SubControlVolume<poreNetworkIndex> scv;
75 VolumeVariables<poreNetworkIndex> volVars;
76 mutable VelocityVector velocity;
79 struct PoreNetworkCouplingContext
81 SubControlVolume<freeFlowMassIndex> scv;
82 SubControlVolumeFace<freeFlowMassIndex> scvf;
83 VolumeVariables<freeFlowMassIndex> volVars;
84 mutable VelocityVector velocity;
87 using CouplingMapper = StaggeredFreeFlowPoreNetworkCouplingMapper;
97 void init(std::shared_ptr<Problem<freeFlowMassIndex>> freeFlowMassProblem,
98 std::shared_ptr<Problem<poreNetworkIndex>> pnmProblem,
99 std::shared_ptr<CouplingMapper> couplingMapper,
102 couplingMapper_ = couplingMapper;
103 this->
setSubProblems(std::make_tuple(freeFlowMassProblem, pnmProblem));
117 template<std::
size_t i,
class Assembler>
118 void bindCouplingContext(Dune::index_constant<i> domainI,
const Element<i>& element,
const Assembler& assembler)
const
120 bindCouplingContext_(domainI, element);
126 template<std::
size_t i, std::
size_t j,
class LocalAssemblerI>
128 const LocalAssemblerI& localAssemblerI,
129 Dune::index_constant<j> domainJ,
130 std::size_t dofIdxGlobalJ,
131 const PrimaryVariables<j>& priVarsJ,
134 this->
curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ];
141 auto& context = std::get<1-j>(couplingContext_);
142 for (
auto& c : context)
144 if (c.scv.dofIndex() == dofIdxGlobalJ)
147 const auto& element =
problem.gridGeometry().element(c.scv.elementIndex());
149 c.volVars.update(elemSol,
problem, element, c.scv);
160 const FVElementGeometry<freeFlowMassIndex>& fvGeometry,
161 const SubControlVolumeFace<freeFlowMassIndex> scvf)
const
163 auto& contexts = std::get<freeFlowMassIndex>(couplingContext_);
164 const auto eIdx = scvf.insideScvIdx();
166 if (contexts.empty() || couplingContextBoundForElement_[
freeFlowMassIndex] != eIdx)
177 const FVElementGeometry<poreNetworkIndex>& fvGeometry,
178 const SubControlVolume<poreNetworkIndex> scv)
const
180 auto& contexts = std::get<poreNetworkIndex>(couplingContext_);
181 const auto eIdx = fvGeometry.gridGeometry().elementMapper().index(fvGeometry.element());
183 if (contexts.empty() || couplingContextBoundForElement_[
poreNetworkIndex] != eIdx)
197 template<std::
size_t i, std::
size_t j>
199 const Element<i>& element,
200 Dune::index_constant<j> domainJ)
const
202 const auto eIdx = this->
problem(domainI).gridGeometry().elementMapper().index(element);
204 return couplingMapper_->freeFlowMassToPoreNetworkCouplingStencil(eIdx);
206 return couplingMapper_->poreNetworkToFreeFlowMassCouplingStencil(eIdx);
214 bool isCoupled(Dune::index_constant<freeFlowMassIndex> domainI,
215 const SubControlVolumeFace<freeFlowMassIndex>& scvf)
const
216 {
return couplingMapper_->isCoupledFreeFlowMassScvf(scvf.index()); }
223 bool isCoupled(Dune::index_constant<poreNetworkIndex> domainI,
224 const SubControlVolume<poreNetworkIndex>& scv)
const
225 {
return couplingMapper_->isCoupledPoreNetworkDof(scv.dofIndex()); }
231 template<std::
size_t i>
232 bool isCoupledElement_(Dune::index_constant<i> domainI, std::size_t eIdx)
const
235 return couplingMapper_->isCoupledFreeFlowElement(eIdx);
237 return couplingMapper_->isCoupledPoreNetworkElement(eIdx);
241 template<std::
size_t i>
242 VolumeVariables<i> volVars_(Dune::index_constant<i> domainI,
243 const Element<i>& element,
244 const SubControlVolume<i>& scv)
const
246 VolumeVariables<i> volVars;
248 element, this->
curSol(domainI), this->
problem(domainI).gridGeometry()
250 volVars.update(elemSol, this->
problem(domainI), element, scv);
257 template<std::
size_t i>
258 void bindCouplingContext_(Dune::index_constant<i> domainI,
const Element<i>& element)
const
260 const auto fvGeometry =
localView(this->
problem(domainI).gridGeometry()).bindElement(element);
261 bindCouplingContext_(domainI, fvGeometry);
267 void bindCouplingContext_(Dune::index_constant<poreNetworkIndex> domainI,
const FVElementGeometry<poreNetworkIndex>& fvGeometry)
const
269 auto& context = std::get<domainI>(couplingContext_);
270 const auto eIdx = fvGeometry.gridGeometry().elementMapper().index(fvGeometry.element());
273 if ((!context.empty() && couplingContextBoundForElement_[domainI] == eIdx) || !isCoupledElement_(domainI, eIdx))
277 couplingContextBoundForElement_[domainI] = eIdx;
280 const auto& freeFlowElements = couplingMapper_->pnmElementToFreeFlowElementsMap().at(eIdx);
283 for (
const auto ffElementIdx : freeFlowElements)
286 ffFVGeometry.bindElement(ffElement);
288 for (
const auto& scvf : scvfs(ffFVGeometry))
290 if (couplingMapper_->isCoupledFreeFlowMassScvf(scvf.index()))
292 const auto& scv = ffFVGeometry.scv(scvf.insideScvIdx());
293 const auto dofIdx = scv.dofIndex();
294 if (std::any_of(stencil.begin(), stencil.end(), [&](
const auto x){ return dofIdx == x; } ))
296 context.push_back({scv,
310 void bindCouplingContext_(Dune::index_constant<freeFlowMassIndex> domainI,
const FVElementGeometry<freeFlowMassIndex>& fvGeometry)
const
312 auto& context = std::get<domainI>(couplingContext_);
313 const auto eIdx = fvGeometry.gridGeometry().elementMapper().index(fvGeometry.element());
316 if ((!context.empty() && couplingContextBoundForElement_[domainI] == eIdx) || !isCoupledElement_(domainI, eIdx))
320 couplingContextBoundForElement_[domainI] = eIdx;
324 const auto poreNetworkElemIdx = couplingMapper_->freeFlowElementToPNMElementMap().at(eIdx);
326 poreNetworkFVGeometry.bindElement(poreNetworkElement);
328 auto poreNetworkScv = [&]
330 SubControlVolume<poreNetworkIndex> result;
331 std::size_t counter = 0;
332 for (
auto&& scv : scvs(poreNetworkFVGeometry))
334 if (couplingMapper_->isCoupledPoreNetworkDof(scv.dofIndex()))
342 DUNE_THROW(Dune::InvalidStateException,
"Only one pore per throat may be coupled");
347 auto volVars = volVars_(
poreNetworkIndex, poreNetworkElement, poreNetworkScv);
349 context.push_back({std::move(poreNetworkScv),
355 mutable std::tuple<std::vector<FreeFlowMassCouplingContext>, std::vector<PoreNetworkCouplingContext>> couplingContext_;
356 mutable std::array<std::size_t, 2> couplingContextBoundForElement_;
358 std::shared_ptr<CouplingMapper> couplingMapper_;
The interface of the coupling manager for multi domain problems.
Definition: multidomain/couplingmanager.hh:37
void attachSolution(const SolutionVectorStorage &curSol)
Attach a solution vector stored outside of this class.
Definition: multidomain/couplingmanager.hh:311
void setSubProblems(const std::tuple< std::shared_ptr< SubProblems >... > &problems)
set the pointers to the sub problems
Definition: multidomain/couplingmanager.hh:276
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Return a reference to the sub problem.
Definition: multidomain/couplingmanager.hh:298
SubSolutionVector< i > & curSol(Dune::index_constant< i > domainIdx)
the solution vector of the subproblem
Definition: multidomain/couplingmanager.hh:327
typename Traits::template TupleOfSharedPtr< SubSolutionVector > SolutionVectorStorage
the type in which the solution vector is stored in the manager
Definition: multidomain/couplingmanager.hh:60
Coupling manager for free-flow mass and pore-network models.
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:35
bool isCoupled(Dune::index_constant< poreNetworkIndex > domainI, const SubControlVolume< poreNetworkIndex > &scv) const
If the boundary entity is on a coupling boundary.
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:223
static constexpr auto poreNetworkIndex
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:41
typename ParentType::SolutionVectorStorage SolutionVectorStorage
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:43
void bindCouplingContext(Dune::index_constant< i > domainI, const Element< i > &element, const Assembler &assembler) const
Methods to be accessed by the assembly.
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:118
const auto & couplingContext(Dune::index_constant< poreNetworkIndex > domainI, const FVElementGeometry< poreNetworkIndex > &fvGeometry, const SubControlVolume< poreNetworkIndex > scv) const
Access the coupling context needed for the PNM domain.
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:176
const auto & couplingContext(Dune::index_constant< freeFlowMassIndex > domainI, const FVElementGeometry< freeFlowMassIndex > &fvGeometry, const SubControlVolumeFace< freeFlowMassIndex > scvf) const
Access the coupling context needed for the Stokes domain.
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:159
static constexpr auto freeFlowMassIndex
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:40
void init(std::shared_ptr< Problem< freeFlowMassIndex > > freeFlowMassProblem, std::shared_ptr< Problem< poreNetworkIndex > > pnmProblem, std::shared_ptr< CouplingMapper > couplingMapper, const SolutionVectorStorage &curSol)
Methods to be accessed by main.
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:97
const CouplingStencil & couplingStencil(Dune::index_constant< i > domainI, const Element< i > &element, Dune::index_constant< j > domainJ) const
The coupling stencils.
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:198
bool isCoupled(Dune::index_constant< freeFlowMassIndex > domainI, const SubControlVolumeFace< freeFlowMassIndex > &scvf) const
Returns whether a given scvf is coupled to the other domain.
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:214
void updateCouplingContext(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ, const PrimaryVariables< j > &priVarsJ, int pvIdxJ)
Update the coupling context.
Definition: multidomain/boundary/freeflowporenetwork/ffmassporenetwork/couplingmanager.hh:127
Defines all properties used in Dumux.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:26
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::cctpfa||GridGeometry::discMethod==DiscretizationMethods::ccmpfa, CCElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for cell-centered schemes.
Definition: cellcentered/elementsolution.hh:101
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
The interface of the coupling manager for multi domain problems.
The local element solution class for staggered methods.