15#include <deal.II/lac/linear_operator.h>
16#include <deal.II/lac/precondition.h>
17#include <deal.II/lac/solver_cg.h>
18#include <deal.II/matrix_free/fe_evaluation.h>
19#include <deal.II/multigrid/mg_coarse.h>
20#include <deal.II/multigrid/mg_matrix.h>
21#include <deal.II/multigrid/mg_transfer.templates.h>
22#include <deal.II/multigrid/mg_transfer_matrix_free.h>
23#include <deal.II/multigrid/multigrid.h>
29 namespace NavierStokes
31 using namespace dealii;
33 template <
typename Description,
int dim,
typename Number>
36 std::map<std::string, dealii::Timer> &computing_timer,
41 const std::string &subsection )
42 : ParameterAcceptor(subsection)
43 , mpi_ensemble_(mpi_ensemble)
44 , computing_timer_(computing_timer)
45 , hyperbolic_system_(&hyperbolic_system)
46 , parabolic_system_(¶bolic_system)
47 , offline_data_(&offline_data)
48 , initial_values_(&initial_values)
52 , n_iterations_velocity_(0.)
53 , n_iterations_internal_energy_(0.)
55 use_gmg_velocity_ =
false;
56 add_parameter(
"multigrid velocity",
58 "Use geometric multigrid for velocity component");
60 gmg_max_iter_vel_ = 12;
61 add_parameter(
"multigrid velocity - max iter",
63 "Maximal number of CG iterations with GMG smoother");
65 gmg_smoother_range_vel_ = 8.;
66 add_parameter(
"multigrid velocity - chebyshev range",
67 gmg_smoother_range_vel_,
68 "Chebyshev smoother: eigenvalue range parameter");
70 gmg_smoother_max_eig_vel_ = 2.0;
71 add_parameter(
"multigrid velocity - chebyshev max eig",
72 gmg_smoother_max_eig_vel_,
73 "Chebyshev smoother: maximal eigenvalue");
75 use_gmg_internal_energy_ =
false;
76 add_parameter(
"multigrid energy",
77 use_gmg_internal_energy_,
78 "Use geometric multigrid for internal energy component");
80 gmg_max_iter_en_ = 15;
81 add_parameter(
"multigrid energy - max iter",
83 "Maximal number of CG iterations with GMG smoother");
85 gmg_smoother_range_en_ = 15.;
86 add_parameter(
"multigrid energy - chebyshev range",
87 gmg_smoother_range_en_,
88 "Chebyshev smoother: eigenvalue range parameter");
90 gmg_smoother_max_eig_en_ = 2.0;
91 add_parameter(
"multigrid energy - chebyshev max eig",
92 gmg_smoother_max_eig_en_,
93 "Chebyshev smoother: maximal eigenvalue");
95 gmg_smoother_degree_ = 3;
96 add_parameter(
"multigrid - chebyshev degree",
98 "Chebyshev smoother: degree");
100 gmg_smoother_n_cg_iter_ = 10;
102 "multigrid - chebyshev cg iter",
103 gmg_smoother_n_cg_iter_,
104 "Chebyshev smoother: number of CG iterations to approximate "
109 "multigrid - min level",
111 "Minimal mesh level to be visited in the geometric multigrid "
112 "cycle where the coarse grid solver (Chebyshev) is called");
114 tolerance_ = Number(1.0e-12);
115 add_parameter(
"tolerance", tolerance_,
"Tolerance for linear solvers");
117 tolerance_linfty_norm_ =
false;
118 add_parameter(
"tolerance linfty norm",
119 tolerance_linfty_norm_,
120 "Use the l_infty norm instead of the l_2 norm for the "
121 "stopping criterion");
125 template <
typename Description,
int dim,
typename Number>
129 std::cout <<
"ParabolicSolver<dim, Number>::prepare()" << std::endl;
132 const auto &discretization = offline_data_->discretization();
134 dealii::ExcMessage(
"The Navier-Stokes module currently only "
135 "supports cG Q1 finite elements."));
137 AssertThrow(!offline_data_->dof_handler().has_hp_capabilities(),
139 "The Navier-Stokes module currently does not support "
140 "DofHandlers set up with hp capabilities."));
144 typename MatrixFree<dim, Number>::AdditionalData additional_data;
145 additional_data.tasks_parallel_scheme =
146 MatrixFree<dim, Number>::AdditionalData::none;
148 matrix_free_.reinit(discretization.mapping(),
149 offline_data_->dof_handler(),
150 offline_data_->affine_constraints(),
151 discretization.quadrature_1d(),
154 const auto &scalar_partitioner =
155 matrix_free_.get_dof_info(0).vector_partitioner;
157 velocity_.reinit(dim);
158 velocity_rhs_.reinit(dim);
159 for (
unsigned int i = 0; i < dim; ++i) {
160 velocity_.block(i).reinit(scalar_partitioner);
161 velocity_rhs_.block(i).reinit(scalar_partitioner);
164 internal_energy_.reinit(scalar_partitioner);
165 internal_energy_rhs_.reinit(scalar_partitioner);
167 density_.reinit(scalar_partitioner);
171 if (!use_gmg_velocity_ && !use_gmg_internal_energy_)
174 const unsigned int n_levels =
175 offline_data_->dof_handler().get_triangulation().n_global_levels();
176 const unsigned int min_level = std::min(gmg_min_level_, n_levels - 1);
177 MGLevelObject<IndexSet> relevant_sets(0, n_levels - 1);
178 for (
unsigned int level = 0; level < n_levels; ++level)
179 dealii::DoFTools::extract_locally_relevant_level_dofs(
180 offline_data_->dof_handler(), level, relevant_sets[level]);
181 mg_constrained_dofs_.initialize(offline_data_->dof_handler(),
183 std::set<types::boundary_id> boundary_ids;
186 mg_constrained_dofs_.make_zero_boundary_constraints(
187 offline_data_->dof_handler(), boundary_ids);
189 typename MatrixFree<dim, float>::AdditionalData additional_data_level;
190 additional_data_level.tasks_parallel_scheme =
191 MatrixFree<dim, float>::AdditionalData::none;
193 level_matrix_free_.resize(min_level, n_levels - 1);
194 level_density_.resize(min_level, n_levels - 1);
195 for (
unsigned int level = min_level; level < n_levels; ++level) {
196 additional_data_level.mg_level = level;
197 AffineConstraints<double> constraints(relevant_sets[level]);
201 level_matrix_free_[level].reinit(discretization.mapping(),
202 offline_data_->dof_handler(),
204 discretization.quadrature_1d(),
205 additional_data_level);
206 level_matrix_free_[level].initialize_dof_vector(level_density_[level]);
209 mg_transfer_velocity_.build(offline_data_->dof_handler(),
210 mg_constrained_dofs_,
212 mg_transfer_energy_.build(offline_data_->dof_handler(),
216 template <
typename Description,
int dim,
typename Number>
227 template <
typename Description,
int dim,
typename Number>
234 const bool reinitialize_gmg)
const
238 step(old_state_vector,
242 id_violation_strategy,
248 template <
typename Description,
int dim,
typename Number>
255 const bool reinitialize_gmg)
const
258 step(old_state_vector,
262 id_violation_strategy,
276 step(old_state_vector,
280 id_violation_strategy,
287 template <
typename Description,
int dim,
typename Number>
294 const bool reinitialize_gmg,
295 const bool crank_nicolson_extrapolation)
const
298 std::cout <<
"ParabolicSolver<dim, Number>::step()" << std::endl;
301 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
303 const auto &old_U = std::get<0>(old_state_vector);
304 auto &new_U = std::get<0>(new_state_vector);
308 using VA = VectorizedArray<Number>;
310 const auto &lumped_mass_matrix = offline_data_->lumped_mass_matrix();
311 const auto &affine_constraints = offline_data_->affine_constraints();
315 constexpr auto simd_length = VA::size();
316 const unsigned int n_owned = offline_data_->n_locally_owned();
317 const unsigned int n_regular = n_owned / simd_length * simd_length;
319 const auto &sparsity_simd = offline_data_->sparsity_pattern_simd();
324 std::cout <<
" perform time-step with tau = " << tau << std::endl;
325 if (crank_nicolson_extrapolation)
326 std::cout <<
" and extrapolate to t + 2 * tau" << std::endl;
342 std::atomic<bool> restart_needed =
false;
353 std::atomic<bool> correction_needed =
false;
363 Scope scope(computing_timer_,
"time step [P] 1 - update velocities");
367 auto loop = [&](
auto sentinel,
unsigned int left,
unsigned int right) {
368 using T =
decltype(sentinel);
369 unsigned int stride_size = get_stride_size<T>;
371 const auto view = hyperbolic_system_->template view<dim, T>();
374 for (
unsigned int i = left; i < right; i += stride_size) {
375 const auto U_i = old_U.template get_tensor<T>(i);
376 const auto rho_i = view.density(U_i);
377 const auto M_i = view.momentum(U_i);
378 const auto rho_e_i = view.internal_energy(U_i);
379 const auto m_i = get_entry<T>(lumped_mass_matrix, i);
381 write_entry<T>(density_, rho_i, i);
383 for (
unsigned int d = 0; d < dim; ++d) {
384 write_entry<T>(velocity_.block(d), M_i[d] / rho_i, i);
385 write_entry<T>(velocity_rhs_.block(d), m_i * (M_i[d]), i);
387 write_entry<T>(internal_energy_, rho_e_i / rho_i, i);
392 loop(Number(), n_regular, n_owned);
394 loop(VA(), 0, n_regular);
405 const auto &boundary_map = offline_data_->boundary_map();
407 for (
auto entry : boundary_map) {
409 const auto i = std::get<0>(entry);
413 const auto normal = std::get<1>(entry);
414 const auto id = std::get<4>(entry);
415 const auto position = std::get<5>(entry);
419 Tensor<1, dim, Number> V_i;
420 Tensor<1, dim, Number> RHS_i;
421 for (
unsigned int d = 0; d < dim; ++d) {
422 V_i[d] = velocity_.block(d).local_element(i);
423 RHS_i[d] = velocity_rhs_.block(d).local_element(i);
425 V_i -= 1. * (V_i * normal) * normal;
426 RHS_i -= 1. * (RHS_i * normal) * normal;
427 for (
unsigned int d = 0; d < dim; ++d) {
428 velocity_.block(d).local_element(i) = V_i[d];
429 velocity_rhs_.block(d).local_element(i) = RHS_i[d];
435 for (
unsigned int d = 0; d < dim; ++d) {
436 velocity_.block(d).local_element(i) = Number(0.);
437 velocity_rhs_.block(d).local_element(i) = Number(0.);
443 const auto U_i = initial_values_->initial_state(position, t + tau);
444 const auto view = hyperbolic_system_->template view<dim, Number>();
445 const auto rho_i = view.density(U_i);
446 const auto V_i = view.momentum(U_i) / rho_i;
447 const auto e_i = view.internal_energy(U_i) / rho_i;
449 for (
unsigned int d = 0; d < dim; ++d) {
450 velocity_.block(d).local_element(i) = V_i[d];
451 velocity_rhs_.block(d).local_element(i) = V_i[d];
454 internal_energy_.local_element(i) = e_i;
465 affine_constraints.set_zero(density_);
466 affine_constraints.set_zero(internal_energy_);
467 for (
unsigned int d = 0; d < dim; ++d) {
468 affine_constraints.set_zero(velocity_.block(d));
469 affine_constraints.set_zero(velocity_rhs_.block(d));
475 lumped_mass_matrix, density_, affine_constraints);
482 if (use_gmg_velocity_ && reinitialize_gmg) {
483 MGLevelObject<
typename PreconditionChebyshev<
484 VelocityMatrix<dim, float, Number>,
485 LinearAlgebra::distributed::BlockVector<float>,
486 DiagonalMatrix<dim, float>>::AdditionalData>
487 smoother_data(level_matrix_free_.min_level(),
488 level_matrix_free_.max_level());
490 level_velocity_matrices_.resize(level_matrix_free_.min_level(),
491 level_matrix_free_.max_level());
492 mg_transfer_velocity_.interpolate_to_mg(
493 offline_data_->dof_handler(), level_density_, density_);
495 for (
unsigned int level = level_matrix_free_.min_level();
496 level <= level_matrix_free_.max_level();
498 level_velocity_matrices_[level].initialize(
501 level_matrix_free_[level],
502 level_density_[level],
505 level_velocity_matrices_[level].compute_diagonal(
506 smoother_data[level].preconditioner);
507 if (level == level_matrix_free_.min_level()) {
508 smoother_data[level].degree = numbers::invalid_unsigned_int;
509 smoother_data[level].eig_cg_n_iterations = 500;
510 smoother_data[level].smoothing_range = 1e-3;
512 smoother_data[level].degree = gmg_smoother_degree_;
513 smoother_data[level].eig_cg_n_iterations =
514 gmg_smoother_n_cg_iter_;
515 smoother_data[level].smoothing_range = gmg_smoother_range_vel_;
516 if (gmg_smoother_n_cg_iter_ == 0)
517 smoother_data[level].max_eigenvalue = gmg_smoother_max_eig_vel_;
520 mg_smoother_velocity_.initialize(level_velocity_matrices_,
530 Scope scope(computing_timer_,
531 "time step [X] _ - synchronization barriers");
537 *std::min_element(internal_energy_.begin(), internal_energy_.end());
539 e_min_old = Utilities::MPI::min(e_min_old,
540 mpi_ensemble_.ensemble_communicator());
543 constexpr Number eps = std::numeric_limits<Number>::epsilon();
544 e_min_old *= (1. - 1000. * eps);
551 Scope scope(computing_timer_,
"time step [P] 1 - update velocities");
555 VelocityMatrix<dim, Number, Number> velocity_operator;
556 velocity_operator.initialize(
557 *parabolic_system_, *offline_data_, matrix_free_, density_, tau);
559 const auto tolerance_velocity =
560 (tolerance_linfty_norm_ ? velocity_rhs_.linfty_norm()
561 : velocity_rhs_.l2_norm()) *
570 if (!use_gmg_velocity_)
571 throw SolverControl::NoConvergence(0, 0.);
573 using bvt_float = LinearAlgebra::distributed::BlockVector<float>;
575 MGCoarseGridApplySmoother<bvt_float> mg_coarse;
576 mg_coarse.initialize(mg_smoother_velocity_);
578 mg::Matrix<bvt_float> mg_matrix(level_velocity_matrices_);
580 Multigrid<bvt_float> mg(mg_matrix,
582 mg_transfer_velocity_,
583 mg_smoother_velocity_,
584 mg_smoother_velocity_,
585 level_velocity_matrices_.min_level(),
586 level_velocity_matrices_.max_level());
588 const auto &dof_handler = offline_data_->dof_handler();
589 PreconditionMG<dim, bvt_float, MGTransferVelocity<dim, float>>
590 preconditioner(dof_handler, mg, mg_transfer_velocity_);
592 SolverControl solver_control(gmg_max_iter_vel_, tolerance_velocity);
593 SolverCG<BlockVector> solver(solver_control);
595 velocity_operator, velocity_, velocity_rhs_, preconditioner);
598 n_iterations_velocity_ =
599 0.9 * n_iterations_velocity_ + 0.1 * solver_control.last_step();
601 }
catch (SolverControl::NoConvergence &) {
603 SolverControl solver_control(1000, tolerance_velocity);
604 SolverCG<BlockVector> solver(solver_control);
606 velocity_operator, velocity_, velocity_rhs_, diagonal_matrix);
609 n_iterations_velocity_ *= 0.9;
610 n_iterations_velocity_ +=
611 0.1 * (use_gmg_velocity_ ? gmg_max_iter_vel_ : 0) +
612 0.1 * solver_control.last_step();
622 Scope scope(computing_timer_,
623 "time step [P] 2 - update internal energy");
628 matrix_free_.template cell_loop<ScalarVector, BlockVector>(
629 [
this](
const auto &data,
632 const auto cell_range) {
633 FEEvaluation<dim, order_fe, order_quad, dim, Number> velocity(
635 FEEvaluation<dim, order_fe, order_quad, 1, Number> energy(data);
637 const auto mu = parabolic_system_->mu();
638 const auto lambda = parabolic_system_->lambda();
640 for (
unsigned int cell = cell_range.first;
641 cell < cell_range.second;
643 velocity.reinit(cell);
645 velocity.gather_evaluate(src, EvaluationFlags::gradients);
647 for (
unsigned int q = 0; q < velocity.n_q_points; ++q) {
648 if constexpr (dim == 1) {
650 const auto gradient = velocity.get_gradient(q);
651 auto S = (4. / 3. * mu + lambda) * gradient;
652 energy.submit_value(gradient * S, q);
656 const auto symmetric_gradient =
657 velocity.get_symmetric_gradient(q);
658 const auto divergence = trace(symmetric_gradient);
659 auto S = 2. * mu * symmetric_gradient;
660 for (
unsigned int d = 0; d < dim; ++d)
661 S[d][d] += (lambda - 2. / 3. * mu) * divergence;
662 energy.submit_value(symmetric_gradient * S, q);
665 energy.integrate_scatter(EvaluationFlags::values, dst);
668 internal_energy_rhs_,
672 const auto &lumped_mass_matrix = offline_data_->lumped_mass_matrix();
676 auto loop = [&](
auto sentinel,
unsigned int left,
unsigned int right) {
677 using T =
decltype(sentinel);
678 unsigned int stride_size = get_stride_size<T>;
680 const auto view = hyperbolic_system_->template view<dim, T>();
683 for (
unsigned int i = left; i < right; i += stride_size) {
684 const auto rhs_i = get_entry<T>(internal_energy_rhs_, i);
685 const auto m_i = get_entry<T>(lumped_mass_matrix, i);
686 const auto rho_i = get_entry<T>(density_, i);
687 const auto e_i = get_entry<T>(internal_energy_, i);
689 const auto U_i = old_U.template get_tensor<T>(i);
690 const auto V_i = view.momentum(U_i) / rho_i;
692 dealii::Tensor<1, dim, T> V_i_new;
693 for (
unsigned int d = 0; d < dim; ++d) {
694 V_i_new[d] = get_entry<T>(velocity_.block(d), i);
701 const auto correction =
702 crank_nicolson_extrapolation
704 : Number(0.5) * (V_i - V_i_new).norm_square();
707 const auto result = m_i * rho_i * (e_i + correction) + tau * rhs_i;
708 write_entry<T>(internal_energy_rhs_, result, i);
713 loop(Number(), n_regular, n_owned);
715 loop(VA(), 0, n_regular);
726 const auto &boundary_map = offline_data_->boundary_map();
728 for (
auto entry : boundary_map) {
730 const auto i = std::get<0>(entry);
734 const auto id = std::get<4>(entry);
735 const auto position = std::get<5>(entry);
739 const auto U_i = initial_values_->initial_state(position, t + tau);
740 const auto view = hyperbolic_system_->template view<dim, Number>();
741 const auto rho_i = view.density(U_i);
742 const auto e_i = view.internal_energy(U_i) / rho_i;
743 internal_energy_rhs_.local_element(i) = e_i;
753 affine_constraints.set_zero(internal_energy_);
754 affine_constraints.set_zero(internal_energy_rhs_);
761 if (use_gmg_internal_energy_ && reinitialize_gmg) {
762 MGLevelObject<
typename PreconditionChebyshev<
763 EnergyMatrix<dim, float, Number>,
764 LinearAlgebra::distributed::Vector<float>>::AdditionalData>
765 smoother_data(level_matrix_free_.min_level(),
766 level_matrix_free_.max_level());
768 level_energy_matrices_.resize(level_matrix_free_.min_level(),
769 level_matrix_free_.max_level());
771 for (
unsigned int level = level_matrix_free_.min_level();
772 level <= level_matrix_free_.max_level();
774 level_energy_matrices_[level].initialize(
776 level_matrix_free_[level],
777 level_density_[level],
778 tau * parabolic_system_->cv_inverse_kappa(),
780 level_energy_matrices_[level].compute_diagonal(
781 smoother_data[level].preconditioner);
782 if (level == level_matrix_free_.min_level()) {
783 smoother_data[level].degree = numbers::invalid_unsigned_int;
784 smoother_data[level].eig_cg_n_iterations = 500;
785 smoother_data[level].smoothing_range = 1e-3;
787 smoother_data[level].degree = gmg_smoother_degree_;
788 smoother_data[level].eig_cg_n_iterations =
789 gmg_smoother_n_cg_iter_;
790 smoother_data[level].smoothing_range = gmg_smoother_range_en_;
791 if (gmg_smoother_n_cg_iter_ == 0)
792 smoother_data[level].max_eigenvalue = gmg_smoother_max_eig_en_;
795 mg_smoother_energy_.initialize(level_energy_matrices_, smoother_data);
805 Scope scope(computing_timer_,
806 "time step [P] 2 - update internal energy");
810 EnergyMatrix<dim, Number, Number> energy_operator;
811 const auto &kappa = parabolic_system_->cv_inverse_kappa();
812 energy_operator.initialize(
813 *offline_data_, matrix_free_, density_, tau * kappa);
815 const auto tolerance_internal_energy =
816 (tolerance_linfty_norm_ ? internal_energy_rhs_.linfty_norm()
817 : internal_energy_rhs_.l2_norm()) *
821 if (!use_gmg_internal_energy_)
822 throw SolverControl::NoConvergence(0, 0.);
824 using vt_float = LinearAlgebra::distributed::Vector<float>;
825 MGCoarseGridApplySmoother<vt_float> mg_coarse;
826 mg_coarse.initialize(mg_smoother_energy_);
827 mg::Matrix<vt_float> mg_matrix(level_energy_matrices_);
829 Multigrid<vt_float> mg(mg_matrix,
834 level_energy_matrices_.min_level(),
835 level_energy_matrices_.max_level());
837 const auto &dof_handler = offline_data_->dof_handler();
838 PreconditionMG<dim, vt_float, MGTransferEnergy<dim, float>>
839 preconditioner(dof_handler, mg, mg_transfer_energy_);
841 SolverControl solver_control(gmg_max_iter_en_,
842 tolerance_internal_energy);
843 SolverCG<ScalarVector> solver(solver_control);
844 solver.solve(energy_operator,
846 internal_energy_rhs_,
850 n_iterations_internal_energy_ = 0.9 * n_iterations_internal_energy_ +
851 0.1 * solver_control.last_step();
853 }
catch (SolverControl::NoConvergence &) {
855 SolverControl solver_control(1000, tolerance_internal_energy);
856 SolverCG<ScalarVector> solver(solver_control);
857 solver.solve(energy_operator,
859 internal_energy_rhs_,
863 n_iterations_internal_energy_ *= 0.9;
864 n_iterations_internal_energy_ +=
865 0.1 * (use_gmg_internal_energy_ ? gmg_max_iter_en_ : 0) +
866 0.1 * solver_control.last_step();
879 Scope scope(computing_timer_,
"time step [P] 3 - write back vectors");
884 auto loop = [&](
auto sentinel,
unsigned int left,
unsigned int right) {
885 using T =
decltype(sentinel);
886 unsigned int stride_size = get_stride_size<T>;
888 const auto view = hyperbolic_system_->template view<dim, T>();
891 for (
unsigned int i = left; i < right; i += stride_size) {
894 const unsigned int row_length = sparsity_simd.row_length(i);
898 auto U_i = old_U.template get_tensor<T>(i);
899 const auto rho_i = view.density(U_i);
901 Tensor<1, dim, T> m_i_new;
902 for (
unsigned int d = 0; d < dim; ++d) {
903 m_i_new[d] = rho_i * get_entry<T>(velocity_.block(d), i);
906 auto rho_e_i_new = rho_i * get_entry<T>(internal_energy_, i);
913 if (!(T(0.) == std::max(T(0.), rho_i * e_min_old - rho_e_i_new))) {
915 std::cout << std::fixed << std::setprecision(16);
916 const auto e_i_new = rho_e_i_new / rho_i;
917 std::cout <<
"Bounds violation: internal energy (critical)!\n"
918 <<
"\t\te_min_old: " << e_min_old <<
"\n"
919 <<
"\t\te_min_old (delta): "
921 <<
"\t\te_min_new: " << e_i_new <<
"\n"
924 restart_needed =
true;
927 if (crank_nicolson_extrapolation) {
928 m_i_new = Number(2.0) * m_i_new - view.momentum(U_i);
930 Number(2.0) * rho_e_i_new - view.internal_energy(U_i);
938 std::max(T(0.), eps * rho_i * e_min_old - rho_e_i_new))) {
940 std::cout << std::fixed << std::setprecision(16);
941 const auto e_i_new = rho_e_i_new / rho_i;
943 std::cout <<
"Bounds violation: high-order internal energy!"
944 <<
"\t\te_min_new: " << e_i_new <<
"\n"
945 <<
"\t\t-- correction required --" << std::endl;
947 correction_needed =
true;
951 const auto E_i_new = rho_e_i_new + 0.5 * m_i_new * m_i_new / rho_i;
953 for (
unsigned int d = 0; d < dim; ++d)
954 U_i[1 + d] = m_i_new[d];
955 U_i[1 + dim] = E_i_new;
957 new_U.template write_tensor<T>(U_i, i);
962 loop(Number(), n_regular, n_owned);
964 loop(VA(), 0, n_regular);
969 new_U.update_ghost_values();
975 Scope scope(computing_timer_,
976 "time step [X] _ - synchronization barriers");
987 restart_needed.store(Utilities::MPI::logical_or(
988 restart_needed.load(),
989 mpi_ensemble_.synchronization_communicator()));
991 correction_needed.store(Utilities::MPI::logical_or(
992 correction_needed.load(),
993 mpi_ensemble_.synchronization_communicator()));
996 if (correction_needed) {
1001 throw Restart{Number(0.5) * tau};
1008 if (restart_needed) {
1009 switch (id_violation_strategy) {
1016 throw Restart{Number(0.5) * tau};
1022 template <
typename Description,
int dim,
typename Number>
1024 std::ostream &output)
const
1026 output <<
" [ " << std::setprecision(2) << std::fixed
1027 << n_iterations_velocity_
1028 << (use_gmg_velocity_ ?
" GMG vel -- " :
" CG vel -- ")
1029 << n_iterations_internal_energy_
1030 << (use_gmg_internal_energy_ ?
" GMG int ]" :
" CG int ]")
void reinit(const vector_type &lumped_mass_matrix, const vector_type &density, const dealii::AffineConstraints< Number > &affine_constraints)
void backward_euler_step(const StateVector &old_state_vector, const Number old_t, StateVector &new_state_vector, Number tau, const IDViolationStrategy id_violation_strategy, const bool reinitialize_gmg) const
typename Description::ParabolicSystem ParabolicSystem
typename View::StateVector StateVector
void print_solver_statistics(std::ostream &output) const
void prepare_state_vector(StateVector &state_vector, Number t) const
typename Description::HyperbolicSystem HyperbolicSystem
ParabolicSolver(const MPIEnsemble &mpi_ensemble, std::map< std::string, dealii::Timer > &computing_timer, const HyperbolicSystem &hyperbolic_system, const ParabolicSystem ¶bolic_system, const OfflineData< dim, Number > &offline_data, const InitialValues< Description, dim, Number > &initial_values, const std::string &subsection="ParabolicSolver")
void crank_nicolson_step(const StateVector &old_state_vector, const Number old_t, StateVector &new_state_vector, Number tau, const IDViolationStrategy id_violation_strategy, const bool reinitialize_gmg) const
void step(Triangulation< dim, dim > &, const double, const double, const double, const double)
#define RYUJIN_PARALLEL_REGION_BEGIN
#define RYUJIN_PARALLEL_REGION_END
DEAL_II_ALWAYS_INLINE Number negative_part(const Number number)
#define LIKWID_MARKER_START(opt)
#define CALLGRIND_START_INSTRUMENTATION
#define LIKWID_MARKER_STOP(opt)
#define CALLGRIND_STOP_INSTRUMENTATION
std::tuple< MultiComponentVector< Number, problem_dim >, MultiComponentVector< Number, prec_dim >, BlockVector< Number > > StateVector