概要
前回(PythonコードをCythonで高速化してFortranに近づける)からの続きで、今回は可視化の話。
せっかくなので、前回の計算結果のプラズマの運動をPythonでかっこよく可視化しようと思い、Plotly.pyに行き着いた。
試行錯誤で3次元のアニメーションを作ってみたので紹介。
Plotly.pyを用いたアニメーション
まずは結果の動画から → https://youtu.be/1OFHpvSOsUM
Plotly.pyのofflineモードでは、html形式のファイルでリンクのようなアニメーションが作成できる。
また、Play&Pauseボタンを設置できたり、Pause中に図をグリグリ動かすことが可能。
(実際は動画よりもプラズマは速く動くのだが、動画撮影による処理落ち(?)によってスピードが落ちている)
パラメータ設定
リンクの動画は、前回の数値計算において物理パラメータを以下のように設定した場合の結果。
N(反復回数) | Δt | m | q | E | B |
---|---|---|---|---|---|
100,000 | 0.001 | 1 | -1 | (0, 0, 0.005) | (0, 0, 1) |
電場と磁場は、空間3次元(x, y, z)に対応。qのマイナスは、プラズマが電子(物理の定義では電子の電荷がマイナスなので)ということを意味している。パラメータの絶対量は基本的に適当だが、厳密なシミュレーションではないのでOK。 | |||||
10万の計算反復の、100ステップごとにプラズマの位置データを保存し、100ステップごとの図をつなげることでリンクのアニメーションが作成されている。 |
可視化方法
今回の動画の生成用コードを以下に示す。
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import plotly.offline as offline
import plotly.graph_objs as go
import numpy as np
if __name__ == '__main__':
load_data = np.loadtxt('gyro_motion_EparaB.dat', delimiter=',', skiprows=1)
x = load_data[:, 0]
y = load_data[:, 1]
z = load_data[:, 2]
scatter = go.Scatter3d(x=x, y=y, z=z, mode='lines', line=dict(width=2, color='blue'))
data = [scatter, scatter]
layout = dict(xaxis=dict(range=[x.min(), x.max()], autorange=False, zeroline=False),
yaxis=dict(range=[y.min(), y.max()], autorange=False, zeroline=False),
zaxis=dict(range=[z.min(), z.max()], autorange=False, zeroline=False),
title='Gyro Motion of Electron', hovermode='closest',
autosize=True,
scene=dict(
aspectratio=dict(x=0.4, y=0.4, z=1.6),
# aspectratio=dict(x=2, y=0.4, z=0.4), # ExB用
),
updatemenus=[{'type': 'buttons',
'buttons': [{'label': 'Play',
'method': 'animate',
'args':[None, dict(frame=dict(duration=0, redraw=False),
transition=dict(duration=0),
fromcurrent=True,
mode='immediate')]
},
{
'args': [[None], {'frame': {'duration': 0, 'redraw': False},
'mode': 'immediate',
'transition': {'duration': 0}}],
'label': 'Pause',
'method': 'animate'
}
]}])
frames = [dict(data=[dict(x=[x[k]],
y=[y[k]],
z=[z[k]],
mode='markers',
marker=dict(color='red', size=4)
)
]) for k in range(len(x))]
figure = dict(data=data, layout=layout, frames=frames)
offline.plot(figure, filename='EparaB.html')
基本的な利用方法は、公式サイトや他のページにも紹介されているので割愛させていただき、ここでは3次元アニメーションの作成方法の要点を(コードの逆順で)紹介する。
最終的に、offline.plot(figure, filename='EparaB.html')
の部分で動画を作成しているため、ここの引数figure
を準備する必要がある。そして、figure
はdata, layout, frames
という情報をディクショナリ形式で持つようにする。
-
frames
には、プラズマのステップごとの位置データをリスト形式で溜め込んでおく。mode='markers'
は、プラズマを点として描くという意味。 -
layout
は、図の設定情報をコードのように入れておく。軸の設定や、動画の再生・停止ボタンを設置することなどが可能。 -
data
には、プラズマの3次元の軌跡を、plotly.graph_objsのScatter3dメソッド用いて保存しておく。その際、コードのようにdata = [scatter, scatter]
と2要素にしておく必要がある(data = [scatter]
では不十分だった。軌跡として認められないため?)。プラズマの3次元の軌跡の画像を準備しておいて、そこにframes
でプラズマを描いていくというイメージだと思われる。
まとめ
簡単にだが、Plotly.pyを用いて3次元の動画を描けるようになった。まだまだPlotly初心者なので、さらにかっこいい動画を作れるようになりたい。コメントや質問等頂ければ幸いです。
補足 ~プラズマ物理~
上記のプラズマの運動は、磁場に沿った方向にかかる電場によって、電子が(電場と逆方向に)加速されつつ、円運動(ジャイロ運動)をするという基本的な物理過程を表している(高校の物理を思い出してください)。
では、電場が磁場と垂直にかかるような場合はどうなるのであろうか。
例えば、電場を以下のように、y成分のみ持つようにした場合について。
N(反復回数) | Δt | m | q | E | B |
---|---|---|---|---|---|
100,000 | 0.001 | 1 | -1 | (0, 0.1, 0) | (0, 0, 1) |
答えはこちら → https://youtu.be/GNTKQ3iMcZg
この運動は、電場と磁場の外積の方向に、プラズマがジャイロ運動しながら動いていくので、プラズマ物理学分野で__ExB drift__ (イークロスビードリフト)と呼ばれる。