Skip to content

Fix bug when combining 2+ mirror symmetries and Bloch-periodic boundary conditions#3155

Merged
stevengj merged 1 commit intoNanoComp:masterfrom
oskooi:bug_fix_issue_132
Feb 27, 2026
Merged

Fix bug when combining 2+ mirror symmetries and Bloch-periodic boundary conditions#3155
stevengj merged 1 commit intoNanoComp:masterfrom
oskooi:bug_fix_issue_132

Conversation

@oskooi
Copy link
Collaborator

@oskooi oskooi commented Feb 26, 2026

Fixes #132.

Root Cause

The Bloch phase factor eikna[d] is computed using the symmetry-reduced grid volume (gv) size, while the periodic lattice translation vector (ilattice_vector) is computed using the full cell size (user_volume). This creates a mismatch between the phase applied per periodic translation and the actual translation distance.

Why it only manifests with 2+ mirror symmetries + periodioc boundaries

  • single mirror (e.g., Mirror(Y)) + periodic in X: only Y is halved, so gv.num_direction(X) equals the original full user_volume.nx(). The phase in X is correct. The Y direction typically has k_y = 0 with mirror symmetry, so eikna[Y] = 1 regardless.
  • 2+ mirrors (e.g., Mirror(X) + Mirror(Y)) + periodic: Both X and Y are halved. If k_x ≠ 0, then gv.num_direction(X)user_volume.nx() / 2 and eikna[X] is computed for the wrong period. The periodic translation moves by the full cell but applies the phase for half the cell. This produces incorrect field values at boundary conditions leading to expontentially growing errors (instability).
  • k = 0 (pure periodic, no Bloch phase): eikna = exp(0) = 1 regardless of cell size, so the bug is latent and harmless.

Two new unit tests are added to compare the symmetry-exploiting simulation against a reference simulation without symmetry, checking field values at multiple points and energies at regular intervals.

@codecov-commenter
Copy link

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 73.90%. Comparing base (f29a8c7) to head (09619c5).
⚠️ Report is 107 commits behind head on master.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3155      +/-   ##
==========================================
+ Coverage   73.81%   73.90%   +0.09%     
==========================================
  Files          18       18              
  Lines        5423     5454      +31     
==========================================
+ Hits         4003     4031      +28     
- Misses       1420     1423       +3     

see 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

else {
const complex<double> I = complex<double>(0.0, 1.0);
eikna[d] = exp(I * kk * ((2 * pi / a) * gv.num_direction(d)));
eikna[d] = exp(I * kk * ((2 * pi / a) * user_volume.num_direction(d)));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wow such a simple fix, for such a hairy bug all these years. Very cool!

Copy link
Collaborator

Choose a reason for hiding this comment

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

The odd thing is that mirror symmetries (the halved dimensions) would only ever be in directions $i$ where $k_i = 0$, so it's not clear why this would have an effect?

Copy link
Collaborator

Choose a reason for hiding this comment

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

However, it would affect you at $k_i = \pi / a$, which does preserve the mirror symmetry.

Copy link
Collaborator

Choose a reason for hiding this comment

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

But then why would this help #132?

@stevengj
Copy link
Collaborator

Can you verify that this fixes #132? It's not clear why it would help in a case where $k \ne 0$.

(But even if it fixed an unrelated bug that is nice too.)

@oskooi
Copy link
Collaborator Author

oskooi commented Feb 27, 2026

It seems the original test case in #132 with k_point = (0, 0, 0) actually runs fine (i.e. the fields do not blow up) even without this fix. The only test case in which the fields do blow up is k_point = (0.5, 0.5, 0.5) (i.e. at the edge of the Brillouin zone, also mentioned in #132) which is fixed by this PR.

@stevengj stevengj merged commit a474edd into NanoComp:master Feb 27, 2026
5 checks passed
@oskooi oskooi deleted the bug_fix_issue_132 branch February 27, 2026 22:00
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.

fields instability when combining 2+ mirror symmetries with periodic boundary conditions in 3d

4 participants