どうも、月見(@Suzuka14144156)です。
今回は、Pythonで霧をシミュレーションする方法を解説します。
この記事のゴール
以下のGIFを得られます。
風が吹くと、四隅に霧は集まりやすいことが、分かります。
どのくらいの風が吹くと霧が浮遊しやすいかなど、探索することができるようになります。
環境の構築
今回は、Anacondaを用います。
以下の記事を参考にしてください。
Python Anacondaとは?|インストール〜Jupyter Notebookの立ち上げ
今回使うライブラリは、Anacondaをインストールすれば、自動でインストールされます。
Pythonで霧をシミュレーションする方法
Pythonで霧をシミュレーションするためのコード。
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
# Simulation parameters
num_particles = 1000 # Number of fog particles
particle_size = 0.01 # Size of each particle
dt = 0.01 # Time step
g = np.array([0, -9.81]) # Acceleration due to gravity
v_mean = np.array([0.0, 0.0]) # Mean wind velocity
v_std = np.array([10.0, 10.0]) # Standard deviation of wind velocity
# Set up initial particle positions and velocities
x = np.random.uniform(low=-1.0, high=1.0, size=(num_particles, 2))
v = np.random.normal(loc=v_mean, scale=v_std, size=(num_particles, 2))
# Set up plot
fig, ax = plt.subplots()
ax.set_xlim(-1.0, 1.0)
ax.set_ylim(-1.0, 1.0)
# Define animation function
def update(frame):
# Update particle positions
x_new = x + v*dt
# Apply gravity
v_new = v + g*dt
# Apply random wind velocity
v_new += np.random.normal(loc=0.0, scale=particle_size, size=(num_particles, 2))
# Reflect off walls
x_new[(x_new[:, 0] < -1.0) | (x_new[:, 0] > 1.0), 0] = x[(x_new[:, 0] < -1.0) | (x_new[:, 0] > 1.0), 0]
v_new[(x_new[:, 0] < -1.0) | (x_new[:, 0] > 1.0), 0] = -v[(x_new[:, 0] < -1.0) | (x_new[:, 0] > 1.0), 0]
x_new[(x_new[:, 1] < -1.0) | (x_new[:, 1] > 1.0), 1] = x[(x_new[:, 1] < -1.0) | (x_new[:, 1] > 1.0), 1]
v_new[(x_new[:, 1] < -1.0) | (x_new[:, 1] > 1.0), 1] = -v[(x_new[:, 1] < -1.0) | (x_new[:, 1] > 1.0), 1]
# Update positions and velocities
x[:] = x_new[:]
v[:] = v_new[:]
# Update scatter plot
ax.clear()
ax.scatter(x[:, 0], x[:, 1], s=particle_size*1000)
ax.set_xlim(-1.0, 1.0)
ax.set_ylim(-1.0, 1.0)
# Create animation
ani = animation.FuncAnimation(fig, update, frames=100, interval=50)
# Save animation to file
ani.save('fog_simulation.gif', writer='imagemagick')
解説
- このコードは、Pythonで空気中に浮遊する霧をシミュレーションし、霧の大きさを任意で可変できること、そしてそれに応じて重力と気流の影響を計算できる、2DのGIFを出力としたシミュレーションです。
このシミュレーションでは、NumPyを使用して、空気中の水分子のランダムな配置を生成しています。この配置に対して、重力と風による影響を考慮して、水分子を移動させ、新しい配置を生成し、これを繰り返すことで霧のシミュレーションを行います。
そして、Matplotlibのanimationモジュールを使用して、これらの配置を連続的に表示し、GIFアニメーションとして保存することができます。
次に、particle_sizeが何に寄与するか解説します。
np.random.normal
の中のscaleの値を決定するのにparticle_sizeが用いられます。
この値が大きいほど、分散が大きくなります。
np.random.normal
は、正規分布に従う乱数を生成する関数です。この関数のパラメータの一つであるscale
は、生成する乱数の分散を指定するものです。具体的には、平均値を0とした正規分布における標準偏差を表します。
例えば、scale=1.0
と指定すると、平均値を0とした正規分布における標準偏差が1.0となります。つまり、生成される乱数は平均値の周りに集中し、その分布の幅が狭くなります。一方、scale=2.0
と指定すると、分散が4.0となり、乱数の分布がより広がります。
したがって、np.random.normal
で生成される乱数のばらつきを調整するために、scale
パラメータを調整することができます。
Pythonで霧をシミュレーションした結果
風の平均速さ0m/s,標準偏差1m/sの場合
風のばらつきが、1m/s程度では、重力によって-Y方向に霧が落ちていくことが分かります。
風の平均速さ0m/s,標準偏差5m/sの場合
風の平均速さ0m/s,標準偏差10m/sの場合
霧が空気中で浮遊する様子を見ていきます。
霧が浮遊するには、上昇気流が必要です。
なぜなら、上昇気流(y方向)の気流があると-y方向の重力を打ち消しあい、長時間浮遊していられるためです。
y方向の風の平均速1m/s,標準偏差1m/sの場合
y方向の風の平均2m/s,標準偏差1m/sの場合
風速が、2mを超えてくると最初浮き上がり、徐々に重力に負ける様子が分かります。
Pythonで流体を勉強する方法
本
私は、以下の本で勉強しましたので、参考にしてみてください。
Udemy
Udemyはオンライン講座です。
一度購入すれば、ずっと閲覧できるのでオススメです。
Pythonの基礎を学びたい方は、以下の口座がオススメです。
まとめ
Pythonで霧をシミュレーションする方法について解説しました。
Pythonを使えば、比較的簡単に実装することができます。
コメント