Flow123d  JS_before_hm-887-g601087d
element_values.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2019 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_values.cc
15  * @brief Class ElementValues calculates data related to transformation
16  * of reference cell to actual cell (Jacobian, inverse Jacobian,
17  * determinant, point coordinates etc.).
18  * @author Jan Stebel
19  */
20 
21 #include "fem/mapping_p1.hh"
22 #include "quadrature/quadrature.hh"
23 #include "fem/element_values.hh"
24 
25 
26 
27 using namespace arma;
28 using namespace std;
29 
30 
31 
32 
33 
34 
35 
36 
38  : n_points(np)
39 {
40  bar_coords.resize(np);
41  weights.resize(np);
42 }
43 
44 
45 template<unsigned int spacedim>
47  UpdateFlags flags,
48  unsigned int dim)
49 : dim_(dim),
50  JxW_values(flags & update_JxW_values ? size : 0),
51  side_JxW_values(flags & update_side_JxW_values ? size : 0),
52  jacobians(spacedim, dim, flags & update_jacobians ? size : 0),
53  determinants(flags & update_volume_elements ? size : 0),
54  inverse_jacobians(dim, spacedim, flags & update_inverse_jacobians ? size : 0),
55  points(spacedim, 1, flags & update_quadrature_points ? size : 0),
56  normal_vectors(spacedim, 1, flags & update_normal_vectors ? size : 0),
57  update_flags(flags)
58 {}
59 
60 
61 template<unsigned int spacedim>
63 {
64  if (cell.is_valid() || side.is_valid())
65  {
66  if (cell.is_valid())
67  printf("cell %d dim %d ", cell.elm_idx(), cell.dim());
68  else if (side.is_valid())
69  printf("cell %d dim %d side %d ", side.elem_idx(), side.dim(), side.side_idx());
70 
71  printf(" det[");
72  for (auto d : determinants) printf("%g ", d); printf("]");
73 
74  printf(" JxW[");
75  for (auto j : JxW_values) printf("%g ", j); printf("]");
76 
77  printf(" side_JxW[");
78  for (auto j : side_JxW_values) printf("%g ", j); printf("]");
79 
80  printf(" nv[");
81  for (unsigned int i=0; i<normal_vectors.size(); i++)
82  {
83  auto n = normal_vectors.vec<spacedim>(i);
84  printf(" [");
85  for (unsigned int c=0; c<spacedim; c++) printf("%g ", n[c]);
86  printf("]");
87  }
88  printf("]\n");
89  }
90 }
91 
92 
93 
94 
95 
96 template<unsigned int spacedim>
98 {
99  ASSERT_DBG( q.dim() == dim_ );
100  ASSERT_DBG( q.size() == n_points_ );
101  RefElementData *ref_data = new RefElementData(q.size());
102 
103  for (unsigned int i=0; i<q.size(); i++)
104  {
105  switch (q.dim())
106  {
107  case 1:
108  ref_data->bar_coords[i] = RefElement<1>::local_to_bary(q.point<1>(i));
109  break;
110  case 2:
111  ref_data->bar_coords[i] = RefElement<2>::local_to_bary(q.point<2>(i));
112  break;
113  case 3:
114  ref_data->bar_coords[i] = RefElement<3>::local_to_bary(q.point<3>(i));
115  break;
116  default:
117  ASSERT(false)(q.dim()).error("Unsupported dimension.\n");
118  break;
119  }
120  ref_data->weights[i] = q.weight(i);
121  }
122 
123  return ref_data;
124 }
125 
126 
127 
128 template<unsigned int spacedim>
130 {
131  switch (dim_)
132  {
133  case 0:
134  flags = MappingP1<0,spacedim>::update_each(flags);
135  break;
136  case 1:
137  flags = MappingP1<1,spacedim>::update_each(flags);
138  break;
139  case 2:
140  flags = MappingP1<2,spacedim>::update_each(flags);
141  break;
142  case 3:
143  flags = MappingP1<3,spacedim>::update_each(flags);
144  break;
145  default:
146  ASSERT(false)(dim_).error("Unsupported dimension.\n");
147  break;
148  }
149  return flags;
150 }
151 
152 
153 
154 template<unsigned int spacedim>
156  Quadrature &_quadrature,
157  UpdateFlags _flags,
158  unsigned int dim)
159 : dim_(dim),
160  n_points_(_quadrature.size()),
161  n_sides_(_quadrature.dim() == dim ? 0 : dim+1),
162  n_side_permutations_(_quadrature.dim() +1 == dim ? (dim+1)*(2*dim*dim-5*dim+6)/6 : 0),
163  ref_data(nullptr),
164  side_ref_data(n_sides_, std::vector<RefElementData*>(n_side_permutations_)),
165  data(n_points_, update_each(_flags), dim)
166 {
167  if (dim == 0) return; // avoid unnecessary allocation of dummy 0 dimensional objects
168  if ( _quadrature.dim() == dim )
169  {
170  // precompute element data
171  ref_data = init_ref_data(_quadrature);
172  }
173  else if ( _quadrature.dim() + 1 == dim )
174  {
175  // precompute side data
176  for (unsigned int sid = 0; sid < n_sides_; sid++)
177  {
178  for (unsigned int pid = 0; pid < n_side_permutations_; pid++)
179  {
180  Quadrature side_quad(dim);
181  // transform the side quadrature points to the cell quadrature points
182  switch (dim)
183  {
184  case 1:
185  side_quad = _quadrature.make_from_side<1>(sid, pid);
186  break;
187  case 2:
188  side_quad = _quadrature.make_from_side<2>(sid, pid);
189  break;
190  case 3:
191  side_quad = _quadrature.make_from_side<3>(sid, pid);
192  break;
193  default:
194  ASSERT(false)(dim).error("Unsupported dimension.\n");
195  break;
196  }
197  side_ref_data[sid][pid] = init_ref_data(side_quad);
198  }
199  }
200  }
201 }
202 
203 
204 template<unsigned int spacedim>
206 {
207  if (ref_data) delete ref_data;
208 
209  for (unsigned int sid=0; sid<n_sides_; sid++)
210  for (unsigned int pid=0; pid<n_side_permutations_; pid++)
211  delete side_ref_data[sid][pid];
212 }
213 
214 
215 template<unsigned int spacedim>
217 {
218  OLD_ASSERT_EQUAL( dim_, cell.dim() );
219  data.cell = cell;
220 
221  // calculate Jacobian of mapping, JxW, inverse Jacobian
222  switch (dim_)
223  {
224  case 1:
225  fill_data<1>();
226  break;
227  case 2:
228  fill_data<2>();
229  break;
230  case 3:
231  fill_data<3>();
232  break;
233  default:
234  ASSERT(false)(dim_).error("Unsupported dimension.\n");
235  break;
236  }
237 }
238 
239 
240 template<unsigned int spacedim>
241 void ElementValues<spacedim>::reinit(const Side & cell_side)
242 {
243  ASSERT_EQ_DBG( dim_, cell_side.dim() );
244  data.side = cell_side;
245 
246  // calculate Jacobian of mapping, JxW, inverse Jacobian, normal vector(s)
247  switch (dim_)
248  {
249  case 1:
250  fill_data<1>();
251  fill_side_data<1>();
252  break;
253  case 2:
254  fill_data<2>();
255  fill_side_data<2>();
256  break;
257  case 3:
258  fill_data<3>();
259  fill_side_data<3>();
260  break;
261  default:
262  ASSERT(false)(dim_).error("Unsupported dimension.\n");
263  break;
264  }
265 }
266 
267 
268 template<unsigned int spacedim>
269 template<unsigned int dim>
271 {
272  typename MappingP1<dim,spacedim>::ElementMap coords;
273 
274  if ((data.update_flags & update_jacobians) |
275  (data.update_flags & update_volume_elements) |
276  (data.update_flags & update_JxW_values) |
277  (data.update_flags & update_inverse_jacobians) |
278  (data.update_flags & update_normal_vectors) |
279  (data.update_flags & update_quadrature_points))
280  {
281  if (cell().is_valid())
283  else
284  coords = MappingP1<dim,spacedim>::element_map(side().element());
285  }
286 
287  // calculation of Jacobian dependent data
288  if ((data.update_flags & update_jacobians) |
289  (data.update_flags & update_volume_elements) |
290  (data.update_flags & update_JxW_values) |
291  (data.update_flags & update_inverse_jacobians) |
292  (data.update_flags & update_normal_vectors))
293  {
294  arma::mat::fixed<spacedim,dim> jac = MappingP1<dim,spacedim>::jacobian(coords);
295 
296  // update Jacobians
297  if (data.update_flags & update_jacobians)
298  for (unsigned int i=0; i<n_points_; i++)
299  data.jacobians.set(i) = Armor::mat<spacedim,dim>( jac );
300 
301  // calculation of determinant dependent data
302  if ((data.update_flags & update_volume_elements) |
303  (data.update_flags & update_JxW_values))
304  {
305  double det = fabs(::determinant(jac));
306 
307  // update determinants
308  if (data.update_flags & update_volume_elements)
309  for (unsigned int i=0; i<n_points_; i++)
310  data.determinants[i] = det;
311 
312  // update JxW values
313  if (data.update_flags & update_JxW_values)
314  for (unsigned int i=0; i<n_points_; i++)
315  data.JxW_values[i] = det*ref_data->weights[i];
316  }
317 
318  // update inverse Jacobians
319  if (data.update_flags & update_inverse_jacobians)
320  {
321  arma::mat::fixed<dim,spacedim> ijac;
322  if (dim==spacedim)
323  {
324  ijac = inv(jac);
325  }
326  else
327  {
328  ijac = pinv(jac);
329  }
330  for (unsigned int i=0; i<n_points_; i++)
331  data.inverse_jacobians.set(i) = Armor::mat<dim,spacedim>( ijac );
332  }
333  }
334 
335  // quadrature points in the actual cell coordinate system
336  if (cell().is_valid() && data.update_flags & update_quadrature_points)
337  {
338  for (unsigned int i=0; i<n_points_; i++)
339  data.points.set(i) = Armor::vec<spacedim>( coords*ref_data->bar_coords[i] );
340  }
341 }
342 
343 
344 template<unsigned int spacedim>
345 template<unsigned int dim>
347 {
348  const unsigned int side_idx = side().side_idx();
349  const unsigned int perm_idx = side().element()->permutation_idx(side_idx);
350 
351  // calculation of normal vectors to the side
352  if (data.update_flags & update_normal_vectors)
353  {
354  arma::vec::fixed<spacedim> n_cell;
355  n_cell = trans(data.inverse_jacobians.template mat<dim,spacedim>(0))*RefElement<dim>::normal_vector(side_idx);
356  n_cell = n_cell/norm(n_cell,2);
357  for (unsigned int i=0; i<n_points_; i++)
358  data.normal_vectors.set(i) = Armor::vec<spacedim>( n_cell );
359  }
360 
361  // Quadrature points in the actual cell coordinate system.
362  // The points location can vary from side to side.
363  if (data.update_flags & update_quadrature_points)
364  {
366  for (unsigned int i=0; i<n_points_; i++)
367  data.points.set(i) = Armor::vec<spacedim>( coords*side_ref_data[side_idx][perm_idx]->bar_coords[i] );
368  }
369 
370  if (data.update_flags & update_side_JxW_values)
371  {
372  double side_det;
373  if (dim <= 1)
374  {
375  side_det = 1;
376  }
377  else
378  {
379  arma::mat::fixed<spacedim,dim> side_coords;
380  arma::mat::fixed<spacedim, MatrixSizes<dim>::dim_minus_one > side_jac; // some compilers complain for case dim==0
381 
382  // calculation of side Jacobian
383  for (unsigned int n=0; n<dim; n++)
384  for (unsigned int c=0; c<spacedim; c++)
385  side_coords(c,n) = (*data.side.node(n))[c];
386  side_jac = MappingP1<MatrixSizes<dim>::dim_minus_one,spacedim>::jacobian(side_coords);
387 
388  // calculation of JxW
389  side_det = fabs(::determinant(side_jac));
390  }
391  for (unsigned int i=0; i<n_points_; i++)
392  data.side_JxW_values[i] = side_det*side_ref_data[side_idx][perm_idx]->weights[i];
393  }
394 }
395 
396 
397 
398 
399 
400 template class ElementValues<3>;
401 
arma::mat::fixed< spacedim, dim+1 > ElementMap
Definition: mapping_p1.hh:64
~ElementValues()
Correct deallocation of objects created by &#39;initialize&#39; methods.
Class MappingP1 implements the affine transformation of the unit cell onto the actual cell...
UpdateFlags
Enum type UpdateFlags indicates which quantities are to be recomputed on each finite element cell...
Definition: update_flags.hh:67
static LocalPoint normal_vector(unsigned int sid)
const ElementAccessor< spacedim > & cell() const
Return cell at which the values were reinited.
unsigned int size() const
Definition: armor.hh:718
Transformed quadrature weight for cell sides.
#define ASSERT_EQ_DBG(a, b)
Definition of comparative assert macro (EQual) only for debug mode.
Definition: asserts.hh:332
ArmaVec< double, N > vec
Definition: armor.hh:861
const Side & side() const
Return cell side where the values were reinited.
unsigned int dim() const
Definition: quadrature.hh:73
void fill_data()
Compute data from reference cell and using MappingP1.
std::vector< double > side_JxW_values
JxW values for sides.
Armor::ArmaVec< double, point_dim > point(unsigned int i) const
Returns the ith quadrature point.
Definition: quadrature.hh:92
ElementData< spacedim > data
Data computed by the mapping.
unsigned int side_idx() const
Returns local index of the side on the element.
Definition: accessors.hh:415
Determinant of the Jacobian.
Quadrature make_from_side(unsigned int sid, unsigned int pid) const
Definition: quadrature.cc:47
RefElementData(unsigned int np)
Resize vectors to size np.
void fill_side_data()
Calculates the mapping data on a side of a cell.
const unsigned int dim_
Dimension of space of reference cell.
std::vector< arma::vec > bar_coords
Barycentric coordinates of quadrature points.
double weight(unsigned int i) const
Returns the ith weight.
Definition: quadrature.hh:108
static UpdateFlags update_each(UpdateFlags flags)
Determines which additional quantities have to be computed.
Definition: mapping_p1.cc:30
Class ElementValues calculates data related to transformation of reference cell to actual cell (Jacob...
double determinant(const unsigned int point_no) const
Return the relative volume change of the cell (Jacobian determinant).
Class for computation of data on cell and side.
Side side
Iterator to last updated cell side.
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library...
Definition: asserts.hh:347
const unsigned int n_sides_
Number of sides in reference cell.
const unsigned int dim_
Dimension of space of reference cell.
ArmaVec< Type, nr > vec(uint mat_index) const
Definition: armor.hh:807
ElementAccessor< 3 > element() const
Returns iterator to the element of the side.
Base class for quadrature rules on simplices in arbitrary dimensions.
Definition: quadrature.hh:48
std::vector< double > weights
Quadrature weights.
Volume element.
arma::mat jacobian(const unsigned int point_no) const
Return Jacobian matrix at point point_no.
Transformed quadrature points.
std::vector< double > determinants
Determinants of Jacobians at quadrature points.
ArmaMat< double, N, M > mat
Definition: armor.hh:864
unsigned int dim() const
Returns dimension of the side, that is dimension of the element minus one.
RefElementData * ref_data
Data on reference element.
bool is_valid() const
Returns true if the side has assigned element.
Definition: accessors.hh:423
RefElementData * init_ref_data(const Quadrature &q)
Precompute data on reference element.
std::vector< double > JxW_values
Transformed quadrature weights.
Basic definitions of numerical quadrature rules.
Affine mapping between reference and actual cell.
Definition: mapping_p1.hh:58
ElementAccessor< spacedim > cell
Iterator to last updated cell.
Normal vectors.
Structure for storing the precomputed element data.
UpdateFlags update_each(UpdateFlags flags)
Determine quantities to be recomputed on each cell.
const unsigned int n_side_permutations_
Number of permutations of points on side of reference cell.
void print()
Print calculated data.
ElementValues(Quadrature &_quadrature, UpdateFlags _flags, unsigned int dim)
Constructor.
Armor::array normal_vectors
Normal vectors (spacedim) to the element at the quadrature points lying on a side.
std::vector< std::vector< RefElementData * > > side_ref_data
Data on reference element (for each side and its permutation).
#define ASSERT_DBG(expr)
static BaryPoint local_to_bary(const LocalPoint &lp)
Converts from local to barycentric coordinates.
Definition: ref_element.cc:305
const unsigned int n_points_
Number of integration points.
#define OLD_ASSERT_EQUAL(a, b)
Definition: global_defs.h:133
unsigned int elem_idx() const
Returns index of element in Mesh::element_vec_.
Definition: accessors.hh:419
static arma::mat::fixed< spacedim, dim > jacobian(const ElementMap &coords)
Definition: mapping_p1.cc:58
ElementData(unsigned int size, UpdateFlags flags, unsigned int dim)
Resize the data arrays.
static ElementMap element_map(ElementAccessor< 3 > elm)
Definition: mapping_p1.cc:48
unsigned int dim() const
Definition: accessors.hh:157
unsigned int size() const
Returns number of quadrature points.
Definition: quadrature.hh:87
unsigned int permutation_idx(unsigned int prm_idx) const
Return permutation_idx of given index.
Definition: elements.h:141
void reinit(const ElementAccessor< spacedim > &cell)
Update cell-dependent data (gradients, Jacobians etc.)
void printf(BasicWriter< Char > &w, BasicCStringRef< Char > format, ArgList args)
Definition: printf.h:444
Transformed quadrature weights.