[docs]@njit(cache=True)defriemann_cgf(idir,ng,idens,ixmom,iymom,iener,irhoX,nspec,lower_solid,upper_solid,gamma,U_l,U_r):r""" Solve riemann shock tube problem for a general equation of state using the method of Colella, Glaz, and Ferguson. See Almgren et al. 2010 (the CASTRO paper) for details. The Riemann problem for the Euler's equation produces 4 regions, separated by the three characteristics (u - cs, u, u + cs):: u - cs t u u + cs \ ^ . / \ *L | . *R / \ | . / \ | . / L \ | . / R \ | . / \ |. / \|./ ----------+----------------> x We care about the solution on the axis. The basic idea is to use estimates of the wave speeds to figure out which region we are in, and: use jump conditions to evaluate the state there. Only density jumps across the u characteristic. All primitive variables jump across the other two. Special attention is needed if a rarefaction spans the axis. Parameters ---------- idir : int Are we predicting to the edges in the x-direction (1) or y-direction (2)? ng : int The number of ghost cells nspec : int The number of species idens, ixmom, iymom, iener, irhoX : int The indices of the density, x-momentum, y-momentum, internal energy density and species partial densities in the conserved state vector. lower_solid, upper_solid : int Are we at lower or upper solid boundaries? gamma : float Adiabatic index U_l, U_r : ndarray Conserved state on the left and right cell edges. Returns ------- out : ndarray Conserved states. """# pylint: disable=unused-variableqx,qy,nvar=U_l.shapeU_out=np.zeros((qx,qy,nvar))smallc=1.e-10smallrho=1.e-10smallp=1.e-10nx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+nyforiinrange(ilo-1,ihi+1):forjinrange(jlo-1,jhi+1):# primitive variable statesrho_l=U_l[i,j,idens]# un = normal velocity; ut = transverse velocityifidir==1:un_l=U_l[i,j,ixmom]/rho_lut_l=U_l[i,j,iymom]/rho_lelse:un_l=U_l[i,j,iymom]/rho_lut_l=U_l[i,j,ixmom]/rho_lrhoe_l=U_l[i,j,iener]-0.5*rho_l*(un_l**2+ut_l**2)p_l=rhoe_l*(gamma-1.0)p_l=max(p_l,smallp)rho_r=U_r[i,j,idens]ifidir==1:un_r=U_r[i,j,ixmom]/rho_rut_r=U_r[i,j,iymom]/rho_relse:un_r=U_r[i,j,iymom]/rho_rut_r=U_r[i,j,ixmom]/rho_rrhoe_r=U_r[i,j,iener]-0.5*rho_r*(un_r**2+ut_r**2)p_r=rhoe_r*(gamma-1.0)p_r=max(p_r,smallp)# define the Lagrangian sound speedW_l=max(smallrho*smallc,np.sqrt(gamma*p_l*rho_l))W_r=max(smallrho*smallc,np.sqrt(gamma*p_r*rho_r))# and the regular sound speedsc_l=max(smallc,np.sqrt(gamma*p_l/rho_l))c_r=max(smallc,np.sqrt(gamma*p_r/rho_r))# define the star statespstar=(W_l*p_r+W_r*p_l+W_l*W_r*(un_l-un_r))/(W_l+W_r)pstar=max(pstar,smallp)ustar=(W_l*un_l+W_r*un_r+(p_l-p_r))/(W_l+W_r)# now compute the remaining state to the left and right# of the contact (in the star region)rhostar_l=rho_l+(pstar-p_l)/c_l**2rhostar_r=rho_r+(pstar-p_r)/c_r**2rhoestar_l=rhoe_l+ \
(pstar-p_l)*(rhoe_l/rho_l+p_l/rho_l)/c_l**2rhoestar_r=rhoe_r+ \
(pstar-p_r)*(rhoe_r/rho_r+p_r/rho_r)/c_r**2cstar_l=max(smallc,np.sqrt(gamma*pstar/rhostar_l))cstar_r=max(smallc,np.sqrt(gamma*pstar/rhostar_r))# figure out which state we are in, based on the location of# the wavesifustar>0.0:# contact is moving to the right, we need to understand# the L and *L states# Note: transverse velocity only jumps across contactut_state=ut_l# define eigenvalueslambda_l=un_l-c_llambdastar_l=ustar-cstar_lifpstar>p_l:# the wave is a shock -- find the shock speedsigma=(lambda_l+lambdastar_l)/2.0ifsigma>0.0:# shock is moving to the right -- solution is L staterho_state=rho_lun_state=un_lp_state=p_lrhoe_state=rhoe_lelse:# solution is *L staterho_state=rhostar_lun_state=ustarp_state=pstarrhoe_state=rhoestar_lelse:# the wave is a rarefactioniflambda_l<0.0andlambdastar_l<0.0:# rarefaction fan is moving to the left -- solution is# *L staterho_state=rhostar_lun_state=ustarp_state=pstarrhoe_state=rhoestar_leliflambda_l>0.0andlambdastar_l>0.0:# rarefaction fan is moving to the right -- solution is# L staterho_state=rho_lun_state=un_lp_state=p_lrhoe_state=rhoe_lelse:# rarefaction spans x/t = 0 -- interpolatealpha=lambda_l/(lambda_l-lambdastar_l)rho_state=alpha*rhostar_l+(1.0-alpha)*rho_lun_state=alpha*ustar+(1.0-alpha)*un_lp_state=alpha*pstar+(1.0-alpha)*p_lrhoe_state=alpha*rhoestar_l+ \
(1.0-alpha)*rhoe_lelifustar<0:# contact moving left, we need to understand the R and *R# states# Note: transverse velocity only jumps across contactut_state=ut_r# define eigenvalueslambda_r=un_r+c_rlambdastar_r=ustar+cstar_rifpstar>p_r:# the wave if a shock -- find the shock speedsigma=(lambda_r+lambdastar_r)/2.0ifsigma>0.0:# shock is moving to the right -- solution is *R staterho_state=rhostar_run_state=ustarp_state=pstarrhoe_state=rhoestar_relse:# solution is R staterho_state=rho_run_state=un_rp_state=p_rrhoe_state=rhoe_relse:# the wave is a rarefactioniflambda_r<0.0andlambdastar_r<0.0:# rarefaction fan is moving to the left -- solution is# R staterho_state=rho_run_state=un_rp_state=p_rrhoe_state=rhoe_reliflambda_r>0.0andlambdastar_r>0.0:# rarefaction fan is moving to the right -- solution is# *R staterho_state=rhostar_run_state=ustarp_state=pstarrhoe_state=rhoestar_relse:# rarefaction spans x/t = 0 -- interpolatealpha=lambda_r/(lambda_r-lambdastar_r)rho_state=alpha*rhostar_r+(1.0-alpha)*rho_run_state=alpha*ustar+(1.0-alpha)*un_rp_state=alpha*pstar+(1.0-alpha)*p_rrhoe_state=alpha*rhoestar_r+ \
(1.0-alpha)*rhoe_relse:# ustar == 0rho_state=0.5*(rhostar_l+rhostar_r)un_state=ustarut_state=0.5*(ut_l+ut_r)p_state=pstarrhoe_state=0.5*(rhoestar_l+rhoestar_r)# species nowifnspec>0:ifustar>0.0:xn=U_l[i,j,irhoX:irhoX+nspec]/U_l[i,j,idens]elifustar<0.0:xn=U_r[i,j,irhoX:irhoX+nspec]/U_r[i,j,idens]else:xn=0.5*(U_l[i,j,irhoX:irhoX+nspec]/U_l[i,j,idens]+U_r[i,j,irhoX:irhoX+nspec]/U_r[i,j,idens])# are we on a solid boundary?ifidir==1:ifi==iloandlower_solid==1:un_state=0.0ifi==ihi+1andupper_solid==1:un_state=0.0elifidir==2:ifj==jloandlower_solid==1:un_state=0.0ifj==jhi+1andupper_solid==1:un_state=0.0# update conserved stateU_out[i,j,idens]=rho_stateifidir==1:U_out[i,j,ixmom]=rho_state*un_stateU_out[i,j,iymom]=rho_state*ut_stateelse:U_out[i,j,ixmom]=rho_state*ut_stateU_out[i,j,iymom]=rho_state*un_stateU_out[i,j,iener]=rhoe_state+ \
0.5*rho_state*(un_state**2+ut_state**2)ifnspec>0:U_out[i,j,irhoX:irhoX+nspec]=xn*rho_statereturnU_out
[docs]@njit(cache=True)defriemann_prim(idir,ng,irho,iu,iv,ip,iX,nspec,lower_solid,upper_solid,gamma,q_l,q_r):r""" this is like riemann_cgf, except that it works on a primitive variable input state and returns the primitive variable interface state Solve riemann shock tube problem for a general equation of state using the method of Colella, Glaz, and Ferguson. See Almgren et al. 2010 (the CASTRO paper) for details. The Riemann problem for the Euler's equation produces 4 regions, separated by the three characteristics :math:`(u - cs, u, u + cs)`:: u - cs t u u + cs \ ^ . / \ *L | . *R / \ | . / \ | . / L \ | . / R \ | . / \ |. / \|./ ----------+----------------> x We care about the solution on the axis. The basic idea is to use estimates of the wave speeds to figure out which region we are in, and: use jump conditions to evaluate the state there. Only density jumps across the :math:`u` characteristic. All primitive variables jump across the other two. Special attention is needed if a rarefaction spans the axis. Parameters ---------- idir : int Are we predicting to the edges in the x-direction (1) or y-direction (2)? ng : int The number of ghost cells nspec : int The number of species irho, iu, iv, ip, iX : int The indices of the density, x-velocity, y-velocity, pressure and species fractions in the state vector. lower_solid, upper_solid : int Are we at lower or upper solid boundaries? gamma : float Adiabatic index q_l, q_r : ndarray Primitive state on the left and right cell edges. Returns ------- out : ndarray Primitive flux """qx,qy,nvar=q_l.shapeq_int=np.zeros((qx,qy,nvar))smallc=1.e-10smallrho=1.e-10smallp=1.e-10nx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+nyforiinrange(ilo-1,ihi+1):forjinrange(jlo-1,jhi+1):# primitive variable statesrho_l=q_l[i,j,irho]# un = normal velocity; ut = transverse velocityifidir==1:un_l=q_l[i,j,iu]ut_l=q_l[i,j,iv]else:un_l=q_l[i,j,iv]ut_l=q_l[i,j,iu]p_l=q_l[i,j,ip]p_l=max(p_l,smallp)rho_r=q_r[i,j,irho]ifidir==1:un_r=q_r[i,j,iu]ut_r=q_r[i,j,iv]else:un_r=q_r[i,j,iv]ut_r=q_r[i,j,iu]p_r=q_r[i,j,ip]p_r=max(p_r,smallp)# define the Lagrangian sound speedrho_l=max(smallrho,rho_l)rho_r=max(smallrho,rho_r)W_l=max(smallrho*smallc,np.sqrt(gamma*p_l*rho_l))W_r=max(smallrho*smallc,np.sqrt(gamma*p_r*rho_r))# and the regular sound speedsc_l=max(smallc,np.sqrt(gamma*p_l/rho_l))c_r=max(smallc,np.sqrt(gamma*p_r/rho_r))# define the star statespstar=(W_l*p_r+W_r*p_l+W_l*W_r*(un_l-un_r))/(W_l+W_r)pstar=max(pstar,smallp)ustar=(W_l*un_l+W_r*un_r+(p_l-p_r))/(W_l+W_r)# now compute the remaining state to the left and right# of the contact (in the star region)rhostar_l=rho_l+(pstar-p_l)/c_l**2rhostar_r=rho_r+(pstar-p_r)/c_r**2cstar_l=max(smallc,np.sqrt(gamma*pstar/rhostar_l))cstar_r=max(smallc,np.sqrt(gamma*pstar/rhostar_r))# figure out which state we are in, based on the location of# the wavesifustar>0.0:# contact is moving to the right, we need to understand# the L and *L states# Note: transverse velocity only jumps across contactut_state=ut_l# define eigenvalueslambda_l=un_l-c_llambdastar_l=ustar-cstar_lifpstar>p_l:# the wave is a shock -- find the shock speedsigma=(lambda_l+lambdastar_l)/2.0ifsigma>0.0:# shock is moving to the right -- solution is L staterho_state=rho_lun_state=un_lp_state=p_lelse:# solution is *L staterho_state=rhostar_lun_state=ustarp_state=pstarelse:# the wave is a rarefactioniflambda_l<0.0andlambdastar_l<0.0:# rarefaction fan is moving to the left -- solution is# *L staterho_state=rhostar_lun_state=ustarp_state=pstareliflambda_l>0.0andlambdastar_l>0.0:# rarefaction fan is moving to the right -- solution is# L staterho_state=rho_lun_state=un_lp_state=p_lelse:# rarefaction spans x/t = 0 -- interpolatealpha=lambda_l/(lambda_l-lambdastar_l)rho_state=alpha*rhostar_l+(1.0-alpha)*rho_lun_state=alpha*ustar+(1.0-alpha)*un_lp_state=alpha*pstar+(1.0-alpha)*p_lelifustar<0:# contact moving left, we need to understand the R and *R# states# Note: transverse velocity only jumps across contactut_state=ut_r# define eigenvalueslambda_r=un_r+c_rlambdastar_r=ustar+cstar_rifpstar>p_r:# the wave if a shock -- find the shock speedsigma=(lambda_r+lambdastar_r)/2.0ifsigma>0.0:# shock is moving to the right -- solution is *R staterho_state=rhostar_run_state=ustarp_state=pstarelse:# solution is R staterho_state=rho_run_state=un_rp_state=p_relse:# the wave is a rarefactioniflambda_r<0.0andlambdastar_r<0.0:# rarefaction fan is moving to the left -- solution is# R staterho_state=rho_run_state=un_rp_state=p_reliflambda_r>0.0andlambdastar_r>0.0:# rarefaction fan is moving to the right -- solution is# *R staterho_state=rhostar_run_state=ustarp_state=pstarelse:# rarefaction spans x/t = 0 -- interpolatealpha=lambda_r/(lambda_r-lambdastar_r)rho_state=alpha*rhostar_r+(1.0-alpha)*rho_run_state=alpha*ustar+(1.0-alpha)*un_rp_state=alpha*pstar+(1.0-alpha)*p_relse:# ustar == 0rho_state=0.5*(rhostar_l+rhostar_r)un_state=ustarut_state=0.5*(ut_l+ut_r)p_state=pstar# species nowifnspec>0:ifustar>0.0:xn=q_l[i,j,iX:iX+nspec]elifustar<0.0:xn=q_r[i,j,iX:iX+nspec]else:xn=0.5*(q_l[i,j,iX:iX+nspec]+q_r[i,j,iX:iX+nspec])# are we on a solid boundary?ifidir==1:ifi==iloandlower_solid==1:un_state=0.0ifi==ihi+1andupper_solid==1:un_state=0.0elifidir==2:ifj==jloandlower_solid==1:un_state=0.0ifj==jhi+1andupper_solid==1:un_state=0.0q_int[i,j,irho]=rho_stateifidir==1:q_int[i,j,iu]=un_stateq_int[i,j,iv]=ut_stateelse:q_int[i,j,iu]=ut_stateq_int[i,j,iv]=un_stateq_int[i,j,ip]=p_stateifnspec>0:q_int[i,j,iX:iX+nspec]=xnreturnq_int
[docs]@njit(cache=True)defestimate_wave_speed(rho_l,u_l,p_l,c_l,rho_r,u_r,p_r,c_r,gamma):# Estimate the star quantities -- use one of three methods to# do this -- the primitive variable Riemann solver, the two# shock approximation, or the two rarefaction approximation.# Pick the method based on the pressure states at the# interface.p_max=max(p_l,p_r)p_min=min(p_l,p_r)Q=p_max/p_minrho_avg=0.5*(rho_l+rho_r)c_avg=0.5*(c_l+c_r)# primitive variable Riemann solver (Toro, 9.3)factor=rho_avg*c_avgpstar=0.5*(p_l+p_r)+0.5*(u_l-u_r)*factorustar=0.5*(u_l+u_r)+0.5*(p_l-p_r)/factorifQ>2and(pstar<p_minorpstar>p_max):# use a more accurate Riemann solver for the estimate hereifpstar<p_min:# 2-rarefaction Riemann solverz=(gamma-1.0)/(2.0*gamma)p_lr=(p_l/p_r)**zustar=(p_lr*u_l/c_l+u_r/c_r+2.0*(p_lr-1.0)/(gamma-1.0))/ \
(p_lr/c_l+1.0/c_r)pstar=0.5*(p_l*(1.0+(gamma-1.0)*(u_l-ustar)/(2.0*c_l))**(1.0/z)+p_r*(1.0+(gamma-1.0)*(ustar-u_r)/(2.0*c_r))**(1.0/z))else:# 2-shock Riemann solverA_r=2.0/((gamma+1.0)*rho_r)B_r=p_r*(gamma-1.0)/(gamma+1.0)A_l=2.0/((gamma+1.0)*rho_l)B_l=p_l*(gamma-1.0)/(gamma+1.0)# guess of the pressurep_guess=max(0.0,pstar)g_l=np.sqrt(A_l/(p_guess+B_l))g_r=np.sqrt(A_r/(p_guess+B_r))pstar=(g_l*p_l+g_r*p_r-(u_r-u_l))/(g_l+g_r)ustar=0.5*(u_l+u_r)+ \
0.5*((pstar-p_r)*g_r-(pstar-p_l)*g_l)# estimate the nonlinear wave speedsifpstar<=p_l:# rarefactionS_l=u_l-c_lelse:# shockS_l=u_l-c_l*np.sqrt(1.0+((gamma+1.0)/(2.0*gamma))*(pstar/p_l-1.0))ifpstar<=p_r:# rarefactionS_r=u_r+c_relse:# shockS_r=u_r+c_r*np.sqrt(1.0+((gamma+1.0)/(2.0/gamma))*(pstar/p_r-1.0))returnS_l,S_r
[docs]@njit(cache=True)defriemann_hllc(idir,ng,idens,ixmom,iymom,iener,irhoX,nspec,lower_solid,upper_solid,# pylint: disable=unused-argumentgamma,U_l,U_r):r""" This is the HLLC Riemann solver. The implementation follows directly out of Toro's book. Note: this does not handle the transonic rarefaction. Parameters ---------- idir : int Are we predicting to the edges in the x-direction (1) or y-direction (2)? ng : int The number of ghost cells nspec : int The number of species idens, ixmom, iymom, iener, irhoX : int The indices of the density, x-momentum, y-momentum, internal energy density and species partial densities in the conserved state vector. lower_solid, upper_solid : int Are we at lower or upper solid boundaries? gamma : float Adiabatic index U_l, U_r : ndarray Conserved state on the left and right cell edges. Returns ------- out : ndarray Conserved flux """# Only Cartesian2d is supported in HLLCcoord_type=0qx,qy,nvar=U_l.shapeF=np.zeros((qx,qy,nvar))smallc=1.e-10smallp=1.e-10U_state=np.zeros(nvar)nx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+nyforiinrange(ilo-1,ihi+1):forjinrange(jlo-1,jhi+1):# primitive variable statesrho_l=U_l[i,j,idens]# un = normal velocity; ut = transverse velocityifidir==1:un_l=U_l[i,j,ixmom]/rho_lut_l=U_l[i,j,iymom]/rho_lelse:un_l=U_l[i,j,iymom]/rho_lut_l=U_l[i,j,ixmom]/rho_lrhoe_l=U_l[i,j,iener]-0.5*rho_l*(un_l**2+ut_l**2)p_l=rhoe_l*(gamma-1.0)p_l=max(p_l,smallp)rho_r=U_r[i,j,idens]ifidir==1:un_r=U_r[i,j,ixmom]/rho_rut_r=U_r[i,j,iymom]/rho_relse:un_r=U_r[i,j,iymom]/rho_rut_r=U_r[i,j,ixmom]/rho_rrhoe_r=U_r[i,j,iener]-0.5*rho_r*(un_r**2+ut_r**2)p_r=rhoe_r*(gamma-1.0)p_r=max(p_r,smallp)# compute the sound speedsc_l=max(smallc,np.sqrt(gamma*p_l/rho_l))c_r=max(smallc,np.sqrt(gamma*p_r/rho_r))S_l,S_r=estimate_wave_speed(rho_l,un_l,p_l,c_l,rho_r,un_r,p_r,c_r,gamma)# We could just take S_c = u_star as the estimate for the# contact speed, but we can actually do this more accurately# by using the Rankine-Hugonoit jump conditions across each# of the waves (see Toro 10.58, Batten et al. SIAM# J. Sci. and Stat. Comp., 18:1553 (1997)S_c=(p_r-p_l+rho_l*un_l*(S_l-un_l)-rho_r*un_r*(S_r-un_r))/ \
(rho_l*(S_l-un_l)-rho_r*(S_r-un_r))# figure out which region we are in and compute the state and# the interface fluxes using the HLLC Riemann solverifS_r<=0.0:# R regionU_state[:]=U_r[i,j,:]F[i,j,:]=consFlux(idir,coord_type,gamma,idens,ixmom,iymom,iener,irhoX,nspec,U_state)elifS_c<=0.0<S_r:# R* regionHLLCfactor=rho_r*(S_r-un_r)/(S_r-S_c)U_state[idens]=HLLCfactorifidir==1:U_state[ixmom]=HLLCfactor*S_cU_state[iymom]=HLLCfactor*ut_relse:U_state[ixmom]=HLLCfactor*ut_rU_state[iymom]=HLLCfactor*S_cU_state[iener]=HLLCfactor*(U_r[i,j,iener]/rho_r+(S_c-un_r)*(S_c+p_r/(rho_r*(S_r-un_r))))# speciesifnspec>0:U_state[irhoX:irhoX+nspec]=HLLCfactor* \
U_r[i,j,irhoX:irhoX+nspec]/rho_r# find the flux on the right interfaceF[i,j,:]=consFlux(idir,coord_type,gamma,idens,ixmom,iymom,iener,irhoX,nspec,U_r[i,j,:])# correct the fluxF[i,j,:]=F[i,j,:]+S_r*(U_state[:]-U_r[i,j,:])elifS_l<0.0<S_c:# L* regionHLLCfactor=rho_l*(S_l-un_l)/(S_l-S_c)U_state[idens]=HLLCfactorifidir==1:U_state[ixmom]=HLLCfactor*S_cU_state[iymom]=HLLCfactor*ut_lelse:U_state[ixmom]=HLLCfactor*ut_lU_state[iymom]=HLLCfactor*S_cU_state[iener]=HLLCfactor*(U_l[i,j,iener]/rho_l+(S_c-un_l)*(S_c+p_l/(rho_l*(S_l-un_l))))# speciesifnspec>0:U_state[irhoX:irhoX+nspec]=HLLCfactor* \
U_l[i,j,irhoX:irhoX+nspec]/rho_l# find the flux on the left interfaceF[i,j,:]=consFlux(idir,coord_type,gamma,idens,ixmom,iymom,iener,irhoX,nspec,U_l[i,j,:])# correct the fluxF[i,j,:]=F[i,j,:]+S_l*(U_state[:]-U_l[i,j,:])else:# L regionU_state[:]=U_l[i,j,:]F[i,j,:]=consFlux(idir,coord_type,gamma,idens,ixmom,iymom,iener,irhoX,nspec,U_state)# we should deal with solid boundaries somehow herereturnF
[docs]@njit(cache=True)defriemann_hllc_lowspeed(idir,ng,idens,ixmom,iymom,iener,irhoX,nspec,lower_solid,upper_solid,# pylint: disable=unused-argumentgamma,U_l,U_r):r""" This is the HLLC Riemann solver based on Toro (2009) alternate formulation (Eqs. 10.43 and 10.44) and the low Mach number asymptotic fix of Minoshima & Miyoshi (2021). It is also based on the Quokka implementation. Parameters ---------- idir : int Are we predicting to the edges in the x-direction (1) or y-direction (2)? ng : int The number of ghost cells nspec : int The number of species idens, ixmom, iymom, iener, irhoX : int The indices of the density, x-momentum, y-momentum, internal energy density and species partial densities in the conserved state vector. lower_solid, upper_solid : int Are we at lower or upper solid boundaries? gamma : float Adiabatic index U_l, U_r : ndarray Conserved state on the left and right cell edges. Returns ------- out : ndarray Conserved flux """# Only Cartesian2d is supported in HLLCcoord_type=0qx,qy,nvar=U_l.shapeF=np.zeros((qx,qy,nvar))smallc=1.e-10smallp=1.e-10nx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+nyforiinrange(ilo-1,ihi+1):forjinrange(jlo-1,jhi+1):D_star=np.zeros(nvar)# primitive variable statesrho_l=U_l[i,j,idens]# un = normal velocity; ut = transverse velocityiun=-1ifidir==1:un_l=U_l[i,j,ixmom]/rho_lut_l=U_l[i,j,iymom]/rho_liun=ixmomelse:un_l=U_l[i,j,iymom]/rho_lut_l=U_l[i,j,ixmom]/rho_liun=iymomrhoe_l=U_l[i,j,iener]-0.5*rho_l*(un_l**2+ut_l**2)p_l=rhoe_l*(gamma-1.0)p_l=max(p_l,smallp)rho_r=U_r[i,j,idens]ifidir==1:un_r=U_r[i,j,ixmom]/rho_rut_r=U_r[i,j,iymom]/rho_relse:un_r=U_r[i,j,iymom]/rho_rut_r=U_r[i,j,ixmom]/rho_rrhoe_r=U_r[i,j,iener]-0.5*rho_r*(un_r**2+ut_r**2)p_r=rhoe_r*(gamma-1.0)p_r=max(p_r,smallp)# compute the sound speedsc_l=max(smallc,np.sqrt(gamma*p_l/rho_l))c_r=max(smallc,np.sqrt(gamma*p_r/rho_r))S_l,S_r=estimate_wave_speed(rho_l,un_l,p_l,c_l,rho_r,un_r,p_r,c_r,gamma)# We could just take S_c = u_star as the estimate for the# contact speed, but we can actually do this more accurately# by using the Rankine-Hugonoit jump conditions across each# of the waves (see Toro 2009 Eq, 10.37, Batten et al. SIAM# J. Sci. and Stat. Comp., 18:1553 (1997)S_c=(p_r-p_l+rho_l*un_l*(S_l-un_l)-rho_r*un_r*(S_r-un_r))/ \
(rho_l*(S_l-un_l)-rho_r*(S_r-un_r))# D* is used to control the pressure addition to the star fluxD_star[iun]=1.0D_star[iener]=S_c# compute the fluxes corresponding to the left and right statesU_state_l=U_l[i,j,:]F_l=consFlux(idir,coord_type,gamma,idens,ixmom,iymom,iener,irhoX,nspec,U_state_l)U_state_r=U_r[i,j,:]F_r=consFlux(idir,coord_type,gamma,idens,ixmom,iymom,iener,irhoX,nspec,U_state_r)# compute the star pressure with the low Mach correction# Minoshima & Miyoshi (2021) Eq. 23. This is actually averaging# the left and right pressures (see also Toro 2009 Eq. 10.42)vmag_l=np.sqrt(un_l**2+ut_l**2)vmag_r=np.sqrt(un_r**2+ut_r**2)cs_max=max(c_l,c_r)chi=min(1.0,max(vmag_l,vmag_r)/cs_max)phi=chi*(2.0-chi)pstar_lr=0.5*(p_l+p_r)+ \
0.5*phi*(rho_l*(S_l-un_l)*(S_c-un_l)+rho_r*(S_r-un_r)*(S_c-un_r))# figure out which region we are in and compute the state and# the interface fluxes using the HLLC Riemann solverifS_r<=0.0:# R regionF[i,j,:]=F_r[:]elifS_c<=0.0<S_r:# R* regionF[i,j,:]=(S_c*(S_r*U_state_r-F_r)+S_r*pstar_lr*D_star)/(S_r-S_c)elifS_l<0.0<S_c:# L* regionF[i,j,:]=(S_c*(S_l*U_state_l-F_l)+S_l*pstar_lr*D_star)/(S_l-S_c)else:# L regionF[i,j,:]=F_l[:]# we should deal with solid boundaries somehow herereturnF
[docs]defriemann_flux(idir,U_l,U_r,my_data,rp,ivars,lower_solid,upper_solid,tc,return_cons=False):""" This is the general interface that constructs the unsplit fluxes through the idir (1 for x, 2 for y) interfaces using the left and right conserved states by using the riemann solver. Parameters ---------- U_l, U_r: ndarray, ndarray Conserved states in the left and right interface my_data : CellCenterData2d object The data object containing the grid and advective scalar that we are advecting. rp : RuntimeParameters object The runtime parameters for the simulation ivars : Variables object The Variables object that tells us which indices refer to which variables lower_solid, upper_solid : int Are we at lower or upper solid boundaries? tc : TimerCollection object The timers we are using to profile return_cons: Boolean If we don't use HLLC Riemann solver, do we also return conserved states? Returns ------- F : ndarray Fluxes in x or y direction Optionally: U: ndarray Conserved states in x or y direction """tm_riem=tc.timer("riemann")tm_riem.begin()myg=my_data.gridriemann_method=rp.get_param("compressible.riemann")gamma=rp.get_param("eos.gamma")riemann_solvers={"HLLC":riemann_hllc,"HLLC_lm":riemann_hllc_lowspeed,"CGF":riemann_cgf}ifriemann_methodnotinriemann_solvers:msg.fail("ERROR: Riemann solver undefined")riemannFunc=riemann_solvers[riemann_method]# This returns Flux in idir direction if we use HLLC# and conserved states otherwise_u=riemannFunc(idir,myg.ng,ivars.idens,ivars.ixmom,ivars.iymom,ivars.iener,ivars.irhox,ivars.naux,lower_solid,upper_solid,gamma,U_l,U_r)# If riemann_method is not HLLC, then construct flux using conserved statesifriemann_methodnotin["HLLC","HLLC_lm"]:_f=consFlux(idir,myg.coord_type,gamma,ivars.idens,ivars.ixmom,ivars.iymom,ivars.iener,ivars.irhox,ivars.naux,_u)else:# If riemann_method is HLLC, then its already flux_f=_uF=ai.ArrayIndexer(d=_f,grid=myg)tm_riem.end()ifriemann_methodnotin["HLLC","HLLC_lm"]andreturn_cons:U=ai.ArrayIndexer(d=_u,grid=myg)returnF,UreturnF
[docs]@njit(cache=True)defconsFlux(idir,coord_type,gamma,idens,ixmom,iymom,iener,irhoX,nspec,U_state):r""" Calculate the conservative flux. Parameters ---------- idir : int Are we predicting to the edges in the x-direction (1) or y-direction (2)? gamma : float Adiabatic index idens, ixmom, iymom, iener, irhoX : int The indices of the density, x-momentum, y-momentum, internal energy density and species partial densities in the conserved state vector. nspec : int The number of species U_state : ndarray Conserved state vector. Returns ------- out : ndarray Conserved flux """F=np.zeros_like(U_state)ifU_state.ndim==1:u=0.0v=0.0ifU_state[idens]!=0.0:u=U_state[ixmom]/U_state[idens]v=U_state[iymom]/U_state[idens]else:u=np.zeros_like(U_state[...,ixmom])v=np.zeros_like(U_state[...,iymom])foriinrange(U_state.shape[0]):forjinrange(U_state.shape[1]):ifU_state[i,j,idens]!=0.0:u[i,j]=U_state[i,j,ixmom]/U_state[i,j,idens]v[i,j]=U_state[i,j,iymom]/U_state[i,j,idens]p=(U_state[...,iener]-0.5*U_state[...,idens]*(u*u+v*v))*(gamma-1.0)ifidir==1:F[...,idens]=U_state[...,idens]*uF[...,ixmom]=U_state[...,ixmom]*u# if Cartesian2d, then add pressure to xmom fluxifcoord_type==0:F[...,ixmom]+=pF[...,iymom]=U_state[...,iymom]*uF[...,iener]=(U_state[...,iener]+p)*uifnspec>0:F[...,irhoX:irhoX+nspec]=U_state[...,irhoX:irhoX+nspec]*uelse:F[...,idens]=U_state[...,idens]*vF[...,ixmom]=U_state[...,ixmom]*vF[...,iymom]=U_state[...,iymom]*v# if Cartesian2d, then add pressure to ymom fluxifcoord_type==0:F[...,iymom]+=pF[...,iener]=(U_state[...,iener]+p)*vifnspec>0:F[...,irhoX:irhoX+nspec]=U_state[...,irhoX:irhoX+nspec]*vreturnF