Fermi surfaces, and two bugs that a missing dependency had been hiding - #18
Merged
Conversation
mv.elec.fermi_surface computes Fermi surfaces through IFermi: total area, how many disconnected sheets, and whether there is a surface at all. The check that makes it trustworthy needs no DFT. A free-electron band, E = hbar^2 k^2 / 2m, has a spherical Fermi surface of area 4 pi kF^2 exactly, so the computed area can be checked against arithmetic rather than against another code. On a simple cubic cell with a = 4 A it matches to within 1% at kF of 0.324, 0.458 and 0.628 - and falls to 0.66 of the sphere at kF = 0.887, which is where the sphere has grown past the zone boundary at 0.785 and is genuinely truncated. That clipping is physics; the area that remains is the one that carries current. A line-mode band structure is refused rather than interpolated. Fourier interpolation needs a grid and a high-symmetry line has no interior, so feeding one in produces a plausible surface rather than an error. An insulator, where no band crosses the level, is reported as zero sheets rather than raised. Adding it turned up two bugs that had nothing to do with Fermi surfaces. mv.elec.transport guarded on `import BoltzTraP2`, which succeeds without touching netCDF, while the modules it actually uses do not. IFermi pulls BoltzTraP2 in as a dependency, so the guard started passing on an installation that cannot run - netCDF4 built against a different numpy raises "numpy.dtype size changed", which is a ValueError and was not caught either. It now imports the submodules it reaches and catches both, and says that this is a rebuild rather than a missing package. The test's skip condition had the same shallow check and has the same fix. Underneath that, the tutorial had been calling mv.elec.transport(metals, bands) where transport wants one BandStructure per material and `bands` is the bands-axis object with one row per band. It had been wrong for a long time and nobody could see it: the missing BoltzTraP2 raised ImportError first and the cell's `except` swallowed it. Removing the import failure exposed the argument error underneath. IFermi is not cheap - interpolation at the default factor of five takes minutes for one 12x12x12 mesh and scales as the cube of the factor - and the notes say so. The fermi extra pins netcdf4 below 1.7 and adds cmake, because 1.7.4 has no wheel for an older glibc and BoltzTraP2 needs cmake at build time. 971 tests pass on py3.12, 851 on py3.10. 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
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.
mv.elec.fermi_surfacecomputes Fermi surfaces through IFermi: total area, how many disconnected sheets, and whether there is a surface at all.Checked against arithmetic, not against another code
A free-electron band,
E = ħ²k²/2m, has a spherical Fermi surface of area4πk_F²exactly. So the computed area needs no DFT to validate. Simple cubic, a = 4 Å, zone boundary at 0.785 Å⁻¹:The last row is not an error. The sphere has grown past the zone boundary and is genuinely truncated — the area that remains is the one that carries current.
A line-mode band structure is refused rather than interpolated: Fourier interpolation needs a grid, a high-symmetry line has no interior, and feeding one in produces a plausible surface rather than an error. An insulator is reported as zero sheets, not raised.
Two bugs that had nothing to do with Fermi surfaces
Adding IFermi pulled BoltzTraP2 in as a dependency, and that removed a mask.
mv.elec.transportguarded on the wrong thing.import BoltzTraP2succeeds without touching netCDF; the modules it actually uses do not. The guard started passing on an installation that cannot run — netCDF4 built against a different numpy raisesnumpy.dtype size changed, a ValueError, which was not caught either. It now imports the submodules it reaches, catches both, and says this is a rebuild rather than a missing package. The test's skip condition had the identical shallow check and the identical fix.Underneath that, the tutorial had been calling it wrongly.
mv.elec.transport(metals, bands)— where transport wants oneBandStructureper material andbandsis the bands-axis object with one row per band. It had been wrong for a long time and was invisible: the missing BoltzTraP2 raisedImportErrorfirst, and the cell'sexceptswallowed it. Removing the import failure exposed the argument error underneath.Cost
Not cheap. Interpolation at the default factor of five takes minutes for one 12×12×12 mesh and scales as the cube of the factor — a shortlist tool, not a library one. The notes say so.
The
fermiextra pinsnetcdf4<1.7and addscmake: 1.7.4 has no wheel for an older glibc and its source build wants netCDF headers, and BoltzTraP2 needs cmake at build time. Three layers, each blocking once.Verification
971 pass on py3.12, 851 on py3.10. Contract-verified rate stays 165/165. All 16 notebooks execute. Docs build.
🤖 Generated with Claude Code
https://claude.ai/code/session_016wh5NzNE9Wn49nuUm7zg2a