!----------------------------------------------------------------------- ! Heat conduction: Euler -- Centered Difference ! ! coded by Shigeo Yoden on Sept. 12, 2000 !----------------------------------------------------------------------- program cond_eu use dcl ! DCL Fortran90 (dcl-5.1/dcl-f90) integer, parameter :: jmax=1000, mmax=10 real, parameter :: xmax=0.5, tmax=1.0 real, parameter :: rkappa=0.14 real, dimension(0:jmax) :: x, u, du real, dimension(0:jmax,0:mmax) :: v character :: ct*30, cl*6, csgi*1 !!! write(*,*) 'dx=?; dt=? ' !!! read (*,*) dx, dt dx = 5.e-3; dt = 5.e-5 imax = xmax/dx nmax = tmax/dt; ndel = nmax/mmax if(imax > jmax) stop 'error: dx must have a larger value' !-- 初期条件 ---- u = 100 u(0) = 0; u(imax) = 0 ! 実験(1):両端が 0 度 !!! u(0) = 0 ! 実験(2):左端が 0 度 do i=0, imax x(i) = i*dx v(i,0) = u(i) end do mm = 0 !-- 時間積分 ---- do n=1, nmax call drv(u, du) u = u + du if(mod(n,ndel) == 0) then mm = mm + 1 v(0:imax,mm) = u end if end do !-- グラフ化 ---- call DclOpenGraphics() call graph call DclCloseGraphics !-- 内部手続き ---- contains subroutine drv(u, du) ! 時間微分を計算する内部サブルーチン real, dimension(0:imax) :: u, du du(0) = 0 ! 境界条件(x=0) du(imax) = 0 ! 境界条件(x=xmax) do i=1, imax-1 du(i) = rkappa*(u(i+1) - 2*u(i) + u(i-1))/dx**2 *dt end do end subroutine drv subroutine graph ! グラフを描く内部サブルーチン call DclNewFrame call DclSetTitle('x', 'temperature', 'cm', '|'//csgi(4)//'"C') call DclDrawScaledGraph(x(0:imax), v(0:imax,0)) call DclSetParm('ENABLE_LINE_LABELING', .true.) call DclSetParm('LINE_CYCLE_LENGTH', 45.) call DclSetLineTextSize(0.018) cl = 't=?.?s' do m=1,mm write(cl(3:5),'(f3.1)') ndel*m*dt call DclSetLineText(cl) if(m == 6) call DclSetParm('ENABLE_LINE_LABELING', .false.) call DclDrawLine(x(0:imax), v(0:imax,m)) end do ct = 'dt=??.??E???s' write(ct(4:12),'(e9.2)') dt call DclDrawTitle('t', ct, position=-0.8) call DclDrawTitle('t', ' Euler-Centered Difference', position=-1.) call DclDrawTitle('t', 'Heat Conduction Equation:', position=-1.) end subroutine graph end program cond_eu !----------------------------------------------------------------------- ! Heat conduction: Runge Kutta(4th) -- Centered Difference ! ! coded by Satoshi Sakai for lectures on Geophysical Fluid Dynamics ! modified by Shigeo Yoden on Sept. 12, 2000 !----------------------------------------------------------------------- program cond_rk use dcl ! DCL Fortran90 (dcl-5.1/dcl-f90) integer, parameter :: jmax=1000, mmax=10 real, parameter :: xmax=0.5, tmax=1.0 real, parameter :: rkappa=0.14 real, dimension(0:jmax) :: x, u, du1, du2, du3, du4 real, dimension(0:jmax,0:mmax) :: v character :: ct*30, cl*6, csgi*1 !!! write(*,*) 'dx=?; dt=? ' !!! read (*,*) dx, dt dx = 5.e-3; dt = 1.e-4 imax = xmax/dx nmax = tmax/dt; ndel = nmax/mmax if(imax > jmax) stop 'error: dx must have a larger value' !-- 初期条件 ---- u = 100 u(0) = 0; u(imax) = 0 ! 実験(1):両端が 0 度 !! u(0) = 0 ! 実験(2):左端が 0 度 do i=0, imax x(i) = i*dx v(i,0) = u(i) end do mm = 0 !-- 時間積分 ---- do n=1, nmax call drv(u , du1) call drv(u+du1/2, du2) call drv(u+du2/2, du3) call drv(u+du3 , du4) u = u + (du1 + 2*(du2+du3) + du4) / 6 if(mod(n,ndel) == 0) then mm = mm + 1 v(0:imax,mm) = u end if end do !-- グラフ化 ---- call DclOpenGraphics() call graph call DclCloseGraphics !-- 内部手続き ---- contains subroutine drv(u, du) ! 時間微分を計算する内部サブルーチン real, dimension(0:imax) :: u, du du(0) = 0 ! 境界条件(x=0) du(imax) = 0 ! 境界条件(x=xmax) do i=1, imax-1 du(i) = rkappa*(u(i+1) - 2*u(i) + u(i-1))/dx**2 *dt end do end subroutine drv subroutine graph ! グラフを描く内部サブルーチン call DclNewFrame call DclSetTitle('x', 'temperature', 'cm', '|'//csgi(4)//'"C') call DclDrawScaledGraph(x(0:imax), v(0:imax,0)) call DclSetParm('ENABLE_LINE_LABELING', .true.) call DclSetParm('LINE_CYCLE_LENGTH', 45.) call DclSetLineTextSize(0.018) cl = 't=?.?s' do m=1,mm write(cl(3:5),'(f3.1)') ndel*m*dt call DclSetLineText(cl) if(m == 6) call DclSetParm('ENABLE_LINE_LABELING', .false.) call DclDrawLine(x(0:imax), v(0:imax,m)) end do ct = 'dt=??.??E???s' write(ct(4:12),'(e9.2)') dt call DclDrawTitle('t', ct, position=-0.8) call DclDrawTitle('t', ' 4th Runge Kutta-Center Difference', & position=-1.) call DclDrawTitle('t', 'Heat Conduction Equation:', position=-1.) end subroutine graph end program cond_rk !----------------------------------------------------------------------- ! Heat conduction: an implicit method (Euler -- Centered Difference) ! ! coded by Shigeo Yoden on Sept. 12, 2000 !----------------------------------------------------------------------- program cond_imp use dcl ! DCL Fortran90 (dcl-5.1/dcl-f90) integer, parameter :: jmax=1000, mmax=10 real, parameter :: xmax=0.5, tmax=1.0 real, parameter :: rkappa=0.14 real, dimension(0:jmax) :: x, u real, dimension(0:jmax,0:mmax) :: v real, dimension(1:jmax-1) :: a, b, c character :: ct*30, cl*6, csgi*1 !!! write(*,*) 'dx=?; dt=? ' !!! read (*,*) dx, dt dx = 5.e-3; dt = 1.e-3 imax = xmax/dx nmax = tmax/dt; ndel = nmax/mmax if(imax > jmax) stop 'error: dx must have a larger value' !-- 初期条件 ---- u = 100 u(0) = 0; u(imax) = 0 ! 実験(1):両端が 0 度 do i=0, imax x(i) = i*dx v(i,0) = u(i) end do mm = 0 !-- 時間積分 ---- r = dt*rkappa/dx**2 a = - r b = 1 + 2*r c = - r do n=1, nmax call tridiag(u(1)) if(mod(n,ndel) == 0) then mm = mm + 1 v(0:imax,mm) = u end if end do !-- グラフ化 ---- call DclOpenGraphics() call graph call DclCloseGraphics !-- 内部手続き ---- contains subroutine tridiag(f) ! 3重対角連立方程式を解く内部サブルーチン ! !-- Durran(1999) pp.440; Thomas tridiagonal algorism ! Solves a standard tridiagonal system ! ! Definition of the variables ! jmax = dimension of all the following arrays <==> imax-1 ! a = sub(lower) diagonal ! b = center diagonal ! c = super(upper) diagonal ! f = right hand side ! q = work array provided by calling program ! ! a(1) and c(jmax) need not be initialized ! The output is in f; a, b, c are unchanged ! 両端の境界条件は 0 のみ ? real, dimension(1:imax-1) :: f, q c(imax-1) = 0. ! Forward elimination sweep q(1) = - c(1)/b(1) f(1) = f(1)/b(1) do j=2, imax-1 p = 1./(b(j) + a(j)*q(j-1)) q(j) = - c(j)*p f(j) = (f(j) - a(j)*f(j-1))*p end do ! Backword pass do j=imax-2, 1, -1 f(j) = f(j) + q(j)*f(j+1) end do end subroutine tridiag subroutine graph ! グラフを描く内部サブルーチン call DclNewFrame call DclSetTitle('x', 'temperature', 'cm', '|'//csgi(4)//'"C') call DclDrawScaledGraph(x(0:imax), v(0:imax,0)) call DclSetParm('ENABLE_LINE_LABELING', .true.) call DclSetParm('LINE_CYCLE_LENGTH', 45.) call DclSetLineTextSize(0.018) cl = 't=?.?s' do m=1,mm write(cl(3:5),'(f3.1)') ndel*m*dt call DclSetLineText(cl) if(m == 6) call DclSetParm('ENABLE_LINE_LABELING', .false.) call DclDrawLine(x(0:imax), v(0:imax,m)) end do ct = 'dt=??.??E???s' write(ct(4:12),'(e9.2)') dt call DclDrawTitle('t', ct, position=-0.8) call DclDrawTitle('t', ' implicit method(Euler-C.D.)', position=-1.) call DclDrawTitle('t', 'Heat Conduction Equation:', position=-1.) end subroutine graph end program cond_imp !----------------------------------------------------------------------- ! Advection equation: Forward -- Upstream ! ! coded by Shigeo Yoden on Sept. 12, 2000 !----------------------------------------------------------------------- program adv_ftus use dcl ! DCL Fortran90 (dcl-5.1/dcl-f90) integer, parameter :: jmax=1000, mmax=5 real, parameter :: xmax=1.0, tmax=1.0 real, parameter :: c=1.0, pi=3.141593 real, dimension(0:jmax) :: x, u, du real, dimension(0:jmax,0:mmax) :: v character :: ct*30, cl*6 !!! write(*,*) 'dx=?; dt=? ' !!! read (*,*) dx, dt dx = 1.e-2; dt = 5.e-3 imax = xmax/dx nmax = tmax/dt; ndel = nmax/mmax if(imax > jmax) stop 'error: dx must have a larger value' !-- 初期条件 ---- !!! write(*,*) 'initial condition # ? 1:cos 2:step 3:delta' !!! read (*,*) init init = 2 if(init == 1) then do i=0, imax u(i) = cos(2*pi*i/imax) end do else if(init == 2) then u = - 1 u(imax/4:imax/2) = 1 else u = -1 u(imax/4) = 1 end if do i=0, imax x(i) = i*dx v(i,0) = u(i) end do mm = 0 !-- 時間積分 ---- do n=1, nmax call drv(u, du) u = u + du if(mod(n,ndel) == 0) then mm = mm + 1 v(0:imax,mm) = u end if end do !-- グラフ化 ---- call DclOpenGraphics() call graph call DclCloseGraphics !-- 内部手続き ---- contains subroutine drv(u, du) ! 時間微分を計算する内部サブルーチン real, dimension(0:imax) :: u, du do i=1, imax du(i) = - c*(u(i) - u(i-1))/dx *dt end do du(0) = du(imax) ! 周期境界条件: x=0 <=> x=xmax end subroutine drv subroutine graph ! グラフを描く内部サブルーチン call DclNewFrame call DclSetTitle('x', 'u(x,t)') call DclDrawScaledGraph(x(0:imax), v(0:imax,0)) call DclSetParm('ENABLE_LINE_LABELING', .true.) call DclSetParm('LINE_CYCLE_LENGTH', 50.) call DclSetLineTextSize(0.02) cl = 't=?.?s' do m=1,mm call DclSetLineType(mod(m,4)+1) write(cl(3:5),'(f3.1)') ndel*m*dt call DclSetLineText(cl) call DclDrawLine(x(0:imax), v(0:imax,m)) end do ct = 'dt=??.??E???s' write(ct(4:12),'(e9.2)') dt call DclDrawTitle('t', ct, position=-0.8) call DclDrawTitle('t', ' forward and upstream', position=-1.) call DclDrawTitle('t', 'Advection Equation:', position=-1.) end subroutine graph end program adv_ftus