楽しい科学(理論)チャンネル
単振動
今回は実際に数字を入れて運動を見てみようの会である。記念すべき第1回は簡単な例で単振動をやる。数値解析は基本オイラー法(区分求積法)でやります!(簡単なので、)
区分求積法は、面積\(y=f(x)\)を底辺\(dx\)高さ\(f(x_i)/dx\)の長方形の足し合わせでだいたい表せるというものである。左から数えて\(i\)番目の長方形の面積は\(dy_i=\frac{f(x_{i-1})}{dx}dx\)なので、
\[y\simeq \sum_i\frac{f(x_i)}{dx}dx\]
となる。ここで扱う微小量\(dx\)は限りなく小さい値ではなく、ある程度小さい値であれば大丈夫。ただし、小さいほうが正確な\(y\)が求められる。単振動の方程式は
\[\frac{d^2x}{dt^2}=-\omega^2x\]
人間であれば方程式を解いて\(x=x_0\cos\omega t+\frac{v_0}{\omega}\sin\omega t\)とするところだが
微小時間\(dt\)というものを用意して、javascriptに
\[\omega,\ v_0,\ x_0=const.\]
\[v_i=v_{i-1}-w^2x_{i-1}dt\]
\[x_i=x_{i-1}+v_idt\]
の手順で計算してもらおう。定数は変えられるようにしたので、変えて遊んでみてほしい。全角だとうまくいかないので定数は半角でお願いします。
初期位置\([x_0]=\mathrm{m}\)
初期速度\([v_0]=\mathrm{m\ s^{-1}}\)
角振動数\([\omega]=\mathrm{rad\ s^{-1}}\)
オイラー法では、長方形を並べても隙間の部分ができてしまう。オイラー法がどれだけ現実に近い動きを再現できているか、単振動の解は\(x=a\cos\omega t\)の形で書けるので、これと上で計算した\(x_i\)を並べて見比べてみよう。
結果がこちら、\(\omega=8\ \mathrm{rad\ s^{-1}}\)でやった結果である。白丸が本物の単振動で黒丸が近似した\(x_i\)である。実際の単振動より初速が早いという印象である。\(\omega=1\ \mathrm{rad\ s^{-1}}\)では肉眼で差が見られなかった。オイラー法でも十分よい近似といえる。htmlが使え自分でも試してみたいという方はとてもお粗末なコードだが、参考にしてみてほしい。以下のコードをhtmlファイルの<body></body>の中にコピペでできるはず。
<div>
初期位置
</div>
<input id="input1">
<div>
初期速度
</div>
<input id="input2">
<div>
角振動数
</div>
<input id="input3">
<div>
<button id="button1">
スタート
</button>
</div>
<canvas id="canvas1"></canvas>
<script>
let xin = document.getElementById("input1");
xin.value = 3;
let vin = document.getElementById("input2");
vin.value = 0;
let omega = document.getElementById("input3");
omega.value = 1;
let but1 = document.getElementById("button1")
let width = 600;
let height = 300;
let canvas1 = document.getElementById("canvas1");
let c1 = canvas1.getContext("2d");
canvas1.width = width;
canvas1.height = height;
let cn=c1;
let xo = 50;
let yo = 250;
let x = 40*xin.value;
let v = 40*vin.value;
let ome = 1*omega.value;
let dt=0.01;
let setI = setInterval(()=>{
cn.clearRect(0,0,width,height);
cn.beginPath();
cn.moveTo(xo,yo);
cn.lineTo(xo+400,yo);
cn.stroke();
for (i=0;i<11;i++) {
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.beginPath();
cn.arc(xo+200+x,yo-80,4,0,Math.PI*2);
cn.fill();
cn.save();
cn.beginPath();
cn.setLineDash([3, 5]);
cn.moveTo(xo,yo-80);
cn.lineTo(xo+400,yo-80);
cn.stroke();
cn.restore();
v = v - ome**2*x*dt;
x = x + v*dt;
},10);
but1.addEventListener("click",()=>{
xin = document.getElementById("input1");
vin = document.getElementById("input2");
omega = document.getElementById("input3");
x = 40*xin.value;
v = 40*vin.value;
ome = 1*omega.value;
});
</script>