§0 準備編¶
§0.1 Julia のインストール¶
§0.1.1 Mac の場合¶
Homebrew (https://brew.sh/ja/) を利用する.
$ brew install --cask julia
§0.1.2 Windows or Linux の場合¶
§0.2 JupyterLab のインストール¶
Anaconda で Python ごと丸っと入れるのがラク. https://hituji-ws.com/code/python/python_env_ana/ 参照.
JupyterLab で Julia を使うには https://leadinge.co.jp/julialang/2022/04/06/jupyterlab/ 参照.
§0.3 パッケージを読み込む¶
# 初回だけで OK
import Pkg
Pkg.add("Plots")
Pkg.add("DifferentialEquations")
Pkg.add("Optim")
Pkg.add("Printf")
Pkg.add("ForwardDiff")
Pkg.add("QuadGK")
Pkg.add("Interpolations")
Pkg.add("LinearAlgebra")
Resolving package versions... No Changes to `~/.julia/environments/v1.11/Project.toml` No Changes to `~/.julia/environments/v1.11/Manifest.toml` Resolving package versions... No Changes to `~/.julia/environments/v1.11/Project.toml` No Changes to `~/.julia/environments/v1.11/Manifest.toml` Resolving package versions... No Changes to `~/.julia/environments/v1.11/Project.toml` No Changes to `~/.julia/environments/v1.11/Manifest.toml` Resolving package versions... No Changes to `~/.julia/environments/v1.11/Project.toml` No Changes to `~/.julia/environments/v1.11/Manifest.toml` Resolving package versions... No Changes to `~/.julia/environments/v1.11/Project.toml` No Changes to `~/.julia/environments/v1.11/Manifest.toml` Resolving package versions... No Changes to `~/.julia/environments/v1.11/Project.toml` No Changes to `~/.julia/environments/v1.11/Manifest.toml` Resolving package versions... No Changes to `~/.julia/environments/v1.11/Project.toml` No Changes to `~/.julia/environments/v1.11/Manifest.toml` Resolving package versions... No Changes to `~/.julia/environments/v1.11/Project.toml` No Changes to `~/.julia/environments/v1.11/Manifest.toml`
# こっちは毎回
using Plots, DifferentialEquations, Optim, Printf, ForwardDiff, QuadGK, Interpolations, LinearAlgebra
§1 基本編¶
§1.1 練習問題¶
$178 + 256$
$\cos(\exp(3)) + \sin(\exp(4))$
$ \begin{pmatrix} 1 & 2 \\ 3 & 4 \end{pmatrix} \begin{pmatrix} 5 \\ 6 \end{pmatrix} $
$A=\begin{pmatrix} 1 & 3 \\ 2 & 3 \end{pmatrix}$, $B=\begin{pmatrix} 4 & 7 \\ 9 & 5 \end{pmatrix}$ のとき $AB$ の $(1,2)$ 成分.
$A=\begin{pmatrix} 2 & 3 \\ 4 & 5 \end{pmatrix}$ の各成分を $3$ 倍.
$\sum_{i=1}^{100}\cos(i)$ を for 文と内包表記の 2 つの方法で求めよ.
$\cos(x)$ をプロットせよ.
正の整数 $n$ に対し, それが偶数なら $n/2$ を, 奇数なら $3n+1$ を返す関数 $$f(x)=\begin{cases} n/2 & \text{for $n\equiv0$} \\ 3n+1 & \text{for $n\equiv1$} \end{cases} \quad\mod{2},$$ を定義せよ. 正の整数 $n$ に対し操作 $f$ を繰り返し, $1$ になるまでの結果を全て出力する関数 $\mathrm{Collatz}(n)$ を定義せよ.
解答¶
178+256
434
cos(exp(3)) + sin(exp(4))
-0.600173180811254
[1 2
3 4]*[5
6]
2-element Vector{Int64}: 17 39
A = [1 3
2 3]
B = [4 7
9 5]
(A*B)[1,2]
22
A = [2 3
4 5]
A .* 3
2×2 Matrix{Int64}: 6 9 12 15
S = 0
for i in 1:100
S += cos(i)
end
@show S
S = -0.5322886082303911
-0.5322886082303911
sum([cos(i) for i in 1:100])
-0.5322886082303911
plot(0:0.01:10, cos)
function f(n) # コラッツ関数
if !(isinteger(n) && n>0) # (整数かつ正) でなかったら
return 1
elseif iseven(n) # (整数かつ正) かつ偶数なら
return div(n,2)
else
return 3n+1 # (整数かつ正) だけど偶数でなかったら
end
end
function Collatz(n)
while n != 1
n = f(n)
@show n
end
end
Collatz (generic function with 1 method)
f(4)
2
Collatz(27)
n = 82 n = 41 n = 124 n = 62 n = 31 n = 94 n = 47 n = 142 n = 71 n = 214 n = 107 n = 322 n = 161 n = 484 n = 242 n = 121 n = 364 n = 182 n = 91 n = 274 n = 137 n = 412 n = 206 n = 103 n = 310 n = 155 n = 466 n = 233 n = 700 n = 350 n = 175 n = 526 n = 263 n = 790 n = 395 n = 1186 n = 593 n = 1780 n = 890 n = 445 n = 1336 n = 668 n = 334 n = 167 n = 502 n = 251 n = 754 n = 377 n = 1132 n = 566 n = 283 n = 850 n = 425 n = 1276 n = 638 n = 319 n = 958 n = 479 n = 1438 n = 719 n = 2158 n = 1079 n = 3238 n = 1619 n = 4858 n = 2429 n = 7288 n = 3644 n = 1822 n = 911 n = 2734 n = 1367 n = 4102 n = 2051 n = 6154 n = 3077 n = 9232 n = 4616 n = 2308 n = 1154 n = 577 n = 1732 n = 866 n = 433 n = 1300 n = 650 n = 325 n = 976 n = 488 n = 244 n = 122 n = 61 n = 184 n = 92 n = 46 n = 23 n = 70 n = 35 n = 106 n = 53 n = 160 n = 80 n = 40 n = 20 n = 10 n = 5 n = 16 n = 8 n = 4 n = 2 n = 1
§ 1.2 常微分方程式¶
常微分方程式 $$\frac{\mathrm{d}x(t)}{\mathrm{d}t}=x(t),$$ を解いてみよう. 微分して同形なので $$ x(t) = C\mathrm{e}^t, $$ だとわかる. $C$ は積分定数.
では $$\frac{\mathrm{d}x(t)}{\mathrm{d}t}=x^3(t)+1, \tag{1}$$ なら?
一般に常微分方程式 $$\frac{\mathrm{d}x(t)}{\mathrm{d}t}=f(x), \tag{2}$$ は解析的に解けるとは限らない. しかし $f(x)$ を評価できるなら以下のように数値的に概形を求めることはできる.

問題¶
オイラー法を用いて常微分方程式 (3) $$\frac{\mathrm{d}x(t)}{\mathrm{d}t}=x^3(t)+1,$$ を, 初期条件 $t_\mathrm{i}=0$, $x_\mathrm{i}=0$ のもとで数値的に解き, 結果をプロットせよ.
f(x) = x^3+1
# 解く時刻範囲 [ti, tf] と時刻幅 dt
ti = 0
tf = 1
N = 100
dt = (tf-ti)/N
tlist = ti:dt:tf
xlist = zeros(N+1) # 空の 101 要素配列を用意しておく.
xi = 0
xlist[1] = xi # xlist の最初の要素に初期条件 xi を代入.
for i in 1:N
xlist[i+1] = xlist[i] + f(xlist[i])*dt # オイラー法
end
plot(tlist,xlist)
§1.2.1 パッケージを使う¶
様々な数値解法が "DifferentialEquations" パッケージに用意されている.
ODE(x,p,t) = f(x) # p: パラメータ (あれば). 1 変数の場合はこの形で dx/dt を用意しておかなければならない
prob = ODEProblem(ODE, xi, (ti,tf)) # 微分方程式を定義
@time sol = solve(prob, Tsit5()); # Tsit5 (可変時間刻み Runge--Kutta) アルゴリズムで解く
0.250389 seconds (670.31 k allocations: 37.314 MiB, 99.98% compilation time: 100% of which was recompilation)
plot(sol.t,sol.u,st=:scatter)
plot!(tlist,xlist) # オイラー法で計算した線と重ねる
@time sol = solve(prob, Tsit5(); reltol=1e-10, abstol=1e-10); # 刻みが粗いので要求精度を上げる
0.061396 seconds (207.80 k allocations: 14.739 MiB, 99.91% compilation time: 100% of which was recompilation)
plot(sol.t,sol.u,st=:scatter)
plot!(tlist,xlist) # オイラー法で計算した線と重ねる
問題¶
微分方程式 $$\frac{\mathrm{d}x}{\mathrm{d}t}=x^3-x,$$ を初期条件 $x_{\mathrm{i},0}=1$, $x_{\mathrm{i},1}=1+10^{-5}$, $x_{\mathrm{i},2}=1-10^{-5}$ の 3 パターンで $t_\mathrm{i}=0$ から $t_\mathrm{f}=5$ まで解き, 重ねてプロットせよ.
Lorenz(x,p,t) = x^3-x
ti = 0
tf = 5
xi0 = 1
xi1 = 1 + 1e-5
xi2 = 1 - 1e-5
prob0 = ODEProblem(Lorenz, xi0, (ti,tf))
prob1 = ODEProblem(Lorenz, xi1, (ti,tf))
prob2 = ODEProblem(Lorenz, xi2, (ti,tf))
@time sol0 = solve(prob0, Tsit5(); reltol=1e-10, abstol=1e-10)
@time sol1 = solve(prob1, Tsit5(); reltol=1e-10, abstol=1e-10)
@time sol2 = solve(prob2, Tsit5(); reltol=1e-10, abstol=1e-10)
plot(sol0.t,sol0.u)
plot!(sol1.t,sol1.u)
plot!(sol2.t,sol2.u)
0.371189 seconds (1.70 M allocations: 94.511 MiB, 99.94% compilation time) 0.033806 seconds (207.46 k allocations: 11.278 MiB, 99.70% compilation time) 0.000044 seconds (191 allocations: 16.125 KiB)
§2 ニュートン力学¶
ニュートンの運動方程式 $$m\frac{\mathrm{d}^2x}{\mathrm{d}t^2}=F.$$ を解いてみよう. 2 階微分方程式を解くには, 位置 $x$ と速度 $v$ の 2 変数を用意して $$\begin{cases} \displaystyle \frac{\mathrm{d}x}{\mathrm{d}t}=v, \\[5pt] \displaystyle \frac{\mathrm{d}v}{\mathrm{d}t}=\frac{F}{m}. \end{cases}$$ と 2 連 1 階微分方程式にすればいい.
§2.1 単振動¶

# 微分 du, 変数 u, パラメータ p, 時間 t
# u[1] = x, u[2] = v
# p[1] = m, p[2] = k
function HarmonicOscillator(du, u, p, t)
du[1] = u[2] # dx/dt = v
du[2] = -p[2]/p[1]*u[1] # dv/dt = -k/m * x
end
HarmonicOscillator (generic function with 1 method)
m = 1 # 質量
k = 1 # ばね定数
xi = 1 # x の初期値
vi = 0 # v の初期値
ui = [xi, vi] # 2 変数の初期値
ti = 0 # 初期時刻
tf = 10 # 終了時刻
p = [m, k] # パラメータ
prob = ODEProblem(HarmonicOscillator, ui, (ti,tf), p) # 問題定義
ODEProblem with uType Vector{Int64} and tType Int64. In-place: true Non-trivial mass matrix: false timespan: (0, 10) u0: 2-element Vector{Int64}: 1 0
@time sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8);
0.005909 seconds (13.70 k allocations: 650.750 KiB, 96.04% compilation time: 100% of which was recompilation)
plot(sol.t, sol[1,:], st=:scatter, xlabel="t", ylabel="x", label="numerical") # t vs x でプロット
plot!(ti:0.01:tf, t -> cos(sqrt(k/m)t), label="analytic") # 解析解 x = cos(sqrt(k/m)t) を重ねる
問題¶
同じ単振動を初期条件 $x_\mathrm{i}=0$, $v_\mathrm{i}=1$ で解け. 解析解は何になるか.
xi = 0 # x の初期値
vi = 1 # v の初期値
prob = ODEProblem(HarmonicOscillator, [xi,vi], (ti,tf), p) # 問題定義
@time sol = solve(prob, Tsit5(), reltol=1e-8, abstol=1e-8)
plot(sol.t, sol[1,:], st=:scatter, xlabel="t", ylabel="x", label="numerical") # t vs x でプロット
plot!(ti:0.01:tf, t -> sin(sqrt(k/m)t), label="analytic") # 解析解 x = sin(sqrt(k/m)t) を重ねる
0.000104 seconds (2.06 k allocations: 90.891 KiB)
§2.2 放物¶

