Related
I am getting an error while I run this code. When I run the code with small L's like L=16 or L=32 I get no error but in L = 128 or L=96 after 7000-8000 steps I get following error :
Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
Backtrace for this error:
#0 0x7FBA5CAC3E08
#1 0x7FBA5CAC2F90
#2 0x7FBA5C1E84AF
#3 0x402769 in MAIN__ at newhys.f90:?
Segmentation fault (core dumped)
This is the full code :
SUBROUTINE init_random_seed()
implicit none
INTEGER :: i, n, clock
INTEGER, DIMENSION(:), ALLOCATABLE :: seed
CALL RANDOM_SEED(size = n)
ALLOCATE(seed(n))
CALL SYSTEM_CLOCK(COUNT=clock)
seed = clock + 37 * (/ (i - 1, i = 1, n) /)
CALL RANDOM_SEED(PUT = seed)
DEALLOCATE(seed)
END SUBROUTINE
!end module
Program Activ_mater
USE OMP_LIB
Implicit none
Integer,parameter :: time=1000000000, L=128, N = L**2*2
Integer,parameter:: n_thread = 8
Real(8),parameter :: pi = 3.14159265359
Real(8),parameter :: v0 = 0.50, alpha = 1.0/36.0
real(8)START,END_1 ,eta
type block_p
Integer :: partical_N
Integer :: particle_ad(10*L)
end type
Type(block_p) ,pointer,dimension(:,:) :: C
Real(8),allocatable :: x(:), y(:) , phi,angle_new(:),angle(:)
Real(8) :: sum_a, sum_b,x_in, y_in, x_out, y_out, avrage_t, r,ra,eta1(5)
Integer :: i,j,t,n_p,I_b,J_b,b_l,neighbor_i(9),neighbor_j(9),A,n_p_b,ne = 1,stateta=0,ot=0,op=175
character(len=10)::name1
call omp_set_num_threads(n_thread)
call init_random_seed()
eta1=(/2.100,2.116,2.120,2.126,2.128/) ! The value of ETA
allocate(x(2*n), y(2*n) , phi,angle_new(2*N),angle(2*N))
allocate(C(2*L,2*L))
C(:,:)%partical_N=0
do i =1,N
call random_number(ra)
x(i)=ra*L
I_b = int(x(i))+1
call random_number(ra)
y(i)=ra*L
J_b = int(y(i))+1
call random_number(ra)
angle(i)=ra*2.0*pi
C(I_b,J_b)%partical_N = C(I_b,J_b)%partical_N + 1 !Number of particle in block C(I_b,J_b)
C(I_b,J_b)%particle_ad( C(I_b,J_b)%partical_N ) = i ! The particle number in block C(I_b,J_b)
end do
! loop for eta
eta= 0.0
write(name1,'(f5.3)')eta
open(unit=10, file='Hysteresis,'//trim(name1)//'.dat')
!=====================explanation of system====================================
print*,'==========================================================================='
print*, 'eta = ', etA ,' ',' alpha = ',alpha
print*,'L=',L ,' ', 'Particle Number=', N,' ','Density=', N/L**2
print*,'==========================================================================='
!==============================================================================
START = omp_get_wtime()
do t =1,time
if (ot == 300000 )then
stateta = 0
ot = 0
op = op + 1
end if
if (stateta == 0 )then
eta = eta + ((1.0/3.0) * (10E-6))
endif
if (int(eta * 100) == op) then
stateta = 1
end if
angle_new(:)=0
!$OMP PARALLEL DEFAULT(PRIVATE) SHARED(x,y,angle,angle_new,c) firstprivate(eta)
!$OMP DO schedule(runtime)
do i =1, N
sum_a=0; sum_b=0;n_p=0
I_b = int(x(i))+1; J_b = int(y(i))+1 ! The block of particle i
! Now I should find nine neighbor of particle i-----------------------------------------------
neighbor_i=(/I_b+1, I_b, I_b-1, I_b, I_b+1, I_b-1, I_b-1, I_b+1, I_b/)
neighbor_j=(/J_b, J_b+1, J_b, J_b-1, J_b+1, J_b+1, J_b-1, J_b-1, J_b/)
do b_l = 1, 9
I_b = neighbor_i(b_l) ; J_b=neighbor_j(b_l)
if (I_b >L )I_b=1
if (I_b <1 )I_b=L
if (J_b >L )J_b=1
if (J_b <1 )J_b=L
!neighbor_i(b_l)=I_b; neighbor_j(b_l)=J_b
A = C( I_b, J_b )%partical_N ! number of particle in block C( neighbor_i(b_l), neighbor_j(b_l) )
!=============================================================================================
do n_p_b =1, A
j = C( I_b, J_b)%particle_ad(n_p_b) !particle j in the block C
if (i /= j )then
X_in = abs(max(x(i),x(j)) - min(x(i),x(j)));
Y_in = abs(max(y(i),y(j)) - min(y(i),y(j)));
X_out =L-X_in
Y_out =L-Y_in
r = sqrt(min(X_in,X_out)**2 + min(Y_in,Y_out)**2)
else
r=0.0
end if
if ( r < 1 )then
if ( j <= i )then
sum_A = sum_A + sin(angle(j));
sum_B = sum_B + cos(angle(j));
else
sum_A = sum_A + alpha*sin(angle(j));
sum_B = sum_B + alpha*cos(angle(j));
endif
n_p = n_p + 1;
endif
enddo
enddo
sum_A = sum_A/n_p; sum_B = sum_B/n_p
!if (int(sum_A*1e10) ==0 .and. int(sum_B*1e10) ==0 )print*,'zerrooo'
avrage_t=atan2(sum_A,sum_B);
if (avrage_t<0.0) then
avrage_t=avrage_t+2.0*pi;
endif
call random_number(ra)
angle_new(i)=avrage_t+eta*(ra-0.50)
if( angle_new(i)>=2*pi) angle_new(i)= angle_new(i)-2*pi
if( angle_new(i)<0) angle_new(i)= 2*pi+angle_new(i)
end do
!$OMP END DO
!$OMP END PARALLEL
angle = angle_new
C(:,:)%partical_N=0
! phi=0.0
do i=1, N
x(i) = x(i) + v0*sin(angle(i));
if (x(i)<1) x(i)=L+x(i)
if (x(i)>L) x(i)=x(i)-L
I_b = int(x(i))+1
y(i) = y(i)+ v0*cos(angle(i));
if (y(i)<1) y(i)=L+y(i)
if (y(i)>L) y(i)=y(i)-L
J_b = int(y(i))+1
C(I_b,J_b)%partical_N = C(I_b,J_b)%partical_N + 1
C(I_b,J_b)%particle_ad( C(I_b,J_b)%partical_N ) = i
end do
if (stateta == 1 )then
phi= sqrt((sum(sin(angle))**2+sum(cos(angle))**2))/N;
ot = ot + 1
end if
write(10,*)phi
if (mod(t,10)==0)then
! ave4_phi=sum(phi**4)/t;
! ave2_phi =sum(phi**2)/t;
!print* ,ave4_phi,ave2_phi
print*,'Time=',t,' ==== Eta : ',eta,"Ot : " , ot
end if
end do
END_1 = omp_get_wtime()
print*,'Run Time = ',end_1-start
End Program
P.S.(1) : I use omp lib to run my program parallel
P.S.(2) : I use gfortran to compile the code
P.S.(3) : Code compiled with -g -fcheck=all and gives me this error :
At line 155 of file z.f90 Fortran runtime error: Index '1281' of dimension 1 of array 'c%particle_ad' above upper bound of 1280
Thanks to you all
Your particle_ad arrays only have space for 10*L particles, but you appear to be trying to store up to N=2*L**2 particles in them (depending on how the random numbers fall). On average, each will have enough space, but your code will fail if too many particles fall into a single block, and (if I'm remembering the probabilities right) the chances of this happening increase as L increases.
You could solve this problem by replacing Integer :: particle_ad(10*L) with Integer :: particle_ad(N), but this will waste an awful lot of space.
A better solution would be to re-size the particle_ad arrays on the fly, making them bigger every time they get full. For convenience, you could wrap this behaviour in a method of the block_p class.
For example,
type block_p
Integer :: partical_N
Integer, allocatable :: particle_ad(:)
contains
subroutine add_particle(this, index)
class(block_p), intent(inout) :: this
integer, intent(in) :: index
integer, allocatable :: temp
! Update partical_N.
this%partical_N = this%partical_N + 1
! Resize particle_ad if it is full.
if (size(this%particle_ad)<this%partical_N) then
temp = this%particle_ad
deallocate(this%particle_ad)
allocate(this%particle_ad(2*this%partical_N))
this%particle_ad(:size(temp)) = temp
endif
! Add the new index to particle_ad.
this%particle_ad(this%partical_N) = index
end subroutine
end type
You could then replace the lines
C(I_b,J_b)%partical_N = C(I_b,J_b)%partical_N + 1
C(I_b,J_b)%particle_ad( C(I_b,J_b)%partical_N ) = i
with
call C(I_b,J_b)%add_particle(i)
Note that as each particle_ad array is now allocatable, you will need to initialise each array before you can call add_particle.
I am trying to write the code for Lid-Driven Cavity in Fortran.
When I want to run the code, suddenly the integer division by zero errors appears.
I know what is the problem but I don't know how I can solve it. I even changed some numbers in order to avoid this issue but again happened.
I uploaded the photo of the error
I searched about it and there are some answers for C++ but I could not find anything for Fortran.
Program Lid
implicit none
Integer :: I,J,nx, ny, dx, dy, L, W, Iteration, Max_Iteration , Re, M, N, dt
Real :: Delta
Real, allocatable :: u(:,:), v(:,:), p(:,:), u_old(:,:), v_old(:,:), p_old(:,:), X(:), Y(:)
!***************************************************!
PRINT *, "ENTER THE DESIRED POINTS ..."
PRINT *, "... IN X DIRECTION: SUGGESTED RANGE (20-200)"
READ*, M
PRINT *, "... IN Y DIRECTION: SUGGESTED RANGE (10-100)"
READ*, N
! Define Geometry
dt = 0.001
Delta = 2
Re = 100
L = 10
W = 10
dx = L /Real(M-1)
dy = W /Real(N-1)
ALLOCATE (X(M),Y(N),u(M,N),u_old(M,N),v(M,N),v_old(M,N),p(M,N),p_old(M,N))
! Grid Generation
Do I = 1, M
x(I) = (I-1)* dx
End Do
Do J=1 , N
y(J) = (J-1) * dy
End Do
! Boundray Condition
Do I=1 , M
u(I,1) = 0
u(1,I) = 0
u(M,I) = 0
u(I,M) = 1 ! Lid Velocity
End Do
Do J=1, N
v(J,1) = 0
v(1,J) = 0
v(J,N) = 0
v(M,J) = 0
End Do
! Initialization
Do I=2, M-1
Do J=2, N-1
u(I,J) = 0
v(I,J) = 0
p(I,J) = 0
End Do
End Do
! Solver
Do I=2, M-1
Do J=2, N-1
u_old(I,J) = u(I,J)
v_old(I,J) = v(I,J)
p_old(I,J) = p(I,J)
u(I,J) = - dt / 4* dx * (( u(I, J+1)+ u_old(I,J))**2 - (u_old(I, J)+u(I,J-1))**2) - dt / 4* dy * ((u_old(I,J)+ u(I-1,J)) &
* (v(I-1,J) + v(I-1, J+1)) - (u_old(I,J) + u(I+1,J)) * (v_old(I,J) + v(I,J+1))) - dt / dx *(p(I, J+1) - p(I,J)) &
+ dt / Re * ((u(I+1,J) - 2 * u_old(I,J) + u(I-1,J)) / dx**2 + (u(I,J+1) - 2 * u_old(I,J) + u(I,J+1)) / dy**2) + u_old(I,J)
v(I,J) = - dt / 4* dy * (( v(I-1, J)+ v(I-1,J+1))**2 - (v_old(I, J)+v(I,J+1))**2) - dt / 4* dx * ((u_old(I,J)+ u(I,J+1)) &
* (v(I,J+1) + v(I-1, J+1)) - (u_old(I,J) + u(I,J-1)) * (v_old(I,J) + v(I-1,J))) - dt / dy *(p(I, J+1) - p(I,J)) &
+ dt / Re * ((v(I+1,J) - 2 * v_old(I,J) + v(I-1,J)) / dx**2 + (v(I,J+1) - 2 * v_old(I,J) + v(I,J+1)) / dy**2) + v_old(I,J)
p(I,J) = - Delta * dt / 2 * ((u(I,J+1)+ u_old(I,J)) - (u_old(I,J) + u(I,J-1))) - Delta * dt / 2 &
* ((v(I-1,J)+ v(I-1,J+1)) - (v_old(I,J) + v(I,J+1)))
End Do
End Do
!-----------------------OUTPUTS GENERATION-----------------------------
OPEN (1,FILE='FIELD.PLT')
WRITE (1,*) 'VARIABLES=X,Y,u,v,p'
WRITE (1,*) 'ZONE I=',M,' J=',N
DO J=1,N
DO I=1,M
WRITE (1,*) X(I),Y(J),u(I,J),v(I,J),p(I,J)
END DO
END DO
End Program Lid
Assuming that the yellow arrow shown on the image indicates the line (72) where the exception occurred:
Apparently dx is or becomes zero, because that's the only devision done on that line.
You must know what it means when dx is zero or what causes it, unless it's a programming or data input issue that causes it.
In any case you must make sure that you don't execute that part of your code that divides by zero.
What you need to do to prevent this, fully depends on what your code is supposed to do. I can't help you with that.
I am trying to simulate harmonic oscillator by using Verlet Method(Original Verlet) in Fortran.
My research tells that the order of error should be 2 but my calculation showed the order of 1.
I couldn't find my mistake in my source code. What should I do?
Edit:
The algorithm I am using is below:
x(t+Δt) = 2x(t) - x(t-Δt) + Δt² F(t)/m
v(t) = {x(t+Δt) -x(t-Δt)}/2Δt
Where x(t) represents the position, v(t) represents velocity and F(t) represents Force. I recognize this is the Original Verlet described here
According to this site, the order of error should be at least O(Δt²) but the error of the order of my program plotted in gnuplot (below) does not have a order of O(Δt²).
program newton_verlet
implicit none
real*16, parameter :: DT = 3.0
real*16, parameter :: T0 = 0.0
real*16, parameter :: TEND = 2.0
integer, parameter :: NT = int(TEND/DT + 0.5)
real*16, parameter :: M = 1.0
real*16, parameter :: X0 = 1.0
real*16, parameter :: V0 = 0.0
real*16 x,v,t,xold,xnew,vnew,ek,ep,et,f,h
integer it,n
do n=0,20
h = DT/2**n
x = X0
v = V0
ek = 0.5*M*v*v
ep = x*x/2
et = ek + ep
xold = x - v*h
do it = 1,2**n
! f = -x
f = -x
xnew = 2.0*x - xold + f*h*h/M
v = (xnew-xold)/(2.0*h)
ek = 0.5*M*v*v
ep = 0.5*xnew*xnew
et = ek + ep
xold = x
x = xnew
end do
write(*,*) h,abs(x-cos(DT))+abs(v+sin(DT))
end do
end program
Above program calculates the error of calculation for the time step h.
According to the Wiki page for Verlet integrators, it seems that we need to use a more accurate way of setting the initial value of xold (i.e., include terms up to the force) to get the global error of order 2. Indeed, if we modify xold as
program newton_verlet
implicit none
real*16, parameter :: DT = 3.0
real*16, parameter :: M = 1.0
real*16, parameter :: X0 = 1.0
real*16, parameter :: V0 = 0.0
real*16 x,v,xold,xnew,f,h
integer it,n
do n = 0, 20
h = DT / 2**n
x = X0
v = V0
f = -x
! xold = x - v * h !! original
xold = x - v * h + f * h**2 / (2 * M) !! modified
do it = 1, 2**n
f = -x
xnew = 2 * x - xold + f * h * h / M
xold = x
x = xnew
end do
write(*,*) log10( h ), log10( abs(x - cos(DT)) )
end do
end program
the global error becomes of order 2 (please see the log-log plot below).
I've written a program that successfully shows a simple limit cycle for the Duffing equation. However, I now need to plot the Poincaré section for this case.
I need to do this by taking snapshots of the Phase-Space diagram at regular time intervals, such that t*omega = 2*pi*n. As I have omega set to 1 for this case, this is just when t = 2*pi*n. I've attempted this, but am not getting the Poincaré section I expect.
Here's my code:
program rungekutta
implicit none
integer, parameter :: dp = selected_real_kind(15,300)
integer :: i, n
real(kind=dp) z, y, t, A, C, D, B, omega, h
open(unit=100, file="rungekutta.dat",status='replace')
n = 0
!constants
omega = 1.0_dp
A = 0.25_dp
B = 1.0_dp
C = 0.1_dp
D = 1.0_dp
y = 0.0_dp
z = 0.0_dp
t = 0.0_dp
do i=1,1000
call rk2(z, y, t, n)
n = n + 1.0_dp
write(100,*) y, z
end do
contains
subroutine rk2(z, y, t, n) !subroutine to implement runge-kutta algorithm
implicit none
integer, parameter :: dp = selected_real_kind(15,300)
integer, intent(inout) :: n
real(kind=dp) :: k1y, k1z, k2y, k2z, y, z, t, pi
pi = 4.0*ATAN(1.0)
h = 0.1_dp
t = n*2*pi
k1y = dydt(y,z,t)*h
k1z = dzdt(y,z,t)*h
k2z = dzdt(y + (0.5_dp*k1y), z + (0.5_dp*k1z), t + (0.5_dp*h))*h
k2y = dydt(y, z +(0.5_dp*k1z), t)*h
y = y + k2y
z = z + k2z
end subroutine
!2nd order ODE split into 2 for coupled Runge-Kutta, useful to define 2
functions
function dzdt(y,z,t)
real(kind=dp) :: y, z, t, dzdt
dzdt = -A*y**3.0_dp + B*y - C*z + D*sin(omega*t)
end function
function dydt(y,z,t)
real(kind=dp) :: z, dydt, y, t
dydt = z
end function
end program
I have also attached an image of what my Poincaré section looks like:
.
This is y on the x axis vs dydt.
And an image of what I'd expect:
In your rk2 routine you perform one step of step length 0.1. Thus the plot is the full trajectory of the solution at that resolution. However the intend seems to be to integrate over a full period length. This would require a loop in that routine.
In other words, what you want is the plot of (y(n*T), z(n*T)) where T is one of the periods of the system, per your code T=2*p. What you actually compute is (y(n*h), z(n*h)) where h=0.1 is the step size of a single step of RK2.
Also the arguments of k2y need to be corrected as per the comment of user5713492
With a corrected integrator you should get something like the following picture:
where the red squares are the points at t=n*2*pi. The indicated step size by the dots on the solution curve is the same h=0.1, the integration is over t=0..300.
def RK2(f,u,times,subdiv = 1):
uout = np.zeros((len(times),)+u.shape)
uout[0] = u;
for k in range(len(times)-1):
t = times[k]
h = (times[k+1]-times[k])/subdiv
for j in range(subdiv):
k1 = f(u,t)*h
k2 = f(u+0.5*k1, t+0.5*h)*h
u, t = u+k2, t+h
uout[k+1]=u
return uout
def plotphase(A,B,C,D):
def derivs(u,t): y,z = u; return np.array([ z, -A*y**3 + B*y - C*z + D*np.sin(t) ])
N=60
u0 = np.array([0.0, 0.0])
t = np.arange(0,300,2*np.pi/N);
u = RK2(derivs, u0, t, subdiv = 10)
plt.plot(u[:-2*N,0],u[:-2*N,1],'.--y', u[-2*N:,0],u[-2*N:,1], '.-b', lw=0.5, ms=2);
plt.plot(u[::N,0],u[::N,1],'rs', ms=4); plt.grid(); plt.show()
plotphase(0.25, 1.0, 0.1, 1.0)
In the Cygwin terminal I enter
$ gfortran -o threed_euler_fluxes_v3.exe threed_euler_fluxes_v3.f90
and I get the compiler error
/usr/lib/gcc/i686-pc-cygwin/4.5.3/../../../libcygwin.a(libcmain.o): In function `main':
/usr/src/debug/cygwin-1.7.17-1/winsup/cygwin/lib/libcmain.c:39: undefined reference to `_WinMain#16'
collect2: ld returned 1 exit status
I also tried compiling like this
$ gfortran -o threed_euler_fluxes_v3.exe threed_euler_fluxes_v3.f90 -shared
but when I tried running I got an error saying it wasn't a valid windows program?
Heres the complete fortran code. I removed some comments inorder to keep word limit below 30k Heres the original.
subroutine inviscid_roe(primL, primR, njk, num_flux)
implicit none
integer , parameter :: p2 = selected_real_kind(15) ! Double precision
!Input
real(p2), intent( in) :: primL(5), primR(5) ! Input: primitive variables
real(p2), intent( in) :: njk(3) ! Input: face normal vector
!Output
real(p2), intent(out) :: num_flux(5) ! Output: numerical flux
!Some constants
real(p2) :: zero = 0.0_p2
real(p2) :: one = 1.0_p2
real(p2) :: two = 2.0_p2
real(p2) :: half = 0.5_p2
real(p2) :: fifth = 0.2_p2
!Local variables
real(p2) :: nx, ny, nz ! Normal vector
real(p2) :: mx, my, mz ! Orthogonal tangent vector
real(p2) :: lx, ly, lz ! Another orthogonal tangent vector
real(p2) :: abs_n_cross_l ! Magnitude of n x l
real(p2) :: uL, uR, vL, vR, wL, wR ! Velocity components.
real(p2) :: rhoL, rhoR, pL, pR ! Primitive variables.
real(p2) :: qnL, qnR, qmL, qmR, qlL, qlR ! Normal and tangent velocities
real(p2) :: aL, aR, HL, HR ! Speed of sound, Total enthalpy
real(p2) :: RT,rho,u,v,w,H,a,qn, ql, qm ! Roe-averages
real(p2) :: drho,dqn,dql,dqm,dp,LdU(5) ! Wave strengths
real(p2) :: ws(5), R(5,5) ! Wave speeds and right-eigenvectors
real(p2) :: dws(5) ! Width of a parabolic fit for entropy fix
real(p2) :: fL(5), fR(5), diss(5) ! Fluxes ad dissipation term
real(p2) :: gamma = 1.4_p2 ! Ratio of specific heats
real(p2) :: temp, tempx, tempy, tempz ! Temoprary variables
! Face normal vector (unit vector)
nx = njk(1)
ny = njk(2)
nz = njk(3)
tempx = ny*ny + nz*nz
tempy = nz*nz + nx*nx
tempz = nx*nx + ny*ny
if ( tempx >= tempy .and. tempx >= tempz ) then
lx = zero
ly = -nz
lz = ny
elseif ( tempy >= tempx .and. tempy >= tempz ) then
lx = -nz
ly = zero
lz = nx
elseif ( tempz >= tempx .and. tempz >= tempy ) then
lx = -ny
ly = nx
lz = zero
else
! Impossible to happen
write(*,*) "subroutine inviscid_roe: Impossible to happen. Please report the problem."
stop
endif
! Make it the unit vector.
temp = sqrt( lx*lx + ly*ly + lz*lz )
lx = lx/temp
ly = ly/temp
lz = lz/temp
mx = ny*lz - nz*ly
my = nz*lx - nx*lz
mz = nx*ly - ny*lx
abs_n_cross_l = sqrt(mx**2 + my**2 + mz**2)
mx = mx / abs_n_cross_l
my = my / abs_n_cross_l
mz = mz / abs_n_cross_l
rhoL = primL(1)
uL = primL(2)
vL = primL(3)
wL = primL(4)
qnL = uL*nx + vL*ny + wL*nz
qlL = uL*lx + vL*ly + wL*lz
qmL = uL*mx + vL*my + wL*mz
pL = primL(5)
aL = sqrt(gamma*pL/rhoL)
HL = aL*aL/(gamma-one) + half*(uL*uL+vL*vL+wL*wL)
! Right state
rhoR = primR(1)
uR = primR(2)
vR = primR(3)
wR = primR(4)
qnR = uR*nx + vR*ny + wR*nz
qlR = uR*lx + vR*ly + wR*lz
qmR = uR*mx + vR*my + wR*mz
pR = primR(5)
aR = sqrt(gamma*pR/rhoR)
HR = aR*aR/(gamma-one) + half*(uR*uR+vR*vR+wR*wR)
RT = sqrt(rhoR/rhoL)
rho = RT*rhoL !Roe-averaged density
u = (uL + RT*uR)/(one + RT) !Roe-averaged x-velocity
v = (vL + RT*vR)/(one + RT) !Roe-averaged y-velocity
w = (wL + RT*wR)/(one + RT) !Roe-averaged z-velocity
H = (HL + RT*HR)/(one + RT) !Roe-averaged total enthalpy
a = sqrt( (gamma-one)*(H-half*(u*u + v*v + w*w)) ) !Roe-averaged speed of sound
qn = u*nx + v*ny + w*nz !Roe-averaged face-normal velocity
ql = u*lx + v*ly + w*lz !Roe-averaged face-tangent velocity
qm = u*mx + v*my + w*mz !Roe-averaged face-tangent velocity
!Wave Strengths
drho = rhoR - rhoL !Density difference
dp = pR - pL !Pressure difference
dqn = qnR - qnL !Normal velocity difference
dql = qlR - qlL !Tangent velocity difference in l
dqm = qmR - qmL !Tangent velocity difference in m
LdU(1) = (dp - rho*a*dqn )/(two*a*a) !Left-moving acoustic wave strength
LdU(2) = drho - dp/(a*a) !Entropy wave strength
LdU(3) = (dp + rho*a*dqn )/(two*a*a) !Right-moving acoustic wave strength
LdU(4) = rho*dql !Shear wave strength
LdU(5) = rho*dqm !Shear wave strength
!Absolute values of the wave speeds
ws(1) = abs(qn-a) !Left-moving acoustic wave speed
ws(2) = abs(qn) !Entropy wave speed
ws(3) = abs(qn+a) !Right-moving acoustic wave speed
ws(4) = abs(qn) !Shear wave speed
ws(5) = abs(qn) !Shear wave speed
!Harten's Entropy Fix JCP(1983), 49, pp357-393: only for the nonlinear fields.
!NOTE: It avoids vanishing wave speeds by making a parabolic fit near ws = 0.
dws(1) = fifth
if ( ws(1) < dws(1) ) ws(1) = half * ( ws(1)*ws(1)/dws(1)+dws(1) )
dws(3) = fifth
if ( ws(3) < dws(3) ) ws(3) = half * ( ws(3)*ws(3)/dws(3)+dws(3) )
!Right Eigenvectors
! Left-moving acoustic wave
R(1,1) = one
R(2,1) = u - a*nx
R(3,1) = v - a*ny
R(4,1) = w - a*nz
R(5,1) = H - a*qn
! Entropy wave
R(1,2) = one
R(2,2) = u
R(3,2) = v
R(4,2) = w
R(5,2) = half*(u*u + v*v + w*w)
! Right-moving acoustic wave
R(1,3) = one
R(2,3) = u + a*nx
R(3,3) = v + a*ny
R(4,3) = w + a*nz
R(5,3) = H + a*qn
! Shear wave
R(1,4) = zero
R(2,4) = lx
R(3,4) = ly
R(4,4) = lz
R(5,4) = ql
! Shear wave
R(1,5) = zero
R(2,5) = mx
R(3,5) = my
R(4,5) = mz
R(5,5) = qm
diss(:) = ws(1)*LdU(1)*R(:,1) + ws(2)*LdU(2)*R(:,2) + ws(3)*LdU(3)*R(:,3) &
+ ws(4)*LdU(4)*R(:,4) + ws(5)*LdU(5)*R(:,5)
fL(1) = rhoL*qnL
fL(2) = rhoL*qnL * uL + pL*nx
fL(3) = rhoL*qnL * vL + pL*ny
fL(4) = rhoL*qnL * wL + pL*nz
fL(5) = rhoL*qnL * HL
fR(1) = rhoR*qnR
fR(2) = rhoR*qnR * uR + pR*nx
fR(3) = rhoR*qnR * vR + pR*ny
fR(4) = rhoR*qnR * wR + pR*nz
fR(5) = rhoR*qnR * HR
num_flux = half * (fL + fR - diss)
subroutine inviscid_roe_n(primL, primR, njk, num_flux)
implicit none
integer , parameter :: p2 = selected_real_kind(15) ! Double precision
!Input
real(p2), intent( in) :: primL(5), primR(5) ! Input: primitive variables
real(p2), intent( in) :: njk(3) ! Input: face normal vector
!Output
real(p2), intent(out) :: num_flux(5) ! Output: numerical flux
!Some constants
real(p2) :: zero = 0.0_p2
real(p2) :: one = 1.0_p2
real(p2) :: two = 2.0_p2
real(p2) :: half = 0.5_p2
real(p2) :: fifth = 0.2_p2
!Local variables
real(p2) :: nx, ny, nz ! Normal vector
real(p2) :: uL, uR, vL, vR, wL, wR ! Velocity components.
real(p2) :: rhoL, rhoR, pL, pR ! Primitive variables.
real(p2) :: qnL, qnR ! Normal velocities
real(p2) :: aL, aR, HL, HR ! Speed of sound, Total enthalpy
real(p2) :: RT,rho,u,v,w,H,a,qn ! Roe-averages
real(p2) :: drho,dqn,dp,LdU(4) ! Wave strengths
real(p2) :: du, dv, dw ! Velocity differences
real(p2) :: ws(4), R(5,4) ! Wave speeds and right-eigenvectors
real(p2) :: dws(4) ! Width of a parabolic fit for entropy fix
real(p2) :: fL(5), fR(5), diss(5) ! Fluxes ad dissipation term
real(p2) :: gamma = 1.4_p2 ! Ratio of specific heats
! Face normal vector (unit vector)
nx = njk(1)
ny = njk(2)
nz = njk(3)
!Primitive and other variables.
! Left state
rhoL = primL(1)
uL = primL(2)
vL = primL(3)
wL = primL(4)
qnL = uL*nx + vL*ny + wL*nz
pL = primL(5)
aL = sqrt(gamma*pL/rhoL)
HL = aL*aL/(gamma-one) + half*(uL*uL+vL*vL+wL*wL)
! Right state
rhoR = primR(1)
uR = primR(2)
vR = primR(3)
wR = primR(4)
qnR = uR*nx + vR*ny + wR*nz
pR = primR(5)
aR = sqrt(gamma*pR/rhoR)
HR = aR*aR/(gamma-one) + half*(uR*uR+vR*vR+wR*wR)
!First compute the Roe-averaged quantities
! NOTE: See http://www.cfdnotes.com/cfdnotes_roe_averaged_density.html for
! the Roe-averaged density.
RT = sqrt(rhoR/rhoL)
rho = RT*rhoL !Roe-averaged density
u = (uL + RT*uR)/(one + RT) !Roe-averaged x-velocity
v = (vL + RT*vR)/(one + RT) !Roe-averaged y-velocity
w = (wL + RT*wR)/(one + RT) !Roe-averaged z-velocity
H = (HL + RT*HR)/(one + RT) !Roe-averaged total enthalpy
a = sqrt( (gamma-one)*(H-half*(u*u + v*v + w*w)) ) !Roe-averaged speed of sound
qn = u*nx + v*ny + w*nz !Roe-averaged face-normal velocity
!Wave Strengths
drho = rhoR - rhoL !Density difference
dp = pR - pL !Pressure difference
dqn = qnR - qnL !Normal velocity difference
LdU(1) = (dp - rho*a*dqn )/(two*a*a) !Left-moving acoustic wave strength
LdU(2) = drho - dp/(a*a) !Entropy wave strength
LdU(3) = (dp + rho*a*dqn )/(two*a*a) !Right-moving acoustic wave strength
LdU(4) = rho !Shear wave strength (not really, just a factor)
!Absolute values of the wave Speeds
ws(1) = abs(qn-a) !Left-moving acoustic wave
ws(2) = abs(qn) !Entropy wave
ws(3) = abs(qn+a) !Right-moving acoustic wave
ws(4) = abs(qn) !Shear waves
!Harten's Entropy Fix JCP(1983), 49, pp357-393: only for the nonlinear fields.
!NOTE: It avoids vanishing wave speeds by making a parabolic fit near ws = 0.
dws(1) = fifth
if ( ws(1) < dws(1) ) ws(1) = half * ( ws(1)*ws(1)/dws(1)+dws(1) )
dws(3) = fifth
if ( ws(3) < dws(3) ) ws(3) = half * ( ws(3)*ws(3)/dws(3)+dws(3) )
R(1,1) = one
R(2,1) = u - a*nx
R(3,1) = v - a*ny
R(4,1) = w - a*nz
R(5,1) = H - a*qn
R(1,2) = one
R(2,2) = u
R(3,2) = v
R(4,2) = w
R(5,2) = half*(u*u + v*v + w*w)
! Right-moving acoustic wave
R(1,3) = one
R(2,3) = u + a*nx
R(3,3) = v + a*ny
R(4,3) = w + a*nz
R(5,3) = H + a*qn
! Two shear wave components combined into one (wave strength incorporated).
du = uR - uL
dv = vR - vL
dw = wR - wL
R(1,4) = zero
R(2,4) = du - dqn*nx
R(3,4) = dv - dqn*ny
R(4,4) = dw - dqn*nz
R(5,4) = u*du + v*dv + w*dw - qn*dqn
!Dissipation Term: |An|(UR-UL) = R|Lambda|L*dU = sum_k of [ ws(k) * R(:,k) * L*dU(k) ]
diss(:) = ws(1)*LdU(1)*R(:,1) + ws(2)*LdU(2)*R(:,2) &
+ ws(3)*LdU(3)*R(:,3) + ws(4)*LdU(4)*R(:,4)
!Compute the physical flux: fL = Fn(UL) and fR = Fn(UR)
fL(1) = rhoL*qnL
fL(2) = rhoL*qnL * uL + pL*nx
fL(3) = rhoL*qnL * vL + pL*ny
fL(4) = rhoL*qnL * wL + pL*nz
fL(5) = rhoL*qnL * HL
fR(1) = rhoR*qnR
fR(2) = rhoR*qnR * uR + pR*nx
fR(3) = rhoR*qnR * vR + pR*ny
fR(4) = rhoR*qnR * wR + pR*nz
fR(5) = rhoR*qnR * HR
! This is the numerical flux: Roe flux = 1/2 *[ Fn(UL)+Fn(UR) - |An|(UR-UL) ]
num_flux = half * (fL + fR - diss)
!Normal max wave speed in the normal direction.
! wsn = abs(qn) + a
end subroutine inviscid_roe_n
subroutine inviscid_rotated_rhll(primL, primR, njk, num_flux)
implicit none
integer , parameter :: p2 = selected_real_kind(15) ! Double precision
!Input
real(p2), intent( in) :: primL(5), primR(5) ! Input: primitive variables
real(p2), intent( in) :: njk(3) ! Input: face normal vector
!Output
real(p2), intent(out) :: num_flux(5) ! Output: numerical flux
!Some constants
real(p2) :: zero = 0.0_p2
real(p2) :: one = 1.0_p2
real(p2) :: two = 2.0_p2
real(p2) :: half = 0.5_p2
real(p2) :: fifth = 0.2_p2
!Local variables
real(p2) :: nx, ny, nz ! Face normal vector
real(p2) :: uL, uR, vL, vR, wL, wR ! Velocity components.
real(p2) :: rhoL, rhoR, pL, pR ! Primitive variables.
real(p2) :: qnL, qnR ! Normal velocity
real(p2) :: aL, aR, HL, HR ! Speed of sound, Total enthalpy
real(p2) :: RT,rho,u,v,w,H,a,qn ! Roe-averages
real(p2) :: drho,dqn,dp,LdU(4) ! Wave strengths
real(p2) :: du, dv, dw ! Velocity conponent differences
real(p2) :: eig(4) ! Eigenvalues
real(p2) :: ws(4), R(5,4) ! Absolute Wave speeds and right-eigenvectors
real(p2) :: dws(4) ! Width of a parabolic fit for entropy fix
real(p2) :: fL(5), fR(5), diss(5) ! Fluxes ad dissipation term
real(p2) :: gamma = 1.4_p2 ! Ratio of specific heats
real(p2) :: SRp,SLm ! Wave speeds for the HLL part
real(p2) :: nx1, ny1, nz1 ! Vector along which HLL is applied
real(p2) :: nx2, ny2, nz2 ! Vector along which Roe is applied
real(p2) :: alpha1, alpha2 ! Projections of the new normals
real(p2) :: abs_dq ! Magnitude of the velocity difference
real(p2) :: temp, tempx, tempy, tempz ! Temporary variables
! Face normal vector (unit vector)
nx = njk(1)
ny = njk(2)
nz = njk(3)
!Primitive and other variables.
! Left state
rhoL = primL(1)
uL = primL(2)
vL = primL(3)
wL = primL(4)
qnL = uL*nx + vL*ny + wL*nz
pL = primL(5)
aL = sqrt(gamma*pL/rhoL)
HL = aL*aL/(gamma-one) + half*(uL*uL+vL*vL+wL*wL)
! Right state
rhoR = primR(1)
uR = primR(2)
vR = primR(3)
wR = primR(4)
qnR = uR*nx + vR*ny + wR*nz
pR = primR(5)
aR = sqrt(gamma*pR/rhoR)
HR = aR*aR/(gamma-one) + half*(uR*uR+vR*vR+wR*wR)
!Compute the physical flux: fL = Fn(UL) and fR = Fn(UR)
fL(1) = rhoL*qnL
fL(2) = rhoL*qnL * uL + pL*nx
fL(3) = rhoL*qnL * vL + pL*ny
fL(4) = rhoL*qnL * wL + pL*nz
fL(5) = rhoL*qnL * HL
fR(1) = rhoR*qnR
fR(2) = rhoR*qnR * uR + pR*nx
fR(3) = rhoR*qnR * vR + pR*ny
fR(4) = rhoR*qnR * wR + pR*nz
fR(5) = rhoR*qnR * HR
abs_dq = sqrt( (uR-uL)**2 + (vR-vL)**2 + (wR-wL)**2 )
if ( abs_dq > 1.0e-12_p2) then
nx1 = (uR-uL)/abs_dq
ny1 = (vR-vL)/abs_dq
nz1 = (wR-wL)/abs_dq
tempx = ny*ny + nz*nz
tempy = nz*nz + nx*nx
tempz = nx*nx + ny*ny
if ( tempx >= tempy .and. tempx >= tempz ) then
nx1 = zero
ny1 = -nz
nz1 = ny
elseif ( tempy >= tempx .and. tempy >= tempz ) then
nx1 = -nz
ny1 = zero
nz1 = nx
elseif ( tempz >= tempx .and. tempz >= tempy ) then
nx1 = -ny
ny1 = nx
nz1 = zero
else
! Impossible to happen
write(*,*) "inviscid_rotated_rhll: Impossible to happen. Please report the problem."
stop
endif
! Make it the unit vector.
temp = sqrt( nx1*nx1 + ny1*ny1 + nz1*nz1 )
nx1 = nx1/temp
ny1 = ny1/temp
nz1 = nz1/temp
endif
alpha1 = nx*nx1 + ny*ny1 + nz*nz1
! Make alpha1 always positive.
temp = sign(one,alpha1)
nx1 = temp * nx1
ny1 = temp * ny1
nz1 = temp * nz1
alpha1 = temp * alpha1
!n2 = direction perpendicular to n1.
! Note: There are infinitely many choices for this vector.
! The best choice may be discovered in future.
! Here, we employ the formula (4.4) in the paper:
! (nx2,ny2,nz2) = (n1xn)xn1 / |(n1xn)xn1| ('x' is the vector product.)
! (tempx,tempy,tempz) = n1xn
tempx = ny1*nz - nz1*ny
tempy = nz1*nx - nx1*nz
tempz = nx1*ny - ny1*nx
! (nx2,ny2,nz2) = (n1xn)xn1
nx2 = tempy*nz1 - tempz*ny1
ny2 = tempz*nx1 - tempx*nz1
nz2 = tempx*ny1 - tempy*nx1
! Make n2 the unit vector
temp = sqrt( nx2*nx2 + ny2*ny2 + nz2*nz2 )
nx2 = nx2/temp
ny2 = ny2/temp
nz2 = nz2/temp
alpha2 = nx*nx2 + ny*ny2 + nz*nz2
! Make alpha2 always positive.
temp = sign(one,alpha2)
nx2 = temp * nx2
ny2 = temp * ny2
nz2 = temp * nz2
alpha2 = temp * alpha2
!--------------------------------------------------------------------------------
!Now we are going to compute the Roe flux with n2 as the normal with modified
!wave speeds (5.12). NOTE: the Roe flux here is computed without tangent vectors.
!See "I do like CFD, VOL.1" for details: page 57, Equation (3.6.31).
!First compute the Roe-averaged quantities
! NOTE: See http://www.cfdnotes.com/cfdnotes_roe_averaged_density.html for
! the Roe-averaged density.
RT = sqrt(rhoR/rhoL)
rho = RT*rhoL !Roe-averaged density.
u = (uL + RT*uR)/(one + RT) !Roe-averaged x-velocity
v = (vL + RT*vR)/(one + RT) !Roe-averaged y-velocity
w = (wL + RT*wR)/(one + RT) !Roe-averaged z-velocity
H = (HL + RT*HR)/(one + RT) !Roe-averaged total enthalpy
a = sqrt( (gamma-one)*(H-half*(u*u + v*v + w*w)) ) !Roe-averaged speed of sound
!----------------------------------------------------
!Compute the wave speed estimates for the HLL part,
!following Einfeldt:
!
! B. Einfeldt, On Godunov-type methods for gas dynamics,
! SIAM Journal on Numerical Analysis 25 (2) (1988) 294–318.
!
! Note: HLL is actually applied to n1, but this is
! all we need to incorporate HLL. See JCP2008 paper.
qn = u *nx1 + v *ny1 + w *nz1
qnL = uL*nx1 + vL*ny1 + wL*nz1
qnR = uR*nx1 + vR*ny1 + wR*nz1
SLm = min( zero, qn - a, qnL - aL ) !Minimum wave speed estimate
SRp = max( zero, qn + a, qnR + aR ) !Maximum wave speed estimate
! This is the only place where n1=(nx1,ny1,nz1) is used.
! n1=(nx1,ny1,nz1) is never used below.
!----------------------------------------------------
!Wave Strengths
qn = u *nx2 + v *ny2 + w *nz2
qnL = uL*nx2 + vL*ny2 + wL*nz2
qnR = uR*nx2 + vR*ny2 + wR*nz2
drho = rhoR - rhoL !Density difference
dp = pR - pL !Pressure difference
dqn = qnR - qnL !Normal velocity difference
LdU(1) = (dp - rho*a*dqn )/(two*a*a) !Left-moving acoustic wave strength
LdU(2) = drho - dp/(a*a) !Entropy wave strength
LdU(3) = (dp + rho*a*dqn )/(two*a*a) !Right-moving acoustic wave strength
LdU(4) = rho !Shear wave strength (not really, just a factor)
!Wave Speed (Eigenvalues)
eig(1) = qn-a !Left-moving acoustic wave velocity
eig(2) = qn !Entropy wave velocity
eig(3) = qn+a !Right-moving acoustic wave velocity
eig(4) = qn !Shear wave velocity
!Absolute values of the wave speeds (Eigenvalues)
ws(1) = abs(qn-a) !Left-moving acoustic wave speed
ws(2) = abs(qn) !Entropy wave speed
ws(3) = abs(qn+a) !Right-moving acoustic wave speed
ws(4) = abs(qn) !Shear wave speed
!Harten's Entropy Fix JCP(1983), 49, pp357-393: only for the nonlinear fields.
!NOTE: It avoids vanishing wave speeds by making a parabolic fit near ws = 0.
dws(1) = fifth
if ( ws(1) < dws(1) ) ws(1) = half * ( ws(1)*ws(1)/dws(1)+dws(1) )
dws(3) = fifth
if ( ws(3) < dws(3) ) ws(3) = half * ( ws(3)*ws(3)/dws(3)+dws(3) )
!Combine the wave speeds for Rotated-RHLL: Eq.(5.12) in the original JCP2008 paper.
ws = alpha2*ws - (alpha1*two*SRp*SLm + alpha2*(SRp+SLm)*eig)/(SRp-SLm)
!Below, we compute the Roe dissipation term in the direction n2
!with the above modified wave speeds. HLL wave speeds act something like
!the entropy fix or eigenvalue limiting; they contribute only by the amount
!given by the fraction, alpha1 (less than or equal to 1.0). See JCP2008 paper.
!Right Eigenvectors:
!Note: Two shear wave components are combined into one, so that tangent vectors
! are not required. And that's why there are only 4 vectors here.
! Left-moving acoustic wave
R(1,1) = one
R(2,1) = u - a*nx2
R(3,1) = v - a*ny2
R(4,1) = w - a*nz2
R(5,1) = H - a*qn
! Entropy wave
R(1,2) = one
R(2,2) = u
R(3,2) = v
R(4,2) = w
R(5,2) = half*(u*u + v*v + w*w)
! Right-moving acoustic wave
R(1,3) = one
R(2,3) = u + a*nx2
R(3,3) = v + a*ny2
R(4,3) = w + a*nz2
R(5,3) = H + a*qn
! Two shear wave components combined into one (wave strength incorporated).
du = uR - uL
dv = vR - vL
dw = wR - wL
R(1,4) = zero
R(2,4) = du - dqn*nx2
R(3,4) = dv - dqn*ny2
R(4,4) = dw - dqn*nz2
R(5,4) = u*du + v*dv + w*dw - qn*dqn
!Dissipation Term: Roe dissipation with the modified wave speeds.
! |An|dU = R|Lambda|L*dU = sum_k of [ ws(k) * R(:,k) * L*dU(k) ], where n=n2.
diss(:) = ws(1)*LdU(1)*R(:,1) + ws(2)*LdU(2)*R(:,2) &
+ ws(3)*LdU(3)*R(:,3) + ws(4)*LdU(4)*R(:,4)
!Compute the Rotated-RHLL flux. (It looks like the HLL flux with Roe dissipation.)
num_flux = (SRp*fL - SLm*fR)/(SRp-SLm) - half*diss
!Normal max wave speed in the normal direction.
! wsn = abs(qn) + a
end subroutine inviscid_rotated_rhll
!--------------------------------------------------------------------------------
Your file is not a program at all! It is a collection of subprograms. You cannot compile it for running as a program, only as an object file or a library (try -c or -shared). You must add the main program body to be able to compile it as a program and run it!