50 void update(
const FreeFlowMomentumGridGeometry& ffMomentumGridGeometry,
51 const FreeFlowMassGridGeometry& ffMassGridGeometry,
52 const PoreNetworkGridGeometry& pnmGridGeometry)
55 resize_(ffMomentumGridGeometry, pnmGridGeometry);
57 std::cout <<
"Initializing the coupling map..." << std::endl;
59 auto ffFvGeometry =
localView(ffMomentumGridGeometry);
60 auto pnmFvGeometry =
localView(pnmGridGeometry);
62 using GlobalPosition =
typename FreeFlowMomentumGridGeometry::GridView::template Codim<0>::Entity::Geometry::GlobalCoordinate;
64 for (
const auto& pnmElement : elements(pnmGridGeometry.gridView()))
66 const auto pnmElementIdx = pnmGridGeometry.elementMapper().index(pnmElement);
67 pnmFvGeometry.bindElement(pnmElement);
68 for (
const auto& pnmScv : scvs(pnmFvGeometry))
71 if (!pnmGridGeometry.dofOnBoundary(pnmScv.dofIndex()))
75 const auto pnmPos = pnmScv.dofPosition();
76 const auto pnmDofIdx = pnmScv.dofIndex();
77 const auto& otherPNMScv = pnmFvGeometry.scv(1 - pnmScv.indexInElement());
78 const auto otherPNMScvDofIdx = otherPNMScv.dofIndex();
81 const auto directlyCoupledFreeFlowElements =
intersectingEntities(pnmPos, ffMomentumGridGeometry.boundingBoxTree());
82 if (directlyCoupledFreeFlowElements.empty())
85 isCoupledPNMDof_[pnmDofIdx] =
true;
90 const std::size_t couplingNormalDirectionIndex = [&]
92 using Key = std::pair<std::size_t, bool>;
93 std::map<Key, std::size_t> result;
94 for (
const auto eIdx : directlyCoupledFreeFlowElements)
96 for (
const auto& intersection : intersections(ffMomentumGridGeometry.gridView(), ffMomentumGridGeometry.element(eIdx)))
100 const auto&
normal = intersection.centerUnitOuterNormal();
109 if (directlyCoupledFreeFlowElements.size() == 1 && result.size() > 1)
110 DUNE_THROW(Dune::InvalidStateException,
"Pore may not intersect with faces of different orientation when coupled to only one element");
112 return std::max_element(result.begin(), result.end(), [](
const auto& x,
const auto& y) { return x.second < y.second;})->first.first;
115 using Scalar =
typename FreeFlowMomentumGridGeometry::GridView::ctype;
116 const Scalar couplingPoreRadius = pnmGridGeometry.poreInscribedRadius(pnmDofIdx);
117 GlobalPosition lowerLeft = pnmPos - GlobalPosition(couplingPoreRadius);
118 lowerLeft[couplingNormalDirectionIndex] = pnmPos[couplingNormalDirectionIndex];
119 GlobalPosition upperRight = pnmPos + GlobalPosition(couplingPoreRadius);
120 upperRight[couplingNormalDirectionIndex] = pnmPos[couplingNormalDirectionIndex];
122 auto axes = std::move(std::bitset<FreeFlowMomentumGridGeometry::Grid::dimensionworld>{}.set());
123 axes.set(couplingNormalDirectionIndex,
false);
125 using PoreIntersectionGeometryType = Dune::AxisAlignedCubeGeometry<Scalar,
126 FreeFlowMomentumGridGeometry::GridView::dimension-1,
127 FreeFlowMomentumGridGeometry::GridView::dimensionworld>;
129 PoreIntersectionGeometryType poreIntersectionGeometry(lowerLeft, upperRight, axes);
130 const auto allCoupledFreeFlowElements =
intersectingEntities(std::move(poreIntersectionGeometry), ffMomentumGridGeometry.boundingBoxTree());
133 for (
const auto& ffElementInfo : allCoupledFreeFlowElements)
135 const auto freeFlowElementIndex = ffElementInfo.second();
136 pnmElementToFreeFlowElementsMap_[pnmElementIdx].push_back(freeFlowElementIndex);
137 freeFlowElementToPNMElementMap_[freeFlowElementIndex] = pnmElementIdx;
139 pnmToFreeFlowMassStencils_[pnmElementIdx].push_back(freeFlowElementIndex);
140 freeFlowMassToPNMStencils_[freeFlowElementIndex].push_back(pnmDofIdx);
142 ffFvGeometry.bindElement(ffMomentumGridGeometry.element(freeFlowElementIndex));
143 const auto coupledFreeFlowMomentumDofIndices = coupledFFMomentumDofs_(ffFvGeometry, ffMassGridGeometry, pnmPos, couplingPoreRadius, couplingNormalDirectionIndex);
145 pnmToFreeFlowMomentumStencils_[pnmElementIdx].push_back(coupledFreeFlowMomentumDofIndices.coupledFrontalDof);
146 freeFlowMomentumToPNMStencils_[coupledFreeFlowMomentumDofIndices.coupledFrontalDof].push_back(pnmDofIdx);
147 freeFlowMomentumToPNMStencils_[coupledFreeFlowMomentumDofIndices.coupledFrontalDof].push_back(otherPNMScvDofIdx);
149 isCoupledFreeFlowMomentumDof_[coupledFreeFlowMomentumDofIndices.coupledFrontalDof] =
true;
150 isCoupledFreeFlowMomentumDofOnInterface_[coupledFreeFlowMomentumDofIndices.coupledFrontalDof] =
true;
153 for (
const auto ffDofIdx : coupledFreeFlowMomentumDofIndices.coupledLateralDofs)
155 freeFlowMomentumToPNMStencils_[ffDofIdx].push_back(pnmDofIdx);
156 freeFlowMomentumToPNMStencils_[ffDofIdx].push_back(otherPNMScvDofIdx);
157 isCoupledFreeFlowMomentumDof_[ffDofIdx] =
true;
163 std::cout <<
"took " << watch.elapsed() <<
" seconds." << std::endl;