3#include <deal.II/base/exceptions.h>
4#include <deal.II/base/point.h>
5#include <deal.II/base/tensor.h>
6#include <deal.II/base/types.h>
7#include <deal.II/base/vectorization.h>
9#include <deal.II/lac/la_parallel_vector.h>
11#include <deal.II/matrix_free/evaluation_flags.h>
12#include <deal.II/matrix_free/face_info.h>
13#include <deal.II/matrix_free/matrix_free.h>
14#include <deal.II/matrix_free/operators.h>
15#include <deal.II/matrix_free/shape_info.h>
23 template <
int dim,
int n_components,
typename number>
25 const dealii::MatrixFree<dim, number> &matrix_free,
26 const bool is_interior_face,
27 const unsigned int dof_no,
28 const unsigned int quad_no)
29 : matrix_free(matrix_free)
30 , is_interior_face(is_interior_face)
31 , fe_cell_evaluator(matrix_free, dof_no, quad_no)
32 , fe_face_evaluator(matrix_free, true, dof_no, quad_no)
37 template <
int dim,
int n_components,
typename number>
41 const dealii::internal::MatrixFreeFunctions::FaceToCellTopology<VectorizedArrayType::size()>
42 &face_info = matrix_free.get_face_info(face_batch_index);
44 is_boundary_face = face_batch_index >= matrix_free.n_inner_face_batches();
47 Assert(dim < 3 or face_info.face_orientation == 0, dealii::ExcNotImplemented());
50 Assert(face_info.subface_index >= dealii::GeometryInfo<dim>::max_children_per_cell,
51 dealii::ExcNotImplemented(
"Hanging faces are not supported."));
53 Assert(is_interior_face or !is_boundary_face,
54 dealii::ExcMessage(
"Exterior evaluation is not possible on boundary faces."));
56 fe_face_evaluator.reinit(face_batch_index);
60 fe_cell_evaluator.reinit(face_info.cells_interior);
61 face_no = face_info.interior_face_no;
65 fe_cell_evaluator.reinit(face_info.cells_exterior);
66 face_no = face_info.exterior_face_no;
69 this->face_batch_index = face_batch_index;
71 determine_subcell_face_sizes();
72 determine_subcell_face_normals();
74 determine_subcell_sizes();
76 determine_subcell_locations();
78 std::ranges::fill(submitted_fluxes,
value_type());
80 is_reinitialized =
true;
81 dof_values_initialized =
false;
82 subcell_values_initialized =
false;
83 subcell_fluxes_submitted =
false;
86 template <
int dim,
int n_components,
typename number>
89 const dealii::LinearAlgebra::distributed::Vector<number> &src_vector,
90 const std::bitset<n_lanes> &mask)
92 Assert(is_reinitialized, dealii::ExcNotInitialized());
93 fe_cell_evaluator.read_dof_values(src_vector, 0, mask);
95 dof_values_initialized =
true;
98 template <
int dim,
int n_components,
typename number>
101 const dealii::EvaluationFlags::EvaluationFlags evaluation_flags)
103 Assert(dof_values_initialized,
105 "DoF values have not been initialized. Call read_dof_values() before evaluate()."));
107 project_dof_values_to_subcell_values(evaluation_flags);
110 template <
int dim,
int n_components,
typename number>
113 const dealii::LinearAlgebra::distributed::Vector<number> &input_vector,
114 const dealii::EvaluationFlags::EvaluationFlags evaluation_flags,
115 const std::bitset<n_lanes> &mask)
117 read_dof_values(input_vector, mask);
118 evaluate(evaluation_flags);
121 template <
int dim,
int n_components,
typename number>
124 const unsigned int subcell_index)
const ->
value_type
126 AssertIndexRange(subcell_index, n_subcells_face);
128 subcell_values_initialized,
130 "FESubcellFaceEvaluation has not been reinitialized. Call reinit() before get_interior_value()."));
131 return layer_values[layer_index(subcell_index)];
134 template <
int dim,
int n_components,
typename number>
139 AssertIndexRange(subcell_index, n_subcells_face);
140 Assert(is_reinitialized, dealii::ExcNotInitialized());
142 submitted_fluxes[subcell_index] = normal_flux;
144 subcell_fluxes_submitted =
true;
147 template <
int dim,
int n_components,
typename number>
150 dealii::LinearAlgebra::distributed::Vector<number> &dst_vector,
151 const std::bitset<n_lanes> &mask)
154 subcell_fluxes_submitted,
156 "Subcell fluxes have not been submitted. Call submit_flux() before integrate_scatter()."));
158 distribute_local_to_global(dst_vector, mask);
161 template <
int dim,
int n_components,
typename number>
162 std::ranges::iota_view<unsigned int, unsigned int>
165 return {0U, n_subcells_face};
168 template <
int dim,
int n_components,
typename number>
173 Assert(is_reinitialized, dealii::ExcNotInitialized());
174 AssertIndexRange(subcell_index, n_subcells_face);
175 return subcell_face_sizes[subcell_index];
178 template <
int dim,
int n_components,
typename number>
181 const unsigned int subcell_index)
const -> dealii::Point<dim, VectorizedArrayType>
183 Assert(is_reinitialized, dealii::ExcNotInitialized());
184 AssertIndexRange(subcell_index, n_subcells_face);
185 return subcell_locations[subcell_index];
188 template <
int dim,
int n_components,
typename number>
192 return n_subcells_face;
195 template <
int dim,
int n_components,
typename number>
198 const unsigned int subcell_index)
const -> dealii::Tensor<1, dim, VectorizedArrayType>
200 Assert(is_reinitialized, dealii::ExcNotInitialized());
201 AssertIndexRange(subcell_index, n_subcells_face);
202 return subcell_face_normals[subcell_index];
205 template <
int dim,
int n_components,
typename number>
209 Assert(is_reinitialized, dealii::ExcNotInitialized());
210 return is_boundary_face;
213 template <
int dim,
int n_components,
typename number>
214 dealii::types::boundary_id
217 Assert(is_reinitialized, dealii::ExcNotInitialized());
221 "The current face is not a boundary face. Call boundary_id() only for boundary faces."));
222 return matrix_free.get_boundary_id(face_batch_index);
225 template <
int dim,
int n_components,
typename number>
230 Assert(is_reinitialized, dealii::ExcNotInitialized());
231 AssertIndexRange(subcell_index, n_subcells_face);
232 return subcell_sizes[subcell_index];
235 template <
int dim,
int n_components,
typename number>
239 for (
const unsigned int q : subcell_face_indices())
241 subcell_face_sizes[q] = fe_face_evaluator.JxW(q);
245 template <
int dim,
int n_components,
typename number>
249 for (
const unsigned int q : subcell_face_indices())
251 subcell_face_normals[q] = fe_face_evaluator.normal_vector(q);
255 template <
int dim,
int n_components,
typename number>
259 for (
const unsigned int q : subcell_face_indices())
261 subcell_sizes[q] = fe_cell_evaluator.JxW(
262 face_to_cell_quadrature_index(face_no, q, fe_cell_evaluator.get_shape_info()));
265 template <
int dim,
int n_components,
typename number>
275 dealii::MatrixFreeOperators::CellwiseInverseMassMatrix<dim, -1, n_components, number> inverse(
278 std::fill(integrated_subcell_values_buffer.begin(),
279 integrated_subcell_values_buffer.end(),
282 for (
unsigned int subcell : subcell_face_indices())
284 const unsigned int cell_q_index =
285 face_to_cell_quadrature_index(face_no, subcell, fe_cell_evaluator.get_shape_info());
287 subcell_face_sizes[subcell] / subcell_sizes[subcell];
288 if constexpr (n_components == 1)
289 integrated_subcell_values_buffer[cell_q_index] =
290 submitted_fluxes[subcell] * scaling_factor;
292 for (
unsigned int c = 0; c < n_components; ++c)
293 integrated_subcell_values_buffer[c * fe_cell_evaluator.n_q_points + cell_q_index] =
294 submitted_fluxes[subcell][c] * scaling_factor;
296 inverse.transform_from_q_points_to_basis(n_components,
297 integrated_subcell_values_buffer.data(),
298 fe_cell_evaluator.begin_dof_values());
301 template <
int dim,
int n_components,
typename number>
304 dealii::LinearAlgebra::distributed::Vector<number> &dst_vector,
305 const std::bitset<n_lanes> &mask)
307 fe_cell_evaluator.distribute_local_to_global(dst_vector, 0, mask);
310 template <
int dim,
int n_components,
typename number>
314 n_subcells_1d = fe_cell_evaluator.get_shape_info().data[0].n_q_points_1d;
315 n_subcells_face = fe_cell_evaluator.get_shape_info().n_q_points_face;
317 const unsigned int padded_size = dealii::Utilities::fixed_power<dim - 1>(n_subcells_1d + 2);
318 layer_values.resize(padded_size);
320 submitted_fluxes.resize(n_subcells_face);
321 subcell_face_normals.resize(n_subcells_face);
323 subcell_face_sizes.resize(n_subcells_face);
324 subcell_sizes.resize(n_subcells_face);
326 subcell_locations.resize(n_subcells_face);
327 integrated_subcell_values_buffer.resize(n_components * fe_cell_evaluator.n_q_points);
330 template <
int dim,
int n_components,
typename number>
333 const dealii::EvaluationFlags::EvaluationFlags evaluation_flags)
335 fe_cell_evaluator.evaluate(evaluation_flags);
336 if (evaluation_flags & dealii::EvaluationFlags::values)
338 for (
const unsigned int subcell : subcell_face_indices())
340 const unsigned int cell_q_index =
341 face_to_cell_quadrature_index(face_no, subcell, fe_cell_evaluator.get_shape_info());
342 layer_values[layer_index(subcell)] = fe_cell_evaluator.get_value(cell_q_index);
345 subcell_values_initialized =
true;
348 if (evaluation_flags & dealii::EvaluationFlags::gradients)
349 AssertThrow(
false, dealii::ExcNotImplemented());
352 template <
int dim,
int n_components,
typename number>
356 for (
const unsigned int subcell : subcell_face_indices())
358 const unsigned int cell_q_index =
359 face_to_cell_quadrature_index(face_no, subcell, fe_cell_evaluator.get_shape_info());
360 subcell_locations[subcell] = fe_cell_evaluator.quadrature_point(cell_q_index);
364 template <
int dim,
int n_components,
typename number>
367 const unsigned int subcell_index)
const
369 AssertIndexRange(subcell_index, n_subcells_face);
371 const unsigned int n_padded_1d = n_subcells_1d + 2;
373 unsigned int remaining_index = subcell_index;
374 unsigned int index = 0;
375 unsigned int stride = 1;
376 for (
unsigned int d = 0; d < dim - 1; ++d)
378 const unsigned int tangential_index = remaining_index % n_subcells_1d;
379 remaining_index /= n_subcells_1d;
381 index += (tangential_index + 1) * stride;
382 stride *= n_padded_1d;
387 template <
int dim,
int n_components,
typename number>
390 const unsigned int face_no,
391 const unsigned int q_face,
392 const dealii::internal::MatrixFreeFunctions::ShapeInfo<number> &shape_info)
const
394 AssertIndexRange(face_no, dealii::GeometryInfo<dim>::faces_per_cell);
395 AssertIndexRange(q_face, fe_face_evaluator.n_q_points);
397 if constexpr (dim == 1)
401 return face_no == 0 ? 0 : shape_info.n_q_points - 1;
405 const unsigned int direction = face_no / 2;
406 const unsigned int n = shape_info.data[0].n_q_points_1d;
408 unsigned int normal_stride = 1;
409 for (
unsigned int d = 0; d < direction; ++d)
414 const unsigned int offset = (face_no % 2) * (n - 1) * normal_stride;
417 if (dim == 3 and direction == 1)
418 return offset + (q_face % n) * n * n + q_face / n;
420 const unsigned int tangential_stride = direction < dim - 1 ? n : 1;
421 return offset + q_face * tangential_stride;
std::ranges::iota_view< unsigned int, unsigned int > subcell_face_indices() const
Definition fe_subcell_face_evaluation.templates.hpp:163
dealii::VectorizedArray< number > VectorizedArrayType
Definition fe_subcell_face_evaluation.hpp:120
void determine_subcell_locations()
Definition fe_subcell_face_evaluation.templates.hpp:354
VectorizedArrayType subcell_size(const unsigned int subcell_index) const
Definition fe_subcell_face_evaluation.templates.hpp:227
void reinit(const unsigned int face_batch_index)
Definition fe_subcell_face_evaluation.templates.hpp:39
dealii::Tensor< 1, dim, VectorizedArrayType > normal_vector(const unsigned int subcell_index) const
Definition fe_subcell_face_evaluation.templates.hpp:197
void determine_subcell_sizes()
Definition fe_subcell_face_evaluation.templates.hpp:257
void setup_internal_data_structures()
Definition fe_subcell_face_evaluation.templates.hpp:312
void project_dof_values_to_subcell_values(const dealii::EvaluationFlags::EvaluationFlags evaluation_flags)
Definition fe_subcell_face_evaluation.templates.hpp:332
VectorizedArrayType subcell_face_size(const unsigned int subcell_index) const
Definition fe_subcell_face_evaluation.templates.hpp:170
void gather_evaluate(const dealii::LinearAlgebra::distributed::Vector< number > &input_vector, const dealii::EvaluationFlags::EvaluationFlags evaluation_flags, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
Definition fe_subcell_face_evaluation.templates.hpp:112
void read_dof_values(const dealii::LinearAlgebra::distributed::Vector< number > &src_vector, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
Definition fe_subcell_face_evaluation.templates.hpp:88
value_type get_value(const unsigned int subcell_index) const
Definition fe_subcell_face_evaluation.templates.hpp:123
bool at_boundary() const
Definition fe_subcell_face_evaluation.templates.hpp:207
void distribute_local_to_global(dealii::LinearAlgebra::distributed::Vector< number > &dst_vector, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
Definition fe_subcell_face_evaluation.templates.hpp:303
void submit_flux(const unsigned int subcell_index, const value_type &normal_flux)
Definition fe_subcell_face_evaluation.templates.hpp:136
FESubcellFaceEvaluation(const dealii::MatrixFree< dim, number > &matrix_free, const bool is_interior_face, const unsigned int dof_no, const unsigned int quad_no)
Definition fe_subcell_face_evaluation.templates.hpp:24
void determine_subcell_face_normals()
Definition fe_subcell_face_evaluation.templates.hpp:247
void determine_subcell_face_sizes()
Definition fe_subcell_face_evaluation.templates.hpp:237
dealii::types::boundary_id boundary_id() const
Definition fe_subcell_face_evaluation.templates.hpp:215
dealii::Point< dim, VectorizedArrayType > subcell_location(const unsigned int subcell_index) const
Definition fe_subcell_face_evaluation.templates.hpp:180
unsigned int n_subcell_faces() const
Definition fe_subcell_face_evaluation.templates.hpp:190
unsigned int layer_index(const unsigned int subcell_index) const
Definition fe_subcell_face_evaluation.templates.hpp:366
void integrate_scatter(dealii::LinearAlgebra::distributed::Vector< number > &dst_vector, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
Definition fe_subcell_face_evaluation.templates.hpp:149
unsigned int face_to_cell_quadrature_index(const unsigned int face_no, const unsigned int q_face, const dealii::internal::MatrixFreeFunctions::ShapeInfo< number > &shape_info) const
Definition fe_subcell_face_evaluation.templates.hpp:389
void evaluate(const dealii::EvaluationFlags::EvaluationFlags evaluation_flags)
Definition fe_subcell_face_evaluation.templates.hpp:100
void integrate()
Definition fe_subcell_face_evaluation.templates.hpp:267
dealii::FEFaceEvaluation< dim, -1, 0, n_components, number, VectorizedArrayType >::value_type value_type
The type of the values on the subcells.
Definition fe_subcell_face_evaluation.hpp:127
Interface for a general preconditioner.
Definition boundary_condition_functions.hpp:17