Reference documentation for deal.II version 9.1.0-pre
fe_dgq.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2001 - 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/quadrature.h>
18 #include <deal.II/base/quadrature_lib.h>
19 #include <deal.II/base/std_cxx14/memory.h>
20 
21 #include <deal.II/fe/fe.h>
22 #include <deal.II/fe/fe_dgq.h>
23 #include <deal.II/fe/fe_tools.h>
24 
25 #include <deal.II/lac/vector.h>
26 
27 #include <iostream>
28 #include <sstream>
29 
30 
31 DEAL_II_NAMESPACE_OPEN
32 
33 
34 namespace internal
35 {
36  namespace FE_DGQ
37  {
38  namespace
39  {
40  std::vector<Point<1>>
41  get_QGaussLobatto_points(const unsigned int degree)
42  {
43  if (degree > 0)
44  return QGaussLobatto<1>(degree + 1).get_points();
45  else
46  return std::vector<Point<1>>(1, Point<1>(0.5));
47  }
48  } // namespace
49  } // namespace FE_DGQ
50 } // namespace internal
51 
52 
53 
54 template <int dim, int spacedim>
55 FE_DGQ<dim, spacedim>::FE_DGQ(const unsigned int degree)
56  : FE_Poly<TensorProductPolynomials<dim>, dim, spacedim>(
58  Polynomials::generate_complete_Lagrange_basis(
59  internal::FE_DGQ::get_QGaussLobatto_points(degree))),
60  FiniteElementData<dim>(get_dpo_vector(degree),
61  1,
62  degree,
63  FiniteElementData<dim>::L2),
64  std::vector<bool>(
65  FiniteElementData<dim>(get_dpo_vector(degree), 1, degree).dofs_per_cell,
66  true),
67  std::vector<ComponentMask>(
68  FiniteElementData<dim>(get_dpo_vector(degree), 1, degree).dofs_per_cell,
69  std::vector<bool>(1, true)))
70 {
71  // Compute support points, which are the tensor product of the Lagrange
72  // interpolation points in the constructor.
73  this->unit_support_points =
74  Quadrature<dim>(internal::FE_DGQ::get_QGaussLobatto_points(degree))
75  .get_points();
76 
77  // do not initialize embedding and restriction here. these matrices are
78  // initialized on demand in get_restriction_matrix and
79  // get_prolongation_matrix
80 
81  // note: no face support points for DG elements
82 }
83 
84 
85 
86 template <int dim, int spacedim>
88  const std::vector<Polynomials::Polynomial<double>> &polynomials)
89  : FE_Poly<TensorProductPolynomials<dim>, dim, spacedim>(
90  TensorProductPolynomials<dim>(polynomials),
91  FiniteElementData<dim>(get_dpo_vector(polynomials.size() - 1),
92  1,
93  polynomials.size() - 1,
94  FiniteElementData<dim>::L2),
95  std::vector<bool>(FiniteElementData<dim>(get_dpo_vector(
96  polynomials.size() - 1),
97  1,
98  polynomials.size() - 1)
100  true),
101  std::vector<ComponentMask>(
102  FiniteElementData<dim>(get_dpo_vector(polynomials.size() - 1),
103  1,
104  polynomials.size() - 1)
105  .dofs_per_cell,
106  std::vector<bool>(1, true)))
107 {
108  // No support points can be defined in general. Derived classes might define
109  // support points like the class FE_DGQArbitraryNodes
110 
111  // do not initialize embedding and restriction here. these matrices are
112  // initialized on demand in get_restriction_matrix and
113  // get_prolongation_matrix
114 }
115 
116 
117 
118 template <int dim, int spacedim>
119 std::string
121 {
122  // note that the FETools::get_fe_by_name function depends on the
123  // particular format of the string this function returns, so they have to be
124  // kept in sync
125 
126  std::ostringstream namebuf;
127  namebuf << "FE_DGQ<" << Utilities::dim_string(dim, spacedim) << ">("
128  << this->degree << ")";
129  return namebuf.str();
130 }
131 
132 
133 
134 template <int dim, int spacedim>
135 void
137  const std::vector<Vector<double>> &support_point_values,
138  std::vector<double> & nodal_values) const
139 {
140  AssertDimension(support_point_values.size(),
141  this->get_unit_support_points().size());
142  AssertDimension(support_point_values.size(), nodal_values.size());
143  AssertDimension(this->dofs_per_cell, nodal_values.size());
144 
145  for (unsigned int i = 0; i < this->dofs_per_cell; ++i)
146  {
147  AssertDimension(support_point_values[i].size(), 1);
148 
149  nodal_values[i] = support_point_values[i](0);
150  }
151 }
152 
153 
154 
155 template <int dim, int spacedim>
156 std::unique_ptr<FiniteElement<dim, spacedim>>
158 {
159  return std_cxx14::make_unique<FE_DGQ<dim, spacedim>>(*this);
160 }
161 
162 
163 //---------------------------------------------------------------------------
164 // Auxiliary functions
165 //---------------------------------------------------------------------------
166 
167 
168 template <int dim, int spacedim>
169 std::vector<unsigned int>
171 {
172  std::vector<unsigned int> dpo(dim + 1, 0U);
173  dpo[dim] = deg + 1;
174  for (unsigned int i = 1; i < dim; ++i)
175  dpo[dim] *= deg + 1;
176  return dpo;
177 }
178 
179 
180 
181 template <int dim, int spacedim>
182 void
184  const char direction) const
185 {
186  const unsigned int n = this->degree + 1;
187  unsigned int s = n;
188  for (unsigned int i = 1; i < dim; ++i)
189  s *= n;
190  numbers.resize(s);
191 
192  unsigned int l = 0;
193 
194  if (dim == 1)
195  {
196  // Mirror around midpoint
197  for (unsigned int i = n; i > 0;)
198  numbers[l++] = --i;
199  }
200  else
201  {
202  switch (direction)
203  {
204  // Rotate xy-plane
205  // counter-clockwise
206  case 'z':
207  for (unsigned int iz = 0; iz < ((dim > 2) ? n : 1); ++iz)
208  for (unsigned int j = 0; j < n; ++j)
209  for (unsigned int i = 0; i < n; ++i)
210  {
211  unsigned int k = n * i - j + n - 1 + n * n * iz;
212  numbers[l++] = k;
213  }
214  break;
215  // Rotate xy-plane
216  // clockwise
217  case 'Z':
218  for (unsigned int iz = 0; iz < ((dim > 2) ? n : 1); ++iz)
219  for (unsigned int iy = 0; iy < n; ++iy)
220  for (unsigned int ix = 0; ix < n; ++ix)
221  {
222  unsigned int k = n * ix - iy + n - 1 + n * n * iz;
223  numbers[k] = l++;
224  }
225  break;
226  // Rotate yz-plane
227  // counter-clockwise
228  case 'x':
229  Assert(dim > 2, ExcDimensionMismatch(dim, 3));
230  for (unsigned int iz = 0; iz < n; ++iz)
231  for (unsigned int iy = 0; iy < n; ++iy)
232  for (unsigned int ix = 0; ix < n; ++ix)
233  {
234  unsigned int k = n * (n * iy - iz + n - 1) + ix;
235  numbers[l++] = k;
236  }
237  break;
238  // Rotate yz-plane
239  // clockwise
240  case 'X':
241  Assert(dim > 2, ExcDimensionMismatch(dim, 3));
242  for (unsigned int iz = 0; iz < n; ++iz)
243  for (unsigned int iy = 0; iy < n; ++iy)
244  for (unsigned int ix = 0; ix < n; ++ix)
245  {
246  unsigned int k = n * (n * iy - iz + n - 1) + ix;
247  numbers[k] = l++;
248  }
249  break;
250  default:
251  Assert(false, ExcNotImplemented());
252  }
253  }
254 }
255 
256 
257 
258 template <int dim, int spacedim>
259 void
261  const FiniteElement<dim, spacedim> &x_source_fe,
262  FullMatrix<double> & interpolation_matrix) const
263 {
264  // this is only implemented, if the
265  // source FE is also a
266  // DGQ element
267  using FE = FiniteElement<dim, spacedim>;
268  AssertThrow((dynamic_cast<const FE_DGQ<dim, spacedim> *>(&x_source_fe) !=
269  nullptr),
270  typename FE::ExcInterpolationNotImplemented());
271 
272  // ok, source is a Q element, so
273  // we will be able to do the work
274  const FE_DGQ<dim, spacedim> &source_fe =
275  dynamic_cast<const FE_DGQ<dim, spacedim> &>(x_source_fe);
276 
277  Assert(interpolation_matrix.m() == this->dofs_per_cell,
278  ExcDimensionMismatch(interpolation_matrix.m(), this->dofs_per_cell));
279  Assert(interpolation_matrix.n() == source_fe.dofs_per_cell,
280  ExcDimensionMismatch(interpolation_matrix.n(),
281  source_fe.dofs_per_cell));
282 
283 
284  // compute the interpolation
285  // matrices in much the same way as
286  // we do for the embedding matrices
287  // from mother to child.
288  FullMatrix<double> cell_interpolation(this->dofs_per_cell,
289  this->dofs_per_cell);
290  FullMatrix<double> source_interpolation(this->dofs_per_cell,
291  source_fe.dofs_per_cell);
292  FullMatrix<double> tmp(this->dofs_per_cell, source_fe.dofs_per_cell);
293  for (unsigned int j = 0; j < this->dofs_per_cell; ++j)
294  {
295  // generate a point on this
296  // cell and evaluate the
297  // shape functions there
298  const Point<dim> p = this->unit_support_points[j];
299  for (unsigned int i = 0; i < this->dofs_per_cell; ++i)
300  cell_interpolation(j, i) = this->poly_space.compute_value(i, p);
301 
302  for (unsigned int i = 0; i < source_fe.dofs_per_cell; ++i)
303  source_interpolation(j, i) = source_fe.poly_space.compute_value(i, p);
304  }
305 
306  // then compute the
307  // interpolation matrix matrix
308  // for this coordinate
309  // direction
310  cell_interpolation.gauss_jordan();
311  cell_interpolation.mmult(interpolation_matrix, source_interpolation);
312 
313  // cut off very small values
314  for (unsigned int i = 0; i < this->dofs_per_cell; ++i)
315  for (unsigned int j = 0; j < source_fe.dofs_per_cell; ++j)
316  if (std::fabs(interpolation_matrix(i, j)) < 1e-15)
317  interpolation_matrix(i, j) = 0.;
318 
319  // make sure that the row sum of
320  // each of the matrices is 1 at
321  // this point. this must be so
322  // since the shape functions sum up
323  // to 1
324  for (unsigned int i = 0; i < this->dofs_per_cell; ++i)
325  {
326  double sum = 0.;
327  for (unsigned int j = 0; j < source_fe.dofs_per_cell; ++j)
328  sum += interpolation_matrix(i, j);
329 
330  Assert(std::fabs(sum - 1) < 5e-14 * std::max(this->degree, 1U) * dim,
331  ExcInternalError());
332  }
333 }
334 
335 
336 
337 template <int dim, int spacedim>
338 void
340  const FiniteElement<dim, spacedim> &x_source_fe,
341  FullMatrix<double> & interpolation_matrix) const
342 {
343  // this is only implemented, if the source
344  // FE is also a DGQ element. in that case,
345  // both elements have no dofs on their
346  // faces and the face interpolation matrix
347  // is necessarily empty -- i.e. there isn't
348  // much we need to do here.
349  (void)interpolation_matrix;
350  using FE = FiniteElement<dim, spacedim>;
351  AssertThrow((dynamic_cast<const FE_DGQ<dim, spacedim> *>(&x_source_fe) !=
352  nullptr),
353  typename FE::ExcInterpolationNotImplemented());
354 
355  Assert(interpolation_matrix.m() == 0,
356  ExcDimensionMismatch(interpolation_matrix.m(), 0));
357  Assert(interpolation_matrix.n() == 0,
358  ExcDimensionMismatch(interpolation_matrix.m(), 0));
359 }
360 
361 
362 
363 template <int dim, int spacedim>
364 void
366  const FiniteElement<dim, spacedim> &x_source_fe,
367  const unsigned int,
368  FullMatrix<double> &interpolation_matrix) const
369 {
370  // this is only implemented, if the source
371  // FE is also a DGQ element. in that case,
372  // both elements have no dofs on their
373  // faces and the face interpolation matrix
374  // is necessarily empty -- i.e. there isn't
375  // much we need to do here.
376  (void)interpolation_matrix;
377  using FE = FiniteElement<dim, spacedim>;
378  AssertThrow((dynamic_cast<const FE_DGQ<dim, spacedim> *>(&x_source_fe) !=
379  nullptr),
380  typename FE::ExcInterpolationNotImplemented());
381 
382  Assert(interpolation_matrix.m() == 0,
383  ExcDimensionMismatch(interpolation_matrix.m(), 0));
384  Assert(interpolation_matrix.n() == 0,
385  ExcDimensionMismatch(interpolation_matrix.m(), 0));
386 }
387 
388 
389 
390 template <int dim, int spacedim>
391 const FullMatrix<double> &
393  const unsigned int child,
394  const RefinementCase<dim> &refinement_case) const
395 {
397  ExcIndexRange(refinement_case,
398  0,
400  Assert(refinement_case != RefinementCase<dim>::no_refinement,
401  ExcMessage(
402  "Prolongation matrices are only available for refined cells!"));
403  Assert(child < GeometryInfo<dim>::n_children(refinement_case),
404  ExcIndexRange(child,
405  0,
406  GeometryInfo<dim>::n_children(refinement_case)));
407 
408  // initialization upon first request
409  if (this->prolongation[refinement_case - 1][child].n() == 0)
410  {
411  Threads::Mutex::ScopedLock lock(this->mutex);
412 
413  // if matrix got updated while waiting for the lock
414  if (this->prolongation[refinement_case - 1][child].n() ==
415  this->dofs_per_cell)
416  return this->prolongation[refinement_case - 1][child];
417 
418  // now do the work. need to get a non-const version of data in order to
419  // be able to modify them inside a const function
420  FE_DGQ<dim, spacedim> &this_nonconst =
421  const_cast<FE_DGQ<dim, spacedim> &>(*this);
422  if (refinement_case == RefinementCase<dim>::isotropic_refinement)
423  {
424  std::vector<std::vector<FullMatrix<double>>> isotropic_matrices(
426  isotropic_matrices.back().resize(
429  if (dim == spacedim)
431  isotropic_matrices,
432  true);
433  else
435  isotropic_matrices,
436  true);
437  this_nonconst.prolongation[refinement_case - 1].swap(
438  isotropic_matrices.back());
439  }
440  else
441  {
442  // must compute both restriction and prolongation matrices because
443  // we only check for their size and the reinit call initializes them
444  // all
446  if (dim == spacedim)
447  {
449  this_nonconst.prolongation);
451  this_nonconst.restriction);
452  }
453  else
454  {
455  FE_DGQ<dim> tmp(this->degree);
457  this_nonconst.prolongation);
459  this_nonconst.restriction);
460  }
461  }
462  }
463 
464  // finally return the matrix
465  return this->prolongation[refinement_case - 1][child];
466 }
467 
468 
469 
470 template <int dim, int spacedim>
471 const FullMatrix<double> &
473  const unsigned int child,
474  const RefinementCase<dim> &refinement_case) const
475 {
477  ExcIndexRange(refinement_case,
478  0,
480  Assert(refinement_case != RefinementCase<dim>::no_refinement,
481  ExcMessage(
482  "Restriction matrices are only available for refined cells!"));
483  Assert(child < GeometryInfo<dim>::n_children(refinement_case),
484  ExcIndexRange(child,
485  0,
486  GeometryInfo<dim>::n_children(refinement_case)));
487 
488  // initialization upon first request
489  if (this->restriction[refinement_case - 1][child].n() == 0)
490  {
491  Threads::Mutex::ScopedLock lock(this->mutex);
492 
493  // if matrix got updated while waiting for the lock...
494  if (this->restriction[refinement_case - 1][child].n() ==
495  this->dofs_per_cell)
496  return this->restriction[refinement_case - 1][child];
497 
498  // now do the work. need to get a non-const version of data in order to
499  // be able to modify them inside a const function
500  FE_DGQ<dim, spacedim> &this_nonconst =
501  const_cast<FE_DGQ<dim, spacedim> &>(*this);
502  if (refinement_case == RefinementCase<dim>::isotropic_refinement)
503  {
504  std::vector<std::vector<FullMatrix<double>>> isotropic_matrices(
506  isotropic_matrices.back().resize(
509  if (dim == spacedim)
511  isotropic_matrices,
512  true);
513  else
515  isotropic_matrices,
516  true);
517  this_nonconst.restriction[refinement_case - 1].swap(
518  isotropic_matrices.back());
519  }
520  else
521  {
522  // must compute both restriction and prolongation matrices because
523  // we only check for their size and the reinit call initializes them
524  // all
526  if (dim == spacedim)
527  {
529  this_nonconst.prolongation);
531  this_nonconst.restriction);
532  }
533  else
534  {
535  FE_DGQ<dim> tmp(this->degree);
537  this_nonconst.prolongation);
539  this_nonconst.restriction);
540  }
541  }
542  }
543 
544  // finally return the matrix
545  return this->restriction[refinement_case - 1][child];
546 }
547 
548 
549 
550 template <int dim, int spacedim>
551 bool
553 {
554  return true;
555 }
556 
557 
558 
559 template <int dim, int spacedim>
560 std::vector<std::pair<unsigned int, unsigned int>>
562  const FiniteElement<dim, spacedim> & /*fe_other*/) const
563 {
564  // this element is discontinuous, so by definition there can
565  // be no identities between its dofs and those of any neighbor
566  // (of whichever type the neighbor may be -- after all, we have
567  // no face dofs on this side to begin with)
568  return std::vector<std::pair<unsigned int, unsigned int>>();
569 }
570 
571 
572 
573 template <int dim, int spacedim>
574 std::vector<std::pair<unsigned int, unsigned int>>
576  const FiniteElement<dim, spacedim> & /*fe_other*/) const
577 {
578  // this element is discontinuous, so by definition there can
579  // be no identities between its dofs and those of any neighbor
580  // (of whichever type the neighbor may be -- after all, we have
581  // no face dofs on this side to begin with)
582  return std::vector<std::pair<unsigned int, unsigned int>>();
583 }
584 
585 
586 
587 template <int dim, int spacedim>
588 std::vector<std::pair<unsigned int, unsigned int>>
590  const FiniteElement<dim, spacedim> & /*fe_other*/) const
591 {
592  // this element is discontinuous, so by definition there can
593  // be no identities between its dofs and those of any neighbor
594  // (of whichever type the neighbor may be -- after all, we have
595  // no face dofs on this side to begin with)
596  return std::vector<std::pair<unsigned int, unsigned int>>();
597 }
598 
599 
600 
601 template <int dim, int spacedim>
604  const FiniteElement<dim, spacedim> & /*fe_other*/) const
605 {
606  // this is a discontinuous element, so by definition there will
607  // be no constraints wherever this element comes together with
608  // any other kind of element
610 }
611 
612 
613 
614 template <int dim, int spacedim>
615 bool
616 FE_DGQ<dim, spacedim>::has_support_on_face(const unsigned int shape_index,
617  const unsigned int face_index) const
618 {
619  Assert(shape_index < this->dofs_per_cell,
620  ExcIndexRange(shape_index, 0, this->dofs_per_cell));
623 
624  unsigned int n = this->degree + 1;
625 
626  // For DGQ elements that do not define support points, we cannot define
627  // whether they have support at the boundary easily, so return true in any
628  // case
629  if (this->unit_support_points.empty())
630  return true;
631 
632  // for DGQ(0) elements or arbitrary node DGQ with support points not located
633  // at the element boundary, the single shape functions is constant and
634  // therefore lives on the boundary
635  bool support_points_on_boundary = true;
636  for (unsigned int d = 0; d < dim; ++d)
637  if (std::abs(this->unit_support_points[0][d]) > 1e-13)
638  support_points_on_boundary = false;
639  for (unsigned int d = 0; d < dim; ++d)
640  if (std::abs(this->unit_support_points.back()[d] - 1.) > 1e-13)
641  support_points_on_boundary = false;
642  if (support_points_on_boundary == false)
643  return true;
644 
645  unsigned int n2 = n * n;
646 
647  switch (dim)
648  {
649  case 1:
650  {
651  // in 1d, things are simple. since
652  // there is only one degree of
653  // freedom per vertex in this
654  // class, the first is on vertex 0
655  // (==face 0 in some sense), the
656  // second on face 1:
657  return (((shape_index == 0) && (face_index == 0)) ||
658  ((shape_index == this->degree) && (face_index == 1)));
659  };
660 
661  case 2:
662  {
663  if (face_index == 0 && (shape_index % n) == 0)
664  return true;
665  if (face_index == 1 && (shape_index % n) == this->degree)
666  return true;
667  if (face_index == 2 && shape_index < n)
668  return true;
669  if (face_index == 3 && shape_index >= this->dofs_per_cell - n)
670  return true;
671  return false;
672  };
673 
674  case 3:
675  {
676  const unsigned int in2 = shape_index % n2;
677 
678  // x=0
679  if (face_index == 0 && (shape_index % n) == 0)
680  return true;
681  // x=1
682  if (face_index == 1 && (shape_index % n) == n - 1)
683  return true;
684  // y=0
685  if (face_index == 2 && in2 < n)
686  return true;
687  // y=1
688  if (face_index == 3 && in2 >= n2 - n)
689  return true;
690  // z=0
691  if (face_index == 4 && shape_index < n2)
692  return true;
693  // z=1
694  if (face_index == 5 && shape_index >= this->dofs_per_cell - n2)
695  return true;
696  return false;
697  };
698 
699  default:
700  Assert(false, ExcNotImplemented());
701  }
702  return true;
703 }
704 
705 
706 
707 template <int dim, int spacedim>
708 std::pair<Table<2, bool>, std::vector<unsigned int>>
710 {
711  Table<2, bool> constant_modes(1, this->dofs_per_cell);
712  constant_modes.fill(true);
713  return std::pair<Table<2, bool>, std::vector<unsigned int>>(
714  constant_modes, std::vector<unsigned int>(1, 0));
715 }
716 
717 
718 
719 template <int dim, int spacedim>
720 std::size_t
722 {
723  Assert(false, ExcNotImplemented());
724  return 0;
725 }
726 
727 
728 
729 // ------------------------------ FE_DGQArbitraryNodes -----------------------
730 
731 template <int dim, int spacedim>
733  const Quadrature<1> &points)
734  : FE_DGQ<dim, spacedim>(
735  Polynomials::generate_complete_Lagrange_basis(points.get_points()))
736 {
737  Assert(points.size() > 0,
739  this->unit_support_points = Quadrature<dim>(points).get_points();
740 }
741 
742 
743 
744 template <int dim, int spacedim>
745 std::string
747 {
748  // note that the FETools::get_fe_by_name function does not work for
749  // FE_DGQArbitraryNodes since there is no initialization by a degree value.
750  std::ostringstream namebuf;
751  bool equidistant = true;
752  std::vector<double> points(this->degree + 1);
753 
754  std::vector<unsigned int> lexicographic =
756  for (unsigned int j = 0; j <= this->degree; j++)
757  points[j] = this->unit_support_points[lexicographic[j]][0];
758 
759  // Check whether the support points are equidistant.
760  for (unsigned int j = 0; j <= this->degree; j++)
761  if (std::abs(points[j] - (double)j / this->degree) > 1e-15)
762  {
763  equidistant = false;
764  break;
765  }
766  if (this->degree == 0 && std::abs(points[0] - 0.5) < 1e-15)
767  equidistant = true;
768 
769  if (equidistant == true)
770  {
771  if (this->degree > 2)
772  namebuf << "FE_DGQArbitraryNodes<"
773  << Utilities::dim_string(dim, spacedim)
774  << ">(QIterated(QTrapez()," << this->degree << "))";
775  else
776  namebuf << "FE_DGQ<" << Utilities::dim_string(dim, spacedim) << ">("
777  << this->degree << ")";
778  return namebuf.str();
779  }
780 
781  // Check whether the support points come from QGaussLobatto.
782  const QGaussLobatto<1> points_gl(this->degree + 1);
783  bool gauss_lobatto = true;
784  for (unsigned int j = 0; j <= this->degree; j++)
785  if (points[j] != points_gl.point(j)(0))
786  {
787  gauss_lobatto = false;
788  break;
789  }
790 
791  if (gauss_lobatto == true)
792  {
793  namebuf << "FE_DGQ<" << Utilities::dim_string(dim, spacedim) << ">("
794  << this->degree << ")";
795  return namebuf.str();
796  }
797 
798  // Check whether the support points come from QGauss.
799  const QGauss<1> points_g(this->degree + 1);
800  bool gauss = true;
801  for (unsigned int j = 0; j <= this->degree; j++)
802  if (points[j] != points_g.point(j)(0))
803  {
804  gauss = false;
805  break;
806  }
807 
808  if (gauss == true)
809  {
810  namebuf << "FE_DGQArbitraryNodes<" << Utilities::dim_string(dim, spacedim)
811  << ">(QGauss(" << this->degree + 1 << "))";
812  return namebuf.str();
813  }
814 
815  // Check whether the support points come from QGauss.
816  const QGaussLog<1> points_glog(this->degree + 1);
817  bool gauss_log = true;
818  for (unsigned int j = 0; j <= this->degree; j++)
819  if (points[j] != points_glog.point(j)(0))
820  {
821  gauss_log = false;
822  break;
823  }
824 
825  if (gauss_log == true)
826  {
827  namebuf << "FE_DGQArbitraryNodes<" << Utilities::dim_string(dim, spacedim)
828  << ">(QGaussLog(" << this->degree + 1 << "))";
829  return namebuf.str();
830  }
831 
832  // All guesses exhausted
833  namebuf << "FE_DGQArbitraryNodes<" << Utilities::dim_string(dim, spacedim)
834  << ">(QUnknownNodes(" << this->degree + 1 << "))";
835  return namebuf.str();
836 }
837 
838 
839 
840 template <int dim, int spacedim>
841 void
844  const std::vector<Vector<double>> &support_point_values,
845  std::vector<double> & nodal_values) const
846 {
847  AssertDimension(support_point_values.size(),
848  this->get_unit_support_points().size());
849  AssertDimension(support_point_values.size(), nodal_values.size());
850  AssertDimension(this->dofs_per_cell, nodal_values.size());
851 
852  for (unsigned int i = 0; i < this->dofs_per_cell; ++i)
853  {
854  AssertDimension(support_point_values[i].size(), 1);
855 
856  nodal_values[i] = support_point_values[i](0);
857  }
858 }
859 
860 
861 
862 template <int dim, int spacedim>
863 std::unique_ptr<FiniteElement<dim, spacedim>>
865 {
866  // Construct a dummy quadrature formula containing the FE's nodes:
867  std::vector<Point<1>> qpoints(this->degree + 1);
868  std::vector<unsigned int> lexicographic =
870  for (unsigned int i = 0; i <= this->degree; ++i)
871  qpoints[i] = Point<1>(this->unit_support_points[lexicographic[i]][0]);
872  Quadrature<1> pquadrature(qpoints);
873 
874  return std_cxx14::make_unique<FE_DGQArbitraryNodes<dim, spacedim>>(
875  pquadrature);
876 }
877 
878 
879 
880 // ---------------------------------- FE_DGQLegendre -------------------------
881 
882 template <int dim, int spacedim>
884  : FE_DGQ<dim, spacedim>(
885  Polynomials::Legendre::generate_complete_basis(degree))
886 {}
887 
888 
889 
890 template <int dim, int spacedim>
891 std::pair<Table<2, bool>, std::vector<unsigned int>>
893 {
894  // Legendre represents a constant function by one in the first basis
895  // function and zero in all others
896  Table<2, bool> constant_modes(1, this->dofs_per_cell);
897  constant_modes(0, 0) = true;
898  return std::pair<Table<2, bool>, std::vector<unsigned int>>(
899  constant_modes, std::vector<unsigned int>(1, 0));
900 }
901 
902 
903 
904 template <int dim, int spacedim>
905 std::string
907 {
908  return "FE_DGQLegendre<" + Utilities::dim_string(dim, spacedim) + ">(" +
909  Utilities::int_to_string(this->degree) + ")";
910 }
911 
912 
913 
914 template <int dim, int spacedim>
915 std::unique_ptr<FiniteElement<dim, spacedim>>
917 {
918  return std_cxx14::make_unique<FE_DGQLegendre<dim, spacedim>>(this->degree);
919 }
920 
921 
922 
923 // ---------------------------------- FE_DGQHermite --------------------------
924 
925 template <int dim, int spacedim>
927  : FE_DGQ<dim, spacedim>(
928  Polynomials::HermiteLikeInterpolation::generate_complete_basis(degree))
929 {}
930 
931 
932 
933 template <int dim, int spacedim>
934 std::string
936 {
937  return "FE_DGQHermite<" + Utilities::dim_string(dim, spacedim) + ">(" +
938  Utilities::int_to_string(this->degree) + ")";
939 }
940 
941 
942 
943 template <int dim, int spacedim>
944 std::unique_ptr<FiniteElement<dim, spacedim>>
946 {
947  return std_cxx14::make_unique<FE_DGQHermite<dim, spacedim>>(this->degree);
948 }
949 
950 
951 
952 // explicit instantiations
953 #include "fe_dgq.inst"
954 
955 
956 DEAL_II_NAMESPACE_CLOSE
virtual std::pair< Table< 2, bool >, std::vector< unsigned int > > get_constant_modes() const override
Definition: fe_dgq.cc:892
static::ExceptionBase & ExcFEHasNoSupportPoints()
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_quad_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
Definition: fe_dgq.cc:589
virtual const FullMatrix< double > & get_prolongation_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const override
Definition: fe_dgq.cc:392
const std::vector< Point< dim > > & get_unit_support_points() const
Definition: fe.cc:1000
std::vector< std::vector< FullMatrix< double > > > restriction
Definition: fe.h:2419
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1366
virtual FiniteElementDomination::Domination compare_for_face_domination(const FiniteElement< dim, spacedim > &fe_other) const override
Definition: fe_dgq.cc:603
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)
double compute_value(const unsigned int i, const Point< dim > &p) const
virtual bool hp_constraints_are_implemented() const override
Definition: fe_dgq.cc:552
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
Definition: fe_dgq.cc:945
void gauss_jordan()
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
Definition: fe_dgq.cc:561
FE_DGQLegendre(const unsigned int degree)
Definition: fe_dgq.cc:883
Definition: fe_dgq.h:109
const unsigned int degree
Definition: fe_base.h:313
virtual std::string get_name() const override
Definition: fe_dgq.cc:746
virtual void get_face_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const override
Definition: fe_dgq.cc:339
STL namespace.
#define AssertThrow(cond, exc)
Definition: exceptions.h:1329
static::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
Definition: point.h:106
const std::vector< unsigned int > & get_numbering_inverse() const
const Point< dim > & point(const unsigned int i) const
std::vector< Point< dim > > unit_support_points
Definition: fe.h:2457
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
Definition: fe_dgq.cc:916
virtual std::size_t memory_consumption() const override
Definition: fe_dgq.cc:721
unsigned int size() const
void compute_projection_matrices(const FiniteElement< dim, spacedim > &fe, std::vector< std::vector< FullMatrix< number >>> &matrices, const bool isotropic_only=false)
static::ExceptionBase & ExcMessage(std::string arg1)
size_type n() const
virtual std::string get_name() const override
Definition: fe_dgq.cc:906
std::vector< std::vector< FullMatrix< double > > > prolongation
Definition: fe.h:2433
virtual std::pair< Table< 2, bool >, std::vector< unsigned int > > get_constant_modes() const override
Definition: fe_dgq.cc:709
static std::vector< unsigned int > get_dpo_vector(const unsigned int degree)
Definition: fe_dgq.cc:170
#define Assert(cond, exc)
Definition: exceptions.h:1227
static::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
virtual void convert_generalized_support_point_values_to_dof_values(const std::vector< Vector< double >> &support_point_values, std::vector< double > &nodal_values) const override
Definition: fe_dgq.cc:136
virtual void get_subface_interpolation_matrix(const FiniteElement< dim, spacedim > &source, const unsigned int subface, FullMatrix< double > &matrix) const override
Definition: fe_dgq.cc:365
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
Definition: fe_dgq.cc:157
void mmult(FullMatrix< number2 > &C, const FullMatrix< number2 > &B, const bool adding=false) const
size_type m() const
std::string int_to_string(const unsigned int value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:96
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const override
Definition: fe_dgq.cc:864
std::string dim_string(const int dim, const int spacedim)
Definition: utilities.cc:170
const unsigned int dofs_per_cell
Definition: fe_base.h:297
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const override
Definition: fe_dgq.cc:616
FE_DGQArbitraryNodes(const Quadrature< 1 > &points)
Definition: fe_dgq.cc:732
virtual void get_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const override
Definition: fe_dgq.cc:260
FE_DGQHermite(const unsigned int degree)
Definition: fe_dgq.cc:926
void rotate_indices(std::vector< unsigned int > &indices, const char direction) const
Definition: fe_dgq.cc:183
virtual void convert_generalized_support_point_values_to_dof_values(const std::vector< Vector< double >> &support_point_values, std::vector< double > &nodal_values) const override
Definition: fe_dgq.cc:843
void reinit_restriction_and_prolongation_matrices(const bool isotropic_restriction_only=false, const bool isotropic_prolongation_only=false)
Definition: fe.cc:276
virtual std::string get_name() const override
Definition: fe_dgq.cc:935
virtual std::string get_name() const override
Definition: fe_dgq.cc:120
virtual const FullMatrix< double > & get_restriction_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const override
Definition: fe_dgq.cc:472
static::ExceptionBase & ExcNotImplemented()
Definition: table.h:37
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const override
Definition: fe_dgq.cc:575
void fill(InputIterator entries, const bool C_style_indexing=true)
friend class FE_DGQ
Definition: fe_dgq.h:390
static::ExceptionBase & ExcInternalError()