1 #ifndef DUNE_PDELAB_COMMON_PARTITIONVIEWENTITYSET_HH
2 #define DUNE_PDELAB_COMMON_PARTITIONVIEWENTITYSET_HH
3 
4 #include <cassert>
5 #include <vector>
6 #include <bitset>
7 #include <memory>
8 #include <algorithm>
9 #include <numeric>
10 #include <type_traits>
11 
12 #include <dune/common/version.hh>
13 #include <dune/common/iteratorrange.hh>
14 #include <dune/geometry/referenceelements.hh>
15 #include <dune/geometry/typeindex.hh>
16 #include <dune/grid/common/capabilities.hh>
17 #include <dune/grid/common/partitionset.hh>
18 #include <dune/grid/common/rangegenerators.hh>
19 
20 namespace Dune {
21 
22   namespace PDELab {
23 
24     // import range generators to make sure they work with PartitionViewEntitySet
25     using Dune::entities;
26     using Dune::elements;
27     using Dune::facets;
28     using Dune::edges;
29     using Dune::vertices;
30     using Dune::descendantElements;
31     using Dune::intersections;
32 
33     template<typename GV, typename P>
34     class PartitionViewEntitySet;
35 
36     template<typename GV, typename P>
37     class PartitionViewEntitySetIndexSet;
38 
39     template<typename GV, typename P>
40     struct PartitionViewEntitySetTraits
41     {
42 
43       using Partitions = typename std::decay<P>::type;
44 
45       using Grid = typename GV::Traits::Grid;
46       using GridView = GV;
47       using EntitySet = Dune::PDELab::PartitionViewEntitySet<GV,P>;
48       using IndexSet = PartitionViewEntitySetIndexSet<GV,Partitions>;
49       using BaseIndexSet = typename GV::Traits::IndexSet;
50 
51       using Element = typename GV::template Codim<0>::Entity;
52 
53       using Intersection = typename GV::Traits::Intersection;
54 
55       using IntersectionIterator = typename GV::Traits::IntersectionIterator;
56 
57       using CollectiveCommunication = typename GV::Traits::CollectiveCommunication;
58 
59       using size_type = std::size_t;
60       using dim_type = int;
61 
62       using Index = typename BaseIndexSet::IndexType;
63 
64       using Types = IteratorRange<std::vector<GeometryType>::const_iterator>;
65 
66       using CodimMask = std::bitset<GV::dimension + 1>;
67 
68       using CoordinateField = typename Grid::ctype;
69 
invalidIndexDune::PDELab::PartitionViewEntitySetTraits70       constexpr static Index invalidIndex()
71       {
72         return ~static_cast<Index>(0ull);
73       }
74 
75       static const bool conforming = GV::Traits::conforming;
76 
77       static const dim_type dimension = GV::dimension;
78 
79       static const dim_type dimensionworld = GV::dimensionworld;
80 
81       template<dim_type codim>
82       struct Codim
83       {
84 
85         using Iterator = typename GV::template Codim<codim>::template Partition<Partitions::partitionIterator()>::Iterator;
86 
87         using Entity = typename GV::template Codim<codim>::Entity;
88 
89         using Geometry = typename GV::template Codim<codim>::Geometry;
90 
91         using LocalGeometry = typename GV::template Codim<codim>::LocalGeometry;
92 
93         template<PartitionIteratorType pitype>
94         struct Partition
95         {
96 
97           using Iterator = typename GV::template Codim<codim>::template Partition<pitype>::Iterator;
98 
99         };
100 
101       };
102 
103     };
104 
105 
106     /**
107      * @brief Partition view (or entity set) of a grid view
108      * @details The partition view creates an index set for the given partition
109      *          which allows to exclude unused codimensions. Additionally, it
110      *          allows to retreive a unique index for every entity contained in
111      *          the index set (Similar to the MCMG mapper functionality).
112      *          This is particularly useful when working with Local Finite
113      *          Elements that do not attach DOFs to all codimensions.
114      * @note A copy of this class is a shallow copy on the underlying index set
115      * @tparam GV Grid view
116      * @tparam P  PartitionSet to restrict view of the entity set
117      */
118     template<typename GV, typename P>
119     class PartitionViewEntitySet
120     {
121 
122     public:
123 
124       using Traits = PartitionViewEntitySetTraits<GV,P>;
125 
126       using Partitions = typename Traits::Partitions;
127       using Grid      = typename Traits::Grid;
128       using GridView = typename Traits::GridView;
129       using IndexSet  = typename Traits::IndexSet;
130       using BaseIndexSet = typename Traits::BaseIndexSet;
131       using Element = typename Traits::Element;
132       using Intersection = typename Traits::Intersection;
133       using IntersectionIterator = typename Traits::IntersectionIterator;
134       using CollectiveCommunication = typename Traits::CollectiveCommunication;
135       using CodimMask = typename Traits::CodimMask;
136       using CoordinateField = typename Traits::CoordinateField;
137       using size_type = typename Traits::size_type;
138       using dim_type = typename Traits::dim_type;
139 
140       using ctype = CoordinateField;
141 
142       static const bool conforming = Traits::conforming;
143       static const dim_type dimension = Traits::dimension;
144       static const dim_type dimensionworld = Traits::dimensionworld;
145 
146       template<dim_type codim>
147       using Codim = typename Traits::template Codim<codim>;
148 
partitions()149       constexpr static Partitions partitions()
150       {
151         return {};
152       }
153 
allCodims()154       constexpr static CodimMask allCodims()
155       {
156         return {~0ull};
157       }
158 
grid() const159       const Grid& grid() const
160       {
161         return gridView().grid();
162       }
163 
164       //! Returns the IndexSet of this EntitySet.
indexSet() const165       const IndexSet& indexSet() const
166       {
167         return *_index_set;
168       }
169 
170       //! Returns the IndexSet of the underlying GridView.
baseIndexSet() const171       const BaseIndexSet& baseIndexSet() const
172       {
173         return indexSet().baseIndexSet();
174       }
175 
176       template<dim_type codim>
177       typename Codim<codim>::Iterator
begin() const178       begin() const
179       {
180         return gridView().template begin<codim,Partitions::partitionIterator()>();
181       }
182 
183       template<dim_type codim>
184       typename Codim<codim>::Iterator
end() const185       end() const
186       {
187         return gridView().template end<codim,Partitions::partitionIterator()>();
188       }
189 
190       template<dim_type codim, PartitionIteratorType pitype>
191       typename GV::template Codim<codim>::template Partition<pitype>::Iterator
begin() const192       begin() const
193       {
194         return gridView().template begin<codim,pitype>();
195       }
196 
197       template<dim_type codim, PartitionIteratorType pitype>
198       typename GV::template Codim<codim>::template Partition<pitype>::Iterator
end() const199       end() const
200       {
201         return gridView().template end<codim,pitype>();
202       }
203 
size(dim_type codim) const204       size_type size(dim_type codim) const
205       {
206         return indexSet().size(codim);
207       }
208 
size(const GeometryType & gt) const209       size_type size(const GeometryType& gt) const
210       {
211         return indexSet().size(gt);
212       }
213 
214       template<typename Entity>
contains(const Entity & e) const215       bool contains(const Entity& e) const
216       {
217         return indexSet().contains(e);
218       }
219 
contains(dim_type codim) const220       bool contains(dim_type codim) const
221       {
222         return indexSet().contains(codim);
223       }
224 
contains(const GeometryType & gt) const225       bool contains(const GeometryType& gt) const
226       {
227         return indexSet().contains(gt);
228       }
229 
ibegin(const typename Codim<0>::Entity & entity) const230       IntersectionIterator ibegin(const typename Codim<0>::Entity& entity) const
231       {
232         return gridView().ibegin(entity);
233       }
234 
iend(const typename Codim<0>::Entity & entity) const235       IntersectionIterator iend(const typename Codim<0>::Entity& entity) const
236       {
237         return gridView().iend(entity);
238       }
239 
comm() const240       const CollectiveCommunication& comm() const
241       {
242         return gridView().comm();
243       }
244 
245       //! Returns the overlap size of this EntitySet, which depends on its PartitionSet.
overlapSize(dim_type codim) const246       size_type overlapSize(dim_type codim) const
247       {
248         return Partitions::contains(Dune::Partitions::overlap) ? gridView().overlapSize(codim) : 0;
249       }
250 
251       //! Returns the ghost size of this EntitySet, which depends on its PartitionSet.
ghostSize(dim_type codim) const252       size_type ghostSize(dim_type codim) const
253       {
254         return Partitions::contains(Dune::Partitions::ghost) ? gridView().ghostSize(codim) : 0;
255       }
256 
257       template<typename DataHandle>
communicate(DataHandle & data,InterfaceType iftype,CommunicationDirection dir) const258       void communicate(DataHandle& data, InterfaceType iftype, CommunicationDirection dir) const
259       {
260         gridView().communicate(data,iftype,dir);
261       }
262 
263       //! Returns the underlying GridView.
gridView() const264       const GridView& gridView() const
265       {
266         return indexSet().gridView();
267       }
268 
PartitionViewEntitySet(const GridView & gv,CodimMask supported_codims)269       PartitionViewEntitySet(const GridView& gv, CodimMask supported_codims)
270         : _index_set(std::make_shared<IndexSet>(gv,supported_codims,true))
271       {}
272 
PartitionViewEntitySet(const GridView & gv,bool initialize=true)273       explicit PartitionViewEntitySet(const GridView& gv, bool initialize = true)
274         : _index_set(std::make_shared<IndexSet>(gv,CodimMask(initialize ? ~0ull : 0ull),initialize))
275       {}
276 
277       //! Reset this EntitySet, which removes all entities from it.
reset()278       void reset()
279       {
280         _index_set->reset();
281       }
282 
283       //! Add all entities of the given codim to this EntitySet.
addCodim(dim_type codim)284       void addCodim(dim_type codim)
285       {
286         _index_set->addCodim(codim);
287       }
288 
289       //! Remove all entities of the given codim from this EntitySet.
removeCodim(dim_type codim)290       void removeCodim(dim_type codim)
291       {
292         _index_set->removeCodim(codim);
293       }
294 
295       //! Returns true if you need to call update on this EntitySet before using it.
needsUpdate() const296       bool needsUpdate() const
297       {
298         return _index_set->needsUpdate();
299       }
300 
301       //! Update the internal state of this EntitySet.
302       /**
303        *
304        * \param force   If true, forces an update even if the EntitySet parameters have not
305        *                changed. This is e.g. required if the underlying grid has changed due
306        *                to adaptivity.
307        *
308        * \return  Returns true if the state of the EntitySet was changed by this method.
309        */
update(bool force=false)310       bool update(bool force = false)
311       {
312         return _index_set->update(force);
313       }
314 
315       /**
316        * @brief Compare to another partition view
317        * @details This check only succeeds for copies of this class
318        *
319        * @param other Another partition view
320        * @return true if other shares the same index set as this
321        * @return false otherwise
322        */
operator ==(const PartitionViewEntitySet & other) const323       bool operator==(const PartitionViewEntitySet& other) const {
324         return _index_set == other._index_set;
325       }
326 
327       //! Compare to another partition view
operator !=(const PartitionViewEntitySet & other) const328       bool operator!=(const PartitionViewEntitySet& other) const {
329         return not (*this == other);
330       }
331 
332     private:
333 
334       std::shared_ptr<IndexSet> _index_set;
335 
336     };
337 
338     template<typename GV, typename P>
339     class PartitionViewEntitySetIndexSetBase
340     {
341 
342       template<typename,typename>
343       friend class PartitionViewEntitySet;
344 
345     public:
346 
347       using Traits = PartitionViewEntitySetTraits<GV,P>;
348 
349       using Partitions = typename Traits::Partitions;
350       using Grid      = typename Traits::Grid;
351       using GridView = typename Traits::GridView;
352       using BaseIndexSet = typename Traits::BaseIndexSet;
353       using size_type = typename Traits::size_type;
354       using dim_type = typename Traits::dim_type;
355       using Index = typename Traits::Index;
356       using Types = typename Traits::Types;
357       using CodimMask = typename Traits::CodimMask;
358 
359       using IndexType = Index;
360 
invalidIndex()361       constexpr static Index invalidIndex()
362       {
363         return Traits::invalidIndex();
364       }
365 
366       template<dim_type codim>
367       using Codim = typename Traits::template Codim<codim>;
368 
369       PartitionViewEntitySetIndexSetBase(const PartitionViewEntitySetIndexSetBase&) = delete;
370       PartitionViewEntitySetIndexSetBase& operator=(const PartitionViewEntitySetIndexSetBase&) = delete;
371 
372 
373     protected:
374 
update(bool force)375       bool update(bool force)
376       {
377         if (!(_needs_update || force))
378           return false;
379         std::fill(_gt_offsets.begin(),_gt_offsets.end(),0);
380         std::fill(_mapped_gt_offsets.begin(),_mapped_gt_offsets.end(),0);
381         _active_geometry_types.reset();
382         _geometry_types.resize(0);
383         for (dim_type codim = 0; codim <= GV::dimension; ++codim)
384           {
385             if (!_wanted_codims.test(codim))
386               continue;
387             for (const auto& gt : baseIndexSet().types(codim))
388               {
389                 auto gt_index = GlobalGeometryTypeIndex::index(gt);
390                 _gt_offsets[gt_index + 1] = baseIndexSet().size(gt);
391                 _geometry_types.push_back(gt);
392                 _active_geometry_types.set(gt_index);
393               }
394           }
395         for (dim_type codim = 0; codim <= GV::dimension; ++codim)
396           {
397             auto range = std::equal_range(
398               _geometry_types.begin(),
399               _geometry_types.end(),
400               GeometryTypes::none(GV::dimension - codim),
401               [](const GeometryType& x, const GeometryType& y)
402               {
403                 // reverse order because we store in ascending order with regard to the codim, not the dim
404                 return y.dim() < x.dim();
405               });
406             _per_codim_geometry_types[codim] = {range.first,range.second};
407           }
408 
409         std::partial_sum(_gt_offsets.begin(),_gt_offsets.end(),_gt_offsets.begin());
410         _active_codims = _wanted_codims;
411         _needs_update = false;
412         return true;
413       }
414 
415     public:
416 
size(GeometryType gt) const417       size_type size(GeometryType gt) const
418       {
419         assert(!needsUpdate());
420         auto gt_index = GlobalGeometryTypeIndex::index(gt);
421         return _mapped_gt_offsets[gt_index + 1] - _mapped_gt_offsets[gt_index];
422       }
423 
size(dim_type codim) const424       size_type size(dim_type codim) const
425       {
426         assert(!needsUpdate());
427         auto dim = GV::dimension;
428         return _mapped_gt_offsets[GlobalGeometryTypeIndex::offset(dim-codim+1)] -
429           _mapped_gt_offsets[GlobalGeometryTypeIndex::offset(dim-codim)];
430       }
431 
432       template<typename Entity>
contains(const Entity & e) const433       bool contains(const Entity& e) const
434       {
435         return Partitions::contains(e.partitionType()) ? baseIndexSet().contains(e) : false;
436       }
437 
contains(dim_type codim) const438       bool contains(dim_type codim) const
439       {
440         return _active_codims.test(codim);
441       }
442 
contains(const GeometryType & gt) const443       bool contains(const GeometryType& gt) const
444       {
445         return _active_geometry_types.test(GlobalGeometryTypeIndex::index(gt));
446       }
447 
baseIndexSet() const448       const BaseIndexSet& baseIndexSet() const
449       {
450         return _gv.indexSet();
451       }
452 
types(dim_type codim) const453       Types types(dim_type codim) const
454       {
455         assert(!needsUpdate());
456         return _per_codim_geometry_types[codim];
457       }
458 
types() const459       Types types() const
460       {
461         assert(!needsUpdate());
462         return {_geometry_types.begin(),_geometry_types.end()};
463       }
464 
PartitionViewEntitySetIndexSetBase(const GV & gv,CodimMask wanted_codims)465       PartitionViewEntitySetIndexSetBase(const GV& gv, CodimMask wanted_codims)
466         : _gv(gv)
467         , _needs_update(true)
468         , _wanted_codims(wanted_codims)
469       {}
470 
gridView() const471       const GridView& gridView() const
472       {
473         return _gv;
474       }
475 
needsUpdate() const476       bool needsUpdate() const
477       {
478         return _needs_update;
479       }
480 
481     protected:
482 
reset()483       void reset()
484       {
485         _needs_update = true;
486         _wanted_codims.reset();
487       }
488 
addCodim(dim_type codim)489       void addCodim(dim_type codim)
490       {
491         _wanted_codims.set(codim);
492         _needs_update = _wanted_codims != _active_codims || _wanted_codims.none();
493       }
494 
removeCodim(dim_type codim)495       void removeCodim(dim_type codim)
496       {
497         _wanted_codims.reset(codim);
498         _needs_update = _wanted_codims != _active_codims || _wanted_codims.none();
499       }
500 
501       GV _gv;
502       bool _needs_update;
503       CodimMask _wanted_codims;
504       std::bitset<GlobalGeometryTypeIndex::size(GV::dimension)> _active_geometry_types;
505       CodimMask _active_codims;
506       std::array<size_type,GlobalGeometryTypeIndex::size(GV::dimension) + 1> _gt_offsets;
507       std::array<size_type,GlobalGeometryTypeIndex::size(GV::dimension) + 1> _mapped_gt_offsets;
508 
509     private:
510 
511       std::vector<GeometryType> _geometry_types;
512       std::array<Types,GV::dimension + 1> _per_codim_geometry_types;
513 
514     };
515 
516     template<typename GV, typename P>
517     class PartitionViewEntitySetIndexSet
518       : public PartitionViewEntitySetIndexSetBase<GV,P>
519     {
520 
521       using Base = PartitionViewEntitySetIndexSetBase<GV,P>;
522 
523       template<typename,typename>
524       friend class PartitionViewEntitySet;
525 
526     public:
527 
528       using typename Base::Index;
529       using typename Base::Partitions;
530       using typename Base::size_type;
531       using typename Base::dim_type;
532 
533       using typename Base::Grid;
534 
535       using Base::gridView;
536       using Base::baseIndexSet;
537       using Base::invalidIndex;
538       using Base::contains;
539       using typename Base::CodimMask;
540       using Base::needsUpdate;
541 
542     private:
543 
hasAllEntityIterators(Dune::Dim<Grid::dimension+1>)544       static constexpr bool hasAllEntityIterators(Dune::Dim<Grid::dimension + 1>)
545       {
546         return true;
547       }
548 
549       template<dim_type dim = 0>
hasAllEntityIterators(Dune::Dim<dim>={})550       static constexpr bool hasAllEntityIterators(Dune::Dim<dim> = {})
551       {
552         return Capabilities::hasEntityIterator<Grid,dim>::v && hasAllEntityIterators(Dune::Dim<dim+1>{});
553       }
554 
update(bool force)555       bool update(bool force)
556       {
557         if (!Base::update(force))
558           return false;
559         _indices.assign(_gt_offsets.back(),invalidIndex());
560         _mapped_gt_offsets[0] = 0;
561         update_codims(std::integral_constant<bool,hasAllEntityIterators()>{});
562         std::partial_sum(_mapped_gt_offsets.begin(),_mapped_gt_offsets.end(),_mapped_gt_offsets.begin());
563         return true;
564       }
565 
update_codims(std::true_type)566       void update_codims(std::true_type)
567       {
568         update_codim(Dune::Codim<0>{});
569       }
570 
update_codim(Dune::Codim<GV::dimension+1>)571       void update_codim(Dune::Codim<GV::dimension+1>)
572       {}
573 
574       template<dim_type cd>
update_codim(Dune::Codim<cd> codim)575       void update_codim(Dune::Codim<cd> codim)
576       {
577         if (_active_codims.test(codim))
578           for (const auto& e : entities(gridView(),codim,Dune::Partitions::all))
579             {
580               auto gt = e.type();
581               auto gt_index = GlobalGeometryTypeIndex::index(gt);
582               if (Partitions::contains(e.partitionType()))
583                 _indices[_gt_offsets[gt_index] + baseIndexSet().index(e)] = _mapped_gt_offsets[gt_index + 1]++;
584             }
585         update_codim(Dune::Codim<cd+1>{});
586       }
587 
588 
update_codims(std::false_type)589       void update_codims(std::false_type)
590       {
591         std::fill(_indices.begin(),_indices.end(),invalidIndex());
592 
593         auto& index_set = baseIndexSet();
594 
595         for (const auto& e : elements(gridView(),Dune::Partitions::all))
596           {
597             if (!Partitions::contains(e.partitionType()))
598               continue;
599 
600             auto ref_el = ReferenceElements<typename Base::Traits::CoordinateField,GV::dimension>::general(e.type());
601             for (dim_type codim = 0; codim <= Grid::dimension; ++codim)
602               {
603                 if (!_active_codims.test(codim))
604                   continue;
605 
606                 size_type sub_entity_count = ref_el.size(codim);
607 
608                 for(size_type i = 0; i < sub_entity_count; ++i)
609                   {
610                     auto gt = ref_el.type(i,codim);
611                     auto gt_index = GlobalGeometryTypeIndex::index(gt);
612                     auto index = index_set.subIndex(e,i,codim);
613                     if (_indices[_gt_offsets[gt_index] + index] == invalidIndex())
614                       _indices[_gt_offsets[gt_index] + index] = _mapped_gt_offsets[gt_index + 1]++;
615                   }
616               }
617           }
618       }
619 
620 
621     public:
622 
623       template<typename E>
index(const E & e) const624       Index index(const E& e) const
625       {
626         assert(!needsUpdate());
627         assert(Partitions::contains(e.partitionType()));
628         assert(contains(e.type()));
629         auto gt_index = GlobalGeometryTypeIndex::index(e.type());
630         return _indices[_gt_offsets[gt_index] + baseIndexSet().index(e)];
631       }
632 
633       template<typename E>
subIndex(const E & e,size_type i,dim_type codim) const634       Index subIndex(const E& e, size_type i, dim_type codim) const
635       {
636         assert(!needsUpdate());
637         assert(Partitions::contains(e.partitionType()));
638         auto gt = ReferenceElements<typename Base::Traits::CoordinateField,GV::dimension>::general(e.type()).type(i,codim);
639         assert(contains(gt));
640         auto gt_index = GlobalGeometryTypeIndex::index(gt);
641         return _indices[_gt_offsets[gt_index] + baseIndexSet().subIndex(e,i,codim)];
642       }
643 
644 
645       template<typename E>
uniqueIndex(const E & e) const646       Index uniqueIndex(const E& e) const
647       {
648         assert(!needsUpdate());
649         assert(Partitions::contains(e.partitionType()));
650         assert(contains(e.type()));
651         auto gt_index = GlobalGeometryTypeIndex::index(e.type());
652         return _indices[_gt_offsets[gt_index] + baseIndexSet().index(e)] + _mapped_gt_offsets[gt_index];
653       }
654 
655       template<typename E>
uniqueSubIndex(const E & e,size_type i,dim_type codim) const656       Index uniqueSubIndex(const E& e, size_type i, dim_type codim) const
657       {
658         assert(!needsUpdate());
659         assert(Partitions::contains(e.partitionType()));
660         auto gt = ReferenceElements<typename Base::Traits::CoordinateField,GV::dimension>::general(e.type()).type(i,codim);
661         assert(contains(gt));
662         auto gt_index = GlobalGeometryTypeIndex::index(gt);
663         return _indices[_gt_offsets[gt_index] + baseIndexSet().subIndex(e,i,codim)] + _mapped_gt_offsets[gt_index];
664       }
665 
666 
PartitionViewEntitySetIndexSet(const GV & gv,CodimMask wanted_codims,bool initialize)667       PartitionViewEntitySetIndexSet(const GV& gv, CodimMask wanted_codims, bool initialize)
668         : Base(gv,wanted_codims)
669       {
670         if (initialize)
671           update(true);
672       }
673 
674     private:
675 
676       using Base::_active_codims;
677       using Base::_gt_offsets;
678       using Base::_mapped_gt_offsets;
679 
680       std::vector<Index> _indices;
681 
682     };
683 
684     template<typename GV>
685     class PartitionViewEntitySetIndexSet<GV,Partitions::All>
686       : public PartitionViewEntitySetIndexSetBase<GV,Partitions::All>
687     {
688 
689       using Base = PartitionViewEntitySetIndexSetBase<GV,Dune::Partitions::All>;
690 
691       template<typename,typename>
692       friend class Dune::PDELab::PartitionViewEntitySet;
693 
694     public:
695 
696       using typename Base::Index;
697       using typename Base::Partitions;
698       using typename Base::size_type;
699       using typename Base::dim_type;
700       using typename Base::CodimMask;
701 
702       using Base::baseIndexSet;
703       using Base::contains;
704 
705     private:
706 
update(bool force)707       bool update(bool force)
708       {
709         if (!Base::update(force))
710           return false;
711         _mapped_gt_offsets[0] = 0;
712         for (const auto& gt : Base::types())
713           _mapped_gt_offsets[GlobalGeometryTypeIndex::index(gt) + 1] = baseIndexSet().size(gt);
714         std::partial_sum(_mapped_gt_offsets.begin(),_mapped_gt_offsets.end(),_mapped_gt_offsets.begin());
715         return true;
716       }
717 
718     public:
719 
720       template<typename E>
index(const E & e) const721       Index index(const E& e) const
722       {
723         assert(contains(e.type()));
724         return baseIndexSet().index(e);
725       }
726 
727       template<typename E>
uniqueIndex(const E & e) const728       Index uniqueIndex(const E& e) const
729       {
730         assert(contains(e.type()));
731         return baseIndexSet().index(e) + _mapped_gt_offsets[Dune::GlobalGeometryTypeIndex::index(e.type())];
732       }
733 
734       template<typename E>
subIndex(const E & e,size_type i,dim_type codim) const735       Index subIndex(const E& e, size_type i, dim_type codim) const
736       {
737 #ifndef NDEBUG
738         auto gt = ReferenceElements<typename Base::Traits::CoordinateField,GV::dimension>::general(e.type()).type(i,codim);
739         assert(contains(gt));
740 #endif
741         return baseIndexSet().subIndex(e,i,codim);
742       }
743 
744       template<typename E>
uniqueSubIndex(const E & e,size_type i,dim_type codim) const745       Index uniqueSubIndex(const E& e, size_type i, dim_type codim) const
746       {
747         auto gt = ReferenceElements<typename Base::Traits::CoordinateField,GV::dimension>::general(e.type()).type(i,codim);
748         assert(contains(gt));
749         return baseIndexSet().subIndex(e,i,codim) + _mapped_gt_offsets[Dune::GlobalGeometryTypeIndex::index(gt)];
750       }
751 
PartitionViewEntitySetIndexSet(const GV & gv,CodimMask wanted_codims,bool initialize=true)752       PartitionViewEntitySetIndexSet(const GV& gv, CodimMask wanted_codims, bool initialize = true)
753         : Base(gv,wanted_codims)
754       {
755         if (initialize)
756           update(true);
757       }
758 
759     private:
760 
761       using Base::_mapped_gt_offsets;
762 
763     };
764 
765     template<typename GV>
766     using AllEntitySet = PartitionViewEntitySet<GV,Partitions::All>;
767 
768     template<typename GV>
769     using OverlappingEntitySet = PartitionViewEntitySet<GV,Partitions::InteriorBorderOverlapFront>;
770 
771     template<typename GV>
772     using NonOverlappingEntitySet = PartitionViewEntitySet<GV,Partitions::InteriorBorder>;
773 
774 #ifndef DOXYGEN
775 
776     namespace impl {
777 
778       template<typename T>
779       struct _isEntitySet
780       {
781         using type = std::false_type;
782       };
783 
784       template<typename GV,typename P>
785       struct _isEntitySet<PartitionViewEntitySet<GV,P>>
786       {
787         using type = std::true_type;
788       };
789 
790     }
791 
792 #endif // DOXYGEN
793 
794     //! Type Trait to determine whether T is an EntitySet.
795     template<typename T>
796     using isEntitySet = typename impl::_isEntitySet<T>::type;
797 
798   } // namespace PDELab
799 } // namespace Dune
800 
801 
802 #endif // DUNE_PDELAB_COMMON_PARTITIONVIEWENTITYSET_HH
803