Return to 単振り子のエネルギー保存則から周期を求める準備

Maxima で単振り子のエネルギー保存則から周期を求める

単振り子の運動方程式から得られるエネルギー保存則から,Maxima を使って数値積分によって周期を求める。導出については以下を参照:

quad_qags() で数値積分する

振幅 $\theta_0$ の単振り子の周期 $T_p$ は,エネルギー保存則の積分から以下のようになる。

\begin{eqnarray}
T_p(\theta_0) &=&
\frac{2}{\pi} \int_{0}^{\theta_0} \frac{1}{\sqrt{2(\cos\theta-\cos\theta_0)}}d\theta \\
&=&
\frac{\sqrt{2}}{\pi} \int_{0}^{\theta_0} \frac{1}{\sqrt{\cos\theta-\cos\theta_0}}d\theta
\end{eqnarray}

積分部分は数値積分 quad_qags() を使う。(romberg() ではなく quad_qags() を使う!)

この積分が一見やっかいなのは,積分範囲の上限 $\theta = \theta_0$ で被積分関数の分母がゼロになることです。$\theta = \theta_0$ で被積分関数が発散してしまうので,何かエラーでも起こるのかと思いきや,quad_qags() は大変優秀で何事もなかったかのように数値積分してしまいます!

ためしに $\theta_0 = 60^{\circ}$ の場合の積分値を数値積分 quad_qags() で求めてみます。

In [1]:
/* 度をラジアンに変換する関数を準備しておく */
radians(deg):= deg * %pi/180$

th0: 60$
theta0: radians(th0)$

quad_qags(sqrt(2)/(%pi*sqrt(cos(theta)-cos(theta0))), 
          theta, 0, theta0);
Out[1]:
\[\tag{${\it \%o}_{4}$}\left[ 1.073182007084969 , 1.400735083478821 \times 10^{-10} , 315 , 0 \right] \]

quad_qags() は4つの要素のリストを返します:

積分の近似値
見積もられた近似の絶対誤差
被積分関数の評価数
エラーコード

quad_qags()Tp1(th0)

積分を使って定義された周期を Tp1(th0) と定義する。

In [2]:
Tp1(th0):= block(
  /* 度で入力した th をラジアンになおす */
  theta0: radians(th0), 
  
  /* quad_gags() で数値積分し,tmp に格納する */
  ans: quad_qags(sqrt(2)/(%pi*sqrt(cos(theta)-cos(theta0))), theta, 0, theta0), 
  
  /* 積分の近似値を tmp[1] として取り出し,係数をかけて周期をかえす */
  return(ans[1])
)$
In [3]:
Tp1(60);
Out[3]:
\[\tag{${\it \%o}_{6}$}1.073182007084969\]

置換積分で被積分関数が発散しないようにする

このへんにまとめているように,変数変換によって
\begin{eqnarray}
\int_0^{\theta_0} \frac{1}{\sqrt{2(\cos\theta-\cos\theta_0)}} d\theta
&=&
\int_0^{\pi/2} \frac{dt}{\sqrt{1 – k^2 \sin^2 t}}, \\ \quad k &\equiv& \sin\frac{\theta_0}{2}
\end{eqnarray}

と書ける。この形にすると,積分範囲内で被積分関数が発散することもない。

quad_qags()Tp2(th0)

置換積分を使って定義された周期を Tp2(th0) と定義する。

In [4]:
Tp2(th0):= block(
  /* 度で入力した th をラジアンになおす */
  theta0: radians(th0), 
  m: sin(theta0/2)**2,
  
  /* quad_gags() で数値積分し,tmp に格納する */
  ans: quad_qags(2/(%pi*sqrt(1-m*sin(t)**2)), t, 0, %pi/2), 
  
  /* 積分の近似値を tmp[1] として取り出し,係数をかけて周期をかえす */
  return(ans[1])
)$
In [5]:
Tp2(60);
Out[5]:
\[\tag{${\it \%o}_{8}$}1.073182007149364\]

第1種完全楕円積分を使う

このへんにまとめているように,
第1種完全楕円積分 $K(k)$ を使うと,振幅 $\theta_0$ の単振り子の周期 $T_p$ は

