# 重力及簡諧 > 作者:王一哲 > 日期:2018/4/15 <br /> 這是在高二下的課程當中一定會出現卻又很抽象的題目: > 在外太空有兩個質量為 $M$ 的星球,星球質量均勻分布且位置固定,兩星球的球星距離為 $2d$,在中垂線上距離 $x$ 處有一個質量為 $m$ 的質點。若質點原為靜止,若只考慮重力的作用,當 $x \ll d$ 時,求 $m$ 運動的週期為何? <img style="display: block; margin-left: auto; margin-right: auto" height="50%" width="50%" src="https://i.imgur.com/9LzKJEj.png"> <br /> #### 解析: 先對 $m$ 畫力圖,則 $m$ 所受合力 $$ F_x = -\frac{2GMmx}{(d^2 + x^2)^{\frac{3}{2}}} \approx -\frac{2GMm}{d^3} x = -kx $$ $$ T = 2\pi \sqrt{\frac{m}{k}} = 2\pi \sqrt{\frac{d^3}{2GM}}$$ <img style="display: block; margin-left: auto; margin-right: auto" height="50%" width="50%" src="https://i.imgur.com/bfaVxHw.png"> <div style="text-align:center"><i>m</i> 的力圖</div> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/CoEApAD.png"> <div style="text-align:center"><i>m</i> 所受合力與距離 <i>x</i> 的關係圖 (0 ≤ x ≤ 100)</div> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/b8C4qYQ.png"> <div style="text-align:center"><i>m</i> 所受合力與距離 <i>x</i> 的關係圖 (0 ≤ x ≤ 8)</div> <br /> 通常還會有加強版,將兩個質量為 $m$ 的星球換成一個質量均勻分布、總質量為 $m$ 、半徑為 $r$ 的圓環。若其餘的條件相同,則 $m$ 所受合力及運動週期: $$ F_x = -\frac{GMmx}{(r^2 + x^2)^{\frac{3}{2}}} \approx -\frac{GMm}{r^3} x = -kx $$ $$ T = 2\pi \sqrt{\frac{m}{k}} = 2\pi \sqrt{\frac{r^3}{GM}}$$ <img style="display: block; margin-left: auto; margin-right: auto" height="50%" width="50%" src="https://i.imgur.com/bwn61kS.png"> <div style="text-align:center"> <i>m</i> 與 <i>M</i> 圓環示意圖</div> <br /> 這次的目標就是要將這兩個題目畫出來。 <br /> ## 程式 11-1:重力造成的簡諧運動, 初速為0, 從端點出發([取得程式碼](https://github.com/YiZheWangTw/VPythonTutorial/blob/master/11.%E9%87%8D%E5%8A%9B%E5%8F%8A%E7%B0%A1%E8%AB%A7/11-1_gravity_SHM.py)) ([GlowScript 網站動畫連結](http://www.glowscript.org/#/user/yizhe/folder/Public/program/11-1gravitySHM)) ```python= """ VPython教學: 11-1.重力造成的簡諧運動, 初速為0, 從端點出發 Ver. 1: 2018/2/23 Ver. 2: 2018/3/14 Ver. 3: 2019/9/8 作者: 王一哲 """ from vpython import * """ 1. 參數設定, 設定變數及初始值, 當 h << d 時週期理論值 3.84669 s """ size = 1 # 小球半徑 m = 1 # 小球質量 M = 2E13 # 星球質量 d = 10 # 星球之間的距離*0.5倍 h = 3 # 小球在星球連線的中垂線上的距離 G = 6.67E-11 # 重力常數 v0 = 0 # 小球初速 i = 0 # 小球回到初位置的次數 t = 0 # 時間 dt = 0.001 # 時間間隔 T = 2*pi*sqrt(d**3/(2*G*M)) # 週期理論值 print("週期理論值 = {:f} s".format(T)) """ 2. 畫面設定 """ # 產生動畫視窗 scene = canvas(title="Gravity and SHM", width=600, height=600, x=0, y=0, center=vec(0, 0, 0), background=color.black, range=1.3*d) # 產生 2 個質量為 M 的星球 s1 = sphere(pos=vec(-d, 0, 0), radius=size, color=color.blue) s2 = sphere(pos=vec(d, 0, 0), radius=size, color=color.blue) # 產生質量為 m 的星球並設定初速度 ball = sphere(pos=vec(0, h, 0), radius=0.4*size, v=vec(0, v0, 0), color=color.red) # 畫星球間的連線、上端點、下端點 line = cylinder(pos=s1.pos, axis=s2.pos-s1.pos, radius=0.1*size, color=color.yellow) top = cylinder(pos=vec(-2, h, 0), axis=vec(4, 0, 0), radius=0.1*size, color=color.white) bottom = cylinder(pos=vec(-2, -h, 0), axis=vec(4, 0, 0), radius=0.1*size, color=color.white) # 產生表示速度、加速度的箭頭 arrow_v = arrow(pos=ball.pos+vec(1, 0, 0), axis=vec(0, 0, 0), shaftwidth=0.3*size, color=color.green) arrow_a = arrow(pos=ball.pos+vec(2, 0, 0), axis=vec(0, 0, 0), shaftwidth=0.3*size, color=color.magenta) # 繪圖部分 gd = graph(title="plot", width=600, height=450, x=0, y=600, xtitle="<i>t</i> (s)", ytitle="blue: <i>y</i> (m), green: <i>v</i> (m/s), magenta: <i>a</i> (m/s<sup>2</sup>)") yt = gcurve(graph=gd, color=color.blue) vt = gcurve(graph=gd, color=color.green) at = gcurve(graph=gd, color=color.magenta) """ 3. 物體運動部分, 小球來回 5 次時停止 """ while i < 5: rate(1000) # 計算小球所受重力並存到變數 F r1 = ball.pos-s1.pos r2 = ball.pos-s2.pos F1 = -(G*M*m)/r1.mag2*r1.norm() F2 = -(G*M*m)/r2.mag2*r2.norm() F = F1+F2 # 計算運動中小球的加速度、速度、位置, 畫出代表速度、加速度的箭頭 ball.a = F/m ball.v += ball.a*dt ball.pos += ball.v*dt arrow_v.pos = ball.pos+vec(1, 0, 0) arrow_a.pos = ball.pos+vec(2, 0, 0) arrow_v.axis = ball.v arrow_a.axis = ball.a # 畫出 y-t, v-t, a-t 圖 yt.plot(pos=(t, ball.pos.y)) vt.plot(pos=(t, ball.v.y)) at.plot(pos=(t, ball.a.y)) # 判斷小球是否回到出發點, 計算回到出發點的次數 if ball.pos.y > h: i += 1 print("第 {:d} 次回到出發點, t = {:f} s".format(i, t)) # 更新時間 t += dt ``` <br /> ### 參數設定 在此設定變數為 size、m、M、d、h、G、v0、i、t、dt,用途已寫在該行的註解當中。 <br /> ### 畫面設定 1. 由於 VPython 預設的視角是從 +z 軸方向朝原點方向看去,畫面右方為 +x 軸方向、畫面上方為 +y 軸方向,原題目中 m 在 x 軸方向上運動,在動畫中改為在 y 軸方向上運動。 2. 產生星球 s1、s2 及小球 ball,並設定小球初位置為 (0, h, 0)、初速度為 0。如果之後想要試著讓小球從不同距離出發,只要修改參數設定當中的 h 即可。 3. 畫星球間的連線,也就是平衡點的位置;出發時的高度為上端點,因此下端點應該位於 y = -h 處。 4. 產生表示速度、加速度的箭頭,為了使箭頭不要疊在一起,分別畫在小球右側距離為 1、2 兩處。 5. 開啟繪圖視窗,畫小球的位置、速度、加速度與時間關係圖。 <br /> ### 物體運動 1. 為了使動畫在小球來回 5 次時,將 while 迴圈當中的條件設定為 i < 5,並用 **if(ball.pos.y > h)** 判斷小球是否回到出發點,若回到出發點則印出經過的時間 t 及回到出發點的次數 i 。 2. 利用萬有引力定律計算小球所受合力 F,再由 F = ma 計算小球的加速度,更新速度及位置。 3. 最後畫 y - t、v - t、a - t 圖、更新時間。 <br /> ### 模擬結果 若以程式當中設定數值為例,當 h 很小的時候,週期理論值為 3.84669;若 h = 0.00001 則週期為 3.8449999999996876;若 h = 3 則週期為 4.036999999999683;若 h = 9 則週期為 5.439000000000151。若從 y - t、v - t、a - t 圖來看,當 h = 3 時圖形相當接近 cos、-sin、-cos 的樣子,但是當 h = 9 時圖形就很奇怪了。 <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://i.imgur.com/BuSmtSX.png"> <div style="text-align:center">程式 11-1 畫面截圖</div> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/JGl1CLR.png"> <div style="text-align:center">程式 11-1:h = 3 的 y - t、v - t、a - t 圖</div> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/4TjLGTH.png"> <div style="text-align:center">程式 11-1:h = 9 的 y - t、v - t、a - t 圖</div> <br /> ## 程式 11-2.重力造成的簡諧運動, 初速不為0, 從平衡點出發([取得程式碼](https://github.com/YiZheWangTw/VPythonTutorial/blob/master/11.%E9%87%8D%E5%8A%9B%E5%8F%8A%E7%B0%A1%E8%AB%A7/11-2_gravity_SHM_2.py)) ([GlowScript 網站動畫連結](http://www.glowscript.org/#/user/yizhe/folder/Public/program/11-2gravitySHM2)) ```python= """ VPython教學: 11-2.重力造成的簡諧運動, 初速不為0, 從平衡點出發 Ver. 1: 2018/2/23 Ver. 2: 2018/3/14 Ver. 3: 2019/9/8 作者: 王一哲 """ from vpython import * """ 1. 參數設定, 設定變數及初始值, 當 h << d 時週期理論值 3.84669 s """ size = 1 # 小球半徑 m = 1 # 小球質量 M = 2E13 # 星球質量 d = 10 # 星球之間的距離*0.5倍 h = 0 # 小球在星球連線的中垂線上的距離 G = 6.67E-11 # 重力常數 v0 = 5 # 小球初速 i = 0 # 小球回到初位置的次數 t = 0 # 時間 dt = 0.001 # 時間間隔 T = 2*pi*sqrt(d**3/(2*G*M)) # 週期理論值 print("週期理論值 = {:f} s".format(T)) """ 2. 畫面設定 """ # 產生動畫視窗 scene = canvas(title="Gravity and SHM", width=600, height=600, x=0, y=0, center=vec(0, 0, 0), range=1.6*d, background=color.black) # 產生 2 個質量為 M 的星球 s1 = sphere(pos=vec(-d, 0, 0), radius=size, color=color.blue) s2 = sphere(pos=vec(d, 0, 0), radius=size, color=color.blue) # 產生質量為 m 的星球並設定初速度 ball = sphere(pos=vec(0, h, 0), radius=0.4*size, color=color.red, v=vec(0, v0, 0)) # 畫星球間的連線 line = cylinder(pos=s1.pos, axis=s2.pos-s1.pos, radius=0.1*size, color=color.yellow) # 產生表示速度、加速度的箭頭 arrow_v = arrow(pos=ball.pos+vec(1, 0, 0), axis=vec(0, 0, 0), shaftwidth=0.3*size, color=color.green) arrow_a = arrow(pos=ball.pos+vec(2, 0, 0), axis=vec(0, 0, 0), shaftwidth=0.3*size, color=color.magenta) # 繪圖部分 gd = graph(title="plot", width=600, height=450, x=0, y=600, xtitle="<i>t</i> (s)", ytitle="blue: <i>y</i> (m), green: <i>v</i> (m/s), magenta: <i>a</i> (m/s<sup>2</sup>)") yt = gcurve(graph=gd, color=color.blue) vt = gcurve(graph=gd, color=color.green) at = gcurve(graph=gd, color=color.magenta) """ 3. 物體運動部分, 小球來回 5 次時停止 """ while i < 6: rate(1000) # 計算小球所受重力並存到變數 F r1 = ball.pos-s1.pos r2 = ball.pos-s2.pos F1 = -(G*M*m) / r1.mag2 * r1.norm() F2 = -(G*M*m) / r2.mag2 * r2.norm() F = F1+F2 # 計算運動中小球的加速度、速度、位置, 畫出代表速度、加速度的箭頭 ball.a = F/m ball.v += ball.a*dt ball.pos += ball.v*dt arrow_v.pos = ball.pos+vec(1, 0, 0) arrow_a.pos = ball.pos+vec(2, 0, 0) arrow_v.axis = ball.v arrow_a.axis = ball.a # 畫出 y-t, v-t, a-t 圖 yt.plot(pos=(t, ball.pos.y)) vt.plot(pos=(t, ball.v.y)) at.plot(pos=(t, ball.a.y)) # 判斷小球是否回到出發點, 計算回到出發點的次數, 出發時會多算1次 if ball.pos.y >= 0 and ball.v.y >= v0: if i >= 1: print("第 {:d} 次回到出發點, t = {:f} s".format(i, t)) i += 1 # 更新時間 t += dt ``` <br /> 這個程式與 11-1 幾乎一樣,差別在於設定參數時 h = 0、v0 = 5,由於無法猜出上、下端點在何處,所以沒有先畫出這兩個位置。由於設定的 v0 不大,小球只在連心線附近運動,週期為 4.060999999999691,與理論值 3.84669 相當接近, y - t、v - t、a - t 圖也相當接近 cos、-sin、-cos 的樣子。 <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://i.imgur.com/d3S3ysj.png"> <div style="text-align:center">程式 11-2 畫面截圖</div> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/bKhMaFI.png"> <div style="text-align:center">程式 11-2:v0 = 5 的 y - t、v - t、a - t 圖</div> <br /> ## 程式 11-3.重力造成的簡諧運動, 圓環, 初速為0, 從端點出發([取得程式碼](https://github.com/YiZheWangTw/VPythonTutorial/blob/master/11.%E9%87%8D%E5%8A%9B%E5%8F%8A%E7%B0%A1%E8%AB%A7/11-3_gravity_SHM_ring.py)) ([GlowScript 網站動畫連結](http://www.glowscript.org/#/user/yizhe/folder/Public/program/11-3gravitySHMring)) ```python= """ VPython教學: 11-3.重力造成的簡諧運動, 圓環, 初速為0, 從端點出發 Ver. 1: 2018/2/25 Ver. 2: 2018/3/14 Ver. 3: 2019/9/8 作者: 王一哲 """ from vpython import * """ 1. 參數設定, 設定變數及初始值, 當 h << r 時週期理論值 3.44058 s """ size = 0.4 # 小球半徑 m = 1 # 小球質量 M = 5E13 # 圓環的質量 r = 10 # 圓環的半徑 N = 100 # 圓環分割成小球的數量 dM = M/N # 圓環分割後每個小球的質量 h = 9 # 小球在圓環中垂線上的距離 G = 6.67E-11 # 重力常數 v0 = 0 # 小球初速 j = 0 # 小球回到初位置的次數 t = 0 # 時間 dt = 0.001 # 時間間隔 T = 2*pi*sqrt(r**3/(G*M)) # 週期理論值 print("週期理論值 = {:f} s".format(T)) """ 2. 畫面設定 """ # 產生動畫視窗 scene = canvas(title="Gravity and SHM", width=600, height=600, x=0, y=0, center=vec(0, 0.3*h, 0), range=1.6*r, background=color.black) # 產生質量為 m 的星球並設定初速度 ball = sphere(pos=vec(0, h, 0), radius=size, color=color.red, v=vec(0, v0, 0)) # 畫圓環間的連線、上端點、下端點 line1 = cylinder(pos=vec(-r, 0, 0), axis=vec(2*r, 0, 0), radius=0.1*size, color=color.yellow) line2 = cylinder(pos=vec(0, 0, -r), axis=vec(0, 0, 2*r), radius=0.1*size, color=color.yellow) top = cylinder(pos=vec(-2, h, 0), axis=vec(4, 0, 0), radius=0.1*size, color=color.white) bottom = cylinder(pos=vec(-2, -h, 0), axis=vec(4, 0, 0), radius=0.1*size, color=color.white) # 產生表示速度、加速度的箭頭 arrow_v = arrow(pos=ball.pos+vec(1, 0, 0), axis=vec(0, 0, 0), shaftwidth=0.8*size, color=color.green) arrow_a = arrow(pos=ball.pos+vec(2, 0, 0), axis=vec(0, 0, 0), shaftwidth=0.8*size, color=color.magenta) # 產生質量為 M 的圓環及空白 list, 用 for 迴圈產生圓環分割後的小球並填入空白 list 中 stars_ring = ring(pos=vec(0, 0, 0), axis=vec(0, 1, 0), radius=r, thickness=0.4*size, color=color.green) stars = [] for i in range(0, N): stars.append(sphere(pos=vec(r*cos(i*2*pi/N), 0, r*sin(i*2*pi/N)), radius=0.5*size, color=color.blue)) # 繪圖部分 gd = graph(title="plot", width=600, height=450, x=0, y=600, xtitle="<i>t</i> (s)", ytitle="blue: <i>y</i> (m), green: <i>v</i> (m/s), magenta: <i>a</i> (m/s<sup>2</sup>)") yt = gcurve(graph=gd, color=color.blue) vt = gcurve(graph=gd, color=color.green) at = gcurve(graph=gd, color=color.magenta) """ 3. 物體運動部分, 小球來回 5 次時停止 """ while j < 5: rate(1000) # 用 for 迴圈將 stars 當中的小球依序讀取出來指定給變數 star, 計算小球的重力並存到變數 F F = vec(0, 0, 0) for star in stars: r = ball.pos-star.pos f = -(G*dM*m)/r.mag2*r.norm() F += f # 計算運動中小球的加速度、速度、位置, 畫出代表速度、加速度的箭頭 ball.a = F/m ball.v += ball.a*dt ball.pos += ball.v*dt arrow_v.pos = ball.pos+vec(1, 0, 0) arrow_a.pos = ball.pos+vec(2, 0, 0) arrow_v.axis = ball.v arrow_a.axis = ball.a # 畫出 y-t, v-t, a-t 圖 yt.plot(pos=(t, ball.pos.y)) vt.plot(pos=(t, ball.v.y)) at.plot(pos=(t, ball.a.y)) # 判斷小球是否回到出發點, 計算回到出發點的次數 if ball.pos.y >= h and ball.v.y >= 0: j += 1 print("第 {:d} 次回到出發點, t = {:f} s".format(j, t)) # 更新時間 t += dt ``` <br /> ### 程式設計部分 這是以程式 11-1 為基礎修改而成的,不同之處共有以下幾點: 1. 在畫面設定部分,將 s1、s2 改為圓環,並將圓環分割為 N 個小球,每個小球的質量為 M/N,利用 for 迴圈將 N 個小球平均地放在圓環上,將資料儲存在名為 stars 的串列當中。 2. 在物體運動部分,利用 for 迴圈將 stars 中的小球一次取一個出來並命名為 star,計star 與質量為 m 的小球 ball 之間的萬有引力 f,再由 F += f 計算 ball 合力 F。 <br /> ### 模擬結果 若以程式當中設定數值為例,當 h 很小的時候,週期理論值為 3.44058;若 h = 0.00001 則週期為 3.4389999999997323;若 h = 5 則週期為 3.9069999999996807;若 h = 9 則週期為 4.864999999999959。若從 y - t、v - t、a - t 圖來看,當 h = 5 時圖形相當接近 cos、-sin、-cos 的樣子,但是當 h = 9 時圖形就很奇怪了。 <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://i.imgur.com/VkPbAEY.png"> <div style="text-align:center">程式 11-3 畫面截圖</div> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/c6v2Eht.png"> <div style="text-align:center">程式 11-3:h = 5 的 y - t、v - t、a - t 圖</div> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/TO51ZiV.png"> <div style="text-align:center">程式 11-3:h = 9 的 y - t、v - t、a - t 圖</div> <br /> ## 結語 同學們可以試著調整參數,模擬各種比較極端的情境,例如h很小或是h很大,看看模擬的結果是否符合課本所寫的內容。 <br /> ## VPython官方說明書 1. **canvas**: http://www.glowscript.org/docs/VPythonDocs/canvas.html 2. **sphere**: http://www.glowscript.org/docs/VPythonDocs/sphere.html 3. **arrow**: http://www.glowscript.org/docs/VPythonDocs/arrow.html 4. **ring**: http://www.glowscript.org/docs/VPythonDocs/ring.html 5. **graph**: http://www.glowscript.org/docs/VPythonDocs/graph.html --- ###### tags: `VPython`