version 3.11-dev
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 <dumux/common/math.hh>
27
28namespace Dumux {
29
31template <class ct>
32struct BoxMLGeometryTraits : public Dune::MultiLinearGeometryTraits<ct>
33{
34 // we use static vectors to store the corners as we know
35 // the number of corners in advance (2^(mydim) corners (1<<(mydim))
36 template< int mydim, int cdim >
38 {
39 using Type = std::array< Dune::FieldVector< ct, cdim >, (1<<(mydim)) >;
40 };
41
42 // we know all scvfs will have the same geometry type
43 template< int mydim >
45 {
46 static const bool v = true;
47 static const unsigned int topologyId = Dune::GeometryTypes::cube(mydim).id();
48 };
49};
50
51namespace Detail::Box {
52
53template<Dune::GeometryType::Id gt>
55
56template<>
58{
59 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
60 static constexpr std::array<std::array<Key, 2>, 2> keys = {{
61 { Key{0, 1}, Key{0, 0} },
62 { Key{1, 1}, Key{0, 0} }
63 }};
64};
65
66template<>
67struct ScvCorners<Dune::GeometryTypes::triangle>
68{
69 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
70 static constexpr std::array<std::array<Key, 4>, 3> keys = {{
71 { Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
72 { Key{1, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
73 { Key{2, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} }
74 }};
75};
76
77template<>
78struct ScvCorners<Dune::GeometryTypes::quadrilateral>
79{
80 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
81 static constexpr std::array<std::array<Key, 4>, 4> keys = {{
82 { Key{0, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
83 { Key{1, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
84 { Key{2, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
85 { Key{3, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} }
86 }};
87};
88
89template<>
90struct ScvCorners<Dune::GeometryTypes::tetrahedron>
91{
92 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
93 static constexpr std::array<std::array<Key, 8>, 4> keys = {{
94 { Key{0, 3}, Key{0, 2}, Key{1, 2}, Key{0, 1}, Key{3, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
95 { Key{1, 3}, Key{2, 2}, Key{0, 2}, Key{0, 1}, Key{4, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
96 { Key{2, 3}, Key{1, 2}, Key{2, 2}, Key{0, 1}, Key{5, 2}, Key{2, 1}, Key{3, 1}, Key{0, 0} },
97 { Key{3, 3}, Key{3, 2}, Key{5, 2}, Key{2, 1}, Key{4, 2}, Key{1, 1}, Key{3, 1}, Key{0, 0} }
98 }};
99};
100
101template<>
102struct ScvCorners<Dune::GeometryTypes::prism>
103{
104 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
105 static constexpr std::array<std::array<Key, 8>, 6> keys = {{
106 { Key{0, 3}, Key{3, 2}, Key{4, 2}, Key{3, 1}, Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
107 { Key{1, 3}, Key{5, 2}, Key{3, 2}, Key{3, 1}, Key{1, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
108 { Key{2, 3}, Key{4, 2}, Key{5, 2}, Key{3, 1}, Key{2, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
109 { Key{3, 3}, Key{7, 2}, Key{6, 2}, Key{4, 1}, Key{0, 2}, Key{1, 1}, Key{0, 1}, Key{0, 0} },
110 { Key{4, 3}, Key{6, 2}, Key{8, 2}, Key{4, 1}, Key{1, 2}, Key{0, 1}, Key{2, 1}, Key{0, 0} },
111 { Key{5, 3}, Key{8, 2}, Key{7, 2}, Key{4, 1}, Key{2, 2}, Key{2, 1}, Key{1, 1}, Key{0, 0} }
112 }};
113};
114
115template<>
116struct ScvCorners<Dune::GeometryTypes::hexahedron>
117{
118 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
119 static constexpr std::array<std::array<Key, 8>, 8> keys = {{
120 { Key{0, 3}, Key{6, 2}, Key{4, 2}, Key{4, 1}, Key{0, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
121 { Key{1, 3}, Key{5, 2}, Key{6, 2}, Key{4, 1}, Key{1, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
122 { Key{2, 3}, Key{4, 2}, Key{7, 2}, Key{4, 1}, Key{2, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
123 { Key{3, 3}, Key{7, 2}, Key{5, 2}, Key{4, 1}, Key{3, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
124 { Key{4, 3}, Key{8, 2}, Key{10, 2}, Key{5, 1}, Key{0, 2}, Key{0, 1}, Key{2, 1}, Key{0, 0} },
125 { Key{5, 3}, Key{10, 2}, Key{9, 2}, Key{5, 1}, Key{1, 2}, Key{2, 1}, Key{1, 1}, Key{0, 0} },
126 { Key{6, 3}, Key{11, 2}, Key{8, 2}, Key{5, 1}, Key{2, 2}, Key{3, 1}, Key{0, 1}, Key{0, 0} },
127 { Key{7, 3}, Key{9, 2}, Key{11, 2}, Key{5, 1}, Key{3, 2}, Key{1, 1}, Key{3, 1}, Key{0, 0} }
128 }};
129};
130
131template<Dune::GeometryType::Id gt>
133
134template<>
136{
137 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
138 static constexpr std::array<std::array<Key, 1>, 1> keys = {{
139 { Key{0, 0} }
140 }};
141};
142
143template<>
144struct ScvfCorners<Dune::GeometryTypes::triangle>
145{
146 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
147 static constexpr std::array<std::array<Key, 2>, 3> keys = {{
148 { Key{0, 0}, Key{0, 1} },
149 { Key{1, 1}, Key{0, 0} },
150 { Key{0, 0}, Key{2, 1} }
151 }};
152};
153
154template<>
155struct ScvfCorners<Dune::GeometryTypes::quadrilateral>
156{
157 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
158 static constexpr std::array<std::array<Key, 2>, 4> keys = {{
159 { Key{0, 1}, Key{0, 0} },
160 { Key{0, 0}, Key{1, 1} },
161 { Key{0, 0}, Key{2, 1} },
162 { Key{3, 1}, Key{0, 0} }
163 }};
164};
165
166template<>
167struct ScvfCorners<Dune::GeometryTypes::tetrahedron>
168{
169 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
170 static constexpr std::array<std::array<Key, 4>, 6> keys = {{
171 { Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
172 { Key{0, 1}, Key{1, 2}, Key{0, 0}, Key{2, 1} },
173 { Key{2, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
174 { Key{2, 1}, Key{3, 2}, Key{0, 0}, Key{1, 1} },
175 { Key{3, 1}, Key{0, 0}, Key{4, 2}, Key{1, 1} },
176 { Key{5, 2}, Key{2, 1}, Key{3, 1}, Key{0, 0} }
177 }};
178};
179
180template<>
181struct ScvfCorners<Dune::GeometryTypes::prism>
182{
183 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
184 static constexpr std::array<std::array<Key, 4>, 9> keys = {{
185 { Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
186 { Key{1, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
187 { Key{2, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
188 { Key{3, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
189 { Key{4, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
190 { Key{5, 2}, Key{2, 1}, Key{3, 1}, Key{0, 0} },
191 { Key{6, 2}, Key{4, 1}, Key{0, 1}, Key{0, 0} },
192 { Key{7, 2}, Key{1, 1}, Key{4, 1}, Key{0, 0} },
193 { Key{8, 2}, Key{4, 1}, Key{2, 1}, Key{0, 0} }
194 }};
195};
196
197template<>
198struct ScvfCorners<Dune::GeometryTypes::hexahedron>
199{
200 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
201 static constexpr std::array<std::array<Key, 4>, 12> keys = {{
202 { Key{0, 1}, Key{0, 2}, Key{0, 0}, Key{2, 1} },
203 { Key{1, 1}, Key{0, 0}, Key{1, 2}, Key{2, 1} },
204 { Key{3, 1}, Key{2, 2}, Key{0, 0}, Key{0, 1} },
205 { Key{3, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
206 { Key{4, 1}, Key{4, 2}, Key{0, 0}, Key{0, 1} },
207 { Key{5, 2}, Key{4, 1}, Key{1, 1}, Key{0, 0} },
208 { Key{6, 2}, Key{4, 1}, Key{2, 1}, Key{0, 0} },
209 { Key{4, 1}, Key{7, 2}, Key{0, 0}, Key{3, 1} },
210 { Key{0, 0}, Key{0, 1}, Key{5, 1}, Key{8, 2} },
211 { Key{9, 2}, Key{1, 1}, Key{5, 1}, Key{0, 0} },
212 { Key{10, 2}, Key{2, 1}, Key{5, 1}, Key{0, 0} },
213 { Key{11, 2}, Key{5, 1}, Key{3, 1}, Key{0, 0} }
214 }};
215};
216
217
218// convert key array to corner storage
219template<class S, class ReferenceElement, class Transformation, class KeyArray, std::size_t... I>
220S keyToCornerStorageImpl(const ReferenceElement& ref, Transformation&& trans, const KeyArray& key, std::index_sequence<I...>)
221{
222 // key is a pair of a local sub-entity index (first) and the sub-entity's codim (second)
223 return { trans(ref.position(key[I].first, key[I].second))... };
224}
225
226// convert key array to corner storage
227template<class S, class ReferenceElement, class Transformation, class T, std::size_t N, class Indices = std::make_index_sequence<N>>
228S keyToCornerStorage(const ReferenceElement& ref, Transformation&& trans, const std::array<T, N>& key)
229{
230 return keyToCornerStorageImpl<S>(ref, trans, key, Indices{});
231}
232
233// convert key array to corner storage
234// for the i-th sub-entity of codim c (e.g. the i-th facet/codim-1-entity for boundaries)
235template<class S, class ReferenceElement, class Transformation, class KeyArray, std::size_t... I>
236S subEntityKeyToCornerStorageImpl(const ReferenceElement& ref, Transformation&& trans,
237 unsigned int i, unsigned int c, const KeyArray& key, std::index_sequence<I...>)
238{
239 // subEntity gives the subEntity number with respect to the codim-0 reference element
240 // 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
241 return { trans(ref.position(ref.subEntity(i, c, key[I].first, c+key[I].second), c+key[I].second))... };
242}
243
244// convert key array to corner storage
245// for the i-th sub-entity of codim c (e.g. the i-th facet/codim-1-entity for boundaries)
246template<class S, class ReferenceElement, class Transformation, class T, std::size_t N, class Indices = std::make_index_sequence<N>>
247S subEntityKeyToCornerStorage(const ReferenceElement& ref, Transformation&& trans,
248 unsigned int i, unsigned int c, const std::array<T, N>& key)
249{
250 return subEntityKeyToCornerStorageImpl<S>(ref, trans, i, c, key, Indices{});
251}
252
253} // end namespace Detail::Box
254
256template<class GridView, int dim, class ScvType, class ScvfType>
258
260template <class GridView, class ScvType, class ScvfType>
261class BoxGeometryHelper<GridView, 1, ScvType, ScvfType>
262{
263private:
264 using Scalar = typename GridView::ctype;
265 using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>;
266 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
267 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
268 using ScvGeometry = typename ScvType::Traits::Geometry;
269 using ScvfGeometry = typename ScvfType::Traits::Geometry;
270 using LocalIndexType = typename ScvType::Traits::LocalIndexType;
271
272 using Element = typename GridView::template Codim<0>::Entity;
273 using Intersection = typename GridView::Intersection;
274
275 static constexpr int dim = 1;
276public:
277
278 explicit BoxGeometryHelper(const typename Element::Geometry& geometry)
279 : geo_(geometry)
280 {}
281
283 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
284 {
285 return getScvCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvIdx);
286 }
287
289 template<class Transformation>
290 static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvIdx)
291 {
292 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
294 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
295 }
296
297 ScvGeometry scvGeometry(unsigned int localScvIdx) const
298 {
299 return { Dune::GeometryTypes::line, getScvCorners(localScvIdx) };
300 }
301
303 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
304 {
305 return getScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvfIdx);
306 }
307
309 template<class Transformation>
310 static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvfIdx)
311 {
312 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
314 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
315 }
316
318 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex,
319 unsigned int) const
320 {
321 return ScvfCornerStorage{{ geo_.corner(localFacetIndex) }};
322 }
323
325 template<class Transformation>
326 static ScvfCornerStorage getBoundaryScvfCorners(Dune::GeometryType type,
327 Transformation&& trans,
328 unsigned int localFacetIndex,
329 unsigned int indexInFacet)
330 {
331 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
332 return trans(ref.position(localFacetIndex, dim));
333 }
334
336 GlobalPosition normal(const ScvfCornerStorage& scvfCorners,
337 const std::array<LocalIndexType, 2>&) const
338 {
339 auto normal = geo_.corner(1) - geo_.corner(0);
340 normal /= normal.two_norm();
341 return normal;
342 }
343
345 std::size_t numInteriorScvf() const
346 {
347 return referenceElement(geo_).size(dim-1);
348 }
349
351 static auto numInteriorScvf(Dune::GeometryType type)
352 {
353 return Dune::referenceElement<Scalar, dim>(type).size(dim-1);
354 }
355
357 std::size_t numScv() const
358 {
359 return referenceElement(geo_).size(dim);
360 }
361
363 const typename Element::Geometry& elementGeometry() const
364 { return geo_; }
365
367 template<class LocalKey>
368 static Element::Geometry::LocalCoordinate localDofPosition(Dune::GeometryType type, const LocalKey& localKey)
369 {
370 return Dune::referenceElement<Scalar, dim>(type).position(localKey.subEntity(), localKey.codim());
371 }
372
374 static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
375 {
376 return Dumux::center(getScvfCorners_(type, [&](const auto& local){ return local; }, localScvfIdx));
377 }
378
380 static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int)
381 {
382 return Dune::referenceElement<Scalar, dim>(type).position(localFacetIndex, dim);
383 }
384
385private:
386 const typename Element::Geometry& geo_;
387};
388
390template <class GridView, class ScvType, class ScvfType>
391class BoxGeometryHelper<GridView, 2, ScvType, ScvfType>
392{
393 using Scalar = typename GridView::ctype;
394 using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>;
395 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
396 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
397 using LocalIndexType = typename ScvType::Traits::LocalIndexType;
398
399 using Element = typename GridView::template Codim<0>::Entity;
400 using Intersection = typename GridView::Intersection;
401
402 static constexpr auto dim = GridView::dimension;
403 static constexpr auto dimWorld = GridView::dimensionworld;
404public:
405
406 explicit BoxGeometryHelper(const typename Element::Geometry& geometry)
407 : geo_(geometry)
408 {}
409
411 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
412 {
413 return getScvCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvIdx);
414 }
415
417 template<class Transformation>
418 static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvIdx)
419 {
420 // proceed according to number of corners of the element
421 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
422 if (type == Dune::GeometryTypes::triangle)
423 {
425 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
426 }
427 else if (type == Dune::GeometryTypes::quadrilateral)
428 {
430 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
431 }
432 else
433 DUNE_THROW(Dune::NotImplemented, "Box scv geometries for dim=" << dim
434 << " dimWorld=" << dimWorld
435 << " type=" << type);
436 }
437
439 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
440 {
441 return getScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvfIdx);
442 }
443
445 template<class Transformation>
446 static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvfIdx)
447 {
448 // proceed according to number of corners
449 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
450 if (type == Dune::GeometryTypes::triangle)
451 {
453 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
454 }
455 else if (type == Dune::GeometryTypes::quadrilateral)
456 {
458 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
459 }
460 else
461 DUNE_THROW(Dune::NotImplemented, "Box scvf geometries for dim=" << dim
462 << " dimWorld=" << dimWorld
463 << " type=" << type);
464 }
465
467 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex,
468 unsigned int indexInFacet) const
469 {
470 return getBoundaryScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localFacetIndex, indexInFacet);
471 }
472
474 template<class Transformation>
475 static ScvfCornerStorage getBoundaryScvfCorners(Dune::GeometryType type,
476 Transformation&& trans,
477 unsigned int localFacetIndex,
478 unsigned int indexInFacet)
479 {
480 // we have to use the corresponding facet geometry as the intersection geometry
481 // might be rotated or flipped. This makes sure that the corners (dof location)
482 // and corresponding scvfs are sorted in the same way
483 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
485 constexpr int facetCodim = 1;
486 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(ref, trans, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
487 }
488
490 template <int w = dimWorld>
491 typename std::enable_if<w == 3, GlobalPosition>::type
492 normal(const ScvfCornerStorage& scvfCorners,
493 const std::array<LocalIndexType, 2>& scvIndices) const
494 {
495 const auto v1 = geo_.corner(1) - geo_.corner(0);
496 const auto v2 = geo_.corner(2) - geo_.corner(0);
497 const auto v3 = Dumux::crossProduct(v1, v2);
498 const auto t = scvfCorners[1] - scvfCorners[0];
499 GlobalPosition normal = Dumux::crossProduct(v3, t);
500 normal /= normal.two_norm();
501
503 const auto v = geo_.corner(scvIndices[1]) - geo_.corner(scvIndices[0]);
504 const auto s = v*normal;
505 if (std::signbit(s))
506 normal *= -1;
507
508 return normal;
509 }
510
512 template <int w = dimWorld>
513 typename std::enable_if<w == 2, GlobalPosition>::type
514 normal(const ScvfCornerStorage& scvfCorners,
515 const std::array<LocalIndexType, 2>& scvIndices) const
516 {
518 const auto t = scvfCorners[1] - scvfCorners[0];
519 GlobalPosition normal({-t[1], t[0]});
520 normal /= normal.two_norm();
521
523 const auto v = geo_.corner(scvIndices[1]) - geo_.corner(scvIndices[0]);
524 const auto s = v*normal;
525 if (std::signbit(s))
526 normal *= -1;
527
528 return normal;
529 }
530
532 std::size_t numInteriorScvf() const
533 {
534 return referenceElement(geo_).size(dim-1);
535 }
536
538 static auto numInteriorScvf(Dune::GeometryType type)
539 {
540 return Dune::referenceElement<Scalar, dim>(type).size(dim-1);
541 }
542
544 std::size_t numScv() const
545 {
546 return referenceElement(geo_).size(dim);
547 }
548
550 const typename Element::Geometry& elementGeometry() const
551 { return geo_; }
552
554 template<class LocalKey>
555 static Element::Geometry::LocalCoordinate localDofPosition(Dune::GeometryType type, const LocalKey& localKey)
556 {
557 return Dune::referenceElement<Scalar, dim>(type).position(localKey.subEntity(), localKey.codim());
558 }
559
561 static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
562 {
563 return Dumux::center(getScvfCorners(type, [&](const auto& local){ return local; }, localScvfIdx));
564 }
565
567 static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int indexInFace)
568 {
569 return Dumux::center(getBoundaryScvfCorners(type, [&](const auto& local){ return local; }, localFacetIndex, indexInFace));
570 }
571
572private:
573 const typename Element::Geometry& geo_;
574};
575
577template <class GridView, class ScvType, class ScvfType>
578class BoxGeometryHelper<GridView, 3, ScvType, ScvfType>
579{
580 using Scalar = typename GridView::ctype;
581 using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>;
582 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
583 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
584 using LocalIndexType = typename ScvType::Traits::LocalIndexType;
585
586 using Element = typename GridView::template Codim<0>::Entity;
587 using Intersection = typename GridView::Intersection;
588
589 static constexpr auto dim = GridView::dimension;
590 static constexpr auto dimWorld = GridView::dimensionworld;
591
592public:
593 explicit BoxGeometryHelper(const typename Element::Geometry& geometry)
594 : geo_(geometry)
595 {}
596
598 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
599 {
600 return getScvCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvIdx);
601 }
602
604 template<class Transformation>
605 static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvIdx)
606 {
607 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
608 if (type == Dune::GeometryTypes::tetrahedron)
609 {
611 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
612 }
613 else if (type == Dune::GeometryTypes::prism)
614 {
616 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
617 }
618 else if (type == Dune::GeometryTypes::hexahedron)
619 {
621 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(ref, trans, Corners::keys[localScvIdx]);
622 }
623 else
624 DUNE_THROW(Dune::NotImplemented, "Box scv geometries for dim=" << dim
625 << " dimWorld=" << dimWorld
626 << " type=" << type);
627 }
628
630 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
631 {
632 return getScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvfIdx);
633 }
634
636 template<class Transformation>
637 static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvfIdx)
638 {
639 // proceed according to number of corners
640 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
641 if (type == Dune::GeometryTypes::tetrahedron)
642 {
644 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
645 }
646 else if (type == Dune::GeometryTypes::prism)
647 {
649 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
650 }
651 else if (type == Dune::GeometryTypes::hexahedron)
652 {
654 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(ref, trans, Corners::keys[localScvfIdx]);
655 }
656 else
657 DUNE_THROW(Dune::NotImplemented, "Box scvf geometries for dim=" << dim
658 << " dimWorld=" << dimWorld
659 << " type=" << type);
660 }
661
663 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex,
664 unsigned int indexInFacet) const
665 {
666 return getBoundaryScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localFacetIndex, indexInFacet);
667 }
668
670 template<class Transformation>
671 static ScvfCornerStorage getBoundaryScvfCorners(Dune::GeometryType type,
672 Transformation&& trans,
673 unsigned localFacetIndex,
674 unsigned int indexInFacet)
675 {
676 constexpr int facetCodim = 1;
677
678 // we have to use the corresponding facet geometry as the intersection geometry
679 // might be rotated or flipped. This makes sure that the corners (dof location)
680 // and corresponding scvfs are sorted in the same way
681 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
682 const auto facetType = ref.type(localFacetIndex, facetCodim);
683 if (facetType == Dune::GeometryTypes::triangle)
684 {
686 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(ref, trans, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
687 }
688 else if (facetType == Dune::GeometryTypes::quadrilateral)
689 {
691 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(ref, trans, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
692 }
693 else
694 DUNE_THROW(Dune::NotImplemented, "Box boundary scvf geometries for dim=" << dim
695 << " dimWorld=" << dimWorld
696 << " type=" << facetType);
697 }
698
700 GlobalPosition normal(const ScvfCornerStorage& p,
701 const std::array<LocalIndexType, 2>& scvIndices) const
702 {
703 auto normal = Dumux::crossProduct(p[1]-p[0], p[2]-p[0]);
704 normal /= normal.two_norm();
705
706 const auto v = geo_.corner(scvIndices[1]) - geo_.corner(scvIndices[0]);
707 const auto s = v*normal;
708 if (std::signbit(s))
709 normal *= -1;
710
711 return normal;
712 }
713
715 std::size_t numInteriorScvf() const
716 {
717 return referenceElement(geo_).size(dim-1);
718 }
719
721 static auto numInteriorScvf(Dune::GeometryType type)
722 {
723 return Dune::referenceElement<Scalar, dim>(type).size(dim-1);
724 }
725
727 std::size_t numScv() const
728 {
729 return referenceElement(geo_).size(dim);
730 }
731
733 const typename Element::Geometry& elementGeometry() const
734 { return geo_; }
735
737 template<class LocalKey>
738 static Element::Geometry::LocalCoordinate localDofPosition(Dune::GeometryType type, const LocalKey& localKey)
739 {
740 return Dune::referenceElement<Scalar, dim>(type).position(localKey.subEntity(), localKey.codim());
741 }
742
744 static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
745 {
746 return Dumux::center(getScvfCorners(type, [&](const auto& local){ return local; }, localScvfIdx));
747 }
748
750 static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int indexInFace)
751 {
752 return Dumux::center(getBoundaryScvfCorners(type, [&](const auto& local){ return local; }, localFacetIndex, indexInFace));
753 }
754
755private:
756 const typename Element::Geometry& geo_;
757};
758
759} // end namespace Dumux
760
761#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:363
std::size_t numInteriorScvf() const
number of sub control volume faces (number of edges)
Definition: boxgeometryhelper.hh:345
static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
local scvf center
Definition: boxgeometryhelper.hh:374
BoxGeometryHelper(const typename Element::Geometry &geometry)
Definition: boxgeometryhelper.hh:278
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition: boxgeometryhelper.hh:283
ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex, unsigned int) const
Create the sub control volume face geometries on the boundary.
Definition: boxgeometryhelper.hh:318
static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvIdx)
Create a vector with the scv corners.
Definition: boxgeometryhelper.hh:290
GlobalPosition normal(const ScvfCornerStorage &scvfCorners, const std::array< LocalIndexType, 2 > &) const
get scvf normal vector
Definition: boxgeometryhelper.hh:336
std::size_t numScv() const
number of sub control volumes (number of vertices)
Definition: boxgeometryhelper.hh:357
ScvGeometry scvGeometry(unsigned int localScvIdx) const
Definition: boxgeometryhelper.hh:297
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:326
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the corners of sub control volume faces.
Definition: boxgeometryhelper.hh:303
static auto numInteriorScvf(Dune::GeometryType type)
number of interior sub control volume faces (number of edges)
Definition: boxgeometryhelper.hh:351
static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int)
local boundary scvf center
Definition: boxgeometryhelper.hh:380
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:310
static Element::Geometry::LocalCoordinate localDofPosition(Dune::GeometryType type, const LocalKey &localKey)
local dof position
Definition: boxgeometryhelper.hh:368
std::size_t numScv() const
number of sub control volumes (number of vertices)
Definition: boxgeometryhelper.hh:544
std::size_t numInteriorScvf() const
number of sub control volume faces (number of edges)
Definition: boxgeometryhelper.hh:532
static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
local scvf center
Definition: boxgeometryhelper.hh:561
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:446
static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvIdx)
Create a vector with the scv corners.
Definition: boxgeometryhelper.hh:418
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the corners of sub control volume faces.
Definition: boxgeometryhelper.hh:439
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:492
BoxGeometryHelper(const typename Element::Geometry &geometry)
Definition: boxgeometryhelper.hh:406
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:475
static Element::Geometry::LocalCoordinate localDofPosition(Dune::GeometryType type, const LocalKey &localKey)
local dof position
Definition: boxgeometryhelper.hh:555
ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex, unsigned int indexInFacet) const
Create the sub control volume face geometries on the boundary.
Definition: boxgeometryhelper.hh:467
const Element::Geometry & elementGeometry() const
the wrapped element geometry
Definition: boxgeometryhelper.hh:550
static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int indexInFace)
local boundary scvf center
Definition: boxgeometryhelper.hh:567
static auto numInteriorScvf(Dune::GeometryType type)
number of interior sub control volume faces (number of edges)
Definition: boxgeometryhelper.hh:538
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition: boxgeometryhelper.hh:411
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:514
static auto numInteriorScvf(Dune::GeometryType type)
number of interior sub control volume faces (number of edges)
Definition: boxgeometryhelper.hh:721
static Element::Geometry::LocalCoordinate localDofPosition(Dune::GeometryType type, const LocalKey &localKey)
local dof position
Definition: boxgeometryhelper.hh:738
GlobalPosition normal(const ScvfCornerStorage &p, const std::array< LocalIndexType, 2 > &scvIndices) const
get scvf normal vector
Definition: boxgeometryhelper.hh:700
BoxGeometryHelper(const typename Element::Geometry &geometry)
Definition: boxgeometryhelper.hh:593
const Element::Geometry & elementGeometry() const
the wrapped element geometry
Definition: boxgeometryhelper.hh:733
static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvfIdx)
Create a vector with the scvf corners.
Definition: boxgeometryhelper.hh:637
ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex, unsigned int indexInFacet) const
Create the sub control volume face geometries on the boundary.
Definition: boxgeometryhelper.hh:663
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition: boxgeometryhelper.hh:598
static Element::Geometry::LocalCoordinate localBoundaryScvfCenter(Dune::GeometryType type, unsigned int localFacetIndex, unsigned int indexInFace)
local boundary scvf center
Definition: boxgeometryhelper.hh:750
static Element::Geometry::LocalCoordinate localScvfCenter(Dune::GeometryType type, unsigned int localScvfIdx)
local scvf center
Definition: boxgeometryhelper.hh:744
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the scvf corners.
Definition: boxgeometryhelper.hh:630
static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvIdx)
Create a vector with the scv corners.
Definition: boxgeometryhelper.hh:605
std::size_t numScv() const
number of sub control volumes (number of vertices)
Definition: boxgeometryhelper.hh:727
std::size_t numInteriorScvf() const
number of sub control volume faces (number of edges)
Definition: boxgeometryhelper.hh:715
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:671
Create sub control volumes and sub control volume face geometries.
Definition: boxgeometryhelper.hh:257
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
Define some often used mathematical functions.
S subEntityKeyToCornerStorage(const ReferenceElement &ref, Transformation &&trans, unsigned int i, unsigned int c, const std::array< T, N > &key)
Definition: boxgeometryhelper.hh:247
S keyToCornerStorageImpl(const ReferenceElement &ref, Transformation &&trans, const KeyArray &key, std::index_sequence< I... >)
Definition: boxgeometryhelper.hh:220
S keyToCornerStorage(const ReferenceElement &ref, Transformation &&trans, const std::array< T, N > &key)
Definition: boxgeometryhelper.hh:228
S subEntityKeyToCornerStorageImpl(const ReferenceElement &ref, Transformation &&trans, unsigned int i, unsigned int c, const KeyArray &key, std::index_sequence< I... >)
Definition: boxgeometryhelper.hh:236
CVFE< CVFEMethods::PQ1 > Box
Definition: method.hh:94
constexpr Line line
Definition: couplingmanager1d3d_line.hh:31
Definition: adapt.hh:17
Definition: common/pdesolver.hh:24
Definition: boxgeometryhelper.hh:38
std::array< Dune::FieldVector< ct, cdim >,(1<<(mydim)) > Type
Definition: boxgeometryhelper.hh:39
Definition: boxgeometryhelper.hh:45
static const bool v
Definition: boxgeometryhelper.hh:46
static const unsigned int topologyId
Definition: boxgeometryhelper.hh:47
Traits for an efficient corner storage for box method sub control volumes.
Definition: boxgeometryhelper.hh:33
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:118
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:59
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:104
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:80
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:92
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:69
Definition: boxgeometryhelper.hh:54
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:200
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:137
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:183
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:157
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:169
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:146
Definition: boxgeometryhelper.hh:132