135    using ctype = 
typename Dune::PromotionTraits<typename DomainEntitySet::ctype, typename TargetEntitySet::ctype>::PromotedType;
 
  137    static constexpr int dimWorld = DomainEntitySet::dimensionworld;
 
  138    static_assert(dimWorld == int(TargetEntitySet::dimensionworld), 
"Entity sets must have the same world dimension");
 
  140    using GlobalPosition = Dune::FieldVector<ctype, dimWorld>;
 
  142    static constexpr int dimDomain = DomainEntitySet::Entity::Geometry::mydimension;
 
  143    static constexpr int dimTarget = TargetEntitySet::Entity::Geometry::mydimension;
 
  144    static constexpr bool isMixedDimensional = dimDomain != dimTarget;
 
  147    using Intersections = std::vector<IntersectionEntity>;
 
  149    using DomainGeometry = 
typename DomainEntitySet::Entity::Geometry;
 
  150    using TargetGeometry = 
typename TargetEntitySet::Entity::Geometry;
 
  166    void build(std::shared_ptr<const DomainEntitySet> domainSet, std::shared_ptr<const TargetEntitySet> targetSet)
 
  169        if (targetSet->size() == 1)
 
  171            domainTree_ = std::make_shared<DomainTree>(domainSet);
 
  172            targetEntitySet_ = targetSet;
 
  173            build_(*domainTree_, targetEntitySet_->entity(0).geometry());
 
  176        else if (domainSet->size() == 1)
 
  178            domainEntitySet_ = domainSet;
 
  179            targetTree_ = std::make_shared<TargetTree>(targetSet);
 
  180            build_(domainEntitySet_->entity(0).geometry(), *targetTree_);
 
  184            domainTree_ = std::make_shared<DomainTree>(domainSet);
 
  185            targetTree_ = std::make_shared<TargetTree>(targetSet);
 
  186            build(*domainTree_, *targetTree_);
 
 
  193    void build(std::shared_ptr<const DomainTree> domainTree, std::shared_ptr<const TargetTree> targetTree)
 
  196        domainTree_ = domainTree;
 
  197        targetTree_ = targetTree;
 
  198        build(*domainTree_, *targetTree_);
 
 
  205    void build(
const DomainTree& domainTree, 
const TargetTree& targetTree)
 
  212        std::cout << 
"Computed " << 
size() << 
" intersection entities in " << timer.elapsed() << std::endl;
 
 
  216    typename Intersections::const_iterator 
ibegin()
 const 
  217    { 
return intersections_.begin(); }
 
 
  220    typename Intersections::const_iterator 
iend()
 const 
  221    { 
return intersections_.end(); }
 
 
  225    { 
return intersections_.size(); }
 
 
  236    void build_(
const DomainTree& domainTree, 
const TargetGeometry& targetGeometry)
 
  244        const bool flipNeighborIndices = 
true;
 
  245        build_(domainTree.entitySet(), *targetEntitySet_, rawIntersections, flipNeighborIndices);
 
  247        std::cout << 
"Computed " << 
size() << 
" intersection entities in " << timer.elapsed() << std::endl;
 
  250    void build_(
const DomainGeometry& domainGeometry, 
const TargetTree& targetTree)
 
  255        build_(*domainEntitySet_, targetTree.entitySet(), rawIntersections);
 
  257        std::cout << 
"Computed " << 
size() << 
" intersection entities in " << timer.elapsed() << std::endl;
 
  260    template<
class RawIntersections>
 
  261    void build_(
const DomainEntitySet& domainEntitySet, 
const TargetEntitySet& targetEntitySet,
 
  262                const RawIntersections& rawIntersections,
 
  263                bool flipNeighborIndices = 
false)
 
  269        std::vector<std::vector<std::vector<GlobalPosition>>> intersectionMap;
 
  270        std::vector<std::vector<std::size_t>> intersectionIndex;
 
  271        if constexpr (isMixedDimensional)
 
  273            const auto numLowDimEntities = dimTarget < dimDomain ? targetEntitySet.size() : domainEntitySet.size();
 
  274            intersectionMap.resize(numLowDimEntities);
 
  275            intersectionIndex.resize(numLowDimEntities);
 
  281        intersections_.clear();
 
  282        intersections_.reserve(rawIntersections.size());
 
  284        for (
const auto& rawIntersection : rawIntersections)
 
  290            if constexpr (isMixedDimensional)
 
  292                const auto lowDimNeighborIdx = getLowDimNeighborIndex_(rawIntersection, flipNeighborIndices);
 
  293                for (
int i = 0; i < intersectionMap[lowDimNeighborIdx].size(); ++i)
 
  295                    if (rawIntersection.cornersMatch(intersectionMap[lowDimNeighborIdx][i]))
 
  299                        auto idx = intersectionIndex[lowDimNeighborIdx][i];
 
  300                        intersections_[idx].addNeighbors(domainNeighborIndex_(rawIntersection, flipNeighborIndices), targetNeighborIndex_(rawIntersection, flipNeighborIndices));
 
  309                if constexpr (isMixedDimensional)
 
  311                    const auto lowDimNeighborIdx = getLowDimNeighborIndex_(rawIntersection, flipNeighborIndices);
 
  312                    intersectionMap[lowDimNeighborIdx].push_back(rawIntersection.corners());
 
  313                    intersectionIndex[lowDimNeighborIdx].push_back(intersections_.size());
 
  317                intersections_.emplace_back(domainEntitySet, targetEntitySet);
 
  318                intersections_.back().setCorners(rawIntersection.corners());
 
  319                intersections_.back().addNeighbors(domainNeighborIndex_(rawIntersection, flipNeighborIndices), targetNeighborIndex_(rawIntersection, flipNeighborIndices));
 
  323        intersections_.shrink_to_fit();
 
  326    template<
class RawIntersection,
 
  327             bool enable = isMixedDimensional, std::enable_if_t<enable, int> = 0>
 
  328    auto getLowDimNeighborIndex_(
const RawIntersection& is, 
bool flipNeighborIndices)
 
  330        if constexpr (dimTarget < dimDomain)
 
  331            return targetNeighborIndex_(is, flipNeighborIndices);
 
  333            return domainNeighborIndex_(is, flipNeighborIndices);
 
  336    template<
class RawIntersection>
 
  337    auto domainNeighborIndex_(
const RawIntersection& is, 
bool flipNeighborIndices)
 
  338    { 
return flipNeighborIndices ? is.second() : is.first(); }
 
  340    template<
class RawIntersection>
 
  341    auto targetNeighborIndex_(
const RawIntersection& is, 
bool flipNeighborIndices)
 
  342    { 
return flipNeighborIndices ? is.first() : is.second(); }
 
  344    Intersections intersections_;
 
  346    std::shared_ptr<const DomainTree> domainTree_;
 
  347    std::shared_ptr<const TargetTree> targetTree_;
 
  348    std::shared_ptr<const DomainEntitySet> domainEntitySet_;
 
  349    std::shared_ptr<const TargetEntitySet> targetEntitySet_;