Deep, code-cited reference. See the readable summary for the public version. This page is the full provenance: canonical formula, cleaved↔uncleaved pairing, rollup schema, best-available rule, error taxonomy.
Work of Separation Benchmark — Methodology
Scientific and numerical specification of the cleavage (W_sep) track for the
mlip-benchmark-gbsegbench corpus. Covers the canonical W_sep formula, how
the cleaved↔uncleaved pair is matched in the DB, the per-(potential,
structure_id) best-available rule, the rollup CSV schema, and the error
taxonomy used by the leaderboard.
Reference implementation: benchmark/build_wsep_dfs.py (the CLEAVAGE_SQL
linkage query plus the per-potential W_sep column build).
1. Quantity computed
For each cleavage row, the work of separation in J/m² is the textbook single-plane normalization
W_sep = (E_cleaved - E_uncleaved) / A_plane · EVA2_TO_JM2 [J/m^2]
with EVA2_TO_JM2 = 16.02176565 (the constant in build_wsep_dfs.py:39)
and A_plane = the area of the one cleavage plane in Ų.
Sign convention. Positive ⇒ energy required to separate the two
half-cells. W_sep is the adhesion energy of the interface, not the
surface energy γ of a free surface (γ = W_sep / 2 for an ideal symmetric
cleave).
How A_plane is sourced — important convention note
Historically the cleavage rows were ingested with extra->>'area_A2' set
equal to 2 · A_plane — i.e. the total free-surface area created by
the cleave (two faces, each of area A_plane). The pre-computed DFT
quantity stored as extra->>'W_sep_J_per_m2' followed
W_sep_stored = ΔE / (2·A_plane), which is the surface energy γ, not
the textbook work of separation.
The current build_wsep_dfs.py restores the textbook convention by
multiplying the stored γ values by 2 on read and by NOT applying the extra
/2 in the surrogate formula. Operationally:
# DFT side (build_wsep_dfs.py:128)
df["dft_w_sep"] = df["dft_w_sep"] * 2.0 # γ → W_sep
# MLIP side (build_wsep_dfs.py:163-164)
w = 2.0 * (E_cleaved - E_uncleaved) / area_a2 * EVA2_TO_JM2
≡ (E_cleaved - E_uncleaved) / A_plane * EVA2_TO_JM2 [A_plane = area_a2 / 2]
Both sides now publish the same convention. Every wsep_* metric on the
live leaderboard is the corrected (×2) value; a representative row
(GRACE-2L-OAM-L, Fe-host, S5-RA001-S210, n_pairs = 7410) shifted from
wsep_rmse_jm2 = 2.411321 → 4.822641 (exactly 2×); Spearman ρ unchanged
at 0.828861 (scale-invariant under uniform rescaling).
| Symbol | Meaning |
|---|---|
E_cleaved |
total energy of the cleaved GB structure (two half-cells, one cleave plane) |
E_uncleaved |
total energy of the uncleaved precursor (same cell, no cleave) |
area_a2 |
(extra->>'area_A2')::float; = 2 · A_plane (the sum of the two free-surface areas, by ingest convention) |
A_plane |
the area of the single cleavage plane in Ų (= area_a2 / 2) |
EVA2_TO_JM2 |
unit-conversion constant 16.02176565 (1 eV/Ų = 16.02176565 J/m²) |
cleave_idx |
enumerated cleave-plane index within the parent GB |
cleave_z_frac |
normalised z-position of the cleave plane |
DB key: (structure_id, potential) for the cleaved row; the uncleaved
energy is joined in on demand.
2. Cleaved↔uncleaved pairing (the linkage SQL)
The structure.extra jsonb on a cleavage row carries:
base_job_name— thejob_nameof the uncleaved precursorarea_A2— the cleavage area in Ų (×2 already folded in)W_sep_J_per_m2— pre-computed DFT W_sep, ingested alongsideE_uncleaved— DFT energy of the uncleaved precursor (for cross-check)cleave_idx,cleave_z_frac— cleave-plane identifiers
The linkage SQL (build_wsep_dfs.py:34-66) joins:
SELECT c.*, bp.base_id, bp.base_atoms_hash, bp.base_dft_energy
FROM cleav c
LEFT JOIN base_pick bp ON bp.cleav_id = c.cleav_id;
Where cleav is state='Cleavage' AND extra->>'W_sep_J_per_m2' IS NOT NULL,
and base_pick resolves the uncleaved precursor by:
JOIN structure b ON b.job_name = c.base_name AND b.state != 'Cleavage'
ROW_NUMBER() ... ORDER BY b.id -- lowest id when multiple variants match
Multiple structures may share the same base_job_name (KP / KS / OMAT
sibling generation), but they all map to the same atoms_hash (de-duplicated
on ingest), so any one resolves to the same MLIP energy. The
ROW_NUMBER() tiebreak just picks the lowest-id sibling deterministically.
3. Why no W_sep_corrected
W_sep is a difference of total energies between two cells of the same
composition (the cleaved pair and its uncleaved precursor). The
per-(composition, ISPIN) offset corrections used on the ASSYST single-point
track cancel by construction in the formula. We do NOT emit a
W_sep_corrected column on this track.
4. Best-available algorithm rule
Relaxation initial frame. As on the segregation track, the MLIP relaxation is initialised from the unrelaxed (as-constructed / DFT-input) geometry — the relaxation's initial frame is the unrelaxed structure, not the DFT-relaxed frame.
The cleavage corpus rides the same relaxation campaign as the segregation
corpus. For each (potential, structure_id) the rollup picks the
best-available result:
algo_used = 'BFGS' if status_BFGS == 'done'
else 'FIRE' if status_FIRE == 'done'
else NULL (excluded)
energy_used = E_final from algo_used
A W_sep value is reported only when both the cleaved row AND its
uncleaved precursor have a best-available done energy for that potential.
Missing either ⇒ NaN ⇒ row excluded from the rollup.
Per-row provenance is preserved via algo_used_cleaved,
algo_used_uncleaved, and per-potential counts n_best_from_bfgs,
n_best_from_fire (a row counts toward n_best_from_fire if either side
came from FIRE).
5. Outlier filter
The build script filters catastrophic MLIP failures (build_wsep_dfs.py:32, 137):
OUTLIER_LIMIT = 1e4 # eV per cell
if energy is None or not np.isfinite(energy) or abs(energy) > OUTLIER_LIMIT:
drop this (pot, atoms_hash) pair
For a typical 50–200 atom GB cell, |E| > 1e4 eV is unphysical — usually
an MLIP exploding on an out-of-distribution element. The energy stays in
mlip_calc; it just doesn't propagate into W_sep.
6. Rollup CSV schema (per_potential_wsep.csv)
One row per (potential, host, GB, partition) bucket plus __all__
aggregate rows. Consumed by /cleavage and the cleavage drill-down on
/elements/[el].
| column | type | meaning |
|---|---|---|
potential |
str | normalized potential id |
display_name |
str | display name from metadata.json / gbseg-metadata.json |
host |
str | Fe or Ni |
gb |
str | grain-boundary id |
partition |
str | gbseg-cleavage (the only partition on this track) |
n_pairs |
int | number of (cleavage_row, potential) with W_sep on both sides |
n_best_from_bfgs |
int | count of pairs where both sides came from BFGS |
n_best_from_fire |
int | count of pairs where either side came from FIRE |
wsep_rmse_jm2 |
float | RMSE of (W_sep^MLIP − W_sep^DFT) in J/m² |
wsep_mae_jm2 |
float | MAE of the same |
wsep_spearman |
float | Spearman ρ of W_sep^MLIP vs W_sep^DFT |
snapshot_date |
date | per-potential rollup-build date |
The headline number on the leaderboard is wsep_rmse_jm2 from the
__all__ row, count-weighted across (host, GB).
7. Aggregation (count-weighted, two-step)
Matches the ASSYST headline pattern:
- Per-bucket at
(potential, host, gb, partition)level:RMSE = sqrt(mean((W_sep^MLIP - W_sep^DFT)^2)),MAE,Spearman ρover the cleavage pairs where the MLIP has best-availabledoneon both sides. - Top-line at
(potential, partition)level: count-weighted mean of the bucket-level metrics, weights =n_pairsper bucket.
Both wsep_rmse_jm2 and wsep_mae_jm2 are emitted. RMSE is the
default leaderboard headline; MAE is shown alongside.
8. Error taxonomy
Same five-class enum as the segregation track (see /methodology/deep/segregation §7). On W_sep, the relevant rule of thumb is:
- A cleavage row counts toward the rollup when both
(cleaved, pot)and(uncleaved, pot)are in classnone(best-availabledone). - Either side in class
unsupported_element(Z = 84–88) ⇒ excluded. This is rare on cleavage because the cleave plane is in the host material, but is the standard rule. - Either side
diverged/step_cap/env_flake⇒ excluded.
The errored sides are surfaced on the errors.parquet.py loader, scoped
to gbseg-cleavage.
9. Implementing code
benchmark/build_wsep_dfs.py— canonical formula, the cleaved↔uncleaved linkage SQL, and the surrogate W_sep build (one column per potential).benchmark/plot_wsep.py,benchmark/plot_wsep_per_element.py— plotting (used to vet the rollup pre-vendor).benchmark/eval/build_gbseg_rollup.py— count-weighted two-step aggregation (Task B will vendor this output).
Linked into the wiki hub at
/u/hmai/llm-wiki/wiki/mlip-benchmark-gbsegbench-relax.md.
10. Partitions
partition |
corpus | comment |
|---|---|---|
gbseg-cleavage |
FeGB / NiGB cleavage pairs | only partition on this track |
E_seg lives on its own page — see /methodology/deep/segregation.
11. Parameter summary
| Parameter | Value |
|---|---|
| W_sep | (E_cleaved - E_uncleaved) / A_plane · 16.02176565 [J/m²], with A_plane = area_a2 / 2 |
| Sign convention | positive ⇒ energy required to separate the two half-cells |
| Energy field | smeared VASP energy |
area_a2 |
from extra->>'area_A2'; historically ingested as 2·A_plane — divide by 2 to get the single-plane area used by W_sep |
| DFT γ→W_sep correction | df["dft_w_sep"] *= 2.0 on read (build_wsep_dfs.py:128) so DFT and MLIP sides match the textbook convention |
| BFGS protocol | fmax = 0.01 eV/Å, max_steps = 10000 |
| FIRE handback | fmax = 0.01 eV/Å, max_steps = 250, merged 2026-06-13 |
| Best-available rule | per-side, both sides required done |
| Outlier filter | |E| > 1e4 eV per cell → drop |
| Aggregation | count-weighted two-step, RMSE default, MAE alongside |
| Magnetic facet | not introduced (corpus is all-magnetic by definition) |
| Corrected variant | not introduced (offsets cancel by construction) |
| DB key | (structure_id, potential) on each side; pair joined by linkage SQL |
Implementation: benchmark/build_wsep_dfs.py ·
rollup builder: benchmark/eval/build_gbseg_rollup.py (Task B) ·
page consumer: src/cleavage.md + src/elements/[el].md (Task D) ·
wiki hub: wiki/mlip-benchmark-gbsegbench-relax.md.