Flow123d  release_2.1.2-337-g6b7a56b
fe_p.hh
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file fe_p.hh
15  * @brief Definitions of basic Lagrangean finite elements with polynomial shape functions.
16  * @author Jan Stebel
17  */
18 
19 #ifndef FE_P_HH_
20 #define FE_P_HH_
21 
22 #include <vector>
23 
24 #include "system/global_defs.h"
25 #include "system/system.hh"
26 #include "fem/finite_element.hh"
27 
28 
29 /**
30  * @brief Space of polynomial functions.
31  *
32  * This class serves for evaluation of the value and gradient
33  * of a polynomial of order @p degree in @p dim variables.
34  */
35 template<unsigned int degree, unsigned int dim>
37 {
38 public:
39 
40  /**
41  * @brief Constructor.
42  *
43  * Creates the coefficients of the basis.
44  */
46 
47  /**
48  * @brief Value of the @p i th basis function at point @p p.
49  * @param i Number of the basis function.
50  * @param p Point at which the function is evaluated.
51  */
52  const double basis_value(unsigned int i, const arma::vec::fixed<dim> &p) const;
53 
54  /**
55  * @brief Gradient of the @p i th basis function at point @p p.
56  * @param i Number of the basis function.
57  * @param p Point at which the function is evaluated.
58  */
59  const arma::vec::fixed<dim> basis_grad(unsigned int i, const arma::vec::fixed<dim> &p) const;
60 
61 private:
62 
63  /**
64  * @brief Coefficients of basis functions.
65  *
66  * Powers of x, y, z, ... in the i-th basis function are stored
67  * in powers[i].
68  */
70 
71 };
72 
73 
74 
75 /**
76  * @brief Distribution of dofs for polynomial finite elements.
77  *
78  * The class holds the information on the total number of dofs
79  * as well as the number of dofs associated to geometrical entities
80  * such as points, lines, triangles and tetrahedra.
81  * Moreover, some dofs are grouped to pairs, triples or sextuples
82  * which are invariant to rotation/reflection of the element.
83  *
84  * The coordinates of unit support points are provided.
85  * The values at support points uniquely determine the finite
86  * element function.
87  *
88  */
89 template<unsigned int degree, unsigned int dim>
91 {
92 public:
93 
94  /**
95  * @brief Constructor.
96  *
97  * Initializes all variables.
98  */
100 
101  /// Total number of degrees of freedom at one finite element.
102  unsigned int number_of_dofs;
103 
104  /**
105  * @brief Number of single dofs at one geometrical entity of the given
106  * dimension (point, line, triangle, tetrahedron).
107  */
108  unsigned int number_of_single_dofs[dim + 1];
109 
110  /**
111  * @brief Number of pairs of dofs at one geometrical entity of the given
112  * dimension (applicable to lines and triangles).
113  */
114  unsigned int number_of_pairs[dim + 1];
115 
116  /**
117  * @brief Number of triples of dofs associated to one triangle.
118  */
119  unsigned int number_of_triples[dim + 1];
120 
121  /**
122  * @brief Number of sextuples of dofs associated to one triangle.
123  */
124  unsigned int number_of_sextuples[dim + 1];
125 
126  /**
127  * @brief Support points.
128  *
129  * Support points are points in the reference element where
130  * function values determine the dofs. In case of Lagrangean
131  * finite elements the dof values are precisely the function
132  * values at @p unit_support_points.
133  */
135 
136 };
137 
138 
139 /**
140  * @brief Conforming Lagrangean finite element on @p dim dimensional simplex.
141  *
142  * The finite element functions are continuous across the interfaces.
143  */
144 template <unsigned int degree, unsigned int dim, unsigned int spacedim>
145 class FE_P : public FiniteElement<dim,spacedim>
146 {
154 
155 public:
156  /// Constructor.
157  FE_P();
158 
159  /**
160  * @brief Returns the @p ith basis function evaluated at the point @p p.
161  * @param i Number of the basis function.
162  * @param p Point of evaluation.
163  */
164  double basis_value(const unsigned int i, const arma::vec::fixed<dim> &p) const;
165 
166  /**
167  * @brief Returns the gradient of the @p ith basis function at the point @p p.
168  * @param i Number of the basis function.
169  * @param p Point of evaluation.
170  */
171  arma::vec::fixed<dim> basis_grad(const unsigned int i, const arma::vec::fixed<dim> &p) const;
172 
173  /**
174  * @brief The vector variant of basis_value must be implemented but may not be used.
175  */
176  arma::vec::fixed<dim> basis_vector(const unsigned int i, const arma::vec::fixed<dim> &p) const;
177 
178  /**
179  * @brief The vector variant of basis_grad must be implemented but may not be used.
180  */
181  arma::mat::fixed<dim,dim> basis_grad_vector(const unsigned int i, const arma::vec::fixed<dim> &p) const;
182 
183  virtual ~FE_P();
184 
185 private:
186 
187  /// The auxiliary polynomial space.
189 
190  /// The auxiliary dof distribution.
192 };
193 
194 
195 /**
196  * @brief Discontinuous Lagrangean finite element on @p dim dimensional simplex.
197  *
198  * No continuity of the finite element functions across the interfaces is
199  * imposed.
200  */
201 template <unsigned int degree, unsigned int dim, unsigned int spacedim>
202 class FE_P_disc : public FiniteElement<dim,spacedim>
203 {
211 
212 public:
213 
214  /// Constructor.
215  FE_P_disc();
216 
217  /**
218  * @brief Returns the @p ith basis function evaluated at the point @p p.
219  * @param i Number of the basis function.
220  * @param p Point of evaluation.
221  */
222  double basis_value(const unsigned int i, const arma::vec::fixed<dim> &p) const;
223 
224  /**
225  * @brief Returns the gradient of the @p ith basis function at the point @p p.
226  * @param i Number of the basis function.
227  * @param p Point of evaluation.
228  */
229  arma::vec::fixed<dim> basis_grad(const unsigned int i, const arma::vec::fixed<dim> &p) const;
230 
231  /**
232  * @brief The vector variant of basis_value must be implemented but may not be used.
233  */
234  arma::vec::fixed<dim> basis_vector(const unsigned int i, const arma::vec::fixed<dim> &p) const;
235 
236  /**
237  * @brief The vector variant of basis_grad must be implemented but may not be used.
238  */
239  arma::mat::fixed<dim,dim> basis_grad_vector(const unsigned int i, const arma::vec::fixed<dim> &p) const;
240 
241  /// Destructor
242  virtual ~FE_P_disc();
243 
244 private:
245 
246  /// The auxiliary polynomial space.
248 
249  /// The auxiliary dof distribution.
251 };
252 
253 
254 
255 template<unsigned int degree, unsigned int dim>
257 {
258 // computes powers of all monomials up to given @p degree
259 // the order is: 1,x,x^2, y, yx,y^2
260 //
261 // TODO: - check and possibly rewrite to be more clear (use sum_degree temporary
262 // - change order of monomials: 1, x, y, xy, x^2 , y^2 (increasing order)
263 // - allow Q polynomials: 1,x, y, xy
264 // - can use tensor products
265 
266  arma::uvec::fixed<dim> pows;
267  pows.zeros();
268 
269  unsigned int degree_sum=0;
270  unsigned int i_dim;
271 
272 
273  while (true) {
274  powers.push_back(pows);
275 
276  // increment pows
277  for(i_dim=0; i_dim < dim; i_dim++) {
278  if (degree_sum < degree) {
279  pows[i_dim]++;
280  degree_sum++;
281  break;
282  } else { // if degree_sum == degree, we find first non empty power, free it, and raise the next one
283  degree_sum-=pows[i_dim];
284  pows[i_dim]=0;
285  }
286  }
287  if (i_dim == dim) break; // just after pow == (0, 0, .., degree)
288  }
289 }
290 
291 template<unsigned int degree, unsigned int dim>
292 const double PolynomialSpace<degree,dim>::basis_value(unsigned int i, const arma::vec::fixed<dim> &p) const
293 {
294  OLD_ASSERT(i<=powers.size(), "Index of basis function is out of range.");
295 
296  double v = 1;
297 
298  for (unsigned int j=0; j<dim; j++)
299  v *= pow(p[j], (int) powers[i][j]);
300 
301  return v;
302 }
303 
304 
305 template<unsigned int degree, unsigned int dim>
306 const arma::vec::fixed<dim> PolynomialSpace<degree,dim>::basis_grad(unsigned int i, const arma::vec::fixed<dim> &p) const
307 {
308  OLD_ASSERT(i<=powers.size(), "Index of basis function is out of range.");
309 
310  arma::vec::fixed<dim> grad;
311 
312  for (unsigned int j=0; j<dim; j++)
313  {
314  grad[j] = powers[i][j];
315  if (powers[i][j] == 0) continue;
316 
317  for (unsigned int k=0; k<dim; k++)
318  {
319  grad[j] *= pow(p[k], (int) (k==j?powers[i][k]-1:powers[i][k]));
320  }
321  }
322  return grad;
323 }
324 
325 
326 
327 
328 
329 
330 
331 
332 
333 
334 
335 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
337 {
338  this->init();
339 
340  for (int i=0; i<=dim; i++)
341  {
342  number_of_dofs += dof_distribution.number_of_single_dofs[i]
343  +2*dof_distribution.number_of_pairs[i]
344  +3*dof_distribution.number_of_triples[i]
345  +6*dof_distribution.number_of_sextuples[i];
346 
347  number_of_single_dofs[i] = dof_distribution.number_of_single_dofs[i];
348  number_of_pairs[i] = dof_distribution.number_of_pairs[i];
349  number_of_triples[i] = dof_distribution.number_of_triples[i];
350  number_of_sextuples[i] = dof_distribution.number_of_sextuples[i];
351  }
352 
353  for (int i=0; i<dof_distribution.unit_support_points.size(); i++)
354  unit_support_points.push_back(dof_distribution.unit_support_points[i]);
355 
356  order = degree;
357 
358  this->compute_node_matrix();
359 }
360 
361 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
362 double FE_P<degree,dim,spacedim>::basis_value(const unsigned int i, const arma::vec::fixed<dim> &p) const
363 {
364  OLD_ASSERT(i <= number_of_dofs, "Index of basis function is out of range.");
365  return poly_space.basis_value(i, p);
366 }
367 
368 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
369 arma::vec::fixed<dim> FE_P<degree,dim,spacedim>::basis_grad(const unsigned int i, const arma::vec::fixed<dim> &p) const
370 {
371  OLD_ASSERT(i <= number_of_dofs, "Index of basis function is out of range.");
372  return poly_space.basis_grad(i, p);
373 }
374 
375 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
376 arma::vec::fixed<dim> FE_P<degree,dim,spacedim>::basis_vector(const unsigned int i, const arma::vec::fixed<dim> &p) const
377 {
378  OLD_ASSERT(false, "basis_vector() may not be called for scalar finite element.");
379 }
380 
381 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
382 arma::mat::fixed<dim,dim> FE_P<degree,dim,spacedim>::basis_grad_vector(const unsigned int i, const arma::vec::fixed<dim> &p) const
383 {
384  OLD_ASSERT(false, "basis_grad_vector() may not be called for scalar finite element.");
385 }
386 
387 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
389 {}
390 
391 
392 
393 
394 
395 
396 
397 
398 
399 
400 
401 
402 
403 
404 
405 
406 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
408 {
409  this->init();
410 
411  number_of_dofs += dof_distribution.number_of_dofs;
412 
413  number_of_single_dofs[dim] = number_of_dofs;
414 
415  for (unsigned int i=0; i<dof_distribution.unit_support_points.size(); i++)
416  unit_support_points.push_back(dof_distribution.unit_support_points[i]);
417 
418  order = degree;
419 
420  this->compute_node_matrix();
421 }
422 
423 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
424 double FE_P_disc<degree,dim,spacedim>::basis_value(const unsigned int i, const arma::vec::fixed<dim> &p) const
425 {
426  OLD_ASSERT(i <= number_of_dofs, "Index of basis function is out of range.");
427  return poly_space.basis_value(i, p);
428 }
429 
430 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
431 arma::vec::fixed<dim> FE_P_disc<degree,dim,spacedim>::basis_grad(const unsigned int i, const arma::vec::fixed<dim> &p) const
432 {
433  OLD_ASSERT(i <= number_of_dofs, "Index of basis function is out of range.");
434  return poly_space.basis_grad(i, p);
435 }
436 
437 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
438 arma::vec::fixed<dim> FE_P_disc<degree,dim,spacedim>::basis_vector(const unsigned int i, const arma::vec::fixed<dim> &p) const
439 {
440  OLD_ASSERT(false, "basis_vector() may not be called for scalar finite element.");
441  return arma::vec::fixed<dim>();
442 }
443 
444 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
445 arma::mat::fixed<dim,dim> FE_P_disc<degree,dim,spacedim>::basis_grad_vector(const unsigned int i, const arma::vec::fixed<dim> &p) const
446 {
447  OLD_ASSERT(false, "basis_grad_vector() may not be called for scalar finite element.");
448  return arma::mat::fixed<dim,dim>();
449 }
450 
451 template<unsigned int degree, unsigned int dim, unsigned int spacedim>
453 {}
454 
455 
456 
457 
458 
459 
460 
461 
462 
463 
464 
465 
466 
467 #ifndef DOXYGEN_SHOULD_SKIP_THIS
468 
469 /****** Template specializations ******/
470 
471 /*** 1D finite elements ***/
472 
473 // P0 constant element
474 template<>
476 
477 // P1 linear element
478 template<>
480 
481 // P2 quadratic element
482 template<>
484 
485 // P3 cubic element
486 template<>
488 
489 
490 /*** 2D finite elements ***/
491 
492 // P0 constant element
493 template<>
495 
496 
497 // P1 linear element
498 template<>
500 
501 // P2 quadratic element
502 template<>
504 
505 // P3 cubic element
506 template<>
508 
509 
510 
511 /*** 3D finite elements ***/
512 
513 // P0 constant element
514 template<>
516 
517 
518 // P1 linear element
519 template<>
521 
522 
523 // P2 quadratic element
524 template<>
526 
527 // P3 cubic element
528 template<>
530 
531 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
532 
533 
534 
535 
536 #endif /* FE_P_HH_ */
arma::vec::fixed< dim > basis_grad(const unsigned int i, const arma::vec::fixed< dim > &p) const
Returns the gradient of the ith basis function at the point p.
Definition: fe_p.hh:369
Space of polynomial functions.
Definition: fe_p.hh:36
unsigned int number_of_dofs
Total number of degrees of freedom at one finite element.
Definition: fe_p.hh:102
PolynomialSpace()
Constructor.
Definition: fe_p.hh:256
double basis_value(const unsigned int i, const arma::vec::fixed< dim > &p) const
Returns the ith basis function evaluated at the point p.
Definition: fe_p.hh:362
FE_P_disc()
Constructor.
Definition: fe_p.hh:407
#define OLD_ASSERT(...)
Definition: global_defs.h:131
Discontinuous Lagrangean finite element on dim dimensional simplex.
Definition: fe_p.hh:202
DofDistribution< degree, dim > dof_distribution
The auxiliary dof distribution.
Definition: fe_p.hh:250
Global macros to enhance readability and debugging, general constants.
PolynomialSpace< degree, dim > poly_space
The auxiliary polynomial space.
Definition: fe_p.hh:247
arma::vec::fixed< dim > basis_vector(const unsigned int i, const arma::vec::fixed< dim > &p) const
The vector variant of basis_value must be implemented but may not be used.
Definition: fe_p.hh:438
FE_P()
Constructor.
Definition: fe_p.hh:336
virtual ~FE_P_disc()
Destructor.
Definition: fe_p.hh:452
DofDistribution()
Constructor.
virtual ~FE_P()
Definition: fe_p.hh:388
double basis_value(const unsigned int i, const arma::vec::fixed< dim > &p) const
Returns the ith basis function evaluated at the point p.
Definition: fe_p.hh:424
const arma::vec::fixed< dim > basis_grad(unsigned int i, const arma::vec::fixed< dim > &p) const
Gradient of the i th basis function at point p.
Definition: fe_p.hh:306
Conforming Lagrangean finite element on dim dimensional simplex.
Definition: fe_p.hh:145
DofDistribution< degree, dim > dof_distribution
The auxiliary dof distribution.
Definition: fe_p.hh:191
const double basis_value(unsigned int i, const arma::vec::fixed< dim > &p) const
Value of the i th basis function at point p.
Definition: fe_p.hh:292
arma::mat::fixed< dim, dim > basis_grad_vector(const unsigned int i, const arma::vec::fixed< dim > &p) const
The vector variant of basis_grad must be implemented but may not be used.
Definition: fe_p.hh:445
arma::mat::fixed< dim, dim > basis_grad_vector(const unsigned int i, const arma::vec::fixed< dim > &p) const
The vector variant of basis_grad must be implemented but may not be used.
Definition: fe_p.hh:382
Distribution of dofs for polynomial finite elements.
Definition: fe_p.hh:90
Abstract class for description of finite elements.
arma::vec::fixed< dim > basis_grad(const unsigned int i, const arma::vec::fixed< dim > &p) const
Returns the gradient of the ith basis function at the point p.
Definition: fe_p.hh:431
Abstract class for the description of a general finite element on a reference simplex in dim dimensio...
Definition: dofhandler.hh:29
arma::vec::fixed< dim > basis_vector(const unsigned int i, const arma::vec::fixed< dim > &p) const
The vector variant of basis_value must be implemented but may not be used.
Definition: fe_p.hh:376
std::vector< arma::uvec::fixed< dim > > powers
Coefficients of basis functions.
Definition: fe_p.hh:69
std::vector< arma::vec::fixed< dim > > unit_support_points
Support points.
Definition: fe_p.hh:134
PolynomialSpace< degree, dim > poly_space
The auxiliary polynomial space.
Definition: fe_p.hh:188