version 3.11-dev
Loading...
Searching...
No Matches
boxgeometryhelper.hh
Go to the documentation of this file.
1// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2// vi: set et ts=4 sw=4 sts=4:
3//
4// SPDX-FileCopyrightText: Copyright © DuMux Project contributors, see AUTHORS.md in root folder
5// SPDX-License-Identifier: GPL-3.0-or-later
6//
13#ifndef DUMUX_DISCRETIZATION_BOX_GEOMETRY_HELPER_HH
14#define DUMUX_DISCRETIZATION_BOX_GEOMETRY_HELPER_HH
15
16#include <array>
17
18#include <dune/common/exceptions.hh>
19
20#include <dune/geometry/type.hh>
21#include <dune/geometry/typeindex.hh>
22#include <dune/geometry/referenceelements.hh>
23#include <dune/geometry/multilineargeometry.hh>
24
25#include <dune/common/rangeutilities.hh>
26
28#include <dumux/common/math.hh>
31
32namespace Dumux {
33
35template <class ct>
36struct BoxMLGeometryTraits : public Dune::MultiLinearGeometryTraits<ct>
37{
38 // we use static vectors to store the corners as we know
39 // the number of corners in advance (2^(mydim) corners (1<<(mydim))
40 template< int mydim, int cdim >
42 {
43 using Type = std::array< Dune::FieldVector< ct, cdim >, (1<<(mydim)) >;
44 };
45
46 // we know all scvfs will have the same geometry type
47 template< int mydim >
49 {
50 static const bool v = true;
51 static const unsigned int topologyId = Dune::GeometryTypes::cube(mydim).id();
52 };
53};
54
55namespace Detail::Box {
56
57template<Dune::GeometryType::Id gt>
59
60template<>
61struct ScvCorners<Dune::GeometryTypes::line>
62{
63 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
64 static constexpr std::array<std::array<Key, 2>, 2> keys = {{
65 { Key{0, 1}, Key{0, 0} },
66 { Key{1, 1}, Key{0, 0} }
67 }};
68};
69
70template<>
71struct ScvCorners<Dune::GeometryTypes::triangle>
72{
73 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
74 static constexpr std::array<std::array<Key, 4>, 3> keys = {{
75 { Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
76 { Key{1, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
77 { Key{2, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} }
78 }};
79};
80
81template<>
82struct ScvCorners<Dune::GeometryTypes::quadrilateral>
83{
84 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
85 static constexpr std::array<std::array<Key, 4>, 4> keys = {{
86 { Key{0, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
87 { Key{1, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
88 { Key{2, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
89 { Key{3, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} }
90 }};
91};
92
93template<>
94struct ScvCorners<Dune::GeometryTypes::tetrahedron>
95{
96 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
97 static constexpr std::array<std::array<Key, 8>, 4> keys = {{
98 { Key{0, 3}, Key{0, 2}, Key{1, 2}, Key{0, 1}, Key{3, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
99 { Key{1, 3}, Key{2, 2}, Key{0, 2}, Key{0, 1}, Key{4, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
100 { Key{2, 3}, Key{1, 2}, Key{2, 2}, Key{0, 1}, Key{5, 2}, Key{2, 1}, Key{3, 1}, Key{0, 0} },
101 { Key{3, 3}, Key{3, 2}, Key{5, 2}, Key{2, 1}, Key{4, 2}, Key{1, 1}, Key{3, 1}, Key{0, 0} }
102 }};
103};
104
105template<>
106struct ScvCorners<Dune::GeometryTypes::prism>
107{
108 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
109 static constexpr std::array<std::array<Key, 8>, 6> keys = {{
110 { Key{0, 3}, Key{3, 2}, Key{4, 2}, Key{3, 1}, Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
111 { Key{1, 3}, Key{5, 2}, Key{3, 2}, Key{3, 1}, Key{1, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
112 { Key{2, 3}, Key{4, 2}, Key{5, 2}, Key{3, 1}, Key{2, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
113 { Key{3, 3}, Key{7, 2}, Key{6, 2}, Key{4, 1}, Key{0, 2}, Key{1, 1}, Key{0, 1}, Key{0, 0} },
114 { Key{4, 3}, Key{6, 2}, Key{8, 2}, Key{4, 1}, Key{1, 2}, Key{0, 1}, Key{2, 1}, Key{0, 0} },
115 { Key{5, 3}, Key{8, 2}, Key{7, 2}, Key{4, 1}, Key{2, 2}, Key{2, 1}, Key{1, 1}, Key{0, 0} }
116 }};
117};
118
119template<>
120struct ScvCorners<Dune::GeometryTypes::hexahedron>
121{
122 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
123 static constexpr std::array<std::array<Key, 8>, 8> keys = {{
124 { Key{0, 3}, Key{6, 2}, Key{4, 2}, Key{4, 1}, Key{0, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
125 { Key{1, 3}, Key{5, 2}, Key{6, 2}, Key{4, 1}, Key{1, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
126 { Key{2, 3}, Key{4, 2}, Key{7, 2}, Key{4, 1}, Key{2, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
127 { Key{3, 3}, Key{7, 2}, Key{5, 2}, Key{4, 1}, Key{3, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
128 { Key{4, 3}, Key{8, 2}, Key{10, 2}, Key{5, 1}, Key{0, 2}, Key{0, 1}, Key{2, 1}, Key{0, 0} },
129 { Key{5, 3}, Key{10, 2}, Key{9, 2}, Key{5, 1}, Key{1, 2}, Key{2, 1}, Key{1, 1}, Key{0, 0} },
130 { Key{6, 3}, Key{11, 2}, Key{8, 2}, Key{5, 1}, Key{2, 2}, Key{3, 1}, Key{0, 1}, Key{0, 0} },
131 { Key{7, 3}, Key{9, 2}, Key{11, 2}, Key{5, 1}, Key{3, 2}, Key{1, 1}, Key{3, 1}, Key{0, 0} }
132 }};
133};
134
135template<Dune::GeometryType::Id gt>
137
138template<>
139struct ScvfCorners<Dune::GeometryTypes::line>
140{
141 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
142 static constexpr std::array<std::array<Key, 1>, 1> keys = {{
143 { Key{0, 0} }
144 }};
145};
146
147template<>
148struct ScvfCorners<Dune::GeometryTypes::triangle>
149{
150 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
151 static constexpr std::array<std::array<Key, 2>, 3> keys = {{
152 { Key{0, 0}, Key{0, 1} },
153 { Key{1, 1}, Key{0, 0} },
154 { Key{0, 0}, Key{2, 1} }
155 }};
156};
157
158template<>
159struct ScvfCorners<Dune::GeometryTypes::quadrilateral>
160{
161 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
162 static constexpr std::array<std::array<Key, 2>, 4> keys = {{
163 { Key{0, 1}, Key{0, 0} },
164 { Key{0, 0}, Key{1, 1} },
165 { Key{0, 0}, Key{2, 1} },
166 { Key{3, 1}, Key{0, 0} }
167 }};
168};
169
170template<>
171struct ScvfCorners<Dune::GeometryTypes::tetrahedron>
172{
173 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
174 static constexpr std::array<std::array<Key, 4>, 6> keys = {{
175 { Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
176 { Key{0, 1}, Key{1, 2}, Key{0, 0}, Key{2, 1} },
177 { Key{2, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
178 { Key{2, 1}, Key{3, 2}, Key{0, 0}, Key{1, 1} },
179 { Key{3, 1}, Key{0, 0}, Key{4, 2}, Key{1, 1} },
180 { Key{5, 2}, Key{2, 1}, Key{3, 1}, Key{0, 0} }
181 }};
182};
183
184template<>
185struct ScvfCorners<Dune::GeometryTypes::prism>
186{
187 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
188 static constexpr std::array<std::array<Key, 4>, 9> keys = {{
189 { Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
190 { Key{1, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
191 { Key{2, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
192 { Key{3, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
193 { Key{4, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
194 { Key{5, 2}, Key{2, 1}, Key{3, 1}, Key{0, 0} },
195 { Key{6, 2}, Key{4, 1}, Key{0, 1}, Key{0, 0} },
196 { Key{7, 2}, Key{1, 1}, Key{4, 1}, Key{0, 0} },
197 { Key{8, 2}, Key{4, 1}, Key{2, 1}, Key{0, 0} }
198 }};
199};
200
201template<>
202struct ScvfCorners<Dune::GeometryTypes::hexahedron>
203{
204 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
205 static constexpr std::array<std::array<Key, 4>, 12> keys = {{
206 { Key{0, 1}, Key{0, 2}, Key{0, 0}, Key{2, 1} },
207 { Key{1, 1}, Key{0, 0}, Key{1, 2}, Key{2, 1} },
208 { Key{3, 1}, Key{2, 2}, Key{0, 0}, Key{0, 1} },
209 { Key{3, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
210 { Key{4, 1}, Key{4, 2}, Key{0, 0}, Key{0, 1} },
211 { Key{5, 2}, Key{4, 1}, Key{1, 1}, Key{0, 0} },
212 { Key{6, 2}, Key{4, 1}, Key{2, 1}, Key{0, 0} },
213 { Key{4, 1}, Key{7, 2}, Key{0, 0}, Key{3, 1} },
214 { Key{0, 0}, Key{0, 1}, Key{5, 1}, Key{8, 2} },
215 { Key{9, 2}, Key{1, 1}, Key{5, 1}, Key{0, 0} },
216 { Key{10, 2}, Key{2, 1}, Key{5, 1}, Key{0, 0} },
217 { Key{11, 2}, Key{5, 1}, Key{3, 1}, Key{0, 0} }
218 }};
219};
220
221
222// convert key array to corner storage
223template<class S, class ReferenceElement, class Transformation, class KeyArray, std::size_t... I>
224S keyToCornerStorageImpl(const ReferenceElement& ref, Transformation&& trans, const KeyArray& key, std::index_sequence<I...>)
225{
226 // key is a pair of a local sub-entity index (first) and the sub-entity's codim (second)
227 return { trans(ref.position(key[I].first, key[I].second))... };
228}
229
230// convert key array to corner storage
231template<class S, class ReferenceElement, class Transformation, class T, std::size_t N, class Indices = std::make_index_sequence<N>>
232S keyToCornerStorage(const ReferenceElement& ref, Transformation&& trans, const std::array<T, N>& key)
233{
234 return keyToCornerStorageImpl<S>(ref, trans, key, Indices{});
235}
236
237// convert key array to corner storage
238// for the i-th sub-entity of codim c (e.g. the i-th facet/codim-1-entity for boundaries)
239template<class S, class ReferenceElement, class Transformation, class KeyArray, std::size_t... I>
240S subEntityKeyToCornerStorageImpl(const ReferenceElement& ref, Transformation&& trans,
241 unsigned int i, unsigned int c, const KeyArray& key, std::index_sequence<I...>)
242{
243 // subEntity gives the subEntity number with respect to the codim-0 reference element
244 // key is a pair of a local sub-entity index (first) and the sub-entity's codim (second) but here w.r.t. the sub-entity i/c
245 return { trans(ref.position(ref.subEntity(i, c, key[I].first, c+key[I].second), c+key[I].second))... };
246}
247
248// convert key array to corner storage
249// for the i-th sub-entity of codim c (e.g. the i-th facet/codim-1-entity for boundaries)
250template<class S, class ReferenceElement, class Transformation, class T, std::size_t N, class Indices = std::make_index_sequence<N>>
251S subEntityKeyToCornerStorage(const ReferenceElement& ref, Transformation&& trans,
252 unsigned int i, unsigned int c, const std::array<T, N>& key)
253{
254 return subEntityKeyToCornerStorageImpl<S>(ref, trans, i, c, key, Indices{});
255}
256
257} // end namespace Detail::Box
258
260template<class GridView, int dim, class ScvType, class ScvfType>
262
264template <class GridView, class ScvType, class ScvfType>
265class BoxGeometryHelper<GridView, 1, ScvType, ScvfType>
266{
267private:
268 using Scalar = typename GridView::ctype;
269 using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>;
270 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
271 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
272 using ScvGeometry = typename ScvType::Traits::Geometry;
273 using ScvfGeometry = typename ScvfType::Traits::Geometry;
274 using LocalIndexType = typename ScvType::Traits::LocalIndexType;
275
276 using Element = typename GridView::template Codim<0>::Entity;
277 using Intersection = typename GridView::Intersection;
278
279 static constexpr int dim = 1;
280public:
282
283 explicit BoxGeometryHelper(const typename Element::Geometry& geometry)
284 : geo_(geometry)
285 {}
286
288 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
289 {
290 return getScvCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvIdx);
291 }
292
294 template<class Transformation>
295 static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvIdx)
296 {
297 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
299 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
300 }
301
302 ScvGeometry scvGeometry(unsigned int localScvIdx) const
303 {
304 return { Dune::GeometryTypes::line, getScvCorners(localScvIdx) };
305 }
306
308 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
309 {
310 return getScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvfIdx);
311 }
312
314 template<class Transformation>
315 static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvfIdx)
316 {
317 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
319 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
320 }
321
323 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex,
324 unsigned int) const
325 {
326 return ScvfCornerStorage{{ geo_.corner(localFacetIndex) }};
327 }
328
330 template<class Transformation>
331 static ScvfCornerStorage getBoundaryScvfCorners(Dune::GeometryType type,
332 Transformation&& trans,
333 unsigned int localFacetIndex,
334 unsigned int indexInFacet)
335 {
336 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
337 return trans(ref.position(localFacetIndex, dim));
338 }
339
341 GlobalPosition normal(const ScvfCornerStorage& scvfCorners,
342 const std::array<LocalIndexType, 2>&) const
343 {
344 auto normal = geo_.corner(1) - geo_.corner(0);
345 normal /= normal.two_norm();
346 return normal;
347 }
348
350 std::size_t numInteriorScvf() const
351 {
352 return referenceElement(geo_).size(dim-1);
353 }
354
356 static auto numInteriorScvf(Dune::GeometryType type)
357 {
358 return Dune::referenceElement<Scalar, dim>(type).size(dim-1);
359 }
360
362 std::size_t numScv() const
363 {
364 return referenceElement(geo_).size(dim);
365 }
366
368 const typename Element::Geometry& elementGeometry() const
369 { return geo_; }
370
372 static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
373 {
374 return Dumux::center(getScvfCorners_(type, [&](const auto& local){ return local; }, localScvfIdx));
375 }
376
378 static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int)
379 {
380 return Dune::referenceElement<Scalar, dim>(type).position(localFacetIndex, dim);
381 }
382
383private:
384 const typename Element::Geometry& geo_;
385};
386
388template <class GridView, class ScvType, class ScvfType>
389class BoxGeometryHelper<GridView, 2, ScvType, ScvfType>
390{
391 using Scalar = typename GridView::ctype;
392 using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>;
393 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
394 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
395 using LocalIndexType = typename ScvType::Traits::LocalIndexType;
396
397 using Element = typename GridView::template Codim<0>::Entity;
398 using Intersection = typename GridView::Intersection;
399
400 static constexpr auto dim = GridView::dimension;
401 static constexpr auto dimWorld = GridView::dimensionworld;
402public:
404
405 explicit BoxGeometryHelper(const typename Element::Geometry& geometry)
406 : geo_(geometry)
407 {}
408
410 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
411 {
412 return getScvCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvIdx);
413 }
414
416 template<class Transformation>
417 static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvIdx)
418 {
419 // proceed according to number of corners of the element
420 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
421 if (type == Dune::GeometryTypes::triangle)
422 {
424 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
425 }
426 else if (type == Dune::GeometryTypes::quadrilateral)
427 {
429 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
430 }
431 else
432 DUNE_THROW(Dune::NotImplemented, "Box scv geometries for dim=" << dim
433 << " dimWorld=" << dimWorld
434 << " type=" << type);
435 }
436
438 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
439 {
440 return getScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvfIdx);
441 }
442
444 template<class Transformation>
445 static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvfIdx)
446 {
447 // proceed according to number of corners
448 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
449 if (type == Dune::GeometryTypes::triangle)
450 {
452 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
453 }
454 else if (type == Dune::GeometryTypes::quadrilateral)
455 {
457 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
458 }
459 else
460 DUNE_THROW(Dune::NotImplemented, "Box scvf geometries for dim=" << dim
461 << " dimWorld=" << dimWorld
462 << " type=" << type);
463 }
464
466 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex,
467 unsigned int indexInFacet) const
468 {
469 return getBoundaryScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localFacetIndex, indexInFacet);
470 }
471
473 template<class Transformation>
474 static ScvfCornerStorage getBoundaryScvfCorners(Dune::GeometryType type,
475 Transformation&& trans,
476 unsigned int localFacetIndex,
477 unsigned int indexInFacet)
478 {
479 // we have to use the corresponding facet geometry as the intersection geometry
480 // might be rotated or flipped. This makes sure that the corners (dof location)
481 // and corresponding scvfs are sorted in the same way
482 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
484 constexpr int facetCodim = 1;
485 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(ref, trans, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
486 }
487
489 template <int w = dimWorld>
490 typename std::enable_if<w == 3, GlobalPosition>::type
491 normal(const ScvfCornerStorage& scvfCorners,
492 const std::array<LocalIndexType, 2>& scvIndices) const
493 {
494 const auto v1 = geo_.corner(1) - geo_.corner(0);
495 const auto v2 = geo_.corner(2) - geo_.corner(0);
496 const auto v3 = Dumux::crossProduct(v1, v2);
497 const auto t = scvfCorners[1] - scvfCorners[0];
498 GlobalPosition normal = Dumux::crossProduct(v3, t);
499 normal /= normal.two_norm();
500
502 const auto v = geo_.corner(scvIndices[1]) - geo_.corner(scvIndices[0]);
503 const auto s = v*normal;
504 if (std::signbit(s))
505 normal *= -1;
506
507 return normal;
508 }
509
511 template <int w = dimWorld>
512 typename std::enable_if<w == 2, GlobalPosition>::type
513 normal(const ScvfCornerStorage& scvfCorners,
514 const std::array<LocalIndexType, 2>& scvIndices) const
515 {
517 const auto t = scvfCorners[1] - scvfCorners[0];
518 GlobalPosition normal({-t[1], t[0]});
519 normal /= normal.two_norm();
520
522 const auto v = geo_.corner(scvIndices[1]) - geo_.corner(scvIndices[0]);
523 const auto s = v*normal;
524 if (std::signbit(s))
525 normal *= -1;
526
527 return normal;
528 }
529
531 std::size_t numInteriorScvf() const
532 {
533 return referenceElement(geo_).size(dim-1);
534 }
535
537 static auto numInteriorScvf(Dune::GeometryType type)
538 {
539 return Dune::referenceElement<Scalar, dim>(type).size(dim-1);
540 }
541
543 std::size_t numScv() const
544 {
545 return referenceElement(geo_).size(dim);
546 }
547
549 const typename Element::Geometry& elementGeometry() const
550 { return geo_; }
551
553 static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
554 {
555 return Dumux::center(getScvfCorners(type, [&](const auto& local){ return local; }, localScvfIdx));
556 }
557
559 static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int indexInFace)
560 {
561 return Dumux::center(getBoundaryScvfCorners(type, [&](const auto& local){ return local; }, localFacetIndex, indexInFace));
562 }
563
564private:
565 const typename Element::Geometry& geo_;
566};
567
569template <class GridView, class ScvType, class ScvfType>
570class BoxGeometryHelper<GridView, 3, ScvType, ScvfType>
571{
572 using Scalar = typename GridView::ctype;
573 using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>;
574 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
575 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
576 using LocalIndexType = typename ScvType::Traits::LocalIndexType;
577
578 using Element = typename GridView::template Codim<0>::Entity;
579 using Intersection = typename GridView::Intersection;
580
581 static constexpr auto dim = GridView::dimension;
582 static constexpr auto dimWorld = GridView::dimensionworld;
583
584public:
586
587 explicit BoxGeometryHelper(const typename Element::Geometry& geometry)
588 : geo_(geometry)
589 {}
590
592 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
593 {
594 return getScvCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvIdx);
595 }
596
598 template<class Transformation>
599 static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvIdx)
600 {
601 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
602 if (type == Dune::GeometryTypes::tetrahedron)
603 {
605 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
606 }
607 else if (type == Dune::GeometryTypes::prism)
608 {
610 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
611 }
612 else if (type == Dune::GeometryTypes::hexahedron)
613 {
615 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
616 }
617 else
618 DUNE_THROW(Dune::NotImplemented, "Box scv geometries for dim=" << dim
619 << " dimWorld=" << dimWorld
620 << " type=" << type);
621 }
622
624 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
625 {
626 return getScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvfIdx);
627 }
628
630 template<class Transformation>
631 static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvfIdx)
632 {
633 // proceed according to number of corners
634 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
635 if (type == Dune::GeometryTypes::tetrahedron)
636 {
638 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
639 }
640 else if (type == Dune::GeometryTypes::prism)
641 {
643 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
644 }
645 else if (type == Dune::GeometryTypes::hexahedron)
646 {
648 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
649 }
650 else
651 DUNE_THROW(Dune::NotImplemented, "Box scvf geometries for dim=" << dim
652 << " dimWorld=" << dimWorld
653 << " type=" << type);
654 }
655
657 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex,
658 unsigned int indexInFacet) const
659 {
660 return getBoundaryScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localFacetIndex, indexInFacet);
661 }
662
664 template<class Transformation>
665 static ScvfCornerStorage getBoundaryScvfCorners(Dune::GeometryType type,
666 Transformation&& trans,
667 unsigned localFacetIndex,
668 unsigned int indexInFacet)
669 {
670 constexpr int facetCodim = 1;
671
672 // we have to use the corresponding facet geometry as the intersection geometry
673 // might be rotated or flipped. This makes sure that the corners (dof location)
674 // and corresponding scvfs are sorted in the same way
675 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
676 const auto facetType = ref.type(localFacetIndex, facetCodim);
677 if (facetType == Dune::GeometryTypes::triangle)
678 {
680 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(ref, trans, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
681 }
682 else if (facetType == Dune::GeometryTypes::quadrilateral)
683 {
685 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(ref, trans, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
686 }
687 else
688 DUNE_THROW(Dune::NotImplemented, "Box boundary scvf geometries for dim=" << dim
689 << " dimWorld=" << dimWorld
690 << " type=" << facetType);
691 }
692
694 GlobalPosition normal(const ScvfCornerStorage& p,
695 const std::array<LocalIndexType, 2>& scvIndices) const
696 {
697 auto normal = Dumux::crossProduct(p[1]-p[0], p[2]-p[0]);
698 normal /= normal.two_norm();
699
700 const auto v = geo_.corner(scvIndices[1]) - geo_.corner(scvIndices[0]);
701 const auto s = v*normal;
702 if (std::signbit(s))
703 normal *= -1;
704
705 return normal;
706 }
707
709 std::size_t numInteriorScvf() const
710 {
711 return referenceElement(geo_).size(dim-1);
712 }
713
715 static auto numInteriorScvf(Dune::GeometryType type)
716 {
717 return Dune::referenceElement<Scalar, dim>(type).size(dim-1);
718 }
719
721 std::size_t numScv() const
722 {
723 return referenceElement(geo_).size(dim);
724 }
725
727 const typename Element::Geometry& elementGeometry() const
728 { return geo_; }
729
731 static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
732 {
733 return Dumux::center(getScvfCorners(type, [&](const auto& local){ return local; }, localScvfIdx));
734 }
735
737 static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int indexInFace)
738 {
739 return Dumux::center(getBoundaryScvfCorners(type, [&](const auto& local){ return local; }, localFacetIndex, indexInFace));
740 }
741
742private:
743 const typename Element::Geometry& geo_;
744};
745
746} // end namespace Dumux
747
748#endif
Compute the center point of a convex polytope geometry or a random-access container of corner points.
const Element::Geometry & elementGeometry() const
the wrapped element geometry
Definition boxgeometryhelper.hh:368
std::size_t numInteriorScvf() const
number of sub control volume faces (number of edges)
Definition boxgeometryhelper.hh:350
static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
local scvf center
Definition boxgeometryhelper.hh:372
BoxGeometryHelper(const typename Element::Geometry &geometry)
Definition boxgeometryhelper.hh:283
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition boxgeometryhelper.hh:288
PQ1LagrangeDofHelper< GridView > DofHelper
Definition boxgeometryhelper.hh:281
ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex, unsigned int) const
Create the sub control volume face geometries on the boundary.
Definition boxgeometryhelper.hh:323
static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvIdx)
Create a vector with the scv corners.
Definition boxgeometryhelper.hh:295
GlobalPosition normal(const ScvfCornerStorage &scvfCorners, const std::array< LocalIndexType, 2 > &) const
get scvf normal vector
Definition boxgeometryhelper.hh:341
std::size_t numScv() const
number of sub control volumes (number of vertices)
Definition boxgeometryhelper.hh:362
ScvGeometry scvGeometry(unsigned int localScvIdx) const
Definition boxgeometryhelper.hh:302
static ScvfCornerStorage getBoundaryScvfCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localFacetIndex, unsigned int indexInFacet)
Create the sub control volume face geometries on the boundary.
Definition boxgeometryhelper.hh:331
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the corners of sub control volume faces.
Definition boxgeometryhelper.hh:308
static auto numInteriorScvf(Dune::GeometryType type)
number of interior sub control volume faces (number of edges)
Definition boxgeometryhelper.hh:356
static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int)
local boundary scvf center
Definition boxgeometryhelper.hh:378
static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvfIdx)
Create a vector with the corners of sub control volume faces.
Definition boxgeometryhelper.hh:315
std::size_t numScv() const
number of sub control volumes (number of vertices)
Definition boxgeometryhelper.hh:543
std::size_t numInteriorScvf() const
number of sub control volume faces (number of edges)
Definition boxgeometryhelper.hh:531
static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
local scvf center
Definition boxgeometryhelper.hh:553
static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvfIdx)
Create a vector with the corners of sub control volume faces.
Definition boxgeometryhelper.hh:445
static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvIdx)
Create a vector with the scv corners.
Definition boxgeometryhelper.hh:417
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the corners of sub control volume faces.
Definition boxgeometryhelper.hh:438
PQ1LagrangeDofHelper< GridView > DofHelper
Definition boxgeometryhelper.hh:403
std::enable_if< w==3, GlobalPosition >::type normal(const ScvfCornerStorage &scvfCorners, const std::array< LocalIndexType, 2 > &scvIndices) const
get scvf normal vector for dim == 2, dimworld == 3
Definition boxgeometryhelper.hh:491
BoxGeometryHelper(const typename Element::Geometry &geometry)
Definition boxgeometryhelper.hh:405
static ScvfCornerStorage getBoundaryScvfCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localFacetIndex, unsigned int indexInFacet)
Create the sub control volume face geometries on the boundary.
Definition boxgeometryhelper.hh:474
ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex, unsigned int indexInFacet) const
Create the sub control volume face geometries on the boundary.
Definition boxgeometryhelper.hh:466
const Element::Geometry & elementGeometry() const
the wrapped element geometry
Definition boxgeometryhelper.hh:549
static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int indexInFace)
local boundary scvf center
Definition boxgeometryhelper.hh:559
static auto numInteriorScvf(Dune::GeometryType type)
number of interior sub control volume faces (number of edges)
Definition boxgeometryhelper.hh:537
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition boxgeometryhelper.hh:410
std::enable_if< w==2, GlobalPosition >::type normal(const ScvfCornerStorage &scvfCorners, const std::array< LocalIndexType, 2 > &scvIndices) const
get scvf normal vector for dim == 2, dimworld == 2
Definition boxgeometryhelper.hh:513
static auto numInteriorScvf(Dune::GeometryType type)
number of interior sub control volume faces (number of edges)
Definition boxgeometryhelper.hh:715
GlobalPosition normal(const ScvfCornerStorage &p, const std::array< LocalIndexType, 2 > &scvIndices) const
get scvf normal vector
Definition boxgeometryhelper.hh:694
BoxGeometryHelper(const typename Element::Geometry &geometry)
Definition boxgeometryhelper.hh:587
const Element::Geometry & elementGeometry() const
the wrapped element geometry
Definition boxgeometryhelper.hh:727
static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvfIdx)
Create a vector with the scvf corners.
Definition boxgeometryhelper.hh:631
ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex, unsigned int indexInFacet) const
Create the sub control volume face geometries on the boundary.
Definition boxgeometryhelper.hh:657
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition boxgeometryhelper.hh:592
static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int indexInFace)
local boundary scvf center
Definition boxgeometryhelper.hh:737
static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
local scvf center
Definition boxgeometryhelper.hh:731
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the scvf corners.
Definition boxgeometryhelper.hh:624
static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvIdx)
Create a vector with the scv corners.
Definition boxgeometryhelper.hh:599
std::size_t numScv() const
number of sub control volumes (number of vertices)
Definition boxgeometryhelper.hh:721
std::size_t numInteriorScvf() const
number of sub control volume faces (number of edges)
Definition boxgeometryhelper.hh:709
static ScvfCornerStorage getBoundaryScvfCorners(Dune::GeometryType type, Transformation &&trans, unsigned localFacetIndex, unsigned int indexInFacet)
Create the sub control volume face geometries on the boundary.
Definition boxgeometryhelper.hh:665
PQ1LagrangeDofHelper< GridView > DofHelper
Definition boxgeometryhelper.hh:585
Create sub control volumes and sub control volume face geometries.
Definition boxgeometryhelper.hh:261
Helper class providing degree of freedom information for the PQ1 Lagrange basis. The pq1 basis uses v...
Definition pq1/dofhelper.hh:32
Dune::FieldVector< Scalar, 3 > crossProduct(const Dune::FieldVector< Scalar, 3 > &vec1, const Dune::FieldVector< Scalar, 3 > &vec2)
Cross product of two vectors in three-dimensional Euclidean space.
Definition math.hh:671
Vector normal(const Vector &v)
Create a vector normal to the given one (v is expected to be non-zero).
Definition normal.hh:26
Corners::value_type center(const Corners &corners)
The center of a given list of corners.
Definition center.hh:24
Defines the index types used for grid and local indices.
Define some often used mathematical functions.
Definition boxgeometryhelper.hh:55
S subEntityKeyToCornerStorage(const ReferenceElement &ref, Transformation &&trans, unsigned int i, unsigned int c, const std::array< T, N > &key)
Definition boxgeometryhelper.hh:251
S keyToCornerStorageImpl(const ReferenceElement &ref, Transformation &&trans, const KeyArray &key, std::index_sequence< I... >)
Definition boxgeometryhelper.hh:224
S keyToCornerStorage(const ReferenceElement &ref, Transformation &&trans, const std::array< T, N > &key)
Definition boxgeometryhelper.hh:232
S subEntityKeyToCornerStorageImpl(const ReferenceElement &ref, Transformation &&trans, unsigned int i, unsigned int c, const KeyArray &key, std::index_sequence< I... >)
Definition boxgeometryhelper.hh:240
Definition adapt.hh:17
Definition common/pdesolver.hh:24
Helper class providing degree of freedom information for the PQ1 Lagrange basis.
Definition boxgeometryhelper.hh:42
std::array< Dune::FieldVector< ct, cdim >,(1<<(mydim)) > Type
Definition boxgeometryhelper.hh:43
Definition boxgeometryhelper.hh:49
static const bool v
Definition boxgeometryhelper.hh:50
static const unsigned int topologyId
Definition boxgeometryhelper.hh:51
Traits for an efficient corner storage for box method sub control volumes.
Definition boxgeometryhelper.hh:37
static constexpr std::array< std::array< Key, 8 >, 8 > keys
Definition boxgeometryhelper.hh:123
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:122
static constexpr std::array< std::array< Key, 2 >, 2 > keys
Definition boxgeometryhelper.hh:64
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:63
static constexpr std::array< std::array< Key, 8 >, 6 > keys
Definition boxgeometryhelper.hh:109
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:108
static constexpr std::array< std::array< Key, 4 >, 4 > keys
Definition boxgeometryhelper.hh:85
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:84
static constexpr std::array< std::array< Key, 8 >, 4 > keys
Definition boxgeometryhelper.hh:97
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:96
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:73
static constexpr std::array< std::array< Key, 4 >, 3 > keys
Definition boxgeometryhelper.hh:74
Definition boxgeometryhelper.hh:58
static constexpr std::array< std::array< Key, 4 >, 12 > keys
Definition boxgeometryhelper.hh:205
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:204
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:141
static constexpr std::array< std::array< Key, 1 >, 1 > keys
Definition boxgeometryhelper.hh:142
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:187
static constexpr std::array< std::array< Key, 4 >, 9 > keys
Definition boxgeometryhelper.hh:188
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:161
static constexpr std::array< std::array< Key, 2 >, 4 > keys
Definition boxgeometryhelper.hh:162
static constexpr std::array< std::array< Key, 4 >, 6 > keys
Definition boxgeometryhelper.hh:174
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:173
static constexpr std::array< std::array< Key, 2 >, 3 > keys
Definition boxgeometryhelper.hh:151
std::pair< std::uint8_t, std::uint8_t > Key
Definition boxgeometryhelper.hh:150
Definition boxgeometryhelper.hh:136