Skip to content

feat: compute the first Brillouin zone from the reciprocal lattice - #295

Open
timurbazhirov wants to merge 1 commit into
mainfrom
claude/brillouin-zone-geometry
Open

feat: compute the first Brillouin zone from the reciprocal lattice#295
timurbazhirov wants to merge 1 commit into
mainfrom
claude/brillouin-zone-geometry

Conversation

@timurbazhirov

Copy link
Copy Markdown
Member

Adds ReciprocalLattice.brillouinZone — the first Brillouin zone as polygonal faces, computed from the lattice we already have.

Why

Consumers illustrate the Brillouin zone with a static PNG per lattice type: @mat3ra/wove derives /images/brillouin_zone/<lattice>.png from the material and renders it through an injectable component (@mat3ra/move's BrillouinZoneImage is one). Two problems with that:

  1. The asset ships in no package — only the web app serves those files, so every other consumer (standalone demos, Storybook, embedders) renders a broken image. The path is also absolute, so it cannot resolve under a non-root deployment base.
  2. One image per type cannot be right for every material of that type. Non-cubic systems have axial-ratio freedom: a graphene monolayer and bulk GaN are both HEX, but the monolayer's vacuum padding flattens its zone. A per-type image shows them identically.

made already owns the reciprocal lattice and its reciprocalVectors, so the zone can simply be derived here instead.

What

  • src/js/lattice/reciprocal/brillouin_zone.tscomputeBrillouinZone(reciprocalVectors). The zone is the set of points closer to the origin than to any other reciprocal lattice point, i.e. the intersection of half-spaces k·G ≤ |G|²/2; vertices are the plane triple-intersections satisfying every other half-space, and faces group the vertices on each plane (ordered counter-clockwise about the face normal, so they can be drawn directly).
  • ReciprocalLattice.brillouinZone getter returning those faces, or null for a degenerate lattice.

No existing behaviour changes; this is additive.

Validation

Tested against the repo's material fixtures rather than hand-made vectors (tests/js/lattice/brillouin_zone.ts, 7 tests):

fixture lattice expected solid faces / vertices
Silicon FCC truncated octahedron 14 (8 hex + 6 square) / 24
Na4Cl4 cubic cube 6 / 8
Graphene hexagonal hexagonal prism 8 (2 hex + 6 rect) / 12
Si slab flattened along the vacuum axis

Plus invariants on all four: Euler characteristic V − E + F = 2, and every vertex at least as close to the origin as to a neighbouring reciprocal lattice point. Existing lattice and lattice_reciprocal suites still pass (14 tests).

Follow-ups (not in this PR)

  • @mat3ra/move: render this zone, superseding the <img>-based BrillouinZoneImage.
  • @mat3ra/wove: pass the provider's material/lattice to the injected component instead of latticeType + a dead imgSrc.
  • With symmetryPoints alongside, labelling Γ/X/L on the drawn zone and overlaying the k-path becomes straightforward — something a static image never allowed.

Context: mat3ra/workflow-designer#12 (SOF-8024), where this shipped first as a local stopgap.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FFFpkKD3zHysJXgAbT2uYV


Generated by Claude Code

Adds ReciprocalLattice.brillouinZone, returning the Wigner-Seitz cell of
the reciprocal lattice as polygonal faces: the intersection of the
half-spaces k.G <= |G|^2/2, with vertices at the plane triple
intersections that satisfy every other half-space.

The zone follows from the lattice's own vectors rather than its Bravais
type, so materials sharing a type but differing in axial ratios — a bulk
crystal and a slab padded with vacuum, say — yield correctly differing
zones. Consumers currently illustrate the zone with one static image per
lattice type, which cannot express that difference (and ships as an
asset outside the package).

Validated against the material fixtures: silicon gives a truncated
octahedron, Na4Cl4 a cube, graphene a hexagonal prism, each closed with
V - E + F = 2 and enclosing no reciprocal lattice point but the origin.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FFFpkKD3zHysJXgAbT2uYV
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