150 static const bool useCircleAverage =
getParam<bool>(
"MixedDimension.UseCircleAverage",
true);
153 const auto& bulkGridGeometry = this->
problem(bulkIdx).gridGeometry();
154 const auto& lowDimGridGeometry = this->
problem(lowDimIdx).gridGeometry();
155 const auto& bulkTree = bulkGridGeometry.boundingBoxTree();
160 std::cout <<
"Initializing the point sources..." << std::endl;
165 extendedSourceStencil_.stencil().clear();
175 const auto& lowDimProblem = this->
problem(lowDimIdx);
176 for (
const auto& is : intersections(this->
glue()))
179 const auto& lowDimElement = is.targetEntity(0);
180 const auto lowDimElementIdx = lowDimGridGeometry.elementMapper().index(lowDimElement);
183 const auto intersectionGeometry = is.geometry();
185 const auto& quad = Dune::QuadratureRules<Scalar, lowDimDim>::rule(intersectionGeometry.type(), order);
194 for (
auto&& qp : quad)
197 const auto globalPos = intersectionGeometry.global(qp.position());
203 if (bulkElementIndices.empty())
210 static const auto numIp =
getParam<int>(
"MixedDimension.NumCircleSegments");
211 const auto radius = lowDimProblem.spatialParams().radius(lowDimElementIdx);
212 const auto normal = intersectionGeometry.corner(1)-intersectionGeometry.corner(0);
213 const auto integrationElement = intersectionGeometry.integrationElement(qp.position())*2*M_PI*
radius/Scalar(numIp);
214 const auto qpweight = qp.weight()/(2*M_PI*
radius);
215 const auto circleAvgWeight = 2*M_PI*
radius/numIp;
218 std::vector<std::vector<std::size_t>> circleBulkElementIndices(circlePoints.size());
219 std::vector<Scalar> circleIpWeight; circleIpWeight.reserve(circlePoints.size());
220 std::vector<GridIndex<bulkIdx>> circleStencil; circleStencil.reserve(circlePoints.size());
222 std::vector<const std::vector<GridIndex<bulkIdx>>*> circleCornerIndices;
223 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
224 std::vector<ShapeValues> circleShapeValues;
227 for (
int k = 0; k < circlePoints.size(); ++k)
230 if (circleBulkElementIndices[k].empty())
233 const auto localCircleAvgWeight = circleAvgWeight / circleBulkElementIndices[k].size();
234 for (
const auto bulkElementIdx : circleBulkElementIndices[k])
236 circleStencil.push_back(bulkElementIdx);
237 circleIpWeight.push_back(localCircleAvgWeight);
240 if constexpr (isBox<bulkIdx>())
242 const auto bulkElement = bulkGridGeometry.element(bulkElementIdx);
243 circleCornerIndices.push_back(&(this->
vertexIndices(bulkIdx, bulkElementIdx)));
246 const auto bulkGeometry = bulkElement.geometry();
247 ShapeValues shapeValues;
248 this->
getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry, circlePoints[k], shapeValues);
249 circleShapeValues.emplace_back(std::move(shapeValues));
255 if constexpr (isBox<bulkIdx>())
258 for (
const auto& vertices : circleCornerIndices)
261 vertices->begin(), vertices->end());
268 circleStencil.begin(), circleStencil.end());
271 for (
int k = 0; k < circlePoints.size(); ++k)
273 const auto& circlePos = circlePoints[k];
276 if (circleBulkElementIndices[k].empty())
281 for (
const auto bulkElementIdx : circleBulkElementIndices[k])
285 this->
pointSources(bulkIdx).emplace_back(circlePos,
id, qpweight, integrationElement, bulkElementIdx);
286 this->
pointSources(bulkIdx).back().setEmbeddings(circleBulkElementIndices[k].size());
287 this->
pointSources(lowDimIdx).emplace_back(globalPos,
id, qpweight, integrationElement, lowDimElementIdx);
288 this->
pointSources(lowDimIdx).back().setEmbeddings(circleBulkElementIndices[k].size());
292 PointSourceData psData;
294 if constexpr (isBox<lowDimIdx>())
296 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
297 ShapeValues shapeValues;
298 this->
getShapeValues(lowDimIdx, lowDimGridGeometry, intersectionGeometry, globalPos, shapeValues);
299 psData.addLowDimInterpolation(shapeValues, this->
vertexIndices(lowDimIdx, lowDimElementIdx), lowDimElementIdx);
303 psData.addLowDimInterpolation(lowDimElementIdx);
307 if constexpr (isBox<bulkIdx>())
309 if (useCircleAverage)
310 psData.addCircleInterpolation(circleCornerIndices, circleShapeValues, circleIpWeight, circleStencil);
312 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
313 const auto bulkGeometry = bulkGridGeometry.element(bulkElementIdx).geometry();
314 ShapeValues shapeValues;
315 this->
getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry, circlePos, shapeValues);
316 psData.addBulkInterpolation(shapeValues, this->
vertexIndices(bulkIdx, bulkElementIdx), bulkElementIdx);
320 if (useCircleAverage)
321 psData.addCircleInterpolation(circleIpWeight, circleStencil);
323 psData.addBulkInterpolation(bulkElementIdx);
331 if constexpr (isBox<lowDimIdx>())
333 const auto& vertices = this->
vertexIndices(lowDimIdx, lowDimElementIdx);
335 vertices.begin(), vertices.end());
340 this->
couplingStencils(bulkIdx)[bulkElementIdx].push_back(lowDimElementIdx);
344 if (useCircleAverage)
346 if constexpr (isBox<bulkIdx>())
349 for (
const auto& vertices : circleCornerIndices)
351 extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
352 vertices->begin(), vertices->end());
358 extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
359 circleStencil.begin(), circleStencil.end());
368 for (
auto&& stencil : extendedSourceStencil_.stencil())
370 std::sort(stencil.second.begin(), stencil.second.end());
371 stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
374 if constexpr (isBox<bulkIdx>())
376 const auto& indices = this->
vertexIndices(bulkIdx, stencil.first);
377 stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
378 [&](
auto i){ return std::find(indices.begin(), indices.end(), i) != indices.end(); }),
379 stencil.second.end());
384 stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
385 [&](
auto i){ return i == stencil.first; }),
386 stencil.second.end());
391 using namespace Dune::Hybrid;
392 forEach(integralRange(Dune::index_constant<2>{}), [&](
const auto domainIdx)
396 std::sort(stencil.second.begin(), stencil.second.end());
397 stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
401 std::cout <<
"took " << watch.elapsed() <<
" seconds." << std::endl;