def compute_eigenvector(U, U0, direction): rho = U[:, 0] u = U[:, 1] / rho v = U[:, 2] / rho E = U[:, 3] / rho P = P_from_Ev(E, rho, u, v) nunk = U.shape[1] nelem = U.shape[0] a = np.sqrt(GAM * P / rho) q = 1 / 2 * (u**2 + v**2) # Dynamic pressure h = a**2 / (GAM - 1) + q # Enthalpy rho0 = U0[:, 0] u0 = U0[:, 1] / rho0 v0 = U0[:, 2] / rho0 E0 = U0[:, 3] / rho0 P0 = P_from_Ev(E0, rho0, u0, v0) nunk = U0.shape[1] nelem = U0.shape[0] a0 = np.sqrt(GAM * P0 / rho0) q0 = 1 / 2 * (u0**2 + v0**2) # Dynamic pressure h0 = a0**2 / (GAM - 1) + q0 # Enthalpy Rjlist = [] Ljlist = [] if direction == 'dx': Rlhs0, Llhs0 = eigenvector_x(u0[0], v0[0], a0[0], q0[0], h0[0], nunk) for idx in range(nelem): Rj, Lj = eigenvector_x(u[idx], v[idx], a[idx], q[idx], h[idx], nunk) Rjlist.append(Rj) Ljlist.append(Lj) Rlhs0pre = None Llhs0pre = None elif direction == 'dy': # For the y-direction, the bottom boundary can either be pre or post-shock Rlhs0, Llhs0 = eigenvector_y(u0[0], v0[0], a0[0], q0[0], h0[0], nunk) Rlhs0pre, Llhs0pre = eigenvector_y(u0[-1], v0[-1], a0[-1], q0[-1], h0[-1], nunk) for idx in range(nelem): Rj, Lj = eigenvector_y(u[idx], v[idx], a[idx], q[idx], h[idx], nunk) Rjlist.append(Rj) Ljlist.append(Lj) Rj = Rjlist Lj = Ljlist return Rj, Lj, Rlhs0, Llhs0, Rlhs0pre, Llhs0pre
def flux_pressure(UL, UR, ah, MaL, MaR): # rhoL = UL[:,0] # rhoR = UR[:,0] # # vL = UL[:,1]/rhoL # vR = UR[:,1]/rhoR # # EL = UL[:,2]/rhoL # ER = UR[:,2]/rhoR # # PL = P_from_Ev(EL,rhoL,vL) # PR = P_from_Ev(ER,rhoR,vR) # aL = np.sqrt(GAM*PL/rhoL) # aR = np.sqrt(GAM*PR/rhoR) # # MaLloc = vL/aL # MaRloc = vR/aR # # qL = np.zeros(UL.shape) # qR = np.zeros(UR.shape) # # qL[:,1] = PL * MaLloc # qL[:,2] = PL * aL # # qR[:,1] = PR * MaRloc # qR[:,2] = PR * aR # # return 1/2 * (qR-qL) # Get the pressure from primitive variables rhoL = UL[:, 0] rhoR = UR[:, 0] vL = UL[:, 1] / rhoL vR = UR[:, 1] / rhoR EL = UL[:, 2] / rhoL ER = UR[:, 2] / rhoR PL = P_from_Ev(EL, rhoL, vL) PR = P_from_Ev(ER, rhoR, vR) Pp, Pm = compute_Ppm(MaL, MaR) Fp = np.zeros(UL.shape) Fp[:, 1] = Pp * PL + Pm * PR Fp[:, 2] = 1 / 2 * (PL * (vL + ah) + PR * (vR - ah)) return Fp
def compute_right_eigenvector(U): rho = U[:,0] v = U[:,1] / rho E = U[:,2] / rho P = P_from_Ev(E,rho,v) a = np.sqrt(GAM*P/rho) Rjlist = [] Rjinvlist = [] for idx in np.arange(0,len(rho),1): Rj = np.zeros((3,3)) Rj[0,:] = np.ones((1,3)) Rj[1,0] = v[idx] Rj[1,1] = v[idx] - a[idx] Rj[1,2] = v[idx] + a[idx] h = v[idx]**2/2 + a[idx]**2/(GAM-1) Rj[2,0] = v[idx]**2/2 Rj[2,1] = h - v[idx]*a[idx] Rj[2,2] = h + v[idx]*a[idx] Rjlist.append(Rj) Rjinvlist.append(np.linalg.inv(Rj)) Rj = Rjlist Rjinv = Rjinvlist return Rj,Rjinv
def compute_alphaR(UL, UR): rhoL = UL[:, 0] rhoR = UR[:, 0] vL = UL[:, 1] / rhoL vR = UR[:, 1] / rhoR EL = UL[:, 2] / rhoL ER = UR[:, 2] / rhoR PL = P_from_Ev(EL, rhoL, vL) PR = P_from_Ev(ER, rhoR, vR) num = 2 * (PR / rhoR) den = (PL / rhoL) + (PR / rhoR) return num / den
def compute_euler_flux(U): rho = U[:, 0] v = U[:, 1] / rho E = U[:, 2] / rho P = P_from_Ev(E, rho, v) flx = np.zeros(U.shape) flx[:, 0] = rho * v flx[:, 1] = rho * v**2 + P flx[:, 2] = rho * E * v + P * v return flx
def compute_eigenvector(U): rho = U[:, 0] v = U[:, 1] / rho E = U[:, 2] / rho P = P_from_Ev(E, rho, v) a = np.sqrt(GAM * P / rho) Rjlist = [] Rjinvlist = [] for idx in np.arange(0, len(rho), 1): Rj = np.zeros((3, 3)) Rjinv = np.zeros((3, 3)) # Right eigenvector Rj[0, :] = np.ones((1, 3)) Rj[1, 0] = v[idx] - a[idx] Rj[1, 1] = v[idx] Rj[1, 2] = v[idx] + a[idx] h = v[idx]**2 / 2 + a[idx]**2 / (GAM - 1) Rj[2, 0] = h - v[idx] * a[idx] Rj[2, 1] = v[idx]**2 / 2 Rj[2, 2] = h + v[idx] * a[idx] # Left eigenvector voa = v[idx] / a[idx] # v over a a2 = a[idx]**2 Rjinv[0, 0] = 1 / 2 * (1 / 2 * (GAM - 1) * voa**2 + voa) Rjinv[0, 1] = -1 / (2 * a[idx]) * ((GAM - 1) * voa + 1) Rjinv[0, 2] = (GAM - 1) / (2 * a2) Rjinv[1, 0] = 1 - 1 / 2 * (GAM - 1) * voa**2 Rjinv[1, 1] = (GAM - 1) * v[idx] / a2 Rjinv[1, 2] = -(GAM - 1) / a2 Rjinv[2, 0] = 1 / 2 * (1 / 2 * (GAM - 1) * voa**2 - voa) Rjinv[2, 1] = -1 / (2 * a[idx]) * ((GAM - 1) * voa - 1) Rjinv[2, 2] = (GAM - 1) / (2 * a2) Rjlist.append(Rj) Rjinvlist.append(Rjinv) Rj = Rjlist Rjinv = Rjinvlist return Rj, Rjinv
def compute_euler_flux(U, direction): rho = U[:, 0] u = U[:, 1] / rho v = U[:, 2] / rho E = U[:, 3] / rho P = P_from_Ev(E, rho, u, v) flx = np.zeros(U.shape) if direction == 'dx': flx[:, 0] = rho * u flx[:, 1] = rho * u**2 + P flx[:, 2] = rho * u * v flx[:, 3] = rho * E * u + P * u elif direction == 'dy': flx[:, 0] = rho * v flx[:, 1] = rho * u * v flx[:, 2] = rho * v**2 + P flx[:, 3] = rho * E * v + P * v return flx
def compute_lfc_flux(u, U0, dz, order): ### Indices nelem = u.shape[0] # Number of elements nunk = u.shape[1] # Number of unknowns # What's r that corresponds to our WENO order? rweno = int((order - 1) / 2) # u_{i+1}, u_{i-1} up1 = np.roll(u, -1, axis=0) um1 = np.roll(u, 1, axis=0) ### Roe average at u^{i+-1/2} up1h, um1h = roe_average(u, U0) # up1h = (u+up1)*1/2 ### LF Flux splitting: f = f^+ + f^- where ### f^{+-} = 1/2*(F[U] + alpha * U) ### We do reconstruction on the FLUX ### Calculate the LF split flux in all cells rho = u[:, 0] v = u[:, 1] / rho E = u[:, 2] / rho P = P_from_Ev(E, rho, v) a = np.sqrt(GAM * P / rho) # We want the max eigenvalue l1 = np.abs(v - a) l2 = np.abs(v) l3 = np.abs(v + a) eig = np.vstack((l1, l2, l3)) alpha = np.max(eig, axis=1) # GLOBAL MAX ### Characteristics # Eigenvectors: Compute the block matrix at each right eigenvector Rjp1h, Rjinvp1h = compute_eigenvector(up1h) ### Compute the flux flx = compute_euler_flux(u) flx0 = compute_euler_flux(U0) ###### # I + 1/2 ###### ### Transform into the characteristic domain v, g, vlf = to_characteristics(u, flx, U0, flx0, order, Rjinvp1h, alpha) ### Compute f+, f- at i+1/2 for all elements on the stencil FLXp = np.zeros((nelem, order, nunk)) FLXm = np.zeros((nelem, order, nunk)) FLXp = 1 / 2 * (g[:, 0:order, :] + vlf[:, 0:order, :]) FLXm = 1 / 2 * (g[:, 1:order + 1, :] - vlf[:, 1:order + 1, :]) # if order == 5: # FLXp = 1/2*(g[:,0:5,:] + vlf[:,0:5,:]) # FLXm = 1/2*(g[:,1:6,:] - vlf[:,1:6,:]) # elif order == 3: # FLXp = 1/2*(g[:,0:3,:] + vlf[:,0:3,:]) # FLXm = 1/2*(g[:,1:6,:] - vlf[:,1:6,:]) # FLXm = 1/2*(g - vlf) ### Reconstruct WENO in the characteristics domain # Reconstruct the data on the stencil fp1hL, fm1hR = compute_lr(FLXp, order) fp3hL, fp1hR = compute_lr(FLXm, order) # Compute the flux FLXp1h = fp1hL + fp1hR FLXm1h = np.roll(FLXp1h, 1, axis=0) # t1 = np.copy(FLXp1h) # t2 = np.copy(FLXm1h) ### Go back into the normal domain for idx in range(nelem): FLXp1h[idx] = np.matmul(Rjp1h[idx], FLXp1h[idx]) if idx > 0: FLXm1h[idx] = np.matmul(Rjp1h[idx - 1], FLXm1h[idx]) else: FLXm1h[idx] = np.matmul(Rjp1h[0], FLXm1h[idx]) return -1 / dz * (FLXp1h - FLXm1h)
def compute_lf_flux(u, U0, dz, order): ### Calculate the max eigenvalue of all cells rho = u[:, 0] v = u[:, 1] / rho E = u[:, 2] / rho P = P_from_Ev(E, rho, v) a = np.sqrt(GAM * P / rho) # We want the max eigenvalue l1 = np.abs(v - a) l2 = np.abs(v) l3 = np.abs(v + a) eig = np.vstack((l1, l2, l3)) alpha = np.max(eig, axis=1) # GLOBAL MAX ### LF Flux splitting: f = f^+ + f^- where ### f^{+-} = 1/2*(F[U] + alpha * U) ### We do reconstruction on the FLUX flx = compute_euler_flux(u) vlf = np.matmul(np.diag(alpha), u.T).T ### Characteristics # Eigenvectors: Compute the block matrix at each right eigenvector up1h = u Rjp1h, Rjinvp1h = compute_eigenvector(up1h) ### Compute the flux flx = compute_euler_flux(u) flx0 = compute_euler_flux(U0) nelem = u.shape[0] nunk = u.shape[1] ###### # I + 1/2 ###### ### Transform into the characteristic domain v, g, vlf = to_characteristics(u, flx, U0, flx0, order, Rjinvp1h, alpha) ### Compute f+, f- at i+1/2 for all elements on the stencil FLXp = np.zeros((nelem, order, nunk)) FLXm = np.zeros((nelem, order, nunk)) FLXp = 1 / 2 * (g[:, 0:order, :] + vlf[:, 0:order, :]) FLXm = 1 / 2 * (g[:, 1:order + 1, :] - vlf[:, 1:order + 1, :]) ### Reconstruct WENO in the characteristics domain # Reconstruct the data on the stencil fp1hL, fm1hR = compute_lr(FLXp, order) fp3hL, fp1hR = compute_lr(FLXm, order) # Compute the flux FLXp1h = fp1hL + fp1hR FLXm1h = np.roll(FLXp1h, 1, axis=0) ### Go back into the normal domain for idx in range(nelem): FLXp1h[idx] = np.matmul(Rjp1h[idx], FLXp1h[idx]) if idx > 0: FLXm1h[idx] = np.matmul(Rjp1h[idx - 1], FLXm1h[idx]) else: FLXm1h[idx] = np.matmul(Rjp1h[0], FLXm1h[idx]) return -1 / dz * (FLXp1h - FLXm1h)
def compute_lfc_flux_1D(U, U0, dx, dy, Nx, Ny, order, direction, options, tc, lambda_calc_char): nelem = U.shape[0] nunk = U.shape[1] ### Compute the average at the border Up1h = compute_average(U, U0, dx, dy, Nx, Ny, direction) ### Calculate the LF split flux in all cells rho = U[:, 0] u = U[:, 1] / rho v = U[:, 2] / rho E = U[:, 3] / rho P = P_from_Ev(E, rho, u, v) a = np.sqrt(GAM * P / rho) # We want the max eigenvalue if direction == 'dx': l1 = np.abs(u - a) l2 = np.abs(u) l3 = np.abs(u + a) l4 = np.abs(u) elif direction == 'dy': l1 = np.abs(v - a) l2 = np.abs(v) l3 = np.abs(v + a) l4 = np.abs(v) eig = np.vstack((l1, l2, l3, l4)) alpha = np.max(eig, axis=1) # GLOBAL MAX ### Characteristics # Eigenvectors: Compute the block matrix at each right eigenvector if direction == 'dx': Rh, Lh, Rlhs0, Llhs0, _, _ = compute_eigenvector(Up1h, U0, direction) elif direction == 'dy': Rh, Lh, Rlhs0, Llhs0, Rlhs0pre, Llhs0pre = compute_eigenvector( Up1h, U0, direction) ### Compute the flux flx = compute_euler_flux(U, direction) flx0 = compute_euler_flux(U0, direction) ### Transform into the characteristic domain # V = R^-1 U, H = R^-1 * F or R^-1 * G, VLF = alpha * V # V,H,VLF = to_characteristics(U,flx,U0,flx0,order,Lh,alpha,Nx,Ny,direction) V, H, VLF = to_characteristics(U, flx, U0, flx0, order, Lh, alpha, Nx, Ny, direction, options, tc, lambda_calc_char) ### Compute f+, f- at i+1/2 for all elements on the stencil FLXp = np.zeros((nelem, order, nunk)) FLXm = np.zeros((nelem, order, nunk)) FLXp = 1 / 2 * (H[:, 0:order, :] + VLF[:, 0:order, :]) FLXm = 1 / 2 * (H[:, 1:order + 1, :] - VLF[:, 1:order + 1, :]) fp1hL, fm1hR = compute_lr(FLXp, order) fp3hL, fp1hR = compute_lr(FLXm, order) # Compute the flux FLXp1h = fp1hL + fp1hR if direction == 'dx': FLXm1h = np.roll(FLXp1h, 1, axis=0) elif direction == 'dy': FLXm1h = np.roll(FLXp1h, Nx, axis=0) ### Go back into the normal domain if direction == 'dx': for idx in range(nelem): FLXp1h[idx] = np.matmul(Rh[idx], FLXp1h[idx]) if idx % Nx != 0: FLXm1h[idx] = np.matmul(Rh[idx - 1], FLXm1h[idx]) else: FLXm1h[idx] = np.matmul(Rlhs0, FLXm1h[idx]) elif direction == 'dy': for idx in range(nelem): FLXp1h[idx] = np.matmul(Rh[idx], FLXp1h[idx]) if idx > Nx - 1: # Any cell with an index higher than Nx is NOT on the bottom boundary FLXm1h[idx] = np.matmul(Rh[idx - Nx], FLXm1h[idx]) else: FLXm1h[idx] = np.matmul( Rlhs0, FLXm1h[idx] ) # We don't care about what's at the bottom boundary: it will be overwritten if direction == 'dx': dz = dx elif direction == 'dy': dz = dy return -1 / dz * (FLXp1h - FLXm1h)
order = 5 flux_type = 'LFC' # Data holders # [rho,rho*u,E] U = np.zeros([len(zvec), 3]) # Case definition caseNum = 7 left, right, cfl, tmax = defineCase(caseNum) #tmax = 0.02 f_0(U) U0 = np.copy(U) # Time P0 = P_from_Ev(U[:, 2] / U[:, 0], U[:, 0], U[:, 1] / U[:, 0]) a0 = np.sqrt(GAM * P0 / U[:, 0]) v0 = U[:, 1] / U[:, 0] lam0 = np.max(v0 + a0) dt = dz / lam0 * cfl tc = 0 # Plots f, axarr = plt.subplots(3, 2) axarr[0, 0].set_title("Density") axarr[0, 1].set_title("Pressure") axarr[1, 0].set_title("Temperature") axarr[1, 1].set_title("Velocity") axarr[2, 0].set_title("Mach number")
def compute_ecusp_flux(u,U0,dz,order): # u_{i+1}, u_{i-1} up1 = np.roll(u,-1,axis=0) um1 = np.roll(u,1,axis=0) ### Reconstruct the data on the stencil up1hL, um1hR = compute_lr(up1,u,um1,order) up1hR = np.roll(um1hR,-1,axis=0) # Compute the RHS flux um1hL = np.roll(up1hL,1,axis=0) # This will contain u_{i-1/2}^L ### i + 1/2 # Calculate the convective flux rhoL = up1hL[:,0] rhoR = up1hR[:,0] vL = up1hL[:,1]/rhoL vR = up1hR[:,1]/rhoR EL = up1hL[:,2]/rhoL ER = up1hR[:,2]/rhoR PL = P_from_Ev(EL,rhoL,vL) PR = P_from_Ev(ER,rhoR,vR) ap1hL = np.sqrt(GAM*PL/rhoL) ap1hR = np.sqrt(GAM*PR/rhoR) ah = 1/2*(ap1hL+ap1hR) MaL = vL/ah MaR = vR/ah fp1hc = flux_convective(up1hL,up1hR,ah,MaL,MaR) fp1hp = flux_pressure(up1hL,up1hR,ah,MaL,MaR) ### i - 1/2 rhoL = um1hL[:,0] rhoR = um1hR[:,0] vL = um1hL[:,1]/rhoL vR = um1hR[:,1]/rhoR EL = um1hL[:,2]/rhoL ER = um1hR[:,2]/rhoR PL = P_from_Ev(EL,rhoL,vL) PR = P_from_Ev(ER,rhoR,vR) am1hL = np.sqrt(GAM*PL/rhoL) am1hR = np.sqrt(GAM*PR/rhoR) ah = 1/2*(am1hL+am1hR) MaL = vL/ah MaR = vR/ah fm1hc = flux_convective(um1hL,um1hR,ah,MaL,MaR) fm1hp = flux_pressure(um1hL,um1hR,ah,MaL,MaR) ### Calculate all types of fluxes # Subsonic fRsub = (fp1hc + fp1hp) fLsub = (fm1hc + fm1hp) # Supersonic traveling right: reconstruct flux on boundary flx = compute_euler_flux(u) # u_{i+1}, u_{i-1} flxp1 = np.roll(flx,-1,axis=0) flxm1 = np.roll(flx,1,axis=0) fp1hL, fm1hR = compute_lr(flxp1,flx,flxm1,order) fm1hL = np.roll(fp1hL,1,axis=0) fRsupr = fp1hL fLsupr = fm1hL # fRsupr = compute_euler_flux(up1hL) # fLsupr = compute_euler_flux(um1hL) # Supersonic travelight left fRsupl = compute_euler_flux(up1hR) fLsupl = compute_euler_flux(um1hR) ### Make sure we use the applicable formula, which depends on the local speed # What's the local speed of sound? vloc = u[:,1]/u[:,0] Eloc = u[:,2]/u[:,0] rholoc = u[:,0] Ploc = P_from_Ev(Eloc,rholoc,vloc) aloc = np.sqrt(GAM*Ploc/rholoc) b1 = (np.abs(vloc) <= aloc) b2 = vloc > aloc b3 = vloc < -aloc fR = np.zeros(u.shape) fL = np.zeros(u.shape) for idx in np.arange(0,3,1): fR[:,idx] = fRsub[:,idx] * b1 + fRsupr[:,idx] * b2 + fRsupl[:,idx] * b3 fL[:,idx] = fLsub[:,idx] * b1 + fLsupr[:,idx] * b2 + fLsupl[:,idx] * b3 return -1/dz * (fR-fL)
# dataZ = griddata(grid, U0[:,1], (xv, yv), method='nearest') # Plots f, axarr = plt.subplots(3, 2) axarr[0, 0].set_title("Density") axarr[0, 1].set_title("Pressure") axarr[1, 0].set_title("Temperature") axarr[1, 1].set_title("x-Velocity") axarr[2, 0].set_title("Mach number") axarr[2, 1].set_title("Energy") rho = U0[:, 0] u = U0[:, 1] / U0[:, 0] v = U0[:, 2] / U0[:, 0] E = U0[:, 3] / U0[:, 0] P = P_from_Ev(E, rho, u, v) asos = np.sqrt(GAM * P / rho) lam = np.max(np.abs(v) + asos) rhoZ = griddata(grid, rho, (xv, yv), method='nearest') uZ = griddata(grid, u, (xv, yv), method='nearest') vZ = griddata(grid, v, (xv, yv), method='nearest') EZ = griddata(grid, E, (xv, yv), method='nearest') PZ = griddata(grid, P, (xv, yv), method='nearest') TZ = PZ / rhoZ aZ = np.sqrt(GAM * PZ / rhoZ) MZ = np.sqrt(uZ**2 + vZ**2) / aZ p0 = axarr[0, 0].contour(xv, yv, rhoZ) p1 = axarr[0, 1].contour(xv, yv, PZ) p2 = axarr[1, 0].contour(xv, yv, TZ)
def compute_lf_flux(u,U0,dz,order): # u_{i+1}, u_{i-1} up1 = np.roll(u,-1,axis=0) um1 = np.roll(u,1,axis=0) ### Roe average at u^{i+-1/2} up1h, um1h = roe_average(u,U0) ### LF Flux splitting: f = f^+ + f^- where ### f^{+-} = 1/2*(F[U] + alpha * U) ### We do reconstruction on the FLUX ### Calculate the LF split flux in all cells rho = u[:,0] v = u[:,1]/rho E = u[:,2]/rho P = P_from_Ev(E,rho,v) a = np.sqrt(GAM*P/rho) # We want the max eigenvalue l1 = np.abs(v-a) l2 = np.abs(v) l3 = np.abs(v+a) eig = np.vstack((l1,l2,l3)) eig = np.transpose(eig) alpha = np.max(eig) # GLOBAL MAX ### Characteristics # Eigenvectors: Compute the block matrix at each right eigenvector Rjp1h,Rjinvp1h = compute_right_eigenvector(up1h); Rjm1h,Rjinvm1h = compute_right_eigenvector(um1h); # Transform into the characteristic domain v = np.copy(u) g = np.copy(u) flx = compute_euler_flux(u) ###### # I + 1/2 ###### nelem = u.shape[0] for idx in np.arange(0,nelem,1): v[idx,:] = np.matmul(Rjinvp1h[idx],u[idx,:]) g[idx,:] = np.matmul(Rjinvp1h[idx],flx[idx,:]) ### Reconstruct WENO in the characteristics domain FLXp = np.zeros(u.shape) FLXm = np.zeros(u.shape) for idx in np.arange(0,3,1): FLXp[:,idx] = 1/2*(g[:,idx] + alpha*v[:,idx]) FLXm[:,idx] = 1/2*(g[:,idx] - alpha*v[:,idx]) ### i + 1/2 ^+ fp1 = np.roll(FLXp,-1,axis=0) fm1 = np.roll(FLXp,1,axis=0) # Reconstruct the data on the stencil fp1hL, fm1hR = compute_lr(fp1,FLXp,fm1,order) fp1hR = np.roll(fm1hR,-1,axis=0) #up1hL, um1hR = compute_lr(up1,u,um1,order) #up1hR = np.roll(um1hR,-1,axis=0) # Compute the RHS flux fiph1_P = fp1hL ### i+1/2 ^- fp1 = np.roll(FLXm,-1,axis=0) fm1 = np.roll(FLXm,1,axis=0) # Reconstruct the data on the stencil fp1hL, fm1hR = compute_lr(fp1,FLXm,fm1,order) fp1hR = np.roll(fm1hR,-1,axis=0) fiph1_M = fp1hR ### Go back to component domain for idx in np.arange(0,nelem,1): fiph1_P[idx,:] = np.matmul(Rjp1h[idx],fiph1_P[idx,:]) fiph1_M[idx,:] = np.matmul(Rjp1h[idx],fiph1_M[idx,:]) FLXp1h = fiph1_P + fiph1_M ###### # I - 1/2 ###### nelem = u.shape[0] for idx in np.arange(0,nelem,1): v[idx,:] = np.matmul(Rjinvm1h[idx],u[idx,:]) g[idx,:] = np.matmul(Rjinvm1h[idx],flx[idx,:]) ### Reconstruct WENO in the characteristics domain FLXp = np.zeros(u.shape) FLXm = np.zeros(u.shape) for idx in np.arange(0,3,1): FLXp[:,idx] = 1/2*(g[:,idx] + alpha*v[:,idx]) FLXm[:,idx] = 1/2*(g[:,idx] - alpha*v[:,idx]) ### i - 1/2 ^+ fp1 = np.roll(FLXp,-1,axis=0) fm1 = np.roll(FLXp,1,axis=0) # Reconstruct the data on the stencil fp1hL, fm1hR = compute_lr(fp1,FLXp,fm1,order) fp1hR = np.roll(fm1hR,-1,axis=0) #up1hL, um1hR = compute_lr(up1,u,um1,order) #up1hR = np.roll(um1hR,-1,axis=0) # Compute the RHS flux fiph1_M = fm1hR ### i-1/2 ^- fp1 = np.roll(FLXm,-1,axis=0) fm1 = np.roll(FLXm,1,axis=0) # Reconstruct the data on the stencil fp1hL, fm1hR = compute_lr(fp1,FLXm,fm1,order) # fp1hR = np.roll(fm1hR,-1,axis=0) fm1hL = np.roll(fp1hL,1,axis=0) fiph1_P = fm1hL ### Go back to component domain for idx in np.arange(0,nelem,1): fiph1_P[idx,:] = np.matmul(Rjm1h[idx],fiph1_P[idx,:]) fiph1_M[idx,:] = np.matmul(Rjm1h[idx],fiph1_M[idx,:]) FLXm1h = fiph1_P + fiph1_M return -1/dz*(FLXp1h - FLXm1h)