<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Lammps on Hunter Heidenreich | Senior AI Research Scientist</title><link>https://hunterheidenreich.com/tags/lammps/</link><description>Recent content in Lammps on Hunter Heidenreich | Senior AI Research Scientist</description><image><title>Hunter Heidenreich | Senior AI Research Scientist</title><url>https://hunterheidenreich.com/img/avatar.webp</url><link>https://hunterheidenreich.com/img/avatar.webp</link></image><generator>Hugo -- 0.163.3</generator><language>en-US</language><copyright>2026 Hunter Heidenreich</copyright><lastBuildDate>Sat, 01 Aug 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://hunterheidenreich.com/tags/lammps/index.xml" rel="self" type="application/rss+xml"/><item><title>Modernizing Rahman's 1964 Argon Simulation</title><link>https://hunterheidenreich.com/projects/rahman-1964-replication/</link><pubDate>Sat, 23 Aug 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/projects/rahman-1964-replication/</guid><description>A high-fidelity replication of foundational molecular dynamics using modern software engineering practices: caching, vectorization, and strict reproducibility.</description><content:encoded><![CDATA[<h2 id="overview">Overview</h2>
<p>This project is a &ldquo;digital restoration&rdquo; of Aneesur Rahman&rsquo;s seminal 1964 paper, <em>Correlations in the Motion of Atoms in Liquid Argon</em>. While the physics of liquid argon is a solved problem, the challenge lies in bridging the gap between 1960s mainframe constraints and 2025 software architecture.</p>
<p>I replicated the simulation using <strong>LAMMPS</strong> and built a <strong>Python analysis pipeline</strong> to process the trajectory data. The project demonstrates how modern tooling (<code>uv</code>, type hinting, vectorized NumPy) can transform academic &ldquo;write-once&rdquo; scripts into a reproducible research toolkit.</p>
<h2 id="features">Features</h2>
<h3 id="the-analysis-pipeline">The Analysis Pipeline</h3>
<p>I architected a modular Python package (<code>argon_sim</code>) designed for performance and maintainability.</p>
<ul>
<li><strong>Intelligent Caching System</strong>: MD analysis is compute-intensive ($O(N^2)$). I implemented a decorator-based caching layer (<code>@cached_computation</code>) that hashes source file modification times and function arguments. This ensures expensive calculations (like RDF or Van Hove correlations) are only re-run when the underlying trajectory or parameters actually change.</li>
<li><strong>Vectorization &amp; Optimization</strong>: To handle the $N^2$ complexity of pair-wise interactions without C++ extensions, I utilized NumPy broadcasting. For example, the Mean Square Displacement (MSD) calculation is fully vectorized, with a fallback &ldquo;chunked&rdquo; implementation to handle memory overflows on smaller machines.</li>
<li><strong>Modern Python Tooling</strong>:
<ul>
<li><strong>Dependency Management</strong>: Used <code>uv</code> for deterministic environment locking (sub-second resolution).</li>
<li><strong>Type Safety</strong>: Fully type-hinted codebase for static analysis compliance.</li>
<li><strong>Automation</strong>: A <code>Makefile</code> abstracts the workflow (simulation → analysis → figure generation) into single commands (e.g., <code>make figure-5</code>).</li>
</ul>
</li>
</ul>
<h3 id="the-simulation-strategy">The Simulation Strategy</h3>
<p>I used LAMMPS for the MD engine but strictly adhered to Rahman&rsquo;s physical parameters while modernizing the stability mechanisms.</p>
<ul>
<li><strong>Integration</strong>: Replaced Rahman&rsquo;s predictor-corrector method with the modern standard <strong>Velocity Verlet</strong> algorithm (2 fs timestep).</li>
<li><strong>Equilibration</strong>: I implemented a 1 ns <strong>NVT equilibration</strong> phase (500,000 steps at the 2 fs timestep) to properly melt the FCC crystal structure before the NVE production run.</li>
<li><strong>Intellectual Honesty</strong>: The <code>in.argon</code> script explicitly documents every deviation from the original methodology (e.g., energy minimization) and the justification for ensuring numerical stability.</li>
</ul>
<h2 id="usage">Usage</h2>
<p>The project uses a <code>Makefile</code> to automate the workflow. Run <code>make all</code> to execute the LAMMPS simulation and generate all analysis figures.</p>
<h2 id="results">Results</h2>
<p>The replication achieved high quantitative agreement with the historical data, validating both the simulation parameters and the custom analysis code.</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Property</th>
					<th style="text-align: left">Rahman (1964)</th>
					<th style="text-align: left">This Work</th>
					<th style="text-align: left">Notes</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left">Diffusion Coefficient ($D$)</td>
					<td style="text-align: left">$2.43 \times 10^{-5}$ cm²/s</td>
					<td style="text-align: left">$2.47 \times 10^{-5}$ cm²/s</td>
					<td style="text-align: left">Agreement within 2%</td>
			</tr>
			<tr>
					<td style="text-align: left">RDF First Peak</td>
					<td style="text-align: left">$3.7$ Å</td>
					<td style="text-align: left">$3.82$ Å</td>
					<td style="text-align: left">Slight shift</td>
			</tr>
			<tr>
					<td style="text-align: left">Velocity Dist. Width ($e^{-1/2}$)</td>
					<td style="text-align: left">$1.77$</td>
					<td style="text-align: left">$1.77$</td>
					<td style="text-align: left">Exact match to theoretical Maxwell-Boltzmann</td>
			</tr>
	</tbody>
</table>
<h3 id="visual-replication">Visual Replication</h3>
<p>I used Matplotlib to digitally recreate Rahman&rsquo;s hand-drawn plots, confirming signatures like the <strong>negative region in the Velocity Autocorrelation Function (VACF)</strong>, which provided the first evidence of the &ldquo;cage effect&rdquo; in simple liquids.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-velocity-autocorrelation.webp"
         alt="Velocity Autocorrelation Function comparison showing the characteristic negative region"
         title="Velocity Autocorrelation Function comparison showing the characteristic negative region"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The VACF&rsquo;s negative region (first evidence of the &lsquo;cage effect&rsquo; in liquids) reproduced 60 years later.</figcaption>
    
</figure>

