25#ifndef DUMUX_MULTIDOMAIN_BOUNDARY_FFPM_FFMMOMENTUMPM_COUPLINGMANAGER_HH
26#define DUMUX_MULTIDOMAIN_BOUNDARY_FFPM_FFMMOMENTUMPM_COUPLINGMANAGER_HH
31#include <dune/common/float_cmp.hh>
32#include <dune/common/exceptions.hh>
45template<
class MDTraits>
49 using Scalar =
typename MDTraits::Scalar;
54 static constexpr auto porousMediumIndex =
typename MDTraits::template SubDomain<1>::Index();
59 using FreeFlowMomentumTypeTag =
typename MDTraits::template SubDomain<freeFlowMomentumIndex>::TypeTag;
60 using PorousMediumTypeTag =
typename MDTraits::template SubDomain<porousMediumIndex>::TypeTag;
62 using CouplingStencils = std::unordered_map<std::size_t, std::vector<std::size_t> >;
63 using CouplingStencil = CouplingStencils::mapped_type;
66 template<std::
size_t id>
67 using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
75 template<std::
size_t id>
using FVElementGeometry =
typename GridGeometry<id>::LocalView;
77 template<std::
size_t id>
using Element =
typename GridView<id>::template Codim<0>::Entity;
79 template<std::
size_t id>
using SubControlVolumeFace =
typename FVElementGeometry<id>::SubControlVolumeFace;
80 template<std::
size_t id>
using SubControlVolume =
typename FVElementGeometry<id>::SubControlVolume;
82 using VelocityVector =
typename Element<freeFlowMomentumIndex>::Geometry::GlobalCoordinate;
84 struct FreeFlowMomentumCouplingContext
86 Element<porousMediumIndex> element;
87 VolumeVariables<porousMediumIndex> volVars;
88 FVElementGeometry<porousMediumIndex> fvGeometry;
89 std::size_t freeFlowMomentumScvfIdx;
90 std::size_t porousMediumScvfIdx;
91 std::size_t porousMediumDofIdx;
92 VelocityVector gravity;
95 struct PorousMediumCouplingContext
97 Element<freeFlowMomentumIndex> element;
98 FVElementGeometry<freeFlowMomentumIndex> fvGeometry;
99 std::size_t porousMediumScvfIdx;
100 std::size_t freeFlowMomentumScvfIdx;
101 std::size_t freeFlowMomentumDofIdx;
102 VelocityVector faceVelocity;
105 using CouplingMapper = FreeFlowMomentumPorousMediumCouplingMapper<MDTraits, FreeFlowMomentumPorousMediumCouplingManager<MDTraits>>;
115 void init(std::shared_ptr<Problem<freeFlowMomentumIndex>> freeFlowMomentumProblem,
116 std::shared_ptr<Problem<porousMediumIndex>> porousMediumProblem,
119 this->
setSubProblems(std::make_tuple(freeFlowMomentumProblem, porousMediumProblem));
122 couplingMapper_.update(*
this);
136 template<std::
size_t i,
class Assembler>
137 void bindCouplingContext(Dune::index_constant<i> domainI,
const Element<i>& element,
const Assembler& assembler)
const
139 bindCouplingContext_(domainI, element);
145 template<std::
size_t i, std::
size_t j,
class LocalAssemblerI>
147 const LocalAssemblerI& localAssemblerI,
148 Dune::index_constant<j> domainJ,
149 std::size_t dofIdxGlobalJ,
150 const PrimaryVariables<j>& priVarsJ,
153 this->
curSol(domainJ)[dofIdxGlobalJ][pvIdxJ] = priVarsJ[pvIdxJ];
165 auto& context = std::get<porousMediumIndex>(couplingContext_);
166 for (
auto& c : context)
168 if (c.freeFlowMomentumDofIdx == dofIdxGlobalJ)
170 const auto& scvf = localAssemblerI.fvGeometry().scvf(c.porousMediumScvfIdx);
171 c.faceVelocity =
faceVelocity(localAssemblerI.element(), scvf);
180 auto& context = std::get<freeFlowMomentumIndex>(couplingContext_);
181 for (
auto& c : context)
183 if (c.porousMediumDofIdx == dofIdxGlobalJ)
185 const auto& ggJ = c.fvGeometry.gridGeometry();
186 const auto& scv = *scvs(c.fvGeometry).begin();
187 const auto elemSol =
elementSolution(c.element, this->curSol(domainJ), ggJ);
188 c.volVars.update(elemSol, this->
problem(domainJ), c.element, scv);
199 template<std::
size_t i>
201 const FVElementGeometry<i>& fvGeometry,
202 const SubControlVolumeFace<i> scvf)
const
204 auto& contexts = std::get<i>(couplingContext_);
206 if (contexts.empty() || couplingContextBoundForElement_[i] != scvf.insideScvIdx())
207 bindCouplingContext_(domainI, fvGeometry);
209 for (
const auto& context : contexts)
211 const auto expectedScvfIdx = domainI ==
freeFlowMomentumIndex ? context.freeFlowMomentumScvfIdx : context.porousMediumScvfIdx;
212 if (scvf.index() == expectedScvfIdx)
216 DUNE_THROW(Dune::InvalidStateException,
"No coupling context found at scvf " << scvf.center());
227 const CouplingStencil&
couplingStencil(Dune::index_constant<porousMediumIndex> domainI,
228 const Element<porousMediumIndex>& element,
229 Dune::index_constant<freeFlowMomentumIndex> domainJ)
const
231 const auto eIdx = this->
problem(domainI).gridGeometry().elementMapper().index(element);
232 return couplingMapper_.couplingStencil(domainI, eIdx, domainJ);
244 const CouplingStencil&
couplingStencil(Dune::index_constant<freeFlowMomentumIndex> domainI,
245 const Element<freeFlowMomentumIndex>& elementI,
246 const SubControlVolume<freeFlowMomentumIndex>& scvI,
247 Dune::index_constant<porousMediumIndex> domainJ)
const
249 return couplingMapper_.couplingStencil(domainI, elementI, scvI, domainJ);
258 template<
class LocalAssemblerI, std::
size_t j>
260 const LocalAssemblerI& localAssemblerI,
261 const SubControlVolume<freeFlowMomentumIndex>& scvI,
262 Dune::index_constant<j> domainJ,
263 std::size_t dofIdxGlobalJ)
const
265 return localAssemblerI.evalLocalResidual();
273 bool isCoupledLateralScvf(Dune::index_constant<freeFlowMomentumIndex> domainI,
const SubControlVolumeFace<freeFlowMomentumIndex>& scvf)
const
274 {
return couplingMapper_.isCoupledLateralScvf(domainI, scvf); }
279 template<std::
size_t i>
280 bool isCoupled(Dune::index_constant<i> domainI,
const SubControlVolumeFace<i>& scvf)
const
283 return couplingMapper_.isCoupled(domainI, scvf) || couplingMapper_.isCoupledLateralScvf(domainI, scvf);
285 return couplingMapper_.isCoupled(domainI, scvf);
293 bool isCoupled(Dune::index_constant<freeFlowMomentumIndex> domainI,
294 const SubControlVolume<freeFlowMomentumIndex>& scv)
const
295 {
return couplingMapper_.isCoupled(domainI, scv); }
301 const SubControlVolumeFace<porousMediumIndex>& scvf)
const
304 auto velocity = scvf.unitOuterNormal();
306 std::for_each(velocity.begin(), velocity.end(), [](
auto& v){ v = abs(v); });
310 couplingMapper_.outsideDofIndex(Dune::index_constant<porousMediumIndex>(), scvf)
318 template<std::
size_t i>
319 VolumeVariables<i> volVars_(Dune::index_constant<i> domainI,
320 const Element<i>& element,
321 const SubControlVolume<i>& scv)
const
323 VolumeVariables<i> volVars;
325 element, this->
curSol(domainI), this->
problem(domainI).gridGeometry()
327 volVars.update(elemSol, this->
problem(domainI), element, scv);
334 template<std::
size_t i>
335 bool isCoupledElement_(Dune::index_constant<i> domainI, std::size_t eIdx)
const
341 template<std::
size_t i>
342 void bindCouplingContext_(Dune::index_constant<i> domainI,
const Element<i>& element)
const
344 const auto fvGeometry =
localView(this->
problem(domainI).gridGeometry()).bindElement(element);
345 bindCouplingContext_(domainI, fvGeometry);
351 template<std::
size_t i>
352 void bindCouplingContext_(Dune::index_constant<i> domainI,
const FVElementGeometry<i>& fvGeometry)
const
354 auto& context = std::get<domainI>(couplingContext_);
357 const auto eIdx = this->
problem(domainI).gridGeometry().elementMapper().index(fvGeometry.element());
360 if (!isCoupledElement_(domainI, eIdx))
363 couplingContextBoundForElement_[domainI] = eIdx;
365 for (
const auto& scvf : scvfs(fvGeometry))
367 if (couplingMapper_.isCoupled(domainI, scvf))
371 const auto otherElementIdx = couplingMapper_.outsideElementIndex(domainI, scvf);
372 constexpr auto domainJ = Dune::index_constant<1-i>();
373 const auto& otherGridGeometry = this->
problem(domainJ).gridGeometry();
374 const auto& otherElement = otherGridGeometry.element(otherElementIdx);
375 auto otherFvGeometry =
localView(otherGridGeometry).bindElement(otherElement);
380 volVars_(domainJ, otherElement, *std::begin(scvs(otherFvGeometry))),
381 std::move(otherFvGeometry),
383 couplingMapper_.flipScvfIndex(domainI, scvf),
385 this->
problem(domainJ).spatialParams().gravity(scvf.center())
391 const auto otherElementIdx = couplingMapper_.outsideElementIndex(domainI, scvf);
392 constexpr auto domainJ = Dune::index_constant<1-i>();
393 const auto& otherGridGeometry = this->
problem(domainJ).gridGeometry();
394 const auto& otherElement = otherGridGeometry.element(otherElementIdx);
395 auto otherFvGeometry =
localView(otherGridGeometry).bindElement(otherElement);
397 const auto otherScvfIdx = couplingMapper_.flipScvfIndex(domainI, scvf);
398 const auto& otherScvf = otherFvGeometry.scvf(otherScvfIdx);
399 const auto& otherScv = otherFvGeometry.scv(otherScvf.insideScvIdx());
403 std::move(otherFvGeometry),
414 mutable std::tuple<std::vector<FreeFlowMomentumCouplingContext>, std::vector<PorousMediumCouplingContext>> couplingContext_;
415 mutable std::array<std::size_t, 2> couplingContextBoundForElement_;
417 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
Definition multidomain/couplingmanager.hh:260
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition propertysystem.hh:150
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:57
Definition common/properties.hh:102
The type for a global container for the volume variables.
Definition common/properties.hh:109
The grid variables object managing variable data on the grid (volvars/fluxvars cache).
Definition common/properties.hh:123
Coupling manager for Stokes and Darcy domains with equal dimension.
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:48
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/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:146
const auto & couplingContext(Dune::index_constant< i > domainI, const FVElementGeometry< i > &fvGeometry, const SubControlVolumeFace< i > scvf) const
Access the coupling context needed for the Stokes domain.
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:200
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/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:273
auto faceVelocity(const Element< porousMediumIndex > &element, const SubControlVolumeFace< porousMediumIndex > &scvf) const
Returns the velocity at a given sub control volume face.
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:300
bool isCoupled(Dune::index_constant< freeFlowMomentumIndex > domainI, const SubControlVolume< freeFlowMomentumIndex > &scv) const
If the boundary entity is on a coupling boundary.
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:293
static constexpr auto freeFlowMomentumIndex
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:53
const CouplingStencil & couplingStencil(Dune::index_constant< freeFlowMomentumIndex > domainI, const Element< freeFlowMomentumIndex > &elementI, const SubControlVolume< freeFlowMomentumIndex > &scvI, Dune::index_constant< porousMediumIndex > domainJ) const
returns an iteratable container of all indices of degrees of freedom of domain j that couple with / i...
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:244
bool isCoupled(Dune::index_constant< i > domainI, const SubControlVolumeFace< i > &scvf) const
Returns whether a given scvf is coupled to the other domain.
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:280
const CouplingStencil & couplingStencil(Dune::index_constant< porousMediumIndex > domainI, const Element< porousMediumIndex > &element, Dune::index_constant< freeFlowMomentumIndex > domainJ) const
The coupling stencils.
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:227
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/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:259
static constexpr auto porousMediumIndex
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:54
void init(std::shared_ptr< Problem< freeFlowMomentumIndex > > freeFlowMomentumProblem, std::shared_ptr< Problem< porousMediumIndex > > porousMediumProblem, SolutionVectorStorage &curSol)
Methods to be accessed by main.
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:115
typename ParentType::SolutionVectorStorage SolutionVectorStorage
Definition multidomain/boundary/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:56
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/freeflowporousmedium/ffmomentumpm/couplingmanager.hh:137
bool isCoupledElement(Dune::index_constant< i >, std::size_t eIdx) const
Return if an element residual with index eIdx of domain i is coupled to domain j.
Definition boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:258
void attachSolution(SolutionVectorStorage &curSol)
Definition multidomain/couplingmanager.hh:333
decltype(auto) curSol()
Definition multidomain/couplingmanager.hh:369
void setSubProblems(const std::tuple< std::shared_ptr< SubProblems >... > &problems)
Definition multidomain/couplingmanager.hh:298
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Definition multidomain/couplingmanager.hh:320
SubSolutionVector< i > & curSol(Dune::index_constant< i > domainIdx)
Definition multidomain/couplingmanager.hh:349
CouplingManager()
Definition multidomain/couplingmanager.hh:93
typename Traits::template TupleOfSharedPtr< SubSolutionVector > SolutionVectorStorage
the type in which the solution vector is stored in the manager
Definition multidomain/couplingmanager.hh:82
The local element solution class for staggered methods.
The interface of the coupling manager for multi domain problems.
the default mapper for conforming equal dimension boundary coupling between two domains (box or cc)
Declares all properties used in Dumux.