62 void update(
const FreeFlowMomentumGridGeometry& ffMomentumGridGeometry,
63 const FreeFlowMassGridGeometry& ffMassGridGeometry,
64 const PoreNetworkGridGeometry& pnmGridGeometry)
67 resize_(ffMomentumGridGeometry, pnmGridGeometry);
69 std::cout <<
"Initializing the coupling map..." << std::endl;
71 auto ffFvGeometry =
localView(ffMomentumGridGeometry);
72 auto pnmFvGeometry =
localView(pnmGridGeometry);
74 using GlobalPosition =
typename FreeFlowMomentumGridGeometry::GridView::template Codim<0>::Entity::Geometry::GlobalCoordinate;
76 for (
const auto& pnmElement : elements(pnmGridGeometry.gridView()))
78 const auto pnmElementIdx = pnmGridGeometry.elementMapper().index(pnmElement);
79 pnmFvGeometry.bindElement(pnmElement);
80 for (
const auto& pnmScv : scvs(pnmFvGeometry))
83 if (!pnmGridGeometry.dofOnBoundary(pnmScv.dofIndex()))
87 const auto pnmPos = pnmScv.dofPosition();
88 const auto pnmDofIdx = pnmScv.dofIndex();
89 const auto& otherPNMScv = pnmFvGeometry.scv(1 - pnmScv.indexInElement());
90 const auto otherPNMScvDofIdx = otherPNMScv.dofIndex();
93 const auto directlyCoupledFreeFlowElements =
intersectingEntities(pnmPos, ffMomentumGridGeometry.boundingBoxTree());
94 if (directlyCoupledFreeFlowElements.empty())
97 isCoupledPNMDof_[pnmDofIdx] =
true;
102 const std::size_t couplingNormalDirectionIndex = [&]
104 using Key = std::pair<std::size_t, bool>;
105 std::map<Key, std::size_t> result;
106 for (
const auto eIdx : directlyCoupledFreeFlowElements)
108 for (
const auto& intersection : intersections(ffMomentumGridGeometry.gridView(), ffMomentumGridGeometry.element(eIdx)))
112 const auto&
normal = intersection.centerUnitOuterNormal();
121 if (directlyCoupledFreeFlowElements.size() == 1 && result.size() > 1)
122 DUNE_THROW(Dune::InvalidStateException,
"Pore may not intersect with faces of different orientation when coupled to only one element");
124 return std::max_element(result.begin(), result.end(), [](
const auto& x,
const auto& y) { return x.second < y.second;})->first.first;
127 using Scalar =
typename FreeFlowMomentumGridGeometry::GridView::ctype;
128 const Scalar couplingPoreRadius = pnmGridGeometry.poreInscribedRadius(pnmDofIdx);
129 GlobalPosition lowerLeft = pnmPos - GlobalPosition(couplingPoreRadius);
130 lowerLeft[couplingNormalDirectionIndex] = pnmPos[couplingNormalDirectionIndex];
131 GlobalPosition upperRight = pnmPos + GlobalPosition(couplingPoreRadius);
132 upperRight[couplingNormalDirectionIndex] = pnmPos[couplingNormalDirectionIndex];
134 auto axes = std::move(std::bitset<FreeFlowMomentumGridGeometry::Grid::dimensionworld>{}.set());
135 axes.set(couplingNormalDirectionIndex,
false);
137 using PoreIntersectionGeometryType = Dune::AxisAlignedCubeGeometry<Scalar,
138 FreeFlowMomentumGridGeometry::GridView::dimension-1,
139 FreeFlowMomentumGridGeometry::GridView::dimensionworld>;
141 PoreIntersectionGeometryType poreIntersectionGeometry(lowerLeft, upperRight, axes);
142 const auto allCoupledFreeFlowElements =
intersectingEntities(std::move(poreIntersectionGeometry), ffMomentumGridGeometry.boundingBoxTree());
145 for (
const auto& ffElementInfo : allCoupledFreeFlowElements)
147 const auto freeFlowElementIndex = ffElementInfo.second();
148 pnmElementToFreeFlowElementsMap_[pnmElementIdx].push_back(freeFlowElementIndex);
149 freeFlowElementToPNMElementMap_[freeFlowElementIndex] = pnmElementIdx;
151 pnmToFreeFlowMassStencils_[pnmElementIdx].push_back(freeFlowElementIndex);
152 freeFlowMassToPNMStencils_[freeFlowElementIndex].push_back(pnmDofIdx);
154 ffFvGeometry.bindElement(ffMomentumGridGeometry.element(freeFlowElementIndex));
155 const auto coupledFreeFlowMomentumDofIndices = coupledFFMomentumDofs_(ffFvGeometry, ffMassGridGeometry, pnmPos, couplingPoreRadius, couplingNormalDirectionIndex);
157 pnmToFreeFlowMomentumStencils_[pnmElementIdx].push_back(coupledFreeFlowMomentumDofIndices.coupledFrontalDof);
158 freeFlowMomentumToPNMStencils_[coupledFreeFlowMomentumDofIndices.coupledFrontalDof].push_back(pnmDofIdx);
159 freeFlowMomentumToPNMStencils_[coupledFreeFlowMomentumDofIndices.coupledFrontalDof].push_back(otherPNMScvDofIdx);
161 isCoupledFreeFlowMomentumDof_[coupledFreeFlowMomentumDofIndices.coupledFrontalDof] =
true;
162 isCoupledFreeFlowMomentumDofOnInterface_[coupledFreeFlowMomentumDofIndices.coupledFrontalDof] =
true;
165 for (
const auto ffDofIdx : coupledFreeFlowMomentumDofIndices.coupledLateralDofs)
167 freeFlowMomentumToPNMStencils_[ffDofIdx].push_back(pnmDofIdx);
168 freeFlowMomentumToPNMStencils_[ffDofIdx].push_back(otherPNMScvDofIdx);
169 isCoupledFreeFlowMomentumDof_[ffDofIdx] =
true;
175 std::cout <<
"took " << watch.elapsed() <<
" seconds." << std::endl;