Lattice2D.jl
A Julia package for constructing and visualizing 2D lattices for quantum many-body physics simulations.
Installation
using Pkg
Pkg.add("Lattice2D")Models
The models implemented in this module is below.
Lattice2D.AVAILABLE_LATTICES — Constant
Tuple listing every topology shipped by Lattice2D.
Lattice2D.AbstractTopology — Type
AbstractTopology{D}Abstract supertype for 2D lattice topologies (Square, Triangular, Honeycomb, ...). Each concrete subtype is a singleton that acts as a dispatch key for get_unit_cell, and, through TopologyTrait in LatticeCore, as the topology(lat) value of the resulting Lattice.
Lattice2D.Connection — Type
Connection(src_sub, dst_sub, dx, dy, type)A unit-cell-level connection rule — the description of an edge between sublattices inside a single unit cell, or between a sublattice in one cell and a sublattice in a neighbouring cell.
This is distinct from LatticeCore.Bond:
- A
Connectionis a template on the unit cell (src_sub,dst_subare sublattice ids,dx,dyare relative cell offsets). It is topology data, known statically fromget_unit_cell. - A
LatticeCore.Bondis an instantiated edge on a concreteLx × Lysample, with absolute site indices and a wrapped displacement vector. It is the per-sample output ofbuild_lattice.
Fields
src_sub::Int— 1-based sublattice id of the source sitedst_sub::Int— 1-based sublattice id of the destination sitedx::Int— x-axis cell offset (0 = same unit cell)dy::Int— y-axis cell offsettype::Int— bond type tag. Currently stored as anInton theConnectionside for backward compatibility;build_latticeconverts this to aSymbol(:type_N) when it emitsLatticeCore.Bond.
Lattice2D.Dice — Type
Dice <: AbstractTopology{2}Dice (T3) lattice: bipartite triangular-based structure with a single 6-coordinated hub site and two 3-coordinated rim sites per unit cell.
Lattice2D.DilutedLattice — Type
DilutedLattice{D, T, L<:AbstractLattice{D, T}} <: AbstractLattice{D, T}Wrapper lattice with disordered sites / bonds. See module docstring of disorder/dilution.jl.
Fields
base::L— the underlying latticeactive_sites::BitVector— lengthnum_sites(base);truewhere the site is keptkilled_bonds::Set{Tuple{Int, Int}}— canonical(min_i, max_j)base-index pairs of bonds that are explicitly removed (in addition to bonds whose endpoints are inactive)new_to_old::Vector{Int}—new_to_old[k]is the base-lattice index of thek-th active site (length == count(active_sites))old_to_new::Vector{Int}—old_to_new[i]is the new index of base sitei, or0ifiis inactive
The new_to_old / old_to_new arrays are derived from active_sites and cached at construction; the constructors below are the only sanctioned entry points so the invariants stay tight.
Lattice2D.DilutedLattice — Method
DilutedLattice(base, active_sites, killed_bonds = Set{Tuple{Int, Int}}())Construct a DilutedLattice from a base lattice plus a site-activity mask and an optional explicit bond-removal set. The remap arrays are derived from active_sites. killed_bonds keys are canonicalised to (min, max) form.
Throws ArgumentError if active_sites does not match num_sites(base), or if any entry of killed_bonds references a site outside 1:num_sites(base).
Lattice2D.Honeycomb — Type
Honeycomb <: AbstractTopology{2}Honeycomb lattice: two-sublattice (A/B) bipartite triangular Bravais lattice, three nearest neighbours per site.
Lattice2D.InfiniteLattice — Type
InfiniteLattice{Topo, T, L}(; layout = UniformLayout(IsingSite()))A truly infinite 2D lattice of topology Topo — the thermodynamic-limit counterpart of the finite Lattice under periodic boundary conditions. It carries no size (size_trait is InfiniteSize, num_sites throws) and is described by, and accessed through, its unit-cell motif:
site_orbits/bond_orbits— the finite fundamental domain (one entry per sublattice / perConnectionofget_unit_cell(Topo));cell_position,neighbors_at,incident_cell_bonds— on-demand access to anyCellSite, computed without materialising the lattice.
If a finite sample is needed, materialize tiles the motif into a periodic Lattice:
inf = InfiniteLattice(Honeycomb)
fin = materialize(inf; dims = (8, 8)) # 8×8 PBC honeycomb Latticebut the lazy accessors above never require it.
Positions use Float64, matching the finite Lattice produced by build_lattice.
Example
inf = InfiniteLattice(Kagome)
site_orbits(inf) # 1:3 (three sublattices)
length(collect(bond_orbits(inf))) # motif bond count
neighbors_at(inf, CellSite((0, 0), 1)) # neighbours of basis-1 siteLattice2D.Kagome — Type
Kagome <: AbstractTopology{2}Kagome lattice: three-sublattice (A/B/C) structure on a triangular Bravais lattice, four nearest neighbours per site.
Lattice2D.Lattice — Type
Lattice{Topo, T}Finite 2D lattice obtained by tiling a unit cell (described by get_unit_cell on a topology singleton) over an Lx × Ly sample, with a LatticeCore.LatticeBoundary defining per-axis boundary conditions. Subtype of LatticeCore.AbstractLattice{2, T}.
The struct stores only the parameters that define the lattice; all pure-function-of-input data (position, sublattice, neighbors, basis_vectors, ...) are derived on demand through the LatticeCore interface (lattice_coord, apply_axis_bc, to_real). This mirrors the reference SimpleSquareLattice in LatticeCore and keeps the type lightweight.
Boundary-condition-dependent aggregates that appear repeatedly (bonds, plaquettes, the bond and plaquette reverse-lookup tables) are memoised through a lazy cache field — populated on first access by _get_cache and then reused by the O(local) element-center and incidence overrides.
Type parameters
Topo<:AbstractTopology{2}— topology singletonT<:AbstractFloat— numeric type for positions
The boundary, indexing, and layout are stored as fields with abstract eltypes (LatticeBoundary, AbstractIndexing, AbstractSiteLayout). Hot paths that depend on the concrete types of these fields (_connection_steps, _neighbors_by_shell, _materialise_plaquettes) use a function-barrier pattern: they extract the fields and immediately forward to a specialised kernel, so the JIT specialises on the runtime types and the inner loops stay type-stable. This trades 5 type parameters for 2 to cut dispatch / compile-time cost without measurable hot-path regression. See issue #48 for context.
Prefer constructing via build_lattice.
Lattice2D.Lattice — Method
Lattice2D.Lattice(Topology, Lx, Ly; kwargs...)Convenience alias for build_lattice. Kept so that Lattice2D.Lattice(Square, 4, 4) reads naturally at the call site.
Lattice2D.LatticeCache — Type
LatticeCache{T}Lazy, per-lattice cache of bonds, plaquettes, and the reverse-lookup tables needed to make the element-center / incidence API O(local) instead of O(numbonds + numplaquettes) per call.
The cache is constructed once on first access through _get_cache and lives inside a Ref field on the parent Lattice, so the struct itself stays immutable and cheap to copy. For sizes typical of MC work (10⁴–10⁶ sites), the cache occupies a few hundred kilobytes and is negligible relative to the state vectors MC actually keeps hot.
Fields
bonds::Vector{Bond{2, T}}— materialised bond list, ordered by(cell_y, cell_x, connection_index)just like the genericbonds(lat)iteration.plaquettes::Vector{Plaquette{2, T}}— materialised plaquette list, ordered by(cell_y, cell_x, rule_index).bond_index_of::Dict{Tuple{Int, Int}, Int}—(min_i, max_j) → integer bond index. Keyed by the canonical (smaller, larger) endpoint tuple so thatbond_index_of[(min(i, j), max(i, j))]always hits regardless of which endpoint walked first.plaquettes_by_vertex::Vector{Vector{Int}}— per-site list of plaquette indices whose boundary contains that site.plaquettes_by_bond::Dict{Tuple{Int, Int}, Vector{Int}}— per-bond list of plaquette indices that have that bond on their boundary. Same canonical(min, max)keying asbond_index_of.
Lattice2D.Lieb — Type
Lieb <: AbstractTopology{2}Lieb (line-centred square) lattice: three-sublattice structure on a square Bravais lattice. Used for flat-band physics.
Lattice2D.ShastrySutherland — Type
ShastrySutherland <: AbstractTopology{2}Shastry–Sutherland lattice: square Bravais lattice with four sites per unit cell, both nearest-neighbour (square) bonds and dimer (J′) bonds.
Lattice2D.Square — Type
Square <: AbstractTopology{2}Standard square lattice: one sublattice, orthonormal primitive vectors, four nearest neighbours per site.
Lattice2D.Step — Type
Step{T}Internal, concretely-typed record returned by _connection_steps: the result of resolving a unit-cell Connection against the sample boundary. Fields:
j::Int— neighbour site indexd_vec::SVector{2,T}— wrapped displacement vectortype::Symbol— bond type tag (:type_N)
Replaces the previous Tuple{Int,SVector{2,T},Symbol} representation to make the eltype concrete and remove the per-step dynamic Symbol("type_", conn.type) from the hot path.
Lattice2D.SymmetryOperation — Type
SymmetryOperationA realized point-group operation of a lattice: the 2×2 orthogonal matrix acting on real-space positions, together with the induced site permutation (permutation[i] is the site that site i is mapped to).
Query it with is_rotation, is_reflection, is_inversion and rotation_angle.
Lattice2D.Triangular — Type
Triangular <: AbstractTopology{2}Triangular lattice: one sublattice, 60° primitive vectors, six nearest neighbours per site.
Lattice2D.UnionJack — Type
UnionJack <: AbstractTopology{2}Union Jack (centred square) lattice: square primitive cell with two sublattices — a corner site and a body-centred site — and eight-coordinated corner sites, four-coordinated body sites.
Lattice2D.UnitCell — Type
UnitCell{D, T}Static topology description for a D-dimensional Bravais lattice with an arbitrary basis. Contains
basis::Vector{Vector{T}}— theDprimitive vectorssublattice_positions::Vector{Vector{T}}— one offset per geometric sublattice inside the unit cellconnections::Vector{Connection}— the full list of intra- and inter-cell connection rules for this topologyplaquettes::Vector{LatticeCore.PlaquetteRule}— declarative list of plaquette rules (one per plaquette kind) anchored at the reference cell. Empty for topologies that haven't been wired up to the plaquette API yet.
Produced by get_unit_cell on an AbstractTopology singleton.
Lattice2D.UnitCell — Method
UnitCell{D, T}(; basis, sublattice_positions, connections, plaquettes = PlaquetteRule[])Keyword-argument constructor for UnitCell. Equivalent to the positional UnitCell{D, T}(basis, sublattice_positions, connections, plaquettes), but lets call sites label each argument explicitly and omit plaquettes for topologies that don't (yet) declare any.
The 3-positional and 4-positional forms remain available unchanged.
Lattice2D._build_lattice_cache — Method
_build_lattice_cache(lat::Lattice{Topo, T}) → LatticeCache{T}Populate the full cache in a single pass over the lattice. Called once on first cache access through _get_cache.
Lattice2D._edge_key — Method
_edge_key(i::Int, j::Int) → Tuple{Int, Int}Canonical, orientation-independent key for an undirected edge between sites i and j, defined as (min(i, j), max(i, j)).
This helper is used by the per-lattice LatticeCache and the element / incidence API in core/element_api.jl to look up bonds and plaquette-by-bond entries without caring which endpoint walked first.
It is shared as a single internal utility (rather than re-defined ad hoc in each file) so that any future change to the canonical-form convention (e.g. promoting it to a struct) only needs to happen here.
This is internal to Lattice2D — it is not exported and should not be relied on by downstream packages. If a similar helper is needed in LatticeCore itself it should be promoted there in a separate PR.
Lattice2D._get_cache — Method
_get_cache(lat::Lattice{Topo, T}) → LatticeCache{T}Return the lattice's per-sample cache, populating it on first access.
Lattice2D._resolve_boundary — Method
_resolve_boundary(axis::LatticeCore.AbstractAxisBC)
_resolve_boundary(boundary::LatticeCore.LatticeBoundary)Normalise the user-facing boundary argument of build_lattice to a LatticeBoundary{2}. A single axis BC is broadcast to both axes with a NoModifier; an explicit LatticeBoundary is returned as-is.
Lattice2D.block_sublattice — Method
block_sublattice(nsub, f, sub, o) -> IntIndex of the new sublattice carrying old sublattice sub at block offset o (a (dx, dy) in 0:f-1). Ordering is old-sublattice-fastest, then ox, then oy, so sub = 1, o = (0,0) is 1.
Lattice2D.blocking — Function
blocking(::Type{Topo}, f::Integer = 2) -> UnitCellConvenience form: blocking(get_unit_cell(Topo), f). Takes a topology type, so no lattice — and in particular no lattice size — has to exist first.
Lattice2D.blocking — Method
blocking(uc::UnitCell{2,T}, f::Integer = 2) -> UnitCell{2,T}The unit cell of the lattice coarse-grained by a factor f per axis: f² old cells become one new cell, whose basis is f times the old one and whose sublattices are the old sublattices at each of the f² block offsets.
Every Connection is re-expressed in the new cell. A bond whose two ends land in the same new cell becomes an internal connection (offset (0,0)); one that crosses gets the corresponding new offset. No site indices are involved, so this applies to an infinite lattice exactly as it does to a finite one — unlike cell_partition, which enumerates 1:num_sites.
julia> using Lattice2D
julia> uc = get_unit_cell(Square);
julia> b = blocking(uc, 2);
julia> length(b.sublattice_positions) # 2×2 block of a one-site cell
4
julia> b.basis # the basis is doubled
2-element Vector{Vector{Float64}}:
[2.0, 0.0]
[0.0, 2.0]
julia> count(c -> c.dx == 0 && c.dy == 0, b.connections) # bonds now internal to the new cell
4Lattice2D.bond_distances — Method
bond_distances(lat::Lattice) -> Vector{Float64}Euclidean length of every bond returned by bonds, in the same order. Lengths are not deduplicated, so the multiset of distances encodes both the bond-type spectrum and the bond multiplicity.
Lattice2D.bond_type — Method
bond_type(lat::Lattice, i::Int, j::Int) → SymbolReturn the bond-type tag of the edge connecting sites i and j on lat. Uses the cached bond-index reverse lookup, so each call is O(1) after the first cache access. Throws ArgumentError if there is no declared bond between i and j.
The tag is inherited from the Connection.type of the underlying unit cell, so it distinguishes anisotropic edges such as the ShastrySutherland J′ dimer (:type_2) from its square-lattice NN bonds (:type_1).
Lattice2D.brillouin_zone — Function
brillouin_zone(lat::Lattice; shell::Int=2) -> Vector{SVector{2,Float64}}Compute the Brillouin zone of lat as the Wigner-Seitz cell of its reciprocal lattice. Returns an ordered list of polygon vertices in Cartesian k-space, walked counter-clockwise around the origin.
Throws ArgumentError if lat has any open axis (no reciprocal lattice => no BZ).
The concrete method lives in the Lattice2DPlotsExt package extension and is loaded automatically once Plots is in scope. See the Lattice2DPlotsExt module docstring for the algorithm and the shell keyword.
Lattice2D.build_lattice — Method
build_lattice(Topology, Lx, Ly;
boundary = PeriodicAxis(),
indexing = RowMajor(),
layout = UniformLayout(IsingSite())) → LatticeConstruct a finite 2D lattice of topology Topology on an Lx × Ly sample. The boundary argument accepts either a single LatticeCore.AbstractAxisBC (broadcast to both axes) or an explicit LatticeCore.LatticeBoundary for mixed-axis setups such as cylinders.
All geometric / connectivity data (positions, neighbours, bonds) are computed lazily by the accessors defined on Lattice; this constructor only validates and wraps its arguments, so building is O(1) regardless of Lx × Ly.
Examples
# 4 × 4 periodic square lattice, row-major linearisation, Ising sites
lat = build_lattice(Square, 4, 4)
# Open honeycomb 6 × 6
open_hc = build_lattice(Honeycomb, 6, 6; boundary = OpenAxis())
# Cylinder: square lattice with PBC in x, OBC in y
cyl = build_lattice(Square, 4, 4;
boundary = LatticeBoundary((PeriodicAxis(), OpenAxis())))
# Kagome with XY sites
xy_kg = build_lattice(Kagome, 4, 4; layout = UniformLayout(XYSite()))Lattice2D.coordination_number — Method
coordination_number(lat::Lattice, i::Int) -> IntDegree of site i in the declared adjacency graph of lat (number of distinct neighbours, no double-counting). For PBC samples on uniform lattices this matches the textbook coordination number (Square = 4, Triangular = 6, Honeycomb = 3, Kagome = 4, ...). For OBC samples it returns the local degree, which is smaller at the boundary.
Lattice2D.coordination_number — Method
coordination_number(lat::Lattice) -> Vector{Int}Per-site degrees, in site-index order. Length num_sites(lat).
Lattice2D.dice — Function
dice(L::Int, M::Int = L; kw...) -> LatticeShortcut for build_lattice(Dice, L, M; kw...).
Lattice2D.dilute_bonds — Method
dilute_bonds(base::AbstractLattice, p::Real; rng=nothing) → DilutedLatticeKeep all sites; delete each bond of base independently with probability p. The returned DilutedLattice shares the site indexing of base (num_sites and position are unchanged) but its bond / neighbour iterators omit the killed edges.
p must lie in [0, 1]. p = 0 keeps every bond; p = 1 deletes every bond.
rng is forwarded as the first positional argument to rand, so any AbstractRNG may be passed for reproducibility. The default nothing falls back to the argument-less rand().
Lattice2D.dilute_sites — Method
dilute_sites(base::AbstractLattice, p::Real; rng=nothing) → DilutedLatticeDelete each site of base independently with probability p. The returned DilutedLattice renumbers the surviving sites contiguously as 1..N_active.
p must lie in [0, 1]. p = 0 reproduces the base lattice (modulo the wrapper); p = 1 removes every site (the wrapper is still well-formed but most queries become empty).
rng is forwarded as the first positional argument to rand, so any AbstractRNG (e.g. Random.MersenneTwister(seed)) may be passed for reproducibility. The default nothing falls back to the argument-less rand() (Julia's thread-local RNG).
Lattice2D.dual_lattice — Method
dual_lattice(lat::Lattice; kwargs...) -> LatticeConstruct the dual lattice of lat (see dual_topology for the topology map). The dual keeps the (Lx, Ly) extents and the boundary condition of lat; the indexing strategy is preserved unless overridden. Any extra kwargs are forwarded to build_lattice.
Because the topology map is an involution, dual_lattice(dual_lattice(lat)) has the same topology, extents and boundary as lat.
Example
tri = triangular(6, 6)
hexy = dual_lattice(tri) # honeycomb, 6x6, same boundary
topology(dual_lattice(hexy)) # back to the triangular topologyThrows ArgumentError if the dual of lat's topology is not a supported tiling (Lieb, ShastrySutherland, UnionJack).
See also dual_topology.
Lattice2D.dual_topology — Method
dual_topology(::Type{T}) where {T <: AbstractTopology} -> TypeReturn the topology type dual to T. Defined for Square (self-dual), Triangular/Honeycomb, and Kagome/Dice. Throws ArgumentError for topologies whose dual is not itself a supported tiling (Lieb, ShastrySutherland, UnionJack).
The map is an involution: dual_topology(dual_topology(T)) === T.
Lattice2D.dual_topology — Method
dual_topology(t::AbstractTopology) -> AbstractTopologyInstance form: returns the dual topology singleton, e.g. dual_topology(Triangular()) === Honeycomb().
Lattice2D.get_plaquette_rules — Method
get_plaquette_rules(::Type{T}) where {T <: AbstractTopology}
→ Vector{PlaquetteRule}Introspection helper that returns the list of PlaquetteRule templates declared in topology T's unit cell. Equivalent to get_unit_cell(T).plaquettes, but communicates intent ("I only want the plaquette rules, not the full unit cell") and returns an empty Vector{PlaquetteRule} for topologies that haven't been wired up to the plaquette API yet.
Each PlaquetteRule is a template on the unit cell: its corners are (sublattice, dx, dy) tuples relative to the reference cell, its type tags the plaquette kind (e.g. :square, :up_triangle), and build_lattice instantiates them into concrete Plaquette objects on the finite sample. The complementary count on the instantiated lattice is num_plaquettes.
Example
julia> rules = get_plaquette_rules(Square);
julia> length(rules), rules[1].type
(1, :square)Lattice2D.get_unit_cell — Method
get_unit_cell(::Type{T}) where {T <: AbstractTopology}Return the UnitCell describing topology T. Concrete topology types (Square, Triangular, ...) specialise this method. The fallback throws.
See also get_plaquette_rules for plaquette-only introspection.
Lattice2D.high_symmetry_points — Function
high_symmetry_points(lat::Lattice) -> Dict{Symbol,SVector{2,Float64}}Topology-keyed dictionary of high-symmetry points (Gamma, X, M, K, ...) in Cartesian k-coordinates. Currently populated for Square, Triangular, and Honeycomb; other topologies fall back to a singleton :Gamma entry.
The concrete method lives in the Lattice2DPlotsExt package extension and is loaded automatically once Plots is in scope.
Lattice2D.honeycomb — Function
honeycomb(L::Int, M::Int = L; kw...) -> LatticeShortcut for build_lattice(Honeycomb, L, M; kw...).
Lattice2D.is_inversion — Method
is_inversion(op::SymmetryOperation) -> Booltrue if op is the point inversion r ↦ -r (in 2D, the 180° rotation).
Lattice2D.is_reflection — Method
is_reflection(op::SymmetryOperation) -> Booltrue if op is an improper operation — a mirror reflection (det = -1).
Lattice2D.is_rotation — Method
is_rotation(op::SymmetryOperation) -> Booltrue if op is a proper rotation (det = +1), including the identity and the 180° inversion.
Lattice2D.kagome — Function
kagome(L::Int, M::Int = L; kw...) -> LatticeShortcut for build_lattice(Kagome, L, M; kw...).
Lattice2D.lieb — Function
lieb(L::Int, M::Int = L; kw...) -> LatticeShortcut for build_lattice(Lieb, L, M; kw...).
Lattice2D.mean_coordination — Method
mean_coordination(lat::Lattice) -> Float64Average coordination number across all sites of lat. For periodic uniform lattices this equals the bulk coordination number; for samples with open boundaries it is strictly smaller.
Lattice2D.num_bonds — Method
num_bonds(lat::Lattice) → IntConvenience alias for num_elements(lat, BondCenter()) / the length of the cached bond Vector. O(1) after the first cache access.
Lattice2D.num_plaquettes — Method
num_plaquettes(lat::Lattice) → IntConvenience alias for num_elements(lat, PlaquetteCenter()). Returns 0 for topologies whose unit cell declares no PlaquetteRule (currently this is just Dice — wait, now it is not; every shipped topology has a plaquette list as of Iter 6).
Lattice2D.plot_bonds — Function
plot_bonds(lat::Lattice; bond_types=:all, color_by=:type, kwargs...)Lattice2D-flavoured standalone bond plot. Returns a fresh Plots.Plot that draws every bond in lat (optionally filtered by bond_types) as a line segment, grouped — and therefore coloured — by either the bond's :type tag or its rounded direction.
This function is a stub in the core module; the concrete method lives in the Lattice2DPlotsExt package extension and is loaded automatically once Plots is in scope.
See the Lattice2DPlotsExt module docstring for the full keyword list and worked examples.
Lattice2D.plot_brillouin_zone — Function
plot_brillouin_zone(lat::Lattice; show_mesh=false, ml=nothing,
show_high_symmetry=false, kwargs...) -> Plots.PlotPlot the Brillouin zone of lat as a closed polygon. Optionally overlays a momentum-lattice mesh on top of the BZ and labels high-symmetry points.
The concrete method lives in the Lattice2DPlotsExt package extension and is loaded automatically once Plots is in scope. See the Lattice2DPlotsExt module docstring for the full keyword list.
Lattice2D.plot_state — Function
plot_state(lat::Lattice, state::AbstractVector;
colormap=:viridis, marker_size=12, kwargs...) → Plots.PlotVisualise a per-site state::AbstractVector (with length(state) == num_sites(lat)) as a coloured scatter on top of the lattice geometry. Both continuous fields (energy density, charge density, expectation values) and discrete labels (Bool, small-cardinality Int spin / clock-model configurations) are supported through the same call.
The concrete method lives in the Lattice2DPlotsExt package extension and is loaded automatically once Plots is in scope. See the Lattice2DPlotsExt module docstring for the full keyword list and worked examples.
Lattice2D.rotation_angle — Method
rotation_angle(op::SymmetryOperation) -> Float64Rotation angle in radians (in (-π, π]) for a proper rotation. For a reflection it returns the angle of the equivalent orthogonal matrix; use is_rotation to guard.
Lattice2D.shastry_sutherland — Function
shastry_sutherland(L::Int, M::Int = L; kw...) -> LatticeShortcut for build_lattice(ShastrySutherland, L, M; kw...).
Lattice2D.shells — Method
shells(lat::Lattice, i::Int; n_shells::Int = 3) -> Vector{Vector{Int}}Return the first n_shells geometric neighbour shells of site i as a list of site-index vectors. Each entry corresponds to one Euclidean distance class, in increasing order; the k-th entry is exactly neighbors(lat, i; shell = k).
Trailing empty shells (e.g. on a small OBC sample where the requested shell count exceeds the geometric reach) are returned as empty vectors, so the result always has length n_shells.
n_shells must be ≥ 1.
Lattice2D.site_orbit — Method
site_orbit(lat::Lattice, i::Int; kwargs...) -> Vector{Int}The orbit (sorted site indices) containing site i under the realized point group of lat. kwargs are forwarded to symmetry_operations.
Lattice2D.square — Function
square(L::Int, M::Int = L; kw...) -> LatticeShortcut for build_lattice(Square, L, M; kw...).
Lattice2D.sublattice_layout — Method
sublattice_layout(Topology, Lx, Ly, types; indexing = RowMajor())Convenience constructor for a SublatticeLayout that matches the geometric sublattice structure of an Lx × Ly lattice of the given Topology.
types must be a tuple of AbstractSiteType values with length equal to the number of sublattices in the topology's unit cell; types[k] becomes the site type for every site in the k-th geometric sublattice.
The indexing keyword must match whatever indexing will be passed to build_lattice — the layout's sublattice_of vector is computed via the chosen linearisation.
Example
# Honeycomb A / B with an Ising A sublattice and an XY B sublattice:
layout = sublattice_layout(Honeycomb, 4, 4, (IsingSite(), XYSite()))
lat = build_lattice(Honeycomb, 4, 4; layout = layout)Lattice2D.symmetry_group_order — Method
symmetry_group_order(lat::Lattice; kwargs...) -> IntNumber of realized point-group operations of lat (length(symmetry_operations(lat; kwargs...))).
Lattice2D.symmetry_operations — Method
symmetry_operations(lat::Lattice; center=:auto, tol=1e-7)
-> Vector{SymmetryOperation}Realized point-group operations of lat — every rotation / reflection / inversion about center that permutes the sites (modulo the supercell on periodic axes). Always contains the identity.
center is :auto (origin for a fully periodic sample, centroid otherwise), :origin, :centroid, or an explicit 2-vector. tol is the position-matching tolerance.
See also symmetry_orbits, symmetry_group_order.
Lattice2D.symmetry_orbits — Method
symmetry_orbits(lat::Lattice; kwargs...) -> Vector{Vector{Int}}Partition the sites of lat into orbits under its realized point group: two sites are in the same orbit iff some symmetry maps one to the other. Each orbit is returned sorted, and the orbits are ordered by their smallest site index. By the orbit–stabilizer theorem every orbit size divides symmetry_group_order.
kwargs are forwarded to symmetry_operations (center, tol).
Example
lat = square(6, 6) # periodic C₄ᵥ about the origin
orbits = symmetry_orbits(lat) # sites grouped by C₄ᵥ equivalenceLattice2D.triangular — Function
triangular(L::Int, M::Int = L; kw...) -> LatticeShortcut for build_lattice(Triangular, L, M; kw...).
Lattice2D.union_jack — Function
union_jack(L::Int, M::Int = L; kw...) -> LatticeShortcut for build_lattice(UnionJack, L, M; kw...).
LatticeCore.cell_partition — Function
cell_partition(lat::Lattice, k::Integer = 1) -> Vector{Vector{Int}}Group the sites of lat by which unit cell of the lattice k steps coarser — that is, of rescale(lat, -k) — they fall into. Entry c lists the site indices of lat inside cell c of the coarser lattice, indexed with lat's own AbstractIndexing; together the groups partition 1:num_sites(lat).
Each group holds factor^k × factor^k unit cells of lat, hence factor^(2k) * num_sublattices(lat) sites. Requires Lx and Ly to be divisible by factor^k, for the same reason rescale does.
julia> using Lattice2D, LatticeCore
julia> groups = cell_partition(build_lattice(Square, 4, 4), 1);
julia> length(groups), length(first(groups))
(4, 4)
julia> sort(reduce(vcat, groups)) == 1:16
trueLatticeCore.is_bipartite — Method
is_bipartite(lat::Lattice) -> BoolReturn true iff the declared adjacency graph of lat is bipartite, i.e. its sites admit a 2-colouring such that every bond connects different colours.
Implemented as a BFS 2-colouring over neighbors, starting a fresh BFS from each unvisited site so disconnected components are handled. O(num_sites + num_bonds).
LatticeCore.materialize — Method
materialize(lat::InfiniteLattice{Topo}; dims::NTuple{2, Int}) → Lattice{Topo}Tile the motif into a dims[1] × dims[2] periodic Lattice of the same topology, carrying the infinite lattice's site layout. This is the optional infinite → finite bridge; the lazy translation-cell accessors do not require it.
LatticeCore.neighbors — Method
neighbors(lat::Lattice, i::Int) → Vector{Int}
neighbors(lat::Lattice, i::Int; shell::Int) → Vector{Int}Neighbour indices of site i.
- Without the
shellkeyword, returns all declared unit-cell connections. For most topologies this is the geometric NN; for topologies whose unit cell mixes bond types at different distances (e.g.ShastrySutherland, which declares both square NN and dimer J′ bonds), the returned set is the union. - With
shell=k(k ≥ 1), returns thek-th geometric neighbour shell, ranked by Euclidean distance. ForShastrySutherlandthis separates the square NN (shell=1) from the dimer partner (shell=2).
The geometric search is bounded by the sample size — for PBC the minimum-image distance is used, for OBC only in-sample candidates are considered.
LatticeCore.rescale — Function
rescale(lat::Lattice, k::Integer = 1) -> LatticeThe same lattice k scale steps larger: (Lx, Ly) are multiplied by factor^k, where factor comes from scaling_rule. Topology, boundary condition, indexing and layout are carried over unchanged.
k = 0 returns lat. Negative k steps down, and requires both Lx and Ly to be divisible by factor^|k| — a lattice that cannot be halved exactly raises rather than rounding, since a silently rounded size would corrupt any sequence built on it.
julia> using Lattice2D, LatticeCore
julia> lat = build_lattice(Square, 2, 3);
julia> l2 = rescale(lat, 2);
julia> (l2.Lx, l2.Ly)
(8, 12)
julia> num_sites.(size_sequence(lat, 2))
3-element Vector{Int64}:
6
24
96LatticeCore.to_lattice — Method
to_lattice(lat::Lattice, coord::RealSpace) → LatticeCoord{2}Inverse of to_real: map a real-space point back to the nearest LatticeCoord on lat. The implementation inverts the basis matrix A = [a1 a2] once per call (SMatrix{2,2}, so the inverse is non-allocating), subtracts each candidate sublattice offset, and picks the (cell, sublattice) triple whose rounded cell indices reproduce coord with the smallest residual.
For periodic axes the rounded cell is wrapped into 1:Lx / 1:Ly through mod1, so points that lie outside the fundamental domain still resolve to a valid in-sample site. For open axes the rounded cell is returned as-is even when it falls outside 1:L; callers that need an in-sample guarantee should validate the result against (Lx, Ly).
Together with to_real this satisfies to_lattice(lat, to_real(lat, c)) == c for every in-sample LatticeCoord and every shipped topology.