25#ifndef DUMUX_MULTIDOMAIN_BOUNDARY_FFPM_FFMMOMENTUMPORENETWORK_COUPLINGMANAGER_HH
26#define DUMUX_MULTIDOMAIN_BOUNDARY_FFPM_FFMMOMENTUMPORENETWORK_COUPLINGMANAGER_HH
31#include <dune/common/float_cmp.hh>
32#include <dune/common/exceptions.hh>
44template<
class MDTraits>
48 using Scalar =
typename MDTraits::Scalar;
53 static constexpr auto poreNetworkIndex =
typename MDTraits::template SubDomain<1>::Index();
58 using FreeFlowMomentumTypeTag =
typename MDTraits::template SubDomain<freeFlowMomentumIndex>::TypeTag;
59 using PoreNetworkTypeTag =
typename MDTraits::template SubDomain<poreNetworkIndex>::TypeTag;
61 using CouplingStencils = std::unordered_map<std::size_t, std::vector<std::size_t> >;
62 using CouplingStencil = CouplingStencils::mapped_type;
65 template<std::
size_t id>
66 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
74 template<std::
size_t id>
using FVElementGeometry =
typename GridGeometry<id>::LocalView;
77 template<std::
size_t id>
using ElementFluxVariablesCache =
typename GridFluxVariablesCache<id>::LocalView;
78 template<std::
size_t id>
using Element =
typename GridView<id>::template Codim<0>::Entity;
80 template<std::
size_t id>
using SubControlVolumeFace =
typename FVElementGeometry<id>::SubControlVolumeFace;
81 template<std::
size_t id>
using SubControlVolume =
typename FVElementGeometry<id>::SubControlVolume;
83 using VelocityVector =
typename Element<freeFlowMomentumIndex>::Geometry::GlobalCoordinate;
85 struct FreeFlowMomentumCouplingContext
87 FVElementGeometry<poreNetworkIndex> fvGeometry;
88 ElementVolumeVariables<poreNetworkIndex> elemVolVars;
89 ElementFluxVariablesCache<poreNetworkIndex> elemFluxVarsCache;
90 std::size_t poreNetworkDofIdx;
93 struct PoreNetworkCouplingContext
95 SubControlVolumeFace<freeFlowMomentumIndex> freeFlowMomentumScvf;
97 std::size_t freeFlowMomentumDofIdx;
100 using CouplingMapper = StaggeredFreeFlowPoreNetworkCouplingMapper;
101 using GridVariablesTuple =
typename MDTraits::template TupleOfSharedPtr<GridVariables>;
111 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem,
112 std::shared_ptr<Problem<poreNetworkIndex>> porousMediumProblem,
113 GridVariablesTuple&& gridVariables,
114 std::shared_ptr<CouplingMapper> couplingMapper,
117 couplingMapper_ = couplingMapper;
118 gridVariables_ = gridVariables;
119 this->
setSubProblems(std::make_tuple(freeFlowMomentumProblem, porousMediumProblem));
134 template<std::
size_t i,
class Assembler>
135 void bindCouplingContext(Dune::index_constant<i> domainI,
const Element<i>& element,
const Assembler& assembler)
const
137 bindCouplingContext_(domainI, element);
143 template<std::
size_t i>
146 bindCouplingContext_(domainI, element);
152 template<std::
size_t i, std::
size_t j,
class LocalAssemblerI>
154 const LocalAssemblerI& localAssemblerI,
155 Dune::index_constant<j> domainJ,
156 std::size_t dofIdxGlobalJ,
157 const PrimaryVariables<j>& priVarsJ,
160 this->
curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ];
162 const auto eIdx = localAssemblerI.fvGeometry().gridGeometry().elementMapper().index(localAssemblerI.fvGeometry().element());
163 if (!isCoupledElement_(domainI, eIdx))
176 auto& context = std::get<poreNetworkIndex>(couplingContext_);
177 for (
auto& c : context)
179 if (c.freeFlowMomentumDofIdx == dofIdxGlobalJ)
181 assert(c.freeFlowMomentumScvf.isFrontal() && c.freeFlowMomentumScvf.boundary());
182 c.faceVelocity =
faceVelocity(c.freeFlowMomentumScvf, c.freeFlowMomentumDofIdx);
191 assert(couplingContextBoundForElement_[domainI] == localAssemblerI.fvGeometry().gridGeometry().elementMapper().index(localAssemblerI.fvGeometry().element()));
193 auto& context = std::get<freeFlowMomentumIndex>(couplingContext_)[0];
194 const auto& ggJ = context.fvGeometry.gridGeometry();
195 const auto& element = context.fvGeometry.element();
198 for (
const auto& scv : scvs(context.fvGeometry))
200 if (scv.dofIndex() == dofIdxGlobalJ)
202 if constexpr (ElementVolumeVariables<poreNetworkIndex>::GridVolumeVariables::cachingEnabled)
203 gridVars_(
poreNetworkIndex).curGridVolVars().volVars(scv).update(std::move(elemSol), this->
problem(domainJ), element, scv);
205 context.elemVolVars[scv].update(std::move(elemSol), this->
problem(domainJ), element, scv);
209 const auto& scvf = context.fvGeometry.scvf(0);
210 if constexpr (ElementFluxVariablesCache<poreNetworkIndex>::GridFluxVariablesCache::cachingEnabled)
212 const auto eIdx = ggJ.elementMapper().index(element);
213 gridVars_(
poreNetworkIndex).gridFluxVarsCache().cache(eIdx, scvf.index()).update(this->
problem(domainJ), element, context.fvGeometry, context.elemVolVars, scvf);
216 context.elemFluxVarsCache[scvf].update(this->
problem(domainJ), element, context.fvGeometry, context.elemVolVars, scvf);
225 const auto&
couplingContext(
const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry,
226 const SubControlVolumeFace<freeFlowMomentumIndex> scvf)
const
228 auto& contexts = std::get<freeFlowMomentumIndex>(couplingContext_);
230 if (contexts.empty() || couplingContextBoundForElement_[
freeFlowMomentumIndex] != fvGeometry.elementIndex())
241 const SubControlVolume<poreNetworkIndex> scv)
const
243 auto& contexts = std::get<poreNetworkIndex>(couplingContext_);
245 const auto eIdx = fvGeometry.gridGeometry().elementMapper().index(fvGeometry.element());
246 if (contexts.empty() || couplingContextBoundForElement_[
poreNetworkIndex] != eIdx)
260 const CouplingStencil&
couplingStencil(Dune::index_constant<poreNetworkIndex> domainI,
261 const Element<poreNetworkIndex>& element,
262 Dune::index_constant<freeFlowMomentumIndex> domainJ)
const
264 const auto eIdx = this->
problem(domainI).gridGeometry().elementMapper().index(element);
265 return couplingMapper_->poreNetworkToFreeFlowMomentumCouplingStencil(eIdx);
277 const CouplingStencil&
couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI,
278 const Element<freeFlowMomentumIndex>& elementI,
279 const SubControlVolume<freeFlowMomentumIndex>& scvI,
280 Dune::index_constant<poreNetworkIndex> domainJ)
const
282 return couplingMapper_->freeFlowMomentumToPoreNetworkCouplingStencil(scvI.dofIndex());
291 template<
class LocalAssemblerI, std::
size_t j>
293 const LocalAssemblerI& localAssemblerI,
294 const SubControlVolume<freeFlowMomentumIndex>& scvI,
295 Dune::index_constant<j> domainJ,
296 std::size_t dofIdxGlobalJ)
const
298 return localAssemblerI.evalLocalResidual();
306 bool isCoupledLateralScvf(Dune::index_constant<freeFlowMomentumIndex> domainI,
const SubControlVolumeFace<freeFlowMomentumIndex>& scvf)
const
307 {
return couplingMapper_->isCoupledFreeFlowMomentumLateralScvf(scvf.index()); }
312 bool isCoupled(Dune::index_constant<freeFlowMomentumIndex> domainI,
const SubControlVolumeFace<freeFlowMomentumIndex>& scvf)
const
314 return couplingMapper_->isCoupledFreeFlowMomentumScvf(scvf.index()) || couplingMapper_->isCoupledFreeFlowMomentumLateralScvf(scvf.index());
322 bool isCoupled(Dune::index_constant<poreNetworkIndex> domainI,
323 const SubControlVolume<poreNetworkIndex>& scv)
const
324 {
return couplingMapper_->isCoupledPoreNetworkDof(scv.dofIndex()); }
329 auto faceVelocity(
const SubControlVolumeFace<freeFlowMomentumIndex>& scvf,
330 std::size_t freeFlowMomentumDofIdx)
const
333 auto velocity = scvf.unitOuterNormal();
335 std::for_each(velocity.begin(), velocity.end(), [](
auto& v){ v = abs(v); });
348 template<std::
size_t i>
349 bool isCoupledElement_(Dune::index_constant<i> domainI, std::size_t eIdx)
const
352 return couplingMapper_->isCoupledFreeFlowElement(eIdx);
354 return couplingMapper_->isCoupledPoreNetworkElement(eIdx);
360 template<std::
size_t i>
361 void bindCouplingContext_(Dune::index_constant<i> domainI,
const Element<i>& element)
const
363 const auto fvGeometry =
localView(this->
problem(domainI).gridGeometry()).bindElement(element);
364 bindCouplingContext_(domainI, fvGeometry);
370 void bindCouplingContext_(Dune::index_constant<freeFlowMomentumIndex> domainI,
const FVElementGeometry<freeFlowMomentumIndex>& fvGeometry)
const
372 auto& context = std::get<domainI>(couplingContext_);
373 const auto eIdx = fvGeometry.elementIndex();
376 if ((!context.empty() && couplingContextBoundForElement_[domainI] == eIdx))
379 bool bindElement =
false;
380 std::size_t actuallyCoupledFreeFlowElementIndex;
384 if (couplingMapper_->isCoupledFreeFlowElement(eIdx))
387 actuallyCoupledFreeFlowElementIndex = eIdx;
393 for (
const auto& intersection : intersections(fvGeometry.gridGeometry().gridView(), fvGeometry.element()))
395 const auto dofIdx = fvGeometry.gridGeometry().intersectionMapper().globalIntersectionIndex(fvGeometry.element(), intersection.indexInInside());
396 if (couplingMapper_->isCoupledFreeFlowMomentumDof(dofIdx))
399 actuallyCoupledFreeFlowElementIndex = fvGeometry.gridGeometry().elementMapper().index(intersection.outside());
409 couplingContextBoundForElement_[domainI] = eIdx;
415 const auto poreNetworkElemIdx = couplingMapper_->freeFlowElementToPNMElementMap().at(actuallyCoupledFreeFlowElementIndex);
418 poreNetworkFVGeometry.bindElement(poreNetworkElement);
420 poreNetworkElemFluxVarsCache.bind(poreNetworkElement, poreNetworkFVGeometry, poreNetworkElemVolVars);
422 const std::size_t poreNetworkDofIdx = [&]
425 std::size_t counter = 0;
426 for (
const auto& scv : scvs(poreNetworkFVGeometry))
428 if (couplingMapper_->isCoupledPoreNetworkDof(scv.dofIndex()))
430 idx = scv.dofIndex();
436 DUNE_THROW(Dune::InvalidStateException,
"Exactly one pore per throat needs to be coupled with the FF domain");
441 context.push_back({std::move(poreNetworkFVGeometry),
442 std::move(poreNetworkElemVolVars),
443 std::move(poreNetworkElemFluxVarsCache),
451 void bindCouplingContext_(Dune::index_constant<poreNetworkIndex> domainI,
const FVElementGeometry<poreNetworkIndex>& fvGeometry)
const
453 auto& context = std::get<domainI>(couplingContext_);
454 const auto eIdx = fvGeometry.gridGeometry().elementMapper().index(fvGeometry.element());
457 if ((!context.empty() && couplingContextBoundForElement_[domainI] == eIdx) || !isCoupledElement_(domainI, eIdx))
461 couplingContextBoundForElement_[domainI] = eIdx;
464 const auto& freeFlowElements = couplingMapper_->pnmElementToFreeFlowElementsMap().at(eIdx);
467 for (
const auto ffElementIdx : freeFlowElements)
470 ffFVGeometry.bindElement(ffElement);
471 for (
const auto& scv : scvs(ffFVGeometry))
473 if (couplingMapper_->isCoupledFreeFlowMomentumDof(scv.dofIndex()))
475 if (std::any_of(stencil.begin(), stencil.end(), [&](
const auto x){ return scv.dofIndex() == x; } ))
477 const auto& coupledScvf = ffFVGeometry.frontalScvfOnBoundary(scv);
478 context.push_back({coupledScvf,
492 template<std::
size_t i>
493 const GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx)
const
495 if (std::get<i>(gridVariables_))
496 return *std::get<i>(gridVariables_);
498 DUNE_THROW(Dune::InvalidStateException,
"The gridVariables pointer was not set. Use setGridVariables() before calling this function");
505 template<std::
size_t i>
506 GridVariables<i>& gridVars_(Dune::index_constant<i> domainIdx)
508 if (std::get<i>(gridVariables_))
509 return *std::get<i>(gridVariables_);
511 DUNE_THROW(Dune::InvalidStateException,
"The gridVariables pointer was not set. Use setGridVariables() before calling this function");
515 GridVariablesTuple gridVariables_;
517 mutable std::tuple<std::vector<FreeFlowMomentumCouplingContext>, std::vector<PoreNetworkCouplingContext>> couplingContext_;
518 mutable std::array<std::size_t, 2> couplingContextBoundForElement_;
520 std::shared_ptr<CouplingMapper> couplingMapper_;
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
auto elementSolution(const Element &element, const SolutionVector &sol, const GridGeometry &gg) -> std::enable_if_t< GridGeometry::discMethod==DiscretizationMethods::box, BoxElementSolution< typename GridGeometry::LocalView, std::decay_t< decltype(std::declval< SolutionVector >()[0])> > >
Make an element solution for box schemes.
Definition: box/elementsolution.hh:118
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:261
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:180
A vector of primary variables.
Definition: common/properties.hh:49
Property to specify the type of a problem which has to be solved.
Definition: common/properties.hh:55
Definition: common/properties.hh:100
The type for a global container for the volume variables.
Definition: common/properties.hh:107
The global vector of flux variable containers.
Definition: common/properties.hh:117
The grid variables object managing variable data on the grid (volvars/fluxvars cache)
Definition: common/properties.hh:121
Coupling manager for free-flow momentum and pore-network models.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:47
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:135
typename ParentType::SolutionVectorStorage SolutionVectorStorage
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:55
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:144
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:306
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:322
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:153
static constexpr auto poreNetworkIndex
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:53
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:240
static constexpr auto freeFlowMomentumIndex
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:52
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:277
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:225
void init(std::shared_ptr< Problem< freeFlowMomentumIndex > > freeFlowMomentumProblem, std::shared_ptr< Problem< poreNetworkIndex > > porousMediumProblem, GridVariablesTuple &&gridVariables, std::shared_ptr< CouplingMapper > couplingMapper, SolutionVectorStorage &curSol)
Methods to be accessed by main.
Definition: multidomain/boundary/freeflowporenetwork/ffmomentumporenetwork/couplingmanager.hh:111
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:329
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:260
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:292
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:312
The interface of the coupling manager for multi domain problems.
Definition: multidomain/couplingmanager.hh:60
void attachSolution(SolutionVectorStorage &curSol)
Attach a solution vector stored outside of this class.
Definition: multidomain/couplingmanager.hh:334
void setSubProblems(const std::tuple< std::shared_ptr< SubProblems >... > &problems)
set the pointers to the sub problems
Definition: multidomain/couplingmanager.hh:299
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Return a reference to the sub problem.
Definition: multidomain/couplingmanager.hh:321
SubSolutionVector< i > & curSol(Dune::index_constant< i > domainIdx)
the solution vector of the subproblem
Definition: multidomain/couplingmanager.hh:350
typename Traits::template TupleOfSharedPtr< SubSolutionVector > SolutionVectorStorage
the type in which the solution vector is stored in the manager
Definition: multidomain/couplingmanager.hh:83
Declares all properties used in Dumux.
The local element solution class for staggered methods.
The interface of the coupling manager for multi domain problems.