# 相疊的木塊
> 作者:王一哲
> 日期:2018/4/22
<br />
這是會出現在基礎物理2B下的例題,出現的章節甚至橫跨動量守恆、功與能量、碰撞等三章,題目敘述如下:
> 木塊A質量為 $2m$、木塊B質量為 $m$,兩個木塊相疊,桌面與木塊A之間沒有摩擦力,A的初速度為 $v$。兩個木塊之間的動摩擦係數為 $\mu_k$,若A的長度夠長,A、B最後能以相同的速度前進,請問:(1) A、B的末速為何? (2) 經過多久之後兩者速度相同。
<img style="display: block; margin-left: auto; margin-right: auto" height="50%" width="50%" src="https://i.imgur.com/AenXbEl.png">
<div style="text-align:center">兩木塊相疊示意圖</div>
<br />
題目有兩種版本,第一種是像上圖的版本,木塊B的初位置在木塊A的最右側且原為靜止,木塊A的初速度向右;第二種則是木塊B的初位置在木塊A的最左側且初速度向右,木塊A原為靜止。這次的目標是將運動過程中木塊A、B的速度 - 時間關係圖、能量 - 時間關係圖畫出來。
<img style="display: block; margin-left: auto; margin-right: auto" height="100%" width="100%" src="https://i.imgur.com/CP8ftNO.png">
<div style="text-align:center">模擬程式畫面截圖</div>
<br />
## 程式 13-1.相疊的木塊完全非彈性碰撞 ([取得程式碼](https://github.com/YiZheWangTw/VPythonTutorial/blob/master/13.%E7%9B%B8%E7%96%8A%E6%9C%A8%E5%A1%8A/13-1_blocks_collision.py)) ([GlowScript 網站動畫連結](http://www.glowscript.org/#/user/yizhe/folder/Public/program/13-1blockscollision))
```python=
"""
VPython教學: 13-1.相疊的木塊完全非彈性碰撞
Ver. 1: 2017/6/16
Ver. 2: 2018/1/4 修改為 Python 3.X 版程式碼
Ver. 3: 2018/2/26 增加 v-t 圖
Ver. 4: 2019/9/8
作者: 王一哲
"""
from vpython import *
"""
1. 參數設定, 設定變數及初始值
(1) m1 = 0.2, v1 = 0.0, m2 = 0.1, v2 = 2.0
(2) m1 = 0.2, v1 = 1.0, m2 = 0.1, v2 = 0.0
(3) m1 = 0.2, v1 = 0.0, m2 = 0.1, v2 = 2.5 => b2 會飛出去
(4) m1 = 0.2, v1 = 2.0, m2 = 0.1, v2 = 0.0 => b1 到畫面右側時還沒有達到等速度
"""
d1 , h1, w1 = 1.8, 0.2, 0.2 # 下方木塊1的長度 = 1.8m, 高度 = 0.2m, 寬度 = 0.2 m
d2 , h2, w2 = 0.2, 0.2, 0.2 # 上方木塊2的長度 = 0.2m, 高度 = 0.2m, 寬度 = 0.2 m
m1, v1, c1 = 0.2, 0.0, color.red # 下方木塊1的質量 = 0.2 kg, 初速 = 0.0 m/s, 紅色
m2, v2, c2 = 0.1, 2.0, color.green # 上方木塊2的質量 = 0.1 kg, 初速 = 2.0 m/s, 綠色
xmax, xmin = 2.0, -2.0 # x 軸範圍
g = 9.8 # 重力加速度 = 9.8 m/s^2
mu = 0.1 # 動摩擦係數
dt = 0.0005 # 畫面更新的時間間隔,單位為s, 原為0.001但不夠準確, 故改為0.0005
t = 0 # 模擬所經過的時間 ,單位為s,初始值為0
bx = 0 # 計算 b2 初位置用的變數
i, te = 0, -1 # 記錄 b1、b2 達到等速度經過時間用的變數
"""
2. 畫面設定
"""
# 產生動畫視窗
scene = canvas(title="Two Blocks", width=800, height=300, center=vec(0, 0.4, 0), background=vec(0, 0.6, 0.6))
# 產生地板
floor = box(pos=vec(0, -0.5*h2, 0), size=vec(xmax - xmin, 0.05, 0.8), color=color.blue)
# 產生下方木塊 b1, 位於畫面最左側 xmin + d1/2, 初速度 v1
b1 = box(pos=vec(xmin + d1/2, 0, 0), size=vec(d1, h1, w1), color = c1, v=vec(v1, 0, 0))
# 產生上方木塊 b2, 若 v2 >= v1 則位於畫面最左側 xmin + d2/2; 若 v2 < v1, 則位於 b1 最右側 xmin + d1 - d2/2, 初速度 v2
if(v2 >= v1): bx = xmin + 0.5*d2
else: bx = xmin + d1 - 0.5*d2
b2 = box(pos=vec(bx, h1, 0), size=vec(d2, h2, w2), color=c2, v=vec(v2, 0, 0))
# 繪圖部分
gd = graph(title="<i>E</i> - <i>t</i> plot", x=0, y=300, width=600, height=450, xtitle="<i>t</i> (s)",
ytitle="red: <i>K</i><sub>1</sub>, green: <i>K</i><sub>2</sub>, blue: <i>E</i> (J)")
kt1 = gcurve(graph=gd, color=c1)
kt2 = gcurve(graph=gd, color=c2)
et = gcurve(graph=gd, color=color.blue)
gd2 = graph(title="<i>v</i> - <i>t</i> plot", x=0, y=750, width=600, height=450, xtitle="<i>t</i> (s)",
ytitle="red: <i>v</i><sub>1</sub>, green: <i>v</i><sub>2</sub> (m/s)")
vt1 = gcurve(graph=gd2, color=c1)
vt2 = gcurve(graph=gd2, color=c2)
"""
3. 物體運動部分, 重複執行直到: (1) b1 抵達邊緣時, (2) b2 抵達 b1 邊緣時
"""
while((b1.pos.x <= xmax - d1/2) and (b2.pos.x + d2/2 <= b1.pos.x + d1/2 + 0.001)):
#動畫執行頻率, 每秒500次
rate(500)
#由 b1, b2 速度判斷動摩擦力量值及加速度方向,
if(b2.v.x > b1.v.x):
force = mu * m2 * g
b1.a = vec(force / m1, 0, 0)
b2.a = vec(-force / m2, 0, 0)
elif(b2.v.x < b1.v.x):
force = mu * m2 * g
b1.a = vec(-force / m1, 0, 0)
b2.a = vec(force / m2, 0, 0)
else:
force = 0
b1.a = vec(0, 0, 0)
b2.a = vec(0, 0, 0)
# 記錄 b1、b2 達到等速度需要的時間
if(abs(b2.v.x - b1.v.x) < 0.0005 and i == 0):
te = t
i = 1
#計算 b1, b2 的速度, 位置
b1.v += b1.a * dt
b2.v += b2.a * dt
b1.pos += b1.v * dt
b2.pos += b2.v * dt
# 計算 b1, b2 動能及系統力學能, 畫能量 - 時間關係圖
k1 = 0.5 * m1 * mag2(b1.v)
k2 = 0.5 * m2 * mag2(b2.v)
e = k1 + k2
kt1.plot(pos = (t, k1))
kt2.plot(pos = (t, k2))
et.plot(pos = (t, e))
# 畫速度 - 時間關係圖
vt1.plot(pos = (t, b1.v.x))
vt2.plot(pos = (t, b2.v.x))
#更新時間
t += dt
#結束 while 迴圈, 印出末速及 b1、b2 達到等速度需要的時間
print("v1 = ", b1.v.x)
print("v2 = ", b2.v.x)
print("te = ", te)
print("end")
```
<br />
### 參數設定
在此設定變數為木塊的長、寬、高、質量、初速度、顏色、x軸的範圍、重力加速度、動摩擦係數、時間、時間間隔,其中時間間隔 dt 設定為 0.0005,這是因為設定為 0.001 時的計算誤差較大,故選擇較小的數值。
<br />
### 畫面設定
大部分的功能在之前的動畫中都已經使用過了,應該只需要解釋比較特別的部分:**由 v1、v2 決定 b2 的初位置**。當 v2 >= v1 時,b2 的初位置要在 b1 的左側,否則在執行動畫之後 b2 會立刻飛出 b1;反之,當 v2 < v1 時,b2 的初位置要在 b1 的右側,因此需要以下兩行程式碼計算 b2 的初位置:
```python
if(v2 >= v1): bx = xmin + d2/2
else: bx = xmin + d1 - d2/2
```
<br />
### 物體運動
1. 為了使動畫重覆執行,直到以下 2 種情況發生為止:
1. b1 抵達畫面邊緣時
2. b2 抵達 b1 邊緣時
因此 while 迴圈中的條件設定為
```python
((b1.pos.x <= xmax - d1/2) and (b2.pos.x + d2/2 <= b1.pos.x + d1/2 + 0.001)
```
第二個條件中加上 0.001 是為了避免當 v1 > v2 時,動畫一開始執行就停止運作。
2. b1、b2 之間的動摩擦力方向與當時的速度有關,共有 3 種狀況:
1. 當 b2.v.x > b1.v.x 時,動摩擦力對 b1 的作用方向向右、對 b2 的作用方向向左。
2. 當 b2.v.x < b1.v.x 時,動摩擦力對 b1 的作用方向向左、對 b2 的作用方向向右。
3. 當 b2.v.x = b1.v.x 時,動摩擦力為 0。
因此需要第 60 ~ 71 行的程式碼,利用 if … elif … else 決定動摩擦力的量值及方向。其實 else 的部分可以省略,因為在程式中 b1.v.x 和 b2.v.x 都是浮點數,幾乎不可能相等。
3. 為了記錄 b1、b2 達到等速度經過的時間,需要第 73 ~ 75 行程式碼。由於 b1.v.x 和 b2.v.x 幾乎不可能相等,因此條件設定為 **abs(b2.v.x - b1.v.x) < 0.0005**。由於只需要記錄 b1.v.x 和 b2.v.x 幾乎相等的第一個時刻,因此條件中再加上 i == 0,並在執行 if 中的程式碼時設定 i = 1,就不會再執行第二次。
4. 計算木塊的加速度,更新速度、位置,計算木塊的動能,畫速度 - 時間關係圖及能量 - 時間關係圖,更新時間。
5. 最後印出木塊末速及 b1、b2 達到等速度需要的時間。
<br />
### 模擬結果
b1、b2 之間的動摩擦力與加速度量值分別為
$$ f_k = \mu_k N = \mu_k m_2 g~~~~~a_1 = \frac{\mu_k m_2 g}{m_1}~~~~~a_2 = \mu_k g $$
可以由上式及動量守恆計算木塊的末速及達成等速度需要的時間。我測試了 4 種不同的條件:
1. m1 = 0.2, v1 = 0.0, m2 = 0.1, v2 = 2.0
理論值:v1’ = v2’ = 2/3, te ≈ 1.360544
模擬結果:v1’ = 0.6668900000000263, v2’ = 0.6662199999997995, te = 1.3604999999999057
<img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/RFP7XEG.png">
<div style="text-align:center">條件1的模擬結果:速度 - 時間關係圖</div>
<br />
<img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/h3yc84S.png">
<div style="text-align:center">條件1的模擬結果:能量 - 時間關係圖</div>
<br />
2. m1 = 0.2, v1 = 1.0, m2 = 0.1, v2 = 0.0
理論值:v1’ = v2’ = 2/3, te ≈ 0.680272
模擬結果:v1’ = 0.666554999999931, v2’ = 0.6668899999999899, te = 0.6799999999999805
<img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/G9Rmt5P.png">
<div style="text-align:center">條件2的模擬結果:速度 - 時間關係圖</div>
<br />
<img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/08Nmo0r.png">
<div style="text-align:center">條件2的模擬結果:能量 - 時間關係圖</div>
<br />
3. m1 = 0.2, v1 = 0.0, m2 = 0.1, v2 = 2.5
理論值:b2 會飛出去,不會達到等速度
模擬結果:b2 會飛出 b1 時 v1’ = 0.41943999999999326, v2’ = 1.6611199999998263
<img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/AOb1wmM.png">
<div style="text-align:center">條件3的模擬結果:速度 - 時間關係圖</div>
<br />
<img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/hBoDeWv.png">
<div style="text-align:center">條件3的模擬結果:能量 - 時間關係圖</div>
<br />
4. m1 = 0.2, v1 = 2.0, m2 = 0.1, v2 = 0.0
理論值:b1 到達畫面右側時兩木塊還未達到等速度
模擬結果:b1 到達畫面右側時 v1’ = 1.357854999999867, v2’ = 1.2842900000000423
<img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/phdvIdQ.png">
<div style="text-align:center">條件4的模擬結果:速度 - 時間關係圖</div>
<br />
<img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://imgur.com/OCERphs.png">
<div style="text-align:center">條件4的模擬結果:能量 - 時間關係圖</div>
<br />
## VPython官方說明書
1. **canvas**: http://www.glowscript.org/docs/VPythonDocs/canvas.html
2. **box**: http://www.glowscript.org/docs/VPythonDocs/box.html
3. **graph**: http://www.glowscript.org/docs/VPythonDocs/graph.html
---
###### tags:`VPython`