Loading [MathJax]/extensions/tex2jax.js

dune-mmesh (1.4)

indexsets.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_MMESH_INTERFACE_INDEXSETS_HH
4#define DUNE_MMESH_INTERFACE_INDEXSETS_HH
5
10// Dune includes
11#include <dune/grid/common/indexidset.hh>
13
14namespace Dune
15{
16
17 template<class GridImp>
18 class MMeshInterfaceGridLeafIndexSet :
19 public IndexSet<GridImp, MMeshInterfaceGridLeafIndexSet<GridImp>>
20 {
21 typedef typename std::remove_const<GridImp>::type::HostGridType HostGrid;
22
23 template<int codim>
24 using HostGridEntity = typename GridImp::template MMeshInterfaceEntity<codim>;
25
26 public:
27 typedef std::size_t IndexType;
28 typedef const std::vector< GeometryType > Types;
29
30 /*
31 * We use the remove_const to extract the Type from the mutable class,
32 * because the const class is not instantiated yet.
33 */
34 enum {dimensionworld = std::remove_const<GridImp>::type::dimensionworld};
35 enum {dimension = dimensionworld-1};
36
37 using LocalIndexMap = std::unordered_map< std::size_t, std::size_t >;
38 using IndexMap = std::unordered_map< std::array< std::size_t, dimension >, LocalIndexMap, HashUIntArray >;
39 using EdgeIndexMap = std::unordered_map< std::array< std::size_t, dimension >, std::size_t, HashUIntArray >;
40 using VertexIndexMap = std::unordered_map< std::size_t, std::size_t >;
41
43 MMeshInterfaceGridLeafIndexSet (const GridImp* grid)
44 : grid_(grid)
45 {}
46
47 MMeshInterfaceGridLeafIndexSet (const MMeshInterfaceGridLeafIndexSet& leafIndexSet)
48 : grid_(leafIndexSet.grid_),
49 sizeOfCodim_(leafIndexSet.sizeOfCodim_),
50 indexMap_(leafIndexSet.indexMap_),
51 edgeIndexMap_(leafIndexSet.edgeIndexMap_),
52 vertexIndices_(leafIndexSet.vertexIndices_)
53 {}
54
56 template<int codim>
57 std::enable_if_t< codim == 0, IndexType >
58 index (const Entity< codim, dimension, GridImp, MMeshInterfaceGridEntity>& e) const
59 {
60 auto hostEntity = e.impl().hostEntity();
61
62 // handle invalid entity (occurs with empty interface)
63 using HostGridHandle = typename GridImp::MMeshType::template HostGridEntity<0>;
64 if (!grid_->canBeMirrored(hostEntity))
65 {
66 if constexpr (dimension == 1)
67 return (hostEntity.first->vertex(0) == grid_->getMMesh().getHostGrid().finite_faces_end()->vertex(0)) ? 1 : 0;
68 else // dimension == 2
69 return (hostEntity.first->vertex(0) == grid_->getMMesh().getHostGrid().finite_cells_end()->vertex(0)) ? 1 : 0;
70 }
71
72 std::array<std::size_t, dimensionworld> ids;
73 for( int i = 0; i < dimensionworld; ++i )
74 try {
75 ids[i] = vertexIndices_.at( hostEntity.first->vertex((hostEntity.second+i+1)%(dimensionworld+1))->info().id );
76 } catch (std::exception &e) {
77 DUNE_THROW(InvalidStateException, e.what());
78 }
79 std::sort(ids.begin(), ids.end());
80
81 std::array<std::size_t, dimension> edgeIds;
82 for( int i = 0; i < dimension; ++i )
83 edgeIds[i] = ids[i];
84
85 try {
86 IndexType index = indexMap_.at( edgeIds ).at( ids[dimension] );
87 assert( index <= size(codim) );
88 return index;
89 } catch (std::exception &e) {
90 DUNE_THROW(InvalidStateException, e.what());
91 }
92 }
93
95 template<int codim>
96 std::enable_if_t< codim == 1 && dimension == 2, IndexType >
97 index (const Entity< codim, dimension, GridImp, MMeshInterfaceGridEntity>& e) const
98 {
99 auto hostEntity = e.impl().hostEntity();
100
101 std::array<std::size_t, 2> ids;
102 try {
103 ids[0] = vertexIndices_.at( hostEntity.first->vertex(hostEntity.second)->info().id );
104 ids[1] = vertexIndices_.at( hostEntity.first->vertex(hostEntity.third)->info().id );
105 } catch (std::exception &e) {
106 DUNE_THROW(InvalidStateException, e.what());
107 }
108 std::sort(ids.begin(), ids.end());
109
110 try {
111 IndexType index = edgeIndexMap_.at( ids );
112 assert( index <= size(codim) );
113 return index;
114 } catch (std::exception &e) {
115 DUNE_THROW(InvalidStateException, e.what());
116 }
117 }
118
120 template<int codim>
121 std::enable_if_t< codim == dimension, IndexType >
122 index (const Entity< codim, dimension, GridImp, MMeshInterfaceGridEntity>& e) const
123 {
124 auto hostEntity = e.impl().hostEntity();
125 IndexType index;
126 try {
127 index = vertexIndices_.at( hostEntity->info().id );
128 } catch (std::exception &e) {
129 DUNE_THROW(InvalidStateException, e.what());
130 }
131 assert( index <= size(codim) );
132 return index;
133 }
134
136 template<class Entity>
137 IndexType subIndex (const Entity& e, int i, int codim)
138 {
139 return subIndex< Entity::codimension >( e, i, codim );
140 }
141
143 template<int cc>
144 std::enable_if_t< cc == dimension, IndexType >
145 subIndex (const typename std::remove_const<GridImp>::type::Traits::template Codim<cc>::Entity& e, int i, int codim) const
146 {
147 assert( i == 0 && codim == dimension );
148 const HostGridEntity<dimension> hostEntity = e.impl().hostEntity();
149 try {
150 return vertexIndices_.at( hostEntity->info().id );
151 } catch (std::exception &e) {
152 DUNE_THROW(InvalidStateException, e.what());
153 }
154 };
155
157 template<int cc>
158 std::enable_if_t< cc == 0, IndexType > subIndex (const typename std::remove_const<GridImp>::type::Traits::template Codim<cc>::Entity& e, int i, int codim) const
159 {
160 assert ( codim >= 0 && codim <= dimension );
161
162 if ( codim == 0 )
163 return index( e );
164 else if ( codim == dimension )
165 return index( e.template subEntity<dimension>( i ) );
166 else if ( codim == 1 && dimension == 2)
167 return index( e.template subEntity<1>( i ) );
168 else
169 DUNE_THROW( NotImplemented, "SubIndices for codim == " << codim << " and dimension == " << dimension );
170
171 return 0;
172 }
173
175 template<int cc>
176 std::enable_if_t< cc != 0 && cc != dimension, IndexType > subIndex (const typename std::remove_const<GridImp>::type::Traits::template Codim<cc>::Entity& e, int i, int codim) const
177 {
178 DUNE_THROW( NotImplemented, "SubIndex for cc != 0." );
179 };
180
182 std::size_t size (GeometryType type) const
183 {
184 if( type == GeometryTypes::vertex )
185 return size(dimension);
186 else if( type == GeometryTypes::line )
187 return size(dimension-1);
188 else if( type == GeometryTypes::triangle )
189 return size(dimension-2);
190 else
191 return 0;
192 }
193
195 std::size_t size (int codim) const
196 {
197 assert( (0 <= codim) && (codim <= dimension) );
198 return sizeOfCodim_[codim];
199 }
200
202 const Types geomTypes (int codim) const
203 {
204 return types( codim );
205 }
206
208 Types types (int codim) const
209 {
210 switch ( dimension - codim ) {
211 case 0:
212 return {{ GeometryTypes::vertex }};
213 case 1:
214 return {{ GeometryTypes::line }};
215 case 2:
216 return {{ GeometryTypes::triangle }};
217 default:
218 DUNE_THROW(InvalidStateException, "Codim is not within 0 <= codim <= dimension.");
219 }
220 }
221
223 template< class EntityType >
224 bool contains (const EntityType& e) const
225 {
226 return grid_->isInterface( e );
227 }
228
230 template< int d = dimensionworld >
231 std::enable_if_t< d == 2, void >
232 update(const GridImp* grid)
233 {
234 grid_ = grid;
235 const auto& hostgrid = grid_->getHostGrid();
236
237 vertexIndices_.clear();
238 indexMap_.clear();
239
240 // Count the finite edges and build index map
241 std::size_t vertexCount = 0;
242 std::size_t elementCount = 0;
243 for (const auto& element : elements(grid_->leafGridView(), Partitions::all))
244 {
245 auto eh = &element.impl().hostEntity();
246 auto vh0 = eh->first->vertex((eh->second+1)%3);
247 auto vh1 = eh->first->vertex((eh->second+2)%3);
248
249 std::size_t idx0 = vh0->info().id;
250 std::size_t idx1 = vh1->info().id;
251
252 addVertexIndex( idx0, vertexCount );
253 addVertexIndex( idx1, vertexCount );
254
255 try {
256 std::size_t id0 = vertexIndices_.at( idx0 );
257 std::size_t id1 = vertexIndices_.at( idx1 );
258
259 // we store the indices for each vertex
260 indexMap_[{id0}].insert( { id1, elementCount } );
261 indexMap_[{id1}].insert( { id0, elementCount++ } );
262 } catch (std::exception &e) {
263 DUNE_THROW(InvalidStateException, e.what());
264 }
265 }
266
267 // Cache sizes since it is expensive to compute them
268 sizeOfCodim_[0] = elementCount;
269 sizeOfCodim_[1] = vertexCount;
270 }
271
272 private:
273 void addVertexIndex( std::size_t index, std::size_t& vertexCount )
274 {
275 auto it = vertexIndices_.find( index );
276 if ( it == vertexIndices_.end() )
277 vertexIndices_.insert( { index, vertexCount++ } );
278 }
279
280 public:
282 template< int d = dimensionworld >
283 std::enable_if_t< d == 3, void >
284 update(const GridImp* grid)
285 {
286 grid_ = grid;
287 const auto& hostgrid = grid_->getHostGrid();
288
289 vertexIndices_.clear();
290 indexMap_.clear();
291 edgeIndexMap_.clear();
292
293 // Count the finite edges and build index map
294 std::size_t vertexCount = 0;
295 std::size_t edgeCount = 0;
296 std::size_t elementCount = 0;
297 for (const auto& element : elements(grid_->leafGridView(), Partitions::all))
298 {
299 auto eh = &element.impl().hostEntity();
300 std::array<std::size_t, dimensionworld> ids;
301 for( int i = 0; i < dimensionworld; ++i )
302 {
303 std::size_t idx = eh->first->vertex((eh->second+i+1)%4)->info().id;
304 addVertexIndex( idx, vertexCount );
305 try {
306 ids[i] = vertexIndices_.at( idx );
307 } catch (std::exception &e) {
308 DUNE_THROW(InvalidStateException, e.what());
309 }
310 }
311 std::sort(ids.begin(), ids.end());
312
313 // we store the indices for each codim 1 edge
314 indexMap_[{ids[0], ids[1]}].insert( { ids[2], elementCount } );
315 indexMap_[{ids[1], ids[2]}].insert( { ids[0], elementCount } );
316 indexMap_[{ids[0], ids[2]}].insert( { ids[1], elementCount++ } );
317
318 // store the index for edges
319 for( int i = 0; i < 3; ++ i )
320 {
321 std::array<std::size_t, dimension> edgeIds;
322 edgeIds[0] = ids[i];
323 edgeIds[1] = ids[(i+1)%3];
324 std::sort(edgeIds.begin(), edgeIds.end());
325
326 if ( edgeIndexMap_.count( edgeIds ) == 0 )
327 edgeIndexMap_.insert( { edgeIds, edgeCount++ } );
328 }
329 }
330
331 // Cache sizes since it is expensive to compute them
332 sizeOfCodim_[0] = elementCount;
333 sizeOfCodim_[1] = edgeCount;
334 sizeOfCodim_[2] = vertexCount;
335 }
336
337 const IndexMap& indexMap() const
338 {
339 return indexMap_;
340 }
341
342 const VertexIndexMap& vertexIndexMap() const
343 {
344 return vertexIndices_;
345 }
346
347 private:
348 GridImp* grid_;
349 std::array<std::size_t, dimension+1> sizeOfCodim_;
350 IndexMap indexMap_;
351 EdgeIndexMap edgeIndexMap_;
352 VertexIndexMap vertexIndices_;
353 };
354
355 template <class GridImp>
356 class MMeshInterfaceGridGlobalIdSet :
357 public IdSet<GridImp, MMeshInterfaceGridGlobalIdSet<GridImp>, MMeshImpl::MultiId>
358 {
359 typedef typename std::remove_const<GridImp>::type::HostGridType HostGrid;
360
361 /*
362 * We use the remove_const to extract the Type from the mutable class,
363 * because the const class is not instantiated yet.
364 */
365 enum {dimensionworld = std::remove_const<GridImp>::type::dimensionworld};
366 enum {dimension = dimensionworld-1};
367
368 template<int codim>
369 using HostGridEntity = typename GridImp::template MMeshInterfaceEntity<codim>;
370
371 public:
373 MMeshInterfaceGridGlobalIdSet (const GridImp* g)
374 {}
375
377 using IdType = MMeshImpl::MultiId;
378
380 /*
381 We use the remove_const to extract the Type from the mutable class,
382 because the const class is not instantiated yet.
383 */
384 template< int cd >
385 IdType id (const typename std::remove_const<GridImp>::type::Traits::template Codim<cd>::Entity& e) const
386 {
387 return id( e );
388 }
389
390 IdType id (const typename std::remove_const<GridImp>::type::Traits::template Codim<0>::Entity& e) const
391 {
392 return IdType( e.impl().id() );
393 }
394
395 template< int d = dimension >
396 std::enable_if_t< d == 2, IdType > id (const typename std::remove_const<GridImp>::type::Traits::template Codim<1>::Entity& e) const
397 {
398 const auto& host = e.impl().hostEntity();
399 return id( host );
400 }
401
403 template< int cd >
404 IdType id (const typename std::remove_const<GridImp>::type::MMeshType::Traits::template Codim<cd>::Entity& e) const
405 {
406 static_assert( cd == dimension );
407 const auto& host = e.impl().hostEntity();
408 return id( host );
409 }
410
411 template< int d = dimensionworld >
412 std::enable_if_t< d == 3, IdType >
413 id (const typename std::remove_const<GridImp>::type::template MMeshInterfaceEntity<1>& host) const
414 {
415 std::vector< std::size_t > ids ( 2 );
416 ids[0] = host.first->vertex(host.second)->info().id;
417 ids[1] = host.first->vertex(host.third)->info().id;
418 std::sort( ids.begin(), ids.end() );
419 return IdType( ids );
420 }
421
422 IdType id (const typename std::remove_const<GridImp>::type::Traits::template Codim<dimension>::Entity& e) const
423 {
424 return { e.impl().hostEntity()->info().id };
425 }
426
428 /*
429 We use the remove_const to extract the Type from the mutable class,
430 because the const class is not instantiated yet.
431 */
432 IdType subId (const typename std::remove_const<GridImp>::type::Traits::template Codim<0>::Entity& e, int i, int codim) const
433 {
434 assert( 0 <= codim && codim <= dimension );
435 IdType dummyId ( { std::size_t(-3), std::size_t(-2) } );
436
437 if( codim == 0 )
438 return e.impl().id();
439
440 if constexpr (dimension == 1)
441 {
442 // ( codim == 1 )
443 {
444 if (e.impl().id() != dummyId )
445 return e.impl().id().vt()[i];
446 else
447 return IdType( std::size_t(-3 + i) );
448 }
449 }
450 else // (dimension == 2)
451 {
452 if ( codim == 1 )
453 return id<1>( e.impl().template subEntity<1>( i ) );
454
455 if( codim == 2 )
456 return id<2>( e.impl().template subEntity<2>( i ) );
457 }
458
459 DUNE_THROW( NotImplemented, "InterfaceGrid: subId of codim != 0 or codim != 1 or codim != 2" );
460 return IdType();
461 }
462
464 void update(const GridImp* grid) {}
465 };
466
467} // end namespace Dune
468
469#endif
The multi id class.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Apr 6, 22:49, 2025)