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