<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2026-11-13T10:12:15+00:00</updated><id>/feed.xml</id><title type="html">Quentin Jian</title><subtitle>Quentin Jian&apos;s personal site. Will add more description later</subtitle><entry><title type="html">Rk4-In-Vpython</title><link href="/numerical-method/python/2025/12/28/vpython-simulation.html" rel="alternate" type="text/html" title="Rk4-In-Vpython" /><published>2025-12-28T00:00:00+00:00</published><updated>2025-12-28T00:00:00+00:00</updated><id>/numerical-method/python/2025/12/28/vpython-simulation</id><content type="html" xml:base="/numerical-method/python/2025/12/28/vpython-simulation.html"><![CDATA[<p>在高中物理課時我曾學過基本的 vpython 做物理模擬，而之後便再也沒碰過。一直到普通物理課時老師在講解作業提到了用 runge kutta4 integrator 畫 phase diagram可以加分，因此寫了這個 vpython 程式。</p>

<h2 id="4th-order-runge-kutta">4th Order Runge Kutta</h2>

<p>Runge Kutta Method 是一個解非線性常微分方程近似的一系列方法，這些方法中以 4th order runge kutta (RK4)最常被使用，因為利用RK4 我們可以用電腦算出許多難以計算的微分方程的近似解，也因此可以被用來做物理模擬。解微分方程就可以模擬物理是因為描述物理行為的數學式通常以微分式表示，像是 ` F=ma ` 可以寫成 <code class="language-plaintext highlighter-rouge">F = m(dv/dt) =&gt; dv = dt * F/m 而 v = dx/dt</code> 只要知道當下的受力與速度，就可以知道下一個瞬間的速度，知道當下的速度，就可以知道下一個瞬間的位置
利用這個想法，我們可以寫出一個十分直觀的程式:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">t</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">dt</span> <span class="o">=</span> <span class="mf">0.001</span>
<span class="n">v</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1">#(m/s)
</span><span class="n">F</span> <span class="o">=</span> <span class="mi">10</span> <span class="c1">#(N)
</span><span class="n">m</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1">#(kg)
</span><span class="k">while</span> <span class="p">(</span><span class="n">t</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">):</span>
  <span class="n">x</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">v</span> <span class="o">*</span> <span class="n">dt</span>
  <span class="n">v</span> <span class="o">=</span> <span class="n">v</span> <span class="o">+</span> <span class="p">(</span><span class="n">F</span><span class="o">/</span><span class="n">m</span><span class="p">)</span> <span class="o">*</span> <span class="n">dt</span>
</code></pre></div></div>

<p>來簡單估算 10 秒後物體的位置、速度等參數，而上面的這個簡單方法稱為歐拉法(Euler method)，當我們給的dt值越小，計算的結果也就越精確。</p>

<h3 id="為何歐拉法不夠好">為何歐拉法不夠好</h3>

<p>利用歐拉法，大部分基本的物理模擬都能十分貼近現實的表現，過程產生的誤差相對十分渺小，但當我們遇到要模擬複雜一點的系統時就會出問題，例如模擬考慮摩擦力的彈簧振盪時會發現彈簧的能量竟然不減反增。</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="p">(</span><span class="n">t</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span> <span class="mi">100</span><span class="p">):</span>
  <span class="n">rate</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
  <span class="n">square</span><span class="p">.</span><span class="n">a</span><span class="o">=</span><span class="p">(</span><span class="o">-</span><span class="n">K</span><span class="o">*</span><span class="p">(</span><span class="n">spring</span><span class="p">.</span><span class="n">length</span><span class="o">-</span><span class="n">spring</span><span class="p">.</span><span class="n">L0</span><span class="p">)</span><span class="o">*</span><span class="n">spring</span><span class="p">.</span><span class="n">axis</span><span class="p">.</span><span class="n">norm</span><span class="p">()</span> <span class="o">-</span> <span class="p">(</span><span class="mf">0.1</span><span class="p">)</span><span class="o">*</span><span class="n">square</span><span class="p">.</span><span class="n">v</span><span class="p">)</span> <span class="o">/</span> <span class="n">m</span>
  <span class="n">square</span><span class="p">.</span><span class="n">pos</span> <span class="o">+=</span> <span class="n">square</span><span class="p">.</span><span class="n">v</span><span class="o">*</span><span class="n">dt</span>
  <span class="n">square</span><span class="p">.</span><span class="n">v</span> <span class="o">+=</span> <span class="n">square</span><span class="p">.</span><span class="n">a</span><span class="o">*</span><span class="n">dt</span>
  
  
  <span class="n">spring</span><span class="p">.</span><span class="n">axis</span><span class="o">=</span> <span class="n">square</span><span class="p">.</span><span class="n">pos</span><span class="o">-</span><span class="n">spring</span><span class="p">.</span><span class="n">pos</span>
  
  <span class="n">plot_graph</span><span class="p">(</span><span class="n">square</span><span class="p">)</span>
  <span class="n">update_arrow</span><span class="p">(</span><span class="n">square</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
  <span class="n">t</span> <span class="o">+=</span> <span class="n">dt</span>
</code></pre></div></div>

<p><img src="/res/image.png" alt="test result" /></p>

<h3 id="runge-kutta-methods">Runge Kutta Methods</h3>

<p>Runge Kutta 法除了這篇文章主要介紹的 RK4 外，其實Runge Kutta Methods 指的是一系列求微分方程數值解的方法，而他基本上也是前面 Euler Method 的一種延伸，相較於前面只針對 <code class="language-plaintext highlighter-rouge">t</code> 與 <code class="language-plaintext highlighter-rouge">t + dt</code> 便求得下一瞬間的 <code class="language-plaintext highlighter-rouge">x</code> 值，Runge Kutta 法是利用 <code class="language-plaintext highlighter-rouge">t</code> 與 <code class="language-plaintext highlighter-rouge">t + dt</code> 之間的不同時間計算出結果後進行加權得到的，因此直觀上精準度也隨著提高，而背後大概的原理來自於利用已知的數值對函式進行模擬泰勒展開後取其中前幾項進行逼近，基本的Euler Method 屬於取第一項，有點像只看起點的斜率，而RK4則是進行四次取樣因此可以更接近的重現原本函數的曲線。</p>

<p>前面的程式利用RK4重寫後便成為這樣</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">evaluate</span><span class="p">(</span><span class="n">initial</span><span class="p">:</span> <span class="n">State</span><span class="p">,</span> <span class="n">t</span><span class="p">:</span> <span class="nb">float</span><span class="p">,</span> <span class="n">dt</span><span class="p">:</span> <span class="nb">float</span><span class="p">,</span> <span class="n">d</span><span class="p">:</span> <span class="n">Derivative</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Derivative</span><span class="p">:</span>
    <span class="n">state</span> <span class="o">=</span> <span class="n">State</span><span class="p">()</span>
    <span class="n">state</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">initial</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">d</span><span class="p">.</span><span class="n">dx</span> <span class="o">*</span> <span class="n">dt</span>
    <span class="n">state</span><span class="p">.</span><span class="n">v</span> <span class="o">=</span> <span class="n">initial</span><span class="p">.</span><span class="n">v</span> <span class="o">+</span> <span class="n">d</span><span class="p">.</span><span class="n">dv</span> <span class="o">*</span> <span class="n">dt</span>
    
    
    <span class="n">output</span> <span class="o">=</span> <span class="n">Derivative</span><span class="p">()</span>
    <span class="n">output</span><span class="p">.</span><span class="n">dx</span> <span class="o">=</span> <span class="n">state</span><span class="p">.</span><span class="n">v</span>
    
    <span class="n">F</span> <span class="o">=</span> <span class="o">-</span><span class="n">K</span><span class="o">*</span><span class="p">(</span><span class="n">state</span><span class="p">.</span><span class="n">x</span><span class="o">-</span><span class="n">spring</span><span class="p">.</span><span class="n">L0</span><span class="p">)</span><span class="o">*</span><span class="n">spring</span><span class="p">.</span><span class="n">axis</span><span class="p">.</span><span class="n">norm</span><span class="p">()</span>
    
    <span class="n">output</span><span class="p">.</span><span class="n">dv</span> <span class="o">=</span> <span class="n">F</span><span class="o">/</span><span class="n">m</span>
    
    <span class="k">return</span> <span class="n">output</span>

<span class="k">def</span> <span class="nf">RK4</span><span class="p">(</span><span class="n">state</span><span class="p">:</span> <span class="n">State</span><span class="p">,</span> <span class="n">t</span><span class="p">:</span> <span class="nb">float</span><span class="p">,</span> <span class="n">dt</span><span class="p">:</span> <span class="nb">float</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">State</span><span class="p">:</span>
    <span class="n">k1</span> <span class="o">=</span> <span class="n">evaluate</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">t</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">Derivative</span><span class="p">())</span>
    <span class="n">k2</span> <span class="o">=</span> <span class="n">evaluate</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">t</span> <span class="o">+</span> <span class="n">dt</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span> <span class="n">dt</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span> <span class="n">k1</span><span class="p">)</span>
    <span class="n">k3</span> <span class="o">=</span> <span class="n">evaluate</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">t</span> <span class="o">+</span> <span class="n">dt</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span> <span class="n">dt</span><span class="o">/</span><span class="mi">2</span><span class="p">,</span> <span class="n">k2</span><span class="p">)</span>
    <span class="n">k4</span> <span class="o">=</span> <span class="n">evaluate</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">t</span> <span class="o">+</span> <span class="n">dt</span><span class="p">,</span> <span class="n">dt</span><span class="p">,</span> <span class="n">k3</span><span class="p">)</span>
    
    <span class="n">state</span><span class="p">.</span><span class="n">x</span> <span class="o">+=</span> <span class="p">(</span><span class="n">dt</span><span class="o">/</span><span class="mf">6.0</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">k1</span><span class="p">.</span><span class="n">dx</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">k2</span><span class="p">.</span><span class="n">dx</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">k3</span><span class="p">.</span><span class="n">dx</span> <span class="o">+</span> <span class="n">k4</span><span class="p">.</span><span class="n">dx</span><span class="p">)</span>
    <span class="n">state</span><span class="p">.</span><span class="n">v</span> <span class="o">+=</span> <span class="p">(</span><span class="n">dt</span><span class="o">/</span><span class="mf">6.0</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">k1</span><span class="p">.</span><span class="n">dv</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">k2</span><span class="p">.</span><span class="n">dv</span> <span class="o">+</span> <span class="mi">2</span><span class="o">*</span><span class="n">k3</span><span class="p">.</span><span class="n">dv</span> <span class="o">+</span> <span class="n">k4</span><span class="p">.</span><span class="n">dv</span><span class="p">)</span>
    
    <span class="k">return</span> <span class="n">state</span>

<span class="k">while</span> <span class="n">t</span> <span class="o">&amp;</span><span class="n">lt</span><span class="p">;</span> <span class="n">t_max</span><span class="p">:</span>
    <span class="n">rate</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
    
    <span class="n">state</span> <span class="o">=</span> <span class="n">RK4</span><span class="p">(</span><span class="n">state</span><span class="p">,</span> <span class="n">t</span><span class="p">,</span> <span class="n">dt</span><span class="p">)</span>

    <span class="n">square</span><span class="p">.</span><span class="n">pos</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">state</span><span class="p">.</span><span class="n">x</span>
    
    <span class="n">spring</span><span class="p">.</span><span class="n">axis</span><span class="o">=</span> <span class="n">square</span><span class="p">.</span><span class="n">pos</span><span class="o">-</span><span class="n">spring</span><span class="p">.</span><span class="n">pos</span>

    <span class="n">t</span> <span class="o">+=</span> <span class="n">dt</span>
</code></pre></div></div>

<p>換成這個寫法後，模擬出來有比前面的結果好了一些。</p>

<p><img src="/res/RK4Damper.png" alt="alt text" /></p>]]></content><author><name></name></author><category term="numerical-method" /><category term="python" /><summary type="html"><![CDATA[在高中物理課時我曾學過基本的 vpython 做物理模擬，而之後便再也沒碰過。一直到普通物理課時老師在講解作業提到了用 runge kutta4 integrator 畫 phase diagram可以加分，因此寫了這個 vpython 程式。]]></summary></entry><entry><title type="html">SICP-Reading</title><link href="/book/reading/2025/09/01/sicp-reading.html" rel="alternate" type="text/html" title="SICP-Reading" /><published>2025-09-01T00:20:16+00:00</published><updated>2025-09-01T00:20:16+00:00</updated><id>/book/reading/2025/09/01/sicp-reading</id><content type="html" xml:base="/book/reading/2025/09/01/sicp-reading.html"><![CDATA[<p>在大一暑假期間我找了 Structure And Interpretation of Computer Programs 這本在網路上十分有名的 Computer Science 入門書來讀，這本書是以前麻省理工 EECS 大一同名必修課所用的課本，網路上還找的到<a href="https://ocw.mit.edu/courses/6-001-structure-and-interpretation-of-computer-programs-spring-2005/">開放課程</a> 。我想說趁這個暑假空閒的時間藉此多初探二三十年前國外的資訊系學的東西有什麼，還有學一些像是functional progamming的概念，以及基本的直譯器、編譯器如何被寫出來。</p>

<p>在閱讀這本書時我照著開放課程中，去安裝了 <code class="language-plaintext highlighter-rouge">mit-scheme</code> 這個 Scheme 直譯器，並試著學了一點點的 edwin (scheme 版的 emacs)。希望能跟著這本書順便學習怎麼寫Scheme，以及試著把一部份裡面的程式轉成 common lisp。</p>

<h2 id="各章節心得-待更新">各章節心得 (待更新)</h2>]]></content><author><name></name></author><category term="book" /><category term="reading" /><summary type="html"><![CDATA[在大一暑假期間我找了 Structure And Interpretation of Computer Programs 這本在網路上十分有名的 Computer Science 入門書來讀，這本書是以前麻省理工 EECS 大一同名必修課所用的課本，網路上還找的到開放課程 。我想說趁這個暑假空閒的時間藉此多初探二三十年前國外的資訊系學的東西有什麼，還有學一些像是functional progamming的概念，以及基本的直譯器、編譯器如何被寫出來。]]></summary></entry></feed>