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
34namespace Dumux {
35
47template<class GridView>
49{
50 using Scalar = typename GridView::ctype;
51 static constexpr int dim = GridView::dimension;
52 using GlobalPosition = Dune::FieldVector<Scalar, GridView::dimensionworld>;
53
63 template<class DofMapper, class Element, class LocalKey, class IdSet>
64 static std::size_t dofIndex(const DofMapper& m, const Element& e,
65 const LocalKey& lk, const IdSet& idSet)
66 {
67 const auto base = m.subIndex(e, lk.subEntity(), lk.codim());
68 const auto& ref = Dune::referenceElement<Scalar, dim>(e.type());
69
70 if (lk.codim() == 0 || lk.codim() == dim)
71 return base + lk.index();
72
73 if (lk.codim() == dim - 1)
74 {
75 const int rv0 = ref.subEntity(lk.subEntity(), dim-1, 0, dim);
76 const int rv1 = ref.subEntity(lk.subEntity(), dim-1, 1, dim);
77 const bool flip = idSet.subId(e, rv0, dim) > idSet.subId(e, rv1, dim);
78 return base + (flip ? 1 - (int)lk.index() : (int)lk.index());
79 }
80
81 if constexpr (dim == 3)
82 {
83 if (lk.codim() == 1)
84 {
85 if (ref.type(lk.subEntity(), 1).isTriangle())
86 return base + lk.index();
87 if (ref.type(lk.subEntity(), 1).isQuadrilateral())
88 {
89 const auto j = quadFaceOrientIdx_(e, lk.subEntity(), ref, idSet);
90 return base + quadFacePerm_[j][lk.index()];
91 }
92 }
93 }
94
95 return base + lk.index();
96 }
97
99 template<class Geometry, class LocalKey>
100 static GlobalPosition dofPosition(const Geometry& geo, const LocalKey& lk)
101 { return geo.global(localDofPos_(geo.type(), lk)); }
102
104 template<class LocalKey>
105 static typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate
106 localDofPos(Dune::GeometryType gt, const LocalKey& lk)
107 { return localDofPos_(gt, lk); }
108
109private:
110 // Permutation table for Q3 quad-face interior DOFs (4 DOFs, 8 orientations).
111 // Adapted from dune-functions LagrangeFaceDOFPermutation::globallyOrientedQuadrilateralDOFTable(3).
112 static constexpr std::array<std::array<unsigned char, 4>, 8> quadFacePerm_ = {{
113 {0,1,2,3}, {1,3,0,2}, {3,2,1,0}, {2,0,3,1},
114 {0,2,1,3}, {2,3,0,1}, {3,1,2,0}, {1,0,3,2},
115 }};
116
117 // Compute orientation index j in [0,8) for a quad face (3D, codim=1).
118 // Adapted from dune-functions FaceOrientations::computeQuadrilateralOrientation.
119 template<class Element, class IdSet>
120 static unsigned int quadFaceOrientIdx_(const Element& e, unsigned int face,
121 const auto& ref, const IdSet& idSet)
122 {
123 std::array<std::size_t, 4> vg;
124 for (int i = 0; i < 4; ++i)
125 vg[i] = idSet.subId(e, ref.subEntity(face, 1, i, dim), dim);
126
127 const auto flip = [&](int ed) {
128 const int ei = ref.subEntity(face, 1, ed, dim-1);
129 return idSet.subId(e, ref.subEntity(ei, dim-1, 0, dim), dim)
130 > idSet.subId(e, ref.subEntity(ei, dim-1, 1, dim), dim);
131 };
132 const std::size_t eo = (std::size_t(flip(0))<<0) | (std::size_t(flip(1))<<1)
133 | (std::size_t(flip(2))<<2) | (std::size_t(flip(3))<<3);
134
135 constexpr uint32_t eoToImin = 0b11'11'01'01'11'00'00'00'10'00'00'01'10'00'10'00;
136 std::size_t i_min;
137 if (eo == 5) i_min = (vg[1] < vg[2]) ? 1 : 2;
138 else if (eo == 10) i_min = (vg[0] < vg[3]) ? 0 : 3;
139 else i_min = (eoToImin >> (2*eo)) & 3;
140
141 if (i_min == 0) return 0u | (unsigned(vg[2] < vg[1]) << 2);
142 if (i_min == 1) return 3u | (unsigned(vg[0] < vg[3]) << 2);
143 if (i_min == 2) return 1u | (unsigned(vg[3] < vg[0]) << 2);
144 /*i_min==3*/ return 2u | (unsigned(vg[1] < vg[2]) << 2);
145 }
146
147 template<class LocalKey>
148 static typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate
149 localDofPos_(Dune::GeometryType gt, const LocalKey& lk)
150 {
151 using LocalCoord = typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate;
152 const auto ref = Dune::referenceElement<Scalar, dim>(gt);
153
154 if (lk.codim() == dim)
155 return ref.position(lk.subEntity(), dim);
156
157 if (lk.codim() == dim - 1)
158 {
159 const int v0 = ref.subEntity(lk.subEntity(), dim-1, 0, dim);
160 const int v1 = ref.subEntity(lk.subEntity(), dim-1, 1, dim);
161 auto pos = LocalCoord(ref.position(v0, dim));
162 const auto dir = LocalCoord(ref.position(v1, dim)) - pos;
163 pos.axpy(Scalar(lk.index() + 1) / Scalar(3), dir);
164 return pos;
165 }
166
167 if constexpr (dim == 3)
168 {
169 if (lk.codim() == 1)
170 {
171 const auto faceGeom = ref.template geometry<1>(lk.subEntity());
172 if (gt.isSimplex())
173 {
174 const Dune::FieldVector<Scalar, 2> c{Scalar(1)/3, Scalar(1)/3};
175 return faceGeom.global(c);
176 }
177 else
178 {
179 const auto ix = lk.index() % 2, iy = lk.index() / 2;
180 const Dune::FieldVector<Scalar, 2> c{Scalar(ix+1)/3, Scalar(iy+1)/3};
181 return faceGeom.global(c);
182 }
183 }
184 }
185
186 if (lk.codim() == 0)
187 {
188 if (gt.isSimplex())
189 return ref.position(0, 0);
190
191 if constexpr (dim == 2)
192 {
193 const auto ix = lk.index() % 2, iy = lk.index() / 2;
194 return LocalCoord{Scalar(ix+1)/3, Scalar(iy+1)/3};
195 }
196 else if constexpr (dim == 3)
197 {
198 const auto ix = lk.index()%2, iy = (lk.index()/2)%2, iz = lk.index()/4;
199 return LocalCoord{Scalar(ix+1)/3, Scalar(iy+1)/3, Scalar(iz+1)/3};
200 }
201 }
202
203 DUNE_THROW(Dune::NotImplemented, "PQ3 local DOF position for codim=" << lk.codim());
204 }
205};
206
207} // namespace Dumux
208
209#endif // DUMUX_DISCRETIZATION_PQ3_DOF_HELPER_HH
Definition adapt.hh:17
const Scalar PengRobinsonMixture< Scalar, StaticParameters >::u
Definition pengrobinsonmixture.hh:138
DOF index and position helper for order-3 Lagrange discretizations.
Definition pq3/dofhelper.hh:49
static constexpr int dim
Definition pq3/dofhelper.hh:51
Dune::FieldVector< Scalar, GridView::dimensionworld > GlobalPosition
Definition pq3/dofhelper.hh:52
static GlobalPosition dofPosition(const Geometry &geo, const LocalKey &lk)
Physical position of a DOF in global coordinates.
Definition pq3/dofhelper.hh:100
static GridView::template Codim< 0 >::Entity::Geometry::LocalCoordinate localDofPos(Dune::GeometryType gt, const LocalKey &lk)
Reference-element position of a DOF for order-3 Lagrange basis.
Definition pq3/dofhelper.hh:106
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:64
typename GridView::ctype Scalar
Definition pq3/dofhelper.hh:50