[docs]@njit(cache=True)defis_symmetric_pair(ng,nodal,sl,sr):r""" Are sl and sr symmetric about an axis parallel with the y-axis in the center of domain the x-direction? Parameters ---------- ng : int The number of ghost cells nodal: bool Is the data nodal? sl, sr : ndarray The two arrays to be compared Returns ------- out : int Are they symmetric? (1 = yes, 0 = no) """qx,qy=sl.shapenx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+nysym=1ifnotnodal:done=Falseforiinrange(nx/2):il=ilo+iir=ihi-iforjinrange(jlo,jhi):if(sl[il,j]!=sr[ir,j]):sym=0done=Truebreakifdone:breakelse:done=Falseforiinrange(nx/2):il=ilo+iir=ihi-i+1forjinrange(jlo,jhi):if(sl[il,j]!=sr[ir,j]):sym=0done=Truebreakifdone:breakreturnsym
[docs]@njit(cache=True)defis_symmetric(ng,nodal,s):r""" Is the left half of s the mirror image of the right half? Parameters ---------- ng : int The number of ghost cells nodal: bool Is the data nodal? s : ndarray The array to be compared Returns ------- out : int Is it symmetric? (1 = yes, 0 = no) """returnis_symmetric_pair(ng,nodal,s,s)
[docs]@njit(cache=True)defis_asymmetric_pair(ng,nodal,sl,sr):r""" Are sl and sr asymmetric about an axis parallel with the y-axis in the center of domain the x-direction? Parameters ---------- ng : int The number of ghost cells nodal: bool Is the data nodal? sl, sr : ndarray The two arrays to be compared Returns ------- out : int Are they asymmetric? (1 = yes, 0 = no) """qx,qy=sl.shapenx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+nyasym=1ifnotnodal:done=Falseforiinrange(nx/2):forjinrange(jlo,jhi):il=ilo+iir=ihi-iif(notsl[il,j]==-sr[ir,j]):asym=0done=Truebreakifdone:breakelse:done=Falseforiinrange(nx/2):forjinrange(jlo,jhi):il=ilo+iir=ihi-i+1# print *, il, ir, sl(il,j), -sr(ir,j)if(notsl[il,j]==-sr[ir,j]):asym=0done=Truebreakifdone:breakreturnasym
[docs]@njit(cache=True)defis_asymmetric(ng,nodal,s):""" Is the left half of s asymmetric to the right half? Parameters ---------- ng : int The number of ghost cells nodal: bool Is the data nodal? s : ndarray The array to be compared Returns ------- out : int Is it asymmetric? (1 = yes, 0 = no) """returnis_asymmetric_pair(ng,nodal,s,s)
[docs]@njit(cache=True)defmac_vels(ng,dx,dy,dt,u,v,ldelta_ux,ldelta_vx,ldelta_uy,ldelta_vy,gradp_x,gradp_y,source):r""" Calculate the MAC velocities in the x and y directions. Parameters ---------- ng : int The number of ghost cells dx, dy : float The cell spacings dt : float The timestep u, v : ndarray x-velocity and y-velocity ldelta_ux, ldelta_uy: ndarray Limited slopes of the x-velocity in the x and y directions ldelta_vx, ldelta_vy: ndarray Limited slopes of the y-velocity in the x and y directions gradp_x, gradp_y : ndarray Pressure gradients in the x and y directions source : ndarray Source terms Returns ------- out : ndarray, ndarray MAC velocities in the x and y directions """# assertions# print *, "checking ldelta_ux"# if (not is_asymmetric(qx, qy, ng, .false., ldelta_ux) == 1):# stop 'ldelta_ux not asymmetric'## print *, "checking ldelta_uy"# if (not is_symmetric(qx, qy, ng, .false., ldelta_uy) == 1):# stop 'ldelta_uy not symmetric'## print *, "checking ldelta_vx"# if (not is_symmetric(qx, qy, ng, .false., ldelta_vx) == 1):# stop 'ldelta_vx not symmetric'## print *, "checking ldelta_vy"# if (not is_symmetric(qx, qy, ng, .false., ldelta_vy) == 1):# stop 'ldelta_vy not symmetric'## print *, "checking gradp_x"# if (not is_asymmetric(qx, qy, ng, .false., gradp_x) == 1):# stop 'gradp_x not asymmetric'## get the full u and v left and right states (including transverse# terms) on both the x- and y-interfaces# pylint: disable-next=unused-variableu_xl,u_xr,u_yl,u_yr,v_xl,v_xr,v_yl,v_yr=get_interface_states(ng,dx,dy,dt,u,v,ldelta_ux,ldelta_vx,ldelta_uy,ldelta_vy,gradp_x,gradp_y,source)# print *, 'checking u_xl'# if (not is_asymmetric_pair(qx, qy, ng, .true., u_xl, u_xr) == 1):# stop 'u_xl/r not asymmetric'## Riemann problem -- this follows Burger's equation. We don't use# any input velocity for the upwinding. Also, we only care about# the normal states here (u on x and v on y)u_MAC=riemann_and_upwind(ng,u_xl,u_xr)v_MAC=riemann_and_upwind(ng,v_yl,v_yr)# print *, 'checking U_MAC'# if (not is_asymmetric(qx, qy, ng, .true., u_MAC) == 1):# stop 'u_MAC not asymmetric'#returnu_MAC,v_MAC
[docs]@njit(cache=True)defstates(ng,dx,dy,dt,u,v,ldelta_ux,ldelta_vx,ldelta_uy,ldelta_vy,gradp_x,gradp_y,source,u_MAC,v_MAC):r""" This is similar to ``mac_vels``, but it predicts the interface states of both u and v on both interfaces, using the MAC velocities to do the upwinding. Parameters ---------- ng : int The number of ghost cells dx, dy : float The cell spacings dt : float The timestep u, v : ndarray x-velocity and y-velocity ldelta_ux, ldelta_uy: ndarray Limited slopes of the x-velocity in the x and y directions ldelta_vx, ldelta_vy: ndarray Limited slopes of the y-velocity in the x and y directions source : ndarray Source terms gradp_x, gradp_y : ndarray Pressure gradients in the x and y directions u_MAC, v_MAC : ndarray MAC velocities in the x and y directions Returns ------- out : ndarray, ndarray, ndarray, ndarray x and y velocities predicted to the interfaces """# get the full u and v left and right states (including transverse# terms) on both the x- and y-interfacesu_xl,u_xr,u_yl,u_yr,v_xl,v_xr,v_yl,v_yr=get_interface_states(ng,dx,dy,dt,u,v,ldelta_ux,ldelta_vx,ldelta_uy,ldelta_vy,gradp_x,gradp_y,source)# upwind using the MAC velocity to determine which state exists on# the interfaceu_xint=upwind(ng,u_xl,u_xr,u_MAC)v_xint=upwind(ng,v_xl,v_xr,u_MAC)u_yint=upwind(ng,u_yl,u_yr,v_MAC)v_yint=upwind(ng,v_yl,v_yr,v_MAC)returnu_xint,v_xint,u_yint,v_yint
[docs]@njit(cache=True)defrho_states(ng,dx,dy,dt,rho,u_MAC,v_MAC,ldelta_rx,ldelta_ry):r""" This predicts rho to the interfaces. We use the MAC velocities to do the upwinding Parameters ---------- ng : int The number of ghost cells dx, dy : float The cell spacings rho : ndarray density u_MAC, v_MAC : ndarray MAC velocities in the x and y directions ldelta_rx, ldelta_ry: ndarray Limited slopes of the density in the x and y directions Returns ------- out : ndarray, ndarray rho predicted to the interfaces """qx,qy=rho.shaperho_xl=np.zeros((qx,qy))rho_xr=np.zeros((qx,qy))rho_yl=np.zeros((qx,qy))rho_yr=np.zeros((qx,qy))nx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+nydtdx=dt/dxdtdy=dt/dyforiinrange(ilo-2,ihi+2):forjinrange(jlo-2,jhi+2):# u on x-edgesrho_xl[i+1,j]=rho[i,j]+0.5* \
(1.0-dtdx*u_MAC[i+1,j])*ldelta_rx[i,j]rho_xr[i,j]=rho[i,j]-0.5* \
(1.0+dtdx*u_MAC[i,j])*ldelta_rx[i,j]# u on y-edgesrho_yl[i,j+1]=rho[i,j]+0.5* \
(1.0-dtdy*v_MAC[i,j+1])*ldelta_ry[i,j]rho_yr[i,j]=rho[i,j]-0.5* \
(1.0+dtdy*v_MAC[i,j])*ldelta_ry[i,j]# we upwind based on the MAC velocitiesrho_xint=upwind(ng,rho_xl,rho_xr,u_MAC)rho_yint=upwind(ng,rho_yl,rho_yr,v_MAC)# now add the transverse term and the non-advective part of the normal# divergenceforiinrange(ilo-2,ihi+2):forjinrange(jlo-2,jhi+2):u_x=(u_MAC[i+1,j]-u_MAC[i,j])/dxv_y=(v_MAC[i,j+1]-v_MAC[i,j])/dy# (rho v)_y is the transverse term for the x-interfaces# rho u_x is the non-advective piece for the x-interfacesrhov_y=(rho_yint[i,j+1]*v_MAC[i,j+1]-rho_yint[i,j]*v_MAC[i,j])/dyrho_xl[i+1,j]=rho_xl[i+1,j]- \
0.5*dt*(rhov_y+rho[i,j]*u_x)rho_xr[i,j]=rho_xr[i,j]-0.5*dt*(rhov_y+rho[i,j]*u_x)# (rho u)_x is the transverse term for the y-interfaces# rho v_y is the non-advective piece for the y-interfacesrhou_x=(rho_xint[i+1,j]*u_MAC[i+1,j]-rho_xint[i,j]*u_MAC[i,j])/dxrho_yl[i,j+1]=rho_yl[i,j+1]- \
0.5*dt*(rhou_x+rho[i,j]*v_y)rho_yr[i,j]=rho_yr[i,j]-0.5*dt*(rhou_x+rho[i,j]*v_y)# finally upwind the full statesrho_xint=upwind(ng,rho_xl,rho_xr,u_MAC)rho_yint=upwind(ng,rho_yl,rho_yr,v_MAC)returnrho_xint,rho_yint
[docs]@njit(cache=True)defget_interface_states(ng,dx,dy,dt,u,v,ldelta_ux,ldelta_vx,ldelta_uy,ldelta_vy,gradp_x,gradp_y,source):r""" Compute the unsplit predictions of u and v on both the x- and y-interfaces. This includes the transverse terms. Note that the ``gradp_x``, ``gradp_y`` should have any coefficients already included (e.g. :math:`\beta_0/\rho`) Parameters ---------- ng : int The number of ghost cells dx, dy : float The cell spacings dt : float The timestep u, v : ndarray x-velocity and y-velocity ldelta_ux, ldelta_uy: ndarray Limited slopes of the x-velocity in the x and y directions ldelta_vx, ldelta_vy: ndarray Limited slopes of the y-velocity in the x and y directions gradp_x, gradp_y : ndarray Pressure gradients in the x and y directions source : ndarray Source terms Returns ------- out : ndarray, ndarray, ndarray, ndarray, ndarray, ndarray, ndarray, ndarray unsplit predictions of u and v on both the x- and y-interfaces """qx,qy=u.shapeu_xl=np.zeros((qx,qy))u_xr=np.zeros((qx,qy))u_yl=np.zeros((qx,qy))u_yr=np.zeros((qx,qy))v_xl=np.zeros((qx,qy))v_xr=np.zeros((qx,qy))v_yl=np.zeros((qx,qy))v_yr=np.zeros((qx,qy))nx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+ny# first predict u and v to both interfaces, considering only the normal# part of the predictor. These are the 'hat' states.dtdx=dt/dxdtdy=dt/dyforiinrange(ilo-2,ihi+2):forjinrange(jlo-2,jhi+2):# u on x-edgesu_xl[i+1,j]=u[i,j]+0.5* \
(1.0-dtdx*u[i,j])*ldelta_ux[i,j]u_xr[i,j]=u[i,j]-0.5* \
(1.0+dtdx*u[i,j])*ldelta_ux[i,j]# v on x-edgesv_xl[i+1,j]=v[i,j]+0.5* \
(1.0-dtdx*u[i,j])*ldelta_vx[i,j]v_xr[i,j]=v[i,j]-0.5* \
(1.0+dtdx*u[i,j])*ldelta_vx[i,j]# u on y-edgesu_yl[i,j+1]=u[i,j]+0.5* \
(1.0-dtdy*v[i,j])*ldelta_uy[i,j]u_yr[i,j]=u[i,j]-0.5* \
(1.0+dtdy*v[i,j])*ldelta_uy[i,j]# v on y-edgesv_yl[i,j+1]=v[i,j]+0.5* \
(1.0-dtdy*v[i,j])*ldelta_vy[i,j]v_yr[i,j]=v[i,j]-0.5* \
(1.0+dtdy*v[i,j])*ldelta_vy[i,j]# print *, 'checking u_xl in states'# if (not is_asymmetric_pair(qx, qy, ng, .true., u_xl, u_xr) == 1):# stop 'u_xl/r not asymmetric'## now get the normal advective velocities on the interfaces by solving# the Riemann problem.uhat_adv=riemann(ng,u_xl,u_xr)vhat_adv=riemann(ng,v_yl,v_yr)# now that we have the advective velocities, upwind the left and right# states using the appropriate advective velocity.# on the x-interfaces, we upwind based on uhat_advu_xint=upwind(ng,u_xl,u_xr,uhat_adv)v_xint=upwind(ng,v_xl,v_xr,uhat_adv)# on the y-interfaces, we upwind based on vhat_advu_yint=upwind(ng,u_yl,u_yr,vhat_adv)v_yint=upwind(ng,v_yl,v_yr,vhat_adv)# at this point, these states are the `hat' states -- they only# considered the normal to the interface portion of the predictor.# add the transverse flux differences to the preliminary interface statesforiinrange(ilo-1,ihi+1):forjinrange(jlo-1,jhi+1):ubar=0.5*(uhat_adv[i,j]+uhat_adv[i+1,j])vbar=0.5*(vhat_adv[i,j]+vhat_adv[i,j+1])# v du/dy is the transerse term for the u states on x-interfacesvu_y=vbar*(u_yint[i,j+1]-u_yint[i,j])u_xl[i+1,j]=u_xl[i+1,j]-0.5* \
dtdy*vu_y-0.5*dt*gradp_x[i,j]u_xr[i,j]=u_xr[i,j]-0.5*dtdy* \
vu_y-0.5*dt*gradp_x[i,j]# v dv/dy is the transverse term for the v states on x-interfacesvv_y=vbar*(v_yint[i,j+1]-v_yint[i,j])v_xl[i+1,j]=v_xl[i+1,j]-0.5*dtdy*vv_y- \
0.5*dt*gradp_y[i,j]+0.5*dt*source[i,j]v_xr[i,j]=v_xr[i,j]-0.5*dtdy*vv_y-0.5* \
dt*gradp_y[i,j]+0.5*dt*source[i,j]# u dv/dx is the transverse term for the v states on y-interfacesuv_x=ubar*(v_xint[i+1,j]-v_xint[i,j])v_yl[i,j+1]=v_yl[i,j+1]-0.5*dtdx*uv_x- \
0.5*dt*gradp_y[i,j]+0.5*dt*source[i,j]v_yr[i,j]=v_yr[i,j]-0.5*dtdx*uv_x-0.5* \
dt*gradp_y[i,j]+0.5*dt*source[i,j]# u du/dx is the transverse term for the u states on y-interfacesuu_x=ubar*(u_xint[i+1,j]-u_xint[i,j])u_yl[i,j+1]=u_yl[i,j+1]-0.5* \
dtdx*uu_x-0.5*dt*gradp_x[i,j]u_yr[i,j]=u_yr[i,j]-0.5*dtdx* \
uu_x-0.5*dt*gradp_x[i,j]returnu_xl,u_xr,u_yl,u_yr,v_xl,v_xr,v_yl,v_yr
[docs]@njit(cache=True)defupwind(ng,q_l,q_r,s):r""" upwind the left and right states based on the specified input velocity, s. The resulting interface state is q_int Parameters ---------- ng : int The number of ghost cells q_l, q_r : ndarray left and right states s : ndarray velocity Returns ------- q_int : ndarray Upwinded state """qx,qy=s.shapeq_int=np.zeros_like(s)nx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+nyforiinrange(ilo-1,ihi+2):forjinrange(jlo-1,jhi+2):if(s[i,j]>0.0):q_int[i,j]=q_l[i,j]elif(s[i,j]==0.0):q_int[i,j]=0.5*(q_l[i,j]+q_r[i,j])else:q_int[i,j]=q_r[i,j]returnq_int
[docs]@njit(cache=True)defriemann(ng,q_l,q_r):""" Solve the Burger's Riemann problem given the input left and right states and return the state on the interface. This uses the expressions from Almgren, Bell, and Szymczak 1996. Parameters ---------- ng : int The number of ghost cells q_l, q_r : ndarray left and right states Returns ------- out : ndarray Interface state """qx,qy=q_l.shapenx=qx-2*ngny=qy-2*ngilo=ngihi=ng+nxjlo=ngjhi=ng+nys=np.zeros((qx,qy))foriinrange(ilo-1,ihi+2):forjinrange(jlo-1,jhi+2):ifq_l[i,j]>0.0andq_l[i,j]+q_r[i,j]>0.0:s[i,j]=q_l[i,j]elifq_l[i,j]<=0.0andq_r[i,j]>=0.0:# pylint: disable=chained-comparisons[i,j]=0.0else:s[i,j]=q_r[i,j]returns
[docs]@njit(cache=True)defriemann_and_upwind(ng,q_l,q_r):r""" First solve the Riemann problem given q_l and q_r to give the velocity on the interface and: use this velocity to upwind to determine the state (q_l, q_r, or a mix) on the interface). This differs from upwind, above, in that we don't take in a velocity to upwind with). Parameters ---------- ng : int The number of ghost cells q_l, q_r : ndarray left and right states Returns ------- out : ndarray Upwinded state """s=riemann(ng,q_l,q_r)returnupwind(ng,q_l,q_r,s)