395 std::array<std::reference_wrapper<const StateVector>, stages>
397 const std::array<Number, stages> stage_weights,
400 Number tau_max )
const
403 std::cout <<
"HyperbolicModule<Description, dim, Number>::step()"
407 auto &[old_U, old_precomputed, old_parabolic] = old_state_vector;
408 auto &new_U = std::get<0>(new_state_vector);
415 old_U.template copy_to_memory_space<MemorySpace>();
416 old_precomputed.template copy_to_memory_space<MemorySpace>();
417 for (
int s = 0; s < stages; ++s) {
418 const auto &[U_s, prec_s, V_s] = stage_state_vectors[s].get();
419 U_s.template copy_to_memory_space<MemorySpace>();
420 prec_s.template copy_to_memory_space<MemorySpace>();
422 new_U.template move_to_memory_space<MemorySpace>();
446 constexpr bool shallow_water =
447 std::is_same_v<Description, ShallowWater::Description>;
451 const unsigned int n_internal = offline_data_->n_locally_internal();
452 const unsigned int n_owned = offline_data_->n_locally_owned();
456 const auto sparsity_simd_view =
457 offline_data_->sparsity_pattern_simd().template view<MemorySpace>();
459 const auto mass_matrix_view =
460 offline_data_->mass_matrix().template view<MemorySpace>();
461 const auto lumped_mass_matrix_view =
462 offline_data_->lumped_mass_matrix().template view<MemorySpace>();
463 const auto lumped_mass_matrix_inverse_view =
464 offline_data_->lumped_mass_matrix_inverse()
465 .template view<MemorySpace>();
467 const auto cij_matrix_view =
468 offline_data_->cij_matrix().template view<MemorySpace>();
474 const bool have_discontinuous_ansatz =
475 offline_data_->discretization().have_discontinuous_ansatz();
476 using MatrixReadView =
477 decltype(offline_data_->mass_matrix().template view<MemorySpace>());
478 const auto mass_matrix_inverse_view =
479 have_discontinuous_ansatz
480 ? offline_data_->mass_matrix_inverse().template view<MemorySpace>()
482 const auto incidence_matrix_view =
483 have_discontinuous_ansatz
484 ? offline_data_->incidence_matrix().template view<MemorySpace>()
487 const auto *coupling_boundary_pairs =
488 offline_data_->coupling_boundary_pairs().template view<MemorySpace>();
489 const auto n_coupling_boundary_pairs =
490 offline_data_->coupling_boundary_pairs().size();
492 const Number measure_of_omega_inverse =
493 Number(1.) / offline_data_->measure_of_omega();
497 const auto dij_matrix_view = dij_matrix_.template view<MemorySpace>();
498 const auto lij_matrix_view = lij_matrix_.template view<MemorySpace>();
499 const auto lij_matrix_next_view =
500 lij_matrix_next_.template view<MemorySpace>();
501 const auto pij_matrix_view = pij_matrix_.template view<MemorySpace>();
505 const auto initial_precomputed_view =
506 initial_precomputed_.template view<MemorySpace>();
508 const auto old_U_view = old_U.template view<MemorySpace>();
509 const auto old_precomputed_view =
510 old_precomputed.template view<MemorySpace>();
517 using HyperbolicVectorView = std::remove_const_t<
decltype(old_U_view)>;
518 using PrecomputedVectorView =
519 std::remove_const_t<
decltype(old_precomputed_view)>;
521 Kokkos::Array<HyperbolicVectorView, stages> stage_U_view;
522 Kokkos::Array<PrecomputedVectorView, stages> stage_precomputed_view;
523 Kokkos::Array<Number, stages> stage_weight;
524 for (
int s = 0; s < stages; ++s) {
525 const auto &[U_s, prec_s, V_s] = stage_state_vectors[s].get();
526 stage_U_view[s] = U_s.template view<MemorySpace>();
527 stage_precomputed_view[s] = prec_s.template view<MemorySpace>();
528 stage_weight[s] = stage_weights[s];
531 const auto new_U_view = new_U.template view<MemorySpace>();
533 const auto alpha_view = alpha_.template view<MemorySpace>();
534 const auto bounds_view = bounds_.template view<MemorySpace>();
535 const auto r_view = r_.template view<MemorySpace>();
544 const Number cfl = cfl_;
546 const auto hyperbolic_system_views =
547 make_select_view<dim, Number, MemorySpace>(*hyperbolic_system_);
549 const auto indicator_views =
550 make_select_view<dim, Number, MemorySpace>(indicator_);
552 const auto limiter_views =
553 make_select_view<dim, Number, MemorySpace>(limiter_);
554 const auto n_limiter_iterations =
555 limiter_.template view<dim, Number>().iterations();
557 const auto wave_speed_estimator_views =
558 make_select_view<dim, Number, MemorySpace>(wave_speed_estimator_);
566 const auto scoped_name = [&step_no](
const auto &name,
567 const bool advance =
true) {
568 advance || step_no--;
569 return "time step [H] " + std::to_string(++step_no) +
" - " + name;
572 const auto loop_name = [&step_no]() {
573 return "hyperbolic_kernel_" + std::format(
"{:02}", step_no);
577 Mirrored<int> restart_needed(
"hyperbolic_module_restart_needed",
579 *restart_needed.
view() = 0;
609 const auto body = [=](
auto sentinel,
unsigned int i) {
610 using T =
decltype(sentinel);
612 const unsigned int stride_size = sparsity_simd_view.stride_of_row(i);
614 const auto wave_speed_estimator_view =
615 wave_speed_estimator_views.template view<T>();
617 auto indicator_view = indicator_views.template view<T>();
620 const unsigned int row_length = sparsity_simd_view.row_length(i);
624 const auto U_i = old_U_view.template read_tensor<T>(i);
626 indicator_view.reset(old_precomputed_view, i, U_i);
628 const unsigned int *js = sparsity_simd_view.columns(i);
629 for (
unsigned int col_idx = 0; col_idx < row_length;
630 ++col_idx, js += stride_size) {
632 const auto U_j = old_U_view.template read_tensor<T>(js);
634 const auto c_ij = cij_matrix_view.template read_tensor<T>(i, col_idx);
636 indicator_view.accumulate(old_precomputed_view, js, U_j, c_ij);
643 if (all_below_diagonal<T>(i, js))
646 const auto norm = c_ij.norm();
647 const auto n_ij = c_ij / norm;
648 const auto lambda_max = wave_speed_estimator_view.compute(
649 old_precomputed_view, U_i, U_j, i, js, n_ij);
650 const auto d_ij = norm * lambda_max;
652 dij_matrix_view.write_entry(d_ij, i, col_idx,
true);
655 const auto mass = lumped_mass_matrix_view.template read_entry<T>(i);
656 const auto hd_i = mass * measure_of_omega_inverse;
657 alpha_view.template write_entry<T>(indicator_view.alpha(hd_i), i);
660 loop<MemorySpace, Number>(loop_name(), body, 0, n_internal, n_owned);
662 alpha_view.update_ghost_values();
673 scoped_name(
"compute bdry d_ij, diag d_ii, and tau_max"));
689 const auto body_boundary = [=](
auto,
const unsigned int k) {
690 const auto &[i, col_idx, j] = coupling_boundary_pairs[k];
692 const auto wave_speed_estimator_view =
693 wave_speed_estimator_views.template view<Number>();
706 const auto U_i = old_U_view.read_tensor(i);
707 const auto U_j = old_U_view.read_tensor(j);
709 const auto c_ji = cij_matrix_view.read_transposed_tensor(i, col_idx);
710 Assert(c_ji.norm() > 1.e-12, ExcInternalError());
711 const auto norm_ji = c_ji.norm();
712 const auto n_ji = c_ji / norm_ji;
714 const auto d_ij = dij_matrix_view.read_entry(i, col_idx);
716 const auto lambda_max = wave_speed_estimator_view.compute(
717 old_precomputed_view, U_j, U_i, j, &i, n_ji);
718 const auto d_ji = norm_ji * lambda_max;
720 dij_matrix_view.write_entry(std::max(d_ij, d_ji), i, col_idx);
723 loop<MemorySpace, Number>(loop_name() +
'a',
727 n_coupling_boundary_pairs);
730 const auto body = [=](
auto,
unsigned int i, Number &result) {
732#ifdef DEBUG_SYMMETRY_CHECK
733 const auto wave_speed_estimator_view =
734 wave_speed_estimator_views.template view<Number>();
738 const unsigned int row_length = sparsity_simd_view.row_length(i);
742 Number d_sum = Number(0.);
745 const unsigned int stride_size = sparsity_simd_view.stride_of_row(i);
746 const unsigned int *js = sparsity_simd_view.columns(i);
747 for (
unsigned int col_idx = 1; col_idx < row_length; ++col_idx) {
748 const auto j = *(js + col_idx * stride_size);
752 const auto d_ji = dij_matrix_view.read_transposed_entry(i, col_idx);
754#ifdef DEBUG_SYMMETRY_CHECK
757 const auto U_i = old_U_view.read_tensor(i);
758 const auto U_j = old_U_view.read_tensor(j);
760 const auto c_ij = cij_matrix_view.read_tensor(i, col_idx);
761 Assert(c_ij.norm() > 1.e-12, ExcInternalError());
762 const auto norm_ij = c_ij.norm();
763 const auto n_ij = c_ij / norm_ij;
765 const auto lambda_max = wave_speed_estimator_view.compute(
766 old_precomputed_view, U_i, U_j, i, &j, n_ij);
767 const auto d_ij = norm_ij * lambda_max;
769 Assert(d_ij <= d_ji + 1.0e-12,
770 dealii::ExcMessage(
"d_ij not symmetrized correctly on "
771 "boundary degrees of freedom."));
774 dij_matrix_view.write_entry(d_ji, i, col_idx);
777 d_sum -= dij_matrix_view.read_entry(i, col_idx);
786 std::min(d_sum, Number(-1.e6) * std::numeric_limits<Number>::min());
789 dij_matrix_view.write_entry(d_sum, i, 0);
791 const Number mass = lumped_mass_matrix_view.read_entry(i);
792 const Number local_tau = cfl * mass / (Number(-2.) * d_sum);
794 result = std::min(result, local_tau);
797 tau_max = reduction_loop<MemorySpace, Kokkos::Min<Number>>(
798 loop_name() +
'b', body, tau_max, 0, n_owned);
808 tau_max = Utilities::MPI::min(
809 tau_max, mpi_ensemble_.synchronization_communicator());
812 !std::isnan(tau_max) && !std::isinf(tau_max) && tau_max > 0.,
814 "I'm sorry, Dave. I'm afraid I can't do that.\nWe crashed."));
816 tau = (tau == Number(0.) ? tau_max : tau);
819 std::cout <<
" computed tau_max = " << tau_max <<
" (CFL = " << cfl
821 std::cout <<
" step with tau = " << tau << std::endl;
825 *restart_needed.
view() = (tau > acceptable_tau_max_ratio_ * tau_max);
828 if (*restart_needed.
view() &&
833 std::cout <<
" signalling restart (suggested_tau_max = "
834 << tau_max <<
")" << std::endl;
842 int *restart_needed_view = restart_needed.
view<MemorySpace>();
846 dij_matrix_view.update_ghost_rows();
857 scoped_name(
"l.-o. update, compute bounds, r_i, and p_ij"));
859 const Number weight =
860 -std::accumulate(stage_weights.begin(), stage_weights.end(), -1.);
862 const auto body = [=](
auto sentinel,
863 auto have_discontinuous_ansatz,
864 const unsigned int i) {
865 using T =
decltype(sentinel);
867 const auto view = hyperbolic_system_views.template view<T>();
869 using View =
decltype(view);
870 using flux_contribution_type =
typename View::flux_contribution_type;
873 const unsigned int stride_size = sparsity_simd_view.stride_of_row(i);
875 auto limiter_view = limiter_views.template view<T>();
878 const unsigned int row_length = sparsity_simd_view.row_length(i);
882 const auto U_i = old_U_view.template read_tensor<T>(i);
885 const auto alpha_i = alpha_view.template read_entry<T>(i);
886 const auto m_i = lumped_mass_matrix_view.template read_entry<T>(i);
888 lumped_mass_matrix_inverse_view.template read_entry<T>(i);
890 const auto flux_i = view.flux_contribution(
891 old_precomputed_view, initial_precomputed_view, i, U_i);
893 Kokkos::Array<flux_contribution_type, stages> flux_iHs;
896 for (
int s = 0; s < stages; ++s) {
897 const auto U_iHs = stage_U_view[s].template read_tensor<T>(i);
898 flux_iHs[s] = view.flux_contribution(
899 stage_precomputed_view[s], initial_precomputed_view, i, U_iHs);
901 if constexpr (View::have_source_terms) {
902 S_iH += stage_weight[s] *
903 view.nodal_source(stage_precomputed_view[s], i, U_iHs, tau);
910 if constexpr (View::have_source_terms) {
911 S_i = view.nodal_source(old_precomputed_view, i, U_i, tau);
912 S_iH += weight * S_i;
913 U_i_new += tau * S_i;
917 limiter_view.reset(old_precomputed_view, i, U_i, flux_i);
927 const unsigned int *js = sparsity_simd_view.columns(i);
928 if constexpr (shallow_water) {
929 for (
unsigned int col_idx = 0; col_idx < row_length;
930 ++col_idx, js += stride_size) {
932 const auto U_j = old_U_view.template read_tensor<T>(js);
933 const auto flux_j = view.flux_contribution(
934 old_precomputed_view, initial_precomputed_view, js, U_j);
937 dij_matrix_view.template read_entry<T>(i, col_idx);
939 cij_matrix_view.template read_tensor<T>(i, col_idx);
941 const auto B_ij = view.affine_shift(flux_i, flux_j, c_ij, d_ij);
942 affine_shift += B_ij;
945 affine_shift *= tau * m_i_inv;
948 if constexpr (View::have_source_terms) {
949 affine_shift += tau * S_i;
952 js = sparsity_simd_view.columns(i);
953 for (
unsigned int col_idx = 0; col_idx < row_length;
954 ++col_idx, js += stride_size) {
956 const auto U_j = old_U_view.template read_tensor<T>(js);
958 const auto alpha_j = alpha_view.template read_entry<T>(js);
960 const auto d_ij = dij_matrix_view.template read_entry<T>(i, col_idx);
961 auto factor = (alpha_i + alpha_j) * Number(.5);
963 if constexpr (have_discontinuous_ansatz) {
964 const auto incidence_ij =
965 incidence_matrix_view.template read_entry<T>(i, col_idx);
966 factor = std::max(factor, incidence_ij);
969 const auto d_ijH = d_ij * factor;
971#ifdef DEBUG_SYMMETRY_CHECK
979 dij_matrix_view.template read_transposed_entry<T>(i, col_idx);
980 Assert(std::max(std::abs(d_ij - d_ji), T(1.0e-12)) == T(1.0e-12),
982 "d_ij not symmetrized correctly over MPI ranks"));
985 const auto c_ij = cij_matrix_view.template read_tensor<T>(i, col_idx);
986 constexpr auto eps = std::numeric_limits<Number>::epsilon();
989 ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
990 std::abs(d_ij), T(eps * eps), T(0.), T(1.) / d_ij);
992 const auto scaled_c_ij = c_ij * scale;
994 const auto flux_j = view.flux_contribution(
995 old_precomputed_view, initial_precomputed_view, js, U_j);
997 const auto m_ij = mass_matrix_view.template read_entry<T>(i, col_idx);
1003 const auto flux_ij = view.flux_divergence(flux_i, flux_j, c_ij);
1004 U_i_new += tau * m_i_inv * flux_ij;
1005 auto P_ij = -flux_ij;
1007 if constexpr (shallow_water) {
1012 const auto &[U_star_ij, U_star_ji] =
1013 view.equilibrated_states(flux_i, flux_j);
1015 U_i_new += tau * m_i_inv * d_ij * (U_star_ji - U_star_ij);
1016 F_iH += d_ijH * (U_star_ji - U_star_ij);
1017 P_ij += (d_ijH - d_ij) * (U_star_ji - U_star_ij);
1019 limiter_view.accumulate(old_precomputed_view,
1028 U_i_new += tau * m_i_inv * d_ij * (U_j - U_i);
1029 F_iH += d_ijH * (U_j - U_i);
1030 P_ij += (d_ijH - d_ij) * (U_j - U_i);
1032 limiter_view.accumulate(old_precomputed_view,
1040 if constexpr (View::have_source_terms) {
1041 F_iH -= m_ij * S_iH;
1049 if constexpr (View::have_high_order_flux) {
1050 const auto high_order_flux_ij =
1051 view.high_order_flux_divergence(flux_i, flux_j, c_ij);
1052 F_iH += weight * high_order_flux_ij;
1053 P_ij += weight * high_order_flux_ij;
1055 F_iH += weight * flux_ij;
1056 P_ij += weight * flux_ij;
1059 if constexpr (View::have_source_terms) {
1061 view.nodal_source(old_precomputed_view, js, U_j, tau);
1062 F_iH += weight * m_ij * S_j;
1063 P_ij += weight * m_ij * S_j;
1066 for (
int s = 0; s < stages; ++s) {
1067 const auto U_jHs = stage_U_view[s].template read_tensor<T>(js);
1068 const auto flux_jHs = view.flux_contribution(
1069 stage_precomputed_view[s], initial_precomputed_view, js, U_jHs);
1071 if constexpr (View::have_high_order_flux) {
1072 const auto high_order_flux_ij =
1073 view.high_order_flux_divergence(flux_iHs[s], flux_jHs, c_ij);
1074 F_iH += stage_weight[s] * high_order_flux_ij;
1075 P_ij += stage_weight[s] * high_order_flux_ij;
1077 const auto flux_ij =
1078 view.flux_divergence(flux_iHs[s], flux_jHs, c_ij);
1079 F_iH += stage_weight[s] * flux_ij;
1080 P_ij += stage_weight[s] * flux_ij;
1083 if constexpr (View::have_source_terms) {
1085 view.nodal_source(stage_precomputed_view[s], js, U_jHs, tau);
1086 F_iH += stage_weight[s] * m_ij * S_js;
1087 P_ij += stage_weight[s] * m_ij * S_js;
1091 pij_matrix_view.template write_tensor<T>(P_ij, i, col_idx,
true);
1094#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
1095 if (!view.is_admissible(U_i_new)) {
1096 atomic_store(restart_needed_view, 1);
1100 new_U_view.template write_tensor<T>(U_i_new, i);
1101 r_view.template write_tensor<T>(F_iH, i);
1103 const auto hd_i = m_i * measure_of_omega_inverse;
1104 const auto relaxed_bounds = limiter_view.bounds(hd_i);
1105 bounds_view.template write_tensor<T>(relaxed_bounds, i);
1114 if (have_discontinuous_ansatz) {
1115 loop<MemorySpace, Number>(
1116 loop_name(), body, 0, n_internal, n_owned, std::true_type{});
1118 loop<MemorySpace, Number>(
1119 loop_name(), body, 0, n_internal, n_owned, std::false_type{});
1122 r_view.update_ghost_values();
1123 if (have_discontinuous_ansatz) {
1129 bounds_view.update_ghost_values();
1139 if (n_limiter_iterations != 0) {
1142 const auto body = [=](
auto sentinel,
1143 auto have_discontinuous_ansatz,
1144 const unsigned int i) {
1145 using T =
decltype(sentinel);
1147 const unsigned int stride_size = sparsity_simd_view.stride_of_row(i);
1149 auto limiter_view = limiter_views.template view<T>();
1152 const unsigned int row_length = sparsity_simd_view.row_length(i);
1153 if (row_length == 1)
1157 bounds_view.template read_tensor<T, std::array<T, n_bounds>>(i);
1164 if constexpr (have_discontinuous_ansatz) {
1166 const unsigned int *js = sparsity_simd_view.columns(i) + stride_size;
1167 for (
unsigned int col_idx = 1; col_idx < row_length;
1168 ++col_idx, js += stride_size) {
1169 local_bounds = limiter_view.combine_bounds(
1171 bounds_view.template read_tensor<T, std::array<T, n_bounds>>(
1174 bounds_view.template write_tensor<T>(local_bounds, i);
1177 [[maybe_unused]] T m_i;
1178 if constexpr (have_discontinuous_ansatz)
1179 m_i = lumped_mass_matrix_view.template read_entry<T>(i);
1181 const auto m_i_inv =
1182 lumped_mass_matrix_inverse_view.template read_entry<T>(i);
1184 const auto U_i_new = new_U_view.template read_tensor<T>(i);
1186 const auto F_iH = r_view.template read_tensor<T>(i);
1188 const auto lambda_inv = Number(row_length - 1);
1189 const auto factor = tau * m_i_inv * lambda_inv;
1199 auto P_ij = pij_matrix_view.template read_tensor<T>(i, 1);
1202 const unsigned int *js = sparsity_simd_view.columns(i) + stride_size;
1203 for (
unsigned int col_idx = 1; col_idx < row_length;
1204 ++col_idx, js += stride_size) {
1206 const auto P_ij_next = pij_matrix_view.template read_tensor<T>(
1207 i, col_idx + 1 < row_length ? col_idx + 1 : col_idx);
1208 const auto F_jH = r_view.template read_tensor<T>(js);
1214 const auto kronecker_ij = col_idx == 0 ? T(1.) : T(0.);
1216 if constexpr (have_discontinuous_ansatz) {
1219 const auto m_j = lumped_mass_matrix_view.template read_entry<T>(js);
1220 const auto m_ij_inv =
1221 mass_matrix_inverse_view.template read_entry<T>(i, col_idx);
1222 const auto b_ij = m_i * m_ij_inv - kronecker_ij;
1223 const auto b_ji = m_j * m_ij_inv - kronecker_ij;
1225 P_ij += b_ij * F_jH - b_ji * F_iH;
1230 const auto m_j_inv =
1231 lumped_mass_matrix_inverse_view.template read_entry<T>(js);
1233 mass_matrix_view.template read_entry<T>(i, col_idx);
1234 const auto b_ij = kronecker_ij - m_ij * m_j_inv;
1235 const auto b_ji = kronecker_ij - m_ij * m_i_inv;
1237 P_ij += b_ij * F_jH - b_ji * F_iH;
1241 pij_matrix_view.template write_tensor<T>(P_ij, i, col_idx);
1247 const auto &[l_ij, success] =
1248 limiter_view.limit(local_bounds, U_i_new, P_ij);
1249 lij_matrix_view.template write_entry<T>(l_ij, i, col_idx,
true);
1260 atomic_store(restart_needed_view, 1);
1272 if (have_discontinuous_ansatz) {
1273 loop<MemorySpace, Number>(
1274 loop_name(), body, 0, n_internal, n_owned, std::true_type{});
1276 loop<MemorySpace, Number>(
1277 loop_name(), body, 0, n_internal, n_owned, std::false_type{});
1280 lij_matrix_view.update_ghost_rows();
1293 for (
unsigned int pass = 0; pass < n_limiter_iterations; ++pass) {
1294 bool last_round = (pass + 1 == n_limiter_iterations);
1296 std::string additional_step = (last_round ?
"" :
", next l_ij");
1298 scoped_name(
"symmetrize l_ij, h.-o. update" + additional_step));
1300 const auto lij_view = (n_limiter_iterations == 2 && last_round)
1301 ? lij_matrix_next_view
1304 const auto body = [=](
auto sentinel,
const unsigned int i) {
1305 using T =
decltype(sentinel);
1307 auto limiter_view = limiter_views.template view<T>();
1310 const unsigned int row_length = sparsity_simd_view.row_length(i);
1311 if (row_length == 1)
1314 auto U_i_new = new_U_view.template read_tensor<T>(i);
1316 const Number lambda = Number(1.) / Number(row_length - 1);
1319 for (
unsigned int col_idx = 1; col_idx < row_length; ++col_idx) {
1322 std::min(lij_view.template read_entry<T>(i, col_idx),
1323 lij_view.template read_transposed_entry<T>(i, col_idx));
1325 const auto p_ij = pij_matrix_view.template read_tensor<T>(i, col_idx);
1327 U_i_new += l_ij * lambda * p_ij;
1330#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
1331 const auto view = hyperbolic_system_views.template view<T>();
1332 if (!view.is_admissible(U_i_new)) {
1333 atomic_store(restart_needed_view, 1);
1337 new_U_view.template write_tensor<T>(U_i_new, i);
1343 const auto local_bounds =
1344 bounds_view.template read_tensor<T, std::array<T, n_bounds>>(i);
1346 for (
unsigned int col_idx = 1; col_idx < row_length; ++col_idx) {
1348 const auto old_l_ij =
1349 std::min(lij_view.template read_entry<T>(i, col_idx),
1350 lij_view.template read_transposed_entry<T>(i, col_idx));
1352 const auto new_p_ij =
1353 (T(1.) - old_l_ij) *
1354 pij_matrix_view.template read_tensor<T>(i, col_idx);
1356 const auto &[new_l_ij, success] =
1357 limiter_view.limit(local_bounds, U_i_new, new_p_ij);
1369#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
1371 atomic_store(restart_needed_view, 1);
1380 const auto entry = (T(1.) - old_l_ij) * new_l_ij;
1381 lij_matrix_next_view.write_entry(entry, i, col_idx,
true);
1385 loop<MemorySpace, Number>(loop_name(), body, 0, n_internal, n_owned);
1388 lij_matrix_next_view.update_ghost_rows();
1395 const auto &old_V = std::get<2>(old_state_vector);
1396 auto &new_V = std::get<2>(new_state_vector);
1415 int &restart_flag = *restart_needed.
view();
1416 restart_flag = Utilities::MPI::logical_or(
1417 restart_flag != 0, mpi_ensemble_.synchronization_communicator());
1420 if (*restart_needed.
view()) {
1421 switch (id_violation_strategy_) {
1425 std::cout <<
" raised warning, CFL/IDP violation encountered "
1433 std::cout <<
" signalling restart (suggested_tau_max = "
1434 << tau_max <<
")" << std::endl;