version 3.11-dev
discretization/pq2/geometryhelper.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_PQ2_GEOMETRY_HELPER_HH
14#define DUMUX_DISCRETIZATION_PQ2_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/referenceelements.hh>
22#include <dune/geometry/multilineargeometry.hh>
23#include <dune/common/reservedvector.hh>
24
25#include <dumux/common/math.hh>
28
29namespace Dumux {
30
32template <class ct>
33struct PQ2MLGeometryTraits : public Dune::MultiLinearGeometryTraits<ct>
34{
35 // we use static vectors to store the corners as we know
36 // the maximum number of corners in advance
37 template< int mydim, int cdim >
39 {
40 using Type = Dune::ReservedVector< Dune::FieldVector< ct, cdim >, (1<<mydim)+ mydim*(1<<(mydim-1))>;
41 };
42};
43
48template <class GridView, class ScvType, class ScvfType>
50{
51 using Scalar = typename GridView::ctype;
52 using GlobalPosition = typename Dune::FieldVector<Scalar, GridView::dimensionworld>;
53 using ScvCornerStorage = typename ScvType::Traits::CornerStorage;
54 using ScvfCornerStorage = typename ScvfType::Traits::CornerStorage;
55 using LocalIndexType = typename ScvType::Traits::LocalIndexType;
56
57 using Element = typename GridView::template Codim<0>::Entity;
58 using Intersection = typename GridView::Intersection;
59
60 static constexpr auto dim = GridView::dimension;
61 static constexpr auto dimWorld = GridView::dimensionworld;
62
64public:
65
66 HybridPQ2GeometryHelper(const typename Element::Geometry& geometry)
67 : geo_(geometry)
68 , boxHelper_(geometry)
69 {}
70
72 ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
73 {
74 return getScvCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvIdx);
75 }
76
78 template<class Transformation>
79 static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvIdx)
80 {
81 // proceed according to number of corners of the element
82 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
83 const auto numBoxScv = ref.size(dim);
84 // reuse box geometry helper for the corner scvs
85 if (localScvIdx < numBoxScv)
86 return BoxHelper::getScvCorners(type, trans, localScvIdx);
87
88 DUNE_THROW(Dune::NotImplemented, "PQ2 scv corners call for hybrid dofs");
89 }
90
91 Dune::GeometryType getScvGeometryType(unsigned int localScvIdx) const
92 {
93 // proceed according to number of corners of the element
94 const auto numBoxScv = boxHelper_.numScv();
95
96 if (localScvIdx < numBoxScv)
97 return Dune::GeometryTypes::cube(dim);
98
99 DUNE_THROW(Dune::NotImplemented, "PQ2 scv geometry call for hybrid dofs");
100 }
101
103 ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
104 {
105 return getScvfCorners(geo_.type(), [&](const auto& local){ return geo_.global(local); }, localScvfIdx);
106 }
107
109 template<class Transformation>
110 static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation&& trans, unsigned int localScvfIdx)
111 {
112 // proceed according to number of corners
113 const auto& ref = Dune::referenceElement<Scalar, dim>(type);
114 const auto numBoxScvf = ref.size(dim-1);
115 // reuse box geometry helper for scvfs
116 if (localScvfIdx < numBoxScvf)
117 return BoxHelper::getScvfCorners(type, trans, localScvfIdx);
118
119 DUNE_THROW(Dune::NotImplemented, "PQ2 scvf corners call for hybrid dofs");
120 }
121
122 Dune::GeometryType getInteriorScvfGeometryType(unsigned int localScvfIdx) const
123 {
124 const auto numBoxScvf = boxHelper_.numInteriorScvf();
125 if (localScvfIdx < numBoxScvf)
126 return Dune::GeometryTypes::cube(dim-1);
127
128 DUNE_THROW(Dune::NotImplemented, "PQ2 interior scvf geometry type call for hybrid dofs");
129 }
130
132 ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex,
133 unsigned int indexInFacet) const
134 {
135 return boxHelper_.getBoundaryScvfCorners(localFacetIndex, indexInFacet);
136 }
137
138 Dune::GeometryType getBoundaryScvfGeometryType(unsigned int localScvfIdx) const
139 {
140 return Dune::GeometryTypes::cube(dim-1);
141 }
142
143 template<int d = dimWorld, std::enable_if_t<(d==3), int> = 0>
144 GlobalPosition normal(const ScvfCornerStorage& p, const std::array<LocalIndexType, 2>& scvPair)
145 {
146 auto normal = Dumux::crossProduct(p[1]-p[0], p[2]-p[0]);
147 normal /= normal.two_norm();
148
149 GlobalPosition v = geo_.corner(scvPair[1]) - geo_.corner(scvPair[0]);
150
151 const auto s = v*normal;
152 if (std::signbit(s))
153 normal *= -1;
154
155 return normal;
156 }
157
158 template<int d = dimWorld, std::enable_if_t<(d==2), int> = 0>
159 GlobalPosition normal(const ScvfCornerStorage& p, const std::array<LocalIndexType, 2>& scvPair)
160 {
162 const auto t = p[1] - p[0];
163 GlobalPosition normal({-t[1], t[0]});
164 normal /= normal.two_norm();
165
166 GlobalPosition v = geo_.corner(scvPair[1]) - geo_.corner(scvPair[0]);
167
168 const auto s = v*normal;
169 if (std::signbit(s))
170 normal *= -1;
171
172 return normal;
173 }
174
176 const typename Element::Geometry& elementGeometry() const
177 { return geo_; }
178
180 static auto numInteriorScvf(Dune::GeometryType type)
181 {
182 return BoxHelper::numInteriorScvf(type);
183 }
184
186 static auto numBoundaryScvf(Dune::GeometryType type, unsigned int localFacetIndex)
187 {
188 return Dune::referenceElement<Scalar, dim>(type).size(localFacetIndex, 1, dim);
189 }
190
192 std::size_t numScv() const
193 {
194 return boxHelper_.numScv();
195 }
196
198 Scalar scvVolume(unsigned int localScvIdx, const ScvCornerStorage& p) const
199 {
200 const auto scvType = getScvGeometryType(localScvIdx);
201
202 return Dumux::convexPolytopeVolume<dim>(
203 scvType,
204 [&](unsigned int i){ return p[i]; }
205 );
206 }
207
209 template<class LocalKey>
210 static auto localDofOnIntersection(Dune::GeometryType type, unsigned int iIdx, const LocalKey& localKey)
211 {
212 const auto& refElement = Dune::referenceElement<Scalar, dim>(type);
213
214 const auto numEntitiesIntersection = refElement.size(iIdx, 1, localKey.codim());
215 for(std::size_t idx=0; idx < numEntitiesIntersection; idx++)
216 if(localKey.subEntity() == refElement.subEntity(iIdx, 1, idx, localKey.codim()))
217 return true;
218
219 return false;
220 }
221
222 template<class DofMapper, class LocalKey>
223 static auto dofIndex(const DofMapper& dofMapper, const Element& element, const LocalKey& localKey)
224 {
225 // All dofs are directly related to grid entities, i.e localKey.index() is always zero
226 return dofMapper.subIndex(element, localKey.subEntity(), localKey.codim());
227 }
228
229 template<class Geometry, class LocalKey>
230 static GlobalPosition dofPosition(const Geometry& geo, const LocalKey& localKey)
231 {
232 if(localKey.codim() == dim)
233 return geo.corner(localKey.subEntity());
234 else if(localKey.codim() == 0) // should only be called for cubes
235 return geo.center();
236 else
237 return geo.global(localDofPosition(geo.type(), localKey));
238 }
239
240 template<class LocalKey>
241 GlobalPosition dofPosition(const LocalKey& localKey) const
242 {
243 return dofPosition(geo_, localKey);
244 }
245
247 template<class LocalKey>
248 static Element::Geometry::LocalCoordinate localDofPosition(Dune::GeometryType type, const LocalKey& localKey)
249 {
250 return Dune::referenceElement<Scalar, dim>(type).position(localKey.subEntity(), localKey.codim());
251 }
252
253 std::array<LocalIndexType, 2> getScvPairForScvf(unsigned int localScvfIndex) const
254 {
255 const auto numBoxFaces = boxHelper_.numInteriorScvf();
256 if (localScvfIndex < numBoxFaces)
257 {
258 return {
259 static_cast<LocalIndexType>(referenceElement(geo_).subEntity(localScvfIndex, dim-1, 0, dim)),
260 static_cast<LocalIndexType>(referenceElement(geo_).subEntity(localScvfIndex, dim-1, 1, dim))
261 };
262 }
263
264 DUNE_THROW(Dune::NotImplemented, "PQ2 scv pair call for hybrid dofs");
265 }
266
267 std::array<LocalIndexType, 2> getScvPairForBoundaryScvf(unsigned int localFacetIndex, unsigned int localIsScvfIndex) const
268 {
269 const auto numBoxScvf = referenceElement(geo_).size(localFacetIndex, 1, dim);
270 if (localIsScvfIndex < numBoxScvf)
271 {
272 const LocalIndexType insideScvIdx
273 = static_cast<LocalIndexType>(referenceElement(geo_).subEntity(localFacetIndex, 1, localIsScvfIndex, dim));
274 return { insideScvIdx, insideScvIdx };
275 }
276
277 DUNE_THROW(Dune::NotImplemented, "PQ2 scv boundary pair call for hybrid dofs");
278 }
279
280 // For hybrid dofs we don't construct scvfs
281 bool isOverlappingScvf(unsigned int localScvfIndex) const
282 { return false; }
283
284 bool isOverlappingBoundaryScvf(unsigned int localFacetIndex) const
285 { return false; }
286
287 // For hybrid dofs we don't construct scvs
288 bool isOverlappingScv(unsigned int localScvIndex) const
289 { return false; }
290
291private:
292 const typename Element::Geometry& geo_;
293 BoxHelper boxHelper_;
294};
295
296} // end namespace Dumux
297
298#endif
Helper class constructing the dual grid finite volume geometries for the box discretizazion method.
Create sub control volumes and sub control volume face geometries.
Definition: boxgeometryhelper.hh:257
A class to create sub control volume and sub control volume face geometries per element.
Definition: discretization/pq2/geometryhelper.hh:50
Dune::GeometryType getBoundaryScvfGeometryType(unsigned int localScvfIdx) const
Definition: discretization/pq2/geometryhelper.hh:138
std::size_t numScv() const
number of sub control volumes (number of codim-1 entities)
Definition: discretization/pq2/geometryhelper.hh:192
bool isOverlappingBoundaryScvf(unsigned int localFacetIndex) const
Definition: discretization/pq2/geometryhelper.hh:284
ScvfCornerStorage getScvfCorners(unsigned int localScvfIdx) const
Create a vector with the corners of sub control volume faces.
Definition: discretization/pq2/geometryhelper.hh:103
GlobalPosition dofPosition(const LocalKey &localKey) const
Definition: discretization/pq2/geometryhelper.hh:241
bool isOverlappingScvf(unsigned int localScvfIndex) const
Definition: discretization/pq2/geometryhelper.hh:281
static auto dofIndex(const DofMapper &dofMapper, const Element &element, const LocalKey &localKey)
Definition: discretization/pq2/geometryhelper.hh:223
static auto localDofOnIntersection(Dune::GeometryType type, unsigned int iIdx, const LocalKey &localKey)
Local dof index related to a localDof, with index ilocalDofIdx, on an intersection with index iIdx.
Definition: discretization/pq2/geometryhelper.hh:210
std::array< LocalIndexType, 2 > getScvPairForBoundaryScvf(unsigned int localFacetIndex, unsigned int localIsScvfIndex) const
Definition: discretization/pq2/geometryhelper.hh:267
ScvCornerStorage getScvCorners(unsigned int localScvIdx) const
Create a vector with the scv corners.
Definition: discretization/pq2/geometryhelper.hh:72
const Element::Geometry & elementGeometry() const
the wrapped element geometry
Definition: discretization/pq2/geometryhelper.hh:176
std::array< LocalIndexType, 2 > getScvPairForScvf(unsigned int localScvfIndex) const
Definition: discretization/pq2/geometryhelper.hh:253
static auto numInteriorScvf(Dune::GeometryType type)
number of interior sub control volume faces
Definition: discretization/pq2/geometryhelper.hh:180
ScvfCornerStorage getBoundaryScvfCorners(unsigned int localFacetIndex, unsigned int indexInFacet) const
Create the sub control volume face geometries on the boundary.
Definition: discretization/pq2/geometryhelper.hh:132
Scalar scvVolume(unsigned int localScvIdx, const ScvCornerStorage &p) const
get scv volume
Definition: discretization/pq2/geometryhelper.hh:198
static auto numBoundaryScvf(Dune::GeometryType type, unsigned int localFacetIndex)
number of boundary sub control volume faces for face localFacetIndex
Definition: discretization/pq2/geometryhelper.hh:186
static Element::Geometry::LocalCoordinate localDofPosition(Dune::GeometryType type, const LocalKey &localKey)
local dof position
Definition: discretization/pq2/geometryhelper.hh:248
Dune::GeometryType getInteriorScvfGeometryType(unsigned int localScvfIdx) const
Definition: discretization/pq2/geometryhelper.hh:122
Dune::GeometryType getScvGeometryType(unsigned int localScvIdx) const
Definition: discretization/pq2/geometryhelper.hh:91
GlobalPosition normal(const ScvfCornerStorage &p, const std::array< LocalIndexType, 2 > &scvPair)
Definition: discretization/pq2/geometryhelper.hh:144
bool isOverlappingScv(unsigned int localScvIndex) const
Definition: discretization/pq2/geometryhelper.hh:288
HybridPQ2GeometryHelper(const typename Element::Geometry &geometry)
Definition: discretization/pq2/geometryhelper.hh:66
static GlobalPosition dofPosition(const Geometry &geo, const LocalKey &localKey)
Definition: discretization/pq2/geometryhelper.hh:230
static ScvfCornerStorage getScvfCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvfIdx)
Create a vector with the corners of sub control volume faces.
Definition: discretization/pq2/geometryhelper.hh:110
static ScvCornerStorage getScvCorners(Dune::GeometryType type, Transformation &&trans, unsigned int localScvIdx)
Create a vector with the scv corners.
Definition: discretization/pq2/geometryhelper.hh:79
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
Define some often used mathematical functions.
Definition: adapt.hh:17
Definition: discretization/pq2/geometryhelper.hh:39
Dune::ReservedVector< Dune::FieldVector< ct, cdim >,(1<< mydim)+mydim *(1<<(mydim-1))> Type
Definition: discretization/pq2/geometryhelper.hh:40
Traits for an efficient corner storage for the PQ2 method.
Definition: discretization/pq2/geometryhelper.hh:34
Compute the volume of several common geometry types.