# 質譜儀 > 作者:王一哲 > 日期:2018/5/13 <br /> 有5種粒子以相同之速度垂直進入均勻磁場B,其軌跡如下圖所示。設此5種粒子為:碳原子(<sup>12</sup>C)、氧離子(<sup>16</sup>O<sup>2-</sup>)、鈉離子(<sup>23</sup>Na<sup>+</sup>)、鎂離子(<sup>24</sup>Mg<sup>2+</sup>)及氯離子(<sup>35</sup>Cl<sup>-</sup>)。若不考慮重力因素,則圖中1、2、3、4及5之示意軌跡分別代表何者? <img style="display: block; margin-left: auto; margin-right: auto" height="60%" width="60%" src="https://i.imgur.com/oX3Xckp.png"> <div style="text-align:center">粒子在質譜儀中運動軌跡示意圖</div> <br /> 這是84年日大聯招的題目,雖然年代已經很久遠,但在坊間各家的參考書中仍然可以找到這個題目。當粒子向上進入磁場時,帶正電粒子所受的磁力向左,帶負電粒子所受的磁力向右,電中性的粒子沒有受到磁力。若以磁力當作向心力,在磁場中做等速率圓周運動,則 $$ qvB = m \cdot \frac{v^2}{R} ~\Rightarrow~ R = \frac{mv}{qB} \propto \frac{m}{q} $$ 因此本題的答案為<sup>23</sup>Na<sup>+</sup>、<sup>24</sup>Mg<sup>2+</sup>、12<sup>C</sup>、<sup>16</sup>O<sup>2-</sup>、<sup>35</sup>Cl<sup>-</sup>。這次我們要試著用 VPython 將粒子在質譜儀中的運動過程畫出來。 <br /> ## 程式 23-1.質譜儀 ([取得程式碼](https://github.com/YiZheWangTw/VPythonTutorial/blob/master/23.%E8%B3%AA%E8%AD%9C%E5%84%80/23-1.mass_spectrometer.py)) ([GlowScript 網站動畫連結](http://www.glowscript.org/#/user/yizhe/folder/Public/program/23-1.massspectrometer)) ```python= """ VPython教學: 23-1.質譜儀 Ver. 1: 2018/4/8 Ver. 2: 2019/9/19 作者: 王一哲 """ from vpython import * """ 1. 參數設定, 設定變數及初始值 """ size, m, q = 0.01, 1E-10, 2E-8 # 粒子半徑, 質量, 電量 v0 = vec(0, 10, 0) # 粒子初速度 # 用 dictionary 儲存的粒子資料, 用 list 儲存的粒子名稱 masses = {"C": 12*m, "O": 16*m, "Na": 23*m, "Mg": 24*m, "Cl": 35*m} charges = {"C": 0, "O": -2*q, "Na": q, "Mg": 2*q, "Cl": -q} colors = {"C": color.red, "O": color.yellow, "Na": color.orange, "Mg": color.white, "Cl": color.green} particles = ["C", "O", "Na", "Mg", "Cl"] L = 0.4 # 金屬板長度 B_field = vec(0, 0, -10) # 磁場 t, dt = 0, 1E-5 # 時間, 時間間隔 """ 2. 畫面設定 """ # 產生動畫視窗、金屬板 scene = canvas(title="Mass Spectrometer", width=800, height=600, x=0, y=0, center=vec(0, 0, 0), background=color.black) p1 = box(pos=vec(-0.55*L, 0, 0), size=vec(L, 0.01*L, 0.1*L), color=color.blue) p2 = box(pos=vec(0.55*L, 0, 0), size=vec(L, 0.01*L, 0.1*L), color=color.blue) # 產生帶電粒子 name = particles[0] particle = sphere(pos=vec(0, -L/3, 0), v=v0, radius=size, m=masses[name], q=charges[name], color=colors[name], make_trail=True) # 產生表示磁場的箭頭及標籤 arrow_B = arrow(pos=vec(-0.5*L, 0.5*L, 0), axis=vec(0, 0, -0.1), shaftwidth=size, color=color.green) label_B = label(pos=vec(-0.5*L, 0.5*L, 0), text="B", xoffset=25, yoffset=25, color=color.green, font="sans") # 產生表示速度、加速度的箭頭 arrow_v = arrow(pos=particle.pos, shaftwidth=0.5*size, color=color.cyan) arrow_a = arrow(pos=particle.pos, shaftwidth=0.5*size, color=color.magenta) """ 3. 物體運動部分 """ while((abs(particle.pos.x) < 0.1*size and particle.pos.y < L/2) or \ (abs(particle.pos.x) > 0 and particle.pos.y > p1.height/2 + size)): rate(1000) # 計算帶電粒子所受合力, 更新帶電粒子加速度、速度、位置 if(particle.pos.y > p1.height/2 + size): F = particle.q*cross(particle.v, B_field) else: F = vec(0, 0, 0) particle.a = F/particle.m particle.v += particle.a*dt particle.pos += particle.v*dt # 更新表示速度、加速度的箭頭, 只畫出方向以避免動畫自動縮小 arrow_v.pos = particle.pos arrow_a.pos = particle.pos arrow_v.axis = particle.v.norm()*0.1 arrow_a.axis = particle.a.norm()*0.1 # 更新時間 t += dt ``` <br /> ### 參數設定 在此設定變數為size、m、q、masses、charges、colors、particles、v0、L、B_field、t、dt,用途已寫在該行的註解當中。為了使動畫較為順暢,刻意將粒子的電量、質量調大很多。 <br /> ### 畫面設定 1. 產生動畫視窗、金屬板。 2. 產生帶電粒子,可以選擇粒子的名稱,程式會從masses、charges、colors讀取粒子的資料。 3. 產生表示磁場的箭頭及標籤。 4. 產生表示速度、加速度的箭頭。 <br /> ### 物體運動 1. while 迴圈當中的條件設定為 **(abs(particle.pos.x) < 0.1*size and particle.pos.y < L/2) or (abs(particle.pos.x) > 0 and particle.pos.y > p1.height/2 + size)** (a) 第1個條件:當粒子沒有偏轉(-0.1*size < x < 0.1*size)而且還沒有到達畫面最上方時(particle.pos.y < L/2),動畫繼續執行。 (b) 第2個條件:當粒子向左或向右偏轉(abs(particle.pos.x) > 0)而且還沒有撞到金屬板時(particle.pos.y > p1.height/2 + size),動畫繼續執行。 2. 計算帶電粒子所受合力,更新帶電粒子加速度、速度、位置。 3. 更新表示速度、加速度的箭頭,只畫出方向以避免動畫自動縮小。 4. 更新時間。 <br /> ### 模擬結果 以下是3種不同粒子的執行結果。程式 23-1 是測試用的,一次輸入一個粒子的資料並觀察執行的結果,接下來要用 for 迴圈一口氣將 5 個粒子的軌跡畫出來。 <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://i.imgur.com/9DBNutT.png"> <div style="text-align:center">程式 23-1:<sup>12</sup>C 畫面截圖</div> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://i.imgur.com/YmrsGYH.png"> <div style="text-align:center">程式 23-1:<sup>16</sup>O<sup>2-</sup> 畫面截圖</div> <br /> <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://i.imgur.com/IMl6PH1.png"> <div style="text-align:center">程式 23-1:<sup>23</sup>Na<sup>+</sup> 畫面截圖</div> <br /> ## 程式 23-2.質譜儀, 用 for 迴圈自動跑完 5 種粒子 ([取得程式碼](https://github.com/YiZheWangTw/VPythonTutorial/blob/master/23.%E8%B3%AA%E8%AD%9C%E5%84%80/23-2.mass_spectrometer_for.py)) ([GlowScript 網站動畫連結](http://www.glowscript.org/#/user/yizhe/folder/Public/program/23-2.massspectrometerfor)) ```python= """ VPython教學: 23-2.質譜儀, 用 for 迴圈自動跑完 5 種粒子 Ver. 1: 2018/4/8 Ver. 2: 2019/9/19 作者: 王一哲 """ from vpython import * """ 1. 參數設定, 設定變數及初始值 """ size, m, q = 0.01, 1E-10, 2E-8 # 粒子半徑, 質量, 電量 v0 = vec(0, 10, 0) # 粒子初速度 # 用 dictionary 儲存的粒子資料, 用 list 儲存的粒子名稱 masses = {"C": 12*m, "O": 16*m, "Na": 23*m, "Mg": 24*m, "Cl": 35*m} charges = {"C": 0, "O": -2*q, "Na": q, "Mg": 2*q, "Cl": -q} colors = {"C": color.red, "O": color.yellow, "Na": color.orange, "Mg": color.white, "Cl": color.green} labels = {"C": "C", "O": "<sup>16</sup>O<sup>2-</sup>", "Na": "<sup>23</sup>Na<sup>+</sup>", "Mg": "<sup>24</sup>Mg<sup>2+</sup>", "Cl": "<sup>35</sup>Cl<sup>-</sup>"} particles = ["C", "O", "Na", "Mg", "Cl"] L = 0.4 # 金屬板長度 B_field = vec(0, 0, -10) # 磁場 t, dt = 0, 1E-5 # 時間, 時間間隔 """ 2. 畫面設定 """ # 產生動畫視窗、金屬板 scene = canvas(title="Mass Spectrometer", width=800, height=600, x=0, y=0, center=vec(0, 0, 0), background=color.black) p1 = box(pos=vec(-0.55*L, 0, 0), size=vec(L, 0.01*L, 0.1*L), color=color.blue) p2 = box(pos=vec(0.55*L, 0, 0), size=vec(L, 0.01*L, 0.1*L), color=color.blue) # 產生表示磁場的箭頭及標籤 arrow_B = arrow(pos=vec(-0.5*L, 0.5*L, 0), axis=vec(0, 0, -0.1), shaftwidth=size, color=color.green) label_B = label(pos=vec(-0.5*L, 0.5*L, 0), text="B", xoffset=25, yoffset=25, color=color.green, font="sans") """ 3. 用 for 迴圈自動跑完 5 種粒子 """ for name in particles: # 產生帶電粒子 particle = sphere(pos=vec(0, -L/3, 0), v=v0, radius=size, m=masses[name], q=charges[name], color=colors[name], make_trail=True, retain=1000) # 物體運動部分 while((abs(particle.pos.x) < 0.1*size and particle.pos.y < L/2) or \ (abs(particle.pos.x) > 0 and particle.pos.y > p1.height/2 + size)): rate(1000) # 計算帶電粒子所受合力, 更新帶電粒子加速度、速度、位置 if(particle.pos.y > p1.height/2 + size): F = particle.q*cross(particle.v, B_field) else: F = vec(0, 0, 0) particle.a = F/particle.m particle.v += particle.a*dt particle.pos += particle.v*dt # 更新時間 t += dt # 粒子標籤 particle_label = label(pos=particle.pos, text=labels[name], xoffset=25, yoffset=25, color=colors[name], font = "sans") ``` <br /> ### 程式設計部分 程式 23-2 和 23-1 很像,以下只說明修改之處。 1. 加上粒子標籤資料 labels,由於 VPython 的標籤支援 html 語法,可以做出上標、下標的效果。<sup> </sup> 之間的文字為上標, <sub> </sub> 之間的文字為下標。 2. 用 for 迴圈讀取粒子的名稱,並將產生粒子及粒子運動部分的 while 迴圈放到 for 迴圈當中,當 while 迴圈執行完畢時加上粒子的標籤。 <br /> ### 模擬結果 以下是程式 23-2 的執行結果,可以看到粒子的迴轉半徑與 m/q 成正比。 <img style="display: block; margin-left: auto; margin-right: auto" height="80%" width="80%" src="https://i.imgur.com/EEFDrf9.png"> <div style="text-align:center">程式 23-2 畫面截圖</div> <br /> ## 結語 以前遇到這類的題目時,總是根據計算得到的結果畫示意圖,用 VPython 計算粒子在每個時刻的受力,再將整個運動過程畫出來,感覺上比較真實。也可以試著改變粒子的質量和電量,看看會有什麼變化。 <br /> ## VPython官方說明書 1. **canvas**: http://www.glowscript.org/docs/VPythonDocs/canvas.html 2. **box**: http://www.glowscript.org/docs/VPythonDocs/box.html 3. **sphere**: http://www.glowscript.org/docs/VPythonDocs/sphere.html 4. **arrow**: http://www.glowscript.org/docs/VPythonDocs/arrow.html 5. **label**: http://www.glowscript.org/docs/VPythonDocs/label.html --- ###### tags:`VPython`