Reference documentation for deal.II version 9.1.0-pre
fe_bernstein.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2018 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.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/polynomials_bernstein.h>
18 #include <deal.II/base/qprojector.h>
19 #include <deal.II/base/quadrature.h>
20 #include <deal.II/base/quadrature_lib.h>
21 #include <deal.II/base/std_cxx14/memory.h>
22 
23 #include <deal.II/fe/fe_bernstein.h>
24 #include <deal.II/fe/fe_nothing.h>
25 #include <deal.II/fe/fe_q.h>
26 #include <deal.II/fe/fe_tools.h>
27 
28 #include <sstream>
29 #include <vector>
30 
31 
32 DEAL_II_NAMESPACE_OPEN
33 
34 
35 
36 template <int dim, int spacedim>
38  : FE_Q_Base<TensorProductPolynomials<dim>, dim, spacedim>(
39  this->renumber_bases(degree),
40  FiniteElementData<dim>(this->get_dpo_vector(degree),
41  1,
42  degree,
43  FiniteElementData<dim>::H1),
44  std::vector<bool>(1, false))
45 {}
46 
47 
48 
49 template <int dim, int spacedim>
50 void
53  FullMatrix<double> &) const
54 {
55  // no interpolation possible. throw exception, as documentation says
57  false,
59 }
60 
61 
62 
63 template <int dim, int spacedim>
64 const FullMatrix<double> &
66  const unsigned int,
67  const RefinementCase<dim> &) const
68 {
69  AssertThrow(false,
71  // return dummy, nothing will happen because the base class FE_Q_Base
72  // implements lazy evaluation of those matrices
73  return this->restriction[0][0];
74 }
75 
76 
77 
78 template <int dim, int spacedim>
79 const FullMatrix<double> &
81  const unsigned int,
82  const RefinementCase<dim> &) const
83 {
84  AssertThrow(false,
86  // return dummy, nothing will happen because the base class FE_Q_Base
87  // implements lazy evaluation of those matrices
88  return this->prolongation[0][0];
89 }
90 
91 
92 
93 template <int dim, int spacedim>
94 void
96  const FiniteElement<dim, spacedim> &source_fe,
97  FullMatrix<double> & interpolation_matrix) const
98 {
99  Assert(dim > 1, ExcImpossibleInDim(1));
102  interpolation_matrix);
103 }
104 
105 
106 template <int dim, int spacedim>
107 void
109  const FiniteElement<dim, spacedim> &x_source_fe,
110  const unsigned int subface,
111  FullMatrix<double> & interpolation_matrix) const
112 {
113  Assert(interpolation_matrix.m() == x_source_fe.dofs_per_face,
114  ExcDimensionMismatch(interpolation_matrix.m(),
115  x_source_fe.dofs_per_face));
116 
117  // see if source is a Bernstein element
118  if (const FE_Bernstein<dim, spacedim> *source_fe =
119  dynamic_cast<const FE_Bernstein<dim, spacedim> *>(&x_source_fe))
120  {
121  // have this test in here since a table of size 2x0 reports its size as
122  // 0x0
123  Assert(interpolation_matrix.n() == this->dofs_per_face,
124  ExcDimensionMismatch(interpolation_matrix.n(),
125  this->dofs_per_face));
126 
127  // Make sure that the element for which the DoFs should be constrained
128  // is the one with the higher polynomial degree. Actually the procedure
129  // will work also if this assertion is not satisfied. But the matrices
130  // produced in that case might lead to problems in the hp procedures,
131  // which use this method.
132  Assert(
133  this->dofs_per_face <= source_fe->dofs_per_face,
134  (typename FiniteElement<dim,
135  spacedim>::ExcInterpolationNotImplemented()));
136 
137  const Quadrature<dim - 1> quad_face_support(
138  FE_Q<dim, spacedim>(QIterated<1>(QTrapez<1>(), source_fe->degree))
140 
141  // Rule of thumb for FP accuracy, that can be expected for a given
142  // polynomial degree. This value is used to cut off values close to
143  // zero.
144  double eps =
145  2e-13 * std::max(this->degree, source_fe->degree) * (dim - 1);
146 
147  // compute the interpolation matrix by simply taking the value at the
148  // support points.
149  // TODO: Verify that all faces are the same with respect to
150  // these support points. Furthermore, check if something has to
151  // be done for the face orientation flag in 3D.
152  const Quadrature<dim> subface_quadrature =
153  subface == numbers::invalid_unsigned_int ?
154  QProjector<dim>::project_to_face(quad_face_support, 0) :
155  QProjector<dim>::project_to_subface(quad_face_support, 0, subface);
156 
157  for (unsigned int i = 0; i < source_fe->dofs_per_face; ++i)
158  {
159  const Point<dim> &p = subface_quadrature.point(i);
160  for (unsigned int j = 0; j < this->dofs_per_face; ++j)
161  {
162  double matrix_entry =
163  this->shape_value(this->face_to_cell_index(j, 0), p);
164 
165  // Correct the interpolated value. I.e. if it is close to 1 or
166  // 0, make it exactly 1 or 0. Unfortunately, this is required to
167  // avoid problems with higher order elements.
168  if (std::fabs(matrix_entry - 1.0) < eps)
169  matrix_entry = 1.0;
170  if (std::fabs(matrix_entry) < eps)
171  matrix_entry = 0.0;
172 
173  interpolation_matrix(i, j) = matrix_entry;
174  }
175  }
176 
177  // make sure that the row sum of each of the matrices is 1 at this
178  // point. this must be so since the shape functions sum up to 1
179  for (unsigned int j = 0; j < source_fe->dofs_per_face; ++j)
180  {
181  double sum = 0.;
182 
183  for (unsigned int i = 0; i < this->dofs_per_face; ++i)
184  sum += interpolation_matrix(j, i);
185 
186  Assert(std::fabs(sum - 1) < eps, ExcInternalError());
187  }
188  }
189  else if (dynamic_cast<const FE_Nothing<dim> *>(&x_source_fe) != nullptr)
190  {
191  // nothing to do here, the FE_Nothing has no degrees of freedom anyway
192  }
193  else
194  AssertThrow(
195  false,
196  (typename FiniteElement<dim,
197  spacedim>::ExcInterpolationNotImplemented()));
198 }
199 
200 
201 
202 template <int dim, int spacedim>
203 bool
205 {
206  return true;
207 }
208 
209 
210 template <int dim, int spacedim>
211 std::vector<std::pair<unsigned int, unsigned int>>
213  const FiniteElement<dim, spacedim> &fe_other) const
214 {
215  // we can presently only compute these identities if both FEs are
216  // FE_Bernsteins or if the other one is an FE_Nothing. in the first case,
217  // there should be exactly one single DoF of each FE at a vertex, and they
218  // should have identical value
219  if (dynamic_cast<const FE_Bernstein<dim, spacedim> *>(&fe_other) != nullptr)
220  {
221  return std::vector<std::pair<unsigned int, unsigned int>>(
222  1, std::make_pair(0U, 0U));
223  }
224  else if (dynamic_cast<const FE_Nothing<dim> *>(&fe_other) != nullptr)
225  {
226  // the FE_Nothing has no degrees of freedom, so there are no
227  // equivalencies to be recorded
228  return std::vector<std::pair<unsigned int, unsigned int>>();
229  }
230  else if (fe_other.dofs_per_face == 0)
231  {
232  // if the other element has no elements on faces at all,
233  // then it would be impossible to enforce any kind of
234  // continuity even if we knew exactly what kind of element
235  // we have -- simply because the other element declares
236  // that it is discontinuous because it has no DoFs on
237  // its faces. in that case, just state that we have no
238  // constraints to declare
239  return std::vector<std::pair<unsigned int, unsigned int>>();
240  }
241  else
242  {
243  Assert(false, ExcNotImplemented());
244  return std::vector<std::pair<unsigned int, unsigned int>>();
245  }
246 }
247 
248 
249 template <int dim, int spacedim>
250 std::vector<std::pair<unsigned int, unsigned int>>
252  const FiniteElement<dim, spacedim> &) const
253 {
254  // Since this fe is not interpolatory but on the vertices, we can
255  // not identify dofs on lines and on quads even if there are dofs
256  // on lines and on quads.
257  //
258  // we also have nothing to say about interpolation to other finite
259  // elements. consequently, we never have anything to say at all
260  return std::vector<std::pair<unsigned int, unsigned int>>();
261 }
262 
263 
264 template <int dim, int spacedim>
265 std::vector<std::pair<unsigned int, unsigned int>>
267  const FiniteElement<dim, spacedim> &) const
268 {
269  // Since this fe is not interpolatory but on the vertices, we can
270  // not identify dofs on lines and on quads even if there are dofs
271  // on lines and on quads.
272  //
273  // we also have nothing to say about interpolation to other finite
274  // elements. consequently, we never have anything to say at all
275  return std::vector<std::pair<unsigned int, unsigned int>>();
276 }
277 
278 
279 template <int dim, int spacedim>
282  const FiniteElement<dim, spacedim> &fe_other) const
283 {
284  if (const FE_Bernstein<dim, spacedim> *fe_b_other =
285  dynamic_cast<const FE_Bernstein<dim, spacedim> *>(&fe_other))
286  {
287  if (this->degree < fe_b_other->degree)
289  else if (this->degree == fe_b_other->degree)
291  else
293  }
294  else if (const FE_Nothing<dim> *fe_nothing =
295  dynamic_cast<const FE_Nothing<dim> *>(&fe_other))
296  {
297  if (fe_nothing->is_dominating())
298  {
300  }
301  else
302  {
303  // the FE_Nothing has no degrees of freedom and it is typically used
304  // in a context where we don't require any continuity along the
305  // interface
307  }
308  }
309 
310  Assert(false, ExcNotImplemented());
312 }
313 
314 
315 template <int dim, int spacedim>
316 std::string
318 {
319  // note that the FETools::get_fe_by_name function depends on the
320  // particular format of the string this function returns, so they have to be
321  // kept in synch
322 
323  std::ostringstream namebuf;
324  namebuf << "FE_Bernstein<" << dim << ">(" << this->degree << ")";
325  return namebuf.str();
326 }
327 
328 
329 template <int dim, int spacedim>
330 std::unique_ptr<FiniteElement<dim, spacedim>>
332 {
333  return std_cxx14::make_unique<FE_Bernstein<dim, spacedim>>(*this);
334 }
335 
336 
340 template <int dim, int spacedim>
341 std::vector<unsigned int>
343 {
344  AssertThrow(deg > 0, ExcMessage("FE_Bernstein needs to be of degree > 0."));
345  std::vector<unsigned int> dpo(dim + 1, 1U);
346  for (unsigned int i = 1; i < dpo.size(); ++i)
347  dpo[i] = dpo[i - 1] * (deg - 1);
348  return dpo;
349 }
350 
351 
352 template <int dim, int spacedim>
355 {
357  ::generate_complete_bernstein_basis<double>(deg));
358  std::vector<unsigned int> renumber(Utilities::fixed_power<dim>(deg + 1));
359  const FiniteElementData<dim> fe(this->get_dpo_vector(deg), 1, deg);
361  tpp.set_numbering(renumber);
362  return tpp;
363 }
364 
365 
366 // explicit instantiations
367 #include "fe_bernstein.inst"
368 
369 DEAL_II_NAMESPACE_CLOSE
virtual void get_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const override
Definition: fe_bernstein.cc:51
static const unsigned int invalid_unsigned_int
Definition: types.h:173
std::vector< std::vector< FullMatrix< double > > > restriction
Definition: fe.h:2419
FE_Bernstein(const unsigned int p)
Definition: fe_bernstein.cc:37
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
virtual double shape_value(const unsigned int i, const Point< dim > &p) const override
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
void hierarchic_to_lexicographic_numbering(unsigned int degree, std::vector< unsigned int > &h2l)
const unsigned int degree
Definition: fe_base.h:313
void set_numbering(const std::vector< unsigned int > &renumber)
STL namespace.
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
static::ExceptionBase & ExcInterpolationNotImplemented()
static::ExceptionBase & ExcMessage(std::string arg1)
Definition: fe_q.h:554
size_type n() const
static::ExceptionBase & ExcImpossibleInDim(int arg1)
std::vector< std::vector< FullMatrix< double > > > prolongation
Definition: fe.h:2433
#define Assert(cond, exc)
Definition: exceptions.h:1227
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
size_type m() const
virtual unsigned int face_to_cell_index(const unsigned int face_dof_index, const unsigned int face, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false) const override
virtual FiniteElementDomination::Domination compare_for_face_domination(const FiniteElement< dim, spacedim > &fe_other) const override
TensorProductPolynomials< dim > renumber_bases(const unsigned int degree)
static void project_to_subface(const SubQuadrature &quadrature, const unsigned int face_no, const unsigned int subface_no, std::vector< Point< dim >> &q_points, const RefinementCase< dim-1 > &ref_case=RefinementCase< dim-1 >::isotropic_refinement)
virtual const FullMatrix< double > & get_prolongation_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const override
Definition: fe_bernstein.cc:80
static void project_to_face(const SubQuadrature &quadrature, const unsigned int face_no, std::vector< Point< dim >> &q_points)
virtual bool hp_constraints_are_implemented() const override
virtual std::string get_name() const override
static std::vector< unsigned int > get_dpo_vector(const unsigned int degree)
const unsigned int dofs_per_face
Definition: fe_base.h:290
static::ExceptionBase & ExcNotImplemented()
virtual void get_face_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const override
Definition: fe_bernstein.cc:95
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_quad_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
const std::vector< Point< dim-1 > > & get_unit_face_support_points() const
Definition: fe.cc:1060
virtual const FullMatrix< double > & get_restriction_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const override
Definition: fe_bernstein.cc:65
virtual void get_subface_interpolation_matrix(const FiniteElement< dim, spacedim > &source, const unsigned int subface, FullMatrix< double > &matrix) const override
static::ExceptionBase & ExcInternalError()