 bondscell_results $081ce252-d083-4f03-a5bc-a4b171d222bcqueued¤logsrunning¦outputbody]<div class="markdown"><h3 id="Procedures-to-obtain-ion-surface-flux">Procedures to obtain ion surface flux</h3>
<ol>
<li><p>Obtain magnetic field, density, velocity and current from the unstructured grid.</p>
</li>
</ol>
<p>Requires a conversion from BATSRUS unstructured *.out format to VTK *.vtu format.</p>
<ol start="2">
<li><p>Interpolate MHD quantities onto a Cartesian grid and calculate the derived electric field including the convective term and Hall term.</p>
</li>
</ol>
<p class="tex">$$\mathbf&#123;E&#125; &#61; -\sum_\alpha\mathbf&#123;U&#125;_\alpha\times\mathbf&#123;B&#125; &#43; \frac&#123;\mathbf&#123;J&#125;\times\mathbf&#123;B&#125;&#125;&#123;\sum_\alpha q_\alpha n_\alpha&#125; - \frac&#123;\nabla P_e&#125;&#123;\sum_\alpha q_\alpha n_\alpha&#125; &#43; \eta \mathbf&#123;J&#125;$$</p>
<p>This step is performed in ParaView with Python.</p>
<blockquote>
<p>It would be better to first convert the basic quantities from spherical coordinates to Cartesian coordinates, then calculate the derived electric field. If we first calculate the electric field and then interpolate to Cartesian coordinates, then around the inner boundary region there might be some artifacts due to interpolations.</p>
</blockquote>
<ol start="3">
<li><p>Read the field info into TestParticle.jl.</p>
</li>
<li><p>Tracing with prescribed seeds.</p>
</li>
</ol>
<h3 id="Potential-Issues">Potential Issues</h3>
<ul>
<li><p>In some MHD models &#40;e.g. <a href="https://doi.org/10.1029/2009JA014375">Jia&#43; 2009</a>&#41;, there is an additional artificial resistivity.</p>
</li>
<li><p>In <a href="https://doi.org/10.1029/2009JA014375">Jia&#43; 2009</a>&#39;s MHD model, the energetic population&#39;s contribution is included in the pressure term. Whether or not self-consistency is maintained is to be debated.</p>
</li>
<li><p>E field near the inner boundary.</p>
</li>
</ul>
</div>mimetext/htmlrootassigneelast_run_timestampA&~hpersist_js_state·has_pluto_hook_features§cell_id$081ce252-d083-4f03-a5bc-a4b171d222bcdepends_on_disabled_cells§runtime Gpublished_object_keysdepends_on_skipped_cells§errored$e73e1a00-3706-42e1-acd1-ebc8b2b95c62queued¤logsrunning¦outputbodyrows0.0text/plain1.0text/plain0.0text/plain0.0text/plain0.0text/plain1.0text/plain0.1text/plain0.00124295text/plain1.0text/plain0.00124295text/plain0.000124295text/plain0.00118993text/plain0.999999text/plain0.1text/plain0.00902976text/plain1.00004text/plain0.00902965text/plain0.000902976text/plain0.00864452text/plain0.999963text/plain0.1text/plain0.0527251text/plain1.00133text/plain0.0527027text/plain0.00527251text/plain0.0504548text/plain0.998726text/plain0.1text/plain0.301738text/plain1.04328text/plain0.297559text/plain0.0301738text/plain0.284868text/plain0.958567text/plain0.1text/plain1.05209text/plain1.48653text/plain0.883008text/plain0.105209text/plain0.845346text/plain0.534219text/plain0.1text/plain2.14553text/plain2.52988text/plain0.924956text/plain0.214553text/plain0.885504text/plain-0.464631text/plain0.1text/plain3.30351text/plain3.08887text/plain-0.0219528text/plain0.330351text/plain-0.0210164text/plain-0.999779text/plain0.1text/plain	4.58819text/plain2.37303text/plain-0.99156text/plain0.458819text/plain-0.949268text/plain-0.314468text/plain0.1text/plain
5.9665text/plain1.16581text/plain-0.564705text/plain0.59665text/plain-0.540619text/plain0.841267text/plain0.1text/plainmoreobjectid872690c148ccb9abschemanamestimestampvalue1value2value3value4value5value6typesFloat64Float64Float64Float64Float64Float64Float64mime"application/vnd.pluto.table+objectrootassigneelast_run_timestampA&persist_js_state·has_pluto_hook_features§cell_id$e73e1a00-3706-42e1-acd1-ebc8b2b95c62depends_on_disabled_cells§runtime   xpublished_object_keysdepends_on_skipped_cells§errored$d8d1dc93-44e7-466f-93fe-a9b427368944queued¤logsrunning¦outputbody<div class="markdown"><h2 id="WIP:-Tracing-Particles-Near-Ganymede">WIP: Tracing Particles Near Ganymede</h2>
<p>Ganymede is believed to have both an ionosphere and an exosphere besides the magnetosphere.</p>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/MIE_coupling.png' type='image/png'></img>
<p>Our ultimate goal is to build a self-consistent magnetosphere-ionosphere-exosphere coupling model for Ganymede.</p>
</div>mimetext/htmlrootassigneelast_run_timestampA&qpersist_js_state·has_pluto_hook_features§cell_id$d8d1dc93-44e7-466f-93fe-a9b427368944depends_on_disabled_cells§runtime !published_object_keysdepends_on_skipped_cells§errored$9c31a2c5-e0c7-4891-ad45-7a0e10012bd8queued¤logsrunning¦outputbody
<div class="markdown"><p>Relativistic B-only tracing:</p>
<p class="tex">$$\begin&#123;aligned&#125;
\frac&#123;\mathrm&#123;d&#125;\mathbf&#123;u&#125;&#125;&#123;\mathrm&#123;d&#125;t&#125; &amp;&#61; \frac&#123;q&#125;&#123;\gamma m c&#125;\mathbf&#123;u&#125;\times\mathbf&#123;B&#125; \\
\frac&#123;\mathrm&#123;d&#125;\mathbf&#123;r&#125;&#125;&#123;\mathrm&#123;d&#125;t&#125; &amp;&#61; \mathbf&#123;u&#125;
\end&#123;aligned&#125;$$</p>
<p>Initial particle seeds: random location, <span class="tex">$u &#61; c$</span>, pitch angle <span class="tex">$\theta &#61; \cos^&#123;-1&#125;&#40;\mu_0&#41;,\,\text&#123;where &#125;\mu_0 &#61; 0.1-0.7$</span>, random azimuthal angle.</p>
<p>The Lorentz equation in SI units is written as</p>
<p class="tex">$$\frac&#123;\mathrm&#123;d&#125;\mathbf&#123;v&#125;&#125;&#123;\mathrm&#123;d&#125;t&#125; &#61; \frac&#123;q&#125;&#123;m&#125;\left&#40; \mathbf&#123;v&#125;\times\mathbf&#123;B&#125; &#43; \mathbf&#123;E&#125; \right&#41;$$</p>
<p>It can be normalized to </p>
<p class="tex">$$\frac&#123;\mathrm&#123;d&#125;\mathbf&#123;v&#125;^\prime&#125;&#123;\mathrm&#123;d&#125;t^\prime&#125; &#61; \mathbf&#123;v&#125;^\prime\times\mathbf&#123;B&#125;^\prime &#43; \mathbf&#123;E&#125;^\prime$$</p>
<p>with the following transformation</p>
<p class="tex">$$\begin&#123;aligned&#125;
\mathbf&#123;v&#125; &amp;&#61; \mathbf&#123;v&#125;^\prime V_0 \\
\mathbf&#123;x&#125; &amp;&#61; \mathbf&#123;x&#125;^\prime l_0 \\
t &amp;&#61; t^\prime t_0 \\
\mathbf&#123;B&#125; &amp;&#61; \mathbf&#123;B&#125;^\prime B_0 \\
\mathbf&#123;E&#125; &amp;&#61; \mathbf&#123;E&#125;^\prime E_0 &#61; \mathbf&#123;E&#125;^\prime V_0 B_0
\end&#123;aligned&#125;$$</p>
<p>where <span class="tex">$V_0, l_0, t_0, B_0$</span> are prescribed parameters.</p>
<p>After the normalization, we can think of everything in the dimensionless natural units. If the magnetic field is homogeneous and the initial perpendicular velocity is 1, then the gyroradius is 1. MHD solutions are also dimensionless by nature. For the turbulence EM fields, we know their values and the spatial range. To make them more easily understandable, we can convert from the dimensionless MHD to natural units via</p>
<p class="tex">$$\begin&#123;aligned&#125;
V_0 &amp;&#61; c \\
l_0 &amp;&#61; 4 / nx \\
t_0 &amp;&#61; l_0 / V_0 \\
B_0 &amp;&#61; \mathrm&#123;norm&#125;&#40;B&#41;
\end&#123;aligned&#125;$$</p>
<p>and</p>
<pre><code class="language-julia">x &#61; range&#40;xmin, xmax, length&#61;nx&#41; / l₀ 
y &#61; range&#40;ymin, ymax, length&#61;ny&#41; / l₀
z &#61; range&#40;zmin, zmax, length&#61;nz&#41; / l₀
B ./&#61; B₀</code></pre>
<p>When the X extent is 1, then after the normalization, the x grid resolution becomes 1/4, which is a quarter of the gyroradius.</p>
</div>mimetext/htmlrootassigneelast_run_timestampA&~h;persist_js_state·has_pluto_hook_features§cell_id$9c31a2c5-e0c7-4891-ad45-7a0e10012bd8depends_on_disabled_cells§runtime 	ҵpublished_object_keysdepends_on_skipped_cells§errored$9643aa92-18fe-4850-a246-8ad134c085e8queued¤logsrunning¦outputbodyY<div class="markdown"><blockquote>
<p>The surface flux is very sensitive to the seeding procedures. Placing a plane source in the upstream as in &#91;Plainaki&#43; 2015, 2020&#93; is deficient in capturing all the possible sources, which ends up in significantly underestimating ion sputtering.</p>
</blockquote>
<h3 id="Stop-Conditions">Stop Conditions</h3>
<ul>
<li><p>Hitting the surface: <span class="tex">$r_\mathrm&#123;final&#125; &lt; 1.07\, R_G$</span></p>
</li>
<li><p>Escaping from the outer boundary: <span class="tex">$r_\mathrm&#123;final&#125; &gt; 4\,R_G$</span></p>
</li>
</ul>
</div>mimetext/htmlrootassigneelast_run_timestampA&~h2ʰpersist_js_state·has_pluto_hook_features§cell_id$9643aa92-18fe-4850-a246-8ad134c085e8depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$45a18eea-80c0-4aa4-86d4-c25f90df9303queued¤logsrunning¦outputbody;<div class="markdown"><h2 id="Julia-Community-Ecosystem">Julia Community Ecosystem</h2>
<ul>
<li><p><code>DifferentialEquations.jl</code> is one of the earliest and largest packages developed in the community. Among them, OrdinaryDiffEq is a general solver library for ordinary differential equations.</p>
</li>
<li><p><code>Interpolations.jl</code> is the most commonly used high-performance interpolation library in the community. It provides support for different grids, different precisions, and different algorithms.</p>
</li>
<li><p><code>StaticArrays.jl</code> is an optimization library for stack-allocated arrays in the community. It provides memory optimization for small fixed-size arrays that Julia itself does not currently support.</p>
</li>
<li><p><code>Meshes.jl</code> is a new library for different types of grids.</p>
</li>
<li><p><code>SpecialFunctions.jl</code> is a native Julia implementation of special mathematical functions.</p>
</li>
<li><p><code>Makie.jl</code> is a new generation of Julia native graphics library target at GPU rendering.</p>
</li>
</ul>
<h2 id="Advantages-of-Julia&#39;s-Open-Source-Community">Advantages of Julia&#39;s Open Source Community</h2>
<ul>
<li><p>Lego-style combination, avoid reinventing the wheel</p>
<ul>
<li><p>Individual abilities are limited</p>
</li>
<li><p>Taking advantage of the vast open-source algorithm library</p>
</li>
</ul>
</li>
<li><p>The function interface at the language level is very convenient to use</p>
<ul>
<li><p>Support for generic types</p>
</li>
<li><p>Consideration for performance</p>
</li>
</ul>
</li>
<li><p>Collaboration with strangers</p>
<ul>
<li><p>Julia has a large and active community, which makes it easy to find people to collaborate with. This can be a great way to learn new things and get feedback on your work.</p>
</li>
</ul>
</li>
</ul>
</div>mimetext/htmlrootassigneelast_run_timestampA&~h~:persist_js_state·has_pluto_hook_features§cell_id$45a18eea-80c0-4aa4-86d4-c25f90df9303depends_on_disabled_cells§runtime Ylpublished_object_keysdepends_on_skipped_cells§errored$85c0b164-b6e0-43f5-a458-939b4fd7dddequeued¤logsrunning¦outputbody<div class="markdown"><p class="tex">$$\mu&#61;0.1,\,l_0&#61;16/nx$$</p>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/CR3_mu0.1_l16.png' type='image/png'></img>
</div>mimetext/htmlrootassigneelast_run_timestampA&Xְpersist_js_state·has_pluto_hook_features§cell_id$85c0b164-b6e0-43f5-a458-939b4fd7dddedepends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$b7244973-218a-4bb6-8a8f-95f84a8fb225queued¤logsrunning¦outputbody<div class="markdown"><h3 id="Magnetospheric-Ion-Motion">Magnetospheric Ion Motion</h3>
<ul>
<li><p>Spitzer orbit</p>
</li>
<li><p>Gradient and curvature drifts</p>
</li>
<li><p>Orbits near the tail reconnection site</p>
</li>
</ul>
<video controls='' src='https://raw.githubusercontent.com/henry2004y/TestParticlePresentation/master/electron_fixedtime_pm0.5RE_EGI_t1298.mp4' type='video/mp4' loop='' autoplay=''></video>
</div>mimetext/htmlrootassigneelast_run_timestampA&&ٰpersist_js_state·has_pluto_hook_features§cell_id$b7244973-218a-4bb6-8a8f-95f84a8fb225depends_on_disabled_cells§runtime Xpublished_object_keysdepends_on_skipped_cells§errored$d058eddf-a8b1-453b-a440-885a3da0a1a0queued¤logsrunning¦outputbodyL<script>
	
