Search Blogs

Sunday, November 30, 2025

Boltzmann vs. Gibbs: Two Roads

In statistical mechanics, sampling from the Boltzmann distribution is one of those basic principles that quietly sits underneath almost everything we model at equilibrium. It's how you characterize the distribution of microscopic states, estimate thermodynamic averages, and connect the energy landscape to measurable observables like temperature, pressure, composition, etc. Numerically, there are multiple ways to draw samples that represent the equilibrium state. Two of the most instructive ways are:

  1. Use Metropolis–Hastings to construct Markov chains that have the Boltzmann distribution as a stationary distribution.
  2. Use Gibbs sampling as a conditional and local way of doing the same thing.

The idea for this post is to give some context for these two ways of sampling, how they relate, and some general background around why the Boltzmann distribution is both fundamental and annoying to work with in practice.

Energy-Based Models (EBMs)

An energy-based model is simply a system whose probability distribution is defined through its energy function. For a thermodynamic system with degrees of freedom $x$, the probability of a configuration $x$ in the canonical ensemble is given by the Boltzmann distribution:

$$ \begin{equation} P(x) = \frac{e^{-\beta E(x)}}{Z}, \qquad Z = \int e^{-\beta E(x)} \, dx, \qquad \beta = \frac{1}{k_B T}. \label{eq:boltzmann} \end{equation} $$

Here, $E(x)$ is the microscopic energy of configuration $x$, $T$ is temperature, and $Z$ (the partition function1) ensures normalization. For discrete microstates you would replace the integral by a sum. In proper Hamiltonian mechanics you would also need to worry about how we measure phase space, but I'm ignoring that here..

What is important is that ratios of probabilities are set by energy differences:

$$ \frac{P(x')}{P(x)} = \exp\big[-\beta \big(E(x') - E(x)\big)\big] = e^{-\beta \Delta E}. $$

So low energy configurations are exponentially more probable than higher energy ones. For example, if $\Delta E = E(x') - E(x) = k_B T \ln 1000$, then $P(x')/P(x) = 10^{-3}$. This captures the essence of the canonical ensemble, that is, probability ratios are determined solely by energy differences.

There's also a lot of interest in machine learning in using EBMs as world models and for self-supervised learning [1]. In that context you again define an energy $E_\theta(x)$, but the partition function is replaced by various approximate tricks and training objectives, because you almost never compute $Z$ exactly there either.

Equilibrium and the Boltzmann Distribution

When a system is in equilibrium its probability distribution over microstates no longer changes in time. If $P(x,t)$ evolves according to some stochastic dynamics, for example the master equation, Fokker–Planck, Langevin, Glauber dynamics, etc., then at equilibrium $\frac{\partial P(x,t)}{\partial t} = 0$.

From a fluctuation–dissipation viewpoint, the microscopic probability fluxes cancel on average and macroscopic observables become stationary quantities. If we take a system coupled to a heat reservoir at fixed $T$, then the stationary distribution of microstates converges to the Boltzmann distribution in Eq. \ref{eq:boltzmann}.[6]

Estimating Expectations

The expectation value typically corresponds to the ensemble average value of an observable quantity. It's the value one would observe if one could ergodically sample from the system for a very long time. Once $P(x)$ is known, the expectation value of any observable $A(x)$ is

$$ \langle A \rangle = \int A(x)\, P(x) \, dx = \frac{\int A(x)\, e^{-\beta E(x)} \, dx}{\int e^{-\beta E(x)} \, dx}. $$

In practice we estimate the expectation value by sampling configurations $x_i \sim P(x)$ and then taking the sample average as $\langle A \rangle \approx \frac{1}{N} \sum_{i=1}^{N} A(x_i)$. The ergodic hypothesis is what lets us identify this time or trajectory average with the ensemble average, at least if the dynamics explores the full relevant region of phase space.

The Boltzmann Distribution

How did we end up with the Boltzmann distribution in the first place? Of course its due to the namesake for which the distribution is named after, Ludwig Boltzmann. In 1868 he published a paper where he derived the equilibrium velocity distribution and the general structure of what we now call the Boltzmann distribution for a kinetic model of a gas [2]. The resulting distribution expresses the probability of microstate configurations as given in Eq. $\ref{eq:boltzmann}$.

