476 const unsigned int *js,
479 const dealii::Tensor<1, dim, Number> &scaled_c_ij,
486 Assert(std::max(affine_shift.norm(), Number(0.)) == Number(0.),
487 dealii::ExcNotImplemented());
490 auto &[rho_min, rho_max, s_min] = bounds_;
492 const auto rho_i = view_.density(U_i_);
493 const auto m_i = view_.momentum(U_i_);
494 const auto rho_j = view_.density(U_j);
495 const auto m_j = view_.momentum(U_j);
496 const auto rho_affine_shift = view_.density(affine_shift);
499 const auto rho_ij_bar =
500 ScalarNumber(0.5) * (rho_i + rho_j + (m_i - m_j) * scaled_c_ij) +
503 rho_min = std::min(rho_min, rho_ij_bar);
504 rho_max = std::max(rho_max, rho_ij_bar);
506 const auto &[s_j, eta_j] =
507 pv.template read_tensor<Number, precomputed_type>(js);
508 s_min = std::min(s_min, s_j);
513 const auto beta_ij = Number(1.);
514 rho_relaxation_numerator_ += beta_ij * (rho_i + rho_j);
515 rho_relaxation_denominator_ += std::abs(beta_ij);
517 const Number s_interp =
518 view_.specific_entropy((U_i_ + U_j) *
ScalarNumber(.5));
519 s_interp_max_ = std::max(s_interp_max_, s_interp);
528 const auto &[rho_min, rho_max, s_min] = bounds_;
530 auto relaxed_bounds = fully_relax_bounds(bounds_, hd_i);
531 auto &[rho_min_relaxed, rho_max_relaxed, s_min_relaxed] = relaxed_bounds;
535 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
537 const auto rho_relaxation =
539 std::abs(rho_relaxation_numerator_) /
540 (std::abs(rho_relaxation_denominator_) + Number(eps));
542 const auto entropy_relaxation =
543 relaxation_factor() * (s_interp_max_ - s_min);
545 rho_min_relaxed = std::max(rho_min_relaxed, rho_min - rho_relaxation);
546 rho_max_relaxed = std::min(rho_max_relaxed, rho_max + rho_relaxation);
547 s_min_relaxed = std::max(s_min_relaxed, s_min - entropy_relaxation);
549 return relaxed_bounds;
560 const Number t_max )
const
565 constexpr ScalarNumber eps = std::numeric_limits<ScalarNumber>::epsilon();
566 const auto small = view_.vacuum_state_relaxation_small();
567 const auto large = view_.vacuum_state_relaxation_large();
578 const auto &rho_U = view_.density(U);
579 const auto &rho_P = view_.density(P);
581 const auto &rho_min = std::get<0>(bounds);
582 const auto &rho_max = std::get<1>(bounds);
588 const auto test_min = view_.filter_vacuum_density(
589 std::max(Number(0.), rho_U - relax * rho_max));
590 const auto test_max = view_.filter_vacuum_density(
591 std::max(Number(0.), rho_min - relax * rho_U));
592 if (!(test_min == Number(0.) && test_max == Number(0.))) {
594 std::cout << std::fixed << std::setprecision(16);
595 std::cout <<
"Bounds violation: low-order density (critical)!"
596 <<
"\n\t\trho min: " << rho_min
597 <<
"\n\t\trho min (delta): "
599 <<
"\n\t\trho: " << rho_U
600 <<
"\n\t\trho max (delta): "
602 <<
"\n\t\trho max: " << rho_max <<
"\n"
608 const Number denominator =
611 constexpr auto lt = dealii::SIMDComparison::less_than;
613 t_r = ryujin::compare_and_apply_mask<lt>(
622 (rho_max - rho_U) * denominator,
625 t_r = ryujin::compare_and_apply_mask<lt>(
634 (rho_U - rho_min) * denominator,
644 t_r = std::min(t_r, t_max);
645 t_r = std::max(t_r, t_min);
647#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
651 const auto rho_new = view_.density(U + t_r * P);
652 const auto test_new_min = view_.filter_vacuum_density(
653 std::max(Number(0.), rho_new - relax * rho_max));
654 const auto test_new_max = view_.filter_vacuum_density(
655 std::max(Number(0.), rho_min - relax * rho_new));
656 if (!(test_new_min == Number(0.) && test_new_max == Number(0.))) {
658 std::cout << std::fixed << std::setprecision(16);
659 std::cout <<
"Bounds violation: high-order density!"
660 <<
"\n\t\trho min: " << rho_min
661 <<
"\n\t\trho min (delta): "
663 <<
"\n\t\trho: " << rho_new
664 <<
"\n\t\trho max (delta): "
666 <<
"\n\t\trho max: " << rho_max <<
"\n"
701 const auto &s_min = std::get<2>(bounds);
703#ifdef DEBUG_OUTPUT_LIMITER
704 std::cout << std::endl;
705 std::cout << std::fixed << std::setprecision(16);
706 std::cout <<
"t_l: (start) " << t_l << std::endl;
707 std::cout <<
"t_r: (start) " << t_r << std::endl;
710 for (
unsigned int n = 0; n < newton_max_iterations(); ++n) {
712 const auto U_r = U + t_r * P;
713 const auto rho_r = view_.density(U_r);
714 const auto rho_r_gamma =
ryujin::pow(rho_r, gamma);
715 const auto rho_e_r = view_.internal_energy(U_r);
718 relax_small * rho_r * rho_e_r - s_min * rho_r * rho_r_gamma;
720#ifndef DEBUG_EXPENSIVE_BOUNDS_CHECK
726 dealii::SIMDComparison::greater_than>(
727 psi_r, Number(0.), t_r, t_l);
745#ifdef DEBUG_OUTPUT_LIMITER
746 std::cout <<
"shortcut: t_l == t_r" << std::endl;
747 std::cout <<
"psi_l: " << psi_l << std::endl;
748 std::cout <<
"psi_r: " << psi_r << std::endl;
749 std::cout <<
"t_l: ( " << n <<
" ) " << t_l << std::endl;
750 std::cout <<
"t_r: ( " << n <<
" ) " << t_r << std::endl;
756 const auto U_l = U + t_l * P;
757 const auto rho_l = view_.density(U_l);
758 const auto rho_l_gamma =
ryujin::pow(rho_l, gamma);
759 const auto rho_e_l = view_.internal_energy(U_l);
762 relax_small * rho_l * rho_e_l - s_min * rho_l * rho_l_gamma;
768 const auto lower_bound =
769 (
ScalarNumber(1.) - relax) * s_min * rho_l * rho_l_gamma;
771 !(std::min(Number(0.), psi_l - lower_bound) == Number(0.))) {
773 std::cout << std::fixed << std::setprecision(16);
775 <<
"Bounds violation: low-order specific entropy (critical)!\n";
776 std::cout <<
"\t\tPsi left: 0 <= " << psi_l <<
"\n" << std::endl;
781#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
787 dealii::SIMDComparison::greater_than>(
788 psi_r, Number(0.), t_r, t_l);
795 const Number tolerance(newton_tolerance());
796 if (std::max(Number(0.), t_r - t_l - tolerance) == Number(0.)) {
797#ifdef DEBUG_OUTPUT_LIMITER
798 std::cout <<
"break: t_l and t_r within tolerance" << std::endl;
799 std::cout <<
"psi_l: " << psi_l << std::endl;
800 std::cout <<
"psi_r: " << psi_r << std::endl;
801 std::cout <<
"t_l: ( " << n <<
" ) " << t_l << std::endl;
802 std::cout <<
"t_r: ( " << n <<
" ) " << t_r << std::endl;
809 const auto drho = view_.density(P);
810 const auto drho_e_l = view_.internal_energy_derivative(U_l) * P;
811 const auto drho_e_r = view_.internal_energy_derivative(U_r) * P;
813 rho_l * drho_e_l + (rho_e_l - gp1 * s_min * rho_l_gamma) * drho;
815 rho_r * drho_e_r + (rho_e_r - gp1 * s_min * rho_r_gamma) * drho;
818 t_l, t_r, psi_l, psi_r, dpsi_l, dpsi_r, Number(-1.));
820#ifdef DEBUG_OUTPUT_LIMITER
821 std::cout <<
"psi_l: " << psi_l << std::endl;
822 std::cout <<
"psi_r: " << psi_r << std::endl;
823 std::cout <<
"dpsi_l: " << dpsi_l << std::endl;
824 std::cout <<
"dpsi_r: " << dpsi_r << std::endl;
825 std::cout <<
"t_l: ( " << n <<
" ) " << t_l << std::endl;
826 std::cout <<
"t_r: ( " << n <<
" ) " << t_r << std::endl;
830#ifdef DEBUG_EXPENSIVE_BOUNDS_CHECK
835 const auto U_new = U + t_l * P;
836 const auto rho_new = view_.density(U_new);
837 const auto rho_new_gamma =
ryujin::pow(rho_new, gamma);
838 const auto rho_e_new = view_.internal_energy(U_new);
840 auto psi_new = relax_small * rho_new * rho_e_new -
841 s_min * rho_new * rho_new_gamma;
843 const auto lower_bound =
844 (
ScalarNumber(1.) - relax) * s_min * rho_new * rho_new_gamma;
846 const bool e_valid = std::min(Number(0.), rho_e_new) == Number(0.);
847 const bool psi_valid =
848 std::min(Number(0.), psi_new - lower_bound) == Number(0.);
850 if (!e_valid || !psi_valid) {
852 std::cout << std::fixed << std::setprecision(16);
853 std::cout <<
"Bounds violation: high-order specific entropy!\n";
854 std::cout <<
"\t\trho e: 0 <= " << rho_e_new <<
"\n";
855 std::cout <<
"\t\tPsi: 0 <= " << psi_new <<
"\n" << std::endl;
863 return {t_l, success};