\begin{eqnarray}
T_p(\theta_0) &=&
\frac{2}{\pi} \int_{0}^{\theta_0} \frac{1}{\sqrt{2(\cos\theta-\cos\theta_0)}}d\theta \\
&=& \frac{2}{\pi} K(k) \\
&=& \frac{2}{\pi}\int_0^{\pi/2} \frac{dt}{\sqrt{1-k^2 \sin^2 t}}, \quad k \equiv \sin\frac{\theta_0}{2}
\end{eqnarray}

elliptic_kc(m)Tp3(th0)

ありがたいことに,Maxima では以下のように定義された第一種完全楕円積分が elliptic_kc(m) として使えます。

$$\mbox{elliptic_kc(m)} = K(m) \equiv \int_0^{\frac{\pi}{2}}\frac{1}{\sqrt{1 – m \sin^2 x}} dx$$

第1種完全楕円積分 elliptic_kc(m) を使って,Tp3(th0) を以下のように定義する。($m = k^2$ に注意。)

In [6]:
Tp3(th0):= block(
  /* 度で入力した th をラジアンになおす */
  theta0: radians(th0), 
  m: float(sin(theta0/2)**2),
    
  return(2/float(%pi) * elliptic_kc(m))
)$
In [7]:
ev(Tp3(60));
Out[7]:
\[\tag{${\it \%o}_{10}$}1.073182007149365\]

Tp3(th0) のグラフ

In [8]:
/* 変数 th0 の初期化 */
kill(th0)$

draw2d(
  title = "単振り子の振幅と周期の関係",
  /* グリッド  */
  grid = true, 
  /* 座標軸のラベル */
  xlabel = "振幅 θ (°)", 
  ylabel = "規格化された周期 T", 
  /* 表示範囲 */
  xrange = [0, 90], yrange = [0.95, 1.2], 
  /* 線の太さ */
  line_width = 2,

  /* 陽関数 y = f(x) のグラフ */
  explicit(Tp3(th0), th0, 1, 90))$

練習

Tp1(th0)Tp2(th0)Tp3(th0) の誤差を調べる。

In [9]:
th0: 1$
printf(true, "Tp1(~2d) = ~,15f~%", th0, Tp1(th0))$
printf(true, "Tp2(~2d) = ~,15f~%", th0, Tp2(th0))$
printf(true, "Tp3(~2d) = ~,15f~%", th0, Tp3(th0))$
printf(true, " ~%")$

for th0:10 thru 90 step 10 do(
  printf(true, "Tp1(~2d) = ~,15f~%", th0, Tp1(th0)),
  printf(true, "Tp2(~2d) = ~,15f~%", th0, Tp2(th0)),
  printf(true, "Tp3(~2d) = ~,15f~%", th0, Tp3(th0)), 
  printf(true, " ~%")
)$
Tp1( 1) = 1.000019039102995
Tp2( 1) = 1.000019038921006
Tp3( 1) = 1.000019038921006
 
Tp1(10) = 1.001907188137489
Tp2(10) = 1.001907188143217
Tp3(10) = 1.001907188143216
 
Tp1(20) = 1.007669025790934
Tp2(20) = 1.007669025791545
Tp3(20) = 1.007669025791545
 
Tp1(30) = 1.017408797605583
Tp2(30) = 1.017408797595956
Tp3(30) = 1.017408797595956
 
Tp1(40) = 1.031340519129231
Tp2(40) = 1.031340519130037
Tp3(40) = 1.031340519130037
 
Tp1(50) = 1.049782960621873
Tp2(50) = 1.049782960623032
Tp3(50) = 1.049782960623032
 
Tp1(60) = 1.073182007084969
Tp2(60) = 1.073182007149364
Tp3(60) = 1.073182007149365
 
Tp1(70) = 1.102144909638067
Tp2(70) = 1.102144909639270
Tp3(70) = 1.102144909639270
 
Tp1(80) = 1.137492559922217
Tp2(80) = 1.137492559923922
Tp3(80) = 1.137492559923922
 
Tp1(90) = 1.180340599016036
Tp2(90) = 1.180340599016096
Tp3(90) = 1.180340599016096