<h2 id="challenges--learnings">Challenges &amp; Learnings</h2>
<ul>
<li><strong>Unit Hell</strong>: Rahman&rsquo;s paper uses a mix of reduced units and CGS. Mapping these to LAMMPS&rsquo;s <code>real</code> units required a dedicated <code>constants.py</code> module and rigorous unit testing to prevent dimensional errors.</li>
<li><strong>Fourier Transforms</strong>: Calculating the Structure Factor $S(k)$ from $g(r)$ required implementing a manual 3D Fourier transform for spherical symmetry, as standard FFT packages do not account for the radial shell integration implicit in liquid structure analysis.</li>
<li><strong>Code as a Liability</strong>: Early in the project, I realized that re-running analysis scripts was becoming a bottleneck. This drove the decision to build the caching infrastructure, reinforcing the lesson that investing in developer tooling pays off even in small-scale scientific projects.</li>
</ul>
<h2 id="related-work">Related Work</h2>
<p>The full methodology and physics are documented in the companion blog post:</p>
<ul>
<li><a href="/posts/rahman-1964-lammps-liquid-argon/">Replicating Rahman&rsquo;s 1964 Liquid Argon Simulation</a></li>
</ul>
]]></content:encoded></item><item><title>Modernizing Rahman's 1964 Argon Simulation</title><link>https://hunterheidenreich.com/posts/rahman-1964-lammps-liquid-argon/</link><pubDate>Sat, 23 Aug 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/rahman-1964-lammps-liquid-argon/</guid><description>How I used modern software engineering (caching, vectorization, and dependency locking) to reproduce a 60-year-old physics milestone.</description><content:encoded><![CDATA[<p>Some papers invent entire fields. Aneesur Rahman&rsquo;s 1964 paper, <strong>&ldquo;Correlations in the Motion of Atoms in Liquid Argon&rdquo;</strong>, is the &ldquo;Hello World&rdquo; of molecular dynamics (MD). Using a computer with less memory than a modern microwave, Rahman solved Newton&rsquo;s equations for 864 atoms and proved that liquids have distinct, quantifiable structure.</p>
<p>The physics of liquid argon is a solved problem. We know the answer.</p>
<p>So, why replicate it in 2025? <strong>To apply modern engineering standards to legacy science.</strong></p>
<p>This project served as an exercise in <strong>software archaeology</strong>: taking a vintage scientific workflow and rebuilding it with a modular Python analysis pipeline. I wanted to see if I could replace Rahman&rsquo;s &ldquo;write-once&rdquo; Fortran mentality with modern reproducibility, type safety, and intelligent caching.</p>
<p>The full source code is available on <a href="https://github.com/hunter-heidenreich/argon-simulation">GitHub</a>. The complete project overview, including analysis results and pipeline architecture, is on the <a href="/projects/rahman-1964-replication/">Rahman 1964 Replication project page</a>.</p>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/KjFixUt6bnQ?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<hr>
<h2 id="engineering-the-pipeline">Engineering the Pipeline</h2>
<p>The most interesting part of this project isn&rsquo;t the simulation engine (LAMMPS handles that); it&rsquo;s the architecture of the analysis suite. MD analysis is computationally expensive ($O(N^2)$), and iterating on plots can be painfully slow if you re-compute trajectory data every time.</p>
<p>Why bother? Don&rsquo;t modern MD packages come with analysis tools?
Well, some say that writing is thinking.
Sometimes getting into the weeds of how an algorithm works or an analysis is performed, you gain insights and a deeper understanding that might be obscured by a plug-and-play tool.</p>
<h3 id="intelligent-caching">Intelligent Caching</h3>
<p>I built the <code>argon_sim</code> package with a decorator-based caching layer. The system hashes the source file&rsquo;s modification time and the function&rsquo;s arguments to avoid re-calculating the Radial Distribution Function (RDF) or Van Hove correlations on every script run.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#a6e22e">@cached_computation</span>(<span style="color:#e6db74">&#34;gr&#34;</span>)
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">def</span> <span style="color:#a6e22e">compute_radial_distribution</span>(filename: str, dr: float <span style="color:#f92672">=</span> <span style="color:#ae81ff">0.05</span>):
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># ... expensive O(N^2) distance calculations ...</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">return</span> r_values, g_r, density
</span></span></code></pre></div><p>If I tweak a plot axis, the script runs instantly, loading pre-computed arrays from disk instead of re-running the $O(N^2)$ computation. If I change the simulation trajectory, the cache invalidates automatically.</p>
<h3 id="vectorization--memory-management">Vectorization &amp; Memory Management</h3>
<p>Rahman likely relied on nested loops. Python is too slow for that. I utilized <strong>NumPy broadcasting</strong> to vectorize the calculation of atomic displacements.</p>
<p>However, calculating an $864 \times 864$ distance matrix for 5,000 frames consumes significant RAM. I implemented a <strong>chunked MSD (Mean Square Displacement) algorithm</strong> that processes the trajectory in blocks, balancing vectorization speed with memory constraints. The chunking trades some vectorization speed for a bounded memory footprint, so the analysis is not capped by holding the full distance matrix in RAM.</p>
<h3 id="reproducibility-as-a-feature">Reproducibility as a Feature</h3>
<p>Academic code is notorious for &ldquo;it works on my machine.&rdquo; To combat this, I used <strong><code>uv</code></strong> for dependency management, locking the exact environment state. The entire workflow (from simulation to final figure generation) is abstracted into a <code>Makefile</code>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e"># One command to run the physics, analyze data, and generate plots</span>
</span></span><span style="display:flex;"><span>make workflow
</span></span></code></pre></div><hr>
<h2 id="the-simulation-1964-vs-2025">The Simulation: 1964 vs. 2025</h2>
<p>I preserved Rahman&rsquo;s physical parameters exactly to ensure a fair comparison:</p>
<ul>
<li><strong>System</strong>: 864 Argon atoms</li>
<li><strong>Potential</strong>: Lennard-Jones ($\sigma = 3.4$ Å, $\epsilon/k_B = 120$ K)</li>
<li><strong>Target</strong>: 94.4 K, 1.374 g/cm³</li>
</ul>
<p>However, I modernized the <em>numerical</em> methods to ensure stability:</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Feature</th>
					<th style="text-align: left">Rahman (1964)</th>
					<th style="text-align: left">This Work (2025)</th>
					<th style="text-align: left">Why it Matters</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong>Integration</strong></td>
					<td style="text-align: left">Predictor-Corrector</td>
					<td style="text-align: left">Velocity Verlet</td>
					<td style="text-align: left">Better energy conservation over long runs</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Timestep</strong></td>
					<td style="text-align: left">10 fs</td>
					<td style="text-align: left">2 fs</td>
					<td style="text-align: left">Rahman&rsquo;s step was aggressive; 2 fs ensures numerical stability</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Equilibration</strong></td>
					<td style="text-align: left">Velocity Scaling</td>
					<td style="text-align: left">1 ns NVT</td>
					<td style="text-align: left">Rahman couldn&rsquo;t afford long equilibrations; I melted the crystal properly to remove bias</td>
			</tr>
	</tbody>
</table>
<p>The production run lasted 10 ps in the NVE ensemble, generating 5,001 frames. Temperature remained within 1% of target with an RMS fluctuation of 0.0165.</p>
<hr>
<h2 id="validation-results">Validation Results</h2>
<p>The replication was quantitatively successful. The analysis pipeline faithfully reproduced every key signature of liquid argon.</p>
<h3 id="the-cage-effect">The Cage Effect</h3>
<p>This is the paper&rsquo;s crown jewel. In a gas, velocity correlations decay exponentially. In a liquid, Rahman discovered that atoms get trapped by their neighbors and bounce back, causing the correlation to go <em>negative</em>.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-velocity-autocorrelation.webp"
         alt="Velocity Autocorrelation Function"
         title="Velocity Autocorrelation Function"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The VACF dips below zero at 0.3 ps. This &rsquo;negative correlation&rsquo; is the signature of the cage effect: atoms rattling against their neighbors.</figcaption>
    
</figure>

<p>My simulation captures this minimum at -0.083, matching Rahman&rsquo;s observation. The Fourier transform of this data (the frequency spectrum) reveals a peak at $\beta \approx 0.25$, physically representing the frequency of atomic collisions within the cage.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-vacf-frequency-spectrum.webp"
         alt="Frequency spectrum of the VACF showing characteristic peak from atomic caging effects"
         title="Frequency spectrum of the VACF showing characteristic peak from atomic caging effects"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Frequency spectrum of the VACF showing characteristic peak from atomic caging effects</figcaption>
    
</figure>

<h3 id="structural-fingerprints">Structural Fingerprints</h3>
<p>The Radial Distribution Function $g(r)$ and its Fourier transform, the Structure Factor $S(k)$, are the &ldquo;fingerprints&rdquo; of a liquid&rsquo;s structure.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-radial-distribution-function.webp"
         alt="Radial Distribution Function and Structure Factor"
         title="Radial Distribution Function and Structure Factor"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">The sharp first peak (3.82 Å) shows defined nearest neighbors, while the decay shows the lack of long-range order. My calculated peaks match Rahman&rsquo;s within 3%.</figcaption>
    
</figure>

<p>The agreement here is striking. My first peak appeared at <strong>3.82 Å</strong> (Rahman: 3.7 Å). The slight discrepancy is likely due to my improved equilibration method, which allowed the system to relax into a more natural liquid state than Rahman&rsquo;s 1960s hardware allowed.</p>
<h3 id="diffusion-and-non-gaussian-behavior">Diffusion and Non-Gaussian Behavior</h3>
<p>By calculating the Mean Square Displacement (MSD), I derived a diffusion coefficient of <strong>$D = 2.47 \times 10^{-5}$ cm²/s</strong>, which deviates only <strong>2%</strong> from Rahman&rsquo;s reported $2.43 \times 10^{-5}$.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-mean-square-displacement.webp"
         alt="Mean Square Displacement vs time showing ballistic to diffusive transition"
         title="Mean Square Displacement vs time showing ballistic to diffusive transition"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Mean Square Displacement vs. time showing ballistic to diffusive transition</figcaption>
    