With eq. $\ref{eq:boltzmann}$, low energy states dominate while high energy states fade exponentially. Temperature acts as the control parameter that redistributes these probabilities:

  • $T \to 0$: the system collapses into ground states and very low-lying minima.
  • $T \to \infty$: the system explores accessible states almost uniformly.

The practical challenge is that the partition function, $Z$, is astronomically large for most realistic systems due to the number of degrees of freedom and the effective number of configurations. So direct evaluation or naive summation/integration is basically impossible beyond simple toy models. This is where Markov chain Monte Carlo and Gibbs sampling come in.

Markov Chains and Sampling

To get around the partition function $Z$, we can construct a Markov chain3 whose stationary distribution is the Boltzmann distribution $P(x)$. The trick is that the transition rules only need ratios of probabilities like $P(x')/P(x)$, so the $Z$ cancels nicely.

The basic idea is:

  1. Build an update rule that depends on the current state $x$ and some proposal mechanism.
  2. Make sure the probability of moving from state $x$ to $x'$ matches the probability of moving back, weighted by their relative probabilities under $P(x)$."
  3. Ensure that the chain is ergodic and aperiodic.

Over long times, the sequence of visited states should reproduce the Boltzmann distribution. So the game isn't to write $P(x)$ in closed form, but to engineer a Markov chain that has the correct stationary distribution. So how can we do this? There are two common(?) approaches, the first is the Metropolis–Hastings and the second is Gibbs sampling.

Metropolis–Hastings: Energy-Based Acceptance

The Metropolis–Hastings algorithm feels like an experimental perturbation process [3,4], that is we start with some initial setup, $x$, and then propose a new state, $x'$, and then decide to accept or reject the proposal if it gave a better result (i.e. lower energy). The steps to implement would be:

  1. Start with, $x$, propose a move $x \to x'$ from some prior distribution $q(x' \mid x)$.
  2. Compute the energy difference $\Delta E = E(x') - E(x)$.
  3. Accept the move with probability $$ \begin{equation} p_{\text{acc}}(x \to x') = \min\left(1, e^{-\beta \Delta E} \frac{q(x \mid x')}{q(x' \mid x)}\right). \label{eq:metropolis} \end{equation} $$

For symmetric proposals where $q(x' \mid x) = q(x \mid x')$, that is the reverse is equally likely as the forward, this reduces to,

$$ p_{\text{acc}}(x \to x') = \min\left(1, e^{-\beta \Delta E}\right). $$

If the move lowers the energy then it is always accepted. If it raises the energy, it may still occur with Boltzmann-weighted probability4. This acceptance rule enforces detailed balance with respect to Eq. \ref{eq:boltzmann}. Under standard conditions, the chain converges to the Boltzmann distribution as the unique stationary distribution.[3,4]

The pain point with Metropolis–Hastings is that in high dimensional systems, many naive proposals (i.e. transition moves) are rejected and the chain diffuses slowly through configuration space. This means long simulation times despite the equilibrium distribution being formally correct. So getting good sampling in a reasonable amount of wall clock time can be challenging if not impossible.

Gibbs Sampling: Conditional Equilibrium

One very useful alternative is Gibbs5 sampling [5]. Instead of proposing global moves, Gibbs sampling uses local conditional updates and draws from exact conditional distributions whenever those are tractable. The key difference from Metropolis–Hastings is that Gibbs sampling doesn't propose and then accept/reject—it samples directly from the conditional distribution, which already has the correct Boltzmann weighting built in. For example, on a spin-lattice, instead of flipping a spin and then deciding whether to accept the flip based on the energy change (as Metropolis–Hastings does), Gibbs sampling directly picks the new spin value with the correct probability given its neighbors. Since we're sampling from the right distribution from the start, every update is automatically accepted.

How do we get the exact probability? if we take a spin-site with 4 neighbors, the energy interaction depends only on those neighbors. We can compute the Boltzmann probability for each possible spin value given those interactions, then normalize. That's it—just a few local energy terms, not the entire system.

     +1
      |
+1 -- X -- +1
      |
     +1

For the center spin $X$ with all neighbors $+1$ as shown above, the energy contribution is:

$$ \begin{align} E(X=+1) &= -J\big[(+1)(+1) + (+1)(+1) + (+1)(+1) + (+1)(+1)\big] \nonumber \\ &= -J(4) = -4J \nonumber \end{align} $$

$$ \begin{align} E(X=-1) &= -J\big[(-1)(+1) + (-1)(+1) + (-1)(+1) + (-1)(+1)\big] \nonumber \\ &= -J(-4) = 4J \nonumber \end{align} $$

Then we get the unnormalized probabilities:

$$ P(X=+1) \propto e^{-\beta E(X=+1)} = e^{4\beta J}, \qquad P(X=-1) \propto e^{-\beta E(X=-1)} = e^{-4\beta J} $$

To normalize, we divide by the sum:

$$ P(X=+1) = \frac{e^{4\beta J}}{e^{4\beta J} + e^{-4\beta J}}, \qquad P(X=-1) = \frac{e^{-4\beta J}}{e^{4\beta J} + e^{-4\beta J}} $$

Now $P(X=+1) + P(X=-1) = 1$ and we can sample from this distribution. The aligned state ($X=+1$) is exponentially more probable than the anti-aligned state. As you see we are conditioning on the neighbors, that is we are sampling from the conditional distribution $P(X \mid X_1, X_2, X_3, X_4)$.

So now if we have the energy in terms of many degrees of freedom, $E(x_1, x_2, \ldots, x_N)$, with Gibbs sampling we can update one variable at a time by drawing from its conditional distribution given all the others:

$$ \begin{equation} x_i^{(t+1)} \sim P(x_i \mid x_{-i}^{(t)}) \propto \exp\left[-\beta E\big(x_i, x_{-i}^{(t)}\big)\right]. \label{eq:gibbs} \end{equation} $$

Here $x_{-i}$ means all degrees of freedom except $x_i$. The proportionality is indicating that you still have to normalize over the allowed values of $x_i$, but you never need the global partition function $Z$ which is big savings.

To recap, each degree of freedom is sampled from its local equilibrium distribution. There are no proposals to reject, so every update is "accepted" simply by construction of the conditional sampling. In many lattice models, the Hamiltonian is a sum of local terms, which means the conditional $P(x_i \mid x_{-i})$ depends only on neighboring variables. So the cost of an update is dominated by very local energy evaluations, not global ones.

In that sense, Gibbs sampling is Boltzmann sampling by conditional decomposition2. It's exact when those conditionals can be written down and sampled efficiently (i.e., the interactions are local), which is the case for a fair amount of models like the Ising model, Potts model, and more general Gibbs random fields in image analysis.

So Boltzmann or Gibbs?

The title was a bit of a mismatch since the Boltzmann distribution is the underlying thing we are trying to sample from, so Boltzmann and Gibbs aren't in competition in any meaningful sense. The main challenge with trying to use the analytical Boltzmann distribution is we can't meaningfully determine the partition function for toy and real-world systems. So what we do instead is:

  • Take the Boltzmann distribution as the target equilibrium distribution.
  • Construct Markov chains whose stationary distribution is exactly that Boltzmann measure.
  • Use different update strategies to actually explore the state space.

Both Metropolis–Hastings and Gibbs sampling are Markov chain Monte Carlo (MCMC) methods that construct Markov chains converging to the same Boltzmann distribution. They differ fundamentally in their update mechanisms:

With Metropolis–Hastings it proceeds by proposing candidate states from a proposal distribution $q(x' \mid x)$ and then accepting or rejecting them based on the energy difference. Gibbs sampling exploits conditional probablity structure by directly sampling from the exact local distributions: $P(x_i \mid x_{-i})$. As a result the the sampled outcome is the update. In systems with local interactions, this makes the process efficient because it avoids global energy evaluations. This means no wanted proposals as in Metropolis-Hastings, but its again only practical when the conditional distributions can be computed efficiently. So Gibbs isn't replacing Boltzmann. It's helping Boltzmann by providing a conditional route to sampling from the same equilibrium distribution.

Gibbs as a special case

Gibbs can be viewed as a special case of Metropolis where the proposal distribution is chosen to be the exact conditional $P(x_i \mid x_{-i})$. In that case the Metropolis–Hastings acceptance probability is identically one, so every proposal is accepted and the chain still converges to the same Boltzmann (Gibbs) distribution.

Both Metropolis–Hastings and Gibbs sampling should approach Eq. $\ref{eq:boltzmann}$ as the number of steps increases. Again they only differ in how they traverse state space and in which cases they are practical.

Method Update rule Uses proposals? Acceptance step Typical use
Metropolis–Hastings Random move + accept/reject Yes Yes, via $p_{\text{acc}}(x \to x')$ Very general purpose, can wrap many proposal types
Gibbs Sampling Exact conditional resampling No Always accepted Structured models with tractable conditionals

Numerical Example

Below is a simple example for a 2-site Ising model with 4 possible microstates. The energy function for a configuration is given by:

$$ E(x) = -J x_1 x_2 $$

where $J$ is the interaction strength and $x_i \in {-1, +1}$ is the spin state at site $i$. We set $J = 1$ and $T = 1$ (so $\beta = 1$). The four possible microstate configurations are:

$$ \begin{align} x_1 &= 1, \quad x_2 = 1 \nonumber \\ x_1 &= 1, \quad x_2 = -1 \nonumber \\ x_1 &= -1, \quad x_2 = 1 \nonumber \\ x_1 &= -1, \quad x_2 = -1 \nonumber \end{align} $$

The Python code below uses both the Metropolis–Hastings and Gibbs sampling algorithms to sample from this system:

import numpy as np
from prettytable import PrettyTable, MARKDOWN

beta, J = 1.0, 1.0
states = np.array([[+1,+1],[+1,-1],[-1,+1],[-1,-1]])

def Ising(s): return -J*s[0]*s[1] # Energy

def boltzmann(E):
    p = np.exp([-beta*E(s) for s in states])
    return p/p.sum()

def metropolis(E,T=10000):
    """Single-spin flips, accept exp(delta E / kT)"""
    s=np.array([1,1]); out=[]
    for _ in range(T):
        i=np.random.randint(2); s2=s.copy(); s2[i]*=-1
        if np.random.rand()<np.exp(-beta*(E(s2)-E(s))): s=s2
        out.append(s.copy())
    return np.array(out)

def gibbs(E,T=10000):
    """P(s_i | s_j) \\prop exp( J s_i s_j / kT)"""
    s=np.array([1,1]); out=[]
    for _ in range(T):
        for i in (0,1):
            p_up=np.exp(beta*J*s[1-i]); p_dn=np.exp(-beta*J*s[1-i])
            s[i]=+1 if np.random.rand()<p_up/(p_up+p_dn) else -1
        out.append(s.copy())
    return np.array(out)

def tally(S):
    c=np.zeros(4)
    for s in S:
        for k,st in enumerate(states):
            if (s==st).all(): c[k]+=1
    return c/len(S)

tbl = PrettyTable(["Microstate",
                   "Exact",
                   f"Metropolis",
                   f"Gibbs"])
tbl.set_style(MARKDOWN)
[tbl.add_row([i+1] + [f"{x:.3f}" for x in row])
 for i,row in enumerate(np.vstack([boltzmann(Ising),
                                   tally(metropolis(Ising)),
                                   tally(gibbs(Ising))]).T)]

Which gives the following table:

Microstate Exact Metropolis Gibbs
1 0.440 0.438 0.445
2 0.060 0.062 0.060
3 0.060 0.057 0.062
4 0.440 0.443 0.433

As you can see, both the Metropolis–Hastings and Gibbs sampling algorithms converge fairly well to the exact Boltzmann distribution, with the sampled probabilities matching the theoretical values quite closely. If you run longer chains (more samples), you'll see even closer agreement.

Footnotes


  1. The partition function is the sum (or integral) of $e^{-\beta E(x)}$ over all microscopic states of the system. For anything beyond very small or highly symmetric systems this is a combinatorial explosion and cannot be evaluated exactly. In practice we work with ratios of probabilities where $Z$ cancels, or we approximate it using specialized methods. Conceptually, $Z$ is the normalization constant that turns $e^{-\beta E(x)}$ into a proper probability distribution. 

  2. Conditional decomposition just means writing a joint distribution in terms of conditionals. For example, a generic factorization is $P(x_1,\ldots,x_N) = \prod_{i=1}^N P(x_i \mid x_1,\ldots,x_{i-1})$. In Gibbs sampling we exploit the fact that for Gibbs measures of the form $P(x) \propto e^{-\beta E(x)}$ with local interactions, the conditionals $P(x_i \mid x_{-i})$ depend only on a local neighborhood, so they can be computed and sampled efficiently. Gibbs sampling then builds a Markov chain by resampling these local conditionals one variable (or one block) at a time. 

  3. A Markov chain is a sequence of random variables $X_0, X_1, X_2, \ldots$ such that the probability of transitioning from state $X_i$ to state $X_{i+1}$ depends only on the current state $X_i$ and not on the previous states $X_0, X_1, \ldots, X_{i-1}$. In other words, we do not require full knowledge of the trajectory/history of the system to determine the future state(s). 

  4. This just means that we weight the probability of the move occuring despite not lowering the energy by the factor $e^{-\beta \Delta E}$. 

  5. Gibbs is the surname of the Josiah Willard Gibbs, who was a major figure in statistical mechanics and thermodynamics in the late 19th century. 

References

[1] Y. LeCun, S. Chopra, R. Hadsell, M. Ranzato, F. Huang, "A Tutorial on Energy-Based Learning," in Predicting Structured Data, MIT Press (2006).

[2] L. Boltzmann, "Studien über das Gleichgewicht der lebendigen Kraft zwischen bewegten materiellen Punkten," Sitzungsberichte der Akademie der Wissenschaften zu Wien 58, 517–560 (1868).

[3] N. Metropolis, A. W. Rosenbluth, M. N. Rosenbluth, A. H. Teller, E. Teller, "Equation of State Calculations by Fast Computing Machines," Journal of Chemical Physics 21, 1087–1092 (1953). DOI.

[4] W. K. Hastings, "Monte Carlo Sampling Methods Using Markov Chains and Their Applications," Biometrika 57, 97–109 (1970). DOI.

[5] S. Geman, D. Geman, "Stochastic Relaxation, Gibbs Distributions, and the Bayesian Restoration of Images," IEEE Transactions on Pattern Analysis and Machine Intelligence PAMI-6(6), 721–741 (1984). DOI.

[6] L. D. Landau, E. M. Lifshitz, Statistical Physics, 3rd ed., Course of Theoretical Physics Vol. 5, Pergamon Press, Oxford (1980).


Reuse and Attribution

Saturday, October 25, 2025

Backups for Headless Linux

On my home network I have a headless Linux server that I use for a variety of tasks. One of the problems is that I can't use Deja Dup to backup the data on the server because it requires a GUI. I'm not sure why this is, but it is what it is. So I needed to find a way to backup the disks.

For some time I had used rsnapshot to take regular backups but the problem is it doesn't have a nice way to restore or find files other than searching through the folder tree, which is fine but sometimes annoying. Also there is a lot of manual config stuff I had to set to get it to behave the way I want because it doesn't use deduplicating backups but rather hard linking. The reason deduplicating backups are nice is they only perform incremental deltas and make efficient use of storage resources.

Fortunately I was able to find, maybe late to the game actually, two CLI tools that are pretty good for this purpose. The first is borgbackup. The other is restic.

Borgbackup

Borgbackup is a deduplicating backup tool ... interesting name though. Seems to be a pretty modern backup tool that is designed to be fast, secure, and efficient. Ideally it focuses on backing up and restoring your data. I had it setup, you can install from Ubuntu repos using sudo apt install borgbackup, but the downside is it doesn't really support cloud storage directly, although through rclone I think you can get it to work, on that note let me talk about rclone.

Rclone

One of the biggest gripes I have about Google is that they don't have a native Linux client/tool to support Google Drive. It is pretty ridiculous in my opinion, but for a long time the rclone project has been a great solution; it's generally cross-platform and supports a lot of cloud storage providers. It is a command line tool to sync files and directories to and from various cloud storage providers. To be honest I'm not too strong with its configuration and structure because on my personal laptop I use insync to sync my Google Drive; I paid $4.99 for a lifetime license and have been grandfathered into the newer versions which are subscription based.

The thing with rclone is if you just go through the generic setup you will have to use the rclone org's built-in Google API Client ID which is going to most likely be rate-limited and have other quotas. So the best thing to do is to create your own Google API Client ID and use that. You'll have to login to console.cloud.google.com and create a new project. Then you can go to APIs & Services > Credentials and create a new credentials for your internal use. Save the output from this its the Client ID and Client Secret.

Configuring Google API Client ID

Then when your setting up rclone and it asks you if you want to setup your own Google API Client ID then input the Client ID and Client Secret you just created. Then you can proceed to setup the rest of the configuration. This will allow you to experience a much more fully transport sync and backup experience. Essentially you have a way to sync your local filesystem to Google Drive and vice versa. Going to leave it there for now.

Restic

So with Borgbackup not being so friendly to cloud storage or rclone. I kept on my search and found restic, which supports rclone natively. The main command to leverage the restic repo (thats how they name things) is:

restic -r rclone:GoogleDrive:Backup init
restic -r rclone:GoogleDrive:Backup <commands>

This creates a backup repository using rclone on your configured Google Drive and it calls the folder Backup in your Google Drive. You can then use the following commands to backup your data:

restic -r rclone:GoogleDrive:Backup backup <path/want/to/backup>
restic -r rclone:GoogleDrive:Backup restore <snapshot_id> --target <path/where/to/restore>
restic -r rclone:GoogleDrive:Backup list snapshots
So the thing is, this is all manual and you'll most likely want to alias things so that it's more natural, because you could have several different restic repositories that you're backing your data onto. The other thing is you will want this to occur through a cron job or some other automated process that way you have regular backups and you don't have to remember to run the commands manually.

There is the downside that restic requires that you password encrypt your backups. So you can't view these backups directly, you have to leverage restic to view them and or mount them with say FUSE to view them locally.

Automating

To achieve regular backups without having to manually run the restic commands, the simplest solution is to just setup a cron job. Run something like:

crontab -e
# Run backup script daily at 2 AM
0 2 * * * /home/user/backup_script.sh

where the backup_script.sh is just a wrapper bash script for running restic and possibly any webhook notifications you want. You can add any logging stdout you want as well.

#!/bin/bash
export RESTIC_PASSWORD_FILE="/path/to/user/.restic_password"
REPO="rclone:GoogleDrive:Backup"
restic -r $REPO backup /location/to/backup
... other restic commands ...

Notice that you'll have to set the RESTIC_PASSWORD_FILE environment variable to the path to the file that contains your restic password for the repo you are backing up 😠.

Backup frequency and retention

The cron job just runs the backup_script.sh script at the specified time but it is not responsible for the backup frequency and retention policies. Although if you have daily backups that occur more than once you would want the cron job to run at that same frequency so that you keep the backups consistent.

So say you want to keep daily backups for 7 days, weekly for 4 weeks, and monthly for 12 months. You would want to run the following command after each backup:

restic -r rclone:GoogleDrive:Backup forget --keep-daily 7 --keep-weekly 4 --keep-monthly 12

# Removes the actual stale backups
restic -r rclone:GoogleDrive:Backup prune

The prune command actually removes the data that's no longer needed, while forget just marks snapshots for deletion. The forget command is more like a "soft delete" in that it marks the snapshots for deletion but doesn't actually remove the data. The prune command is more like a "hard delete" in that it actually removes the data.

Performance Considerations

Because I backup directly to Google Drive, I've noticed it's very slow and time consuming. This probably means I need to tune the restic command to be more efficient like using parallel uploading or changing the chunking size.

Final Thoughts

I'm finding that rclone + restic is a pretty good combination for my needs. The deduplication will prevent a lot of Google Drive storage consumption. I don't really care about the data encryption (wish I could turn off) but it is what it is. I think if you're working on a headless server (e.g. self-managed compute cluster) and you want to backup data on your network, this is a pretty reasonable solution.

The one thing I can't speak to is how syncing behaves, where you're working on two systems and need files to be locked and synced properly as you work on those files. Like I mentioned on my personal laptop I use insync to sync my Google Drive and this works pretty well.


Reuse and Attribution

Saturday, September 27, 2025

I now know why Boron Carbide shatters

Hard high-temperature ceramics is an area I've been involved with throughout my career. One of these materials is Boron Carbide. The B₄C polymorph is one of the hardest known materials and is incredibly lightweight due to its constituents and density. These attributes make B₄C a leading candidate for personal body armor, vehicle shielding, and other high-impact applications. Its remarkable properties originate from its rhombohedral crystal structure that consists of a 12-atom icosahedra that are connected by stiff three-atom chains.

Figure 1. Unit cell of B₄C with 12-atom icosahedra & C-B-C fragment (Materialscientist, CC BY-SA)

Despite its exceptional hardness boron carbide exhibits a critical weakness under high-speed impact: it can fail catastrophically through amorphization, where the ordered crystal collapses into a glassy/disordered state. This phase change results in loss of outstanding hardness and strength. For a long time the atomic-scale mechanisms behind this phenomenon weren't really well characterized or understood. I remember shock physics molecular dynamics studies trying to look at this and it was never quite clear what the incipient (i.e. onset/preceding) steps were to amorphiziation. From a modeling perspective, a lot of it is related to the ability of interatomic potentials to capture the atomic-scale process. That seems to have changed. A recent study by Ghaffari et al. [1] used machine-learned interatomic potentials (MLIPs) and MD simulations to reveal how the crystal orientation, polymorphism, and velocity impact the amorphization failure process.

One of the nails in the coffin, so to speak, is shown in Figure 2, which reveals thin amorphous bands forming at ~45° relative to the impact direction, demonstrating the shear-driven nature of failure. Previous MD simulations could not reproduce this experimentally observed phenomenon.

Figure 2. Amorphous bands at ~45° relative to impact (Fig. 4 from Ghaffari et al. 2025)

The Paradox of Boron Carbide

The exceptional hardness of most carbides, like B₄C (Vickers ≥ 30 GPa)1, originate from the covalent bonds, and in the case of B₄C its icosahedra and three-atom chains. However, under dynamic loading beyond its Hugoniot Elastic Limit (HEL), which is the transition condition where a material goes from elastic to plastic deformation under shock loading and for B₄C it is experimentally around 20 to 25 GPa. So under shock loading B₄C softens instead of hardening, exhibiting glass-like mechanical behavior [1]. Amorphization degrades the structure of the material by breaking up icosahedral cages, resulting in loss of long-range order, and therefore sharp reduction in shear strength and hardness. In experiments they have observed narrow amorphous bands forming along shear planes [2-4], but these of course lacked temporal and spatial resolution to identify the atomic processes responsible for the amorphization.

New kid on the block: MLIPs

I've posted a bit on this blog about machine-learned interatomic potentials (MLIPs) because they have shifted the type of classical atomistic simulations that can be now, mostly in terms of chemistries simulated, but with the work by Ghaffari et al. [1] its pushed this to new physics regimes and mechanisms. From what I recall, simulating shock physics amorphization in carbides has been a challenge with classical interatomic potentials. I'm sure some have tried AIMD but the spatial scale would always be the limiting factor, i.e., nearly impossible to capture the amorphous band formation. Force fields such as ReaxFF have been tried [5] but fail to reproduce the observed experimental features. Ghaffari et al. [1] address this by developing a machine-learned interatomic potential trained on DFT-calculated structures for four dominant polymorphs, amorphous phases, and high-pressure states. Using DeePMD-kit, the resulting model achieved high accuracy and enables MD simulations of systems scaled up to ~450K atoms.

tl;dr

Simulations using their trained boron carbide MLIP model successfully capture shear-induced amorphous band formation for the first time, directly matching experimental observations and providing atomistic process responsible for the amorphization.

So what did they find?

I mentioned earlier in Figure 2 that the amorphous bands formation being directly observed in the MD simulations. This was one of the key results that they were able to achieve, but some other important details were also revealed.

1. Crystal Orientation Strongly Influences HEL

The HEL depends strongly on the orientation of the three-atom chain relative to the impact direction. The lowest HEL values, between 18 and 22 GPa, occurred when the chains were either aligned parallel or perpendicular to the impact. In contrast, orientations such as 45° and 60° showed the highest HEL values, between 32 and 38 GPa [1]. This seems to overturn the earlier assumptions from ReaxFF-based simulations [5] that aligning the orientation with the least compliance with the impact direction would maximize strength. But what the results in the paper indicate is the failure is driven primarily by shear stress rather than compression. Amorphous bands consistently form at planes oriented approximately 45° from the impact direction, corresponding to the planes of maximum shear stress.

2. Polymorphism Governs Toughness

Boron carbide polymorphs differ subtly in atomic arrangement but behave very differently under shock loading, as highlighted in Figure 3. The paper directly compares B₁₂(CBC), which contains a C–B–C chain, and B₁₂(CCC), which has a C–C–C chain, revealing how polymorphism controls toughness. B₁₂(CBC) exhibits the highest Hugoniot Elastic Limit (HEL) and the greatest resistance to amorphization, surviving shock by forming amorphous bands that expand in volume. In contrast, B₁₂(CCC) has a much lower HEL and fails via irreversible structural collapse and significant volume shrinkage. This difference is directly linked to the atomic arrangement: in B₁₂(CBC), the middle boron atom temporarily migrates into a cage space during compression and returns upon unloading, resulting in reversible chain bending and recovery of the lattice structure. For B₁₂(CCC), the central carbon atom instead forms permanent bonds with nearby icosahedra due to the higher bond dissociation energy of C–B bonding (448 KJ/mol) relative to B–B bonding (297 KJ/mol), leading to irreversible bonding, collapse, and densification. Figure 4 provides side-by-side atomistic snapshots of these chain mechanics, illustrating the reversible bending and recovery in CBC versus the irreversible bonding and collapse in CCC. Figure 5 further strengthens this mechanistic explanation by showing the cage-space migration pathway that enables reversibility in CBC.

Figure 3. Reversible vs Irreversible Chain Bending (Fig. 8 from Ghaffari et al. 2025)

Figure 4. Reversible vs Irreversible Chain Bending (Fig. 10 from Ghaffari et al. 2025)

Figure 5. Cage-Space Migration (Fig. 11 from Ghaffari et al. 2025)

3. Two Distinct Regimes of Amorphization

The study also identifies two fundamentally different deformation regimes controlled by impact velocity [1]. In Figure 6 the response to 2.5, 3.0, and 4.0 km/s shocks is shown and it establishes distinct band-dominated versus collapse-dominated regimes. At 2.5 km/s, localized amorphous bands dominate, and the volume inside these bands expands by ~6% relative to the surrounding crystal lattice, which then suppresses crack initiation (i.e. extrinsic toughening). At 3.0 km/s, amorphous banding and partial structural collapse both coexist. But at 4.0 km/s and above, widespread collapse of icosahedral units occurs, producing significant volume shrinkage and creating voids that promote crack growth. The preservation or destruction of icosahedral motifs determines whether a region undergoes expansion, local compressive shielding, or irreversible densification.

Figure 6. Atomic Volume Variation

Implications for Materials Design

The results from Ghaffari et al. [1] provide an atomic-level framework for designing boron carbide that is more resistant to amorphization. Orienting grains to align their stiffest chains with the planes of maximum shear resistance, approximately 45°, increases HEL and delays failure. Favoring polymorphs containing C–B–C chains during synthesis improves toughness by enabling reversible chain bending and reducing susceptibility to catastrophic collapse. Furthermore, the demonstrated accuracy of machine-learned interatomic potentials shows that AI-driven simulations are now a critical tool for predicting material behavior under extreme conditions and guiding the design of next-generation superhard ceramics.

Footnotes


  1. In contrast to Boron Carbide, Tungsten carbide is another hard and refractory material, but Tungsten carbide density is ~7x (15.7 g/cm³) that of Boron Carbide. I believe the hardness of Boron Carbide is also slightly higher than that of Tungsten carbide. 

References

[1] K. Ghaffari, S. Bavdekar, D.E. Spearot, G. Subhash, Influence of Crystal Orientation and Polymorphism on the Shock Response of Boron Carbide, SSRN Preprint, (2025). https://ssrn.com/abstract=5186595.

[2] G. Parsard, G. Subhash, P. Jannotti, Amorphization-Induced Volume Change and Residual Stresses in Boron Carbide, Journal of the American Ceramic Society. 101 (2018) 2606–2615. https://doi.org/10.1111/jace.15442.

[3] M. Chen, J.W. McCauley, K.J. Hemker, Shock-Induced Localized Amorphization in Boron Carbide, Science. 299 (2003) 1563–1566. https://doi.org/10.1126/science.1080067.

[4] K.M. Reddy, P. Liu, A. Hirata, T. Fujita, M.W. Chen, Atomic Structure of Amorphous Shear Bands in Boron Carbide, Nature Communications. 4 (2013) 2483. https://doi.org/10.1038/ncomms3483.

[5] A.A. Cheenady, A. Awasthi, M. DeVries, C. Haines, G. Subhash, Shock Response of Single-Crystal Boron Carbide Along Orientations with the Highest and Lowest Elastic Moduli, Physical Review B 104 (2021) 184110. https://doi.org/10.1103/PhysRevB.104.184110



Reuse and Attribution