Reference documentation for deal.II version 8.5.1
fe_q_dg0.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2012 - 2017 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/qprojector.h>
19 #include <deal.II/base/template_constraints.h>
20 #include <deal.II/fe/fe_q_dg0.h>
21 #include <deal.II/fe/fe_nothing.h>
22 #include <deal.II/base/quadrature_lib.h>
23 #include <deal.II/dofs/dof_accessor.h>
24 
25 
26 #include <vector>
27 #include <sstream>
28 
29 DEAL_II_NAMESPACE_OPEN
30 
31 
32 template <int dim, int spacedim>
33 FE_Q_DG0<dim,spacedim>::FE_Q_DG0 (const unsigned int degree)
34  :
35  FE_Q_Base<TensorProductPolynomialsConst<dim>, dim, spacedim> (
36  TensorProductPolynomialsConst<dim>(Polynomials::generate_complete_Lagrange_basis(QGaussLobatto<1>(degree+1).get_points())),
37  FiniteElementData<dim>(get_dpo_vector(degree),
38  1, degree,
39  FiniteElementData<dim>::L2),
40  get_riaf_vector(degree))
41 {
42  Assert (degree > 0,
43  ExcMessage ("This element can only be used for polynomial degrees "
44  "greater than zero"));
45 
46  this->initialize(QGaussLobatto<1>(degree+1).get_points());
47 
48  // adjust unit support point for discontinuous node
49  Point<dim> point;
50  for (unsigned int d=0; d<dim; ++d)
51  point[d] = 0.5;
52  this->unit_support_points.push_back(point);
54 }
55 
56 
57 
58 template <int dim, int spacedim>
60  :
61  FE_Q_Base<TensorProductPolynomialsConst<dim>, dim, spacedim> (
62  TensorProductPolynomialsConst<dim>(Polynomials::generate_complete_Lagrange_basis(points.get_points())),
63  FiniteElementData<dim>(get_dpo_vector(points.size()-1),
64  1, points.size()-1,
65  FiniteElementData<dim>::L2),
66  get_riaf_vector(points.size()-1))
67 {
68  const int degree = points.size()-1;
69  (void)degree;
70 
71  Assert (degree > 0,
72  ExcMessage ("This element can only be used for polynomial degrees "
73  "at least zero"));
74 
75  this->initialize(points.get_points());
76 
77  // adjust unit support point for discontinuous node
78  Point<dim> point;
79  for (unsigned int d=0; d<dim; ++d)
80  point[d] = 0.5;
81  this->unit_support_points.push_back(point);
83 }
84 
85 
86 
87 template <int dim, int spacedim>
88 std::string
90 {
91  // note that the FETools::get_fe_by_name function depends on the
92  // particular format of the string this function returns, so they have to be
93  // kept in synch
94 
95  std::ostringstream namebuf;
96  bool type = true;
97  const unsigned int n_points = this->degree +1;
98  std::vector<double> points(n_points);
99  const unsigned int dofs_per_cell = this->dofs_per_cell;
100  const std::vector<Point<dim> > &unit_support_points = this->unit_support_points;
101  unsigned int index = 0;
102 
103  // Decode the support points in one coordinate direction.
104  for (unsigned int j=0; j<dofs_per_cell; j++)
105  {
106  if ((dim>1) ? (unit_support_points[j](1)==0 &&
107  ((dim>2) ? unit_support_points[j](2)==0: true)) : true)
108  {
109  if (index == 0)
110  points[index] = unit_support_points[j](0);
111  else if (index == 1)
112  points[n_points-1] = unit_support_points[j](0);
113  else
114  points[index-1] = unit_support_points[j](0);
115 
116  index++;
117  }
118  }
119  // Do not consider the discontinuous node for dimension 1
120  Assert (index == n_points || (dim==1 && index == n_points+1),
121  ExcMessage ("Could not decode support points in one coordinate direction."));
122 
123  // Check whether the support points are equidistant.
124  for (unsigned int j=0; j<n_points; j++)
125  if (std::fabs(points[j] - (double)j/this->degree) > 1e-15)
126  {
127  type = false;
128  break;
129  }
130 
131  if (type == true)
132  {
133  if (this->degree > 2)
134  namebuf << "FE_Q_DG0<"
135  << Utilities::dim_string(dim,spacedim)
136  << ">(QIterated(QTrapez()," << this->degree << "))";
137  else
138  namebuf << "FE_Q_DG0<"
139  << Utilities::dim_string(dim,spacedim)
140  << ">(" << this->degree << ")";
141  }
142  else
143  {
144 
145  // Check whether the support points come from QGaussLobatto.
146  const QGaussLobatto<1> points_gl(n_points);
147  type = true;
148  for (unsigned int j=0; j<n_points; j++)
149  if (points[j] != points_gl.point(j)(0))
150  {
151  type = false;
152  break;
153  }
154  if (type == true)
155  namebuf << "FE_Q_DG0<"
156  << Utilities::dim_string(dim,spacedim)
157  << ">(" << this->degree << ")";
158  else
159  namebuf << "FE_Q_DG0<"
160  << Utilities::dim_string(dim,spacedim)
161  << ">(QUnknownNodes(" << this->degree << "))";
162  }
163  return namebuf.str();
164 }
165 
166 
167 
168 template <int dim, int spacedim>
171 {
172  return new FE_Q_DG0<dim,spacedim>(*this);
173 }
174 
175 
176 
177 template <int dim, int spacedim>
178 void
181  std::vector<double> &nodal_dofs) const
182 {
183  Assert (support_point_values.size() == this->unit_support_points.size(),
184  ExcDimensionMismatch(support_point_values.size(),
185  this->unit_support_points.size()));
186  Assert (nodal_dofs.size() == this->dofs_per_cell,
187  ExcDimensionMismatch(nodal_dofs.size(),this->dofs_per_cell));
188  Assert (support_point_values[0].size() == this->n_components(),
189  ExcDimensionMismatch(support_point_values[0].size(),this->n_components()));
190 
191  for (unsigned int i=0; i<this->dofs_per_cell-1; ++i)
192  {
193  const std::pair<unsigned int, unsigned int> index
194  = this->system_to_component_index(i);
195  nodal_dofs[i] = support_point_values[i](index.first);
196  }
197 
198  // We don't need the discontinuous function for local interpolation
199  nodal_dofs[nodal_dofs.size()-1] = 0.;
200 }
201 
202 
203 
204 template <int dim, int spacedim>
205 void
206 FE_Q_DG0<dim,spacedim>::interpolate(std::vector<double> &local_dofs,
207  const std::vector<double> &values) const
208 {
209  Assert (values.size() == this->unit_support_points.size(),
210  ExcDimensionMismatch(values.size(),
211  this->unit_support_points.size()));
212  Assert (local_dofs.size() == this->dofs_per_cell,
213  ExcDimensionMismatch(local_dofs.size(),this->dofs_per_cell));
214  Assert (this->n_components() == 1,
215  ExcDimensionMismatch(this->n_components(), 1));
216 
217  std::copy(values.begin(), values.end(), local_dofs.begin());
218 
219  // We don't need the discontinuous function for local interpolation
220  local_dofs[local_dofs.size()-1] = 0.;
221 }
222 
223 
224 
225 template <int dim, int spacedim>
226 void
227 FE_Q_DG0<dim,spacedim>::interpolate(std::vector<double> &local_dofs,
228  const std::vector<Vector<double> > &values,
229  const unsigned int offset) const
230 {
231  Assert (values.size() == this->unit_support_points.size(),
232  ExcDimensionMismatch(values.size(),
233  this->unit_support_points.size()));
234  Assert (local_dofs.size() == this->dofs_per_cell,
235  ExcDimensionMismatch(local_dofs.size(),this->dofs_per_cell));
236  Assert (values[0].size() >= offset+this->n_components(),
237  ExcDimensionMismatch(values[0].size(),offset+this->n_components()));
238 
239  for (unsigned int i=0; i<this->dofs_per_cell-1; ++i)
240  {
241  const std::pair<unsigned int, unsigned int> index
242  = this->system_to_component_index(i);
243  local_dofs[i] = values[i](offset+index.first);
244  }
245 
246  // We don't need the discontinuous function for local interpolation
247  local_dofs[local_dofs.size()-1] = 0.;
248 }
249 
250 
251 
252 template <int dim, int spacedim>
253 void
255  std::vector<double> &local_dofs,
256  const VectorSlice<const std::vector<std::vector<double> > > &values) const
257 {
258  Assert (values[0].size() == this->unit_support_points.size(),
259  ExcDimensionMismatch(values.size(),
260  this->unit_support_points.size()));
261  Assert (local_dofs.size() == this->dofs_per_cell,
262  ExcDimensionMismatch(local_dofs.size(),this->dofs_per_cell));
263  Assert (values.size() == this->n_components(),
264  ExcDimensionMismatch(values.size(), this->n_components()));
265 
266  for (unsigned int i=0; i<this->dofs_per_cell-1; ++i)
267  {
268  const std::pair<unsigned int, unsigned int> index
269  = this->system_to_component_index(i);
270  local_dofs[i] = values[index.first][i];
271  }
272 
273  // We don't need the discontinuous function for local interpolation
274  local_dofs[local_dofs.size()-1] = 0.;
275 }
276 
277 
278 
279 template <int dim, int spacedim>
280 void
283  FullMatrix<double> &interpolation_matrix) const
284 {
285  // this is only implemented, if the source FE is also a Q_DG0 element
286  typedef FE_Q_DG0<dim,spacedim> FEQDG0;
287  typedef FiniteElement<dim,spacedim> FEL;
288 
289  AssertThrow ((x_source_fe.get_name().find ("FE_Q_DG0<") == 0)
290  ||
291  (dynamic_cast<const FEQDG0 *>(&x_source_fe) != 0),
292  typename FEL::
293  ExcInterpolationNotImplemented());
294 
295  Assert (interpolation_matrix.m() == this->dofs_per_cell,
296  ExcDimensionMismatch (interpolation_matrix.m(),
297  this->dofs_per_cell));
298  Assert (interpolation_matrix.n() == x_source_fe.dofs_per_cell,
299  ExcDimensionMismatch (interpolation_matrix.m(),
300  x_source_fe.dofs_per_cell));
301 
303  get_interpolation_matrix(x_source_fe, interpolation_matrix);
304 }
305 
306 
307 
308 template <int dim, int spacedim>
309 std::vector<bool>
311 {
312  std::vector<bool> riaf(Utilities::fixed_power<dim>(deg+1)+1,false);
313  riaf[riaf.size()-1]=true;
314  return riaf;
315 }
316 
317 
318 
319 template <int dim, int spacedim>
320 std::vector<unsigned int>
322 {
323  std::vector<unsigned int> dpo(dim+1, 1U);
324  for (unsigned int i=1; i<dpo.size(); ++i)
325  dpo[i]=dpo[i-1]*(deg-1);
326 
327  dpo[dim]++;//we need an additional DG0-node for a dim-dimensional object
328  return dpo;
329 }
330 
331 
332 
333 template <int dim, int spacedim>
334 bool
335 FE_Q_DG0<dim,spacedim>::has_support_on_face (const unsigned int shape_index,
336  const unsigned int face_index) const
337 {
338  // discontinuous function has support on all faces
339  if (shape_index == this->dofs_per_cell-1)
340  return true;
341  else
342  return FE_Q_Base<TensorProductPolynomialsConst<dim>,dim,spacedim>::has_support_on_face(shape_index, face_index);
343 }
344 
345 
346 
347 template <int dim, int spacedim>
348 std::pair<Table<2,bool>, std::vector<unsigned int> >
350 {
351  Table<2,bool> constant_modes(2, this->dofs_per_cell);
352 
353  // 1 represented by FE_Q part
354  for (unsigned int i=0; i<this->dofs_per_cell-1; ++i)
355  constant_modes(0, i) = true;
356 
357  // 1 represented by DG0 part
358  constant_modes(1, this->dofs_per_cell-1) = true;
359 
360  return std::pair<Table<2,bool>, std::vector<unsigned int> >
361  (constant_modes, std::vector<unsigned int> (2, 0));
362 }
363 
364 
365 
366 // explicit instantiations
367 #include "fe_q_dg0.inst"
368 
369 DEAL_II_NAMESPACE_CLOSE
size_type m() const
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1146
const std::vector< Point< dim > > & get_points() const
const unsigned int degree
Definition: fe_base.h:311
const Point< dim > & point(const unsigned int i) const
#define AssertThrow(cond, exc)
Definition: exceptions.h:369
std::vector< Point< dim > > unit_support_points
Definition: fe.h:2223
virtual std::string get_name() const
Definition: fe_q_dg0.cc:89
virtual void interpolate(std::vector< double > &local_dofs, const std::vector< double > &values) const 1
Definition: fe_q_dg0.cc:206
static ::ExceptionBase & ExcMessage(std::string arg1)
size_type n() const
#define Assert(cond, exc)
Definition: exceptions.h:313
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const
Definition: fe_q_dg0.cc:335
virtual std::pair< Table< 2, bool >, std::vector< unsigned int > > get_constant_modes() const
Definition: fe_q_dg0.cc:349
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
virtual std::string get_name() const =0
std::string dim_string(const int dim, const int spacedim)
Definition: utilities.cc:161
unsigned int size() const
const unsigned int dofs_per_cell
Definition: fe_base.h:295
static std::vector< bool > get_riaf_vector(const unsigned int degree)
Definition: fe_q_dg0.cc:310
void initialize(const std::vector< Point< 1 > > &support_points_1d)
Definition: fe_q_base.cc:430
FE_Q_DG0(const unsigned int p)
Definition: fe_q_dg0.cc:33
virtual void get_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const
Definition: fe_q_dg0.cc:282
unsigned int n_components(const DoFHandler< dim, spacedim > &dh)
virtual void convert_generalized_support_point_values_to_nodal_values(const std::vector< Vector< double > > &support_point_values, std::vector< double > &nodal_values) const
Definition: fe_q_dg0.cc:180
virtual FiniteElement< dim, spacedim > * clone() const
Definition: fe_q_dg0.cc:170
static std::vector< unsigned int > get_dpo_vector(const unsigned int degree)
Definition: fe_q_dg0.cc:321