</figure>

<p>More interestingly, I reproduced the &ldquo;Non-Gaussian&rdquo; parameters. Standard diffusion assumes a Gaussian distribution of displacements. Rahman found (and I confirmed) that liquid atoms deviate from this. They exhibit &ldquo;jump&rdquo; and &ldquo;wait&rdquo; dynamics, a behavior that standard Brownian motion models fail to capture.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-non-gaussian-parameters.webp"
         alt="Non-Gaussian parameters showing deviation from simple diffusive behavior"
         title="Non-Gaussian parameters showing deviation from simple diffusive behavior"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Evidence that atoms do not follow a simple random walk. The non-zero alpha parameters indicate heterogeneous dynamics.</figcaption>
    
</figure>

<h3 id="advanced-analysis-van-hove-functions">Advanced Analysis: Van Hove Functions</h3>
<p>Rahman also explored advanced properties like the Van Hove correlation function $G(r,t)$, which describes how liquid structure evolves over time.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-van-hove-correlation.webp"
         alt="Van Hove distinct correlation function G_d(r,t) at two time points"
         title="Van Hove distinct correlation function G_d(r,t) at two time points"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Van Hove distinct correlation function showing how neighbor coordination shells &lsquo;melt&rsquo; as time progresses</figcaption>
    
</figure>

<p>At 1.0 ps, the structure remains well-defined with clear shells. By 2.5 ps, it becomes increasingly diffuse. Rahman compared this evolution to theoretical predictions (the Vineyard approximation) and found that theory predicted overly rapid structural decay. My results confirm this finding.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-delayed-convolution.webp"
         alt="Delayed convolution approximation testing Rahman&#39;s theoretical improvement"
         title="Delayed convolution approximation testing Rahman&#39;s theoretical improvement"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Testing Rahman&rsquo;s &lsquo;delayed convolution approximation&rsquo; (his proposed improvement over existing theory)</figcaption>
    
</figure>

<hr>
<h2 id="system-validation">System Validation</h2>
<p>Before analyzing physics, basic sanity checks confirmed proper thermal equilibrium.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-temperature-stability.webp"
         alt="Temperature vs time plot showing excellent temperature control around 94.4 K target"
         title="Temperature vs time plot showing excellent temperature control around 94.4 K target"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Temperature vs. Time - 5001 frames showing excellent temperature control with mean 94.73 K</figcaption>
    
</figure>

<p>Mean temperature was 94.73 K (0.33 K off target) with a standard deviation of 1.56 K.</p>















<figure class="post-figure center ">
    <img src="/img/rahman-1964-argon-molecular-dynamics/rahman-argon-maxwell-boltzmann-velocity.webp"
         alt="Maxwell-Boltzmann velocity distribution"
         title="Maxwell-Boltzmann velocity distribution"
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Maxwell-Boltzmann velocity distribution from 12.9 million velocity components</figcaption>
    
</figure>

<p>The velocity distribution from 12.9 million velocity components produces a clean Maxwell-Boltzmann distribution, as expected for thermal equilibrium. The distribution widths at various heights closely match Rahman&rsquo;s results: 1.77, 2.48, and 3.56 compared to his 1.77, 2.52, and 3.52.</p>
<hr>
<h2 id="conclusion">Conclusion</h2>
<p>Replicating a 60-year-old paper might seem like a solved puzzle, but it teaches a valuable lesson in computational science. Rahman relied on brilliance and raw mathematical intuition because he lacked compute power. Today, pairing modern compute with disciplined software practices makes the same result reproducible and auditable.</p>
<p>Applying modern software engineering (<strong>modular architecture, caching, and automated workflows</strong>) to classical physics reproduces the past and builds a foundation that makes the <em>next</em> discovery easier, faster, and more reliable.</p>
<p>The quantitative agreement is striking: diffusion coefficients within 2%, structural peaks within 0.1 Å, velocity distributions matching to three significant figures. This level of reproducibility, achieved with completely different hardware and software, validates something fundamental: Rahman&rsquo;s physical model was remarkably sound, and his computational methodology was scientifically rigorous despite 1960s constraints.</p>
<p>The cage effect, velocity correlations, and structural evolution are fundamental characteristics of how matter behaves at the atomic scale, as relevant today as they were six decades ago.</p>
]]></content:encoded></item><item><title>Liquid Argon: LAMMPS Simulation</title><link>https://hunterheidenreich.com/videos/liquid-argon-lammps-simulation/</link><pubDate>Sat, 23 Aug 2025 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/videos/liquid-argon-lammps-simulation/</guid><description>LAMMPS molecular dynamics simulation of liquid argon demonstrating fundamental liquid-state behavior and molecular motion.</description><content:encoded><![CDATA[<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/KjFixUt6bnQ?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<p>Details on the simulation can be found in the <a href="/posts/rahman-1964-lammps-liquid-argon/">Liquid Argon: LAMMPS Simulation</a> post.</p>
]]></content:encoded></item><item><title>Platinum Adatom Diffusion on Pt(100): LAMMPS Simulation</title><link>https://hunterheidenreich.com/videos/pt-adatom-diffusion/</link><pubDate>Wed, 27 Sep 2023 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/videos/pt-adatom-diffusion/</guid><description>LAMMPS molecular dynamics simulation of platinum adatom diffusion on a Pt(100) surface, showing atomic mobility mechanisms.</description><content:encoded><![CDATA[<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/1hhf5cQh56w?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<p>Details on the simulation can be found in the <a href="/posts/adatom-cu-diffusion/">LAMMPS Tutorial: Copper and Platinum Adatom Diffusion</a> post and the <a href="/projects/lammps-adatom-diffusion/">Automated Adatom Diffusion Workflow</a> project page.</p>
]]></content:encoded></item><item><title>LAMMPS Tutorial: Copper and Platinum Adatom Diffusion</title><link>https://hunterheidenreich.com/posts/adatom-cu-diffusion/</link><pubDate>Wed, 27 Sep 2023 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/posts/adatom-cu-diffusion/</guid><description>LAMMPS tutorial for copper and platinum surface diffusion simulation and ML training data generation. Includes setup, analysis, and Ovito visualization.</description><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Understanding how individual atoms move on crystal surfaces is fundamental to materials science, catalysis, and nanotechnology. This atomic-scale motion, called adatom diffusion, drives processes like thin film growth and surface chemical reactions.</p>
<p>While learning molecular dynamics simulations for my graduate work, I discovered these simulations generate valuable training data for machine learning models. This tutorial walks through simulating copper adatom diffusion on a Cu(100) surface using LAMMPS, building on Eric N. Hahn&rsquo;s excellent <a href="https://www.ericnhahn.com/tutorials/lammps-tutorials/adatom">adatom tutorial</a>.</p>
<p><strong>What you&rsquo;ll learn:</strong></p>
<ul>
<li>Setting up LAMMPS for surface diffusion simulations</li>
<li>Understanding simulation parameters and their impact</li>
<li>Visualizing results with Ovito</li>
<li>Analyzing trajectory data for ML applications</li>
<li>Connecting simulation data to machine learning workflows</li>
</ul>
<p>In this tutorial, we will explore both Copper (Cu) and Platinum (Pt) to show how atomic properties affect diffusion behavior, generating data for training element-aware ML models.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before starting this tutorial, you&rsquo;ll need:</p>
<ul>
<li><strong>LAMMPS</strong> with EAM potential support (version 2020 or later recommended)</li>
<li><strong>Python 3.x</strong> with matplotlib for analysis scripts</li>
<li><strong>Ovito</strong> (free version) for trajectory visualization</li>
<li><strong>Cu01.eam.alloy</strong> potential file from the <a href="https://www.ctcms.nist.gov/potentials/">NIST repository</a></li>
<li>Basic familiarity with molecular dynamics concepts (atoms, forces, timesteps)</li>
</ul>
<h2 id="understanding-adatoms-and-surface-diffusion">Understanding Adatoms and Surface Diffusion</h2>
<h3 id="what-is-an-adatom">What is an Adatom?</h3>
<p>An <strong>adatom</strong> (adsorbed atom) sits on a crystal surface but isn&rsquo;t incorporated into the bulk structure. Adatoms have fewer bonds than fully coordinated bulk atoms, making them highly mobile and reactive.</p>















