1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2020 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
20 #include <deal.II/dofs/dof_accessor.h>
21
22 #include <deal.II/fe/fe.h>
23 #include <deal.II/fe/fe_values.h>
24 #include <deal.II/fe/mapping.h>
25
26 #include <deal.II/grid/tria.h>
27 #include <deal.II/grid/tria_iterator.h>
28
29 #include <algorithm>
30 #include <functional>
31 #include <numeric>
32 #include <typeinfo>
33
34 DEAL_II_NAMESPACE_OPEN
35
36
37 /*------------------------------- FiniteElement ----------------------*/
38
39
40 template <int dim, int spacedim>
InternalDataBase()41 FiniteElement<dim, spacedim>::InternalDataBase::InternalDataBase()
42 : update_each(update_default)
43 {}
44
45
46
47 template <int dim, int spacedim>
48 std::size_t
memory_consumption() const49 FiniteElement<dim, spacedim>::InternalDataBase::memory_consumption() const
50 {
51 return sizeof(*this);
52 }
53
54
55
56 template <int dim, int spacedim>
FiniteElement(const FiniteElementData<dim> & fe_data,const std::vector<bool> & r_i_a_f,const std::vector<ComponentMask> & nonzero_c)57 FiniteElement<dim, spacedim>::FiniteElement(
58 const FiniteElementData<dim> & fe_data,
59 const std::vector<bool> & r_i_a_f,
60 const std::vector<ComponentMask> &nonzero_c)
61 : FiniteElementData<dim>(fe_data)
62 , adjust_line_dof_index_for_line_orientation_table(
63 dim == 3 ? this->n_dofs_per_line() : 0)
64 , system_to_base_table(this->n_dofs_per_cell())
65 , component_to_base_table(this->components,
66 std::make_pair(std::make_pair(0U, 0U), 0U))
67 ,
68
69 // Special handling of vectors of length one: in this case, we
70 // assume that all entries were supposed to be equal
71 restriction_is_additive_flags(
72 r_i_a_f.size() == 1 ?
73 std::vector<bool>(fe_data.n_dofs_per_cell(), r_i_a_f[0]) :
74 r_i_a_f)
75 , nonzero_components(
76 nonzero_c.size() == 1 ?
77 std::vector<ComponentMask>(fe_data.n_dofs_per_cell(), nonzero_c[0]) :
78 nonzero_c)
79 , n_nonzero_components_table(compute_n_nonzero_components(nonzero_components))
80 , cached_primitivity(std::find_if(n_nonzero_components_table.begin(),
81 n_nonzero_components_table.end(),
82 [](const unsigned int n_components) {
83 return n_components != 1U;
84 }) == n_nonzero_components_table.end())
85 {
86 Assert(restriction_is_additive_flags.size() == this->n_dofs_per_cell(),
87 ExcDimensionMismatch(restriction_is_additive_flags.size(),
88 this->n_dofs_per_cell()));
89 AssertDimension(nonzero_components.size(), this->n_dofs_per_cell());
90 for (unsigned int i = 0; i < nonzero_components.size(); ++i)
91 {
92 Assert(nonzero_components[i].size() == this->n_components(),
93 ExcInternalError());
94 Assert(nonzero_components[i].n_selected_components() >= 1,
95 ExcInternalError());
96 Assert(n_nonzero_components_table[i] >= 1, ExcInternalError());
97 Assert(n_nonzero_components_table[i] <= this->n_components(),
98 ExcInternalError());
99 }
100
101 // initialize some tables in the default way, i.e. if there is only one
102 // (vector-)component; if the element is not primitive, leave these tables
103 // empty.
104 if (this->is_primitive())
105 {
106 system_to_component_table.resize(this->n_dofs_per_cell());
107 for (unsigned int j = 0; j < this->n_dofs_per_cell(); ++j)
108 system_to_component_table[j] = std::pair<unsigned, unsigned>(0, j);
109
110 face_system_to_component_table.resize(this->n_unique_faces());
111 for (unsigned int f = 0; f < this->n_unique_faces(); ++f)
112 {
113 face_system_to_component_table[f].resize(this->n_dofs_per_face(f));
114 for (unsigned int j = 0; j < this->n_dofs_per_face(f); ++j)
115 face_system_to_component_table[f][j] =
116 std::pair<unsigned, unsigned>(0, j);
117 }
118 }
119
120 for (unsigned int j = 0; j < this->n_dofs_per_cell(); ++j)
121 system_to_base_table[j] = std::make_pair(std::make_pair(0U, 0U), j);
122
123 face_system_to_base_table.resize(this->n_unique_faces());
124 for (unsigned int f = 0; f < this->n_unique_faces(); ++f)
125 {
126 face_system_to_base_table[f].resize(this->n_dofs_per_face(f));
127 for (unsigned int j = 0; j < this->n_dofs_per_face(f); ++j)
128 face_system_to_base_table[f][j] =
129 std::make_pair(std::make_pair(0U, 0U), j);
130 }
131
132 // Fill with default value; may be changed by constructor of derived class.
133 base_to_block_indices.reinit(1, 1);
134
135 // initialize the restriction and prolongation matrices. the default
136 // constructor of FullMatrix<dim> initializes them with size zero
137 prolongation.resize(RefinementCase<dim>::isotropic_refinement);
138 restriction.resize(RefinementCase<dim>::isotropic_refinement);
139 for (unsigned int ref = RefinementCase<dim>::cut_x;
140 ref < RefinementCase<dim>::isotropic_refinement + 1;
141 ++ref)
142 {
143 prolongation[ref - 1].resize(GeometryInfo<dim>::n_children(
144 RefinementCase<dim>(ref)),
145 FullMatrix<double>());
146 restriction[ref - 1].resize(GeometryInfo<dim>::n_children(
147 RefinementCase<dim>(ref)),
148 FullMatrix<double>());
149 }
150
151
152 if (dim == 3)
153 {
154 adjust_quad_dof_index_for_face_orientation_table.resize(
155 this->n_unique_quads());
156
157 for (unsigned int f = 0; f < this->n_unique_quads(); ++f)
158 {
159 adjust_quad_dof_index_for_face_orientation_table[f] = Table<2, int>(
160 this->n_dofs_per_quad(f),
161 ReferenceCell::internal::Info::get_cell(this->reference_cell_type())
162 .face_reference_cell_type(f) == ReferenceCell::Type::Quad ?
163 8 :
164 6);
165 adjust_quad_dof_index_for_face_orientation_table[f].fill(0);
166 }
167 }
168
169 unit_face_support_points.resize(this->n_unique_faces());
170 generalized_face_support_points.resize(this->n_unique_faces());
171 }
172
173
174
175 template <int dim, int spacedim>
176 std::pair<std::unique_ptr<FiniteElement<dim, spacedim>>, unsigned int>
operator ^(const unsigned int multiplicity) const177 FiniteElement<dim, spacedim>::operator^(const unsigned int multiplicity) const
178 {
179 return {this->clone(), multiplicity};
180 }
181
182
183
184 template <int dim, int spacedim>
185 double
shape_value(const unsigned int,const Point<dim> &) const186 FiniteElement<dim, spacedim>::shape_value(const unsigned int,
187 const Point<dim> &) const
188 {
189 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
190 return 0.;
191 }
192
193
194
195 template <int dim, int spacedim>
196 double
shape_value_component(const unsigned int,const Point<dim> &,const unsigned int) const197 FiniteElement<dim, spacedim>::shape_value_component(const unsigned int,
198 const Point<dim> &,
199 const unsigned int) const
200 {
201 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
202 return 0.;
203 }
204
205
206
207 template <int dim, int spacedim>
208 Tensor<1, dim>
shape_grad(const unsigned int,const Point<dim> &) const209 FiniteElement<dim, spacedim>::shape_grad(const unsigned int,
210 const Point<dim> &) const
211 {
212 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
213 return Tensor<1, dim>();
214 }
215
216
217
218 template <int dim, int spacedim>
219 Tensor<1, dim>
shape_grad_component(const unsigned int,const Point<dim> &,const unsigned int) const220 FiniteElement<dim, spacedim>::shape_grad_component(const unsigned int,
221 const Point<dim> &,
222 const unsigned int) const
223 {
224 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
225 return Tensor<1, dim>();
226 }
227
228
229
230 template <int dim, int spacedim>
231 Tensor<2, dim>
shape_grad_grad(const unsigned int,const Point<dim> &) const232 FiniteElement<dim, spacedim>::shape_grad_grad(const unsigned int,
233 const Point<dim> &) const
234 {
235 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
236 return Tensor<2, dim>();
237 }
238
239
240
241 template <int dim, int spacedim>
242 Tensor<2, dim>
shape_grad_grad_component(const unsigned int,const Point<dim> &,const unsigned int) const243 FiniteElement<dim, spacedim>::shape_grad_grad_component(
244 const unsigned int,
245 const Point<dim> &,
246 const unsigned int) const
247 {
248 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
249 return Tensor<2, dim>();
250 }
251
252
253
254 template <int dim, int spacedim>
255 Tensor<3, dim>
shape_3rd_derivative(const unsigned int,const Point<dim> &) const256 FiniteElement<dim, spacedim>::shape_3rd_derivative(const unsigned int,
257 const Point<dim> &) const
258 {
259 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
260 return Tensor<3, dim>();
261 }
262
263
264
265 template <int dim, int spacedim>
266 Tensor<3, dim>
shape_3rd_derivative_component(const unsigned int,const Point<dim> &,const unsigned int) const267 FiniteElement<dim, spacedim>::shape_3rd_derivative_component(
268 const unsigned int,
269 const Point<dim> &,
270 const unsigned int) const
271 {
272 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
273 return Tensor<3, dim>();
274 }
275
276
277
278 template <int dim, int spacedim>
279 Tensor<4, dim>
shape_4th_derivative(const unsigned int,const Point<dim> &) const280 FiniteElement<dim, spacedim>::shape_4th_derivative(const unsigned int,
281 const Point<dim> &) const
282 {
283 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
284 return Tensor<4, dim>();
285 }
286
287
288
289 template <int dim, int spacedim>
290 Tensor<4, dim>
shape_4th_derivative_component(const unsigned int,const Point<dim> &,const unsigned int) const291 FiniteElement<dim, spacedim>::shape_4th_derivative_component(
292 const unsigned int,
293 const Point<dim> &,
294 const unsigned int) const
295 {
296 AssertThrow(false, ExcUnitShapeValuesDoNotExist());
297 return Tensor<4, dim>();
298 }
299
300
301 template <int dim, int spacedim>
302 void
reinit_restriction_and_prolongation_matrices(const bool isotropic_restriction_only,const bool isotropic_prolongation_only)303 FiniteElement<dim, spacedim>::reinit_restriction_and_prolongation_matrices(
304 const bool isotropic_restriction_only,
305 const bool isotropic_prolongation_only)
306 {
307 for (unsigned int ref_case = RefinementCase<dim>::cut_x;
308 ref_case <= RefinementCase<dim>::isotropic_refinement;
309 ++ref_case)
310 {
311 const unsigned int nc =
312 GeometryInfo<dim>::n_children(RefinementCase<dim>(ref_case));
313
314 for (unsigned int i = 0; i < nc; ++i)
315 {
316 if (this->restriction[ref_case - 1][i].m() !=
317 this->n_dofs_per_cell() &&
318 (!isotropic_restriction_only ||
319 ref_case == RefinementCase<dim>::isotropic_refinement))
320 this->restriction[ref_case - 1][i].reinit(this->n_dofs_per_cell(),
321 this->n_dofs_per_cell());
322 if (this->prolongation[ref_case - 1][i].m() !=
323 this->n_dofs_per_cell() &&
324 (!isotropic_prolongation_only ||
325 ref_case == RefinementCase<dim>::isotropic_refinement))
326 this->prolongation[ref_case - 1][i].reinit(this->n_dofs_per_cell(),
327 this->n_dofs_per_cell());
328 }
329 }
330 }
331
332
333 template <int dim, int spacedim>
334 const FullMatrix<double> &
get_restriction_matrix(const unsigned int child,const RefinementCase<dim> & refinement_case) const335 FiniteElement<dim, spacedim>::get_restriction_matrix(
336 const unsigned int child,
337 const RefinementCase<dim> &refinement_case) const
338 {
339 AssertIndexRange(refinement_case,
340 RefinementCase<dim>::isotropic_refinement + 1);
341 Assert(refinement_case != RefinementCase<dim>::no_refinement,
342 ExcMessage(
343 "Restriction matrices are only available for refined cells!"));
344 AssertIndexRange(
345 child, GeometryInfo<dim>::n_children(RefinementCase<dim>(refinement_case)));
346 // we use refinement_case-1 here. the -1 takes care of the origin of the
347 // vector, as for RefinementCase<dim>::no_refinement (=0) there is no data
348 // available and so the vector indices are shifted
349 Assert(restriction[refinement_case - 1][child].n() == this->n_dofs_per_cell(),
350 ExcProjectionVoid());
351 return restriction[refinement_case - 1][child];
352 }
353
354
355
356 template <int dim, int spacedim>
357 const FullMatrix<double> &
get_prolongation_matrix(const unsigned int child,const RefinementCase<dim> & refinement_case) const358 FiniteElement<dim, spacedim>::get_prolongation_matrix(
359 const unsigned int child,
360 const RefinementCase<dim> &refinement_case) const
361 {
362 AssertIndexRange(refinement_case,
363 RefinementCase<dim>::isotropic_refinement + 1);
364 Assert(refinement_case != RefinementCase<dim>::no_refinement,
365 ExcMessage(
366 "Prolongation matrices are only available for refined cells!"));
367 AssertIndexRange(
368 child, GeometryInfo<dim>::n_children(RefinementCase<dim>(refinement_case)));
369 // we use refinement_case-1 here. the -1 takes care
370 // of the origin of the vector, as for
371 // RefinementCase::no_refinement (=0) there is no
372 // data available and so the vector indices
373 // are shifted
374 Assert(prolongation[refinement_case - 1][child].n() ==
375 this->n_dofs_per_cell(),
376 ExcEmbeddingVoid());
377 return prolongation[refinement_case - 1][child];
378 }
379
380
381 // TODO:[GK] This is probably not the most efficient way of doing this.
382 template <int dim, int spacedim>
383 unsigned int
component_to_block_index(const unsigned int index) const384 FiniteElement<dim, spacedim>::component_to_block_index(
385 const unsigned int index) const
386 {
387 AssertIndexRange(index, this->n_components());
388
389 return first_block_of_base(component_to_base_table[index].first.first) +
390 component_to_base_table[index].second;
391 }
392
393
394 template <int dim, int spacedim>
395 ComponentMask
component_mask(const FEValuesExtractors::Scalar & scalar) const396 FiniteElement<dim, spacedim>::component_mask(
397 const FEValuesExtractors::Scalar &scalar) const
398 {
399 AssertIndexRange(scalar.component, this->n_components());
400
401 // TODO: it would be nice to verify that it is indeed possible
402 // to select this scalar component, i.e., that it is not part
403 // of a non-primitive element. unfortunately, there is no simple
404 // way to write such a condition...
405
406 std::vector<bool> mask(this->n_components(), false);
407 mask[scalar.component] = true;
408 return mask;
409 }
410
411
412 template <int dim, int spacedim>
413 ComponentMask
component_mask(const FEValuesExtractors::Vector & vector) const414 FiniteElement<dim, spacedim>::component_mask(
415 const FEValuesExtractors::Vector &vector) const
416 {
417 AssertIndexRange(vector.first_vector_component + dim - 1,
418 this->n_components());
419
420 // TODO: it would be nice to verify that it is indeed possible
421 // to select these vector components, i.e., that they don't span
422 // beyond the beginning or end of anon-primitive element.
423 // unfortunately, there is no simple way to write such a condition...
424
425 std::vector<bool> mask(this->n_components(), false);
426 for (unsigned int c = vector.first_vector_component;
427 c < vector.first_vector_component + dim;
428 ++c)
429 mask[c] = true;
430 return mask;
431 }
432
433
434 template <int dim, int spacedim>
435 ComponentMask
component_mask(const FEValuesExtractors::SymmetricTensor<2> & sym_tensor) const436 FiniteElement<dim, spacedim>::component_mask(
437 const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
438 {
439 AssertIndexRange((sym_tensor.first_tensor_component +
440 SymmetricTensor<2, dim>::n_independent_components - 1),
441 this->n_components());
442
443 // TODO: it would be nice to verify that it is indeed possible
444 // to select these vector components, i.e., that they don't span
445 // beyond the beginning or end of anon-primitive element.
446 // unfortunately, there is no simple way to write such a condition...
447
448 std::vector<bool> mask(this->n_components(), false);
449 for (unsigned int c = sym_tensor.first_tensor_component;
450 c < sym_tensor.first_tensor_component +
451 SymmetricTensor<2, dim>::n_independent_components;
452 ++c)
453 mask[c] = true;
454 return mask;
455 }
456
457
458
459 template <int dim, int spacedim>
460 ComponentMask
component_mask(const BlockMask & block_mask) const461 FiniteElement<dim, spacedim>::component_mask(const BlockMask &block_mask) const
462 {
463 // if we get a block mask that represents all blocks, then
464 // do the same for the returned component mask
465 if (block_mask.represents_the_all_selected_mask())
466 return {};
467
468 AssertDimension(block_mask.size(), this->n_blocks());
469
470 std::vector<bool> component_mask(this->n_components(), false);
471 for (unsigned int c = 0; c < this->n_components(); ++c)
472 if (block_mask[component_to_block_index(c)] == true)
473 component_mask[c] = true;
474
475 return component_mask;
476 }
477
478
479
480 template <int dim, int spacedim>
481 BlockMask
block_mask(const FEValuesExtractors::Scalar & scalar) const482 FiniteElement<dim, spacedim>::block_mask(
483 const FEValuesExtractors::Scalar &scalar) const
484 {
485 // simply create the corresponding component mask (a simpler
486 // process) and then convert it to a block mask
487 return block_mask(component_mask(scalar));
488 }
489
490
491 template <int dim, int spacedim>
492 BlockMask
block_mask(const FEValuesExtractors::Vector & vector) const493 FiniteElement<dim, spacedim>::block_mask(
494 const FEValuesExtractors::Vector &vector) const
495 {
496 // simply create the corresponding component mask (a simpler
497 // process) and then convert it to a block mask
498 return block_mask(component_mask(vector));
499 }
500
501
502 template <int dim, int spacedim>
503 BlockMask
block_mask(const FEValuesExtractors::SymmetricTensor<2> & sym_tensor) const504 FiniteElement<dim, spacedim>::block_mask(
505 const FEValuesExtractors::SymmetricTensor<2> &sym_tensor) const
506 {
507 // simply create the corresponding component mask (a simpler
508 // process) and then convert it to a block mask
509 return block_mask(component_mask(sym_tensor));
510 }
511
512
513
514 template <int dim, int spacedim>
515 BlockMask
block_mask(const ComponentMask & component_mask) const516 FiniteElement<dim, spacedim>::block_mask(
517 const ComponentMask &component_mask) const
518 {
519 // if we get a component mask that represents all component, then
520 // do the same for the returned block mask
521 if (component_mask.represents_the_all_selected_mask())
522 return {};
523
524 AssertDimension(component_mask.size(), this->n_components());
525
526 // walk over all of the components
527 // of this finite element and see
528 // if we need to set the
529 // corresponding block. inside the
530 // block, walk over all the
531 // components that correspond to
532 // this block and make sure the
533 // component mask is set for all of
534 // them
535 std::vector<bool> block_mask(this->n_blocks(), false);
536 for (unsigned int c = 0; c < this->n_components();)
537 {
538 const unsigned int block = component_to_block_index(c);
539 if (component_mask[c] == true)
540 block_mask[block] = true;
541
542 // now check all of the other
543 // components that correspond
544 // to this block
545 ++c;
546 while ((c < this->n_components()) &&
547 (component_to_block_index(c) == block))
548 {
549 Assert(component_mask[c] == block_mask[block],
550 ExcMessage(
551 "The component mask argument given to this function "
552 "is not a mask where the individual components belonging "
553 "to one block of the finite element are either all "
554 "selected or not selected. You can't call this function "
555 "with a component mask that splits blocks."));
556 ++c;
557 }
558 }
559
560
561 return block_mask;
562 }
563
564
565
566 template <int dim, int spacedim>
567 unsigned int
face_to_cell_index(const unsigned int face_index,const unsigned int face,const bool face_orientation,const bool face_flip,const bool face_rotation) const568 FiniteElement<dim, spacedim>::face_to_cell_index(const unsigned int face_index,
569 const unsigned int face,
570 const bool face_orientation,
571 const bool face_flip,
572 const bool face_rotation) const
573 {
574 const auto &refence_cell =
575 ReferenceCell::internal::Info::get_cell(this->reference_cell_type());
576
577 AssertIndexRange(face_index, this->n_dofs_per_face(face));
578 AssertIndexRange(face, refence_cell.n_faces());
579
580 // TODO: we could presumably solve the 3d case below using the
581 // adjust_quad_dof_index_for_face_orientation_table field. for the
582 // 2d case, we can't use adjust_line_dof_index_for_line_orientation_table
583 // since that array is empty (presumably because we thought that
584 // there are no flipped edges in 2d, but these can happen in
585 // DoFTools::make_periodicity_constraints, for example). so we
586 // would need to either fill this field, or rely on derived classes
587 // implementing this function, as we currently do
588
589 // see the function's documentation for an explanation of this
590 // assertion -- in essence, derived classes have to implement
591 // an overloaded version of this function if we are to use any
592 // other than standard orientation
593 if ((face_orientation != true) || (face_flip != false) ||
594 (face_rotation != false))
595 Assert((this->n_dofs_per_line() <= 1) && (this->n_dofs_per_quad(face) <= 1),
596 ExcMessage(
597 "The function in this base class can not handle this case. "
598 "Rather, the derived class you are using must provide "
599 "an overloaded version but apparently hasn't done so. See "
600 "the documentation of this function for more information."));
601
602 // we need to distinguish between DoFs on vertices, lines and in 3d quads.
603 // do so in a sequence of if-else statements
604 if (face_index < this->get_first_face_line_index(face))
605 // DoF is on a vertex
606 {
607 // get the number of the vertex on the face that corresponds to this DoF,
608 // along with the number of the DoF on this vertex
609 const unsigned int face_vertex = face_index / this->n_dofs_per_vertex();
610 const unsigned int dof_index_on_vertex =
611 face_index % this->n_dofs_per_vertex();
612
613 // then get the number of this vertex on the cell and translate
614 // this to a DoF number on the cell
615 return (refence_cell.face_to_cell_vertices(face,
616 face_vertex,
617 face_orientation +
618 2 * face_rotation +
619 4 * face_flip) *
620 this->n_dofs_per_vertex() +
621 dof_index_on_vertex);
622 }
623 else if (face_index < this->get_first_face_quad_index(face))
624 // DoF is on a face
625 {
626 // do the same kind of translation as before. we need to only consider
627 // DoFs on the lines, i.e., ignoring those on the vertices
628 const unsigned int index =
629 face_index - this->get_first_face_line_index(face);
630
631 const unsigned int face_line = index / this->n_dofs_per_line();
632 const unsigned int dof_index_on_line = index % this->n_dofs_per_line();
633
634 return (this->get_first_line_index() +
635 refence_cell.face_to_cell_lines(face,
636 face_line,
637 face_orientation +
638 2 * face_rotation +
639 4 * face_flip) *
640 this->n_dofs_per_line() +
641 dof_index_on_line);
642 }
643 else
644 // DoF is on a quad
645 {
646 Assert(dim >= 3, ExcInternalError());
647
648 // ignore vertex and line dofs
649 const unsigned int index =
650 face_index - this->get_first_face_quad_index(face);
651
652 return (this->get_first_quad_index(face) + index);
653 }
654 }
655
656
657
658 template <int dim, int spacedim>
659 unsigned int
adjust_quad_dof_index_for_face_orientation(const unsigned int index,const unsigned int face,const bool face_orientation,const bool face_flip,const bool face_rotation) const660 FiniteElement<dim, spacedim>::adjust_quad_dof_index_for_face_orientation(
661 const unsigned int index,
662 const unsigned int face,
663 const bool face_orientation,
664 const bool face_flip,
665 const bool face_rotation) const
666 {
667 // general template for 1D and 2D: not
668 // implemented. in fact, the function
669 // shouldn't even be called unless we are
670 // in 3d, so throw an internal error
671 Assert(dim == 3, ExcInternalError());
672 if (dim < 3)
673 return index;
674
675 // adjust dofs on 3d faces if the face is
676 // flipped. note that we query a table that
677 // derived elements need to have set up
678 // front. the exception are discontinuous
679 // elements for which there should be no
680 // face dofs anyway (i.e. dofs_per_quad==0
681 // in 3d), so we don't need the table, but
682 // the function should also not have been
683 // called
684 AssertIndexRange(index, this->n_dofs_per_quad(face));
685 Assert(adjust_quad_dof_index_for_face_orientation_table
686 [this->n_unique_quads() == 1 ? 0 : face]
687 .n_elements() ==
688 (ReferenceCell::internal::Info::get_cell(this->reference_cell_type())
689 .face_reference_cell_type(face) == ReferenceCell::Type::Quad ?
690 8 :
691 6) *
692 this->n_dofs_per_quad(face),
693 ExcInternalError());
694 return index +
695 adjust_quad_dof_index_for_face_orientation_table
696 [this->n_unique_quads() == 1 ? 0 : face](
697 index, 4 * face_orientation + 2 * face_flip + face_rotation);
698 }
699
700
701
702 template <int dim, int spacedim>
703 unsigned int
adjust_line_dof_index_for_line_orientation(const unsigned int index,const bool line_orientation) const704 FiniteElement<dim, spacedim>::adjust_line_dof_index_for_line_orientation(
705 const unsigned int index,
706 const bool line_orientation) const
707 {
708 // general template for 1D and 2D: do
709 // nothing. Do not throw an Assertion,
710 // however, in order to allow to call this
711 // function in 2D as well
712 if (dim < 3)
713 return index;
714
715 AssertIndexRange(index, this->n_dofs_per_line());
716 Assert(adjust_line_dof_index_for_line_orientation_table.size() ==
717 this->n_dofs_per_line(),
718 ExcInternalError());
719 if (line_orientation)
720 return index;
721 else
722 return index + adjust_line_dof_index_for_line_orientation_table[index];
723 }
724
725
726
727 template <int dim, int spacedim>
728 bool
prolongation_is_implemented() const729 FiniteElement<dim, spacedim>::prolongation_is_implemented() const
730 {
731 for (unsigned int ref_case = RefinementCase<dim>::cut_x;
732 ref_case < RefinementCase<dim>::isotropic_refinement + 1;
733 ++ref_case)
734 for (unsigned int c = 0;
735 c < GeometryInfo<dim>::n_children(RefinementCase<dim>(ref_case));
736 ++c)
737 {
738 // make sure also the lazily initialized matrices are created
739 get_prolongation_matrix(c, RefinementCase<dim>(ref_case));
740 Assert((prolongation[ref_case - 1][c].m() == this->n_dofs_per_cell()) ||
741 (prolongation[ref_case - 1][c].m() == 0),
742 ExcInternalError());
743 Assert((prolongation[ref_case - 1][c].n() == this->n_dofs_per_cell()) ||
744 (prolongation[ref_case - 1][c].n() == 0),
745 ExcInternalError());
746 if ((prolongation[ref_case - 1][c].m() == 0) ||
747 (prolongation[ref_case - 1][c].n() == 0))
748 return false;
749 }
750 return true;
751 }
752
753
754
755 template <int dim, int spacedim>
756 bool
restriction_is_implemented() const757 FiniteElement<dim, spacedim>::restriction_is_implemented() const
758 {
759 for (unsigned int ref_case = RefinementCase<dim>::cut_x;
760 ref_case < RefinementCase<dim>::isotropic_refinement + 1;
761 ++ref_case)
762 for (unsigned int c = 0;
763 c < GeometryInfo<dim>::n_children(RefinementCase<dim>(ref_case));
764 ++c)
765 {
766 // make sure also the lazily initialized matrices are created
767 get_restriction_matrix(c, RefinementCase<dim>(ref_case));
768 Assert((restriction[ref_case - 1][c].m() == this->n_dofs_per_cell()) ||
769 (restriction[ref_case - 1][c].m() == 0),
770 ExcInternalError());
771 Assert((restriction[ref_case - 1][c].n() == this->n_dofs_per_cell()) ||
772 (restriction[ref_case - 1][c].n() == 0),
773 ExcInternalError());
774 if ((restriction[ref_case - 1][c].m() == 0) ||
775 (restriction[ref_case - 1][c].n() == 0))
776 return false;
777 }
778 return true;
779 }
780
781
782
783 template <int dim, int spacedim>
784 bool
isotropic_prolongation_is_implemented() const785 FiniteElement<dim, spacedim>::isotropic_prolongation_is_implemented() const
786 {
787 const RefinementCase<dim> ref_case =
788 RefinementCase<dim>::isotropic_refinement;
789
790 for (unsigned int c = 0;
791 c < GeometryInfo<dim>::n_children(RefinementCase<dim>(ref_case));
792 ++c)
793 {
794 // make sure also the lazily initialized matrices are created
795 get_prolongation_matrix(c, RefinementCase<dim>(ref_case));
796 Assert((prolongation[ref_case - 1][c].m() == this->n_dofs_per_cell()) ||
797 (prolongation[ref_case - 1][c].m() == 0),
798 ExcInternalError());
799 Assert((prolongation[ref_case - 1][c].n() == this->n_dofs_per_cell()) ||
800 (prolongation[ref_case - 1][c].n() == 0),
801 ExcInternalError());
802 if ((prolongation[ref_case - 1][c].m() == 0) ||
803 (prolongation[ref_case - 1][c].n() == 0))
804 return false;
805 }
806 return true;
807 }
808
809
810
811 template <int dim, int spacedim>
812 bool
isotropic_restriction_is_implemented() const813 FiniteElement<dim, spacedim>::isotropic_restriction_is_implemented() const
814 {
815 const RefinementCase<dim> ref_case =
816 RefinementCase<dim>::isotropic_refinement;
817
818 for (unsigned int c = 0;
819 c < GeometryInfo<dim>::n_children(RefinementCase<dim>(ref_case));
820 ++c)
821 {
822 // make sure also the lazily initialized matrices are created
823 get_restriction_matrix(c, RefinementCase<dim>(ref_case));
824 Assert((restriction[ref_case - 1][c].m() == this->n_dofs_per_cell()) ||
825 (restriction[ref_case - 1][c].m() == 0),
826 ExcInternalError());
827 Assert((restriction[ref_case - 1][c].n() == this->n_dofs_per_cell()) ||
828 (restriction[ref_case - 1][c].n() == 0),
829 ExcInternalError());
830 if ((restriction[ref_case - 1][c].m() == 0) ||
831 (restriction[ref_case - 1][c].n() == 0))
832 return false;
833 }
834 return true;
835 }
836
837
838
839 template <int dim, int spacedim>
840 bool
constraints_are_implemented(const internal::SubfaceCase<dim> & subface_case) const841 FiniteElement<dim, spacedim>::constraints_are_implemented(
842 const internal::SubfaceCase<dim> &subface_case) const
843 {
844 // TODO: the implementation makes the assumption that all faces have the
845 // same number of dofs
846 AssertDimension(this->n_unique_faces(), 1);
847 const unsigned int face_no = 0;
848
849 if (subface_case == internal::SubfaceCase<dim>::case_isotropic)
850 return (this->n_dofs_per_face(face_no) == 0) ||
851 (interface_constraints.m() != 0);
852 else
853 return false;
854 }
855
856
857
858 template <int dim, int spacedim>
859 bool
hp_constraints_are_implemented() const860 FiniteElement<dim, spacedim>::hp_constraints_are_implemented() const
861 {
862 return false;
863 }
864
865
866
867 template <int dim, int spacedim>
868 const FullMatrix<double> &
constraints(const internal::SubfaceCase<dim> & subface_case) const869 FiniteElement<dim, spacedim>::constraints(
870 const internal::SubfaceCase<dim> &subface_case) const
871 {
872 // TODO: the implementation makes the assumption that all faces have the
873 // same number of dofs
874 AssertDimension(this->n_unique_faces(), 1);
875 const unsigned int face_no = 0;
876 (void)face_no;
877
878 (void)subface_case;
879 Assert(subface_case == internal::SubfaceCase<dim>::case_isotropic,
880 ExcMessage("Constraints for this element are only implemented "
881 "for the case that faces are refined isotropically "
882 "(which is always the case in 2d, and in 3d requires "
883 "that the neighboring cell of a coarse cell presents "
884 "exactly four children on the common face)."));
885 Assert((this->n_dofs_per_face(face_no) == 0) ||
886 (interface_constraints.m() != 0),
887 ExcMessage("The finite element for which you try to obtain "
888 "hanging node constraints does not appear to "
889 "implement them."));
890
891 if (dim == 1)
892 Assert((interface_constraints.m() == 0) && (interface_constraints.n() == 0),
893 ExcWrongInterfaceMatrixSize(interface_constraints.m(),
894 interface_constraints.n()));
895
896 return interface_constraints;
897 }
898
899
900
901 template <int dim, int spacedim>
902 TableIndices<2>
interface_constraints_size() const903 FiniteElement<dim, spacedim>::interface_constraints_size() const
904 {
905 // TODO: the implementation makes the assumption that all faces have the
906 // same number of dofs
907 AssertDimension(this->n_unique_faces(), 1);
908 const unsigned int face_no = 0;
909
910 switch (dim)
911 {
912 case 1:
913 return {0U, 0U};
914 case 2:
915 return {this->n_dofs_per_vertex() + 2 * this->n_dofs_per_line(),
916 this->n_dofs_per_face(face_no)};
917 case 3:
918 return {5 * this->n_dofs_per_vertex() + 12 * this->n_dofs_per_line() +
919 4 * this->n_dofs_per_quad(face_no),
920 this->n_dofs_per_face(face_no)};
921 default:
922 Assert(false, ExcNotImplemented());
923 }
924 return {numbers::invalid_unsigned_int, numbers::invalid_unsigned_int};
925 }
926
927
928
929 template <int dim, int spacedim>
930 void
get_interpolation_matrix(const FiniteElement<dim,spacedim> &,FullMatrix<double> &) const931 FiniteElement<dim, spacedim>::get_interpolation_matrix(
932 const FiniteElement<dim, spacedim> &,
933 FullMatrix<double> &) const
934 {
935 // by default, no interpolation
936 // implemented. so throw exception,
937 // as documentation says
938 AssertThrow(
939 false,
940 (typename FiniteElement<dim, spacedim>::ExcInterpolationNotImplemented()));
941 }
942
943
944
945 template <int dim, int spacedim>
946 void
get_face_interpolation_matrix(const FiniteElement<dim,spacedim> &,FullMatrix<double> &,const unsigned int) const947 FiniteElement<dim, spacedim>::get_face_interpolation_matrix(
948 const FiniteElement<dim, spacedim> &,
949 FullMatrix<double> &,
950 const unsigned int) const
951 {
952 // by default, no interpolation
953 // implemented. so throw exception,
954 // as documentation says
955 AssertThrow(
956 false,
957 (typename FiniteElement<dim, spacedim>::ExcInterpolationNotImplemented()));
958 }
959
960
961
962 template <int dim, int spacedim>
963 void
get_subface_interpolation_matrix(const FiniteElement<dim,spacedim> &,const unsigned int,FullMatrix<double> &,const unsigned int) const964 FiniteElement<dim, spacedim>::get_subface_interpolation_matrix(
965 const FiniteElement<dim, spacedim> &,
966 const unsigned int,
967 FullMatrix<double> &,
968 const unsigned int) const
969 {
970 // by default, no interpolation
971 // implemented. so throw exception,
972 // as documentation says
973 AssertThrow(
974 false,
975 (typename FiniteElement<dim, spacedim>::ExcInterpolationNotImplemented()));
976 }
977
978
979
980 template <int dim, int spacedim>
981 std::vector<std::pair<unsigned int, unsigned int>>
hp_vertex_dof_identities(const FiniteElement<dim,spacedim> &) const982 FiniteElement<dim, spacedim>::hp_vertex_dof_identities(
983 const FiniteElement<dim, spacedim> &) const
984 {
985 Assert(false, ExcNotImplemented());
986 return std::vector<std::pair<unsigned int, unsigned int>>();
987 }
988
989
990
991 template <int dim, int spacedim>
992 std::vector<std::pair<unsigned int, unsigned int>>
hp_line_dof_identities(const FiniteElement<dim,spacedim> &) const993 FiniteElement<dim, spacedim>::hp_line_dof_identities(
994 const FiniteElement<dim, spacedim> &) const
995 {
996 Assert(false, ExcNotImplemented());
997 return std::vector<std::pair<unsigned int, unsigned int>>();
998 }
999
1000
1001
1002 template <int dim, int spacedim>
1003 std::vector<std::pair<unsigned int, unsigned int>>
hp_quad_dof_identities(const FiniteElement<dim,spacedim> &,const unsigned int) const1004 FiniteElement<dim, spacedim>::hp_quad_dof_identities(
1005 const FiniteElement<dim, spacedim> &,
1006 const unsigned int) const
1007 {
1008 Assert(false, ExcNotImplemented());
1009 return std::vector<std::pair<unsigned int, unsigned int>>();
1010 }
1011
1012
1013
1014 template <int dim, int spacedim>
1015 FiniteElementDomination::Domination
compare_for_domination(const FiniteElement<dim,spacedim> &,const unsigned int) const1016 FiniteElement<dim, spacedim>::compare_for_domination(
1017 const FiniteElement<dim, spacedim> &,
1018 const unsigned int) const
1019 {
1020 Assert(false, ExcNotImplemented());
1021 return FiniteElementDomination::neither_element_dominates;
1022 }
1023
1024
1025
1026 template <int dim, int spacedim>
1027 bool
1028 FiniteElement<dim, spacedim>::
operator ==(const FiniteElement<dim,spacedim> & f) const1029 operator==(const FiniteElement<dim, spacedim> &f) const
1030 {
1031 // Compare fields in roughly increasing order of how expensive the
1032 // comparison is
1033 return ((typeid(*this) == typeid(f)) && (this->get_name() == f.get_name()) &&
1034 (static_cast<const FiniteElementData<dim> &>(*this) ==
1035 static_cast<const FiniteElementData<dim> &>(f)) &&
1036 (interface_constraints == f.interface_constraints));
1037 }
1038
1039
1040
1041 template <int dim, int spacedim>
1042 bool
1043 FiniteElement<dim, spacedim>::
operator !=(const FiniteElement<dim,spacedim> & f) const1044 operator!=(const FiniteElement<dim, spacedim> &f) const
1045 {
1046 return !(*this == f);
1047 }
1048
1049
1050
1051 template <int dim, int spacedim>
1052 const std::vector<Point<dim>> &
get_unit_support_points() const1053 FiniteElement<dim, spacedim>::get_unit_support_points() const
1054 {
1055 // a finite element may define
1056 // support points, but only if
1057 // there are as many as there are
1058 // degrees of freedom
1059 Assert((unit_support_points.size() == 0) ||
1060 (unit_support_points.size() == this->n_dofs_per_cell()),
1061 ExcInternalError());
1062 return unit_support_points;
1063 }
1064
1065
1066
1067 template <int dim, int spacedim>
1068 bool
has_support_points() const1069 FiniteElement<dim, spacedim>::has_support_points() const
1070 {
1071 return (unit_support_points.size() != 0);
1072 }
1073
1074
1075
1076 template <int dim, int spacedim>
1077 const std::vector<Point<dim>> &
get_generalized_support_points() const1078 FiniteElement<dim, spacedim>::get_generalized_support_points() const
1079 {
1080 // If the finite element implements generalized support points, return
1081 // those. Otherwise fall back to unit support points.
1082 return ((generalized_support_points.size() == 0) ?
1083 unit_support_points :
1084 generalized_support_points);
1085 }
1086
1087
1088
1089 template <int dim, int spacedim>
1090 bool
has_generalized_support_points() const1091 FiniteElement<dim, spacedim>::has_generalized_support_points() const
1092 {
1093 return (get_generalized_support_points().size() != 0);
1094 }
1095
1096
1097
1098 template <int dim, int spacedim>
1099 Point<dim>
unit_support_point(const unsigned int index) const1100 FiniteElement<dim, spacedim>::unit_support_point(const unsigned int index) const
1101 {
1102 AssertIndexRange(index, this->n_dofs_per_cell());
1103 Assert(unit_support_points.size() == this->n_dofs_per_cell(),
1104 ExcFEHasNoSupportPoints());
1105 return unit_support_points[index];
1106 }
1107
1108
1109
1110 template <int dim, int spacedim>
1111 const std::vector<Point<dim - 1>> &
get_unit_face_support_points(const unsigned int face_no) const1112 FiniteElement<dim, spacedim>::get_unit_face_support_points(
1113 const unsigned int face_no) const
1114 {
1115 // a finite element may define
1116 // support points, but only if
1117 // there are as many as there are
1118 // degrees of freedom on a face
1119 Assert((unit_face_support_points[this->n_unique_faces() == 1 ? 0 : face_no]
1120 .size() == 0) ||
1121 (unit_face_support_points[this->n_unique_faces() == 1 ? 0 : face_no]
1122 .size() == this->n_dofs_per_face(face_no)),
1123 ExcInternalError());
1124 return unit_face_support_points[this->n_unique_faces() == 1 ? 0 : face_no];
1125 }
1126
1127
1128
1129 template <int dim, int spacedim>
1130 bool
has_face_support_points(const unsigned int face_no) const1131 FiniteElement<dim, spacedim>::has_face_support_points(
1132 const unsigned int face_no) const
1133 {
1134 return (unit_face_support_points[this->n_unique_faces() == 1 ? 0 : face_no]
1135 .size() != 0);
1136 }
1137
1138
1139
1140 template <int dim, int spacedim>
1141 Point<dim - 1>
unit_face_support_point(const unsigned int index,const unsigned int face_no) const1142 FiniteElement<dim, spacedim>::unit_face_support_point(
1143 const unsigned int index,
1144 const unsigned int face_no) const
1145 {
1146 AssertIndexRange(index, this->n_dofs_per_face(face_no));
1147 Assert(unit_face_support_points[this->n_unique_faces() == 1 ? 0 : face_no]
1148 .size() == this->n_dofs_per_face(face_no),
1149 ExcFEHasNoSupportPoints());
1150 return unit_face_support_points[this->n_unique_faces() == 1 ? 0 : face_no]
1151 [index];
1152 }
1153
1154
1155
1156 template <int dim, int spacedim>
1157 bool
has_support_on_face(const unsigned int,const unsigned int) const1158 FiniteElement<dim, spacedim>::has_support_on_face(const unsigned int,
1159 const unsigned int) const
1160 {
1161 return true;
1162 }
1163
1164
1165
1166 template <int dim, int spacedim>
1167 const FiniteElement<dim, spacedim> &
get_sub_fe(const ComponentMask & mask) const1168 FiniteElement<dim, spacedim>::get_sub_fe(const ComponentMask &mask) const
1169 {
1170 // Translate the ComponentMask into first_selected and n_components after
1171 // some error checking:
1172 const unsigned int n_total_components = this->n_components();
1173 Assert((n_total_components == mask.size()) || (mask.size() == 0),
1174 ExcMessage("The given ComponentMask has the wrong size."));
1175
1176 const unsigned int n_selected =
1177 mask.n_selected_components(n_total_components);
1178 Assert(n_selected > 0,
1179 ExcMessage("You need at least one selected component."));
1180
1181 const unsigned int first_selected =
1182 mask.first_selected_component(n_total_components);
1183
1184 #ifdef DEBUG
1185 // check that it is contiguous:
1186 for (unsigned int c = 0; c < n_total_components; ++c)
1187 Assert((c < first_selected && (!mask[c])) ||
1188 (c >= first_selected && c < first_selected + n_selected &&
1189 mask[c]) ||
1190 (c >= first_selected + n_selected && !mask[c]),
1191 ExcMessage("Error: the given ComponentMask is not contiguous!"));
1192 #endif
1193
1194 return get_sub_fe(first_selected, n_selected);
1195 }
1196
1197
1198
1199 template <int dim, int spacedim>
1200 const FiniteElement<dim, spacedim> &
get_sub_fe(const unsigned int first_component,const unsigned int n_selected_components) const1201 FiniteElement<dim, spacedim>::get_sub_fe(
1202 const unsigned int first_component,
1203 const unsigned int n_selected_components) const
1204 {
1205 // No complicated logic is needed here, because it is overridden in
1206 // FESystem<dim,spacedim>. Just make sure that what the user chose is valid:
1207 Assert(first_component == 0 && n_selected_components == this->n_components(),
1208 ExcMessage(
1209 "You can only select a whole FiniteElement, not a part of one."));
1210
1211 (void)first_component;
1212 (void)n_selected_components;
1213 return *this;
1214 }
1215
1216
1217
1218 template <int dim, int spacedim>
1219 std::pair<Table<2, bool>, std::vector<unsigned int>>
get_constant_modes() const1220 FiniteElement<dim, spacedim>::get_constant_modes() const
1221 {
1222 Assert(false, ExcNotImplemented());
1223 return std::pair<Table<2, bool>, std::vector<unsigned int>>(
1224 Table<2, bool>(this->n_components(), this->n_dofs_per_cell()),
1225 std::vector<unsigned int>(this->n_components()));
1226 }
1227
1228
1229
1230 template <int dim, int spacedim>
1231 void
1232 FiniteElement<dim, spacedim>::
convert_generalized_support_point_values_to_dof_values(const std::vector<Vector<double>> &,std::vector<double> &) const1233 convert_generalized_support_point_values_to_dof_values(
1234 const std::vector<Vector<double>> &,
1235 std::vector<double> &) const
1236 {
1237 Assert(has_generalized_support_points(),
1238 ExcMessage("The element for which you are calling the current "
1239 "function does not have generalized support points (see "
1240 "the glossary for a definition of generalized support "
1241 "points). Consequently, the current function can not "
1242 "be defined and is not implemented by the element."));
1243 Assert(false, ExcNotImplemented());
1244 }
1245
1246
1247
1248 template <int dim, int spacedim>
1249 std::size_t
memory_consumption() const1250 FiniteElement<dim, spacedim>::memory_consumption() const
1251 {
1252 return (
1253 sizeof(FiniteElementData<dim>) +
1254 MemoryConsumption::memory_consumption(restriction) +
1255 MemoryConsumption::memory_consumption(prolongation) +
1256 MemoryConsumption::memory_consumption(interface_constraints) +
1257 MemoryConsumption::memory_consumption(system_to_component_table) +
1258 MemoryConsumption::memory_consumption(face_system_to_component_table) +
1259 MemoryConsumption::memory_consumption(system_to_base_table) +
1260 MemoryConsumption::memory_consumption(face_system_to_base_table) +
1261 MemoryConsumption::memory_consumption(component_to_base_table) +
1262 MemoryConsumption::memory_consumption(restriction_is_additive_flags) +
1263 MemoryConsumption::memory_consumption(nonzero_components) +
1264 MemoryConsumption::memory_consumption(n_nonzero_components_table));
1265 }
1266
1267
1268
1269 template <int dim, int spacedim>
1270 std::vector<unsigned int>
compute_n_nonzero_components(const std::vector<ComponentMask> & nonzero_components)1271 FiniteElement<dim, spacedim>::compute_n_nonzero_components(
1272 const std::vector<ComponentMask> &nonzero_components)
1273 {
1274 std::vector<unsigned int> retval(nonzero_components.size());
1275 for (unsigned int i = 0; i < nonzero_components.size(); ++i)
1276 retval[i] = nonzero_components[i].n_selected_components();
1277 return retval;
1278 }
1279
1280
1281
1282 /*------------------------------- FiniteElement ----------------------*/
1283
1284 template <int dim, int spacedim>
1285 std::unique_ptr<typename FiniteElement<dim, spacedim>::InternalDataBase>
get_face_data(const UpdateFlags flags,const Mapping<dim,spacedim> & mapping,const Quadrature<dim-1> & quadrature,dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,spacedim> & output_data) const1286 FiniteElement<dim, spacedim>::get_face_data(
1287 const UpdateFlags flags,
1288 const Mapping<dim, spacedim> &mapping,
1289 const Quadrature<dim - 1> & quadrature,
1290 dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,
1291 spacedim>
1292 &output_data) const
1293 {
1294 return get_data(flags,
1295 mapping,
1296 QProjector<dim>::project_to_all_faces(
1297 this->reference_cell_type(), quadrature),
1298 output_data);
1299 }
1300
1301
1302
1303 template <int dim, int spacedim>
1304 std::unique_ptr<typename FiniteElement<dim, spacedim>::InternalDataBase>
get_subface_data(const UpdateFlags flags,const Mapping<dim,spacedim> & mapping,const Quadrature<dim-1> & quadrature,dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,spacedim> & output_data) const1305 FiniteElement<dim, spacedim>::get_subface_data(
1306 const UpdateFlags flags,
1307 const Mapping<dim, spacedim> &mapping,
1308 const Quadrature<dim - 1> & quadrature,
1309 dealii::internal::FEValuesImplementation::FiniteElementRelatedData<dim,
1310 spacedim>
1311 &output_data) const
1312 {
1313 return get_data(flags,
1314 mapping,
1315 QProjector<dim>::project_to_all_subfaces(
1316 this->reference_cell_type(), quadrature),
1317 output_data);
1318 }
1319
1320
1321
1322 template <int dim, int spacedim>
1323 const FiniteElement<dim, spacedim> &
base_element(const unsigned int index) const1324 FiniteElement<dim, spacedim>::base_element(const unsigned int index) const
1325 {
1326 (void)index;
1327 AssertIndexRange(index, 1);
1328 // This function should not be
1329 // called for a system element
1330 Assert(base_to_block_indices.size() == 1, ExcInternalError());
1331 return *this;
1332 }
1333
1334
1335
1336 /*------------------------------- Explicit Instantiations -------------*/
1337 #include "fe.inst"
1338
1339
1340 DEAL_II_NAMESPACE_CLOSE
1341