Flow123d
mapping_p1.cc
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 Class MappingP1 implements the affine transformation of
27  * the unit cell onto the actual cell.
28  * @author Jan Stebel
29  */
30 
31 
32 #include "fem/mapping_p1.hh"
33 #include "quadrature/quadrature.hh"
34 #include "fem/fe_values.hh"
35 
36 
37 
38 using namespace std;
39 using namespace arma;
40 
41 
42 
43 
44 template<unsigned int dim, unsigned int spacedim>
46 {
47 }
48 
49 template<unsigned int dim, unsigned int spacedim>
51 {
53 
54  // Initialize the gradients of the canonical basis in the
55  // barycentric coordinates.
56  // In the case of P1 mapping the shape functions are linear,
57  // hence the gradients are constant and can be precomputed.
58  if ((flags & update_jacobians) |
59  (flags & update_volume_elements) |
60  (flags & update_JxW_values) |
61  (flags & update_side_JxW_values) |
62  (flags & update_inverse_jacobians))
63  {
64  grad.zeros();
65  for (unsigned int i=0; i<dim; i++)
66  {
67  grad(0,i) = -1;
68  grad(i+1,i) = 1;
69  }
70  }
71 
72  // barycentric coordinates of quadrature points
73  if (flags & update_quadrature_points)
74  {
75  vec::fixed<dim+1> basis;
76  data->bar_coords.resize(q.size());
77  for (unsigned int i=0; i<q.size(); i++)
78  {
79  basis[0] = 1;
80  for (unsigned int j=0; j<dim; j++)
81  {
82  basis[0] -= q.point(i)[j];
83  basis[j+1] = q.point(i)[j];
84  }
85  data->bar_coords[i] = basis;
86  }
87  }
88 
89 
90 
91  return data;
92 }
93 
94 template<unsigned int dim, unsigned int spacedim>
96 {
97  UpdateFlags f = flags;
98 
99  if (flags & update_normal_vectors)
101 
102  if ((flags & update_volume_elements) |
103  (flags & update_JxW_values) |
104  (flags & update_inverse_jacobians))
105  f |= update_jacobians;
106 
107  return f;
108 }
109 
110 
111 template<unsigned int dim, unsigned int spacedim>
113  const Quadrature<dim> &q,
114  MappingInternalData &data,
116 {
117  mat::fixed<spacedim,dim+1> coords;
118  mat::fixed<spacedim,dim> jac;
119 
120  if ((fv_data.update_flags & update_jacobians) |
122  (fv_data.update_flags & update_JxW_values) |
125  {
126  coords.zeros();
127  for (unsigned int n=0; n<dim+1; n++)
128  for (unsigned int c=0; c<spacedim; c++)
129  coords(c,n) = cell->node[n]->point()[c];
130  }
131 
132  // calculation of Jacobian dependent data
133  if ((fv_data.update_flags & update_jacobians) |
135  (fv_data.update_flags & update_JxW_values) |
137  {
138  jac = coords*grad;
139 
140  // update Jacobians
141  if (fv_data.update_flags & update_jacobians)
142  for (unsigned int i=0; i<q.size(); i++)
143  fv_data.jacobians[i] = jac;
144 
145  // calculation of determinant dependent data
147  {
148  double det = fabs(determinant(jac));
149 
150  // update determinants
151  if (fv_data.update_flags & update_volume_elements)
152  for (unsigned int i=0; i<q.size(); i++)
153  fv_data.determinants[i] = det;
154 
155  // update JxW values
156  if (fv_data.update_flags & update_JxW_values)
157  for (unsigned int i=0; i<q.size(); i++)
158  fv_data.JxW_values[i] = det*q.weight(i);
159  }
160 
161  // update inverse Jacobians
163  {
164  mat::fixed<dim,spacedim> ijac;
165  if (dim==spacedim)
166  {
167  ijac = inv(jac);
168  }
169  else
170  {
171  ijac = pinv(jac);
172  }
173  for (unsigned int i=0; i<q.size(); i++)
174  fv_data.inverse_jacobians[i] = ijac;
175  }
176  }
177 
178  // quadrature points in the actual cell coordinate system
180  {
181  vec::fixed<dim+1> basis;
182  for (unsigned int i=0; i<q.size(); i++)
183  fv_data.points[i] = coords*data.bar_coords[i];
184  }
185 }
186 
187 template<unsigned int dim, unsigned int spacedim>
189  unsigned int sid,
190  const Quadrature<dim> &q,
191  MappingInternalData &data,
193 {
194  mat::fixed<spacedim,dim+1> coords;
195 
196  if ((fv_data.update_flags & update_jacobians) |
199  (fv_data.update_flags & update_normal_vectors) |
201  {
202  coords.zeros();
203  for (unsigned int n=0; n<dim+1; n++)
204  for (unsigned int c=0; c<spacedim; c++)
205  coords(c,n) = cell->node[n]->point()[c];
206  }
207 
208  // calculation of cell Jacobians and dependent data
209  if ((fv_data.update_flags & update_jacobians) |
213  {
214  mat::fixed<spacedim,dim> jac = coords*grad;
215 
216  // update cell Jacobians
217  if (fv_data.update_flags & update_jacobians)
218  for (unsigned int i=0; i<q.size(); i++)
219  fv_data.jacobians[i] = jac;
220 
221  // update determinants of Jacobians
222  if (fv_data.update_flags & update_volume_elements)
223  {
224  double det = fabs(determinant(jac));
225  for (unsigned int i=0; i<q.size(); i++)
226  fv_data.determinants[i] = det;
227  }
228 
229  // inverse Jacobians
231  {
232  mat::fixed<dim,spacedim> ijac;
233  if (dim==spacedim)
234  {
235  ijac = inv(jac);
236  }
237  else
238  {
239  ijac = pinv(jac);
240  }
241  for (unsigned int i=0; i<q.size(); i++)
242  fv_data.inverse_jacobians[i] = ijac;
243 
244  // calculation of normal vectors to the side
245  if ((fv_data.update_flags & update_normal_vectors))
246  {
247  vec::fixed<spacedim> n_cell;
248  n_cell = trans(ijac)*RefElement<dim>::normal_vector(sid);
249  n_cell = n_cell/norm(n_cell,2);
250  for (unsigned int i=0; i<q.size(); i++)
251  fv_data.normal_vectors[i] = n_cell;
252  }
253  }
254  }
255 
256  // Quadrature points in the actual cell coordinate system.
257  // The points location can vary from side to side.
259  {
260  for (unsigned int i=0; i<q.size(); i++)
261  fv_data.points[i] = coords*data.bar_coords[i];
262  }
263 
264  if (fv_data.update_flags & update_side_JxW_values)
265  {
266  double side_det;
267  if (dim <= 1)
268  {
269  side_det = 1;
270  }
271  else
272  {
273  mat::fixed<spacedim,dim> side_coords;
274  mat::fixed<spacedim, MatrixSizes<dim>::dim_minus_one > side_jac; // some compilers complain for case dim==0
275 
276  // calculation of side Jacobian
277  side_coords.zeros();
278  for (unsigned int n=0; n<dim; n++)
279  for (unsigned int c=0; c<spacedim; c++)
280  side_coords(c,n) = cell->side(sid)->node(n)->point()[c];
281  side_jac = side_coords * grad.submat(0,0,dim-1,dim-2);
282 
283  // calculation of JxW
284  side_det = fabs(determinant(side_jac));
285  }
286  for (unsigned int i=0; i<q.size(); i++)
287  fv_data.JxW_values[i] = side_det*q.weight(i);
288  }
289 }
290 
291 template<>
293  unsigned int sid,
294  const Quadrature<0> &q,
295  MappingInternalData &data,
296  FEValuesData<0,3> &fv_data)
297 {}
298 
299 
300 
301 template class MappingP1<0,3>;
302 template class MappingP1<1,3>;
303 template class MappingP1<2,3>;
304 template class MappingP1<3,3>;
305 
306 
307 
308