mag4.dimers

Dimer search for the four-state method (direct intra-cell Cartesian distances).

Functions

can_assign_unique_dimers(dimers, couplings)

Return True iff the greedy assignment used by the four-state pipeline can give every coupling a distinct (idx_a, idx_b) pair.

check_coupling_spacing(couplings, user_tol)

Inspect spacing between consecutive J distances and return a safe dimer-search tolerance.

find_dimers(atoms, lat_mat, couplings, tol)

Find all intra-cell atom pairs for each coupling distance ± tol.

mag4.dimers.check_coupling_spacing(couplings, user_tol)[source]

Inspect spacing between consecutive J distances and return a safe dimer-search tolerance.

Warns when:

  • --tol is larger than half the minimum spacing (two J shells could share a dimer).

  • Two consecutive J values are closer than 2*DIST_EQUIV_TOL (probably the same shell).

When two adjacent couplings are intentionally at the same distance (e.g. sub-shells J1a / J1b produced by geometry-aware grouping — distinguished by their bridging-angle fingerprint, not by distance), the zero gap between them is not a noise issue: it is dropped from the warning and from the safe_tol computation so the dimer search can still use a non-zero distance tolerance. The angle filter in find_dimers() keeps the sub-shells apart.

Return type:

float

Parameters:
mag4.dimers.find_dimers(atoms, lat_mat, couplings, tol, verbose=True, *, structure=None, ligand_elements=None, bond_cutoff=2.5, angle_tol=1.0, ll_cutoff=0.0, signed_dihedral=False)[source]

Find all intra-cell atom pairs for each coupling distance ± tol.

Set verbose=False to silence info logs and the missing-coupling warning block; useful when scanning many trial supercells.

Return type:

Dict[str, List[Dimer]]

Parameters:

Design principle

The four-state method requires that the two atoms of a dimer be DISTINCT sites in the working cell so that they can be assigned independent spins. Using periodic images to “find” a coupling would conflate atom j with its image j + (h, k, l), which is already a different atom in the supercell.

The correct workflow is therefore:

  1. Build a supercell large enough that every coupling distance d_Jn appears as a genuine intra-cell pair (direct Cartesian distance).

  2. Use plain scipy.spatial.distance.cdist() here — no wrapping, no image search.

If a coupling is not found as a direct pair the cell is too small along one axis. The function diagnoses which axis and tells the user exactly which --supercell flag to try.

Angle-aware mode

When structure (a pymatgen.core.Structure of the same supercell, with the magnetic atoms placed at indices 0..N_mag-1 — see mag4.geometry.crystal_to_pymatgen()) and ligand_elements are supplied, each couplings entry must be a triple [label, distance, fingerprint]. A candidate pair is then accepted only when both its distance and its M–L–M bridging-angle fingerprint match the target. This lets the four-state pipeline distinguish J shells that are degenerate in distance but route super-exchange through different bridging geometries.

mag4.dimers.can_assign_unique_dimers(dimers, couplings)[source]

Return True iff the greedy assignment used by the four-state pipeline can give every coupling a distinct (idx_a, idx_b) pair.

Mirrors the assignment logic in mag4.cli.fourstate so the optimal supercell search rejects cells that find the right distances but cannot assign them all to non-overlapping site pairs.

Return type:

bool

Parameters: