Dune Core Modules (2.6.0)

qklocalcoefficients.hh
1 // -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=4 sw=2 sts=2:
3 
4 #ifndef DUNE_LOCALFUNCTIONS_QK_LOCALCOEFFICIENTS_HH
5 #define DUNE_LOCALFUNCTIONS_QK_LOCALCOEFFICIENTS_HH
6 
7 #include <array>
8 #include <cassert>
9 #include <vector>
10 
12 #include <dune/common/power.hh>
13 
14 #include <dune/localfunctions/common/localkey.hh>
15 
16 namespace Dune
17 {
23  template<int k, int d>
25 
26  static const unsigned unsignedK = k;
27 
28  // Return i as a d-digit number in the (k+1)-nary system
29  static std::array<unsigned int,d> multiindex (unsigned int i)
30  {
31  std::array<unsigned int,d> alpha;
32  for (int j=0; j<d; j++)
33  {
34  alpha[j] = i % (k+1);
35  i = i/(k+1);
36  }
37  return alpha;
38  }
39 
41  void setup1d(std::vector<unsigned int>& subEntity)
42  {
43  // Special-handling for piecewise constant elements
44  if (k==0)
45  {
46  subEntity[0] = 0;
47  return;
48  }
49 
50  unsigned lastIndex=0;
51 
52  /* edge and vertex numbering
53  0----0----1
54  */
55 
56  // edge (0)
57  subEntity[lastIndex++] = 0; // corner 0
58  for (unsigned i = 0; i < unsignedK - 1; ++i)
59  subEntity[lastIndex++] = 0; // inner dofs of element (0)
60 
61  subEntity[lastIndex++] = 1; // corner 1
62 
63  assert((StaticPower<k+1,d>::power==lastIndex));
64  }
65 
66  void setup2d(std::vector<unsigned int>& subEntity)
67  {
68  // Special-handling for piecewise constant elements
69  if (k==0)
70  {
71  subEntity[0] = 0;
72  return;
73  }
74 
75  unsigned lastIndex=0;
76 
77  // LocalKey: entity number, entity codim, dof indices within each entity
78  /* edge and vertex numbering
79  2----3----3
80  | |
81  | |
82  0 1
83  | |
84  | |
85  0----2----1
86  */
87 
88  // lower edge (2)
89  subEntity[lastIndex++] = 0; // corner 0
90  for (unsigned i = 0; i < unsignedK - 1; ++i)
91  subEntity[lastIndex++] = 2; // inner dofs of lower edge (2)
92 
93  subEntity[lastIndex++] = 1; // corner 1
94 
95  // iterate from bottom to top over inner edge dofs
96  for (unsigned e = 0; e < unsignedK - 1; ++e) {
97  subEntity[lastIndex++] = 0; // left edge (0)
98  for (unsigned i = 0; i < unsignedK - 1; ++i)
99  subEntity[lastIndex++] = 0; // face dofs
100  subEntity[lastIndex++] = 1; // right edge (1)
101  }
102 
103  // upper edge (3)
104  subEntity[lastIndex++] = 2; // corner 2
105  for (unsigned i = 0; i < unsignedK - 1; ++i)
106  subEntity[lastIndex++] = 3; // inner dofs of upper edge (3)
107 
108  subEntity[lastIndex++] = 3; // corner 3
109 
110  assert((StaticPower<k+1,d>::power==lastIndex));
111  }
112 
113 
114 
115  void setup3d(std::vector<unsigned int>& subEntity)
116  {
117  // Special-handling for piecewise constant elements
118  if (k==0)
119  {
120  subEntity[0] = 0;
121  return;
122  }
123 
124  unsigned lastIndex=0;
125 #ifndef NDEBUG
126  const unsigned numIndices = StaticPower<k+1,d>::power;
127  const unsigned numFaceIndices = StaticPower<k+1,d-1>::power;
128 #endif
129  const unsigned numInnerEdgeDofs = k-1;
130 
131  // LocalKey: entity number, entity codim, dof indices within each entity
132  /* edge and vertex numbering
133 
134  6---(11)--7 6---------7
135  /| /| /| (5) /|
136  (8)| (9)| / | top / |
137  / (2) / (3) / |(3)bac/k |
138  4---(10)--5 | 4---------5 |
139  | | | | left|(0)| |(1)|right
140  | 2--(7)|---3 | 2-----|---3
141  (0) / (1) / |(2)front | /
142  |(4) |(5) | / (4) | /
143  |/ |/ |/ bottom |/
144  0---(6)---1 0---------1
145  */
146 
147  // bottom face (4)
148  lastIndex=0;
149  // lower edge (6)
150  subEntity[lastIndex++] = 0; // corner 0
151  for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
152  subEntity[lastIndex++] = 6; // inner dofs of lower edge (6)
153 
154  subEntity[lastIndex++] = 1; // corner 1
155 
156  // iterate from bottom to top over inner edge dofs
157  for (unsigned e = 0; e < numInnerEdgeDofs; ++e) {
158  subEntity[lastIndex++] = 4; // left edge (4)
159  for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
160  subEntity[lastIndex++] = 4; // inner face dofs
161  subEntity[lastIndex++] = 5; // right edge (5)
162  }
163 
164  // upper edge (7)
165  subEntity[lastIndex++] = 2; // corner 2
166  for (unsigned i = 0; i < unsignedK - 1; ++i)
167  subEntity[lastIndex++] = 7; // inner dofs of upper edge (7)
168  subEntity[lastIndex++] = 3; // corner 3
169 
170  assert(numFaceIndices==lastIndex); // added 1 face so far
172 
174  for(unsigned f = 0; f < numInnerEdgeDofs; ++f) {
175 
176  // lower edge (connecting edges 0 and 1)
177  subEntity[lastIndex++] = 0; // dof on edge 0
178  for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
179  subEntity[lastIndex++] = 2; // dof in front face
180  subEntity[lastIndex++] = 1; // dof on edge 1
181 
182  // iterate from bottom to top over inner edge dofs
183  for (unsigned e = 0; e < numInnerEdgeDofs; ++e) {
184  subEntity[lastIndex++] = 0; // on left face (0)
185  for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
186  subEntity[lastIndex++] = 0; // volume dofs
187  subEntity[lastIndex++] = 1; // right face (1)
188  }
189 
190  // upper edge (connecting edges 0 and 1)
191  subEntity[lastIndex++] = 2; // dof on edge 2
192  for (unsigned i = 0; i < numInnerEdgeDofs; ++i)
193  subEntity[lastIndex++] = 3; // dof on rear face (3)
194  subEntity[lastIndex++] = 3; // dof on edge 3
195 
196  assert(lastIndex==(f+1+1)*numFaceIndices);
197  }
198 
200  // lower edge (10)
201  subEntity[lastIndex++] = 4; // corner 4
202  for (unsigned i = 0; i < unsignedK - 1; ++i)
203  subEntity[lastIndex++] = 10; // inner dofs on lower edge (10)
204  subEntity[lastIndex++] = 5; // corner 5
205 
206  // iterate from bottom to top over inner edge dofs
207  for (unsigned e = 0; e < unsignedK - 1; ++e) {
208  subEntity[lastIndex++] = 8; // left edge (8)
209  for (unsigned i = 0; i < unsignedK - 1; ++i)
210  subEntity[lastIndex++] = 5; // face dofs
211  subEntity[lastIndex++] = 9; // right edge (9)
212  }
213 
214  // upper edge (11)
215  subEntity[lastIndex++] = 6; // corner 6
216  for (unsigned i = 0; i < unsignedK - 1; ++i)
217  subEntity[lastIndex++] = 11; // inner dofs of upper edge (11)
218  subEntity[lastIndex++] = 7; // corner 7
219 
220  assert(numIndices==lastIndex);
221  }
222 
223  public:
225  QkLocalCoefficients () : li(StaticPower<k+1,d>::power)
226  {
227  // Set up array of codimension-per-dof-number
228  std::vector<unsigned int> codim(li.size());
229 
230  for (std::size_t i=0; i<codim.size(); i++) {
231  codim[i] = 0;
232  if (k==0)
233  continue;
234  // Codimension gets increased by 1 for each coordinate direction
235  // where dof is on boundary
236  std::array<unsigned int,d> mIdx = multiindex(i);
237  for (int j=0; j<d; j++)
238  if (mIdx[j]==0 or mIdx[j]==k)
239  codim[i]++;
240  }
241 
242  // Set up index vector (the index of the dof in the set of dofs of a given subentity)
243  // Algorithm: the 'index' has the same ordering as the dof number 'i'.
244  // To make it consecutive we interpret 'i' in the (k+1)-adic system, omit all digits
245  // that correspond to axes where the dof is on the element boundary, and transform the
246  // rest to the (k-1)-adic system.
247  std::vector<unsigned int> index(size());
248 
249  for (std::size_t i=0; i<size(); i++) {
250 
251  index[i] = 0;
252 
253  std::array<unsigned int,d> mIdx = multiindex(i);
254 
255  for (int j=d-1; j>=0; j--)
256  if (mIdx[j]>0 and mIdx[j]<unsignedK)
257  index[i] = (k-1)*index[i] + (mIdx[j]-1);
258 
259  }
260 
261  // Set up entity and dof numbers for each (supported) dimension separately
262  std::vector<unsigned int> subEntity(li.size());
263 
264  if (k==1) { // We can handle the first-order case in any dimension
265 
266  for (std::size_t i=0; i<size(); i++)
267  subEntity[i] = i;
268 
269  } else if (d==1) {
270 
271  setup1d(subEntity);
272 
273  } else if (d==2) {
274 
275  setup2d(subEntity);
276 
277  } else if (d==3) {
278 
279  setup3d(subEntity);
280 
281  } else
282  DUNE_THROW(Dune::NotImplemented, "QkLocalCoefficients for k==" << k << " and d==" << d);
283 
284  for (size_t i=0; i<li.size(); i++)
285  li[i] = LocalKey(subEntity[i], codim[i], index[i]);
286  }
287 
289  std::size_t size () const
290  {
292  }
293 
295  const LocalKey& localKey (std::size_t i) const
296  {
297  return li[i];
298  }
299 
300  private:
301  std::vector<LocalKey> li;
302  };
303 
304 }
305 
306 #endif
Describe position of one degree of freedom.
Definition: localkey.hh:21
Default exception for dummy implementations.
Definition: exceptions.hh:261
Attaches a shape function to an entity.
Definition: qklocalcoefficients.hh:24
QkLocalCoefficients()
Default constructor.
Definition: qklocalcoefficients.hh:225
std::size_t size() const
number of coefficients
Definition: qklocalcoefficients.hh:289
const LocalKey & localKey(std::size_t i) const
get i'th index
Definition: qklocalcoefficients.hh:295
A few common exception classes.
Various implementations of the power function for run-time and static arguments.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:216
Dune namespace.
Definition: alignedallocator.hh:10
Calculates m^p at compile time.
Definition: power.hh:20
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 3, 22:32, 2024)