13#ifndef DUMUX_MULTIDOMAIN_EMBEDDED_COUPLINGMANAGER_1D3D_SURFACE_HH
14#define DUMUX_MULTIDOMAIN_EMBEDDED_COUPLINGMANAGER_1D3D_SURFACE_HH
18#include <dune/common/timer.hh>
19#include <dune/geometry/quadraturerules.hh>
32namespace Embedded1d3dCouplingMode {
34 static std::string
name() {
return "surface"; }
41template<
class MDTraits,
class CouplingMode>
42class Embedded1d3dCouplingManager;
51template<
class MDTraits>
54 CircleAveragePointSourceTraits<MDTraits>>
58 using Scalar =
typename MDTraits::Scalar;
59 using PointSourceData =
typename ParentType::PointSourceTraits::PointSourceData;
61 static constexpr auto bulkIdx =
typename MDTraits::template SubDomain<0>::Index();
62 static constexpr auto lowDimIdx =
typename MDTraits::template SubDomain<1>::Index();
65 template<std::
size_t id>
using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
68 template<std::
size_t id>
using GridView =
typename GridGeometry<id>::GridView;
69 template<std::
size_t id>
using Element =
typename GridView<id>::template Codim<0>::Entity;
72 using GlobalPosition =
typename Element<bulkIdx>::Geometry::GlobalCoordinate;
74 template<std::
size_t id>
75 static constexpr bool isBox()
79 bulkDim = GridView<bulkIdx>::dimension,
80 lowDimDim = GridView<lowDimIdx>::dimension,
81 dimWorld = GridView<bulkIdx>::dimensionworld
86 using ParentType::ParentType;
94 template<std::
size_t id,
class JacobianPattern>
97 extendedSourceStencil_.extendJacobianPattern(*
this, domainI, pattern);
107 template<std::
size_t i,
class LocalAssemblerI,
class JacobianMatrixDiagBlock,
class Gr
idVariables>
109 const LocalAssemblerI& localAssemblerI,
110 const typename LocalAssemblerI::LocalResidual::ElementResidualVector&,
111 JacobianMatrixDiagBlock& A,
112 GridVariables& gridVariables)
114 extendedSourceStencil_.evalAdditionalDomainDerivatives(*
this, domainI, localAssemblerI, A, gridVariables);
129 static const bool useCircleAverage = getParam<bool>(
"MixedDimension.UseCircleAverage",
true);
132 const auto& bulkGridGeometry = this->problem(bulkIdx).gridGeometry();
133 const auto& lowDimGridGeometry = this->problem(lowDimIdx).gridGeometry();
134 const auto& bulkTree = bulkGridGeometry.boundingBoxTree();
139 std::cout <<
"Initializing the point sources..." << std::endl;
144 extendedSourceStencil_.stencil().clear();
147 this->precomputeVertexIndices(bulkIdx);
148 this->precomputeVertexIndices(lowDimIdx);
154 const auto& lowDimProblem = this->problem(lowDimIdx);
155 for (
const auto& is : intersections(this->glue()))
158 const auto& lowDimElement = is.targetEntity(0);
159 const auto lowDimElementIdx = lowDimGridGeometry.elementMapper().index(lowDimElement);
162 const auto intersectionGeometry = is.geometry();
164 const auto& quad = Dune::QuadratureRules<Scalar, lowDimDim>::rule(intersectionGeometry.type(), order);
173 for (
auto&& qp : quad)
176 const auto globalPos = intersectionGeometry.global(qp.position());
182 if (bulkElementIndices.empty())
189 static const auto numIp = getParam<int>(
"MixedDimension.NumCircleSegments");
190 const auto radius = lowDimProblem.spatialParams().radius(lowDimElementIdx);
191 const auto normal = intersectionGeometry.corner(1)-intersectionGeometry.corner(0);
192 const auto integrationElement = intersectionGeometry.integrationElement(qp.position())*2*M_PI*radius/Scalar(numIp);
193 const auto qpweight = qp.weight()/(2*M_PI*radius);
194 const auto circleAvgWeight = 2*M_PI*radius/numIp;
197 std::vector<std::vector<std::size_t>> circleBulkElementIndices(
circlePoints.size());
198 std::vector<Scalar> circleIpWeight; circleIpWeight.reserve(
circlePoints.size());
199 std::vector<GridIndex<bulkIdx>> circleStencil; circleStencil.reserve(
circlePoints.size());
201 std::vector<const std::vector<GridIndex<bulkIdx>>*> circleCornerIndices;
202 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
203 std::vector<ShapeValues> circleShapeValues;
209 if (circleBulkElementIndices[k].empty())
212 const auto localCircleAvgWeight = circleAvgWeight / circleBulkElementIndices[k].size();
213 for (
const auto bulkElementIdx : circleBulkElementIndices[k])
215 circleStencil.push_back(bulkElementIdx);
216 circleIpWeight.push_back(localCircleAvgWeight);
219 if constexpr (isBox<bulkIdx>())
221 const auto bulkElement = bulkGridGeometry.element(bulkElementIdx);
222 circleCornerIndices.push_back(&(this->vertexIndices(bulkIdx, bulkElementIdx)));
225 const auto bulkGeometry = bulkElement.geometry();
226 ShapeValues shapeValues;
227 this->getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry,
circlePoints[k], shapeValues);
228 circleShapeValues.emplace_back(std::move(shapeValues));
234 if constexpr (isBox<bulkIdx>())
237 for (
const auto& vertices : circleCornerIndices)
239 this->couplingStencils(lowDimIdx)[lowDimElementIdx].insert(this->couplingStencils(lowDimIdx)[lowDimElementIdx].end(),
240 vertices->begin(), vertices->end());
246 this->couplingStencils(lowDimIdx)[lowDimElementIdx].insert(this->couplingStencils(lowDimIdx)[lowDimElementIdx].end(),
247 circleStencil.begin(), circleStencil.end());
255 if (circleBulkElementIndices[k].empty())
260 for (
const auto bulkElementIdx : circleBulkElementIndices[k])
262 const auto id = this->idCounter_++;
264 this->pointSources(bulkIdx).emplace_back(circlePos,
id, qpweight, integrationElement, bulkElementIdx);
265 this->pointSources(bulkIdx).back().setEmbeddings(circleBulkElementIndices[k].size());
266 this->pointSources(lowDimIdx).emplace_back(globalPos,
id, qpweight, integrationElement, lowDimElementIdx);
267 this->pointSources(lowDimIdx).back().setEmbeddings(circleBulkElementIndices[k].size());
271 PointSourceData psData;
273 if constexpr (isBox<lowDimIdx>())
275 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
276 ShapeValues shapeValues;
277 this->getShapeValues(lowDimIdx, lowDimGridGeometry, lowDimElement.geometry(), globalPos, shapeValues);
278 psData.addLowDimInterpolation(shapeValues, this->vertexIndices(lowDimIdx, lowDimElementIdx), lowDimElementIdx);
282 psData.addLowDimInterpolation(lowDimElementIdx);
286 if constexpr (isBox<bulkIdx>())
288 if (useCircleAverage)
289 psData.addCircleInterpolation(circleCornerIndices, circleShapeValues, circleIpWeight, circleStencil);
291 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
292 const auto bulkGeometry = bulkGridGeometry.element(bulkElementIdx).geometry();
293 ShapeValues shapeValues;
294 this->getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry, circlePos, shapeValues);
295 psData.addBulkInterpolation(shapeValues, this->vertexIndices(bulkIdx, bulkElementIdx), bulkElementIdx);
299 if (useCircleAverage)
300 psData.addCircleInterpolation(circleIpWeight, circleStencil);
302 psData.addBulkInterpolation(bulkElementIdx);
306 this->pointSourceData().emplace_back(std::move(psData));
310 if constexpr (isBox<lowDimIdx>())
312 const auto& vertices = this->vertexIndices(lowDimIdx, lowDimElementIdx);
313 this->couplingStencils(bulkIdx)[bulkElementIdx].insert(this->couplingStencils(bulkIdx)[bulkElementIdx].end(),
314 vertices.begin(), vertices.end());
319 this->couplingStencils(bulkIdx)[bulkElementIdx].push_back(lowDimElementIdx);
323 if (useCircleAverage)
325 if constexpr (isBox<bulkIdx>())
328 for (
const auto& vertices : circleCornerIndices)
330 extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
331 vertices->begin(), vertices->end());
337 extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
338 circleStencil.begin(), circleStencil.end());
347 for (
auto&& stencil : extendedSourceStencil_.stencil())
349 std::sort(stencil.second.begin(), stencil.second.end());
350 stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
353 if constexpr (isBox<bulkIdx>())
355 const auto& indices = this->vertexIndices(bulkIdx, stencil.first);
356 stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
357 [&](
auto i){ return std::find(indices.begin(), indices.end(), i) != indices.end(); }),
358 stencil.second.end());
363 stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
364 [&](
auto i){ return i == stencil.first; }),
365 stencil.second.end());
370 using namespace Dune::Hybrid;
371 forEach(integralRange(Dune::index_constant<2>{}), [&](
const auto domainIdx)
373 for (
auto&& stencil : this->couplingStencils(domainIdx))
375 std::sort(stencil.second.begin(), stencil.second.end());
376 stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
380 std::cout <<
"took " << watch.elapsed() <<
" seconds." << std::endl;
387 const typename ParentType::template CouplingStencils<bulkIdx>::mapped_type&
390 const auto& sourceStencils = extendedSourceStencil_.stencil();
391 if (
auto stencil = sourceStencils.find(eIdx); stencil != sourceStencils.end())
392 return stencil->second;
394 return this->emptyStencil(bulkIdx);
402 std::vector<Scalar> lowDimVolumeInBulkElement_;
406template<
class MDTraits>
408:
public std::true_type {};
Point source traits for average-based coupling modes.
Helper function to compute points on a circle.
Manages the coupling between bulk elements and lower dimensional elements Point sources on each integ...
Definition: couplingmanager1d3d_surface.hh:55
void computePointSourceData(std::size_t order=1, bool verbose=false)
Definition: couplingmanager1d3d_surface.hh:126
void evalAdditionalDomainDerivatives(Dune::index_constant< i > domainI, const LocalAssemblerI &localAssemblerI, const typename LocalAssemblerI::LocalResidual::ElementResidualVector &, JacobianMatrixDiagBlock &A, GridVariables &gridVariables)
evaluate additional derivatives of the element residual of a domain with respect to dofs in the same ...
Definition: couplingmanager1d3d_surface.hh:108
void extendJacobianPattern(Dune::index_constant< id > domainI, JacobianPattern &pattern) const
extend the jacobian pattern of the diagonal block of domain i by those entries that are not already i...
Definition: couplingmanager1d3d_surface.hh:95
const ParentType::template CouplingStencils< bulkIdx >::mapped_type & extendedSourceStencil(std::size_t eIdx) const
Extended source stencil (for the bulk domain)
Definition: couplingmanager1d3d_surface.hh:388
Manages the coupling between bulk elements and lower dimensional elements Point sources on each integ...
Definition: couplingmanager1d3dbase.hh:35
Manages the coupling between bulk elements and lower dimensional elements Point sources on each integ...
Definition: couplingmanager1d3d.hh:24
A class managing an extended source stencil.
Definition: embedded/extendedsourcestencil.hh:36
Defines all properties used in Dumux.
Coupling manager for low-dimensional domains embedded in the bulk domain.
Extended source stencil helper class for coupling managers.
void circlePoints(std::vector< GlobalPosition > &points, const std::vector< Scalar > &sincos, const GlobalPosition ¢er, const GlobalPosition &normal, const Scalar radius)
Definition: circlepoints.hh:38
Vector normal(const Vector &v)
Create a vector normal to the given one (v is expected to be non-zero)
Definition: normal.hh:26
std::vector< std::size_t > intersectingEntities(const Dune::FieldVector< ctype, dimworld > &point, const BoundingBoxTree< EntitySet > &tree, bool isCartesianGrid=false)
Compute all intersections between entities and a point.
Definition: intersectingentities.hh:102
typename GetProp< TypeTag, Property >::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:296
constexpr Box box
Definition: method.hh:147
constexpr Surface surface
Definition: couplingmanager1d3d_surface.hh:37
Type trait that is specialized for coupling manager supporting multithreaded assembly.
Definition: multistagemultidomainfvassembler.hh:78
Definition: couplingmanager1d3d_surface.hh:33
static std::string name()
Definition: couplingmanager1d3d_surface.hh:34
Structure to define the index types used for grid and local indices.
Definition: indextraits.hh:26
Helper class to create (named and comparable) tagged types Tags any given type. The tagged type is eq...
Definition: tag.hh:30
Helper class to create (named and comparable) tagged types.