Skip to content

kups.application.potential.filter

Concrete relaxation filters as gradient lenses over the shared Geometry.

A relaxation filter answers "which degrees of freedom does the optimizer see?". Each is a Lens[Geometry, PositionsAndCell] selecting the optimizer DOFs from the shared geometric view; compose a carrier adapter (e.g. GRAPH_GEOMETRY) with a filter via NestedLens to obtain a potential gradient_lens.

The geometric-view types live in kups.potential.common.geometry.

FRECHET_FILTER = LambdaLens(_frechet_filter_get, _frechet_filter_set) module-attribute

Atoms-ride-the-cell filter; the frame chooses the conditioning.

DOFs are (q, cell) with q = (r @ h^-1) @ R for the cell's fixed reference basis R = frame.reference_vectors. On set, r = (q @ R^-1) @ h so atoms ride the cell at fixed fractional coordinates (the virial coupling falls out of autodiff); the per-axis periodicity mask h_eff = m*h + (1-m)*stop_gradient(h) keeps non-periodic axes out of the riding derivative without disturbing the primal.

The reference is the frame's: a DeformedFrame returns its base, so q is reference-cartesian (ASE FrechetCellFilter conditioning); any other frame returns the identity, so q is fractional (ASE UnitCellFilter conditioning).

POSITIONS_AND_CELL = lens(lambda g: PositionsAndCell(g.particles.map_data(lambda p: p.positions), g.systems)) module-attribute

Positions + cell DOFs with atoms pinned (today's default cell gradient).

POSITIONS_ONLY = LambdaLens(lambda g: PositionsAndCell(g.particles.map_data(lambda p: p.positions), g.systems), _positions_only_set) module-attribute

Positions-only DOFs (optimize_cell=False): the cell rides along in the PositionsAndCell codomain but is stop-gradiented on set, so ∂E/∂cell is zero while the DOF pytree matches the cell filters.