Flow123d  release_2.2.0-914-gf1a3a4f
finite_element.cc
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 finite_element.cc
15  * @brief Abstract class for description of finite elements.
16  * @author Jan Stebel
17  */
18 
19 #include "system/system.hh"
20 #include "quadrature/quadrature.hh"
21 #include "fem/dofhandler.hh"
22 #include "fem/finite_element.hh"
23 #include "fem/fe_values.hh"
24 
25 
26 
27 using namespace std;
28 
29 
30 
31 
32 
33 template<class FS> const double Dof::evaluate(const FS &function_space,
34  unsigned int basis_idx) const
35 {
36  // Check that FS is derived from FunctionSpace.
37  static_assert(std::is_base_of<FunctionSpace, FS>::value, "FS must be derived from FunctionSpace.");
38 
39  // We cannot evaluate dof on dim-dimensional n-face if the function space lies on lower-dimensional n-face.
40  ASSERT(function_space.space_dim()+1 == coords.size());
41 
42  switch (type)
43  {
44  case Value:
45  {
46  // evaluate basis function and return the linear combination of components
47  arma::vec vec_value(function_space.n_components());
48  for (unsigned int c=0; c<function_space.n_components(); c++)
49  vec_value[c] = function_space.basis_value(basis_idx, coords.subvec(0,coords.size()-2), c);
50  return dot(coefs, vec_value);
51  break;
52  }
53 
54  default:
55  OLD_ASSERT(false, "Dof evaluation not implemented for this type.");
56  }
57  return 0;
58 }
59 
60 
61 
62 template<unsigned int dim, unsigned int spacedim>
64  : function_space_(nullptr)
65 {
66  init();
67 }
68 
69 template<unsigned int dim, unsigned int spacedim>
70 void FiniteElement<dim,spacedim>::init(bool primitive, FEType type)
71 {
72  dofs_.clear();
73  is_primitive_ = primitive;
74  type_ = type;
75 }
76 
77 
78 template<unsigned int dim, unsigned int spacedim>
80 {
81  component_indices_.resize(dofs_.size(), 0);
82  nonzero_components_.resize(dofs_.size(), { true });
83 }
84 
85 
86 template<unsigned int dim, unsigned int spacedim> inline
88 {
89  arma::mat M(dofs_.size(), dofs_.size());
90 
91  for (unsigned int i = 0; i < dofs_.size(); i++)
92  for (unsigned int j = 0; j < dofs_.size(); j++) {
93  M(j, i) = dofs_[i].evaluate(*function_space_, j);
94 
95  }
96  node_matrix = arma::inv(M);
97 }
98 
99 template<unsigned int dim, unsigned int spacedim>
101 {
102  FEInternalData *data = new FEInternalData;
103 
104  arma::mat raw_values(function_space_->dim(), n_components());
105  arma::mat shape_values(n_dofs(), n_components());
106 
107  data->ref_shape_values.resize(q.size());
108  for (unsigned int i=0; i<q.size(); i++)
109  {
110  for (unsigned int j=0; j<function_space_->dim(); j++)
111  for (unsigned int c=0; c<n_components(); c++)
112  raw_values(j,c) = basis_value(j, q.point(i), c);
113 
114  shape_values = node_matrix * raw_values;
115 
116  data->ref_shape_values[i].resize(n_dofs());
117  for (unsigned int j=0; j<n_dofs(); j++)
118  data->ref_shape_values[i][j] = trans(shape_values.row(j));
119  }
120 
121  arma::mat grad(dim,n_components());
122  vector<arma::mat> grads(n_dofs());
123 
124  data->ref_shape_grads.resize(q.size());
125  for (unsigned int i=0; i<q.size(); i++)
126  {
127  data->ref_shape_grads[i].resize(n_dofs());
128  for (unsigned int j=0; j<n_dofs(); j++)
129  {
130  grad.zeros();
131  for (unsigned int l=0; l<function_space_->dim(); l++)
132  for (unsigned int c=0; c<n_components(); c++)
133  grad.col(c) += basis_grad(l, q.point(i), c) * node_matrix(j,l);
134  data->ref_shape_grads[i][j] = grad;
135  }
136  }
137 
138  return data;
139 }
140 
141 
142 template<unsigned int dim, unsigned int spacedim>
143 double FiniteElement<dim,spacedim>::basis_value(const unsigned int i,
144  const arma::vec::fixed<dim> &p,
145  const unsigned int comp) const
146 {
147  ASSERT_DBG( comp < n_components() );
148  ASSERT_DBG( i < dofs_.size()).error("Index of basis function is out of range.");
149  return this->function_space_->basis_value(i, p, comp);
150 }
151 
152 template<unsigned int dim, unsigned int spacedim>
153 arma::vec::fixed<dim> FiniteElement<dim,spacedim>::basis_grad(const unsigned int i,
154  const arma::vec::fixed<dim> &p,
155  const unsigned int comp) const
156 {
157  ASSERT_DBG( comp < n_components() );
158  ASSERT_DBG( i < dofs_.size()).error("Index of basis function is out of range.");
159  return this->function_space_->basis_grad(i, p, comp);
160 }
161 
162 
163 template<unsigned int dim, unsigned int spacedim> inline
165 {
166  UpdateFlags f = flags;
167 
168  switch (type_)
169  {
170  case FEScalar:
171  if (flags & update_gradients)
173  break;
175  if (flags & update_values)
176  f |= update_jacobians;
177  if (flags & update_gradients)
179  break;
180  case FEVectorPiola:
181  if (flags & update_values)
183  if (flags & update_gradients)
185  break;
186  default:;
187  }
188 
189  return f;
190 }
191 
192 template<unsigned int dim, unsigned int spacedim> inline
194  const Quadrature<dim> &q,
195  FEInternalData &data,
197 {
198  // shape values
199  if (fv_data.update_flags & update_values)
200  {
201  for (unsigned int i = 0; i < q.size(); i++)
202  for (unsigned int j = 0; j < n_dofs(); j++)
203  {
204  arma::vec fv_vec;
205  switch (type_) {
206  case FEScalar:
207  fv_data.shape_values[i][j] = data.ref_shape_values[i][j][0];
208  break;
210  fv_vec = fv_data.jacobians[i] * data.ref_shape_values[i][j];
211  for (unsigned int c=0; c<spacedim; c++)
212  fv_data.shape_values[i][j*spacedim+c] = fv_vec[c];
213  break;
214  case FEVectorPiola:
215  fv_vec = fv_data.jacobians[i]*data.ref_shape_values[i][j]/fv_data.determinants[i];
216  for (unsigned int c=0; c<spacedim; c++)
217  fv_data.shape_values[i][j*spacedim+c] = fv_vec(c);
218  break;
219 // case FETensor:
220 // arma::mat ref_mat(dim);
221 // for (unsigned int c=0; c<spacedim*spacedim; c++)
222 // ref_mat[c/spacedim,c%spacedim] = data.ref_shape_values[i][j][c];
223 // arma::mat fv_mat = ref_mat*fv_data.inverse_jacobians[i];
224 // for (unsigned int c=0; c<spacedim*spacedim; c++)
225 // fv_data.shape_values[i][j*spacedim*spacedim+c] = fv_mat[c];
226 // break;
227  default:
228  ASSERT(false).error("Not implemented.");
229  }
230  }
231  }
232 
233  // shape gradients
234  if (fv_data.update_flags & update_gradients)
235  {
236  for (unsigned int i = 0; i < q.size(); i++)
237  {
238  for (unsigned int j = 0; j < n_dofs(); j++)
239  {
240  arma::mat grads;
241  switch (type_) {
242  case FEScalar:
243  grads = trans(fv_data.inverse_jacobians[i]) * data.ref_shape_grads[i][j];
244  fv_data.shape_gradients[i][j] = grads;
245  break;
247  grads = trans(fv_data.inverse_jacobians[i]) * data.ref_shape_grads[i][j] * trans(fv_data.jacobians[i]);
248  for (unsigned int c=0; c<spacedim; c++)
249  fv_data.shape_gradients[i][j*spacedim+c] = grads.col(c);
250  break;
251  case FEVectorPiola:
252  grads = trans(fv_data.inverse_jacobians[i]) * data.ref_shape_grads[i][j] * trans(fv_data.jacobians[i])
253  / fv_data.determinants[i];
254  for (unsigned int c=0; c<spacedim; c++)
255  fv_data.shape_gradients[i][j*spacedim+c] = grads.col(c);
256  break;
257  default:
258  ASSERT(false).error("Not implemented.");
259  }
260  }
261  }
262  }
263 }
264 
265 
266 
267 template<unsigned int dim, unsigned int spacedim>
269 {
270  if (function_space_ != nullptr) delete function_space_;
271 }
272 
273 
274 template class FiniteElement<0,3>;
275 template class FiniteElement<1,3>;
276 template class FiniteElement<2,3>;
277 template class FiniteElement<3,3>;
278 
279 
FEType type_
Type of FiniteElement.
Shape function values.
Definition: update_flags.hh:87
UpdateFlags
Enum type UpdateFlags indicates which quantities are to be recomputed on each finite element cell...
Definition: update_flags.hh:67
Declaration of class which handles the ordering of degrees of freedom (dof) and mappings between loca...
void init(bool primitive=true, FEType type=FEScalar)
Clears all internal structures.
std::vector< Dof > dofs_
Set of degrees of freedom (functionals) defining the FE.
Determinant of the Jacobian.
std::vector< arma::mat::fixed< dim, spacedim > > inverse_jacobians
Inverse Jacobians at the quadrature points.
Definition: fe_values.hh:84
virtual FEInternalData * initialize(const Quadrature< dim > &q)
Calculates the data on the reference cell.
UpdateFlags update_flags
Flags that indicate which finite element quantities are to be computed.
Definition: fe_values.hh:123
virtual const double basis_value(unsigned int basis_index, const arma::vec &point, unsigned int comp_index=0) const =0
Value of the i th basis function at point point.
std::vector< std::vector< bool > > nonzero_components_
Footprints of nonzero components of shape functions.
Class FEValues calculates finite element data on the actual cells such as shape function values...
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:346
FEType
Base class for quadrature rules on simplices in arbitrary dimensions.
Definition: fe_values.hh:32
static constexpr bool value
Definition: json.hpp:87
Volume element.
virtual const arma::vec basis_grad(unsigned int basis_index, const arma::vec &point, unsigned int comp_index=0) const =0
Gradient of the i th basis function at point point.
virtual UpdateFlags update_each(UpdateFlags flags)
Decides which additional quantities have to be computed for each cell.
#define OLD_ASSERT(...)
Definition: global_defs.h:131
virtual const unsigned int dim() const =0
Dimension of function space (number of basis functions).
virtual ~FiniteElement()
Destructor.
std::vector< arma::mat::fixed< spacedim, dim > > jacobians
Jacobians of the mapping at the quadrature points.
Definition: fe_values.hh:74
std::vector< unsigned int > component_indices_
Indices of nonzero components of shape functions (for primitive FE).
bool is_primitive_
Primitive FE is using componentwise shape functions, i.e. only one component is nonzero for each shap...
virtual void compute_node_matrix()
Initializes the node_matrix for computing the coefficients of the shape functions in the raw basis of...
void setup_components()
Initialize vectors with information about components of basis functions.
Basic definitions of numerical quadrature rules.
Shape function gradients.
Definition: update_flags.hh:95
std::vector< std::vector< arma::mat > > ref_shape_grads
Precomputed gradients of basis functions at the quadrature points.
Class FEValuesData holds the arrays of data computed by Mapping and FiniteElement.
Definition: fe_values.hh:48
const double evaluate(const FS &function_space, unsigned int basis_idx) const
Evaulate dof for basis function of given function space.
const unsigned int size() const
Returns number of quadrature points.
Definition: quadrature.hh:139
virtual arma::vec::fixed< dim > basis_grad(const unsigned int i, const arma::vec::fixed< dim > &p, const unsigned int comp=0) const
Calculates the comp-th component of the gradient of the i-th raw basis function at the point p on the...
std::vector< std::vector< double > > shape_values
Shape functions evaluated at the quadrature points.
Definition: fe_values.hh:94
#define ASSERT_DBG(expr)
Definition: asserts.hh:349
std::vector< double > determinants
Determinants of Jacobians at quadrature points.
Definition: fe_values.hh:79
const arma::vec::fixed< dim > & point(const unsigned int i) const
Returns the ith quadrature point.
Definition: quadrature.hh:144
FiniteElement()
Constructor.
virtual double basis_value(const unsigned int i, const arma::vec::fixed< dim > &p, const unsigned int comp=0) const
Calculates the value of the comp-th component of the i-th raw basis function at the point p on the re...
const unsigned int n_dofs() const
Returns the number of degrees of freedom needed by the finite element.
Structure for storing the precomputed finite element data.
std::vector< std::vector< arma::vec > > ref_shape_values
Precomputed values of basis functions at the quadrature points.
Abstract class for description of finite elements.
virtual void fill_fe_values(const Quadrature< dim > &q, FEInternalData &data, FEValuesData< dim, spacedim > &fv_data)
Computes the shape function values and gradients on the actual cell and fills the FEValues structure...
FunctionSpace * function_space_
Function space defining the FE.
Abstract class for the description of a general finite element on a reference simplex in dim dimensio...
Definition: dofhandler.hh:30
arma::mat node_matrix
Matrix that determines the coefficients of the raw basis functions from the values at the support poi...
std::vector< std::vector< arma::vec::fixed< spacedim > > > shape_gradients
Gradients of shape functions evaluated at the quadrature points.
Definition: fe_values.hh:101
virtual unsigned int n_components() const
Returns numer of components of the basis function.