!=============================================================================== ! Global module !=============================================================================== module Globals real(8), allocatable, save :: u(:), flux(:)
integer, save :: cells, ntmaxi
real(8), save :: cflcoe, domlen, dt, timeout, timeto, dx
end module Globals
!=============================================================================== ! Main module !=============================================================================== module MainModule use Globals implicit none
contains
!---------------------------------------------------------------------------- ! Purpose: to read initial parameters of the problem !---------------------------------------------------------------------------- subroutine reader open(unit=1, file='b1god.ini', status='unknown')
read(1, *)cflcoe
read(1, *)domlen
read(1, *)cells
read(1, *)ntmaxi
read(1, *)timeout
close(1)
write(*, *)
write(*, *)'Input data echoed to screen'
write(*, *)
write(*, *)'cflcoe =', cflcoe
write(*, *)'domlen =', domlen
write(*, *)'cells =', cells
write(*, *)'ntmaxi =', ntmaxi
write(*, *)'timeout =', timeout
end subroutine reader
!---------------------------------------------------------------------------
! Purpose: to set initial conditions for solution U
! and initialise other variables
!---------------------------------------------------------------------------
subroutine initia(domlen, cells)
real(8), intent(in) :: domlen
integer, intent(in) :: cells
integer i
real(8) xleft, xpos, xmiddle, xright
allocate(flux(0 : cells+1))
allocate(u (0 : cells+1))
dx = domlen/real(cells)
do i = 0, cells + 1
flux(i) = 0.0
u (i) = 0.0
end do
xleft = 0.3*domlen
xright = 0.7*domlen
do i = 1, cells
xpos = (real(i)-1.0)*dx
if(xpos < xleft) then
u(i) = -0.5
else if(xleft <= xpos .and. xpos <=xright) then
u(i) = 1.0
else
u(i) = 0
endif
end do
end subroutine initia
!---------------------------------------------------------------------------
! Purpose: to apply boundary conditions
!---------------------------------------------------------------------------
subroutine bcondi(cells)
integer, intent (in) :: cells
u(0) = u(1)
u(cells + 1) = u(cells)
end subroutine bcondi
!---------------------------------------------------------------------------
! Purpose: to apply the CFL condition to compute a stable time step DT
!---------------------------------------------------------------------------
subroutine cflcon(cflcoe, cells, time, timeout)
real(8), intent(in) :: cflcoe, time, timeout
integer, intent(in) :: cells
real(8) smax
integer i
smax = -1.0e+06
do i = 0, cells + 1
if(abs(u(i)) >= smax) smax = abs(u(i))
end do
dt = cflcoe*dx/smax ! Choosing the time step
if(time + dt> timeout) then
dt = timeout - time
endif
end subroutine cflcon
!---------------------------------------------------------------------------
! Purpose: to update the solution to a new time level
! @using the explicit conservative formula
!---------------------------------------------------------------------------
subroutine update(cells)
integer, intent(in) :: cells
real(8) dtodx
integer i
dtodx = dt / dx
do i = 1, cells
u(i) = u(i) + dtodx*(flux(i-1) - flux(i)) !(2.29)
end do
end subroutine update
!---------------------------------------------------------------------------
! Purpose: to output the solution at a specified time TIMEOUT
!---------------------------------------------------------------------------
subroutine output(cells)
integer, intent(in) :: cells
integer i
real(8) xpos
open(unit = 1, file = 'numerical.out', status = 'unknown')
do i = 1, cells
xpos = real(i)*dx
write(1,'(f14.6, 2x, f14.6)')xpos, u(i)
end do
close(1)
end subroutine output
!---------------------------------------------------------------------------
! Purpose: to compute intercell fluxes according to the
! Godunov first-order upwind method, inconjunction with
! the exact Riemann solver
!---------------------------------------------------------------------------
subroutine fluxes(cells)
integer, intent(in) :: cells
integer i
real(8) ul, ur, ustar
do i = 0, cells
ul = u(i)
ur = u(i+1)
call riemann(ul, ur, ustar)
flux(i) = 0.5*ustar*ustar !flux for Burgers equation
end do
end subroutine fluxes
!---------------------------------------------------------------------------
! Purpose: to solve the Riemann problem for the inviscid Burgers
! equation exactly
!---------------------------------------------------------------------------
subroutine riemann(ul, ur, ustar)
real(8), intent(in) :: ul, ur
real(8), intent(out):: ustar
real(8)s
if(ul > ur) then
s=0.5* (ul+ur)
if(s>0) then
ustar =ul
else
ustar =ur
end subroutine riemann
end module MainModule
!=============================================================================== ! Main program !=============================================================================== program main use Globals use MainModule
implicit none
integer n real(8) time
time = 0.0
! Parameters of problem are read in from file 'b1god.ini' call reader
! Initial conditions are set up call initia(domlen, cells) write(*, )' ' write(, )'---------------------------------------------' write(, )' Time step N Time ' write(, *)'---------------------------------------------'
! Time marching procedure do n = 1, ntmaxi write(,) n, time
! Boundary conditions are set
call bcondi (cells)
! Courant-Friedrichs-Lewy (CFL) condition imposed
call cflcon(cflcoe, cells, time, timeout)
time = time + dt
! Intercell numerical fluxes are computed
call fluxes(cells)
! Solution is updated according to conservation formula
call update(cells)
! Check output time
if(abs(time - timeout) <= timeto) then
! Solution is written to \'numerical.out\'
! at specified time TIMEOUT
call output(cells)
write(*, *)'-------------------------------------------'
write(*, *)' Number of time steps =',n
write(*, *)'-------------------------------------------'
exit
endif
end do
end program main
why fail to compile with fatal error? compile online in https://www.tutorialspoint.com/compile_fortran_online.php