Reference documentation for deal.II version 9.0.0
fe_system.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1999 - 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 at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #include <deal.II/base/memory_consumption.h>
17 #include <deal.II/base/quadrature.h>
18 #include <deal.II/base/qprojector.h>
19 #include <deal.II/grid/tria.h>
20 #include <deal.II/grid/tria_iterator.h>
21 #include <deal.II/dofs/dof_accessor.h>
22 #include <deal.II/fe/mapping.h>
23 #include <deal.II/fe/fe_system.h>
24 #include <deal.II/fe/fe_values.h>
25 #include <deal.II/fe/fe_tools.h>
26 
27 #include <sstream>
28 #include <deal.II/base/std_cxx14/memory.h>
29 
30 
31 DEAL_II_NAMESPACE_OPEN
32 
33 namespace internal
34 {
35  namespace FESystemImplementation
36  {
37  namespace
38  {
39  unsigned int count_nonzeros(const std::vector<unsigned int> &vec)
40  {
41  return std::count_if(vec.begin(), vec.end(), [](const unsigned int i)
42  {
43  return i > 0;
44  });
45  }
46  }
47  }
48 }
49 /* ----------------------- FESystem::InternalData ------------------- */
50 
51 
52 template <int dim, int spacedim>
53 FESystem<dim,spacedim>::InternalData::InternalData(const unsigned int n_base_elements)
54  :
55  base_fe_datas(n_base_elements),
56  base_fe_output_objects(n_base_elements)
57 {}
58 
59 
60 
61 template <int dim, int spacedim>
63 {
64  // delete pointers and set them to zero to avoid inadvertent use
65  for (unsigned int i=0; i<base_fe_datas.size(); ++i)
66  base_fe_datas[i].reset();
67 }
68 
69 
70 template <int dim, int spacedim>
73 InternalData::get_fe_data (const unsigned int base_no) const
74 {
75  Assert(base_no<base_fe_datas.size(),
76  ExcIndexRange(base_no,0,base_fe_datas.size()));
77  return *base_fe_datas[base_no];
78 }
79 
80 
81 
82 template <int dim, int spacedim>
83 void
85 InternalData::set_fe_data (const unsigned int base_no,
86  std::unique_ptr<typename FiniteElement<dim,spacedim>::InternalDataBase> ptr)
87 {
88  Assert(base_no<base_fe_datas.size(),
89  ExcIndexRange(base_no,0,base_fe_datas.size()));
90  base_fe_datas[base_no]=std::move(ptr);
91 }
92 
93 
94 
95 template <int dim, int spacedim>
98 InternalData::get_fe_output_object (const unsigned int base_no) const
99 {
100  Assert(base_no<base_fe_output_objects.size(),
101  ExcIndexRange(base_no,0,base_fe_output_objects.size()));
102  return base_fe_output_objects[base_no];
103 }
104 
105 
106 
107 /* ---------------------------------- FESystem ------------------- */
108 
109 
110 template <int dim, int spacedim>
112 
113 
114 template <int dim, int spacedim>
116  const unsigned int n_elements) :
117  FiniteElement<dim,spacedim> (FETools::Compositing::multiply_dof_numbers(&fe, n_elements),
118  FETools::Compositing::compute_restriction_is_additive_flags (&fe, n_elements),
119  FETools::Compositing::compute_nonzero_components(&fe, n_elements)),
120  base_elements((n_elements>0))
121 {
122  std::vector<const FiniteElement<dim,spacedim>*> fes;
123  fes.push_back(&fe);
124  std::vector<unsigned int> multiplicities;
125  multiplicities.push_back(n_elements);
126  initialize(fes, multiplicities);
127 }
128 
129 
130 
131 template <int dim, int spacedim>
133  const unsigned int n1,
134  const FiniteElement<dim,spacedim> &fe2,
135  const unsigned int n2) :
136  FiniteElement<dim,spacedim> (FETools::Compositing::multiply_dof_numbers(&fe1, n1, &fe2, n2),
137  FETools::Compositing::compute_restriction_is_additive_flags (&fe1, n1,
138  &fe2, n2),
139  FETools::Compositing::compute_nonzero_components(&fe1, n1,
140  &fe2, n2)),
141  base_elements((n1>0)+(n2>0))
142 {
143  std::vector<const FiniteElement<dim,spacedim>*> fes;
144  fes.push_back(&fe1);
145  fes.push_back(&fe2);
146  std::vector<unsigned int> multiplicities;
147  multiplicities.push_back(n1);
148  multiplicities.push_back(n2);
149  initialize(fes, multiplicities);
150 }
151 
152 
153 
154 template <int dim, int spacedim>
156  const unsigned int n1,
157  const FiniteElement<dim,spacedim> &fe2,
158  const unsigned int n2,
159  const FiniteElement<dim,spacedim> &fe3,
160  const unsigned int n3) :
161  FiniteElement<dim,spacedim> (FETools::Compositing::multiply_dof_numbers(&fe1, n1,
162  &fe2, n2,
163  &fe3, n3),
164  FETools::Compositing::compute_restriction_is_additive_flags (&fe1, n1,
165  &fe2, n2,
166  &fe3, n3),
167  FETools::Compositing::compute_nonzero_components(&fe1, n1,
168  &fe2, n2,
169  &fe3, n3)),
170  base_elements((n1>0)+(n2>0)+(n3>0))
171 {
172  std::vector<const FiniteElement<dim,spacedim>*> fes;
173  fes.push_back(&fe1);
174  fes.push_back(&fe2);
175  fes.push_back(&fe3);
176  std::vector<unsigned int> multiplicities;
177  multiplicities.push_back(n1);
178  multiplicities.push_back(n2);
179  multiplicities.push_back(n3);
180  initialize(fes, multiplicities);
181 }
182 
183 
184 
185 template <int dim, int spacedim>
187  const unsigned int n1,
188  const FiniteElement<dim,spacedim> &fe2,
189  const unsigned int n2,
190  const FiniteElement<dim,spacedim> &fe3,
191  const unsigned int n3,
192  const FiniteElement<dim,spacedim> &fe4,
193  const unsigned int n4) :
194  FiniteElement<dim,spacedim> (FETools::Compositing::multiply_dof_numbers(&fe1, n1,
195  &fe2, n2,
196  &fe3, n3,
197  &fe4, n4),
198  FETools::Compositing::compute_restriction_is_additive_flags (&fe1, n1,
199  &fe2, n2,
200  &fe3, n3,
201  &fe4, n4),
202  FETools::Compositing::compute_nonzero_components(&fe1, n1,
203  &fe2, n2,
204  &fe3, n3,
205  &fe4, n4)),
206  base_elements((n1>0)+(n2>0)+(n3>0)+(n4>0))
207 {
208  std::vector<const FiniteElement<dim,spacedim>*> fes;
209  fes.push_back(&fe1);
210  fes.push_back(&fe2);
211  fes.push_back(&fe3);
212  fes.push_back(&fe4);
213  std::vector<unsigned int> multiplicities;
214  multiplicities.push_back(n1);
215  multiplicities.push_back(n2);
216  multiplicities.push_back(n3);
217  multiplicities.push_back(n4);
218  initialize(fes, multiplicities);
219 }
220 
221 
222 
223 template <int dim, int spacedim>
225  const unsigned int n1,
226  const FiniteElement<dim,spacedim> &fe2,
227  const unsigned int n2,
228  const FiniteElement<dim,spacedim> &fe3,
229  const unsigned int n3,
230  const FiniteElement<dim,spacedim> &fe4,
231  const unsigned int n4,
232  const FiniteElement<dim,spacedim> &fe5,
233  const unsigned int n5) :
234  FiniteElement<dim,spacedim> (FETools::Compositing::multiply_dof_numbers(&fe1, n1,
235  &fe2, n2,
236  &fe3, n3,
237  &fe4, n4,
238  &fe5, n5),
239  FETools::Compositing::compute_restriction_is_additive_flags (&fe1, n1,
240  &fe2, n2,
241  &fe3, n3,
242  &fe4, n4,
243  &fe5, n5),
244  FETools::Compositing::compute_nonzero_components(&fe1, n1,
245  &fe2, n2,
246  &fe3, n3,
247  &fe4, n4,
248  &fe5, n5)),
249  base_elements((n1>0)+(n2>0)+(n3>0)+(n4>0)+(n5>0))
250 {
251  std::vector<const FiniteElement<dim,spacedim>*> fes;
252  fes.push_back(&fe1);
253  fes.push_back(&fe2);
254  fes.push_back(&fe3);
255  fes.push_back(&fe4);
256  fes.push_back(&fe5);
257  std::vector<unsigned int> multiplicities;
258  multiplicities.push_back(n1);
259  multiplicities.push_back(n2);
260  multiplicities.push_back(n3);
261  multiplicities.push_back(n4);
262  multiplicities.push_back(n5);
263  initialize(fes, multiplicities);
264 }
265 
266 
267 
268 template <int dim, int spacedim>
270  const std::vector<const FiniteElement<dim,spacedim>*> &fes,
271  const std::vector<unsigned int> &multiplicities)
272  :
273  FiniteElement<dim,spacedim> (FETools::Compositing::multiply_dof_numbers(fes, multiplicities),
274  FETools::Compositing::compute_restriction_is_additive_flags (fes, multiplicities),
275  FETools::Compositing::compute_nonzero_components(fes, multiplicities)),
276  base_elements(internal::FESystemImplementation::count_nonzeros(multiplicities))
277 {
278  initialize(fes, multiplicities);
279 }
280 
281 
282 
283 template <int dim, int spacedim>
284 std::string
286 {
287  // note that the
288  // FETools::get_fe_by_name
289  // function depends on the
290  // particular format of the string
291  // this function returns, so they
292  // have to be kept in synch
293 
294  std::ostringstream namebuf;
295 
296  namebuf << "FESystem<"
297  << Utilities::dim_string(dim,spacedim)
298  << ">[";
299  for (unsigned int i=0; i< this->n_base_elements(); ++i)
300  {
301  namebuf << base_element(i).get_name();
302  if (this->element_multiplicity(i) != 1)
303  namebuf << '^' << this->element_multiplicity(i);
304  if (i != this->n_base_elements()-1)
305  namebuf << '-';
306  }
307  namebuf << ']';
308 
309  return namebuf.str();
310 }
311 
312 
313 
314 template <int dim, int spacedim>
315 std::unique_ptr<FiniteElement<dim,spacedim> >
317 {
318  std::vector< const FiniteElement<dim,spacedim>* > fes;
319  std::vector<unsigned int> multiplicities;
320 
321  for (unsigned int i=0; i<this->n_base_elements(); i++)
322  {
323  fes.push_back( & base_element(i) );
324  multiplicities.push_back(this->element_multiplicity(i) );
325  }
326  return std_cxx14::make_unique<FESystem<dim,spacedim>>(fes, multiplicities);
327 }
328 
329 
330 
331 template <int dim, int spacedim>
334 get_sub_fe (const unsigned int first_component,
335  const unsigned int n_selected_components) const
336 {
337  Assert(first_component+n_selected_components <= this->n_components(),
338  ExcMessage("Invalid arguments (not a part of this FiniteElement)."));
339 
340  const unsigned int base_index = this->component_to_base_table[first_component].first.first;
341  const unsigned int component_in_base = this->component_to_base_table[first_component].first.second;
342  const unsigned int base_components = this->base_element(base_index).n_components();
343 
344  // Only select our child base_index if that is all the user wanted. Error
345  // handling will be done inside the recursion.
346  if (n_selected_components<=base_components)
347  return this->base_element(base_index).get_sub_fe(component_in_base, n_selected_components);
348 
349  Assert(n_selected_components == this->n_components(),
350  ExcMessage("You can not select a part of a FiniteElement."));
351  return *this;
352 }
353 
354 
355 
356 template <int dim, int spacedim>
357 double
359  const Point<dim> &p) const
360 {
361  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
362  Assert (this->is_primitive(i),
364 
365  return (base_element(this->system_to_base_table[i].first.first)
366  .shape_value(this->system_to_base_table[i].second, p));
367 }
368 
369 
370 
371 template <int dim, int spacedim>
372 double
374  const Point<dim> &p,
375  const unsigned int component) const
376 {
377  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
378  Assert (component < this->n_components(),
379  ExcIndexRange (component, 0, this->n_components()));
380 
381  // if this value is supposed to be
382  // zero, then return right away...
383  if (this->nonzero_components[i][component] == false)
384  return 0;
385 
386  // ...otherwise: first find out to
387  // which of the base elements this
388  // desired component belongs, and
389  // which component within this base
390  // element it is
391  const unsigned int base = this->component_to_base_index(component).first;
392  const unsigned int component_in_base = this->component_to_base_index(component).second;
393 
394  // then get value from base
395  // element. note that that will
396  // throw an error should the
397  // respective shape function not be
398  // primitive; thus, there is no
399  // need to check this here
400  return (base_element(base).
401  shape_value_component(this->system_to_base_table[i].second,
402  p,
403  component_in_base));
404 }
405 
406 
407 
408 template <int dim, int spacedim>
411  const Point<dim> &p) const
412 {
413  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
414  Assert (this->is_primitive(i),
416 
417  return (base_element(this->system_to_base_table[i].first.first)
418  .shape_grad(this->system_to_base_table[i].second, p));
419 }
420 
421 
422 
423 template <int dim, int spacedim>
426  const Point<dim> &p,
427  const unsigned int component) const
428 {
429  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
430  Assert (component < this->n_components(),
431  ExcIndexRange (component, 0, this->n_components()));
432 
433  // if this value is supposed to be zero, then return right away...
434  if (this->nonzero_components[i][component] == false)
435  return Tensor<1,dim>();
436 
437  // ...otherwise: first find out to which of the base elements this desired
438  // component belongs, and which component within this base element it is
439  const unsigned int base = this->component_to_base_index(component).first;
440  const unsigned int component_in_base = this->component_to_base_index(component).second;
441 
442  // then get value from base element. note that that will throw an error
443  // should the respective shape function not be primitive; thus, there is no
444  // need to check this here
445  return (base_element(base).
446  shape_grad_component(this->system_to_base_table[i].second,
447  p,
448  component_in_base));
449 }
450 
451 
452 
453 template <int dim, int spacedim>
456  const Point<dim> &p) const
457 {
458  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
459  Assert (this->is_primitive(i),
461 
462  return (base_element(this->system_to_base_table[i].first.first)
463  .shape_grad_grad(this->system_to_base_table[i].second, p));
464 }
465 
466 
467 
468 template <int dim, int spacedim>
471  const Point<dim> &p,
472  const unsigned int component) const
473 {
474  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
475  Assert (component < this->n_components(),
476  ExcIndexRange (component, 0, this->n_components()));
477 
478  // if this value is supposed to be zero, then return right away...
479  if (this->nonzero_components[i][component] == false)
480  return Tensor<2,dim>();
481 
482  // ...otherwise: first find out to which of the base elements this desired
483  // component belongs, and which component within this base element it is
484  const unsigned int base = this->component_to_base_index(component).first;
485  const unsigned int component_in_base = this->component_to_base_index(component).second;
486 
487  // then get value from base element. note that that will throw an error
488  // should the respective shape function not be primitive; thus, there is no
489  // need to check this here
490  return (base_element(base).
491  shape_grad_grad_component(this->system_to_base_table[i].second,
492  p,
493  component_in_base));
494 }
495 
496 
497 
498 template <int dim, int spacedim>
501  const Point<dim> &p) const
502 {
503  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
504  Assert (this->is_primitive(i),
506 
507  return (base_element(this->system_to_base_table[i].first.first)
508  .shape_3rd_derivative(this->system_to_base_table[i].second, p));
509 }
510 
511 
512 
513 template <int dim, int spacedim>
516  const Point<dim> &p,
517  const unsigned int component) const
518 {
519  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
520  Assert (component < this->n_components(),
521  ExcIndexRange (component, 0, this->n_components()));
522 
523  // if this value is supposed to be zero, then return right away...
524  if (this->nonzero_components[i][component] == false)
525  return Tensor<3,dim>();
526 
527  // ...otherwise: first find out to which of the base elements this desired
528  // component belongs, and which component within this base element it is
529  const unsigned int base = this->component_to_base_index(component).first;
530  const unsigned int component_in_base = this->component_to_base_index(component).second;
531 
532  // then get value from base element. note that that will throw an error
533  // should the respective shape function not be primitive; thus, there is no
534  // need to check this here
535  return (base_element(base).
536  shape_3rd_derivative_component(this->system_to_base_table[i].second,
537  p,
538  component_in_base));
539 }
540 
541 
542 
543 template <int dim, int spacedim>
546  const Point<dim> &p) const
547 {
548  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
549  Assert (this->is_primitive(i),
551 
552  return (base_element(this->system_to_base_table[i].first.first)
553  .shape_4th_derivative(this->system_to_base_table[i].second, p));
554 }
555 
556 
557 
558 template <int dim, int spacedim>
561  const Point<dim> &p,
562  const unsigned int component) const
563 {
564  Assert (i<this->dofs_per_cell, ExcIndexRange(i, 0, this->dofs_per_cell));
565  Assert (component < this->n_components(),
566  ExcIndexRange (component, 0, this->n_components()));
567 
568  // if this value is supposed to be zero, then return right away...
569  if (this->nonzero_components[i][component] == false)
570  return Tensor<4,dim>();
571 
572  // ...otherwise: first find out to which of the base elements this desired
573  // component belongs, and which component within this base element it is
574  const unsigned int base = this->component_to_base_index(component).first;
575  const unsigned int component_in_base = this->component_to_base_index(component).second;
576 
577  // then get value from base element. note that that will throw an error
578  // should the respective shape function not be primitive; thus, there is no
579  // need to check this here
580  return (base_element(base).
581  shape_4th_derivative_component(this->system_to_base_table[i].second,
582  p,
583  component_in_base));
584 }
585 
586 
587 
588 template <int dim, int spacedim>
589 void
591  const FiniteElement<dim,spacedim> &x_source_fe,
592  FullMatrix<double> &interpolation_matrix) const
593 {
594  // check that the size of the matrices is correct. for historical
595  // reasons, if you call matrix.reinit(8,0), it sets the sizes
596  // to m==n==0 internally. this may happen when we use a FE_Nothing,
597  // so write the test in a more lenient way
598  Assert ((interpolation_matrix.m() == this->dofs_per_cell)
599  ||
600  (x_source_fe.dofs_per_cell == 0),
601  ExcDimensionMismatch (interpolation_matrix.m(),
602  this->dofs_per_cell));
603  Assert ((interpolation_matrix.n() == x_source_fe.dofs_per_cell)
604  ||
605  (this->dofs_per_cell == 0),
606  ExcDimensionMismatch (interpolation_matrix.m(),
607  x_source_fe.dofs_per_cell));
608 
609  // there are certain conditions that the two elements have to satisfy so
610  // that this can work.
611  //
612  // condition 1: the other element must also be a system element
613 
614  AssertThrow ((x_source_fe.get_name().find ("FESystem<") == 0)
615  ||
616  (dynamic_cast<const FESystem<dim,spacedim>*>(&x_source_fe) != nullptr),
617  (typename FiniteElement<dim,spacedim>::
618  ExcInterpolationNotImplemented()));
619 
620  // ok, source is a system element, so we may be able to do the work
621  const FESystem<dim,spacedim> &source_fe
622  = dynamic_cast<const FESystem<dim,spacedim>&>(x_source_fe);
623 
624  // condition 2: same number of basis elements
625  AssertThrow (this->n_base_elements() == source_fe.n_base_elements(),
628 
629  // condition 3: same number of basis elements
630  for (unsigned int i=0; i< this->n_base_elements(); ++i)
631  AssertThrow (this->element_multiplicity(i) ==
632  source_fe.element_multiplicity(i),
635 
636  // ok, so let's try whether it works:
637 
638  // first let's see whether all the basis elements actually generate their
639  // interpolation matrices. if we get past the following loop, then
640  // apparently none of the called base elements threw an exception, so we're
641  // fine continuing and assembling the one big matrix from the small ones of
642  // the base elements
643  std::vector<FullMatrix<double> > base_matrices (this->n_base_elements());
644  for (unsigned int i=0; i<this->n_base_elements(); ++i)
645  {
646  base_matrices[i].reinit (base_element(i).dofs_per_cell,
647  source_fe.base_element(i).dofs_per_cell);
648  base_element(i).get_interpolation_matrix (source_fe.base_element(i),
649  base_matrices[i]);
650  }
651 
652  // first clear big matrix, to make sure that entries that would couple
653  // different bases (or multiplicity indices) are really zero. then assign
654  // entries
655  interpolation_matrix = 0;
656  for (unsigned int i=0; i<this->dofs_per_cell; ++i)
657  for (unsigned int j=0; j<source_fe.dofs_per_cell; ++j)
658  if (this->system_to_base_table[i].first ==
659  source_fe.system_to_base_table[j].first)
660  interpolation_matrix(i,j)
661  = (base_matrices[this->system_to_base_table[i].first.first]
662  (this->system_to_base_table[i].second,
663  source_fe.system_to_base_table[j].second));
664 }
665 
666 
667 
668 template <int dim, int spacedim>
669 const FullMatrix<double> &
671 ::get_restriction_matrix (const unsigned int child,
672  const RefinementCase<dim> &refinement_case) const
673 {
676  Assert (refinement_case!=RefinementCase<dim>::no_refinement,
677  ExcMessage("Restriction matrices are only available for refined cells!"));
678  Assert (child<GeometryInfo<dim>::n_children(refinement_case),
679  ExcIndexRange(child,0,GeometryInfo<dim>::n_children(refinement_case)));
680 
681  // initialization upon first request
682  if (this->restriction[refinement_case-1][child].n() == 0)
683  {
684  Threads::Mutex::ScopedLock lock(this->mutex);
685 
686  // check if updated while waiting for lock
687  if (this->restriction[refinement_case-1][child].n() ==
688  this->dofs_per_cell)
689  return this->restriction[refinement_case-1][child];
690 
691  // Check if some of the matrices of the base elements are void.
692  bool do_restriction = true;
693 
694  // shortcut for accessing local restrictions further down
695  std::vector<const FullMatrix<double> *>
696  base_matrices(this->n_base_elements());
697 
698  for (unsigned int i=0; i<this->n_base_elements(); ++i)
699  {
700  base_matrices[i] =
701  &base_element(i).get_restriction_matrix(child, refinement_case);
702  if (base_matrices[i]->n() != base_element(i).dofs_per_cell)
703  do_restriction = false;
704  }
705  Assert(do_restriction,
707 
708  // if we did not encounter void matrices, initialize the matrix sizes
709  if (do_restriction)
710  {
711  FullMatrix<double> restriction(this->dofs_per_cell,
712  this->dofs_per_cell);
713 
714  // distribute the matrices of the base finite elements to the
715  // matrices of this object. for this, loop over all degrees of
716  // freedom and take the respective entry of the underlying base
717  // element.
718  //
719  // note that we by definition of a base element, they are
720  // independent, i.e. do not couple. only DoFs that belong to the
721  // same instance of a base element may couple
722  for (unsigned int i=0; i<this->dofs_per_cell; ++i)
723  for (unsigned int j=0; j<this->dofs_per_cell; ++j)
724  {
725  // first find out to which base element indices i and j
726  // belong, and which instance thereof in case the base element
727  // has a multiplicity greater than one. if they should not
728  // happen to belong to the same instance of a base element,
729  // then they cannot couple, so go on with the next index
730  if (this->system_to_base_table[i].first !=
731  this->system_to_base_table[j].first)
732  continue;
733 
734  // so get the common base element and the indices therein:
735  const unsigned int
736  base = this->system_to_base_table[i].first.first;
737 
738  const unsigned int
739  base_index_i = this->system_to_base_table[i].second,
740  base_index_j = this->system_to_base_table[j].second;
741 
742  // if we are sure that DoFs i and j may couple, then copy
743  // entries of the matrices:
744  restriction(i,j) = (*base_matrices[base])(base_index_i,base_index_j);
745  }
746 
747  restriction.swap(const_cast<FullMatrix<double> &>
748  (this->restriction[refinement_case-1][child]));
749  }
750  }
751 
752  return this->restriction[refinement_case-1][child];
753 }
754 
755 
756 
757 template <int dim, int spacedim>
758 const FullMatrix<double> &
760 ::get_prolongation_matrix (const unsigned int child,
761  const RefinementCase<dim> &refinement_case) const
762 {
765  Assert (refinement_case!=RefinementCase<dim>::no_refinement,
766  ExcMessage("Restriction matrices are only available for refined cells!"));
767  Assert (child<GeometryInfo<dim>::n_children(refinement_case),
768  ExcIndexRange(child,0,GeometryInfo<dim>::n_children(refinement_case)));
769 
770  // initialization upon first request, construction completely analogous to
771  // restriction matrix
772  if (this->prolongation[refinement_case-1][child].n() == 0)
773  {
774  Threads::Mutex::ScopedLock lock(this->mutex);
775 
776  if (this->prolongation[refinement_case-1][child].n() ==
777  this->dofs_per_cell)
778  return this->prolongation[refinement_case-1][child];
779 
780  bool do_prolongation = true;
781  std::vector<const FullMatrix<double> *>
782  base_matrices(this->n_base_elements());
783  for (unsigned int i=0; i<this->n_base_elements(); ++i)
784  {
785  base_matrices[i] =
786  &base_element(i).get_prolongation_matrix(child, refinement_case);
787  if (base_matrices[i]->n() != base_element(i).dofs_per_cell)
788  do_prolongation = false;
789  }
790  Assert(do_prolongation,
792 
793  if (do_prolongation)
794  {
795  FullMatrix<double> prolongate (this->dofs_per_cell,
796  this->dofs_per_cell);
797 
798  for (unsigned int i=0; i<this->dofs_per_cell; ++i)
799  for (unsigned int j=0; j<this->dofs_per_cell; ++j)
800  {
801  if (this->system_to_base_table[i].first !=
802  this->system_to_base_table[j].first)
803  continue;
804  const unsigned int
805  base = this->system_to_base_table[i].first.first;
806 
807  const unsigned int
808  base_index_i = this->system_to_base_table[i].second,
809  base_index_j = this->system_to_base_table[j].second;
810  prolongate(i,j) = (*base_matrices[base])(base_index_i,base_index_j);
811  }
812  prolongate.swap(const_cast<FullMatrix<double> &>
813  (this->prolongation[refinement_case-1][child]));
814  }
815  }
816 
817  return this->prolongation[refinement_case-1][child];
818 }
819 
820 
821 template <int dim, int spacedim>
822 unsigned int
824 face_to_cell_index (const unsigned int face_dof_index,
825  const unsigned int face,
826  const bool face_orientation,
827  const bool face_flip,
828  const bool face_rotation) const
829 {
830  // we need to ask the base elements how they want to translate
831  // the DoFs within their own numbering. thus, translate to
832  // the base element numbering and then back
833  const std::pair<std::pair<unsigned int, unsigned int>, unsigned int>
834  face_base_index = this->face_system_to_base_index(face_dof_index);
835 
836  const unsigned int
837  base_face_to_cell_index
838  = this->base_element(face_base_index.first.first).face_to_cell_index (face_base_index.second,
839  face,
840  face_orientation,
841  face_flip,
842  face_rotation);
843 
844  // it would be nice if we had a base_to_system_index function, but
845  // all that exists is a component_to_system_index function. we can't do
846  // this here because it won't work for non-primitive elements. consequently,
847  // simply do a loop over all dofs till we find whether it corresponds
848  // to the one we're interested in -- crude, maybe, but works for now
849  const std::pair<std::pair<unsigned int, unsigned int>, unsigned int>
850  target = std::make_pair (face_base_index.first, base_face_to_cell_index);
851  for (unsigned int i=0; i<this->dofs_per_cell; ++i)
852  if (this->system_to_base_index(i) == target)
853  return i;
854 
855  Assert (false, ExcInternalError());
857 }
858 
859 
860 
861 //---------------------------------------------------------------------------
862 // Data field initialization
863 //---------------------------------------------------------------------------
864 
865 
866 
867 template <int dim, int spacedim>
870 {
872  // generate maximal set of flags
873  // that are necessary
874  for (unsigned int base_no=0; base_no<this->n_base_elements(); ++base_no)
875  out |= base_element(base_no).requires_update_flags (flags);
876  return out;
877 }
878 
879 
880 
881 template <int dim, int spacedim>
882 std::unique_ptr<typename FiniteElement<dim,spacedim>::InternalDataBase>
884 get_data (const UpdateFlags flags,
885  const Mapping<dim,spacedim> &mapping,
886  const Quadrature<dim> &quadrature,
888 {
889  // create an internal data object and set the update flags we will need
890  // to deal with. the current object does not make use of these flags,
891  // but we need to nevertheless set them correctly since we look
892  // into the update_each flag of base elements in fill_fe_values,
893  // and so the current object's update_each flag needs to be
894  // correct in case the current FESystem is a base element for another,
895  // higher-level FESystem itself.
896  auto data = std_cxx14::make_unique<InternalData>(this->n_base_elements());
897  data->update_each = requires_update_flags(flags);
898 
899  // get data objects from each of the base elements and store
900  // them. one might think that doing this in parallel (over the
901  // base elements) would be a good idea, but this turns out to
902  // be wrong because we would then run these jobs on different
903  // threads/processors and this allocates memory in different
904  // NUMA domains; this has large detrimental effects when later
905  // writing into these objects in fill_fe_*_values. all of this
906  // is particularly true when using FEValues objects in
907  // WorkStream contexts where we explicitly make sure that
908  // every function only uses objects previously allocated
909  // in the same NUMA context and on the same thread as the
910  // function is called
911  for (unsigned int base_no=0; base_no<this->n_base_elements(); ++base_no)
912  {
914  = data->get_fe_output_object(base_no);
915  base_fe_output_object.initialize (quadrature.size(), base_element(base_no),
916  flags | base_element(base_no).requires_update_flags(flags));
917 
918  // let base objects produce their scratch objects. they may
919  // also at this time write into the output objects we provide
920  // for them; it would be nice if we could already copy something
921  // out of the base output object into the system output object,
922  // but we can't because we can't know what the elements already
923  // copied and/or will want to update on every cell
924  auto base_fe_data =
925  base_element(base_no).get_data (flags, mapping, quadrature,
926  base_fe_output_object);
927 
928  data->set_fe_data(base_no, std::move(base_fe_data));
929  }
930 
931  return std::move(data);
932 }
933 
934 // The following function is a clone of get_data, with the exception
935 // that get_face_data of the base elements is called.
936 
937 template <int dim, int spacedim>
938 std::unique_ptr<typename FiniteElement<dim,spacedim>::InternalDataBase>
941  const Mapping<dim,spacedim> &mapping,
942  const Quadrature<dim-1> &quadrature,
944 {
945  // create an internal data object and set the update flags we will need
946  // to deal with. the current object does not make use of these flags,
947  // but we need to nevertheless set them correctly since we look
948  // into the update_each flag of base elements in fill_fe_values,
949  // and so the current object's update_each flag needs to be
950  // correct in case the current FESystem is a base element for another,
951  // higher-level FESystem itself.
952  auto data = std_cxx14::make_unique<InternalData>(this->n_base_elements());
953  data->update_each = requires_update_flags(flags);
954 
955  // get data objects from each of the base elements and store
956  // them. one might think that doing this in parallel (over the
957  // base elements) would be a good idea, but this turns out to
958  // be wrong because we would then run these jobs on different
959  // threads/processors and this allocates memory in different
960  // NUMA domains; this has large detrimental effects when later
961  // writing into these objects in fill_fe_*_values. all of this
962  // is particularly true when using FEValues objects in
963  // WorkStream contexts where we explicitly make sure that
964  // every function only uses objects previously allocated
965  // in the same NUMA context and on the same thread as the
966  // function is called
967  for (unsigned int base_no=0; base_no<this->n_base_elements(); ++base_no)
968  {
970  = data->get_fe_output_object(base_no);
971  base_fe_output_object.initialize (quadrature.size(), base_element(base_no),
972  flags | base_element(base_no).requires_update_flags(flags));
973 
974  // let base objects produce their scratch objects. they may
975  // also at this time write into the output objects we provide
976  // for them; it would be nice if we could already copy something
977  // out of the base output object into the system output object,
978  // but we can't because we can't know what the elements already
979  // copied and/or will want to update on every cell
980  auto base_fe_data =
981  base_element(base_no).get_face_data (flags, mapping, quadrature,
982  base_fe_output_object);
983 
984  data->set_fe_data(base_no, std::move(base_fe_data));
985  }
986 
987  return std::move(data);
988 }
989 
990 
991 
992 // The following function is a clone of get_data, with the exception
993 // that get_subface_data of the base elements is called.
994 
995 template <int dim, int spacedim>
996 std::unique_ptr<typename FiniteElement<dim,spacedim>::InternalDataBase>
999  const Mapping<dim,spacedim> &mapping,
1000  const Quadrature<dim-1> &quadrature,
1002 {
1003  // create an internal data object and set the update flags we will need
1004  // to deal with. the current object does not make use of these flags,
1005  // but we need to nevertheless set them correctly since we look
1006  // into the update_each flag of base elements in fill_fe_values,
1007  // and so the current object's update_each flag needs to be
1008  // correct in case the current FESystem is a base element for another,
1009  // higher-level FESystem itself.
1010  auto data = std_cxx14::make_unique<InternalData>(this->n_base_elements());
1011  data->update_each = requires_update_flags(flags);
1012 
1013  // get data objects from each of the base elements and store
1014  // them. one might think that doing this in parallel (over the
1015  // base elements) would be a good idea, but this turns out to
1016  // be wrong because we would then run these jobs on different
1017  // threads/processors and this allocates memory in different
1018  // NUMA domains; this has large detrimental effects when later
1019  // writing into these objects in fill_fe_*_values. all of this
1020  // is particularly true when using FEValues objects in
1021  // WorkStream contexts where we explicitly make sure that
1022  // every function only uses objects previously allocated
1023  // in the same NUMA context and on the same thread as the
1024  // function is called
1025  for (unsigned int base_no=0; base_no<this->n_base_elements(); ++base_no)
1026  {
1028  = data->get_fe_output_object(base_no);
1029  base_fe_output_object.initialize (quadrature.size(), base_element(base_no),
1030  flags | base_element(base_no).requires_update_flags(flags));
1031 
1032  // let base objects produce their scratch objects. they may
1033  // also at this time write into the output objects we provide
1034  // for them; it would be nice if we could already copy something
1035  // out of the base output object into the system output object,
1036  // but we can't because we can't know what the elements already
1037  // copied and/or will want to update on every cell
1038  auto base_fe_data =
1039  base_element(base_no).get_subface_data (flags, mapping, quadrature,
1040  base_fe_output_object);
1041 
1042  data->set_fe_data(base_no, std::move(base_fe_data));
1043  }
1044 
1045  return std::move(data);
1046 }
1047 
1048 
1049 
1050 template <int dim, int spacedim>
1051 void
1054  const CellSimilarity::Similarity cell_similarity,
1055  const Quadrature<dim> &quadrature,
1056  const Mapping<dim,spacedim> &mapping,
1057  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_internal,
1058  const ::internal::FEValuesImplementation::MappingRelatedData<dim, spacedim> &mapping_data,
1059  const typename FiniteElement<dim,spacedim>::InternalDataBase &fe_internal,
1061 {
1062  compute_fill(mapping, cell, invalid_face_number, invalid_face_number,
1063  quadrature, cell_similarity, mapping_internal, fe_internal,
1064  mapping_data, output_data);
1065 }
1066 
1067 
1068 
1069 template <int dim, int spacedim>
1070 void
1073  const unsigned int face_no,
1074  const Quadrature<dim-1> &quadrature,
1075  const Mapping<dim,spacedim> &mapping,
1076  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_internal,
1077  const ::internal::FEValuesImplementation::MappingRelatedData<dim, spacedim> &mapping_data,
1078  const typename FiniteElement<dim,spacedim>::InternalDataBase &fe_internal,
1080 {
1081  compute_fill (mapping, cell, face_no, invalid_face_number, quadrature,
1082  CellSimilarity::none, mapping_internal, fe_internal,
1083  mapping_data, output_data);
1084 }
1085 
1086 
1087 
1088 
1089 template <int dim, int spacedim>
1090 void
1093  const unsigned int face_no,
1094  const unsigned int sub_no,
1095  const Quadrature<dim-1> &quadrature,
1096  const Mapping<dim,spacedim> &mapping,
1097  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_internal,
1098  const ::internal::FEValuesImplementation::MappingRelatedData<dim, spacedim> &mapping_data,
1099  const typename FiniteElement<dim,spacedim>::InternalDataBase &fe_internal,
1101 {
1102  compute_fill (mapping, cell, face_no, sub_no, quadrature,
1103  CellSimilarity::none, mapping_internal, fe_internal,
1104  mapping_data, output_data);
1105 }
1106 
1107 
1108 
1109 template <int dim, int spacedim>
1110 template <int dim_1>
1111 void
1114  const typename Triangulation<dim,spacedim>::cell_iterator &cell,
1115  const unsigned int face_no,
1116  const unsigned int sub_no,
1117  const Quadrature<dim_1> &quadrature,
1118  const CellSimilarity::Similarity cell_similarity,
1119  const typename Mapping<dim,spacedim>::InternalDataBase &mapping_internal,
1120  const typename FiniteElement<dim,spacedim>::InternalDataBase &fe_internal,
1123 {
1124  // convert data object to internal
1125  // data for this class. fails with
1126  // an exception if that is not
1127  // possible
1128  Assert (dynamic_cast<const InternalData *> (&fe_internal) != nullptr, ExcInternalError());
1129  const InternalData &fe_data = static_cast<const InternalData &> (fe_internal);
1130 
1131  // Either dim_1==dim
1132  // (fill_fe_values) or dim_1==dim-1
1133  // (fill_fe_(sub)face_values)
1134  Assert(dim_1==dim || dim_1==dim-1, ExcInternalError());
1135  const UpdateFlags flags = fe_data.update_each;
1136 
1137 
1138  // loop over the base elements, let them compute what they need to compute,
1139  // and then copy what is necessary.
1140  //
1141  // one may think that it would be a good idea to parallelize this over
1142  // base elements, but it turns out to be not worthwhile: doing so lets
1143  // multiple threads access data objects that were created by the current
1144  // thread, leading to many NUMA memory access inefficiencies. we specifically
1145  // want to avoid this if this class is called in a WorkStream context where
1146  // we very carefully allocate objects only on the thread where they
1147  // will actually be used; spawning new tasks here would be counterproductive
1148  if (flags & (update_values | update_gradients
1150  for (unsigned int base_no=0; base_no<this->n_base_elements(); ++base_no)
1151  {
1153  base_fe = base_element(base_no);
1155  base_fe_data = fe_data.get_fe_data(base_no);
1157  base_data = fe_data.get_fe_output_object(base_no);
1158 
1159  // fill_fe_face_values needs argument Quadrature<dim-1> for both cases
1160  // dim_1==dim-1 and dim_1=dim. Hence the following workaround
1161  const Quadrature<dim> *cell_quadrature = nullptr;
1162  const Quadrature<dim-1> *face_quadrature = nullptr;
1163  const unsigned int n_q_points = quadrature.size();
1164 
1165  // static cast to the common base class of quadrature being either
1166  // Quadrature<dim> or Quadrature<dim-1>:
1167  const Subscriptor *quadrature_base_pointer = &quadrature;
1168 
1169  if (face_no==invalid_face_number)
1170  {
1171  Assert(dim_1==dim, ExcDimensionMismatch(dim_1,dim));
1172  Assert (dynamic_cast<const Quadrature<dim> *>(quadrature_base_pointer) != nullptr,
1173  ExcInternalError());
1174 
1175  cell_quadrature
1176  = static_cast<const Quadrature<dim> *>(quadrature_base_pointer);
1177  }
1178  else
1179  {
1180  Assert(dim_1==dim-1, ExcDimensionMismatch(dim_1,dim-1));
1181  Assert (dynamic_cast<const Quadrature<dim-1> *>(quadrature_base_pointer) != nullptr,
1182  ExcInternalError());
1183 
1184  face_quadrature
1185  = static_cast<const Quadrature<dim-1> *>(quadrature_base_pointer);
1186  }
1187 
1188 
1189  // Make sure that in the case of fill_fe_values the data is only
1190  // copied from base_data to data if base_data is changed. therefore
1191  // use fe_fe_data.current_update_flags()
1192  //
1193  // for the case of fill_fe_(sub)face_values the data needs to be
1194  // copied from base_data to data on each face, therefore use
1195  // base_fe_data.update_flags.
1196  if (face_no==invalid_face_number)
1197  base_fe.fill_fe_values(cell, cell_similarity,
1198  *cell_quadrature,
1199  mapping, mapping_internal, mapping_data,
1200  base_fe_data, base_data);
1201  else if (sub_no==invalid_face_number)
1202  base_fe.fill_fe_face_values(cell, face_no,
1203  *face_quadrature,
1204  mapping, mapping_internal, mapping_data,
1205  base_fe_data, base_data);
1206  else
1207  base_fe.fill_fe_subface_values(cell, face_no, sub_no,
1208  *face_quadrature,
1209  mapping, mapping_internal, mapping_data,
1210  base_fe_data, base_data);
1211 
1212  // now data has been generated, so copy it. we used to work by
1213  // looping over all base elements (i.e. this outer loop), then over
1214  // multiplicity, then over the shape functions from that base
1215  // element, but that requires that we can infer the global number of
1216  // a shape function from its number in the base element. for that we
1217  // had the component_to_system_table.
1218  //
1219  // however, this does of course no longer work since we have
1220  // non-primitive elements. so we go the other way round: loop over
1221  // all shape functions of the composed element, and here only treat
1222  // those shape functions that belong to a given base element
1223  //TODO: Introduce the needed table and loop only over base element shape functions. This here is not efficient at all AND very bad style
1224  const UpdateFlags base_flags = base_fe_data.update_each;
1225 
1226  // some base element might involve values that depend on the shape
1227  // of the geometry, so we always need to copy the shape values around
1228  // also in case we detected a cell similarity (but no heavy work will
1229  // be done inside the individual elements in case we have a
1230  // translation and simple elements).
1231  for (unsigned int system_index=0; system_index<this->dofs_per_cell;
1232  ++system_index)
1233  if (this->system_to_base_table[system_index].first.first == base_no)
1234  {
1235  const unsigned int
1236  base_index = this->system_to_base_table[system_index].second;
1237  Assert (base_index<base_fe.dofs_per_cell, ExcInternalError());
1238 
1239  // now copy. if the shape function is primitive, then there
1240  // is only one value to be copied, but for non-primitive
1241  // elements, there might be more values to be copied
1242  //
1243  // so, find out from which index to take this one value, and
1244  // to which index to put
1245  unsigned int out_index = 0;
1246  for (unsigned int i=0; i<system_index; ++i)
1247  out_index += this->n_nonzero_components(i);
1248  unsigned int in_index = 0;
1249  for (unsigned int i=0; i<base_index; ++i)
1250  in_index += base_fe.n_nonzero_components(i);
1251 
1252  // then loop over the number of components to be copied
1253  Assert (this->n_nonzero_components(system_index) ==
1254  base_fe.n_nonzero_components(base_index),
1255  ExcInternalError());
1256 
1257  if (base_flags & update_values)
1258  for (unsigned int s=0; s<this->n_nonzero_components(system_index); ++s)
1259  for (unsigned int q=0; q<n_q_points; ++q)
1260  output_data.shape_values[out_index+s][q] =
1261  base_data.shape_values(in_index+s,q);
1262 
1263  if (base_flags & update_gradients)
1264  for (unsigned int s=0; s<this->n_nonzero_components(system_index); ++s)
1265  for (unsigned int q=0; q<n_q_points; ++q)
1266  output_data.shape_gradients[out_index+s][q] =
1267  base_data.shape_gradients[in_index+s][q];
1268 
1269  if (base_flags & update_hessians)
1270  for (unsigned int s=0; s<this->n_nonzero_components(system_index); ++s)
1271  for (unsigned int q=0; q<n_q_points; ++q)
1272  output_data.shape_hessians[out_index+s][q] =
1273  base_data.shape_hessians[in_index+s][q];
1274 
1275  if (base_flags & update_3rd_derivatives)
1276  for (unsigned int s=0; s<this->n_nonzero_components(system_index); ++s)
1277  for (unsigned int q=0; q<n_q_points; ++q)
1278  output_data.shape_3rd_derivatives[out_index+s][q] =
1279  base_data.shape_3rd_derivatives[in_index+s][q];
1280 
1281  }
1282  }
1283 }
1284 
1285 
1286 template <int dim, int spacedim>
1288 {
1289  // check whether all base elements implement their interface constraint
1290  // matrices. if this is not the case, then leave the interface costraints of
1291  // this composed element empty as well; however, the rest of the element is
1292  // usable
1293  for (unsigned int base=0; base<this->n_base_elements(); ++base)
1294  if (base_element(base).constraints_are_implemented() == false)
1295  return;
1296 
1297  this->interface_constraints.
1298  TableBase<2,double>::reinit (this->interface_constraints_size());
1299 
1300  // the layout of the constraints matrix is described in the FiniteElement
1301  // class. you may want to look there first before trying to understand the
1302  // following, especially the mapping of the @p{m} index.
1303  //
1304  // in order to map it to the fe-system class, we have to know which base
1305  // element a degree of freedom within a vertex, line, etc belongs to. this
1306  // can be accomplished by the system_to_component_index function in
1307  // conjunction with the numbers first_{line,quad,...}_index
1308  for (unsigned int n=0; n<this->interface_constraints.n(); ++n)
1309  for (unsigned int m=0; m<this->interface_constraints.m(); ++m)
1310  {
1311  // for the pair (n,m) find out which base element they belong to and
1312  // the number therein
1313  //
1314  // first for the n index. this is simple since the n indices are in
1315  // the same order as they are usually on a face. note that for the
1316  // data type, first value in pair is (base element,instance of base
1317  // element), second is index within this instance
1318  const std::pair<std::pair<unsigned int,unsigned int>, unsigned int> n_index
1319  = this->face_system_to_base_table[n];
1320 
1321  // likewise for the m index. this is more complicated due to the
1322  // strange ordering we have for the dofs on the refined faces.
1323  std::pair<std::pair<unsigned int,unsigned int>, unsigned int> m_index;
1324  switch (dim)
1325  {
1326  case 1:
1327  {
1328  // we should never get here! (in 1d, the constraints matrix
1329  // should be of size zero)
1330  Assert (false, ExcInternalError());
1331  break;
1332  };
1333 
1334  case 2:
1335  {
1336  // the indices m=0..d_v-1 are from the center vertex. their order
1337  // is the same as for the first vertex of the whole cell, so we
1338  // can use the system_to_base_table variable (using the
1339  // face_s_t_base_t function would yield the same)
1340  if (m < this->dofs_per_vertex)
1341  m_index = this->system_to_base_table[m];
1342  else
1343  // then come the two sets of line indices
1344  {
1345  const unsigned int index_in_line
1346  = (m-this->dofs_per_vertex) % this->dofs_per_line;
1347  const unsigned int sub_line
1348  = (m-this->dofs_per_vertex) / this->dofs_per_line;
1349  Assert (sub_line < 2, ExcInternalError());
1350 
1351  // from this information, try to get base element and instance
1352  // of base element. we do so by constructing the corresponding
1353  // face index of m in the present element, then use
1354  // face_system_to_base_table
1355  const unsigned int tmp1 = 2*this->dofs_per_vertex+index_in_line;
1356  m_index.first = this->face_system_to_base_table[tmp1].first;
1357 
1358  // what we are still missing is the index of m within the base
1359  // elements interface_constraints table
1360  //
1361  // here, the second value of face_system_to_base_table can
1362  // help: it denotes the face index of that shape function
1363  // within the base element. since we know that it is a line
1364  // dof, we can construct the rest: tmp2 will denote the index
1365  // of this shape function among the line shape functions:
1366  Assert (this->face_system_to_base_table[tmp1].second >=
1367  2*base_element(m_index.first.first).dofs_per_vertex,
1368  ExcInternalError());
1369  const unsigned int tmp2 = this->face_system_to_base_table[tmp1].second -
1370  2*base_element(m_index.first.first).dofs_per_vertex;
1371  Assert (tmp2 < base_element(m_index.first.first).dofs_per_line,
1372  ExcInternalError());
1373  m_index.second = base_element(m_index.first.first).dofs_per_vertex +
1374  base_element(m_index.first.first).dofs_per_line*sub_line +
1375  tmp2;
1376  };
1377  break;
1378  };
1379 
1380  case 3:
1381  {
1382  // same way as above, although a little more complicated...
1383 
1384  // the indices m=0..5*d_v-1 are from the center and the four
1385  // subline vertices. their order is the same as for the first
1386  // vertex of the whole cell, so we can use the simple arithmetic
1387  if (m < 5*this->dofs_per_vertex)
1388  m_index = this->system_to_base_table[m];
1389  else
1390  // then come the 12 sets of line indices
1391  if (m < 5*this->dofs_per_vertex + 12*this->dofs_per_line)
1392  {
1393  // for the meaning of all this, see the 2d part
1394  const unsigned int index_in_line
1395  = (m-5*this->dofs_per_vertex) % this->dofs_per_line;
1396  const unsigned int sub_line
1397  = (m-5*this->dofs_per_vertex) / this->dofs_per_line;
1398  Assert (sub_line < 12, ExcInternalError());
1399 
1400  const unsigned int tmp1 = 4*this->dofs_per_vertex+index_in_line;
1401  m_index.first = this->face_system_to_base_table[tmp1].first;
1402 
1403  Assert (this->face_system_to_base_table[tmp1].second >=
1404  4*base_element(m_index.first.first).dofs_per_vertex,
1405  ExcInternalError());
1406  const unsigned int tmp2 = this->face_system_to_base_table[tmp1].second -
1407  4*base_element(m_index.first.first).dofs_per_vertex;
1408  Assert (tmp2 < base_element(m_index.first.first).dofs_per_line,
1409  ExcInternalError());
1410  m_index.second = 5*base_element(m_index.first.first).dofs_per_vertex +
1411  base_element(m_index.first.first).dofs_per_line*sub_line +
1412  tmp2;
1413  }
1414  else
1415  // on one of the four sub-quads
1416  {
1417  // for the meaning of all this, see the 2d part
1418  const unsigned int index_in_quad
1419  = (m-5*this->dofs_per_vertex-12*this->dofs_per_line) %
1420  this->dofs_per_quad;
1421  Assert (index_in_quad < this->dofs_per_quad,
1422  ExcInternalError());
1423  const unsigned int sub_quad
1424  = ((m-5*this->dofs_per_vertex-12*this->dofs_per_line) /
1425  this->dofs_per_quad);
1426  Assert (sub_quad < 4, ExcInternalError());
1427 
1428  const unsigned int tmp1 = 4*this->dofs_per_vertex +
1429  4*this->dofs_per_line +
1430  index_in_quad;
1431  Assert (tmp1 < this->face_system_to_base_table.size(),
1432  ExcInternalError());
1433  m_index.first = this->face_system_to_base_table[tmp1].first;
1434 
1435  Assert (this->face_system_to_base_table[tmp1].second >=
1436  4*base_element(m_index.first.first).dofs_per_vertex +
1437  4*base_element(m_index.first.first).dofs_per_line,
1438  ExcInternalError());
1439  const unsigned int tmp2 = this->face_system_to_base_table[tmp1].second -
1440  4*base_element(m_index.first.first).dofs_per_vertex -
1441  4*base_element(m_index.first.first).dofs_per_line;
1442  Assert (tmp2 < base_element(m_index.first.first).dofs_per_quad,
1443  ExcInternalError());
1444  m_index.second = 5*base_element(m_index.first.first).dofs_per_vertex +
1445  12*base_element(m_index.first.first).dofs_per_line +
1446  base_element(m_index.first.first).dofs_per_quad*sub_quad +
1447  tmp2;
1448  };
1449 
1450  break;
1451  };
1452 
1453  default:
1454  Assert (false, ExcNotImplemented());
1455  };
1456 
1457  // now that we gathered all information: use it to build the
1458  // matrix. note that if n and m belong to different base elements or
1459  // instances, then there definitely will be no coupling
1460  if (n_index.first == m_index.first)
1461  this->interface_constraints(m,n)
1462  = (base_element(n_index.first.first).constraints()(m_index.second,
1463  n_index.second));
1464  };
1465 }
1466 
1467 
1468 
1469 template <int dim, int spacedim>
1471  const std::vector<unsigned int> &multiplicities)
1472 {
1473  Assert (fes.size() == multiplicities.size(),
1474  ExcDimensionMismatch (fes.size(), multiplicities.size()) );
1475  Assert (fes.size() > 0,
1476  ExcMessage ("Need to pass at least one finite element."));
1477  Assert (internal::FESystemImplementation::count_nonzeros(multiplicities) > 0,
1478  ExcMessage("You only passed FiniteElements with multiplicity 0."));
1479 
1480  // Note that we need to skip every fe with multiplicity 0 in the following block of code
1481 
1482  this->base_to_block_indices.reinit(0, 0);
1483 
1484  for (unsigned int i=0; i<fes.size(); i++)
1485  if (multiplicities[i]>0)
1486  this->base_to_block_indices.push_back( multiplicities[i] );
1487 
1488  {
1489  Threads::TaskGroup<> clone_base_elements;
1490 
1491  unsigned int ind=0;
1492  for (unsigned int i=0; i<fes.size(); i++)
1493  if (multiplicities[i]>0)
1494  {
1495  clone_base_elements += Threads::new_task ([ &,i,ind] ()
1496  {
1497  base_elements[ind] = { fes[i]->clone(), multiplicities[i] };
1498  });
1499  ++ind;
1500  }
1501  Assert(ind>0, ExcInternalError());
1502 
1503  // wait for all of these clone operations to finish
1504  clone_base_elements.join_all();
1505  }
1506 
1507 
1508  {
1509  // If the system is not primitive, these have not been initialized by
1510  // FiniteElement
1511  this->system_to_component_table.resize(this->dofs_per_cell);
1512  this->face_system_to_component_table.resize(this->dofs_per_face);
1513 
1514  FETools::Compositing::build_cell_tables(this->system_to_base_table,
1515  this->system_to_component_table,
1516  this->component_to_base_table,
1517  *this);
1518 
1519  FETools::Compositing::build_face_tables(this->face_system_to_base_table,
1520  this->face_system_to_component_table,
1521  *this);
1522 
1523  }
1524 
1525  // now initialize interface constraints, support points, and other tables.
1526  // (restriction and prolongation matrices are only built on demand.) do
1527  // this in parallel
1528 
1529  Threads::TaskGroup<> init_tasks;
1530 
1531  init_tasks += Threads::new_task ([&]()
1532  {
1533  this->build_interface_constraints ();
1534  });
1535 
1536  init_tasks += Threads::new_task ([&]()
1537  {
1538  // if one of the base elements has no support points, then it makes no sense
1539  // to define support points for the composed element, so return an empty
1540  // array to demonstrate that fact. Note that we ignore FE_Nothing in this logic.
1541  for (unsigned int base_el=0; base_el<this->n_base_elements(); ++base_el)
1542  if (!base_element(base_el).has_support_points() && base_element(base_el).dofs_per_cell!=0)
1543  {
1544  this->unit_support_points.resize(0);
1545  return;
1546  }
1547 
1548  // generate unit support points from unit support points of sub elements
1549  this->unit_support_points.resize(this->dofs_per_cell);
1550 
1551  for (unsigned int i=0; i<this->dofs_per_cell; ++i)
1552  {
1553  const unsigned int
1554  base = this->system_to_base_table[i].first.first,
1555  base_index = this->system_to_base_table[i].second;
1556  Assert (base<this->n_base_elements(), ExcInternalError());
1557  Assert (base_index<base_element(base).unit_support_points.size(),
1558  ExcInternalError());
1559  this->unit_support_points[i] = base_element(base).unit_support_points[base_index];
1560  }
1561  });
1562 
1563  // initialize face support points (for dim==2,3). same procedure as above
1564  if (dim > 1)
1565  init_tasks += Threads::new_task ([&]()
1566  {
1567  // if one of the base elements has no support points, then it makes no sense
1568  // to define support points for the composed element. In that case, return
1569  // an empty array to demonstrate that fact (note that we ask whether the
1570  // base element has no support points at all, not only none on the face!)
1571  //
1572  // on the other hand, if there is an element that simply has no degrees of
1573  // freedom on the face at all, then we don't care whether it has support
1574  // points or not. this is, for example, the case for the stable Stokes
1575  // element Q(p)^dim \times DGP(p-1).
1576  for (unsigned int base_el=0; base_el<this->n_base_elements(); ++base_el)
1577  if (!base_element(base_el).has_support_points()
1578  &&
1579  (base_element(base_el).dofs_per_face > 0))
1580  {
1581  this->unit_face_support_points.resize(0);
1582  return;
1583  }
1584 
1585 
1586  // generate unit face support points from unit support points of sub
1587  // elements
1588  this->unit_face_support_points.resize(this->dofs_per_face);
1589 
1590  for (unsigned int i=0; i<this->dofs_per_face; ++i)
1591  {
1592  const unsigned int base_i = this->face_system_to_base_table[i].first.first;
1593  const unsigned int index_in_base = this->face_system_to_base_table[i].second;
1594 
1595  Assert (index_in_base < base_element(base_i).unit_face_support_points.size(),
1596  ExcInternalError());
1597 
1598  this->unit_face_support_points[i]
1599  = base_element(base_i).unit_face_support_points[index_in_base];
1600  }
1601  });
1602 
1603  // Initialize generalized support points and an (internal) index table
1604  init_tasks += Threads::new_task ([&]()
1605  {
1606  // Iterate over all base elements, extract a representative set of
1607  // _unique_ generalized support points and store the information how
1608  // generalized support points of base elements are mapped to this list
1609  // of representatives. Complexity O(n^2), where n is the number of
1610  // generalized support points.
1611 
1612  generalized_support_points_index_table.resize(this->n_base_elements());
1613 
1614  for (unsigned int base = 0; base < this->n_base_elements(); ++base)
1615  {
1616  // If the current base element does not have generalized support
1617  // points, ignore it. Note that
1618  // * FESystem::convert_generalized_support_point_values_to_dof_values
1619  // will simply skip such non-interpolatory base elements by
1620  // assigning NaN to all dofs.
1621  // * If this routine does not pick up any generalized support
1622  // points the corresponding vector will be empty and
1623  // FiniteElement::has_generalized_support_points will return
1624  // false.
1625  if (!base_element(base).has_generalized_support_points())
1626  continue;
1627 
1628  for (const auto &point :
1629  base_element(base).get_generalized_support_points())
1630  {
1631  // Is point already an element of generalized_support_points?
1632  const auto p =
1633  std::find(std::begin(this->generalized_support_points),
1634  std::end(this->generalized_support_points),
1635  point);
1636 
1637  if (p == std::end(this->generalized_support_points))
1638  {
1639  // If no, update the table and add the point to the vector
1640  const auto n = this->generalized_support_points.size();
1641  generalized_support_points_index_table[base].push_back(n);
1642  this->generalized_support_points.push_back(point);
1643  }
1644  else
1645  {
1646  // If yes, just add the correct index to the table.
1647  const auto n = p - std::begin(this->generalized_support_points);
1648  generalized_support_points_index_table[base].push_back(n);
1649  }
1650  }
1651  }
1652 
1653 #ifdef DEBUG
1654  // check generalized_support_points_index_table for consistency
1655  for (unsigned int i = 0; i < base_elements.size(); ++i)
1656  {
1657  if (!base_element(i).has_generalized_support_points())
1658  continue;
1659 
1660  const auto &points =
1661  base_elements[i].first->get_generalized_support_points();
1662  for (unsigned int j = 0; j < points.size(); ++j)
1663  {
1664  const auto n = generalized_support_points_index_table[i][j];
1665  Assert(this->generalized_support_points[n] == points[j],
1666  ExcInternalError());
1667  }
1668  }
1669 #endif /* DEBUG */
1670  });
1671 
1672  // initialize quad dof index permutation in 3d and higher
1673  if (dim >= 3)
1674  init_tasks += Threads::new_task ([&]()
1675  {
1676  // the array into which we want to write should have the correct size
1677  // already.
1678  Assert (this->adjust_quad_dof_index_for_face_orientation_table.n_elements()==
1679  8*this->dofs_per_quad, ExcInternalError());
1680 
1681  // to obtain the shifts for this composed element, copy the shift
1682  // information of the base elements
1683  unsigned int index = 0;
1684  for (unsigned int b=0; b<this->n_base_elements(); ++b)
1685  {
1686  const Table<2,int> &temp
1687  = this->base_element(b).adjust_quad_dof_index_for_face_orientation_table;
1688  for (unsigned int c=0; c<this->element_multiplicity(b); ++c)
1689  {
1690  for (unsigned int i=0; i<temp.size(0); ++i)
1691  for (unsigned int j=0; j<8; ++j)
1692  this->adjust_quad_dof_index_for_face_orientation_table(index+i,j)=
1693  temp(i,j);
1694  index += temp.size(0);
1695  }
1696  }
1697  Assert (index == this->dofs_per_quad,
1698  ExcInternalError());
1699 
1700  // additionally compose the permutation information for lines
1701  Assert (this->adjust_line_dof_index_for_line_orientation_table.size()==
1702  this->dofs_per_line, ExcInternalError());
1703  index = 0;
1704  for (unsigned int b=0; b<this->n_base_elements(); ++b)
1705  {
1706  const std::vector<int> &temp2
1707  = this->base_element(b).adjust_line_dof_index_for_line_orientation_table;
1708  for (unsigned int c=0; c<this->element_multiplicity(b); ++c)
1709  {
1710  std::copy(temp2.begin(), temp2.end(),
1711  this->adjust_line_dof_index_for_line_orientation_table.begin()
1712  +index);
1713  index += temp2.size();
1714  }
1715  }
1716  Assert (index == this->dofs_per_line,
1717  ExcInternalError());
1718  });
1719 
1720  // wait for all of this to finish
1721  init_tasks.join_all();
1722 }
1723 
1724 
1725 
1726 template <int dim, int spacedim>
1727 bool
1730 {
1731  for (unsigned int b=0; b<this->n_base_elements(); ++b)
1732  if (base_element(b).hp_constraints_are_implemented() == false)
1733  return false;
1734 
1735  return true;
1736 }
1737 
1738 
1739 
1740 template <int dim, int spacedim>
1741 void
1744  FullMatrix<double> &interpolation_matrix) const
1745 {
1746  Assert (interpolation_matrix.n() == this->dofs_per_face,
1747  ExcDimensionMismatch (interpolation_matrix.n(),
1748  this->dofs_per_face));
1749  Assert (interpolation_matrix.m() == x_source_fe.dofs_per_face,
1750  ExcDimensionMismatch (interpolation_matrix.m(),
1751  x_source_fe.dofs_per_face));
1752 
1753  // since dofs for each base are independent, we only have to stack things up
1754  // from base element to base element
1755  //
1756  // the problem is that we have to work with two FEs (this and
1757  // fe_other). only deal with the case that both are FESystems and that they
1758  // both have the same number of bases (counting multiplicity) each of which
1759  // match in their number of components. this covers
1760  // FESystem(FE_Q(p),1,FE_Q(q),2) vs FESystem(FE_Q(r),2,FE_Q(s),1), but not
1761  // FESystem(FE_Q(p),1,FE_Q(q),2) vs
1762  // FESystem(FESystem(FE_Q(r),2),1,FE_Q(s),1)
1763  if (const auto *fe_other_system = dynamic_cast<const FESystem<dim,spacedim>*>(&x_source_fe))
1764  {
1765  // clear matrix, since we will not get to set all elements
1766  interpolation_matrix = 0;
1767 
1768  // loop over all the base elements of this and the other element, counting
1769  // their multiplicities
1770  unsigned int base_index = 0,
1771  base_index_other = 0;
1772  unsigned int multiplicity = 0,
1773  multiplicity_other = 0;
1774 
1775  FullMatrix<double> base_to_base_interpolation;
1776 
1777  while (true)
1778  {
1780  &base = base_element(base_index),
1781  &base_other = fe_other_system->base_element(base_index_other);
1782 
1783  Assert (base.n_components() == base_other.n_components(),
1784  ExcNotImplemented());
1785 
1786  // get the interpolation from the bases
1787  base_to_base_interpolation.reinit (base_other.dofs_per_face,
1788  base.dofs_per_face);
1789  base.get_face_interpolation_matrix (base_other,
1790  base_to_base_interpolation);
1791 
1792  // now translate entries. we'd like to have something like
1793  // face_base_to_system_index, but that doesn't exist. rather, all we
1794  // have is the reverse. well, use that then
1795  for (unsigned int i=0; i<this->dofs_per_face; ++i)
1796  if (this->face_system_to_base_index(i).first
1797  ==
1798  std::make_pair (base_index, multiplicity))
1799  for (unsigned int j=0; j<fe_other_system->dofs_per_face; ++j)
1800  if (fe_other_system->face_system_to_base_index(j).first
1801  ==
1802  std::make_pair (base_index_other, multiplicity_other))
1803  interpolation_matrix(j, i)
1804  = base_to_base_interpolation(fe_other_system->face_system_to_base_index(j).second,
1805  this->face_system_to_base_index(i).second);
1806 
1807  // advance to the next base element for this and the other fe_system;
1808  // see if we can simply advance the multiplicity by one, or if have to
1809  // move on to the next base element
1810  ++multiplicity;
1811  if (multiplicity == this->element_multiplicity(base_index))
1812  {
1813  multiplicity = 0;
1814  ++base_index;
1815  }
1816  ++multiplicity_other;
1817  if (multiplicity_other ==
1818  fe_other_system->element_multiplicity(base_index_other))
1819  {
1820  multiplicity_other = 0;
1821  ++base_index_other;
1822  }
1823 
1824  // see if we have reached the end of the present element. if so, we
1825  // should have reached the end of the other one as well
1826  if (base_index == this->n_base_elements())
1827  {
1828  Assert (base_index_other == fe_other_system->n_base_elements(),
1829  ExcInternalError());
1830  break;
1831  }
1832 
1833  // if we haven't reached the end of this element, we shouldn't have
1834  // reached the end of the other one either
1835  Assert (base_index_other != fe_other_system->n_base_elements(),
1836  ExcInternalError());
1837  }
1838  }
1839  else
1840  {
1841  // repeat the cast to make the exception message more useful
1842  AssertThrow ((dynamic_cast<const FESystem<dim,spacedim>*>(&x_source_fe) != nullptr),
1843  (typename FiniteElement<dim,spacedim>::
1844  ExcInterpolationNotImplemented()));
1845  }
1846 }
1847 
1848 
1849 
1850 template <int dim, int spacedim>
1851 void
1854  const unsigned int subface,
1855  FullMatrix<double> &interpolation_matrix) const
1856 {
1857  AssertThrow ((x_source_fe.get_name().find ("FE_System<") == 0)
1858  ||
1859  (dynamic_cast<const FESystem<dim,spacedim>*>(&x_source_fe) != nullptr),
1860  (typename FiniteElement<dim,spacedim>::
1861  ExcInterpolationNotImplemented()));
1862 
1863  Assert (interpolation_matrix.n() == this->dofs_per_face,
1864  ExcDimensionMismatch (interpolation_matrix.n(),
1865  this->dofs_per_face));
1866  Assert (interpolation_matrix.m() == x_source_fe.dofs_per_face,
1867  ExcDimensionMismatch (interpolation_matrix.m(),
1868  x_source_fe.dofs_per_face));
1869 
1870  // since dofs for each base are independent, we only have to stack things up
1871  // from base element to base element
1872  //
1873  // the problem is that we have to work with two FEs (this and
1874  // fe_other). only deal with the case that both are FESystems and that they
1875  // both have the same number of bases (counting multiplicity) each of which
1876  // match in their number of components. this covers
1877  // FESystem(FE_Q(p),1,FE_Q(q),2) vs FESystem(FE_Q(r),2,FE_Q(s),1), but not
1878  // FESystem(FE_Q(p),1,FE_Q(q),2) vs
1879  // FESystem(FESystem(FE_Q(r),2),1,FE_Q(s),1)
1880  const FESystem<dim,spacedim> *fe_other_system
1881  = dynamic_cast<const FESystem<dim,spacedim>*>(&x_source_fe);
1882  if (fe_other_system != nullptr)
1883  {
1884  // clear matrix, since we will not get to set all elements
1885  interpolation_matrix = 0;
1886 
1887  // loop over all the base elements of this and the other element, counting
1888  // their multiplicities
1889  unsigned int base_index = 0,
1890  base_index_other = 0;
1891  unsigned int multiplicity = 0,
1892  multiplicity_other = 0;
1893 
1894  FullMatrix<double> base_to_base_interpolation;
1895 
1896  while (true)
1897  {
1899  &base = base_element(base_index),
1900  &base_other = fe_other_system->base_element(base_index_other);
1901 
1902  Assert (base.n_components() == base_other.n_components(),
1903  ExcNotImplemented());
1904 
1905  // get the interpolation from the bases
1906  base_to_base_interpolation.reinit (base_other.dofs_per_face,
1907  base.dofs_per_face);
1908  base.get_subface_interpolation_matrix (base_other,
1909  subface,
1910  base_to_base_interpolation);
1911 
1912  // now translate entries. we'd like to have something like
1913  // face_base_to_system_index, but that doesn't exist. rather, all we
1914  // have is the reverse. well, use that then
1915  for (unsigned int i=0; i<this->dofs_per_face; ++i)
1916  if (this->face_system_to_base_index(i).first
1917  ==
1918  std::make_pair (base_index, multiplicity))
1919  for (unsigned int j=0; j<fe_other_system->dofs_per_face; ++j)
1920  if (fe_other_system->face_system_to_base_index(j).first
1921  ==
1922  std::make_pair (base_index_other, multiplicity_other))
1923  interpolation_matrix(j, i)
1924  = base_to_base_interpolation(fe_other_system->face_system_to_base_index(j).second,
1925  this->face_system_to_base_index(i).second);
1926 
1927  // advance to the next base element for this and the other fe_system;
1928  // see if we can simply advance the multiplicity by one, or if have to
1929  // move on to the next base element
1930  ++multiplicity;
1931  if (multiplicity == this->element_multiplicity(base_index))
1932  {
1933  multiplicity = 0;
1934  ++base_index;
1935  }
1936  ++multiplicity_other;
1937  if (multiplicity_other ==
1938  fe_other_system->element_multiplicity(base_index_other))
1939  {
1940  multiplicity_other = 0;
1941  ++base_index_other;
1942  }
1943 
1944  // see if we have reached the end of the present element. if so, we
1945  // should have reached the end of the other one as well
1946  if (base_index == this->n_base_elements())
1947  {
1948  Assert (base_index_other == fe_other_system->n_base_elements(),
1949  ExcInternalError());
1950  break;
1951  }
1952 
1953  // if we haven't reached the end of this element, we shouldn't have
1954  // reached the end of the other one either
1955  Assert (base_index_other != fe_other_system->n_base_elements(),
1956  ExcInternalError());
1957  }
1958  }
1959  else
1960  {
1961  // we should have caught this at the start, but check again anyway
1962  Assert(fe_other_system != nullptr, (typename FiniteElement<dim,spacedim>::
1963  ExcInterpolationNotImplemented()));
1964  }
1965 }
1966 
1967 
1968 
1969 template <int dim, int spacedim>
1970 template <int structdim>
1971 std::vector<std::pair<unsigned int, unsigned int> >
1973 {
1974  // since dofs on each subobject (vertex, line, ...) are ordered such that
1975  // first come all from the first base element all multiplicities, then
1976  // second base element all multiplicities, etc., we simply have to stack all
1977  // the identities after each other
1978  //
1979  // the problem is that we have to work with two FEs (this and
1980  // fe_other). only deal with the case that both are FESystems and that they
1981  // both have the same number of bases (counting multiplicity) each of which
1982  // match in their number of components. this covers
1983  // FESystem(FE_Q(p),1,FE_Q(q),2) vs FESystem(FE_Q(r),2,FE_Q(s),1), but not
1984  // FESystem(FE_Q(p),1,FE_Q(q),2) vs
1985  // FESystem(FESystem(FE_Q(r),2),1,FE_Q(s),1)
1986  if (const FESystem<dim,spacedim> *fe_other_system
1987  = dynamic_cast<const FESystem<dim,spacedim>*>(&fe_other))
1988  {
1989  // loop over all the base elements of this and the other element,
1990  // counting their multiplicities
1991  unsigned int base_index = 0,
1992  base_index_other = 0;
1993  unsigned int multiplicity = 0,
1994  multiplicity_other = 0;
1995 
1996  // we also need to keep track of the number of dofs already treated for
1997  // each of the elements
1998  unsigned int dof_offset = 0,
1999  dof_offset_other = 0;
2000 
2001  std::vector<std::pair<unsigned int, unsigned int> > identities;
2002 
2003  while (true)
2004  {
2006  &base = base_element(base_index),
2007  &base_other = fe_other_system->base_element(base_index_other);
2008 
2009  Assert (base.n_components() == base_other.n_components(),
2010  ExcNotImplemented());
2011 
2012  // now translate the identities returned by the base elements to the
2013  // indices of this system element
2014  std::vector<std::pair<unsigned int, unsigned int> > base_identities;
2015  switch (structdim)
2016  {
2017  case 0:
2018  base_identities = base.hp_vertex_dof_identities (base_other);
2019  break;
2020  case 1:
2021  base_identities = base.hp_line_dof_identities (base_other);
2022  break;
2023  case 2:
2024  base_identities = base.hp_quad_dof_identities (base_other);
2025  break;
2026  default:
2027  Assert (false, ExcNotImplemented());
2028  }
2029 
2030  for (unsigned int i=0; i<base_identities.size(); ++i)
2031  identities.emplace_back (base_identities[i].first + dof_offset,
2032  base_identities[i].second + dof_offset_other);
2033 
2034  // record the dofs treated above as already taken care of
2035  dof_offset += base.template n_dofs_per_object<structdim>();
2036  dof_offset_other += base_other.template n_dofs_per_object<structdim>();
2037 
2038  // advance to the next base element for this and the other
2039  // fe_system; see if we can simply advance the multiplicity by one,
2040  // or if have to move on to the next base element
2041  ++multiplicity;
2042  if (multiplicity == this->element_multiplicity(base_index))
2043  {
2044  multiplicity = 0;
2045  ++base_index;
2046  }
2047  ++multiplicity_other;
2048  if (multiplicity_other ==
2049  fe_other_system->element_multiplicity(base_index_other))
2050  {
2051  multiplicity_other = 0;
2052  ++base_index_other;
2053  }
2054 
2055  // see if we have reached the end of the present element. if so, we
2056  // should have reached the end of the other one as well
2057  if (base_index == this->n_base_elements())
2058  {
2059  Assert (base_index_other == fe_other_system->n_base_elements(),
2060  ExcInternalError());
2061  break;
2062  }
2063 
2064  // if we haven't reached the end of this element, we shouldn't have
2065  // reached the end of the other one either
2066  Assert (base_index_other != fe_other_system->n_base_elements(),
2067  ExcInternalError());
2068  }
2069 
2070  return identities;
2071  }
2072  else
2073  {
2074  Assert (false, ExcNotImplemented());
2075  return std::vector<std::pair<unsigned int, unsigned int> >();
2076  }
2077 }
2078 
2079 
2080 
2081 template <int dim, int spacedim>
2082 std::vector<std::pair<unsigned int, unsigned int> >
2084 {
2085  return hp_object_dof_identities<0> (fe_other);
2086 }
2087 
2088 template <int dim, int spacedim>
2089 std::vector<std::pair<unsigned int, unsigned int> >
2091 {
2092  return hp_object_dof_identities<1> (fe_other);
2093 }
2094 
2095 
2096 
2097 template <int dim, int spacedim>
2098 std::vector<std::pair<unsigned int, unsigned int> >
2100 {
2101  return hp_object_dof_identities<2> (fe_other);
2102 }
2103 
2104 
2105 
2106 template <int dim, int spacedim>
2110 {
2111  // at present all we can do is to compare with other FESystems that have the
2112  // same number of components and bases
2113  if (const FESystem<dim,spacedim> *fe_sys_other
2114  = dynamic_cast<const FESystem<dim,spacedim>*>(&fe_other))
2115  {
2116  Assert (this->n_components() == fe_sys_other->n_components(),
2117  ExcNotImplemented());
2118  Assert (this->n_base_elements() == fe_sys_other->n_base_elements(),
2119  ExcNotImplemented());
2120 
2123 
2124  // loop over all base elements and do some sanity checks
2125  for (unsigned int b=0; b<this->n_base_elements(); ++b)
2126  {
2127  Assert (this->base_element(b).n_components() ==
2128  fe_sys_other->base_element(b).n_components(),
2129  ExcNotImplemented());
2130  Assert (this->element_multiplicity(b) ==
2131  fe_sys_other->element_multiplicity(b),
2132  ExcNotImplemented());
2133 
2134  // for this pair of base elements, check who dominates and combine
2135  // with previous result
2137  base_domination = (this->base_element(b)
2138  .compare_for_face_domination (fe_sys_other->base_element(b)));
2139  domination = domination & base_domination;
2140  }
2141 
2142  return domination;
2143  }
2144 
2145  Assert (false, ExcNotImplemented());
2147 }
2148 
2149 
2150 
2151 template <int dim, int spacedim>
2153 FESystem<dim,spacedim>::base_element (const unsigned int index) const
2154 {
2155  Assert (index < base_elements.size(),
2156  ExcIndexRange(index, 0, base_elements.size()));
2157  return *base_elements[index].first;
2158 }
2159 
2160 
2161 
2162 template <int dim, int spacedim>
2163 bool
2164 FESystem<dim,spacedim>::has_support_on_face (const unsigned int shape_index,
2165  const unsigned int face_index) const
2166 {
2167  return (base_element(this->system_to_base_index(shape_index).first.first)
2168  .has_support_on_face(this->system_to_base_index(shape_index).second,
2169  face_index));
2170 }
2171 
2172 
2173 
2174 template <int dim, int spacedim>
2175 Point<dim>
2176 FESystem<dim,spacedim>::unit_support_point (const unsigned int index) const
2177 {
2178  Assert (index < this->dofs_per_cell,
2179  ExcIndexRange (index, 0, this->dofs_per_cell));
2180  Assert ((this->unit_support_points.size() == this->dofs_per_cell) ||
2181  (this->unit_support_points.size() == 0),
2183 
2184  // let's see whether we have the information pre-computed
2185  if (this->unit_support_points.size() != 0)
2186  return this->unit_support_points[index];
2187  else
2188  // no. ask the base element whether it would like to provide this
2189  // information
2190  return (base_element(this->system_to_base_index(index).first.first)
2191  .unit_support_point(this->system_to_base_index(index).second));
2192 }
2193 
2194 
2195 
2196 template <int dim, int spacedim>
2197 Point<dim-1>
2198 FESystem<dim,spacedim>::unit_face_support_point (const unsigned int index) const
2199 {
2200  Assert (index < this->dofs_per_face,
2201  ExcIndexRange (index, 0, this->dofs_per_face));
2202  Assert ((this->unit_face_support_points.size() == this->dofs_per_face) ||
2203  (this->unit_face_support_points.size() == 0),
2205 
2206  // let's see whether we have the information pre-computed
2207  if (this->unit_face_support_points.size() != 0)
2208  return this->unit_face_support_points[index];
2209  else
2210  // no. ask the base element whether it would like to provide this
2211  // information
2212  return (base_element(this->face_system_to_base_index(index).first.first)
2213  .unit_face_support_point(this->face_system_to_base_index(index).second));
2214 }
2215 
2216 
2217 
2218 template <int dim, int spacedim>
2219 std::pair<Table<2,bool>, std::vector<unsigned int> >
2221 {
2222  // Note that this->n_components() is actually only an estimate of how many
2223  // constant modes we will need. There might be more than one such mode
2224  // (e.g. FE_Q_DG0).
2225  Table<2,bool> constant_modes(this->n_components(), this->dofs_per_cell);
2226  std::vector<unsigned int> components;
2227  for (unsigned int i=0; i<base_elements.size(); ++i)
2228  {
2229  const std::pair<Table<2,bool>, std::vector<unsigned int> >
2230  base_table = base_elements[i].first->get_constant_modes();
2231  AssertDimension(base_table.first.n_rows(), base_table.second.size());
2232  const unsigned int element_multiplicity = this->element_multiplicity(i);
2233 
2234  // there might be more than one constant mode for some scalar elements,
2235  // so make sure the table actually fits: Create a new table with more
2236  // rows
2237  const unsigned int comp = components.size();
2238  if (constant_modes.n_rows() < comp+base_table.first.n_rows()*element_multiplicity)
2239  {
2240  Table<2,bool> new_constant_modes(comp+base_table.first.n_rows()*
2241  element_multiplicity,
2242  constant_modes.n_cols());
2243  for (unsigned int r=0; r<comp; ++r)
2244  for (unsigned int c=0; c<this->dofs_per_cell; ++c)
2245  new_constant_modes(r,c) = constant_modes(r,c);
2246  constant_modes.swap(new_constant_modes);
2247  }
2248 
2249  // next, fill the constant modes from the individual components as well
2250  // as the component numbers corresponding to the constant mode rows
2251  for (unsigned int k=0; k<this->dofs_per_cell; ++k)
2252  {
2253  std::pair<std::pair<unsigned int,unsigned int>, unsigned int> ind
2254  = this->system_to_base_index(k);
2255  if (ind.first.first == i)
2256  for (unsigned int c=0; c<base_table.first.n_rows(); ++c)
2257  constant_modes(comp+ind.first.second*base_table.first.n_rows()+c,k)
2258  = base_table.first(c,ind.second);
2259  }
2260  for (unsigned int r=0; r<element_multiplicity; ++r)
2261  for (unsigned int c=0; c<base_table.second.size(); ++c)
2262  components.push_back(comp+r*this->base_elements[i].first->n_components()
2263  +base_table.second[c]);
2264  }
2265  AssertDimension(components.size(), constant_modes.n_rows());
2266  return std::pair<Table<2,bool>, std::vector<unsigned int> >(constant_modes,
2267  components);
2268 }
2269 
2270 
2271 
2272 template <int dim, int spacedim>
2273 void
2276  std::vector<double> &dof_values) const
2277 {
2278  Assert(this->has_generalized_support_points(),
2279  ExcMessage("The FESystem does not have generalized support points"));
2280 
2281  AssertDimension(point_values.size(),
2282  this->get_generalized_support_points().size());
2283  AssertDimension(dof_values.size(), this->dofs_per_cell);
2284 
2285  std::vector<double> base_dof_values;
2286  std::vector<Vector<double> > base_point_values;
2287 
2288  // loop over all base elements (respecting multiplicity) and let them do
2289  // the work on their share of the input argument
2290 
2291  unsigned int current_vector_component = 0;
2292  for (unsigned int base = 0; base < base_elements.size(); ++base)
2293  {
2294  // We need access to the base_element, its multiplicity, the
2295  // number of generalized support points (n_base_points) and the
2296  // number of components we're dealing with.
2297  const auto &base_element = this->base_element(base);
2298  const unsigned int multiplicity = this->element_multiplicity(base);
2299  const unsigned int n_base_dofs = base_element.dofs_per_cell;
2300  const unsigned int n_base_components = base_element.n_components();
2301 
2302  // If the number of base degrees of freedom is zero, there is nothing
2303  // to do, skip the rest of the body in this case and continue with
2304  // the next element
2305  if (n_base_dofs == 0)
2306  {
2307  current_vector_component += multiplicity * n_base_components;
2308  continue;
2309  }
2310 
2311  if (base_element.has_generalized_support_points())
2312  {
2313  const unsigned int n_base_points =
2314  base_element.get_generalized_support_points().size();
2315 
2316  base_dof_values.resize(n_base_dofs);
2317  base_point_values.resize(n_base_points);
2318 
2319  for (unsigned int m = 0; m < multiplicity;
2320  ++m, current_vector_component += n_base_components)
2321  {
2322  // populate base_point_values for a recursive call to
2323  // convert_generalized_support_point_values_to_dof_values
2324  for (unsigned int j = 0; j < base_point_values.size(); ++j)
2325  {
2326  base_point_values[j].reinit(n_base_components, false);
2327 
2328  const auto n =
2329  generalized_support_points_index_table[base][j];
2330 
2331  // we have to extract the correct slice out of the global
2332  // vector of values:
2333  const auto begin =
2334  std::begin(point_values[n]) + current_vector_component;
2335  const auto end = begin + n_base_components;
2336  std::copy(begin, end, std::begin(base_point_values[j]));
2337  }
2338 
2339  base_element
2340  .convert_generalized_support_point_values_to_dof_values(
2341  base_point_values, base_dof_values);
2342 
2343  // Finally put these dof values back into global dof values
2344  // vector.
2345 
2346  // To do this, we could really use a base_to_system_index()
2347  // function, but that doesn't exist -- just do it by using the
2348  // reverse table -- the amount of work done here is not worth
2349  // trying to optimizing this.
2350  for (unsigned int i = 0; i < this->dofs_per_cell; ++i)
2351  if (this->system_to_base_index(i).first ==
2352  std::make_pair(base, m))
2353  dof_values[i] =
2354  base_dof_values[this->system_to_base_index(i).second];
2355  } /*for*/
2356  }
2357  else
2358  {
2359  // If the base element is non-interpolatory, assign NaN to all
2360  // DoFs associated to it.
2361 
2362  // To do this, we could really use a base_to_system_index()
2363  // function, but that doesn't exist -- just do it by using the
2364  // reverse table -- the amount of work done here is not worth
2365  // trying to optimizing this.
2366  for (unsigned int m = 0; m < multiplicity; ++m)
2367  for (unsigned int i = 0; i < this->dofs_per_cell; ++i)
2368  if (this->system_to_base_index(i).first ==
2369  std::make_pair(base, m))
2370  dof_values[i] = std::numeric_limits<double>::signaling_NaN();
2371 
2372  current_vector_component += multiplicity * n_base_components;
2373  }
2374  } /*for*/
2375 }
2376 
2377 
2378 
2379 template <int dim, int spacedim>
2380 std::size_t
2382 {
2383  // neglect size of data stored in @p{base_elements} due to some problems
2384  // with the compiler. should be neglectable after all, considering the size
2385  // of the data of the subelements
2386  std::size_t mem = (FiniteElement<dim,spacedim>::memory_consumption () +
2387  sizeof (base_elements));
2388  for (unsigned int i=0; i<base_elements.size(); ++i)
2389  mem += MemoryConsumption::memory_consumption (*base_elements[i].first);
2390  return mem;
2391 }
2392 
2393 
2394 
2395 
2396 // explicit instantiations
2397 #include "fe_system.inst"
2398 
2399 DEAL_II_NAMESPACE_CLOSE
Shape function values.
size_type m() const
Definition: tria.h:67
static const unsigned int invalid_unsigned_int
Definition: types.h:173
virtual std::unique_ptr< typename FiniteElement< dim, spacedim >::InternalDataBase > get_face_data(const UpdateFlags update_flags, const Mapping< dim, spacedim > &mapping, const Quadrature< dim-1 > &quadrature, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const
Definition: fe_system.cc:940
virtual std::unique_ptr< FiniteElement< dim, spacedim > > clone() const
Definition: fe_system.cc:316
void build_interface_constraints()
Definition: fe_system.cc:1287
#define AssertDimension(dim1, dim2)
Definition: exceptions.h:1248
virtual void get_face_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const
Definition: fe.cc:863
void initialize(const std::vector< const FiniteElement< dim, spacedim > *> &fes, const std::vector< unsigned int > &multiplicities)
Definition: fe_system.cc:1470
void swap(TableBase< N, T > &v)
std::vector< std::pair< unsigned int, unsigned int > > hp_object_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe_system.cc:1972
virtual std::unique_ptr< typename FiniteElement< dim, spacedim >::InternalDataBase > get_data(const UpdateFlags update_flags, const Mapping< dim, spacedim > &mapping, const Quadrature< dim > &quadrature, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const
Definition: fe_system.cc:884
unsigned int n_nonzero_components(const unsigned int i) const
Definition: fe.h:3217
Task< RT > new_task(const std::function< RT()> &function)
virtual double shape_value_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const
Definition: fe_system.cc:373
virtual bool hp_constraints_are_implemented() const
Definition: fe_system.cc:1729
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe_system.cc:2083
std::vector< std::pair< std::unique_ptr< const FiniteElement< dim, spacedim > >, unsigned int > > base_elements
Definition: fe_system.h:1055
void build_face_tables(std::vector< std::pair< std::pair< unsigned int, unsigned int >, unsigned int > > &face_system_to_base_table, std::vector< std::pair< unsigned int, unsigned int > > &face_system_to_component_table, const FiniteElement< dim, spacedim > &finite_element, const bool do_tensor_product=true)
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_quad_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe.cc:918
virtual std::pair< Table< 2, bool >, std::vector< unsigned int > > get_constant_modes() const
Definition: fe_system.cc:2220
virtual Point< dim > unit_support_point(const unsigned int index) const
Definition: fe_system.cc:2176
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
virtual void fill_fe_subface_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const unsigned int sub_no, const Quadrature< dim-1 > &quadrature, const Mapping< dim, spacedim > &mapping, const typename Mapping< dim, spacedim >::InternalDataBase &mapping_internal, const ::internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &mapping_data, const InternalDataBase &fe_internal, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const =0
static ::ExceptionBase & ExcInterpolationNotImplemented()
static ::ExceptionBase & ExcIndexRange(int arg1, int arg2, int arg3)
InternalData(const unsigned int n_base_elements)
Definition: fe_system.cc:53
virtual Tensor< 3, dim > shape_3rd_derivative(const unsigned int i, const Point< dim > &p) const
Definition: fe_system.cc:500
virtual UpdateFlags requires_update_flags(const UpdateFlags update_flags) const
Definition: fe_system.cc:869
virtual Tensor< 3, dim > shape_3rd_derivative_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const
Definition: fe_system.cc:515
virtual std::string get_name() const
Definition: fe_system.cc:285
static ::ExceptionBase & ExcMessage(std::string arg1)
virtual Tensor< 4, dim > shape_4th_derivative_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const
Definition: fe_system.cc:560
virtual std::size_t memory_consumption() const
Definition: fe.cc:1179
size_type n() const
No update.
virtual void convert_generalized_support_point_values_to_dof_values(const std::vector< Vector< double > > &support_point_values, std::vector< double > &dof_values) const
Definition: fe_system.cc:2275
Third derivatives of shape functions.
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_quad_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe_system.cc:2099
void reinit(const TableIndices< N > &new_size, const bool omit_default_initialization=false)
#define Assert(cond, exc)
Definition: exceptions.h:1142
unsigned int element_multiplicity(const unsigned int index) const
Definition: fe.h:3056
UpdateFlags
static ::ExceptionBase & ExcDimensionMismatch(std::size_t arg1, std::size_t arg2)
Abstract base class for mapping classes.
Definition: dof_tools.h:46
Definition: fe.h:36
virtual const FullMatrix< double > & get_prolongation_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const
Definition: fe_system.cc:760
virtual Tensor< 2, dim > shape_grad_grad(const unsigned int i, const Point< dim > &p) const
Definition: fe_system.cc:455
virtual void get_subface_interpolation_matrix(const FiniteElement< dim, spacedim > &source, const unsigned int subface, FullMatrix< double > &matrix) const
Definition: fe.cc:879
void initialize(const unsigned int n_quadrature_points, const FiniteElement< dim, spacedim > &fe, const UpdateFlags flags)
Definition: fe_values.cc:2662
void set_fe_data(const unsigned int base_no, std::unique_ptr< typename FiniteElement< dim, spacedim >::InternalDataBase >)
Definition: fe_system.cc:85
virtual void fill_fe_face_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const Quadrature< dim-1 > &quadrature, const Mapping< dim, spacedim > &mapping, const typename Mapping< dim, spacedim >::InternalDataBase &mapping_internal, const ::internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &mapping_data, const InternalDataBase &fe_internal, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const =0
virtual const FiniteElement< dim, spacedim > & base_element(const unsigned int index) const
Definition: fe.cc:1242
virtual std::string get_name() const =0
virtual double shape_value(const unsigned int i, const Point< dim > &p) const
Definition: fe_system.cc:358
virtual void get_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const
Definition: fe_system.cc:590
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_vertex_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe.cc:896
Second derivatives of shape functions.
std::string dim_string(const int dim, const int spacedim)
Definition: utilities.cc:176
virtual Tensor< 1, dim > shape_grad_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const
Definition: fe_system.cc:425
unsigned int size() const
const unsigned int dofs_per_cell
Definition: fe_base.h:295
virtual void get_subface_interpolation_matrix(const FiniteElement< dim, spacedim > &source, const unsigned int subface, FullMatrix< double > &matrix) const
Definition: fe_system.cc:1853
virtual const FiniteElement< dim, spacedim > & base_element(const unsigned int index) const
Definition: fe_system.cc:2153
virtual void get_face_interpolation_matrix(const FiniteElement< dim, spacedim > &source, FullMatrix< double > &matrix) const
Definition: fe_system.cc:1743
virtual std::size_t memory_consumption() const
Definition: fe_system.cc:2381
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe_system.cc:2090
virtual std::vector< std::pair< unsigned int, unsigned int > > hp_line_dof_identities(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe.cc:907
size_type size(const unsigned int i) const
std::pair< std::pair< unsigned int, unsigned int >, unsigned int > face_system_to_base_index(const unsigned int index) const
Definition: fe.h:3131
virtual FiniteElementDomination::Domination compare_for_face_domination(const FiniteElement< dim, spacedim > &fe_other) const
Definition: fe_system.cc:2109
unsigned int n_components() const
FiniteElement< dim, spacedim >::InternalDataBase & get_fe_data(const unsigned int base_no) const
Definition: fe_system.cc:73
virtual Point< dim-1 > unit_face_support_point(const unsigned int index) const
Definition: fe_system.cc:2198
Shape function gradients.
void build_cell_tables(std::vector< std::pair< std::pair< unsigned int, unsigned int >, unsigned int > > &system_to_base_table, std::vector< std::pair< unsigned int, unsigned int > > &system_to_component_table, std::vector< std::pair< std::pair< unsigned int, unsigned int >, unsigned int > > &component_to_base_table, const FiniteElement< dim, spacedim > &finite_element, const bool do_tensor_product=true)
FESystem(const FiniteElement< dim, spacedim > &fe, const unsigned int n_elements)
Definition: fe_system.cc:115
virtual Tensor< 4, dim > shape_4th_derivative(const unsigned int i, const Point< dim > &p) const
Definition: fe_system.cc:545
const unsigned int dofs_per_face
Definition: fe_base.h:288
internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > & get_fe_output_object(const unsigned int base_no) const
Definition: fe_system.cc:98
static ::ExceptionBase & ExcNotImplemented()
void compute_fill(const Mapping< dim, spacedim > &mapping, const typename Triangulation< dim, spacedim >::cell_iterator &cell, const unsigned int face_no, const unsigned int sub_no, const Quadrature< dim_1 > &quadrature, const CellSimilarity::Similarity cell_similarity, const typename Mapping< dim, spacedim >::InternalDataBase &mapping_internal, const typename FiniteElement< dim, spacedim >::InternalDataBase &fe_data, const internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &mapping_data, internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const
Definition: fe_system.cc:1113
virtual unsigned int face_to_cell_index(const unsigned int face_dof_index, const unsigned int face, const bool face_orientation=true, const bool face_flip=false, const bool face_rotation=false) const
Definition: fe_system.cc:824
virtual bool has_support_on_face(const unsigned int shape_index, const unsigned int face_index) const
Definition: fe_system.cc:2164
virtual std::unique_ptr< typename FiniteElement< dim, spacedim >::InternalDataBase > get_subface_data(const UpdateFlags update_flags, const Mapping< dim, spacedim > &mapping, const Quadrature< dim-1 > &quadrature, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const
Definition: fe_system.cc:998
unsigned int n_components(const DoFHandler< dim, spacedim > &dh)
unsigned int n_base_elements() const
Definition: fe.h:3046
virtual const FullMatrix< double > & get_restriction_matrix(const unsigned int child, const RefinementCase< dim > &refinement_case=RefinementCase< dim >::isotropic_refinement) const
Definition: fe_system.cc:671
virtual void fill_fe_values(const typename Triangulation< dim, spacedim >::cell_iterator &cell, const CellSimilarity::Similarity cell_similarity, const Quadrature< dim > &quadrature, const Mapping< dim, spacedim > &mapping, const typename Mapping< dim, spacedim >::InternalDataBase &mapping_internal, const ::internal::FEValuesImplementation::MappingRelatedData< dim, spacedim > &mapping_data, const InternalDataBase &fe_internal, ::internal::FEValuesImplementation::FiniteElementRelatedData< dim, spacedim > &output_data) const =0
virtual Tensor< 2, dim > shape_grad_grad_component(const unsigned int i, const Point< dim > &p, const unsigned int component) const
Definition: fe_system.cc:470
UpdateFlags update_each
Definition: fe.h:702
std::enable_if< std::is_fundamental< T >::value, std::size_t >::type memory_consumption(const T &t)
virtual const FiniteElement< dim, spacedim > & get_sub_fe(const unsigned int first_component, const unsigned int n_selected_components) const
Definition: fe_system.cc:334
std::vector< std::pair< std::pair< unsigned int, unsigned int >, unsigned int > > system_to_base_table
Definition: fe.h:2499
virtual Tensor< 1, dim > shape_grad(const unsigned int i, const Point< dim > &p) const
Definition: fe_system.cc:410
static ::ExceptionBase & ExcInternalError()