k-point meshes

vibe-qc samples the Brillouin zone with a Monkhorst-Pack grid.

from vibeqc import monkhorst_pack

km = monkhorst_pack(sysp, mesh=[4, 4, 4])
print(len(km))         # 64 (full mesh)
print(km.kpoints[0])   # first k-point in Cartesian coords (bohr^-1)
print(km.weights[0])   # 1/64

The mesh argument says how many subdivisions along each reciprocal axis. vibe-qc auto-clamps non-periodic axes to 1 k-point regardless of the input:

# 1D system: mesh[1] and mesh[2] silently become 1.
km = monkhorst_pack(sysp_1d, [8, 4, 4])   # effectively [8, 1, 1]

IBZ reduction

Attach the space group first, then request symmetry reduction:

from vibeqc import attach_symmetry

attach_symmetry(sysp)
km = monkhorst_pack(sysp, [4, 4, 4], use_symmetry=True)
print(len(km))         # fewer — points related by crystal symmetry are merged

Note

The multi-k SCF drivers (run_rhf_periodic, run_rks_periodic) currently use the full mesh, not the IBZ. Supporting IBZ in the SCF requires the D(R) transformation matrices for basis-function pairs under each symmetry operation; that’s on the roadmap as a performance optimisation.

Choosing the mesh size

For insulators: start with 4 points per reciprocal axis, double until the total energy per unit cell stops changing. Rough guide:

System type

Starting mesh

Finite cluster in periodic box (molecular limit)

[1, 1, 1]

1D polymer

[6, 1, 1]

2D slab

[6, 6, 1]

3D wide-gap insulator

[4, 4, 4]

3D narrow-gap

[8, 8, 8]

Metal

— not supported yet (requires smearing; see roadmap)