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