問題¶
投げ上げを初期位置 $(x_\mathrm{i},y_\mathrm{i})=(0,0)$, 初速 $(v_{x,\mathrm{i}},v_{y,\mathrm{i}})=(5,10)$ のもとで解き, $(x,y)$ 平面にプロットせよ. $m=1$, $g=9.8$ とする.
解答¶
運動方程式は $$\begin{cases} \dot{x}=v_x, \\ \dot{v}_x=0, \\ \dot{y}=v_y, \\ \dot{v}_y=-g, \end{cases}$$ である.
# 微分 du, 変数 u, パラメータ p, 時間 t
# u[1] = x, u[2] = vx, u[3] = y, u[4] = vy
# p = g
function Throw(du, u, p, t)
du[1] = u[2]
du[2] = 0
du[3] = u[4]
du[4] = -p
end
g = 9.8 # 重力加速度
xi = 0 # x の初期値
vxi = 5 # vx の初期値
yi = 0 # y の初期値
vyi = 10 # vy の初期値
ti = 0 # 初期時刻
tf = 2 # 終了時刻
prob = ODEProblem(Throw, [xi,vxi,yi,vyi], (ti,tf), g) # 問題定義
@time sol = solve(prob, Tsit5(); reltol=1e-20, abstol=1e-20);
0.935387 seconds (6.21 M allocations: 331.317 MiB, 9.79% gc time, 89.68% compilation time)
plot(sol[1,:], sol[3,:], xlabel="x", ylabel="y")
§2.3 単振り子¶

