Cluster (flake.cluster)
Cluster creation utilities for rigid-cluster simulations.
A cluster is always an (N, 2) float64 ndarray of (x, y) positions with the center of mass at the origin. Nothing else – no (N,6) legacy format, no hidden state, no file intermediaries in the shape functions.
The cluster is built from a Bravais lattice defined by two primitive vectors a1, a2 (each shape (2,)). N1, N2 count unit cells along each direction and control the cluster size. The precise meaning of N1, N2 depends on shape:
circle : encloses N1*N2 particles at correct areal density hexagon : N1 particles per edge of the hexagon rectangle : N1 (N2) cells along the a1 (a2) direction triangle : triangle spanned by N1*a1, N2*a2 parallelogram: sqrt(N1*N2) x sqrt(N1*N2) lattice (sqrt must be odd int) ellipse : semi-axes rx = N1*|a1|, ry = N2*|a2|
Units follow the calling code; no unit conversion is done here.
ASE and Shapely are optional dependencies – their imports are guarded and raise ImportError with installation hints if absent.
- flake.cluster.add_basis(lat_pos, basis)
Tile a Bravais lattice with a crystal basis.
Each lattice point is displaced by every basis vector; the results are flattened into a single (N*M, 2) array.
- Args:
lat_pos: (N, 2) array-like – Bravais lattice positions. basis: (M, 2) array-like – basis site offsets relative to each
lattice point.
- Returns:
(N*M, 2) float64 ndarray.
- flake.cluster.calc_cluster_langevin(eta, pos)
Effective translational and rotational damping for overdamped dynamics.
- For a cluster of N identical particles with friction coefficient eta:
etat_eff = eta * N (translational, scales as N) etar_eff = eta * sum_i |r_i|^2 (rotational, varies with shape)
- Args:
eta: float – single-particle friction coefficient. pos: (N, 2) ndarray – particle positions (CM at origin).
- Returns:
(etat_eff, etar_eff): floats.
- flake.cluster.cluster_from_params(params)
Build a cluster from a parameter dictionary (for JSON input files).
- Required keys:
a1, a2: primitive lattice vectors. N1, N2: grid repetitions. cluster_shape: shape string as in make_cluster, plus ‘polygon’.
- Optional keys:
- cl_basis: list of (2,) offsets for a multi-site basis
(default [[0,0]] – single-site Bravais lattice).
cl_poly: vertex list for polygon masking (required if shape=’polygon’). direction: polygon masking direction – 0 interior, 1 exterior. theta: float, rotation in degrees applied after cluster creation. (ellipse semi-axes are N1*|a1| and N2*|a2|; no extra keys needed.)
- Returns:
(N, 2) float64 ndarray, CM at origin.
- flake.cluster.cluster_poly(polygon, params, direction=0)
Mask a lattice with a Shapely polygon.
- Args:
polygon: shapely.geometry.Polygon – masking region. params: dict – cluster parameters (see cluster_from_params). direction: int – 0 = keep interior, 1 = keep exterior.
- Returns:
(N, 2) float64 ndarray.
- flake.cluster.get_poly(points, scale=1, tho=0, c=(0, 0), shift=0, cm=False)
Build a Shapely Polygon from a list of vertices.
Optionally scale, rotate, and shift the polygon before returning.
- Args:
points: array-like (M, 2) – polygon vertices. scale: float – uniform scale factor. tho: float – rotation angle in degrees (ACW). c: (2,) – rotation centre. shift: float or (2,) – translation applied after rotation. cm: bool – if True, translate vertices so their
mean is at the origin before rotating.
- Returns:
shapely.geometry.Polygon
- flake.cluster.load_cluster(filename, angle_deg=0)
Load cluster from .npy file, optionally rotate, then re-centre CM.
- Args:
filename: str – path to .npy file (with or without ‘.npy’). angle_deg: float – ACW rotation applied before recentring (degrees).
- Returns:
(N, 2) float64 ndarray, CM at origin.
- flake.cluster.make_cluster(a1, a2, N1, N2, shape='circle')
Build a finite-size 2D lattice cluster of the requested shape.
- Args:
a1, a2: array-like (2,) – primitive lattice vectors. N1, N2: int – grid repetitions; meaning depends on shape (see module docstring). shape: str – one of ‘circle’, ‘hexagon’, ‘rectangle’, ‘triangle’,
‘parallelogram’, ‘ellipse’.
- Returns:
(N, 2) float64 ndarray – particle positions with CM at origin.
- Raises:
- ValueError: if shape is not recognised, or if shape constraints
are violated (e.g. parallelogram with even sqrt(N)).
- flake.cluster.params_from_poscar(filename, cut_z=0, tol=0.9)
Extract lattice parameters from a POSCAR file via ASE.
Reads the primitive vectors and atomic basis from a 2D slab POSCAR. The returned dict can be passed directly to cluster_from_params to create a cluster of any shape with the correct lattice geometry.
The POSCAR must have the 2D periodicity in the first two lattice vectors (a, b); the third vector c must be along z. All z information is discarded – the geometry is projected to the (x, y) plane. If the slab has multiple layers, use cut_z to select one.
- Args:
filename: str – path to POSCAR file. cut_z: float – keep only atoms with z < cut_z. If 0 (default),
uses one standard deviation of z as threshold.
tol: float – fractional tolerance on cut_z (default 0.9).
- Returns:
Tuple
(params_dict, pos_z)whereparams_dicthas keys'a1', 'a2', 'cl_basis'andpos_zis a(M,)array of z coordinates of atoms excluded by the z filter.- Raises:
ImportError: if ASE is not installed. RuntimeError: if no atoms pass the z filter.
- flake.cluster.rotate(pos, angle_deg, center=(0, 0))
Rotate positions counter-clockwise by angle_deg degrees about center.
- Args:
pos: (N, 2) array-like – input positions. angle_deg: float – rotation angle in degrees (ACW positive). center: (2,) array-like – rotation center (default origin).
- Returns:
(N, 2) float64 ndarray – rotated positions.
- flake.cluster.save_cluster(pos, filename)
Save cluster positions as a .npy file.
- Args:
pos: (N, 2) array-like – particle positions. filename: str – output path (extension added by np.save).
- flake.cluster.save_xyz(pos, filename, elem='X')
Write an XYZ file for visualisation (z coordinate set to zero).
- Args:
pos: (N, 2) array-like – particle positions. filename: str – output path. elem: str – element symbol written in each line.