def viscous_shock_exact(x, Ms, MP, μ, center=0): """ Returns the density, pressure, and velocity of the viscous shock (Mach number Ms) at x """ x -= center γ = MP.γ ρ0 = 1 p0 = 1 / γ if Ms == 2: L = 0.3 elif Ms == 3: L = 0.13 x = min(x, L) x = max(x, -L) c0 = c_0(ρ0, p0, eye(3), MP) a = 2 / (Ms**2 * (γ + 1)) + (γ - 1) / (γ + 1) Re = ρ0 * c0 * Ms / μ c1 = ((1 - a) / 2)**(1 - a) c2 = 3 / 4 * Re * (Ms**2 - 1) / (γ * Ms**2) def f(z): return (1 - z) / (z - a)**a - c1 * exp(c2 * -x) vbar = brentq(f, a + 1e-16, 1) p = p0 / vbar * (1 + (γ - 1) / 2 * Ms**2 * (1 - vbar**2)) ρ = ρ0 / vbar v = Ms * c0 * vbar v = Ms * c0 - v # Shock travelling into fluid at rest return ρ, p, v
def Xi2(P, d, MP): ρ = P.ρ p = P.p() A = P.A c0 = c_0(ρ, p, A, MP) if THERMAL: ret = zeros([5, 4]) else: ret = zeros([5, 3]) ret[0, 0] = ρ ret[1, d] = ρ * c0**2 if VISCOUS: σ = P.σ() dσdρ = P.dσdρ() ret[1, :3] += σ[d] - ρ * dσdρ[d] ret[2:, :3] = A if THERMAL: T = P.T() dTdp = P.dTdp() ch = c_h(ρ, T, MP) ret[1, 3] = ρ * ch**2 / dTdp return ret
def c0_star(p_, P, MP): r = P.ρ p = P.p() y = MP.γ pINF = MP.pINF c0 = c_0(r, p, eye(3), MP) return c0 * pow((p_ + pINF) / (p + pINF), (y - 1) / (2 * y))
def Y_matrix(P, MP, sgn): ρ = P.ρ A = P.A σρ = P.dσdρ() σA = P.dσdA() e0 = array([1, 0, 0]) Π1 = σA[0, :, :, 0] tmp = zeros([5, 5]) tmp[:3, 0] = -σρ[0] tmp[0, 1] = 1 tmp[:3, 2:5] = -Π1 if THERMAL: tmp[3, 0] = P.dTdρ() tmp[3, 1] = P.dTdp() tmp[4, 0] = -1 / ρ tmp[4, 2:5] = inv(A)[0] else: p = P.p() σ = P.σ() c0 = c_0(ρ, p, A, MP) B = zeros([2, 3]) B[0, 0] = ρ B[1] = σ[0] - ρ * σρ[0] B[1, 0] += ρ * c0**2 rhs = column_stack((-σρ[0], e0)) C = solve(Π1, rhs) BA_1 = dot(B, inv(A)) Z = eye(2) - dot(BA_1, C) W = concatenate([eye(2), -BA_1], axis=1) tmp[3:5] = solve(Z, W) b = zeros([5, n1]) b[:n1, :n1] = eye(n1) X = solve(tmp, b) Ξ1 = Xi1(P, 0, MP) Ξ2 = Xi2(P, 0, MP) Ξ = dot(Ξ1, Ξ2) w, vr = eig(Ξ) D_1 = diag(1 / sqrt(w.real)) Q_1 = vr Q = inv(Q_1) Y0 = dot(Q_1, dot(D_1, Q)) return sgn * dot(Y0, dot(Ξ1, X))
def f1(z, P, MP): r = P.ρ p = P.p() y = MP.γ pINF = MP.pINF c0 = c_0(r, p, eye(3), MP) if (z > p): temp = sqrt(A0(r, y) / (z + B(p, y, pINF))) return (1 - (z - p) / (2 * (z + B(p, y, pINF)))) * temp else: temp = pow((z + pINF) / (p + pINF), -(y + 1) / (2 * y)) return temp * c0 / (y * (p + pINF))
def f0(z, P, MP): r = P.ρ p = P.p() y = MP.γ pINF = MP.pINF c0 = c_0(r, p, eye(3), MP) if (z > p): temp = sqrt(A0(r, y) / (z + B(p, y, pINF))) return (z - p) * temp else: temp = pow((z + pINF) / (p + pINF), (y - 1) / (2 * y)) return 2 * c0 / (y - 1) * (temp - 1)
def M_prim(Q, d, MP): """ The system jacobian of the primitive system NOTE: Uses typical ordering """ P = State(Q, MP) ρ = P.ρ p = P.p() A = P.A v = P.v c0 = c_0(ρ, p, A, MP) ret = v[d] * eye(NV) ret[0, 2 + d] = ρ ret[1, 2 + d] = ρ * c0**2 ret[2 + d, 1] = 1 / ρ if VISCOUS: σ = P.σ() dσdρ = P.dσdρ() dσdA = P.dσdA() ret[1, 2:5] += σ[d] - ρ * dσdρ[d] ret[2:5, 0] = -1 / ρ * dσdρ[d] ret[2:5, 5:14] = -1 / ρ * dσdA[d].reshape([3, 9]) ret[5 + d, 2:5] = A[0] ret[8 + d, 2:5] = A[1] ret[11 + d, 2:5] = A[2] if THERMAL: dTdρ = P.dTdρ() dTdp = P.dTdp() T = P.T() ch = c_h(ρ, T, MP) ret[1, 14 + d] = ρ * ch**2 / dTdp ret[14 + d, 0] = dTdρ / ρ ret[14 + d, 1] = dTdp / ρ return ret
def riemann_constraints(P, sgn, MP, left=False): """ K=R: sgn = -1 K=L: sgn = 1 NOTE: Uses atypical ordering Extra constraints are: dΣ = dΣ/dρ * dρ + dΣ/dp * dp + dΣ/dA * dA dT = dT/dρ * dρ + dT/dp * dp v*L = v*R J*L = J*R """ _, Lhat, Rhat = eigen(P, 0, False, MP, values=False, right=True, left=left, typical_order=False) if left: Lhat = left_riemann_constraints(P, Lhat, sgn) ρ = P.ρ A = P.A σρ = P.dσdρ() σA = P.dσdA() e0 = array([1, 0, 0]) Π1 = σA[0, :, :, 0] tmp = zeros([5, 5]) tmp[:3, 0] = -σρ[0] tmp[0, 1] = 1 tmp[:3, 2:5] = -Π1 if THERMAL: tmp[3, 0] = P.dTdρ() tmp[3, 1] = P.dTdp() tmp[4, 0] = -1 / ρ tmp[4, 2:5] = inv(A)[0] else: p = P.p() σ = P.σ() c0 = c_0(ρ, p, A, MP) B = zeros([2, 3]) B[0, 0] = ρ B[1] = σ[0] - ρ * σρ[0] B[1, 0] += ρ * c0**2 rhs = column_stack((-σρ[0], e0)) C = solve(Π1, rhs) BA_1 = dot(B, inv(A)) Z = eye(2) - dot(BA_1, C) W = concatenate([eye(2), -BA_1], axis=1) tmp[3:5] = solve(Z, W) b = zeros([5, n1]) b[:n1, :n1] = eye(n1) X = solve(tmp, b) Rhat[:5, :n1] = X Ξ1 = Xi1(P, 0, MP) Ξ2 = Xi2(P, 0, MP) Q, Q_1, _, D_1 = decompose_Ξ(Ξ1, Ξ2) Y0 = dot(Q_1, dot(D_1, Q)) Rhat[11:n5, :n1] = -sgn * dot(Y0, dot(Ξ1, X)) Rhat[:11, n1:n2] = 0 Rhat[11:n5, n1:n2] = sgn * dot(Q_1, D_1) return Lhat, Rhat
def left_eigenvectors(P, d, MP, typical_order): ρ = P.ρ A = P.A σA = P.dσdA() σρ = P.dσdρ() Π1 = σA[d, :, :, 0] Π2 = σA[d, :, :, 1] Π3 = σA[d, :, :, 2] Ξ1 = Xi1(P, d, MP) Ξ2 = Xi2(P, d, MP) Q, Q_1, D, D_1 = decompose_Ξ(Ξ1, Ξ2) n1, n2, n3, n4, n5, n6 = get_indexes() e0 = array([1, 0, 0]) L = zeros([17, 17]) tmp1 = dot(Q, Ξ1) tmp2 = -dot(Q[:, :3], Π2) / ρ tmp3 = -dot(Q[:, :3], Π3) / ρ tmp4 = dot(D, Q) L[:n1, :5] = tmp1 L[n1:n2, :5] = tmp1 L[:n1, 5:8] = tmp2 L[n1:n2, 5:8] = tmp2 L[:n1, 8:11] = tmp3 L[n1:n2, 8:11] = tmp3 L[:n1, 11:n5] = tmp4 L[n1:n2, 11:n5] = -tmp4 if THERMAL: tmp = inv(A)[0] L[8, 0] = -1 / ρ L[8, 2:5] = tmp L[8, 5:8] = dot(tmp, solve(Π1, Π2)) L[8, 8:11] = dot(tmp, solve(Π1, Π3)) L[15, 15] = 1 L[16, 16] = 1 else: σ = P.σ() p = P.p() c0 = c_0(ρ, p, A, MP) B = zeros([2, 3]) B[0, 0] = ρ B[1] = σ[0] - ρ * σρ[0] B[1, 0] += ρ * c0**2 C = zeros([3, 2]) C[:, 0] = -solve(Π1, σρ[0]) C[:, 1] = solve(Π1, e0) BA_1 = dot(B, inv(A)) Z = eye(2) - dot(BA_1, C) X = zeros([2, 14]) X[:, :2] = eye(2) X[:, 2:5] = -BA_1 X[:, 5:8] = -dot(BA_1, solve(Π1, Π2)) X[:, 8:11] = -dot(BA_1, solve(Π1, Π3)) L[6:8, :14] = solve(Z, X) for i in range(6): L[n3 + i, 5 + i] = 1 if typical_order: L = reorder(L.T).T if not THERMAL: L = L[:14, :14] return L
def exact_euler(n, t, x0, QL, QR, MPL, MPR): """ Returns the exact solution to the Euler equations at (x,t), given initial states PL for x<x0 and PR for x>x0 """ ret = zeros([n, len(QL)]) PL = State(QL, MPL) PR = State(QR, MPR) ρL = PL.ρ ρR = PR.ρ uL = PL.v[0] uR = PR.v[0] pL = PL.p() pR = PR.p() c0L = c_0(ρL, pL, eye(3), MPL) c0R = c_0(ρR, pR, eye(3), MPR) p_ = p_star(PL, PR, MPL, MPR) u_ = u_star(p_, PL, PR, MPL, MPR) print('Interface:', u_ * t + x0) for i in range(n): x = (i + 0.5) / n S = (x - x0) / t if (S < u_): if (p_ < pL): # Left fan if (S < uL - c0L): ret[i] = QL else: STL = u_ - c0_star(p_, PL, MPL) if (S < STL): ret[i] = Wfan(S, PL, MPL, c0L) else: r_ = r_star_fan(p_, PL, MPL) v_ = array([u_, 0, 0]) ret[i] = Cvec(r_, p_, v_, MPL) else: # Left shock SL = uL - Q(p_, PL, MPL) / ρL if (S < SL): ret[i] = QL else: r_ = r_star_shock(p_, PL, MPL) v_ = array([u_, 0, 0]) ret[i] = Cvec(r_, p_, v_, MPL) ret[i, -1] = -1 else: if (p_ < pR): # Right fan if (uR + c0R < S): ret[i] = QR else: STR = u_ + c0_star(p_, PR, MPR) if (STR < S): ret[i] = Wfan(S, PR, MPR, -c0R) else: r_ = r_star_fan(p_, PR, MPR) v_ = array([u_, 0, 0]) ret[i] = Cvec(r_, p_, v_, MPR) else: # Right shock SR = uR + Q(p_, PR, MPR) / ρR if (SR < S): ret[i] = QR else: r_ = r_star_shock(p_, PR, MPR) v_ = array([u_, 0, 0]) ret[i] = Cvec(r_, p_, v_, MPR) ret[i, -1] = 1 return ret