Flow123d  DF_patch_fe_data_tables-398e8e7
patch_fe_values.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 patch_fe_values.cc
15  * @brief Class FEValues calculates finite element data on the actual
16  * cells such as shape function values, gradients, Jacobian of
17  * the mapping from the reference cell etc.
18  * @author Jan Stebel, David Flanderka
19  */
20 
21 #include "fem/patch_fe_values.hh"
22 #include "fem/mapping_p1.hh"
23 #include "fem/fe_system.hh"
24 #include "fem/fe_values_map.hh"
25 
26 
27 
28 //template<unsigned int spacedim>
29 //PatchFEValues<spacedim>::FEInternalData::FEInternalData(unsigned int np, unsigned int nd)
30 // : n_points(np),
31 // n_dofs(nd)
32 //{
33 // ref_shape_values.resize(np, vector<arma::vec>(nd));
34 // ref_shape_grads.resize(np, vector<arma::mat>(nd));
35 //}
36 //
37 //
38 //template<unsigned int spacedim>
39 //PatchFEValues<spacedim>::FEInternalData::FEInternalData(const PatchFEValues<spacedim>::FEInternalData &fe_system_data,
40 // const std::vector<unsigned int> &dof_indices,
41 // unsigned int first_component_idx,
42 // unsigned int ncomps)
43 // : FEInternalData(fe_system_data.n_points, dof_indices.size())
44 //{
45 // for (unsigned int ip=0; ip<n_points; ip++)
46 // for (unsigned int id=0; id<dof_indices.size(); id++)
47 // {
48 // ref_shape_values[ip][id] = fe_system_data.ref_shape_values[ip][dof_indices[id]].subvec(first_component_idx, first_component_idx+ncomps-1);
49 // ref_shape_grads[ip][id] = fe_system_data.ref_shape_grads[ip][dof_indices[id]].cols(first_component_idx, first_component_idx+ncomps-1);
50 // }
51 //}
52 
53 
54 template<unsigned int spacedim>
55 template<unsigned int DIM>
57  Quadrature &q,
58  FiniteElement<DIM> &_fe,
59  UpdateFlags _flags)
60 {
61  if (DIM == 0) //return; // avoid unnecessary allocation of dummy 0 dimensional objects
62  ASSERT(q.size() == 1);
63 
64  this->allocate( q, _fe, _flags);
65  for (uint i=0; i<max_size(); ++i)
66  element_data_[i].elm_values_ = std::make_shared<ElementValues<spacedim> >(q, this->update_flags, DIM);
67 
68  // In case of mixed system allocate data for sub-elements.
69  if (fe_type_ == FEMixedSystem)
70  {
71  FESystem<DIM> *fe = dynamic_cast<FESystem<DIM>*>(&_fe);
72  ASSERT(fe != nullptr).error("Mixed system must be represented by FESystem.");
73 
74  fe_values_vec.resize(fe->fe().size());
75  for (unsigned int f=0; f<fe->fe().size(); f++) {
76  fe_values_vec[f].resize( this->max_size() );
77  fe_values_vec[f].initialize(q, *fe->fe()[f], update_flags);
78  }
79  }
80 
81  // precompute finite element data
82  if ( q.dim() == DIM )
83  {
84  fe_data_ = init_fe_data(_fe, q);
85  }
86  else if ( q.dim() + 1 == DIM )
87  {
89  for (unsigned int sid = 0; sid < RefElement<DIM>::n_sides; sid++)
90  {
91  side_fe_data_[sid] = init_fe_data(_fe, q.make_from_side<DIM>(sid));
92  }
93  }
94  else
95  ASSERT(false)(q.dim())(DIM).error("Dimension mismatch in FEValues::initialize().");
96 }
97 
98 
99 template<unsigned int spacedim>
100 template<unsigned int DIM>
102  Quadrature &_q,
103  FiniteElement<DIM> & _fe,
104  UpdateFlags _flags)
105 {
106  // For FEVector and FETensor check number of components.
107  // This cannot be done in FiniteElement since it does not know spacedim.
108  if (_fe.type_ == FEVector) {
109  ASSERT(_fe.n_components() == spacedim).error("FEVector must have spacedim components.");
110  } else if (_fe.type_ == FETensor) {
111  ASSERT(_fe.n_components() == spacedim*spacedim).error("FETensor must have spacedim*spacedim components.");
112  }
113  ASSERT_PERMANENT_GT(this->max_n_elem_, 0);
114 
115  fe_sys_dofs_.clear();
116  fe_sys_n_components_.clear();
117  fe_sys_n_space_components_.clear();
118 
119  dim_ = DIM;
120  n_points_ = _q.size();
121  n_dofs_ = _fe.n_dofs();
122  n_components_ = _fe.n_space_components(spacedim);
123  fe_type_ = _fe.type_;
124  FESystem<DIM> *fe_sys = dynamic_cast<FESystem<DIM>*>(&_fe);
125  if (fe_sys != nullptr)
126  {
127  for (unsigned int f=0; f<fe_sys->fe().size(); f++)
128  {
129  fe_sys_dofs_.push_back(fe_sys->fe_dofs(f));
130  fe_sys_n_components_.push_back(fe_sys->fe()[f]->n_components());
131  fe_sys_n_space_components_.push_back(fe_sys->fe()[f]->n_space_components(spacedim));
132  }
133  }
134 
135  // add flags required by the finite element or mapping
136  update_flags = _flags | _fe.update_each(_flags);
137  update_flags |= MappingP1<DIM,spacedim>::update_each(update_flags);
138 
139  if ( _q.dim() == this->dim_ ) {
140  element_data_.resize( this->max_n_elem_ );
141  object_type_ = ElementFE;
142  } else if ( _q.dim()+1 == this->dim_ ) {
143  element_data_.resize( this->max_n_elem_ * (this->dim_+1) );
144  object_type_ = SideFE;
145  } else
146  ASSERT(false)(_q.dim())(this->dim_).error("Invalid dimension of quadrature!");
147 
148  for (uint i=0; i<max_size(); ++i) {
149  if (this->update_flags & update_values)
150  element_data_[i].shape_values_.resize(this->n_points_, vector<double>(this->n_dofs_*this->n_components_));
151 
152  if (this->update_flags & update_gradients)
153  element_data_[i].shape_gradients_.resize(this->n_points_, vector<arma::vec::fixed<spacedim> >(this->n_dofs_*this->n_components_));
154  }
155 
156  //views_cache_.initialize(*this->fv_, _fe);
157 }
158 
159 
160 template<unsigned int spacedim>
161 template<unsigned int DIM>
163 {
164  ASSERT( DIM == dim_ );
165  ASSERT( q.dim() == DIM );
166  std::shared_ptr<FEInternalData> data = std::make_shared<FEInternalData>(q.size(), n_dofs_);
167 
168  arma::mat shape_values(n_dofs_, fe.n_components());
169  for (unsigned int i=0; i<q.size(); i++)
170  {
171  for (unsigned int j=0; j<n_dofs_; j++)
172  {
173  for (unsigned int c=0; c<fe.n_components(); c++)
174  shape_values(j,c) = fe.shape_value(j, q.point<DIM>(i), c);
175 
176  data->ref_shape_values[i][j] = trans(shape_values.row(j));
177  }
178  }
179 
180  arma::mat grad(DIM, fe.n_components());
181  for (unsigned int i=0; i<q.size(); i++)
182  {
183  for (unsigned int j=0; j<n_dofs_; j++)
184  {
185  grad.zeros();
186  for (unsigned int c=0; c<fe.n_components(); c++)
187  grad.col(c) += fe.shape_grad(j, q.point<DIM>(i), c);
188 
189  data->ref_shape_grads[i][j] = grad;
190  }
191  }
192 
193  return data;
194 }
195 
196 
197 template<unsigned int spacedim>
199 {
200  if (dim_ == 0) return; // Temporary skip, remove if PatchFEValues objects will be merge to common object of GenericAssembly
201 
202  element_patch_map_.clear();
203  if (object_type_ == ElementFE)
204  used_size_ = patch_elements.size();
205  else
206  used_size_ = patch_elements.size() * (this->dim_+1);
207  ASSERT_LE(used_size_, max_size());
208 
209  unsigned int i=0;
210  for (auto it=patch_elements.begin(); it!=patch_elements.end(); ++it, ++i) {
211  if (object_type_ == ElementFE) {
212  patch_data_idx_ = i;
213  element_patch_map_[it->second] = i;
214  element_data_[i].elm_values_->reinit(it->first);
215  this->fill_data(*element_data_[i].elm_values_, *this->fe_data_);
216  } else {
217  element_patch_map_[it->second] = i * (this->dim_+1);
218  for (unsigned int sid=0; sid<this->dim_+1; ++sid) {
219  patch_data_idx_ = i * (this->dim_+1) + sid;
220  element_data_[patch_data_idx_].elm_values_->reinit( *it->first.side(sid) );
221  this->fill_data(*element_data_[patch_data_idx_].elm_values_, *this->side_fe_data_[sid]);
222 
223  }
224  }
225  }
226 }
227 
228 
229 template<unsigned int spacedim>
231 {
232  switch (this->fe_type_) {
233  case FEScalar:
234  this->fill_data_specialized<MapScalar<PatchFEValues<spacedim>::DimPatchFEValues, spacedim>>(elm_values, fe_data);
235  break;
236  case FEVector:
237  this->fill_data_specialized<MapVector<PatchFEValues<spacedim>::DimPatchFEValues, spacedim>>(elm_values, fe_data);
238  break;
240  this->fill_data_specialized<MapContravariant<PatchFEValues<spacedim>::DimPatchFEValues, spacedim>>(elm_values, fe_data);
241  break;
242  case FEVectorPiola:
243  this->fill_data_specialized<MapPiola<PatchFEValues<spacedim>::DimPatchFEValues, spacedim>>(elm_values, fe_data);
244  break;
245  case FETensor:
246  this->fill_data_specialized<MapTensor<PatchFEValues<spacedim>::DimPatchFEValues, spacedim>>(elm_values, fe_data);
247  break;
248  case FEMixedSystem:
249  this->fill_data_specialized<MapSystem<PatchFEValues<spacedim>::DimPatchFEValues, spacedim>>(elm_values, fe_data);
250  break;
251  default:
252  ASSERT_PERMANENT(false).error("Not implemented.");
253  }
254 }
255 
256 
257 template<unsigned int spacedim>
258 template<class MapType>
260  MapType map_type;
261  map_type.fill_values_vec(*this, elm_values, fe_data);
262  if (this->update_flags & update_values)
263  map_type.update_values(*this, elm_values, fe_data);
264  if (this->update_flags & update_gradients)
265  map_type.update_gradients(*this, elm_values, fe_data);
266 }
267 
268 
269 // explicit instantiation
274 
275 template class PatchFEValues<3>;
#define ASSERT(expr)
Definition: asserts.hh:351
#define ASSERT_PERMANENT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:348
#define ASSERT_PERMANENT_GT(a, b)
Definition of comparative assert macro (Greater Than)
Definition: asserts.hh:313
#define ASSERT_LE(a, b)
Definition of comparative assert macro (Less or Equal) only for debug mode.
Definition: asserts.hh:309
Class for computation of data on cell and side.
Structure for storing the precomputed finite element data.
Definition: fe_values.hh:62
Compound finite element on dim dimensional simplex.
Definition: fe_system.hh:102
const std::vector< std::shared_ptr< FiniteElement< dim > > > & fe() const
Definition: fe_system.hh:147
std::vector< unsigned int > fe_dofs(unsigned int fe_index)
Return dof indices belonging to given sub-FE.
Definition: fe_system.cc:267
Abstract class for the description of a general finite element on a reference simplex in dim dimensio...
unsigned int n_space_components(unsigned int spacedim)
Number of components of FE in a mapped space with dimension spacedim.
virtual UpdateFlags update_each(UpdateFlags flags)
Decides which additional quantities have to be computed for each cell.
unsigned int n_dofs() const
Returns the number of degrees of freedom needed by the finite element.
FEType type_
Type of FiniteElement.
double shape_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 shape function at the point p on the refere...
arma::vec::fixed< dim > shape_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 shape function at the point p on the ref...
unsigned int n_components() const
Returns numer of components of the basis function.
static UpdateFlags update_each(UpdateFlags flags)
Determines which additional quantities have to be computed.
Definition: mapping_p1.cc:30
void fill_data_specialized(const ElementValues< spacedim > &elm_values, const FEInternalData &fe_data)
Computes the shape function values and gradients on the actual cell and fills the FEValues structure....
std::shared_ptr< FEInternalData > init_fe_data(const FiniteElement< DIM > &fe, const Quadrature &q)
Precompute finite element data on reference element.
std::vector< ElementFEData > element_data_
Data of elements / sides on patch.
void allocate(Quadrature &_quadrature, FiniteElement< DIM > &_fe, UpdateFlags flags)
Allocates space for computed data.
void fill_data(const ElementValues< spacedim > &elm_values, const FEInternalData &fe_data)
Computes the shape function values and gradients on the actual cell and fills the FEValues structure.
void reinit(PatchElementsList patch_elements)
void initialize(Quadrature &_quadrature, FiniteElement< DIM > &_fe, UpdateFlags _flags)
Initialize structures and calculates cell-independent data.
UpdateFlags update_flags
Flags that indicate which finite element quantities are to be computed.
std::vector< shared_ptr< FEInternalData > > side_fe_data_
Precomputed FE data (shape functions on reference element) for all side quadrature points.
std::shared_ptr< FEInternalData > fe_data_
Precomputed finite element data.
FEType fe_type_
Type of finite element (scalar, vector, tensor).
std::vector< PatchFEValues< spacedim >::DimPatchFEValues > fe_values_vec
Vector of FEValues for sub-elements of FESystem.
Base class for quadrature rules on simplices in arbitrary dimensions.
Definition: quadrature.hh:48
Quadrature make_from_side(unsigned int sid) const
Definition: quadrature.cc:47
unsigned int size() const
Returns number of quadrature points.
Definition: quadrature.hh:86
unsigned int dim() const
Definition: quadrature.hh:72
Armor::ArmaVec< double, point_dim > point(unsigned int i) const
Returns the ith quadrature point.
Definition: quadrature.hh:151
Class FESystem for compound finite elements.
@ FEScalar
@ FEMixedSystem
@ FEVectorPiola
@ FETensor
@ FEVectorContravariant
@ FEVector
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell.
unsigned int uint
ArmaMat< double, N, M > mat
Definition: armor.hh:936
Class FEValues calculates finite element data on the actual cells such as shape function values,...
UpdateFlags
Enum type UpdateFlags indicates which quantities are to be recomputed on each finite element cell.
Definition: update_flags.hh:68
@ update_values
Shape function values.
Definition: update_flags.hh:87
@ update_gradients
Shape function gradients.
Definition: update_flags.hh:95