// Load the library for consistent smooth scrolling
const {default: scrollIntoView} = await import("data:text/javascript;base64,dmFyIFE9ZT0+Im9iamVjdCI9PXR5cGVvZiBlJiZudWxsIT1lJiYxPT09ZS5ub2RlVHlwZSxVPShlLHQpPT4oIXR8fCJoaWRkZW4iIT09ZSkmJiJ2aXNpYmxlIiE9PWUmJiJjbGlwIiE9PWUsQT0oZSx0KT0+e2lmKGUuY2xpZW50SGVpZ2h0PGUuc2Nyb2xsSGVpZ2h0fHxlLmNsaWVudFdpZHRoPGUuc2Nyb2xsV2lkdGgpe2xldCBsPWdldENvbXB1dGVkU3R5bGUoZSxudWxsKTtyZXR1cm4gVShsLm92ZXJmbG93WSx0KXx8VShsLm92ZXJmbG93WCx0KXx8KGU9PntsZXQgdD0oZT0+e2lmKCFlLm93bmVyRG9jdW1lbnR8fCFlLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcpcmV0dXJuIG51bGw7dHJ5e3JldHVybiBlLm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcuZnJhbWVFbGVtZW50fWNhdGNoe3JldHVybiBudWxsfX0pKGUpO3JldHVybiEhdCYmKHQuY2xpZW50SGVpZ2h0PGUuc2Nyb2xsSGVpZ2h0fHx0LmNsaWVudFdpZHRoPGUuc2Nyb2xsV2lkdGgpfSkoZSl9cmV0dXJuITF9LFg9KGUsdCxsLG8sbixyLGkscyk9PnI8ZSYmaT50fHxyPmUmJmk8dD8wOnI8PWUmJnM8PWx8fGk+PXQmJnM+PWw/ci1lLW86aT50JiZzPGx8fHI8ZSYmcz5sP2ktdCtuOjAsJD1lPT5lLnBhcmVudEVsZW1lbnQ/PyhlLmdldFJvb3ROb2RlKCkuaG9zdHx8bnVsbCksdHQ9KGUsdCk9Pnt2YXIgbCxvLG4scjtpZih0eXBlb2YgZG9jdW1lbnQ+InUiKXJldHVybltdO2xldHtzY3JvbGxNb2RlOmksYmxvY2s6cyxpbmxpbmU6YSxib3VuZGFyeTpoLHNraXBPdmVyZmxvd0hpZGRlbkVsZW1lbnRzOnV9PXQsZz0iZnVuY3Rpb24iPT10eXBlb2YgaD9oOmU9PmUhPT1oO2lmKCFRKGUpKXRocm93IFR5cGVFcnJvcigiSW52YWxpZCB0YXJnZXQiKTtsZXQgdj1kb2N1bWVudC5zY3JvbGxpbmdFbGVtZW50fHxkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsbT1bXSx3PWU7Zm9yKDtRKHcpJiZnKHcpOyl7aWYoKHc9JCh3KSk9PT12KXttLnB1c2godyk7YnJlYWt9bnVsbCE9dyYmdz09PWRvY3VtZW50LmJvZHkmJkEodykmJiFBKGRvY3VtZW50LmRvY3VtZW50RWxlbWVudCl8fG51bGwhPXcmJkEodyx1KSYmbS5wdXNoKHcpfWxldCBXPW51bGwhPShvPW51bGw9PShsPXdpbmRvdy52aXN1YWxWaWV3cG9ydCk/dm9pZCAwOmwud2lkdGgpP286aW5uZXJXaWR0aCxIPW51bGwhPShyPW51bGw9PShuPXdpbmRvdy52aXN1YWxWaWV3cG9ydCk/dm9pZCAwOm4uaGVpZ2h0KT9yOmlubmVySGVpZ2h0LHtzY3JvbGxYOl8sc2Nyb2xsWTp4fT13aW5kb3cse2hlaWdodDpFLHdpZHRoOlQsdG9wOk4scmlnaHQ6TCxib3R0b206WSxsZWZ0OkN9PWUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksUj0ic3RhcnQiPT09c3x8Im5lYXJlc3QiPT09cz9OOiJlbmQiPT09cz9ZOk4rRS8yLFY9ImNlbnRlciI9PT1hP0MrVC8yOiJlbmQiPT09YT9MOkMsQj1bXTtmb3IobGV0IEQ9MDtEPG0ubGVuZ3RoO0QrKyl7bGV0IE89bVtEXSx7aGVpZ2h0Omosd2lkdGg6SSx0b3A6UyxyaWdodDpxLGJvdHRvbTp6LGxlZnQ6Rn09Ty5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtpZigiaWYtbmVlZGVkIj09PWkmJk4+PTAmJkM+PTAmJlk8PUgmJkw8PVcmJk4+PVMmJlk8PXomJkM+PUYmJkw8PXEpYnJlYWs7bGV0IEc9Z2V0Q29tcHV0ZWRTdHlsZShPKSxKPXBhcnNlSW50KEcuYm9yZGVyTGVmdFdpZHRoLDEwKSxLPXBhcnNlSW50KEcuYm9yZGVyVG9wV2lkdGgsMTApLFA9cGFyc2VJbnQoRy5ib3JkZXJSaWdodFdpZHRoLDEwKSxaPXBhcnNlSW50KEcuYm9yZGVyQm90dG9tV2lkdGgsMTApLGVlPTAsZXQ9MCxlbD0ib2Zmc2V0V2lkdGgiaW4gTz9PLm9mZnNldFdpZHRoLU8uY2xpZW50V2lkdGgtSi1QOjAsZW89Im9mZnNldEhlaWdodCJpbiBPP08ub2Zmc2V0SGVpZ2h0LU8uY2xpZW50SGVpZ2h0LUstWjowLGVuPSJvZmZzZXRXaWR0aCJpbiBPPzA9PT1PLm9mZnNldFdpZHRoPzA6SS9PLm9mZnNldFdpZHRoOjAsZXI9Im9mZnNldEhlaWdodCJpbiBPPzA9PT1PLm9mZnNldEhlaWdodD8wOmovTy5vZmZzZXRIZWlnaHQ6MDtpZih2PT09TyllZT0ic3RhcnQiPT09cz9SOiJlbmQiPT09cz9SLUg6Im5lYXJlc3QiPT09cz9YKHgseCtILEgsSyxaLHgrUix4K1IrRSxFKTpSLUgvMixldD0ic3RhcnQiPT09YT9WOiJjZW50ZXIiPT09YT9WLVcvMjoiZW5kIj09PWE/Vi1XOlgoXyxfK1csVyxKLFAsXytWLF8rVitULFQpLGVlPU1hdGgubWF4KDAsZWUreCksZXQ9TWF0aC5tYXgoMCxldCtfKTtlbHNle2VlPSJzdGFydCI9PT1zP1ItUy1LOiJlbmQiPT09cz9SLXorWitlbzoibmVhcmVzdCI9PT1zP1goUyx6LGosSyxaK2VvLFIsUitFLEUpOlItKFMrai8yKStlby8yLGV0PSJzdGFydCI9PT1hP1YtRi1KOiJjZW50ZXIiPT09YT9WLShGK0kvMikrZWwvMjoiZW5kIj09PWE/Vi1xK1ArZWw6WChGLHEsSSxKLFArZWwsVixWK1QsVCk7bGV0e3Njcm9sbExlZnQ6ZWksc2Nyb2xsVG9wOmVkfT1PO2VlPU1hdGgubWF4KDAsTWF0aC5taW4oZWQrZWUvZXIsTy5zY3JvbGxIZWlnaHQtai9lcitlbykpLGV0PU1hdGgubWF4KDAsTWF0aC5taW4oZWkrZXQvZW4sTy5zY3JvbGxXaWR0aC1JL2VuK2VsKSksUis9ZWQtZWUsVis9ZWktZXR9Qi5wdXNoKHtlbDpPLHRvcDplZSxsZWZ0OmV0fSl9cmV0dXJuIEJ9LGY9ZT0+e3ZhciB0O3JldHVybiExPT09ZT97YmxvY2s6ImVuZCIsaW5saW5lOiJuZWFyZXN0In06KHQ9ZSk9PT1PYmplY3QodCkmJjAhPT1PYmplY3Qua2V5cyh0KS5sZW5ndGg/ZTp7YmxvY2s6InN0YXJ0IixpbmxpbmU6Im5lYXJlc3QifX07ZnVuY3Rpb24gYyhlLHQpe3ZhciBsO2lmKCFlLmlzQ29ubmVjdGVkfHwhKGU9PntsZXQgdD1lO2Zvcig7dCYmdC5wYXJlbnROb2RlOyl7aWYodC5wYXJlbnROb2RlPT09ZG9jdW1lbnQpcmV0dXJuITA7dD10LnBhcmVudE5vZGUgaW5zdGFuY2VvZiBTaGFkb3dSb290P3QucGFyZW50Tm9kZS5ob3N0OnQucGFyZW50Tm9kZX1yZXR1cm4hMX0pKGUpKXJldHVybjtpZigib2JqZWN0Ij09dHlwZW9mKGw9dCkmJiJmdW5jdGlvbiI9PXR5cGVvZiBsLmJlaGF2aW9yKXJldHVybiB0LmJlaGF2aW9yKHR0KGUsdCkpO2xldCBvPSJib29sZWFuIj09dHlwZW9mIHR8fG51bGw9PXQ/dm9pZCAwOnQuYmVoYXZpb3I7Zm9yKGxldHtlbDpuLHRvcDpyLGxlZnQ6aX1vZiB0dChlLGYodCkpKW4uc2Nyb2xsKHt0b3A6cixsZWZ0OmksYmVoYXZpb3I6b30pfXZhciBkLHA9KCk9PihkfHwoZD0icGVyZm9ybWFuY2UiaW4gd2luZG93P3BlcmZvcm1hbmNlLm5vdy5iaW5kKHBlcmZvcm1hbmNlKTpEYXRlLm5vdyksZCgpKTtmdW5jdGlvbiBiKGUpe2xldCB0PU1hdGgubWluKChwKCktZS5zdGFydFRpbWUpL2UuZHVyYXRpb24sMSksbD1lLmVhc2UodCksbz1lLnN0YXJ0WCsoZS54LWUuc3RhcnRYKSpsLG49ZS5zdGFydFkrKGUueS1lLnN0YXJ0WSkqbDtlLm1ldGhvZChvLG4sdCxsKSxvIT09ZS54fHxuIT09ZS55P3JlcXVlc3RBbmltYXRpb25GcmFtZSgoKT0+YihlKSk6ZS5jYigpfWZ1bmN0aW9uIHkoZSx0LGwpe2xldCBvPWFyZ3VtZW50cy5sZW5ndGg+MyYmdm9pZCAwIT09YXJndW1lbnRzWzNdP2FyZ3VtZW50c1szXTo2MDAsbj1hcmd1bWVudHMubGVuZ3RoPjQmJnZvaWQgMCE9PWFyZ3VtZW50c1s0XT9hcmd1bWVudHNbNF06ZT0+MSstLWUqZSplKmUqZSxyPWFyZ3VtZW50cy5sZW5ndGg+NT9hcmd1bWVudHNbNV06dm9pZCAwLGk9YXJndW1lbnRzLmxlbmd0aD42P2FyZ3VtZW50c1s2XTp2b2lkIDAscz1lLnNjcm9sbExlZnQsYT1lLnNjcm9sbFRvcDtiKHtzY3JvbGxhYmxlOmUsbWV0aG9kKHQsbCxvLG4pe2xldCByPU1hdGguY2VpbCh0KSxzPU1hdGguY2VpbChsKTtlLnNjcm9sbExlZnQ9cixlLnNjcm9sbFRvcD1zLGk/Lih7dGFyZ2V0OmUsZWxhcHNlZDpvLHZhbHVlOm4sbGVmdDpyLHRvcDpzfSl9LHN0YXJ0VGltZTpwKCksc3RhcnRYOnMsc3RhcnRZOmEseDp0LHk6bCxkdXJhdGlvbjpvLGVhc2U6bixjYjpyfSl9dmFyIE09ZT0+ZSYmIWUuYmVoYXZpb3J8fCJzbW9vdGgiPT09ZS5iZWhhdmlvcixrPWZ1bmN0aW9uKGUsdCl7bGV0IGw9dHx8e307cmV0dXJuIE0obCk/YyhlLHtibG9jazpsLmJsb2NrLGlubGluZTpsLmlubGluZSxzY3JvbGxNb2RlOmwuc2Nyb2xsTW9kZSxib3VuZGFyeTpsLmJvdW5kYXJ5LHNraXBPdmVyZmxvd0hpZGRlbkVsZW1lbnRzOmwuc2tpcE92ZXJmbG93SGlkZGVuRWxlbWVudHMsYmVoYXZpb3I6ZT0+UHJvbWlzZS5hbGwoZS5yZWR1Y2UoKGUsdCk9PntsZXR7ZWw6byxsZWZ0Om4sdG9wOnJ9PXQsaT1vLnNjcm9sbExlZnQscz1vLnNjcm9sbFRvcDtyZXR1cm4gaT09PW4mJnM9PT1yP2U6Wy4uLmUsbmV3IFByb21pc2UoZT0+eShvLG4scixsLmR1cmF0aW9uLGwuZWFzZSwoKT0+ZSh7ZWw6byxsZWZ0OltpLG5dLHRvcDpbcyxyXX0pLGwub25TY3JvbGxDaGFuZ2UpKV19LFtdKSl9KTpQcm9taXNlLnJlc29sdmUoYyhlLHQpKX07ZXhwb3J0e2sgYXMgZGVmYXVsdH07")

