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