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_;
Helper function to compute points on a circle.
Point source traits for average-based coupling modes.
Coupling manager for low-dimensional domains embedded in the bulk domain. Point sources on each integ...
Helper class to create (named and comparable) tagged types.
Defines the index types used for grid and local indices.
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.