25#ifndef DUMUX_MULTIDOMAIN_FREEFLOWMOMENTUM_POROUSMEDIUM_COUPLINGMAPPER_HH
26#define DUMUX_MULTIDOMAIN_FREEFLOWMOMENTUM_POROUSMEDIUM_COUPLINGMAPPER_HH
29#include <unordered_map>
33#include <dune/common/timer.hh>
34#include <dune/common/exceptions.hh>
35#include <dune/common/indices.hh>
47template<
class MDTraits,
class CouplingManager>
50 using Scalar =
typename MDTraits::Scalar;
52 template<std::
size_t i>
using GridGeometry =
typename MDTraits::template SubDomain<i>::GridGeometry;
53 template<std::
size_t i>
using SubControlVolume =
typename GridGeometry<i>::SubControlVolume;
54 template<std::
size_t i>
using SubControlVolumeFace =
typename GridGeometry<i>::SubControlVolumeFace;
55 template<std::
size_t i>
using GridView =
typename GridGeometry<i>::GridView;
56 template<std::
size_t i>
using Element =
typename GridView<i>::template Codim<0>::Entity;
58 template<std::
size_t i>
59 static constexpr auto domainIdx()
60 {
return typename MDTraits::template SubDomain<i>::Index{}; }
62 template<std::
size_t i>
63 static constexpr bool isFcStaggered()
66 template<std::
size_t i>
67 static constexpr bool isCCTpfa()
72 std::size_t eIdxOutside;
73 std::size_t flipScvfIdx;
78 std::size_t eIdxOutside;
79 std::size_t flipScvfIdx;
80 std::size_t dofIdxOutside;
83 using FlipScvfMapTypePM = std::unordered_map<std::size_t, ScvfInfoPM>;
84 using FlipScvfMapTypeFF = std::unordered_map<std::size_t, ScvfInfoFF>;
85 using MapType = std::unordered_map<std::size_t, std::vector<std::size_t>>;
87 static constexpr std::size_t numSD = MDTraits::numSubDomains;
96 static_assert(numSD == 2,
"More than two subdomains not implemented!");
97 static_assert(isFcStaggered<0>() && isCCTpfa<1>(),
"Only coupling between fcstaggered and cctpfa implemented!");
100 std::cout <<
"Initializing the coupling map..." << std::endl;
102 for (std::size_t domIdx = 0; domIdx < numSD; ++domIdx)
103 stencils_[domIdx].clear();
105 std::get<CouplingManager::freeFlowMomentumIndex>(scvfInfo_).clear();
106 std::get<CouplingManager::porousMediumIndex>(scvfInfo_).clear();
110 const auto& freeFlowMomentumGG = freeFlowMomentumProblem.gridGeometry();
111 const auto& porousMediumGG = porousMediumProblem.gridGeometry();
113 isCoupledFFDof_.resize(freeFlowMomentumGG.numScvf(),
false);
114 isCoupledFFElement_.resize(freeFlowMomentumGG.gridView().size(0),
false);
118 auto pmFvGeometry =
localView(porousMediumGG);
119 auto ffFvGeometry =
localView(freeFlowMomentumGG);
121 for (
const auto& pmElement : elements(porousMediumGG.gridView()))
123 pmFvGeometry.bindElement(pmElement);
125 for (
const auto& pmScvf : scvfs(pmFvGeometry))
128 if (!pmScvf.boundary())
133 const auto eps = (pmScvf.ipGlobal() - pmFvGeometry.geometry(pmScvf).corner(0)).two_norm()*1e-8;
134 auto globalPos = pmScvf.ipGlobal(); globalPos.axpy(eps, pmScvf.unitOuterNormal());
142 if (indices.size() > 1)
143 DUNE_THROW(Dune::InvalidStateException,
"Are you sure your sub-domain grids are conformingly discretized on the common interface?");
146 const auto pmElemIdx = porousMediumGG.elementMapper().index(pmElement);
147 const auto ffElemIdx = indices[0];
148 const auto& ffElement = freeFlowMomentumGG.element(ffElemIdx);
149 ffFvGeometry.bindElement(ffElement);
151 for (
const auto& ffScvf : scvfs(ffFvGeometry))
154 if (!ffScvf.boundary() || !ffScvf.isFrontal())
157 const auto dist = (pmScvf.ipGlobal() - ffScvf.ipGlobal()).two_norm();
161 const auto& ffScv = ffFvGeometry.scv(ffScvf.insideScvIdx());
170 for (
const auto& otherFfScvf : scvfs(ffFvGeometry, ffScv))
172 if (otherFfScvf.isLateral())
175 const auto& lateralOrthogonalScvf = ffFvGeometry.lateralOrthogonalScvf(otherFfScvf);
176 isCoupledLateralScvf_[lateralOrthogonalScvf.index()] =
true;
179 if (!otherFfScvf.boundary())
180 isCoupledLateralScvf_[otherFfScvf.index()] =
true;
184 const auto otherScvfEps = (otherFfScvf.ipGlobal() - ffFvGeometry.geometry(otherFfScvf).corner(0)).two_norm()*1e-8;
185 auto otherScvfGlobalPos = otherFfScvf.center(); otherScvfGlobalPos.axpy(otherScvfEps, otherFfScvf.unitOuterNormal());
188 isCoupledLateralScvf_[otherFfScvf.index()] =
true;
192 isCoupledFFDof_[ffScv.dofIndex()] =
true;
193 isCoupledFFElement_[ffElemIdx] =
true;
195 std::get<CouplingManager::porousMediumIndex>(scvfInfo_)[pmScvf.index()] = ScvfInfoPM{ffElemIdx, ffScvf.index()};
196 std::get<CouplingManager::freeFlowMomentumIndex>(scvfInfo_)[ffScvf.index()] = ScvfInfoFF{pmElemIdx, pmScvf.index(), ffScv.dofIndex()};
201 std::cout <<
"took " << watch.elapsed() <<
" seconds." << std::endl;
218 const std::vector<std::size_t>&
couplingStencil(Dune::index_constant<CouplingManager::porousMediumIndex> domainI,
219 const std::size_t eIdxI,
220 Dune::index_constant<CouplingManager::freeFlowMomentumIndex> domainJ)
const
225 return emptyStencil_;
243 const std::vector<std::size_t>&
couplingStencil(Dune::index_constant<CouplingManager::freeFlowMomentumIndex> domainI,
244 const Element<CouplingManager::freeFlowMomentumIndex>& elementI,
245 const SubControlVolume<CouplingManager::freeFlowMomentumIndex>& scvI,
246 Dune::index_constant<CouplingManager::porousMediumIndex> domainJ)
const
251 return emptyStencil_;
257 template<std::
size_t i>
261 return static_cast<bool>(stencils_[i].count(eIdx));
263 return isCoupledFFElement_[eIdx];
271 template<std::
size_t i>
273 const SubControlVolumeFace<i>& scvf)
const
275 return isCoupledScvf_[i].at(scvf.index());
284 const SubControlVolumeFace<CouplingManager::freeFlowMomentumIndex>& scvf)
const
285 {
return isCoupledLateralScvf_.count(scvf.index()); }
292 bool isCoupled(Dune::index_constant<CouplingManager::freeFlowMomentumIndex> domainI,
293 const SubControlVolume<CouplingManager::freeFlowMomentumIndex>& scv)
const
294 {
return isCoupledFFDof_[scv.dofIndex()]; }
301 template<std::
size_t i>
303 const SubControlVolumeFace<i>& scvf)
const
305 return std::get<i>(scvfInfo_).at(scvf.index()).flipScvfIdx;
313 template<std::
size_t i>
315 const SubControlVolumeFace<i>& scvf)
const
317 return std::get<i>(scvfInfo_).at(scvf.index()).eIdxOutside;
325 template<std::
size_t i>
327 const SubControlVolumeFace<i>& scvf)
const
332 return std::get<i>(scvfInfo_).at(scvf.index()).dofIdxOutside;
336 std::array<MapType, numSD> stencils_;
337 std::vector<std::size_t> emptyStencil_;
338 std::array<std::vector<bool>, numSD> isCoupledScvf_;
339 std::unordered_map<std::size_t, bool> isCoupledLateralScvf_;
340 std::vector<bool> isCoupledFFDof_;
341 std::vector<bool> isCoupledFFElement_;
342 std::tuple<FlipScvfMapTypeFF, FlipScvfMapTypePM> scvfInfo_;
The available discretization methods in Dumux.
Algorithms that finds which geometric entities intersect.
std::vector< std::size_t > intersectingEntities(const Dune::FieldVector< ctype, dimworld > &point, const BoundingBoxTree< EntitySet > &tree, bool isCartesianGrid=false)
Compute all intersections between entities and a point.
Definition: intersectingentities.hh:114
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
Adaption of the non-isothermal two-phase two-component flow model to problems with CO2.
Definition: adapt.hh:29
constexpr CCTpfa cctpfa
Definition: method.hh:134
constexpr FCStaggered fcstaggered
Definition: method.hh:140
static constexpr auto freeFlowMomentumIndex
Definition: multidomain/boundary/freeflowporenetwork/couplingmanager.hh:46
static constexpr auto porousMediumIndex
Definition: multidomain/boundary/freeflowporousmedium/couplingmanager.hh:47
the default mapper for conforming equal dimension boundary coupling between two domains (box or cc)
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:49
bool isCoupled(Dune::index_constant< i > domainI, const SubControlVolumeFace< i > &scvf) const
If the boundary entity is on a coupling boundary.
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:272
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
const std::vector< std::size_t > & couplingStencil(Dune::index_constant< CouplingManager::freeFlowMomentumIndex > domainI, const Element< CouplingManager::freeFlowMomentumIndex > &elementI, const SubControlVolume< CouplingManager::freeFlowMomentumIndex > &scvI, Dune::index_constant< CouplingManager::porousMediumIndex > domainJ) const
returns an iterable container of all indices of degrees of freedom of domain j that couple with / inf...
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:243
bool isCoupled(Dune::index_constant< CouplingManager::freeFlowMomentumIndex > domainI, const SubControlVolume< CouplingManager::freeFlowMomentumIndex > &scv) const
If the boundary entity is on a coupling boundary.
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:292
bool isCoupledLateralScvf(Dune::index_constant< CouplingManager::freeFlowMomentumIndex > domainI, const SubControlVolumeFace< CouplingManager::freeFlowMomentumIndex > &scvf) const
If the boundary entity is on a coupling boundary.
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:283
std::size_t flipScvfIndex(Dune::index_constant< i > domainI, const SubControlVolumeFace< i > &scvf) const
Return the scvf index of the flipped scvf in the other domain.
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:302
const std::vector< std::size_t > & couplingStencil(Dune::index_constant< CouplingManager::porousMediumIndex > domainI, const std::size_t eIdxI, Dune::index_constant< CouplingManager::freeFlowMomentumIndex > domainJ) const
returns an iterable container of all indices of degrees of freedom of domain j that couple with / inf...
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:218
std::size_t outsideDofIndex(Dune::index_constant< i > domainI, const SubControlVolumeFace< i > &scvf) const
Return the outside element index (the element index of the other domain)
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:326
std::size_t outsideElementIndex(Dune::index_constant< i > domainI, const SubControlVolumeFace< i > &scvf) const
Return the outside element index (the element index of the other domain)
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:314
void update(const CouplingManager &couplingManager)
Main update routine.
Definition: boundary/freeflowporousmedium/ffmomentumpm/couplingmapper.hh:93
The interface of the coupling manager for multi domain problems.
Definition: multidomain/couplingmanager.hh:60
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Return a reference to the sub problem.
Definition: multidomain/couplingmanager.hh:321