12#include "../euler/hyperbolic_system.h"
15#include <deal.II/base/vectorization.h>
16#include <deal.II/lac/diagonal_matrix.h>
17#include <deal.II/matrix_free/fe_evaluation.h>
18#include <deal.II/multigrid/mg_base.h>
19#include <deal.II/multigrid/mg_transfer_matrix_free.h>
28 namespace NavierStokes
40 template <
int dim,
typename Number>
47 using vector_type = dealii::LinearAlgebra::distributed::Vector<Number>;
53 dealii::LinearAlgebra::distributed::BlockVector<Number>;
66 const dealii::AffineConstraints<Number> &affine_constraints)
68 diagonal.reinit(density,
true);
70 DEAL_II_OPENMP_SIMD_PRAGMA
71 for (
unsigned int i = 0;
72 i < density.get_partitioner()->locally_owned_size();
74 diagonal.local_element(i) =
76 (density.local_element(i) * lumped_mass_matrix.local_element(i));
83 affine_constraints.set_zero(diagonal);
99 return diagonal_block;
107 AssertDimension(diagonal_block.size(), 0);
108 DEAL_II_OPENMP_SIMD_PRAGMA
109 for (
unsigned int i = 0;
110 i < diagonal.get_partitioner()->locally_owned_size();
112 dst.local_element(i) =
113 diagonal.local_element(i) * src.local_element(i);
121 AssertDimension(dim, dst.n_blocks());
122 AssertDimension(dim, src.n_blocks());
123 if (diagonal_block.size() == 0) {
124 DEAL_II_OPENMP_SIMD_PRAGMA
125 for (
unsigned int i = 0;
126 i < diagonal.get_partitioner()->locally_owned_size();
128 for (
unsigned int d = 0; d < dim; ++d)
129 dst.block(d).local_element(i) =
130 diagonal.local_element(i) * src.block(d).local_element(i);
132 for (
unsigned int d = 0; d < dim; ++d) {
133 DEAL_II_OPENMP_SIMD_PRAGMA
134 for (
unsigned int i = 0;
135 i < src.block(d).get_partitioner()->locally_owned_size();
137 dst.block(d).local_element(i) =
138 diagonal_block.block(d).local_element(i) *
139 src.block(d).local_element(i);
155 template <
int dim,
typename Number,
typename Number2>
163 using vector_type = dealii::LinearAlgebra::distributed::Vector<Number>;
165 dealii::LinearAlgebra::distributed::BlockVector<Number>;
172 const dealii::MatrixFree<dim, Number> &matrix_free,
173 const dealii::LinearAlgebra::distributed::Vector<Number> &density,
174 const Number theta_x_tau,
175 const unsigned int level = dealii::numbers::invalid_unsigned_int)
177 parabolic_system_ = ¶bolic_system;
178 offline_data_ = &offline_data;
179 matrix_free_ = &matrix_free;
181 theta_x_tau_ = theta_x_tau;
194 using VA = dealii::VectorizedArray<Number>;
195 constexpr auto simd_length = VA::size();
198 if constexpr (std::is_same<Number, Number2>::value) {
199 if constexpr (std::is_same<Number, float>::value) {
200 if (level_ == dealii::numbers::invalid_unsigned_int)
206 Assert(level_ == dealii::numbers::invalid_unsigned_int,
207 dealii::ExcInternalError());
214 const unsigned int n_owned =
215 lumped_mass_matrix->get_partitioner()->locally_owned_size();
216 const unsigned int size_regular = n_owned / simd_length * simd_length;
221 for (
unsigned int i = 0; i < size_regular; i += simd_length) {
222 const auto m_i = get_entry<VA>(*lumped_mass_matrix, i);
223 const auto rho_i = get_entry<VA>(*density_, i);
224 for (
unsigned int d = 0; d < dim; ++d) {
225 const auto temp = get_entry<VA>(src.block(d), i);
226 write_entry<VA>(dst.block(d), m_i * rho_i * temp, i);
232 for (
unsigned int i = size_regular; i < n_owned; ++i) {
233 const auto m_i = lumped_mass_matrix->local_element(i);
234 const auto rho_i = density_->local_element(i);
236 for (
unsigned int d = 0; d < dim; ++d) {
237 const auto temp = src.block(d).local_element(i);
238 dst.block(d).local_element(i) = m_i * rho_i * temp;
244 const auto integrator = [
this](
const auto &data,
248 dealii::FEEvaluation<dim, order_fe, order_quad, dim, Number> velocity(
251 for (
unsigned int cell = range.first; cell < range.second; ++cell) {
252 velocity.reinit(cell);
253 velocity.read_dof_values(src);
254 apply_local_operator(velocity);
255 velocity.distribute_local_to_global(dst);
259 matrix_free_->template cell_loop<block_vector_type, block_vector_type>(
260 integrator, dst, src,
false);
264 const auto &boundary_map =
265 level_ == dealii::numbers::invalid_unsigned_int
269 for (
auto entry : boundary_map) {
271 const auto i = std::get<0>(entry);
275 const dealii::Tensor<1, dim, Number> normal = std::get<1>(entry);
276 const auto id = std::get<4>(entry);
279 dealii::Tensor<1, dim, Number> V_i;
280 for (
unsigned int d = 0; d < dim; ++d)
281 V_i[d] = dst.block(d).local_element(i);
284 V_i -= 1. * (V_i * normal) * normal;
285 for (
unsigned int d = 0; d < dim; ++d) {
286 const auto src_d = src.block(d).local_element(i);
287 V_i += 1. * (src_d * normal[d]) * normal;
290 for (
unsigned int d = 0; d < dim; ++d)
291 dst.block(d).local_element(i) = V_i[d];
296 for (
unsigned int d = 0; d < dim; ++d)
297 dst.block(d).local_element(i) = src.block(d).local_element(i);
305 Assert(level_ != dealii::numbers::invalid_unsigned_int,
306 dealii::ExcNotImplemented());
307 matrix = std::make_shared<DiagonalMatrix<dim, Number>>();
310 for (
unsigned int d = 0; d < dim; ++d)
311 matrix_free_->initialize_dof_vector(vector.block(d));
312 vector.collect_sizes();
314 const auto &lumped_mass_matrix =
317 unsigned int dummy = 0;
318 matrix_free_->template cell_loop<block_vector_type, unsigned int>(
320 const auto &data,
auto &dst,
const auto &,
const auto range) {
321 dealii::FEEvaluation<dim, order_fe, order_quad, dim, Number>
323 dealii::FEEvaluation<dim, order_fe, order_quad, dim, Number>
326 for (
unsigned int cell = range.first; cell < range.second;
328 velocity.reinit(cell);
330 for (
unsigned int i = 0; i < velocity.dofs_per_cell; ++i) {
331 for (
unsigned int j = 0; j < velocity.dofs_per_cell; ++j)
332 velocity.begin_dof_values()[j] =
333 dealii::VectorizedArray<Number>();
334 velocity.begin_dof_values()[i] =
335 dealii::make_vectorized_array<Number>(1.);
336 apply_local_operator(velocity);
337 writer.begin_dof_values()[i] = velocity.begin_dof_values()[i];
339 writer.distribute_local_to_global(dst);
346 const unsigned int n_owned =
347 lumped_mass_matrix.get_partitioner()->locally_owned_size();
352 for (
unsigned int i = 0; i < n_owned; ++i) {
353 const auto m_i = lumped_mass_matrix.local_element(i);
354 const auto rho_i = density_->local_element(i);
355 for (
unsigned int d = 0; d < dim; ++d)
356 vector.block(d).local_element(i) =
357 1. / (m_i * rho_i + vector.block(d).local_element(i));
364 for (
auto entry : boundary_map) {
366 const auto i = std::get<0>(entry);
370 const dealii::Tensor<1, dim, Number> normal = std::get<1>(entry);
371 const auto id = std::get<4>(entry);
374 dealii::Tensor<1, dim, Number> V_i;
375 for (
unsigned int d = 0; d < dim; ++d)
376 V_i[d] = vector.block(d).local_element(i);
379 V_i -= 1. * (V_i * normal) * normal;
380 for (
unsigned int d = 0; d < dim; ++d) {
381 V_i += 1. * (1. * normal[d]) * normal;
384 for (
unsigned int d = 0; d < dim; ++d)
385 vector.block(d).local_element(i) = V_i[d];
390 for (
unsigned int d = 0; d < dim; ++d)
391 vector.block(d).local_element(i) = 1.;
399 const dealii::MatrixFree<dim, Number> *matrix_free_;
404 template <
typename Evaluator>
405 void apply_local_operator(Evaluator &velocity)
const
407 const Number mu = parabolic_system_->mu();
408 const Number lambda = parabolic_system_->lambda();
410 velocity.evaluate(dealii::EvaluationFlags::gradients);
412 for (
unsigned int q = 0; q < velocity.n_q_points; ++q) {
413 if constexpr (dim == 1) {
415 const auto gradient = velocity.get_gradient(q);
416 auto S = (4. / 3. * mu + lambda) * gradient;
417 velocity.submit_gradient(theta_x_tau_ * S, q);
421 const auto symmetric_gradient = velocity.get_symmetric_gradient(q);
422 const auto divergence = trace(symmetric_gradient);
424 auto S = 2. * mu * symmetric_gradient;
425 for (
unsigned int d = 0; d < dim; ++d)
426 S[d][d] += (lambda - 2. / 3. * mu) * divergence;
427 velocity.submit_symmetric_gradient(theta_x_tau_ * S, q);
431 velocity.integrate(dealii::EvaluationFlags::gradients);
439 template <
int dim,
typename Number>
441 :
public dealii::MGTransferBase<
442 dealii::LinearAlgebra::distributed::BlockVector<Number>>
445 using scalar_type = dealii::LinearAlgebra::distributed::Vector<Number>;
447 dealii::LinearAlgebra::distributed::BlockVector<Number>;
451 void build(
const dealii::DoFHandler<dim> &dof_handler,
452 const dealii::MGConstrainedDoFs &mg_constrained_dofs,
453 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
456 transfer_.initialize_constraints(mg_constrained_dofs);
457 transfer_.build(dof_handler);
458 level_matrix_free_ = &matrix_free;
459 scalar_vector.resize(matrix_free.min_level(), matrix_free.max_level());
460 for (
unsigned int level = matrix_free.min_level();
461 level < matrix_free.max_level();
463 matrix_free[level].initialize_dof_vector(scalar_vector[level]);
470 for (
unsigned int block = 0; block < src.n_blocks(); ++block)
471 transfer_.prolongate(to_level, dst.block(block), src.block(block));
478 for (
unsigned int block = 0; block < src.n_blocks(); ++block)
479 transfer_.restrict_and_add(
480 to_level, dst.block(block), src.block(block));
483 template <
typename Number2>
485 const dealii::DoFHandler<dim> &dof_handler,
486 dealii::MGLevelObject<scalar_type> &dst,
487 const dealii::LinearAlgebra::distributed::Vector<Number2> &src)
const
489 if (dst[dst.min_level()].size() == 0)
490 for (
unsigned int l = dst.min_level(); l <= dst.max_level(); ++l)
491 (*level_matrix_free_)[l].initialize_dof_vector(dst[l]);
492 transfer_.interpolate_to_mg(dof_handler, dst, src);
495 template <
typename Number2>
498 dealii::MGLevelObject<vector_type> &dst,
499 const dealii::LinearAlgebra::distributed::BlockVector<Number2>
502 if (dst[dst.min_level()].size() == 0)
503 for (
unsigned int l = dst.min_level(); l <= dst.max_level(); ++l) {
504 dst[l].reinit(src.n_blocks());
505 for (
unsigned int block = 0; block < src.n_blocks(); ++block)
506 (*level_matrix_free_)[l].initialize_dof_vector(
507 dst[l].block(block));
508 dst[l].collect_sizes();
511 for (
unsigned int block = 0; block < src.n_blocks(); ++block) {
512 transfer_.copy_to_mg(dof_handler, scalar_vector, src.block(block));
513 for (
unsigned int level = dst.min_level(); level <= dst.max_level();
515 dst[level].block(block).copy_locally_owned_data_from(
516 scalar_vector[level]);
520 template <
typename Number2>
522 const dealii::DoFHandler<dim> &dof_handler,
523 dealii::LinearAlgebra::distributed::BlockVector<Number2> &dst,
524 const dealii::MGLevelObject<vector_type> &src)
const
526 for (
unsigned int block = 0; block < dst.n_blocks(); ++block) {
527 for (
unsigned int level = src.min_level(); level <= src.max_level();
529 scalar_vector[level].copy_locally_owned_data_from(
530 src[level].block(block));
531 transfer_.copy_from_mg(dof_handler, dst.block(block), scalar_vector);
536 dealii::MGTransferMatrixFree<dim, Number> transfer_;
537 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
539 mutable dealii::MGLevelObject<scalar_type> scalar_vector;
546 template <
int dim,
typename Number,
typename Number2>
554 using vector_type = dealii::LinearAlgebra::distributed::Vector<Number>;
560 const dealii::MatrixFree<dim, Number> &matrix_free,
561 const dealii::LinearAlgebra::distributed::Vector<Number> &density,
562 const Number time_factor,
563 const unsigned int level = dealii::numbers::invalid_unsigned_int)
565 offline_data_ = &offline_data;
566 matrix_free_ = &matrix_free;
568 factor_ = time_factor;
577 dealii::types::global_dof_index
m()
const
579 return density_->size();
582 Number
el(
const unsigned int,
const unsigned int)
const
584 Assert(
false, dealii::ExcNotImplemented());
592 using VA = dealii::VectorizedArray<Number>;
593 constexpr auto simd_length = VA::size();
596 if constexpr (std::is_same<Number, Number2>::value) {
597 if constexpr (std::is_same<Number, float>::value) {
598 if (level_ == dealii::numbers::invalid_unsigned_int)
604 Assert(level_ == dealii::numbers::invalid_unsigned_int,
605 dealii::ExcInternalError());
612 const unsigned int n_owned =
613 lumped_mass_matrix->get_partitioner()->locally_owned_size();
614 const unsigned int size_regular = n_owned / simd_length * simd_length;
619 for (
unsigned int i = 0; i < size_regular; i += simd_length) {
620 const auto m_i = get_entry<VA>(*lumped_mass_matrix, i);
621 const auto rho_i = get_entry<VA>(*density_, i);
622 const auto e_i = get_entry<VA>(src, i);
623 write_entry<VA>(dst, m_i * rho_i * e_i, i);
628 for (
unsigned int i = size_regular; i < n_owned; ++i) {
629 const auto m_i = lumped_mass_matrix->local_element(i);
630 const auto rho_i = density_->local_element(i);
631 const auto e_i = src.local_element(i);
632 dst.local_element(i) = m_i * rho_i * e_i;
637 const auto integrator = [
this](
const auto &data,
641 dealii::FEEvaluation<dim, order_fe, order_quad, 1, Number> energy(
644 for (
unsigned int cell = range.first; cell < range.second; ++cell) {
646 energy.read_dof_values(src);
647 apply_local_operator(energy);
648 energy.distribute_local_to_global(dst);
652 matrix_free_->template cell_loop<vector_type, vector_type>(
653 integrator, dst, src,
false);
657 const auto &boundary_map =
658 (level_ == dealii::numbers::invalid_unsigned_int)
662 for (
auto entry : boundary_map) {
663 const auto i = std::get<0>(entry);
667 const auto id = std::get<4>(entry);
669 dst.local_element(i) = src.local_element(i);
674 std::shared_ptr<dealii::DiagonalMatrix<vector_type>> &matrix)
const
676 Assert(level_ != dealii::numbers::invalid_unsigned_int,
677 dealii::ExcNotImplemented());
678 matrix = std::make_shared<dealii::DiagonalMatrix<vector_type>>();
680 matrix_free_->initialize_dof_vector(vector);
685 unsigned int dummy = 0;
686 matrix_free_->template cell_loop<vector_type, unsigned int>(
688 const auto &data,
auto &dst,
const auto &,
const auto range) {
689 dealii::FEEvaluation<dim, order_fe, order_quad, 1, Number> energy(
691 dealii::FEEvaluation<dim, order_fe, order_quad, 1, Number> writer(
694 for (
unsigned int cell = range.first; cell < range.second;
698 for (
unsigned int i = 0; i < energy.dofs_per_cell; ++i) {
699 for (
unsigned int j = 0; j < energy.dofs_per_cell; ++j)
700 energy.begin_dof_values()[j] =
701 dealii::VectorizedArray<Number>();
702 energy.begin_dof_values()[i] =
703 dealii::make_vectorized_array<Number>(1.);
704 apply_local_operator(energy);
705 writer.begin_dof_values()[i] = energy.begin_dof_values()[i];
707 writer.distribute_local_to_global(dst);
714 const unsigned int n_owned =
715 lumped_mass_matrix.get_partitioner()->locally_owned_size();
720 for (
unsigned int i = 0; i < n_owned; ++i) {
721 const auto m_i = lumped_mass_matrix.local_element(i);
722 const auto rho_i = density_->local_element(i);
723 vector.local_element(i) =
724 1. / (m_i * rho_i + vector.local_element(i));
731 for (
auto entry : boundary_map) {
732 const auto i = std::get<0>(entry);
736 const auto id = std::get<4>(entry);
738 vector.local_element(i) = 1.;
744 const dealii::MatrixFree<dim, Number> *matrix_free_;
745 const dealii::LinearAlgebra::distributed::Vector<Number> *density_;
749 template <
typename Evaluator>
750 void apply_local_operator(Evaluator &energy)
const
752 energy.evaluate(dealii::EvaluationFlags::gradients);
753 for (
unsigned int q = 0; q < energy.n_q_points; ++q) {
754 energy.submit_gradient(factor_ * energy.get_gradient(q), q);
756 energy.integrate(dealii::EvaluationFlags::gradients);
764 template <
int dim,
typename Number>
768 void build(
const dealii::DoFHandler<dim> &dof_handler,
769 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
772 dealii::MGTransferMatrixFree<dim, Number>::build(dof_handler);
773 level_matrix_free_ = &matrix_free;
776 template <
typename Number2>
778 const dealii::DoFHandler<dim> &dof_handler,
779 dealii::MGLevelObject<
780 dealii::LinearAlgebra::distributed::Vector<Number>> &dst,
781 const dealii::LinearAlgebra::distributed::Vector<Number2> &src)
const
783 if (dst[dst.min_level()].size() == 0)
784 for (
unsigned int l = dst.min_level(); l <= dst.max_level(); ++l)
785 (*level_matrix_free_)[l].initialize_dof_vector(dst[l]);
786 dealii::MGTransferMatrixFree<dim, Number>::copy_to_mg(
787 dof_handler, dst, src);
791 const dealii::MGLevelObject<dealii::MatrixFree<dim, Number>>
798#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
void reinit(const vector_type &lumped_mass_matrix, const vector_type &density, const dealii::AffineConstraints< Number > &affine_constraints)
vector_type & get_vector()
dealii::LinearAlgebra::distributed::BlockVector< Number > block_vector_type
block_vector_type & get_block_vector()
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
auto & boundary_map() const
auto & level_lumped_mass_matrix() const
auto & lumped_mass_matrix() const
auto & level_boundary_map() const
#define RYUJIN_PARALLEL_REGION_BEGIN
#define RYUJIN_PARALLEL_REGION_END
Euler::HyperbolicSystem HyperbolicSystem