# 微分 du, 変数 u, パラメータ p, 時間 t
# u[1] = theta, u[2] = \dot{theta}
# p[1] = R, p[2] = g
function Pendulum(du, u, p, t)
du[1] = u[2] # d theta / d t = vtheta
du[2] = -p[2]/p[1]*sin(u[1]) # d vtheta / d t = - g/R * sin(theta)
end
Pendulum (generic function with 1 method)
R = 1 # 腕の長さ
g = 9.8 # 重力加速度
θi = π/4 # theta の初期値
vθi = 0 # vtheta の初期値
ui = [θi, vθi] # 2 変数の初期値
ti = 0 # 初期時刻
tf = 10 # 終了時刻
p = [R, g] # パラメータ
prob = ODEProblem(Pendulum, ui, (ti,tf), p) # 問題定義
ODEProblem with uType Vector{Float64} and tType Int64. In-place: true Non-trivial mass matrix: false timespan: (0, 10) u0: 2-element Vector{Float64}: 0.7853981633974483 0.0
@time sol = solve(prob, Tsit5(), reltol = 1e-8, abstol = 1e-8);
0.000453 seconds (5.70 k allocations: 256.016 KiB)
plot(sol.t, sol[1,:], st=:scatter)
# 描画設定
anim = @animate for t in ti:0.05:tf
θ = sol(t)[1]
x = R * sin(θ)
y = R * cos(θ)
plot([0, x], [0, -y],
xlims = (-R-0.2, R+0.2),
ylims = (-R-0.2, 0.2),
lw=3, marker=:circle, markersize=8,
legend=false, aspect_ratio=:equal,
xlabel="x", ylabel="y", title=@sprintf("t = %.2f s", t))
end
# gifとして保存
gif(anim, "gifs/pendulum.gif", fps=20)
[ Info: Saved animation to /Users/yuichirotada/Documents/Univ/website/julia/gifs/pendulum.gif
中間発表¶
好きな質点系をシミュレートしアニメーションを出力せよ
例 1: 2 重振り子¶

例 2: ローレンツアトラクター¶
$$\begin{cases} \displaystyle \frac{\mathrm{d}x}{\mathrm{d}t}=\sigma(y-x), \\[5pt] \displaystyle \frac{\mathrm{d}y}{\mathrm{d}t}=x(\rho-z)-y, \\[5pt] \displaystyle \frac{\mathrm{d}z}{\mathrm{d}t}=xy-\beta z. \end{cases}$$ $\sigma$, $\rho$, $\beta$ は正のパラメータ.
例 3: $N$ ($\geq3$) 体万有引力シミュレーション¶
$$\begin{cases} \displaystyle \ddot{x}_i=\sum_{j\neq i}m_j\frac{x_j-x_i}{r_{ij}^3}, \\ \displaystyle \ddot{y}_i=\sum_{j\neq i}m_j\frac{y_j-y_i}{r_{ij}^3}, \\ \displaystyle \ddot{z}_i=\sum_{j\neq i}m_j\frac{z_j-z_i}{r_{ij}^3}, \end{cases}$$ ただし $$r_{ij}=\sqrt{(x_i-x_j)^2+(y_i-y_j)^2+(z_i-z_j)^2}.$$
例 1: 解答例¶
# 微分 du, 変数 u, パラメータ p, 時間 t
# u[1] = theta1, u[2] = v1, u[3] = theta2, u[4] = v2
# p[1] = l1, p[2] = l2, p[3] = m1, p[4] = m2, p[5] = g
function DoublePendulum(du, u, p, t)
theta1 = u[1]
v1 = u[2]
theta2 = u[3]
v2 = u[4]
l1 = p[1]
l2 = p[2]
m1 = p[3]
m2 = p[4]
g = p[5]
C = cos(theta1-theta2)
S = sin(theta1-theta2)
m12 = m1+m2
du[1] = v1
du[2] = (g*(C*sin(theta2)-m12/m2*sin(theta1)) - (l1*v1*v1*C + l2*v2*v2)*S) / l1 / (m12/m2 - C*C)
du[3] = v2
du[4] = (g*m12/m2*(C*sin(theta1)-sin(theta2)) + (m12/m2*l1*v1*v1 + l2*v2*v2*C)*S) / l2 / (m12/m2 - C*C)
end
DoublePendulum (generic function with 1 method)
l1 = 1
l2 = 1
m1 = 1
m2 = 1
g = 9.8
theta1i = π/2
v1i = 0
theta2i = π/2
v2i = 0
ti = 0
tf = 25
p = [l1,l2,m1,m2,g]
ui0 = [theta1i, v1i, theta2i, v2i]
ui1 = [theta1i, v1i, theta2i + 1e-5, v2i]
ui2 = [theta1i, v1i, theta2i - 1e-5, v2i]
prob0 = ODEProblem(DoublePendulum, ui0, (ti,tf), p)
prob1 = ODEProblem(DoublePendulum, ui1, (ti,tf), p)
prob2 = ODEProblem(DoublePendulum, ui2, (ti,tf), p)
ODEProblem with uType Vector{Float64} and tType Int64. In-place: true Non-trivial mass matrix: false timespan: (0, 25) u0: 4-element Vector{Float64}: 1.5707963267948966 0.0 1.5707863267948965 0.0
@time begin
sol0 = solve(prob0, Tsit5(); reltol = 1e-8, abstol = 1e-8)
sol1 = solve(prob1, Tsit5(); reltol = 1e-8, abstol = 1e-8)
sol2 = solve(prob2, Tsit5(); reltol = 1e-8, abstol = 1e-8)
end;
0.046810 seconds (269.39 k allocations: 14.073 MiB, 89.89% compilation time)
# 描画設定
anim = @animate for t in ti:0.05:tf
θ1 = sol0(t)[1]
θ2 = sol0(t)[3]
x1 = l1 * sin(θ1)
y1 = l1 * cos(θ1)
x2 = x1 + l2 * sin(θ2)
y2 = y1 + l2 * cos(θ2)
plot([0, x1, x2], [0, -y1, -y2],
xlims = (-l1-l2-0.2, l1+l2+0.2),
ylims = (-l1-l2-0.2, l1+l2+0.2),
lw=3, marker=:circle, markersize=8,
legend=false, aspect_ratio=:equal,
xlabel="x", ylabel="y", title=@sprintf("t = %.2f s", t))
θ1 = sol1(t)[1]
θ2 = sol1(t)[3]
x1 = l1 * sin(θ1)
y1 = l1 * cos(θ1)
x2 = x1 + l2 * sin(θ2)
y2 = y1 + l2 * cos(θ2)
plot!([0, x1, x2], [0, -y1, -y2],
xlims = (-l1-l2-0.2, l1+l2+0.2),
ylims = (-l1-l2-0.2, l1+l2+0.2),
lw=3, marker=:circle, markersize=8,
legend=false)
θ1 = sol2(t)[1]
θ2 = sol2(t)[3]
x1 = l1 * sin(θ1)
y1 = l1 * cos(θ1)
x2 = x1 + l2 * sin(θ2)
y2 = y1 + l2 * cos(θ2)
plot!([0, x1, x2], [0, -y1, -y2],
xlims = (-l1-l2-0.2, l1+l2+0.2),
ylims = (-l1-l2-0.2, l1+l2+0.2),
lw=3, marker=:circle, markersize=8,
legend=false)
end
# gifとして保存
gif(anim, "gifs/double_pendulum.gif", fps=20)
[ Info: Saved animation to /Users/yuichirotada/Documents/Univ/website/julia/gifs/double_pendulum.gif
例 2: 解答例¶
function Lorenz(du, u, p, t)
du[1] = p[1]*(u[2]-u[1])
du[2] = u[1]*(p[2]-u[3]) - u[2]
du[3] = u[1]*u[2] - p[3]*u[3]
end
Lorenz (generic function with 2 methods)
σ = 10
ρ = 28
β = 8/3
ti = 0
tf = 50
ui0 = [-10,-10,30]
uip = [-10+1e-5,-10+1e-5,30+1e-5]
uim = [-10-1e-5,-10-1e-5,30-1e-5]
prob0 = ODEProblem(Lorenz, ui0, (ti,tf), [σ,ρ,β])
probp = ODEProblem(Lorenz, uip, (ti,tf), [σ,ρ,β])
probm = ODEProblem(Lorenz, uim, (ti,tf), [σ,ρ,β])
ODEProblem with uType Vector{Float64} and tType Int64. In-place: true Non-trivial mass matrix: false timespan: (0, 50) u0: 3-element Vector{Float64}: -10.00001 -10.00001 29.99999
@time begin
sol0 = solve(prob0, Tsit5(); dt = 0.01, adaptive=false) # 固定幅で解く
solp = solve(probp, Tsit5(); dt = 0.01, adaptive=false)
solm = solve(probm, Tsit5(); dt = 0.01, adaptive=false)
end;
0.143964 seconds (656.87 k allocations: 32.537 MiB, 95.97% compilation time)
anim = @animate for i in 1:10:length(sol0.u)
plot(sol0[1,max(1,i-500):i], sol0[2,max(1,i-500):i], sol0[3,max(1,i-500):i],
xlims = (-20,20), ylims = (-30,30), zlims = (-20,50),
title=@sprintf("t = %.2f s", sol0.t[i]))
plot!(solp[1,max(1,i-500):i], solp[2,max(1,i-500):i], solp[3,max(1,i-500):i])
plot!(solm[1,max(1,i-500):i], solm[2,max(1,i-500):i], solm[3,max(1,i-500):i])
end
gif(anim, "gifs/Lorenz.gif", fps=20)
[ Info: Saved animation to /Users/yuichirotada/Documents/Univ/website/julia/gifs/Lorenz.gif
例 3: 解答例¶
# xy 平面のみ
# u[4i-3] = xi, u[4i-2] = yi, u[4i-1] = vxi, u[4i] = vyi
# p[i] = mi
function Nbody(du,u,p,t)
for i in 1:div(length(u),4)
du[4i-3] = u[4i-1]
du[4i-2] = u[4i]
du[4i-1] = 0
du[4i] = 0
for j in 1:div(length(u),4)
if i == j
continue
end
rijvec = u[4j-3:4j-2]-u[4i-3:4i-2]
rij = norm(rijvec)
du[4i-1] += p[j]*rijvec[1]/rij^3
du[4i] += p[j]*rijvec[2]/rij^3
end
end
end
Nbody (generic function with 1 method)
Np = 3
u0 = [4,0,0,0, 1,1,0,0, -1,-1,0,0]
up = [4,0,0,0, 1+1e-3,1,0,0, -1,-1,0,0]
um = [4,0,0,0, 1-1e-3,1,0,0, -1,-1,0,0]
tf = 50
mass = [1 for i in 1:Np]
prob0 = ODEProblem(Nbody,u0,(0,tf),mass)
probp = ODEProblem(Nbody,up,(0,tf),mass)
probm = ODEProblem(Nbody,um,(0,tf),mass);
@time begin
sol0 = solve(prob0, Tsit5(), reltol=1e-8, abstol=1e-8)
solp = solve(probp, Tsit5(), reltol=1e-8, abstol=1e-8)
solm = solve(probm, Tsit5(), reltol=1e-8, abstol=1e-8)
end;
0.709019 seconds (14.11 M allocations: 580.464 MiB, 58.98% gc time)
# 描画設定
lim = 5
anim = @animate for t in ti:0.1:tf
plot([sol0(t)[i] for i in 1:4:4Np], [sol0(t)[i] for i in 2:4:4Np],
xlims = (-lim, lim),
ylims = (-lim, lim),
marker=:circle, markersize=5, st=:scatter,
legend=false, aspect_ratio=:equal,
xlabel="x", ylabel="y", title=@sprintf("t = %.2f s", t))
plot!([solp(t)[i] for i in 1:4:4Np], [solp(t)[i] for i in 2:4:4Np],
marker=:circle, markersize=5, st=:scatter)
plot!([solm(t)[i] for i in 1:4:4Np], [solm(t)[i] for i in 2:4:4Np],
marker=:circle, markersize=5, st=:scatter)
end
# gifとして保存
gif(anim, "gifs/Nbody.gif", fps=20)
[ Info: Saved animation to /Users/yuichirotada/Documents/Univ/website/julia/gifs/Nbody.gif
§3 解析力学¶
§3.1 最速降下曲線¶


§3.1.1 3 つの例¶

y1(x) = x/2
y2(x) = -3/2*x*(x-7/3)
y3(x) = -(x-2)^2/4 + 1.
g = 9.8
9.8
yoff = 0.1 # 原点で初速がないとプログラム上動かないので少しかさまし
vx1(x) = sqrt(2g*(y1(x)+yoff) / (1+ForwardDiff.derivative(y1,x)^2))
vx2(x) = sqrt(2g*(y2(x)+yoff) / (1+ForwardDiff.derivative(y2,x)^2))
vx3(x) = sqrt(2g*(y3(x)+yoff) / (1+ForwardDiff.derivative(y3,x)^2))
xi = 0
xf = 2
function brachistochrone(du,u,p,t)
if u[1] < xf
du[1] = vx1(u[1])
else
du[1] = 0 # xf を越えたら止める
end
if u[2] < xf
du[2] = vx2(u[2])
else
du[2] = 0 # xf を越えたら止める
end
if u[3] < xf
du[3] = vx3(u[3])
else
du[3] = 0 # xf を越えたら止める
end
end
ti = 0
tf = 1.5
prob = ODEProblem(brachistochrone, [xi,xi,xi], (ti,tf))
ODEProblem with uType Vector{Int64} and tType Float64. In-place: true Non-trivial mass matrix: false timespan: (0.0, 1.5) u0: 3-element Vector{Int64}: 0 0 0
@time sol = solve(prob, Tsit5(); reltol=1e-8, abstol=1e-8);
0.031474 seconds (37.88 k allocations: 1.198 MiB, 96.87% compilation time: 100% of which was recompilation)
xlist = [x for x in 0:0.01:2]; # プロット用 x リスト
# 描画設定
anim = @animate for t in ti:0.01:tf
x1t, x2t, x3t = sol(t)
y1t = -y1(x1t)
y2t = -y2(x2t)
y3t = -y3(x3t)
plot([x1t], [y1t],
xlims = (-0.2, 2+0.2),
ylims = (-2-0.2, 0.2),
marker=:circle, markersize=8, primary=false,
xlabel="x", ylabel="y", title=@sprintf("t = %.2f s", t), aspect_ratio=:equal)
plot!([x2t],[y2t],marker=:circle, markersize=8, primary=false)
plot!([x3t],[y3t],marker=:circle, markersize=8, primary=false)
plot!(xlist, -y1.(xlist), label="y1")
plot!(xlist, -y2.(xlist), label="y2")
plot!(xlist, -y3.(xlist), label="y3")
end
# gifとして保存
gif(anim, "gifs/brachistochrone.gif", fps=30)
[ Info: Saved animation to /Users/yuichirotada/Documents/Univ/website/julia/gifs/brachistochrone.gif
問題¶
最速で到達する関数形 $y_\mathrm{fast}(x)$ を探してみよう.
§3.1.2 最小時間問題¶
$x$ における $x$ 方向の速度 $v_x$ は (4) 式で与えられるので, 微小区間 $(x,x+\mathrm{d}x)$ の間にかかる微小時間 $\mathrm{d}t$ は $$\mathrm{d}t=\frac{\mathrm{d}x}{v_x}=\sqrt{\frac{1+y'(x)^2}{2gy(x)}}\mathrm{d}x,$$ で与えられる. これを積分の変数変換の式だと考えれば, 到達時間 $T$ は以下の積分で与えられることになる. $$T[y(x)] = \int_0^T\mathrm{d}t = \int_0^{x_\mathrm{f}}\frac{1}{v_x}\mathrm{d}x = \int_0^{x_\mathrm{f}}\sqrt{\frac{1+y'(x)^2}{2gy(x)}}\mathrm{d}x.$$ 到達時間 $T$ は曲線の方程式 $y(x)$ を 1 つ与えると値が 1 つ決まる. このように関数形を与えると 1 つ値を返す変換を「汎函数」と呼び, $T[y(x)]$ のように $[]$ を使って表す.
function arrivalT(vx::Function, xi, xf)
return quadgk(x -> 1/vx(x), xi, xf)[1] # 1/vx を xi から xf まで積分する
end
arrivalT (generic function with 1 method)
@show arrivalT(vx1, xi, xf)
@show arrivalT(vx2, xi, xf)
@show arrivalT(vx3, xi, xf)
arrivalT(vx1, xi, xf) = 0.7400186442279827 arrivalT(vx2, xi, xf) = 0.8392208962277332 arrivalT(vx3, xi, xf) = 0.6774096266267688
0.6774096266267688
$T[y(x)]$ が最小となる $y(x)$ はどうすればもとまるだろうか. 数値的には次のようにすればよい.
$x_\mathrm{i}$ における $y$ は $y_\mathrm{i}$, 曲線の傾きは $y'_\mathrm{i}\coloneqq(y_1-y_\mathrm{i})/\mathrm{d}x$. したがって次の $x_1$ までかかる時間 $\mathrm{d}T_\mathrm{i}$ は
$$\mathrm{d}T_\mathrm{i}=\sqrt{\frac{1+{y'_\mathrm{i}}^2}{2gy_\mathrm{i}}}\mathrm{d}x.$$
同様に $x_n$ ($n=1,2,\dots,N-2$) において次の点までかかる時間は
$$\mathrm{d}T_n=\sqrt{\frac{1+{y'_n}^2}{2gy_n}}\mathrm{d}x, \quad y'_n=\frac{y_{n+1}-y_n}{\mathrm{d}x}.$$
$x_{N-1}$ では
$$\mathrm{d}T_{N-1}=\sqrt{\frac{1+{y'_{N-1}}^2}{2gy_{N-1}}}\mathrm{d}x, \quad y'_{N-1}=\frac{y_\mathrm{f}-y_{N-1}}{\mathrm{d}x}.$$
$x_N=x_\mathrm{f}$ はすでにゴールに到着しているので考慮しない.
以上より適当に与えたリスト $\mathbf{y}=[y_1,y_2,\dots,y_{N-1}]$ に対し到達時間は
$$T[\mathbf{y}]=\mathrm{d}T_\mathrm{i}+\sum_{n=1}^{N-2}\mathrm{d}T_n+\mathrm{d}T_{N-1},$$
と計算できる. これを最小化するよう $y_n$ を 1 つずつ合わせる (南京錠を開けるように) ことを繰り返していけば, 真の解 $y(x)$ に近づく.
xi = 0
xf = 2
N = 100+1 # x 分割数
dx = (xf-xi) / N
yi = 0
yf = 1
function arrivalT(y::Vector) # y は長さ N-1 のリスト
yprime = diff(y) ./ dx # y[n+1] - y[n] のリスト
ypi = (y[1] - yi) /dx
ypf = (yf - y[end]) / dx
T = (sqrt((1+ypi^2)/2/g/(yi+yoff)) # dTi
+ sum([sqrt((1+yprime[i]^2)/2/g/(y[i]+yoff)) for i in 1:length(y)-1]) # dTn
+ sqrt((1+ypf^2)/2/g/(y[end]+yoff)))*dx # dT(N-1)
return T
end
arrivalT (generic function with 2 methods)
y0 = [y1(x) for x in dx:dx:xf-dx] # 初期試行リストとしては直線 y(x) = y1(x) = x/2 を用いよう
arrivalT(y0) # y1(x) に対する近似到着時間
0.7456049262661909
opt_result = optimize(arrivalT, y0, BFGS()) # BFGS法で最適化する準備
y_opt = opt_result.minimizer # T を最小にする y を求める
xlist = [x for x in 0:0.01:2]
# 結果プロット
plot(xi:dx:xf, vcat([-yi],-y_opt,[-yf]), label="opt", aspect_ratio=:equal, xlabel="x", ylabel="y")
plot!(xlist, -y1.(xlist), label="y1", line=:auto)
plot!(xlist, -y2.(xlist), label="y2", line=:auto)
plot!(xlist, -y3.(xlist), label="y3", line=:auto)
y_opt_int = CubicSplineInterpolation(xi:dx:xf, vcat([yi],y_opt,[yf])) # 滑らかにつなぐ
plot(xi:dx:xf, (x -> -y_opt_int(x)), label="opt", aspect_ratio=:equal, xlabel="x", ylabel="y") # 同じ図が得られる
plot!(xlist, -y1.(xlist), label="y1", line=:auto)
plot!(xlist, -y2.(xlist), label="y2", line=:auto)
plot!(xlist, -y3.(xlist), label="y3", line=:auto)
yoff = 0.1 # 原点で初速がないとプログラム上動かないので少しかさまし
vx1(x) = sqrt(2g*(y1(x)+yoff) / (1+ForwardDiff.derivative(y1,x)^2))
vx2(x) = sqrt(2g*(y2(x)+yoff) / (1+ForwardDiff.derivative(y2,x)^2))
vx3(x) = sqrt(2g*(y3(x)+yoff) / (1+ForwardDiff.derivative(y3,x)^2))
vx_opt(x) = sqrt(2g*(y_opt_int(x)+yoff) / (1+ForwardDiff.derivative(y_opt_int,x)^2))
xi = 0
xf = 2
function brachistochrone(du,u,p,t)
if u[1] < xf
du[1] = vx1(u[1])
else
du[1] = 0 # xf を越えたら止める
end
if u[2] < xf
du[2] = vx2(u[2])
else
du[2] = 0 # xf を越えたら止める
end
if u[3] < xf
du[3] = vx3(u[3])
else
du[3] = 0 # xf を越えたら止める
end
if u[4] < xf
du[4] = vx_opt(u[4])
else
du[4] = 0 # xf を越えたら止める
end
end
ti = 0
tf = 1.5
prob = ODEProblem(brachistochrone, [xi,xi,xi,xi], (ti,tf))
ODEProblem with uType Vector{Int64} and tType Float64. In-place: true Non-trivial mass matrix: false timespan: (0.0, 1.5) u0: 4-element Vector{Int64}: 0 0 0 0
@time sol = solve(prob, Tsit5(); reltol=1e-8, abstol=1e-8);
0.131399 seconds (822.82 k allocations: 39.412 MiB, 99.18% compilation time: 25% of which was recompilation)
xlist = [x for x in 0:0.01:2]; # プロット用 x リスト
# 描画設定
anim = @animate for t in ti:0.01:tf
x1t, x2t, x3t, x4t = sol(t)
y1t = -y1(x1t)
y2t = -y2(x2t)
y3t = -y3(x3t)
x_opt_t = min(x4t,2)
y_opt_t = -y_opt_int(x_opt_t)
plot([x1t], [y1t],
xlims = (-0.2, 2+0.2),
ylims = (-2-0.2, 0.2),
marker=:circle, markersize=8,
xlabel="x", ylabel="y", title=@sprintf("t = %.2f s", t),
aspect_ratio=:equal, primary=false)
plot!([x2t],[y2t],marker=:circle, markersize=8, primary=false)
plot!([x3t],[y3t],marker=:circle, markersize=8, primary=false)
plot!([x_opt_t],[y_opt_t],marker=:circle, markersize=8, primary=false)
plot!(xlist, -y_opt_int.(xlist), label="y_opt")
plot!(xlist, -y1.(xlist), line=:auto, label="y1")
plot!(xlist, -y2.(xlist), line=:auto, label="y2")
plot!(xlist, -y3.(xlist), line=:auto, label="y3")
end
# gifとして保存
gif(anim, "gifs/brachistochrone_opt.gif", fps=30)
[ Info: Saved animation to /Users/yuichirotada/Documents/Univ/website/julia/gifs/brachistochrone_opt.gif
@show arrivalT(vx1, xi, xf)
@show arrivalT(vx2, xi, xf)
@show arrivalT(vx3, xi, xf)
@show arrivalT(vx_opt, xi, xf)
arrivalT(vx1, xi, xf) = 0.7400186442279827 arrivalT(vx2, xi, xf) = 0.8392208962277332 arrivalT(vx3, xi, xf) = 0.6774096266267688 arrivalT(vx_opt, xi, xf) = 0.6627676593799467
0.6627676593799467
§3.1.3 最小汎函数問題¶
結局 $T[y(x)]$ のような汎函数を最小化する $y_\mathrm{min}(x)$ はどのような関数だったのか. 例えば関数 $f(x)$ を最小化する点 $x_\mathrm{min}$ は $\mathrm{d}f/\mathrm{d}x=0$ となる点を求めればよい. これは $x_\mathrm{min}$ 付近では $x$ をわずかに ($\mathrm{d}x$) 動かしても $f$ が変わらないことを意味する. $$f(x_\mathrm{min}+\mathrm{d}x)\approx f(x_\mathrm{min}).$$ 汎函数においても $y_\mathrm{min}(x)$ を少しずらした経路 $y_\mathrm{min}(x)+\delta y(x)$ に対しても $T$ があまり変わらないはずだ: $$T[y_\mathrm{min}(x)+\delta y(x)]\approx T[y_\mathrm{min}].$$ この条件を満たす $y_\mathrm{min}(x)$ を見つけてくればよい.
到達時間 $T[y(x)]=\int_0^{x_\mathrm{f}}\sqrt{\frac{1+y'(x)^2}{2gy(x)}}\mathrm{d}x$ で具体的に考えてみよう. ずらした経路の微分が $y_\mathrm{min}'(x)+\delta y'(x)$ で与えられることに注意して \begin{align} T[y_\mathrm{min}(x)+\delta y(x)]&=\int_0^{x_\mathrm{f}}\mathrm{d}x\sqrt{\frac{1+(y_\mathrm{min}'(x)+\delta y'(x))^2}{2g(y_\mathrm{min}(x)+\delta y(x))}} \\ &\simeq\int_0^{x_\mathrm{f}}\mathrm{d}x\sqrt{\frac{1+(y_\mathrm{min}'(x))^2+2y_\mathrm{min}'(x)\delta y'(x)}{2g(y_\mathrm{min}(x)+\delta y(x))}} \quad \left(\text{$\because$ $(\delta y'(x))^2$ を無視}\right) \\ &=\int_0^{x_\mathrm{f}}\mathrm{d}x\sqrt{1+(y_\mathrm{min}'(x))^2}\times\left(1+\frac{2y_\mathrm{min}'(x)\delta y'(x)}{1+(y_\mathrm{min}'(x))^2}\right)^{1/2}\times\frac{1}{\sqrt{2gy_\mathrm{min}(x)}}\times\left(1+\frac{\delta y(x)}{y_\mathrm{min}(x)}\right)^{-1/2} \\ &\simeq\int_0^{x_\mathrm{f}}\mathrm{d}x\sqrt{\frac{1+(y_\mathrm{min}'(x))^2}{2gy_\mathrm{min}(x)}}\times\left(1+\frac{1}{2}\frac{2y_\mathrm{min}'(x)\delta y'(x)}{1+(y_\mathrm{min}'(x))^2}\right)\times\left(1-\frac{1}{2}\frac{\delta y(x)}{y_\mathrm{min}(x)}\right) \quad \left(\text{$\because$ $(1+\epsilon)^{1/2}\simeq1+\frac{1}{2}\epsilon$, $(1+\epsilon)^{-1/2}=(1-\frac{1}{2}\epsilon)$}\right) \\ &\simeq\int_0^{x_\mathrm{f}}\mathrm{d}x\sqrt{\frac{1+(y_\mathrm{min}'(x))^2}{2gy_\mathrm{min}(x)}}\times\left(1+\frac{y_\mathrm{min}'(x)\delta y'(x)}{1+(y_\mathrm{min}'(x))^2}-\frac{\delta y(x)}{2y_\mathrm{min}(x)}\right) \quad \left(\text{$\because$ $\delta y(x)\delta y'(x)$ を無視}\right) \\ &=T[y_\mathrm{min}(x)]+\int_0^{x_\mathrm{f}}\mathrm{d}x\left(\sqrt{\frac{1+(y_\mathrm{min}'(x))^2}{2gy_\mathrm{min}(x)}}\frac{y_\mathrm{min}'(x)}{1+(y_\mathrm{min}'(x))^2}\right)\delta y'(x)-\int_0^{x_\mathrm{f}}\mathrm{d}x\left(\sqrt{\frac{1+(y_\mathrm{min}'(x))^2}{2gy_\mathrm{min}(x)}}\frac{1}{2y_\mathrm{min}(x)}\right)\delta y(x) \\ &=T[y_\mathrm{min}(x)]-\int_0^{x_\mathrm{f}}\mathrm{d}x\left[\partial_x\left(\sqrt{\frac{1+(y_\mathrm{min}'(x))^2}{2gy_\mathrm{min}(x)}}\frac{y_\mathrm{min}'(x)}{1+(y_\mathrm{min}'(x))^2}\right)+\sqrt{\frac{1+(y_\mathrm{min}'(x))^2}{2gy_\mathrm{min}(x)}}\frac{1}{2y_\mathrm{min}(x)}\right]\delta y(x) \quad \left(\text{$\because$ 部分積分}\right) \\ &=T[y_\mathrm{min}(x)]-\int_0^{x_\mathrm{f}}\mathrm{d}x\sqrt{\frac{1+(y_\mathrm{min}'(x))^2}{2gy_\mathrm{min}(x)}}\times\frac{1+(y_\mathrm{min}'(x))^2+2y_\mathrm{min}y_\mathrm{min}''(x)}{2y_\mathrm{min}(x)(1+(y_\mathrm{min}'(x))^2)^2}\delta y(x). \tag{5} \end{align} この第 2 項がどんな微小ずらし $\delta y(x)$ に対しても 0 にならなければならないので, $y_\mathrm{min}(x)$ は $$\boxed{1+(y_\mathrm{min}'(x))^2+2y_\mathrm{min}(x)y_\mathrm{min}''(x)=0, \tag{6}}$$ を満たさなければならない. 実はこの微分方程式の解はサイクロイド (https://ja.wikipedia.org/wiki/%E3%82%B5%E3%82%A4%E3%82%AF%E3%83%AD%E3%82%A4%E3%83%89): $$\begin{cases} x=r_\mathrm{m}(\theta-\sin\theta), \\ y=r_\mathrm{m}(1-\cos\theta), \end{cases}$$ で与えられることが知られている. 実際この時 \begin{align} &\frac{\mathrm{d}y}{\mathrm{d}x}=\frac{\mathrm{d}y/\mathrm{d}\theta}{\mathrm{d}x/\mathrm{d}\theta}=\frac{\sin\theta}{1-\cos\theta}, \\ &\frac{\mathrm{d}^2y}{\mathrm{d}x^2}=\frac{\mathrm{d}}{\mathrm{d}x}\frac{\mathrm{d}y}{\mathrm{d}x}=\left(\frac{\mathrm{d}x}{\mathrm{d}\theta}\right)^{-1}\frac{\mathrm{d}}{\mathrm{d}\theta}\frac{\mathrm{d}y}{\mathrm{d}x}=-\frac{1}{r_\mathrm{m}(1-\cos\theta)^2}, \end{align} であり, これを代入すると (6) 式を満たす.
ちなみに (5) 式第 2 項の $\delta y(x)$ の係数は, 形式的に $T[y(x)]$ の被積分関数 $\sqrt{\frac{1+y'(x)^2}{2gy(x)}}$ を $y(x)$ と $y'(x)$ の関数 $\tau\left(y(x),y'(x)\right)$ とみなせば $$\frac{\partial\tau(y(x),y'(x))}{\partial y(x)}-\partial_x\left(\frac{\partial\tau(y(x),y'(x))}{\partial y'(x)}\right),$$ によって得られる. このように汎函数 $T[y(x)]$ の $y(x)$ を微小にずらすことを変分といい $\delta T/\delta y$ と書く (↔︎ 関数 $f(x)$ の微分 $\mathrm{d}f/\mathrm{d}x$). $T[y(x)]$ を最小化する $y_\mathrm{min}(x)$ は変分 $\delta T/\delta y$ を 0 にする関数として求められる: $$\boxed{\frac{\delta T[y(x)]}{\delta y(x)}=\frac{\partial\tau(y(x),y'(x))}{\partial y(x)}-\partial_x\left(\frac{\partial\tau(y(x),y'(x))}{\partial y'(x)}\right)=0.}$$
§3.2 ラグランジアン¶
汎函数の変分を $0$ にするという条件から微分方程式が得られた. これをニュートン力学に応用できないだろうか. すなわち $$\text{変分が「$ma-F$」となるような汎函数}$$ とはどのようなものだろうか. 実はラグランジアン $L(x,\dot{x})$ なる位置 $x$ と速度 $\dot{x}$ の関数 $$L(x,\dot{x})=\text{(運動エネルギー)}-\text{(位置エネルギー)},$$ を積分した作用 $S[x(t)]$: $$S[x(t)]=\int_{t_\mathrm{i}}^{t_\mathrm{f}}L(x,\dot{x})\mathrm{d}t,$$ がそのような汎函数であることが知られている. すなわち $$\frac{\delta S[x(t)]}{\delta x(t)}=\frac{\partial L}{\partial x}-\partial_t\left(\frac{\partial L}{\partial\dot{x}}\right)=0 \quad \Leftrightarrow \quad F=m\ddot{x}.$$
例 1: 鉛直投げ上げ¶
$$L(y,\dot{y})=\frac{1}{2}m\dot{y}^2-mgy,$$ より $$0=\frac{\delta S[y(t)]}{\delta y(t)}=\frac{\partial L}{\partial y}-\partial_t\left(\frac{\partial L}{\partial\dot{y}}\right)=-mg-\partial_t\left(m\dot{y}\right)=-mg-m\ddot{y}.$$ たしかに鉛直投げ上げの運動方程式 $$m\ddot{y}=-mg,$$ が得られる.
# パラメータ設定
m = 1
g = 9.8
T = 2 # 終了時間
N = 20 # 時間分割数
dt = T / N # 時間刻み
t = 0:dt:T # 時間配列
yi = 0
yf = 5
# ラグランジアンの定義
function Lagrangian(y, v)
return (1/2) * m * v^2 - m * g * y
end
# 作用 S の計算
function action(y::Vector)
v = diff(y) ./ dt # 速度の計算(前進差分)
vi = (y[1] - yi) / dt
vf = (yf - y[end]) / dt
S = (Lagrangian(yi,vi) + sum(Lagrangian.(y[1:end-1], v)) + Lagrangian(y[end],vf)) * dt
return S
end
y0 = [yi + (yf-yi) * k/N for k=1:(N-1)] # 初期経路 (直線)
result = optimize(action, y0, BFGS()) # BFGS法で最適化
y_opt = result.minimizer
y_EoM(t) = -1/2*g*t*(t-T-2*yf/g/T) # 解析解
# 結果プロット
plot(t, vcat([yi],y_opt,[yf]), lw=3, label="action", xlabel="t", ylabel="y")
plot!(t, y_EoM, linestyle=:auto, label="EoM")
例 2: 単振り子¶

ラグランジアンは $$L=\frac{1}{2}m\dot{x}^2+\frac{1}{2}m\dot{y}^2+mgy.$$ これに $$x=R\sin\theta, \quad y=R\cos\theta,$$ を代入すると $$L(\theta,\dot{\theta})=\frac{1}{2}m(R\dot{\theta}\cos\theta)^2+\frac{1}{2}m(R\dot{\theta}\sin\theta)^2+mgR\cos\theta=\frac{1}{2}mgR^2\dot{\theta}^2+mgR\cos\theta.$$ 運動方程式は $$0=\frac{\delta S[\theta(t)]}{\delta\theta(t)}=\frac{\partial L}{\partial\theta}-\partial_t\left(\frac{\partial L}{\partial\dot{\theta}}\right)=-mgR\sin\theta-\partial_t(mgR^2\dot{\theta})=-mgR\sin\theta-mgR^2\ddot{\theta},$$ すなわち $$R\ddot{\theta}=-g\sin\theta.$$
挑戦問題: 2 重振り子¶

2 重振り子の運動方程式 $$\begin{cases} \displaystyle \ddot{\theta}_1=\frac{g(C\sin\theta_2-\frac{m_{12}}{m_2}\sin\theta_1)-(l_1v_1^2C+l_2v_2^2)S}{l_1(\frac{m_{12}}{m_2}-C^2)}, \\ \displaystyle \ddot{\theta}_2=\frac{g\frac{m_{12}}{m_2}(C\sin\theta_1-\sin\theta_2)+(\frac{m_{12}}{m_2}l_1v_1^2+l_2v_2^2C)S}{l_2(\frac{m_{12}}{m_2}-C^2)}, \end{cases}$$ を導出できるだろうか. ただし $C=\cos(\theta_1-\theta_2)$, $S=\sin(\theta_1-\theta_2)$, $m_{12}=m_1+m_2$ である.
ラグランジアンは $$L=\frac{1}{2}m_1(\dot{x}_1^2+\dot{y}_1^2)+\frac{1}{2}m_2(\dot{x}_2^2+\dot{y}_2^2)+m_1gy_1+m_2gy_2,$$ それぞれの振り子の位置は $$x_1=l_1\sin\theta_1, \quad y_1=l_1\cos\theta_1,$$ $$x_2=l_1\sin\theta_1+l_2\sin\theta_2, \quad y_2=l_1\cos\theta_1+l_2\cos\theta_2,$$ であり, 最終的にラグランジアンは $\theta_1$, $\theta_2$, $\dot{\theta}_1$, $\dot{\theta}_2$ の関数 $L(\theta_1,\theta_2,\dot{\theta}_1,\dot{\theta}_2)$ である.
§4 量子力学¶
なぜ物体は作用 $S[x(t)]$ を最小にする経路を取るのだろうか. 放たれた瞬間にゴールを知ってるかのようではないか. 実はその疑問は量子力学によって解決される.

作用 $S[x(t)]$ の典型的な値に対し $\hbar$ が非常に小さいような「古典的」な系を考えてみよう. この場合 $S[x(t)]$ がわずかに変わるだけで複素数 $\exp(iS[x(t)]/\hbar)$ は激しく振動し, 近い経路同士の効果が打ち消し合うことになる. 結局, 近い経路で作用がほとんど変化しない ($\delta S/\delta x=0$) 「古典経路」が互いに打ち消し合わず, 選択されやすいというだけのことである.
$\hbar$ が小さくない系においては, より多様な経路の効果が効いてきて「量子力学的」振る舞いを見ることができる. 実験してみよう.
時刻 $t=0$ に位置 $z=0$ から電子を 1 個発射して, 時刻 $t=2$ に位置 $z=2$ にあるスクリーンに当てることを考える. 位置 $z=1$ には 2 つスリットの空いた壁があり, 電子はスリットしか通過できない. スリット位置は $0.99\leq h\leq 1.01$ と $-1.01\leq h\leq-0.99$ である. 簡単のため時刻 $t=1$ に位置 $h$ を通過し時刻 $t=2$ にスクリーン位置 $x$ にあたる, 途中は直線の経路のみを考える. すなわち作用は $h$ と $x$ のみの関数として
$$S(h,x) = \frac{1}{2}m\left[\left(\frac{\Delta z}{\Delta t}\right)^2+\left(\frac{h}{\Delta t}\right)^2\right]\Delta t+\frac{1}{2}m\left[\left(\frac{\Delta z}{\Delta t}\right)^2+\left(\frac{x-h}{\Delta t}\right)^2\right]\Delta t,$$
で与えられる. $\Delta z=\Delta t=1$ である. スリット 1 ($0.99\leq h\leq1.01$) を通った寄与は
$$\phi_1(x)=\int_{0.99}^{1.01}\mathrm{d}h\,\exp\left(\frac{i}{\hbar}S(h,x)\right),$$
で与えられるし, スリット 2 ($-1.01\leq h\leq-0.99$) を通った寄与は
$$\phi_2(x)=\int_{-1.01}^{-0.99}\mathrm{d}h\,\exp\left(\frac{i}{\hbar}S(h,x)\right),$$
全寄与は
$$\phi(x)=\phi_1(x)+\phi_2(x),$$
となる. 簡単のため規格化定数 $\mathcal{N}$ は無視した.
slit = 0.1
width = 0.01
dz = 1
dt = 1
m = 1
1
function actionS(h,x)
return 1/2*m*((dz/dt)^2+(h/dt)^2)*dt + 1/2*m*((dz/dt)^2+((x-h)/dt)^2)*dt
end
function Phi_slit1(x,hbar)
return quadgk(h -> exp(im/hbar*actionS(h,x)), slit-width/2, slit+width/2)[1]
end
function Phi_slit2(x,hbar)
return quadgk(h -> exp(im/hbar*actionS(h,x)), -slit-width/2, -slit+width/2)[1]
end
function Phi_tot(x,hbar)
return Phi_slit1(x,hbar) + Phi_slit2(x,hbar)
end
Phi_tot (generic function with 1 method)
lnhbar = -5
plot(-0.4:0.001:0.4, x->norm(Phi_slit1(x,10.0^lnhbar))^2, title=@sprintf("hbar=1e%d",lnhbar))
plot!(-0.4:0.001:0.4, x->norm(Phi_slit2(x,10.0^lnhbar))^2)
lnhbar = -5
plot(-0.4:0.001:0.4, x->norm(Phi_tot(x,10.0^lnhbar))^2, title=@sprintf("hbar=1e%d",lnhbar))
lnhbar = -4
plot(-0.4:0.001:0.4, x->norm(Phi_slit1(x,10.0^lnhbar))^2, title=@sprintf("hbar=1e%d",lnhbar))
plot!(-0.4:0.001:0.4, x->norm(Phi_slit2(x,10.0^lnhbar))^2)
lnhbar = -4
plot(-0.4:0.001:0.4, x->norm(Phi_tot(x,10.0^lnhbar))^2, title=@sprintf("hbar=1e%d",lnhbar))
lnhbar = -3
plot(-0.4:0.001:0.4, x->norm(Phi_slit1(x,10.0^lnhbar))^2, title=@sprintf("hbar=1e%d",lnhbar))
plot!(-0.4:0.001:0.4, x->norm(Phi_slit2(x,10.0^lnhbar))^2)
lnhbar = -3
plot(-0.4:0.001:0.4, x->norm(Phi_tot(x,10.0^lnhbar))^2, title=@sprintf("hbar=1e%d",lnhbar))
lnhbar = -2
plot(-0.4:0.001:0.4, x->norm(Phi_slit1(x,10.0^lnhbar))^2, title=@sprintf("hbar=1e%d",lnhbar))
plot!(-0.4:0.001:0.4, x->norm(Phi_slit2(x,10.0^lnhbar))^2)
lnhbar = -2
plot(-0.4:0.001:0.4, x->norm(Phi_tot(x,10.0^lnhbar))^2, title=@sprintf("hbar=1e%d",lnhbar))
最終課題¶
ニュートン力学・解析力学・量子力学のいずれかで好きなシミュレーションを実装せよ.