13#ifndef DUMUX_MULTIDOMAIN_BOUNDARY_FFPM_FFMMOMENTUMPORENETWORK_COUPLINGMANAGER_HH
14#define DUMUX_MULTIDOMAIN_BOUNDARY_FFPM_FFMMOMENTUMPORENETWORK_COUPLINGMANAGER_HH
19#include <dune/common/float_cmp.hh>
20#include <dune/common/exceptions.hh>
32template<
class MDTraits>
36 using Scalar =
typename MDTraits::Scalar;
41 static constexpr auto poreNetworkIndex =
typename MDTraits::template SubDomain<1>::Index();
46 using FreeFlowMomentumTypeTag =
typename MDTraits::template SubDomain<freeFlowMomentumIndex>::TypeTag;
47 using PoreNetworkTypeTag =
typename MDTraits::template SubDomain<poreNetworkIndex>::TypeTag;
49 using CouplingStencils = std::unordered_map<std::size_t, std::vector<std::size_t> >;
50 using CouplingStencil = CouplingStencils::mapped_type;
53 template<std::
size_t id>
54 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
62 template<std::
size_t id>
using FVElementGeometry =
typename GridGeometry<id>::LocalView;
65 template<std::
size_t id>
using ElementFluxVariablesCache =
typename GridFluxVariablesCache<id>::LocalView;
66 template<std::
size_t id>
using Element =
typename GridView<id>::template Codim<0>::Entity;
68 template<std::
size_t id>
using SubControlVolumeFace =
typename FVElementGeometry<id>::SubControlVolumeFace;
69 template<std::
size_t id>
using SubControlVolume =
typename FVElementGeometry<id>::SubControlVolume;
71 using VelocityVector =
typename Element<freeFlowMomentumIndex>::Geometry::GlobalCoordinate;
73 struct FreeFlowMomentumCouplingContext
75 FVElementGeometry<poreNetworkIndex> fvGeometry;
76 ElementVolumeVariables<poreNetworkIndex> elemVolVars;
77 ElementFluxVariablesCache<poreNetworkIndex> elemFluxVarsCache;
78 std::size_t poreNetworkDofIdx;
81 struct PoreNetworkCouplingContext
83 SubControlVolumeFace<freeFlowMomentumIndex> freeFlowMomentumScvf;
85 std::size_t freeFlowMomentumDofIdx;
88 using CouplingMapper = StaggeredFreeFlowPoreNetworkCouplingMapper;
89 using GridVariablesTuple =
typename MDTraits::template TupleOfSharedPtr<GridVariables>;
99 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem,
100 std::shared_ptr<Problem<poreNetworkIndex>> porousMediumProblem,
101 GridVariablesTuple&& gridVariables,
102 std::shared_ptr<CouplingMapper> couplingMapper,
105 couplingMapper_ = couplingMapper;
106 gridVariables_ = gridVariables;
107 this->
setSubProblems(std::make_tuple(freeFlowMomentumProblem, porousMediumProblem));
122 template<std::
size_t i,
class Assembler>
123 void bindCouplingContext(Dune::index_constant<i> domainI,
const Element<i>& element,
const Assembler& assembler)
const
125 bindCouplingContext_(domainI, element);
131 template<std::
size_t i>
134 bindCouplingContext_(domainI, element);
140 template<std::
size_t i, std::
size_t j,
class LocalAssemblerI>
142 const LocalAssemblerI& localAssemblerI,
143 Dune::index_constant<j> domainJ,
144 std::size_t dofIdxGlobalJ,
145 const PrimaryVariables<j>& priVarsJ,
148 this->
curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ];
150 const auto eIdx = localAssemblerI.fvGeometry().gridGeometry().elementMapper().index(localAssemblerI.fvGeometry().element());
151 if (!isCoupledElement_(domainI, eIdx))
164 auto& context = std::get<poreNetworkIndex>(couplingContext_);
165 for (
auto& c : context)
167 if (c.freeFlowMomentumDofIdx == dofIdxGlobalJ)
169 assert(c.freeFlowMomentumScvf.isFrontal() && c.freeFlowMomentumScvf.boundary());
170 c.faceVelocity =
faceVelocity(c.freeFlowMomentumScvf, c.freeFlowMomentumDofIdx);
179 assert(couplingContextBoundForElement_[domainI] == localAssemblerI.fvGeometry().gridGeometry().elementMapper().index(localAssemblerI.fvGeometry().element()));
181 auto& context = std::get<freeFlowMomentumIndex>(couplingContext_)[0];
182 const auto& ggJ = context.fvGeometry.gridGeometry();
183 const auto& element = context.fvGeometry.element();
186 for (
const auto& scv : scvs(context.fvGeometry))
188 if (scv.dofIndex() == dofIdxGlobalJ)
190 if constexpr (ElementVolumeVariables<poreNetworkIndex>::GridVolumeVariables::cachingEnabled)
191 gridVars_(
poreNetworkIndex).curGridVolVars().volVars(scv).update(std::move(elemSol), this->
problem(domainJ), element, scv);
193 context.elemVolVars[scv].update(std::move(elemSol), this->
problem(domainJ), element, scv);
197 const auto& scvf = context.fvGeometry.scvf(0);
198 if constexpr (ElementFluxVariablesCache<poreNetworkIndex>::GridFluxVariablesCache::cachingEnabled)
200 const auto eIdx = ggJ.elementMapper().index(element);
201 gridVars_(
poreNetworkIndex).gridFluxVarsCache().cache(eIdx, scvf.index()).update(this->
problem(domainJ), element, context.fvGeometry, context.elemVolVars, scvf);
204 context.elemFluxVarsCache[scvf].update(this->
problem(domainJ), element, context.fvGeometry, context.elemVolVars, scvf);
213 const auto&
couplingContext(
const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
214 const SubControlVolumeFace<freeFlowMomentumIndex> scvf)
const
216 auto& contexts = std::get<freeFlowMomentumIndex>(couplingContext_);
218 if (contexts.empty() || couplingContextBoundForElement_[
freeFlowMomentumIndex] != fvGeometry.elementIndex())
229 const SubControlVolume<poreNetworkIndex> scv)
const
231 auto& contexts = std::get<poreNetworkIndex>(couplingContext_);
233 const auto eIdx = fvGeometry.gridGeometry().elementMapper().index(fvGeometry.element());
234 if (contexts.empty() || couplingContextBoundForElement_[
poreNetworkIndex] != eIdx)
248 const CouplingStencil&
couplingStencil(Dune::index_constant<poreNetworkIndex> domainI,
249 const Element<poreNetworkIndex>& element,
250 Dune::index_constant<freeFlowMomentumIndex> domainJ)
const
252 const auto eIdx = this->
problem(domainI).gridGeometry().elementMapper().index(element);
253 return couplingMapper_->poreNetworkToFreeFlowMomentumCouplingStencil(eIdx);
265 const CouplingStencil&
couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI,
266 const Element<freeFlowMomentumIndex>& elementI,
267 const SubControlVolume<freeFlowMomentumIndex>& scvI,
268 Dune::index_constant<poreNetworkIndex> domainJ)
const
270 return couplingMapper_->freeFlowMomentumToPoreNetworkCouplingStencil(scvI.dofIndex());
279 template<
class LocalAssemblerI, std::
size_t j>
281 const LocalAssemblerI& localAssemblerI,
282 const SubControlVolume<freeFlowMomentumIndex>& scvI,
283 Dune::index_constant<j> domainJ,
284 std::size_t dofIdxGlobalJ)
const
286 return localAssemblerI.evalLocalResidual();
294 bool isCoupledLateralScvf(Dune::index_constant<freeFlowMomentumIndex> domainI,
const SubControlVolumeFace<freeFlowMomentumIndex>& scvf)
const
295 {
return couplingMapper_->isCoupledFreeFlowMomentumLateralScvf(scvf.index()); }
300 bool isCoupled(Dune::index_constant<freeFlowMomentumIndex> domainI,
const SubControlVolumeFace<freeFlowMomentumIndex>& scvf)
const
302 return couplingMapper_->isCoupledFreeFlowMomentumScvf(scvf.index()) || couplingMapper_->isCoupledFreeFlowMomentumLateralScvf(scvf.index());
310 bool isCoupled(Dune::index_constant<poreNetworkIndex> domainI,
311 const SubControlVolume<poreNetworkIndex>& scv)
const
312 {
return couplingMapper_->isCoupledPoreNetworkDof(scv.dofIndex()); }
317 auto faceVelocity(
const SubControlVolumeFace<freeFlowMomentumIndex>& scvf,
318 std::size_t freeFlowMomentumDofIdx)
const
321 auto velocity = scvf.unitOuterNormal();
323 std::for_each(velocity.begin(), velocity.end(), [](
auto& v){ v = abs(v); });
336 template<std::
size_t i>
337 bool isCoupledElement_(Dune::index_constant<i> domainI, std::size_t eIdx)
const
340 return couplingMapper_->isCoupledFreeFlowElement(eIdx);
342 return couplingMapper_->isCoupledPoreNetworkElement(eIdx);
348 template<std::
size_t i>
349 void bindCouplingContext_(Dune::index_constant<i> domainI,
const Element<i>& element)
const
351 const auto fvGeometry =
localView(this->
problem(domainI).gridGeometry()).bindElement(element);
352 bindCouplingContext_(domainI, fvGeometry);
358 void bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex> domainI,
const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry)
const
360 auto& context = std::get<domainI>(couplingContext_);
361 const auto eIdx = fvGeometry.elementIndex();
364 if ((!context.empty() && couplingContextBoundForElement_[domainI] == eIdx))
367 bool bindElement =
false;
368 std::size_t actuallyCoupledFreeFlowElementIndex;
372 if (couplingMapper_->isCoupledFreeFlowElement(eIdx))
375 actuallyCoupledFreeFlowElementIndex = eIdx;
381 for (
const auto& intersection : intersections(fvGeometry.gridGeometry().gridView(), fvGeometry.element()))
383 const auto dofIdx = fvGeometry.gridGeometry().intersectionMapper().globalIntersectionIndex(fvGeometry.element(), intersection.indexInInside());
384 if (couplingMapper_->isCoupledFreeFlowMomentumDof(dofIdx))
387 actuallyCoupledFreeFlowElementIndex = fvGeometry.gridGeometry().elementMapper().index(intersection.outside());
397 couplingContextBoundForElement_[domainI] = eIdx;
403 const auto poreNetworkElemIdx = couplingMapper_->freeFlowElementToPNMElementMap().at(actuallyCoupledFreeFlowElementIndex);
406 poreNetworkFVGeometry.bindElement(poreNetworkElement);
408 poreNetworkElemFluxVarsCache.bind(poreNetworkElement, poreNetworkFVGeometry, poreNetworkElemVolVars);
410 const std::size_t poreNetworkDofIdx = [&]
413 std::size_t counter = 0;
414 for (
const auto& scv : scvs(poreNetworkFVGeometry))
416 if (couplingMapper_->isCoupledPoreNetworkDof(scv.dofIndex()))
418 idx = scv.dofIndex();
424 DUNE_THROW(Dune::InvalidStateException,
"Exactly one pore per throat needs to be coupled with the FF domain");
429 context.push_back({std::move(poreNetworkFVGeometry),
430 std::move(poreNetworkElemVolVars),
431 std::move(poreNetworkElemFluxVarsCache),
439 void bindCouplingContext_(Dune::index_constant<poreNetworkIndex> domainI,
const FVElementGeometry<poreNetworkIndex>& fvGeometry)
const
441 auto& context = std::get<domainI>(couplingContext_);
442 const auto eIdx = fvGeometry.gridGeometry().elementMapper().index(fvGeometry.element());
445 if ((!context.empty() && couplingContextBoundForElement_[domainI] == eIdx) || !isCoupledElement_(domainI, eIdx))
449 couplingContextBoundForElement_[domainI] = eIdx;
452 const auto& freeFlowElements = couplingMapper_->pnmElementToFreeFlowElementsMap().at(eIdx);
455 for (
const auto ffElementIdx : freeFlowElements)
458 ffFVGeometry.bindElement(ffElement);
459 for (
const auto& scv : scvs(ffFVGeometry))
461 if (couplingMapper_->isCoupledFreeFlowMomentumDof(scv.dofIndex()))
463 if (std::any_of(stencil.begin(), stencil.end(), [&](
const auto x){ return scv.dofIndex() == x; } ))
465 const auto& coupledScvf = ffFVGeometry.frontalScvfOnBoundary(scv);
466 context.push_back({coupledScvf,
480 template<std::
size_t i>
481 const GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx)
const
483 if (std::get<i>(gridVariables_))
484 return *std::get<i>(gridVariables_);
486 DUNE_THROW(Dune::InvalidStateException,
"The gridVariables pointer was not set. Use setGridVariables() before calling this function");
493 template<std::
size_t i>
494 GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx)
496 if (std::get<i>(gridVariables_))
497 return *std::get<i>(gridVariables_);
499 DUNE_THROW(Dune::InvalidStateException,
"The gridVariables pointer was not set. Use setGridVariables() before calling this function");
503 GridVariablesTuple gridVariables_;
505 mutable std::tuple<std::vector<FreeFlowMomentumCouplingContext>, std::vector<PoreNetworkCouplingContext>> couplingContext_;
506 mutable std::array<std::size_t, 2> couplingContextBoundForElement_;
508 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 momentum and pore-network models.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:35
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/ffmomentumporenetwork/couplingmanager.hh:123
typename ParentType::SolutionVectorStorage SolutionVectorStorage
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:43
void bindCouplingContext(Dune::index_constant< i > domainI, const Element< i > &element) const
prepares all data and variables that are necessary to evaluate the residual (called from the local as...
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:132
bool isCoupledLateralScvf(Dune::index_constant< freeFlowMomentumIndex > domainI, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf) const
Returns whether a given scvf is coupled to the other domain.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:294
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/ffmomentumporenetwork/couplingmanager.hh:310
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/ffmomentumporenetwork/couplingmanager.hh:141
static constexpr auto poreNetworkIndex
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:41
const auto & couplingContext(const FVElementGeometry< poreNetworkIndex > &fvGeometry, const SubControlVolume< poreNetworkIndex > scv) const
Access the coupling context needed for the PNM domain.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:228
void init(std::shared_ptr< Problem< freeFlowMomentumIndex > > freeFlowMomentumProblem, std::shared_ptr< Problem< poreNetworkIndex > > porousMediumProblem, GridVariablesTuple &&gridVariables, std::shared_ptr< CouplingMapper > couplingMapper, const SolutionVectorStorage &curSol)
Methods to be accessed by main.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:99
static constexpr auto freeFlowMomentumIndex
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:40
const CouplingStencil & couplingStencil(Dune::index_constant< freeFlowMomentumIndex > domainI, const Element< freeFlowMomentumIndex > &elementI, const SubControlVolume< freeFlowMomentumIndex > &scvI, Dune::index_constant< poreNetworkIndex > domainJ) const
returns an iterable container of all indices of degrees of freedom of domain j that couple with / inf...
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:265
const auto & couplingContext(const FVElementGeometry< freeFlowMomentumIndex > &fvGeometry, const SubControlVolumeFace< freeFlowMomentumIndex > scvf) const
Access the coupling context needed for the Stokes domain.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:213
auto faceVelocity(const SubControlVolumeFace< freeFlowMomentumIndex > &scvf, std::size_t freeFlowMomentumDofIdx) const
Returns the velocity at a given sub control volume face.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:317
const CouplingStencil & couplingStencil(Dune::index_constant< poreNetworkIndex > domainI, const Element< poreNetworkIndex > &element, Dune::index_constant< freeFlowMomentumIndex > domainJ) const
The coupling stencils.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:248
decltype(auto) evalCouplingResidual(Dune::index_constant< freeFlowMomentumIndex > domainI, const LocalAssemblerI &localAssemblerI, const SubControlVolume< freeFlowMomentumIndex > &scvI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ) const
evaluate the coupling residual special interface for fcstaggered methods
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:280
bool isCoupled(Dune::index_constant< freeFlowMomentumIndex > domainI, const SubControlVolumeFace< freeFlowMomentumIndex > &scvf) const
Returns whether a given scvf is coupled to the other domain.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:300
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
decltype(auto) evalCouplingResidual(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, Dune::index_constant< j > domainJ, std::size_t dofIdxGlobalJ) const
evaluates the element residual of a coupled element of domain i which depends on the variables at the...
Definition: multidomain/couplingmanager.hh:238
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.