Reciprocal space

简体中文

LatticeGeom keeps reciprocal geometry explicit and derives phases without storing any Hamiltonian coefficient.

Conventions

Primitive reciprocal vectors are rows of lat.reciprocal_vectors and obey

basis @ reciprocal_vectors.T = 2 pi I.

Finite simulation-supercell vectors and their reciprocal vectors are available as lat.supercell_vectors and lat.supercell_reciprocal_vectors. Methods taking cell= accept either "primitive" or "supercell"; the choice is never inferred.

Coordinate conversion

q = (0.2, 0.3)
k = lat.k_from_coordinates(q, cell="primitive")
restored = lat.reciprocal_coordinates(k, cell="primitive")

Inputs may contain one vector or a batch. For a lower-dimensional lattice embedded in a larger Cartesian space, reciprocal_coordinates(..., check_span=True) rejects a normal component instead of silently projecting it away.

Continuous meshes and finite momenta

integration_mesh = lat.sample_kmesh(
    (80, 80),
    cell="primitive",
    centered=True,
)
finite_modes = lat.allowed_momenta(centered=True)

sample_kmesh samples one reciprocal parallelepiped and returns a flattened array of Cartesian wave vectors. It is a continuous integration mesh. allowed_momenta instead returns the discrete primitive-coordinate modes permitted by the finite periodic axes; an open axis contributes only zero.

Periodic-image phases

For the default sign=-1, translation phases are

exp(-i k . T[super_idx]).
phase_by_image = lat.translation_phases(k)
phase_by_bond = phase_by_image[..., lat.bonds.super_idx]

The last axis indexes lat.supercell_translations, so batches of wave vectors work without a Python loop.

For unit-cell declarations, choose the gauge explicitly:

periodic_gauge = lat.unit_bond_phases(k, gauge="cell")
position_gauge = lat.unit_bond_phases(k, gauge="position")

cell uses only the integer Bravais translation. position uses the full source-to-target vector including sublattice offsets.

First Brillouin zone

bz = lat.brillouin_zone(cell="primitive")
inside = bz.contains(integration_mesh)
points = bz.sample((100, 100))
vertices = bz.vertices

Rank-one zones are intervals. Rank-two Wigner--Seitz zones require the bz optional extra and may be embedded in a higher-dimensional Cartesian space. The current API deliberately rejects rank-three first-zone construction; reciprocal vectors, coordinate conversion, meshes, momenta, and phases remain available in any supported rank.

A BrillouinZone is constructed per request and is not cached on Lattice.