42 struct HostGridConnectionInfo
44 std::size_t hostGridElementIndex;
45 std::size_t voidVertexHostIdx;
46 std::size_t solidVertexHostIdx;
47 Scalar connectionArea;
48 Scalar connectionLength;
49 std::vector<std::size_t> voidElementHostIdx;
50 std::vector<std::size_t> solidElementHostIdx;
51 std::vector<std::size_t> coupledVoidVertexHostIdx;
52 std::vector<std::size_t> coupledSolidVertexHostIdx;
53 std::size_t connectionGlobalId;
56 struct SubGridConnectionInfo
59 std::size_t solidVertexIdx;
60 std::size_t voidVertexIdx;
61 std::size_t someSolidElementIdx;
62 std::size_t someVoidElementIdx;
63 std::vector<std::size_t> convectionVoidElementIdx;
64 Scalar connectionArea;
65 Scalar connectionLength;
68 template<
class Vector>
69 class ConnectionIterator :
public Dune::ForwardIteratorFacade<ConnectionIterator<Vector>, const SubGridConnectionInfo>
71 using ThisType = ConnectionIterator<Vector>;
72 using Iterator =
typename Vector::const_iterator;
74 ConnectionIterator(
const Iterator& it,
const std::vector<SubGridConnectionInfo>& info)
75 : it_(it), InfoPtr_(&info) {}
77 ConnectionIterator() : it_(Iterator()), InfoPtr_(
nullptr) {}
80 const SubGridConnectionInfo& dereference()
const
81 {
return InfoPtr_->at(*it_); }
84 bool equals(
const ThisType& other)
const
85 {
return it_ == other.it_; }
92 const std::vector<SubGridConnectionInfo>* InfoPtr_;
98 template<
class HostGr
idView,
class HostGr
idData,
class Vo
idGr
idGeometry,
class Sol
idGr
idGeometry>
100 const HostGridData& hostGridData,
101 const VoidGridGeometry& voidGridGeometry,
102 const SolidGridGeometry& solidGridGeometry)
104 fillVertexMap_(hostGridView, voidGridGeometry, voidHostToSubVertexIdxMap_);
105 fillVertexMap_(hostGridView, solidGridGeometry, solidHostToSubVertexIdxMap_);
106 fillElementMap_(hostGridView, voidGridGeometry, voidHostToSubElementIdxMap_);
107 fillElementMap_(hostGridView, solidGridGeometry, solidHostToSubElementIdxMap_);
109 isCoupledVoidDof_.resize(voidGridGeometry.gridView().size(1),
false);
110 isCoupledSolidDof_.resize(solidGridGeometry.gridView().size(1),
false);
112 const auto connectionInfo = getConnectionInfo_(hostGridView, hostGridData);
116 auto voidHostToSubVertexIdx = [&](
const auto hostIdx)
117 {
return voidHostToSubVertexIdxMap_.at(hostIdx); };
119 auto solidHostToSubVertexIdx = [&](
const auto hostIdx)
120 {
return solidHostToSubVertexIdxMap_.at(hostIdx); };
122 const auto directlyCoupledVoidDofIdx = voidHostToSubVertexIdx(info.voidVertexHostIdx);
123 const auto directlyCoupledSolidDofIdx = solidHostToSubVertexIdx(info.solidVertexHostIdx);
125 auto coupledVoidElementIdxSub = info.voidElementHostIdx;
126 auto coupledSolidElementIdxSub = info.solidElementHostIdx;
129 std::transform(coupledVoidElementIdxSub.begin(), coupledVoidElementIdxSub.end(),
130 coupledVoidElementIdxSub.begin(), [&](
const auto eIdx){ return voidHostToSubElementIdxMap_.at(eIdx); });
131 std::transform(coupledSolidElementIdxSub.begin(), coupledSolidElementIdxSub.end(),
132 coupledSolidElementIdxSub.begin(), [&](
const auto eIdx){ return solidHostToSubElementIdxMap_.at(eIdx); });
135 auto convectionVoidElementIdx = std::vector<std::size_t>();
137 voidToSolidConnectionIds_[directlyCoupledVoidDofIdx].emplace_back(info.connectionGlobalId);
138 solidToVoidConnectionIds_[directlyCoupledSolidDofIdx].emplace_back(info.connectionGlobalId);
140 connectionInfo_[info.connectionGlobalId] = SubGridConnectionInfo{info.connectionGlobalId,
141 directlyCoupledSolidDofIdx,
142 directlyCoupledVoidDofIdx,
143 coupledSolidElementIdxSub[0],
144 coupledVoidElementIdxSub[0],
145 convectionVoidElementIdx,
147 info.connectionLength};
149 hostGridElementIndexToGlobalId_[info.hostGridElementIndex] = info.connectionGlobalId;
151 isCoupledVoidDof_[directlyCoupledVoidDofIdx] =
true;
152 isCoupledSolidDof_[directlyCoupledSolidDofIdx] =
true;
154 for (
const auto eIdxVoidHost : info.voidElementHostIdx)
156 const auto eIdxSubVoid = voidHostToSubElementIdxMap_.at(eIdxVoidHost);
157 voidToSolidStencils_[eIdxSubVoid].push_back(directlyCoupledSolidDofIdx);
160 for (
const auto eIdxSolidHost : info.solidElementHostIdx)
162 const auto eIdxSubSolid = solidHostToSubElementIdxMap_.at(eIdxSolidHost);
163 solidToVoidStencils_[eIdxSubSolid].push_back(directlyCoupledVoidDofIdx);
167 for (
auto& stencil : voidToSolidStencils_)
168 removeDuplicates_(stencil.second);
169 for (
auto& stencil : solidToVoidStencils_)
170 removeDuplicates_(stencil.second);
173 auto voidFVGeometry =
localView(voidGridGeometry);
174 for (
const auto& voidElement : elements(voidGridGeometry.gridView()))
176 voidFVGeometry.bindElement(voidElement);
177 std::array<std::size_t, 2> dofIndex;
178 std::array<std::vector<std::size_t>, 2> coupledSolidVertexIdx;
179 for (
const auto& scv : scvs(voidFVGeometry))
180 dofIndex[scv.indexInElement()] = scv.dofIndex();
183 if (isCoupledVoidDof_[dofIndex[0]] && isCoupledVoidDof_[dofIndex[1]])
185 for (
auto& conn0 : voidToSolidConnectionIds_[dofIndex[0]])
187 for (
auto& conn1 : voidToSolidConnectionIds_[dofIndex[1]])
189 const auto globalId0 = conn0;
190 const auto globalId1 = conn1;
191 assert(globalId0 != globalId1);
193 if (connectionInfo_[globalId0].solidVertexIdx == connectionInfo_[globalId1].solidVertexIdx)
195 const auto voidElemIdx = voidGridGeometry.elementMapper().index(voidElement);
196 connectionInfo_[globalId0].convectionVoidElementIdx.push_back(voidElemIdx);
197 connectionInfo_[globalId1].convectionVoidElementIdx.push_back(voidElemIdx);
204 for (
auto& entry : voidToSolidConnectionIds_)
206 removeDuplicates_(entry.second);
208 std::cout <<
"void dof " << entry.first <<
" couples to " << entry.second.size() <<
" solid dofs: " << std::endl;
209 for (
auto& conn : entry.second)
211 const auto& info = connectionInfo_[conn];
212 assert(entry.first == info.voidVertexIdx);
213 std::cout <<
"solid vertex " << info.solidVertexIdx <<
" with elems ";
214 for (
const auto e : info.convectionVoidElementIdx)
215 std::cout << e <<
" ";
216 std:: cout <<
"||" << std::endl;
219 std::cout << std::endl;
222 for (
auto& entry : solidToVoidConnectionIds_)
224 removeDuplicates_(entry.second);
226 std::cout <<
"solid dof " << entry.first <<
" couples to " << entry.second.size() <<
" void dofs: " << std::endl;
227 for (
auto& conn : entry.second)
229 const auto& info = connectionInfo_[conn];
230 assert(entry.first == info.solidVertexIdx);
231 std::cout <<
"void vertex " << info.voidVertexIdx <<
" with elems ";
232 for (
const auto e : info.convectionVoidElementIdx)
233 std::cout << e <<
" ";
234 std:: cout <<
"||" << std::endl;
237 std::cout << std::endl;
244 {
return voidToSolidStencils_; }
247 {
return solidToVoidStencils_; }
250 {
return isCoupledVoidDof_; }
253 {
return isCoupledSolidDof_; }
259 using Iterator = ConnectionIterator<std::vector<std::size_t>>;
260 return Dune::IteratorRange<Iterator>(Iterator(ids.cbegin(),
connectionInfo()),
267 using Iterator = ConnectionIterator<std::vector<std::size_t>>;
268 return Dune::IteratorRange<Iterator>(Iterator(ids.cbegin(),
connectionInfo()),
273 {
return voidToSolidConnectionIds_; }
276 {
return solidToVoidConnectionIds_; }
279 {
return connectionInfo_; }
282 {
return voidHostToSubVertexIdxMap_; }
285 {
return solidHostToSubVertexIdxMap_; }
288 {
return voidHostToSubElementIdxMap_; }
291 {
return solidHostToSubElementIdxMap_; }
294 {
return hostGridElementIndexToGlobalId_; }
298 template<
class HostGr
idView,
class HostGr
idData>
299 std::vector<HostGridConnectionInfo> getConnectionInfo_(
const HostGridView& hostGridView,
300 const HostGridData& hostGridData)
303 std::size_t connectionGlobalId = 0;
305 for (
const auto& element : elements(hostGridView))
307 if (hostGridData.getParameter(element,
"ThroatDomainType") == 2)
309 const auto& vertex0 = element.template subEntity<1>(0);
310 const auto& vertex1 = element.template subEntity<1>(1);
312 HostGridConnectionInfo info;
313 info.hostGridElementIndex = hostGridView.indexSet().index(element);
314 info.connectionGlobalId = connectionGlobalId++;
315 info.voidVertexHostIdx = hostGridView.indexSet().index(vertex0);
316 info.solidVertexHostIdx = hostGridView.indexSet().index(vertex1);
318 if (hostGridData.getParameter(vertex0,
"PoreDomainType") == 1)
320 assert(hostGridData.getParameter(vertex1,
"PoreDomainType") == 0);
322 swap(info.voidVertexHostIdx, info.solidVertexHostIdx);
325 info.connectionArea = hostGridData.getParameter(element,
"ThroatCrossSectionalArea");
326 info.connectionLength = element.geometry().volume();
328 for (
const auto& intersection : intersections(hostGridView, element))
330 if (!intersection.neighbor())
333 const auto& outsideElement = intersection.outside();
336 if (hostGridData.getParameter(outsideElement,
"ThroatDomainType") == 2)
339 const auto outsideElementIdx = hostGridView.indexSet().index(outsideElement);
341 if (hostGridData.getParameter(outsideElement,
"ThroatDomainType") == 0)
342 info.voidElementHostIdx.push_back(outsideElementIdx);
344 info.solidElementHostIdx.push_back(outsideElementIdx);
346 std::array outsideDomainType = {-1, -1};
347 for (
int localVIdx = 0; localVIdx < 2; ++localVIdx)
349 const auto& outsideVertex = outsideElement.template subEntity<1>(localVIdx);
350 const auto outsideVertexIdx = hostGridView.indexSet().index(outsideVertex);
351 outsideDomainType[localVIdx] = hostGridData.getParameter(outsideVertex,
"PoreDomainType");
353 if (localVIdx == 1 && (outsideDomainType[1] != outsideDomainType[0]))
354 DUNE_THROW(Dune::IOError,
"Pore with hostIdx " << hostGridView.indexSet().index(outsideElement.template subEntity<1>(0))
355 <<
" has domain type " << outsideDomainType[0]
356 <<
", but pore with hostIdx " << outsideVertexIdx
357 <<
" has domain type " << outsideDomainType[1] <<
". Check your grid file");
359 if (outsideDomainType[localVIdx] == 0)
360 info.coupledVoidVertexHostIdx.push_back(outsideVertexIdx);
362 info.coupledSolidVertexHostIdx.push_back(outsideVertexIdx);
373 template<
class HostGr
idView,
class SubGr
idGeometry,
class Map>
374 void fillVertexMap_(
const HostGridView& hostGridView,
const SubGridGeometry& subGridGeometry, Map& map)
376 for (
const auto& vertex : vertices(subGridGeometry.gridView()))
378 const auto vIdxSub = subGridGeometry.vertexMapper().index(vertex);
379 const auto vIdxHost = hostGridView.indexSet().index(
vertex.impl().hostEntity());
380 map[vIdxHost] = vIdxSub;
384 template<
class HostGr
idView,
class SubGr
idGeometry,
class Map>
385 void fillElementMap_(
const HostGridView& hostGridView,
const SubGridGeometry& subGridGeometry, Map& map)
387 for (
const auto& element : elements(subGridGeometry.gridView()))
389 const auto eIdxSub = subGridGeometry.elementMapper().index(element);
390 const auto eIdxHost = hostGridView.indexSet().index(
element.impl().hostEntity());
391 map[eIdxHost] = eIdxSub;
396 void removeDuplicates_(std::vector<std::size_t>& stencil)
398 std::sort(stencil.begin(), stencil.end());
399 stencil.erase(std::unique(stencil.begin(), stencil.end()), stencil.end());
402 std::unordered_map<std::size_t, std::size_t> voidHostToSubVertexIdxMap_;
403 std::unordered_map<std::size_t, std::size_t> solidHostToSubVertexIdxMap_;
404 std::unordered_map<std::size_t, std::size_t> voidHostToSubElementIdxMap_;
405 std::unordered_map<std::size_t, std::size_t> solidHostToSubElementIdxMap_;
407 std::vector<bool> isCoupledVoidDof_;
408 std::vector<bool> isCoupledSolidDof_;
410 std::unordered_map<std::size_t, Stencil> voidToSolidStencils_;
411 std::unordered_map<std::size_t, Stencil> solidToVoidStencils_;
413 std::unordered_map<std::size_t, std::vector<std::size_t>> voidToSolidConnectionIds_;
414 std::unordered_map<std::size_t, std::vector<std::size_t>> solidToVoidConnectionIds_;
416 std::vector<SubGridConnectionInfo> connectionInfo_;
417 std::unordered_map<std::size_t, std::size_t> hostGridElementIndexToGlobalId_;