25#ifndef DUMUX_MULTIDOMAIN_EMBEDDED_COUPLINGMANAGER_1D3D_SURFACE_HH
26#define DUMUX_MULTIDOMAIN_EMBEDDED_COUPLINGMANAGER_1D3D_SURFACE_HH
30#include <dune/common/timer.hh>
31#include <dune/geometry/quadraturerules.hh>
43namespace Embedded1d3dCouplingMode {
45 static std::string
name() {
return "surface"; }
47 [[deprecated(
"Comparison with enum is deprecated. Removed after 3.3. Use tags.")]]
49 [[deprecated(
"Comparison with enum is deprecated. Removed after 3.3. Use tags.")]]
51 [[deprecated(
"Comparison with enum is deprecated. Removed after 3.3. Use tags.")]]
53 [[deprecated(
"Comparison with enum is deprecated. Removed after 3.3. Use tags.")]]
61template<
class MDTraits,
class CouplingMode>
62class Embedded1d3dCouplingManager;
71template<
class MDTraits>
74 CircleAveragePointSourceTraits<MDTraits>>
78 using Scalar =
typename MDTraits::Scalar;
79 using SolutionVector =
typename MDTraits::SolutionVector;
80 using PointSourceData =
typename ParentType::PointSourceTraits::PointSourceData;
82 static constexpr auto bulkIdx =
typename MDTraits::template SubDomain<0>::Index();
83 static constexpr auto lowDimIdx =
typename MDTraits::template SubDomain<1>::Index();
86 template<std::
size_t id>
using SubDomainTypeTag =
typename MDTraits::template SubDomain<id>::TypeTag;
89 template<std::
size_t id>
using GridView =
typename GridGeometry<id>::GridView;
90 template<std::
size_t id>
using Element =
typename GridView<id>::template Codim<0>::Entity;
93 using GlobalPosition =
typename Element<bulkIdx>::Geometry::GlobalCoordinate;
95 template<std::
size_t id>
96 static constexpr bool isBox()
100 bulkDim = GridView<bulkIdx>::dimension,
101 lowDimDim = GridView<lowDimIdx>::dimension,
102 dimWorld = GridView<bulkIdx>::dimensionworld
107 using ParentType::ParentType;
109 void init(std::shared_ptr<Problem<bulkIdx>> bulkProblem,
110 std::shared_ptr<Problem<lowDimIdx>> lowDimProblem,
111 const SolutionVector& curSol)
113 ParentType::init(bulkProblem, lowDimProblem, curSol);
114 computeLowDimVolumeFractions();
123 template<std::
size_t id,
class JacobianPattern>
126 extendedSourceStencil_.extendJacobianPattern(*
this, domainI, pattern);
136 template<std::
size_t i,
class LocalAssemblerI,
class JacobianMatrixDiagBlock,
class Gr
idVariables>
138 const LocalAssemblerI& localAssemblerI,
139 const typename LocalAssemblerI::LocalResidual::ElementResidualVector&,
140 JacobianMatrixDiagBlock& A,
141 GridVariables& gridVariables)
143 extendedSourceStencil_.evalAdditionalDomainDerivatives(*
this, domainI, localAssemblerI, this->curSol(), A, gridVariables);
158 static const bool useCircleAverage = getParam<bool>(
"MixedDimension.UseCircleAverage",
true);
161 const auto& bulkGridGeometry = this->problem(bulkIdx).gridGeometry();
162 const auto& lowDimGridGeometry = this->problem(lowDimIdx).gridGeometry();
163 const auto& bulkTree = bulkGridGeometry.boundingBoxTree();
168 std::cout <<
"Initializing the point sources..." << std::endl;
173 extendedSourceStencil_.stencil().clear();
176 this->precomputeVertexIndices(bulkIdx);
177 this->precomputeVertexIndices(lowDimIdx);
183 const auto& lowDimProblem = this->problem(lowDimIdx);
184 for (
const auto& is : intersections(this->glue()))
187 const auto& lowDimElement = is.targetEntity(0);
188 const auto lowDimElementIdx = lowDimGridGeometry.elementMapper().index(lowDimElement);
191 const auto intersectionGeometry = is.geometry();
193 const auto& quad = Dune::QuadratureRules<Scalar, lowDimDim>::rule(intersectionGeometry.type(), order);
202 for (
auto&& qp : quad)
205 const auto globalPos = intersectionGeometry.global(qp.position());
211 if (bulkElementIndices.empty())
218 static const auto numIp = getParam<int>(
"MixedDimension.NumCircleSegments");
219 const auto radius = lowDimProblem.spatialParams().radius(lowDimElementIdx);
220 const auto normal = intersectionGeometry.corner(1)-intersectionGeometry.corner(0);
221 const auto integrationElement = intersectionGeometry.integrationElement(qp.position())*2*M_PI*radius/Scalar(numIp);
222 const auto qpweight = qp.weight()/(2*M_PI*radius);
223 const auto circleAvgWeight = 2*M_PI*radius/numIp;
226 std::vector<std::vector<std::size_t>> circleBulkElementIndices(
circlePoints.size());
227 std::vector<Scalar> circleIpWeight; circleIpWeight.reserve(
circlePoints.size());
228 std::vector<GridIndex<bulkIdx>> circleStencil; circleStencil.reserve(
circlePoints.size());
230 std::vector<const std::vector<GridIndex<bulkIdx>>*> circleCornerIndices;
231 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
232 std::vector<ShapeValues> circleShapeValues;
238 if (circleBulkElementIndices[k].empty())
241 const auto localCircleAvgWeight = circleAvgWeight / circleBulkElementIndices[k].size();
242 for (
const auto bulkElementIdx : circleBulkElementIndices[k])
244 circleStencil.push_back(bulkElementIdx);
245 circleIpWeight.push_back(localCircleAvgWeight);
248 if constexpr (isBox<bulkIdx>())
250 const auto bulkElement = bulkGridGeometry.element(bulkElementIdx);
251 circleCornerIndices.push_back(&(this->vertexIndices(bulkIdx, bulkElementIdx)));
254 const auto bulkGeometry = bulkElement.geometry();
255 ShapeValues shapeValues;
256 this->getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry,
circlePoints[k], shapeValues);
257 circleShapeValues.emplace_back(std::move(shapeValues));
263 if constexpr (isBox<bulkIdx>())
266 for (
const auto& vertices : circleCornerIndices)
268 this->couplingStencils(lowDimIdx)[lowDimElementIdx].insert(this->couplingStencils(lowDimIdx)[lowDimElementIdx].end(),
269 vertices->begin(), vertices->end());
275 this->couplingStencils(lowDimIdx)[lowDimElementIdx].insert(this->couplingStencils(lowDimIdx)[lowDimElementIdx].end(),
276 circleStencil.begin(), circleStencil.end());
284 if (circleBulkElementIndices[k].empty())
289 for (
const auto bulkElementIdx : circleBulkElementIndices[k])
291 const auto id = this->idCounter_++;
293 this->pointSources(bulkIdx).emplace_back(circlePos,
id, qpweight, integrationElement, bulkElementIdx);
294 this->pointSources(bulkIdx).back().setEmbeddings(circleBulkElementIndices[k].size());
295 this->pointSources(lowDimIdx).emplace_back(globalPos,
id, qpweight, integrationElement, lowDimElementIdx);
296 this->pointSources(lowDimIdx).back().setEmbeddings(circleBulkElementIndices[k].size());
300 PointSourceData psData;
302 if constexpr (isBox<lowDimIdx>())
304 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
305 ShapeValues shapeValues;
306 this->getShapeValues(lowDimIdx, lowDimGridGeometry, intersectionGeometry, globalPos, shapeValues);
307 psData.addLowDimInterpolation(shapeValues, this->vertexIndices(lowDimIdx, lowDimElementIdx), lowDimElementIdx);
311 psData.addLowDimInterpolation(lowDimElementIdx);
315 if constexpr (isBox<bulkIdx>())
317 if (useCircleAverage)
318 psData.addCircleInterpolation(circleCornerIndices, circleShapeValues, circleIpWeight, circleStencil);
320 using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
321 const auto bulkGeometry = bulkGridGeometry.element(bulkElementIdx).geometry();
322 ShapeValues shapeValues;
323 this->getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry, circlePos, shapeValues);
324 psData.addBulkInterpolation(shapeValues, this->vertexIndices(bulkIdx, bulkElementIdx), bulkElementIdx);
328 if (useCircleAverage)
329 psData.addCircleInterpolation(circleIpWeight, circleStencil);
331 psData.addBulkInterpolation(bulkElementIdx);
335 this->pointSourceData().emplace_back(std::move(psData));
339 if constexpr (isBox<lowDimIdx>())
341 const auto& vertices = this->vertexIndices(lowDimIdx, lowDimElementIdx);
342 this->couplingStencils(bulkIdx)[bulkElementIdx].insert(this->couplingStencils(bulkIdx)[bulkElementIdx].end(),
343 vertices.begin(), vertices.end());
348 this->couplingStencils(bulkIdx)[bulkElementIdx].push_back(lowDimElementIdx);
352 if (useCircleAverage)
354 if constexpr (isBox<bulkIdx>())
357 for (
const auto& vertices : circleCornerIndices)
359 extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
360 vertices->begin(), vertices->end());
366 extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
367 circleStencil.begin(), circleStencil.end());
376 for (
auto&& stencil : extendedSourceStencil_.stencil())
378 std::sort(stencil.second.begin(), stencil.second.end());
379 stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
382 if constexpr (isBox<bulkIdx>())
384 const auto& indices = this->vertexIndices(bulkIdx, stencil.first);
385 stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
386 [&](
auto i){ return std::find(indices.begin(), indices.end(), i) != indices.end(); }),
387 stencil.second.end());
392 stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
393 [&](
auto i){ return i == stencil.first; }),
394 stencil.second.end());
399 using namespace Dune::Hybrid;
400 forEach(integralRange(Dune::index_constant<2>{}), [&](
const auto domainIdx)
402 for (
auto&& stencil : this->couplingStencils(domainIdx))
404 std::sort(stencil.second.begin(), stencil.second.end());
405 stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
409 std::cout <<
"took " << watch.elapsed() <<
" seconds." << std::endl;
416 lowDimVolumeInBulkElement_.resize(this->gridView(bulkIdx).size(0));
418 const auto& lowDimGridGeometry = this->problem(lowDimIdx).gridGeometry();
419 const auto& bulkGridGeometry = this->problem(bulkIdx).gridGeometry();
422 for (
const auto& is : intersections(this->glue()))
425 const auto& inside = is.targetEntity(0);
426 const auto intersectionGeometry = is.geometry();
427 const auto lowDimElementIdx = lowDimGridGeometry.elementMapper().index(inside);
430 const auto radius = this->problem(lowDimIdx).spatialParams().radius(lowDimElementIdx);
431 for (
int outsideIdx = 0; outsideIdx < is.numDomainNeighbors(); ++outsideIdx)
433 const auto& outside = is.domainEntity(outsideIdx);
434 const auto bulkElementIdx = bulkGridGeometry.elementMapper().index(outside);
435 lowDimVolumeInBulkElement_[bulkElementIdx] += intersectionGeometry.volume()*M_PI*radius*radius;
448 const auto& data = this->pointSourceData()[id];
449 return this->problem(lowDimIdx).spatialParams().radius(data.lowDimElementIdx());
456 const auto eIdx = this->problem(bulkIdx).gridGeometry().elementMapper().index(element);
457 return lowDimVolumeInBulkElement_[eIdx];
464 const auto totalVolume = element.geometry().volume();
465 return lowDimVolume(element) / totalVolume;
475 std::vector<Scalar> lowDimVolumeInBulkElement_;
Defines the index types used for grid and local indices.
Helper class to create (named and comparable) tagged types.
Point source traits for average-based coupling modes.
Helper function to compute points on a circle.
Coupling manager for low-dimensional domains embedded in the bulk domain. Point sources on each integ...
Vector normal(const Vector &v)
Create a vector normal to the given one (v is expected to be non-zero)
Definition: geometry/normal.hh:36
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: geometry/intersectingentities.hh:100
EmbeddedCouplingMode
The coupling mode.
Definition: couplingmanager1d3d.hh:44
void circlePoints(std::vector< GlobalPosition > &points, const std::vector< Scalar > &sincos, const GlobalPosition ¢er, const GlobalPosition &normal, const Scalar radius)
Definition: circlepoints.hh:50
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:149
constexpr Surface surface
Definition: couplingmanager1d3d_surface.hh:57
Struture to define the index types used for grid and local indices.
Definition: indextraits.hh:38
Property to specify the type of a problem which has to be solved.
Definition: common/properties.hh:57
Definition: common/properties.hh:101
Helper class to create (named and comparable) tagged types Tags any given type. The tagged type is eq...
Definition: tag.hh:42
Manages the coupling between bulk elements and lower dimensional elements Point sources on each integ...
Definition: couplingmanager1d3d.hh:36
Definition: couplingmanager1d3d_surface.hh:44
friend constexpr bool operator==(Surface, EmbeddedCouplingMode m)
Definition: couplingmanager1d3d_surface.hh:48
friend constexpr bool operator!=(EmbeddedCouplingMode m, Surface)
Definition: couplingmanager1d3d_surface.hh:54
static std::string name()
Definition: couplingmanager1d3d_surface.hh:45
friend constexpr bool operator!=(Surface, EmbeddedCouplingMode m)
Definition: couplingmanager1d3d_surface.hh:52
friend constexpr bool operator==(EmbeddedCouplingMode m, Surface)
Definition: couplingmanager1d3d_surface.hh:50
Manages the coupling between bulk elements and lower dimensional elements Point sources on each integ...
Definition: couplingmanager1d3d_surface.hh:75
void computePointSourceData(std::size_t order=1, bool verbose=false)
Definition: couplingmanager1d3d_surface.hh:155
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:137
Scalar lowDimVolume(const Element< bulkIdx > &element) const
The volume the lower dimensional domain occupies in the bulk domain element.
Definition: couplingmanager1d3d_surface.hh:454
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:124
void computeLowDimVolumeFractions()
Compute the low dim volume fraction in the bulk domain cells.
Definition: couplingmanager1d3d_surface.hh:413
Scalar radius(std::size_t id) const
Methods to be accessed by the subproblems.
Definition: couplingmanager1d3d_surface.hh:446
Scalar lowDimVolumeFraction(const Element< bulkIdx > &element) const
The volume fraction the lower dimensional domain occupies in the bulk domain element.
Definition: couplingmanager1d3d_surface.hh:462
void init(std::shared_ptr< Problem< bulkIdx > > bulkProblem, std::shared_ptr< Problem< lowDimIdx > > lowDimProblem, const SolutionVector &curSol)
Definition: couplingmanager1d3d_surface.hh:109
Manages the coupling between bulk elements and lower dimensional elements Point sources on each integ...
Definition: couplingmanagerbase.hh:78
A class managing an extended source stencil.
Definition: extendedsourcestencil.hh:46
Declares all properties used in Dumux.