50 using Scalar =
typename GridView::ctype;
51 static constexpr int dim = GridView::dimension;
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)
67 const auto base = m.subIndex(e, lk.subEntity(), lk.codim());
68 const auto& ref = Dune::referenceElement<Scalar, dim>(e.type());
70 if (lk.codim() == 0 || lk.codim() ==
dim)
71 return base + lk.index();
73 if (lk.codim() ==
dim - 1)
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());
81 if constexpr (
dim == 3)
85 if (ref.type(lk.subEntity(), 1).isTriangle())
86 return base + lk.index();
87 if (ref.type(lk.subEntity(), 1).isQuadrilateral())
89 const auto j = quadFaceOrientIdx_(e, lk.subEntity(), ref, idSet);
90 return base + quadFacePerm_[j][lk.index()];
95 return base + lk.index();
99 template<
class Geometry,
class LocalKey>
101 {
return geo.global(localDofPos_(geo.type(), lk)); }
104 template<
class LocalKey>
105 static typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate
107 {
return localDofPos_(gt, lk); }
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},
119 template<
class Element,
class IdSet>
120 static unsigned int quadFaceOrientIdx_(
const Element& e,
unsigned int face,
121 const auto& ref,
const IdSet& idSet)
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);
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);
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);
135 constexpr uint32_t eoToImin = 0b11'11'01'01'11'00'00'00'10'00'00'01'10'00'10'00;
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;
141 if (i_min == 0)
return 0
u | (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 return 2u | (unsigned(vg[1] < vg[2]) << 2);
147 template<
class LocalKey>
148 static typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate
149 localDofPos_(Dune::GeometryType gt,
const LocalKey& lk)
151 using LocalCoord =
typename GridView::template Codim<0>::Entity::Geometry::LocalCoordinate;
152 const auto ref = Dune::referenceElement<Scalar, dim>(gt);
154 if (lk.codim() ==
dim)
155 return ref.position(lk.subEntity(),
dim);
157 if (lk.codim() ==
dim - 1)
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;
167 if constexpr (
dim == 3)
171 const auto faceGeom = ref.template geometry<1>(lk.subEntity());
174 const Dune::FieldVector<Scalar, 2> c{
Scalar(1)/3,
Scalar(1)/3};
175 return faceGeom.global(c);
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);
189 return ref.position(0, 0);
191 if constexpr (
dim == 2)
193 const auto ix = lk.index() % 2, iy = lk.index() / 2;
196 else if constexpr (
dim == 3)
198 const auto ix = lk.index()%2, iy = (lk.index()/2)%2, iz = lk.index()/4;
203 DUNE_THROW(Dune::NotImplemented,
"PQ3 local DOF position for codim=" << lk.codim());