読者です 読者をやめる 読者になる 読者になる

倭算数理研究所

科学・数学・学習関連の記事を、「倭マン日記」とは別に書いていくのだ!

2.9 視覚化 : 問題 2.6 リサージュ図形 lissajous

計算物理学入門 シミュレーション

またまた関数をプロットするサンプル。 今回はちょっとパラメータを変えるといろいろな図形になるリサージュ図形です。

問題

{ x,\,y } 座標が

  { \displaystyle
\begin{align*}
    \begin{cases}
        x = A\sin(\omega_x t + \phi_x) \\
        y = B\cos(\omega_y t + \phi_y)
    \end{cases}
\end{align*}
}

で与えられる曲線が出発点に戻って繰り返し描かれるとき、そのような曲線をリサージュ (Lissajous) 図形という。 角振動数 { \omega_x,\,\omega_y } がどのようなときにリサージュ図形になるだろうか。 初め、

  { \displaystyle
\begin{align*}
    \begin{cases}
        &A = B = 1 \\
        &\omega_x = 2,\,\omega_y = 3 \\
        &\phi_x = \frac{\pi}{6} ,\, \phi_y= \frac{\pi}{4}
    \end{cases}
\end{align*}
}

とし { y }{ x } に対してプロットするプログラムを書け*1

与えられたパラメータで曲線の方程式を書き下すと

  { \displaystyle
\begin{align*}
    \begin{cases}
        x = \sin(2t + \frac{\pi}{6}) \\
        y = \cos(3 t + \frac{\pi}{4})
    \end{cases}
\end{align*}
}

となります。

リサージュ図形となるための条件

与えられた { x,\,y } はとも周期関数で、周期はそれぞれ { \frac{2\pi}{\omega_x},\,\frac{2\pi}{\omega_y} } です。 この曲線がリサージュ図形になるためには、ある自然数 { n_x,\,n_y } に対して

  { \displaystyle
\begin{align*}
    \frac{2\pi}{\omega_x}n_x = \frac{2\pi}{\omega_y}n_y
\end{align*}
}

が成り立つことです。 これを少し変形すると

  { \displaystyle
\begin{align*}
    \frac{\omega_x}{\omega_y} = \frac{n_x}{n_y}
\end{align*}
}

となり、{ x,\,y } の角振動数が有理数比であればいいことが分かります。

シミュレーション・スクリプト

問題では、パラメータをあれこれ変えて考察せよ、みたいなことが書いてますが、ここでは与えられたパラメータでのプロットのみを行います:

@GrabResolver('https://github.com/waman/groops-core/tree/master/repo')
@Grab('org.waman.groops:groops-core:0.2-beta')

import org.waman.groops.builder.SimulationBuilder
import org.waman.groops.simulation.system.*
import static java.lang.Math.*

def a = 1d, omega_x = 2d, phy_x = PI/6d
def b = 1d, omega_y = 3d, phy_y = PI/4d

new SimulationBuilder().simulation{

    function(xy:{ double t -> [a*sin(omega_x*t + phy_x), b*cos(omega_y*t + phy_y)] },
             tmin:0d, tmax:2d*PI, dt:0.01d)

    //function(x:{ double t -> a*sin(omega_x*t + phy_x) },
    //         y:{ double t -> b*cos(omega_y*t + phy_y) },
    //         tmin:0d, tmax:2d*PI, dt:0.01d)

    png(fileName:'problem2_6.png', overwrite:true){
        chart(title:'Problem 2.6', domainLabel:'x', rangeLabel:'y'){
            dot(label:"Simulation", x:'x', y:'y')
        }
    }
}.simulate()
  • problem2_6.groovy 直
  • function ノードの xy 属性に、引数が1つ(サンプルでは t )のクロージャを渡すと、媒介変数表示のグラフをプロットできます。 返り値は Double の List (成分は2つ)にします。
  • コメントアウトしてますが、function ノードの x, y 属性にそれぞれ媒介変数 (t) から値を計算するクロージャを渡しても同様のプロットができます。

シミュレーションを実行すると、以下のようなチャートが生成されます:

追記

計算物理学入門』の本文ではプロットを時間経過と共に描けという問題だったので、そういうサンプルも載せておきます。 Groops のバージョンは 0.2-beta 以降が必要です:

@GrabResolver('https://github.com/waman/groops-core/tree/master/repo')
@Grab('org.waman.groops:groops-core:0.2-beta')

import org.waman.groops.builder.SimulationBuilder
import org.waman.groops.simulation.system.*
import static java.lang.Math.*

def a = 1d, omega_x = 2d, phy_x = PI/6d
def b = 1d, omega_y = 3d, phy_y = PI/4d

new SimulationBuilder().simulation{

    function(xy:{ double t -> [a*sin(omega_x*t + phy_x), b*cos(omega_y*t + phy_y)] },
                tmin:0d, dt:0.1d)

    continueUntilKeyPress()
    swing{
        chart(title:'Problem 2.6'){
            point(label:"Simulation", x:'x', y:'y')
        }
    }
}.simulate()
  • problem2_6_swing.groovy 直
  • 標準入力でキーを入力([Enter] を押す必要在あり)すると、シミュレーションが終了します。 ただし、GUI は終了されないので別途「×」ボタンで閉じてください。
  • swing ノードで Swing の GUI を起動してデータ出力を GUI に出力できます。 ただし、現在のところ、Swing GUI に出力できるのはチャートだけです。

計算物理学入門

計算物理学入門

  • 作者: ハーベイゴールド,ジャントボチニク,Harvey Gould,Jan Tobochnik,鈴木増雄,石川正勝,溜渕継博,宮島佐介
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/12
  • メディア: 単行本
  • 購入: 1人 クリック: 28回
  • この商品を含むブログ (45件) を見る
プログラミングGROOVY

プログラミングGROOVY

*1:少し問題を省略しています。