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

万有引力

 今回は、実際に数値を入れて運動を見ようの第2弾!質量\(M\)の物体が作る万有引力場にある物体の運動である。万有引力は一般解があるのだが、どうも難しい形をしている。それなら万有引力の運動方程式を直接解いてもらおう。(コンピューターに) \[\frac{d^2\boldsymbol{x}}{dt^2}=-G\frac{M}{|\boldsymbol{x}|^2}\hat{\boldsymbol{x}}\] 原点に質量\(M\)の物体を置いたとき万有引力を受ける物体の運動方程式はベクトルを使って書くとこんなにすっきりした形をしているが、 \[\frac{d^2x}{dt^2}=-GM\frac{x}{\sqrt{x^2+y^2}^3}\] \[\frac{d^2y}{dt^2}=-GM\frac{y}{\sqrt{x^2+y^2}^3}\] と2階微分、連立方程式で一般解を求めるのは非常に難しい。\(\dot x,\dot y\)をそれぞれ\(x\)方向の速さ、\(y\)方向の速さとすると、今回も\(dt\)を使って \[x_0,\ y_0,\ \dot x_0,\ \dot y_0,\ G,\ M=const.\] \[\dot x_i=\dot x_{i-1}-GM\frac{x_{i-1}}{\sqrt{(x_{i-1})^2+(y_{i-1})^2}^3}dt\] \[\dot y_i=\dot y_{i-1}-GM\frac{y_{i-1}}{\sqrt{(x_{i-1})^2+(y_{i-1})^2}^3}dt\] \[x_i=x_{i-1}+\dot x_{i-1}dt\] \[y_i=y_{i-1}+\dot y_{i-1}dt\] を計算してもらおう。ただ定数の桁数がでかすぎる。コンピューターが計算してくれるか心配なので桁数をまずは減らす。具体的な数値はとりあえず太陽と地球の距離を参考にする。 万有引力定数は \[G=6.67\times10^{-11}\ \mathrm{m^3\ s^{-2}\ kg^{-1}}\] 太陽の質量は \[M=1.98\times10^{30}\ \mathrm{kg}=1.98\ (\times10^{30}\ \mathrm{kg})\] \(10^{30}\)も単位のほうに含んだ。1.98とわかりやすい数字になった。地球と太陽の平均距離は、 \[a=1.5\times10^{11}\ \mathrm{m}=1\ \mathrm{au}\] 太陽から地球までの平均距離は\(1\ \mathrm{au}\)(astronomical unit)とあらわす。しかし1周で1年かかる運動を見るには遅い。1秒で1ヶ月(\(2\ 592\ 000\ \mathrm{s}\))経過することにする。万有引力定数は \[G=6.67\times10^{-11}\ \mathrm{m^3\ s^{-2}\ kg^{-1}}\] \[G\simeq0.13\ \mathrm{au^3\ mth^{-2}(\times 10^{30}\ kg)^{-1}}\] よし!これでいいことにしよう。
初期位置\([x_0],[y_0]=\mathrm{au}\)
初速\([\dot x_0],[\dot y_0]=\mathrm{au\ mth^{-1}}\)
太陽の質量\([M]=\times 10^{30}\ \mathrm{kg}\)
 あまり極端な運動をさせると運動が上手くいかない。太陽は特異点になっているので、あまり近づかなように!太陽の質量を大きくすればちゃんと物体の加速度もあがっているし、速度を少しずつ上げていけばだんだん楕円になり、放物線、双曲線(片側)になる。面白いですな。もし自分でも作ってみたいという方はお粗末ですが、以下を参考にしてください。bodyタグにコピペで動くはず。
    <div>
        初期位置
    </div>
    <input id="input1">
    <input id="input2">
    <div>
        初速
    </div>
    <input id="input3">
    <input id="input4">
    <div style="margin-top: 20px;">
        太陽の質量\([M]=\times 10^{30}\ \mathrm{kg}\)
    </div>
    <input id="input5">
    <div>
        <button id="button1">
            スタート
        </button>
    </div>
    <canvas id="canvas1"></canvas>
    <script>
        //inputを取得てきとーに名前を定義してあげる。
        let xinter = document.getElementById("input1");
        let yinter = document.getElementById("input2");
        let vxinte = document.getElementById("input3");
        let vyinte = document.getElementById("input4");
        let massun = document.getElementById("input5");
        // inputに初期値を代入
        xinter.value = 1;
        yinter.value = 0;
        vxinte.value = 0;
        vyinte.value = 0.5;
        massun.value = 2;
        //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 G = 0.13;
        let dt = 0.01;
        //inputから拾った文字列を1を掛けて数にする。
        let msun = 1*massun.value;
        let vx = 1*vxinte.value;
        let vy = 1*vyinte.value;
        let x = 1*xinter.value;
        let y = 1*yinter.value;
        //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.arc(xo+200,yo-200,4,0,Math.PI*2);
            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();
            //次の描写時に位置を決めるための計算
            vx = vx - G*msun*x/(Math.sqrt(x**2+y**2)**3)*dt;
            vy = vy - G*msun*y/(Math.sqrt(x**2+y**2)**3)*dt;
            x = x + vx*dt;
            y = y + vy*dt;
        },10);
        
        // ボタンを押すとinputの値を再取得する仕組み
        but1.addEventListener("click",()=>{
            xinter = document.getElementById("input1");
            yinter = document.getElementById("input2");
            vxinte = document.getElementById("input3");
            vyinte = document.getElementById("input4");
            massun = document.getElementById("input5");
            msun = 1*massun.value;
            vx = 1*vxinte.value;
            vy = 1*vyinte.value;
            x = 1*xinter.value;
            y = 1*yinter.value;
        });
        
        </script>