↗️

GPU.jsで電場シミュレータを作る

2023/06/27に公開

モチベーション

研究室で以前つくられた電場シミュレータをWeb上で実装し,それを以て卒業研究にしようというモチベーションで作られた.
作っているうちに知ったが他の年度にも色々と試されていたようで陳腐な卒研となった.

制作物

https://slnq.github.io/werve-gpujs/

機能

白い範囲をクリックすると赤い円と無数の矢印が見える.赤は正を円は電荷を示し赤い円は正電荷で矢印は電場を表現している.
右下にchargeとあるスライダーを左に動かし,白い範囲をクリックすると円の大きさが違う青い円が現れ動き出す.青は負で大きさは電荷の大きさを示しており,青い円は負電荷となっている.
精密なシミュレータではないが,電荷や電場の動きは習ったそれと変わらないのではないだろうか.これが基本で,その他に8つあるスイッチは細かい設定の為にあり,下で説明する.

time : 時間を再生/停止する
norm : 電場の大きさを輝度で表す
vector : 電場のベクトルを矢印で表す
install : クリックするとchargeに合う値の電荷を置く
delete : 電荷をクリックすると消すことができる
fix : 電荷をクリックすると固定できる
move : 電荷をドラッグ・アンド・ドロップで移動させられる

ソースコード

https://github.com/slnq/werve-gpujs

基本的にsrc内の.jsファイルを読めばシミュレーションについてはわかると思う.

処理

  1. 1つの電荷に対する電場の値を599×599で計算しテンプレートに格納する.
  2. 電荷の位置を元に電場のテンプレートを動かし配列300×300に格納する.
  3. 電荷の数だけ電場を総和して配列300×300に格納していく.
  4. 電荷の座標に対応する電場配列の要素を電荷値と乗算してクーロン力を計算する.
  5. クーロン力を元に位置と速度と加速度を計算する.
  6. 表示する.

これの2.から6.を繰り返している.配列の大きさ(すなわちシミュレートの解像度)である300×300は色々と試した結果であり,最適な解像度とかでは無い.

GPU.js

GPU.jsは1.から3.及び6.で使っている.new GPU({ mode: 'cpu' });でGPUを使わない手法も取れるとドキュメントには書いてあるが機能せず,CPUとの比較が出来ていないのだから,GPUのありがたみも未知数となる.

Canvas

GPU.jsを6.で使っているのも事実だが,使われた割合としてはせいぜい半分くらい.normでの電場の輝度表示はGPU.jsを用いているが,vectorで使える電場のベクトル表示や電荷の円はJavaScriptで描いている.300×300でいくつも矢印を描くと画質的に見てられないので,300×300で出た輝度表示は600×600に補間せず拡大しベクトル表示の方は600×600で出している.

ダークモード

ちょうど流行りだったので作った.JavaScriptで輝度表示の色を反転させると計算量を食うかなと思い,GPU.jsの表示用配列の時点で反転させている.他のところで最適化に程遠いのだから,こんなの無意味だろと言われれば,それはそのとおり.

デプロイ

webpackを用いてローカルで生成したものをGitHub Pages/docs内をデプロイしている.当初はBitbucketを使っていたので,Herokuを使おうとしていたが,うまくいかなかった.最近のHerokuを見ている感じ災い転じて福となすなんて思うわけだが.(結局Herokuの使い方はわからないまま,使う機会がなくなったね.)

所感

卒業研究として作ったのは確かだが,研究といえる代物ではない.
とはいえ一応こうして形になったのは嬉しかったな.

Discussion