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