430 const auto &[rho_min, rho_max, s_min, gamma_min] = bounds;
432 auto relaxed_bounds = bounds;
433 auto &[rho_min_relaxed, rho_max_relaxed, s_min_relaxed, g_m_relaxed] =
438 Number r = std::sqrt(hd);
439 if constexpr (dim == 2)
440 r = dealii::Utilities::fixed_power<3>(std::sqrt(r));
441 else if constexpr (dim == 1)
442 r = dealii::Utilities::fixed_power<3>(r);
443 r *= relaxation_factor();
445 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
446 rho_min_relaxed *= std::max(Number(1.) - r, Number(eps));
447 rho_max_relaxed *= (Number(1.) + r);
448 s_min_relaxed *= std::max(Number(1.) - r, Number(eps));
456 const auto numerator = (gamma_min + Number(1.)) * rho_max;
457 const auto covolume_b = view_.eos_covolume_constant();
458 const auto denominator =
459 gamma_min - Number(1.) +
ScalarNumber(2.) * covolume_b * rho_max;
460 const auto rho_compressibility_bound = numerator / denominator;
462 rho_max_relaxed = std::min(rho_compressibility_bound, rho_max_relaxed);
464 return relaxed_bounds;
504 const unsigned int *js,
507 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
514 Assert(std::max(affine_shift.norm(), Number(0.)) == Number(0.),
515 dealii::ExcNotImplemented());
518 auto &[rho_min, rho_max, s_min, gamma_min] = bounds_;
520 const auto rho_i = view_.density(U_i_);
521 const auto rho_j = view_.density(U_j);
524 const auto U_ij_bar =
529 const auto rho_ij_bar = view_.density(U_ij_bar);
533 rho_min = std::min(rho_min, rho_ij_bar);
534 rho_max = std::max(rho_max, rho_ij_bar);
539 const auto beta_ij = Number(1.);
540 rho_relaxation_numerator_ += beta_ij * (rho_i + rho_j);
541 rho_relaxation_denominator_ += std::abs(beta_ij);
545 if (view_.compute_strict_bounds()) {
556 const auto s_j = view_.surrogate_specific_entropy(U_j, gamma_min);
558 const auto s_ij_bar =
559 view_.surrogate_specific_entropy(U_ij_bar, gamma_min);
561 const Number s_interp = view_.surrogate_specific_entropy(
564 s_min = std::min(s_min, s_j);
565 s_min = std::min(s_min, s_ij_bar);
566 s_interp_max_ = std::max(s_interp_max_, s_interp);
575 const auto [p_j, gamma_min_j, s_j, eta_j] =
576 pv.template read_tensor<Number, precomputed_type>(js);
578 const auto s_ij_bar =
579 view_.surrogate_specific_entropy(U_ij_bar, gamma_min);
581 s_min = std::min(s_min, s_j);
582 s_min = std::min(s_min, s_ij_bar);
583 s_interp_max_ = std::max(s_interp_max_, s_ij_bar);
593 const auto &[rho_min, rho_max, s_min, gamma_min] = bounds_;
595 auto relaxed_bounds = fully_relax_bounds(bounds_, hd_i);
596 auto &[rho_min_relaxed, rho_max_relaxed, s_min_relaxed, g_m_relaxed] =
601 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
603 const auto rho_relaxation =
605 std::abs(rho_relaxation_numerator_) /
606 (std::abs(rho_relaxation_denominator_) + Number(eps));
608 const auto entropy_relaxation =
609 relaxation_factor() * (s_interp_max_ - s_min);
611 rho_min_relaxed = std::max(rho_min_relaxed, rho_min - rho_relaxation);
612 rho_max_relaxed = std::min(rho_max_relaxed, rho_max + rho_relaxation);
613 s_min_relaxed = std::max(s_min_relaxed, s_min - entropy_relaxation);
615 return relaxed_bounds;
626 const Number t_max )
const
631 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
632 const auto small = view_.vacuum_state_relaxation_small();
633 const auto large = view_.vacuum_state_relaxation_large();
644 const auto &rho_U = view_.density(U);
645 const auto &rho_P = view_.density(P);
647 const auto &rho_min = std::get<0>(bounds);
648 const auto &rho_max = std::get<1>(bounds);
654 const auto test_min = view_.filter_vacuum_density(
655 std::max(Number(0.), rho_U - relax * rho_max));
656 const auto test_max = view_.filter_vacuum_density(
657 std::max(Number(0.), rho_min - relax * rho_U));
658 if (!(test_min == Number(0.) && test_max == Number(0.))) {
660 std::cout << std::fixed << std::setprecision(16);
661 std::cout <<
"Bounds violation: low-order density (critical)!"
662 <<
"\n\t\trho min: " << rho_min
663 <<
"\n\t\trho min (delta): "
665 <<
"\n\t\trho: " << rho_U
666 <<
"\n\t\trho max (delta): "
668 <<
"\n\t\trho max: " << rho_max <<
"\n"
674 const Number denominator =
677 t_r = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
686 (rho_max - rho_U) * denominator,
689 t_r = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
698 (rho_U - rho_min) * denominator,
708 t_r = std::min(t_r, t_max);
709 t_r = std::max(t_r, t_min);
711#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
715 const auto rho_new = view_.density(U + t_r * P);
716 const auto test_new_min = view_.filter_vacuum_density(
717 std::max(Number(0.), rho_new - relax * rho_max));
718 const auto test_new_max = view_.filter_vacuum_density(
719 std::max(Number(0.), rho_min - relax * rho_new));
720 if (!(test_new_min == Number(0.) && test_new_max == Number(0.))) {
722 std::cout << std::fixed << std::setprecision(16);
723 std::cout <<
"Bounds violation: high-order density!"
724 <<
"\n\t\trho min: " << rho_min
725 <<
"\n\t\trho min (delta): "
727 <<
"\n\t\trho: " << rho_new
728 <<
"\n\t\trho max (delta): "
730 <<
"\n\t\trho max: " << rho_max <<
"\n"
748 const auto &gamma = std::get<3>(bounds) ;
749 const Number gm1 = gamma - Number(1.);
751 const auto b = Number(view_.eos_covolume_constant());
752 const auto pinf = Number(view_.eos_interpolation_pinfty());
753 const auto q = Number(view_.eos_interpolation_q());
772 const auto &s_min = std::get<2>(bounds);
774#ifdef DEBUG_OUTPUT_LIMITER
775 std::cout << std::endl;
776 std::cout << std::fixed << std::setprecision(16);
777 std::cout <<
"t_l: (start) " << t_l << std::endl;
778 std::cout <<
"t_r: (start) " << t_r << std::endl;
781 for (
unsigned int n = 0; n < newton_max_iterations(); ++n) {
783 const auto U_r = U + t_r * P;
784 const auto rho_r = view_.density(U_r);
785 const auto rho_r_gamma =
ryujin::pow(rho_r, gamma);
786 const auto covolume_r = Number(1.) - b * rho_r;
788 const auto rho_e_r = view_.internal_energy(U_r);
789 const auto shift_r = rho_e_r - rho_r * q - pinf * covolume_r;
792 relax_small * rho_r * shift_r -
793 s_min * rho_r * rho_r_gamma *
ryujin::pow(covolume_r, -gm1);
795#ifndef DEBUG_EXPENSIVE_BOUNDS_CHECK
801 dealii::SIMDComparison::greater_than>(
802 psi_r, Number(0.), t_r, t_l);
820#ifdef DEBUG_OUTPUT_LIMITER
821 std::cout <<
"shortcut: t_l == t_r" << std::endl;
822 std::cout <<
"psi_l: " << psi_l << std::endl;
823 std::cout <<
"psi_r: " << psi_r << std::endl;
824 std::cout <<
"t_l: ( " << n <<
" ) " << t_l << std::endl;
825 std::cout <<
"t_r: ( " << n <<
" ) " << t_r << std::endl;
831 const auto U_l = U + t_l * P;
832 const auto rho_l = view_.density(U_l);
833 const auto rho_l_gamma =
ryujin::pow(rho_l, gamma);
834 const auto covolume_l = Number(1.) - b * rho_l;
835 const auto rho_e_l = view_.internal_energy(U_l);
836 const auto shift_l = rho_e_l - rho_l * q - pinf * covolume_l;
839 relax_small * rho_l * shift_l -
840 s_min * rho_l * rho_l_gamma *
ryujin::pow(covolume_l, -gm1);
846 const auto lower_bound = (
ScalarNumber(1.) - relax) * s_min * rho_l *
849 !(std::min(Number(0.), psi_l - lower_bound) == Number(0.))) {
851 std::cout << std::fixed << std::setprecision(16);
853 <<
"Bounds violation: low-order specific entropy (critical)!\n";
854 std::cout <<
"\t\tPsi left: 0 <= " << psi_l <<
"\n" << std::endl;
859#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
865 dealii::SIMDComparison::greater_than>(
866 psi_r, Number(0.), t_r, t_l);
873 const Number tolerance(newton_tolerance());
874 if (std::max(Number(0.), t_r - t_l - tolerance) == Number(0.)) {
875#ifdef DEBUG_OUTPUT_LIMITER
876 std::cout <<
"break: t_l and t_r within tolerance" << std::endl;
877 std::cout <<
"psi_l: " << psi_l << std::endl;
878 std::cout <<
"psi_r: " << psi_r << std::endl;
879 std::cout <<
"t_l: ( " << n <<
" ) " << t_l << std::endl;
880 std::cout <<
"t_r: ( " << n <<
" ) " << t_r << std::endl;
887 const auto drho = view_.density(P);
888 const auto drho_e_l = view_.internal_energy_derivative(U_l) * P;
889 const auto drho_e_r = view_.internal_energy_derivative(U_r) * P;
891 const auto q_pinf_term_l =
894 const auto q_pinf_term_r =
898 const auto extra_term_l = s_min *
900 (covolume_l + gamma - b * rho_l);
901 const auto extra_term_r = s_min *
903 (covolume_r + gamma - b * rho_r);
905 const auto dpsi_l = rho_l * drho_e_l +
906 (rho_e_l - q_pinf_term_l - extra_term_l) * drho;
907 const auto dpsi_r = rho_r * drho_e_r +
908 (rho_e_r - q_pinf_term_r - extra_term_r) * drho;
911 t_l, t_r, psi_l, psi_r, dpsi_l, dpsi_r, Number(-1.));
913#ifdef DEBUG_OUTPUT_LIMITER
914 std::cout <<
"psi_l: " << psi_l << std::endl;
915 std::cout <<
"psi_r: " << psi_r << std::endl;
916 std::cout <<
"dpsi_l: " << dpsi_l << std::endl;
917 std::cout <<
"dpsi_r: " << dpsi_r << std::endl;
918 std::cout <<
"t_l: ( " << n <<
" ) " << t_l << std::endl;
919 std::cout <<
"t_r: ( " << n <<
" ) " << t_r << std::endl;
923#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
928 const auto U_new = U + t_l * P;
930 const auto rho_new = view_.density(U_new);
931 const auto covolume_new = Number(1.) - b * rho_new;
933 const auto rho_new_gamma =
ryujin::pow(rho_new, gamma);
934 const auto rho_e_new = view_.internal_energy(U_new);
936 const auto shift_new = rho_e_new - rho_new * q - pinf * covolume_new;
939 relax_small * rho_new * shift_new -
940 s_min * rho_new * rho_new_gamma *
ryujin::pow(covolume_new, -gm1);
942 const auto lower_bound = (
ScalarNumber(1.) - relax) * s_min *
943 rho_new * rho_new_gamma *
946 const bool e_valid = std::min(Number(0.), shift_new) == Number(0.);
947 const bool psi_valid =
948 std::min(Number(0.), psi_new - lower_bound) == Number(0.);
950 if (!e_valid || !psi_valid) {
952 std::cout << std::fixed << std::setprecision(16);
953 std::cout <<
"Bounds violation: high-order specific entropy!\n";
954 std::cout <<
"\t\trho e: 0 <= " << rho_e_new <<
"\n";
955 std::cout <<
"\t\tPsi: 0 <= " << psi_new <<
"\n" << std::endl;
963 return {t_l, success};