141 const auto& bulkGridGeometry = this->problem(bulkIdx).gridGeometry();
142 const auto& lowDimGridGeometry = this->problem(lowDimIdx).gridGeometry();
143 const auto& bulkTree = bulkGridGeometry.boundingBoxTree();
148 std::cout <<
"Initializing the point sources..." << std::endl;
153 extendedSourceStencil_.clear();
156 this->precomputeVertexIndices(bulkIdx);
157 this->precomputeVertexIndices(lowDimIdx);
163 const auto& lowDimProblem = this->problem(lowDimIdx);
164 for (
const auto& is : intersections(this->glue()))
167 const auto& lowDimElement = is.targetEntity(0);
168 const auto lowDimElementIdx = lowDimGridGeometry.elementMapper().index(lowDimElement);
171 const auto intersectionGeometry = is.geometry();
173 const auto& quad = Dune::QuadratureRules<Scalar, lowDimDim>::rule(intersectionGeometry.type(), order);
182 for (
auto&& qp : quad)
185 const auto globalPos = intersectionGeometry.global(qp.position());
191 if (bulkElementIndices.empty())
198 static const auto numIp =
getParam<int>(
"MixedDimension.NumCircleSegments");
199 const auto radius = lowDimProblem.spatialParams().radius(lowDimElementIdx);
200 const auto normal = intersectionGeometry.corner(1)-intersectionGeometry.corner(0);
201 const auto circleAvgWeight = 2*M_PI*radius/numIp;
202 const auto integrationElement = intersectionGeometry.integrationElement(qp.position());
203 const auto qpweight = qp.weight();
206 std::vector<Scalar> circleIpWeight; circleIpWeight.reserve(circlePoints.size());
207 std::vector<GridIndex<bulkIdx>> circleStencil; circleStencil.reserve(circlePoints.size());
210 std::vector<const std::vector<GridIndex<bulkIdx>>*> circleCornerIndices;
211 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
212 std::vector<ShapeValues> circleShapeValues;
215 int insideCirclePoints = 0;
216 for (
int k = 0; k < circlePoints.size(); ++k)
219 if (circleBulkElementIndices.empty())
222 ++insideCirclePoints;
223 const auto localCircleAvgWeight = circleAvgWeight / circleBulkElementIndices.size();
224 for (
const auto bulkElementIdx : circleBulkElementIndices)
226 circleStencil.push_back(bulkElementIdx);
227 circleIpWeight.push_back(localCircleAvgWeight);
230 if constexpr (isBox<bulkIdx>())
232 const auto bulkElement = bulkGridGeometry.element(bulkElementIdx);
233 circleCornerIndices.push_back(&(this->vertexIndices(bulkIdx, bulkElementIdx)));
236 const auto bulkGeometry = bulkElement.geometry();
237 ShapeValues shapeValues;
238 this->getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry, circlePoints[k], shapeValues);
239 circleShapeValues.emplace_back(std::move(shapeValues));
246 if (circleStencil.empty())
250 if constexpr (isBox<bulkIdx>())
253 for (
const auto& vertices : circleCornerIndices)
255 this->couplingStencils(lowDimIdx)[lowDimElementIdx].insert(this->couplingStencils(lowDimIdx)[lowDimElementIdx].end(),
256 vertices->begin(), vertices->end());
262 this->couplingStencils(lowDimIdx)[lowDimElementIdx].insert(this->couplingStencils(lowDimIdx)[lowDimElementIdx].end(),
263 circleStencil.begin(), circleStencil.end());
267 const auto surfaceFraction = Scalar(insideCirclePoints)/Scalar(circlePoints.size());
270 for (
auto bulkElementIdx : bulkElementIndices)
272 const auto id = this->idCounter_++;
274 this->pointSources(bulkIdx).emplace_back(globalPos,
id, qpweight, integrationElement*surfaceFraction, bulkElementIdx);
275 this->pointSources(bulkIdx).back().setEmbeddings(bulkElementIndices.size());
276 this->pointSources(lowDimIdx).emplace_back(globalPos,
id, qpweight, integrationElement*surfaceFraction, lowDimElementIdx);
277 this->pointSources(lowDimIdx).back().setEmbeddings(bulkElementIndices.size());
281 PointSourceData psData;
283 if constexpr (isBox<lowDimIdx>())
285 ShapeValues shapeValues;
286 this->getShapeValues(lowDimIdx, lowDimGridGeometry, intersectionGeometry, globalPos, shapeValues);
287 psData.addLowDimInterpolation(shapeValues, this->vertexIndices(lowDimIdx, lowDimElementIdx), lowDimElementIdx);
291 psData.addLowDimInterpolation(lowDimElementIdx);
295 if constexpr (isBox<bulkIdx>())
297 psData.addCircleInterpolation(circleCornerIndices, circleShapeValues, circleIpWeight, circleStencil);
299 const auto bulkGeometry = bulkGridGeometry.element(bulkElementIdx).geometry();
300 ShapeValues shapeValues;
301 this->getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry, globalPos, shapeValues);
302 psData.addBulkInterpolation(shapeValues, this->vertexIndices(bulkIdx, bulkElementIdx), bulkElementIdx);
306 psData.addCircleInterpolation(circleIpWeight, circleStencil);
307 psData.addBulkInterpolation(bulkElementIdx);
311 this->pointSourceData().emplace_back(std::move(psData));
314 const auto outsideGeometry = bulkGridGeometry.element(bulkElementIdx).geometry();
318 if constexpr (isBox<lowDimIdx>())
320 this->couplingStencils(bulkIdx)[bulkElementIdx].insert(this->couplingStencils(bulkIdx)[bulkElementIdx].end(),
321 this->vertexIndices(lowDimIdx, lowDimElementIdx).begin(),
322 this->vertexIndices(lowDimIdx, lowDimElementIdx).end());
327 this->couplingStencils(bulkIdx)[bulkElementIdx].push_back(lowDimElementIdx);
331 if constexpr (isBox<bulkIdx>())
334 for (
const auto& vertices : circleCornerIndices)
336 extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
337 vertices->begin(), vertices->end());
343 extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
344 circleStencil.begin(), circleStencil.end());
351 for (
auto&& stencil : extendedSourceStencil_.stencil())
353 std::sort(stencil.second.begin(), stencil.second.end());
354 stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
357 if constexpr (isBox<bulkIdx>())
359 const auto& indices = this->vertexIndices(bulkIdx, stencil.first);
360 stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
361 [&](
auto i){ return std::find(indices.begin(), indices.end(), i) != indices.end(); }),
362 stencil.second.end());
367 stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
368 [&](
auto i){ return i == stencil.first; }),
369 stencil.second.end());
374 using namespace Dune::Hybrid;
375 forEach(integralRange(Dune::index_constant<2>{}), [&](
const auto domainIdx)
377 for (
auto&& stencil : this->couplingStencils(domainIdx))
379 std::sort(stencil.second.begin(), stencil.second.end());
380 stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
384 std::cout <<
"took " << watch.elapsed() <<
" seconds." << std::endl;