@@ -270,8 +270,8 @@ contains
270270 @:ALLOCATE(gammas (1 :num_fluids))
271271 @:ALLOCATE(eoss (1 :num_fluids), rho0s (1 :num_fluids), t0s (1 :num_fluids), gruneisen0s (1 :num_fluids), &
272272 & gruneisen_as (1 :num_fluids), mg_c0s (1 :num_fluids), mg_ss (1 :num_fluids), mg_s2s (1 :num_fluids), &
273- & mg_s3s (1 :num_fluids), jwl_as (1 :num_fluids), jwl_bs (1 :num_fluids), jwl_r1s (1 :num_fluids), &
274- & jwl_r2s (1 :num_fluids), vinet_k0s (1 :num_fluids), vinet_k0ps (1 :num_fluids))
273+ & mg_s3s (1 :num_fluids), mg_mu_maxs (1 :num_fluids), jwl_as (1 :num_fluids), jwl_bs (1 :num_fluids), &
274+ & jwl_r1s ( 1 :num_fluids), jwl_r2s (1 :num_fluids), vinet_k0s (1 :num_fluids), vinet_k0ps (1 :num_fluids))
275275 @:ALLOCATE(isentrope_n (1 :num_fluids))
276276 @:ALLOCATE(pi_infs(1 :num_fluids))
277277 @:ALLOCATE(isentrope_B(1 :num_fluids))
@@ -303,6 +303,9 @@ contains
303303 mg_ss(i) = fluid_pp(i)%mg_s
304304 mg_s2s(i) = fluid_pp(i)%mg_s2
305305 mg_s3s(i) = fluid_pp(i)%mg_s3
306+ ! Where a cubic Hugoniot fit turns over: mu(u_p) peaks where c0 = s2 u_p^2 + 2 s3 u_p^3 , and past it
307+ ! no shock state exists, so the Newton below would wander. Solved once here, on the host.
308+ mg_mu_maxs(i) = f_hugoniot_compression_limit(fluid_pp(i)%mg_c0, fluid_pp(i)%mg_s, fluid_pp(i)%mg_s2, fluid_pp(i)%mg_s3)
306309 jwl_as(i) = fluid_pp(i)%jwl_a
307310 jwl_bs(i) = fluid_pp(i)%jwl_b
308311 jwl_r1s(i) = fluid_pp(i)%jwl_r1
@@ -335,7 +338,8 @@ contains
335338 if (f_is_state_dependent(i)) any_state_dependent_eos = .true.
336339 end do
337340 $:GPU_UPDATE(device= ' [gammas, isentrope_n, pi_infs, isentrope_B, cvs, qvs, qvps, Gs_vc, eoss, rho0s, t0s, gruneisen0s, &
338- & gruneisen_as, mg_c0s, mg_ss, mg_s2s, mg_s3s, jwl_as, jwl_bs, jwl_r1s, jwl_r2s, vinet_k0s, vinet_k0ps, any_state_dependent_eos]' )
341+ & gruneisen_as, mg_c0s, mg_ss, mg_s2s, mg_s3s, mg_mu_maxs, jwl_as, jwl_bs, jwl_r1s, jwl_r2s, vinet_k0s, &
342+ & vinet_k0ps, any_state_dependent_eos]' )
339343
340344 @:ALLOCATE(Res_vc(1 :2 , 1 :max (1 , Re_size_max)))
341345 Res_vc = dflt_real
@@ -1219,7 +1223,7 @@ contains
12191223 if (allocated(rho_sf)) deallocate (rho_sf, gamma_sf, pi_inf_sf)
12201224
12211225 @:DEALLOCATE(gammas, isentrope_n, pi_infs, isentrope_B, cvs, qvs, qvps, Gs_vc, eoss, rho0s, t0s, gruneisen0s, &
1222- & gruneisen_as, mg_c0s, mg_ss, mg_s2s, mg_s3s, jwl_as, jwl_bs, jwl_r1s, jwl_r2s, vinet_k0s, vinet_k0ps)
1226+ & gruneisen_as, mg_c0s, mg_ss, mg_s2s, mg_s3s, mg_mu_maxs, jwl_as, jwl_bs, jwl_r1s, jwl_r2s, vinet_k0s, vinet_k0ps)
12231227 if (allocated(bubrs_vc)) then
12241228 @:DEALLOCATE(bubrs_vc)
12251229 end if
@@ -1353,6 +1357,9 @@ contains
13531357 integer :: iter
13541358
13551359 mu = rho/rho0s(i) - 1._wp
1360+ ! Past the fit' s turnover there is no shock state to find; clamp rather than let the Newton below wander
1361+ ! off and return a silently wrong pressure. mg_mu_maxs is huge for the linear fit, so this is a no- op there.
1362+ if (eoss(i) == eos_mie_gruneisen .and. mu > mg_mu_maxs(i)) mu = mg_mu_maxs(i)
13561363 select case (eoss(i))
13571364 case (eos_mie_gruneisen)
13581365 ! Hugoniot reference u_s = c0 + s u_p + s2 u_p^2 + s3 u_p^3 , with p_H = rho0 u_s u_p and the Hugoniot
@@ -1435,6 +1442,33 @@ contains
14351442
14361443 end function f_has_isentropic_reference
14371444
1445+ !> The largest compression a cubic Hugoniot fit can represent. mu(u_p) = u_p/ (u_s - u_p) rises, peaks where c0 = s2 u_p^2 + 2 s3
1446+ !! u_p^3 , and falls after; only the rising branch is a physical shock. Returns a huge value for the linear fit, which never
1447+ !! turns over. Host- side: called once per fluid at initialization.
1448+ impure function f_hugoniot_compression_limit (c0 , s , s2 , s3 ) result(mu_max)
1449+
1450+ real (wp), intent (in ) :: c0, s, s2, s3
1451+ real (wp) :: mu_max, up, f, df, us
1452+ integer :: iter
1453+
1454+ if (s2 == 0._wp .and. s3 == 0._wp ) then
1455+ mu_max = huge (1._wp )
1456+ return
1457+ end if
1458+
1459+ ! Newton on c0 - s2 u^2 - 2 s3 u^3 = 0 , from a guess that brackets the physical range
1460+ up = c0
1461+ do iter = 1 , 100
1462+ f = c0 - s2* up** 2 - 2._wp * s3* up** 3
1463+ df = - 2._wp * s2* up - 6._wp * s3* up** 2
1464+ if (abs (df) < verysmall) exit
1465+ up = max (up - f/ df, verysmall)
1466+ end do
1467+ us = c0 + up* (s + up* (s2 + up* s3))
1468+ mu_max = up/ max (us - up, verysmall)
1469+
1470+ end function f_hugoniot_compression_limit
1471+
14381472 !> Gamma, Pi, dPi/ drho and dGamma/ drho of fluid i at density rho, the coefficients of rho e = Gamma p + Pi(rho). Stiffened and
14391473 !! ideal gas keep the constants resolved at init, bit for bit.
14401474 subroutine s_eos_coefficients (rho , i , gamma , pi_inf , dpi , dgamma )
0 commit comments