solutions.f90
Go to the documentation of this file.
1 !#############################################################################
2 !# #
3 !# fosite - 3D hydrodynamical simulation program #
4 !# module: solutions.f90 #
5 !# #
6 !# Copyright (C) 2013 Manuel Jung <mjung@astrophysik.uni-kiel.de> #
7 !# #
8 !# This program is free software; you can redistribute it and/or modify #
9 !# it under the terms of the GNU General Public License as published by #
10 !# the Free Software Foundation; either version 2 of the License, or (at #
11 !# your option) any later version. #
12 !# #
13 !# This program is distributed in the hope that it will be useful, but #
14 !# WITHOUT ANY WARRANTY; without even the implied warranty of #
15 !# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or #
16 !# NON INFRINGEMENT. See the GNU General Public License for more #
17 !# details. #
18 !# #
19 !# You should have received a copy of the GNU General Public License #
20 !# along with this program; if not, write to the Free Software #
21 !# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #
22 !# #
23 !#############################################################################
24 
25 !----------------------------------------------------------------------------!
31 !----------------------------------------------------------------------------!
32 
33 MODULE solutions
34  USE roots, ONLY: getroot
35  IMPLICIT NONE
36  !--------------------------------------------------------------------------!
37  PRIVATE
38  REAL :: rho_l,u_l,p_l,a_l,b_l,c_l,&
40  REAL :: gam_p1, gam_m1, r0, rt, vmin, vmax, &
41  vshock, n1, n2, n3, n4, n5
42  REAL :: r, xi, vxi, gxi, zxi, zgxi, xacc
43  REAL :: e0, rho0, p1
44  !--------------------------------------------------------------------------!
45  PUBLIC :: &
46  riemann, &
47  sedov
48  !--------------------------------------------------------------------------!
49 CONTAINS
50  SUBROUTINE riemann(x0,gamma_,rho_l_,u_l_,p_l_,rho_r_,u_r_,p_r_,t,x,pvar)
51  IMPLICIT NONE
52  !------------------------------------------------------------------------!
53  REAL :: gamma_,t,x0,rho_l_,u_l_,p_l_,rho_r_,u_r_,p_r_
54  REAL,DIMENSION(:) :: x
55  REAL,DIMENSION(:,:) :: pvar
56  !------------------------------------------------------------------------!
57  INTEGER :: i
58  Real :: rho_lstar, rho_rstar, p_star, u_star, &
59  c_lstar, c_rstar, &
60  s_l, s_hl, s_tl, s_r, s_hr, s_tr
61  INTEGER :: error
62  !------------------------------------------------------------------------!
63  gamma = gamma_ !1.4 !heat capacity ratio
64 
65  rho_l = rho_l_
66  rho_r = rho_r_
67 
68  u_l = u_l_
69  u_r = u_r_
70 
71  p_l = p_l_
72  p_r = p_r_
73 
74  ! sound speeds of far regions
75  c_l = sqrt(gamma*p_l/rho_l)
76  c_r = sqrt(gamma*p_r/rho_r)
77 
78  a_l = 2.0/((gamma+1.0)*rho_l)
79  a_r = 2.0/((gamma+1.0)*rho_r)
80 
81  b_l = p_l*(gamma-1.0)/(gamma+1.0)
82  b_r = p_r*(gamma-1.0)/(gamma+1.0)
83 
84  ! calculate p_star by findung the root of function f
85  ! upper limit is just a somewhat big number. Is this really always
86  ! sufficient?
87  CALL getroot(f, 0., 2.e+3, p_star, error)
88  !p_star = GetRoot_andbjo(f, 0., 1.E+4,1.E-6)
89 
90  u_star = 0.5*((u_l + u_r) + ( f_x(p_star, rho_r, u_r, p_r, a_r, b_r, c_r) &
91  - f_x(p_star, rho_l, u_l, p_l, a_l, b_l, c_l)))
92 
93  IF (p_star > p_l) THEN
94  !left shock
95  rho_lstar = rho_l * ( ((p_star/p_l) + (gamma-1.0)/(gamma+1.0)) &
96  / (((gamma-1.0)/(gamma+1.0))*(p_star/p_l) + 1.0))
97  ELSE
98  !left rarefaction
99  rho_lstar = rho_l * (p_star/p_l)**(1.0/gamma)
100  END IF
101 
102  IF (p_star > p_r) THEN
103  !right shock
104  rho_rstar = rho_r * ( ((p_star/p_r) + (gamma-1.0)/(gamma+1.0)) &
105  /(((gamma-1.0)/(gamma+1.0))*(p_star/p_r) + 1.0))
106  ELSE
107  !right rarefaction
108  rho_rstar = rho_r * (p_star/p_r)**(1.0/gamma)
109  END IF
110 
111  ! sound speeds of star regions
112  c_lstar = c_l * (p_star/p_l)**((gamma-1.0)/(2.0*gamma))
113  c_rstar = c_r * (p_star/p_r)**((gamma-1.0)/(2.0*gamma))
114 
115  ! shock speeds
116  s_l = u_l - c_l * sqrt( ((gamma+1.0)/(2.0*gamma))*(p_star/p_l) + (gamma-1.0)/(2.0*gamma))
117  s_r = u_r + c_r * sqrt( ((gamma+1.0)/(2.0*gamma))*(p_star/p_r) + (gamma-1.0)/(2.0*gamma))
118 
119  ! head speed of rarefraction waves
120  s_hl = u_l - c_l
121  s_hr = u_r + c_r
122  ! tail speed of rarefraction waves
123  s_tl = u_star - c_lstar
124  s_tr = u_star + c_rstar
125 
126  DO i=1,SIZE(x)
127  CALL sample(x(i),pvar(i,1),pvar(i,2),pvar(i,3))
128  END DO
129 
130  CONTAINS
131  SUBROUTINE sample(x,rho,u,p)
132  IMPLICIT NONE
133  !----------------------------------------------------------------------!
134  REAL :: x, rho, u, p
135  !----------------------------------------------------------------------!
136  REAL :: S
137  !----------------------------------------------------------------------!
138  INTENT(IN) :: x
139  INTENT(OUT) :: rho, u, p
140  !----------------------------------------------------------------------!
141 
142  !Sampling the solution
143  s = (x-x0)/t
144  IF (s <= u_star) THEN
145  !left side of contact
146  IF (p_star > p_l) THEN
147  !left shock
148  IF (s < s_l) THEN
149  !far left region
150  rho = rho_l
151  u = u_l
152  p = p_l
153  ELSE
154  !left star region
155  rho = rho_lstar
156  u = u_star
157  p = p_star
158  END IF
159  ELSE
160  !left fan
161  IF (s < s_hl) THEN
162  !far left region
163  rho = rho_l
164  u = u_l
165  p = p_l
166  ELSE IF (s > s_tl) THEN
167  !left star region
168  rho = rho_lstar
169  u = u_star
170  p = p_star
171  ELSE
172  !left fan region
173  rho = rho_l * ( 2.0/(gamma+1.0) + ((gamma-1.0)/((gamma+1.0)*c_l)) &
174  *(u_l - (x-x0)/t) ) ** (2.0/(gamma-1.0))
175  u = 2.0/(gamma+1.0) * (c_l + (gamma-1.0)*u_l/2.0 + (x-x0)/t)
176  p = p_l * ( 2.0/(gamma+1.0) + ((gamma-1.0)/((gamma+1.0)*c_l)) &
177  * (u_l - (x-x0)/t) ) ** (2.0*gamma/(gamma-1.0))
178  END IF
179  END IF
180  ELSE
181  !right side of contact
182  IF (p_star > p_r) THEN
183  !right shock
184  IF (s > s_r) THEN
185  rho = rho_r
186  u = u_r
187  p = p_r
188  ELSE
189  rho = rho_rstar
190  u = u_star
191  p = p_star
192  END IF
193  ELSE
194  !right fan
195  IF (s > s_hr) THEN
196  rho = rho_r
197  u = u_r
198  p = p_r
199  ELSE IF (s < s_tr) THEN
200  rho = rho_rstar
201  u = u_star
202  p = p_star
203  ELSE
204  rho = rho_r * ( 2.0/(gamma+1.0) - ((gamma-1.0)/((gamma+1.0)*c_r)) &
205  * (u_r - (x-x0)/t) ) ** (2.0/(gamma-1.0))
206  u = 2.0/(gamma+1.0) * ( -c_r + (gamma-1.0)*u_r/2.0 + (x-x0)/t)
207  p = p_r * ( 2.0/(gamma+1.0) - ((gamma-1.0)/((gamma+1.0)*c_r)) &
208  * (u_r - (x-x0)/t) ) ** (2.0*gamma/(gamma-1.0))
209  END IF
210  END IF
211  END IF
212  END SUBROUTINE sample
213  END SUBROUTINE riemann
214 
215  SUBROUTINE sedov(gamma_, E0_, rho0_, P1_, time, dim, x, pvar)
216  IMPLICIT NONE
217  !----------------------------------------------------------------------!
218  REAL, INTENT(IN) :: gamma_, e0_, rho0_, p1_, time
219  INTEGER, INTENT(IN) :: dim
220  REAL, DIMENSION(:), INTENT(IN) :: x
221  REAL, DIMENSION(:,:), INTENT(INOUT) :: pvar
222  !----------------------------------------------------------------------!
223  REAL, PARAMETER :: eps = 1.0d-09
224  INTEGER, PARAMETER :: maxit = 1.0d+08
225  INTEGER :: i
226  !----------------------------------------------------------------------!
227  gamma = gamma_
228  e0 = e0_
229  rho0 = rho0_
230  p1 = p1_
231  gam_p1 = gamma + 1.0
232  gam_m1 = gamma - 1.0
233 
234  SELECT CASE(dim)
235  CASE(2)
236  r0 = 1.0
237  rt = r0*(e0*time**2/rho0)**0.25
238  vmin = 1.0 / gamma
239  vmax = 2.0 / gamma
240  vshock = 0.5 *rt/time
241  n1 = -2.0
242  n2 = 2.0*gam_m1/gamma
243  n3 = 1.0/gamma
244  n4 = -n1 / (2.0-gamma)
245  n5 = -2.0 / (2.0-gamma)
246  CASE(3)
247  r0 = 1.033 ! for gamma=7/5, see Padmanabhan: Theo. Astro., Vol 1, p.409
248  rt = r0*(e0*time**2/rho0)**0.2
249  vmin = 1./gamma
250  vmax = 5./(3.*gamma-1.)
251  vshock = 2.*rt/(5.*time)
252  n1 = -(13.*gamma**2.-7.*gamma+12.) / ((3.*gamma-1.)*(2.*gamma+1.))
253  n2 = 5.*gam_m1 / (2.*gamma+1.)
254  n3 = 3. / (2.*gamma+1.)
255  n4 = -n1 / (2.-gamma)
256  n5 = -2. / (2.-gamma)
257  END SELECT
258  ! accuracy
259  xacc = eps
260 
261  ! main loop
262  DO i=1, SIZE(x)
263  r = x(i)
264  xi = r/rt
265  IF (xi.LE.1.0) THEN
266  ! Newton-Raphson to solve the implicit equation
267  IF (dim.EQ.2) THEN
269  gxi = gam_p1/gam_m1*(gam_p1/gam_m1*(gamma*vxi-1.0))**n3 &
270  *(gam_p1/2.0*(2.0-gamma*vxi))**n4 &
271  *(gam_p1/gam_m1*(1.0-vxi))**n5
272  ELSE
274  gxi = gam_p1/gam_m1*(gam_p1/gam_m1*(gamma*vxi-1.))**n3 &
275  *(gam_p1/(7.-gamma)*(5.-(3.*gamma-1.)*vxi))**n4 &
276  *(gam_p1/gam_m1*(1.-vxi))**n5
277  END IF
278  zxi = gamma*gam_m1*(1.-vxi)*vxi*vxi/(2.*(gamma*vxi-1.))
279 ! IF (xi.GT.0.01) THEN
280 ! zgxi = 0.5*gam*gam_p1*(gam_p1/gam_m1)**(n3+n5) * vxi**2 &
281 ! *(gam*vxi-1.)**(n3-1.) * (1.-vxi)**(n5+1.) &
282 ! *(gam_p1/(7.-gam)*(5.-(3.*gam-1.)*vxi))**n4
283 ! ELSE
284 ! zgxi = 0.5*gam*gam_m1*(1.-vxi)*vxi**2 * xi**(5/n2*(n3-1.))
285 ! END IF
286 ! CALL funcd2D(vxi,fv,dfv)
287 ! WRITE (*,"(5(ES15.7))") xi,vxi,gxi,zxi,fv
288 ! STOP
289  ELSE
290  vxi = 0.
291  gxi = 1.
292  zxi = ((2.+dim)*time/(2.*r))**2 * gamma*p1/rho0
293  zgxi= zxi
294  END IF
295  ! set primitive variables
296  pvar(i,1) = rho0*gxi
297  pvar(i,2) = vshock*xi*vxi
298  pvar(i,3) = pvar(i,1)/gamma*zxi*(2.*r/((2.+dim)*time))**2
299 ! pvar(i,3) = Control%rho0/gam*(2.*r/(5.*Control%time))**2 * zgxi
300  END DO
301 
302  CONTAINS
303 
304  FUNCTION getroot_test(funcd,x1,x2,xacc) RESULT(root)
305  IMPLICIT NONE
306  !------------------------------------------------------------------------!
307  REAL, INTENT(IN) :: x1,x2,xacc
308  REAL :: root
309  !------------------------------------------------------------------------!
310  INTERFACE
311  SUBROUTINE funcd(x,fx,dfx)
312  IMPLICIT NONE
313  REAL, INTENT(IN) :: x
314  REAL, INTENT(OUT) :: fx,dfx
315  END SUBROUTINE funcd
316  END INTERFACE
317  !------------------------------------------------------------------------!
318  REAL :: fm,dfm,fl,dfl,fr,dfr
319  REAL :: xm,xl,xr,dx
320  INTEGER :: i
321  !------------------------------------------------------------------------!
322  ! compute left and right function values
323  xl = min(x1,x2)
324  xr = max(x1,x2)
325  CALL funcd(xl,fl,dfl)
326  CALL funcd(xr,fr,dfr)
327  ! check if root is within the interval [x1,x2]
328  IF (fl*fr.GT.0.0) THEN
329  WRITE (*,*) xl, xr,fl, fr,gamma, "Error: f(x1)*f(x2) should be < 0, aborting!"
330  stop
331  END IF
332  ! main loop
333  DO i=1,maxit
334  ! WRITE (*,"(4(ES20.12))") xl,fl,xr,fr
335  ! regular falsi
336  dx = fl*(xl-xr)/(fl-fr)
337  xm = xl - dx
338  root = xm
339  CALL funcd(xm,fm,dfm)
340  ! check abort criteron
341  IF (abs(fm).LT.xacc) THEN
342  EXIT
343  END IF
344  IF (fm*fl.GT.0.0) THEN
345  xl=xm
346  fl=fm
347  ELSE
348  xr=xm
349  fr=fm
350  END IF
351  END DO
352  IF (i.GT.maxit) THEN
353  WRITE (*,*) "WARNING: limit of iterations exceeded!"
354  END IF
355  END FUNCTION getroot_test
356 
357  END SUBROUTINE sedov
358 
359 
360  ! the root of this function gives p_star
361  !REAL FUNCTION f(p)
362  PURE SUBROUTINE f(p,fx,plist)
363  IMPLICIT NONE
364  !----------------------------------------------------------------------!
365  REAL, INTENT(IN) :: p
366  REAL, INTENT(OUT) :: fx
367  REAL, INTENT(IN), DIMENSION(:), OPTIONAL :: plist
368  !----------------------------------------------------------------------!
369  fx = f_x(p, rho_l, u_l, p_l, a_l, b_l, c_l) &
370  + f_x(p, rho_r, u_r, p_r, a_r, b_r, c_r) &
371  + (u_r - u_l)
372  END SUBROUTINE f
373 
374  !left side or right side function
375  REAL PURE FUNCTION f_x(p, rho_x, u_x, p_x, A_x, B_x, c_x)
376  IMPLICIT NONE
377  !----------------------------------------------------------------------!
378  REAL, INTENT(IN) :: p, rho_x, u_x, p_x, a_x, b_x, c_x
379  !----------------------------------------------------------------------!
380  IF (p > p_x) THEN
381  f_x = (p-p_x) * sqrt(a_x/(p+b_x))
382  ELSE
383  f_x = (2.0*c_x/(gamma-1.0)) * ((p/p_x)**((gamma-1.0)/(2.0*gamma)) - 1.0)
384  END IF
385  END FUNCTION f_x
386 
387 SUBROUTINE funcd2d(y,fy,dfy)
388  IMPLICIT NONE
389  !------------------------------------------------------------------------!
390  REAL, INTENT(IN) :: y
391  REAL, INTENT(OUT) :: fy,dfy
392  !------------------------------------------------------------------------!
393  REAL :: Ay,dAy,By,dBy,Cy,dCy
394  !------------------------------------------------------------------------!
395 
396  ay = 2./(gam_p1*y)
397  day= -ay/y
398  by = gam_p1/2. * (2.-gamma*y)
399  dby= -gam_p1/2. * gamma
400  cy = gam_p1/gam_m1*(gamma*y-1.0)
401  dcy= gamma*gam_p1/gam_m1
402  fy = ay**2 * by**n1 * cy**n2 - xi**4
403  dfy= day*by*cy + ay*dby*cy + ay*by*dcy
404 ! PRINT "(A,4(ES14.6))", "xi,n1,n2 = ", xi,n1,n2
405 ! PRINT "(A,3(ES14.6))", "A(y),B(y),C(y) = ", Ay,By,Cy
406 ! PRINT "(A,3(ES14.6))", "y,f(y),df(y) = ", y,fy,dfy
407 ! PRINT "(A,3(ES14.6))", "gamma,gam_p1,gam_m1 = ", gamma,gam_p1,gam_m1
408 END SUBROUTINE funcd2d
409 
410 
411 SUBROUTINE funcd3d(y,fy,dfy)
412  IMPLICIT NONE
413  !------------------------------------------------------------------------!
414  REAL, INTENT(IN) :: y
415  REAL, INTENT(OUT) :: fy,dfy
416  !------------------------------------------------------------------------!
417  REAL :: Ay,dAy,By,dBy,Cy,dCy
418  !------------------------------------------------------------------------!
419 
420  ay = 2./(gam_p1*y)
421  day= -ay/y
422  by = abs(gam_p1/(7.-gamma)*(5.-(3*gamma-1.)*y))
423  dby= -gam_p1/(7.-gamma)*(3*gamma-1.)
424  cy = gam_p1/gam_m1*(gamma*y-1.)
425  dcy= gamma*gam_p1/gam_m1
426  IF (abs(gamma*y-1.).LT.1.0d-20) THEN
427  fy = -xi**5
428  ELSE
429  fy = ay**2 * by**n1 * cy**n2 - xi**5
430  END IF
431  fy = ay**2 * by**n1 * cy**n2 - xi**5
432  dfy= day*by*cy + ay*dby*cy + ay*by*dcy
433 ! PRINT "(A,ES14.6)","xi = ", xi
434 ! PRINT "(A,3(ES14.6))", "A(y),B(y),C(y) = ", Ay,By,Cy
435 ! PRINT "(A,3(ES14.6))", "y,f(y),df(y) = ", y,fy,dfy
436 END SUBROUTINE funcd3d
437 
438 
439 END MODULE
440 
real vmax
Definition: solutions.f90:40
subroutine error(this, modproc, msg, rank, node_info)
Print error message on standard error and terminate the program.
pure subroutine funcd(y, fy, dfy, plist)
Definition: bondi2d.f90:416
real u_l
Definition: solutions.f90:38
real gam_p1
Definition: solutions.f90:40
real b_l
Definition: solutions.f90:38
real xacc
Definition: solutions.f90:42
real gam_m1
Definition: solutions.f90:40
subroutine, public sedov(gamma_, E0_, rho0_, P1_, time, dim, x, pvar)
Definition: solutions.f90:216
real a_l
Definition: solutions.f90:38
real gxi
Definition: solutions.f90:42
real c_l
Definition: solutions.f90:38
real zgxi
Definition: solutions.f90:42
real vmin
Definition: solutions.f90:40
subroutine sample(x, rho, u, p)
Definition: solutions.f90:132
real vxi
Definition: solutions.f90:42
real u_r
Definition: solutions.f90:38
real p_l
Definition: solutions.f90:38
real rho0
Definition: solutions.f90:43
subroutine funcd2d(y, fy, dfy)
Definition: solutions.f90:388
real rho_l
Definition: solutions.f90:38
real zxi
Definition: solutions.f90:42
real pure function f_x(p, rho_x, u_x, p_x, A_x, B_x, c_x)
Definition: solutions.f90:376
real p_r
Definition: solutions.f90:38
pure subroutine f(p, fx, plist)
Definition: solutions.f90:363
root finding subroutines
Definition: roots.f90:45
real b_r
Definition: solutions.f90:38
subroutine, public riemann(x0, gamma_, rho_l_, u_l_, p_l_, rho_r_, u_r_, p_r_, t, x, pvar)
Definition: solutions.f90:51
real c_r
Definition: solutions.f90:38
real vshock
Definition: solutions.f90:40
real function getroot_test(funcd, x1, x2, xacc)
Definition: solutions.f90:305
real rho_r
Definition: solutions.f90:38
subroutine funcd3d(y, fy, dfy)
Definition: solutions.f90:412
real a_r
Definition: solutions.f90:38
real gamma
Definition: solutions.f90:38