@@ -593,6 +593,91 @@ def riemann_prim(idir, ng,
593593 return q_int
594594
595595
596+ @njit (cache = True )
597+ def estimate_wave_speed (rho_l , u_l , p_l , c_l ,
598+ rho_r , u_r , p_r , c_r ,
599+ gamma ):
600+
601+ # Estimate the star quantities -- use one of three methods to
602+ # do this -- the primitive variable Riemann solver, the two
603+ # shock approximation, or the two rarefaction approximation.
604+ # Pick the method based on the pressure states at the
605+ # interface.
606+
607+ p_max = max (p_l , p_r )
608+ p_min = min (p_l , p_r )
609+
610+ Q = p_max / p_min
611+
612+ rho_avg = 0.5 * (rho_l + rho_r )
613+ c_avg = 0.5 * (c_l + c_r )
614+
615+ # primitive variable Riemann solver (Toro, 9.3)
616+ factor = rho_avg * c_avg
617+
618+ pstar = 0.5 * (p_l + p_r ) + 0.5 * (u_l - u_r ) * factor
619+ ustar = 0.5 * (u_l + u_r ) + 0.5 * (p_l - p_r ) / factor
620+
621+ if Q > 2 and (pstar < p_min or pstar > p_max ):
622+
623+ # use a more accurate Riemann solver for the estimate here
624+
625+ if pstar < p_min :
626+
627+ # 2-rarefaction Riemann solver
628+ z = (gamma - 1.0 ) / (2.0 * gamma )
629+ p_lr = (p_l / p_r )** z
630+
631+ ustar = (p_lr * u_l / c_l + u_r / c_r +
632+ 2.0 * (p_lr - 1.0 ) / (gamma - 1.0 )) / \
633+ (p_lr / c_l + 1.0 / c_r )
634+
635+ pstar = 0.5 * (p_l * (1.0 + (gamma - 1.0 ) * (u_l - ustar ) /
636+ (2.0 * c_l ))** (1.0 / z ) +
637+ p_r * (1.0 + (gamma - 1.0 ) * (ustar - u_r ) /
638+ (2.0 * c_r ))** (1.0 / z ))
639+
640+ else :
641+
642+ # 2-shock Riemann solver
643+ A_r = 2.0 / ((gamma + 1.0 ) * rho_r )
644+ B_r = p_r * (gamma - 1.0 ) / (gamma + 1.0 )
645+
646+ A_l = 2.0 / ((gamma + 1.0 ) * rho_l )
647+ B_l = p_l * (gamma - 1.0 ) / (gamma + 1.0 )
648+
649+ # guess of the pressure
650+ p_guess = max (0.0 , pstar )
651+
652+ g_l = np .sqrt (A_l / (p_guess + B_l ))
653+ g_r = np .sqrt (A_r / (p_guess + B_r ))
654+
655+ pstar = (g_l * p_l + g_r * p_r - (u_r - u_l )) / (g_l + g_r )
656+
657+ ustar = 0.5 * (u_l + u_r ) + \
658+ 0.5 * ((pstar - p_r ) * g_r - (pstar - p_l ) * g_l )
659+
660+ # estimate the nonlinear wave speeds
661+
662+ if pstar <= p_l :
663+ # rarefaction
664+ S_l = u_l - c_l
665+ else :
666+ # shock
667+ S_l = u_l - c_l * np .sqrt (1.0 + ((gamma + 1.0 ) / (2.0 * gamma )) *
668+ (pstar / p_l - 1.0 ))
669+
670+ if pstar <= p_r :
671+ # rarefaction
672+ S_r = u_r + c_r
673+ else :
674+ # shock
675+ S_r = u_r + c_r * np .sqrt (1.0 + ((gamma + 1.0 ) / (2.0 / gamma )) *
676+ (pstar / p_r - 1.0 ))
677+
678+ return S_l , S_r
679+
680+
596681@njit (cache = True )
597682def riemann_hllc (idir , ng ,
598683 idens , ixmom , iymom , iener , irhoX , nspec ,
@@ -683,96 +768,8 @@ def riemann_hllc(idir, ng,
683768 c_l = max (smallc , np .sqrt (gamma * p_l / rho_l ))
684769 c_r = max (smallc , np .sqrt (gamma * p_r / rho_r ))
685770
686- # Estimate the star quantities -- use one of three methods to
687- # do this -- the primitive variable Riemann solver, the two
688- # shock approximation, or the two rarefaction approximation.
689- # Pick the method based on the pressure states at the
690- # interface.
691-
692- p_max = max (p_l , p_r )
693- p_min = min (p_l , p_r )
694-
695- Q = p_max / p_min
696-
697- rho_avg = 0.5 * (rho_l + rho_r )
698- c_avg = 0.5 * (c_l + c_r )
699-
700- # primitive variable Riemann solver (Toro, 9.3)
701- factor = rho_avg * c_avg
702- # factor2 = rho_avg / c_avg
703-
704- pstar = 0.5 * (p_l + p_r ) + 0.5 * (un_l - un_r ) * factor
705- ustar = 0.5 * (un_l + un_r ) + 0.5 * (p_l - p_r ) / factor
706-
707- # rhostar_l = rho_l + (un_l - ustar) * factor2
708- # rhostar_r = rho_r + (ustar - un_r) * factor2
709-
710- if Q > 2 and (pstar < p_min or pstar > p_max ):
711-
712- # use a more accurate Riemann solver for the estimate here
713-
714- if pstar < p_min :
715-
716- # 2-rarefaction Riemann solver
717- z = (gamma - 1.0 ) / (2.0 * gamma )
718- p_lr = (p_l / p_r )** z
719-
720- ustar = (p_lr * un_l / c_l + un_r / c_r +
721- 2.0 * (p_lr - 1.0 ) / (gamma - 1.0 )) / \
722- (p_lr / c_l + 1.0 / c_r )
723-
724- pstar = 0.5 * (p_l * (1.0 + (gamma - 1.0 ) * (un_l - ustar ) /
725- (2.0 * c_l ))** (1.0 / z ) +
726- p_r * (1.0 + (gamma - 1.0 ) * (ustar - un_r ) /
727- (2.0 * c_r ))** (1.0 / z ))
728-
729- # rhostar_l = rho_l * (pstar / p_l)**(1.0 / gamma)
730- # rhostar_r = rho_r * (pstar / p_r)**(1.0 / gamma)
731-
732- else :
733-
734- # 2-shock Riemann solver
735- A_r = 2.0 / ((gamma + 1.0 ) * rho_r )
736- B_r = p_r * (gamma - 1.0 ) / (gamma + 1.0 )
737-
738- A_l = 2.0 / ((gamma + 1.0 ) * rho_l )
739- B_l = p_l * (gamma - 1.0 ) / (gamma + 1.0 )
740-
741- # guess of the pressure
742- p_guess = max (0.0 , pstar )
743-
744- g_l = np .sqrt (A_l / (p_guess + B_l ))
745- g_r = np .sqrt (A_r / (p_guess + B_r ))
746-
747- pstar = (g_l * p_l + g_r * p_r -
748- (un_r - un_l )) / (g_l + g_r )
749-
750- ustar = 0.5 * (un_l + un_r ) + \
751- 0.5 * ((pstar - p_r ) * g_r - (pstar - p_l ) * g_l )
752-
753- # rhostar_l = rho_l * (pstar / p_l + (gamma - 1.0) / (gamma + 1.0)) / \
754- # ((gamma - 1.0) / (gamma + 1.0) * (pstar / p_l) + 1.0)
755- #
756- # rhostar_r = rho_r * (pstar / p_r + (gamma - 1.0) / (gamma + 1.0)) / \
757- # ((gamma - 1.0) / (gamma + 1.0) * (pstar / p_r) + 1.0)
758-
759- # estimate the nonlinear wave speeds
760-
761- if pstar <= p_l :
762- # rarefaction
763- S_l = un_l - c_l
764- else :
765- # shock
766- S_l = un_l - c_l * np .sqrt (1.0 + ((gamma + 1.0 ) / (2.0 * gamma )) *
767- (pstar / p_l - 1.0 ))
768-
769- if pstar <= p_r :
770- # rarefaction
771- S_r = un_r + c_r
772- else :
773- # shock
774- S_r = un_r + c_r * np .sqrt (1.0 + ((gamma + 1.0 ) / (2.0 / gamma )) *
775- (pstar / p_r - 1.0 ))
771+ S_l , S_r = estimate_wave_speed (rho_l , un_l , p_l , c_l ,
772+ rho_r , un_r , p_r , c_r , gamma )
776773
777774 # We could just take S_c = u_star as the estimate for the
778775 # contact speed, but we can actually do this more accurately
@@ -863,6 +860,166 @@ def riemann_hllc(idir, ng,
863860 return F
864861
865862
863+ @njit (cache = True )
864+ def riemann_hllc_lowspeed (idir , ng ,
865+ idens , ixmom , iymom , iener , irhoX , nspec ,
866+ lower_solid , upper_solid , # pylint: disable=unused-argument
867+ gamma , U_l , U_r ):
868+ r"""
869+ This is the HLLC Riemann solver based on Toro (2009) alternate formulation
870+ (Eqs. 10.43 and 10.44) and the low Mach number asymptotic fix of
871+ Minoshima & Miyoshi (2021). It is also based on the Quokka implementation.
872+
873+ Parameters
874+ ----------
875+ idir : int
876+ Are we predicting to the edges in the x-direction (1) or y-direction (2)?
877+ ng : int
878+ The number of ghost cells
879+ nspec : int
880+ The number of species
881+ idens, ixmom, iymom, iener, irhoX : int
882+ The indices of the density, x-momentum, y-momentum, internal energy density
883+ and species partial densities in the conserved state vector.
884+ lower_solid, upper_solid : int
885+ Are we at lower or upper solid boundaries?
886+ gamma : float
887+ Adiabatic index
888+ U_l, U_r : ndarray
889+ Conserved state on the left and right cell edges.
890+
891+ Returns
892+ -------
893+ out : ndarray
894+ Conserved flux
895+ """
896+
897+ # Only Cartesian2d is supported in HLLC
898+ coord_type = 0
899+
900+ qx , qy , nvar = U_l .shape
901+
902+ F = np .zeros ((qx , qy , nvar ))
903+
904+ smallc = 1.e-10
905+ smallp = 1.e-10
906+
907+ nx = qx - 2 * ng
908+ ny = qy - 2 * ng
909+ ilo = ng
910+ ihi = ng + nx
911+ jlo = ng
912+ jhi = ng + ny
913+
914+ for i in range (ilo - 1 , ihi + 1 ):
915+ for j in range (jlo - 1 , jhi + 1 ):
916+
917+ D_star = np .zeros (nvar )
918+
919+ # primitive variable states
920+ rho_l = U_l [i , j , idens ]
921+
922+ # un = normal velocity; ut = transverse velocity
923+ iun = - 1
924+ if idir == 1 :
925+ un_l = U_l [i , j , ixmom ] / rho_l
926+ ut_l = U_l [i , j , iymom ] / rho_l
927+ iun = ixmom
928+ else :
929+ un_l = U_l [i , j , iymom ] / rho_l
930+ ut_l = U_l [i , j , ixmom ] / rho_l
931+ iun = iymom
932+
933+ rhoe_l = U_l [i , j , iener ] - 0.5 * rho_l * (un_l ** 2 + ut_l ** 2 )
934+
935+ p_l = rhoe_l * (gamma - 1.0 )
936+ p_l = max (p_l , smallp )
937+
938+ rho_r = U_r [i , j , idens ]
939+
940+ if idir == 1 :
941+ un_r = U_r [i , j , ixmom ] / rho_r
942+ ut_r = U_r [i , j , iymom ] / rho_r
943+ else :
944+ un_r = U_r [i , j , iymom ] / rho_r
945+ ut_r = U_r [i , j , ixmom ] / rho_r
946+
947+ rhoe_r = U_r [i , j , iener ] - 0.5 * rho_r * (un_r ** 2 + ut_r ** 2 )
948+
949+ p_r = rhoe_r * (gamma - 1.0 )
950+ p_r = max (p_r , smallp )
951+
952+ # compute the sound speeds
953+ c_l = max (smallc , np .sqrt (gamma * p_l / rho_l ))
954+ c_r = max (smallc , np .sqrt (gamma * p_r / rho_r ))
955+
956+ S_l , S_r = estimate_wave_speed (rho_l , un_l , p_l , c_l ,
957+ rho_r , un_r , p_r , c_r , gamma )
958+
959+ # We could just take S_c = u_star as the estimate for the
960+ # contact speed, but we can actually do this more accurately
961+ # by using the Rankine-Hugonoit jump conditions across each
962+ # of the waves (see Toro 2009 Eq, 10.37, Batten et al. SIAM
963+ # J. Sci. and Stat. Comp., 18:1553 (1997)
964+
965+ S_c = (p_r - p_l +
966+ rho_l * un_l * (S_l - un_l ) -
967+ rho_r * un_r * (S_r - un_r )) / \
968+ (rho_l * (S_l - un_l ) - rho_r * (S_r - un_r ))
969+
970+ # D* is used to control the pressure addition to the star flux
971+ D_star [iun ] = 1.0
972+ D_star [iener ] = S_c
973+
974+ # compute the fluxes corresponding to the left and right states
975+
976+ U_state_l = U_l [i , j , :]
977+ F_l = consFlux (idir , coord_type , gamma ,
978+ idens , ixmom , iymom , iener , irhoX , nspec ,
979+ U_state_l )
980+
981+ U_state_r = U_r [i , j , :]
982+ F_r = consFlux (idir , coord_type , gamma ,
983+ idens , ixmom , iymom , iener , irhoX , nspec ,
984+ U_state_r )
985+
986+ # compute the star pressure with the low Mach correction
987+ # Minoshima & Miyoshi (2021) Eq. 23. This is actually averaging
988+ # the left and right pressures (see also Toro 2009 Eq. 10.42)
989+
990+ vmag_l = np .sqrt (un_l ** 2 + ut_l ** 2 )
991+ vmag_r = np .sqrt (un_r ** 2 + ut_r ** 2 )
992+
993+ cs_max = max (c_l , c_r )
994+ chi = min (1.0 , max (vmag_l , vmag_r ) / cs_max )
995+ phi = chi * (2.0 - chi )
996+ pstar_lr = 0.5 * (p_l + p_r ) + \
997+ 0.5 * phi * (rho_l * (S_l - un_l ) * (S_c - un_l ) +
998+ rho_r * (S_r - un_r ) * (S_c - un_r ))
999+
1000+ # figure out which region we are in and compute the state and
1001+ # the interface fluxes using the HLLC Riemann solver
1002+ if S_r <= 0.0 :
1003+ # R region
1004+ F [i , j , :] = F_r [:]
1005+
1006+ elif S_c <= 0.0 < S_r :
1007+ # R* region
1008+ F [i , j , :] = (S_c * (S_r * U_state_r - F_r ) + S_r * pstar_lr * D_star ) / (S_r - S_c )
1009+
1010+ elif S_l < 0.0 < S_c :
1011+ # L* region
1012+ F [i , j , :] = (S_c * (S_l * U_state_l - F_l ) + S_l * pstar_lr * D_star ) / (S_l - S_c )
1013+
1014+ else :
1015+ # L region
1016+ F [i , j , :] = F_l [:]
1017+
1018+ # we should deal with solid boundaries somehow here
1019+
1020+ return F
1021+
1022+
8661023def riemann_flux (idir , U_l , U_r , my_data , rp , ivars ,
8671024 lower_solid , upper_solid , tc , return_cons = False ):
8681025 """
@@ -907,7 +1064,9 @@ def riemann_flux(idir, U_l, U_r, my_data, rp, ivars,
9071064 riemann_method = rp .get_param ("compressible.riemann" )
9081065 gamma = rp .get_param ("eos.gamma" )
9091066
910- riemann_solvers = {"HLLC" : riemann_hllc , "CGF" : riemann_cgf }
1067+ riemann_solvers = {"HLLC" : riemann_hllc ,
1068+ "HLLC_lm" : riemann_hllc_lowspeed ,
1069+ "CGF" : riemann_cgf }
9111070
9121071 if riemann_method not in riemann_solvers :
9131072 msg .fail ("ERROR: Riemann solver undefined" )
@@ -923,7 +1082,7 @@ def riemann_flux(idir, U_l, U_r, my_data, rp, ivars,
9231082 gamma , U_l , U_r )
9241083
9251084 # If riemann_method is not HLLC, then construct flux using conserved states
926- if riemann_method != "HLLC" :
1085+ if riemann_method not in [ "HLLC" , "HLLC_lm" ] :
9271086 _f = consFlux (idir , myg .coord_type , gamma ,
9281087 ivars .idens , ivars .ixmom , ivars .iymom ,
9291088 ivars .iener , ivars .irhox , ivars .naux ,
@@ -935,7 +1094,7 @@ def riemann_flux(idir, U_l, U_r, my_data, rp, ivars,
9351094 F = ai .ArrayIndexer (d = _f , grid = myg )
9361095 tm_riem .end ()
9371096
938- if riemann_method != "HLLC" and return_cons :
1097+ if riemann_method not in [ "HLLC" , "HLLC_lm" ] and return_cons :
9391098 U = ai .ArrayIndexer (d = _u , grid = myg )
9401099 return F , U
9411100
0 commit comments