const indent = true
const aside = true
const title_text = "Table of Contents"
const include_definitions = false


const tocNode = html`<nav class="plutoui-toc">
	<header>
	 <span class="toc-toggle open-toc"></span>
	 <span class="toc-toggle closed-toc"></span>
	 ${title_text}
	</header>
	<section></section>
</nav>`

tocNode.classList.toggle("aside", aside)
tocNode.classList.toggle("indent", indent)


const getParentCell = el => el.closest("pluto-cell")

const getHeaders = () => {
	const depth = Math.max(1, Math.min(6, 3)) // should be in range 1:6
	const range = Array.from({length: depth}, (x, i) => i+1) // [1, ..., depth]
	
	const selector = [
		...(include_definitions ? [
			`pluto-notebook pluto-cell .pluto-docs-binding`, 
			`pluto-notebook pluto-cell assignee:not(:empty)`, 
		] : []),
		...range.map(i => `pluto-notebook pluto-cell h${i}`)
	].join(",")
	return Array.from(document.querySelectorAll(selector)).filter(el => 
		// exclude headers inside of a pluto-docs-binding block
		!(el.nodeName.startsWith("H") && el.closest(".pluto-docs-binding"))
	)
}


const document_click_handler = (event) => {
	const path = (event.path || event.composedPath())
	const toc = path.find(elem => elem?.classList?.contains?.("toc-toggle"))
	if (toc) {
		event.stopImmediatePropagation()
		toc.closest(".plutoui-toc").classList.toggle("hide")
	}
}

document.addEventListener("click", document_click_handler)


const header_to_index_entry_map = new Map()
const currently_highlighted_set = new Set()

const last_toc_element_click_time = { current: 0 }

const intersection_callback = (ixs) => {
	let on_top = ixs.filter(ix => ix.intersectionRatio > 0 && ix.intersectionRect.y < ix.rootBounds.height / 2)
	if(on_top.length > 0){
		currently_highlighted_set.forEach(a => a.classList.remove("in-view"))
		currently_highlighted_set.clear()
		on_top.slice(0,1).forEach(i => {
			let div = header_to_index_entry_map.get(i.target)
			div.classList.add("in-view")
			currently_highlighted_set.add(div)
			
			/// scroll into view
			/*
			const toc_height = tocNode.offsetHeight
			const div_pos = div.offsetTop
			const div_height = div.offsetHeight
			const current_scroll = tocNode.scrollTop
			const header_height = tocNode.querySelector("header").offsetHeight
			
			const scroll_to_top = div_pos - header_height
			const scroll_to_bottom = div_pos + div_height - toc_height
			
			// if we set a scrollTop, then the browser will stop any currently ongoing smoothscroll animation. So let's only do this if you are not currently in a smoothscroll.
			if(Date.now() - last_toc_element_click_time.current >= 2000)
				if(current_scroll < scroll_to_bottom){
					tocNode.scrollTop = scroll_to_bottom
				} else if(current_scroll > scroll_to_top){
					tocNode.scrollTop = scroll_to_top
				}
			*/
		})
	}
}
let intersection_observer_1 = new IntersectionObserver(intersection_callback, {
	root: null, // i.e. the viewport
  	threshold: 1,
	rootMargin: "-15px", // slightly smaller than the viewport
	// delay: 100,
})
let intersection_observer_2 = new IntersectionObserver(intersection_callback, {
	root: null, // i.e. the viewport
  	threshold: 1,
	rootMargin: "15px", // slightly larger than the viewport
	// delay: 100,
})

const render = (elements) => {
	header_to_index_entry_map.clear()
	currently_highlighted_set.clear()
	intersection_observer_1.disconnect()
	intersection_observer_2.disconnect()

		let last_level = `H1`
	return html`${elements.map(h => {
	const parent_cell = getParentCell(h)

		let [className, title_el] = h.matches(`.pluto-docs-binding`) ? ["pluto-docs-binding-el", h.firstElementChild] : [h.nodeName, h]

	const a = html`<a 
		class="${className}" 
		title="${title_el.innerText}"
		href="#${parent_cell.id}"
	>${title_el.innerHTML}</a>`
	/* a.onmouseover=()=>{
		parent_cell.firstElementChild.classList.add(
			'highlight-pluto-cell-shoulder'
		)
	}
	a.onmouseout=() => {
		parent_cell.firstElementChild.classList.remove(
			'highlight-pluto-cell-shoulder'
		)
	} */
		
		
	a.onclick=(e) => {
		e.preventDefault();
		last_toc_element_click_time.current = Date.now()
		scrollIntoView(h, {
			behavior: 'smooth', 
			block: 'start',
		}).then(() => 
			// sometimes it doesn't scroll to the right place
			// solution: try a second time!
			scrollIntoView(h, {
				behavior: 'smooth', 
				block: 'start',
			})
	   )
	}

	const row =  html`<div class="toc-row ${className} after-${last_level}">${a}</div>`
		intersection_observer_1.observe(title_el)
		intersection_observer_2.observe(title_el)
		header_to_index_entry_map.set(title_el, row)

	if(className.startsWith("H"))
		last_level = className
		
	return row
})}`
}

const invalidated = { current: false }

const updateCallback = () => {
	if (!invalidated.current) {
		tocNode.querySelector("section").replaceWith(
			html`<section>${render(getHeaders())}</section>`
		)
	}
}
updateCallback()
setTimeout(updateCallback, 100)
setTimeout(updateCallback, 1000)
setTimeout(updateCallback, 5000)

const notebook = document.querySelector("pluto-notebook")


// We have a mutationobserver for each cell:
const mut_observers = {
	current: [],
}

const createCellObservers = () => {
	mut_observers.current.forEach((o) => o.disconnect())
	mut_observers.current = Array.from(notebook.querySelectorAll("pluto-cell")).map(el => {
		const o = new MutationObserver(updateCallback)
		o.observe(el, {attributeFilter: ["class"]})
		return o
	})
}
createCellObservers()

// And one for the notebook's child list, which updates our cell observers:
const notebookObserver = new MutationObserver(() => {
	updateCallback()
	createCellObservers()
})
notebookObserver.observe(notebook, {childList: true})

// And finally, an observer for the document.body classList, to make sure that the toc also works when it is loaded during notebook initialization
const bodyClassObserver = new MutationObserver(updateCallback)
bodyClassObserver.observe(document.body, {attributeFilter: ["class"]})

// Hide/show the ToC when the screen gets small
let m = matchMedia("(max-width: 1000px)")
let match_listener = () => 
	tocNode.classList.toggle("hide", m.matches)
match_listener()
m.addListener(match_listener)

invalidation.then(() => {
	invalidated.current = true
	intersection_observer_1.disconnect()
	intersection_observer_2.disconnect()
	notebookObserver.disconnect()
	bodyClassObserver.disconnect()
	mut_observers.current.forEach((o) => o.disconnect())
	document.removeEventListener("click", document_click_handler)
	m.removeListener(match_listener)
})

return tocNode
</script>
<style>
@media not print {

.plutoui-toc {
	font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Cantarell, Helvetica, Arial, "Apple Color Emoji",
		"Segoe UI Emoji", "Segoe UI Symbol", system-ui, sans-serif;
	--main-bg-color: #fafafa;
	--pluto-output-color: hsl(0, 0%, 36%);
	--pluto-output-h-color: hsl(0, 0%, 21%);
	--sidebar-li-active-bg: rgb(235, 235, 235);
	--icon-filter: unset;
}

@media (prefers-color-scheme: dark) {
	.plutoui-toc {
		--main-bg-color: #303030;
		--pluto-output-color: hsl(0, 0%, 90%);
		--pluto-output-h-color: hsl(0, 0%, 97%);
		--sidebar-li-active-bg: rgb(82, 82, 82);
		--icon-filter: invert(1);
	}
}

.plutoui-toc.aside {
	color: var(--pluto-output-color);
	position: fixed;
	right: 1rem;
	top: 5rem;
	width: min(80vw, 300px);
	padding: 0.5rem;
	padding-top: 0em;
	/* border: 3px solid rgba(0, 0, 0, 0.15); */
	border-radius: 10px;
	/* box-shadow: 0 0 11px 0px #00000010; */
	max-height: calc(100vh - 5rem - 90px);
	overflow: auto;
	z-index: 40;
	background-color: var(--main-bg-color);
	transition: transform 300ms cubic-bezier(0.18, 0.89, 0.45, 1.12);
}

.plutoui-toc.aside.hide {
	transform: translateX(calc(100% - 28px));
}
.plutoui-toc.aside.hide section {
	display: none;
}
.plutoui-toc.aside.hide header {
	margin-bottom: 0em;
	padding-bottom: 0em;
	border-bottom: none;
}
}  /* End of Media print query */
.plutoui-toc.aside.hide .open-toc,
.plutoui-toc.aside:not(.hide) .closed-toc,
.plutoui-toc:not(.aside) .closed-toc {
	display: none;
}

@media (prefers-reduced-motion) {
  .plutoui-toc.aside {
	transition-duration: 0s;
  }
}

.toc-toggle {
	cursor: pointer;
    padding: 1em;
    margin: -1em;
    margin-right: -0.7em;
    line-height: 1em;
    display: flex;
}

.toc-toggle::before {
    content: "";
    display: inline-block;
    height: 1em;
    width: 1em;
    background-image: url("https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/list-outline.svg");
	/* generated using https://dopiaza.org/tools/datauri/index.php */
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPmlvbmljb25zLXY1LW88L3RpdGxlPjxsaW5lIHgxPSIxNjAiIHkxPSIxNDQiIHgyPSI0NDgiIHkyPSIxNDQiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozMnB4Ii8+PGxpbmUgeDE9IjE2MCIgeTE9IjI1NiIgeDI9IjQ0OCIgeTI9IjI1NiIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjMycHgiLz48bGluZSB4MT0iMTYwIiB5MT0iMzY4IiB4Mj0iNDQ4IiB5Mj0iMzY4IiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6MzJweCIvPjxjaXJjbGUgY3g9IjgwIiBjeT0iMTQ0IiByPSIxNiIgc3R5bGU9ImZpbGw6bm9uZTtzdHJva2U6IzAwMDtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7c3Ryb2tlLXdpZHRoOjMycHgiLz48Y2lyY2xlIGN4PSI4MCIgY3k9IjI1NiIgcj0iMTYiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDozMnB4Ii8+PGNpcmNsZSBjeD0iODAiIGN5PSIzNjgiIHI9IjE2IiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6MzJweCIvPjwvc3ZnPg==");
    background-size: 1em;
	filter: var(--icon-filter);
}

.aside .toc-toggle.open-toc:hover::before {
    background-image: url("https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/arrow-forward-outline.svg");
	/* generated using https://dopiaza.org/tools/datauri/index.php */
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPmlvbmljb25zLXY1LWE8L3RpdGxlPjxwb2x5bGluZSBwb2ludHM9IjI2OCAxMTIgNDEyIDI1NiAyNjggNDAwIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NDhweCIvPjxsaW5lIHgxPSIzOTIiIHkxPSIyNTYiIHgyPSIxMDAiIHkyPSIyNTYiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDo0OHB4Ii8+PC9zdmc+");
}
.aside .toc-toggle.closed-toc:hover::before {
    background-image: url("https://cdn.jsdelivr.net/gh/ionic-team/ionicons@5.5.1/src/svg/arrow-back-outline.svg");
	/* generated using https://dopiaza.org/tools/datauri/index.php */
    background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNTEyIDUxMiI+PHRpdGxlPmlvbmljb25zLXY1LWE8L3RpdGxlPjxwb2x5bGluZSBwb2ludHM9IjI0NCA0MDAgMTAwIDI1NiAyNDQgMTEyIiBzdHlsZT0iZmlsbDpub25lO3N0cm9rZTojMDAwO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NDhweCIvPjxsaW5lIHgxPSIxMjAiIHkxPSIyNTYiIHgyPSI0MTIiIHkyPSIyNTYiIHN0eWxlPSJmaWxsOm5vbmU7c3Ryb2tlOiMwMDA7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDo0OHB4Ii8+PC9zdmc+");
}



