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> 
   34    static std::string 
name() { 
return "surface"; }
 
 
   41template<
class MDTraits, 
class CouplingMode>
 
   42class Embedded1d3dCouplingManager;
 
   51template<
class MDTraits>
 
   52class Embedded1d3dCouplingManager<MDTraits, Embedded1d3dCouplingMode::Surface>
 
   53: 
public EmbeddedCouplingManagerBase<MDTraits, Embedded1d3dCouplingManager<MDTraits, Embedded1d3dCouplingMode::Surface>,
 
   54                                     CircleAveragePointSourceTraits<MDTraits>>
 
   56    using ThisType = Embedded1d3dCouplingManager<MDTraits, Embedded1d3dCouplingMode::Surface>;
 
   57    using ParentType = EmbeddedCouplingManagerBase<MDTraits, ThisType, CircleAveragePointSourceTraits<MDTraits>>;
 
   58    using Scalar = 
typename MDTraits::Scalar;
 
   59    using SolutionVector = 
typename MDTraits::SolutionVector;
 
   60    using PointSourceData = 
typename ParentType::PointSourceTraits::PointSourceData;
 
   62    static constexpr auto bulkIdx = 
typename MDTraits::template SubDomain<0>::Index();
 
   63    static constexpr auto lowDimIdx = 
typename MDTraits::template SubDomain<1>::Index();
 
   66    template<std::
size_t id> 
using SubDomainTypeTag = 
typename MDTraits::template SubDomain<id>::TypeTag;
 
   67    template<std::
size_t id> 
using Problem = GetPropType<SubDomainTypeTag<id>, Properties::Problem>;
 
   68    template<std::
size_t id> 
using GridGeometry = GetPropType<SubDomainTypeTag<id>, Properties::GridGeometry>;
 
   69    template<std::
size_t id> 
using GridView = 
typename GridGeometry<id>::GridView;
 
   70    template<std::
size_t id> 
using Element = 
typename GridView<id>::template Codim<0>::Entity;
 
   71    template<std::
size_t id> 
using GridIndex = 
typename IndexTraits<GridView<id>>::GridIndex;
 
   73    using GlobalPosition = 
typename Element<bulkIdx>::Geometry::GlobalCoordinate;
 
   75    template<std::
size_t id>
 
   76    static constexpr bool isBox()
 
   80        bulkDim = GridView<bulkIdx>::dimension,
 
   81        lowDimDim = GridView<lowDimIdx>::dimension,
 
   82        dimWorld = GridView<bulkIdx>::dimensionworld
 
   85    static constexpr Embedded1d3dCouplingMode::Surface couplingMode{};
 
   87    using ParentType::ParentType;
 
   89    void init(std::shared_ptr<Problem<bulkIdx>> bulkProblem,
 
   90              std::shared_ptr<Problem<lowDimIdx>> lowDimProblem,
 
   91              const SolutionVector& curSol)
 
   93        ParentType::init(bulkProblem, lowDimProblem, curSol);
 
   94        computeLowDimVolumeFractions();
 
  103    template<std::
size_t id, 
class JacobianPattern>
 
  104    void extendJacobianPattern(Dune::index_constant<id> domainI, JacobianPattern& pattern)
 const 
  106        extendedSourceStencil_.extendJacobianPattern(*
this, domainI, pattern);
 
  116    template<std::
size_t i, 
class LocalAssemblerI, 
class JacobianMatrixDiagBlock, 
class Gr
idVariables>
 
  117    void evalAdditionalDomainDerivatives(Dune::index_constant<i> domainI,
 
  118                                         const LocalAssemblerI& localAssemblerI,
 
  119                                         const typename LocalAssemblerI::LocalResidual::ElementResidualVector&,
 
  120                                         JacobianMatrixDiagBlock& A,
 
  121                                         GridVariables& gridVariables)
 
  123        extendedSourceStencil_.evalAdditionalDomainDerivatives(*
this, domainI, localAssemblerI, A, gridVariables);
 
  135    void computePointSourceData(std::size_t order = 1, 
bool verbose = 
false)
 
  138        static const bool useCircleAverage = 
getParam<bool>(
"MixedDimension.UseCircleAverage", 
true);
 
  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_.stencil().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 integrationElement = intersectionGeometry.integrationElement(qp.position())*2*M_PI*radius/Scalar(numIp);
 
  202                const auto qpweight = qp.weight()/(2*M_PI*radius);
 
  203                const auto circleAvgWeight = 2*M_PI*radius/numIp;
 
  206                std::vector<std::vector<std::size_t>> circleBulkElementIndices(
circlePoints.size());
 
  207                std::vector<Scalar> circleIpWeight; circleIpWeight.reserve(
circlePoints.size());
 
  208                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;
 
  218                    if (circleBulkElementIndices[k].empty())
 
  221                    const auto localCircleAvgWeight = circleAvgWeight / circleBulkElementIndices[k].size();
 
  222                    for (
const auto bulkElementIdx : circleBulkElementIndices[k])
 
  224                        circleStencil.push_back(bulkElementIdx);
 
  225                        circleIpWeight.push_back(localCircleAvgWeight);
 
  228                        if constexpr (isBox<bulkIdx>())
 
  230                            const auto bulkElement = bulkGridGeometry.element(bulkElementIdx);
 
  231                            circleCornerIndices.push_back(&(this->vertexIndices(bulkIdx, bulkElementIdx)));
 
  234                            const auto bulkGeometry = bulkElement.geometry();
 
  235                            ShapeValues shapeValues;
 
  236                            this->getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry, circlePoints[k], shapeValues);
 
  237                            circleShapeValues.emplace_back(std::move(shapeValues));
 
  243                if constexpr (isBox<bulkIdx>())
 
  246                    for (
const auto& vertices : circleCornerIndices)
 
  248                        this->couplingStencils(lowDimIdx)[lowDimElementIdx].insert(this->couplingStencils(lowDimIdx)[lowDimElementIdx].end(),
 
  249                                                                                   vertices->begin(), vertices->end());
 
  255                    this->couplingStencils(lowDimIdx)[lowDimElementIdx].insert(this->couplingStencils(lowDimIdx)[lowDimElementIdx].end(),
 
  256                                                                               circleStencil.begin(), circleStencil.end());
 
  264                    if (circleBulkElementIndices[k].empty())
 
  269                    for (
const auto bulkElementIdx : circleBulkElementIndices[k])
 
  271                        const auto id = this->idCounter_++;
 
  273                        this->pointSources(bulkIdx).emplace_back(circlePos, 
id, qpweight, integrationElement, bulkElementIdx);
 
  274                        this->pointSources(bulkIdx).back().setEmbeddings(circleBulkElementIndices[k].size());
 
  275                        this->pointSources(lowDimIdx).emplace_back(globalPos, 
id, qpweight, integrationElement, lowDimElementIdx);
 
  276                        this->pointSources(lowDimIdx).back().setEmbeddings(circleBulkElementIndices[k].size());
 
  280                        PointSourceData psData;
 
  282                        if constexpr (isBox<lowDimIdx>())
 
  284                            using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
 
  285                            ShapeValues shapeValues;
 
  286                            this->getShapeValues(lowDimIdx, lowDimGridGeometry, lowDimElement.geometry(), globalPos, shapeValues);
 
  287                            psData.addLowDimInterpolation(shapeValues, this->vertexIndices(lowDimIdx, lowDimElementIdx), lowDimElementIdx);
 
  291                            psData.addLowDimInterpolation(lowDimElementIdx);
 
  295                        if constexpr (isBox<bulkIdx>())
 
  297                            if (useCircleAverage)
 
  298                                psData.addCircleInterpolation(circleCornerIndices, circleShapeValues, circleIpWeight, circleStencil);
 
  300                            using ShapeValues = std::vector<Dune::FieldVector<Scalar, 1> >;
 
  301                            const auto bulkGeometry = bulkGridGeometry.element(bulkElementIdx).geometry();
 
  302                            ShapeValues shapeValues;
 
  303                            this->getShapeValues(bulkIdx, bulkGridGeometry, bulkGeometry, circlePos, shapeValues);
 
  304                            psData.addBulkInterpolation(shapeValues, this->vertexIndices(bulkIdx, bulkElementIdx), bulkElementIdx);
 
  308                            if (useCircleAverage)
 
  309                                psData.addCircleInterpolation(circleIpWeight, circleStencil);
 
  311                            psData.addBulkInterpolation(bulkElementIdx);
 
  315                        this->pointSourceData().emplace_back(std::move(psData));
 
  319                        if constexpr (isBox<lowDimIdx>())
 
  321                            const auto& vertices = this->vertexIndices(lowDimIdx, lowDimElementIdx);
 
  322                            this->couplingStencils(bulkIdx)[bulkElementIdx].insert(this->couplingStencils(bulkIdx)[bulkElementIdx].end(),
 
  323                                                                                   vertices.begin(), vertices.end());
 
  328                            this->couplingStencils(bulkIdx)[bulkElementIdx].push_back(lowDimElementIdx);
 
  332                        if (useCircleAverage)
 
  334                            if constexpr (isBox<bulkIdx>())
 
  337                                for (
const auto& vertices : circleCornerIndices)
 
  339                                    extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
 
  340                                                                               vertices->begin(), vertices->end());
 
  346                                extendedSourceStencil_.stencil()[bulkElementIdx].insert(extendedSourceStencil_.stencil()[bulkElementIdx].end(),
 
  347                                                                           circleStencil.begin(), circleStencil.end());
 
  356        for (
auto&& stencil : extendedSourceStencil_.stencil())
 
  358            std::sort(stencil.second.begin(), stencil.second.end());
 
  359            stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
 
  362            if constexpr (isBox<bulkIdx>())
 
  364                const auto& indices = this->vertexIndices(bulkIdx, stencil.first);
 
  365                stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
 
  366                                                   [&](
auto i){ return std::find(indices.begin(), indices.end(), i) != indices.end(); }),
 
  367                                     stencil.second.end());
 
  372                stencil.second.erase(std::remove_if(stencil.second.begin(), stencil.second.end(),
 
  373                                                   [&](
auto i){ return i == stencil.first; }),
 
  374                                     stencil.second.end());
 
  379        using namespace Dune::Hybrid;
 
  380        forEach(integralRange(Dune::index_constant<2>{}), [&](
const auto domainIdx)
 
  382            for (
auto&& stencil : this->couplingStencils(domainIdx))
 
  384                std::sort(stencil.second.begin(), stencil.second.end());
 
  385                stencil.second.erase(std::unique(stencil.second.begin(), stencil.second.end()), stencil.second.end());
 
  389        std::cout << 
"took " << watch.elapsed() << 
" seconds." << std::endl;
 
  393    void computeLowDimVolumeFractions()
 
  396        lowDimVolumeInBulkElement_.resize(this->gridView(bulkIdx).size(0));
 
  398        const auto& lowDimGridGeometry = this->problem(lowDimIdx).gridGeometry();
 
  399        const auto& bulkGridGeometry = this->problem(bulkIdx).gridGeometry();
 
  402        for (
const auto& is : intersections(this->glue()))
 
  405            const auto& inside = is.targetEntity(0);
 
  406            const auto intersectionGeometry = is.geometry();
 
  407            const auto lowDimElementIdx = lowDimGridGeometry.elementMapper().index(inside);
 
  410            const auto radius = this->problem(lowDimIdx).spatialParams().radius(lowDimElementIdx);
 
  411            for (
int outsideIdx = 0; outsideIdx < is.numDomainNeighbors(); ++outsideIdx)
 
  413                const auto& outside = is.domainEntity(outsideIdx);
 
  414                const auto bulkElementIdx = bulkGridGeometry.elementMapper().index(outside);
 
  415                lowDimVolumeInBulkElement_[bulkElementIdx] += intersectionGeometry.volume()*M_PI*radius*radius;
 
  426    Scalar radius(std::size_t 
id)
 const 
  428        const auto& data = this->pointSourceData()[id];
 
  429        return this->problem(lowDimIdx).spatialParams().radius(data.lowDimElementIdx());
 
  434    Scalar lowDimVolume(
const Element<bulkIdx>& element)
 const 
  436        const auto eIdx = this->problem(bulkIdx).gridGeometry().elementMapper().index(element);
 
  437        return lowDimVolumeInBulkElement_[eIdx];
 
  442    Scalar lowDimVolumeFraction(
const Element<bulkIdx>& element)
 const 
  444        const auto totalVolume = 
element.geometry().volume();
 
  445        return lowDimVolume(element) / totalVolume;
 
  453    const typename ParentType::template CouplingStencils<bulkIdx>::mapped_type&
 
  454    extendedSourceStencil(std::size_t eIdx)
 const 
  456        const auto& sourceStencils = extendedSourceStencil_.stencil();
 
  457        if (
auto stencil = sourceStencils.find(eIdx); stencil != sourceStencils.end())
 
  458            return stencil->second;
 
  460        return this->emptyStencil(bulkIdx);
 
  465    EmbeddedCoupling::ExtendedSourceStencil<ThisType> extendedSourceStencil_;
 
  468    std::vector<Scalar> lowDimVolumeInBulkElement_;
 
  472template<
class MDTraits>
 
  474: 
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.hh:24
Defines all properties used in Dumux.
Coupling manager for low-dimensional domains embedded in the bulk domain. Point sources on each integ...
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
T getParam(Args &&... args)
A free function to get a parameter from the parameter tree singleton.
Definition parameters.hh:139
constexpr Box box
Definition method.hh:147
Definition couplingmanager1d3d_average.hh:34
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
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.