Julia は 2012年に公開された新しいプログラミング言語で、 色々な特徴があるが、特に数値計算に向いているとされている。
Juliaの処理系のインストールの仕方は、付録 B を見よ。
参考のため1次元の問題のJuliaによるプログラムを掲げる。
| rk1ex1.jl |
# rk1ex1.jl --- dx/dt=x (0<t<1), x(0)=1 を Runge-Kutta法で解く
using Printf
function testrungekutta(Tmax=1.0,N=10)
# 初期値
t0=0.0
x0=1.0
#
@printf("#N=%d Tmax=%f\n", N, Tmax)
@printf("# t x\n")
# Runge-Kutta法
dt=Tmax/N
t=t0
x=x0
for j=1:N
k1=dt*f(t,x)
k2=dt*f(t+dt/2, x+k1/2)
k3=dt*f(t+dt/2, x+k2/2)
k4=dt*f(t+dt, x+k3)
x += (k1+2*k2+2*k3+k4) / 6
t = j * dt
@printf("%.4f %.7f\n", t, x)
end
end
function f(t,x)
x
end
# julia rk1ex1.jl と実行した場合に testrungekutta() を実行する。
if abspath(PROGRAM_FILE) == @__FILE__
testrungekutta()
end
|
| 実行の仕方1 |
% julia rk1ex1.jl
#N=10 Tmax=1.000000 # t x 0.1000 1.1051708 0.2000 1.2214026 0.3000 1.3498585 0.4000 1.4918242 0.5000 1.6487206 0.6000 1.8221180 0.7000 2.0137516 0.8000 2.2255396 0.9000 2.4596014 1.0000 2.7182797 % |
| 実行の仕方2 |
% juliajulia> include("rk1ex1.jl") julia> testrungekutta(1,100) #N=10 Tmax=1.000000 # t x 0.1000 1.1051708 0.2000 1.2214026 0.3000 1.3498585 (中略) 0.9800 2.6644562 0.9900 2.6912345 1.0000 2.7182818 julia> |
次は van der Pol 方程式の問題のJuliaによるプログラムである。 Tmax, N を実行時に入力できるような工夫を入れてみた。
| rk2ex1.jl |
# rk2ex1.jl (Runge-Kutta method for van der Pol equation)
#
# 使い方
# julia rk2ex1.jl デフォルト Tmax=50, N=1000
# julia rk2ex1.jl 100 2000 Tmax=100, N=2000
# echo 'plot "rk2ex1.data" using 2:3 with l"' | gnuplot
using Printf
mu=1.0
# Runge-Kutta 法の1ステップ
function rungekutta(f,t,x,dt)
k1=dt*f(t,x)
k2=dt*f(t+dt/2, x+k1/2)
k3=dt*f(t+dt/2, x+k2/2)
k4=dt*f(t+dt, x+k3)
x + (k1 + 2 * k2 + 2 * k3 + k4) / 6
end
# van der Pol 方程式の右辺
function f(t,x)
y=similar(x)
y[1]=x[2]
y[2]=-x[1]+mu*(1.0-x[1]*x[1])*x[2]
y
end
function testrungekutta(Tmax=50.0,N=1000)
# 初期値
t0=0.0
x0=[0.1,0.1]
#
of=open("rk2ex1.data","w")
# Runge-Kutta法
dt=Tmax/N
t=t0
x=x0
for i=1:N
x=rungekutta(f,t,x,dt)
t=i*dt
s=@sprintf "%f %f %f\n" t x[1] x[2]
print(s)
print(of,s)
end
close(of)
end
# main
argc=length(ARGS)
if argc==0
testrungekutta()
elseif argc==1
testrungekutta(parse(Float64,ARGS[1]))
elseif argc==2
testrungekutta(parse(Float64,ARGS[1]), parse(Int,ARGS[2]))
end
|
| 実行の仕方 |
|
% julia rk2ex1.jl
% gnuplot gnuplot> plot "rk2ex1.data" using 2:3 with l gnuplot> quit
% julia rk2ex1.jl 100 2000
|
Julia には、グラフィックスのためのパッケージが色々ある。 Plots というパッケージを利用してグラフを描く機能を追加したのが、 次のプログラムである。
| rk2ex1plot.jl |
# rk2ex1plot.jl (Runge-Kutta method for van der Pol equation)
#
# 使い方
# julia> include("rk2ex1plot.jl")
# julia> testrungekutta()
# julia> testrungekutta(10)
# julia> testrungekutta(100,10000)
using Printf
using Plots
gr() # デフォルトがGRなので不要という説もある
mu=1.0
# Runge-Kutta 法の1ステップ
function rungekutta(f,t,x,dt)
k1=dt*f(t,x)
k2=dt*f(t+dt/2, x+k1/2)
k3=dt*f(t+dt/2, x+k2/2)
k4=dt*f(t+dt, x+k3)
x + (k1 + 2 * k2 + 2 * k3 + k4) / 6
end
function f(t,x)
y=similar(x)
y[1]=x[2]
y[2]=-x[1]+mu*(1.0-x[1]*x[1])*x[2]
y
end
function testrungekutta(Tmax=50.0,N=1000)
tv=zeros(N+1,1)
xv=zeros(N+1,1)
yv=zeros(N+1,1)
# 初期値
t0=0.0
x0=[0.1,0.1]
#
of=open("rk2ex1.data","w")
s="# Lotka-Volterrra equation"; println(s); println(of,s)
s="# t x y"; println(s); println(of, s)
# Runge-Kutta法
dt=Tmax/N
t=t0
x=x0
s=@sprintf "%f %f %f\n" t x[1] x[2]
print(s)
print(of,s)
# 記録
tv[1]=t; xv[1]=x[1]; yv[1]=x[2]
# 時間を進める
for i=1:N
x=rungekutta(f,t,x,dt)
t=i*dt
tv[i+1]=t; xv[i+1]=x[1]; yv[i+1]=x[2]
s=@sprintf "%f %f %f\n" t x[1] x[2]
print(s)
print(of,s)
end
close(of)
p=plot(xv,yv,title="van der Pol",
xaxis=("x"),yaxis=("y"),xlims=(-3,3),ylims=(-3,3),legend=false)
savefig(p,"rk2ex1plot.png")
display(p)
end
# main
println("usage: testrungekutta()")
println("usage: testrungekutta(10.0) Tmax=10.0")
println("usage: testrungekutta(500.0, 5000) Tmax=500.0, N=5000")
|