.plutoui-toc header {
	display: flex;
	align-items: center;
	gap: .3em;
	font-size: 1.5em;
	/* margin-top: -0.1em; */
	margin-bottom: 0.4em;
	padding: 0.5rem;
	margin-left: 0;
	margin-right: 0;
	font-weight: bold;
	/* border-bottom: 2px solid rgba(0, 0, 0, 0.15); */
	position: sticky;
	top: 0px;
	background: var(--main-bg-color);
	z-index: 41;
}
.plutoui-toc.aside header {
	padding-left: 0;
	padding-right: 0;
}

.plutoui-toc section .toc-row {
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
	padding: .1em;
	border-radius: .2em;
}

.plutoui-toc section .toc-row.H1 {
	margin-top: 1em;
}


.plutoui-toc.aside section .toc-row.in-view {
	background: var(--sidebar-li-active-bg);
}


	
.highlight-pluto-cell-shoulder {
	background: rgba(0, 0, 0, 0.05);
	background-clip: padding-box;
}

.plutoui-toc section a {
	text-decoration: none;
	font-weight: normal;
	color: var(--pluto-output-color);
}
.plutoui-toc section a:hover {
	color: var(--pluto-output-h-color);
}

.plutoui-toc.indent section a.H1 {
	font-weight: 700;
	line-height: 1em;
}

.plutoui-toc.indent section .after-H2 a { padding-left: 10px; }
.plutoui-toc.indent section .after-H3 a { padding-left: 20px; }
.plutoui-toc.indent section .after-H4 a { padding-left: 30px; }
.plutoui-toc.indent section .after-H5 a { padding-left: 40px; }
.plutoui-toc.indent section .after-H6 a { padding-left: 50px; }

.plutoui-toc.indent section a.H1 { padding-left: 0px; }
.plutoui-toc.indent section a.H2 { padding-left: 10px; }
.plutoui-toc.indent section a.H3 { padding-left: 20px; }
.plutoui-toc.indent section a.H4 { padding-left: 30px; }
.plutoui-toc.indent section a.H5 { padding-left: 40px; }
.plutoui-toc.indent section a.H6 { padding-left: 50px; }