<figure class="post-figure center ">
    <img src="/img/posts/crystal-surface.webp"
         alt="Ball model representation of a real (atomically rough) crystal surface with steps, kinks, adatoms, and vacancies in a closely-packed crystalline material. Adsorbed molecules, substitutional and interstitial atoms are also illustrated."
         title="Ball model representation of a real (atomically rough) crystal surface with steps, kinks, adatoms, and vacancies in a closely-packed crystalline material. Adsorbed molecules, substitutional and interstitial atoms are also illustrated."
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Ball model representation of a real (atomically rough) crystal surface with steps, kinks, adatoms, and vacancies in a closely-packed crystalline material. Adsorbed molecules, substitutional and interstitial atoms are also illustrated. (<a href="https://creativecommons.org/licenses/by-sa/4.0/deed.en">CC-BY-SA-4.0: ShutterWaves</a>)</figcaption>
    
</figure>

<h3 id="why-study-adatom-diffusion">Why Study Adatom Diffusion?</h3>
<p>Adatom diffusion is important for several technological processes:</p>
<ul>
<li><strong>Thin film growth</strong>: Adatoms are the building blocks of deposited films</li>
<li><strong>Catalysis</strong>: Many reactions happen at these mobile surface atoms</li>
<li><strong>Corrosion</strong>: How surface atoms move affects material degradation</li>
<li><strong>Self-assembly</strong>: Adatom movement enables formation of ordered structures</li>
</ul>
<p>From a <strong>machine learning perspective</strong>, adatom diffusion is an ideal test case because:</p>
<ul>
<li>Well-understood physics provides ground truth for validation</li>
<li>Small system size enables extensive simulation</li>
<li>Behavior varies significantly with temperature and atomic species</li>
<li>Systematic data generation across different conditions</li>
</ul>
<h3 id="why-cu100">Why Cu(100)?</h3>
<p>Cu(100) surfaces are well-studied in literature, making them excellent benchmarks. The face-centered cubic (fcc) structure creates clear diffusion pathways, and copper&rsquo;s moderate binding energy lets us observe diffusion at reasonable temperatures without extreme computational demands.</p>
<h2 id="simulation-overview">Simulation Overview</h2>
<p>Before diving into the code details, let&rsquo;s understand the simulation design:</p>
<h3 id="key-simulation-parameters">Key Simulation Parameters</h3>
<table>
	<thead>
			<tr>
					<th>Parameter</th>
					<th>Value</th>
					<th>Why this choice</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>System size</strong></td>
					<td>$8 \x8 \x6$ unit cells</td>
					<td>Large enough to avoid edge effects while keeping simulation time reasonable</td>
			</tr>
			<tr>
					<td><strong>Ensemble</strong></td>
					<td>NVT (constant volume, temperature)</td>
					<td>Appropriate for surface studies where pressure isn&rsquo;t the focus</td>
			</tr>
			<tr>
					<td><strong>Potential</strong></td>
					<td>EAM (Embedded Atom Method)</td>
					<td>Captures metallic bonding better than simple pair potentials</td>
			</tr>
			<tr>
					<td><strong>Time step</strong></td>
					<td>5 fs</td>
					<td>Small enough for numerical stability while allowing reasonable run times</td>
			</tr>
			<tr>
					<td><strong>Duration</strong></td>
					<td>500 ps</td>
					<td>Long enough to see multiple diffusion events</td>
			</tr>
			<tr>
					<td><strong>Temperature</strong></td>
					<td>600 K initial seed; 850 K thermostat on the bottom reservoir layer</td>
					<td>Drives thermal energy up from the substrate into the free surface where the adatom diffuses</td>
			</tr>
	</tbody>
</table>
<h3 id="simulation-strategy">Simulation Strategy</h3>
<p>The approach uses a <strong>thermal gradient setup</strong>:</p>
<ul>
<li>Bottom layers: Fixed to represent bulk crystal</li>
<li>Middle layers: Heated to 850 K for thermal energy</li>
<li>Top layers and adatom: Equilibrate to $\sim 600$ K for diffusion</li>
<li>This lets thermal energy propagate up from the heated reservoir to the free surface where the adatom diffuses</li>
</ul>
<p>The complete LAMMPS script implementing this approach:</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">### Original Created by Eric N. Hahn  ###
### ericnhahn@gmail.com ###

### Modifications by Hunter Heidenreich, CSE lab (Harvard, 2023)
### hheidenreich@g.harvard.edu
### 2023-09-01

### Simulating adatoms ###
### Version 0.2 ###


units metal
dimension 3
boundary p p s
atom_style atomic

lattice fcc 3.614
variable cubel equal 4
variable fixer1 equal &#34;v_cubel+2&#34;
variable fixer2 equal &#34;v_cubel+1.49&#34;
region  box block -${cubel} ${cubel} -${cubel} ${cubel} -${fixer1} 1 units lattice
region cbox block -${cubel} ${cubel} -${cubel} ${cubel} -${fixer1} 0 units lattice
create_box 1 box
create_atoms 1 region cbox
create_atoms 1 single -0.5 0 0.5 units lattice
region hold block INF INF INF INF -${fixer1} -${fixer2} units lattice
region temp block INF INF INF INF -${fixer2} -${cubel} units lattice
group hold region hold
group temp region temp

pair_style eam/alloy
pair_coeff * * Cu01.eam.alloy Cu

timestep        0.005
compute         new all temp
velocity        temp create 600 12345
fix heater temp temp/rescale 1 850 850 5 1
fix nve all nve
fix freeze hold setforce 0 0 0

variable e     equal pe
variable k     equal ke
variable t     equal etotal
variable T     equal temp
fix energy all ave/time 1 50 50 v_k v_e v_t v_T file energy_avg.txt

minimize 1.0e-4 1.0e-6 1000 10000

dump eve all custom 5 dump.lammpstrj id type xu yu zu   # fx fy fz  # uncomment for forces
dump_modify eve sort id

thermo 50
run 100000  # 100_000 * 5 fs = 500 ps
</code></pre><h2 id="line-by-line-breakdown">Line-by-Line Breakdown</h2>
<p>Let&rsquo;s examine each part of the LAMMPS script:</p>
<h3 id="simulation-setup">Simulation Setup</h3>
<h4 id="units">Units</h4>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">units metal
</code></pre><p>Sets simulation units to &ldquo;metal&rdquo; units (a standard choice for metallic systems). Key conversions: length in $\text{\AA}$, energy in eV, time in ps. Full details in the <a href="https://docs.lammps.org/units.html">LAMMPS documentation</a>.</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">dimension 3
</code></pre><p>Sets 3D simulation.</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">boundary p p s
</code></pre><p>Boundary conditions: periodic in x,y (infinite surface) and shrink-wrapped in z (finite surface height). This allows the adatom to potentially leave the surface if needed.</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">atom_style atomic
</code></pre><p>Uses &ldquo;atomic&rdquo; style, atoms as point masses without internal structure. Standard for metallic systems.</p>
<h4 id="lattice">Lattice</h4>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">lattice fcc 3.614
</code></pre><p>Defines face-centered cubic lattice with experimental Cu lattice constant ($3.614 \text{ \AA}$).</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">variable cubel equal 4
variable fixer1 equal &#34;v_cubel+2&#34;
variable fixer2 equal &#34;v_cubel+1.49&#34;
</code></pre><p>Define variables for simulation box dimensions. <code>cubel=4</code> sets system size, while <code>fixer1</code> and <code>fixer2</code> define the frozen and heated regions.</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">region  box block -${cubel} ${cubel} -${cubel} ${cubel} -${fixer1} 1 units lattice
region cbox block -${cubel} ${cubel} -${cubel} ${cubel} -${fixer1} 0 units lattice
</code></pre><p>Define regions: <code>box</code> for the entire simulation volume and <code>cbox</code> for crystal creation (excludes the surface layer where we&rsquo;ll place the adatom).</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">create_box 1 box
create_atoms 1 region cbox
create_atoms 1 single -0.5 0 0.5 units lattice
</code></pre><p>Create simulation box, populate with Cu atoms, then add single adatom at specified position.</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">region hold block INF INF INF INF -${fixer1} -${fixer2} units lattice
region temp block INF INF INF INF -${fixer2} -${cubel} units lattice
group hold region hold
group temp region temp
</code></pre><p>Define atom groups: <code>hold</code> (frozen bottom layers) and <code>temp</code> (heated middle layers for thermal energy).</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">pair_style eam/alloy
pair_coeff * * Cu01.eam.alloy Cu
</code></pre><p>Use <a href="/notes/chemistry/molecular-simulation/classical-methods/embedded-atom-method/">Embedded Atom Method (EAM)</a> potential for metallic bonding. The Cu01.eam.alloy potential from <a href="https://doi.org/10.1103/PhysRevB.63.224106">Mishin et al.</a> is available from the <a href="https://www.ctcms.nist.gov/potentials/testing/entry/2001--Mishin-Y-Mehl-M-J-Papaconstantopoulos-D-A-et-al--Cu-1/">NIST repository</a>.</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">timestep        0.005
</code></pre><p>5 femtosecond timestep (small enough for numerical stability).</p>
<h4 id="initial-conditions">Initial Conditions</h4>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">velocity        temp create 600 12345
</code></pre><p>Initialize velocities for 600 K temperature using random seed 12345.</p>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">fix heater temp temp/rescale 1 850 850 5 1
fix nve all nve
fix freeze hold setforce 0 0 0
</code></pre><p>Three fixes control dynamics:</p>
<ul>
<li><code>heater</code>: Maintains 850 K in middle layers</li>
<li><code>nve</code>: Velocity Verlet integration for all atoms</li>
<li><code>freeze</code>: Sets forces to zero for bottom atoms</li>
</ul>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">variable e     equal pe
variable k     equal ke
variable t     equal etotal
variable T     equal temp
fix energy all ave/time 1 50 50 v_k v_e v_t v_T file energy_avg.txt
</code></pre><p>Track energies and temperature, averaging every 50 timesteps and writing to file.</p>
<h3 id="execution">Execution</h3>
<h4 id="minimization">Minimization</h4>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">minimize 1.0e-4 1.0e-6 1000 10000
</code></pre><p>Relax initial structure. Should converge quickly, indicating the system is already well-optimized.</p>
<h4 id="output-setup">Output Setup</h4>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">dump eve all custom 5 dump.lammpstrj id type xu yu zu   # fx fy fz  # uncomment for forces
dump_modify eve sort id
</code></pre><p>Write atomic positions every 5 timesteps, sorted by atom ID. Uncomment force components if needed for analysis.</p>
<h4 id="production-run">Production Run</h4>
<pre tabindex="0"><code class="language-lammps" data-lang="lammps">thermo 50
run 100000  # 100_000 * 5 fs = 500 ps
</code></pre><p>Run simulation for 500 ps with thermo output every 50 steps.</p>
<h2 id="visualization-and-analysis">Visualization and Analysis</h2>
<p>Visualize results using <a href="https://www.ovito.org/">Ovito</a>, a free atomistic visualization tool:</p>
<ol>
<li>Open the trajectory file in Ovito</li>
<li>Color atoms by z-coordinate</li>
<li>Restrict height range to $0\text{-}2 \text{ \AA}$ for surface focus</li>
<li>Animate to observe diffusion events</li>
</ol>
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/nIdbNqEEPys?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<h2 id="analysis-results">Analysis Results</h2>
<p>The simulation generates rich data for machine learning applications:</p>
<h3 id="energy-analysis">Energy Analysis</h3>
<p>Energy fluctuations reveal thermal motion patterns:</p>















<figure class="post-figure center ">
    <img src="/img/adatom_cu_energy_avg.webp"
         alt="Average kinetic energy, potential energy, total energy, and temperature over time."
         title="Average kinetic energy, potential energy, total energy, and temperature over time."
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Energy and temperature evolution over 500 ps simulation.</figcaption>
    
</figure>

<p>Skipping the first 30 logged data points (each averaged over 50 timesteps, so the first ~1500 timesteps / 7.5 ps of equilibration), these fluctuations enable:</p>
<ul>
<li><strong>Anomaly detection</strong>: Identifying unusual diffusion events</li>
<li><strong>Temperature prediction</strong>: Estimating local temperature from atomic motion</li>
<li><strong>Stability analysis</strong>: Detecting equilibrium states</li>
</ul>
<h3 id="trajectory-analysis">Trajectory Analysis</h3>
<p>Adatom motion reveals diffusion mechanisms:</p>















<figure class="post-figure center ">
    <img src="/img/adatom_cu_xy.webp"
         alt="x and y coordinates of the adatom over time."
         title="x and y coordinates of the adatom over time."
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Adatom surface trajectory showing random walk behavior.</figcaption>
    
</figure>

<p>This data enables:</p>
<ul>
<li><strong>Path prediction</strong>: Training models for future position forecasting</li>
<li><strong>Diffusion coefficient estimation</strong>: Learning temperature-mobility relationships</li>
<li><strong>Transition state identification</strong>: Detecting hops between stable sites</li>
</ul>















<figure class="post-figure center ">
    <img src="/img/adatom_cu_z.webp"
         alt="z coordinate of the adatom over time."
         title="z coordinate of the adatom over time."
         
         
         loading="lazy"
         class="post-image">
    
    <figcaption class="post-caption">Height fluctuations revealing exchange events with surface atoms.</figcaption>
    
</figure>

<p>Z-coordinate data shows <strong>exchange events</strong> where the adatom swaps with surface atoms (crucial for surface chemistry understanding). This enables:</p>
<ul>
<li><strong>Event classification</strong>: Distinguishing diffusion vs. exchange mechanisms</li>
<li><strong>Activation barrier estimation</strong>: Learning energy landscapes from fluctuations</li>
<li><strong>Surface coordination analysis</strong>: Correlating height with local environment</li>
</ul>
<h3 id="machine-learning-applications">Machine Learning Applications</h3>
<p>This simulation produces multiple data types for ML training:</p>
<ol>
<li><strong>Coordinate trajectories</strong>: Neural network potential inputs or graph neural network features</li>
<li><strong>Energy time series</strong>: Regression model features for system property prediction</li>
<li><strong>Event annotations</strong>: Supervised learning labels for diffusion mechanism classification</li>
<li><strong>Environmental descriptors</strong>: Local atomic arrangement features</li>
</ol>
<p>Systematic MD simulations generate large, labeled datasets across varied conditions.</p>
<h2 id="extending-to-platinum-mass-and-bonding-effects">Extending to Platinum: Mass and Bonding Effects</h2>
<p>To understand how different elements behave, we can extend this framework to platinum (Pt). Platinum&rsquo;s higher atomic mass and stronger metallic bonding create notably different diffusion behavior, providing comparative data for machine learning.</p>
<h3 id="key-differences-from-copper">Key Differences from Copper</h3>
<table>
	<thead>
			<tr>
					<th>Parameter</th>
					<th>Copper (Cu)</th>
					<th>Platinum (Pt)</th>
					<th>Impact</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td><strong>Atomic mass</strong></td>
					<td>63.5 u</td>
					<td>195.1 u</td>
					<td>Slower diffusion, longer correlation times</td>
			</tr>
			<tr>
					<td><strong>Lattice const.</strong></td>
					<td>3.614 Å</td>
					<td>3.96 Å</td>
					<td>Larger diffusion barriers, different pathways</td>
			</tr>
			<tr>
					<td><strong>Potential</strong></td>
					<td>Mishin et al.</td>
					<td>Zhou et al.</td>
					<td>Different interaction strengths</td>
			</tr>
			<tr>
					<td><strong>Melting point</strong></td>
					<td>1358 K</td>
					<td>2041 K</td>
					<td>Stronger surface binding</td>
			</tr>
	</tbody>
