13#ifndef DUMUX_MULTIDOMAIN_COUPLINGMAPPER_BOUNDARYFACES_HH
14#define DUMUX_MULTIDOMAIN_COUPLINGMAPPER_BOUNDARYFACES_HH
24#include <dune/common/timer.hh>
25#include <dune/common/exceptions.hh>
26#include <dune/common/indices.hh>
38template<
class MDTraits,
class CouplingManager>
41 template<std::
size_t i>
using GridDiscretization =
typename MDTraits::template SubDomain<i>::GridGeometry;
42 template<std::
size_t i>
using GridView =
typename GridDiscretization<i>::GridView;
44 template<std::
size_t i>
45 static constexpr auto domainIdx()
46 {
return typename MDTraits::template SubDomain<i>::Index{}; }
50 std::size_t eIdxOutside;
51 std::size_t iIdxOutside;
54 using FlipIntersectionMapType = std::map<std::pair<std::size_t,std::size_t>, FaceInfo>;
55 using MapType = std::map<std::size_t, std::vector<std::size_t>>;
57 static constexpr std::size_t numSD = MDTraits::numSubDomains;
67 static_assert(numSD == 2,
"More than two subdomains not implemented!");
70 std::cout <<
"Initializing the coupling map..." << std::endl;
72 for (std::size_t domIdx = 0; domIdx < numSD; ++domIdx)
73 stencils_[domIdx].clear();
75 std::get<0>(intersectionInfo_).clear();
76 std::get<1>(intersectionInfo_).clear();
78 const auto& problem0 = couplingManager.
problem(domainIdx<0>());
79 const auto& problem1 = couplingManager.
problem(domainIdx<1>());
83 isCoupledDof_[0].assign(gridDisc0.numDofs(),
false);
84 isCoupledDof_[1].assign(gridDisc1.numDofs(),
false);
89 for (
const auto& element1 : elements(gridDisc1.gridView()))
91 elemDisc1.bindElement(element1);
95 std::vector<std::size_t> coupledOutsideElements;
97 for (
const auto& boundaryFace1 : boundaryFaces(elemDisc1))
101 const auto eps = boundaryFace1.area()*1e-8;
102 auto globalPos = boundaryFace1.center(); globalPos.axpy(eps, boundaryFace1.unitOuterNormal());
110 if (indices.size() > 1)
111 DUNE_THROW(Dune::InvalidStateException,
"Are you sure your sub-domain grids are conformingly discretized on the common interface?");
114 const auto eIdx1 = gridDisc1.elementMapper().index(element1);
115 const auto eIdx0 = indices[0];
116 const auto& element0 = gridDisc0.element(eIdx0);
117 elemDisc0.bindElement(element0);
120 if (std::find(coupledOutsideElements.begin(), coupledOutsideElements.end(), eIdx0) == coupledOutsideElements.end())
122 coupledOutsideElements.push_back(eIdx0);
124 for(
auto&& localDof :
localDofs(elemDisc1))
125 stencils_[0][eIdx0].push_back(localDof.dofIndex());
127 for(
auto&& localDof :
localDofs(elemDisc0))
128 stencils_[1][eIdx1].push_back(localDof.dofIndex());
131 for (
const auto& boundaryFace0 : boundaryFaces(elemDisc0))
133 const auto dist = (boundaryFace1.center() - boundaryFace0.center()).two_norm();
137 for(
const auto& localDof :
localDofs(elemDisc0, boundaryFace0))
138 isCoupledDof_[0][localDof.dofIndex()] =
true;
140 for(
const auto& localDof :
localDofs(elemDisc1, boundaryFace1))
141 isCoupledDof_[1][localDof.dofIndex()] =
true;
143 std::get<0>(intersectionInfo_)[std::make_pair(eIdx0,
static_cast<std::size_t
>(boundaryFace0.intersectionIndex()))]
144 = FaceInfo{eIdx1,
static_cast<std::size_t
>(boundaryFace1.intersectionIndex())};
145 std::get<1>(intersectionInfo_)[std::make_pair(eIdx1,
static_cast<std::size_t
>(boundaryFace1.intersectionIndex()))]
146 = FaceInfo{eIdx0,
static_cast<std::size_t
>(boundaryFace0.intersectionIndex())};
153 for (
auto& stencil : stencils_)
154 for (
auto& [eIdx, dofs] : stencil)
156 std::sort(dofs.begin(), dofs.end());
157 dofs.erase(std::unique(dofs.begin(), dofs.end()), dofs.end());
160 std::cout <<
"took " << watch.elapsed() <<
" seconds." << std::endl;
173 template<std::
size_t i, std::
size_t j>
175 const std::size_t eIdxI,
176 Dune::index_constant<j> domainJ)
const
179 return stencils_[i].at(eIdxI);
181 return emptyStencil_;
187 template<std::
size_t i>
190 return static_cast<bool>(stencils_[i].count(eIdx));
196 template<std::
size_t i>
199 return isCoupledDof_[i][dofIdx];
208 template<std::
size_t i>
211 std::size_t iIdxI)
const
213 return static_cast<bool>(std::get<i>(intersectionInfo_).count(std::make_pair(eIdxI, iIdxI)));
222 template<std::
size_t i>
225 std::size_t iIdxI)
const
227 return std::get<i>(intersectionInfo_).at(std::make_pair(eIdxI, iIdxI)).eIdxOutside;
236 template<std::
size_t i>
239 std::size_t iIdxI)
const
241 return std::get<i>(intersectionInfo_).at(std::make_pair(eIdxI, iIdxI)).iIdxOutside;
245 std::array<MapType, numSD> stencils_;
246 std::vector<std::size_t> emptyStencil_;
247 std::array<std::vector<bool>, numSD> isCoupledDof_;
248 std::tuple<FlipIntersectionMapType, FlipIntersectionMapType> intersectionInfo_;
The interface of the coupling manager for multi domain problems.
Definition multidomain/couplingmanager.hh:37
const Problem< i > & problem(Dune::index_constant< i > domainIdx) const
Return a reference to the sub problem.
Definition multidomain/couplingmanager.hh:318
Mapper for the boundary coupling of two domains of equal dimension using the boundary faces for coupl...
Definition couplingmapper_boundaryfaces.hh:40
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 iterable container of all indices of degrees of freedom of domain j that couple with the e...
Definition couplingmapper_boundaryfaces.hh:174
bool isCoupled(Dune::index_constant< i > domainI, std::size_t eIdxI, std::size_t iIdxI) const
If the boundary entity is on a coupling boundary.
Definition couplingmapper_boundaryfaces.hh:209
bool isCoupledDof(Dune::index_constant< i >, std::size_t dofIdx) const
Return if a dof with index dofIdx of domain i is coupled to domain j.
Definition couplingmapper_boundaryfaces.hh:197
std::size_t flipIntersectionIndex(Dune::index_constant< i > domainI, std::size_t eIdxI, std::size_t iIdxI) const
Return the intersection index on the outside element (the other domain).
Definition couplingmapper_boundaryfaces.hh:237
std::size_t outsideElementIndex(Dune::index_constant< i > domainI, std::size_t eIdxI, std::size_t iIdxI) const
Return the outside element index (the element index of the other domain).
Definition couplingmapper_boundaryfaces.hh:223
void update(const CouplingManager &couplingManager)
Main update routine.
Definition couplingmapper_boundaryfaces.hh:65
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 couplingmapper_boundaryfaces.hh:188
std::vector< std::size_t > CouplingStencil
Definition couplingmapper_boundaryfaces.hh:60
Type traits for classes providing a grid discretization.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition localview.hh:26
std::vector< std::pair< int, std::size_t > > intersectingEntities(const Dune::FieldVector< ctype, dimworld > &point, const DistributedBoundingBoxTree< EntitySet > &tree, bool isCartesianGrid=false, bool onlyOwned=true)
Compute all intersections between entities and a point on a distributed tree.
Definition distributedintersectingentities.hh:81
decltype(auto) gridDiscretization(const T &t, Args &&... args)
The grid discretization.
Definition griddiscretization.hh:65
Algorithms that finds which geometric entities intersect.
auto localDofs(const FVElementGeometry &fvGeometry)
range over local dofs
Definition localdof.hh:50