mag4.supercell

Build (na × nb × nc) supercells from a CrystalData.

Functions

check_four_state_isolation(conv_lat_mat, ...)

Per-J algebraic isolation check for the four-state method.

expand_supercell(crystal, na, nb, nc)

Expand a CrystalData by (na × nb × nc).

find_all_dimer_directions(conv_lat_mat, ...)

All distinct unit bond directions of a J shell in the conventional cell.

find_dimer_direction(conv_lat_mat, ...[, ...])

Return a representative unit vector along a J-shell dimer in the conventional cell.

find_optimal_supercell(crystal, couplings, tol)

Return the smallest (na, nb, nc) supercell that resolves and isolates every coupling for the four-state method.

find_supercell_for_enumeration(crystal, ...)

Smallest supercell with no coupling folding onto a periodic self-image.

shortest_periodic_image(lat_mat[, max_n])

Shortest non-zero supercell lattice vector length.

mag4.supercell.expand_supercell(crystal, na, nb, nc)[source]

Expand a CrystalData by (na × nb × nc).

Returns the original instance unchanged when na = nb = nc = 1.

Return type:

CrystalData

Parameters:
mag4.supercell.shortest_periodic_image(lat_mat, max_n=3)[source]

Shortest non-zero supercell lattice vector length.

Iterates over (n_a, n_b, n_c) [-max_n, max_n]^3 \ {(0,0,0)} and returns the minimum |n_a a + n_b b + n_c c|. For cubic / orthorhombic / hexagonal cells this reduces to min(|a|,|b|,|c|); for general triclinic cells the enumeration catches the short diagonal combinations.

Parameters:
  • lat_mat (ndarray) – 3×3 matrix whose columns are the Cartesian lattice vectors a, b, c (mag4’s CrystalData.lattice_matrix convention).

  • max_n (int) – Range of integer coefficients to try. 3 is enough for all standard Bravais types — only severely skewed triclinic lattices could need more, and mag4 doesn’t build those.

Return type:

float

mag4.supercell.find_dimer_direction(conv_lat_mat, target_species, distance, *, dist_tol=0.01, max_image=1)[source]

Return a representative unit vector along a J-shell dimer in the conventional cell.

For each pair (i, j) of magnetic atoms in target_species and each periodic-image translation T within [-max_image, max_image]^3 of the conv lattice, returns the first (r_j + T r_i)/|.| whose length matches distance within dist_tol. None if no such pair exists in the conv cell (rare: would mean the J shell only appears across multiple conv-cell copies in the supercell).

Return type:

Optional[ndarray]

Parameters:
mag4.supercell.find_all_dimer_directions(conv_lat_mat, target_species, distance, *, dist_tol=0.01, max_image=1)[source]

All distinct unit bond directions of a J shell in the conventional cell.

Like find_dimer_direction() but returns every symmetry-equivalent direction (deduplicated by sign, since ±u give the same periodic-image distance). A single coupling can run along several directions at once — e.g. a honeycomb J1 has three — and in an anisotropic supercell they isolate differently, so the isolation check must test all of them, not just one representative. Returns [] if the shell has no in-cell pair.

Return type:

List[ndarray]

Parameters:
mag4.supercell.check_four_state_isolation(conv_lat_mat, multipliers, couplings, target_species=None, *, dimer_vectors=None, rel_tol=0.001, max_multiplicity=None, dimer_multiplicity=None)[source]

Per-J algebraic isolation check for the four-state method.

A Jk dimer (i, j) is isolable in the chosen supercell when its four-state combination E_uu + E_dd E_ud E_du returns only Jk. Flipping (i, j) touches one bond for every periodic image of j that i couples to (all other atoms are a fixed bath that cancels), so the combination equals 4·(Σ over those bonds of their J). Therefore:

  • clean — none of those images sits at a different coupling distance Jm (m≠k). If one does, the formula mixes Jk with Jm and the dimer is contaminated (cross lists the offending Jm). Cleanliness is the whole criterion — this is the “check the cancellation of the other dimers in the 4-state equation” rule.

  • multiplicity M — the number of images at d_k itself ( 1, the bond included). When a compact cell wraps the bond onto its own image through the same Jk (e.g. an axial bond along a doubled axis links ±a, M = 2), the combination yields M·Jk·S² and the extractor divides by the self-coefficient 4·M instead of the textbook 4.

This is purely a property of which images fall at which coupling distance, so it is frame-independent and handles oblique cells. It replaces the older geometric surrogates — bounding box Σ|u_i|L_i, per-axis n_i·L_i 3·d, and the “3 copies of d along the bond” chain rule — all of which demanded a fully isolated (M = 1) dimer and so over-sized the cell. The algebraic rule accepts the smallest cell in which the cross terms cancel, multiplicity and all.

Worked examples (--cutoff giving the J set): tetragonal La₂CuO₄ (J1∥a,b; J2∥[110]) → 2×2×1 (J1 M=2 → /8, J2 M=4 → /16); CsVI₃ (J1, J2 both ∥c) → 1×1×2 (J2 M=2), J1 alone → 1×1×1 (M=2); SrFeO₂ (J1,J2,J3) → 2×2×3 (J2,J3 M=2).

