8#include <compile_time_options.h>
15#include "../euler/hyperbolic_system.h"
18#include <deal.II/base/vectorization.h>
19#include <deal.II/lac/diagonal_matrix.h>
20#include <deal.II/matrix_free/fe_evaluation.h>
21#include <deal.II/matrix_free/tools.h>
22#include <deal.II/multigrid/mg_base.h>
23#include <deal.II/multigrid/mg_transfer_matrix_free.h>
32 namespace NavierStokes
44 template <
int dim,
typename Number>
51 using vector_type = dealii::LinearAlgebra::distributed::Vector<Number>;
57 dealii::LinearAlgebra::distributed::BlockVector<Number>;
68 template <
typename Vector>
69 void reinit(
const Vector &lumped_mass_matrix,
71 const dealii::AffineConstraints<Number> &affine_constraints)
73 diagonal.reinit(density,
true);
75 const auto n_owned = density.get_partitioner()->locally_owned_size();
77 const auto body_invert = [&](
auto sentinel,
const unsigned int i) {
78 using T =
decltype(sentinel);
81 if constexpr (std::is_same_v<Vector, vector_type>) {
82 m_i = read_entry<T>(lumped_mass_matrix, i);
84 m_i = lumped_mass_matrix.template read_entry<T>(i);
87 const auto rho_i = read_entry<T>(density, i);
88 write_entry<T>(diagonal, Number(1.0) / (rho_i * m_i), i);
91 cpu_simd_loop<Number>(
"", body_invert, 0, n_owned, n_owned);
97 affine_constraints.set_zero(diagonal);
113 return diagonal_block;
121 AssertDimension(diagonal_block.size(), 0);
122 DEAL_II_OPENMP_SIMD_PRAGMA
123 for (
unsigned int i = 0;
124 i < diagonal.get_partitioner()->locally_owned_size();
126 dst.local_element(i) =
127 diagonal.local_element(i) * src.local_element(i);
135 AssertDimension(dim, dst.n_blocks());
136 AssertDimension(dim, src.n_blocks());
137 if (diagonal_block.size() == 0) {
138 DEAL_II_OPENMP_SIMD_PRAGMA
139 for (
unsigned int i = 0;
140 i < diagonal.get_partitioner()->locally_owned_size();
142 for (
unsigned int d = 0; d < dim; ++d)
143 dst.block(d).local_element(i) =
144 diagonal.local_element(i) * src.block(d).local_element(i);
146 for (
unsigned int d = 0; d < dim; ++d) {
147 DEAL_II_OPENMP_SIMD_PRAGMA
148 for (
unsigned int i = 0;
149 i < src.block(d).get_partitioner()->locally_owned_size();
151 dst.block(d).local_element(i) =
152 diagonal_block.block(d).local_element(i) *
153 src.block(d).local_element(i);
169 template <
int dim,
typename Number,
typename Number2>
177 using vector_type = dealii::LinearAlgebra::distributed::Vector<Number>;
179 dealii::LinearAlgebra::distributed::BlockVector<Number>;
186 const dealii::MatrixFree<dim, Number> &matrix_free,
187 const dealii::LinearAlgebra::distributed::Vector<Number> &density,
188 const Number theta_x_tau,
189 const unsigned int level = dealii::numbers::invalid_unsigned_int)
191 parabolic_system_ = ¶bolic_system;
192 offline_data_ = &offline_data;
193 matrix_free_ = &matrix_free;
195 theta_x_tau_ = theta_x_tau;
209 const auto get_lumped_mass = [&](
auto sentinel,
unsigned int i) {
210 using T =
decltype(sentinel);
211 if constexpr (std::is_same_v<Number, Number2>) {
212 if constexpr (std::is_same_v<Number, float>) {
213 if (level_ == dealii::numbers::invalid_unsigned_int) {
215 return lumped.template read_entry<T>(i);
217 const auto &level_lumped =
219 return read_entry<T>(level_lumped, i);
222 Assert(level_ == dealii::numbers::invalid_unsigned_int,
223 dealii::ExcInternalError());
225 return lumped.template read_entry<T>(i);
228 const auto &level_lumped =
230 return read_entry<T>(level_lumped, i);
234 const unsigned int n_owned =
235 dst.block(0).get_partitioner()->locally_owned_size();
237 const auto body_mass = [&](
auto sentinel,
unsigned int i) {
238 using T =
decltype(sentinel);
240 const auto m_i = get_lumped_mass(T(), i);
242 const auto rho_i = read_entry<T>(*density_, i);
243 for (
unsigned int d = 0; d < dim; ++d) {
244 const auto temp = read_entry<T>(src.block(d), i);
245 write_entry<T>(dst.block(d), m_i * rho_i * temp, i);
249 cpu_simd_loop<Number>(
"", body_mass, 0, n_owned, n_owned);
253 const auto integrator = [
this](
const auto &data,
257 dealii::FEEvaluation<dim, order_fe, order_quad, dim, Number> velocity(
260 for (
unsigned int cell = range.first; cell < range.second; ++cell) {
261 velocity.reinit(cell);
262 velocity.read_dof_values(src);
263 apply_local_operator(velocity);
264 velocity.distribute_local_to_global(dst);
268 matrix_free_->template cell_loop<block_vector_type, block_vector_type>(
269 integrator, dst, src,
false);
273 const auto &boundary_map =
274 level_ == dealii::numbers::invalid_unsigned_int
278 for (
auto entry : boundary_map) {
280 const auto i = std::get<0>(entry);
284 const dealii::Tensor<1, dim, Number> normal = std::get<1>(entry);
285 const auto id = std::get<4>(entry);
288 dealii::Tensor<1, dim, Number> V_i;
289 for (
unsigned int d = 0; d < dim; ++d)
290 V_i[d] = dst.block(d).local_element(i);
293 V_i -= 1. * (V_i * normal) * normal;
294 for (
unsigned int d = 0; d < dim; ++d) {
295 const auto src_d = src.block(d).local_element(i);
296 V_i += 1. * (src_d * normal[d]) * normal;
299 for (
unsigned int d = 0; d < dim; ++d)
300 dst.block(d).local_element(i) = V_i[d];
305 for (
unsigned int d = 0; d < dim; ++d)
306 dst.block(d).local_element(i) = src.block(d).local_element(i);
314 Assert(level_ != dealii::numbers::invalid_unsigned_int,
315 dealii::ExcNotImplemented());
316 matrix = std::make_shared<DiagonalMatrix<dim, Number>>();
319 for (
unsigned int d = 0; d < dim; ++d)
320 matrix_free_->initialize_dof_vector(vector.block(d));
321 vector.collect_sizes();
323 dealii::MatrixFreeTools::compute_diagonal(
326 &VelocityMatrix::template apply_local_operator<
327 dealii::FEEvaluation<dim, -1, 0, dim, Number>>,
330 const auto &lumped_mass_matrix =
332 const unsigned int n_owned =
333 lumped_mass_matrix.get_partitioner()->locally_owned_size();
335 const auto body_invert = [&](
auto sentinel,
const unsigned int i) {
336 using T =
decltype(sentinel);
337 const auto m_i = lumped_mass_matrix.local_element(i);
338 const auto rho_i = density_->local_element(i);
339 for (
unsigned int d = 0; d < dim; ++d)
342 (m_i * rho_i + read_entry<T>(vector.block(d), i)),
346 cpu_simd_loop<Number>(
"", body_invert, 0, n_owned, n_owned);
350 for (
auto entry : boundary_map) {
352 const auto i = std::get<0>(entry);
356 const dealii::Tensor<1, dim, Number> normal = std::get<1>(entry);
357 const auto id = std::get<4>(entry);
360 dealii::Tensor<1, dim, Number> V_i;
361 for (
unsigned int d = 0; d < dim; ++d)
362 V_i[d] = vector.block(d).local_element(i);
365 V_i -= 1. * (V_i * normal) * normal;
366 for (
unsigned int d = 0; d < dim; ++d) {
367 V_i += 1. * (1. * normal[d]) * normal;
370 for (
unsigned int d = 0; d < dim; ++d)
371 vector.block(d).local_element(i) = V_i[d];
376 for (
unsigned int d = 0; d < dim; ++d)
377 vector.block(d).local_element(i) = 1.;
385 const dealii::MatrixFree<dim, Number> *matrix_free_;
390 template <
typename Evaluator>
391 void apply_local_operator(Evaluator &velocity)
const
393 const Number mu = parabolic_system_->mu();
394 const Number lambda = parabolic_system_->lambda();
396 velocity.evaluate(dealii::EvaluationFlags::gradients);
398 for (
const unsigned int q : velocity.quadrature_point_indices()) {
399 if constexpr (dim == 1) {
401 const auto gradient = velocity.get_gradient(q);
402 auto S = (4. / 3. * mu + lambda) * gradient;
403 velocity.submit_gradient(theta_x_tau_ * S, q);
407 const auto symmetric_gradient = velocity.get_symmetric_gradient(q);
408 const auto divergence = trace(symmetric_gradient);
410 auto S = 2. * mu * symmetric_gradient;
411 for (
unsigned int d = 0; d < dim; ++d)
412 S[d][d] += (lambda - 2. / 3. * mu) * divergence;
413 velocity.submit_symmetric_gradient(theta_x_tau_ * S, q);
417 velocity.integrate(dealii::EvaluationFlags::gradients);
425 template <
int dim,
typename Number>
427 :
public dealii::MGTransferBase<
428 dealii::LinearAlgebra::distributed::BlockVector<Number>>
431 using scalar_type = dealii::LinearAlgebra::distributed::Vector<Number>;
433 dealii::LinearAlgebra::distributed::BlockVector<Number>;
437 void build(
const dealii::DoFHandler<dim> &dof_handler,
438 const dealii::MGConstrainedDoFs &mg_constrained_dofs,
439 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
442 transfer_.initialize_constraints(mg_constrained_dofs);
443 transfer_.build(dof_handler);
444 level_matrix_free_ = &matrix_free;
445 scalar_vector.resize(matrix_free.min_level(), matrix_free.max_level());
446 for (
unsigned int level = matrix_free.min_level();
447 level < matrix_free.max_level();
449 matrix_free[level].initialize_dof_vector(scalar_vector[level]);
456 for (
unsigned int block = 0; block < src.n_blocks(); ++block)
457 transfer_.prolongate(to_level, dst.block(block), src.block(block));
464 for (
unsigned int block = 0; block < src.n_blocks(); ++block)
465 transfer_.restrict_and_add(
466 to_level, dst.block(block), src.block(block));
469 template <
typename Number2>
471 const dealii::DoFHandler<dim> &dof_handler,
472 dealii::MGLevelObject<scalar_type> &dst,
473 const dealii::LinearAlgebra::distributed::Vector<Number2> &src)
const
475 if (dst[dst.min_level()].size() == 0)
476 for (
unsigned int l = dst.min_level(); l <= dst.max_level(); ++l)
477 (*level_matrix_free_)[l].initialize_dof_vector(dst[l]);
478 transfer_.interpolate_to_mg(dof_handler, dst, src);
481 template <
typename Number2>
484 dealii::MGLevelObject<vector_type> &dst,
485 const dealii::LinearAlgebra::distributed::BlockVector<Number2>
488 if (dst[dst.min_level()].size() == 0)
489 for (
unsigned int l = dst.min_level(); l <= dst.max_level(); ++l) {
490 dst[l].reinit(src.n_blocks());
491 for (
unsigned int block = 0; block < src.n_blocks(); ++block)
492 (*level_matrix_free_)[l].initialize_dof_vector(
493 dst[l].block(block));
494 dst[l].collect_sizes();
497 for (
unsigned int block = 0; block < src.n_blocks(); ++block) {
498 transfer_.copy_to_mg(dof_handler, scalar_vector, src.block(block));
499 for (
unsigned int level = dst.min_level(); level <= dst.max_level();
501 dst[level].block(block).copy_locally_owned_data_from(
502 scalar_vector[level]);
506 template <
typename Number2>
508 const dealii::DoFHandler<dim> &dof_handler,
509 dealii::LinearAlgebra::distributed::BlockVector<Number2> &dst,
510 const dealii::MGLevelObject<vector_type> &src)
const
512 for (
unsigned int block = 0; block < dst.n_blocks(); ++block) {
513 for (
unsigned int level = src.min_level(); level <= src.max_level();
515 scalar_vector[level].copy_locally_owned_data_from(
516 src[level].block(block));
517 transfer_.copy_from_mg(dof_handler, dst.block(block), scalar_vector);
522 dealii::MGTransferMatrixFree<dim, Number> transfer_;
523 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
525 mutable dealii::MGLevelObject<scalar_type> scalar_vector;
532 template <
int dim,
typename Number,
typename Number2>
540 using vector_type = dealii::LinearAlgebra::distributed::Vector<Number>;
546 const dealii::MatrixFree<dim, Number> &matrix_free,
547 const dealii::LinearAlgebra::distributed::Vector<Number> &density,
548 const Number time_factor,
549 const unsigned int level = dealii::numbers::invalid_unsigned_int)
551 offline_data_ = &offline_data;
552 matrix_free_ = &matrix_free;
554 factor_ = time_factor;
563 dealii::types::global_dof_index
m()
const
565 return density_->size();
568 Number
el(
const unsigned int,
const unsigned int)
const
570 Assert(
false, dealii::ExcNotImplemented());
579 const auto get_lumped_mass = [&](
auto sentinel,
unsigned int i) {
580 using T =
decltype(sentinel);
581 if constexpr (std::is_same_v<Number, Number2>) {
582 if constexpr (std::is_same_v<Number, float>) {
583 if (level_ == dealii::numbers::invalid_unsigned_int) {
585 return lumped.template read_entry<T>(i);
587 const auto &level_lumped =
589 return read_entry<T>(level_lumped, i);
592 Assert(level_ == dealii::numbers::invalid_unsigned_int,
593 dealii::ExcInternalError());
595 return lumped.template read_entry<T>(i);
598 const auto &level_lumped =
600 return read_entry<T>(level_lumped, i);
604 const unsigned int n_owned =
605 dst.get_partitioner()->locally_owned_size();
607 const auto body_mass = [&](
auto sentinel,
unsigned int i) {
608 using T =
decltype(sentinel);
609 const auto m_i = get_lumped_mass(T(), i);
610 const auto rho_i = read_entry<T>(*density_, i);
611 const auto e_i = read_entry<T>(src, i);
612 write_entry<T>(dst, m_i * rho_i * e_i, i);
615 cpu_simd_loop<Number>(
"", body_mass, 0, n_owned, n_owned);
619 const auto integrator = [
this](
const auto &data,
623 dealii::FEEvaluation<dim, order_fe, order_quad, 1, Number> energy(
626 for (
unsigned int cell = range.first; cell < range.second; ++cell) {
628 energy.read_dof_values(src);
629 apply_local_operator(energy);
630 energy.distribute_local_to_global(dst);
634 matrix_free_->template cell_loop<vector_type, vector_type>(
635 integrator, dst, src,
false);
639 const auto &boundary_map =
640 (level_ == dealii::numbers::invalid_unsigned_int)
644 for (
auto entry : boundary_map) {
645 const auto i = std::get<0>(entry);
649 const auto id = std::get<4>(entry);
651 dst.local_element(i) = src.local_element(i);
656 std::shared_ptr<dealii::DiagonalMatrix<vector_type>> &matrix)
const
658 Assert(level_ != dealii::numbers::invalid_unsigned_int,
659 dealii::ExcNotImplemented());
660 matrix = std::make_shared<dealii::DiagonalMatrix<vector_type>>();
662 matrix_free_->initialize_dof_vector(vector);
667 dealii::MatrixFreeTools::compute_diagonal(
670 &EnergyMatrix::template apply_local_operator<
671 dealii::FEEvaluation<dim, -1, 0, dim, Number>>,
674 const unsigned int n_owned =
675 lumped_mass_matrix.get_partitioner()->locally_owned_size();
677 const auto body_invert = [&](
auto sentinel,
const unsigned int i) {
678 using T =
decltype(sentinel);
680 const auto m_i = read_entry<T>(lumped_mass_matrix, i);
681 const auto rho_i = read_entry<T>(*density_, i);
683 vector, Number(1.) / (m_i * rho_i + read_entry<T>(vector, i)), i);
685 cpu_simd_loop<Number>(
"", body_invert, 0, n_owned, n_owned);
689 for (
auto entry : boundary_map) {
690 const auto i = std::get<0>(entry);
694 const auto id = std::get<4>(entry);
696 vector.local_element(i) = 1.;
702 const dealii::MatrixFree<dim, Number> *matrix_free_;
703 const dealii::LinearAlgebra::distributed::Vector<Number> *density_;
707 template <
typename Evaluator>
708 void apply_local_operator(Evaluator &energy)
const
710 energy.evaluate(dealii::EvaluationFlags::gradients);
711 for (
unsigned int q = 0; q < energy.n_q_points; ++q) {
712 energy.submit_gradient(factor_ * energy.get_gradient(q), q);
714 energy.integrate(dealii::EvaluationFlags::gradients);
722 template <
int dim,
typename Number>
726 void build(
const dealii::DoFHandler<dim> &dof_handler,
727 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
730 dealii::MGTransferMatrixFree<dim, Number>::build(dof_handler);
731 level_matrix_free_ = &matrix_free;
734 template <
typename Number2>
736 const dealii::DoFHandler<dim> &dof_handler,
737 dealii::MGLevelObject<
738 dealii::LinearAlgebra::distributed::Vector<Number>> &dst,
739 const dealii::LinearAlgebra::distributed::Vector<Number2> &src)
const
741 if (dst[dst.min_level()].size() == 0)
742 for (
unsigned int l = dst.min_level(); l <= dst.max_level(); ++l)
743 (*level_matrix_free_)[l].initialize_dof_vector(dst[l]);
744 dealii::MGTransferMatrixFree<dim, Number>::copy_to_mg(
745 dof_handler, dst, src);
749 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
756#undef locally_owned_size
void vmult(vector_type &dst, const vector_type &src) const
void vmult(block_vector_type &dst, const block_vector_type &src) const
dealii::LinearAlgebra::distributed::Vector< Number > vector_type
vector_type & get_vector()
dealii::LinearAlgebra::distributed::BlockVector< Number > block_vector_type
block_vector_type & get_block_vector()
void reinit(const Vector &lumped_mass_matrix, const vector_type &density, const dealii::AffineConstraints< Number > &affine_constraints)
static constexpr unsigned int order_quad
dealii::LinearAlgebra::distributed::Vector< Number > vector_type
void compute_diagonal(std::shared_ptr< dealii::DiagonalMatrix< vector_type > > &matrix) const
void Tvmult(vector_type &dst, const vector_type &src) const
void vmult(vector_type &dst, const vector_type &src) const
static constexpr unsigned int order_fe
Number el(const unsigned int, const unsigned int) const
dealii::types::global_dof_index m() const
void initialize(const OfflineData< dim, Number2 > &offline_data, const dealii::MatrixFree< dim, Number > &matrix_free, const dealii::LinearAlgebra::distributed::Vector< Number > &density, const Number time_factor, const unsigned int level=dealii::numbers::invalid_unsigned_int)
void build(const dealii::DoFHandler< dim > &dof_handler, const dealii::MGLevelObject< dealii::MatrixFree< dim, Number > > &matrix_free)
void copy_to_mg(const dealii::DoFHandler< dim > &dof_handler, dealii::MGLevelObject< dealii::LinearAlgebra::distributed::Vector< Number > > &dst, const dealii::LinearAlgebra::distributed::Vector< Number2 > &src) const
void prolongate(const unsigned int to_level, vector_type &dst, const vector_type &src) const override
void copy_to_mg(const dealii::DoFHandler< dim > &dof_handler, dealii::MGLevelObject< vector_type > &dst, const dealii::LinearAlgebra::distributed::BlockVector< Number2 > &src) const
void restrict_and_add(const unsigned int to_level, vector_type &dst, const vector_type &src) const override
dealii::LinearAlgebra::distributed::Vector< Number > scalar_type
dealii::LinearAlgebra::distributed::BlockVector< Number > vector_type
void interpolate_to_mg(const dealii::DoFHandler< dim > &dof_handler, dealii::MGLevelObject< scalar_type > &dst, const dealii::LinearAlgebra::distributed::Vector< Number2 > &src) const
void build(const dealii::DoFHandler< dim > &dof_handler, const dealii::MGConstrainedDoFs &mg_constrained_dofs, const dealii::MGLevelObject< dealii::MatrixFree< dim, Number > > &matrix_free)
void copy_from_mg(const dealii::DoFHandler< dim > &dof_handler, dealii::LinearAlgebra::distributed::BlockVector< Number2 > &dst, const dealii::MGLevelObject< vector_type > &src) const
MGTransferVelocity()=default
void vmult(block_vector_type &dst, const block_vector_type &src) const
static constexpr unsigned int order_quad
dealii::LinearAlgebra::distributed::BlockVector< Number > block_vector_type
void initialize(const ParabolicSystem ¶bolic_system, const OfflineData< dim, Number2 > &offline_data, const dealii::MatrixFree< dim, Number > &matrix_free, const dealii::LinearAlgebra::distributed::Vector< Number > &density, const Number theta_x_tau, const unsigned int level=dealii::numbers::invalid_unsigned_int)
dealii::LinearAlgebra::distributed::Vector< Number > vector_type
static constexpr unsigned int order_fe
void Tvmult(block_vector_type &dst, const block_vector_type &src) const
void compute_diagonal(std::shared_ptr< DiagonalMatrix< dim, Number > > &matrix) const
const auto & boundary_map() const
const auto & level_lumped_mass_matrix() const
const auto & level_boundary_map() const
const auto & lumped_mass_matrix() const
DEAL_II_ALWAYS_INLINE void write_entry(V &vector, const T &values, unsigned int i)