14#include <deal.II/lac/linear_operator.h>
15#include <deal.II/lac/precondition.h>
16#include <deal.II/lac/solver_cg.h>
17#include <deal.II/matrix_free/fe_evaluation.h>
18#include <deal.II/multigrid/mg_coarse.h>
19#include <deal.II/multigrid/mg_matrix.h>
20#include <deal.II/multigrid/mg_transfer.templates.h>
21#include <deal.II/multigrid/mg_transfer_matrix_free.h>
22#include <deal.II/multigrid/multigrid.h>
28 namespace NavierStokes
30 using namespace dealii;
32 template <
int dim,
typename Number>
39 const std::string &subsection )
40 : ParameterAcceptor(subsection)
41 , mpi_ensemble_(mpi_ensemble)
42 , hyperbolic_system_(&hyperbolic_system)
43 , parabolic_system_(¶bolic_system)
44 , offline_data_(&offline_data)
45 , initial_values_(&initial_values)
51 , n_iterations_velocity_(0.)
52 , n_iterations_internal_energy_(0.)
54 use_gmg_velocity_ =
false;
55 add_parameter(
"multigrid velocity",
57 "Use geometric multigrid for velocity component");
59 gmg_max_iter_vel_ = 12;
60 add_parameter(
"multigrid velocity - max iter",
62 "Maximal number of CG iterations with GMG smoother");
64 gmg_smoother_range_vel_ = 8.;
65 add_parameter(
"multigrid velocity - chebyshev range",
66 gmg_smoother_range_vel_,
67 "Chebyshev smoother: eigenvalue range parameter");
69 gmg_smoother_max_eig_vel_ = 2.0;
70 add_parameter(
"multigrid velocity - chebyshev max eig",
71 gmg_smoother_max_eig_vel_,
72 "Chebyshev smoother: maximal eigenvalue");
74 use_gmg_internal_energy_ =
false;
75 add_parameter(
"multigrid energy",
76 use_gmg_internal_energy_,
77 "Use geometric multigrid for internal energy component");
79 gmg_max_iter_en_ = 15;
80 add_parameter(
"multigrid energy - max iter",
82 "Maximal number of CG iterations with GMG smoother");
84 gmg_smoother_range_en_ = 15.;
85 add_parameter(
"multigrid energy - chebyshev range",
86 gmg_smoother_range_en_,
87 "Chebyshev smoother: eigenvalue range parameter");
89 gmg_smoother_max_eig_en_ = 2.0;
90 add_parameter(
"multigrid energy - chebyshev max eig",
91 gmg_smoother_max_eig_en_,
92 "Chebyshev smoother: maximal eigenvalue");
94 gmg_smoother_degree_ = 3;
95 add_parameter(
"multigrid - chebyshev degree",
97 "Chebyshev smoother: degree");
99 gmg_smoother_n_cg_iter_ = 10;
101 "multigrid - chebyshev cg iter",
102 gmg_smoother_n_cg_iter_,
103 "Chebyshev smoother: number of CG iterations to approximate "
108 "multigrid - min level",
110 "Minimal mesh level to be visited in the geometric multigrid "
111 "cycle where the coarse grid solver (Chebyshev) is called");
113 tolerance_ = Number(1.0e-12);
114 add_parameter(
"tolerance", tolerance_,
"Tolerance for linear solvers");
116 tolerance_linfty_norm_ =
false;
117 add_parameter(
"tolerance linfty norm",
118 tolerance_linfty_norm_,
119 "Use the l_infty norm instead of the l_2 norm for the "
120 "stopping criterion");
124 template <
int dim,
typename Number>
128 std::cout <<
"ParabolicModule<dim, Number>::prepare()" << std::endl;
136 const auto &discretization = offline_data_->discretization();
138 dealii::ExcMessage(
"The Navier-Stokes module currently only "
139 "supports cG Q1 finite elements."));
141 AssertThrow(!offline_data_->dof_handler().has_hp_capabilities(),
143 "The Navier-Stokes module currently does not support "
144 "DoFHandlers set up with hp capabilities."));
148 typename MatrixFree<dim, Number>::AdditionalData additional_data;
149 additional_data.tasks_parallel_scheme =
150 MatrixFree<dim, Number>::AdditionalData::none;
152 matrix_free_.reinit(discretization.mapping(),
153 offline_data_->dof_handler(),
154 offline_data_->affine_constraints(),
155 discretization.quadrature_1d(),
158 const auto &scalar_partitioner =
159 matrix_free_.get_dof_info(0).vector_partitioner;
161 velocity_.reinit(dim);
162 velocity_rhs_.reinit(dim);
163 for (
unsigned int i = 0; i < dim; ++i) {
164 velocity_.block(i).reinit(scalar_partitioner);
165 velocity_rhs_.block(i).reinit(scalar_partitioner);
168 internal_energy_.reinit(scalar_partitioner);
169 internal_energy_rhs_.reinit(scalar_partitioner);
171 density_.reinit(scalar_partitioner);
175 if (!use_gmg_velocity_ && !use_gmg_internal_energy_)
178 const unsigned int n_levels =
179 offline_data_->dof_handler().get_triangulation().n_global_levels();
180 const unsigned int min_level = std::min(gmg_min_level_, n_levels - 1);
181 MGLevelObject<IndexSet> relevant_sets(0, n_levels - 1);
182 for (
unsigned int level = 0; level < n_levels; ++level)
183 relevant_sets[level] =
184 dealii::DoFTools::extract_locally_relevant_level_dofs(
185 offline_data_->dof_handler(), level);
186 mg_constrained_dofs_.initialize(offline_data_->dof_handler(),
188 std::set<types::boundary_id> boundary_ids;
191 mg_constrained_dofs_.make_zero_boundary_constraints(
192 offline_data_->dof_handler(), boundary_ids);
194 typename MatrixFree<dim, float>::AdditionalData additional_data_level;
195 additional_data_level.tasks_parallel_scheme =
196 MatrixFree<dim, float>::AdditionalData::none;
198 level_matrix_free_.resize(min_level, n_levels - 1);
199 level_density_.resize(min_level, n_levels - 1);
200 for (
unsigned int level = min_level; level < n_levels; ++level) {
201 additional_data_level.mg_level = level;
202 AffineConstraints<double> constraints(relevant_sets[level],
203 relevant_sets[level]);
207 level_matrix_free_[level].reinit(discretization.mapping(),
208 offline_data_->dof_handler(),
210 discretization.quadrature_1d(),
211 additional_data_level);
212 level_matrix_free_[level].initialize_dof_vector(level_density_[level]);
215 mg_transfer_velocity_.build(offline_data_->dof_handler(),
216 mg_constrained_dofs_,
218 mg_transfer_energy_.build(offline_data_->dof_handler(),
223 template <
int dim,
typename Number>
234 template <
int dim,
typename Number>
235 template <
int stages>
239 std::array<std::reference_wrapper<const StateVector>,
241 const std::array<Number, stages> ,
247 step(old_state_vector,
255 template <
int dim,
typename Number>
263 step(old_state_vector,
279 step(old_state_vector,
288 template <
int dim,
typename Number>
290 std::ostream &output)
const
292 output <<
" [ " << std::setprecision(2) << std::fixed
293 << n_iterations_velocity_
294 << (use_gmg_velocity_ ?
" GMG vel -- " :
" CG vel -- ")
295 << n_iterations_internal_energy_
296 << (use_gmg_internal_energy_ ?
" GMG int ]" :
" CG int ]")
301 template <
int dim,
typename Number>
303 const StateVector &old_state_vector,
305 StateVector &new_state_vector,
307 const bool crank_nicolson_extrapolation)
const
310 std::cout <<
"ParabolicModule<dim, Number>::step()" << std::endl;
312 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
314 const auto old_U_view = std::get<0>(old_state_vector).view();
315 const auto new_U_view = std::get<0>(new_state_vector).view();
317 const auto lumped_mass_matrix_view =
318 offline_data_->lumped_mass_matrix().view();
319 const auto &affine_constraints = offline_data_->affine_constraints();
323 const unsigned int n_owned = offline_data_->n_locally_owned();
325 const auto sparsity_simd_view =
326 offline_data_->sparsity_pattern_simd().view();
331 std::cout <<
" perform time-step with tau = " << tau << std::endl;
332 if (crank_nicolson_extrapolation)
333 std::cout <<
" and extrapolate to t + 2 * tau" << std::endl;
341 const bool reinitialize_gmg = (cycle_++ % 4 == 0);
356 std::atomic<bool> restart_needed =
false;
367 std::atomic<bool> correction_needed =
false;
379 const auto body = [&](
auto sentinel,
unsigned int i) {
380 using T =
decltype(sentinel);
382 const auto view = hyperbolic_system_->template view<dim, T>();
384 const auto U_i = old_U_view.template read_tensor<T>(i);
385 const auto rho_i = view.density(U_i);
386 const auto M_i = view.momentum(U_i);
387 const auto rho_e_i = view.internal_energy(U_i);
388 const auto m_i = lumped_mass_matrix_view.template read_entry<T>(i);
390 write_entry<T>(density_, rho_i, i);
392 for (
unsigned int d = 0; d < dim; ++d) {
393 write_entry<T>(velocity_.block(d), M_i[d] / rho_i, i);
394 write_entry<T>(velocity_rhs_.block(d), m_i * (M_i[d]), i);
396 write_entry<T>(internal_energy_, rho_e_i / rho_i, i);
399 cpu_simd_loop<Number>(
400 "time_step_parabolic_1", body, 0, n_owned, n_owned);
409 const auto &boundary_map = offline_data_->boundary_map();
411 for (
auto entry : boundary_map) {
413 const auto i = std::get<0>(entry);
417 const auto normal = std::get<1>(entry);
418 const auto id = std::get<4>(entry);
419 const auto position = std::get<5>(entry);
423 Tensor<1, dim, Number> V_i;
424 Tensor<1, dim, Number> RHS_i;
425 for (
unsigned int d = 0; d < dim; ++d) {
426 V_i[d] = velocity_.block(d).local_element(i);
427 RHS_i[d] = velocity_rhs_.block(d).local_element(i);
429 V_i -= 1. * (V_i * normal) * normal;
430 RHS_i -= 1. * (RHS_i * normal) * normal;
431 for (
unsigned int d = 0; d < dim; ++d) {
432 velocity_.block(d).local_element(i) = V_i[d];
433 velocity_rhs_.block(d).local_element(i) = RHS_i[d];
439 for (
unsigned int d = 0; d < dim; ++d) {
440 velocity_.block(d).local_element(i) = Number(0.);
441 velocity_rhs_.block(d).local_element(i) = Number(0.);
447 const auto U_i = initial_values_->initial_state(position, t + tau);
448 const auto view = hyperbolic_system_->template view<dim, Number>();
449 const auto rho_i = view.density(U_i);
450 const auto V_i = view.momentum(U_i) / rho_i;
451 const auto e_i = view.internal_energy(U_i) / rho_i;
453 for (
unsigned int d = 0; d < dim; ++d) {
454 velocity_.block(d).local_element(i) = V_i[d];
455 velocity_rhs_.block(d).local_element(i) = V_i[d];
458 internal_energy_.local_element(i) = e_i;
469 affine_constraints.set_zero(density_);
470 affine_constraints.set_zero(internal_energy_);
471 for (
unsigned int d = 0; d < dim; ++d) {
472 affine_constraints.set_zero(velocity_.block(d));
473 affine_constraints.set_zero(velocity_rhs_.block(d));
479 lumped_mass_matrix_view, density_, affine_constraints);
481 if (use_gmg_velocity_ && reinitialize_gmg) {
482 MGLevelObject<
typename PreconditionChebyshev<
483 VelocityMatrix<dim, float, Number>,
484 LinearAlgebra::distributed::BlockVector<float>,
485 DiagonalMatrix<dim, float>>::AdditionalData>
486 smoother_data(level_matrix_free_.min_level(),
487 level_matrix_free_.max_level());
489 level_velocity_matrices_.resize(level_matrix_free_.min_level(),
490 level_matrix_free_.max_level());
491 mg_transfer_velocity_.interpolate_to_mg(
492 offline_data_->dof_handler(), level_density_, density_);
494 for (
unsigned int level = level_matrix_free_.min_level();
495 level <= level_matrix_free_.max_level();
497 level_velocity_matrices_[level].initialize(
500 level_matrix_free_[level],
501 level_density_[level],
504 level_velocity_matrices_[level].compute_diagonal(
505 smoother_data[level].preconditioner);
506 if (level == level_matrix_free_.min_level()) {
507 smoother_data[level].degree = numbers::invalid_unsigned_int;
508 smoother_data[level].eig_cg_n_iterations = 500;
509 smoother_data[level].smoothing_range = 1e-3;
511 smoother_data[level].degree = gmg_smoother_degree_;
512 smoother_data[level].eig_cg_n_iterations =
513 gmg_smoother_n_cg_iter_;
514 smoother_data[level].smoothing_range = gmg_smoother_range_vel_;
515 if (gmg_smoother_n_cg_iter_ == 0)
516 smoother_data[level].max_eigenvalue = gmg_smoother_max_eig_vel_;
519 mg_smoother_velocity_.initialize(level_velocity_matrices_,
527 ComputingTimer::Scope scope(
528 "time step [X] _ - synchronization barriers");
534 *std::min_element(internal_energy_.begin(), internal_energy_.end());
536 e_min_old = Utilities::MPI::min(e_min_old,
537 mpi_ensemble_.ensemble_communicator());
540 constexpr Number eps = std::numeric_limits<Number>::epsilon();
541 e_min_old *= (1. - 1000. * eps);
548 ComputingTimer::Scope scope(
"time step [P] 1 - update velocities");
550 VelocityMatrix<dim, Number, Number> velocity_operator;
551 velocity_operator.initialize(
552 *parabolic_system_, *offline_data_, matrix_free_, density_, tau);
554 const auto tolerance_velocity =
555 (tolerance_linfty_norm_ ? velocity_rhs_.linfty_norm()
556 : velocity_rhs_.l2_norm()) *
565 if (!use_gmg_velocity_)
566 throw SolverControl::NoConvergence(0, 0.);
568 using bvt_float = LinearAlgebra::distributed::BlockVector<float>;
570 MGCoarseGridApplySmoother<bvt_float> mg_coarse;
571 mg_coarse.initialize(mg_smoother_velocity_);
573 mg::Matrix<bvt_float> mg_matrix(level_velocity_matrices_);
575 Multigrid<bvt_float> mg(mg_matrix,
577 mg_transfer_velocity_,
578 mg_smoother_velocity_,
579 mg_smoother_velocity_,
580 level_velocity_matrices_.min_level(),
581 level_velocity_matrices_.max_level());
583 const auto &dof_handler = offline_data_->dof_handler();
584 PreconditionMG<dim, bvt_float, MGTransferVelocity<dim, float>>
585 preconditioner(dof_handler, mg, mg_transfer_velocity_);
587 SolverControl solver_control(gmg_max_iter_vel_, tolerance_velocity);
588 SolverCG<BlockHostVector> solver(solver_control);
590 velocity_operator, velocity_, velocity_rhs_, preconditioner);
593 n_iterations_velocity_ =
594 0.9 * n_iterations_velocity_ + 0.1 * solver_control.last_step();
596 }
catch (SolverControl::NoConvergence &) {
598 SolverControl solver_control(1000, tolerance_velocity);
599 SolverCG<BlockHostVector> solver(solver_control);
601 velocity_operator, velocity_, velocity_rhs_, diagonal_matrix);
604 n_iterations_velocity_ *= 0.9;
605 n_iterations_velocity_ +=
606 0.1 * (use_gmg_velocity_ ? gmg_max_iter_vel_ : 0) +
607 0.1 * solver_control.last_step();
615 ComputingTimer::Scope scope(
"time step [P] 2 - update internal energy");
618 matrix_free_.template cell_loop<ScalarHostVector, BlockHostVector>(
619 [
this](
const auto &data,
622 const auto cell_range) {
623 FEEvaluation<dim, order_fe, order_quad, dim, Number> velocity(
625 FEEvaluation<dim, order_fe, order_quad, 1, Number> energy(data);
627 const auto mu = parabolic_system_->mu();
628 const auto lambda = parabolic_system_->lambda();
630 for (
unsigned int cell = cell_range.first;
631 cell < cell_range.second;
633 velocity.reinit(cell);
635 velocity.gather_evaluate(src, EvaluationFlags::gradients);
637 for (
unsigned int q = 0; q < velocity.n_q_points; ++q) {
638 if constexpr (dim == 1) {
640 const auto gradient = velocity.get_gradient(q);
641 auto S = (4. / 3. * mu + lambda) * gradient;
642 energy.submit_value(gradient * S, q);
646 const auto symmetric_gradient =
647 velocity.get_symmetric_gradient(q);
648 const auto divergence = trace(symmetric_gradient);
649 auto S = 2. * mu * symmetric_gradient;
650 for (
unsigned int d = 0; d < dim; ++d)
651 S[d][d] += (lambda - 2. / 3. * mu) * divergence;
652 energy.submit_value(symmetric_gradient * S, q);
655 energy.integrate_scatter(EvaluationFlags::values, dst);
658 internal_energy_rhs_,
662 const auto lumped_mass_matrix_view =
663 offline_data_->lumped_mass_matrix().view();
665 const auto body = [&](
auto sentinel,
unsigned int i) {
666 using T =
decltype(sentinel);
668 const auto view = hyperbolic_system_->template view<dim, T>();
670 const auto rhs_i = read_entry<T>(internal_energy_rhs_, i);
671 const auto m_i = lumped_mass_matrix_view.template read_entry<T>(i);
672 const auto rho_i = read_entry<T>(density_, i);
673 const auto e_i = read_entry<T>(internal_energy_, i);
675 const auto U_i = old_U_view.template read_tensor<T>(i);
676 const auto V_i = view.momentum(U_i) / rho_i;
678 dealii::Tensor<1, dim, T> V_i_new;
679 for (
unsigned int d = 0; d < dim; ++d) {
680 V_i_new[d] = read_entry<T>(velocity_.block(d), i);
688 crank_nicolson_extrapolation
690 : Number(0.5) * (V_i - V_i_new).norm_square();
693 const auto result = m_i * rho_i * (e_i +
correction) + tau * rhs_i;
694 write_entry<T>(internal_energy_rhs_, result, i);
697 cpu_simd_loop<Number>(
698 "time_step_parabolic_2", body, 0, n_owned, n_owned);
707 const auto &boundary_map = offline_data_->boundary_map();
709 for (
auto entry : boundary_map) {
711 const auto i = std::get<0>(entry);
715 const auto id = std::get<4>(entry);
716 const auto position = std::get<5>(entry);
720 const auto U_i = initial_values_->initial_state(position, t + tau);
721 const auto view = hyperbolic_system_->template view<dim, Number>();
722 const auto rho_i = view.density(U_i);
723 const auto e_i = view.internal_energy(U_i) / rho_i;
724 internal_energy_rhs_.local_element(i) = e_i;
734 affine_constraints.set_zero(internal_energy_);
735 affine_constraints.set_zero(internal_energy_rhs_);
742 if (use_gmg_internal_energy_ && reinitialize_gmg) {
743 MGLevelObject<
typename PreconditionChebyshev<
744 EnergyMatrix<dim, float, Number>,
745 LinearAlgebra::distributed::Vector<float>>::AdditionalData>
746 smoother_data(level_matrix_free_.min_level(),
747 level_matrix_free_.max_level());
749 level_energy_matrices_.resize(level_matrix_free_.min_level(),
750 level_matrix_free_.max_level());
752 for (
unsigned int level = level_matrix_free_.min_level();
753 level <= level_matrix_free_.max_level();
755 level_energy_matrices_[level].initialize(
757 level_matrix_free_[level],
758 level_density_[level],
759 tau * parabolic_system_->cv_inverse_kappa(),
761 level_energy_matrices_[level].compute_diagonal(
762 smoother_data[level].preconditioner);
763 if (level == level_matrix_free_.min_level()) {
764 smoother_data[level].degree = numbers::invalid_unsigned_int;
765 smoother_data[level].eig_cg_n_iterations = 500;
766 smoother_data[level].smoothing_range = 1e-3;
768 smoother_data[level].degree = gmg_smoother_degree_;
769 smoother_data[level].eig_cg_n_iterations =
770 gmg_smoother_n_cg_iter_;
771 smoother_data[level].smoothing_range = gmg_smoother_range_en_;
772 if (gmg_smoother_n_cg_iter_ == 0)
773 smoother_data[level].max_eigenvalue = gmg_smoother_max_eig_en_;
776 mg_smoother_energy_.initialize(level_energy_matrices_, smoother_data);
784 ComputingTimer::Scope scope(
"time step [P] 2 - update internal energy");
786 EnergyMatrix<dim, Number, Number> energy_operator;
787 const auto &kappa = parabolic_system_->cv_inverse_kappa();
788 energy_operator.initialize(
789 *offline_data_, matrix_free_, density_, tau * kappa);
791 const auto tolerance_internal_energy =
792 (tolerance_linfty_norm_ ? internal_energy_rhs_.linfty_norm()
793 : internal_energy_rhs_.l2_norm()) *
797 if (!use_gmg_internal_energy_)
798 throw SolverControl::NoConvergence(0, 0.);
800 using vt_float = LinearAlgebra::distributed::Vector<float>;
801 MGCoarseGridApplySmoother<vt_float> mg_coarse;
802 mg_coarse.initialize(mg_smoother_energy_);
803 mg::Matrix<vt_float> mg_matrix(level_energy_matrices_);
805 Multigrid<vt_float> mg(mg_matrix,
810 level_energy_matrices_.min_level(),
811 level_energy_matrices_.max_level());
813 const auto &dof_handler = offline_data_->dof_handler();
814 PreconditionMG<dim, vt_float, MGTransferEnergy<dim, float>>
815 preconditioner(dof_handler, mg, mg_transfer_energy_);
817 SolverControl solver_control(gmg_max_iter_en_,
818 tolerance_internal_energy);
819 SolverCG<ScalarHostVector> solver(solver_control);
820 solver.solve(energy_operator,
822 internal_energy_rhs_,
826 n_iterations_internal_energy_ = 0.9 * n_iterations_internal_energy_ +
827 0.1 * solver_control.last_step();
829 }
catch (SolverControl::NoConvergence &) {
831 SolverControl solver_control(1000, tolerance_internal_energy);
832 SolverCG<ScalarHostVector> solver(solver_control);
833 solver.solve(energy_operator,
835 internal_energy_rhs_,
839 n_iterations_internal_energy_ *= 0.9;
840 n_iterations_internal_energy_ +=
841 0.1 * (use_gmg_internal_energy_ ? gmg_max_iter_en_ : 0) +
842 0.1 * solver_control.last_step();
853 ComputingTimer::Scope scope(
"time step [P] 3 - write back vectors");
855 const auto body = [&](
auto sentinel,
unsigned int i) {
856 using T =
decltype(sentinel);
858 const auto view = hyperbolic_system_->template view<dim, T>();
861 const unsigned int row_length = sparsity_simd_view.row_length(i);
865 auto U_i = old_U_view.template read_tensor<T>(i);
866 const auto rho_i = view.density(U_i);
868 Tensor<1, dim, T> m_i_new;
869 for (
unsigned int d = 0; d < dim; ++d) {
870 m_i_new[d] = rho_i * read_entry<T>(velocity_.block(d), i);
873 auto rho_e_i_new = rho_i * read_entry<T>(internal_energy_, i);
880 if (!(T(0.) == std::max(T(0.), rho_i * e_min_old - rho_e_i_new))) {
882 std::cout << std::fixed << std::setprecision(16);
883 const auto e_i_new = rho_e_i_new / rho_i;
884 std::cout <<
"Bounds violation: internal energy (critical)!\n"
885 <<
"\t\te_min_old: " << e_min_old <<
"\n"
886 <<
"\t\te_min_old (delta): "
888 <<
"\t\te_min_new: " << e_i_new <<
"\n"
891 restart_needed =
true;
894 if (crank_nicolson_extrapolation) {
895 m_i_new = Number(2.0) * m_i_new - view.momentum(U_i);
896 rho_e_i_new = Number(2.0) * rho_e_i_new - view.internal_energy(U_i);
904 std::max(T(0.), eps * rho_i * e_min_old - rho_e_i_new))) {
906 std::cout << std::fixed << std::setprecision(16);
907 const auto e_i_new = rho_e_i_new / rho_i;
909 std::cout <<
"Bounds violation: high-order internal energy!"
910 <<
"\t\te_min_new: " << e_i_new <<
"\n"
911 <<
"\t\t-- correction required --" << std::endl;
913 correction_needed =
true;
917 const auto E_i_new = rho_e_i_new + 0.5 * m_i_new * m_i_new / rho_i;
919 for (
unsigned int d = 0; d < dim; ++d)
920 U_i[1 + d] = m_i_new[d];
921 U_i[1 + dim] = E_i_new;
923 new_U_view.template write_tensor<T>(U_i, i);
926 cpu_simd_loop<Number>(
927 "time_step_parabolic_3", body, 0, n_owned, n_owned);
929 new_U_view.update_ghost_values();
933 ComputingTimer::Scope scope(
934 "time step [X] _ - synchronization barriers");
945 restart_needed.store(Utilities::MPI::logical_or(
946 restart_needed.load(),
947 mpi_ensemble_.synchronization_communicator()));
949 correction_needed.store(Utilities::MPI::logical_or(
950 correction_needed.load(),
951 mpi_ensemble_.synchronization_communicator()));
954 if (correction_needed) {
959 throw Restart{Number(0.5) * tau};
966 if (restart_needed) {
967 switch (id_violation_strategy_) {
974 throw Restart{Number(0.5) * tau};
void reinit(const Vector &lumped_mass_matrix, const vector_type &density, const dealii::AffineConstraints< Number > &affine_constraints)
typename View::StateVector StateVector
DEAL_II_HOST_DEVICE_ALWAYS_INLINE Number negative_part(const Number number)