25#ifndef DUMUX_MULTIDOMAIN_DARCYDARCY_BOUNDARY_COUPLINGMAPPER_HH
26#define DUMUX_MULTIDOMAIN_DARCYDARCY_BOUNDARY_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>
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 SubControlVolumeFace =
typename GridGeometry<i>::SubControlVolumeFace;
54 template<std::
size_t i>
using GridView =
typename GridGeometry<i>::GridView;
55 template<std::
size_t i>
using Element =
typename GridView<i>::template Codim<0>::Entity;
57 template<std::
size_t i>
58 static constexpr auto domainIdx()
59 {
return typename MDTraits::template SubDomain<i>::Index{}; }
61 template<std::
size_t i>
62 static constexpr bool isCCTpfa()
67 std::size_t eIdxOutside;
68 std::size_t flipScvfIdx;
71 using FlipScvfMapType = std::unordered_map<std::size_t, ScvfInfo>;
72 using MapType = std::unordered_map<std::size_t, std::vector<std::size_t>>;
74 static constexpr std::size_t numSD = MDTraits::numSubDomains;
80 template<
class CouplingManager>
84 static_assert(numSD == 2,
"More than two subdomains not implemented!");
85 static_assert(isCCTpfa<0>() && isCCTpfa<1>(),
"Only cctpfa implemented!");
88 std::cout <<
"Initializing the coupling map..." << std::endl;
90 for (std::size_t domIdx = 0; domIdx < numSD; ++domIdx)
92 stencils_[domIdx].clear();
93 scvfInfo_[domIdx].clear();
96 const auto& problem0 = couplingManager.
problem(domainIdx<0>());
97 const auto& problem1 = couplingManager.
problem(domainIdx<1>());
98 const auto& gg0 = problem0.gridGeometry();
99 const auto& gg1 = problem1.gridGeometry();
101 isCoupledScvf_[0].resize(gg0.numScvf(),
false);
102 isCoupledScvf_[1].resize(gg1.numScvf(),
false);
104 for (
const auto& element0 : elements(gg0.gridView()))
107 fvGeometry0.bindElement(element0);
109 for (
const auto& scvf0 : scvfs(fvGeometry0))
112 if (!scvf0.boundary())
117 const auto eps = (scvf0.ipGlobal() - element0.geometry().corner(0)).two_norm()*1e-8;
118 auto globalPos = scvf0.ipGlobal(); globalPos.axpy(
eps, scvf0.unitOuterNormal());
126 if (indices.size() > 1)
127 DUNE_THROW(Dune::InvalidStateException,
"Are you sure your grids is conforming at the boundary?");
130 const auto eIdx0 = gg0.elementMapper().index(element0);
131 const auto eIdx1 = indices[0];
132 stencils_[0][eIdx0].push_back(eIdx1);
135 isCoupledScvf_[0][scvf0.index()] =
true;
136 const auto& element1 = gg1.element(eIdx1);
138 fvGeometry1.bindElement(element1);
141 for (
const auto& scvf1 : scvfs(fvGeometry1))
142 if (scvf1.boundary())
143 if (abs(scvf1.unitOuterNormal()*scvf0.unitOuterNormal() + 1) <
eps)
145 isCoupledScvf_[1][scvf1.index()] =
true;
146 scvfInfo_[0][scvf0.index()] = ScvfInfo{eIdx1, scvf1.index()};
147 scvfInfo_[1][scvf1.index()] = ScvfInfo{eIdx0, scvf0.index()};
153 for (
const auto& entry : stencils_[0])
154 for (
const auto idx : entry.second)
155 stencils_[1][idx].push_back(entry.first);
157 std::cout <<
"took " << watch.elapsed() <<
" seconds." << std::endl;
174 template<std::
size_t i, std::
size_t j>
176 const std::size_t eIdxI,
177 Dune::index_constant<j> domainJ)
const
179 static_assert(i != j,
"A domain cannot be coupled to itself!");
181 return stencils_[i].at(eIdxI);
183 return emptyStencil_;
189 template<std::
size_t i>
191 {
return static_cast<bool>(stencils_[i].count(eIdx)); }
198 template<std::
size_t i>
200 const SubControlVolumeFace<i>& scvf)
const
202 return isCoupledScvf_[i].at(scvf.index());
210 template<std::
size_t i>
212 const SubControlVolumeFace<i>& scvf)
const
214 return scvfInfo_[i].at(scvf.index()).flipScvfIdx;
222 template<std::
size_t i>
224 const SubControlVolumeFace<i>& scvf)
const
226 return scvfInfo_[i].at(scvf.index()).eIdxOutside;
230 std::array<MapType, numSD> stencils_;
231 std::vector<std::size_t> emptyStencil_;
232 std::array<std::vector<bool>, numSD> isCoupledScvf_;
233 std::array<FlipScvfMapType, numSD> scvfInfo_;
Algorithms that finds which geometric entites intersect.
The available discretization methods in Dumux.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:38
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:45
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
constexpr double eps
epsilon for checking direction of scvf normals
Definition: test_tpfafvgeometry_nonconforming.cc:44
the default mapper for conforming equal dimension boundary coupling between two domains (box or cc)
Definition: boundary/darcydarcy/couplingmapper.hh:49
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/darcydarcy/couplingmapper.hh:190
void update(const CouplingManager &couplingManager)
Main update routine.
Definition: boundary/darcydarcy/couplingmapper.hh:81
const std::vector< std::size_t > & couplingStencil(Dune::index_constant< i > domainI, const std::size_t eIdxI, Dune::index_constant< j > domainJ) const
returns an iteratable container of all indices of degrees of freedom of domain j that couple with / i...
Definition: boundary/darcydarcy/couplingmapper.hh:175
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/darcydarcy/couplingmapper.hh:223
bool isCoupled(Dune::index_constant< i > domainI, const SubControlVolumeFace< i > &scvf) const
If the boundary entity is on a coupling boundary.
Definition: boundary/darcydarcy/couplingmapper.hh:199
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/darcydarcy/couplingmapper.hh:211
Definition: multidomain/couplingmanager.hh:46
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Return a reference to the sub problem.
Definition: multidomain/couplingmanager.hh:264