Reference documentation for deal.II version 8.4.2
fe_bernstein.cc
1 // ---------------------------------------------------------------------
2 // @f$Id: fe_q.cc 30037 2013-07-18 16:55:40Z maier @f$
3 //
4 // Copyright (C) 2000 - 2015 by the deal.II authors
5 //
6 // This file is part of the deal.II library.
7 //
8 // The deal.II library is free software; you can use it, redistribute
9 // it, and/or modify it under the terms of the GNU Lesser General
10 // Public License as published by the Free Software Foundation; either
11 // version 2.1 of the License, or (at your option) any later version.
12 // The full text of the license can be found in the file LICENSE at
13 // the top level of the deal.II distribution.
14 //
15 // ---------------------------------------------------------------------
16 
17 
18 #include <deal.II/base/quadrature.h>
19 #include <deal.II/base/quadrature_lib.h>
20 #include <deal.II/base/qprojector.h>
21 #include <deal.II/fe/fe_nothing.h>
22 #include <deal.II/fe/fe_q.h>
23 #include <deal.II/fe/fe_tools.h>
24 #include <deal.II/fe/fe_bernstein.h>
25 #include <deal.II/base/polynomials_bernstein.h>
26 
27 #include <vector>
28 #include <sstream>
29 
30 DEAL_II_NAMESPACE_OPEN
31 
32 
33 
34 template <int dim, int spacedim>
35 FE_Bernstein<dim,spacedim>::FE_Bernstein (const unsigned int degree)
36  :
37  FE_Q_Base<TensorProductPolynomials<dim>, dim, spacedim> (
38  this->renumber_bases(degree),
39  FiniteElementData<dim>(this->get_dpo_vector(degree),
40  1, degree,
41  FiniteElementData<dim>::H1),
42  std::vector<bool> (1, false))
43 {}
44 
45 
46 template <int dim, int spacedim>
47 void
50  FullMatrix<double> &interpolation_matrix) const
51 {
52  Assert (dim > 1, ExcImpossibleInDim(1));
54  interpolation_matrix);
55 }
56 
57 
58 template <int dim, int spacedim>
59 void
62  const unsigned int subface,
63  FullMatrix<double> &interpolation_matrix) const
64 {
65  Assert (interpolation_matrix.m() == x_source_fe.dofs_per_face,
66  ExcDimensionMismatch (interpolation_matrix.m(),
67  x_source_fe.dofs_per_face));
68 
69  // see if source is a Bernstein element
70  if (const FE_Bernstein<dim,spacedim> *source_fe
71  = dynamic_cast<const FE_Bernstein<dim,spacedim> *>(&x_source_fe))
72  {
73  // have this test in here since a table of size 2x0 reports its size as
74  // 0x0
75  Assert (interpolation_matrix.n() == this->dofs_per_face,
76  ExcDimensionMismatch (interpolation_matrix.n(),
77  this->dofs_per_face));
78 
79  // Make sure that the element for which the DoFs should be constrained
80  // is the one with the higher polynomial degree. Actually the procedure
81  // will work also if this assertion is not satisfied. But the matrices
82  // produced in that case might lead to problems in the hp procedures,
83  // which use this method.
84  Assert (this->dofs_per_face <= source_fe->dofs_per_face,
85  (typename FiniteElement<dim,spacedim>::
86  ExcInterpolationNotImplemented ()));
87 
88  const Quadrature<dim-1>
89  quad_face_support(FE_Q<dim,spacedim>(source_fe->degree).get_unit_face_support_points ());
90 
91  // Rule of thumb for FP accuracy, that can be expected for a given
92  // polynomial degree. This value is used to cut off values close to
93  // zero.
94  double eps = 2e-13 * std::max(this->degree, source_fe->degree) * (dim-1);
95 
96  // compute the interpolation matrix by simply taking the value at the
97  // support points.
98 //TODO: Verify that all faces are the same with respect to
99 // these support points. Furthermore, check if something has to
100 // be done for the face orientation flag in 3D.
101  const Quadrature<dim> subface_quadrature
102  = subface == numbers::invalid_unsigned_int
103  ?
104  QProjector<dim>::project_to_face (quad_face_support, 0)
105  :
106  QProjector<dim>::project_to_subface (quad_face_support, 0, subface);
107 
108  for (unsigned int i=0; i<source_fe->dofs_per_face; ++i)
109  {
110  const Point<dim> &p = subface_quadrature.point (i);
111  for (unsigned int j=0; j<this->dofs_per_face; ++j)
112  {
113  double matrix_entry = this->shape_value (this->face_to_cell_index(j, 0), p);
114 
115  // Correct the interpolated value. I.e. if it is close to 1 or
116  // 0, make it exactly 1 or 0. Unfortunately, this is required to
117  // avoid problems with higher order elements.
118  if (std::fabs (matrix_entry - 1.0) < eps)
119  matrix_entry = 1.0;
120  if (std::fabs (matrix_entry) < eps)
121  matrix_entry = 0.0;
122 
123  interpolation_matrix(i,j) = matrix_entry;
124  }
125  }
126 
127  // make sure that the row sum of each of the matrices is 1 at this
128  // point. this must be so since the shape functions sum up to 1
129  for (unsigned int j=0; j<source_fe->dofs_per_face; ++j)
130  {
131  double sum = 0.;
132 
133  for (unsigned int i=0; i<this->dofs_per_face; ++i)
134  sum += interpolation_matrix(j,i);
135 
136  Assert (std::fabs(sum-1) < eps, ExcInternalError());
137  }
138  }
139  else if (dynamic_cast<const FE_Nothing<dim> *>(&x_source_fe) != 0)
140  {
141  // nothing to do here, the FE_Nothing has no degrees of freedom anyway
142  }
143  else
144  AssertThrow (false,(typename FiniteElement<dim,spacedim>::
145  ExcInterpolationNotImplemented()));
146 }
147 
148 
149 
150 template <int dim, int spacedim>
151 bool
153 {
154  return true;
155 }
156 
157 
158 template <int dim, int spacedim>
159 std::vector<std::pair<unsigned int, unsigned int> >
161 {
162  // we can presently only compute these identities if both FEs are FE_Bernsteins
163  // or if the other one is an FE_Nothing. in the first case, there should be
164  // exactly one single DoF of each FE at a vertex, and they should have
165  // identical value
166  if (dynamic_cast<const FE_Bernstein<dim,spacedim>*>(&fe_other) != 0)
167  {
168  return
169  std::vector<std::pair<unsigned int, unsigned int> >
170  (1, std::make_pair (0U, 0U));
171  }
172  else if (dynamic_cast<const FE_Nothing<dim>*>(&fe_other) != 0)
173  {
174  // the FE_Nothing has no degrees of freedom, so there are no
175  // equivalencies to be recorded
176  return std::vector<std::pair<unsigned int, unsigned int> > ();
177  }
178  else if (fe_other.dofs_per_face == 0)
179  {
180  // if the other element has no elements on faces at all,
181  // then it would be impossible to enforce any kind of
182  // continuity even if we knew exactly what kind of element
183  // we have -- simply because the other element declares
184  // that it is discontinuous because it has no DoFs on
185  // its faces. in that case, just state that we have no
186  // constraints to declare
187  return std::vector<std::pair<unsigned int, unsigned int> > ();
188  }
189  else
190  {
191  Assert (false, ExcNotImplemented());
192  return std::vector<std::pair<unsigned int, unsigned int> > ();
193  }
194 }
195 
196 
197 template <int dim, int spacedim>
198 std::vector<std::pair<unsigned int, unsigned int> >
200 {
201  // Since this fe is not interpolatory but on the vertices, we can
202  // not identify dofs on lines and on quads even if there are dofs
203  // on lines and on quads.
204  //
205  // we also have nothing to say about interpolation to other finite
206  // elements. consequently, we never have anything to say at all
207  return std::vector<std::pair<unsigned int, unsigned int> > ();
208 }
209 
210 
211 template <int dim, int spacedim>
212 std::vector<std::pair<unsigned int, unsigned int> >
214 {
215  // Since this fe is not interpolatory but on the vertices, we can
216  // not identify dofs on lines and on quads even if there are dofs
217  // on lines and on quads.
218  //
219  // we also have nothing to say about interpolation to other finite
220  // elements. consequently, we never have anything to say at all
221  return std::vector<std::pair<unsigned int, unsigned int> > ();
222 }
223 
224 
225 template <int dim, int spacedim>
228 {
229  if (const FE_Bernstein<dim,spacedim> *fe_b_other
230  = dynamic_cast<const FE_Bernstein<dim,spacedim>*>(&fe_other))
231  {
232  if (this->degree < fe_b_other->degree)
233  return FiniteElementDomination::this_element_dominates;
234  else if (this->degree == fe_b_other->degree)
235  return FiniteElementDomination::either_element_can_dominate;
236  else
237  return FiniteElementDomination::other_element_dominates;
238  }
239  else if (const FE_Nothing<dim> *fe_nothing = dynamic_cast<const FE_Nothing<dim>*>(&fe_other))
240  {
241  if (fe_nothing->is_dominating())
242  {
243  return FiniteElementDomination::other_element_dominates;
244  }
245  else
246  {
247  // the FE_Nothing has no degrees of freedom and it is typically used in
248  // a context where we don't require any continuity along the interface
249  return FiniteElementDomination::no_requirements;
250  }
251  }
252 
253  Assert (false, ExcNotImplemented());
254  return FiniteElementDomination::neither_element_dominates;
255 }
256 
257 
258 template <int dim, int spacedim>
259 std::string
261 {
262  // note that the FETools::get_fe_from_name function depends on the
263  // particular format of the string this function returns, so they have to be
264  // kept in synch
265 
266  std::ostringstream namebuf;
267  namebuf << "FE_Bernstein<" << dim << ">(" << this->degree << ")";
268  return namebuf.str();
269 }
270 
271 
272 template <int dim, int spacedim>
275 {
276  return new FE_Bernstein<dim,spacedim>(*this);
277 }
278 
279 
283 template <int dim, int spacedim>
284 std::vector<unsigned int>
286 {
287  AssertThrow(deg>0,ExcMessage("FE_Bernstein needs to be of degree > 0."));
288  std::vector<unsigned int> dpo(dim+1, 1U);
289  for (unsigned int i=1; i<dpo.size(); ++i)
290  dpo[i]=dpo[i-1]*(deg-1);
291  return dpo;
292 }
293 
294 
295 template <int dim, int spacedim>
298 {
299  TensorProductPolynomials<dim> tpp(::generate_complete_bernstein_basis<double>(deg));
300  std::vector<unsigned int> renumber(Utilities::fixed_power<dim>(deg+1));
301  const FiniteElementData<dim> fe(this->get_dpo_vector(deg),1,
302  deg);
304  tpp.set_numbering(renumber);
305  return tpp;
306 }
307 
308 
309 // explicit instantiations
310 #include "fe_bernstein.inst"
311 
312 DEAL_II_NAMESPACE_CLOSE
size_type m() const
static const unsigned int invalid_unsigned_int
Definition: types.h:164
FE_Bernstein(const unsigned int p)
Definition: fe_bernstein.cc:35
const std::vector< Point< dim-1 > > & get_unit_face_support_points() const
Definition: fe.cc:1018
virtual std::string get_name() const
::ExceptionBase & ExcMessage(std::string arg1)
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)
Definition: fe_tools.cc:1896
const unsigned int degree
Definition: fe_base.h:299
void set_numbering(const std::vector< unsigned int > &renumber)
STL namespace.
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
virtual bool hp_constraints_are_implemented() const
Definition: fe_q.h:522
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
Definition: fe_bernstein.cc:61
#define Assert(cond, exc)
Definition: exceptions.h:294
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 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
Definition: fe_q_base.cc:1001
virtual void get_face_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const
Definition: fe_bernstein.cc:49
virtual FiniteElementDomination::Domination compare_for_face_domination(const FiniteElement< dim, spacedim > &fe_other) const
TensorProductPolynomials< dim > renumber_bases(const unsigned int degree)
virtual FiniteElement< dim, spacedim > * clone() const
virtual double shape_value(const unsigned int i, const Point< dim > &p) const
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:276