1 #ifndef DUNE_MULTIDOMAINGRID_INDEXSETS_HH
2 #define DUNE_MULTIDOMAINGRID_INDEXSETS_HH
3
4 #include <map>
5 #include <unordered_map>
6 #include <vector>
7 #include <array>
8 #include <algorithm>
9 #include <memory>
10 #include <type_traits>
11 #include <tuple>
12 #include <utility>
13
14
15 #include <dune/geometry/typeindex.hh>
16 #include <dune/grid/common/exceptions.hh>
17 #include <dune/grid/common/indexidset.hh>
18
19 #include <dune/grid/multidomaingrid/utility.hh>
20 #include <dune/grid/multidomaingrid/subdomaingrid/indexsets.hh>
21
22 #include <dune/typetree/utility.hh>
23
24 namespace Dune {
25
26 namespace mdgrid {
27
28 template<typename HostGrid, typename MDGridTraits>
29 class MultiDomainGrid;
30
31 //! @cond DEV_DOC
32
33 //! \internal
34 namespace detail {
35
36 template<template<int> class StructForCodim, typename Codims>
37 struct _buildMap;
38
39 //! \internal template meta program for assembling the per-codim map vector
40 template<template<int> class StructForCodim, std::size_t... codim>
41 struct _buildMap<StructForCodim,std::index_sequence<codim...> > {
42
43 typedef std::tuple<StructForCodim<codim>... > type;
44
45 };
46
47 template<template<int> class StructForCodim, int dimension>
48 struct buildMap {
49
50 typedef typename _buildMap<
51 StructForCodim,
52 decltype(std::make_index_sequence<dimension+1>())
53 >::type type;
54
55 };
56
57 //! \internal Helper mechanism for dispatching a call to a possibly non-existent method
58 /**
59 * This trick is necessary because some calls in the indexset (e.g. IndexSet::size(int codim) )
60 * pass the codim as a run-time parameter. But as we do not necessarily support all codimensions,
61 * we have to make sure that we only call the actual method if there is a data structure to
62 * operate on. This is handled by the template parameter doDispatch: The specialisation for
63 * doDispatch == false will simply throw an exception.
64 */
65 template<bool doDispatch, typename Impl, typename resulttype,bool alternate_dispatch>
66 struct invokeIf;
67
68 template<typename Impl, typename resulttype, bool alternate_dispatch>
69 struct invokeIf<true,Impl,resulttype,alternate_dispatch> {
70
71 typedef resulttype result_type;
72
73 template<int codim>
invokeDune::mdgrid::detail::invokeIf74 result_type invoke() {
75 return _impl.template invoke<codim>();
76 }
77
78 Impl& _impl;
79
invokeIfDune::mdgrid::detail::invokeIf80 invokeIf(Impl& impl) :
81 _impl(impl)
82 {}
83
84 };
85
86 //! \internal
87 template<typename Impl, typename resulttype>
88 struct invokeIf<false,Impl, resulttype,false> {
89
90 typedef resulttype result_type;
91
92 template<int codim>
invokeDune::mdgrid::detail::invokeIf93 result_type invoke() {
94 DUNE_THROW(GridError,"codim not supported");
95 }
96
97 Impl& _impl;
98
invokeIfDune::mdgrid::detail::invokeIf99 invokeIf(Impl& impl) :
100 _impl(impl)
101 {}
102
103 };
104
105 template<typename Impl, typename resulttype>
106 struct invokeIf<false,Impl, resulttype,true> {
107
108 typedef resulttype result_type;
109
110 template<int codim>
invokeDune::mdgrid::detail::invokeIf111 result_type invoke() {
112 return _impl.template invoke_unsupported<codim>();
113 }
114
115 Impl& _impl;
116
invokeIfDune::mdgrid::detail::invokeIf117 invokeIf(Impl& impl) :
118 _impl(impl)
119 {}
120
121 };
122
123 //! \internal Template meta program for dispatching a method to the correctly parameterised template method base on a run-time parameter
124 template<typename Impl, typename resulttype, typename MDGridTraits, int codim, bool protect = true, bool alternate_dispatch = false>
125 struct dispatchToCodim
126 : public dispatchToCodim<Impl,resulttype,MDGridTraits,codim-1,protect,alternate_dispatch> {
127
128 typedef resulttype result_type;
129
dispatchDune::mdgrid::detail::dispatchToCodim130 result_type dispatch(int cc) {
131 if (cc == codim)
132 return invokeIf<MDGridTraits::template Codim<codim>::supported,Impl,result_type,alternate_dispatch>(static_cast<Impl&>(*this)).template invoke<codim>();
133 return static_cast<dispatchToCodim<Impl,result_type,MDGridTraits,codim-1,protect,alternate_dispatch>&>(*this).dispatch(cc);
134 }
135
136 };
137
138 //! \internal Recursion limit for dispatchToCodim
139 template<typename Impl, typename resulttype, typename MDGridTraits, bool alternate_dispatch>
140 struct dispatchToCodim<Impl,resulttype,MDGridTraits,0,true,alternate_dispatch> {
141
142 typedef resulttype result_type;
143
dispatchDune::mdgrid::detail::dispatchToCodim144 result_type dispatch(int cc) {
145 if (cc == 0)
146 return invokeIf<MDGridTraits::template Codim<0>::supported,Impl,result_type,alternate_dispatch>(static_cast<Impl&>(*this)).template invoke<0>();
147 DUNE_THROW(GridError,"invalid codimension specified");
148 }
149
150 };
151
152 //! \internal Template meta program for dispatching a method to the correctly parameterised template method base on a run-time parameter
153 template<typename Impl, typename resulttype, typename MDGridTraits, int codim, bool alternate_dispatch>
154 struct dispatchToCodim<Impl,resulttype,MDGridTraits,codim,false,alternate_dispatch>
155 : public dispatchToCodim<Impl,resulttype,MDGridTraits,codim-1,false,alternate_dispatch> {
156
157 typedef resulttype result_type;
158
dispatchDune::mdgrid::detail::dispatchToCodim159 result_type dispatch(int cc) {
160 if (cc == codim)
161 return static_cast<Impl&>(*this).template invoke<codim>();
162 return static_cast<dispatchToCodim<Impl,result_type,MDGridTraits,codim-1,false,alternate_dispatch>&>(*this).dispatch(cc);
163 }
164
165 };
166
167 //! \internal Recursion limit for dispatchToCodim
168 template<typename Impl, typename resulttype, typename MDGridTraits, bool alternate_dispatch>
169 struct dispatchToCodim<Impl,resulttype,MDGridTraits,0,false,alternate_dispatch> {
170
171 typedef resulttype result_type;
172
dispatchDune::mdgrid::detail::dispatchToCodim173 result_type dispatch(int cc) {
174 if (cc == 0)
175 return static_cast<Impl&>(*this).template invoke<0>();
176 DUNE_THROW(GridError,"invalid codimension specified");
177 }
178
179 };
180
181 /**
182 * \internal Helper structure for protecting calls at non-supported codims, similar to invokeIf.
183 *
184 * The main difference is that failures are silently ignored and that the called method may not return anything.
185 */
186 template<bool doApply, typename Impl>
187 struct applyIf {
188
189 template<int codim, typename T>
applyDune::mdgrid::detail::applyIf190 void apply(T& t) const {
191 _impl.template apply<codim>(t);
192 }
193
194 Impl& _impl;
195
applyIfDune::mdgrid::detail::applyIf196 applyIf(Impl& impl) :
197 _impl(impl)
198 {}
199
200 };
201
202 //! \internal
203 template<typename Impl>
204 struct applyIf<false,Impl> {
205
206 template<int codim, typename T>
applyDune::mdgrid::detail::applyIf207 void apply(T& t) const {
208 }
209
210 Impl& _impl;
211
applyIfDune::mdgrid::detail::applyIf212 applyIf(Impl& impl) :
213 _impl(impl)
214 {}
215
216 };
217
218 //! \internal Little helper function for casting away constness. Avoids having to spell out the typename.
219 template<typename T>
rw(const T & t)220 T& rw(const T& t) {
221 return const_cast<T&>(t);
222 }
223
224 }
225
226 //! @endcond
227
228 /**
229 * Index set for the MultiDomainGrid.
230 */
231 template<typename GridImp, typename HostGridViewType>
232 class IndexSetWrapper :
233 public Dune::IndexSet<GridImp,IndexSetWrapper<GridImp,HostGridViewType>,
234 typename HostGridViewType::IndexSet::IndexType,
235 typename HostGridViewType::IndexSet::Types>
236 {
237
238 using Grid = std::remove_const_t<GridImp>;
239
240 template<typename, typename>
241 friend class IndexSetWrapper;
242
243 template<typename, typename>
244 friend class MultiDomainGrid;
245
246 template<typename, typename>
247 friend class subdomain::IndexSetWrapper;
248
249 template<typename, typename, typename, typename>
250 friend class SubDomainInterface;
251
252 template<typename>
253 friend class SubDomainToSubDomainController;
254
255 template<typename>
256 friend class AllInterfacesController;
257
258 typedef IndexSetWrapper<GridImp,HostGridViewType> ThisType;
259
260 using HostGrid = typename Grid::HostGrid;
261 typedef HostGridViewType HostGridView;
262 typedef typename HostGridView::IndexSet HostIndexSet;
263 using ctype = typename Grid::ctype;
264 using CellReferenceElement = Dune::ReferenceElement<typename HostGrid::template Codim<0>::Entity::Geometry>;
265
266 typedef Dune::IndexSet<
267 GridImp,
268 IndexSetWrapper<
269 GridImp,
270 HostGridViewType
271 >,
272 typename HostGridViewType::IndexSet::IndexType,
273 typename HostGridViewType::IndexSet::Types
274 > BaseT;
275
276 public:
277
278 typedef typename BaseT::Types Types;
279
280 using MDGridTraits = typename Grid::MDGridTraits;
281 typedef typename MDGridTraits::template Codim<0>::SubDomainSet SubDomainSet;
282 typedef typename MDGridTraits::SubDomainIndex SubDomainIndex;
283
284
285 typedef typename HostIndexSet::IndexType IndexType;
286 static const int dimension = Grid::dimension;
287 static const std::size_t maxSubDomains = SubDomainSet::maxSize;
288
289 private:
290
291 typedef typename HostGridView::template Codim<0>::Iterator HostEntityIterator;
292 typedef typename HostGridView::template Codim<0>::Entity HostEntity;
293 using Codim0Entity = typename Grid::Traits::template Codim<0>::Entity;
294
295 template<int cc>
296 struct MapEntry {
297
298 typedef typename MDGridTraits::template Codim<cc>::SubDomainSet SubDomainSet;
299
300 SubDomainSet domains;
301 IndexType index;
302 };
303
304 //! Placeholder struct for non-supported codimensions in data structures.
305 struct NotSupported {};
306
307 template<int codim>
308 struct Containers {
309
310 static const bool supported = Grid::MDGridTraits::template Codim<codim>::supported;
311
312 static_assert((codim > 0 || supported), "index mapping of codimension 0 must be supported!");
313
314 using IndexMap = std::conditional_t<
315 supported,
316 std::vector<std::vector<MapEntry<codim> > >,
317 NotSupported
318 >;
319
320 using SizeMap = std::conditional_t<
321 supported,
322 std::vector<typename Grid::MDGridTraits::template Codim<codim>::SizeContainer>,
323 NotSupported
324 >;
325
326 using CodimSizeMap = std::conditional_t<
327 supported,
328 typename Grid::MDGridTraits::template Codim<codim>::SizeContainer,
329 NotSupported
330 >;
331
332 using MultiIndexMap = std::conditional_t<
333 supported,
334 std::vector<typename Grid::MDGridTraits::template Codim<codim>::MultiIndexContainer>,
335 NotSupported
336 >;
337
338 IndexMap indexMap;
339 SizeMap sizeMap;
340 CodimSizeMap codimSizeMap;
341 MultiIndexMap multiIndexMap;
342
343 // containers should not be assignable...
344 Containers& operator=(const Containers&) = delete;
345
346 // ...but must be movable
347 Containers& operator=(Containers&&) = default;
348
349 // make sure the compiler generates all necessary constructors...
350 Containers(const Containers&) = default;
351 Containers(Containers&&) = default;
352 Containers() = default;
353
354 };
355
356 typedef typename detail::buildMap<Containers,dimension>::type ContainerMap;
357
358 typedef std::vector<std::shared_ptr<IndexSetWrapper<GridImp, typename HostGridView::Grid::LevelGridView> > > LevelIndexSets;
359
360 //! Convenience subclass of dispatchToCodim for automatically passing in the MDGridTraits and the dimension
361 template<typename Impl,typename result_type, bool protect = true, bool alternate_dispatch = false>
362 struct dispatchToCodim : public detail::dispatchToCodim<Impl,result_type,MDGridTraits,dimension,protect,alternate_dispatch> {};
363
364 public:
365
366 //! Returns the index of the entity with codimension codim.
367 template<int codim>
index(const typename Grid::Traits::template Codim<codim>::Entity & e) const368 IndexType index(const typename Grid::Traits::template Codim<codim>::Entity& e) const {
369 return _hostGridView.indexSet().index(_grid.hostEntity(e));
370 }
371
372 //! Returns the index of the entity.
373 template<typename Entity>
index(const Entity & e) const374 IndexType index(const Entity& e) const {
375 return _hostGridView.indexSet().index(_grid.hostEntity(e));
376 }
377
378 //! Returns the subdindex of the i-th subentity of e with codimension codim.
379 template<int codim, typename Entity>
subIndex(const Entity & e,int i) const380 IndexType subIndex(const Entity& e, int i) const {
381 return _hostGridView.indexSet().subIndex(_grid.hostEntity(e),i,codim);
382 }
383
384 //! Returns the subdindex of the i-th subentity of e with codimension codim.
385 template<typename Entity>
subIndex(const Entity & e,int i,unsigned int codim) const386 IndexType subIndex(const Entity& e, int i, unsigned int codim) const {
387 IndexType r = _hostGridView.indexSet().subIndex(_grid.hostEntity(e),i,codim);
388 return r;
389 }
390
391 //! Returns a list of all geometry types with codimension codim contained in the grid.
types(int codim) const392 Types types(int codim) const {
393 return _hostGridView.indexSet().types(codim);
394 }
395
396 //! Returns the number of entities with GeometryType type in the grid.
size(GeometryType type) const397 IndexType size(GeometryType type) const {
398 return _hostGridView.indexSet().size(type);
399 }
400
401 //! Returns the number of entities with codimension codim in the grid.
size(int codim) const402 IndexType size(int codim) const {
403 return _hostGridView.indexSet().size(codim);
404 }
405
406 //! Returns true if the entity is contained in the grid.
407 template<typename EntityType>
contains(const EntityType & e) const408 bool contains(const EntityType& e) const {
409 return _hostGridView.indexSet().contains(_grid.hostEntity(e));
410 }
411
412 //! Returns a constant reference to the SubDomainSet of the given entity.
413 template<typename EntityType>
subDomains(const EntityType & e) const414 const typename MapEntry<EntityType::codimension>::SubDomainSet& subDomains(const EntityType& e) const {
415 return subDomainsForHostEntity(_grid.hostEntity(e));
416 }
417
418 //! Returns a constant reference to the SubDomainSet of the given entity with codimension cc.
419 //! \tparam cc the codimension of the entity.
420 template<int cc>
subDomains(const typename Grid::Traits::template Codim<cc>::Entity & e) const421 const typename MapEntry<cc>::SubDomainSet& subDomains(const typename Grid::Traits::template Codim<cc>::Entity& e) const {
422 return subDomainsForHostEntity<cc>(_grid.hostEntity(e));
423 }
424
425 //! Returns the index of the entity in a specific subdomain.
426 template<class EntityType>
index(SubDomainIndex subDomain,const EntityType & e) const427 IndexType index(SubDomainIndex subDomain, const EntityType& e) const {
428 return index<EntityType::codimension>(subDomain,e);
429 }
430
431 //! Returns the index of the entity with codimension cc in a specific subdomain.
432 //! \tparam the codimension of the entity.
433 template<int cc>
index(SubDomainIndex subDomain,const typename Grid::Traits::template Codim<cc>::Entity & e) const434 IndexType index(SubDomainIndex subDomain, const typename Grid::Traits::template Codim<cc>::Entity& e) const {
435 GeometryType gt = e.type();
436 IndexType hostIndex = _hostGridView.indexSet().index(_grid.hostEntity(e));
437 const MapEntry<cc>& me = indexMap<cc>()[LocalGeometryTypeIndex::index(gt)][hostIndex];
438 assert(me.domains.contains(subDomain));
439 if (me.domains.simple()) {
440 return me.index;
441 } else {
442 return multiIndexMap<cc>()[me.index][me.domains.domainOffset(subDomain)];
443 }
444 }
445
446 private:
447
448 //! Returns a mutable reference to the SubDomainSet of the given entity.
449 template<typename EntityType>
subDomains(const EntityType & e)450 typename MapEntry<EntityType::codimension>::SubDomainSet& subDomains(const EntityType& e) {
451 return subDomainsForHostEntity(_grid.hostEntity(e));
452 }
453
454 //! Returns a mutable reference to the SubDomainSet of the given entity with codimension cc.
455 //! \tparam cc the codimension of the entity.
456 template<int cc>
subDomains(const typename Grid::Traits::template Codim<cc>::Entity & e)457 typename MapEntry<cc>::SubDomainSet& subDomains(const typename Grid::Traits::template Codim<cc>::Entity& e) {
458 return subDomainsForHostEntity<cc>(_grid.hostEntity(e));
459 }
460
461 //! Returns a mutable reference to the SubDomainSet of the given host entity.
462 template<typename HostEntity>
subDomainsForHostEntity(const HostEntity & e)463 typename MapEntry<HostEntity::codimension>::SubDomainSet& subDomainsForHostEntity(const HostEntity& e) {
464 return subDomainsForHostEntity<HostEntity::codimension>(e);
465 }
466
467 //! Returns a mutable reference to the SubDomainSet of the given entity with codimension cc.
468 //! \tparam cc the codimension of the entity.
469 template<int cc>
subDomainsForHostEntity(const typename Grid::HostGrid::Traits::template Codim<cc>::Entity & he)470 typename MapEntry<cc>::SubDomainSet& subDomainsForHostEntity(const typename Grid::HostGrid::Traits::template Codim<cc>::Entity& he) {
471 return indexMap<cc>()[LocalGeometryTypeIndex::index(he.type())][_hostGridView.indexSet().index(he)].domains;
472 }
473
474 //! Returns a constant reference to the SubDomainSet of the given host entity.
475 template<typename HostEntity>
subDomainsForHostEntity(const HostEntity & e) const476 const typename MapEntry<HostEntity::codimension>::SubDomainSet& subDomainsForHostEntity(const HostEntity& e) const {
477 return subDomainsForHostEntity<HostEntity::codimension>(e);
478 }
479
480 //! Returns a constant reference to the SubDomainSet of the given entity with codimension cc.
481 //! \tparam cc the codimension of the entity.
482 template<int cc>
subDomainsForHostEntity(const typename Grid::HostGrid::Traits::template Codim<cc>::Entity & he) const483 const typename MapEntry<cc>::SubDomainSet& subDomainsForHostEntity(const typename Grid::HostGrid::Traits::template Codim<cc>::Entity& he) const {
484 return indexMap<cc>()[LocalGeometryTypeIndex::index(he.type())][_hostGridView.indexSet().index(he)].domains;
485 }
486
487 template<int cc>
indexForSubDomain(SubDomainIndex subDomain,const typename Grid::HostGrid::Traits::template Codim<cc>::Entity & he) const488 IndexType indexForSubDomain(SubDomainIndex subDomain, const typename Grid::HostGrid::Traits::template Codim<cc>::Entity& he) const {
489 const GeometryType gt = he.type();
490 const IndexType hostIndex = _hostGridView.indexSet().index(he);
491 const MapEntry<cc>& me = indexMap<cc>()[LocalGeometryTypeIndex::index(gt)][hostIndex];
492 assert(me.domains.contains(subDomain));
493 if (me.domains.simple()) {
494 return me.index;
495 } else {
496 return multiIndexMap<cc>()[me.index][me.domains.domainOffset(subDomain)];
497 }
498 }
499
500 //! functor template for retrieving a subindex.
501 struct getSubIndexForSubDomain : public dispatchToCodim<getSubIndexForSubDomain,IndexType> {
502
503 template<int codim>
invokeDune::mdgrid::IndexSetWrapper::getSubIndexForSubDomain504 IndexType invoke() const {
505 const MapEntry<codim>& me = _indexSet.indexMap<codim>()[LocalGeometryTypeIndex::index(_gt)][_hostIndex];
506 assert(me.domains.contains(_subDomain));
507 if (me.domains.simple()) {
508 return me.index;
509 } else {
510 return _indexSet.multiIndexMap<codim>()[me.index][me.domains.domainOffset(_subDomain)];
511 }
512 }
513
514 SubDomainIndex _subDomain;
515 GeometryType _gt;
516 IndexType _hostIndex;
517 const ThisType& _indexSet;
518
getSubIndexForSubDomainDune::mdgrid::IndexSetWrapper::getSubIndexForSubDomain519 getSubIndexForSubDomain(SubDomainIndex subDomain, GeometryType gt, IndexType hostIndex, const ThisType& indexSet) :
520 _subDomain(subDomain),
521 _gt(gt),
522 _hostIndex(hostIndex),
523 _indexSet(indexSet)
524 {}
525
526 };
527
528 template<typename HostEntity>
subIndexForSubDomain(SubDomainIndex subDomain,const HostEntity & he,int i,int codim) const529 IndexType subIndexForSubDomain(SubDomainIndex subDomain, const HostEntity& he, int i, int codim) const {
530 return getSubIndexForSubDomain(subDomain,
531 referenceElement(he.geometry()).type(i,codim - he.codimension),
532 _hostGridView.indexSet().subIndex(he,i,codim),
533 *this).dispatch(codim);
534 }
535
typesForSubDomain(SubDomainIndex subDomain,int codim) const536 Types typesForSubDomain(SubDomainIndex subDomain, int codim) const {
537 return types(codim);
538 }
539
540 struct getGeometryTypeSizeForSubDomain : public dispatchToCodim<getGeometryTypeSizeForSubDomain,IndexType,true,true> {
541
542 template<int codim>
invokeDune::mdgrid::IndexSetWrapper::getGeometryTypeSizeForSubDomain543 IndexType invoke() const {
544 return _indexSet.sizeMap<codim>()[LocalGeometryTypeIndex::index(_gt)][_subDomain];
545 }
546
547 template<int codim>
invoke_unsupportedDune::mdgrid::IndexSetWrapper::getGeometryTypeSizeForSubDomain548 IndexType invoke_unsupported() const {
549 return 0;
550 }
551
552 SubDomainIndex _subDomain;
553 GeometryType _gt;
554 const ThisType& _indexSet;
555
getGeometryTypeSizeForSubDomainDune::mdgrid::IndexSetWrapper::getGeometryTypeSizeForSubDomain556 getGeometryTypeSizeForSubDomain(SubDomainIndex subDomain, GeometryType gt, const ThisType& indexSet) :
557 _subDomain(subDomain),
558 _gt(gt),
559 _indexSet(indexSet)
560 {}
561
562 };
563
sizeForSubDomain(SubDomainIndex subDomain,GeometryType type) const564 IndexType sizeForSubDomain(SubDomainIndex subDomain, GeometryType type) const {
565 return getGeometryTypeSizeForSubDomain(subDomain,type,*this).dispatch(dimension-type.dim());
566 }
567
568 struct getCodimSizeForSubDomain : public dispatchToCodim<getCodimSizeForSubDomain,IndexType,true,true> {
569
570 template<int codim>
invokeDune::mdgrid::IndexSetWrapper::getCodimSizeForSubDomain571 IndexType invoke() const {
572 return _indexSet.codimSizes<codim>()[_subDomain];
573 }
574
575 template<int codim>
invoke_unsupportedDune::mdgrid::IndexSetWrapper::getCodimSizeForSubDomain576 IndexType invoke_unsupported() const {
577 return 0;
578 }
579
580 SubDomainIndex _subDomain;
581 const ThisType& _indexSet;
582
getCodimSizeForSubDomainDune::mdgrid::IndexSetWrapper::getCodimSizeForSubDomain583 getCodimSizeForSubDomain(SubDomainIndex subDomain, const ThisType& indexSet) :
584 _subDomain(subDomain),
585 _indexSet(indexSet)
586 {}
587
588 };
589
sizeForSubDomain(SubDomainIndex subDomain,int codim) const590 IndexType sizeForSubDomain(SubDomainIndex subDomain, int codim) const {
591 return getCodimSizeForSubDomain(subDomain,*this).dispatch(codim);
592 }
593
594 template<typename EntityType>
containsForSubDomain(SubDomainIndex subDomain,const EntityType & he) const595 bool containsForSubDomain(SubDomainIndex subDomain, const EntityType& he) const {
596 const GeometryType gt = he.type();
597 const IndexType hostIndex = _hostGridView.indexSet().index(he);
598 const MapEntry<EntityType::codimension>& me = indexMap<EntityType::codimension>()[LocalGeometryTypeIndex::index(gt)][hostIndex];
599 return me.domains.contains(subDomain);
600 }
601
602 public:
603
604 template<typename SubDomainEntity>
subIndex(SubDomainIndex subDomain,const SubDomainEntity & e,int i,int codim) const605 IndexType subIndex(SubDomainIndex subDomain, const SubDomainEntity& e, int i, int codim) const {
606 return subIndexForSubDomain(subDomain,_grid.hostEntity(e),i,codim);
607 }
608
types(SubDomainIndex subDomain,int codim) const609 Types types(SubDomainIndex subDomain, int codim) const {
610 return types(codim);
611 }
612
size(SubDomainIndex subDomain,GeometryType type) const613 IndexType size(SubDomainIndex subDomain, GeometryType type) const {
614 return sizeForSubDomain(subDomain,type);
615 }
616
size(SubDomainIndex subDomain,int codim) const617 IndexType size(SubDomainIndex subDomain, int codim) const {
618 return sizeForSubDomain(subDomain,codim);
619 }
620
621 //! Returns true if the entity is contained in a specific subdomain.
622 template<typename EntityType>
contains(SubDomainIndex subDomain,const EntityType & e) const623 bool contains(SubDomainIndex subDomain, const EntityType& e) const {
624 const GeometryType gt = e.type();
625 const IndexType hostIndex = _hostGridView.indexSet().index(_grid.hostEntity(e));
626 const MapEntry<EntityType::codimension>& me = indexMap<EntityType::codimension>()[LocalGeometryTypeIndex::index(gt)][hostIndex];
627 return me.domains.contains(subDomain);
628 }
629
630 private:
631
632 const GridImp& _grid;
633 HostGridView _hostGridView;
634 ContainerMap _containers;
635
swap(ThisType & rhs)636 void swap(ThisType& rhs) {
637 assert(&_grid == &rhs._grid);
638 std::swap(_containers,rhs._containers);
639 }
640
addToSubDomain(SubDomainIndex subDomain,const Codim0Entity & e)641 void addToSubDomain(SubDomainIndex subDomain, const Codim0Entity& e) {
642 GeometryType gt = e.type();
643 IndexType hostIndex = _hostGridView.indexSet().index(_grid.hostEntity(e));
644 indexMap<0>()[LocalGeometryTypeIndex::index(gt)][hostIndex].domains.add(subDomain);
645 }
646
removeFromSubDomain(SubDomainIndex subDomain,const Codim0Entity & e)647 void removeFromSubDomain(SubDomainIndex subDomain, const Codim0Entity& e) {
648 GeometryType gt = e.type();
649 IndexType hostIndex = _hostGridView.indexSet().index(_grid.hostEntity(e));
650 indexMap<0>()[LocalGeometryTypeIndex::index(gt)][hostIndex].domains.remove(subDomain);
651 }
652
removeFromAllSubDomains(const Codim0Entity & e)653 void removeFromAllSubDomains(const Codim0Entity& e) {
654 GeometryType gt = e.type();
655 IndexType hostIndex = _hostGridView.indexSet().index(_grid.hostEntity(e));
656 indexMap<0>()[LocalGeometryTypeIndex::index(gt)][hostIndex].domains.clear();
657 }
658
assignToSubDomain(SubDomainIndex subDomain,const Codim0Entity & e)659 void assignToSubDomain(SubDomainIndex subDomain, const Codim0Entity& e) {
660 GeometryType gt = e.type();
661 IndexType hostIndex = _hostGridView.indexSet().index(_grid.hostEntity(e));
662 indexMap<0>()[LocalGeometryTypeIndex::index(gt)][hostIndex].domains.set(subDomain);
663 }
664
addToSubDomains(const typename MDGridTraits::template Codim<0>::SubDomainSet & subDomains,const Codim0Entity & e)665 void addToSubDomains(const typename MDGridTraits::template Codim<0>::SubDomainSet& subDomains, const Codim0Entity& e) {
666 GeometryType gt = e.type();
667 IndexType hostIndex = _hostGridView.indexSet().index(_grid.hostEntity(e));
668 indexMap<0>()[LocalGeometryTypeIndex::index(gt)][hostIndex].domains.addAll(subDomains);
669 }
670
671 public:
672
673 // just make these public for std::make_shared() access
674
IndexSetWrapper(const GridImp & grid,HostGridView hostGridView)675 IndexSetWrapper(const GridImp& grid, HostGridView hostGridView) :
676 _grid(grid),
677 _hostGridView(hostGridView)
678 {}
679
IndexSetWrapper(const ThisType & rhs)680 explicit IndexSetWrapper(const ThisType& rhs) :
681 _grid(rhs._grid),
682 _hostGridView(rhs._hostGridView),
683 _containers(rhs._containers)
684 {}
685
686 private:
687
688 //! Returns the index map for the given codimension.
689 //! \tparam cc The requested codimension.
690 template<int cc>
indexMap()691 typename Containers<cc>::IndexMap& indexMap() {
692 return std::get<cc>(_containers).indexMap;
693 }
694
695 template<int cc>
sizeMap()696 typename Containers<cc>::SizeMap& sizeMap() {
697 return std::get<cc>(_containers).sizeMap;
698 }
699
700 template<int cc>
codimSizes()701 typename Containers<cc>::CodimSizeMap& codimSizes() {
702 return std::get<cc>(_containers).codimSizeMap;
703 }
704
705 template<int cc>
multiIndexMap()706 typename Containers<cc>::MultiIndexMap& multiIndexMap() {
707 return std::get<cc>(_containers).multiIndexMap;
708 }
709
710 template<int cc>
indexMap() const711 const typename Containers<cc>::IndexMap& indexMap() const {
712 return std::get<cc>(_containers).indexMap;
713 }
714
715 template<int cc>
sizeMap() const716 const typename Containers<cc>::SizeMap& sizeMap() const {
717 return std::get<cc>(_containers).sizeMap;
718 }
719
720 template<int cc>
codimSizes() const721 const typename Containers<cc>::CodimSizeMap& codimSizes() const {
722 return std::get<cc>(_containers).codimSizeMap;
723 }
724
725 template<int cc>
multiIndexMap() const726 const typename Containers<cc>::MultiIndexMap& multiIndexMap() const {
727 return std::get<cc>(_containers).multiIndexMap;
728 }
729
730 template<typename Functor>
applyToCodims(Functor func) const731 void applyToCodims(Functor func) const {
732 TypeTree::apply_to_tuple(
733 _containers,
734 func,
735 TypeTree::apply_to_tuple_policy::pass_index()
736 );
737 }
738
739 template<typename Functor>
applyToCodims(Functor func)740 void applyToCodims(Functor func) {
741 TypeTree::apply_to_tuple(
742 _containers,
743 func,
744 TypeTree::apply_to_tuple_policy::pass_index()
745 );
746 }
747
748 template<typename Impl>
749 struct applyToCodim {
750
751 template<typename I, typename T>
operator ()Dune::mdgrid::IndexSetWrapper::applyToCodim752 void operator()(I i, T&& t) const {
753 const int codim = I::value;
754 detail::applyIf<MDGridTraits::template Codim<codim>::supported,const Impl>(static_cast<const Impl&>(*this)).template apply<codim>(std::forward<T>(t));
755 }
756
757 };
758
759 struct resetPerCodim : public applyToCodim<resetPerCodim> {
760
761 template<int codim>
applyDune::mdgrid::IndexSetWrapper::resetPerCodim762 void apply(Containers<codim>& c) const {
763 // setup per-codim sizemap
764 _traits.template setupSizeContainer<codim>(c.codimSizeMap);
765 c.indexMap.resize(LocalGeometryTypeIndex::size(dimension-codim));
766 c.sizeMap.resize(LocalGeometryTypeIndex::size(dimension-codim));
767 for (auto gt : _his.types(codim)) {
768 const auto gt_index = LocalGeometryTypeIndex::index(gt);
769 if (_full) {
770 // resize index map
771 c.indexMap[gt_index].resize(_his.size(gt));
772 } else if (codim > 0) {
773 // clear out marked state for codim > 0 (we cannot keep the old
774 // state for subentities, as doing so will leave stale entries if
775 // elements are removed from a subdomain
776 for (auto& mapEntry : c.indexMap[gt_index])
777 mapEntry.domains.clear();
778 }
779 // setup / reset SizeMap counter
780 auto& size_map = c.sizeMap[gt_index];
781 _traits.template setupSizeContainer<codim>(size_map);
782 std::fill(size_map.begin(),size_map.end(),0);
783 }
784 // clear MultiIndexMap
785 c.multiIndexMap.clear();
786 }
787
resetPerCodimDune::mdgrid::IndexSetWrapper::resetPerCodim788 resetPerCodim(bool full, const HostIndexSet& his, const MDGridTraits& traits) :
789 _full(full),
790 _his(his),
791 _traits(traits)
792 {}
793
794 const bool _full;
795 const HostIndexSet& _his;
796 const MDGridTraits& _traits;
797 };
798
reset(bool full)799 void reset(bool full) {
800 const HostIndexSet& his = _hostGridView.indexSet();
801 if (full) {
802 ContainerMap cm = ContainerMap();
803 std::swap(_containers,cm);
804 }
805 applyToCodims(resetPerCodim(full,his,_grid._traits));
806 }
807
808 struct updatePerCodimSizes : public applyToCodim<updatePerCodimSizes> {
809
810 template<int codim>
applyDune::mdgrid::IndexSetWrapper::updatePerCodimSizes811 void apply(Containers<codim>& c) const {
812 // reset size for this codim to zero
813 std::fill(c.codimSizeMap.begin(),c.codimSizeMap.end(),0);
814 // collect per-geometrytype sizes into codim size structure
815 std::for_each(c.sizeMap.begin(),
816 c.sizeMap.end(),
817 util::collect_elementwise<std::plus<IndexType> >(c.codimSizeMap));
818 }
819
820 };
821
update(LevelIndexSets & levelIndexSets,bool full)822 void update(LevelIndexSets& levelIndexSets, bool full) {
823 const HostIndexSet& his = _hostGridView.indexSet();
824 //reset(full);
825 for (typename LevelIndexSets::iterator it = levelIndexSets.begin(); it != levelIndexSets.end(); ++it) {
826 (*it)->reset(full);
827 }
828
829 this->communicateSubDomainSelection();
830
831 typename Containers<0>::IndexMap& im = indexMap<0>();
832 typename Containers<0>::SizeMap& sm = sizeMap<0>();
833 for (const auto& he : elements(_hostGridView)) {
834 auto geo = he.geometry();
835 auto hgt = geo.type();
836 const auto hgt_index = LocalGeometryTypeIndex::index(hgt);
837 IndexType hostIndex = his.index(he);
838 MapEntry<0>& me = im[hgt_index][hostIndex];
839
840 if (_grid.supportLevelIndexSets()) {
841 levelIndexSets[he.level()]->template indexMap<0>()[hgt_index][levelIndexSets[he.level()]->_hostGridView.indexSet().index(he)].domains.addAll(me.domains);
842 markAncestors(levelIndexSets,he,me.domains);
843 }
844 updateMapEntry(me,sm[hgt_index],multiIndexMap<0>());
845 applyToCodims(markSubIndices(he,me.domains,his,geo));
846 }
847
848 propagateBorderEntitySubDomains();
849
850 applyToCodims(updateSubIndices(*this));
851 applyToCodims(updatePerCodimSizes());
852 for(typename LevelIndexSets::iterator it = levelIndexSets.begin(); it != levelIndexSets.end(); ++it) {
853 (*it)->updateLevelIndexSet();
854 }
855 }
856
857
updateLevelIndexSet()858 void updateLevelIndexSet() {
859 const HostIndexSet& his = _hostGridView.indexSet();
860 typename Containers<0>::IndexMap& im = indexMap<0>();
861 typename Containers<0>::SizeMap& sm = sizeMap<0>();
862
863 communicateSubDomainSelection();
864
865 for (const auto& he : elements(_hostGridView)) {
866 auto geo = he.geometry();
867 const GeometryType hgt = geo.type();
868 const auto hgt_index = LocalGeometryTypeIndex::index(hgt);
869 IndexType hostIndex = his.index(he);
870 MapEntry<0>& me = im[hgt_index][hostIndex];
871 updateMapEntry(me,sm[hgt_index],multiIndexMap<0>());
872 applyToCodims(markSubIndices(he,me.domains,his,geo));
873 }
874
875 propagateBorderEntitySubDomains();
876
877 applyToCodims(updateSubIndices(*this));
878 applyToCodims(updatePerCodimSizes());
879 }
880
881 template<int codim, typename SizeContainer, typename MultiIndexContainer>
updateMapEntry(MapEntry<codim> & me,SizeContainer & sizes,std::vector<MultiIndexContainer> & multiIndexMap)882 void updateMapEntry(MapEntry<codim>& me, SizeContainer& sizes, std::vector<MultiIndexContainer>& multiIndexMap) {
883 switch (me.domains.state()) {
884 case MapEntry<codim>::SubDomainSet::emptySet:
885 break;
886 case MapEntry<codim>::SubDomainSet::simpleSet:
887 me.index = sizes[*me.domains.begin()]++;
888 break;
889 case MapEntry<codim>::SubDomainSet::multipleSet:
890 me.index = multiIndexMap.size();
891 multiIndexMap.push_back(MultiIndexContainer());
892 MultiIndexContainer& mic = multiIndexMap.back();
893 for (typename SubDomainSet::Iterator it = me.domains.begin(); it != me.domains.end(); ++it) {
894 mic[me.domains.domainOffset(*it)] = sizes[*it]++;
895 }
896 }
897 }
898
899 template<typename SubDomainSet>
markAncestors(LevelIndexSets & levelIndexSets,HostEntity he,const SubDomainSet & domains)900 void markAncestors(LevelIndexSets& levelIndexSets, HostEntity he, const SubDomainSet& domains) {
901 while (he.level() > 0) {
902 he = he.father();
903 SubDomainSet& fatherDomains =
904 levelIndexSets[he.level()]->template indexMap<0>()[LocalGeometryTypeIndex::index(he.type())][levelIndexSets[he.level()]->_hostGridView.indexSet().index(he)].domains;
905 if (fatherDomains.containsAll(domains))
906 break;
907 fatherDomains.addAll(domains);
908 }
909 }
910
911 struct markSubIndices : public applyToCodim<const markSubIndices> {
912
913 template<int codim>
applyDune::mdgrid::IndexSetWrapper::markSubIndices914 void apply(Containers<codim>& c) const {
915 if (codim == 0)
916 return;
917 const int size = _refEl.size(codim);
918 for (int i = 0; i < size; ++i) {
919 IndexType hostIndex = _his.subIndex(_he,i,codim);
920 GeometryType gt = _refEl.type(i,codim);
921 c.indexMap[LocalGeometryTypeIndex::index(gt)][hostIndex].domains.addAll(_domains);
922 }
923 }
924
925 typedef typename MapEntry<0>::SubDomainSet& DomainSet;
926
927 const HostEntity& _he;
928 DomainSet& _domains;
929 const HostIndexSet& _his;
930 CellReferenceElement _refEl;
931
markSubIndicesDune::mdgrid::IndexSetWrapper::markSubIndices932 markSubIndices(const HostEntity& he, DomainSet& domains, const HostIndexSet& his, const typename HostEntity::Geometry& geo) :
933 _he(he),
934 _domains(domains),
935 _his(his),
936 _refEl(referenceElement(geo))
937 {}
938
939 };
940
941 struct updateSubIndices : public applyToCodim<const updateSubIndices> {
942
943 template<int codim>
applyDune::mdgrid::IndexSetWrapper::updateSubIndices944 void apply(Containers<codim>& c) const {
945 if (codim == 0)
946 return;
947 for (std::size_t gt_index = 0,
948 gt_end = c.indexMap.size();
949 gt_index != gt_end;
950 ++gt_index)
951 for (auto& im_entry : c.indexMap[gt_index])
952 _indexSet.updateMapEntry(im_entry,c.sizeMap[gt_index],c.multiIndexMap);
953 }
954
955 ThisType& _indexSet;
956
updateSubIndicesDune::mdgrid::IndexSetWrapper::updateSubIndices957 updateSubIndices(ThisType& indexSet) :
958 _indexSet(indexSet)
959 {}
960 };
961
962 //! functor template for retrieving a subindex.
963 struct getSupportsCodim : public dispatchToCodim<getSupportsCodim,bool,false> {
964
965 template<int codim>
invokeDune::mdgrid::IndexSetWrapper::getSupportsCodim966 bool invoke() const {
967 return MDGridTraits::template Codim<codim>::supported && Dune::Capabilities::hasEntity<HostGrid,codim>::v;
968 }
969
970 };
971
supportsCodim(int codim) const972 bool supportsCodim(int codim) const
973 {
974 return getSupportsCodim().dispatch(codim);
975 }
976
977 template<typename Impl>
978 struct SubDomainSetDataHandleBase
979 : public Dune::CommDataHandleIF<Impl,
980 typename MapEntry<0>::SubDomainSet::DataHandle::DataType
981 >
982 {
983 typedef typename MapEntry<0>::SubDomainSet SubDomainSet;
984 typedef typename SubDomainSet::DataHandle DataHandle;
985
fixedSizeDune::mdgrid::IndexSetWrapper::SubDomainSetDataHandleBase986 bool fixedSize(int dim, int codim) const
987 {
988 return DataHandle::fixedSize(dim,codim);
989 }
990
991 template<typename Entity>
sizeDune::mdgrid::IndexSetWrapper::SubDomainSetDataHandleBase992 std::size_t size(const Entity& e) const
993 {
994 return MapEntry<Entity::codimension>::SubDomainSet::DataHandle::size(_indexSet.subDomainsForHostEntity(e));
995 }
996
997 template<typename MessageBufferImp, typename Entity>
gatherDune::mdgrid::IndexSetWrapper::SubDomainSetDataHandleBase998 void gather(MessageBufferImp& buf, const Entity& e) const
999 {
1000 MapEntry<Entity::codimension>::SubDomainSet::DataHandle::gather(buf,_indexSet.subDomainsForHostEntity(e));
1001 }
1002
1003 template<typename MessageBufferImp, typename Entity>
scatterDune::mdgrid::IndexSetWrapper::SubDomainSetDataHandleBase1004 void scatter(MessageBufferImp& buf, const Entity& e, std::size_t n)
1005 {
1006 MapEntry<Entity::codimension>::SubDomainSet::DataHandle::scatter(buf,_indexSet.subDomainsForHostEntity(e),n);
1007 }
1008
SubDomainSetDataHandleBaseDune::mdgrid::IndexSetWrapper::SubDomainSetDataHandleBase1009 SubDomainSetDataHandleBase(ThisType& indexSet)
1010 : _indexSet(indexSet)
1011 {}
1012
1013 ThisType& _indexSet;
1014
1015 };
1016
1017 struct SelectionDataHandle
1018 : public SubDomainSetDataHandleBase<SelectionDataHandle>
1019 {
1020
containsDune::mdgrid::IndexSetWrapper::SelectionDataHandle1021 bool contains(int dim, int codim) const
1022 {
1023 return codim == 0;
1024 }
1025
SelectionDataHandleDune::mdgrid::IndexSetWrapper::SelectionDataHandle1026 SelectionDataHandle(ThisType& indexSet)
1027 : SubDomainSetDataHandleBase<SelectionDataHandle>(indexSet)
1028 {}
1029
1030 };
1031
1032 struct BorderPropagationDataHandle
1033 : public SubDomainSetDataHandleBase<BorderPropagationDataHandle>
1034 {
1035
containsDune::mdgrid::IndexSetWrapper::BorderPropagationDataHandle1036 bool contains(int dim, int codim) const
1037 {
1038 return codim > 0 && this->_indexSet.supportsCodim(codim);
1039 }
1040
BorderPropagationDataHandleDune::mdgrid::IndexSetWrapper::BorderPropagationDataHandle1041 BorderPropagationDataHandle(ThisType& indexSet)
1042 : SubDomainSetDataHandleBase<BorderPropagationDataHandle>(indexSet)
1043 {}
1044
1045 };
1046
1047
communicateSubDomainSelection()1048 void communicateSubDomainSelection()
1049 {
1050 SelectionDataHandle dh(*this);
1051 _hostGridView.template communicate<SelectionDataHandle>(dh,Dune::InteriorBorder_All_Interface,Dune::ForwardCommunication);
1052 }
1053
propagateBorderEntitySubDomains()1054 void propagateBorderEntitySubDomains()
1055 {
1056 BorderPropagationDataHandle dh(*this);
1057 _hostGridView.communicate(dh,Dune::InteriorBorder_All_Interface,Dune::ForwardCommunication);
1058 }
1059
1060 };
1061
1062 } // namespace mdgrid
1063
1064 } // namespace Dune
1065
1066 #endif // DUNE_MULTIDOMAINGRID_INDEXSETS_HH
1067