The bond directions come from target_species (all symmetry-equivalent directions) or a single dimer_vectors entry; with neither, a shell has no testable direction and is passed optimistically (M=1).

max_multiplicity (opt-in) caps the accepted dimer multiplicity: a shell is accepted only when it is clean and its multiplicity M (the number of Jk images linking the dimer atoms — the 4·M divisor) does not exceed the cap. max_multiplicity=1 demands a fully isolated dimer (textbook divisor 4) — the geometric-style behaviour exposed on the CLI as --full-isolation — and grows the cell (La₂CuO₄ 2×2×1 → 3×3×1, CsVI₃ 1×1×2 → 1×1×3, SrFeO₂ 2×2×3 → 3×3×3) in exchange for larger, less noise-sensitive cells; intermediate caps (e.g. 2) trade cell size against the largest divisor. A clean shell whose M exceeds the cap is reported ok=False with an empty cross (the failure is high multiplicity, not contamination).

dimer_multiplicity (post-selection only) maps each coupling to the multiplicity of the actually selected dimer — the exact 4·M the report divides by, counted from that dimer’s supercell images. When given it overrides the direction-based worst case for clean shells, so the displayed multiplicity and the cap decision match the formula exactly. The supercell search omits it (no dimer is chosen yet) and stays pessimistic.

Returns a dict with keys:

  • axes — tuple (L_a, L_b, L_c) of supercell axis lengths.

  • d_max — longest coupling distance (the in-range threshold).

  • per_shell — list of {name, d, dimer_dir, multiplicity, cross, ok} dicts, one per coupling. dimer_dir is the chosen clean direction (the one of smallest multiplicity), cross the sorted list of contaminating Jm (empty when clean), ok = (cross is empty). A shell with several symmetry-equivalent directions is OK if any one is clean (mag4 selects that representative dimer).

  • okTrue iff every shell is clean.

  • failing(name, d) tuples for contaminated shells.

  • recommended — smallest (na, nb, nc) (≥ multipliers, by atom count) for which every shell is clean.

Return type:

dict

Parameters:
mag4.supercell.find_optimal_supercell(crystal, couplings, tol, max_mult=4, *, ligand_elements=None, bond_cutoff=2.5, angle_tol=1.0, ll_cutoff=0.0, signed_dihedral=False, isolation=True, max_multiplicity=None)[source]

Return the smallest (na, nb, nc) supercell that resolves and isolates every coupling for the four-state method.

Candidates are enumerated over [1..max_mult]^3 and ranked by (volume, max(na,nb,nc), (na,nb,nc)) so that (1,1,1) is tried first and the most compact / isotropic cells win ties.

Two acceptance criteria are applied to each candidate, in order of size:

  1. Resolve — every coupling has a distinct intra-cell dimer pair (can_assign_unique_dimers()).

  2. Isolate (when isolation=True, the default) — every J shell is also four-state-clean (check_four_state_isolation()): no periodic image of the partner couples to it through a different Jm, so the four-state combination returns only Jk (mixed in with its own multiplicity M, which the extractor divides out as 4·M). This is the algebraic cancellation rule — much weaker than demanding a fully isolated dimer — so the chosen cell is the smallest in which the cross terms vanish.

The smallest candidate passing both is returned. If none isolates within max_mult the function falls back to the smallest resolving cell and logs a warning; the CLI’s post-selection isolation check then errors (the four-state method is only valid for an isolated dimer), telling the user to raise --max-supercell or lower --cutoff. Pass isolation=False to restore the legacy resolve-only selection, or max_multiplicity=N to cap the accepted dimer multiplicity — 1 demands a fully isolated dimer (divisor 4, the old geometric “3 copies of d” rule), larger values trade cell size against the largest 4·M divisor.

When ligand_elements is supplied the geometric fingerprint of each candidate pair must also match the target — sub-shells like J1a / J1b are then resolved as distinct couplings, which may require a larger supercell than distance-only mode.

Raises:

RuntimeError – When no candidate up to max_mult in each direction yields a complete, conflict-free dimer assignment. The message lists the couplings that remained unresolvable.

Return type:

Tuple[Tuple[int, int, int], CrystalData]

Parameters:
mag4.supercell.find_supercell_for_enumeration(crystal, couplings, max_mult=4, *, tol=0.001)[source]

Smallest supercell with no coupling folding onto a periodic self-image.

This is the energy-mapping sizing criterion (distinct from the four-state find_optimal_supercell()). The all-orders enumeration needs every coupling distance d to stay strictly below the shortest lattice translation; otherwise s_i·s_j collapses to s_i² = +1 in every order, the coefficient becomes a constant absorbed into E0, and the coupling is indeterminate in the fit.

Returns the smallest (na, nb, nc) (size-ordered) for which shortest_periodic_image(super) > d_max + tol. If none within max_mult qualifies, returns the largest candidate (which has the longest lattice translations, i.e. the fewest folds) and warns.

Return type:

Tuple[Tuple[int, int, int], CrystalData]

Parameters: