楽しい科学(理論)チャンネル

振り子

 今回は、実際に数値を入れて運動を見ようの第3弾! 振り子である。実はこちらも一般解はそう簡単に求められない。これも数値解析の出番だ。糸のたわみのないものを仮定する。糸というよりは棒である。
長さ\(l\)の糸からの張力を\(T_{string}\)とすると、物体の運動方程式は \[m\frac{d^2x}{dt^2}=-T_{string}\sin\theta\] \[m\frac{d^2y}{dt^2}=T_{string}\cos\theta-mg\] \(x\)成分に\(\cos\theta\)、\(y\)成分に\(\sin\theta\)を掛けて2つの式を足すと、\(T_{string}\)を消去できる。 \[\cos\theta\ m\frac{d^2x}{dt^2}+\sin\theta\ m\frac{d^2y}{dt^2}=-mg\sin\theta\tag{1}\] 直交座標では難しそうなので\((x,y)=(l\sin\theta,-l\cos\theta)\)としよう。 \[\begin{pmatrix}\dot x\\\dot y\end{pmatrix}=\begin{pmatrix}l\cos\theta\ \dot\theta\\l\sin\theta\ \dot\theta\end{pmatrix}\] \[\begin{pmatrix}\ddot x\\\ddot y\end{pmatrix}=\begin{pmatrix}-l\sin\theta\ \dot\theta^2+l\cos\theta\ \ddot\theta\\l\cos\theta\ \dot\theta^2+l\sin\theta\ \ddot\theta\end{pmatrix}\] これを(1)式に代入すると、\(\dot\theta\)の項がなくなる。 \[ml\frac{d^2\theta}{dt^2}=-mg\sin\theta\] \[\frac{d^2\theta}{dt^2}=-\frac{g}{l}\sin\theta\] シンプルな形になったのでこれで、数値解析をやってみる。 \[\theta_0,\ \dot\theta_0,\ l,\ g=const.\] \[\dot\theta_i=\dot\theta_{i-1}-\frac{g}{l}\sin\theta_{i-1} dt\] \[\theta_i=\theta_{i-1}+\dot\theta_{i-1}dt\] \[(x_i,y_i)=(l\sin\theta_i,-l\cos\theta_i)\] このように計算していただこう。
初期角度\([\theta_0]=\mathrm{rad}\)  初期角速度\([\dot\theta_0]=\mathrm{rad\ s^{-1}}\)
糸の長さ\([l]=\mathrm{m}\)    重力加速度\([g]=\mathrm{m\ s^{-2}}\)
\(\sin\theta\)を原点でテイラー展開すると、\[\sin\theta=\theta-\frac{\theta^3}{3!}+\frac{\theta^5}{5!}-\cdots\] となる。\(\theta\)が十分に小さいとき\(\theta^3/3!\)以降の項を無視して、 \[\frac{d^2\theta}{dt^2}\simeq\frac{g}{l}\theta\] と単振動の微分方程式になる。単振動とみれば各振動数\(\omega=2\pi/T=g/l\)なので、糸を長くすると、周期運動が遅くなり、重力が大きい所では周期運動が早くなることがわかるだろう。\(\theta=3\)とかにして運動を見てみてほしい。単振動で近似できないのがみてわかる。初期角速度を大きくしていて1回転する振り子を見るのも面白い。今回使ったコードを最後に載せておく。
<div>
    糸の長さ 
    重力加速度
</div>
<input id="input3">
<input id="input4">
<div>
    <button id="button1">
        スタート
    </button>
</div>
<canvas id="canvas1">
<script>
    //inputを取得てきとーに名前を定義してあげる。
    let theint = document.getElementById("input1");
    let vthint = document.getElementById("input2");
    let lstrin = document.getElementById("input3");
    let gravac = document.getElementById("input4");
    // inputに初期値を代入
    theint.value = 0.1;
    vthint.value = 0;
    lstrin.value = 2;
    gravac.value = 9.8;
    //buttonを取得、名前を付ける。
    let but1 = document.getElementById("button1");
    //canvasAPIのお約束事
    let width = 600;
    let height = 600;
    let canvas1 = document.getElementById("canvas1");
    let c1 = canvas1.getContext("2d");
    canvas1.width = width;
    canvas1.height = height;
    let cn=c1;

    //定数
    let xo = 50;
    let yo = 550;
    let dt = 0.01;
    //inputから拾った文字列を1を掛けて数にする。
    let th = 1*theint.value;
    let vth = 1*vthint.value;
    let ls = 1*lstrin.value;
    let g = 1*gravac.value;
    let x = ls*Math.sin(th);
    let y = -ls*Math.cos(th);
    //setInervalでcanvasを10ms間隔で更新  
    let setI = setInterval(()=>{
        //10ms前の描写をクリア
        cn.clearRect(0,0,width,height);
        //グラフの軸、目盛り
        cn.beginPath();
        cn.moveTo(xo,yo);
        cn.lineTo(xo+400,yo);
        cn.stroke();
        cn.beginPath();
        cn.moveTo(xo,yo);
        cn.lineTo(xo,yo-400);
        cn.stroke();
        for (i=0;i<11;i++) {
            cn.beginPath();
            cn.moveTo(xo,yo-i*40);
            cn.lineTo(xo-10,yo-i*40);
            cn.stroke();
            cn.beginPath();
            cn.moveTo(xo+i*40,yo);
            cn.lineTo(xo+i*40,yo+10);
            cn.stroke();
            cn.font = "20px 'Alial'";
            cn.fillText(i-5,xo+40*i,yo+20);
            cn.fillText(i-5,xo-40,yo-40*i);
        };
        //物体arc(円)を使う。
        cn.beginPath();
        cn.arc(xo+200+40*x,yo-200+40*y,4,0,Math.PI*2);
        cn.fill();
        //糸
        cn.beginPath();
        cn.moveTo(xo+200,yo-200);
        cn.lineTo(xo+200+40*x,yo-200+40*y);
        cn.stroke();
        //点線
        cn.save();
        cn.setLineDash([3, 5]);
        cn.beginPath();
        cn.moveTo(xo+200,yo);
        cn.lineTo(xo+200,yo-400);
        cn.stroke();
        cn.beginPath();
        cn.moveTo(xo,yo-200);
        cn.lineTo(xo+400,yo-200);
        cn.stroke();
        cn.restore();
        // 次の描写時に位置を決めるための計算
        vth = vth - g/ls*Math.sin(th)*dt;
        th = th + vth*dt;
        x = ls*Math.sin(th);
        y = ls*Math.cos(th);
    },10);

    // ボタンを押すとinputの値を再取得する仕組み
    but1.addEventListener("click",()=>{
        theint = document.getElementById("input1");
        vthint = document.getElementById("input2");
        lstrin = document.getElementById("input3");
        gravac = document.getElementById("input4");
        th = 1*theint.value;
        vth = 1*vthint.value;
        ls = 1*lstrin.value;
        g = 1*gravac.value;
        x = ls*Math.sin(th);
        y = -ls*Math.cos(th);
    });
<\script>