Geometry guide

简体中文

Predefined lattices

All constructors accept finite extents and boundary conditions. Lowercase names are the canonical API; capitalized aliases are provided for migration convenience.

Constructor Sites per cell Built-in plaquettes Meaning of a
chain 1 none nearest-neighbor spacing
square 1 square nearest-neighbor spacing
triangular 1 up/down triangles nearest-neighbor spacing
triangular_nnn 1 up/down triangles nearest-neighbor spacing
honeycomb 2 hexagon nearest-neighbor spacing
kagome 3 up/down triangles and hexagon nearest-neighbor spacing
grid / hypercubic 1 none per-axis spacing / common spacing
bcc / fcc 1 none conventional cubic lattice constant
diamond 2 none conventional cubic lattice constant
pyrochlore 4 typed tetrahedron faces conventional cubic lattice constant

bond_types= reclassifies the declared directions without assigning coupling values.

Declare a custom unit cell

from latticegeom import Bond, Lattice, Plaquette, Site, UnitCell

cell = UnitCell(
    sites=[Site((0.0, 0.0), "A"), Site((0.5, 0.0), "B")],
    bonds=[
        Bond(0, 1, (0, 0), "intracell"),
        Bond(1, 0, (1, 0), "intercell"),
    ],
    plaquettes=[
        Plaquette(
            [(0, (0, 0)), (1, (0, 0)), (0, (1, 0)), (1, (0, 1))],
            "loop",
        )
    ],
)

lat = Lattice(
    basis=((1.0, 0.0), (0.2, 1.0)),
    unit_cell=cell,
    extent=(8, 5),
    pbc=(True, False),
)

Site positions are Cartesian offsets from the cell origin. Every relation shift is an integer coordinate in the primitive basis. A plaquette must contain at least three unique vertices; do not repeat the first vertex to close it.

Boundary conditions

Use pbc=True or False for all axes, or a boolean sequence for mixed boundaries. Open-axis relations that leave the finite extent are dropped. Periodic-axis relations are wrapped while retaining their exact image shift.

site = lat.site_id((7, 2), site=1)
cell_coord, sublattice = lat.cell_and_site(site)
unfolded = lat.position(site, super_idx=lat.super_index((1, 0)))

wrap=True in site_id may fold periodic axes but never folds an open axis.

Query bonds and plaquettes

rows = lat.find_bonds(
    type="intercell",
    cell_shift=(1, 0),
    crossing=True,
)

plaquettes = lat.plaquettes.indices(type="loop", crossing=False)
sites, images = lat.plaquettes.vertices(plaquettes[0])
boundary = lat.plaquette_boundary(plaquettes[0])

Bond filters return row indices because multiedges are intentional. PlaquetteBoundary returns exact directed perimeter endpoints plus primitive and simulation-supercell shifts. plaquette_positions, plaquette_centers, and plaquette_signed_areas use unfolded geometry.

For lightweight graph code, lat.edges(...) and lat.adjacency_list(...) return Python containers. Performance-sensitive code should access lat.bonds directly.

Compose unit cells

UnitCellBuilder is mutable only during authoring:

from latticegeom import UnitCellBuilder

builder = UnitCellBuilder(lower_cell)
upper = builder.extend(
    lower_cell,
    offset=(0.0, 0.0, 0.3),
    site_type_map=lambda label: ("upper", label),
)
builder.add_bond(0, upper[0], (0, 0), "interlayer")
bilayer = builder.build()

translate_unit_cell shifts Cartesian site offsets. merge_unit_cells combines declarations and renumbers their references.

Enlarge or tilt the declaration cell

Use an orientation-preserving integer transformation to create a crystallographic or magnetic supercell without rediscovering bonds by distance:

from latticegeom import Lattice, make_unit_cell_supercell

new_basis, new_cell = make_unit_cell_supercell(
    lat.basis,
    lat.unit_cell,
    ((2, 1), (0, 1)),
)
enlarged = Lattice(new_basis, new_cell, (3, 3), pbc=True)

The transformation remaps site representatives, bond shifts, and plaquette vertices exactly. Its determinant gives the number of old cells inside the new declaration cell.