432 const auto &[rho_min, rho_max, s_min, gamma_min] = bounds;
434 auto relaxed_bounds = bounds;
435 auto &[rho_min_relaxed, rho_max_relaxed, s_min_relaxed, g_m_relaxed] =
440 Number r = std::sqrt(hd);
441 if constexpr (dim == 2)
442 r = dealii::Utilities::fixed_power<3>(std::sqrt(r));
443 else if constexpr (dim == 1)
444 r = dealii::Utilities::fixed_power<3>(r);
445 r *= relaxation_factor();
447 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
448 rho_min_relaxed *= std::max(Number(1.) - r, Number(eps));
449 rho_max_relaxed *= (Number(1.) + r);
450 s_min_relaxed *= std::max(Number(1.) - r, Number(eps));
458 const auto numerator = (gamma_min + Number(1.)) * rho_max;
459 const auto covolume_b = view_.eos_covolume_constant();
460 const auto denominator =
461 gamma_min - Number(1.) +
ScalarNumber(2.) * covolume_b * rho_max;
462 const auto rho_compressibility_bound = numerator / denominator;
464 rho_max_relaxed = std::min(rho_compressibility_bound, rho_max_relaxed);
466 return relaxed_bounds;
506 const unsigned int *js,
509 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
516 Assert(std::max(affine_shift.norm(), Number(0.)) == Number(0.),
517 dealii::ExcNotImplemented());
520 auto &[rho_min, rho_max, s_min, gamma_min] = bounds_;
522 const auto rho_i = view_.density(U_i_);
523 const auto rho_j = view_.density(U_j);
526 const auto U_ij_bar =
531 const auto rho_ij_bar = view_.density(U_ij_bar);
535 rho_min = std::min(rho_min, rho_ij_bar);
536 rho_max = std::max(rho_max, rho_ij_bar);
541 const auto beta_ij = Number(1.);
542 rho_relaxation_numerator_ += beta_ij * (rho_i + rho_j);
543 rho_relaxation_denominator_ += std::abs(beta_ij);
547 if (view_.compute_strict_bounds()) {
558 const auto s_j = view_.surrogate_specific_entropy(U_j, gamma_min);
560 const auto s_ij_bar =
561 view_.surrogate_specific_entropy(U_ij_bar, gamma_min);
563 const Number s_interp = view_.surrogate_specific_entropy(
566 s_min = std::min(s_min, s_j);
567 s_min = std::min(s_min, s_ij_bar);
568 s_interp_max_ = std::max(s_interp_max_, s_interp);
577 const auto [p_j, gamma_min_j, s_j, eta_j] =
578 pv.template read_tensor<Number, precomputed_type>(js);
580 const auto s_ij_bar =
581 view_.surrogate_specific_entropy(U_ij_bar, gamma_min);
583 s_min = std::min(s_min, s_j);
584 s_min = std::min(s_min, s_ij_bar);
585 s_interp_max_ = std::max(s_interp_max_, s_ij_bar);
595 const auto &[rho_min, rho_max, s_min, gamma_min] = bounds_;
597 auto relaxed_bounds = fully_relax_bounds(bounds_, hd_i);
598 auto &[rho_min_relaxed, rho_max_relaxed, s_min_relaxed, g_m_relaxed] =
603 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
605 const auto rho_relaxation =
607 std::abs(rho_relaxation_numerator_) /
608 (std::abs(rho_relaxation_denominator_) + Number(eps));
610 const auto entropy_relaxation =
611 relaxation_factor() * (s_interp_max_ - s_min);
613 rho_min_relaxed = std::max(rho_min_relaxed, rho_min - rho_relaxation);
614 rho_max_relaxed = std::min(rho_max_relaxed, rho_max + rho_relaxation);
615 s_min_relaxed = std::max(s_min_relaxed, s_min - entropy_relaxation);
617 return relaxed_bounds;
628 const Number t_max )
const
633 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
634 const auto small = view_.vacuum_state_relaxation_small();
635 const auto large = view_.vacuum_state_relaxation_large();
646 const auto &rho_U = view_.density(U);
647 const auto &rho_P = view_.density(P);
649 const auto &rho_min = std::get<0>(bounds);
650 const auto &rho_max = std::get<1>(bounds);
656 const auto test_min = view_.filter_vacuum_density(
657 std::max(Number(0.), rho_U - relax * rho_max));
658 const auto test_max = view_.filter_vacuum_density(
659 std::max(Number(0.), rho_min - relax * rho_U));
660 if (!(test_min == Number(0.) && test_max == Number(0.))) {
662 std::cout << std::fixed << std::setprecision(16);
663 std::cout <<
"Bounds violation: low-order density (critical)!"
664 <<
"\n\t\trho min: " << rho_min
665 <<
"\n\t\trho min (delta): "
667 <<
"\n\t\trho: " << rho_U
668 <<
"\n\t\trho max (delta): "
670 <<
"\n\t\trho max: " << rho_max <<
"\n"
676 const Number denominator =
679 t_r = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
688 (rho_max - rho_U) * denominator,
691 t_r = ryujin::compare_and_apply_mask<dealii::SIMDComparison::less_than>(
700 (rho_U - rho_min) * denominator,
710 t_r = std::min(t_r, t_max);
711 t_r = std::max(t_r, t_min);
713#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
717 const auto rho_new = view_.density(U + t_r * P);
718 const auto test_new_min = view_.filter_vacuum_density(
719 std::max(Number(0.), rho_new - relax * rho_max));
720 const auto test_new_max = view_.filter_vacuum_density(
721 std::max(Number(0.), rho_min - relax * rho_new));
722 if (!(test_new_min == Number(0.) && test_new_max == Number(0.))) {
724 std::cout << std::fixed << std::setprecision(16);
725 std::cout <<
"Bounds violation: high-order density!"
726 <<
"\n\t\trho min: " << rho_min
727 <<
"\n\t\trho min (delta): "
729 <<
"\n\t\trho: " << rho_new
730 <<
"\n\t\trho max (delta): "
732 <<
"\n\t\trho max: " << rho_max <<
"\n"
750 const auto &gamma = std::get<3>(bounds) ;
751 const Number gm1 = gamma - Number(1.);
753 const auto b = Number(view_.eos_covolume_constant());
754 const auto pinf = Number(view_.eos_interpolation_pinfty());
755 const auto q = Number(view_.eos_interpolation_q());
774 const auto &s_min = std::get<2>(bounds);
776#ifdef DEBUG_OUTPUT_LIMITER
777 std::cout << std::endl;
778 std::cout << std::fixed << std::setprecision(16);
779 std::cout <<
"t_l: (start) " << t_l << std::endl;
780 std::cout <<
"t_r: (start) " << t_r << std::endl;
783 for (
unsigned int n = 0; n < newton_max_iterations(); ++n) {
785 const auto U_r = U + t_r * P;
786 const auto rho_r = view_.density(U_r);
787 const auto rho_r_gamma =
ryujin::pow(rho_r, gamma);
788 const auto covolume_r = Number(1.) - b * rho_r;
790 const auto rho_e_r = view_.internal_energy(U_r);
791 const auto shift_r = rho_e_r - rho_r * q - pinf * covolume_r;
794 relax_small * rho_r * shift_r -
795 s_min * rho_r * rho_r_gamma *
ryujin::pow(covolume_r, -gm1);
797#ifndef DEBUG_EXPENSIVE_BOUNDS_CHECK
803 dealii::SIMDComparison::greater_than>(
804 psi_r, Number(0.), t_r, t_l);
822#ifdef DEBUG_OUTPUT_LIMITER
823 std::cout <<
"shortcut: t_l == t_r" << std::endl;
824 std::cout <<
"psi_l: " << psi_l << std::endl;
825 std::cout <<
"psi_r: " << psi_r << std::endl;
826 std::cout <<
"t_l: ( " << n <<
" ) " << t_l << std::endl;
827 std::cout <<
"t_r: ( " << n <<
" ) " << t_r << std::endl;
833 const auto U_l = U + t_l * P;
834 const auto rho_l = view_.density(U_l);
835 const auto rho_l_gamma =
ryujin::pow(rho_l, gamma);
836 const auto covolume_l = Number(1.) - b * rho_l;
837 const auto rho_e_l = view_.internal_energy(U_l);
838 const auto shift_l = rho_e_l - rho_l * q - pinf * covolume_l;
841 relax_small * rho_l * shift_l -
842 s_min * rho_l * rho_l_gamma *
ryujin::pow(covolume_l, -gm1);
848 const auto lower_bound = (
ScalarNumber(1.) - relax) * s_min * rho_l *
851 !(std::min(Number(0.), psi_l - lower_bound) == Number(0.))) {
853 std::cout << std::fixed << std::setprecision(16);
855 <<
"Bounds violation: low-order specific entropy (critical)!\n";
856 std::cout <<
"\t\tPsi left: 0 <= " << psi_l <<
"\n" << std::endl;
861#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
867 dealii::SIMDComparison::greater_than>(
868 psi_r, Number(0.), t_r, t_l);
875 const Number tolerance(newton_tolerance());
876 if (std::max(Number(0.), t_r - t_l - tolerance) == Number(0.)) {
877#ifdef DEBUG_OUTPUT_LIMITER
878 std::cout <<
"break: t_l and t_r within tolerance" << std::endl;
879 std::cout <<
"psi_l: " << psi_l << std::endl;
880 std::cout <<
"psi_r: " << psi_r << std::endl;
881 std::cout <<
"t_l: ( " << n <<
" ) " << t_l << std::endl;
882 std::cout <<
"t_r: ( " << n <<
" ) " << t_r << std::endl;
889 const auto drho = view_.density(P);
890 const auto drho_e_l = view_.internal_energy_derivative(U_l) * P;
891 const auto drho_e_r = view_.internal_energy_derivative(U_r) * P;
893 const auto q_pinf_term_l =
896 const auto q_pinf_term_r =
900 const auto extra_term_l = s_min *
902 (covolume_l + gamma - b * rho_l);
903 const auto extra_term_r = s_min *
905 (covolume_r + gamma - b * rho_r);
907 const auto dpsi_l = rho_l * drho_e_l +
908 (rho_e_l - q_pinf_term_l - extra_term_l) * drho;
909 const auto dpsi_r = rho_r * drho_e_r +
910 (rho_e_r - q_pinf_term_r - extra_term_r) * drho;
913 t_l, t_r, psi_l, psi_r, dpsi_l, dpsi_r, Number(-1.));
915#ifdef DEBUG_OUTPUT_LIMITER
916 std::cout <<
"psi_l: " << psi_l << std::endl;
917 std::cout <<
"psi_r: " << psi_r << std::endl;
918 std::cout <<
"dpsi_l: " << dpsi_l << std::endl;
919 std::cout <<
"dpsi_r: " << dpsi_r << std::endl;
920 std::cout <<
"t_l: ( " << n <<
" ) " << t_l << std::endl;
921 std::cout <<
"t_r: ( " << n <<
" ) " << t_r << std::endl;
925#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
930 const auto U_new = U + t_l * P;
932 const auto rho_new = view_.density(U_new);
933 const auto covolume_new = Number(1.) - b * rho_new;
935 const auto rho_new_gamma =
ryujin::pow(rho_new, gamma);
936 const auto rho_e_new = view_.internal_energy(U_new);
938 const auto shift_new = rho_e_new - rho_new * q - pinf * covolume_new;
941 relax_small * rho_new * shift_new -
942 s_min * rho_new * rho_new_gamma *
ryujin::pow(covolume_new, -gm1);
944 const auto lower_bound = (
ScalarNumber(1.) - relax) * s_min *
945 rho_new * rho_new_gamma *
948 const bool e_valid = std::min(Number(0.), shift_new) == Number(0.);
949 const bool psi_valid =
950 std::min(Number(0.), psi_new - lower_bound) == Number(0.);
952 if (!e_valid || !psi_valid) {
954 std::cout << std::fixed << std::setprecision(16);
955 std::cout <<
"Bounds violation: high-order specific entropy!\n";
956 std::cout <<
"\t\trho e: 0 <= " << rho_e_new <<
"\n";
957 std::cout <<
"\t\tPsi: 0 <= " << psi_new <<
"\n" << std::endl;
965 return {t_l, success};