Reference documentation for deal.II version 9.1.0-pre
fe_dgp_monomial.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2004 - 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.md at
12 // the top level directory of deal.II.
13 //
14 // ---------------------------------------------------------------------
15 
16 
17 #include <deal.II/base/std_cxx14/memory.h>
18 
19 #include <deal.II/fe/fe_dgp_monomial.h>
20 #include <deal.II/fe/fe_tools.h>
21 
22 #include <sstream>
23 
24 
25 DEAL_II_NAMESPACE_OPEN
26 
27 namespace internal
28 {
29  namespace FE_DGPMonomial
30  {
31  namespace
32  {
33  // storage of hand-chosen support
34  // points
35  //
36  // For dim=2, dofs_per_cell of
37  // FE_DGPMonomial(k) is given by
38  // 0.5(k+1)(k+2), i.e.
39  //
40  // k 0 1 2 3 4 5 6 7
41  // dofs 1 3 6 10 15 21 28 36
42  //
43  // indirect access of unit points:
44  // the points for degree k are
45  // located at
46  //
47  // points[start_index[k]..start_index[k+1]-1]
48  const unsigned int start_index2d[6] = {0, 1, 4, 10, 20, 35};
49  const double points2d[35][2] = {
50  {0, 0}, {0, 0}, {1, 0}, {0, 1}, {0, 0},
51  {1, 0}, {0, 1}, {1, 1}, {0.5, 0}, {0, 0.5},
52  {0, 0}, {1, 0}, {0, 1}, {1, 1}, {1. / 3., 0},
53  {2. / 3., 0}, {0, 1. / 3.}, {0, 2. / 3.}, {0.5, 1}, {1, 0.5},
54  {0, 0}, {1, 0}, {0, 1}, {1, 1}, {0.25, 0},
55  {0.5, 0}, {0.75, 0}, {0, 0.25}, {0, 0.5}, {0, 0.75},
56  {1. / 3., 1}, {2. / 3., 1}, {1, 1. / 3.}, {1, 2. / 3.}, {0.5, 0.5}};
57 
58  // For dim=3, dofs_per_cell of
59  // FE_DGPMonomial(k) is given by
60  // 1./6.(k+1)(k+2)(k+3), i.e.
61  //
62  // k 0 1 2 3 4 5 6 7
63  // dofs 1 4 10 20 35 56 84 120
64  const unsigned int start_index3d[6] = {0, 1, 5, 15 /*,35*/};
65  const double points3d[35][3] = {{0, 0, 0},
66  {0, 0, 0},
67  {1, 0, 0},
68  {0, 1, 0},
69  {0, 0, 1},
70  {0, 0, 0},
71  {1, 0, 0},
72  {0, 1, 0},
73  {0, 0, 1},
74  {0.5, 0, 0},
75  {0, 0.5, 0},
76  {0, 0, 0.5},
77  {1, 1, 0},
78  {1, 0, 1},
79  {0, 1, 1}};
80 
81 
82  template <int dim>
83  void
84  generate_unit_points(const unsigned int, std::vector<Point<dim>> &);
85 
86  template <>
87  void
88  generate_unit_points(const unsigned int k, std::vector<Point<1>> &p)
89  {
90  Assert(p.size() == k + 1, ExcDimensionMismatch(p.size(), k + 1));
91  const double h = 1. / k;
92  for (unsigned int i = 0; i < p.size(); ++i)
93  p[i](0) = i * h;
94  }
95 
96  template <>
97  void
98  generate_unit_points(const unsigned int k, std::vector<Point<2>> &p)
99  {
100  Assert(k <= 4, ExcNotImplemented());
101  Assert(p.size() == start_index2d[k + 1] - start_index2d[k],
102  ExcInternalError());
103  for (unsigned int i = 0; i < p.size(); ++i)
104  {
105  p[i](0) = points2d[start_index2d[k] + i][0];
106  p[i](1) = points2d[start_index2d[k] + i][1];
107  }
108  }
109 
110  template <>
111  void
112  generate_unit_points(const unsigned int k, std::vector<Point<3>> &p)
113  {
114  Assert(k <= 2, ExcNotImplemented());
115  Assert(p.size() == start_index3d[k + 1] - start_index3d[k],
116  ExcInternalError());
117  for (unsigned int i = 0; i < p.size(); ++i)
118  {
119  p[i](0) = points3d[start_index3d[k] + i][0];
120  p[i](1) = points3d[start_index3d[k] + i][1];
121  p[i](2) = points3d[start_index3d[k] + i][2];
122  }
123  }
124  } // namespace
125  } // namespace FE_DGPMonomial
126 } // namespace internal
127 
128 
129 
130 template <int dim>
131 FE_DGPMonomial<dim>::FE_DGPMonomial(const unsigned int degree)
132  : FE_Poly<PolynomialsP<dim>, dim>(
133  PolynomialsP<dim>(degree),
134  FiniteElementData<dim>(get_dpo_vector(degree),
135  1,
136  degree,
137  FiniteElementData<dim>::L2),
138  std::vector<bool>(
139  FiniteElementData<dim>(get_dpo_vector(degree), 1, degree).dofs_per_cell,
140  true),
141  std::vector<ComponentMask>(
142  FiniteElementData<dim>(get_dpo_vector(degree), 1, degree).dofs_per_cell,
143  std::vector<bool>(1, true)))
144 {
145  Assert(this->poly_space.n() == this->dofs_per_cell, ExcInternalError());
146  Assert(this->poly_space.degree() == this->degree, ExcInternalError());
147 
148  // DG doesn't have constraints, so
149  // leave them empty
150 
151  // Reinit the vectors of
152  // restriction and prolongation
153  // matrices to the right sizes
155  // Fill prolongation matrices with embedding operators
157  // Fill restriction matrices with L2-projection
159 }
160 
161 
162 
163 template <int dim>
164 std::string
166 {
167  // note that the
168  // FETools::get_fe_by_name
169  // function depends on the
170  // particular format of the string
171  // this function returns, so they
172  // have to be kept in synch
173 
174  std::ostringstream namebuf;
175  namebuf << "FE_DGPMonomial<" << dim << ">(" << this->degree << ")";
176 
177  return namebuf.str();
178 }
179 
180 
181 
182 template <int dim>
183 std::unique_ptr<FiniteElement<dim, dim>>
185 {
186  return std_cxx14::make_unique<FE_DGPMonomial<dim>>(*this);
187 }
188 
189 
190 
191 // TODO: Remove this function and use the one in FETools, if needed
192 template <int dim>
193 void
195  const FiniteElement<dim> &source_fe,
196  FullMatrix<double> & interpolation_matrix) const
197 {
198  const FE_DGPMonomial<dim> *source_dgp_monomial =
199  dynamic_cast<const FE_DGPMonomial<dim> *>(&source_fe);
200 
201  if (source_dgp_monomial)
202  {
203  // ok, source_fe is a DGP_Monomial
204  // element. Then, the interpolation
205  // matrix is simple
206  const unsigned int m = interpolation_matrix.m();
207  const unsigned int n = interpolation_matrix.n();
208  (void)m;
209  (void)n;
210  Assert(m == this->dofs_per_cell,
212  Assert(n == source_dgp_monomial->dofs_per_cell,
213  ExcDimensionMismatch(n, source_dgp_monomial->dofs_per_cell));
214 
215  const unsigned int min_mn =
216  interpolation_matrix.m() < interpolation_matrix.n() ?
217  interpolation_matrix.m() :
218  interpolation_matrix.n();
219 
220  for (unsigned int i = 0; i < min_mn; ++i)
221  interpolation_matrix(i, i) = 1.;
222  }
223  else
224  {
225  std::vector<Point<dim>> unit_points(this->dofs_per_cell);
226  internal::FE_DGPMonomial::generate_unit_points(this->degree, unit_points);
227 
228  FullMatrix<double> source_fe_matrix(unit_points.size(),
229  source_fe.dofs_per_cell);
230  for (unsigned int j = 0; j < source_fe.dofs_per_cell; ++j)
231  for (unsigned int k = 0; k < unit_points.size(); ++k)
232  source_fe_matrix(k, j) = source_fe.shape_value(j, unit_points[k]);
233 
234  FullMatrix<double> this_matrix(this->dofs_per_cell, this->dofs_per_cell);
235  for (unsigned int j = 0; j < this->dofs_per_cell; ++j)
236  for (unsigned int k = 0; k < unit_points.size(); ++k)
237  this_matrix(k, j) = this->poly_space.compute_value(j, unit_points[k]);
238 
239  this_matrix.gauss_jordan();
240 
241  this_matrix.mmult(interpolation_matrix, source_fe_matrix);
242  }
243 }
244 
245 
246 
247 template <int dim>
248 void
250 {
251  Assert(false, ExcNotImplemented());
252 }
253 
254 
255 //---------------------------------------------------------------------------
256 // Auxiliary functions
257 //---------------------------------------------------------------------------
258 
259 
260 template <int dim>
261 std::vector<unsigned int>
262 FE_DGPMonomial<dim>::get_dpo_vector(const unsigned int deg)
263 {
264  std::vector<unsigned int> dpo(dim + 1, 0U);
265  dpo[dim] = deg + 1;
266  for (unsigned int i = 1; i < dim; ++i)
267  {
268  dpo[dim] *= deg + 1 + i;
269  dpo[dim] /= i + 1;
270  }
271  return dpo;
272 }
273 
274 
275 template <int dim>
276 void
278  const FiniteElement<dim> &x_source_fe,
279  FullMatrix<double> & interpolation_matrix) const
280 {
281  // this is only implemented, if the source
282  // FE is also a DGPMonomial element. in that case,
283  // both elements have no dofs on their
284  // faces and the face interpolation matrix
285  // is necessarily empty -- i.e. there isn't
286  // much we need to do here.
287  (void)interpolation_matrix;
288  AssertThrow((x_source_fe.get_name().find("FE_DGPMonomial<") == 0) ||
289  (dynamic_cast<const FE_DGPMonomial<dim> *>(&x_source_fe) !=
290  nullptr),
292 
293  Assert(interpolation_matrix.m() == 0,
294  ExcDimensionMismatch(interpolation_matrix.m(), 0));
295  Assert(interpolation_matrix.n() == 0,
296  ExcDimensionMismatch(interpolation_matrix.n(), 0));
297 }
298 
299 
300 
301 template <int dim>
302 void
304  const FiniteElement<dim> &x_source_fe,
305  const unsigned int,
306  FullMatrix<double> &interpolation_matrix) const
307 {
308  // this is only implemented, if the source
309  // FE is also a DGPMonomial element. in that case,
310  // both elements have no dofs on their
311  // faces and the face interpolation matrix
312  // is necessarily empty -- i.e. there isn't
313  // much we need to do here.
314  (void)interpolation_matrix;
315  AssertThrow((x_source_fe.get_name().find("FE_DGPMonomial<") == 0) ||
316  (dynamic_cast<const FE_DGPMonomial<dim> *>(&x_source_fe) !=
317  nullptr),
319 
320  Assert(interpolation_matrix.m() == 0,
321  ExcDimensionMismatch(interpolation_matrix.m(), 0));
322  Assert(interpolation_matrix.n() == 0,
323  ExcDimensionMismatch(interpolation_matrix.n(), 0));
324 }
325 
326 
327 
328 template <int dim>
329 bool
331 {
332  return true;
333 }
334 
335 
336 
337 template <int dim>
338 std::vector<std::pair<unsigned int, unsigned int>>
340  const FiniteElement<dim> &fe_other) const
341 {
342  // there are no such constraints for DGPMonomial
343  // elements at all
344  if (dynamic_cast<const FE_DGPMonomial<dim> *>(&fe_other) != nullptr)
345  return std::vector<std::pair<unsigned int, unsigned int>>();
346  else
347  {
348  Assert(false, ExcNotImplemented());
349  return std::vector<std::pair<unsigned int, unsigned int>>();
350  }
351 }
352 
353 
354 
355 template <int dim>
356 std::vector<std::pair<unsigned int, unsigned int>>
358  const FiniteElement<dim> &fe_other) const
359 {
360  // there are no such constraints for DGPMonomial
361  // elements at all
362  if (dynamic_cast<const FE_DGPMonomial<dim> *>(&fe_other) != nullptr)
363  return std::vector<std::pair<unsigned int, unsigned int>>();
364  else
365  {
366  Assert(false, ExcNotImplemented());
367  return std::vector<std::pair<unsigned int, unsigned int>>();
368  }
369 }
370 
371 
372 
373 template <int dim>
374 std::vector<std::pair<unsigned int, unsigned int>>
376  const FiniteElement<dim> &fe_other) const
377 {
378  // there are no such constraints for DGPMonomial
379  // elements at all
380  if (dynamic_cast<const FE_DGPMonomial<dim> *>(&fe_other) != nullptr)
381  return std::vector<std::pair<unsigned int, unsigned int>>();
382  else
383  {
384  Assert(false, ExcNotImplemented());
385  return std::vector<std::pair<unsigned int, unsigned int>>();
386  }
387 }
388 
389 
390 
391 template <int dim>
394  const FiniteElement<dim> &fe_other) const
395 {
396  // check whether both are discontinuous
397  // elements, see
398  // the description of
399  // FiniteElementDomination::Domination
400  if (dynamic_cast<const FE_DGPMonomial<dim> *>(&fe_other) != nullptr)
402 
403  Assert(false, ExcNotImplemented());
405 }
406 
407 
408 
409 template <>
410 bool
412  const unsigned int face_index) const
413 {
414  return face_index == 1 || (face_index == 0 && this->degree == 0);
415 }
416 
417 
418 
419 template <>
420 bool
421 FE_DGPMonomial<2>::has_support_on_face(const unsigned int shape_index,
422  const unsigned int face_index) const
423 {
424  bool support_on_face = false;
425  if (face_index == 1 || face_index == 2)
426  support_on_face = true;
427  else
428  {
429  const std::array<unsigned int, 2> degrees =
430  this->poly_space.directional_degrees(shape_index);
431 
432  if ((face_index == 0 && degrees[1] == 0) ||
433  (face_index == 3 && degrees[0] == 0))
434  support_on_face = true;
435  }
436  return support_on_face;
437 }
438 
439 
440 
441 template <>
442 bool
443 FE_DGPMonomial<3>::has_support_on_face(const unsigned int shape_index,
444  const unsigned int face_index) const
445 {
446  bool support_on_face = false;
447  if (face_index == 1 || face_index == 3 || face_index == 4)
448  support_on_face = true;
449  else
450  {
451  const std::array<unsigned int, 3> degrees =
452  this->poly_space.directional_degrees(shape_index);
453 
454  if ((face_index == 0 && degrees[1] == 0) ||
455  (face_index == 2 && degrees[2] == 0) ||
456  (face_index == 5 && degrees[0] == 0))
457  support_on_face = true;
458  }
459  return support_on_face;
460 }
461 
462 
463 
464 template <int dim>
465 std::size_t
467 {
468  Assert(false, ExcNotImplemented());
469  return 0;
470 }
471 
472 
473 
474 // explicit instantiations
475 #include "fe_dgp_monomial.inst"
476 
477 
478 DEAL_II_NAMESPACE_CLOSE
virtual double shape_value(const unsigned int i, const Point< dim > &p) const
Definition: fe.cc:159
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_quad_dof_identities(const FiniteElement< dim > &fe_other) const override
static std::vector< unsigned int > get_dpo_vector(const unsigned int degree)
virtual void get_subface_interpolation_matrix(const FiniteElement< dim > &source, const unsigned int subface, FullMatrix< double > &matrix) const override
std::vector< std::vector< FullMatrix< double > > > restriction
Definition: fe.h:2419
virtual FiniteElementDomination::Domination compare_for_face_domination(const FiniteElement< dim > &fe_other) const override
FE_DGPMonomial(const unsigned int p)
void compute_embedding_matrices(const FiniteElement< dim, spacedim > &fe, std::vector< std::vector< FullMatrix< number >>> &matrices, const bool isotropic_only=false, const double threshold=1.e-12)
void gauss_jordan()
const unsigned int degree
Definition: fe_base.h:313
virtual std::size_t memory_consumption() const override
STL namespace.
virtual void get_face_interpolation_matrix(const FiniteElement< dim > &source, FullMatrix< double > &matrix) const override
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim > &fe_other) const override
virtual void get_interpolation_matrix(const FiniteElement< dim > &source, FullMatrix< double > &matrix) const override
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const override
void initialize_restriction()
void compute_projection_matrices(const FiniteElement< dim, spacedim > &fe, std::vector< std::vector< FullMatrix< number >>> &matrices, const bool isotropic_only=false)
size_type n() const
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)
virtual std::string get_name() const =0
void mmult(FullMatrix< number2 > &C, const FullMatrix< number2 > &B, const bool adding=false) const
size_type m() const
const unsigned int dofs_per_cell
Definition: fe_base.h:297
virtual bool hp_constraints_are_implemented() const override
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim > &fe_other) const override
void reinit_restriction_and_prolongation_matrices(const bool isotropic_restriction_only=false, const bool isotropic_prolongation_only=false)
static::ExceptionBase & ExcNotImplemented()
PolynomialsP< dim > poly_space
Definition: fe_poly.h:480
virtual std::string get_name() const override
virtual std::unique_ptr< FiniteElement< dim, dim > > clone() const override
static::ExceptionBase & ExcInternalError()