Skip to content

Fix test_run_te_no_geometry convergence at degenerate band - #3308

Open
yorickreum wants to merge 1 commit into
NanoComp:masterfrom
yorickreum:fix-mpb-degenerate-band-tolerance
Open

Fix test_run_te_no_geometry convergence at degenerate band#3308
yorickreum wants to merge 1 commit into
NanoComp:masterfrom
yorickreum:fix-mpb-degenerate-band-tolerance

Conversation

@yorickreum

Copy link
Copy Markdown

Bands 1 and 2 of the empty lattice are degenerate at k=(0.5,0,0): |k+G| is 0.5 for both G=(0,0,0) and G=(-1,0,0). The sweep reaches that k-point carrying the previous point's fields as its initial guess, which is a poor basis for the pair, and at 1e-7 -- the only run in this file not using 1e-12 -- the solver stops with band 2 still at 0.5447. That exceeds the frequency at the next k-point, so the band minimum relocates there and comes out as |(0.5,0.1,0)| = 0.50990 instead of 0.5.

Solving that k-point on its own converges correctly at any tolerance, so what fails is the stopping criterion during the sweep; whether it is met before band 2 settles depends on details of BLAS, FFTW and libm. The expected values are accurate to 1e-11, four orders tighter than a 1e-7 criterion can justify, so ask for that much convergence. The assertions are unchanged.

Same class of defect as #2298: a test asserting more precision than its convergence resolves at a degeneracy. Reported among the test_mpb failures on Apple silicon in #1853 and in #2244.

@yorickreum
yorickreum marked this pull request as draft September 11, 2026 12:57
@yorickreum

Copy link
Copy Markdown
Author

Looking at the CI again, just changing the tolerance won't fix it reliably on all platforms.
Will think about it again.

MPB carries the previous k-point's fields into the next solve.  At
k=(0.5,0,0), where bands 1 and 2 of the empty lattice are degenerate
(|k+G| = 0.5 for both G=(0,0,0) and G=(-1,0,0)), that guess is close enough
to invariant that the eigensolver stops after two iterations with band 2 at
0.545 instead of 0.5.  The band minimum then moves to the next k-point and
comes out as |(0.5,0.1,0)| = 0.50990.

Whether the stopping criterion is met before the pair settles depends on
BLAS, FFTW and libm; this is among the test_mpb failures reported in NanoComp#1853
and NanoComp#2244.  The tolerance is not the lever -- it only changes what earlier
k-points hand over, so tightening it fixes one machine and breaks another.
Randomizing the fields at each k-point removes the inherited basis instead.

All eight bands then match the analytic |k+G| to 8e-09.  Band 8's expected
maximum was the one value that did not: 1.80278 is an eigenvalue at
k=(0.5,0,0) but not the eighth, which is 1.5.  Over the path band 8 peaks at
1.64012 at k=(0.3,0,0); the inherited guess misses one of the two 1.5 states
there and records an 1.80278 state in its place.
@yorickreum
yorickreum force-pushed the fix-mpb-degenerate-band-tolerance branch from 7374971 to 0867b1f Compare September 11, 2026 14:31
@yorickreum

Copy link
Copy Markdown
Author

Replaced the approach in this PR.

The original one (tightening ms.tolerance to 1e-11) was wrong, as the CI caught, it failed all three jobs on Linux with exactly the symptom it was supposed to fix (detected on a Windows machine).

The tolerance is not the right lever. MPB seeds each k-point with the previous k-point's fields, so changing the tolerance changes what earlier k-points hand over, and its effect on the degenerate pair has no consistent sign:

tol 1e-7 tol 1e-11
Linux (CI) passes band 2 = 0.54484
mingw-w64 / Windows band 2 = 0.5447 passes

What actually happens at k=(0.5,0,0), from the CI log:

tefreqs:, 6, 0.5, 0, 0,  0.5, 0.5, 0.54484, 1.12367, 1.13047, 1.13732, ...
solve_kpoint (0.5,0,0):    Finished solving for bands 1 to 8 after 2 iterations.
solve_kpoint (0.5,0.1,0):  Finished solving for bands 1 to 8 after 12 iterations.

The whole k-point is unconverged. Bands 3-6 should be 1.118034 four-fold. And the eigensolver stops after two iterations because the inherited basis is close enough to invariant to satisfy the stopping criterion. The next k-point then needs 12 iterations to recover.

So the PR now randomizes the fields at each k-point and leaves the tolerance at 1e-7.

With that, all eight bands match the analytic empty-lattice |k+G| to under 1e-08. The one expected value that had to change is band 8's maximum: 1.80278 is an eigenvalue at k=(0.5,0,0) but not the eighth, which is 1.5. The inherited guess misses one of the two 1.5 states and picks up an 1.80278 state instead. The randomized approach finds the correct states imo,
over the k-path band 8 actually peaks at 1.64012 at k=(0.3,0,0), which is what the test now asserts.

@yorickreum
yorickreum marked this pull request as ready for review September 11, 2026 16:03
@yorickreum yorickreum changed the title Converge test_run_te_no_geometry far enough to resolve a degenerate band Fix test_run_te_no_geometry convergence at degenerate band Sep 11, 2026
Comment thread python/tests/test_mpb.py
(
(1.4142135623752818, mp.Vector3(0.0, 0.0, 0.0)),
(1.8027756376524435, mp.Vector3(0.5, 0.0, 0.0)),
(1.6401219539085534, mp.Vector3(0.3, 0.0, 0.0)),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not change this line to (1.5, mp.Vector3(0.5, 0.0, 0.0)), since this is the correct result for the eighth eigenvalue which randomizing the fields actually uncovers (as you described in your bug report)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants