<?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>Ovito on Hunter Heidenreich | Senior AI Research Scientist</title><link>https://hunterheidenreich.com/tags/ovito/</link><description>Recent content in Ovito 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, 11 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://hunterheidenreich.com/tags/ovito/index.xml" rel="self" type="application/rss+xml"/><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></channel></rss>