14 | | !------------------------------------------------------------------------------------------------- |
15 | | ! This program finds the solution of p*, u*, and rho*_L and rho*_R given initial data states wL |
16 | | ! and wR of the Riemann problem |
17 | | ! Author: Erica Kaminski, 12.17.12 |
18 | | !------------------------------------------------------------------------------------------------- |
19 | | |
20 | | IMPLICIT NONE |
21 | | |
22 | | REAL :: DomLen, TimeOut, DisPos |
23 | | INTEGER :: cells, i |
24 | | REAL :: rho_L, p_L, u_L !Left data vars |
25 | | REAL :: rho_R, p_R, u_R !Right data vars |
26 | | REAL, dimension(3) :: wL !Left data state |
27 | | REAL, dimension(3) :: wR !Right data state |
28 | | REAL :: Cs_L, Cs_R !Sound speed Left and Right states |
29 | | REAL, PARAMETER :: gamma = 1.4 ! Ratio specific heats |
30 | | REAL :: p_Star, u_Star ! Output of program |
31 | | REAL :: mpa ! Normalization constant for P |
32 | | REAL :: u_diff, dx, xpos, s |
33 | | REAL :: rhos, us, ps |
34 | | |
35 | | NAMELIST /InitialData/ DomLen, TimeOut, DisPos, cells, rho_L, p_L, u_L, rho_R, p_R, u_R, mpa |
36 | | |
37 | | !-------------------------------------------------------------------------------------------------- |
38 | | ! Main body of program here |
39 | | !-------------------------------------------------------------------------------------------------- |
40 | | |
41 | | |
42 | | OPEN(UNIT = 3, File = "initial.data", status = 'old') !Initialize data |
43 | | READ(3, NML = InitialData) |
44 | | CLOSE(3) |
45 | | |
46 | | wL = (/rho_L, p_L, u_L/) !Populate w arrays |
47 | | wR = (/rho_R, p_R, u_R/) |
48 | | |
49 | | Cs_L = Sqrt(Gamma*p_L/rho_L) |
50 | | Cs_R = Sqrt(Gamma*p_R/rho_R) |
51 | | |
52 | | U_DIFF = u_R - u_L |
53 | | |
54 | | !PRESSURE POSITIVITY CONDITION --- |
55 | | |
56 | | IF (2.0*Cs_L/(gamma-1.0) + 2.0*Cs_R/(gamma-1.0).LE.U_DIFF) THEN |
57 | | |
58 | | PRINT *, 'PRESSURE POSITIVITY CONDITION VIOLATED!' |
59 | | PRINT *, 'VACUUM STATE IS CREATED BY INITIAL CONDITIONS' |
60 | | PRINT *, 'THIS RIEMANN SOLVER IS NOT CORRECT METHOD FOR SOLUTION' |
61 | | PRINT *, 'PROGRAM STOPPED' |
62 | | STOP |
63 | | |
64 | | END IF |
65 | | |
66 | | CALL Find_Pstar(p_Star, u_Star) |
67 | | !check that p_Star = p from subprpgram with a print statement - I did, it does |
68 | | |
69 | | OPEN(UNIT=2, FILE='exact.out', STATUS='OLD', POSITION='APPEND') |
70 | | |
71 | | dx = DomLen/REAL(cells) |
72 | | WRITE(2,*)'xpos rho u P iE' |
73 | | DO 10 i = 1, cells |
74 | | xpos = dx*(REAL(i)-0.5) !cell-centered |
75 | | s = (xpos - DisPos)/TimeOut !characteristic speed |
76 | | CALL SampleExact(p_Star, u_Star, s, rhos, us, ps) |
77 | | WRITE(2, 20)xpos, rhos, us, ps/mpa, ps/rhos/(gamma-1.0)/mpa !the last may be internal energy...? |
78 | | 10 Continue |
79 | | |
80 | | CLOSE(2) |
81 | | |
82 | | 20 FORMAT(5(F14.6,2X)) |
83 | | |
84 | | |
85 | | |
86 | | CONTAINS |
87 | | |
88 | | SUBROUTINE SampleExact(p_Star, u_Star, s, rhos, us, ps) |
89 | | REAL,INTENT(IN) :: p_Star, u_Star, s |
90 | | REAL,INTENT(OUT) ::rhos, us, ps !sampled density, velocity, pressure at point (x,t) |
91 | | REAL :: SHL, STL !Speed of left rarefaction head and tail |
92 | | REAL :: SHR, STR !Speed of right rarefaction head and tail |
93 | | REAL :: CsL_Star, CsR_Star !Sound speed behind left and right rarefactions |
94 | | REAL :: SL, SR !Left and right shock speeds |
95 | | REAL :: G1, G2, G3, G4, G5, G6, ppl, ppr |
96 | | |
97 | | CsL_Star = Cs_L*(p_Star/p_L)**(G3/G2) |
98 | | CsR_Star = Cs_R*(p_Star/p_R)**(G3/G2) |
99 | | |
100 | | G1 = gamma + 1.0 |
101 | | G2 = 2.0*gamma |
102 | | G3 = gamma - 1.0 |
103 | | ppl = p_Star/p_L |
104 | | ppr = p_Star/p_R |
105 | | G4 = G3/G1 |
106 | | G5 = G1/G2 |
107 | | G6 = G3/G2 |
108 | | |
109 | | IF(s.LE.u_Star)THEN |
110 | | ! (x,t) is to the left of contact |
111 | | IF(p_L.GE.p_Star)THEN |
112 | | !Left wave is a rarefaction, based on initial data |
113 | | !3 possible left data states then - WL, WL_Fan, W_Star - next we determine which |
114 | | ! PRINT*,'IT"S A RAREFACTION' |
115 | | |
116 | | !Are these negative quantities:? |
117 | | SHL = u_L - Cs_L |
118 | | STL = u_Star - CsL_Star |
119 | | |
120 | | IF(S.LE.SHL)THEN |
121 | | ! PRINT *, 'LEFT DATA STATE' |
122 | | !Left data state |
123 | | rhos = rho_L |
124 | | us = u_L |
125 | | ps = p_L |
126 | | ELSE |
127 | | |
128 | | ! IF((SHL.GE.S).AND.(S.LE.STL))THEN |
129 | | IF((SHL.LE.S).AND.(S.LE.STL)) THEN |
130 | | ! PRINT*, 'iNSIDE RARE WAVE' |
131 | | !Inside rarefaction fan |
132 | | rhos = rho_L*(2/G1 + G3/(G1*Cs_L)*(u_L - s))**(2/G3) |
133 | | us = 2/G1*(Cs_L + (G3/2)*u_L + s) |
134 | | ps = p_L*( 2/G1 + G3/(G1*Cs_L)*(u_L - s) )**(G2/G3) |
135 | | ELSE |
136 | | !In left star region |
137 | | ! PRINT *, 'IN STAR REGION' |
138 | | rhos = rho_L*ppl**(1.0/gamma) !follows from isentropic law |
139 | | us = u_Star |
140 | | ps = p_Star |
141 | | END IF |
142 | | |
143 | | END IF |
144 | | |
145 | | ELSE |
146 | | !Left wave is a shock |
147 | | !Two states possible - pre-shock, post-shock |
148 | | ! PRINT*,'IT"S A SHOCK ! ! !' |
149 | | SL = (u_L - Cs_L)*SQRT(G1/G2*ppl + G3/G2) |
150 | | IF(s.LE.SL)THEN |
151 | | !Data state is left state/pre-shock |
152 | | rhos = rho_L |
153 | | us = u_L |
154 | | ps = p_L |
155 | | ELSE |
156 | | !Data state is post-shock |
157 | | rhos = rho_L*((ppl + G3/G1)/((G3/G1)*ppl + 1.0)) |
158 | | us = u_Star |
159 | | ps = p_Star |
160 | | END IF |
161 | | END IF |
162 | | |
163 | | ELSE |
164 | | |
165 | | !(x,t) is on right of contact |
166 | | IF(p_Star.LE.p_R)THEN |
167 | | !Rarefaction, and 3 wave states possible: wR, WRFan, W*R |
168 | | SHR = Cs_R + u_R |
169 | | STR = CsR_Star + u_Star |
170 | | IF(S.LE.STR)THEN |
171 | | !In r star region |
172 | | rhos = rho_R*ppr**(1.0/gamma) !follows from isentropic law -- CHECK? |
173 | | us = u_Star |
174 | | ps = p_Star |
175 | | ELSE |
176 | | IF((STR.LE.S).AND.(S.LE.SHR))THEN |
177 | | !Inside right rarefaction fan |
178 | | rhos = rho_R*(2/G1 - G3/(G1*Cs_R)*(u_R - s))**(2/G3) |
179 | | us = 2/G1*(-Cs_R + (G3/2)*u_R + s) |
180 | | ps = p_R*( 2/G1 - G3/(G1*Cs_R)*(u_R - s) )**(G2/G3) |
181 | | !Check these expressions |
182 | | ELSE |
183 | | !In right data state |
184 | | rhos = rho_R |
185 | | us = u_R |
186 | | ps = p_R |
187 | | END IF |
188 | | END IF |
189 | | ELSE |
190 | | !Right wave is a shock |
191 | | SR = (u_R + Cs_R)*SQRT(G1/G2*ppr + G3/G2) |
192 | | IF(s.LE.SR)THEN |
193 | | !In post-shock region |
194 | | rhos = rho_R*((ppr + G3/G1)/((G3/G1)*ppr + 1.0)) |
195 | | us = u_Star |
196 | | ps = p_Star |
197 | | ELSE |
198 | | !In pre-shock region |
199 | | rhos = rho_R |
200 | | us = u_R |
201 | | ps = p_R |
202 | | END IF |
203 | | END IF |
204 | | END IF |
205 | | |
206 | | |
207 | | END SUBROUTINE SampleExact |
208 | | |
209 | | |
210 | | SUBROUTINE Find_Pstar(p, u) |
211 | | !Does mpa NEED to be read into this subroutine, if it is already initialized in main body of program? |
212 | | !----------------------------------------------------------------------------------------------- |
213 | | ! Implements Newton's iterative method to solve for p_star |
214 | | !----------------------------------------------------------------------------------------------- |
215 | | REAL, INTENT(OUT) :: p, u |
216 | | REAL :: p0 ! Initial estimate of P_star |
217 | | REAL, PARAMETER :: tol = 0.0000001 |
218 | | REAL :: change ! Relative change in pressure due to iteration |
219 | | REAL :: pOld, pNew! Cs_L, Cs_R, rho_L, rho_R, p_L, p_R, u_L, u_R -- these should be all accessible as they are global vars |
220 | | INTEGER :: i, NmrItr |
221 | | REAL :: f_p, f_pD, FL, FLD, FR, FRD ! pressure function in Toro |
222 | | REAL :: Delta |
223 | | NAMELIST /Itr/ NmrItr |
224 | | |
225 | | !statement labels are not global: |
226 | | OPEN(UNIT = 3, FILE = 'initial.data') |
227 | | READ(3, NML = Itr) |
228 | | CLOSE(3) |
229 | | |
230 | | |
231 | | !Get estimate for P_star |
232 | | CALL P_estimate(p0) |
233 | | |
234 | | |
235 | | pOld = p0 ! Initialize pOld |
236 | | |
237 | | !Check that the vars are global: |
238 | | ! PRINT *, 'u_L, p_L, rho_L, cs_L =', u_L, p_L, rho_L, cs_L |
239 | | |
240 | | OPEN(UNIT = 2, FILE = 'exact.out', STATUS = 'UNKNOWN') |
241 | | WRITE(2,*) '--------------------------------------------------------------------------' |
242 | | WRITE(2,*) ' Iteration number Change ' |
243 | | WRITE(2,*) '--------------------------------------------------------------------------' |
244 | | |
245 | | !Need define Cs_L here too or main program enough? |
246 | | DO 10 i = 1,NmrItr |
247 | | CALL PressFunct(FL, FLD, pOld, rho_L, p_L, Cs_L) |
248 | | CALL PressFunct(FR, FRD, pOld, rho_R, p_R, Cs_R) |
249 | | f_p = FL + FR + U_diff |
250 | | f_pD = FLD + FRD |
251 | | Delta = f_p/f_pD |
252 | | pNew = pOld - Delta ! This is corrected p. |
253 | | change = 2.0*ABS((pNew - pOld)/(pNew + pOld)) |
254 | | WRITE(2,*) i, change |
255 | | IF (change.LE.tol) GOTO 20 |
256 | | IF (pNew.LT.0.0) pNew = tol |
257 | | pOld = pNew |
258 | | 10 Continue |
259 | | |
260 | | WRITE(2,*) 'Newton Rhapson Method Diverged!' |
261 | | |
262 | | 20 WRITE(2,*) 'Pressure in Star Region and U in star region' |
263 | | p = pNew/MPA |
264 | | u = (1.0/2.0)*(u_L + u_R) + (1.0/2.0)*(fR - fL) |
265 | | WRITE(2,*) 'p_Star = ', p |
266 | | WRITE(2,*) 'u_Star = ', u |
267 | | |
268 | | CLOSE(2) |
269 | | |
270 | | END SUBROUTINE Find_Pstar |
271 | | |
272 | | SUBROUTINE P_estimate(pEst) |
273 | | !Employs the subroutine from Toro for estimating initial P_star |
274 | | |
275 | | REAL,INTENT(OUT) :: pEst |
276 | | REAL :: G1, G2, G3, G4, G5, G6, G7, G8 |
277 | | REAL :: CUP, GEL, GER, pMax, pMin, PPV, PQ, PTL, PTR, QMAX, QUSER, UM |
278 | | |
279 | | G1 = (gamma - 1.0)/(2.0*gamma) |
280 | | G2 = (gamma + 1.0)/(2.0*gamma) |
281 | | G3 = 2.0*gamma/(gamma - 1.0) |
282 | | G4 = 2.0/(gamma - 1.0) |
283 | | G5 = 2.0/(gamma + 1.0) |
284 | | G6 = (gamma - 1.0)/(gamma + 1.0) |
285 | | G7 = (gamma - 1.0)/2.0 |
286 | | G8 = (gamma - 1.0) |
287 | | |
288 | | QUSER = 2.0 |
289 | | |
290 | | ! Guess P using the PVRS solver |
291 | | |
292 | | CUP = 0.25*(rho_L + rho_R)*(Cs_L + Cs_R) |
293 | | PPV = 0.5*(p_L + p_R) + 0.5*(u_L - u_R)*CUP |
294 | | PPV = MAX(0.0, PPV) |
295 | | PMIN = MIN(p_L, p_R) |
296 | | PMAX = MAX(p_L, p_R) |
297 | | QMAX = PMAX/PMIN |
298 | | |
299 | | IF (QMAX.LE.QUSER.AND.(PMIN.LE.PPV.AND.PPV.LE.PMAX)) THEN |
300 | | !SELECT PVRS SOLVER |
301 | | pEst = PPV |
302 | | |
303 | | ELSE |
304 | | |
305 | | IF(PPV.LT.PMIN) THEN |
306 | | !SELECT 2-RAREFACTION RS |
307 | | PQ = (p_L/p_R)**G1 |
308 | | UM = (PQ*u_L/Cs_L + u_R/Cs_R + G4*(PQ - 1.0))/(PQ/Cs_L + 1.0/Cs_R) |
309 | | PTL = 1.0 + G7*(u_L - UM)/Cs_L |
310 | | PTR = 1.0 + G7*(UM - u_R)/Cs_R |
311 | | pEst = 0.5*(p_L*PTL**G3 + p_R*PTR**G3) |
312 | | |
313 | | ELSE |
314 | | !Select the 2-shock RS with PVRS as estimate |
315 | | |
316 | | GEL = SQRT((G5/rho_L)/(G6*p_L + PPV)) |
317 | | GER = SQRT((G5/rho_R)/(G6*p_R + PPV)) |
318 | | pEst = (GEL*p_L + GER*p_R - (u_R - u_L))/(GEL + GER) |
319 | | |
320 | | END IF |
321 | | |
322 | | END IF |
323 | | |
324 | | |
325 | | END SUBROUTINE P_estimate |
326 | | |
327 | | SUBROUTINE PressFunct(f, fD, pItr, rho, p, Cs) |
328 | | |
329 | | |
330 | | REAL, INTENT(OUT) :: f, fd ! Pressure function and its derivative in Toro |
331 | | REAL, INTENT(IN) :: pItr ! Pressure correction as computed by Find_Pstar |
332 | | REAL, INTENT(IN) :: rho, p, Cs !Initial data |
333 | | REAL :: A, B ! Constants in pressure function |
334 | | |
335 | | |
336 | | A = 2.0/((gamma+1.0)*rho) |
337 | | B = ((gamma-1.0)/(gamma+1.0))*p |
338 | | |
339 | | |
340 | | IF(pItr.LT.p)THEN !Rarefaction wave |
341 | | |
342 | | f = (2.0*Cs/(gamma - 1.0))*((pItr/p)**((gamma-1.0)/(2.0*gamma)) - 1.0) |
343 | | fd = (1.0/(rho*Cs))*(pItr/p)**(-(gamma+1)/(2*gamma)) |
344 | | |
345 | | ELSE |
346 | | |
347 | | !Shock |
348 | | f = (pItr - p)*SQRT(A/(pItr+B)) |
349 | | fd = Sqrt(A /(B + pItr))*(1 - (pItr - p)/(2*(B+pItr))) |
350 | | |
351 | | END IF |
352 | | |
353 | | END SUBROUTINE PressFunct |
354 | | |
355 | | END PROGRAM ExactRiemannSolver |
356 | | |
| 14 | 1. |