</table>
<h3 id="modifying-the-lammps-script">Modifying the LAMMPS Script</h3>
<p>The platinum simulation uses the exact same framework as the copper case, with three simple element-specific modifications:</p>
<ol>
<li><strong>Lattice constant</strong>: Change <code>lattice fcc 3.614</code> to <code>lattice fcc 3.96</code></li>
<li><strong>Potential file</strong>: Change <code>Cu01.eam.alloy</code> to <code>Pt_Zhou04.eam.alloy</code> (available from the <a href="https://www.ctcms.nist.gov/potentials/testing/entry/2004--Zhou-X-W-Johnson-R-A-Wadley-H-N-G--Pt/">NIST repository</a>)</li>
<li><strong>Element specification</strong>: Change <code>Cu</code> to <code>Pt</code> in the <code>pair_coeff</code> line</li>
</ol>
<p>These simple changes capture the essential physics differences between elements while maintaining the same simulation protocol, which is ideal for generating comparative datasets for ML training.</p>
<h3 id="expected-behavior-vs-copper">Expected Behavior vs. Copper</h3>
<p>When you run the analysis scripts on the platinum trajectory, you will observe:</p>
<ul>
<li><strong>Slower motion</strong>: Heavier atoms move more slowly at the same temperature. Platinum&rsquo;s ~3x greater mass reduces diffusion rates.</li>
<li><strong>Higher energy barriers</strong>: Stronger metallic bonding creates deeper potential wells, requiring more thermal energy for diffusion hops.</li>
<li><strong>Different pathways</strong>: The larger lattice constant changes the energy landscape, potentially favoring different diffusion mechanisms.</li>
</ul>
<p>Comparing Cu and Pt trajectories enables training element-aware models that account for atomic mass effects, binding strengths, and temperature scaling across different metals.</p>
<h2 id="code-and-data">Code and Data</h2>
<p>The complete simulation scripts and analysis tools are available for reproducibility:</p>
<h3 id="energy-analysis-script">Energy Analysis Script</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># Hunter Heidenreich, 2023</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Plots the energy of a simulation over time.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> matplotlib.pyplot <span style="color:#66d9ef">as</span> plt
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> argparse <span style="color:#f92672">import</span> ArgumentParser
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#39;__main__&#39;</span>:
</span></span><span style="display:flex;"><span>    parser <span style="color:#f92672">=</span> ArgumentParser()
</span></span><span style="display:flex;"><span>    parser<span style="color:#f92672">.</span>add_argument(<span style="color:#e6db74">&#39;--input&#39;</span>, type<span style="color:#f92672">=</span>str, required<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>    parser<span style="color:#f92672">.</span>add_argument(<span style="color:#e6db74">&#39;--output&#39;</span>, type<span style="color:#f92672">=</span>str, required<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>    parser<span style="color:#f92672">.</span>add_argument(<span style="color:#e6db74">&#39;--skip&#39;</span>, type<span style="color:#f92672">=</span>int, default<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>    args <span style="color:#f92672">=</span> parser<span style="color:#f92672">.</span>parse_args()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Parse energy data</span>
</span></span><span style="display:flex;"><span>    data <span style="color:#f92672">=</span> {<span style="color:#e6db74">&#39;ts&#39;</span>: [], <span style="color:#e6db74">&#39;kes&#39;</span>: [], <span style="color:#e6db74">&#39;pes&#39;</span>: [], <span style="color:#e6db74">&#39;tes&#39;</span>: [], <span style="color:#e6db74">&#39;Ts&#39;</span>: []}
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">with</span> open(args<span style="color:#f92672">.</span>input, <span style="color:#e6db74">&#39;r&#39;</span>) <span style="color:#66d9ef">as</span> f:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> line <span style="color:#f92672">in</span> f:
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> line<span style="color:#f92672">.</span>startswith(<span style="color:#e6db74">&#39;#&#39;</span>) <span style="color:#f92672">or</span> <span style="color:#f92672">not</span> line<span style="color:#f92672">.</span>strip():
</span></span><span style="display:flex;"><span>                <span style="color:#66d9ef">continue</span>
</span></span><span style="display:flex;"><span>            t, v_k, v_e, v_t, v_T <span style="color:#f92672">=</span> map(float, line<span style="color:#f92672">.</span>split())
</span></span><span style="display:flex;"><span>            data[<span style="color:#e6db74">&#39;ts&#39;</span>]<span style="color:#f92672">.</span>append(t)
</span></span><span style="display:flex;"><span>            data[<span style="color:#e6db74">&#39;kes&#39;</span>]<span style="color:#f92672">.</span>append(v_k)
</span></span><span style="display:flex;"><span>            data[<span style="color:#e6db74">&#39;pes&#39;</span>]<span style="color:#f92672">.</span>append(v_e)
</span></span><span style="display:flex;"><span>            data[<span style="color:#e6db74">&#39;tes&#39;</span>]<span style="color:#f92672">.</span>append(v_t)
</span></span><span style="display:flex;"><span>            data[<span style="color:#e6db74">&#39;Ts&#39;</span>]<span style="color:#f92672">.</span>append(v_T)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Skip initial equilibration</span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> key <span style="color:#f92672">in</span> data:
</span></span><span style="display:flex;"><span>        data[key] <span style="color:#f92672">=</span> data[key][args<span style="color:#f92672">.</span>skip:]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#75715e"># Create subplots</span>
</span></span><span style="display:flex;"><span>    fig, axs <span style="color:#f92672">=</span> plt<span style="color:#f92672">.</span>subplots(<span style="color:#ae81ff">2</span>, <span style="color:#ae81ff">2</span>, figsize<span style="color:#f92672">=</span>(<span style="color:#ae81ff">16</span>, <span style="color:#ae81ff">12</span>))
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    plots <span style="color:#f92672">=</span> [(<span style="color:#e6db74">&#39;Kinetic Energy&#39;</span>, <span style="color:#e6db74">&#39;kes&#39;</span>), (<span style="color:#e6db74">&#39;Potential Energy&#39;</span>, <span style="color:#e6db74">&#39;pes&#39;</span>),
</span></span><span style="display:flex;"><span>             (<span style="color:#e6db74">&#39;Total Energy&#39;</span>, <span style="color:#e6db74">&#39;tes&#39;</span>), (<span style="color:#e6db74">&#39;Temperature&#39;</span>, <span style="color:#e6db74">&#39;Ts&#39;</span>)]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">for</span> ax, (title, key) <span style="color:#f92672">in</span> zip(axs<span style="color:#f92672">.</span>flat, plots):
</span></span><span style="display:flex;"><span>        ax<span style="color:#f92672">.</span>plot(data[<span style="color:#e6db74">&#39;ts&#39;</span>], data[key])
</span></span><span style="display:flex;"><span>        ax<span style="color:#f92672">.</span>set_xlabel(<span style="color:#e6db74">&#39;TimeStep&#39;</span>)
</span></span><span style="display:flex;"><span>        ax<span style="color:#f92672">.</span>set_ylabel(title)
</span></span><span style="display:flex;"><span>        ax<span style="color:#f92672">.</span>set_title(title)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    plt<span style="color:#f92672">.</span>tight_layout()
</span></span><span style="display:flex;"><span>    plt<span style="color:#f92672">.</span>savefig(args<span style="color:#f92672">.</span>output, dpi<span style="color:#f92672">=</span><span style="color:#ae81ff">300</span>, bbox_inches<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;tight&#39;</span>)
</span></span></code></pre></div><h3 id="trajectory-analysis-script">Trajectory Analysis Script</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-python" data-lang="python"><span style="display:flex;"><span><span style="color:#75715e"># Hunter Heidenreich, 2023</span>
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Plots the coordinates of the adatom.</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">import</span> matplotlib.pyplot <span style="color:#66d9ef">as</span> plt
</span></span><span style="display:flex;"><span><span style="color:#f92672">from</span> argparse <span style="color:#f92672">import</span> ArgumentParser
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> __name__ <span style="color:#f92672">==</span> <span style="color:#e6db74">&#39;__main__&#39;</span>:
</span></span><span style="display:flex;"><span>    parser <span style="color:#f92672">=</span> ArgumentParser()
</span></span><span style="display:flex;"><span>    parser<span style="color:#f92672">.</span>add_argument(<span style="color:#e6db74">&#39;--input&#39;</span>, type<span style="color:#f92672">=</span>str, required<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>    parser<span style="color:#f92672">.</span>add_argument(<span style="color:#e6db74">&#39;--output&#39;</span>, type<span style="color:#f92672">=</span>str, required<span style="color:#f92672">=</span><span style="color:#66d9ef">True</span>)
</span></span><span style="display:flex;"><span>    parser<span style="color:#f92672">.</span>add_argument(<span style="color:#e6db74">&#39;--id&#39;</span>, type<span style="color:#f92672">=</span>int, default<span style="color:#f92672">=</span><span style="color:#ae81ff">1665</span>,
</span></span><span style="display:flex;"><span>                       help<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;Atom ID to track (the adatom is the last created atom)&#39;</span>)
</span></span><span style="display:flex;"><span>    parser<span style="color:#f92672">.</span>add_argument(<span style="color:#e6db74">&#39;--do_z&#39;</span>, action<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;store_true&#39;</span>,
</span></span><span style="display:flex;"><span>                       help<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;Plot z-coordinate instead of xy scatter&#39;</span>)
</span></span><span style="display:flex;"><span>    args <span style="color:#f92672">=</span> parser<span style="color:#f92672">.</span>parse_args()
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    coords <span style="color:#f92672">=</span> {<span style="color:#e6db74">&#39;x&#39;</span>: [], <span style="color:#e6db74">&#39;y&#39;</span>: [], <span style="color:#e6db74">&#39;z&#39;</span>: []}
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">with</span> open(args<span style="color:#f92672">.</span>input, <span style="color:#e6db74">&#39;r&#39;</span>) <span style="color:#66d9ef">as</span> f:
</span></span><span style="display:flex;"><span>        <span style="color:#66d9ef">for</span> line <span style="color:#f92672">in</span> f:
</span></span><span style="display:flex;"><span>            <span style="color:#66d9ef">if</span> line<span style="color:#f92672">.</span>startswith(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#39;</span><span style="color:#e6db74">{</span>args<span style="color:#f92672">.</span>id<span style="color:#e6db74">}</span><span style="color:#e6db74"> &#39;</span>):
</span></span><span style="display:flex;"><span>                x, y, z <span style="color:#f92672">=</span> map(float, line<span style="color:#f92672">.</span>split()[<span style="color:#ae81ff">2</span>:<span style="color:#ae81ff">5</span>])
</span></span><span style="display:flex;"><span>                coords[<span style="color:#e6db74">&#39;x&#39;</span>]<span style="color:#f92672">.</span>append(x)
</span></span><span style="display:flex;"><span>                coords[<span style="color:#e6db74">&#39;y&#39;</span>]<span style="color:#f92672">.</span>append(y)
</span></span><span style="display:flex;"><span>                coords[<span style="color:#e6db74">&#39;z&#39;</span>]<span style="color:#f92672">.</span>append(z)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    plt<span style="color:#f92672">.</span>figure(figsize<span style="color:#f92672">=</span>(<span style="color:#ae81ff">10</span>, <span style="color:#ae81ff">8</span>))
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">if</span> args<span style="color:#f92672">.</span>do_z:
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>plot(range(len(coords[<span style="color:#e6db74">&#39;z&#39;</span>])), coords[<span style="color:#e6db74">&#39;z&#39;</span>], <span style="color:#e6db74">&#39;b-&#39;</span>, linewidth<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>)
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>xlabel(<span style="color:#e6db74">&#39;Simulation Step&#39;</span>)
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>ylabel(<span style="color:#e6db74">&#39;Z Coordinate (Å)&#39;</span>)
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>title(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#39;Height vs. Time for Adatom </span><span style="color:#e6db74">{</span>args<span style="color:#f92672">.</span>id<span style="color:#e6db74">}</span><span style="color:#e6db74">&#39;</span>)
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>grid(<span style="color:#66d9ef">True</span>, alpha<span style="color:#f92672">=</span><span style="color:#ae81ff">0.3</span>)
</span></span><span style="display:flex;"><span>    <span style="color:#66d9ef">else</span>:
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>scatter(coords[<span style="color:#e6db74">&#39;x&#39;</span>], coords[<span style="color:#e6db74">&#39;y&#39;</span>], s<span style="color:#f92672">=</span><span style="color:#ae81ff">1</span>, alpha<span style="color:#f92672">=</span><span style="color:#ae81ff">0.7</span>, c<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;red&#39;</span>)
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>xlabel(<span style="color:#e6db74">&#39;X Coordinate (Å)&#39;</span>)
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>ylabel(<span style="color:#e6db74">&#39;Y Coordinate (Å)&#39;</span>)
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>title(<span style="color:#e6db74">f</span><span style="color:#e6db74">&#39;XY Trajectory for Adatom </span><span style="color:#e6db74">{</span>args<span style="color:#f92672">.</span>id<span style="color:#e6db74">}</span><span style="color:#e6db74">&#39;</span>)
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>axis(<span style="color:#e6db74">&#39;equal&#39;</span>)
</span></span><span style="display:flex;"><span>        plt<span style="color:#f92672">.</span>grid(<span style="color:#66d9ef">True</span>, alpha<span style="color:#f92672">=</span><span style="color:#ae81ff">0.3</span>)
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    plt<span style="color:#f92672">.</span>savefig(args<span style="color:#f92672">.</span>output, dpi<span style="color:#f92672">=</span><span style="color:#ae81ff">300</span>, bbox_inches<span style="color:#f92672">=</span><span style="color:#e6db74">&#39;tight&#39;</span>)
</span></span></code></pre></div><h2 id="summary-and-next-steps">Summary and Next Steps</h2>
<p>This tutorial demonstrates how molecular dynamics generates valuable ML training data for materials science. Adatom diffusion provides an ideal starting point because it:</p>
<ul>
<li><strong>Has interpretable physics</strong>: Well-understood mechanisms enable ML validation</li>
<li><strong>Shows diverse behaviors</strong>: Temperature-dependent dynamics create rich datasets</li>
<li><strong>Scales efficiently</strong>: Small systems allow extensive parameter exploration</li>
<li><strong>Connects to applications</strong>: Direct relevance to catalysis and surface engineering</li>
</ul>
<h3 id="whats-next">What&rsquo;s Next</h3>
<p>Future posts will extend this framework:</p>
<ol>
<li><strong>Mixed-metal surfaces</strong>: Alloy effects on diffusion pathways</li>
<li><strong>Stepped surfaces</strong>: How defects alter atomic mobility</li>
<li><strong>ML implementation</strong>: Training neural networks on simulation data</li>
</ol>
<h3 id="broader-applications">Broader Applications</h3>
<p>These simulation techniques enable various ML applications:</p>
<ul>
<li><strong>Neural network potentials</strong>: Replacing expensive quantum calculations with trained models</li>
<li><strong>Rare event sampling</strong>: ML-enhanced diffusion pathway identification</li>
<li><strong>Catalyst design</strong>: Predicting surface modification effects on reactivity</li>
<li><strong>Materials discovery</strong>: Screening alloy compositions for desired properties</li>
</ul>
<h3 id="getting-started">Getting Started</h3>
<p>To reproduce these simulations:</p>
<ol>
<li>Install LAMMPS with EAM potential support</li>
<li>Download Cu01.eam.alloy from the <a href="https://www.ctcms.nist.gov/potentials/entry/2001--Mishin-Y-Mehl-M-J-Papaconstantopoulos-D-A-et-al--Cu-1/">NIST repository</a> and place in your working directory</li>
<li>Save the LAMMPS script as <code>adatom_cu.lammps</code> and run:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>lammps -in adatom_cu.lammps
</span></span></code></pre></div></li>
<li>Analyze the results with the Python scripts:
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>python plot_energy.py --input energy_avg.txt --output energy.png --skip <span style="color:#ae81ff">30</span>
</span></span><span style="display:flex;"><span>python plot_trajectory.py --input dump.lammpstrj --output trajectory_xy.png
</span></span><span style="display:flex;"><span>python plot_trajectory.py --input dump.lammpstrj --output trajectory_z.png --do_z
</span></span></code></pre></div></li>
<li>Visualize in Ovito by opening <code>dump.lammpstrj</code></li>
<li>Experiment with different temperatures, orientations, or elements</li>
</ol>
<hr>
<p>The full project, including the simulation architecture and automated analysis pipeline, is documented on the <a href="/projects/lammps-adatom-diffusion/">Automated Adatom Diffusion Workflow project page</a>.</p>
<p><em>Questions about the simulation setup or interested in applying these techniques to your research? Feel free to reach out. I&rsquo;m always happy to discuss molecular dynamics and machine learning applications.</em></p>
<h2 id="references">References</h2>
<ul>
<li><a href="https://www.lammps.org/">LAMMPS</a></li>
<li><a href="https://www.ovito.org/">Ovito</a></li>
<li><a href="https://www.ctcms.nist.gov/potentials/">NIST Interatomic Potentials Repository</a></li>
<li><a href="https://doi.org/10.1103/PhysRevB.63.224106">Mishin et al.</a></li>
</ul>
]]></content:encoded></item><item><title>Copper Adatom Diffusion on Cu(100): LAMMPS Simulation</title><link>https://hunterheidenreich.com/videos/cu-adatom-diffusion/</link><pubDate>Wed, 27 Sep 2023 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/videos/cu-adatom-diffusion/</guid><description>LAMMPS molecular dynamics simulation of copper adatom diffusion on a Cu(100) surface, showing atomic mobility mechanisms.</description><content:encoded><![CDATA[<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;">
			<iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube-nocookie.com/embed/nIdbNqEEPys?autoplay=0&amp;controls=1&amp;end=0&amp;loop=0&amp;mute=0&amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"></iframe>
		</div>

<p>Details on the simulation can be found in the <a href="/posts/adatom-cu-diffusion/">Cu Adatom Diffusion on Cu(100)</a> post and the <a href="/projects/lammps-adatom-diffusion/">Automated Adatom Diffusion Workflow</a> project page.</p>
]]></content:encoded></item><item><title>Automated Adatom Diffusion Workflow</title><link>https://hunterheidenreich.com/projects/lammps-adatom-diffusion/</link><pubDate>Thu, 21 Sep 2023 00:00:00 +0000</pubDate><guid>https://hunterheidenreich.com/projects/lammps-adatom-diffusion/</guid><description>Python-wrapped reference implementation for surface diffusion simulations using LAMMPS and EAM potentials, with automated analysis pipelines.</description><content:encoded><![CDATA[<h2 id="overview">Overview</h2>
<p>This project provides an &ldquo;input-to-analysis&rdquo; workflow for simulating adatom diffusion on FCC metal surfaces. It demonstrates how to set up surface diffusion simulations in LAMMPS, manage EAM potentials, and parse trajectory data into energy and trajectory plots using Python. The LAMMPS input scripts are adapted from Eric N. Hahn&rsquo;s adatom tutorial; the Python analysis layer (<code>plot_energy.py</code>, <code>plot_xy.py</code>) is my own, written while in CSElab (Harvard, 2023).</p>
<p>The workflow covers two material systems (Copper (Cu) and Platinum (Pt)) providing comparative datasets that highlight how atomic mass and bonding strength affect surface dynamics.</p>
<h2 id="features">Features</h2>
<h3 id="simulation-architecture">Simulation Architecture</h3>
<p>The project separates simulation logic from analysis code:</p>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Directory</th>
					<th style="text-align: left">Description</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong><code>/adatom_cu</code></strong></td>
					<td style="text-align: left">Copper adatom diffusion on Cu(100)</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong><code>/adatom_pt</code></strong></td>
					<td style="text-align: left">Platinum adatom diffusion on Pt(100)</td>
			</tr>
	</tbody>
</table>
<p>Each directory contains:</p>
<ul>
<li><strong>LAMMPS input scripts</strong> (<code>.in</code> files) defining the physics</li>
<li><strong>EAM potential files</strong> for metallic bonding (the Cu potential is committed; the Pt potential must be downloaded separately from the NIST Interatomic Potentials Repository, so the Pt system does not run as-checked-out)</li>
<li><strong>Python analysis scripts</strong> for trajectory and energy parsing</li>
</ul>
<h3 id="key-features">Key Features</h3>
<ul>
<li><strong>EAM Potentials</strong>: Uses Embedded Atom Method alloy potentials to accurately model metallic bonding and surface energies, providing accuracy beyond simple Lennard-Jones potentials</li>
<li><strong>Automated Analysis</strong>: Python pipeline (<code>plot_energy.py</code>, <code>plot_xy.py</code>) that parses raw thermodynamic logs and trajectory dumps to generate &ldquo;health check&rdquo; dashboards</li>
<li><strong>Workflow Orchestration</strong>: Demonstrates the &ldquo;Input → Simulation → Analysis&rdquo; loop, automating the transition from raw <code>.lammpstrj</code> files to publication-ready plots</li>
<li><strong>Kokkos Support</strong>: Includes Kokkos execution commands for GPU/multi-threaded runs</li>
</ul>
<h3 id="simulation-parameters">Simulation Parameters</h3>
<table>
	<thead>
			<tr>
					<th style="text-align: left">Parameter</th>
					<th style="text-align: left">Value</th>
					<th style="text-align: left">Purpose</th>
			</tr>
	</thead>
	<tbody>
			<tr>
					<td style="text-align: left"><strong>Ensemble</strong></td>
					<td style="text-align: left">NVT → NVE</td>
					<td style="text-align: left">Equilibration followed by energy conservation checks</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Potential</strong></td>
					<td style="text-align: left">EAM/alloy</td>
					<td style="text-align: left">Accurate metallic bonding for surface dynamics</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Minimization</strong></td>
					<td style="text-align: left">CG (1.0e-4)</td>
					<td style="text-align: left">Remove steric overlaps before dynamics</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Timestep</strong></td>
					<td style="text-align: left">5 fs (metal units)</td>
					<td style="text-align: left">EAM-appropriate integration step</td>
			</tr>
			<tr>
					<td style="text-align: left"><strong>Trajectory dump</strong></td>
					<td style="text-align: left">every 5 steps (25 fs)</td>
					<td style="text-align: left">Tracks adatom site-to-site hops</td>
			</tr>
	</tbody>
</table>
<h2 id="usage">Usage</h2>
<p>The repository includes LAMMPS input scripts and Python analysis scripts. Run the LAMMPS scripts to generate trajectory data, then use the Python scripts to visualize the results.</p>
<h2 id="results">Results</h2>
<p>This workflow is documented in detail in companion blog posts:</p>
<ul>
<li><a href="/posts/adatom-cu-diffusion/">LAMMPS Tutorial: Copper and Platinum Adatom Diffusion</a> - Complete setup walkthrough with line-by-line script explanation and comparison of how heavier atoms behave differently on surfaces</li>
</ul>
]]></content:encoded></item></channel></rss>