1- # solve the Riemann problem for a gamma-law gas
1+ """An exact Riemann solver for the Euler equations with a gamma-law
2+ gas. The left and right states are stored as State objects. We then
3+ create a RiemannProblem object with the left and right state:
24
3- from __future__ import print_function
5+ > rp = RiemannProblem(left_state, right_state)
6+
7+ Next we solve for the star state:
8+
9+ > rp.find_star_state()
10+
11+ Finally, we sample the solution to find the interface state, which
12+ is returned as a State object:
13+
14+ > q_int = rp.sample_solution()
15+ """
416
517import matplotlib .pyplot as plt
618import numpy as np
719import scipy .optimize as optimize
820
9- class State ( object ) :
21+ class State :
1022 """ a simple object to hold a primitive variable state """
1123
1224 def __init__ (self , p = 1.0 , u = 0.0 , rho = 1.0 ):
@@ -15,9 +27,9 @@ def __init__(self, p=1.0, u=0.0, rho=1.0):
1527 self .rho = rho
1628
1729 def __str__ (self ):
18- return "rho: {}; u: {}; p: {}" . format ( self .rho , self . u , self . p )
30+ return f "rho: { self . rho } ; u: { self . u } ; p: { self .p } "
1931
20- class RiemannProblem ( object ) :
32+ class RiemannProblem :
2133 """ a class to define a Riemann problem. It takes a left
2234 and right state. Note: we assume a constant gamma """
2335
@@ -29,6 +41,9 @@ def __init__(self, left_state, right_state, gamma=1.4):
2941 self .ustar = None
3042 self .pstar = None
3143
44+ def __str__ (self ):
45+ return f"pstar = { self .pstar } , ustar = { self .ustar } "
46+
3247 def u_hugoniot (self , p , side , shock = False ):
3348 """define the Hugoniot curve, u(p). If shock=True, we do a 2-shock
3449 solution"""
@@ -80,11 +95,67 @@ def find_2shock_star_state(self, p_min=0.001, p_max=1000.0):
8095 p_min , p_max )
8196 self .ustar = self .u_hugoniot (self .pstar , "left" , shock = True )
8297
98+ def shock_solution (self , sgn , xi , state ):
99+ """return the interface solution considering a shock"""
100+
101+ p_ratio = self .pstar / state .p
102+ c = np .sqrt (self .gamma * state .p / state .rho )
103+
104+ # Toro, eq. 4.52 / 4.59
105+ S = state .u + sgn * c * np .sqrt (0.5 * (self .gamma + 1.0 )/ self .gamma * p_ratio +
106+ 0.5 * (self .gamma - 1.0 )/ self .gamma )
107+
108+ # are we to the left or right of the shock?
109+ if (sgn > 0 and xi > S ) or (sgn < 0 and xi < S ):
110+ # R/L region
111+ solution = state
112+ else :
113+ # * region -- get rhostar from Toro, eq. 4.50 / 4.57
114+ gam_fac = (self .gamma - 1.0 )/ (self .gamma + 1.0 )
115+ rhostar = state .rho * (p_ratio + gam_fac )/ (gam_fac * p_ratio + 1.0 )
116+ solution = State (rho = rhostar , u = self .ustar , p = self .pstar )
117+
118+ return solution
119+
120+ def rarefaction_solution (self , sgn , xi , state ):
121+ """return the interface solution considering a rarefaction wave"""
122+
123+ # find the speed of the head and tail of the rarefaction fan
124+
125+ # isentropic (Toro eq. 4.54 / 4.61)
126+ p_ratio = self .pstar / state .p
127+ c = np .sqrt (self .gamma * state .p / state .rho )
128+ cstar = c * p_ratio ** ((self .gamma - 1.0 )/ (2 * self .gamma ))
129+
130+ lambda_head = state .u + sgn * c
131+ lambda_tail = self .ustar + sgn * cstar
132+
133+ gam_fac = (self .gamma - 1.0 )/ (self .gamma + 1.0 )
134+
135+ if (sgn > 0 and xi > lambda_head ) or (sgn < 0 and xi < lambda_head ):
136+ # R/L region
137+ solution = state
138+
139+ elif (sgn > 0 and xi < lambda_tail ) or (sgn < 0 and xi > lambda_tail ):
140+ # * region, we use the isentropic density (Toro 4.53 / 4.60)
141+ solution = State (rho = state .rho * p_ratio ** (1.0 / self .gamma ),
142+ u = self .ustar , p = self .pstar )
143+
144+ else :
145+ # we are in the fan -- Toro 4.56 / 4.63
146+ rho = state .rho * (2 / (self .gamma + 1.0 ) -
147+ sgn * gam_fac * (state .u - xi )/ c )** (2.0 / (self .gamma - 1.0 ))
148+ u = 2.0 / (self .gamma + 1.0 ) * ( - sgn * c + 0.5 * (self .gamma - 1.0 )* state .u + xi )
149+ p = state .p * (2 / (self .gamma + 1.0 ) -
150+ sgn * gam_fac * (state .u - xi )/ c )** (2.0 * self .gamma / (self .gamma - 1.0 ))
151+ solution = State (rho = rho , u = u , p = p )
152+
153+ return solution
83154
84155 def sample_solution (self , time , npts , xmin = 0.0 , xmax = 1.0 ):
85156 """given the star state (ustar, pstar), sample the solution for npts
86157 points between xmin and xmax at the given time.
87-
158+
88159 this is a similarity solution in xi = x/t """
89160
90161 # we write it all explicitly out here -- this could be vectorized
@@ -117,65 +188,20 @@ def sample_solution(self, time, npts, xmin=0.0, xmax=1.0):
117188 state = self .left
118189 sgn = - 1.0
119190
120- p_ratio = self .pstar / state .p
121-
122- c = np .sqrt (gam * state .p / state .rho )
123-
124- # isentropic (Toro eq. 4.54 / 4.61)
125- cstar = c * p_ratio ** ((gam - 1.0 )/ (2 * gam ))
126-
127- # is the right wave in our a shock or rarefaction?
191+ # is non-contact wave a shock or rarefaction?
128192 if self .pstar > state .p :
129- # shock
130-
131- # Toro, eq. 4.50 / 4.57
132- rhostar = state .rho * (p_ratio + gam_fac )/ (gam_fac * p_ratio + 1.0 )
133-
134- # Toro, eq. 4.52 / 4.59
135- S = state .u + sgn * c * np .sqrt (0.5 * (gam + 1.0 )/ gam * p_ratio + 0.5 * (gam - 1.0 )/ gam )
136-
137- # are we to the left or right of the shock?
138- if (sgn > 0 and xi [n ] > S ) or (sgn < 0 and xi [n ] < S ):
139- # R/L region
140- rho = state .rho
141- u = state .u
142- p = state .p
143- else :
144- # * region
145- rho = rhostar
146- u = self .ustar
147- p = self .pstar
193+ # compression! we are a shock
194+ solution = self .shock_solution (sgn , xi [n ], state )
148195
149196 else :
150- # rarefaction -- the rarefaction is spread out, so
151- # find the speed of the head and tail of the rarefaction fan
152- lambda_head = state .u + sgn * c
153- lambda_tail = self .ustar + sgn * cstar
154-
155- if (sgn > 0 and xi [n ] > lambda_head ) or (sgn < 0 and xi [n ] < lambda_head ):
156- # R/L region
157- rho = state .rho
158- u = state .u
159- p = state .p
160-
161- elif (sgn > 0 and xi [n ] < lambda_tail ) or (sgn < 0 and xi [n ] > lambda_tail ):
162- # * region
163- # isentropic density (Toro 4.53 / 4.60)
164- rho = state .rho * p_ratio ** (1.0 / gam )
165- u = self .ustar
166- p = self .pstar
167-
168- else :
169- # we are in the fan -- Toro 4.56 / 4.63
170- rho = state .rho * (2 / (gam + 1.0 ) - sgn * gam_fac * (state .u - xi [n ])/ c )** (2.0 / (gam - 1.0 ))
171- u = 2.0 / (gam + 1.0 ) * ( - sgn * c + 0.5 * (gam - 1.0 )* state .u + xi [n ])
172- p = state .p * (2 / (gam + 1.0 ) - sgn * gam_fac * (state .u - xi [n ])/ c )** (2.0 * gam / (gam - 1.0 ))
197+ # rarefaction
198+ solution = self .rarefaction_solution (sgn , xi [n ], state )
173199
174200
175201 # store
176- rho_v .append (rho )
177- u_v .append (u )
178- p_v .append (p )
202+ rho_v .append (solution . rho )
203+ u_v .append (solution . u )
204+ p_v .append (solution . p )
179205
180206 return x , np .array (rho_v ), np .array (u_v ), np .array (p_v )
181207
0 commit comments