version 3.8
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-FileCopyrightInfo: 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>
26
27namespace Dumux {
28
30template <class ct>
31struct BoxMLGeometryTraits : public Dune::MultiLinearGeometryTraits<ct>
32{
33 // we use static vectors to store the corners as we know
34 // the number of corners in advance (2^(mydim) corners (1<<(mydim))
35 template< int mydim, int cdim >
37 {
38 using Type = std::array< Dune::FieldVector< ct, cdim >, (1<<(mydim)) >;
39 };
40
41 // we know all scvfs will have the same geometry type
42 template< int mydim >
44 {
45 static const bool v = true;
46 static const unsigned int topologyId = Dune::GeometryTypes::cube(mydim).id();
47 };
48};
49
50namespace Detail::Box {
51
52template<Dune::GeometryType::Id gt>
54
55template<>
57{
58 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
59 static constexpr std::array<std::array<Key, 2>, 2> keys = {{
60 { Key{0, 1}, Key{0, 0} },
61 { Key{1, 1}, Key{0, 0} }
62 }};
63};
64
65template<>
66struct ScvCorners<Dune::GeometryTypes::triangle>
67{
68 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
69 static constexpr std::array<std::array<Key, 4>, 3> keys = {{
70 { Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
71 { Key{1, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
72 { Key{2, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} }
73 }};
74};
75
76template<>
77struct ScvCorners<Dune::GeometryTypes::quadrilateral>
78{
79 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
80 static constexpr std::array<std::array<Key, 4>, 4> keys = {{
81 { Key{0, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
82 { Key{1, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
83 { Key{2, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
84 { Key{3, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} }
85 }};
86};
87
88template<>
89struct ScvCorners<Dune::GeometryTypes::tetrahedron>
90{
91 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
92 static constexpr std::array<std::array<Key, 8>, 4> keys = {{
93 { Key{0, 3}, Key{0, 2}, Key{1, 2}, Key{0, 1}, Key{3, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
94 { Key{1, 3}, Key{2, 2}, Key{0, 2}, Key{0, 1}, Key{4, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
95 { Key{2, 3}, Key{1, 2}, Key{2, 2}, Key{0, 1}, Key{5, 2}, Key{2, 1}, Key{3, 1}, Key{0, 0} },
96 { Key{3, 3}, Key{3, 2}, Key{5, 2}, Key{2, 1}, Key{4, 2}, Key{1, 1}, Key{3, 1}, Key{0, 0} }
97 }};
98};
99
100template<>
101struct ScvCorners<Dune::GeometryTypes::prism>
102{
103 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
104 static constexpr std::array<std::array<Key, 8>, 6> keys = {{
105 { Key{0, 3}, Key{3, 2}, Key{4, 2}, Key{3, 1}, Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
106 { Key{1, 3}, Key{5, 2}, Key{3, 2}, Key{3, 1}, Key{1, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
107 { Key{2, 3}, Key{4, 2}, Key{5, 2}, Key{3, 1}, Key{2, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
108 { Key{3, 3}, Key{7, 2}, Key{6, 2}, Key{4, 1}, Key{0, 2}, Key{1, 1}, Key{0, 1}, Key{0, 0} },
109 { Key{4, 3}, Key{6, 2}, Key{8, 2}, Key{4, 1}, Key{1, 2}, Key{0, 1}, Key{2, 1}, Key{0, 0} },
110 { Key{5, 3}, Key{8, 2}, Key{7, 2}, Key{4, 1}, Key{2, 2}, Key{2, 1}, Key{1, 1}, Key{0, 0} }
111 }};
112};
113
114template<>
115struct ScvCorners<Dune::GeometryTypes::hexahedron>
116{
117 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
118 static constexpr std::array<std::array<Key, 8>, 8> keys = {{
119 { Key{0, 3}, Key{6, 2}, Key{4, 2}, Key{4, 1}, Key{0, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
120 { Key{1, 3}, Key{5, 2}, Key{6, 2}, Key{4, 1}, Key{1, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
121 { Key{2, 3}, Key{4, 2}, Key{7, 2}, Key{4, 1}, Key{2, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
122 { Key{3, 3}, Key{7, 2}, Key{5, 2}, Key{4, 1}, Key{3, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
123 { Key{4, 3}, Key{8, 2}, Key{10, 2}, Key{5, 1}, Key{0, 2}, Key{0, 1}, Key{2, 1}, Key{0, 0} },
124 { Key{5, 3}, Key{10, 2}, Key{9, 2}, Key{5, 1}, Key{1, 2}, Key{2, 1}, Key{1, 1}, Key{0, 0} },
125 { Key{6, 3}, Key{11, 2}, Key{8, 2}, Key{5, 1}, Key{2, 2}, Key{3, 1}, Key{0, 1}, Key{0, 0} },
126 { Key{7, 3}, Key{9, 2}, Key{11, 2}, Key{5, 1}, Key{3, 2}, Key{1, 1}, Key{3, 1}, Key{0, 0} }
127 }};
128};
129
130template<Dune::GeometryType::Id gt>
132
133template<>
135{
136 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
137 static constexpr std::array<std::array<Key, 1>, 1> keys = {{
138 { Key{0, 0} }
139 }};
140};
141
142template<>
143struct ScvfCorners<Dune::GeometryTypes::triangle>
144{
145 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
146 static constexpr std::array<std::array<Key, 2>, 3> keys = {{
147 { Key{0, 0}, Key{0, 1} },
148 { Key{1, 1}, Key{0, 0} },
149 { Key{0, 0}, Key{2, 1} }
150 }};
151};
152
153template<>
154struct ScvfCorners<Dune::GeometryTypes::quadrilateral>
155{
156 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
157 static constexpr std::array<std::array<Key, 2>, 4> keys = {{
158 { Key{0, 1}, Key{0, 0} },
159 { Key{0, 0}, Key{1, 1} },
160 { Key{0, 0}, Key{2, 1} },
161 { Key{3, 1}, Key{0, 0} }
162 }};
163};
164
165template<>
166struct ScvfCorners<Dune::GeometryTypes::tetrahedron>
167{
168 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
169 static constexpr std::array<std::array<Key, 4>, 6> keys = {{
170 { Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
171 { Key{0, 1}, Key{1, 2}, Key{0, 0}, Key{2, 1} },
172 { Key{2, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
173 { Key{2, 1}, Key{3, 2}, Key{0, 0}, Key{1, 1} },
174 { Key{3, 1}, Key{0, 0}, Key{4, 2}, Key{1, 1} },
175 { Key{5, 2}, Key{2, 1}, Key{3, 1}, Key{0, 0} }
176 }};
177};
178
179template<>
180struct ScvfCorners<Dune::GeometryTypes::prism>
181{
182 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
183 static constexpr std::array<std::array<Key, 4>, 9> keys = {{
184 { Key{0, 2}, Key{0, 1}, Key{1, 1}, Key{0, 0} },
185 { Key{1, 2}, Key{2, 1}, Key{0, 1}, Key{0, 0} },
186 { Key{2, 2}, Key{1, 1}, Key{2, 1}, Key{0, 0} },
187 { Key{3, 2}, Key{0, 1}, Key{3, 1}, Key{0, 0} },
188 { Key{4, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
189 { Key{5, 2}, Key{2, 1}, Key{3, 1}, Key{0, 0} },
190 { Key{6, 2}, Key{4, 1}, Key{0, 1}, Key{0, 0} },
191 { Key{7, 2}, Key{1, 1}, Key{4, 1}, Key{0, 0} },
192 { Key{8, 2}, Key{4, 1}, Key{2, 1}, Key{0, 0} }
193 }};
194};
195
196template<>
197struct ScvfCorners<Dune::GeometryTypes::hexahedron>
198{
199 using Key = std::pair<std::uint8_t, std::uint8_t>; // (i, codim)
200 static constexpr std::array<std::array<Key, 4>, 12> keys = {{
201 { Key{0, 1}, Key{0, 2}, Key{0, 0}, Key{2, 1} },
202 { Key{1, 1}, Key{0, 0}, Key{1, 2}, Key{2, 1} },
203 { Key{3, 1}, Key{2, 2}, Key{0, 0}, Key{0, 1} },
204 { Key{3, 2}, Key{3, 1}, Key{1, 1}, Key{0, 0} },
205 { Key{4, 1}, Key{4, 2}, Key{0, 0}, Key{0, 1} },
206 { Key{5, 2}, Key{4, 1}, Key{1, 1}, Key{0, 0} },
207 { Key{6, 2}, Key{4, 1}, Key{2, 1}, Key{0, 0} },
208 { Key{4, 1}, Key{7, 2}, Key{0, 0}, Key{3, 1} },
209 { Key{0, 0}, Key{0, 1}, Key{5, 1}, Key{8, 2} },
210 { Key{9, 2}, Key{1, 1}, Key{5, 1}, Key{0, 0} },
211 { Key{10, 2}, Key{2, 1}, Key{5, 1}, Key{0, 0} },
212 { Key{11, 2}, Key{5, 1}, Key{3, 1}, Key{0, 0} }
213 }};
214};
215
216// convert key array to global corner storage
217template<class S, class Geo, class KeyArray, std::size_t... I>
218S keyToCornerStorageImpl(const Geo& geo, const KeyArray& key, std::index_sequence<I...>)
219{
220 using Dune::referenceElement;
221 const auto ref = referenceElement(geo);
222 // key is a pair of a local sub-entity index (first) and the sub-entity's codim (second)
223 return { geo.global(ref.position(key[I].first, key[I].second))... };
224}
225
226// convert key array to global corner storage
227template<class S, class Geo, class T, std::size_t N, class Indices = std::make_index_sequence<N>>
228S keyToCornerStorage(const Geo& geo, const std::array<T, N>& key)
229{
230 return keyToCornerStorageImpl<S>(geo, key, Indices{});
231}
232
233// convert key array to global 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 Geo, class KeyArray, std::size_t... I>
236S subEntityKeyToCornerStorageImpl(const Geo& geo, unsigned int i, unsigned int c, const KeyArray& key, std::index_sequence<I...>)
237{
238 using Dune::referenceElement;
239 const auto ref = referenceElement(geo);
240 // subEntity gives the subEntity number with respect to the codim-0 reference element
241 // 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
242 return { geo.global(ref.position(ref.subEntity(i, c, key[I].first, c+key[I].second), c+key[I].second))... };
243}
244
245// convert key array to global corner storage
246// for the i-th sub-entity of codim c (e.g. the i-th facet/codim-1-entity for boundaries)
247template<class S, class Geo, class T, std::size_t N, class Indices = std::make_index_sequence<N>>
248S subEntityKeyToCornerStorage(const Geo& geo, unsigned int i, unsigned int c, const std::array<T, N>& key)
249{
250 return subEntityKeyToCornerStorageImpl<S>(geo, 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
271 using Element = typename GridView::template Codim<0>::Entity;
272 using Intersection = typename GridView::Intersection;
273
274 static constexpr int dim = 1;
275public:
276
277 BoxGeometryHelper(const typename Element::Geometry& geometry)
278 : geo_(geometry)
279 {}
280
282 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
283 {
285 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localScvIdx]);
286 }
287
288 ScvGeometry scvGeometry(unsigned int localScvIdx) const
289 {
290 return { Dune::GeometryTypes::line, getScvCorners(localScvIdx) };
291 }
292
294 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
295 {
297 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localScvfIdx]);
298 }
299
301 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex,
302 unsigned int) const
303 {
304 return ScvfCornerStorage{{ geo_.corner(localFacetIndex) }};
305 }
306
308 GlobalPosition normal(const ScvfCornerStorage& scvfCorners,
309 const std::vector<unsigned int>& scvIndices) const
310 {
311 auto normal = geo_.corner(1) - geo_.corner(0);
312 normal /= normal.two_norm();
313 return normal;
314 }
315
317 std::size_t numInteriorScvf() const
318 {
319 return referenceElement(geo_).size(dim-1);
320 }
321
323 std::size_t numScv() const
324 {
325 return referenceElement(geo_).size(dim);
326 }
327
329 const typename Element::Geometry& elementGeometry() const
330 { return geo_; }
331
332private:
333 const typename Element::Geometry& geo_;
334};
335
337template <class GridView, class ScvType, class ScvfType>
338class BoxGeometryHelper<GridView, 2, ScvType, ScvfType>
339{
340 using Scalar = typename GridView::ctype;
341 using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>;
342 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
343 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
344
345 using Element = typename GridView::template Codim<0>::Entity;
346 using Intersection = typename GridView::Intersection;
347
348 static constexpr auto dim = GridView::dimension;
349 static constexpr auto dimWorld = GridView::dimensionworld;
350public:
351
352 BoxGeometryHelper(const typename Element::Geometry& geometry)
353 : geo_(geometry)
354 {}
355
357 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
358 {
359 // proceed according to number of corners of the element
360 const auto type = geo_.type();
361 if (type == Dune::GeometryTypes::triangle)
362 {
364 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localScvIdx]);
365 }
366 else if (type == Dune::GeometryTypes::quadrilateral)
367 {
369 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localScvIdx]);
370 }
371 else
372 DUNE_THROW(Dune::NotImplemented, "Box scv geometries for dim=" << dim
373 << " dimWorld=" << dimWorld
374 << " type=" << type);
375 }
376
378 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
379 {
380 // proceed according to number of corners
381 const auto type = geo_.type();
382 if (type == Dune::GeometryTypes::triangle)
383 {
385 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localScvfIdx]);
386 }
387 else if (type == Dune::GeometryTypes::quadrilateral)
388 {
390 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localScvfIdx]);
391 }
392 else
393 DUNE_THROW(Dune::NotImplemented, "Box scvf geometries for dim=" << dim
394 << " dimWorld=" << dimWorld
395 << " type=" << type);
396 }
397
399 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex,
400 unsigned int indexInFacet) const
401 {
402 // we have to use the corresponding facet geometry as the intersection geometry
403 // might be rotated or flipped. This makes sure that the corners (dof location)
404 // and corresponding scvfs are sorted in the same way
406 constexpr int facetCodim = 1;
407 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(geo_, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
408 }
409
411 template <int w = dimWorld>
412 typename std::enable_if<w == 3, GlobalPosition>::type
413 normal(const ScvfCornerStorage& scvfCorners,
414 const std::vector<unsigned int>& scvIndices) const
415 {
416 const auto v1 = geo_.corner(1) - geo_.corner(0);
417 const auto v2 = geo_.corner(2) - geo_.corner(0);
418 const auto v3 = Dumux::crossProduct(v1, v2);
419 const auto t = scvfCorners[1] - scvfCorners[0];
420 GlobalPosition normal = Dumux::crossProduct(v3, t);
421 normal /= normal.two_norm();
422
424 const auto v = geo_.corner(scvIndices[1]) - geo_.corner(scvIndices[0]);
425 const auto s = v*normal;
426 if (std::signbit(s))
427 normal *= -1;
428
429 return normal;
430 }
431
433 template <int w = dimWorld>
434 typename std::enable_if<w == 2, GlobalPosition>::type
435 normal(const ScvfCornerStorage& scvfCorners,
436 const std::vector<unsigned int>& scvIndices) const
437 {
439 const auto t = scvfCorners[1] - scvfCorners[0];
440 GlobalPosition normal({-t[1], t[0]});
441 normal /= normal.two_norm();
442
444 const auto v = geo_.corner(scvIndices[1]) - geo_.corner(scvIndices[0]);
445 const auto s = v*normal;
446 if (std::signbit(s))
447 normal *= -1;
448
449 return normal;
450 }
451
453 std::size_t numInteriorScvf() const
454 {
455 return referenceElement(geo_).size(dim-1);
456 }
457
459 std::size_t numScv() const
460 {
461 return referenceElement(geo_).size(dim);
462 }
463
465 const typename Element::Geometry& elementGeometry() const
466 { return geo_; }
467
468private:
469 const typename Element::Geometry& geo_;
470};
471
473template <class GridView, class ScvType, class ScvfType>
474class BoxGeometryHelper<GridView, 3, ScvType, ScvfType>
475{
476 using Scalar = typename GridView::ctype;
477 using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>;
478 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
479 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
480
481 using Element = typename GridView::template Codim<0>::Entity;
482 using Intersection = typename GridView::Intersection;
483
484 static constexpr auto dim = GridView::dimension;
485 static constexpr auto dimWorld = GridView::dimensionworld;
486
487public:
488 BoxGeometryHelper(const typename Element::Geometry& geometry)
489 : geo_(geometry)
490 {}
491
493 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
494 {
495 const auto type = geo_.type();
496 if (type == Dune::GeometryTypes::tetrahedron)
497 {
499 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localScvIdx]);
500 }
501 else if (type == Dune::GeometryTypes::prism)
502 {
504 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localScvIdx]);
505 }
506 else if (type == Dune::GeometryTypes::hexahedron)
507 {
509 return Detail::Box::keyToCornerStorage<ScvCornerStorage>(geo_, Corners::keys[localScvIdx]);
510 }
511 else
512 DUNE_THROW(Dune::NotImplemented, "Box scv geometries for dim=" << dim
513 << " dimWorld=" << dimWorld
514 << " type=" << type);
515 }
516
518 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
519 {
520 // proceed according to number of corners
521 const auto type = geo_.type();
522 if (type == Dune::GeometryTypes::tetrahedron)
523 {
525 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localScvfIdx]);
526 }
527 else if (type == Dune::GeometryTypes::prism)
528 {
530 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localScvfIdx]);
531 }
532 else if (type == Dune::GeometryTypes::hexahedron)
533 {
535 return Detail::Box::keyToCornerStorage<ScvfCornerStorage>(geo_, Corners::keys[localScvfIdx]);
536 }
537 else
538 DUNE_THROW(Dune::NotImplemented, "Box scvf geometries for dim=" << dim
539 << " dimWorld=" << dimWorld
540 << " type=" << type);
541 }
542
544 ScvfCornerStorage getBoundaryScvfCorners(unsigned localFacetIndex,
545 unsigned int indexInFacet) const
546 {
547 constexpr int facetCodim = 1;
548
549 // we have to use the corresponding facet geometry as the intersection geometry
550 // might be rotated or flipped. This makes sure that the corners (dof location)
551 // and corresponding scvfs are sorted in the same way
552 using Dune::referenceElement;
553 const auto type = referenceElement(geo_).type(localFacetIndex, facetCodim);
554 if (type == Dune::GeometryTypes::triangle)
555 {
557 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(geo_, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
558 }
559 else if (type == Dune::GeometryTypes::quadrilateral)
560 {
562 return Detail::Box::subEntityKeyToCornerStorage<ScvfCornerStorage>(geo_, localFacetIndex, facetCodim, Corners::keys[indexInFacet]);
563 }
564 else
565 DUNE_THROW(Dune::NotImplemented, "Box boundary scvf geometries for dim=" << dim
566 << " dimWorld=" << dimWorld
567 << " type=" << type);
568 }
569
571 GlobalPosition normal(const ScvfCornerStorage& p,
572 const std::vector<unsigned int>& scvIndices) const
573 {
574 auto normal = Dumux::crossProduct(p[1]-p[0], p[2]-p[0]);
575 normal /= normal.two_norm();
576
577 const auto v = geo_.corner(scvIndices[1]) - geo_.corner(scvIndices[0]);
578 const auto s = v*normal;
579 if (std::signbit(s))
580 normal *= -1;
581
582 return normal;
583 }
584
586 std::size_t numInteriorScvf() const
587 {
588 return referenceElement(geo_).size(dim-1);
589 }
590
592 std::size_t numScv() const
593 {
594 return referenceElement(geo_).size(dim);
595 }
596
598 const typename Element::Geometry& elementGeometry() const
599 { return geo_; }
600
601private:
602 const typename Element::Geometry& geo_;
603};
604
605} // end namespace Dumux
606
607#endif
const Element::Geometry & elementGeometry() const
the wrapped element geometry
Definition: boxgeometryhelper.hh:329
std::size_t numInteriorScvf() const
number of sub control volume faces (number of edges)
Definition: boxgeometryhelper.hh:317
BoxGeometryHelper(const typename Element::Geometry &geometry)
Definition: boxgeometryhelper.hh:277
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition: boxgeometryhelper.hh:282
ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex, unsigned int) const
Create the sub control volume face geometries on the boundary.
Definition: boxgeometryhelper.hh:301
GlobalPosition normal(const ScvfCornerStorage &scvfCorners, const std::vector< unsigned int > &scvIndices) const
get scvf normal vector
Definition: boxgeometryhelper.hh:308
std::size_t numScv() const
number of sub control volumes (number of vertices)
Definition: boxgeometryhelper.hh:323
ScvGeometry scvGeometry(unsigned int localScvIdx) const
Definition: boxgeometryhelper.hh:288
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the corners of sub control volume faces.
Definition: boxgeometryhelper.hh:294
std::size_t numScv() const
number of sub control volumes (number of vertices)
Definition: boxgeometryhelper.hh:459
std::enable_if< w==2, GlobalPosition >::type normal(const ScvfCornerStorage &scvfCorners, const std::vector< unsigned int > &scvIndices) const
get scvf normal vector for dim == 2, dimworld == 2
Definition: boxgeometryhelper.hh:435
std::size_t numInteriorScvf() const
number of sub control volume faces (number of edges)
Definition: boxgeometryhelper.hh:453
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the corners of sub control volume faces.
Definition: boxgeometryhelper.hh:378
BoxGeometryHelper(const typename Element::Geometry &geometry)
Definition: boxgeometryhelper.hh:352
ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex, unsigned int indexInFacet) const
Create the sub control volume face geometries on the boundary.
Definition: boxgeometryhelper.hh:399
const Element::Geometry & elementGeometry() const
the wrapped element geometry
Definition: boxgeometryhelper.hh:465
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition: boxgeometryhelper.hh:357
std::enable_if< w==3, GlobalPosition >::type normal(const ScvfCornerStorage &scvfCorners, const std::vector< unsigned int > &scvIndices) const
get scvf normal vector for dim == 2, dimworld == 3
Definition: boxgeometryhelper.hh:413
ScvfCornerStorage getBoundaryScvfCorners(unsigned localFacetIndex, unsigned int indexInFacet) const
Create the sub control volume face geometries on the boundary.
Definition: boxgeometryhelper.hh:544
GlobalPosition normal(const ScvfCornerStorage &p, const std::vector< unsigned int > &scvIndices) const
get scvf normal vector
Definition: boxgeometryhelper.hh:571
BoxGeometryHelper(const typename Element::Geometry &geometry)
Definition: boxgeometryhelper.hh:488
const Element::Geometry & elementGeometry() const
the wrapped element geometry
Definition: boxgeometryhelper.hh:598
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition: boxgeometryhelper.hh:493
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the scvf corners.
Definition: boxgeometryhelper.hh:518
std::size_t numScv() const
number of sub control volumes (number of vertices)
Definition: boxgeometryhelper.hh:592
std::size_t numInteriorScvf() const
number of sub control volume faces (number of edges)
Definition: boxgeometryhelper.hh:586
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:642
Vector normal(const Vector &v)
Create a vector normal to the given one (v is expected to be non-zero)
Definition: normal.hh:26
Define some often used mathematical functions.
S subEntityKeyToCornerStorage(const Geo &geo, unsigned int i, unsigned int c, const std::array< T, N > &key)
Definition: boxgeometryhelper.hh:248
S subEntityKeyToCornerStorageImpl(const Geo &geo, unsigned int i, unsigned int c, const KeyArray &key, std::index_sequence< I... >)
Definition: boxgeometryhelper.hh:236
S keyToCornerStorage(const Geo &geo, const std::array< T, N > &key)
Definition: boxgeometryhelper.hh:228
S keyToCornerStorageImpl(const Geo &geo, const KeyArray &key, std::index_sequence< I... >)
Definition: boxgeometryhelper.hh:218
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:37
std::array< Dune::FieldVector< ct, cdim >,(1<<(mydim)) > Type
Definition: boxgeometryhelper.hh:38
Definition: boxgeometryhelper.hh:44
static const bool v
Definition: boxgeometryhelper.hh:45
static const unsigned int topologyId
Definition: boxgeometryhelper.hh:46
Traits for an efficient corner storage for box method sub control volumes.
Definition: boxgeometryhelper.hh:32
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:117
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:58
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:103
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:79
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:91
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:68
Definition: boxgeometryhelper.hh:53
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:199
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:136
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:182
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:156
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:168
std::pair< std::uint8_t, std::uint8_t > Key
Definition: boxgeometryhelper.hh:145
Definition: boxgeometryhelper.hh:131