14#ifndef DUMUX_DUAL_NETWORK_COUPLINGMAPPER_HH
15#define DUMUX_DUAL_NETWORK_COUPLINGMAPPER_HH
18#include <unordered_map>
24#include <dune/common/iteratorrange.hh>
25#include <dune/common/iteratorfacades.hh>
27#include <dune/common/exceptions.hh>
41 struct HostGridConnectionInfo
43 std::size_t hostGridElementIndex;
44 std::size_t voidVertexHostIdx;
45 std::size_t solidVertexHostIdx;
46 Scalar connectionArea;
47 Scalar connectionLength;
48 std::vector<std::size_t> voidElementHostIdx;
49 std::vector<std::size_t> solidElementHostIdx;
50 std::vector<std::size_t> coupledVoidVertexHostIdx;
51 std::vector<std::size_t> coupledSolidVertexHostIdx;
52 std::size_t connectionGlobalId;
55 struct SubGridConnectionInfo
58 std::size_t solidVertexIdx;
59 std::size_t voidVertexIdx;
60 std::size_t someSolidElementIdx;
61 std::size_t someVoidElementIdx;
62 std::vector<std::size_t> convectionVoidElementIdx;
63 Scalar connectionArea;
64 Scalar connectionLength;
67 template<
class Vector>
68 class ConnectionIterator :
public Dune::ForwardIteratorFacade<ConnectionIterator<Vector>, const SubGridConnectionInfo>
70 using ThisType = ConnectionIterator<Vector>;
71 using Iterator =
typename Vector::const_iterator;
73 ConnectionIterator(
const Iterator& it,
const std::vector<SubGridConnectionInfo>& info)
74 : it_(it), InfoPtr_(&info) {}
76 ConnectionIterator() : it_(Iterator()), InfoPtr_(
nullptr) {}
79 const SubGridConnectionInfo& dereference()
const
80 {
return InfoPtr_->at(*it_); }
83 bool equals(
const ThisType& other)
const
84 {
return it_ == other.it_; }
91 const std::vector<SubGridConnectionInfo>* InfoPtr_;
97 template<
class HostGr
idView,
class HostGr
idData,
class Vo
idGr
idGeometry,
class Sol
idGr
idGeometry>
99 const HostGridData& hostGridData,
100 const VoidGridGeometry& voidGridGeometry,
101 const SolidGridGeometry& solidGridGeometry)
103 fillVertexMap_(hostGridView, voidGridGeometry, voidHostToSubVertexIdxMap_);
104 fillVertexMap_(hostGridView, solidGridGeometry, solidHostToSubVertexIdxMap_);
105 fillElementMap_(hostGridView, voidGridGeometry, voidHostToSubElementIdxMap_);
106 fillElementMap_(hostGridView, solidGridGeometry, solidHostToSubElementIdxMap_);
108 isCoupledVoidDof_.resize(voidGridGeometry.gridView().size(1),
false);
109 isCoupledSolidDof_.resize(solidGridGeometry.gridView().size(1),
false);
111 const auto connectionInfo = getConnectionInfo_(hostGridView, hostGridData);
115 auto voidHostToSubVertexIdx = [&](
const auto hostIdx)
116 {
return voidHostToSubVertexIdxMap_.at(hostIdx); };
118 auto solidHostToSubVertexIdx = [&](
const auto hostIdx)
119 {
return solidHostToSubVertexIdxMap_.at(hostIdx); };
121 const auto directlyCoupledVoidDofIdx = voidHostToSubVertexIdx(info.voidVertexHostIdx);
122 const auto directlyCoupledSolidDofIdx = solidHostToSubVertexIdx(info.solidVertexHostIdx);
124 auto coupledVoidElementIdxSub = info.voidElementHostIdx;
125 auto coupledSolidElementIdxSub = info.solidElementHostIdx;
128 std::transform(coupledVoidElementIdxSub.begin(), coupledVoidElementIdxSub.end(),
129 coupledVoidElementIdxSub.begin(), [&](
const auto eIdx){ return voidHostToSubElementIdxMap_.at(eIdx); });
130 std::transform(coupledSolidElementIdxSub.begin(), coupledSolidElementIdxSub.end(),
131 coupledSolidElementIdxSub.begin(), [&](
const auto eIdx){ return solidHostToSubElementIdxMap_.at(eIdx); });
134 auto convectionVoidElementIdx = std::vector<std::size_t>();
136 voidToSolidConnectionIds_[directlyCoupledVoidDofIdx].emplace_back(info.connectionGlobalId);
137 solidToVoidConnectionIds_[directlyCoupledSolidDofIdx].emplace_back(info.connectionGlobalId);
139 connectionInfo_[info.connectionGlobalId] = SubGridConnectionInfo{info.connectionGlobalId,
140 directlyCoupledSolidDofIdx,
141 directlyCoupledVoidDofIdx,
142 coupledSolidElementIdxSub[0],
143 coupledVoidElementIdxSub[0],
144 convectionVoidElementIdx,
146 info.connectionLength};
148 hostGridElementIndexToGlobalId_[info.hostGridElementIndex] = info.connectionGlobalId;
150 isCoupledVoidDof_[directlyCoupledVoidDofIdx] =
true;
151 isCoupledSolidDof_[directlyCoupledSolidDofIdx] =
true;
153 for (
const auto eIdxVoidHost : info.voidElementHostIdx)
155 const auto eIdxSubVoid = voidHostToSubElementIdxMap_.at(eIdxVoidHost);
156 voidToSolidStencils_[eIdxSubVoid].push_back(directlyCoupledSolidDofIdx);
159 for (
const auto eIdxSolidHost : info.solidElementHostIdx)
161 const auto eIdxSubSolid = solidHostToSubElementIdxMap_.at(eIdxSolidHost);
162 solidToVoidStencils_[eIdxSubSolid].push_back(directlyCoupledVoidDofIdx);
166 for (
auto& stencil : voidToSolidStencils_)
167 removeDuplicates_(stencil.second);
168 for (
auto& stencil : solidToVoidStencils_)
169 removeDuplicates_(stencil.second);
172 auto voidFVGeometry =
localView(voidGridGeometry);
173 for (
const auto& voidElement : elements(voidGridGeometry.gridView()))
175 voidFVGeometry.bindElement(voidElement);
176 std::array<std::size_t, 2> dofIndex;
177 std::array<std::vector<std::size_t>, 2> coupledSolidVertexIdx;
178 for (
const auto& scv : scvs(voidFVGeometry))
179 dofIndex[scv.indexInElement()] = scv.dofIndex();
182 if (isCoupledVoidDof_[dofIndex[0]] && isCoupledVoidDof_[dofIndex[1]])
184 for (
auto& conn0 : voidToSolidConnectionIds_[dofIndex[0]])
186 for (
auto& conn1 : voidToSolidConnectionIds_[dofIndex[1]])
188 const auto globalId0 = conn0;
189 const auto globalId1 = conn1;
190 assert(globalId0 != globalId1);
192 if (connectionInfo_[globalId0].solidVertexIdx == connectionInfo_[globalId1].solidVertexIdx)
194 const auto voidElemIdx = voidGridGeometry.elementMapper().index(voidElement);
195 connectionInfo_[globalId0].convectionVoidElementIdx.push_back(voidElemIdx);
196 connectionInfo_[globalId1].convectionVoidElementIdx.push_back(voidElemIdx);
203 for (
auto& entry : voidToSolidConnectionIds_)
205 removeDuplicates_(entry.second);
207 std::cout <<
"void dof " << entry.first <<
" couples to " << entry.second.size() <<
" solid dofs: " << std::endl;
208 for (
auto& conn : entry.second)
210 const auto& info = connectionInfo_[conn];
211 assert(entry.first == info.voidVertexIdx);
212 std::cout <<
"solid vertex " << info.solidVertexIdx <<
" with elems ";
213 for (
const auto e : info.convectionVoidElementIdx)
214 std::cout << e <<
" ";
215 std:: cout <<
"||" << std::endl;
218 std::cout << std::endl;
221 for (
auto& entry : solidToVoidConnectionIds_)
223 removeDuplicates_(entry.second);
225 std::cout <<
"solid dof " << entry.first <<
" couples to " << entry.second.size() <<
" void dofs: " << std::endl;
226 for (
auto& conn : entry.second)
228 const auto& info = connectionInfo_[conn];
229 assert(entry.first == info.solidVertexIdx);
230 std::cout <<
"void vertex " << info.voidVertexIdx <<
" with elems ";
231 for (
const auto e : info.convectionVoidElementIdx)
232 std::cout << e <<
" ";
233 std:: cout <<
"||" << std::endl;
236 std::cout << std::endl;
243 {
return voidToSolidStencils_; }
246 {
return solidToVoidStencils_; }
249 {
return isCoupledVoidDof_; }
252 {
return isCoupledSolidDof_; }
258 using Iterator = ConnectionIterator<std::vector<std::size_t>>;
259 return Dune::IteratorRange<Iterator>(Iterator(ids.cbegin(),
connectionInfo()),
266 using Iterator = ConnectionIterator<std::vector<std::size_t>>;
267 return Dune::IteratorRange<Iterator>(Iterator(ids.cbegin(),
connectionInfo()),
272 {
return voidToSolidConnectionIds_; }
275 {
return solidToVoidConnectionIds_; }
278 {
return connectionInfo_; }
281 {
return voidHostToSubVertexIdxMap_; }
284 {
return solidHostToSubVertexIdxMap_; }
287 {
return voidHostToSubElementIdxMap_; }
290 {
return solidHostToSubElementIdxMap_; }
293 {
return hostGridElementIndexToGlobalId_; }
297 template<
class HostGr
idView,
class HostGr
idData>
298 std::vector<HostGridConnectionInfo> getConnectionInfo_(
const HostGridView& hostGridView,
299 const HostGridData& hostGridData)
302 std::size_t connectionGlobalId = 0;
304 for (
const auto& element : elements(hostGridView))
306 if (hostGridData.getParameter(element,
"ThroatDomainType") == 2)
308 const auto& vertex0 = element.template subEntity<1>(0);
309 const auto& vertex1 = element.template subEntity<1>(1);
311 HostGridConnectionInfo info;
312 info.hostGridElementIndex = hostGridView.indexSet().index(element);
313 info.connectionGlobalId = connectionGlobalId++;
314 info.voidVertexHostIdx = hostGridView.indexSet().index(vertex0);
315 info.solidVertexHostIdx = hostGridView.indexSet().index(vertex1);
317 if (hostGridData.getParameter(vertex0,
"PoreDomainType") == 1)
319 assert(hostGridData.getParameter(vertex1,
"PoreDomainType") == 0);
321 swap(info.voidVertexHostIdx, info.solidVertexHostIdx);
324 info.connectionArea = hostGridData.getParameter(element,
"ThroatCrossSectionalArea");
325 info.connectionLength = element.geometry().volume();
327 for (
const auto& intersection : intersections(hostGridView, element))
329 if (!intersection.neighbor())
332 const auto& outsideElement = intersection.outside();
335 if (hostGridData.getParameter(outsideElement,
"ThroatDomainType") == 2)
338 const auto outsideElementIdx = hostGridView.indexSet().index(outsideElement);
340 if (hostGridData.getParameter(outsideElement,
"ThroatDomainType") == 0)
341 info.voidElementHostIdx.push_back(outsideElementIdx);
343 info.solidElementHostIdx.push_back(outsideElementIdx);
345 std::array outsideDomainType = {-1, -1};
346 for (
int localVIdx = 0; localVIdx < 2; ++localVIdx)
348 const auto& outsideVertex = outsideElement.template subEntity<1>(localVIdx);
349 const auto outsideVertexIdx = hostGridView.indexSet().index(outsideVertex);
350 outsideDomainType[localVIdx] = hostGridData.getParameter(outsideVertex,
"PoreDomainType");
352 if (localVIdx == 1 && (outsideDomainType[1] != outsideDomainType[0]))
353 DUNE_THROW(Dune::IOError,
"Pore with hostIdx " << hostGridView.indexSet().index(outsideElement.template subEntity<1>(0))
354 <<
" has domain type " << outsideDomainType[0]
355 <<
", but pore with hostIdx " << outsideVertexIdx
356 <<
" has domain type " << outsideDomainType[1] <<
". Check your grid file");
358 if (outsideDomainType[localVIdx] == 0)
359 info.coupledVoidVertexHostIdx.push_back(outsideVertexIdx);
361 info.coupledSolidVertexHostIdx.push_back(outsideVertexIdx);
372 template<
class HostGr
idView,
class SubGr
idGeometry,
class Map>
373 void fillVertexMap_(
const HostGridView& hostGridView,
const SubGridGeometry& subGridGeometry, Map& map)
375 for (
const auto& vertex : vertices(subGridGeometry.gridView()))
377 const auto vIdxSub = subGridGeometry.vertexMapper().index(vertex);
378 const auto vIdxHost = hostGridView.indexSet().index(
vertex.impl().hostEntity());
379 map[vIdxHost] = vIdxSub;
383 template<
class HostGr
idView,
class SubGr
idGeometry,
class Map>
384 void fillElementMap_(
const HostGridView& hostGridView,
const SubGridGeometry& subGridGeometry, Map& map)
386 for (
const auto& element : elements(subGridGeometry.gridView()))
388 const auto eIdxSub = subGridGeometry.elementMapper().index(element);
389 const auto eIdxHost = hostGridView.indexSet().index(
element.impl().hostEntity());
390 map[eIdxHost] = eIdxSub;
395 void removeDuplicates_(std::vector<std::size_t>& stencil)
397 std::sort(stencil.begin(), stencil.end());
398 stencil.erase(std::unique(stencil.begin(), stencil.end()), stencil.end());
401 std::unordered_map<std::size_t, std::size_t> voidHostToSubVertexIdxMap_;
402 std::unordered_map<std::size_t, std::size_t> solidHostToSubVertexIdxMap_;
403 std::unordered_map<std::size_t, std::size_t> voidHostToSubElementIdxMap_;
404 std::unordered_map<std::size_t, std::size_t> solidHostToSubElementIdxMap_;
406 std::vector<bool> isCoupledVoidDof_;
407 std::vector<bool> isCoupledSolidDof_;
409 std::unordered_map<std::size_t, Stencil> voidToSolidStencils_;
410 std::unordered_map<std::size_t, Stencil> solidToVoidStencils_;
412 std::unordered_map<std::size_t, std::vector<std::size_t>> voidToSolidConnectionIds_;
413 std::unordered_map<std::size_t, std::vector<std::size_t>> solidToVoidConnectionIds_;
415 std::vector<SubGridConnectionInfo> connectionInfo_;
416 std::unordered_map<std::size_t, std::size_t> hostGridElementIndexToGlobalId_;
Coupling mapper for Stokes and Darcy domains with equal dimension.
Definition: dualnetwork/couplingmapper.hh:40
const auto & solidToVoidConnectionIds() const
Definition: dualnetwork/couplingmapper.hh:274
auto voidToSolidConnections(const std::size_t dofIdx) const
Returns an iterator allowing for (const auto& conn : voidToSolidConnections(dofIdx)) {....
Definition: dualnetwork/couplingmapper.hh:255
const auto & voidToSolidStencils() const
Definition: dualnetwork/couplingmapper.hh:242
std::vector< std::size_t > Stencil
Definition: dualnetwork/couplingmapper.hh:95
const std::vector< bool > & isCoupledVoidDof() const
Definition: dualnetwork/couplingmapper.hh:248
const std::vector< bool > & isCoupledSolidDof() const
Definition: dualnetwork/couplingmapper.hh:251
const auto & voidToSolidConnectionIds() const
Definition: dualnetwork/couplingmapper.hh:271
const auto & connectionInfo() const
Definition: dualnetwork/couplingmapper.hh:277
DualNetworkCouplingMapper(const HostGridView &hostGridView, const HostGridData &hostGridData, const VoidGridGeometry &voidGridGeometry, const SolidGridGeometry &solidGridGeometry)
Definition: dualnetwork/couplingmapper.hh:98
auto solidToVoidConnections(const std::size_t dofIdx) const
Definition: dualnetwork/couplingmapper.hh:263
const auto & hostGridElementIndexToGlobalId() const
Definition: dualnetwork/couplingmapper.hh:292
const auto & solidHostToSubVertexIdxMap() const
Definition: dualnetwork/couplingmapper.hh:283
const auto & solidHostToSubElementIdxMap() const
Definition: dualnetwork/couplingmapper.hh:289
const auto & voidHostToSubElementIdxMap() const
Definition: dualnetwork/couplingmapper.hh:286
const auto & solidToVoidStencils() const
Definition: dualnetwork/couplingmapper.hh:245
const auto & voidHostToSubVertexIdxMap() const
Definition: dualnetwork/couplingmapper.hh:280
A map from indices to entities using grid entity seeds.
GridCache::LocalView localView(const GridCache &gridCache)
Free function to get the local view of a grid cache object.
Definition: localview.hh:26
Definition: discretization/porenetwork/fvelementgeometry.hh:24