Real DFT as a level of theory, four more potentials, and two silent unit errors - #15
Merged
Merged
Conversation
…nit errors
matverse could reach six levels and every one of them was a surrogate. GPAW is
now registered as gpaw-pbe and gpaw-pbe-fast, with kind="dft" and
surrogate=False, so the one level that solves the Kohn-Sham equations is
distinguishable from the ones that reproduce something that did. m3gnet,
m3gnet-r2scan, tensornet and orb are added alongside.
Validated by running it, not by citing it. Through matverse, on real PBE:
mv.calc.relax -> Si lattice constant 5.479 A (PBE literature 5.47)
mv.prop.eos -> Si bulk modulus 88.7 GPa (PBE literature 88-89)
fit residual 0.002 meV/atom
Two things that would have been wrong silently.
matgl returns stress in GPa while ASE's contract is eV/A^3, so leaving
stress_unit alone makes every stress-derived quantity - elastic constants, bulk
modulus, pressure - exactly 160.2x too large with no error raised anywhere. The
factor is the GPa-to-eV/A^3 conversion, which is what makes it recognisable
once you look. Fixed, with a test that fails on the unfixed version.
The second took longer to find and is not GPAW's fault. I first gave the DFT
levels a k-point *density*, which is the sensible thing for comparing different
materials and the wrong thing for scanning one material's volume: the mesh
changes discretely as the cell grows, and each change puts a step in E(V) that
the fit reads as curvature. Silicon, same calculator, only the k-points varying:
density 2.0 -> -879 GPa (125 -> 64 k-points)
density 2.5 -> 319 GPa (216 -> 125)
density 3.0 -> 125 GPa (343 -> 216)
density 4.0 -> 85.7 GPa (729 -> 512)
fixed 8x8x8 -> 88.7 GPa (unchanged)
A negative bulk modulus is not a soft crystal. Raising the density only shrinks
the jump; it never removes it. The plane-wave cutoff was converged the whole
time - PW(400), PW(600) and PW(800) agree to 0.1 GPa - so the entire error was
the mesh. The built-in levels use a fixed mesh, and mv.prop.eos now says why.
obs['eos_residual'] catches it long before the modulus does: 9.5 meV/atom
against 0.002, a factor of nearly five thousand, and the advice already in that
function's notes - a residual far above a meV is a fit that should not be read -
was enough to reject it without knowing the cause.
On pymatviz I made a judgement rather than adding it wholesale. Most of it
duplicates mv.pl, which already has hull, parity, periodic_table, spectra,
scatter, bands and distribution; wrapping those again would be the mistake the
coverage map exists to prevent. The one genuinely absent capability is the
space-group distribution, so mv.pl.spacegroups does that directly, grouped and
coloured by crystal system rather than plotted as 230 flat categories.
mv.pp.symmetry gained spacegroup_number and spacegroup_symbol while I was
there - it was already building the analyser, and a symmetry report that gives
the crystal system and the point group but not the group itself is missing the
one label everybody cites.
960 tests pass on py3.12 with GPAW and matgl, 850 on py3.10 without them. The
level-metadata tests skip where a backend is absent rather than failing, which
they did not do at first. Contract-verified rate stays 165/165, all 16
notebooks execute, docs build.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wh5NzNE9Wn49nuUm7zg2a
All three test legs went red on the previous commit. GPAW has no wheel: it compiles against libxc and BLAS, and the runner carries neither, so pip got as far as "fatal error: xc.h: No such file or directory" before anything ran. It built here only because this node happens to have both. Installing it in the main matrix was the wrong call regardless of the headers. GPAW compiles from source, and matgl and orb-models pull torch, which nothing else in the matrix needs — three legs would each pay a couple of minutes to cover one job's worth of tests. They now share a 'calculators' job, the same shape the anharmonic job already has and for the same reason. The job prints mv.calc.available() before running anything, so a level whose backend failed to install is visible as a line in the log rather than as a silently skipped test.
GPAW 26 includes <algorithm> from sources the build compiles as C, so the runner needs a C++ standard library it does not carry by default. The previous attempt got past libxc and stopped at 'fatal error: algorithm: No such file or directory'.
Three attempts, same error. GPAW ships no wheel and its 26.x sources include C++ headers from files the build compiles as C, so it stops at 'fatal error: algorithm: No such file or directory' whether or not libxc, BLAS and build-essential are installed. It builds here because this node's compiler puts the C++ headers on the default include path; a stock ubuntu runner's does not. So the calculators job installs the torch-backed potentials only, and keeps the test that matters most there — the one that fails when matgl's stress is left in GPa, a 160x error nothing else would catch. The real-DFT numbers stay where they were measured, in the notes, and TestRealDFT says why it skips rather than leaving a reader to assume CI covers it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
matverse could reach six levels and every one of them was a surrogate. GPAW is now registered as
gpaw-pbe/gpaw-pbe-fastwithkind="dft"andsurrogate=False, so the one level that solves the Kohn-Sham equations is distinguishable from the ones that reproduce something that did.m3gnet,m3gnet-r2scan,tensornetandorbare added alongside.Validated by running it, not by citing it
Through matverse, on real PBE:
mv.calc.relax)mv.prop.eos)Two things that would have been wrong silently
matgl returns stress in GPa; ASE's contract is eV/ų. Leaving
stress_unitalone makes every stress-derived quantity — elastic constants, bulk modulus, pressure — exactly 160.2× too large, with no error raised anywhere. That factor is the GPa→eV/ų conversion, which is what makes it recognisable once you look. Fixed, with a test that fails on the unfixed version.The second took longer and is not GPAW's fault. I first gave the DFT levels a k-point density — sensible for comparing different materials, wrong for scanning one material's volume. The mesh changes discretely as the cell grows, and each change puts a step in E(V) that the fit reads as curvature. Silicon, same calculator, only the k-points varying:
A negative bulk modulus is not a soft crystal. Raising the density only shrinks the jump; it never removes it. The plane-wave cutoff was converged the whole time — PW(400), PW(600) and PW(800) agree to 0.1 GPa — so the entire error was the mesh.
obs["eos_residual"]catches it long before the modulus does: 9.5 meV/atom against 0.002, a factor of nearly five thousand. The advice already in that function's notes — a residual far above a meV is a fit that should not be read — was enough to reject it without knowing the cause.pymatviz: a judgement, not a wholesale add
Most of it duplicates
mv.pl, which already has hull, parity, periodic_table, spectra, scatter, bands and distribution. Wrapping those again is the mistake the coverage map exists to prevent. The one genuinely absent capability is the space-group distribution, somv.pl.spacegroupsdoes that directly — grouped and coloured by crystal system rather than plotted as 230 flat categories, and able to overlay requested against achieved formv.gen.from_symmetryoutput.mv.pp.symmetrygainedspacegroup_numberandspacegroup_symbolwhile I was there: it was already building the analyser, and a symmetry report giving the crystal system and point group but not the group itself is missing the one label everybody cites.Verification
dft: the GPAW test is one H₂ molecule in LCAO, ~3 s. The crystal validations behind the numbers above take minutes each and stay out.🤖 Generated with Claude Code
https://claude.ai/code/session_016wh5NzNE9Wn49nuUm7zg2a