dune-mmesh (unstable)

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