include/meltpooldg/utilities/fe_subcell_evaluation.templates.hpp Source File

Developer Documentation: include/meltpooldg/utilities/fe_subcell_evaluation.templates.hpp Source File
Developer Documentation
fe_subcell_evaluation.templates.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <deal.II/base/tensor.h>
4#include <deal.II/base/vectorization.h>
5
6#include <deal.II/lac/la_parallel_vector.h>
7
8#include <deal.II/matrix_free/matrix_free.h>
9#include <deal.II/matrix_free/operators.h>
10
13
14#include <cmath>
15
16namespace MeltPoolDG
17{
18 template <int dim, int n_components, typename number>
20 const dealii::MatrixFree<dim, number> &matrix_free,
21 const unsigned int dof_no,
22 const unsigned int quad_no)
23 : fe_cell_evaluator(matrix_free, dof_no, quad_no)
24 {
26 }
27
28 template <int dim, int n_components, typename number>
30 const dealii::FEEvaluation<dim, -1, 0, n_components, number, VectorizedArrayType>
31 &fe_evaluation)
32 : fe_cell_evaluator(fe_evaluation)
33 {
35 }
36
37 template <int dim, int n_components, typename number>
38 void
39 FESubcellEvaluation<dim, n_components, number>::reinit(const unsigned int cell_batch_index_in)
40 {
41 cell_batch_index = cell_batch_index_in;
42 fe_cell_evaluator.reinit(cell_batch_index);
43 compute_intra_cell_face_sizes();
44
45 dof_values_initialized = false;
46 subcell_values_initialized = false;
47 subcell_values_submitted = false;
48 subcell_fluxes_submitted = false;
49
50 is_reinitialized = true;
51 }
52
53 template <int dim, int n_components, typename number>
54 void
56 const dealii::LinearAlgebra::distributed::Vector<number> &src_vector,
57 const std::bitset<n_lanes> &mask)
58 {
59 Assert(is_reinitialized,
60 dealii::ExcMessage(
61 "FESubcellEvaluation has not been reinitialized. Call reinit() before evaluate()."));
62 fe_cell_evaluator.read_dof_values(src_vector, 0, mask);
63
64 dof_values_initialized = true;
65 }
66
67 template <int dim, int n_components, typename number>
68 void
70 const dealii::EvaluationFlags::EvaluationFlags evaluation_flags)
71 {
72 Assert(dof_values_initialized,
73 dealii::ExcMessage(
74 "DoF values have not been initialized. Call read_dof_values() before evaluate()."));
75
76 project_dof_values_to_subcell_values(evaluation_flags);
77 }
78
79 template <int dim, int n_components, typename number>
80 void
82 const dealii::LinearAlgebra::distributed::Vector<number> &input_vector,
83 const dealii::EvaluationFlags::EvaluationFlags evaluation_flags,
84 const std::bitset<n_lanes> &mask)
85 {
86 read_dof_values(input_vector, mask);
87 evaluate(evaluation_flags);
88 }
89
90 template <int dim, int n_components, typename number>
91 auto
92 FESubcellEvaluation<dim, n_components, number>::get_value(const unsigned int subcell_index) const
93 -> value_type
94 {
95 AssertIndexRange(subcell_index, n_subcells_total);
96 Assert(subcell_values_initialized,
97 dealii::ExcMessage(
98 "Subcell values have not been initialized. Call evaluate() before get_value()."));
99 return subcell_values[subcell_index];
100 }
101
102 template <int dim, int n_components, typename number>
103 auto
105 const unsigned int subcell_face_index,
106 bool interior_face) const -> value_type
107 {
108 AssertIndexRange(subcell_face_index, n_intra_cell_faces);
109 Assert(subcell_values_initialized,
110 dealii::ExcMessage(
111 "Subcell values have not been initialized. Call evaluate() before get_value()."));
112 return subcell_values[face_adjacent_subcell_index(subcell_face_index, interior_face)];
113 }
114
115 template <int dim, int n_components, typename number>
116 auto
118 const unsigned int subcell_index) const -> gradient_type
119 {
120 AssertIndexRange(subcell_index, n_subcells_total);
121 Assert(
122 subcell_gradients_initialized,
123 dealii::ExcMessage(
124 "Subcell gradients have not been initialized. Call evaluate() before get_gradient()."));
125 return subcell_gradients[subcell_index];
126 }
127
128 template <int dim, int n_components, typename number>
129 void
131 const value_type &value)
132 {
133 AssertIndexRange(subcell_index, n_subcells_total);
134 submitted_subcell_values[subcell_index] = value;
135 subcell_values_submitted = true;
136 }
137
138 template <int dim, int n_components, typename number>
139 void
141 const value_type &value)
142 {
143 AssertIndexRange(subcell_face_index, n_intra_cell_faces);
144 intra_cell_face_fluxes[subcell_face_index] = value;
145 subcell_fluxes_submitted = true;
146 }
147
148 template <int dim, int n_components, typename number>
149 void
151 {
152 Assert(
153 subcell_values_submitted or subcell_fluxes_submitted,
154 dealii::ExcMessage(
155 "Subcell values or fluxes have not been submitted. Call submit_value() or submit_flux() before integrate()."));
156
157 if (subcell_values_submitted)
158 {
159 for (unsigned int subcell : subcell_indices())
160 integrated_values_buffer[subcell] = submitted_subcell_values[subcell];
161 }
162 else
163 {
164 std::ranges::fill(integrated_values_buffer, value_type());
165 }
166
167 if (subcell_fluxes_submitted)
168 {
169 for (unsigned int subcell_face : subcell_face_indices())
170 {
171 const unsigned int interior_subcell_index =
172 face_adjacent_subcell_index(subcell_face, true);
173 const unsigned int exterior_subcell_index =
174 face_adjacent_subcell_index(subcell_face, false);
175
176 integrated_values_buffer[interior_subcell_index] +=
177 intra_cell_face_fluxes[subcell_face] * subcell_face_size(subcell_face) /
178 subcell_size(interior_subcell_index);
179 integrated_values_buffer[exterior_subcell_index] -=
180 intra_cell_face_fluxes[subcell_face] * subcell_face_size(subcell_face) /
181 subcell_size(exterior_subcell_index);
182 }
183 }
184
185 project_subcell_values_to_dof_values(integrated_values_buffer);
186 }
187
188 template <int dim, int n_components, typename number>
189 void
191 dealii::LinearAlgebra::distributed::Vector<number> &dst_vector,
192 const std::bitset<n_lanes> &mask)
193 {
194 integrate();
195 distribute_local_to_global(dst_vector, mask);
196 }
197
198 template <int dim, int n_components, typename number>
199 void
201 dealii::LinearAlgebra::distributed::Vector<number> &dst_vector,
202 const std::bitset<n_lanes> &mask)
203 {
204 fe_cell_evaluator.distribute_local_to_global(dst_vector, 0, mask);
205 }
206
207 template <int dim, int n_components, typename number>
208 void
210 dealii::LinearAlgebra::distributed::Vector<number> &dst_vector,
211 const std::bitset<n_lanes> &mask)
212 {
213 fe_cell_evaluator.set_dof_values(dst_vector, 0, mask);
214 }
215
216 template <int dim, int n_components, typename number>
217 std::ranges::iota_view<unsigned int, unsigned int>
219 {
220 return {0U, n_subcells_total};
221 }
222
223 template <int dim, int n_components, typename number>
224 std::ranges::iota_view<unsigned int, unsigned int>
226 {
227 return {0U, n_intra_cell_faces};
228 }
229
230 template <int dim, int n_components, typename number>
231 auto
233 const unsigned int subcell_index) const -> VectorizedArrayType
234 {
235 Assert(
236 is_reinitialized,
237 dealii::ExcMessage(
238 "FESubcellEvaluation has not been reinitialized. Call reinit() before subcell_size()."));
239 AssertIndexRange(subcell_index, n_subcells_total);
240 return fe_cell_evaluator.JxW(subcell_index);
241 }
242
243 template <int dim, int n_components, typename number>
244 auto
246 const unsigned int subcell_face_index) const -> VectorizedArrayType
247 {
248 Assert(
249 is_reinitialized,
250 dealii::ExcMessage(
251 "FESubcellEvaluation has not been reinitialized. Call reinit() before subcell_face_size()."));
252 AssertIndexRange(subcell_face_index, n_intra_cell_faces);
253
254 return intra_cell_face_sizes[subcell_face_index];
255 }
256
257 template <int dim, int n_components, typename number>
258 auto
260 const unsigned int subcell_index) const -> dealii::Point<dim, VectorizedArrayType>
261 {
262 AssertIndexRange(subcell_index, n_subcells_total);
263 Assert(
264 is_reinitialized,
265 dealii::ExcMessage(
266 "FESubcellEvaluation has not been reinitialized. Call reinit() before subcell_location()."));
267 return fe_cell_evaluator.quadrature_point(subcell_index);
268 }
269
270 template <int dim, int n_components, typename number>
271 unsigned int
273 {
274 return n_subcells_total;
275 }
276
277 template <int dim, int n_components, typename number>
278 dealii::Tensor<1, dim, dealii::VectorizedArray<number>>
280 const unsigned int subcell_face_index) const
281 {
282 AssertIndexRange(subcell_face_index, n_intra_cell_faces);
283 Assert(
284 is_reinitialized,
285 dealii::ExcMessage(
286 "FESubcellEvaluation has not been reinitialized. Call reinit() before subcell_face_normal_vector()."));
287 const unsigned int face_normal_direction =
288 compute_reference_coordinates_normal_direction(subcell_face_index);
289 dealii::Tensor<1, dim, VectorizedArrayType> normal_vector;
290 normal_vector[face_normal_direction] = VectorizedArrayType(1.0);
291 return normal_vector;
292 }
293
294 template <int dim, int n_components, typename number>
295 std::pair<unsigned int, unsigned int>
297 const unsigned int subcell_face_index) const
298 {
299 AssertIndexRange(subcell_face_index, n_intra_cell_faces);
300 Assert(
301 is_reinitialized,
302 dealii::ExcMessage(
303 "FESubcellEvaluation has not been reinitialized. Call reinit() before subcell_face_interior_exterior_indices()."));
304 const unsigned int interior_subcell_index =
305 face_adjacent_subcell_index(subcell_face_index, true);
306 const unsigned int exterior_subcell_index =
307 face_adjacent_subcell_index(subcell_face_index, false);
308 return {interior_subcell_index, exterior_subcell_index};
309 }
310
311 template <int dim, int n_components, typename number>
312 void
314 {
315 n_subcells_total = fe_cell_evaluator.n_q_points;
316 this->n_subcells_1d = fe_cell_evaluator.get_shape_info().data[0].n_q_points_1d;
317
318 n_intra_cell_faces =
319 dim * (n_subcells_1d - 1) * dealii::Utilities::fixed_power<dim - 1>(n_subcells_1d);
320
321 subcell_values.resize(n_subcells_total);
322 subcell_gradients.resize(n_subcells_total);
323 submitted_subcell_values.resize(n_subcells_total);
324 intra_cell_face_fluxes.resize(n_intra_cell_faces);
325 intra_cell_face_sizes.resize(n_intra_cell_faces);
326 subcell_values_to_project_buffer.resize(n_components * n_subcells_total);
327 integrated_values_buffer.resize(n_subcells_total);
328 }
329
330 template <int dim, int n_components, typename number>
331 void
333 {
334 Assert(fe_cell_evaluator.get_cell_type() == dealii::internal::MatrixFreeFunctions::cartesian,
335 dealii::ExcNotImplemented());
336
337 // On a Cartesian cell, the extent of a subcell in direction d is h_d * w_{i_d}, with the cell
338 // extent h_d, the subcell index i_d in direction d and the 1D quadrature weight w_{i_d} on the
339 // unit interval. The size of a face is thus the volume of its interior subcell divided by the
340 // extent of that subcell in the face normal direction assuming the inverse Jacobian is diagonal
341 // with the entries 1/h_d.
342 const dealii::Quadrature<1> &quadrature_1d =
343 fe_cell_evaluator.get_shape_info().data[0].quadrature;
344
345 for (const unsigned int subcell_face : subcell_face_indices())
346 {
347 const unsigned int face_normal_direction =
348 compute_reference_coordinates_normal_direction(subcell_face);
349 const unsigned int interior_subcell = face_adjacent_subcell_index(subcell_face, true);
350 const unsigned int interior_subcell_index_1d =
351 (interior_subcell / dealii::Utilities::pow(n_subcells_1d, face_normal_direction)) %
352 n_subcells_1d;
353
354 intra_cell_face_sizes[subcell_face] =
355 fe_cell_evaluator.JxW(interior_subcell) *
356 fe_cell_evaluator.inverse_jacobian(
357 interior_subcell)[face_normal_direction][face_normal_direction] /
358 quadrature_1d.weight(interior_subcell_index_1d);
359 }
360 }
361
362 template <int dim, int n_components, typename number>
363 void
365 const dealii::EvaluationFlags::EvaluationFlags evaluation_flags)
366 {
367 AssertDimension(subcell_values.size(), fe_cell_evaluator.n_q_points);
368
369 fe_cell_evaluator.evaluate(evaluation_flags);
370
371 for (unsigned int q : fe_cell_evaluator.quadrature_point_indices())
372 {
373 if (evaluation_flags & dealii::EvaluationFlags::values)
374 subcell_values[q] = fe_cell_evaluator.get_value(q);
375 if (evaluation_flags & dealii::EvaluationFlags::gradients)
376 subcell_gradients[q] = fe_cell_evaluator.get_gradient(q);
377 }
378
379 if (evaluation_flags & dealii::EvaluationFlags::values)
380 subcell_values_initialized = true;
381 if (evaluation_flags & dealii::EvaluationFlags::gradients)
382 subcell_gradients_initialized = true;
383 }
384
385 template <int dim, int n_components, typename number>
386 void
388 const std::vector<value_type> &values_to_project)
389 {
390 AssertDimension(values_to_project.size(), fe_cell_evaluator.n_q_points);
391
392 dealii::MatrixFreeOperators::CellwiseInverseMassMatrix<dim, -1, n_components, number> inverse(
393 fe_cell_evaluator);
394
395 for (unsigned int subcell : subcell_indices())
396 {
397 if constexpr (n_components == 1)
398 subcell_values_to_project_buffer[subcell] = values_to_project[subcell];
399 else
400 for (unsigned int c = 0; c < n_components; ++c)
401 subcell_values_to_project_buffer[c * n_subcells_total + subcell] =
402 values_to_project[subcell][c];
403 }
404 inverse.transform_from_q_points_to_basis(n_components,
405 subcell_values_to_project_buffer.data(),
406 fe_cell_evaluator.begin_dof_values());
407 }
408
409 template <int dim, int n_components, typename number>
410 unsigned int
412 const unsigned int subcell_face_index) const
413 {
414 const unsigned int n_faces_per_direction =
415 (n_subcells_1d - 1) * dealii::Utilities::fixed_power<dim - 1>(n_subcells_1d);
416
417 return subcell_face_index / n_faces_per_direction;
418 }
419
420 template <int dim, int n_components, typename number>
421 unsigned int
423 const unsigned int subcell_face_index,
424 const bool interior_face) const
425 {
426 AssertIndexRange(subcell_face_index, n_intra_cell_faces);
427
428 const unsigned int n_faces_per_direction =
429 (n_subcells_1d - 1) * dealii::Utilities::fixed_power<dim - 1>(n_subcells_1d);
430
431 const unsigned int face_normal_direction =
432 compute_reference_coordinates_normal_direction(subcell_face_index);
433
434 unsigned int frame_local_index =
435 subcell_face_index - face_normal_direction * n_faces_per_direction;
436 if (face_normal_direction == dim - 1)
437 {
438 if (interior_face)
439 return frame_local_index;
440 else
441 return frame_local_index + dealii::Utilities::pow(n_subcells_1d, face_normal_direction);
442 }
443 else if (dim == 3 and face_normal_direction == 1)
444 {
445 const unsigned int layer = frame_local_index / (n_subcells_1d * (n_subcells_1d - 1));
446 if (interior_face)
447 return frame_local_index + layer * n_subcells_1d;
448 else
449 return frame_local_index + (layer + 1) * n_subcells_1d;
450 }
451 else
452 {
453 const unsigned int layer = frame_local_index / (n_subcells_1d - 1);
454 if (interior_face)
455 return frame_local_index + layer;
456 else
457 return frame_local_index + layer + 1;
458 }
459 }
460} // namespace MeltPoolDG
dealii::FEEvaluation< dim, -1, 0, n_components, number, VectorizedArrayType >::value_type value_type
Definition fe_subcell_evaluation.hpp:192
void submit_value(const unsigned int subcell_index, const value_type &value)
Definition fe_subcell_evaluation.templates.hpp:130
unsigned int compute_reference_coordinates_normal_direction(const unsigned int subcell_face_index) const
Definition fe_subcell_evaluation.templates.hpp:411
value_type get_value(const unsigned int subcell_index) const
Definition fe_subcell_evaluation.templates.hpp:92
void integrate()
Definition fe_subcell_evaluation.templates.hpp:150
value_type get_face_value(const unsigned int subcell_face_index, const bool interior_value) const
Definition fe_subcell_evaluation.templates.hpp:104
std::ranges::iota_view< unsigned int, unsigned int > subcell_indices() const
Definition fe_subcell_evaluation.templates.hpp:218
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_evaluation.templates.hpp:81
std::ranges::iota_view< unsigned int, unsigned int > subcell_face_indices() const
Definition fe_subcell_evaluation.templates.hpp:225
dealii::Tensor< 1, dim, VectorizedArrayType > subcell_face_normal_vector(const unsigned int subcell_face_index) const
Definition fe_subcell_evaluation.templates.hpp:279
void evaluate(const dealii::EvaluationFlags::EvaluationFlags evaluation_flags)
Definition fe_subcell_evaluation.templates.hpp:69
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_evaluation.templates.hpp:200
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_evaluation.templates.hpp:55
gradient_type get_gradient(const unsigned int subcell_index) const
Definition fe_subcell_evaluation.templates.hpp:117
dealii::FEEvaluation< dim, -1, 0, n_components, number, VectorizedArrayType >::gradient_type gradient_type
Definition fe_subcell_evaluation.hpp:195
void reinit(const unsigned int cell_batch_index)
Definition fe_subcell_evaluation.templates.hpp:39
std::pair< unsigned int, unsigned int > subcell_face_interior_exterior_indices(const unsigned int subcell_face_index) const
Definition fe_subcell_evaluation.templates.hpp:296
unsigned int face_adjacent_subcell_index(const unsigned int subcell_face_index, const bool interior_face) const
Definition fe_subcell_evaluation.templates.hpp:422
dealii::Point< dim, VectorizedArrayType > subcell_location(const unsigned int subcell_index) const
Definition fe_subcell_evaluation.templates.hpp:259
VectorizedArrayType subcell_size(const unsigned int subcell_index) const
Definition fe_subcell_evaluation.templates.hpp:232
FESubcellEvaluation(const dealii::MatrixFree< dim, number > &matrix_free, const unsigned int dof_no, const unsigned int quad_no)
Definition fe_subcell_evaluation.templates.hpp:19
void project_dof_values_to_subcell_values(const dealii::EvaluationFlags::EvaluationFlags evaluation_flags)
Definition fe_subcell_evaluation.templates.hpp:364
dealii::VectorizedArray< number > VectorizedArrayType
Definition fe_subcell_evaluation.hpp:189
VectorizedArrayType subcell_face_size(const unsigned int subcell_face_index) const
Definition fe_subcell_evaluation.templates.hpp:245
void project_subcell_values_to_dof_values(const std::vector< value_type > &values_to_project)
Definition fe_subcell_evaluation.templates.hpp:387
void submit_flux(const unsigned int subcell_face_index, const value_type &flux)
Definition fe_subcell_evaluation.templates.hpp:140
void compute_intra_cell_face_sizes()
Definition fe_subcell_evaluation.templates.hpp:332
void set_dof_values(dealii::LinearAlgebra::distributed::Vector< number > &dst, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
Definition fe_subcell_evaluation.templates.hpp:209
void setup_internal_data_structures()
Definition fe_subcell_evaluation.templates.hpp:313
void integrate_scatter(dealii::LinearAlgebra::distributed::Vector< number > &dst_vector, const std::bitset< n_lanes > &mask=std::bitset< n_lanes >().flip())
Definition fe_subcell_evaluation.templates.hpp:190
unsigned n_subcells() const
Definition fe_subcell_evaluation.templates.hpp:272
Interface for a general preconditioner.
Definition boundary_condition_functions.hpp:17