include/meltpooldg/utilities/matrix_free_util.hpp Source File

Developer Documentation: include/meltpooldg/utilities/matrix_free_util.hpp Source File
Developer Documentation
matrix_free_util.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <deal.II/base/tensor.h>
4
5#include <deal.II/grid/grid_tools.h>
6#include <deal.II/grid/tria.h>
7
8#include <deal.II/matrix_free/fe_evaluation.h>
9#include <deal.II/matrix_free/matrix_free.h>
10#include <deal.II/matrix_free/tools.h>
11
13
14#include <vector>
15
16namespace MeltPoolDG
17{
18
19 template <int dim, typename Number>
21 {
22 const dealii::MatrixFree<dim, Number> &mf;
23 unsigned int dof_idx;
24 unsigned int quad_idx;
25 };
26
43 template <typename FeEval>
44 dealii::Tensor<1, FeEval::n_components, dealii::VectorizedArray<typename FeEval::number_type>>
45 fe_evaluation_tensor_value_at_q(const FeEval &fe_eval, const unsigned q_index)
46 {
47 using ValueType = typename FeEval::value_type;
48 using VectorizedArrayType = dealii::VectorizedArray<typename FeEval::number_type>;
49
50 if constexpr (std::is_same_v<ValueType, VectorizedArrayType>)
51 {
52 dealii::Tensor<1, 1, VectorizedArrayType> t;
53 t[0] = fe_eval.get_value(q_index);
54 return t;
55 }
56 else
57 return fe_eval.get_value(q_index);
58 }
59
67 template <int dim, typename number>
68 std::vector<dealii::TriaIterator<dealii::CellAccessor<dim>>>
69 cells_in_cell_batch(const dealii::MatrixFree<dim, number> &mf, const unsigned int cell_batch_id)
70 {
71 unsigned int n_active_lanes = mf.n_active_entries_per_cell_batch(cell_batch_id);
72
73 std::vector<dealii::TriaIterator<dealii::CellAccessor<dim>>> cells;
74 cells.reserve(n_active_lanes);
75
76 for (unsigned int lane = 0; lane < n_active_lanes; ++lane)
77 cells.push_back(mf.get_cell_iterator(cell_batch_id, lane));
78
79 return cells;
80 }
81
90 template <int dim, typename number>
91 dealii::VectorizedArray<number>
92 cell_batch_measure(const dealii::MatrixFree<dim, number> &mf,
93 const unsigned int cell_batch_id,
94 const unsigned int dof_handler_index = 0)
95 {
96 dealii::VectorizedArray<number> measures = 0.;
97 for (unsigned int lane = 0; lane < mf.n_active_entries_per_cell_batch(cell_batch_id); ++lane)
98 {
99 measures[lane] = mf.get_cell_iterator(cell_batch_id, lane, dof_handler_index)->measure();
100 }
101 return measures;
102 }
103
112 template <int dim, typename number>
113 dealii::Point<dim, dealii::VectorizedArray<number>>
114 cell_batch_center(const dealii::MatrixFree<dim, number> &mf,
115 const unsigned int cell_batch_id,
116 const unsigned int dof_handler_index = 0)
117 {
118 dealii::Point<dim, dealii::VectorizedArray<number>> centers;
119 for (unsigned int lane = 0; lane < mf.n_active_entries_per_cell_batch(cell_batch_id); ++lane)
120 {
121 const auto center =
122 mf.get_cell_iterator(cell_batch_id, lane, dof_handler_index)->barycenter();
123 for (unsigned int d = 0; d < dim; ++d)
124 {
125 centers[d][lane] = center[d];
126 }
127 }
128 return centers;
129 }
130
138
144 template <typename OperatorType, int dim, typename number>
146 requires(OperatorType op,
147 dealii::FEEvaluation<dim, -1, 0, dim + 2, number> &fe_evaluator,
148 const dealii::FEEvaluation<dim, -1, 0, dim + 2, number> &const_fe_evaluator,
149 dealii::FEFaceEvaluation<dim, -1, 0, dim + 2, number> &fe_face_evaluator,
150 const dealii::FEFaceEvaluation<dim, -1, 0, dim + 2, number> &const_fe_face_evaluator,
151 unsigned int q_index) {
156 op.local_cell_jacobian_kernel(fe_evaluator, const_fe_evaluator, q_index);
157
162 op.local_face_jacobian_kernel(fe_face_evaluator,
163 fe_face_evaluator,
164 const_fe_face_evaluator,
165 const_fe_face_evaluator,
166 q_index);
167
172 op.local_boundary_face_jacobian_kernel(fe_face_evaluator, const_fe_face_evaluator, q_index);
173 };
174
190 template <int dim,
191 int n_components,
192 typename number,
194 void
196 const OperatorType &implicit_operator,
197 std::variant<dealii::LinearAlgebra::distributed::Vector<number> *,
198 dealii::TrilinosWrappers::SparseMatrix *> dst,
199 const MatrixRepresentationType type,
200 const dealii::LinearAlgebra::distributed::Vector<number> &current_solution,
201 const dealii::MatrixFree<dim, number> &matrix_free,
202 const unsigned int dof_idx,
203 const unsigned int quad_idx)
204 {
205 FECellIntegrator<dim, n_components, number> phi(matrix_free, dof_idx, quad_idx);
206
207 // ## Cell ## //
208 std::function<void(FECellIntegrator<dim, n_components, number> &)> cell_operation =
209 [&](FECellIntegrator<dim, n_components, number> &delta_phi) -> void {
210 phi.reinit(delta_phi.get_cell_or_face_batch_id());
211 phi.gather_evaluate(current_solution,
212 dealii::EvaluationFlags::values | dealii::EvaluationFlags::gradients);
213 delta_phi.evaluate(dealii::EvaluationFlags::values | dealii::EvaluationFlags::gradients);
214
215 for (const unsigned int q_index : delta_phi.quadrature_point_indices())
216 {
217 implicit_operator.local_cell_jacobian_kernel(delta_phi, phi, q_index);
218 }
219
220 delta_phi.integrate(dealii::EvaluationFlags::values | dealii::EvaluationFlags::gradients);
221 };
222
223 // ## Face ##//
225 true /*is_interior_face*/,
226 dof_idx,
227 quad_idx);
229 false /*is_interior_face*/,
230 dof_idx,
231 quad_idx);
234 face_operation = [&](FEFaceIntegrator<dim, n_components, number> &delta_phi_m,
235 FEFaceIntegrator<dim, n_components, number> &delta_phi_p) -> void {
236 phi_m.reinit(delta_phi_m.get_cell_or_face_batch_id());
237 phi_p.reinit(delta_phi_p.get_cell_or_face_batch_id());
238 phi_m.gather_evaluate(current_solution,
239 dealii::EvaluationFlags::values | dealii::EvaluationFlags::gradients);
240 phi_p.gather_evaluate(current_solution,
241 dealii::EvaluationFlags::values | dealii::EvaluationFlags::gradients);
242
243 delta_phi_p.evaluate(dealii::EvaluationFlags::values | dealii::EvaluationFlags::gradients);
244 delta_phi_m.evaluate(dealii::EvaluationFlags::values | dealii::EvaluationFlags::gradients);
245
246
247 for (const unsigned int q_index : delta_phi_m.quadrature_point_indices())
248 {
249 implicit_operator.local_face_jacobian_kernel(
250 delta_phi_m, delta_phi_p, phi_m, phi_p, q_index);
251 }
252 delta_phi_m.integrate(dealii::EvaluationFlags::values);
253 delta_phi_p.integrate(dealii::EvaluationFlags::values);
254 };
255
256 // ## Boundary face ##//
257 FEFaceIntegrator<dim, n_components, number> phi_boundary(matrix_free,
258 true /*is_interior_face*/,
259 dof_idx,
260 quad_idx);
261 std::function<void(FEFaceIntegrator<dim, n_components, number> &)> boundary_operation =
262 [&](FEFaceIntegrator<dim, n_components, number> &delta_phi_boundary) -> void {
263 phi_boundary.reinit(delta_phi_boundary.get_cell_or_face_batch_id());
264 phi_boundary.gather_evaluate(current_solution,
265 dealii::EvaluationFlags::values |
266 dealii::EvaluationFlags::gradients);
267 delta_phi_boundary.evaluate(dealii::EvaluationFlags::values |
268 dealii::EvaluationFlags::gradients);
269
270
271 for (const unsigned int q_index : delta_phi_boundary.quadrature_point_indices())
272 {
273 implicit_operator.local_boundary_face_jacobian_kernel(delta_phi_boundary,
274 phi_boundary,
275 q_index);
276 }
277 delta_phi_boundary.integrate(dealii::EvaluationFlags::values);
278 };
279
280 switch (type)
281 {
283 dealii::MatrixFreeTools::compute_diagonal(
284 matrix_free,
285 *std::get<dealii::LinearAlgebra::distributed::Vector<number> *>(dst),
286 cell_operation,
287 face_operation,
288 boundary_operation,
289 dof_idx,
290 quad_idx);
291 break;
292 }
294 dealii::MatrixFreeTools::compute_matrix(
295 matrix_free,
296 dealii::AffineConstraints<number>(),
297 *std::get<dealii::TrilinosWrappers::SparseMatrix *>(dst),
298 cell_operation,
299 face_operation,
300 boundary_operation,
301 dof_idx,
302 quad_idx);
303 break;
304 }
305 default:
306 DEAL_II_ASSERT_UNREACHABLE();
307 }
308 }
309
325 template <int dim, typename number, int n_components>
326 std::vector<std::pair<dealii::Tensor<1, n_components, number>,
327 dealii::Tensor<1, n_components, dealii::Tensor<1, dim, number>>>>
329 const MatrixFreeContext<dim, number> &mf_context,
330 const dealii::LinearAlgebra::distributed::Vector<number> &solution)
331 {
332 using VectorizedArrayType = dealii::VectorizedArray<number>;
333 using ActiveCellIterator = typename dealii::Triangulation<dim>::active_cell_iterator;
334
335 using AveragePairType =
336 std::pair<dealii::Tensor<1, n_components, number>,
337 dealii::Tensor<1, n_components, dealii::Tensor<1, dim, number>>>;
338
339 // A lambda used to exchange the cell average values of ghost cells after they have been
340 // computed for the locally owned cells.
341 const auto exchange_cell_data_to_ghosts =
342 [](const dealii::Triangulation<dim> &triangulation,
343 std::vector<AveragePairType> &cell_average_values) {
344 std::function<std::optional<AveragePairType>(const ActiveCellIterator &)> pack =
345 [&](const ActiveCellIterator &cell) -> std::optional<AveragePairType> {
346 return cell_average_values[cell->active_cell_index()];
347 };
348 std::function<void(const ActiveCellIterator &, const AveragePairType &)> unpack =
349 [&](const ActiveCellIterator &cell, const AveragePairType &value) {
350 cell_average_values[cell->active_cell_index()] = value;
351 };
352 dealii::GridTools::exchange_cell_data_to_ghosts(triangulation, pack, unpack);
353 };
354
355 // A lambda that computes the cell average values for a given range of cells used in the cell
356 // loop of the matrix free object.
357 const std::function<void(const dealii::MatrixFree<dim, number, VectorizedArrayType> &,
358 std::vector<AveragePairType> &,
359 const dealii::LinearAlgebra::distributed::Vector<number> &,
360 const std::pair<unsigned int, unsigned int> &)>
361 cell_loop = [&](const dealii::MatrixFree<dim, number, VectorizedArrayType> &matrix_free,
362 std::vector<AveragePairType> &dst_cell_average_values,
363 const dealii::LinearAlgebra::distributed::Vector<number> &src,
364 const std::pair<unsigned int, unsigned int> &cell_range) {
365 FECellIntegrator<dim, n_components, number> fe_cell_integrator(matrix_free,
366 mf_context.dof_idx,
367 mf_context.quad_idx);
368
369 for (unsigned int cell = cell_range.first; cell < cell_range.second; ++cell)
370 {
371 fe_cell_integrator.reinit(cell);
372 fe_cell_integrator.gather_evaluate(src,
373 dealii::EvaluationFlags::values |
374 dealii::EvaluationFlags::gradients);
375
378 cell_average_gradient;
379 VectorizedArrayType cell_volume = 0.;
380 for (const unsigned int q : fe_cell_integrator.quadrature_point_indices())
381 {
382 cell_average_value += fe_cell_integrator.get_value(q) * fe_cell_integrator.JxW(q);
383 cell_average_gradient +=
384 fe_cell_integrator.get_gradient(q) * fe_cell_integrator.JxW(q);
385 cell_volume += fe_cell_integrator.JxW(q);
386 }
387 cell_average_value /= cell_volume;
388 for (unsigned int c = 0; c < n_components; ++c)
389 cell_average_gradient[c] /= cell_volume;
390
391 const auto cells = cells_in_cell_batch(mf_context.mf, cell);
392
393 for (unsigned int lane = 0; lane < mf_context.mf.n_active_entries_per_cell_batch(cell);
394 ++lane)
395 {
396 for (unsigned int c = 0; c < n_components; ++c)
397 {
398 dst_cell_average_values[cells[lane]->active_cell_index()].first[c] =
399 cell_average_value[c][lane];
400 for (unsigned int d = 0; d < dim; ++d)
401 {
402 dst_cell_average_values[cells[lane]->active_cell_index()].second[c][d] =
403 cell_average_gradient[c][d][lane];
404 }
405 }
406 }
407 }
408 };
409
410 std::vector<AveragePairType> cell_average_values(
411 mf_context.mf.get_dof_handler(mf_context.dof_idx).get_triangulation().n_active_cells());
412 mf_context.mf.cell_loop(cell_loop, cell_average_values, solution);
413
414 exchange_cell_data_to_ghosts(
415 mf_context.mf.get_dof_handler(mf_context.dof_idx).get_triangulation(), cell_average_values);
416
417 return cell_average_values;
418 }
419} // namespace MeltPoolDG
Definition matrix_free_util.hpp:145
Interface for a general preconditioner.
Definition boundary_condition_functions.hpp:17
dealii::Point< dim, dealii::VectorizedArray< number > > cell_batch_center(const dealii::MatrixFree< dim, number > &mf, const unsigned int cell_batch_id, const unsigned int dof_handler_index=0)
Definition matrix_free_util.hpp:114
dealii::Tensor< 1, FeEval::n_components, dealii::VectorizedArray< typename FeEval::number_type > > fe_evaluation_tensor_value_at_q(const FeEval &fe_eval, const unsigned q_index)
Definition matrix_free_util.hpp:45
dealii::FEFaceEvaluation< dim, -1, 0, n_components, number, VectorizedArrayType > FEFaceIntegrator
Definition fe_integrator.hpp:22
std::vector< std::pair< dealii::Tensor< 1, n_components, number >, dealii::Tensor< 1, n_components, dealii::Tensor< 1, dim, number > > > > compute_cell_average_quantities(const MatrixFreeContext< dim, number > &mf_context, const dealii::LinearAlgebra::distributed::Vector< number > &solution)
Definition matrix_free_util.hpp:328
std::vector< dealii::TriaIterator< dealii::CellAccessor< dim > > > cells_in_cell_batch(const dealii::MatrixFree< dim, number > &mf, const unsigned int cell_batch_id)
Definition matrix_free_util.hpp:69
void compute_jacobian_matrix_representation(const OperatorType &implicit_operator, std::variant< dealii::LinearAlgebra::distributed::Vector< number > *, dealii::TrilinosWrappers::SparseMatrix * > dst, const MatrixRepresentationType type, const dealii::LinearAlgebra::distributed::Vector< number > &current_solution, const dealii::MatrixFree< dim, number > &matrix_free, const unsigned int dof_idx, const unsigned int quad_idx)
Definition matrix_free_util.hpp:195
dealii::VectorizedArray< number > cell_batch_measure(const dealii::MatrixFree< dim, number > &mf, const unsigned int cell_batch_id, const unsigned int dof_handler_index=0)
Definition matrix_free_util.hpp:92
MatrixRepresentationType
Definition matrix_free_util.hpp:134
@ DiagonalMatrix
Definition matrix_free_util.hpp:135
@ SystemMatrix
Definition matrix_free_util.hpp:136
dealii::FEEvaluation< dim, -1, 0, n_components, number, VectorizedArrayType > FECellIntegrator
Definition fe_integrator.hpp:14
Definition matrix_free_util.hpp:21
unsigned int quad_idx
Definition matrix_free_util.hpp:24
const dealii::MatrixFree< dim, Number > & mf
Definition matrix_free_util.hpp:22
unsigned int dof_idx
Definition matrix_free_util.hpp:23