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