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