Reference documentation for deal.II version 8.5.1
mapping_q.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2001 - 2016 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/utilities.h>
17 #include <deal.II/base/polynomial.h>
18 #include <deal.II/base/quadrature.h>
19 #include <deal.II/base/quadrature_lib.h>
20 #include <deal.II/base/memory_consumption.h>
21 #include <deal.II/base/tensor_product_polynomials.h>
22 #include <deal.II/base/std_cxx11/unique_ptr.h>
23 #include <deal.II/lac/full_matrix.h>
24 #include <deal.II/grid/tria_iterator.h>
25 #include <deal.II/dofs/dof_accessor.h>
26 #include <deal.II/fe/mapping_q.h>
27 #include <deal.II/fe/fe_q.h>
28 #include <deal.II/fe/fe_values.h>
29 
30 #include <numeric>
31 
32 DEAL_II_NAMESPACE_OPEN
33 
34 
35 template<int dim, int spacedim>
37  :
38  use_mapping_q1_on_current_cell(false)
39 {}
40 
41 
42 
43 template<int dim, int spacedim>
44 std::size_t
46 {
48  MemoryConsumption::memory_consumption (use_mapping_q1_on_current_cell) +
49  MemoryConsumption::memory_consumption (mapping_q1_data) +
50  MemoryConsumption::memory_consumption (mapping_qp_data));
51 }
52 
53 
54 
55 template<int dim, int spacedim>
56 MappingQ<dim,spacedim>::MappingQ (const unsigned int degree,
57  const bool use_mapping_q_on_all_cells)
58  :
59  polynomial_degree (degree),
60 
61  // see whether we want to use *this* mapping objects on *all* cells,
62  // or defer to an explicit Q1 mapping on interior cells. if
63  // degree==1, then we are already that Q1 mapping, so we don't need
64  // it; if dim!=spacedim, there is also no need for anything because
65  // we're most likely on a curved manifold
67  ||
69  ||
70  (dim != spacedim)),
71  // create a Q1 mapping for use on interior cells (if necessary)
72  // or to create a good initial guess in transform_real_to_unit_cell()
73  q1_mapping (new MappingQGeneric<dim,spacedim>(1)),
74 
75  // create a Q_p mapping; if p=1, simply share the Q_1 mapping already
76  // created via the shared_ptr objects
78  ?
79  std_cxx11::shared_ptr<const MappingQGeneric<dim,spacedim> >(new MappingQGeneric<dim,spacedim>(degree))
80  :
81  q1_mapping)
82 {}
83 
84 
85 
86 template<int dim, int spacedim>
88  :
89  polynomial_degree (mapping.polynomial_degree),
90  use_mapping_q_on_all_cells (mapping.use_mapping_q_on_all_cells),
91  // clone the Q1 mapping for use on interior cells (if necessary)
92  // or to create a good initial guess in transform_real_to_unit_cell()
93  q1_mapping (dynamic_cast<MappingQGeneric<dim,spacedim>*>(mapping.q1_mapping->clone())),
94  // create a Q_p mapping; if p=1, simply share the Q_1 mapping already
95  // created via the shared_ptr objects
96  qp_mapping (this->polynomial_degree>1
97  ?
98  std_cxx11::shared_ptr<const MappingQGeneric<dim,spacedim> >(dynamic_cast<MappingQGeneric<dim,spacedim>*>(mapping.qp_mapping->clone()))
99  :
100  q1_mapping)
101 {}
102 
103 
104 
105 template<int dim, int spacedim>
106 unsigned int
108 {
109  return polynomial_degree;
110 }
111 
112 
113 
114 template <int dim, int spacedim>
115 inline
116 bool
118 {
119  return true;
120 }
121 
122 
123 
124 template<int dim, int spacedim>
127 {
128  return (q1_mapping->requires_update_flags(in)
129  |
130  qp_mapping->requires_update_flags(in));
131 }
132 
133 
134 
135 template<int dim, int spacedim>
138  const Quadrature<dim> &quadrature) const
139 {
140  InternalData *data = new InternalData;
141 
142  // build the Q1 and Qp internal data objects in parallel
145  *qp_mapping,
146  update_flags,
147  quadrature);
148 
149  if (!use_mapping_q_on_all_cells)
150  data->mapping_q1_data.reset (q1_mapping->get_data (update_flags, quadrature));
151 
152  // wait for the task above to finish and use returned value
153  data->mapping_qp_data.reset (do_get_data.return_value());
154  return data;
155 }
156 
157 
158 
159 template<int dim, int spacedim>
162  const Quadrature<dim-1>& quadrature) const
163 {
164  InternalData *data = new InternalData;
165 
166  // build the Q1 and Qp internal data objects in parallel
169  *qp_mapping,
170  update_flags,
171  quadrature);
172 
173  if (!use_mapping_q_on_all_cells)
174  data->mapping_q1_data.reset (q1_mapping->get_face_data (update_flags, quadrature));
175 
176  // wait for the task above to finish and use returned value
177  data->mapping_qp_data.reset (do_get_data.return_value());
178  return data;
179 }
180 
181 
182 
183 template<int dim, int spacedim>
186  const Quadrature<dim-1>& quadrature) const
187 {
188  InternalData *data = new InternalData;
189 
190  // build the Q1 and Qp internal data objects in parallel
193  *qp_mapping,
194  update_flags,
195  quadrature);
196 
197  if (!use_mapping_q_on_all_cells)
198  data->mapping_q1_data.reset (q1_mapping->get_subface_data (update_flags, quadrature));
199 
200  // wait for the task above to finish and use returned value
201  data->mapping_qp_data.reset (do_get_data.return_value());
202  return data;
203 }
204 
205 
206 // Note that the CellSimilarity flag is modifiable, since MappingQ can need to
207 // recalculate data even when cells are similar.
208 template<int dim, int spacedim>
212  const CellSimilarity::Similarity cell_similarity,
213  const Quadrature<dim> &quadrature,
214  const typename Mapping<dim,spacedim>::InternalDataBase &internal_data,
216 {
217  // convert data object to internal data for this class. fails with an
218  // exception if that is not possible
219  Assert (dynamic_cast<const InternalData *> (&internal_data) != 0, ExcInternalError());
220  const InternalData &data = static_cast<const InternalData &> (internal_data);
221 
222  // check whether this cell needs the full mapping or can be treated by a
223  // reduced Q1 mapping, e.g. if the cell is in the interior of the domain
224  data.use_mapping_q1_on_current_cell = !(use_mapping_q_on_all_cells
225  || cell->has_boundary_lines());
226 
227 
228  // call the base class. we need to ensure that the flag indicating whether
229  // we can use some similarity has to be modified - for a general MappingQ,
230  // the data needs to be recomputed anyway since then the mapping changes the
231  // data. this needs to be known also for later operations, so modify the
232  // variable here. this also affects the calculation of the next cell -- if
233  // we use Q1 data on the next cell, the data will still be invalid.
234  const CellSimilarity::Similarity updated_cell_similarity
235  = ((data.use_mapping_q1_on_current_cell == false)
236  &&
237  (this->polynomial_degree > 1)
238  ?
240  :
241  cell_similarity);
242 
243  // depending on the results above, decide whether the Q1 mapping or
244  // the Qp mapping needs to handle this cell
245  if (data.use_mapping_q1_on_current_cell)
246  q1_mapping->fill_fe_values (cell,
247  updated_cell_similarity,
248  quadrature,
249  *data.mapping_q1_data,
250  output_data);
251  else
252  qp_mapping->fill_fe_values(cell,
253  updated_cell_similarity,
254  quadrature,
255  *data.mapping_qp_data,
256  output_data);
257 
258  return updated_cell_similarity;
259 }
260 
261 
262 
263 template<int dim, int spacedim>
264 void
267  const unsigned int face_no,
268  const Quadrature<dim-1> &quadrature,
269  const typename Mapping<dim,spacedim>::InternalDataBase &internal_data,
271 {
272  // convert data object to internal data for this class. fails with an
273  // exception if that is not possible
274  Assert (dynamic_cast<const InternalData *> (&internal_data) != 0,
275  ExcInternalError());
276  const InternalData &data = static_cast<const InternalData &> (internal_data);
277 
278  // check whether this cell needs the full mapping or can be treated by a
279  // reduced Q1 mapping, e.g. if the cell is entirely in the interior of the
280  // domain. note that it is not sufficient to ask whether the present _face_
281  // is in the interior, as the mapping on the face depends on the mapping of
282  // the cell, which in turn depends on the fact whether _any_ of the faces of
283  // this cell is at the boundary, not only the present face
284  data.use_mapping_q1_on_current_cell = !(use_mapping_q_on_all_cells
285  || cell->has_boundary_lines());
286 
287  // depending on the results above, decide whether the Q1 mapping or
288  // the Qp mapping needs to handle this cell
289  if (data.use_mapping_q1_on_current_cell)
290  q1_mapping->fill_fe_face_values (cell,
291  face_no,
292  quadrature,
293  *data.mapping_q1_data,
294  output_data);
295  else
296  qp_mapping->fill_fe_face_values(cell,
297  face_no,
298  quadrature,
299  *data.mapping_qp_data,
300  output_data);
301 }
302 
303 
304 template<int dim, int spacedim>
305 void
308  const unsigned int face_no,
309  const unsigned int subface_no,
310  const Quadrature<dim-1> &quadrature,
311  const typename Mapping<dim,spacedim>::InternalDataBase &internal_data,
313 {
314  // convert data object to internal data for this class. fails with an
315  // exception if that is not possible
316  Assert (dynamic_cast<const InternalData *> (&internal_data) != 0,
317  ExcInternalError());
318  const InternalData &data = static_cast<const InternalData &> (internal_data);
319 
320  // check whether this cell needs the full mapping or can be treated by a
321  // reduced Q1 mapping, e.g. if the cell is entirely in the interior of the
322  // domain. note that it is not sufficient to ask whether the present _face_
323  // is in the interior, as the mapping on the face depends on the mapping of
324  // the cell, which in turn depends on the fact whether _any_ of the faces of
325  // this cell is at the boundary, not only the present face
326  data.use_mapping_q1_on_current_cell = !(use_mapping_q_on_all_cells
327  || cell->has_boundary_lines());
328 
329  // depending on the results above, decide whether the Q1 mapping or
330  // the Qp mapping needs to handle this cell
331  if (data.use_mapping_q1_on_current_cell)
332  q1_mapping->fill_fe_subface_values (cell,
333  face_no,
334  subface_no,
335  quadrature,
336  *data.mapping_q1_data,
337  output_data);
338  else
339  qp_mapping->fill_fe_subface_values(cell,
340  face_no,
341  subface_no,
342  quadrature,
343  *data.mapping_qp_data,
344  output_data);
345 }
346 
347 
348 
349 template<int dim, int spacedim>
350 void
352 transform (const ArrayView<const Tensor<1,dim> > &input,
353  const MappingType mapping_type,
354  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
355  const ArrayView<Tensor<1,spacedim> > &output) const
356 {
357  AssertDimension (input.size(), output.size());
358  Assert ((dynamic_cast<const typename MappingQ<dim,spacedim>::InternalData *> (&mapping_data)
359  != 0),
360  ExcInternalError());
361  const InternalData *data = dynamic_cast<const InternalData *>(&mapping_data);
362 
363  // check whether we should in fact work on the Q1 portion of it
365  q1_mapping->transform (input, mapping_type, *data->mapping_q1_data, output);
366  else
367  // otherwise use the full mapping
368  qp_mapping->transform(input, mapping_type, *data->mapping_qp_data, output);
369 }
370 
371 
372 
373 template<int dim, int spacedim>
374 void
377  const MappingType mapping_type,
378  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
379  const ArrayView<Tensor<2,spacedim> > &output) const
380 {
381  AssertDimension (input.size(), output.size());
382  Assert ((dynamic_cast<const typename MappingQ<dim,spacedim>::InternalData *> (&mapping_data)
383  != 0),
384  ExcInternalError());
385  const InternalData *data = dynamic_cast<const InternalData *>(&mapping_data);
386 
387  // check whether we should in fact work on the Q1 portion of it
389  q1_mapping->transform (input, mapping_type, *data->mapping_q1_data, output);
390  else
391  // otherwise use the full mapping
392  qp_mapping->transform(input, mapping_type, *data->mapping_qp_data, output);
393 }
394 
395 
396 
397 template<int dim, int spacedim>
398 void
400 transform (const ArrayView<const Tensor<2, dim> > &input,
401  const MappingType mapping_type,
402  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
403  const ArrayView<Tensor<2,spacedim> > &output) const
404 {
405  AssertDimension (input.size(), output.size());
406  Assert ((dynamic_cast<const typename MappingQ<dim,spacedim>::InternalData *> (&mapping_data)
407  != 0),
408  ExcInternalError());
409  const InternalData *data = dynamic_cast<const InternalData *>(&mapping_data);
410 
411  // check whether we should in fact work on the Q1 portion of it
413  q1_mapping->transform (input, mapping_type, *data->mapping_q1_data, output);
414  else
415  // otherwise use the full mapping
416  qp_mapping->transform(input, mapping_type, *data->mapping_qp_data, output);
417 }
418 
419 
420 
421 template<int dim, int spacedim>
422 void
425  const MappingType mapping_type,
426  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
427  const ArrayView<Tensor<3,spacedim> > &output) const
428 {
429  AssertDimension (input.size(), output.size());
430  Assert ((dynamic_cast<const typename MappingQ<dim,spacedim>::InternalData *> (&mapping_data)
431  != 0),
432  ExcInternalError());
433  const InternalData *data = dynamic_cast<const InternalData *>(&mapping_data);
434 
435  // check whether we should in fact work on the Q1 portion of it
437  q1_mapping->transform (input, mapping_type, *data->mapping_q1_data, output);
438  else
439  // otherwise use the full mapping
440  qp_mapping->transform(input, mapping_type, *data->mapping_qp_data, output);
441 }
442 
443 
444 
445 template<int dim, int spacedim>
447 transform (const ArrayView<const Tensor<3, dim> > &input,
448  const MappingType mapping_type,
449  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_data,
450  const ArrayView<Tensor<3,spacedim> > &output) const
451 {
452  AssertDimension (input.size(), output.size());
453  Assert ((dynamic_cast<const typename MappingQ<dim,spacedim>::InternalData *> (&mapping_data)
454  != 0),
455  ExcInternalError());
456  const InternalData *data = dynamic_cast<const InternalData *>(&mapping_data);
457 
458  // check whether we should in fact work on the Q1 portion of it
460  q1_mapping->transform (input, mapping_type, *data->mapping_q1_data, output);
461  else
462  // otherwise use the full mapping
463  qp_mapping->transform(input, mapping_type, *data->mapping_qp_data, output);
464 }
465 
466 
467 
468 template<int dim, int spacedim>
472  const Point<dim> &p) const
473 {
474  // first see, whether we want to use a linear or a higher order
475  // mapping, then either use our own facilities or that of the Q1
476  // mapping we store
477  if (use_mapping_q_on_all_cells || cell->has_boundary_lines())
478  return qp_mapping->transform_unit_to_real_cell (cell, p);
479  else
480  return q1_mapping->transform_unit_to_real_cell (cell, p);
481 }
482 
483 
484 
485 template<int dim, int spacedim>
489  const Point<spacedim> &p) const
490 {
491  if (cell->has_boundary_lines()
492  ||
493  use_mapping_q_on_all_cells
494  ||
495  (dim!=spacedim) )
496  return qp_mapping->transform_real_to_unit_cell(cell, p);
497  else
498  return q1_mapping->transform_real_to_unit_cell(cell, p);
499 }
500 
501 
502 
503 template<int dim, int spacedim>
506 {
507  return new MappingQ<dim,spacedim>(this->polynomial_degree,
508  this->use_mapping_q_on_all_cells);
509 }
510 
511 
512 
513 // explicit instantiations
514 #include "mapping_q.inst"
515 
516 
517 DEAL_II_NAMESPACE_CLOSE
unsigned int get_degree() const
Definition: mapping_q.cc:107
virtual InternalData * get_face_data(const UpdateFlags flags, const Quadrature< dim-1 > &quadrature) const
Definition: mapping_q.cc:161
std_cxx11::shared_ptr< const MappingQGeneric< dim, spacedim > > q1_mapping
Definition: mapping_q.h:355
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1146
virtual Point< dim > transform_real_to_unit_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< spacedim > &p) const
Definition: mapping_q.cc:488
MappingType
Definition: mapping.h:50
virtual InternalData * get_subface_data(const UpdateFlags flags, const Quadrature< dim-1 > &quadrature) const
Definition: mapping_q.cc:185
bool use_mapping_q1_on_current_cell
Definition: mapping_q.h:254
std_cxx11::unique_ptr< typename MappingQGeneric< dim, spacedim >::InternalData > mapping_q1_data
Definition: mapping_q.h:260
const bool use_mapping_q_on_all_cells
Definition: mapping_q.h:336
virtual std::size_t memory_consumption() const
Definition: mapping_q.cc:45
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) const
Definition: mapping_q.cc:126
virtual void transform(const ArrayView< const Tensor< 1, dim > > &input, const MappingType type, const typename Mapping< dim, spacedim >::InternalDataBase &internal, const ArrayView< Tensor< 1, spacedim > > &output) const
Definition: mapping_q.cc:352
#define Assert(cond, exc)
Definition: exceptions.h:313
UpdateFlags
Abstract base class for mapping classes.
Definition: dof_tools.h:46
const unsigned int polynomial_degree
Definition: mapping_q.h:330
virtual Mapping< dim, spacedim > * clone() const
Definition: mapping_q.cc:505
std_cxx11::enable_if< std_cxx11::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
std_cxx11::unique_ptr< typename MappingQGeneric< dim, spacedim >::InternalData > mapping_qp_data
Definition: mapping_q.h:266
virtual Point< spacedim > transform_unit_to_real_cell(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const Point< dim > &p) const
Definition: mapping_q.cc:471
virtual InternalData * get_data(const UpdateFlags, const Quadrature< dim > &quadrature) const
Definition: mapping_q.cc:137
std_cxx11::shared_ptr< const MappingQGeneric< dim, spacedim > > qp_mapping
Definition: mapping_q.h:371
MappingQ(const unsigned int polynomial_degree, const bool use_mapping_q_on_all_cells=false)
Definition: mapping_q.cc:56
virtual bool preserves_vertex_locations() const
Definition: mapping_q.cc:117
Task< RT > new_task(const std_cxx11::function< RT()> &function)
static ::ExceptionBase & ExcInternalError()