version 3.11-dev
Loading...
Searching...
No Matches
pq3/dofhelper.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//
7// This file includes code adapted from dune-functions.
8// These parts are clearly marked with inline comments and were originally
9// licensed under LGPL-3.0-or-later. They are adapted and relicensed here
10// under the terms of the GNU GPL-3.0-or-later as permitted by LGPLv3 Sec. 3.
11//
12// SPDX-FileCopyrightText: Copyright © DUNE Project contributors, see file AUTHORS.md
13//
25#ifndef DUMUX_DISCRETIZATION_PQ3_DOF_HELPER_HH
26#define DUMUX_DISCRETIZATION_PQ3_DOF_HELPER_HH
27
28#include <array>
29#include <cstdint>
30
31#include <dune/common/fvector.hh>
32#include <dune/geometry/referenceelements.hh>
33
35
36namespace Dumux {
37
49template<class GridView>
51{
52private:
54 using LocalIndexType = typename IndexTraits<GridView>::LocalIndex;
55 using GridIndexType = typename IndexTraits<GridView>::GridIndex;
56 using Scalar = typename GridView::ctype;
57 static constexpr int dim = GridView::dimension;
58 using GlobalPosition = Dune::FieldVector<Scalar, GridView::dimensionworld>;
59
60public:
70 template<class DofMapper, class Element, class LocalKey, class IdSet>
71 static std::size_t dofIndex(const DofMapper& m, const Element& e,
72 const LocalKey& lk, const IdSet& idSet)
73 {
74 const auto base = m.subIndex(e, lk.subEntity(), lk.codim());
75 const auto& ref = Dune::referenceElement<Scalar, dim>(e.type());
76
77 if (lk.codim() == 0 || lk.codim() == dim)
78 return base + lk.index();
79
80 if (lk.codim() == dim - 1)
81 {
82 const int rv0 = ref.subEntity(lk.subEntity(), dim-1, 0, dim);
83 const int rv1 = ref.subEntity(lk.subEntity(), dim-1, 1, dim);
84 const bool flip = idSet.subId(e, rv0, dim) > idSet.subId(e, rv1, dim);
85 return base + (flip ? 1 - (int)lk.index() : (int)lk.index());
86 }
87
88 if constexpr (dim == 3)
89 {
90 if (lk.codim() == 1)
91 {
92 if (ref.type(lk.subEntity(), 1).isTriangle())
93 return base + lk.index();
94 if (ref.type(lk.subEntity(), 1).isQuadrilateral())
95 {
96 const auto j = quadFaceOrientIdx_(e, lk.subEntity(), ref, idSet);
97 return base + quadFacePerm_[j][lk.index()];
98 }
99 }
100 }
101
102 return base + lk.index();
103 }
104
109 template<class ElemDisc>
110 static auto localDofs(const ElemDisc& elemDisc)
111 {
112 const auto& gridDisc = elemDisc.gridDiscretization();
113
114 return Dune::transformedRangeView(
115 Dune::range(elemDisc.numLocalDofs()),
116 [&](const auto i) {
117 return CVFE::LocalDof{
118 static_cast<LocalIndexType>(i),
119 static_cast<GridIndexType>(dofIndex(
120 gridDisc.dofMapper(),
121 elemDisc.element(),
122 elemDisc.feLocalCoefficients().localKey(i),
123 gridDisc.gridView().grid().globalIdSet())),
124 static_cast<GridIndexType>(elemDisc.elementIndex())
125 };
126 }
127 );
128 }
129
136 template<class ElemDisc, class BoundaryFace>
137 static auto localDofsOnBoundaryFace(const ElemDisc& elemDisc, const BoundaryFace& boundaryFace)
138 {
139 const auto& gridDisc = elemDisc.gridDiscretization();
140
141 return std::views::iota(std::size_t(0), elemDisc.numLocalDofs())
142 | std::views::filter([&](std::size_t i) {
144 elemDisc.element().type(),
145 boundaryFace.intersectionIndex(),
146 elemDisc.feLocalCoefficients().localKey(i));
147 })
148 | std::views::transform([&](std::size_t i) {
149 return CVFE::LocalDof(
150 static_cast<LocalIndexType>(i),
151 static_cast<GridIndexType>(dofIndex(
152 gridDisc.dofMapper(),
153 elemDisc.element(),
154 elemDisc.feLocalCoefficients().localKey(i),
155 gridDisc.gridView().grid().globalIdSet())),
156 static_cast<GridIndexType>(elemDisc.elementIndex())
157 );
158 });
159 }
160
162 template<class Geometry, class LocalKey>
163 static GlobalPosition dofPosition(const Geometry& geo, const LocalKey& lk)
164 { return geo.global(localDofPos_(geo.type(), lk)); }
165
167 template<class LocalKey>
168 static typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate
169 localDofPosition(Dune::GeometryType gt, const LocalKey& lk)
170 { return localDofPos_(gt, lk); }
171
172private:
173 // Permutation table for Q3 quad-face interior DOFs (4 DOFs, 8 orientations).
174 // Adapted from dune-functions LagrangeFaceDOFPermutation::globallyOrientedQuadrilateralDOFTable(3).
175 static constexpr std::array<std::array<unsigned char, 4>, 8> quadFacePerm_ = {{
176 {0,1,2,3}, {1,3,0,2}, {3,2,1,0}, {2,0,3,1},
177 {0,2,1,3}, {2,3,0,1}, {3,1,2,0}, {1,0,3,2},
178 }};
179
180 // Compute orientation index j in [0,8) for a quad face (3D, codim=1).
181 // Adapted from dune-functions FaceOrientations::computeQuadrilateralOrientation.
182 template<class Element, class IdSet>
183 static unsigned int quadFaceOrientIdx_(const Element& e, unsigned int face,
184 const auto& ref, const IdSet& idSet)
185 {
186 std::array<typename IdSet::IdType, 4> vg;
187 for (int i = 0; i < 4; ++i)
188 vg[i] = idSet.subId(e, ref.subEntity(face, 1, i, dim), dim);
189
190 const auto flip = [&](int ed) {
191 const int ei = ref.subEntity(face, 1, ed, dim-1);
192 return idSet.subId(e, ref.subEntity(ei, dim-1, 0, dim), dim)
193 > idSet.subId(e, ref.subEntity(ei, dim-1, 1, dim), dim);
194 };
195 const std::size_t eo = (std::size_t(flip(0))<<0) | (std::size_t(flip(1))<<1)
196 | (std::size_t(flip(2))<<2) | (std::size_t(flip(3))<<3);
197
198 constexpr uint32_t eoToImin = 0b11'11'01'01'11'00'00'00'10'00'00'01'10'00'10'00;
199 std::size_t i_min;
200 if (eo == 5) i_min = (vg[1] < vg[2]) ? 1 : 2;
201 else if (eo == 10) i_min = (vg[0] < vg[3]) ? 0 : 3;
202 else i_min = (eoToImin >> (2*eo)) & 3;
203
204 if (i_min == 0) return 0u | (unsigned(vg[2] < vg[1]) << 2);
205 if (i_min == 1) return 3u | (unsigned(vg[0] < vg[3]) << 2);
206 if (i_min == 2) return 1u | (unsigned(vg[3] < vg[0]) << 2);
207 /*i_min==3*/ return 2u | (unsigned(vg[1] < vg[2]) << 2);
208 }
209
210 template<class LocalKey>
211 static typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate
212 localDofPos_(Dune::GeometryType gt, const LocalKey& lk)
213 {
214 using LocalCoord = typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate;
215 const auto ref = Dune::referenceElement<Scalar, dim>(gt);
216
217 if (lk.codim() == dim)
218 return ref.position(lk.subEntity(), dim);
219
220 if (lk.codim() == dim - 1)
221 {
222 const int v0 = ref.subEntity(lk.subEntity(), dim-1, 0, dim);
223 const int v1 = ref.subEntity(lk.subEntity(), dim-1, 1, dim);
224 auto pos = LocalCoord(ref.position(v0, dim));
225 const auto dir = LocalCoord(ref.position(v1, dim)) - pos;
226 pos.axpy(Scalar(lk.index() + 1) / Scalar(3), dir);
227 return pos;
228 }
229
230 if constexpr (dim == 3)
231 {
232 if (lk.codim() == 1)
233 {
234 const auto faceGeom = ref.template geometry<1>(lk.subEntity());
235 if (gt.isSimplex())
236 {
237 const Dune::FieldVector<Scalar, 2> c{Scalar(1)/3, Scalar(1)/3};
238 return faceGeom.global(c);
239 }
240 else
241 {
242 const auto ix = lk.index() % 2, iy = lk.index() / 2;
243 const Dune::FieldVector<Scalar, 2> c{Scalar(ix+1)/3, Scalar(iy+1)/3};
244 return faceGeom.global(c);
245 }
246 }
247 }
248
249 if (lk.codim() == 0)
250 {
251 if (gt.isSimplex())
252 return ref.position(0, 0);
253
254 if constexpr (dim == 2)
255 {
256 const auto ix = lk.index() % 2, iy = lk.index() / 2;
257 return LocalCoord{Scalar(ix+1)/3, Scalar(iy+1)/3};
258 }
259 else if constexpr (dim == 3)
260 {
261 const auto ix = lk.index()%2, iy = (lk.index()/2)%2, iz = lk.index()/4;
262 return LocalCoord{Scalar(ix+1)/3, Scalar(iy+1)/3, Scalar(iz+1)/3};
263 }
264 }
265
266 DUNE_THROW(Dune::NotImplemented, "PQ3 local DOF position for codim=" << lk.codim());
267 }
268};
269
270} // namespace Dumux
271
272#endif // DUMUX_DISCRETIZATION_PQ3_DOF_HELPER_HH
A local degree of freedom from an element perspective.
Definition localdof.hh:27
Default Dof helper for finite-element discretizations providing dof-related utility functions....
Definition fedofhelper.hh:34
static auto localDofOnIntersection(Dune::GeometryType type, unsigned int iIdx, const LocalKey &localKey)
Returns true if the local dof with a given local key is on the intersection with index iIdx.
Definition fedofhelper.hh:48
DOF index and position helper for order-3 Lagrange discretizations.
Definition pq3/dofhelper.hh:51
static GridView::template Codim< 0 >::Entity::Geometry::LocalCoordinate localDofPosition(Dune::GeometryType gt, const LocalKey &lk)
Reference-element position of a DOF for order-3 Lagrange basis.
Definition pq3/dofhelper.hh:169
static auto localDofs(const ElemDisc &elemDisc)
Iterator range over all local dofs on an element.
Definition pq3/dofhelper.hh:110
static GlobalPosition dofPosition(const Geometry &geo, const LocalKey &lk)
Physical position of a DOF in global coordinates.
Definition pq3/dofhelper.hh:163
static std::size_t dofIndex(const DofMapper &m, const Element &e, const LocalKey &lk, const IdSet &idSet)
Orientation-consistent global DOF index.
Definition pq3/dofhelper.hh:71
static auto localDofsOnBoundaryFace(const ElemDisc &elemDisc, const BoundaryFace &boundaryFace)
Iterator range over all local dofs on a given boundary face. Uses a filter over all local dofs via lo...
Definition pq3/dofhelper.hh:137
Default Dof helper for finite-element discretizations providing dof-related utility functions....
Definition adapt.hh:17
const Scalar PengRobinsonMixture< Scalar, StaticParameters >::u
Definition pengrobinsonmixture.hh:138
typename GridView::IndexSet::IndexType GridIndex
Definition indextraits.hh:27
unsigned int LocalIndex
Definition indextraits.hh:28