2008-07-18[n年前へ]
■エクセルでシミュレーション Vol.1 [静電界準備 編]
「表計算プログラムでシミュレーションをする」というのは、物理などにそれほど詳しくない人が、複雑な数式で記述された世界を感覚的を大雑把に・感覚的に理解するのに、とても向いています。もちろん、そこには、かなり単純であることなどの前提条件がいくつもあります。けれど、自分のコンピュータで、マウスを動かしキーボードを少し叩くだけで、物理シミュレーションができたりすると何だか少し嬉しくなりますし、その計算過程を通して、「自然なこの世界」を「自然に」納得できる、というのは(私たちのような勉強世界からの REST OF US にとっては)とても素晴らしいと思います。
ところで、現在では”表計算プログラム=マイクロソフトのエクセル(Microsoft Excel)”だと考える人も多いことでしょう。だから、上に書いたことを言い換えれば、「エクセルでシミュレーションをする」のは、とても楽しい勉強になるということになります。
自分自身でエクセルでシミュレーションをすることもたまにあります。また、「エクセルで物理現象のシミュレーションをする」という趣旨の講習会にも、何回も関わってきました。ふと、そういった場で得たことを一回整理してみようと思いました。そこで、一番初めの今日は、「静電界を記述するポワソン方程式をエクセルで計算するための前準備(事前確認)」をしてみました。
まず、静電場を記述するポワソン方程式をテーラ級数展開することで離散化し、差分方程式に変えてみます。2次元世界を離散化するということは、エクセルの表がそうであるように「世界(画面)をセルで分割する」ということです。
上で(x,y座標空間での)差分方程式にしたものを、さらにエクセル(表計算ソフトウェア)で解くときのやり方を図解したものが下の図です。「ある点の電位(φ)は上下左右の電位の平均にその点の(係数がかかった)空間電荷を加えたもの」になっているわけです。
また、2種類の境界条件(電位を指定するディリクレ条件/電界を指定するノイマン条件)をどのようにエクセル上で処理するか、というのが下の部分になります。
こういったセルの値が「(そのセル自身を含む)セル間の関係式」で表わされるような計算式を解くためには、エクセルの設定で「反復計算を行う」という設定を有効にしておく必要があります。エクセルのバージョンによってその設定メニュー場所は違いますが、たとえば、下の画面はExcel 2003の設定ダイアログの例です。
以上で、「静電界を記述するポワソン方程式をエクセルで計算するための前準備(事前確認)」が終わりましたから、次は実際に「身近な静電界」をエクセルでシミュレーション計算してみたいと思います。
2008-07-19[n年前へ]
■エクセルでシミュレーション Vol.2 [静電界計算の動画 編]
エクセルでシミュレーション Vol.1 [静電界準備 編]で、(ポワソン方程式で表わされる)静電場の計算をエクセルでする準備作業ができたので、実際にエクセルで静電界計算をしてみました。どのような状態を計算してみたかというと、「夏の空に帯電した雲が生じた時の、地面から空へ向かう空間の断面の電場」の状態です。地面をグラウンド=0Vとして、空に電荷を帯びた雲が浮かんでいる状態を計算してみました。エクセルを使って、その計算シミュレーションをゼロから作り上げ、結果を描き終わるまでの8分弱の動画が下のものになります。また、mpeg形式の動画ファイル(65MB)もここに置いておきます。
夏の雷雲は負の電荷を帯びていることが多い、といいます。上のシミュレーション条件では、(動画を見ればわかるように、式後半に正電荷を入れましたから)雲の部分に正電荷を帯びさせましたが、そこは正負をひっくり返せば良いだけです。夏の日、暑い午後、都会や田舎の空に雷雲が見えてきたら、そのときの電場シミュレーションを(突然の落雷による停電に気をつけながら)PCのエクセル上でしてみるのも、気分転換になるかもしれません。
2008-07-20[n年前へ]
■エクセルでシミュレーション Vol.3 [夏の午後の雷雲の下 編]
エクセルでシミュレーション Vol.2 [静電界計算の動画 編]で、「地面と空に浮かぶ雷雲」を含む世界の静電場計算を行うエクセルシートを作ってみました(あくまで2次元ですが)。そこで、前回とは少しだけ違う”いかにも夏らしい”2つの例を計算してみました。
まず最初の計算は、地面の上に人が立っている状態です。空を見上げると、頭の上には雷雲が広がっていて、いかにも不安を感じている状態です。
計算結果を見ればわかるように、人体部分に電界が集中していて、すぐにもカミナリに打たれてしまいそうなことがわかります。
これは怖すぎる……というわけで、人の少し横に避雷針を立ててみたのが、次の例になります。高さのスケールが少し変に見えますが、そこら辺は適当に無視しておいて下さい。とにかく、人の少し横に避雷針を立ててみたわけです。
すると、今度は避雷針の先には強い電界が集中していますが、人がいる部分ではほとんど電位変化がないことがわかります。ということは、カミナリに打たれる心配もなく(といっても近くに落ちるカミナリはやはり怖いですけれど)安心していられる……ということがわかるわけです。
そういえば、もう夏ですね。日差しを強く感じる暑い午後に空を見上げると、いつも白い積乱雲が見えます。暑い夏を楽しみつつも、夏バテにはお気をつけください。
2009-12-07[n年前へ]
■エクセルの計算ワークシートをRuby計算スクリプトに変換してみよう
下記で使ったエクセルファイルは、自己参照部分がなく、つまり反復計算が必要ないものを使ってしまいました。反復収束計算が必要なエクセルファイルを「続 エクセルの計算ワークシートをRubyでC言語に変換してみよう」 でサーバ内に置きましたので、下記記事を読んだ後には、上記記事(さらにその後に続く記事など)を引き続きご覧ください。
目的に対して達成方法があまりに過剰、あるいは、あまりに的外れで荒唐無稽なものというのは、それはそれで何だか面白いような気がします。
今日は、そんなものを、ふと、けれど無性に作ってみたくなりました。
先日、Microsoft Excelのような「表計算ソフト」スプレッドシートを使った「静電界計算や非定常熱伝導シミュレーション計算」をみっちりしてきました。離散化された物理式を表計算ソフトウェアを用いて計算を行うというのは、「セル」というメッシュと空間が感覚的に近く感じられることから、とても自然にシミュレーション計算を行う空間分割と計算領域との対応を感じることができるのが、とても便利で良いと思っています。
もちろん、セル間の計算を「反復計算」を行うことで、複雑なことを気にせず、計算が自然に終わってしまう、というのも実に「自然」で「お手軽」で良い、と思っています。
とはいえ、私はエクセルは苦手です。毎年何回か、エクセルでのシミュレーション計算を(悩んでいる)人に教えるという作業をするのですが、それでもエクセルを使うのは苦手です。そこで、エクセルで作った離散化シミュレーション用.xlsシートをRuby Script(プログラム)に自動的に変換する、Rubyスクリプトを作ってみることにしました。そう、「エクセルで物理シミュレーションを学んだ人が、そのエクセルシートをそのまま多言語に移植することができる」スクリプトを作ってみよう、と考えてみたのです。
作ったコードxls2rb.rbは次のようになります(近日中にサーバに置いて置きます)。これは、「反復計算を使った」エクセルファイルを読み込み、それをRubyスクリプトに変換するスクリプトです。「表計算ソフト」スプレッドシートを使いった「静電界計算や非定常熱伝導シミュレーション計算」は、四則演算と周囲の空間が持つ値の計算だけで行うことができます。だから、そういう「条件」下では、そんなスクリプトを作るのも比較的簡単です。初期化や反復計算をそれぞれ「関数」化しているとはいえ、変数はすべてグローバル変数ですし、そこら辺の「エクセル感」も再現してみたスクリプトです。
require 'win32ole' def getAbsolutePath(filename) fso=WIN32OLE.new('Scripting.FileSystemObject') fso.GetAbsolutePathName(filename) end def getAlphabet(n) val=n.to_f/25.0 mod=n%25 result='' result+=('a'..'z').to_a[(n-val)/25] if val>1 result+=('a'..'z').to_a[mod] end def defFunc(state,book) src='' book.Worksheets.each do |sheet| y=1 sheet.UsedRange.Rows.each do |row| x=0 record=[] row.Columns.each do |cell| if state==:init &&cell.Value!='' record<<' '+'$'+getAlphabet(x)+y.to_s+ '='+cell.Value.to_s if cell.Value.to_s!='' end if state==:calc &&cell.Formula!='' t=cell.Formula.sub(/[=$]/,'') t=t.downcase.gsub(/([a-zA-Z]+\d+)/,'$\1') record<<' '+'$'+getAlphabet(x)+y.to_s+'='+t end x+=1 end src+=record.join("\n")+"\n" if record.join('').gsub("\n",'')!='' y+=1 end end return src end filename=getAbsolutePath(ARGV[0]) excel=WIN32OLE.new('Excel.Application') book=excel.Workbooks.Open(filename) initsrc=defFunc(:init,book) calcsrc=defFunc(:calc,book) book.close excel.quit GC.start puts <<INIT # autocreated ruby script from excel file # jun hirabayashi jun@irax.net http://www.hirax.net def init #{initsrc}end def calc #{calcsrc}end 10.times do calc end INIT
ちなみに、このスクリプトを
ruby xls2rb.rb ex.xlsという具合にして(引数は変換したいXLSファイルです)、実行すると、次のようなスクリプトができあがります。ちなみに、ここで使ったex.xlsファイルは、ラプラス方程式を3X3のセルに離散化し解く、実に単純なエクセルシートです。(この辺りのファイル一式を週末にでもサーバ上に置いておきます)
# autocreated ruby script from excel file # jun hirabayashi jun@irax.net http://www.hirax.net def init $a1=1.0 $b1=2.0 $c1=3.0 $a2=1.0 $b2=2.0 $c2=5.0 $a3=1.0 $b3=2.0 $c3=3.0 end def calc $a1=1 $b1=2 $c1=3 $a2=1 $b2=2 $c2=$b2+$c1 $a3=1 $b3=2 $c3=3 end 10.times do calc endつまり、今日私が作ったスクリプトの動作は、エクセルが最初に行う初期化ルーチンを"init"関数として定義(作成)し、次に行う反復計算を"calc"関数として定義(作成)し、それを(適当に決めた)10回繰り返すスクリプトを作り出す、という具合です。ポイントは初期化時には、cell.Valueを用いることで初期数値を設定し、逐次計算時にはcell.Formulaを使うことで数式を使う、という「使い分け」になります。反復計算自体は、ガウスザイデル法によって行われます。
あとは適当に、知りたい値を出力する(たとえば、"puts $c2"といった)出力処理文でも書き足せば、はい、シミュレーション・rubyプログラムのできあがり、というわけです。
離散化された物理計算をするために作成したエクセル・シートを、Rubyスクリプトに自動で変換し、好きに加工できるプログラム…って便利なような、そもそもそんな用途ってある訳ないような…というのが正直で的確な感想だと思います。つまり、それはかなり無意味なツールです。
他の言語に置き換えて、高速化指向の変換プログラムを書いてみるのも(一回くらいはやってみようと思いますが、今ひとつ「魅力」に欠けるように思います。
今日作った、「離散化された物理現象を計算するために作成したエクセル・シートを、Rubyスクリプトに自動で変換するプログラム」なんていうものを、(何だか馬鹿馬鹿しいけれど)意外に少し面白い笑える、そう思える人が一人でもいたら、幸いに思います。