Skip to content

Instantly share code, notes, and snippets.

@genkuroki
Created March 19, 2018 19:51
Show Gist options
  • Save genkuroki/659798ab6f7a78d0d65ef21f34d116d8 to your computer and use it in GitHub Desktop.
Save genkuroki/659798ab6f7a78d0d65ef21f34d116d8 to your computer and use it in GitHub Desktop.
FFTを用いた熱方程式やKdV方程式などを数値解法の in-place 版 jshtml no output
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"metadata": {
"toc": true
},
"cell_type": "markdown",
"source": "<h1>Table of Contents<span class=\"tocSkip\"></span></h1>\n<div class=\"toc\"><ul class=\"toc-item\"><li><span><a href=\"#FFTを用いた熱方程式やKdV方程式などを数値解法の-in-place-版\" data-toc-modified-id=\"FFTを用いた熱方程式やKdV方程式などを数値解法の-in-place-版-1\"><span class=\"toc-item-num\">1&nbsp;&nbsp;</span>FFTを用いた熱方程式やKdV方程式などを数値解法の in-place 版</a></span><ul class=\"toc-item\"><li><span><a href=\"#諸定義\" data-toc-modified-id=\"諸定義-1.1\"><span class=\"toc-item-num\">1.1&nbsp;&nbsp;</span>諸定義</a></span><ul class=\"toc-item\"><li><span><a href=\"#パッケージの読み込み\" data-toc-modified-id=\"パッケージの読み込み-1.1.1\"><span class=\"toc-item-num\">1.1.1&nbsp;&nbsp;</span>パッケージの読み込み</a></span></li><li><span><a href=\"#数式を使った解説\" data-toc-modified-id=\"数式を使った解説-1.1.2\"><span class=\"toc-item-num\">1.1.2&nbsp;&nbsp;</span>数式を使った解説</a></span></li><li><span><a href=\"#FFT_Data-タイプの定義\" data-toc-modified-id=\"FFT_Data-タイプの定義-1.1.3\"><span class=\"toc-item-num\">1.1.3&nbsp;&nbsp;</span>FFT_Data タイプの定義</a></span></li><li><span><a href=\"#プロット用の函数\" data-toc-modified-id=\"プロット用の函数-1.1.4\"><span class=\"toc-item-num\">1.1.4&nbsp;&nbsp;</span>プロット用の函数</a></span></li></ul></li><li><span><a href=\"#熱方程式で以上の定義のテスト\" data-toc-modified-id=\"熱方程式で以上の定義のテスト-1.2\"><span class=\"toc-item-num\">1.2&nbsp;&nbsp;</span>熱方程式で以上の定義のテスト</a></span></li><li><span><a href=\"#KdV方程式の数値解法の最適化\" data-toc-modified-id=\"KdV方程式の数値解法の最適化-1.3\"><span class=\"toc-item-num\">1.3&nbsp;&nbsp;</span>KdV方程式の数値解法の最適化</a></span><ul class=\"toc-item\"><li><span><a href=\"#プロット用函数\" data-toc-modified-id=\"プロット用函数-1.3.1\"><span class=\"toc-item-num\">1.3.1&nbsp;&nbsp;</span>プロット用函数</a></span></li><li><span><a href=\"#FFTを-FFT-*-v,-FFT-\\-v-の形式で利用した場合\" data-toc-modified-id=\"FFTを-FFT-*-v,-FFT-\\-v-の形式で利用した場合-1.3.2\"><span class=\"toc-item-num\">1.3.2&nbsp;&nbsp;</span>FFTを <code>FFT * v</code>, <code>FFT \\ v</code> の形式で利用した場合</a></span></li><li><span><a href=\"#FFTを-in-place-で利用した場合\" data-toc-modified-id=\"FFTを-in-place-で利用した場合-1.3.3\"><span class=\"toc-item-num\">1.3.3&nbsp;&nbsp;</span>FFTを in-place で利用した場合</a></span></li><li><span><a href=\"#KdV方程式:-初期条件-sin\" data-toc-modified-id=\"KdV方程式:-初期条件-sin-1.3.4\"><span class=\"toc-item-num\">1.3.4&nbsp;&nbsp;</span>KdV方程式: 初期条件 sin</a></span></li><li><span><a href=\"#ベンチマークテスト\" data-toc-modified-id=\"ベンチマークテスト-1.3.5\"><span class=\"toc-item-num\">1.3.5&nbsp;&nbsp;</span>ベンチマークテスト</a></span></li><li><span><a href=\"#KdV方程式:-2-soliton解\" data-toc-modified-id=\"KdV方程式:-2-soliton解-1.3.6\"><span class=\"toc-item-num\">1.3.6&nbsp;&nbsp;</span>KdV方程式: 2-soliton解</a></span></li></ul></li><li><span><a href=\"#1次元のSchroedinger方程式\" data-toc-modified-id=\"1次元のSchroedinger方程式-1.4\"><span class=\"toc-item-num\">1.4&nbsp;&nbsp;</span>1次元のSchroedinger方程式</a></span><ul class=\"toc-item\"><li><span><a href=\"#Gaussian-packet\" data-toc-modified-id=\"Gaussian-packet-1.4.1\"><span class=\"toc-item-num\">1.4.1&nbsp;&nbsp;</span>Gaussian packet</a></span></li><li><span><a href=\"#自由粒子\" data-toc-modified-id=\"自由粒子-1.4.2\"><span class=\"toc-item-num\">1.4.2&nbsp;&nbsp;</span>自由粒子</a></span></li><li><span><a href=\"#低い壁\" data-toc-modified-id=\"低い壁-1.4.3\"><span class=\"toc-item-num\">1.4.3&nbsp;&nbsp;</span>低い壁</a></span></li><li><span><a href=\"#高い壁\" data-toc-modified-id=\"高い壁-1.4.4\"><span class=\"toc-item-num\">1.4.4&nbsp;&nbsp;</span>高い壁</a></span></li><li><span><a href=\"#調和振動子\" data-toc-modified-id=\"調和振動子-1.4.5\"><span class=\"toc-item-num\">1.4.5&nbsp;&nbsp;</span>調和振動子</a></span></li><li><span><a href=\"#$V(x)-=--100-\\exp(-x^2/100)$\" data-toc-modified-id=\"$V(x)-=--100-\\exp(-x^2/100)$-1.4.6\"><span class=\"toc-item-num\">1.4.6&nbsp;&nbsp;</span>$V(x) = -100 \\exp(-x^2/100)$</a></span></li></ul></li><li><span><a href=\"#Smith方程式\" data-toc-modified-id=\"Smith方程式-1.5\"><span class=\"toc-item-num\">1.5&nbsp;&nbsp;</span>Smith方程式</a></span><ul class=\"toc-item\"><li><span><a href=\"#Smith方程式:-初期条件-sin\" data-toc-modified-id=\"Smith方程式:-初期条件-sin-1.5.1\"><span class=\"toc-item-num\">1.5.1&nbsp;&nbsp;</span>Smith方程式: 初期条件 sin</a></span></li><li><span><a href=\"#Smith方程式:-初期条件-KdV-2-soliton\" data-toc-modified-id=\"Smith方程式:-初期条件-KdV-2-soliton-1.5.2\"><span class=\"toc-item-num\">1.5.2&nbsp;&nbsp;</span>Smith方程式: 初期条件 KdV 2-soliton</a></span></li></ul></li></ul></li></ul></div>"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "# FFTを用いた熱方程式やKdV方程式などを数値解法の in-place 版\n\n黒木玄\n\n2018-01-23\n\n* Copyrigtht 2018 Gen Kuroki\n* License: MIT https://opensource.org/licenses/MIT\n\nこのノートブックは\n\n* http://nbviewer.jupyter.org/gist/genkuroki/14b05a2cfa172fc5ea351641d4bdda11\n* http://nbviewer.jupyter.org/gist/genkuroki/26928d4a1ae2e912a3850ed1b31e2941\n\nの続き. このノートブックでは in-place でFFTを使うことによってメモリ効率を最適化することを行いたい. 例としてKdV方程式を扱う."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "@show Sys.CPU_CORES\nFFTW.set_num_threads(Sys.CPU_CORES)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## 諸定義"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### パッケージの読み込み"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "using PyPlot\n\ndefault_figsize = (6.4, 4.8) # このデフォルトサイズは大き過ぎるので\nrc(\"figure\", figsize=(3,2.4)) # このように小さくしておく.\n\nusing PyCall\nconst animation = pyimport(\"matplotlib.animation\")\n\nfunction displayfile(mimetype, file)\n open(file) do f\n base64text = base64encode(f)\n display(\"text/html\", \"\"\"<img src=\"data:$mimetype;base64,$base64text\">\"\"\")\n end\nend",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### 数式を使った解説\n\n周期 $L=2\\pi K$ を持つ函数を\n\n$$\nf(x) = \n\\sum_{k=-N/2+1}^{N/2} (-1)^{k-1} a_k\\;e^{2\\pi i(k-1)x/L} =\n\\sum_{k=-N/2+1}^{N/2} (-1)^{k-1} a_k\\;e^{i(k-1)x/K}\n$$\n\nの形の有限Fourier級数でよく近似できていると仮定する. これの導函数は\n\n$$\nf'(x) = \\sum_{k=-N/2+1}^{N/2} (-1)^{k-1} \\frac{i(k-1)}{K}a_k\\;e^{i(k-1)x/K}\n$$\n\nになる. すなわち, $f(x)$ を微分する操作は, $-N/2< k \\leqq N/2$ のとき $a_k$ に $i(k-1)/K$ をかける操作に対応している. $-N/2< k \\leqq N/2$ のとき $a_k$ に $i(k-1)/K$ をかける操作は(丸め誤差)を除いて, 有限Fourier級数の正確な微分を与えることに注意せよ. この計算方法は小さな $h$ について $(f(x+h/2)-f(x-h/2))/h$ のような方法で微分を求める方法よりも誤差が小さい.\n\nさらに $x$ を\n\n$$\n\\Delta x = \\frac{L}{N} = \\frac{2\\pi K}{N}, \\quad\nx_j = (j-1)\\Delta x -\\frac{L}{2} = L\\left(\\frac{j-1}{N} - \\frac{1}{2}\\right)\n$$\n\nで離散化したとする. このとき,\n\n$$\nf(x_j) = \\sum_{k=-N/2-1}^{N/2} a_k\\;e^{i(k-1)(j-1)/N}.\n$$\n\nこれは $a_{k+N}=a_k$ という仮定のもとで\n\n$$\nf(x_j) = \\sum_{k=1}^N a_k\\; e^{i(k-1)(j-1)/N}\n$$\n\nと書き直される. これはJulia言語の離散Fourier変換のスタイルに一致している. この表示のもとで, $f(x)$ を微分する操作は, $1\\leqq k\\leqq N/2$ のとき $i(k-1)/N$ を $a_k$ にかけ, $N/2+1\\leqq k\\leqq N$ のとき $i(k-1-N)/N$ を $a_k$ にかける操作に対応している. `FFT_Data` における `D` を成分ごとにかける操作はまさにこの操作になっている."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "?ifft",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### FFT_Data タイプの定義"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# right-open interval [a,b)\n#\nroi(a, b, N) = collect(linspace(a, b-(b-a)/N, N))\n\n# x axis (Assume the priodic boundary condition with period L)\n#\nx_axis(L, N) = roi(-L/2, L/2, N)\n\n# k axis (k = the wave number)\n#\nfunction k_axis(N)\n @assert iseven(N)\n Ndiv2 = div(N,2)\n vcat(roi(0,Ndiv2,Ndiv2), roi(-Ndiv2,0,Ndiv2))\nend\n\n# FFT Data\n#\nmutable struct FFT_Data{T<:Real, S}\n K::T\n L::T\n N::Int64\n x::Array{T,1}\n k::Array{T,1}\n D::Array{Complex{T},1}\n D2::Array{Complex{T},1}\n D3::Array{Complex{T},1}\n D4::Array{Complex{T},1}\n FFT::S\nend\n\n# FFT \\ (D.^m .* (FFT * u)) = (d/dx)^m u\n#\nfunction FFT_Data(K, N)\n L = 2π*K\n x = x_axis(L, N)\n k = k_axis(N)\n D = im .* k ./ K\n FFT = plan_fft(Array{Complex{Float64},1}(N))\n FFT_Data(Float64(K), L, N, x, k, D, D.^2, D.^3, D.^4, FFT)\nend",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### プロット用の函数"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# nearly zero\n#\nfunction imagisnealyzero(z)\n maximum(abs, imag(z))/(maximum(abs, real(z)) + 1e-15) < 1e-3\nend\n\n# plot complex number array u on x\n#\nfunction plot_u(x, u)\n plot(x, real(u), label=\"Re\", lw=0.8)\n imagisnealyzero(u) || plot(x, imag(u), label=\"Im\", lw=0.8, ls=\"--\")\n grid(ls=\":\")\n xticks(fontsize=8)\n yticks(fontsize=8)\nend",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## 熱方程式で以上の定義のテスト"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# Application - the solution of the heat equation u_t = u_{xx}\n#\n# u(t) = exp(t (∂/∂x)^2) u(0)\n#\nsol_of_heat_eq(o::FFT_Data, u0, t) = o.FFT \\ (exp.(t .* o.D2) .* (o.FFT * u0))\n\nN = 2^8\nK = 3\no = FFT_Data(K, N);\n\nf0(x) = exp(-4(x+4)^2) + exp(-2(x-3)^2)\nu0 = f0.(o.x)\nt = roi(0,2,10)\n@time u = [sol_of_heat_eq(o, u0, t) for t in t]\n\nfigure(figsize=(10, 3))\nfor j in 1:10\n subplot(2,5,j)\n plot_u(o.x, u[j])\n ylim(-0.05,1.05)\nend\ntight_layout()",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## KdV方程式の数値解法の最適化\n\n$$\nu_t = -u_{xxx}-3(u^2)_x\n$$"
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### プロット用函数"
},
{
"metadata": {
"scrolled": false,
"trusted": true
},
"cell_type": "code",
"source": "function plot_u(o, u, nrows, j, ymin, ymax)\n subplot(nrows, 5, j+1)\n plot_u(o.x, u)\n ylim(ymin, ymax)\n xticks(fontsize=8)\n yticks(fontsize=8)\n title(\"j = $j\", fontsize=8)\nend\n\nfunction plot_KdV(o::FFT_Data, u, t; thin=10, ymin=-7.0, ymax=15.0)\n nplots = div(length(t), thin)\n nrows = div(nplots+4, 5)\n\n figure(figsize=(10, 1.75nrows))\n \n j = 0\n plot_u(o, @view(u[:,j+1]), nrows, j, ymin, ymax)\n\n for j in 1:nplots-1\n plot_u(o, @view(u[:,thin*j+1]), nrows, j, ymin, ymax)\n end\n \n tight_layout()\nend\n\nfunction anim_KdV(figname, o::FFT_Data, u, t; thin=2, interval=100, ymin=-7.0, ymax=15.0)\n function plotframe(j)\n clf()\n plot(o.x, real(u[:, (j-1)*thin + 1]), lw=1.0)\n grid(ls=\":\")\n ylim(ymin, ymax)\n xticks(fontsize=8)\n yticks(fontsize=8)\n title(\"$(figname): j = $(j-1)\", fontsize=10)\n plot()\n end\n fig = figure(figsize=(4, 3))\n n = (length(t)-1)÷thin + 1\n frames = [1:n;]\n ani=animation[:FuncAnimation](fig, plotframe, frames=frames, interval=interval)\n anim_html = ani[:to_jshtml]()\n clf()\n display(\"text/html\", anim_html)\nend",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### FFTを `FFT * v`, `FFT \\ v` の形式で利用した場合"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# FFT*v and FFT\\v version\n\nfunction update_KdV(o::FFT_Data, u, Δt, niters)\n v = o.FFT * u\n for iter in 1:niters\n v .= exp.(-Δt .* o.D3) .* v\n v .-= 3.*Δt .* o.D .*(o.FFT * (o.FFT \\ v).^2)\n end\n o.FFT \\ v\nend\n\nfunction solve_KdV(o::FFT_Data{T}, f0, tmax) where T\n Δt = 1/o.N^2\n skip = floor(Int, 0.005/Δt)\n t = 0:skip*Δt:tmax\n M = length(t)\n u = Array{Complex{T},2}(o.N, M)\n u[:,1] = Complex.(f0.(o.x))\n for j in 2:M\n u[:,j] = update_KdV(o, @view(u[:,j-1]), Δt, skip)\n end\n return real(u), t\nend\n\nN = 2^8\nK = 20/(2π)\no = FFT_Data(K, N);\n\nf0(x) = -5*sin(π*x/10)\nΔt = 1/N^2\nskip = 10*floor(Int, 0.005/Δt)\n\ntmax = 1.0\n@time u, t = solve_KdV(o, f0, tmax)\n\nsleep(0.1)\nplot_KdV(o, u, t)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### FFTを in-place で利用した場合"
},
{
"metadata": {
"scrolled": false,
"trusted": true
},
"cell_type": "code",
"source": "function update_KdV!(o::FFT_Data, u1, u0, Δt, niters)\n v = similar(u0)\n v_tmp = similar(u0)\n u_tmp = similar(u0)\n \n A_mul_B!(v, o.FFT, u0)\n for iter in 1:niters\n # v .= exp.(-Δt .* o.D3) .* v\n v .= exp.(-Δt .* o.D3) .* v\n \n # v .-= 3.*Δt .* o.D .*(o.FFT * (o.FFT \\ v).^2)\n A_ldiv_B!(u_tmp, o.FFT, v)\n u_tmp .*= u_tmp\n A_mul_B!(v_tmp, o.FFT, u_tmp)\n v .-= 3.*Δt .* o.D .* v_tmp\n end\n A_ldiv_B!(u1, o.FFT, v)\nend\n\nfunction solve_KdV_inplace(o::FFT_Data{T}, f0, tmax) where T\n Δt = 1/o.N^2\n skip = floor(Int, 0.005/Δt)\n t = 0:skip*Δt:tmax\n M = length(t)\n u = Array{Complex{T},2}(o.N, M)\n u[:,1] = Complex.(f0.(o.x))\n for j in 2:M\n update_KdV!(o, @view(u[:,j]), @view(u[:,j-1]), Δt, skip)\n end\n return real(u), t\nend\n\nN = 2^8\nK = 20/(2π)\no = FFT_Data(K, N);\n\nf0(x) = -5*sin(π*x/10)\nΔt = 1/N^2\nskip = 10*floor(Int, 0.005/Δt)\n\ntmax = 1.0\n@time u, t = solve_KdV_inplace(o, f0, tmax)\n\nsleep(0.1)\nplot_KdV(o, u, t)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### KdV方程式: 初期条件 sin"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "figname = \"KdV sin\"\n@time anim_KdV(figname, o, u, t)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### ベンチマークテスト"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "using BenchmarkTools\n\nN = 2^8\nK = 20/(2π)\no = FFT_Data(K, N)\n\nf0(x) = -5*sin(π*x/10)\nΔt = 1/N^2\nskip = 10*floor(Int, 0.005/Δt)\n\ntmax = 1.4",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "@benchmark u, t = solve_KdV(o, f0, tmax)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "@benchmark u, t = solve_KdV_inplace(o, f0, tmax)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "以上のように in-place 版は非 in-place 版よりも計算時間を十数パーセント短く, in-place版の消費メモリは非 in-pace 版の50分の1である."
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### KdV方程式: 2-soliton解"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "N = 2^8\nK = 20/(2π)\no = FFT_Data(K, N);\n\nKdVsoliton(c, a, x) = c/2*(sech(sqrt(c)/2*(x-a)))^2\nf0(x) = KdVsoliton(16.0, -8.0, x) + KdVsoliton(4.0, -2.0, x)\nΔt = 1/N^2\nskip = 10*floor(Int, 0.005/Δt)\n\ntmax = 1.0\n@time u, t = solve_KdV_inplace(o, f0, tmax)\n\nsleep(0.1)\nplot_KdV(o, u, t, ymin=-0.5, ymax=10.0)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "figname = \"KdV 2-soliton\"\n@time anim_KdV(figname, o, u, t, ymin=-0.5, ymax=10.0)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## 1次元のSchroedinger方程式"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "# V はポテンシャル函数\n#\nmutable struct Schroedinger_Data{T, S, R}\n o::FFT_Data{T,S}\n V::R\n v::Array{T,1}\nend\n\n# FFT_Data o とポテンシャル函数 V から Schroedinger_Data を作成する函数\n#\nSchroedinger_Data(o, V) = Schroedinger_Data(o, V, V.(o.x))\n\nfunction update_Schroedinger!(s::Schroedinger_Data, u1, u0, Δt, skip)\n o = s.o\n U_tmp = similar(u0)\n u1 .= u0\n\n for iter in 1:skip\n # exp.(-im .* Δt .* s.v) .* (o.FFT\\(exp.(0.5im .* Δt .* o.D2).*(o.FFT * u)))\n A_mul_B!(U_tmp, o.FFT, u1)\n U_tmp .*= exp.(0.5im .* Δt .* o.D2)\n A_ldiv_B!(u1, o.FFT, U_tmp)\n u1 .*= exp.(-im .* Δt .* s.v)\n end\nend\n\nfunction solve_Schroedinger(s::Schroedinger_Data{T,S,R}, u0, tmax; Δt=2π/1000, skip=10) where {T,S,R}\n o = s.o\n t = 0:skip*Δt:tmax+10eps()\n M = length(t)\n u = Array{Complex{T},2}(o.N, M)\n u[:,1] = u0\n for j in 2:M\n update_Schroedinger!(s, @view(u[:,j]), @view(u[:,j-1]), Δt, skip)\n end\n return u, t\nend\n\nfunction plot_complexvalued(x, u, ymin, ymax)\n plot(o.x, real(u), lw=0.8)\n plot(o.x, imag(u), lw=0.8, ls=\"--\")\n ylim(ymin, ymax)\n grid(ls=\":\")\n xticks(fontsize=8)\n yticks(fontsize=8)\nend\n\nfunction plot_Schroedinger(s::Schroedinger_Data, u, t; thin=10, ymin=-1.1, ymax=1.1)\n nplots = (length(t)-1)÷thin + 1\n o = s.o\n nrows = div(nplots+3, 5)\n\n figure(figsize=(4, 1.75))\n subplot(121)\n plot_complexvalued(o.x, u[:,1], ymin, ymax)\n title(\"initial state\", fontsize=9)\n subplot(122)\n plot_u(o.x, s.v)\n title(\"potential\", fontsize=9)\n tight_layout()\n\n \n figure(figsize=(10, 1.75nrows))\n for j in 1:nplots-1\n subplot(nrows, 5, j)\n plot_complexvalued(o.x, u[:,(j-1)*thin+2], ymin, ymax)\n title(\"j = $j\", fontsize=9)\n end\n tight_layout()\nend\n\nfunction anim_Schroedinger(figname, s::Schroedinger_Data, u, t; thin=2, interval=100, ymin=-1.1, ymax=1.1, figtitle=figname)\n o = s.o\n function plotframe(j)\n clf()\n plot(o.x, real(u[:, (j-1)*thin+1]), lw=1.0)\n plot(o.x, imag(u[:, (j-1)*thin+1]), lw=1.0, ls=\"--\")\n grid(ls=\":\")\n ylim(ymin, ymax)\n xticks(fontsize=8)\n yticks(fontsize=8)\n title(\"$(figtitle): j = $(j-1)\", fontsize=10)\n plot()\n end\n fig = figure(figsize=(4, 3))\n n = (length(t)-1)÷thin + 1\n frames = [1:n;]\n ani=animation[:FuncAnimation](fig, plotframe, frames=frames, interval=interval)\n anim_html = ani[:to_jshtml]()\n clf()\n display(\"text/html\", anim_html)\nend",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Gaussian packet"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "mutable struct GaussianPacket{T<:Real}\n x₀::T\n p₀::T\n σ::T\n Δx::T\nend\n\nfunction GaussianPacket(x₀, p₀, σ, o::FFT_Data)\n Δx = o.x[2] - o.x[1]\n GaussianPacket(x₀, p₀, σ, Δx)\nend\n\nfunction (f::GaussianPacket)(x)\n sqrt(f.Δx)/(π^(1/4)*sqrt(f.σ)) *\n exp(im*f.p₀*(x-f.x₀/2) - (x-f.x₀)^2/(2f.σ^2))\nend\n\nN = 2^10\nK = 10\no = FFT_Data(K, N);\n\ng0 = GaussianPacket(-20.0, 5.0, 2.0, o)\nplot_u(o.x, g0.(o.x));",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### 自由粒子"
},
{
"metadata": {
"scrolled": false,
"trusted": true
},
"cell_type": "code",
"source": "# 自由粒子\n\nN = 2^10\nK = 10\no = FFT_Data(K, N);\n@show typeof(o)\n\nV(x) = 0.0\ns = Schroedinger_Data(o, V)\n\ng0 = GaussianPacket(-20.0, 5.0, 2.0, o)\nu0 = g0.(o.x)\n\nT = 2.0\ntmax = 2π*T\n@time u, t = solve_Schroedinger(s, u0, tmax)\n\nsleep(0.1)\nplot_Schroedinger(s, u, t, ymin=-0.2, ymax=0.2)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "figname = \"free particle\"\n@time anim_Schroedinger(figname, s, u, t, ymin=-0.2, ymax=0.2)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### 低い壁"
},
{
"metadata": {
"scrolled": false,
"trusted": true
},
"cell_type": "code",
"source": "# 壁=(高さ10、幅10)、粒子=運動量5)\n\nN = 2^10\nK = 10\no = FFT_Data(K, N);\n@show typeof(o)\n\nV(x) = ifelse(0 ≤ x ≤ 10, 10.0, 0.0)\ns = Schroedinger_Data(o, V)\n\ng0 = GaussianPacket(-20.0, 5.0, 1.0, o)\nu0 = g0.(o.x)\n\nT = 1.5\ntmax = 2π*T\n@time u, t = solve_Schroedinger(s, u0, tmax)\n\nsleep(0.1)\nplot_Schroedinger(s, u, t, ymin=-0.2, ymax=0.2)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "figname = \"low barrier\"\n@time anim_Schroedinger(figname, s, u, t, ymin=-0.2, ymax=0.2)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### 高い壁"
},
{
"metadata": {
"scrolled": false,
"trusted": true
},
"cell_type": "code",
"source": "# 壁=(高さ20、幅10)、粒子=運動量5)\n\nN = 2^10\nK = 10\no = FFT_Data(K, N);\n@show typeof(o)\n\nV(x) = ifelse(0 ≤ x ≤ 10, 20.0, 0.0)\ns = Schroedinger_Data(o, V)\n\ng0 = GaussianPacket(-20.0, 5.0, 1.0, o)\nu0 = g0.(o.x)\n\nT = 1.5\ntmax = 2π*T\n@time u, t = solve_Schroedinger(s, u0, tmax)\n\nsleep(0.1)\nplot_Schroedinger(s, u, t, ymin=-0.2, ymax=0.2)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "figname = \"high barrier\"\n@time anim_Schroedinger(figname, s, u, t, ymin=-0.2, ymax=0.2)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### 調和振動子"
},
{
"metadata": {
"scrolled": false,
"trusted": true
},
"cell_type": "code",
"source": "# 調和振動子 (周期 2π)\n\nN = 2^10\nK = 10\no = FFT_Data(K, N);\n@show typeof(o)\n\nV(x) = x^2/2\ns = Schroedinger_Data(o, V)\n\ng0 = GaussianPacket(-20.0, 0.0, 0.5, o)\nu0 = g0.(o.x)\n\nT = 2.0\ntmax = 2π*T\n@time u, t = solve_Schroedinger(s, u0, tmax)\n\nsleep(0.1)\nplot_Schroedinger(s, u, t, ymin=-0.3, ymax=0.3)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "figname = \"harmonic oscillator\"\n@time anim_Schroedinger(figname, s, u, t, ymin=-0.3, ymax=0.3, thin=1)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### $V(x) = -100 \\exp(-x^2/100)$"
},
{
"metadata": {
"scrolled": false,
"trusted": true
},
"cell_type": "code",
"source": "# V(x) = -20 exp(-x^2/25)\n\nN = 2^10\nK = 10\no = FFT_Data(K, N);\n@show typeof(o)\n\nV(x) = -100 * exp(-x^2/100)\ns = Schroedinger_Data(o, V)\n\ng0 = GaussianPacket(-15.0, 0.0, 1.0, o)\nu0 = g0.(o.x)\n\nT = 4.0\ntmax = 2π*T\n@time u, t = solve_Schroedinger(s, u0, tmax, skip=20)\n\nsleep(0.1)\nplot_Schroedinger(s, u, t, ymin=-0.2, ymax=0.2)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "figname = \"V(x)=-100exp(-x2/100)\"\nfigtitle = \"\\$V(x)=-100\\\\exp(-100x^2)\\$\"\n@time anim_Schroedinger(figname, s, u, t, ymin=-0.2, ymax=0.2, figtitle=figtitle)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "## Smith方程式\n\nKdV equation:\n$$\nu_t = -\\partial_x^3 u - 3\\partial_x(u^2).\n$$\n\nSmith's equation:\n$$\nu_t = 2a^{-2}\\left( \\sqrt{1-a^2\\partial_x^2} - 1 \\right)\\partial_x u - 3\\partial_x(u^2).\n$$\n\n以下では $a^2=0.15$ と仮定する."
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "function plot_Smith(o::FFT_Data, u, t; thin=10, ymin=-7.0, ymax=25.0)\n nplots = div(length(t), thin)\n nrows = div(nplots+4, 5)\n\n figure(figsize=(10, 1.75nrows))\n \n j = 0\n plot_u(o, @view(u[:,j+1]), nrows, j, ymin, ymax)\n\n for j in 1:nplots-1\n plot_u(o, @view(u[:,thin*j+1]), nrows, j, ymin, ymax)\n end\n \n tight_layout()\nend\n\nfunction anim_Smith(figname, o::FFT_Data, u, t; thin=2, interval=100, ymin=-7.0, ymax=25.0)\n function plotframe(j)\n clf()\n plot(o.x, real(u[:, (j-1)*thin + 1]), lw=1.0)\n grid(ls=\":\")\n ylim(ymin, ymax)\n xticks(fontsize=8)\n yticks(fontsize=8)\n title(\"$(figname): j = $(j-1)\", fontsize=10)\n plot()\n end\n fig = figure(figsize=(4, 3))\n n = (length(t)-1)÷thin + 1\n frames = [1:n;]\n ani=animation[:FuncAnimation](fig, plotframe, frames=frames, interval=interval)\n anim_html = ani[:to_jshtml]()\n clf()\n display(\"text/html\", anim_html)\nend",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "function update_Smith!(o::FFT_Data, u1, u0, Δt, niters, a²)\n v = similar(u0)\n v_tmp = similar(u0)\n u_tmp = similar(u0)\n \n A_mul_B!(v, o.FFT, u0)\n for iter in 1:niters\n v .= exp.(2 ./ a² .* Δt .* (sqrt.(1 .- a² .* o.D2) .- 1).*o.D) .* v\n \n # v .-= 3.*Δt .* o.D .*(o.FFT * (o.FFT \\ v).^2)\n A_ldiv_B!(u_tmp, o.FFT, v)\n u_tmp .*= u_tmp\n A_mul_B!(v_tmp, o.FFT, u_tmp)\n v .-= 3.*Δt .* o.D .* v_tmp\n end\n A_ldiv_B!(u1, o.FFT, v)\nend\n\nfunction solve_Smith_inplace(o::FFT_Data{T}, f0, tmax; a²=0.15) where T\n Δt = 1/o.N^2\n skip = floor(Int, 0.005/Δt)\n t = 0:skip*Δt:tmax\n M = length(t)\n u = Array{Complex{T},2}(o.N, M)\n u[:,1] = Complex.(f0.(o.x))\n for j in 2:M\n update_Smith!(o, @view(u[:,j]), @view(u[:,j-1]), Δt, skip, a²)\n end\n return real(u), t\nend",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Smith方程式: 初期条件 sin"
},
{
"metadata": {
"scrolled": false,
"trusted": true
},
"cell_type": "code",
"source": "N = 2^9\nK = 20/(2π)\no = FFT_Data(K, N);\n\nf0(x) = -5*sin(π*x/10)\nΔt = 1/N^2\nskip = 10*floor(Int, 0.005/Δt)\n\ntmax = 1.0\n@time u, t = solve_Smith_inplace(o, f0, tmax)\n\nsleep(0.1)\nplot_Smith(o, u, t, thin=10)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "figname = \"Smith sin\"\n@time anim_Smith(figname, o, u, t)",
"execution_count": null,
"outputs": []
},
{
"metadata": {},
"cell_type": "markdown",
"source": "### Smith方程式: 初期条件 KdV 2-soliton"
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "N = 2^9\nK = 20/(2π)\no = FFT_Data(K, N);\n\nKdVsoliton(c, a, x) = c/2*(sech(sqrt(c)/2*(x-a)))^2\nf0(x) = KdVsoliton(16.0, -8.0, x) + KdVsoliton(4.0, -2.0, x)\nΔt = 1/N^2\nskip = 10*floor(Int, 0.005/Δt)\n\ntmax = 1.0\n@time u, t = solve_Smith_inplace(o, f0, tmax)\n\nsleep(0.1)\nplot_Smith(o, u, t, ymin=-0.5, ymax=12.0)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "figname = \"Smith 2-soliton\"\n@time anim_Smith(figname, o, u, t, ymin=-0.5, ymax=12.0)",
"execution_count": null,
"outputs": []
},
{
"metadata": {
"trusted": true
},
"cell_type": "code",
"source": "",
"execution_count": null,
"outputs": []
}
],
"metadata": {
"kernelspec": {
"name": "julia-0.6",
"display_name": "Julia 0.6.2",
"language": "julia"
},
"toc": {
"nav_menu": {},
"toc_window_display": false,
"toc_section_display": true,
"sideBar": true,
"title_cell": "Table of Contents",
"number_sections": true,
"title_sidebar": "Contents",
"skip_h1_title": false,
"toc_position": {
"width": "256px",
"top": "150px",
"left": "10px",
"height": "calc(100% - 180px)"
},
"toc_cell": true
},
"_draft": {
"nbviewer_url": "https://gist.github.com/d7328478c1188f876052fce859e91b40"
},
"language_info": {
"mimetype": "application/julia",
"file_extension": ".jl",
"version": "0.6.2",
"name": "julia"
},
"gist": {
"id": "d7328478c1188f876052fce859e91b40",
"data": {
"description": "FFTを用いた熱方程式やKdV方程式などを数値解法の in-place 版 jshtml no output",
"public": true
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment