P1 expansion and symmetry operations
A Structure stores the asymmetric unit and an explicit operation list. A P1Cell is the expanded cell; every atom keeps the parent site (site_idx), the operation (op_idx) and the integer lattice shift (tau), so op.apply(site.frac) + tau reproduces its position.
API
use xtalforge::core::{Lattice, Site, StructureBuilder, SymOp};
let inversion = SymOp::parse("-x,-y,-z")?;
let structure = StructureBuilder::new("P -1", Lattice::cubic(5.0)?)
.hall("P -1")
.operation(SymOp::identity())
.operation(inversion)
.site(Site::new("C1", "C", [0.1, 0.2, 0.3])?)
.build()?;
let cell = structure.p1()?;
assert_eq!(cell.n_atoms(), 2);SymOp
SymOp::new(rotation, translation) stores an integer 3x3 rotation and a fractional translation wrapped into [0, 1). identity() builds the identity; rotation() and translation() read the parts; apply and apply_many transform fractional points; compose and inverse build the group arithmetic; is_identity tests it; parse and triplet convert between the -x+1/2,y,z form and the operation.
P1Cell
P1Cell::expand(structure, tolerance) applies every operation to every site, wraps the result into [0, 1), records the provenance and drops duplicate images whose periodic distance is within the tolerance. Structure::p1() uses the default 0.05 Angstrom tolerance. Readers: n_atoms, elements, frac, occupancy, images_of, and the public lattice and atoms fields. P1Atom carries element, label, frac, occupancy, site_idx, op_idx and tau.
The P1 expansion is validated against the Phase 2 symmetry backend and the corpus in Task 1.6.4; the current tests cover the group arithmetic, special positions, provenance and the identity case.