mag4.fit

Linear least-squares (energy-mapping) estimator for Heisenberg couplings.

Layer: common — the back-end-agnostic estimator behind mag4-extract --method energy-mapping. The model energy of a magnetic configuration is linear in the unknowns,

E(config) = E0 + Σ_k JS²_k · c_k(config),

where c_k are the integer coefficients written by mag4.energy_mapping.write_energy_mapping_report() (Ising spins ±1, so each fitted coupling is the JS² product; divide by for the bare J). Because the model is linear, the RMS-optimal parameters come from a single np.linalg.lstsq solve — the global solution, no iteration.

Ported from the standalone fit_J.py precursor. Before fitting, columns that are indeterminate are dropped:

  • constant columns (the same coefficient in every order) are collinear with E0 and only shift it;

  • columns flagged as folding onto a periodic self-image (unreliable);

  • columns exactly proportional to another kept column (aliased in a too-small cell) — only their combination is determined.

A near-collinearity (VIF) diagnostic and covariance-based error bars flag couplings whose split is poorly conditioned even when the overall fit is tight.

Functions

fit_couplings(records, labels, energies, *)

Fit E = E0 + Σ JS²_k c_k by linear least-squares.

spin_power(label)

Power of S by which a fitted coupling is divided to get the bare exchange: pairwise enters as J·S², the four-spin ring term as Jring·S⁴ (Ising spins ±1).

Classes

FitResult(e0, js2, se, se_e0, dropped, kept, ...)

Outcome of one energy-mapping fit (energies and JS² in eV).

mag4.fit.spin_power(label)[source]

Power of S by which a fitted coupling is divided to get the bare exchange: pairwise enters as J·S², the four-spin ring term as Jring·S⁴ (Ising spins ±1).

Return type:

int

Parameters:

label (str)

class mag4.fit.FitResult(e0, js2, se, se_e0, dropped, kept, vif, rms_eV, rms_dof_eV, n_data, n_param, residuals, max_corr)[source]

Bases: object

Outcome of one energy-mapping fit (energies and JS² in eV).

Parameters:
e0: float
js2: Dict[str, float]
se: Dict[str, float]
se_e0: float | None
dropped: Dict[str, str]
kept: List[str]
vif: Dict[str, float]
rms_eV: float
rms_dof_eV: float
n_data: int
n_param: int
residuals: Dict[int, float]
max_corr: Tuple[str, str, float] | None
mag4.fit.fit_couplings(records, labels, energies, *, weight_by_deg=False, keep_collinear=False, unreliable=())[source]

Fit E = E0 + Σ JS²_k c_k by linear least-squares.

Parameters:
  • records (list of {"number", "coefficients": {label: c}, "degeneracy", "sz"}.)

  • labels (coupling names in column order.)

  • energies ({config_number: energy_eV} for the configurations to fit) – (caller filters to converged ones).

  • weight_by_deg (weight each residual by sqrt(degeneracy).)

  • keep_collinear (keep every column (skip the indeterminate-column drops).)

  • unreliable (coupling names known to fold onto self-images (dropped).)

Raises:

ValueError – If fewer usable energies than parameters (E0 + kept couplings).

Return type:

FitResult