.plutoui-toc.indent section a.pluto-docs-binding-el,
.plutoui-toc.indent section a.ASSIGNEE
	{
	font-family: JuliaMono, monospace;
	font-size: .8em;
	/* background: black; */
	font-weight: 700;
    font-style: italic;
	color: var(--cm-var-color); /* this is stealing a variable from Pluto, but it's fine if that doesnt work */
}
.plutoui-toc.indent section a.pluto-docs-binding-el::before,
.plutoui-toc.indent section a.ASSIGNEE::before
	{
	content: "> ";
	opacity: .3;
}
</style>
mimetext/htmlrootassigneelast_run_timestampA&t"persist_js_state·has_pluto_hook_features§cell_id$d058eddf-a8b1-453b-a440-885a3da0a1a0depends_on_disabled_cells§runtime͈published_object_keysdepends_on_skipped_cells§errored$72412346-af0c-49dc-8c0d-c5b4fe97429bqueued¤logsrunning¦outputbody<div class="markdown"><h3 id="Our-Model">Our Model</h3>
<p>We use ideal MHD G2 spherical output as a starting point.</p>
<ul>
<li><p>G2 ideal MHD</p>
</li>
<li><p>G2 Hall MHD</p>
</li>
<li><p>G8 ideal MHD</p>
</li>
<li><p>G8 Hall MHD</p>
</li>
</ul>
<h3 id="Seeding">Seeding</h3>
<p>An important question is how to set seeds.</p>
<ul>
<li><p>Thermal population: using MHD values</p>
</li>
<li><p>Energetic population: using observed differential flux, 10 logarithmic bins for sampling</p>
</li>
</ul>
<img controls='' src='https://agupubs.onlinelibrary.wiley.com/cms/asset/818da498-ee6b-4e80-9136-46d032b32092/jgra54295-fig-0002-m.jpg' type='image/jpeg'></img>
</div>mimetext/htmlrootassigneelast_run_timestampA&]ٰpersist_js_state·has_pluto_hook_features§cell_id$72412346-af0c-49dc-8c0d-c5b4fe97429bdepends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$bf6d18d0-ee99-4a2e-badb-c1f42071903bqueued¤logslinemsg;[92m[1mPrecompiling[22m[39m TestParticle...
    437.0 ms[32m  ✓ [39m[90mJLLWrappers[39m
    523.9 ms[33m  ✓ [39m[90mPrecompileTools[39m
    660.0 ms[32m  ✓ [39m[90mTruncatedStacktraces[39m
    700.1 ms[32m  ✓ [39m[90mOpenSpecFun_jll[39m
    704.5 ms[32m  ✓ [39m[90mRmath_jll[39m
   1113.9 ms[32m  ✓ [39m[90mRmath[39m
   2161.2 ms[32m  ✓ [39m[90mRecipesBase[39m
   2855.1 ms[32m  ✓ [39m[90mSpecialFunctions[39m
   1262.5 ms[32m  ✓ [39m[90mDualNumbers[39m
   2834.0 ms[32m  ✓ [39m[90mRecursiveArrayTools[39m
   2277.3 ms[32m  ✓ [39m[90mSpecialFunctions → SpecialFunctionsChainRulesCoreExt[39m
   1285.0 ms[32m  ✓ [39m[90mHypergeometricFunctions[39m
   1616.0 ms[32m  ✓ [39m[90mStatsFuns[39m
   2346.2 ms[32m  ✓ [39m[90mStatsFuns → StatsFunsChainRulesCoreExt[39m
  10176.9 ms[32m  ✓ [39mStaticArrays
    834.7 ms[32m  ✓ [39mStaticArrays → StaticArraysStatisticsExt
   1013.2 ms[32m  ✓ [39mStaticArrays → StaticArraysChainRulesCoreExt
   1108.6 ms[32m  ✓ [39m[90mConstructionBase → ConstructionBaseStaticArraysExt[39m
    862.7 ms[32m  ✓ [39m[90mAdapt → AdaptStaticArraysExt[39m
   8647.3 ms[32m  ✓ [39m[90mSciMLBase[39m
   3359.2 ms[32m  ✓ [39m[90mRotations[39m
   3369.9 ms[32m  ✓ [39m[90mNearestNeighbors[39m
   3289.6 ms[32m  ✓ [39m[90mInterpolations[39m
   1528.8 ms[32m  ✓ [39m[90mSciMLBase → SciMLBaseChainRulesCoreExt[39m
   7832.1 ms[32m  ✓ [39m[90mDistributions[39m
    861.9 ms[32m  ✓ [39m[90mDistributions → DistributionsChainRulesCoreExt[39m
   2864.4 ms[32m  ✓ [39m[90mMeshes[39m
   7147.0 ms[32m  ✓ [39mTestParticle
  28 dependencies successfully precompiled in 26 seconds. 103 already precompiled.
  [33m1[39m dependency precompiled but a different version is currently loaded. Restart julia to access the new version. Otherwise, loading dependents of this package may trigger further precompilation to work with the unexpected version.
[92m[1mPrecompiling[22m[39m OrdinaryDiffEq...
    880.8 ms[32m  ✓ [39m[90mIntelOpenMP_jll[39m
   1461.7 ms[32m  ✓ [39m[90mFiniteDiff → FiniteDiffStaticArraysExt[39m
   1721.0 ms[32m  ✓ [39m[90mCPUSummary[39m
   2236.0 ms[32m  ✓ [39m[90mStaticArrayInterface[39m
   1780.0 ms[32m  ✓ [39m[90mArnoldiMethod[39m
    962.1 ms[32m  ✓ [39m[90mPolyesterWeave[39m
   2270.1 ms[32m  ✓ [39m[90mLazyArrays → LazyArraysStaticArraysExt[39m
   1965.1 ms[32m  ✓ [39m[90mMKL_jll[39m
   1247.5 ms[32m  ✓ [39m[90mStaticArrayInterface → StaticArrayInterfaceOffsetArraysExt[39m
    889.7 ms[32m  ✓ [39m[90mCloseOpenIntervals[39m
   1497.4 ms[32m  ✓ [39m[90mStaticArrayInterface → StaticArrayInterfaceStaticArraysExt[39m
   1024.3 ms[32m  ✓ [39m[90mLayoutPointers[39m
   5986.0 ms[32m  ✓ [39m[90mForwardDiff[39m
   1917.0 ms[32m  ✓ [39m[90mStrideArraysCore[39m
   1373.7 ms[32m  ✓ [39m[90mForwardDiff → ForwardDiffStaticArraysExt[39m
   1399.3 ms[32m  ✓ [39m[90mPreallocationTools[39m
   1210.4 ms[32m  ✓ [39m[90mPolyester[39m
   1683.3 ms[32m  ✓ [39m[90mNLSolversBase[39m
   1109.3 ms[32m  ✓ [39m[90mFastBroadcast[39m
   6642.5 ms[32m  ✓ [39m[90mGraphs[39m
   1318.0 ms[32m  ✓ [39m[90mRecursiveArrayTools → RecursiveArrayToolsFastBroadcastExt[39m
   1450.1 ms[32m  ✓ [39m[90mVertexSafeGraphs[39m
   3005.6 ms[32m  ✓ [39m[90mLineSearches[39m
   2768.7 ms[32m  ✓ [39m[90mSparseDiffTools[39m
  12544.6 ms[32m  ✓ [39m[90mVectorizationBase[39m
   1490.1 ms[32m  ✓ [39m[90mSLEEFPirates[39m
   7681.6 ms[32m  ✓ [39m[90mDiffEqBase[39m
  43693.8 ms[32m  ✓ [39m[90mLoopVectorization[39m
   1916.9 ms[32m  ✓ [39m[90mLoopVectorization → SpecialFunctionsExt[39m
   2358.0 ms[32m  ✓ [39m[90mTriangularSolve[39m
  48781.8 ms[32m  ✓ [39m[90mSimpleNonlinearSolve[39m
   2325.2 ms[32m  ✓ [39m[90mSimpleNonlinearSolve → SimpleNonlinearSolveStaticArraysExt[39m
   9235.7 ms[32m  ✓ [39m[90mRecursiveFactorization[39m
  76765.1 ms[32m  ✓ [39m[90mExponentialUtilities[39m
  34376.6 ms[32m  ✓ [39m[90mLinearSolve[39m
   1935.6 ms[32m  ✓ [39m[90mLinearSolve → LinearSolveRecursiveArrayToolsExt[39m
  90560.9 ms[32m  ✓ [39m[90mNonlinearSolve[39m
  74759.3 ms[32m  ✓ [39mOrdinaryDiffEq
  38 dependencies successfully precompiled in 277 seconds. 125 already precompiled.
[92m[1mPrecompiling[22m[39m DiffEqBaseUnitfulExt...
   1167.5 ms[32m  ✓ [39m[90mDiffEqBase → DiffEqBaseUnitfulExt[39m
  1 dependency successfully precompiled in 1 seconds. 111 already precompiled.
[92m[1mPrecompiling[22m[39m DiffEqBaseChainRulesCoreExt...
   1052.1 ms[32m  ✓ [39m[90mDiffEqBase → DiffEqBaseChainRulesCoreExt[39m
  1 dependency successfully precompiled in 1 seconds. 114 already precompiled.
[92m[1mPrecompiling[22m[39m DiffEqBaseDistributionsExt...
    877.9 ms[32m  ✓ [39m[90mDistributions → DistributionsTestExt[39m
   1109.1 ms[32m  ✓ [39m[90mDiffEqBase → DiffEqBaseDistributionsExt[39m
  2 dependencies successfully precompiled in 1 seconds. 123 already precompiled.
[92m[1mPrecompiling[22m[39m ForwardDiffExt...
   1062.1 ms[32m  ✓ [39m[90mLoopVectorization → ForwardDiffExt[39m
  1 dependency successfully precompiled in 1 seconds. 77 already precompiled.
text/plaincell_id$bf6d18d0-ee99-4a2e-badb-c1f42071903bkwargsidPlutoRunner_d1acb81efileP/home/runner/.julia/packages/Pluto/u5fFh/src/runner/PlutoRunner/src/io/stdout.jlgroupstdoutlevelLogLevel(-555)running¦outputbodymimetext/plainrootassigneelast_run_timestampA&kpersist_js_state·has_pluto_hook_features§cell_id$bf6d18d0-ee99-4a2e-badb-c1f42071903bdepends_on_disabled_cells§runtime   H@Xpublished_object_keysdepends_on_skipped_cells§errored$05aee60b-fdb4-4856-a1cd-a0dbb470bbb3queued¤logsrunning¦outputbody<div class="markdown"><h3 id="Preliminary-Results">Preliminary Results</h3>
<ul>
<li><p>Thermal O&#43; population</p>
</li>
</ul>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/impact_flux_G2_thermal_O_idealMHD.png' type='image/png'></img>
<ul>
<li><p>Energetic H&#43; population</p>
</li>
</ul>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/impact_flux_G2_idealMHD_H_bin1-5-9.png' type='image/png'></img>
</div>mimetext/htmlrootassigneelast_run_timestampA&꠲persist_js_state·has_pluto_hook_features§cell_id$05aee60b-fdb4-4856-a1cd-a0dbb470bbb3depends_on_disabled_cells§runtime 
="published_object_keysdepends_on_skipped_cells§errored$36be1db4-39d5-4067-b42d-53b669bf4ae3queued¤logsrunning¦outputbody_<div class="markdown"><h2 id="Motion-of-Charged-Particles">Motion of Charged Particles</h2>
<h3 id="Non-relativistic-case">Non-relativistic case</h3>
<p class="tex">$$m\frac&#123;\mathrm&#123;d&#125;\mathbf&#123;v&#125;&#125;&#123;\mathrm&#123;d&#125;t&#125; &#61; q&#40;\mathbf&#123;E&#125; &#43; \mathbf&#123;v&#125;\times\mathbf&#123;B&#125;&#41; \tag&#123;1&#125;$$</p>
<h3 id="Relativistic-case">Relativistic case</h3>
<p>The four-dimensional momentum equation satisfying Lorentz covariance is</p>
<p class="tex">$$\frac&#123;\mathrm&#123;d&#125;p^\mu&#125;&#123;\mathrm&#123;d&#125;\tau&#125; &#61; \gamma qF^&#123;\mu \nu&#125;v_\nu \tag&#123;2&#125;$$</p>
<p>where <span class="tex">$\gamma &#61; 1/\sqrt&#123;1-v^2/c^2&#125;$</span> is the Lorentz factor， <span class="tex">$\tau$</span> is the proper time， <span class="tex">$p^\mu &#61; \gamma m v^\mu$</span> is the four-dimensional momentum, and <span class="tex">$F^&#123;\mu\nu&#125;$</span> is the electromagnetic tensor。</p>
<p>There are two forms that can be used in numerical computation after simplification:</p>
<p class="tex">$$\frac&#123;\mathrm&#123;d&#125;&#40;\gamma v^i&#41;&#125;&#123;\mathrm&#123;d&#125;t&#125; &#61; \frac&#123;q&#125;&#123;m&#125;&#40;E^i&#43;\epsilon^&#123;ijk&#125;v_j B_k&#41; \tag&#123;3&#125;$$</p>
<p>or</p>
<p class="tex">$$\frac&#123;\mathrm&#123;d&#125;v^i&#125;&#123;\mathrm&#123;d&#125;t&#125; &#61; \frac&#123;q&#125;&#123;m \gamma^3&#125;&#40;E^i&#43;\epsilon^&#123;ijk&#125;v_j B_k&#41; \tag&#123;4&#125;$$</p>
<p>Currently we only include Eq.&#40;4&#41; in TestParticle.jl. This needs further testing.</p>
</div>mimetext/htmlrootassigneelast_run_timestampA&~h}8persist_js_state·has_pluto_hook_features§cell_id$36be1db4-39d5-4067-b42d-53b669bf4ae3depends_on_disabled_cells§runtime õpublished_object_keysdepends_on_skipped_cells§errored$d50e4350-49ac-4203-870b-903a8801156equeued¤logsrunning¦outputbody,<button onclick='present()'>present</button>mimetext/htmlrootassigneelast_run_timestampA&~h|persist_js_state·has_pluto_hook_features§cell_id$d50e4350-49ac-4203-870b-903a8801156edepends_on_disabled_cells§runtime gpublished_object_keysdepends_on_skipped_cells§errored$45b02635-24ef-4a95-adbd-f6fee4413f21queued¤logsrunning¦outputbody<div class="markdown"><p class="tex">$$\mu&#61;0.7,\,l_0&#61;4/nx$$</p>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/CR1_mu0.7_l4.png' type='image/png'></img>
</div>mimetext/htmlrootassigneelast_run_timestampA&|persist_js_state·has_pluto_hook_features§cell_id$45b02635-24ef-4a95-adbd-f6fee4413f21depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$84dcadfc-4b85-48fc-b7a5-5bbc71d66b7fqueued¤logsrunning¦outputbody/<div class="markdown"><h2 id="Demos">Demos</h2>
<h3 id="Electron-and-Ion-Motion">Electron and Ion Motion</h3>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/TestParticlePresentation/master/double_trajectories_static_B.png' type='image/png'></img>
<h3 id="Grad-B-and-Curvature-Drift">Grad-B and Curvature Drift</h3>
<img controls='' src='https://henry2004y.github.io/TestParticle.jl/dev/examples/basics/demo_curvature_B-4.png' type='image/png'></img>
<h3 id="Finite-Larmor-Radius-Effect">Finite-Larmor-Radius Effect</h3>
<img controls='' src='https://henry2004y.github.io/TestParticle.jl/dev/examples/basics/demo_FLR-4.png' type='image/png'></img>
<h3 id="Polarization-Drift">Polarization Drift</h3>
<img controls='' src='https://henry2004y.github.io/TestParticle.jl/dev/examples/basics/demo_polarization_drift-4.png' type='image/png'></img>
<h3 id="Adiabatic-motion">Adiabatic motion</h3>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/TestParticlePresentation/master/adiabatic_trajectory_dipole.png' type='image/png'></img>
</div>mimetext/htmlrootassigneelast_run_timestampA&ܝpersist_js_state·has_pluto_hook_features§cell_id$84dcadfc-4b85-48fc-b7a5-5bbc71d66b7fdepends_on_disabled_cells§runtime 3&published_object_keysdepends_on_skipped_cells§errored$75936fde-d5a7-4920-a4ca-a626a2e90123queued¤logsrunning¦outputbody9<div class="markdown"><h2 id="What-Are-Test-Particles?">What Are Test Particles?</h2>
<p>A test particle model describes non-self-consistent field-particle interactions. A complete description of the particle phase space trajectory not only needs to reflect the effect of the field on the particle, but also needs to reflect the effect of the particle on the field.</p>
<p><strong>Field</strong> &lt;–&gt; <strong>Particle</strong></p>
<p>However, as an approximate treatment, we can ignore the feedback of a small number of particles on the field and only focus on the effect of the field on the particle.</p>
<p><strong>Field</strong> –&gt; <strong>Particle</strong></p>
<img controls='' src='https://www.schoolphysics.co.uk/age14-16/Electricity%20and%20magnetism/Current%20electricity/text/Particles_and_fields/images/2.png' type='image/png'></img>
<h2 id="Applications-of-Test-Particle-Models">Applications of Test Particle Models</h2>
<ul>
<li><p>Studying charged particle trajectories under EM fields.</p>
</li>
<li><p>Explaining collective behaviors of particles controlled by fields.</p>
</li>
<li><p>Substituting expensive laboratory experiments.</p>
</li>
</ul>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/TestParticlePresentation/master/single_trajectory_static_B.png' type='image/png'></img>
</div>mimetext/htmlrootassigneelast_run_timestampA&Opersist_js_state·has_pluto_hook_features§cell_id$75936fde-d5a7-4920-a4ca-a626a2e90123depends_on_disabled_cells§runtimeZpublished_object_keysdepends_on_skipped_cells§errored$0906fe4a-8f2d-4e6d-8726-97bc493da577queued¤logsrunning¦outputbodyl<div class="markdown"><h3 id="Scales-in-the-System">Scales in the System</h3>
<ul>
<li><p>Numerical dissipation scale</p>
</li>
<li><p>Injection scale</p>
</li>
</ul>
<p class="tex">$$\mu&#61;0.1,\,l_0&#61;4/nx$$</p>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/CR3_mu0.1_l4.png' type='image/png'></img>
</div>mimetext/htmlrootassigneelast_run_timestampA&3persist_js_state·has_pluto_hook_features§cell_id$0906fe4a-8f2d-4e6d-8726-97bc493da577depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$db26a01b-b01c-41dc-b23a-02dbb3867655queued¤logsrunning¦outputbodyK<div class="markdown"><h2 id="Demo:-Tracing-Electrons-in-Mars&#39;-Crustal-Field">Demo: Tracing Electrons in Mars&#39; Crustal Field</h2>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/mars_electron_dispersion.png' type='image/png'></img>
<p>Goal: Given Mars&#39; crustal field and the locations of the observed electrons, can we determine their source location?</p>
<p>Unknown factors:</p>
<ul>
<li><p>Exact pitch angles</p>
</li>
<li><p>Electric field</p>
</li>
</ul>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/mars_crustal_field_pass_count.png' type='image/png'></img>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/electron_trajectory_3eV_10eV.png' type='image/png'></img>
</div>mimetext/htmlrootassigneelast_run_timestampA&mpersist_js_state·has_pluto_hook_features§cell_id$db26a01b-b01c-41dc-b23a-02dbb3867655depends_on_disabled_cells§runtime j*published_object_keysdepends_on_skipped_cells§errored$47fd7e19-9859-404e-a0e0-be356eef83b0queued¤logsrunning¦outputbody<div class="markdown"><p class="tex">$$\mu&#61;0.7,\,l_0&#61;16/nx$$</p>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/CR1_mu0.7_l16.png' type='image/png'></img>
</div>mimetext/htmlrootassigneelast_run_timestampA&#persist_js_state·has_pluto_hook_features§cell_id$47fd7e19-9859-404e-a0e0-be356eef83b0depends_on_disabled_cells§runtime epublished_object_keysdepends_on_skipped_cells§errored$b3e0e1b5-4f11-41b4-b2e3-fdb36c6c8b20queued¤logsrunning¦outputbody<div class="markdown"><h2 id="Demo:-Tracing-Particles-in-MHD-Turbulence">Demo: Tracing Particles in MHD Turbulence</h2>
<img controls='' src='https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/turbulence_mhd_bx_cut.png' type='image/png'></img>
<p class="tex">$$\begin&#123;aligned&#125;
B_\mathrm&#123;in-plane&#125; &amp;&#61; 1 \\
B_z &amp;&#61; 4 \\
U_\mathrm&#123;in-plane&#125; &amp;&#61; 1 \\
U_z &amp;&#61; 0 \\
\end&#123;aligned&#125;$$</p>
</div>mimetext/htmlrootassigneelast_run_timestampA&ϰpersist_js_state·has_pluto_hook_features§cell_id$b3e0e1b5-4f11-41b4-b2e3-fdb36c6c8b20depends_on_disabled_cells§runtime 1published_object_keysdepends_on_skipped_cells§errored$96a6b000-b558-11ee-1024-4d2ef81f5ad0queued¤logsrunning¦outputbody٨<div class="markdown"><h1 id="TestParticle.jl:-A-New-Tool-for-An-Old-Problem">TestParticle.jl: A New Tool for An Old Problem</h1>
<p>2024/01/31 Hongyang Zhou</p>
</div>mimetext/htmlrootassigneelast_run_timestampA&~h}persist_js_state·has_pluto_hook_features§cell_id$96a6b000-b558-11ee-1024-4d2ef81f5ad0depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$021d3bb6-ceb6-460a-a56e-c8b094f3d932queued¤logsrunning¦outputbody<div class="markdown"><h2 id="The-Goal-of-TestParticle.jl">The Goal of TestParticle.jl</h2>
<ol>
<li><p>Simplicity: Users only need to provide field information and particle initial conditions</p>
</li>
<li><p>Generality: Compatible with general models, can run independently</p>
</li>
<li><p>Efficiency: The efficiency of C</p>
</li>
<li><p>Visuality: Connected to powerful visualization tools</p>
</li>
</ol>
</div>mimetext/htmlrootassigneelast_run_timestampA&~h~kpersist_js_state·has_pluto_hook_features§cell_id$021d3bb6-ceb6-460a-a56e-c8b094f3d932depends_on_disabled_cells§runtime published_object_keysdepends_on_skipped_cells§errored$e8daa564-73a1-4306-87ab-7334cb44f96dqueued¤logsrunning¦outputbody<div class="markdown"><h2 id="Design">Design</h2>
<h3 id="DifferentialEquations.jl-Interface">DifferentialEquations.jl Interface</h3>
<pre><code class="language-julia">param &#61; prepare&#40;E, B, species&#41;
prob &#61; ODEProblem&#40;trace&#33;, stateinit, tspan, param&#41;
sol &#61; solve&#40;prob, algorithm&#41;</code></pre>
<ul>
<li><p>Analytical or numerical field?</p>
</li>
<li><p>Contains external field &#40;e.g. gravity&#41;?</p>
</li>
<li><p>Normalized unit system?</p>
</li>
<li><p>Time-dependent?</p>
</li>
<li><p>Relativistic?</p>
</li>
</ul>
<p>By taking advantage of Julia&#39;s multiple dispatch property, we come up with 4 ODE functions:</p>
<ul>
<li><p><code>trace&#33;</code></p>
</li>
<li><p><code>trace_relativistic&#33;</code></p>
</li>
<li><p><code>trace_normalized&#33;</code></p>
</li>
<li><p><code>trace_relativistic_normalized&#33;</code></p>
</li>
</ul>
<h3 id="Energy-Conservation">Energy Conservation</h3>
<p>We need to make sure that the energy is conserved in a B-only tracing for validity. In classical mechanics, Hamiltonian&#39;s equations naturally have that the solutions reside on a symplectic manifold in phase space, with the natural splitting being the position and momentum components. <em>For the true Hamiltonian solution, that phase space path is constant energy</em>.</p>
<p>For example, the most commonly used solver in DifferentialEquations.jl, <code>Tsit5&#40;&#41;</code> &#40;adaptive 4/5th order Runge-Kutta method&#41;, does not conserve energy well. The following shows the test result of a proton in a static magnetic field gyrating for 304 cycles. All adaptive timestepping schemes from DifferentialEquations.jl use a relative tolerence of 1e-3 and an absolute tolerence of 1e-6.</p>
<table><tr><th align="right">Scheme</th><th align="right">Energy difference ratio</th><th align="right">Time &#91;ms&#93;</th><th align="right">Memory &#91;MiB&#93;</th><th align="right">fixed time step</th></tr><tr><td align="right"><strong>Boris</strong></td><td align="right">0&#37;</td><td align="right">0.2</td><td align="right">0.047</td><td align="right">true</td></tr><tr><td align="right"><strong>ImplicitMidpoint</strong></td><td align="right">0&#37;</td><td align="right">6.1</td><td align="right">2.974</td><td align="right">true</td></tr><tr><td align="right"><strong>SSPSDIRK2</strong></td><td align="right">0&#37;</td><td align="right">11.7</td><td align="right">4.090</td><td align="right">true</td></tr><tr><td align="right">Vern8</td><td align="right">0.17&#37;</td><td align="right">0.9</td><td align="right">1.707</td><td align="right">false</td></tr><tr><td align="right">RosenbrockW6S4OS</td><td align="right">0.23&#37;</td><td align="right">11.5</td><td align="right">3.464</td><td align="right">true</td></tr><tr><td align="right">Vern9</td><td align="right">-0.59&#37;</td><td align="right">1.1</td><td align="right">1.662</td><td align="right">false</td></tr><tr><td align="right">Trapezoid</td><td align="right">1.14&#37;</td><td align="right">20.2</td><td align="right">5.088</td><td align="right">false</td></tr><tr><td align="right">Vern6</td><td align="right">-5.36&#37;</td><td align="right">1.1</td><td align="right">2.036</td><td align="right">false</td></tr><tr><td align="right">Tsit5</td><td align="right">20.59&#37;</td><td align="right">1.2</td><td align="right">2.309</td><td align="right">false</td></tr><tr><td align="right">BS3</td><td align="right">-89.73&#37;</td><td align="right">2.6</td><td align="right">3.503</td><td align="right">false</td></tr></table>
<h3 id="Native-Boris-Solver">Native Boris Solver</h3>
<ul>
<li><p><code>trace_trajectory</code></p>
</li>
</ul>
<p>The classical Boris method is not a general ODE solver, but designed specifically for the Lorentz equation with the symmetry of the EM fields.</p>
<pre><code class="language-julia">param &#61; prepare&#40;E, B, species&#61;Electron&#41;
prob &#61; TraceProblem&#40;stateinit, tspan, param&#41;
sol &#61; trace_trajectory&#40;prob; dt, savestepinterval&#41;</code></pre>
<p>This method is 2nd order accurate in space. A fixed <code>dt</code> is required to conserve phase space volume, even though it is not a symplectic method &#40;<a href="https://doi.org/10.1063/1.4818428">Qin&#43; 2013</a>&#41;. It is the de facto algorithm for particle pusher after being proposed in the 1960s. However, the phase error may still be an issue.</p>
<h3 id="Implementation:-Analytic-or-Numerical-Fields?">Implementation: Analytic or Numerical Fields?</h3>
<ul>
<li><p>Analytic –&gt; <code>Field&#40;F&#41;</code></p>
</li>
<li><p>Numerical –&gt; Needs interpolation</p>
</li>
</ul>
<pre><code class="language-julia">function getinterp&#40;A, gridx, gridy, gridz, order::Int&#61;1, bc::Int&#61;1&#41;
   @assert size&#40;A,1&#41; &#61;&#61; 3 &amp;&amp; ndims&#40;A&#41; &#61;&#61; 4 &quot;Inconsistent 3D force field and grid&#33;&quot;

   Ax &#61; @view A&#91;1,:,:,:&#93;
   Ay &#61; @view A&#91;2,:,:,:&#93;
   Az &#61; @view A&#91;3,:,:,:&#93;

   itpx, itpy, itpz &#61; _getinterp&#40;Ax, Ay, Az, order, bc&#41;

   interpx &#61; scale&#40;itpx, gridx, gridy, gridz&#41;
   interpy &#61; scale&#40;itpy, gridx, gridy, gridz&#41;
   interpz &#61; scale&#40;itpz, gridx, gridy, gridz&#41;

   # Return field value at a given location.
   function get_field&#40;xu&#41;
      r &#61; @view xu&#91;1:3&#93;

      return SA&#91;interpx&#40;r...&#41;, interpy&#40;r...&#41;, interpz&#40;r...&#41;&#93;
   end

   return get_field
end</code></pre>
</div>mimetext/htmlrootassigneelast_run_timestampA&~hpersist_js_state·has_pluto_hook_features§cell_id$e8daa564-73a1-4306-87ab-7334cb44f96ddepends_on_disabled_cells§runtime 0bhpublished_object_keysdepends_on_skipped_cells§errored±cell_dependencies $081ce252-d083-4f03-a5bc-a4b171d222bcprecedence_heuristic	cell_id$081ce252-d083-4f03-a5bc-a4b171d222bcdownstream_cells_mapupstream_cells_map@md_strgetindex$e73e1a00-3706-42e1-acd1-ebc8b2b95c62precedence_heuristic	cell_id$e73e1a00-3706-42e1-acd1-ebc8b2b95c62downstream_cells_mapBparamx0tspanstateinitsolEprobv0upstream_cells_mapProtonODEProblemprepareVern9solveSAtrace!$d8d1dc93-44e7-466f-93fe-a9b427368944precedence_heuristic	cell_id$d8d1dc93-44e7-466f-93fe-a9b427368944downstream_cells_mapupstream_cells_map@md_strResourcegetindex$9c31a2c5-e0c7-4891-ad45-7a0e10012bd8precedence_heuristic	cell_id$9c31a2c5-e0c7-4891-ad45-7a0e10012bd8downstream_cells_mapupstream_cells_map@md_strgetindex$9643aa92-18fe-4850-a246-8ad134c085e8precedence_heuristic	cell_id$9643aa92-18fe-4850-a246-8ad134c085e8downstream_cells_mapupstream_cells_map@md_strgetindex$45a18eea-80c0-4aa4-86d4-c25f90df9303precedence_heuristic	cell_id$45a18eea-80c0-4aa4-86d4-c25f90df9303downstream_cells_mapupstream_cells_map@md_strgetindex$85c0b164-b6e0-43f5-a458-939b4fd7dddeprecedence_heuristic	cell_id$85c0b164-b6e0-43f5-a458-939b4fd7dddedownstream_cells_mapupstream_cells_map@md_strResourcegetindex$b7244973-218a-4bb6-8a8f-95f84a8fb225precedence_heuristic	cell_id$b7244973-218a-4bb6-8a8f-95f84a8fb225downstream_cells_mapupstream_cells_map@md_strResource=>getindex$d058eddf-a8b1-453b-a440-885a3da0a1a0precedence_heuristic	cell_id$d058eddf-a8b1-453b-a440-885a3da0a1a0downstream_cells_mapupstream_cells_mapTableOfContents$72412346-af0c-49dc-8c0d-c5b4fe97429bprecedence_heuristic	cell_id$72412346-af0c-49dc-8c0d-c5b4fe97429bdownstream_cells_mapupstream_cells_map@md_strResourcegetindex$bf6d18d0-ee99-4a2e-badb-c1f42071903bprecedence_heuristiccell_id$bf6d18d0-ee99-4a2e-badb-c1f42071903bdownstream_cells_mapStaticArraysTestParticlePlutoUIOrdinaryDiffEqupstream_cells_map$05aee60b-fdb4-4856-a1cd-a0dbb470bbb3precedence_heuristic	cell_id$05aee60b-fdb4-4856-a1cd-a0dbb470bbb3downstream_cells_mapupstream_cells_map@md_strResourcegetindex$36be1db4-39d5-4067-b42d-53b669bf4ae3precedence_heuristic	cell_id$36be1db4-39d5-4067-b42d-53b669bf4ae3downstream_cells_mapupstream_cells_map@md_strgetindex$d50e4350-49ac-4203-870b-903a8801156eprecedence_heuristic	cell_id$d50e4350-49ac-4203-870b-903a8801156edownstream_cells_mapupstream_cells_mapBaseBase.Docs.HTML@html_str$45b02635-24ef-4a95-adbd-f6fee4413f21precedence_heuristic	cell_id$45b02635-24ef-4a95-adbd-f6fee4413f21downstream_cells_mapupstream_cells_map@md_strResourcegetindex$84dcadfc-4b85-48fc-b7a5-5bbc71d66b7fprecedence_heuristic	cell_id$84dcadfc-4b85-48fc-b7a5-5bbc71d66b7fdownstream_cells_mapupstream_cells_map@md_strResourcegetindex$75936fde-d5a7-4920-a4ca-a626a2e90123precedence_heuristic	cell_id$75936fde-d5a7-4920-a4ca-a626a2e90123downstream_cells_mapupstream_cells_map@md_strResourcegetindex$0906fe4a-8f2d-4e6d-8726-97bc493da577precedence_heuristic	cell_id$0906fe4a-8f2d-4e6d-8726-97bc493da577downstream_cells_mapupstream_cells_map@md_strResourcegetindex$db26a01b-b01c-41dc-b23a-02dbb3867655precedence_heuristic	cell_id$db26a01b-b01c-41dc-b23a-02dbb3867655downstream_cells_mapupstream_cells_map@md_strResourcegetindex$47fd7e19-9859-404e-a0e0-be356eef83b0precedence_heuristic	cell_id$47fd7e19-9859-404e-a0e0-be356eef83b0downstream_cells_mapupstream_cells_map@md_strResourcegetindex$b3e0e1b5-4f11-41b4-b2e3-fdb36c6c8b20precedence_heuristic	cell_id$b3e0e1b5-4f11-41b4-b2e3-fdb36c6c8b20downstream_cells_mapupstream_cells_map@md_strResourcegetindex$96a6b000-b558-11ee-1024-4d2ef81f5ad0precedence_heuristic	cell_id$96a6b000-b558-11ee-1024-4d2ef81f5ad0downstream_cells_mapupstream_cells_map@md_strgetindex$021d3bb6-ceb6-460a-a56e-c8b094f3d932precedence_heuristic	cell_id$021d3bb6-ceb6-460a-a56e-c8b094f3d932downstream_cells_mapupstream_cells_map@md_strgetindex$e8daa564-73a1-4306-87ab-7334cb44f96dprecedence_heuristic	cell_id$e8daa564-73a1-4306-87ab-7334cb44f96ddownstream_cells_mapupstream_cells_map@md_strgetindexcell_execution_order $bf6d18d0-ee99-4a2e-badb-c1f42071903b$d50e4350-49ac-4203-870b-903a8801156e$d058eddf-a8b1-453b-a440-885a3da0a1a0$96a6b000-b558-11ee-1024-4d2ef81f5ad0$75936fde-d5a7-4920-a4ca-a626a2e90123$36be1db4-39d5-4067-b42d-53b669bf4ae3$45a18eea-80c0-4aa4-86d4-c25f90df9303$021d3bb6-ceb6-460a-a56e-c8b094f3d932$e8daa564-73a1-4306-87ab-7334cb44f96d$e73e1a00-3706-42e1-acd1-ebc8b2b95c62$84dcadfc-4b85-48fc-b7a5-5bbc71d66b7f$b7244973-218a-4bb6-8a8f-95f84a8fb225$db26a01b-b01c-41dc-b23a-02dbb3867655$b3e0e1b5-4f11-41b4-b2e3-fdb36c6c8b20$9c31a2c5-e0c7-4891-ad45-7a0e10012bd8$0906fe4a-8f2d-4e6d-8726-97bc493da577$85c0b164-b6e0-43f5-a458-939b4fd7ddde$45b02635-24ef-4a95-adbd-f6fee4413f21$47fd7e19-9859-404e-a0e0-be356eef83b0$d8d1dc93-44e7-466f-93fe-a9b427368944$72412346-af0c-49dc-8c0d-c5b4fe97429b$9643aa92-18fe-4850-a246-8ad134c085e8$081ce252-d083-4f03-a5bc-a4b171d222bc$05aee60b-fdb4-4856-a1cd-a0dbb470bbb3last_hot_reload_time        shortpathtestparticle_202401.jlprocess_statusreadypathJ/home/runner/work/pluto_playground/pluto_playground/testparticle_202401.jlpluto_versionv0.20.13last_save_timeA&~h^cell_order $d50e4350-49ac-4203-870b-903a8801156e$bf6d18d0-ee99-4a2e-badb-c1f42071903b$d058eddf-a8b1-453b-a440-885a3da0a1a0$96a6b000-b558-11ee-1024-4d2ef81f5ad0$75936fde-d5a7-4920-a4ca-a626a2e90123$36be1db4-39d5-4067-b42d-53b669bf4ae3$45a18eea-80c0-4aa4-86d4-c25f90df9303$021d3bb6-ceb6-460a-a56e-c8b094f3d932$e8daa564-73a1-4306-87ab-7334cb44f96d$e73e1a00-3706-42e1-acd1-ebc8b2b95c62$84dcadfc-4b85-48fc-b7a5-5bbc71d66b7f$b7244973-218a-4bb6-8a8f-95f84a8fb225$db26a01b-b01c-41dc-b23a-02dbb3867655$b3e0e1b5-4f11-41b4-b2e3-fdb36c6c8b20$9c31a2c5-e0c7-4891-ad45-7a0e10012bd8$0906fe4a-8f2d-4e6d-8726-97bc493da577$85c0b164-b6e0-43f5-a458-939b4fd7ddde$45b02635-24ef-4a95-adbd-f6fee4413f21$47fd7e19-9859-404e-a0e0-be356eef83b0$d8d1dc93-44e7-466f-93fe-a9b427368944$72412346-af0c-49dc-8c0d-c5b4fe97429b$9643aa92-18fe-4850-a246-8ad134c085e8$081ce252-d083-4f03-a5bc-a4b171d222bc$05aee60b-fdb4-4856-a1cd-a0dbb470bbb3published_objectsnbpkginstall_time_ns   TOW뗬instantiatedòinstalled_versionsStaticArrays1.9.1TestParticle0.4.1PlutoUI0.7.55OrdinaryDiffEq6.69.0terminal_outputsStaticArraysX
[0m[1mResolving...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mPkg operation failed. Fixing stdlib dependencies and trying again...
[33m[1m└ [22m[39m[90m@ GracefulPkg ~/.julia/packages/GracefulPkg/LmTcK/src/apply strategies.jl:92[39m

[0m[1mResolving...[22m
[90m===[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Project.toml`
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Manifest.toml`

[0m[1mInstantiating...[22m
[90m===[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_T0dgzP`
[92m[1mPrecompiling[22m[39m project...
  176 dependencies successfully precompiled in 358 seconds. 46 already precompiled.
  [33m1[39m dependency had output during precompilation:[33m
┌ [39mMKL_jll[33m
│  [39mDownloading artifact: MKL[33m
└  [39mnbpkg_syncX
[0m[1mResolving...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mPkg operation failed. Fixing stdlib dependencies and trying again...
[33m[1m└ [22m[39m[90m@ GracefulPkg ~/.julia/packages/GracefulPkg/LmTcK/src/apply strategies.jl:92[39m

[0m[1mResolving...[22m
[90m===[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Project.toml`
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Manifest.toml`

[0m[1mInstantiating...[22m
[90m===[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_T0dgzP`
[92m[1mPrecompiling[22m[39m project...
  176 dependencies successfully precompiled in 358 seconds. 46 already precompiled.
  [33m1[39m dependency had output during precompilation:[33m
┌ [39mMKL_jll[33m
│  [39mDownloading artifact: MKL[33m
└  [39mTestParticleX
[0m[1mResolving...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mPkg operation failed. Fixing stdlib dependencies and trying again...
[33m[1m└ [22m[39m[90m@ GracefulPkg ~/.julia/packages/GracefulPkg/LmTcK/src/apply strategies.jl:92[39m

[0m[1mResolving...[22m
[90m===[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Project.toml`
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Manifest.toml`

[0m[1mInstantiating...[22m
[90m===[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_T0dgzP`
[92m[1mPrecompiling[22m[39m project...
  176 dependencies successfully precompiled in 358 seconds. 46 already precompiled.
  [33m1[39m dependency had output during precompilation:[33m
┌ [39mMKL_jll[33m
│  [39mDownloading artifact: MKL[33m
└  [39mPlutoUIX
[0m[1mResolving...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mPkg operation failed. Fixing stdlib dependencies and trying again...
[33m[1m└ [22m[39m[90m@ GracefulPkg ~/.julia/packages/GracefulPkg/LmTcK/src/apply strategies.jl:92[39m

[0m[1mResolving...[22m
[90m===[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Project.toml`
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Manifest.toml`

[0m[1mInstantiating...[22m
[90m===[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_T0dgzP`
[92m[1mPrecompiling[22m[39m project...
  176 dependencies successfully precompiled in 358 seconds. 46 already precompiled.
  [33m1[39m dependency had output during precompilation:[33m
┌ [39mMKL_jll[33m
│  [39mDownloading artifact: MKL[33m
└  [39mOrdinaryDiffEqX
[0m[1mResolving...[22m
[90m===[39m
[33m[1m┌ [22m[39m[33m[1mWarning: [22m[39mPkg operation failed. Fixing stdlib dependencies and trying again...
[33m[1m└ [22m[39m[90m@ GracefulPkg ~/.julia/packages/GracefulPkg/LmTcK/src/apply strategies.jl:92[39m

[0m[1mResolving...[22m
[90m===[39m
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Project.toml`
[32m[1m  No Changes[22m[39m to `/tmp/jl_T0dgzP/Manifest.toml`

[0m[1mInstantiating...[22m
[90m===[39m

[0m[1mPrecompiling...[22m
[90m===[39m
[32m[1m  Activating[22m[39m project at `/tmp/jl_T0dgzP`
[92m[1mPrecompiling[22m[39m project...
  176 dependencies successfully precompiled in 358 seconds. 46 already precompiled.
  [33m1[39m dependency had output during precompilation:[33m
┌ [39mMKL_jll[33m
│  [39mDownloading artifact: MKL[33m
└  [39menabled÷restart_recommended_msgrestart_required_msgbusy_packageswaiting_for_permission,waiting_for_permission_but_probably_disabled«cell_inputs $081ce252-d083-4f03-a5bc-a4b171d222bccell_id$081ce252-d083-4f03-a5bc-a4b171d222bccodemd"""
### Procedures to obtain ion surface flux

1. Obtain magnetic field, density, velocity and current from the unstructured grid.

Requires a conversion from BATSRUS unstructured *.out format to VTK *.vtu format.

2. Interpolate MHD quantities onto a Cartesian grid and calculate the derived electric field including the convective term and Hall term.
```math
\mathbf{E} = -\sum_\alpha\mathbf{U}_\alpha\times\mathbf{B} + \frac{\mathbf{J}\times\mathbf{B}}{\sum_\alpha q_\alpha n_\alpha} - \frac{\nabla P_e}{\sum_\alpha q_\alpha n_\alpha} + \eta \mathbf{J}
```

This step is performed in ParaView with Python.

> It would be better to first convert the basic quantities from spherical coordinates to Cartesian coordinates, then calculate the derived electric field. If we first calculate the electric field and then interpolate to Cartesian coordinates, then around the inner boundary region there might be some artifacts due to interpolations.

3. Read the field info into TestParticle.jl.

4. Tracing with prescribed seeds.

### Potential Issues

* In some MHD models (e.g. [Jia+ 2009](https://doi.org/10.1029/2009JA014375)), there is an additional artificial resistivity.
* In [Jia+ 2009](https://doi.org/10.1029/2009JA014375)'s MHD model, the energetic population's contribution is included in the pressure term. Whether or not self-consistency is maintained is to be debated.
* E field near the inner boundary.

"""metadatashow_logsèdisabled®skip_as_script«code_folded$e73e1a00-3706-42e1-acd1-ebc8b2b95c62cell_id$e73e1a00-3706-42e1-acd1-ebc8b2b95c62codebegin
	# Magnetic field
	B(x) = SA[0.0, 0.0, 1e-8] # [nT]
	# Electric field
	E(x) = SA[0.0, 0.0, 0.0]  # [V/m]
	# Initial conditions
	x0 = [1.0, 0.0, 0.0]      # [m]
	v0 = [0.0, 1.0, 0.1]      # [m/s]
	stateinit = [x0..., v0...]
	tspan = (0, 18)           # [s]
	# Assemble particle + fields
	param = prepare(E, B, species=Proton)
	prob = ODEProblem(trace!, stateinit, tspan, param)
	# Trace trajectory and save positions & velocities
	sol = solve(prob, Vern9())
endmetadatashow_logsèdisabled®skip_as_script«code_folded$d8d1dc93-44e7-466f-93fe-a9b427368944cell_id$d8d1dc93-44e7-466f-93fe-a9b427368944codemmd"""
## WIP: Tracing Particles Near Ganymede

Ganymede is believed to have both an ionosphere and an exosphere besides the magnetosphere.

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/MIE_coupling.png"))

Our ultimate goal is to build a self-consistent magnetosphere-ionosphere-exosphere coupling model for Ganymede.
"""metadatashow_logsèdisabled®skip_as_script«code_folded$9c31a2c5-e0c7-4891-ad45-7a0e10012bd8cell_id$9c31a2c5-e0c7-4891-ad45-7a0e10012bd8codeAmd"""
Relativistic B-only tracing:

```math
\begin{aligned}
\frac{\mathrm{d}\mathbf{u}}{\mathrm{d}t} &= \frac{q}{\gamma m c}\mathbf{u}\times\mathbf{B} \\
\frac{\mathrm{d}\mathbf{r}}{\mathrm{d}t} &= \mathbf{u}
\end{aligned}
```

Initial particle seeds:
random location,
$u = c$,
pitch angle $\theta = \cos^{-1}(\mu_0),\,\text{where }\mu_0 = 0.1-0.7$,
random azimuthal angle.

The Lorentz equation in SI units is written as

```math
\frac{\mathrm{d}\mathbf{v}}{\mathrm{d}t} = \frac{q}{m}\left( \mathbf{v}\times\mathbf{B} + \mathbf{E} \right)
```

It can be normalized to 

```math
\frac{\mathrm{d}\mathbf{v}^\prime}{\mathrm{d}t^\prime} = \mathbf{v}^\prime\times\mathbf{B}^\prime + \mathbf{E}^\prime
```

with the following transformation

```math
\begin{aligned}
\mathbf{v} &= \mathbf{v}^\prime V_0 \\
\mathbf{x} &= \mathbf{x}^\prime l_0 \\
t &= t^\prime t_0 \\
\mathbf{B} &= \mathbf{B}^\prime B_0 \\
\mathbf{E} &= \mathbf{E}^\prime E_0 = \mathbf{E}^\prime V_0 B_0
\end{aligned}
```

where $V_0, l_0, t_0, B_0$ are prescribed parameters.

After the normalization, we can think of everything in the dimensionless natural units. If the magnetic field is homogeneous and the initial perpendicular velocity is 1, then the gyroradius is 1. MHD solutions are also dimensionless by nature. For the turbulence EM fields, we know their values and the spatial range. To make them more easily understandable, we can convert from the dimensionless MHD to natural units via

```math
\begin{aligned}
V_0 &= c \\
l_0 &= 4 / nx \\
t_0 &= l_0 / V_0 \\
B_0 &= \mathrm{norm}(B)
\end{aligned}
```

and

```julia
x = range(xmin, xmax, length=nx) / l₀ 
y = range(ymin, ymax, length=ny) / l₀
z = range(zmin, zmax, length=nz) / l₀
B ./= B₀
```

When the X extent is 1, then after the normalization, the x grid resolution becomes 1/4, which is a quarter of the gyroradius.
"""metadatashow_logsèdisabled®skip_as_script«code_folded$9643aa92-18fe-4850-a246-8ad134c085e8cell_id$9643aa92-18fe-4850-a246-8ad134c085e8codemd"""
> The surface flux is very sensitive to the seeding procedures. Placing a plane source in the upstream as in [Plainaki+ 2015, 2020] is deficient in capturing all the possible sources, which ends up in significantly underestimating ion sputtering.

### Stop Conditions

* Hitting the surface: $r_\mathrm{final} < 1.07\, R_G$

* Escaping from the outer boundary: $r_\mathrm{final} > 4\,R_G$
"""metadatashow_logsèdisabled®skip_as_script«code_folded$45a18eea-80c0-4aa4-86d4-c25f90df9303cell_id$45a18eea-80c0-4aa4-86d4-c25f90df9303codemd"""
## Julia Community Ecosystem

- `DifferentialEquations.jl` is one of the earliest and largest packages developed in the community. Among them, OrdinaryDiffEq is a general solver library for ordinary differential equations.

- `Interpolations.jl` is the most commonly used high-performance interpolation library in the community. It provides support for different grids, different precisions, and different algorithms.

- `StaticArrays.jl` is an optimization library for stack-allocated arrays in the community. It provides memory optimization for small fixed-size arrays that Julia itself does not currently support.

- `Meshes.jl` is a new library for different types of grids.

- `SpecialFunctions.jl` is a native Julia implementation of special mathematical functions.

- `Makie.jl` is a new generation of Julia native graphics library target at GPU rendering.

## Advantages of Julia's Open Source Community

- Lego-style combination, avoid reinventing the wheel
  - Individual abilities are limited
  - Taking advantage of the vast open-source algorithm library

- The function interface at the language level is very convenient to use
  - Support for generic types
  - Consideration for performance

- Collaboration with strangers
  - Julia has a large and active community, which makes it easy to find people to collaborate with. This can be a great way to learn new things and get feedback on your work.
"""metadatashow_logsèdisabled®skip_as_script«code_folded$85c0b164-b6e0-43f5-a458-939b4fd7dddecell_id$85c0b164-b6e0-43f5-a458-939b4fd7dddecodeَmd"""
$\mu=0.1,\,l_0=16/nx$

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/CR3_mu0.1_l16.png"))
"""metadatashow_logsèdisabled®skip_as_script«code_folded$b7244973-218a-4bb6-8a8f-95f84a8fb225cell_id$b7244973-218a-4bb6-8a8f-95f84a8fb225code$md"""
### Magnetospheric Ion Motion
- Spitzer orbit
- Gradient and curvature drifts
- Orbits near the tail reconnection site

$(Resource("https://raw.githubusercontent.com/henry2004y/TestParticlePresentation/master/electron_fixedtime_pm0.5RE_EGI_t1298.mp4", :autoplay => "", :loop => ""))
"""metadatashow_logsèdisabled®skip_as_script«code_folded$d058eddf-a8b1-453b-a440-885a3da0a1a0cell_id$d058eddf-a8b1-453b-a440-885a3da0a1a0codeTableOfContents()metadatashow_logsèdisabled®skip_as_script«code_folded$72412346-af0c-49dc-8c0d-c5b4fe97429bcell_id$72412346-af0c-49dc-8c0d-c5b4fe97429bcodemd"""
### Our Model

We use ideal MHD G2 spherical output as a starting point.

- G2 ideal MHD
- G2 Hall MHD
- G8 ideal MHD
- G8 Hall MHD

### Seeding

An important question is how to set seeds.

* Thermal population: using MHD values
* Energetic population: using observed differential flux, 10 logarithmic bins for sampling

$(Resource("https://agupubs.onlinelibrary.wiley.com/cms/asset/818da498-ee6b-4e80-9136-46d032b32092/jgra54295-fig-0002-m.jpg"))
"""metadatashow_logsèdisabled®skip_as_script«code_folded$bf6d18d0-ee99-4a2e-badb-c1f42071903bcell_id$bf6d18d0-ee99-4a2e-badb-c1f42071903bcodebbegin
    using TestParticle
    using OrdinaryDiffEq
    using StaticArrays
    using PlutoUI
endmetadatashow_logsèdisabled®skip_as_script«code_folded$05aee60b-fdb4-4856-a1cd-a0dbb470bbb3cell_id$05aee60b-fdb4-4856-a1cd-a0dbb470bbb3code]md"""
### Preliminary Results

* Thermal O+ population

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/impact_flux_G2_thermal_O_idealMHD.png"))

* Energetic H+ population

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/impact_flux_G2_idealMHD_H_bin1-5-9.png"))

"""metadatashow_logsèdisabled®skip_as_script«code_folded$36be1db4-39d5-4067-b42d-53b669bf4ae3cell_id$36be1db4-39d5-4067-b42d-53b669bf4ae3codemd"""

## Motion of Charged Particles

### Non-relativistic case

```math
m\frac{\mathrm{d}\mathbf{v}}{\mathrm{d}t} = q(\mathbf{E} + \mathbf{v}\times\mathbf{B}) \tag{1}
```

### Relativistic case

The four-dimensional momentum equation satisfying Lorentz covariance is

```math
\frac{\mathrm{d}p^\mu}{\mathrm{d}\tau} = \gamma qF^{\mu \nu}v_\nu \tag{2}
```

where $\gamma = 1/\sqrt{1-v^2/c^2}$ is the Lorentz factor， $\tau$ is the proper time， $p^\mu = \gamma m v^\mu$ is the four-dimensional momentum, and $F^{\mu\nu}$ is the electromagnetic tensor。

There are two forms that can be used in numerical computation after simplification:

```math
\frac{\mathrm{d}(\gamma v^i)}{\mathrm{d}t} = \frac{q}{m}(E^i+\epsilon^{ijk}v_j B_k) \tag{3}
```

or

```math
\frac{\mathrm{d}v^i}{\mathrm{d}t} = \frac{q}{m \gamma^3}(E^i+\epsilon^{ijk}v_j B_k) \tag{4}
```

Currently we only include Eq.(4) in TestParticle.jl. This needs further testing.
"""metadatashow_logsèdisabled®skip_as_script«code_folded$d50e4350-49ac-4203-870b-903a8801156ecell_id$d50e4350-49ac-4203-870b-903a8801156ecode2html"<button onclick='present()'>present</button>"metadatashow_logsèdisabled®skip_as_script«code_folded$45b02635-24ef-4a95-adbd-f6fee4413f21cell_id$45b02635-24ef-4a95-adbd-f6fee4413f21codeٌmd"""
$\mu=0.7,\,l_0=4/nx$

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/CR1_mu0.7_l4.png"))
"""metadatashow_logsèdisabled®skip_as_script«code_folded$84dcadfc-4b85-48fc-b7a5-5bbc71d66b7fcell_id$84dcadfc-4b85-48fc-b7a5-5bbc71d66b7fcodemd"""
## Demos

### Electron and Ion Motion
$(Resource("https://raw.githubusercontent.com/henry2004y/TestParticlePresentation/master/double_trajectories_static_B.png"))

### Grad-B and Curvature Drift

$(Resource("https://henry2004y.github.io/TestParticle.jl/dev/examples/basics/demo_curvature_B-4.png"))

### Finite-Larmor-Radius Effect

$(Resource("https://henry2004y.github.io/TestParticle.jl/dev/examples/basics/demo_FLR-4.png"))

### Polarization Drift
$(Resource("https://henry2004y.github.io/TestParticle.jl/dev/examples/basics/demo_polarization_drift-4.png"))

### Adiabatic motion
$(Resource("https://raw.githubusercontent.com/henry2004y/TestParticlePresentation/master/adiabatic_trajectory_dipole.png"))
"""metadatashow_logsèdisabled®skip_as_script«code_folded$75936fde-d5a7-4920-a4ca-a626a2e90123cell_id$75936fde-d5a7-4920-a4ca-a626a2e90123code
md"""

## What Are Test Particles?

A test particle model describes non-self-consistent field-particle interactions. A complete description of the particle phase space trajectory not only needs to reflect the effect of the field on the particle, but also needs to reflect the effect of the particle on the field.

**Field** <--> **Particle**

However, as an approximate treatment, we can ignore the feedback of a small number of particles on the field and only focus on the effect of the field on the particle.

**Field** --> **Particle**

$(Resource("https://www.schoolphysics.co.uk/age14-16/Electricity%20and%20magnetism/Current%20electricity/text/Particles_and_fields/images/2.png"))

## Applications of Test Particle Models

- Studying charged particle trajectories under EM fields.

- Explaining collective behaviors of particles controlled by fields.

- Substituting expensive laboratory experiments.

$(Resource("https://raw.githubusercontent.com/henry2004y/TestParticlePresentation/master/single_trajectory_static_B.png"))
"""metadatashow_logsèdisabled®skip_as_script«code_folded$0906fe4a-8f2d-4e6d-8726-97bc493da577cell_id$0906fe4a-8f2d-4e6d-8726-97bc493da577codemd"""
### Scales in the System

* Numerical dissipation scale
* Injection scale

$\mu=0.1,\,l_0=4/nx$

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/CR3_mu0.1_l4.png"))
"""metadatashow_logsèdisabled®skip_as_script«code_folded$db26a01b-b01c-41dc-b23a-02dbb3867655cell_id$db26a01b-b01c-41dc-b23a-02dbb3867655codebmd"""
## Demo: Tracing Electrons in Mars' Crustal Field

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/mars_electron_dispersion.png"))

Goal: Given Mars' crustal field and the locations of the observed electrons, can we determine their source location?

Unknown factors:

* Exact pitch angles
* Electric field

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/mars_crustal_field_pass_count.png"))

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/electron_trajectory_3eV_10eV.png"))

"""metadatashow_logsèdisabled®skip_as_script«code_folded$47fd7e19-9859-404e-a0e0-be356eef83b0cell_id$47fd7e19-9859-404e-a0e0-be356eef83b0codeَmd"""
$\mu=0.7,\,l_0=16/nx$

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/CR1_mu0.7_l16.png"))
"""metadatashow_logsèdisabled®skip_as_script«code_folded$b3e0e1b5-4f11-41b4-b2e3-fdb36c6c8b20cell_id$b3e0e1b5-4f11-41b4-b2e3-fdb36c6c8b20code(md"""
## Demo: Tracing Particles in MHD Turbulence

$(Resource("https://raw.githubusercontent.com/henry2004y/pluto_playground/master/figures/turbulence_mhd_bx_cut.png"))

```math
\begin{aligned}
B_\mathrm{in-plane} &= 1 \\
B_z &= 4 \\
U_\mathrm{in-plane} &= 1 \\
U_z &= 0 \\
\end{aligned}
```
"""metadatashow_logsèdisabled®skip_as_script«code_folded$96a6b000-b558-11ee-1024-4d2ef81f5ad0cell_id$96a6b000-b558-11ee-1024-4d2ef81f5ad0codeTmd"""
# TestParticle.jl: A New Tool for An Old Problem

2024/01/31 Hongyang Zhou
"""metadatashow_logsèdisabled®skip_as_script«code_folded$021d3bb6-ceb6-460a-a56e-c8b094f3d932cell_id$021d3bb6-ceb6-460a-a56e-c8b094f3d932code(md"""
## The Goal of TestParticle.jl

1. Simplicity: Users only need to provide field information and particle initial conditions

2. Generality: Compatible with general models, can run independently

3. Efficiency: The efficiency of C

4. Visuality: Connected to powerful visualization tools
"""metadatashow_logsèdisabled®skip_as_script«code_folded$e8daa564-73a1-4306-87ab-7334cb44f96dcell_id$e8daa564-73a1-4306-87ab-7334cb44f96dcode	md"""
## Design

### DifferentialEquations.jl Interface

```julia
param = prepare(E, B, species)
prob = ODEProblem(trace!, stateinit, tspan, param)
sol = solve(prob, algorithm)
```

- Analytical or numerical field?
- Contains external field (e.g. gravity)?
- Normalized unit system?
- Time-dependent?
- Relativistic?

By taking advantage of Julia's multiple dispatch property, we come up with 4 ODE functions:

- `trace!`
- `trace_relativistic!`
- `trace_normalized!`
- `trace_relativistic_normalized!`

### Energy Conservation

We need to make sure that the energy is conserved in a B-only tracing for validity.
In classical mechanics, Hamiltonian's equations naturally have that the solutions reside on a symplectic manifold in phase space, with the natural splitting being the position and momentum components. _For the true Hamiltonian solution, that phase space path is constant energy_.

For example, the most commonly used solver in DifferentialEquations.jl, `Tsit5()` (adaptive 4/5th order Runge-Kutta method), does not conserve energy well. The following shows the test result of a proton in a static magnetic field gyrating for 304 cycles. All adaptive timestepping schemes from DifferentialEquations.jl use a relative tolerence of 1e-3 and an absolute tolerence of 1e-6.

| Scheme    | Energy difference ratio |  Time [ms] | Memory [MiB] | fixed time step |
|-----------|-------------|---------|-----------|-----|
| **Boris**     | 0%      | 0.2  | 0.047  | true |
| **ImplicitMidpoint**     | 0%      | 6.1  | 2.974  | true |
| **SSPSDIRK2**  | 0%      |  11.7  | 4.090  | true |
| Vern8   | 0.17%  | 0.9  |  1.707  |  false |
| RosenbrockW6S4OS      | 0.23%  | 11.5  |  3.464  | true  |
| Vern9   | -0.59%  | 1.1  |  1.662  |  false |
| Trapezoid | 1.14% | 20.2  | 5.088  |  false |
| Vern6 | -5.36% | 1.1  |  2.036  | false |
| Tsit5 | 20.59% | 1.2  |  2.309  | false |
| BS3 | -89.73% | 2.6  |  3.503  | false |

### Native Boris Solver

- `trace_trajectory`

The classical Boris method is not a general ODE solver, but designed specifically for the Lorentz equation with the symmetry of the EM fields.

```julia
param = prepare(E, B, species=Electron)
prob = TraceProblem(stateinit, tspan, param)
sol = trace_trajectory(prob; dt, savestepinterval)
```

This method is 2nd order accurate in space. A fixed `dt` is required to conserve phase space volume, even though it is not a symplectic method ([Qin+ 2013](https://doi.org/10.1063/1.4818428)). It is the de facto algorithm for particle pusher after being proposed in the 1960s. However, the phase error may still be an issue.

### Implementation: Analytic or Numerical Fields?

- Analytic --> `Field(F)`
- Numerical --> Needs interpolation
```julia
function getinterp(A, gridx, gridy, gridz, order::Int=1, bc::Int=1)
   @assert size(A,1) == 3 && ndims(A) == 4 "Inconsistent 3D force field and grid!"

   Ax = @view A[1,:,:,:]
   Ay = @view A[2,:,:,:]
   Az = @view A[3,:,:,:]

   itpx, itpy, itpz = _getinterp(Ax, Ay, Az, order, bc)

   interpx = scale(itpx, gridx, gridy, gridz)
   interpy = scale(itpy, gridx, gridy, gridz)
   interpz = scale(itpz, gridx, gridy, gridz)

   # Return field value at a given location.
   function get_field(xu)
      r = @view xu[1:3]

      return SA[interpx(r...), interpy(r...), interpz(r...)]
   end

   return get_field
end
```
"""metadatashow_logsèdisabled®skip_as_script«code_foldedënotebook_id$d09ca6a8-76bc-11f0-1aa6-e505a09f9b3fin_temp_dir¨metadata