Jekyll2016-07-10T11:30:36+00:00https://leios.github.io//LeiosOSThis is a site for James Schloss, physics PhD student at <a href="http://www.oist.jp/" target="_blank">OIST</a>. We solve silly questions with code.James SchlossBatman Integration2016-07-10T00:00:00+00:002016-07-10T00:00:00+00:00https://leios.github.io//Batman<div class="youtube-16-9">
<iframe height="100%" width="100%" src="https://www.youtube.com/embed/AyBNnkYrSWY" frameborder="0" allowfullscreen=""></iframe>
</div>
<ul>
<li><a href="#bg">Background</a></li>
<li><a href="#BatmanCurve">Integrating the Batman Curve</a></li>
</ul>
<p><a name="bg"></a></p>
<h2 id="background">Background</h2>
<p>The Monte Carlo algorithm is used all over the world for a number of things.
In physics, it is often used to find integrals of poorly-behaved functions, and it works incredibly well for that!
Let’s take a minute to describe how the Monte Carlo algorithm works and why it’s cool.</p>
<p>Firstly, let’s define what an integral is: it is a fancy way to find an area.
For now, that’s all we need to know.
Sure, there are plenty of people who make it way, way more complicated than that, but the simpler the definition, the simpler the algorithm.
I like simple algorithms.</p>
<p>So, if an integral is just an area, what do we need to do to find that area?
Well, use geometry!
If we have a box, the area of the box is obviously its <script type="math/tex">width \times height</script>.
If we have a triangle, the area is simply <script type="math/tex">\frac{1}{2} width \times height</script>.
Generally, the more complicated the shape, the harder it is to find the shape’s area from geometry.</p>
<p>That said, we don’t really need to find the shape of the object we are integrating to find it’s area.
Instead, we can take a simple object, find the area of that and then embed a more complicated object inside of it.
If we can find the ratio of how filled the simple object is by the more complicated object inside of it, then we can find the area of the complicated object like so:</p>
<script type="math/tex; mode=display">Ratio \times Area\ of\ simple\ object</script>
<p>Of course, this will only work if the simple object is larger than the more complicated one, such that the complicated object falls perfectly inside of the larger object’s boundaries.</p>
<p>Let’s take the example of a circle and square:</p>
<p><img src="../images/Batman/square_circle.png" alt="Circle inside of Square" class="center-image" /></p>
<p>In this case, the area of the circle is <script type="math/tex">\pi \times Radius^2</script> and the area of the square is <script type="math/tex">4 * Radius^2</script>.
This means that</p>
<script type="math/tex; mode=display">Ratio = \frac{\pi \times Radius^2}{4 * Radius^2} = \frac{\pi}{4}</script>
<p>From here, it’s obvious that</p>
<script type="math/tex; mode=display">Ratio \times Area\ of\ Square = \frac{\pi}{4} \times 4 * Radius^2 = \pi \times Radius^2</script>
<p>Or the area of the circle.</p>
<p>But now we have a question: How do we find that ratio for arbitrary shapes?
Well, Monte Carlo’s solution to this is <em>Random Sampling</em>.
If we take a bunch of points in the simple region with the more complicated shape inside, then</p>
<script type="math/tex; mode=display">Ratio = \frac{Count\ in\ Complicated\ Shape}{Count\ in\ Box}</script>
<p>And that’s pretty cool.
It means that if we take a whole bunch of points, we should be able to find the ratio and integrate any arbitrarily shaped / size object!
For the example above:</p>
<p><img src="../images/Batman/MonteCarlo.gif" alt="gif of simple Monte Carlo algorithm" class="center-image" /></p>
<p>And we see that the ratio is pretty darn close to <script type="math/tex">\frac{\pi}{4} = 0.785398</script>.</p>
<p>The most difficult part of the Monte Carlo algorithm is finding the appropriate evaluation function.
For example: How did we know whether a random point on the plane was within the circle above?
Well, we simply had to plug it into a function that checked to see whether a line drawn from the origin to the x-y location of the random point was greater or less than a provided radius for the circle.
The code basically looks like:</p>
<div class="language-cpp highlighter-rouge"><pre class="highlight"><code><span class="c1">// Function to check whether point is in circle or not
</span><span class="kt">bool</span> <span class="n">in_circle</span><span class="p">(</span><span class="n">pos</span> <span class="n">loc</span><span class="p">,</span> <span class="n">pos</span> <span class="n">origin</span><span class="p">,</span> <span class="kt">double</span> <span class="n">radius</span><span class="p">){</span>
<span class="kt">double</span> <span class="n">x</span> <span class="o">=</span> <span class="n">loc</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">origin</span><span class="p">.</span><span class="n">x</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">y</span> <span class="o">=</span> <span class="n">loc</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">origin</span><span class="p">.</span><span class="n">y</span><span class="p">;</span>
<span class="k">if</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">y</span><span class="o">*</span><span class="n">y</span> <span class="o"><</span> <span class="n">radius</span> <span class="o">*</span> <span class="n">radius</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
</div>
<p>That said, the true power of the Monte Carlo algorithm comes from the fact that we may now integrate somewhat arbitrary functions, for a good example of this, see the next section!</p>
<p><a href="" name="BatmanCurve"></a></p>
<h2 id="integrating-the-batman-curve">Integrating the Batman Curve</h2>
<p>Now here’s the thing: Monte Carlo doesn’t need to use boxes and it doesn’t need to integrate obvious shapes.
Let’s talk about what you need to do to integrate non-obvious functions with one of our favorite superheroes: Batman!</p>
<p>To be clear: the Batman Curve was not created by me.
I found it on <a href="https://www.reddit.com/">reddit</a> and found all the information I needed <a href="http://math.stackexchange.com/questions/54506/is-this-batman-equation-for-real">on this math stack exchange post</a>.
In addition, <a href="http://mathworld.wolfram.com/BatmanCurve.html">WolframMathWorld had a decent page with the integral on it</a>.
Because the Batman Curve is difficult to integrate (though not impossible by any means!) and it has a clear analytically-defined integral to compare our Monte Carlo integration algorithm against, it was the perfect choice to test some things out.</p>
<p>First things first, for this integral, we were not using a standard box as described above. Instead we were using an oval.
Honestly, the objects don’t matter, but I thought it was worthwhile to point out that the area of the oval is simple <script type="math/tex">\pi \times Shortest\ distance \times Longest\ distance</script>, so <script type="math/tex">\pi \times Radius^2</script> with the shortest and longest distances to the oval from the origin as the radii.</p>
<p>The batman curve was a little tricky, we had to split it into the following equations (<a href="http://math.stackexchange.com/questions/54506/is-this-batman-equation-for-real">image created by Jack in the previously mentioned math stack exchange post</a>):</p>
<p><img src="http://i.stack.imgur.com/EHNR8.png" alt="Image of equations, found here: http://math.stackexchange.com/questions/54506/is-this-batman-equation-for-real" class="center-image" /></p>
<p>Which, when plotted provide:</p>
<p><img src="../images/Batman/simple_bat.png" alt="Batman Curve" class="center-image" /></p>
<p>Then we had to write a simple function to determine if a point inside the oval was within the Batman Curve or not.
To do this, we divided the curve into the following sections:</p>
<p><img src="../images/Batman/batblocks.png" alt="Batman Curve with blocks" class="center-image" /></p>
<p>And here is a visualization of the output:</p>
<p><img src="../images/Batman/batman.gif" alt="gif of Batman Monte Carlo" class="center-image" /></p>
<p>Here is the function (Nothing special, really):</p>
<div class="language-cpp highlighter-rouge"><pre class="highlight"><code>
<span class="c1">// Function to check if we are in batman function for monte_carlo
</span><span class="kt">bool</span> <span class="n">is_batman</span><span class="p">(</span><span class="n">pos</span> <span class="n">dot</span><span class="p">,</span> <span class="n">pos</span> <span class="n">ori</span><span class="p">,</span> <span class="kt">double</span> <span class="n">scale</span><span class="p">){</span>
<span class="c1">// Determine x and y locations
</span> <span class="kt">double</span> <span class="n">pos_x</span> <span class="o">=</span> <span class="p">(</span><span class="n">dot</span><span class="p">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">ori</span><span class="p">.</span><span class="n">x</span><span class="p">)</span> <span class="o">/</span> <span class="n">scale</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">pos_y</span> <span class="o">=</span> <span class="p">(</span><span class="n">dot</span><span class="p">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">ori</span><span class="p">.</span><span class="n">y</span><span class="p">)</span> <span class="o">/</span> <span class="n">scale</span><span class="p">;</span>
<span class="kt">double</span> <span class="n">temp_x</span><span class="p">,</span> <span class="n">temp_y</span><span class="p">;</span>
<span class="c1">// Drawing left upper wing
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o"><=</span> <span class="o">-</span><span class="mi">3</span><span class="p">){</span>
<span class="n">temp_x</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">7</span> <span class="o">*</span> <span class="n">sqrt</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="p">((</span><span class="n">pos_y</span> <span class="o">*</span> <span class="n">pos_y</span><span class="p">)</span><span class="o">/</span><span class="mf">9.0</span><span class="p">)));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">>=</span> <span class="n">temp_x</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing left shoulder
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">></span> <span class="o">-</span><span class="mi">3</span> <span class="o">&&</span> <span class="n">pos_x</span> <span class="o"><=</span> <span class="o">-</span><span class="mi">1</span><span class="p">){</span>
<span class="n">temp_x</span> <span class="o">=</span> <span class="o">-</span><span class="n">pos_x</span><span class="p">;</span>
<span class="n">temp_y</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="mf">2.710523708715754</span> <span class="o">+</span> <span class="p">(</span><span class="mf">1.5</span> <span class="o">-</span> <span class="mf">0.5</span> <span class="o">*</span> <span class="n">temp_x</span><span class="p">))</span>
<span class="o">+</span><span class="mf">1.355261854357877</span>
<span class="o">*</span><span class="n">sqrt</span><span class="p">(</span><span class="mf">4.0</span><span class="o">-</span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">temp_x</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">temp_x</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_y</span> <span class="o">></span> <span class="n">temp_y</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing exterior left ear
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">></span> <span class="o">-</span><span class="mi">1</span> <span class="o">&&</span> <span class="n">pos_x</span> <span class="o"><=</span> <span class="o">-</span><span class="mf">0.75</span><span class="p">){</span>
<span class="n">temp_y</span> <span class="o">=</span> <span class="mf">9.0</span> <span class="o">+</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">pos_x</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_y</span> <span class="o">></span> <span class="o">-</span><span class="n">temp_y</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing interior left ear
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">></span> <span class="o">-</span><span class="mf">0.75</span> <span class="o">&&</span> <span class="n">pos_x</span> <span class="o"><=</span> <span class="o">-</span><span class="mf">0.5</span><span class="p">){</span>
<span class="n">temp_y</span> <span class="o">=</span> <span class="o">-</span><span class="mi">3</span> <span class="o">*</span> <span class="n">pos_x</span> <span class="o">+</span> <span class="mf">0.75</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_y</span> <span class="o">></span> <span class="o">-</span><span class="n">temp_y</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing top of head
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">></span> <span class="o">-</span><span class="mf">.5</span> <span class="o">&&</span> <span class="n">pos_x</span> <span class="o"><=</span> <span class="mf">0.5</span><span class="p">){</span>
<span class="n">temp_y</span> <span class="o">=</span> <span class="mf">2.25</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_y</span> <span class="o">></span> <span class="o">-</span><span class="n">temp_y</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing interior right ear
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">></span> <span class="mf">0.5</span> <span class="o">&&</span> <span class="n">pos_x</span> <span class="o"><=</span> <span class="mf">0.75</span><span class="p">){</span>
<span class="n">temp_y</span> <span class="o">=</span> <span class="mi">3</span> <span class="o">*</span> <span class="n">pos_x</span> <span class="o">+</span> <span class="mf">0.75</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_y</span> <span class="o">></span> <span class="o">-</span><span class="n">temp_y</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing exterior right ear
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">></span> <span class="mf">0.75</span> <span class="o">&&</span> <span class="n">pos_x</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">){</span>
<span class="n">temp_y</span> <span class="o">=</span> <span class="mf">9.0</span> <span class="o">-</span> <span class="mi">8</span> <span class="o">*</span> <span class="n">pos_x</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_y</span> <span class="o">></span> <span class="o">-</span><span class="n">temp_y</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing right shoulder
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o"><=</span> <span class="mi">3</span> <span class="o">&&</span> <span class="n">pos_x</span> <span class="o">></span> <span class="mi">1</span><span class="p">){</span>
<span class="n">temp_y</span> <span class="o">=</span> <span class="o">-</span><span class="p">(</span><span class="mf">2.710523708715754</span> <span class="o">+</span> <span class="p">(</span><span class="mf">1.5</span> <span class="o">-</span> <span class="mf">0.5</span> <span class="o">*</span> <span class="n">pos_x</span><span class="p">))</span>
<span class="o">+</span><span class="mf">1.355261854357877</span>
<span class="o">*</span><span class="n">sqrt</span><span class="p">(</span><span class="mf">4.0</span><span class="o">-</span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">pos_x</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span><span class="o">*</span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">pos_x</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_y</span> <span class="o">></span> <span class="n">temp_y</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing right upper wing
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">></span> <span class="mi">3</span><span class="p">){</span>
<span class="n">temp_x</span> <span class="o">=</span> <span class="p">(</span><span class="mi">7</span> <span class="o">*</span> <span class="n">sqrt</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="p">((</span><span class="n">pos_y</span> <span class="o">*</span> <span class="n">pos_y</span><span class="p">)</span><span class="o">/</span><span class="mf">9.0</span><span class="p">)));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o"><=</span> <span class="n">temp_x</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_y</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">){</span>
<span class="c1">// Drawing bottom left wing
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o"><=</span> <span class="o">-</span><span class="mf">4.0</span><span class="p">){</span>
<span class="n">temp_x</span> <span class="o">=</span> <span class="p">(</span><span class="o">-</span><span class="mi">7</span> <span class="o">*</span> <span class="n">sqrt</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="p">((</span><span class="n">pos_y</span> <span class="o">*</span> <span class="n">pos_y</span><span class="p">)</span><span class="o">/</span><span class="mf">9.0</span><span class="p">)));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">>=</span> <span class="n">temp_x</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing bottom wing
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">></span> <span class="o">-</span><span class="mf">4.0</span> <span class="o">&&</span> <span class="n">pos_x</span> <span class="o"><=</span> <span class="mi">4</span><span class="p">){</span>
<span class="c1">//return false;
</span> <span class="n">temp_y</span> <span class="o">=</span> <span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">pos_x</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span>
<span class="o">-</span> <span class="mf">0.09137221374655434</span> <span class="o">*</span> <span class="n">pos_x</span> <span class="o">*</span> <span class="n">pos_x</span> <span class="o">-</span> <span class="mf">3.0</span><span class="p">)</span>
<span class="o">+</span> <span class="n">sqrt</span><span class="p">(</span><span class="mi">1</span> <span class="o">-</span> <span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">pos_x</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="o">*</span> <span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">pos_x</span><span class="p">)</span><span class="o">-</span><span class="mi">2</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">));</span>
<span class="n">temp_y</span> <span class="o">*=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_y</span> <span class="o"><</span> <span class="n">temp_y</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// Drawing bottom right wing
</span> <span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o">>=</span> <span class="mf">4.0</span><span class="p">){</span>
<span class="c1">//return true;
</span> <span class="n">temp_x</span> <span class="o">=</span> <span class="p">(</span><span class="mi">7</span> <span class="o">*</span> <span class="n">sqrt</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="p">((</span><span class="n">pos_y</span> <span class="o">*</span> <span class="n">pos_y</span><span class="p">)</span><span class="o">/</span><span class="mf">9.0</span><span class="p">)));</span>
<span class="k">if</span> <span class="p">(</span><span class="n">pos_x</span> <span class="o"><=</span> <span class="n">temp_x</span><span class="p">){</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
</code></pre>
</div>
<p><a href="https://github.com/leios/simuleios/blob/master/visualization/monte_carlo/monte_carlo_vis.cpp">The full code is available here</a>.
Note that it is a little messy and long.
That’s because the we used <a href="https://www.cairographics.org/">Cairo</a> to do the visualization, which added a bunch of extra lines to the code.</p>
<p>Overall, this was a pretty fun side-project!</p>
<p>Thanks for reading!</p>James SchlossInvisible Lens2015-11-20T00:00:00+00:002015-11-20T00:00:00+00:00https://leios.github.io//InvLens<ul>
<li><a href="#bg">Background</a></li>
<li><a href="#code">Time-dependent raytracing</a></li>
<li><a href="#FDTD">Finite-Difference Time Domain (FDTD)</a>
<ul>
<li><a href="#TFSF">Total-Field Scattered-Field (TFSF) Boundaries</a></li>
<li><a href="#ABC">Absorbing Boundary Conditions (ABC)</a></li>
</ul>
</li>
</ul>
<p><a name="bg"></a></p>
<h2 id="background">Background</h2>
<p>So, light is an intertesting thing. It’s absolutely fundamental to our lives in every possible way. Even so… understanding the true beauty of light took millenia, with some of the brightest human minds devoted to understanding it. Looking at light, though, it is not immediately obvious why.</p>
<p>Let’s think about light, then. What is it? Well, it might be easier to describe something it is not: a shadow. In fact, any toddler can tell you that when light hits something, it leaves a shadow on the other side. This interaction between light, objects, and shadows led many scientists to believe that light acted as a line of particles, all chained together. This wasn’t inherently wrong, but it wasn’t completely right either. It turns out that light can also act as a wave. How? Well, to answer this question, we need to talk a little more about what light is in the first place.</p>
<p>Light is something called an electromagnetic wave. What is that? Well, an electric field is the thing that causes like charges to repel and opposite charges to attract, and a magnetic field does the same thing except with magnets. These two fields follow particular equations known as Maxwell’s equations that can be written as:</p>
<script type="math/tex; mode=display">\nabla \cdot \vec{B} = 0</script>
<script type="math/tex; mode=display">\nabla \cdot \vec{E} = \frac{\rho}{\epsilon _0}</script>
<script type="math/tex; mode=display">\nabla \times \vec{B} = \mu _0 \vec{J} + \mu _0 \epsilon _0 \frac{\partial \vec{E}}{\partial t}</script>
<script type="math/tex; mode=display">\nabla \cdot \vec{E} = -\frac{\partial \vec{B}}{\partial t}</script>
<p>What do these mean? Well, that depends on who you ask and what we are talking a
bout, but for the most part, the mean the following:</p>
<ol>
<li>There are no Magnetic monopoles</li>
<li>[Gauss’s Law] Charge is conserved unless something else acts on the system</li>
<li>[Amphere’s Law] The magnetic field is related to the change in electric field over time</li>
<li>[Faraday’s Law] The electric field is related to the change in magnetic field over time</li>
</ol>
<p>For our purposes, we only care about the last two: Amphere’s Law and Faraday’s Law. These relate the electric and magnetic fields as they change in time. Basically, they mean that whenever the electric field changes in one direction, the magnetic field must change in another direction, and any time the magnetic field changes in some direction, the electric field must change in another direction. Because of these laws, the electric and magnetic fields must always be perpendicular.</p>
<p>In the case of light, this means that the electric field may move up and down, while the magnetic field moves in and out and the light itself moves forward. In this way, light is a truly 3-dimensional object.</p>
<p>But how does this related to the whole ray vs wave argument? Well, the electromagnetic wave that is light moves forward, but is made of two diffferent waveforms. This means that when we look at light from a distance, it acts as a ray. We don’t even notice the fact that it is a wave hidden in disguise; however, if we start looking closer… all of a sudden we realize that there are some wave-like properties to deal with like diffraction. Now, to be clear: these wave-like phenomenon are only noticeable when the distance in which we are interacting with the light is comparable to the wavelength of the light.</p>
<p>I believe this is a decent enough introduction to light, so let’s talk about an abject that light often interacts with: lenses.</p>
<p>When we consider light as a ray, it interacts with a lens via Snell’s Law:</p>
<script type="math/tex; mode=display">n _1 \sin (\theta _1) = n _2 \sin (\theta _2)</script>
<p>This equation basically relates the angle of a wave entering a lens with the angle of a wave within the lens, itself. In this case, <em>n</em> is something known as an “Index of Refraction,” which is basically a ratio of how dens a medium is when compared to the outside air. If we draw a line perpendicular to the surface of the lens, and assume that the lens is denser than the air outside of it, then the ray will bend towards that line as it enters the lens. If it leaves the lens, it will bend back to the angle it was before.</p>
<p>Now here’s an interesting thought: what if the index of refraction inside the lens was not constant, but instead changed as the light moved through it? Well, in principle the ray would be entering consecutive layers of new lenses. In this way, we could arbitrarily force the ray of light to draw structures for us… or we could do something else.</p>
<p>We could make the lens, itself, invisible!</p>
<p>How? Well, all we need to do is match the rays of light on one side of the lens with the rays of light on the other side of the lens. In this way, an observer would not even notice a difference when looking through the lens. Well, that’s not completely true. An astute observer might recognize a small time delay, but why would that matter? I mean, the delay would be related to the time it took for light to weave it’s way through the lens and light is the fastest thing in the known universe! Surely the time delay would be negligible!</p>
<p>Well, yes. When we consider light to be a ray, it is totally negligible; however, if we consider light to be a wave… we now need to make sure that the time delay perfectly aligns with the light such that the wavefronts do not look disturbed.</p>
<p>In order to really do this system justice, we need to simulate it twice, once with time-dependent ray-tracing and another with one of the most useful physics algorithms out there: Finite-Difference Time Domain (FDTD). That’s exactly what we are going to do!</p>
<p><a href="" name="code"></a></p>
<h2 id="time-dependent-ray-tracing">Time-dependent Ray Tracing</h2>
<p>Remember from our discussion before, the ray approximation of light is only valid when the distance in which we are interacting with the light is much, much greater than the wavelength of the light. In math-speak, this is:</p>
<script type="math/tex; mode=display">\lambda \ll d</script>
<p>MORE COMING SOON</p>
<p><a href="" name="FDTD"></a></p>
<h2 id="finite-difference-time-domain-fdtd">Finite Difference Time Domain (FDTD)</h2>
<p>The Finite Difference Time Domain (FDTD) method is one of the most useful computational methods in the field of electricity and magnetism (which is a pretty active field, if you know the right people). What is it? It’s basically a simulation of the Electric and Magnetic fields in a typical electromagnetic wave. How does it work? Well, that might be a little complicated to explain, so let’s start with something simple-ish: Maxwell’s Equations.</p>
<p>Again, for FDTD simulations we only care about Amphere’s Law and Faraday’s Law because we are trying to find a way to relate the electric and magnetic field in a wave. I mean, for this purpose, who cares if charge is conserved or if there are no such things as magnetic monopoles?</p>
<p>From this information, it would look like we have equations and we know what electromagnetic waves should look like, so that should mean that we are set to start our simulation, right?</p>
<p>Well… Not exactly. Computers do not think like we do, so we need to discretize Maxwell’s Equations. What does that mean? Well, it means that we need to take a continuous system (nature) and split it into a bunch of little blocks that a computer can understand.</p>
<p>But let’s take a minute to think about what we know:</p>
<ul>
<li>The electric field is dependent on the variance of the magnetic field with time</li>
<li>the magnetic field is dependent on the variance of the electric field with time</li>
</ul>
<p>Let’s constrain ourselves to 1 dimension for now and a row of points. Each point will correspond to the electric field at some point in space. With only this one line, we could enforce an electric field distribution by setting all the points to appropriate values and waving our hands in the air like we just don’t care; however, this distribution would be stuck, unmoving for all eternity. How do we get it to move?</p>
<p>Well, we introduce a string of magnetic field points exactly halfway between each electric field point. In this case, though, we do not assign the magnetic field values. Instead, we allow the magnetic field to be calculated from the electric field – where each individual magnetic field point is related to the average of the two nearest electric field points.</p>
<p>So now we have a bit of a situation. The magnetic field is going to change in the very next time step! This is super exciting because it means that the magnetic field is changing with time. What else happens when the magnetic field changes with time?</p>
<p>Right! The electric field also changes! Of course, this is an endless cycle, because the moment the electric field changes, the magnetic field will also change. And then the electric field will change again!
In this way, we have simulated Maxwell’s equations in distritized time and space with an incredibly intuitive method.</p>
<p>Now, I know what you are thinking, “Let’s just plug in this newfangled FDTD nonsense to our index of refraction profile and move on with our lives!” The truth is that life is not that simple.</p>
<p>Just because we can simulate a 1 dimensional wave does not mean we can simulate a lens in 2 dimensions. We need to make a few modifications, some of which are easier than others:</p>
<ol>
<li>Extend the code to 2 dimensions</li>
<li>Force the wave to move in 1 direction only</li>
<li>Stop the wave from moving at some point.</li>
</ol>
<p>Now, all of these seem like they should be simple, right? In fact, the first one is. It’s just a matter of keepign track of your new 2-dimensional array. The latter two, though… they can be a little tricky. They require the introduction of two new devices: the <a href="#TFSF">total-field scattered-field boundary</a> and <a href="#ABC">absorbing boundary conditions</a>.</p>
<p><a href="" name="TFSF"></a></p>
<h3 id="total-field-scattered-field-tfsf-boundaries">Total-Field Scattered-Field (TFSF) boundaries</h3>
<p>What is a Total-Field Scattered-Field (TFSF) boundary? Well, I am glad you asked! It is a boundary that splits your electromagnetic wave into two parts:</p>
<ul>
<li>Total field</li>
<li>Scattered Field</li>
</ul>
<p>It’s literally in the name. But what does this mean? It means that when we create a wave at some point, we can split the wave into two sections – one that goes right and one that goes left. If we keep one of the sides from propagating, we have a TFSF bounday! This means that the wave is only moving in 1 direction!</p>
<p>Why is that cool? Well, think about what we are doing right now. We are trying to simulate an invisible lens. How can we do that without having a wave that moves in a single direction: towards the lens.</p>
<p>Now let’s talk about our ABC’s!</p>
<p><a href="" name="ABC"></a></p>
<h3 id="absorbing-boundary-conditions-abc">Absorbing Boundary Conditions (ABC)</h3>
<p>So, we have a problem. When the wave hits the edge of a box, it bounces back. Why? Well, it’s still trying to solve Maxwell’s equations, right? This means that the magnetic field changes based on the electric field and the electric field changes based on the magnetic field. In this case, if the electric field gets stuck on a wall, our algorithm will just resolve Maxwell’s equations and send the wave back where it came from. This can lead to some interesting physics, but it might not be what you want all the time.</p>
<p>Let’s say we want to pretend our wave is ongoing for all eternity. In this case, we need to do something to our very last elements in our row (or grid in 2 dimensions). What do we need to do? Well, we need to set up a little trap. Sure, we’ll allow the electric and magnetic field to move to the very last grid poing, but when they do, we do something nasty:</p>
<p>We set the very last element to be the value of the second-to-last element (or the very first element to be the second).</p>
<p>What does this mean? Well, it means that there is no longer a difference between the two electric field points, which means there is no magnetic field… and without a magnetic field, the electric field can no longer exist!</p>
<p>This is, in essence, an ABC. Sure. It might not sound too menacing, but it can be depending on the rules you have layed out for yourself. For example, in 2 dimensions, this simple case of setting the two final elements equal to each other will not longer work because you could have the wave moving in a way that is not directly perpendicular to the edge. What a shame that would be. What do you do in that case? Well, that is exactly what we are trying to figure out right now!</p>James SchlossBackground
Time-dependent raytracing
Finite-Difference Time Domain (FDTD)
Total-Field Scattered-Field (TFSF) Boundaries
Absorbing Boundary Conditions (ABC)Maxwell’s Demon2015-11-01T00:00:00+00:002015-11-01T00:00:00+00:00https://leios.github.io//MaxwellsDemon<div class="youtube-16-9">
<iframe height="100%" width="100%" src="https://www.youtube.com/embed/5niDIoptyIU" frameborder="0" allowfullscreen=""></iframe>
</div>
<ul>
<li><a href="#bg">Background</a></li>
<li><a href="#code">About the code</a></li>
</ul>
<p><a name="bg"></a></p>
<h2 id="background">Background</h2>
<p>So. Let’s talk about time travel. I hate to break it to ya, but time travel is
theoretically impossible. It’s not a matter of building or engineering a time
travelling device. It’s a matter of creating theoretical breakthroughs that can
combat the arrows of time.</p>
<p>See, time moves forward. It always moves forward and only makes sense in one
direction: forward. Why? Because of a number of things. Every natural
time-dependent phenomenon has a reason for moving in the direction it does.
Sure, there are some physics equations that are essentially time-independent,
but those are another story entirely. For the most part, we call the reason
time tends to move forward an “arrow of time.”</p>
<p>What is an arrow of time? Well, there are quite a few.</p>
<ul>
<li>
<p>The quantum arrow of time has to do with measurement. After a quantum state is
measured, the state is disturbed and forced into the measured state.</p>
</li>
<li>
<p>The cosmological arrow of time has to do with the universe. In fact, it is the
direction of the expansion of the universe.</p>
</li>
<li>
<p>The causal arrow of time has to do with events. Cause must come before effect.</p>
</li>
</ul>
<p>These are some of the reasons why time must move forward. Now, here’s the thing:
No matter what you do (assuming you are using currently known physics), you will
not be able to physically reverse an arrow of time. You just cannot; however,
some scientists could not help but ponder what kind of being could reverse time.</p>
<p>This leads us to Maxwell’s Demon.</p>
<p>There is an arrow of time known as the thermodynamic arrow of time, which is
essentially the second law of thermodynamics:</p>
<ul>
<li>In any cyclic process the entropy will either increase or remain the same.</li>
</ul>
<p>It doesn’t sound menacing, but it is. Basically this means that in any thermal
process where we can measure the entropy, things will end up more chaotic than
they started.</p>
<p>It probably still doesn’t make any sense, so let’s pretend you had a large
rectangular box in your hands. On the right side, there are only white marbles
and on the left side, there are only black. Let’s also pretend there is a
plastic barrier separating the two sides. If you remove the barrier, the
marbles just around the barrier will move, but for the most part, all the white
marbles will stay on one side and all the black ones will stay on the other.</p>
<p>But what happens if you put a lid on the box and shake it really, really hard?</p>
<p>Well, all of a sudden the white and black marbles mix. Visually, we
immediately notice a difference; however, we can describe this process
thermodynamically as irreversible. It cannot be undone by shaking the box again
and again. Technically, we could remove each of the marbles and carefully place
them on their appropriate side, which would reverse the shaking… but that’s
cheating. Nature cannot do that. Nature can only shake the box and hope for the
best.</p>
<p>And this leads us back to entropy. When all the marbles were neatly ordered on
either side of their box, there was the lowest amount of entropy in the system,
and when the marbles were all mixed up, there was the highest amount. Entropy,
then, is basically the amount of disorder in a system. This process of shaking
a box over and over again shows the second law of thermodynamics. If we take an
ordered state (one with little entropy) and shake it, it will become a
disordered one (one with high entropy).</p>
<p>Of course this is the case, right! We all know how things thermalize… And yet,
looking at this single arrow, scientists have thought of a way to reverse it. To
become one step closer to reversing time. How?</p>
<p>Maxwell’s Demon.</p>
<p>Let’s say you just shook your box of marbles and the marbles are in their most
entropic state. Now let’s say you placed a small (and magical) plastic barrier
in the center. The barrier would only allow white marbles to move to the right
and black particles to move to the left, but would not allow the reverse.</p>
<p>If you shake the box again with the magic barrier, the white marbles would
magically become more likely to move to the right and the black marbles would
magically become more likely to move to the left! Super cool stuff!</p>
<p>Now imagine that instead of black and white marbles, you have particles moving
at different speeds – particles of different temperature. In this way, we could
take a gas that is at some temperature and force all the cooler particles to one
side and all the hotter particles to another. It would be like an oven and
fridge combined into a single device!</p>
<p>And this is Maxwell’s Demon: A sheet of plastic that allows only certain
particles to pass through. A simple concept with revolutionary results!</p>
<p><a href="" name="code"></a></p>
<h2 id="about-the-code">About the code</h2>
<p>The code for out Maxwell’s Demon simulation can be found <a href="https://github.com/leios/simuleios/tree/master/MD/demon">here</a>, feel free to check it out! It is a simple event-driven <a href="http://introcs.cs.princeton.edu/java/assignments/collisions.html">Molecular Dynamics</a> (MD) simulation in 3 dimensions. What does this mean?</p>
<p>Well, imagine that every particle in the simulation is a hard sphere of sorts – like billiard balls. If we give them all an initial kick, they’ll be moving all around and bouncing off each other, like billiard balls do. In this case, we know how the should interact with each other (it’s a super well-solved system). We basically need to take into account 2 interaction types:</p>
<ol>
<li>Particle on particle</li>
<li>Particle on wall</li>
</ol>
<p>We assume that the chances of more than two particles interacting is negligible.</p>
<p>Now. Let’s take a step back and think about the simulation. When most people think about MD simulations, they think about time-driven ones. Every timestep, we move the particles forward a certain amount depending on their initial velocity. If it happens that a particle overlaps with something, we deal with the interaction accordingly. This is a perfectly legitimate way of doing MD; however, because our simulation is (in a sense) simple, we can do something different and exactly solve the interactions in our system with some simple physics formulae.</p>
<p>Basically, the algorithm creates a list of all the next interactions the particles will undergo and sorts the list by which interactions will occur first. It then moves the entire algorithm to that timestep and recalculates the necessary elements in the list, sorting them again by which interactions will occur first.</p>
<p>In the case of a traditional event-driven MD simulation, this simulation keeps moving forward until a set timestep; however, this is not quite traditional. It’s Maxwell’s demon! Instead of just stopping the simulation at a particular timestep, we instead allow the particles to thermalize between two boxes. Once complete, we then insert the demon in the center of the box, which will sort the particles according to their velocity. If a particle’s velocity is faster than the average velocity of all the particles, it is only allowed to the right. If it is slower, it will only be allowed to pass into the left. In this way, we’vesifted the hot and cold particles into two separate boxes, recreating Maxwell’s Demon.</p>
<p>If you are interested in visualizing the code via blender, check out <a href="https://github.com/leios/simuleios/blob/master/visualization/demon.py">this code</a>.</p>James Schloss