#流線
直交座標系$\boldsymbol{x} = (x, y)$,速度$\boldsymbol{u} = (u, v)$で表される流れ場の,ある時刻$t$における流線(streamline)は数学的に常微分方程式
$$
\frac{\text{d} x}{\text{d} u(x,y,t)} = \frac{\text{d} y}{\text{d} v(x,y,t)}
$$
で定義されます.この記事で紹介する流線はこの常微分方程式を解いて描くわけではなく,単純に速度ベクトルをつないだものを描画しているものと思ってください.
#matplotlib組み込みのstreamplotで描く
例として2次元定常Taylor-Green渦:
$$
\begin{aligned}
u &= \sin x \cos y \\
v &= -\cos x \sin y
\end{aligned}
$$
を使います.
matplotlib組み込みのstreamplot
で簡単に流線を描くことができます.
import matplotlib.pyplot as plt
import numpy as np
from numpy import sin, cos, pi, sqrt
n = 1000
x = np.linspace(0, 2*pi, n)
y = np.linspace(0, 2*pi, n)
X, Y = np.meshgrid(x, y)
# Taylor-Green Vortices
u = sin(X)*cos(Y)
v = - cos(X)*sin(Y)
speed = sqrt(u**2 + v**2)
# Plot
plt.figure(1)
plt.streamplot(X, Y, u, v, density=3, color='k', arrowstyle='-', linewidth=0.6)
plt.contourf(X, Y, speed, 100, cmap='viridis')
plt.show()
#Line Integral Convolution (LIC) で描く
こっちが本題.上のmatplotlib組み込みのstreamplot
でも十分綺麗なのですが,もっと美しく(芸術的に)描きたいときはLine Integral Convolution (LIC,線積分畳み込み) という手法を用いると流線をとても美しく描画できます.wikipedia(英語)に簡単な説明があります.アルゴリズムはCabral and Leedom, 1993参照.LICを用いて描いた流線の例として,Phillips et al., 2015やVan Der Kindere et al., 2019などがあります.
SciPy Cookbookにサンプルコードがあるのでありがたく使わせてもらいます.setup.py
をビルドすると使えるようになります.
リンク先のlic_demo.py
の前半を書き換えます.背景に流速を表示させたいので最後の行でLICと流速をかけています.
Vector = np.stack([u, v], axis=2)
Vector = np.array(Vector, dtype=np.float32)
texture = np.random.rand(n, n).astype(np.float32)
plt.bone()
frame = 0
dpi = 1000
video = False
if video:
kernellen = 31
for t in np.linspace(0,1,16*5):
kernel = np.sin(np.arange(kernellen)*np.pi/kernellen)*(1+np.sin(2*np.pi*5*(np.arange(kernellen)/float(kernellen)+t)))
kernel = kernel.astype(np.float32)
image = lic_internal.line_integral_convolution(Vector, texture, kernel)
frame += 1
else:
kernellen = 31
kernel = np.sin(np.arange(kernellen)*np.pi/kernellen)
kernel = kernel.astype(np.float32)
image = lic_internal.line_integral_convolution(Vector, texture, kernel)
speed_LIC = image[1:-1, 1:-1]*speed[1:-1, 1:-1]
とても綺麗ですね.
#ちなみにMathematicaだともっと簡単
Mathematicaには組み込みでLineIntegralConvolutionPlot
がある!
LineIntegralConvolutionPlot[{{Sin[x] Cos[y], -Sin[y] Cos[x]}, {"noise", 1000, 1000}}, {x, 0, 2 Pi}, {y, 0, 2 Pi},
ColorFunction -> "BlueGreenYellow", RasterSize -> 300]
めちゃくちゃ間単にできた...