dune-localfunctions 2.12-git
Loading...
Searching...
No Matches
hierarchicalsimplexp2withelementbubble.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5#ifndef DUNE_HIERARCHICAL_SIMPLEX_P2_WITH_ELEMENT_BUBBLE_LOCALBASIS_HH
6#define DUNE_HIERARCHICAL_SIMPLEX_P2_WITH_ELEMENT_BUBBLE_LOCALBASIS_HH
7
12#include <array>
13#include <cassert>
14#include <numeric>
15#include <stdexcept>
16#include <vector>
17
20#include <dune/common/math.hh>
21
23
27
28namespace Dune
29{
45 template<class D, class R, int dim>
47 {
49
52
55
58
59 // Number of vertices
60 static constexpr int numVertices = dim+1;
61
62 // Number of edges (or zero for dim==1)
63 static constexpr int numEdges = (dim > 1 ? ((dim+1)*dim / 2) : 0);
64
65 // helper function to evaluate the vertex basis functions
66 template <class It>
67 static constexpr It evaluateVertexFunctions (const DomainType& in, It outIt)
68 {
69 *outIt = 1;
70 for (int i = 0; i < dim; ++i)
71 *outIt -= in[i];
72 ++outIt;
73 for (int i = 0; i < dim; ++i)
74 *outIt++ = in[i];
75 return outIt;
76 }
77
78 // helper function to evaluate the basis functions
79 template <class It>
80 static constexpr It evaluateAllFunctions (const DomainType& in, It outIt)
81 {
82 It vertexValues = outIt;
83 outIt = evaluateVertexFunctions(in, outIt);
84
85 if constexpr(dim > 1) {
86 auto refElem = referenceElement<D,dim>(GeometryTypes::simplex(dim));
87 for (int i = 0; i < numEdges; ++i) {
88 const int v0 = refElem.subEntity(i,dim-1,0,dim);
89 const int v1 = refElem.subEntity(i,dim-1,1,dim);
90 *outIt++ = 4 * vertexValues[v0] * vertexValues[v1];
91 }
92 }
93
94 // element bubble function
95 *outIt = power(dim+1, dim+1);
96 for (int i = 0; i < numVertices; ++i)
97 *outIt *= Impl::rangeCast(vertexValues[i]);
98 return outIt;
99 }
100
101 public:
104
106 static constexpr std::size_t size () noexcept
107 {
108 return numVertices + numEdges + 1;
109 }
110
112 static constexpr void evaluateFunction (const DomainType& in,
114 {
115 out.resize(size());
116 evaluateAllFunctions(in,out.begin());
117 }
118
120 static constexpr void evaluateJacobian (const DomainType& in,
122 {
123 out.resize(size());
124
125 // vertex basis functions
126 R tmp = 1;
127 for (int i = 0; i < dim; ++i) {
128 out[0][0][i] = -1;
129 for (int j = 0; j < dim; ++j)
130 out[j+1][0][i] = (i == j);
131 tmp -= in[i];
132 }
133
134 int n = numVertices;
136 evaluateVertexFunctions(in, shapeValues.begin());
137
138 // edge basis functions
139 if constexpr(dim > 1) {
140 auto refElem = referenceElement<D,dim>(GeometryTypes::simplex(dim));
141 for (int i = 0; i < numEdges; ++i,++n) {
142 const int v0 = refElem.subEntity(i,dim-1,0,dim);
143 const int v1 = refElem.subEntity(i,dim-1,1,dim);
144 for (int j = 0; j < dim; ++j)
145 out[n][0][j] = 4 * (out[v0][0][j] * shapeValues[v1][0] + shapeValues[v0][0] * out[v1][0][j]);
146 }
147 }
148
149 // element bubble function
150 for (int i = 0; i < dim; ++i) {
151 out[n][0][i] = power(dim+1, dim+1) * (tmp - in[i]);
152 for (int j = i+1; j < dim+i; ++j)
153 out[n][0][i] *= in[j % dim];
154 }
155 }
156
158 static constexpr void partial (const std::array<unsigned int, dim>& order,
159 const DomainType& in,
161 {
162 unsigned int totalOrder = 0;
163 for (int i = 0; i < dim; ++i)
164 totalOrder += order[i];
165
166 switch (totalOrder) {
167 case 0:
168 evaluateFunction(in,out);
169 break;
170 case 1: {
171 out.resize(size());
172 int d = 0; // the direction of differentiation
173 for (int i = 0; i < dim; ++i)
174 d += i * order[i];
175
176 // vertex basis functions
177 R tmp = 1;
178 for (int i = 0; i < dim; ++i) {
179 out[0] = -1;
180 for (int j = 0; j < dim; ++j)
181 out[j+1] = (dim == j);
182 tmp -= in[i];
183 }
184
185 int n = numVertices;
187 evaluateVertexFunctions(in, shapeValues.begin());
188
189 // edge basis functions
190 if constexpr(dim > 1) {
191 auto refElem = referenceElement<D,dim>(GeometryTypes::simplex(dim));
192 for (int i = 0; i < numEdges; ++i,++n) {
193 const int v0 = refElem.subEntity(i,dim-1,0,dim);
194 const int v1 = refElem.subEntity(i,dim-1,1,dim);
195 out[n] = 4 * (out[v0] * shapeValues[v1] + shapeValues[v0] * out[v1]);
196 }
197 }
198
199 // element bubble function
200 out[n] = power(dim+1, dim+1) * (tmp - in[d]);
201 for (int j = d+1; j < dim+d; ++j)
202 out[n] *= in[j % dim];
203 } break;
204 default:
205 throw std::runtime_error("Desired derivative order is not implemented");
206 }
207 }
208
210 static constexpr unsigned int order () noexcept
211 {
212 return dim+1;
213 }
214 };
215
216
228 template <int dim>
230 {
231 // Number of vertices
232 static constexpr int numVertices = dim+1;
233
234 // Number of edges (or zero for dim==1)
235 static constexpr int numEdges = (dim > 1 ? ((dim+1)*dim / 2) : 0);
236
237 public:
240 {
241 int n = 0;
242 for (int i = 0; i < numVertices; ++i)
243 li_[n++] = LocalKey(i,dim,0); // Vertex
244 if constexpr(dim > 1) {
245 for (int i = 0; i < numEdges; ++i)
246 li_[n++] = LocalKey(i,dim-1,0); // Edges
247 }
248 li_[n++] = LocalKey(0,0,0); // Element
249 }
250
252 static constexpr std::size_t size () noexcept
253 {
254 return numVertices + numEdges + 1;
255 }
256
258 const LocalKey& localKey (std::size_t i) const noexcept
259 {
260 return li_[i];
261 }
262
263 private:
265 };
266
270 template<class LB, int dim>
272 {
273 using LocalBasis = LB;
274 using DomainType = typename LB::Traits::DomainType;
275 using RangeType = typename LB::Traits::RangeType;
276
277 // Number of vertices
278 static constexpr int numVertices = dim+1;
279
280 // Number of edges (or zero for dim==1)
281 static constexpr int numEdges = (dim > 1 ? ((dim+1)*dim / 2) : 0);
282
283 public:
291 template<class F, class C>
292 requires ( requires (const F& f, const DomainType& x, C& y){ y = Impl::rangeCast(f(x)); } )
293 static constexpr void interpolate (const F& f, std::vector<C>& out)
294 {
295 auto refElem = referenceElement<typename LB::Traits::DomainFieldType,dim>(GeometryTypes::simplex(dim));
296
297 out.resize(LB::size());
298 int n = 0;
299
300 // vertices
301 assert(numVertices == refElem.size(dim));
302 for (int i = 0; i < numVertices; ++i)
303 out[n++] = Impl::rangeCast(f(refElem.position(i,dim)));
304
305 std::array<RangeType,LB::size()> shapeValues;
306
307 // edge bubbles
308 if constexpr(dim > 1) {
309 assert(numEdges == refElem.size(dim-1));
310 for (int i = 0; i < numEdges; ++i) {
311 auto y = Impl::rangeCast(f(refElem.position(i,dim-1)));
312 LB::evaluateVertexFunctions(refElem.position(i,dim-1), shapeValues.begin());
313 for (int j = 0; j < numVertices; ++j)
314 y -= out[j]*shapeValues[j][0];
315 out[n++] = y;
316 }
317 }
318
319 // element bubble
320 auto y = Impl::rangeCast(f(refElem.position(0,0)));
321 LB::evaluateAllFunctions(refElem.position(0,0), shapeValues.begin());
322 for (int j = 0; j < numVertices+numEdges; ++j)
323 y -= out[j]*shapeValues[j][0];
324 out[n++] = y;
325 }
326 };
327
328} // end namespace Dune
329
330#endif // DUNE_HIERARCHICAL_SIMPLEX_P2_WITH_ELEMENT_BUBBLE_LOCALBASIS_HH
size_type dim() const
constexpr Base power(Base m, Exponent p)
Type traits for LocalBasisVirtualInterface.
Definition common/localbasis.hh:35
Describe position of one degree of freedom.
Definition localkey.hh:24
P1 basis in dim-d enriched by quadratic edge bubble functions and an element bubble function of order...
Definition hierarchicalsimplexp2withelementbubble.hh:47
static constexpr void evaluateFunction(const DomainType &in, std::vector< RangeType > &out)
Evaluate all shape functions.
Definition hierarchicalsimplexp2withelementbubble.hh:112
static constexpr void partial(const std::array< unsigned int, dim > &order, const DomainType &in, std::vector< RangeType > &out)
Evaluate partial derivatives of all shape functions.
Definition hierarchicalsimplexp2withelementbubble.hh:158
static constexpr unsigned int order() noexcept
Polynomial order of the shape functions (4 in this case)
Definition hierarchicalsimplexp2withelementbubble.hh:210
static constexpr void evaluateJacobian(const DomainType &in, std::vector< JacobianType > &out)
Evaluate Jacobian of all shape functions.
Definition hierarchicalsimplexp2withelementbubble.hh:120
static constexpr std::size_t size() noexcept
Returns number of shape functions.
Definition hierarchicalsimplexp2withelementbubble.hh:106
The local keys of the hierarchical basis functions with element bubble.
Definition hierarchicalsimplexp2withelementbubble.hh:230
HierarchicalSimplexP2WithElementBubbleLocalCoefficients() noexcept
Default constructor, initializes the local keys.
Definition hierarchicalsimplexp2withelementbubble.hh:239
static constexpr std::size_t size() noexcept
Returns number of coefficients.
Definition hierarchicalsimplexp2withelementbubble.hh:252
const LocalKey & localKey(std::size_t i) const noexcept
Returns the i'th local key.
Definition hierarchicalsimplexp2withelementbubble.hh:258
Definition hierarchicalsimplexp2withelementbubble.hh:272
static constexpr void interpolate(const F &f, std::vector< C > &out)
Local interpolation of the function f.
Definition hierarchicalsimplexp2withelementbubble.hh:293
T begin(T... args)
T resize(T... args)