Skip to content

Port the magnetic exchange workflow from atomate1 (Heisenberg fit + Vampire Tc) - #1528

Draft
Luguza wants to merge 11 commits into
materialsproject:mainfrom
Luguza:exchange-workflow-port-from-atomate1
Draft

Port the magnetic exchange workflow from atomate1 (Heisenberg fit + Vampire Tc)#1528
Luguza wants to merge 11 commits into
materialsproject:mainfrom
Luguza:exchange-workflow-port-from-atomate1

Conversation

@Luguza

@Luguza Luguza commented Aug 18, 2026

Copy link
Copy Markdown

Summary

Port of atomate1's ExchangeWF. Closes #1404.
However, this PR is part of a large refactor I did for the underlying HeisenbergMapper from pymatgen.
The following PRs are connected and potentially still ongoing:

Introduces

  • New ExchangeMaker flow (atomate2/common/flows/exchange.py): port of atomate1's
    ExchangeWF. Given magnetic structures with different spin configurations and
    their energies it fits a classical Heisenberg Hamiltonian with pymatgen's
    HeisenbergMapper and, optionally, runs Vampire Monte-Carlo for the critical temperature.
  • New jobs (atomate2/common/jobs/exchange.py): heisenberg_mapping and
    build_exchange_doc, replacing the atomate1 HeisenbergModelMapping,
    HeisenbergModelToDb and VampireToDb firetasks.
  • ExchangeMaker.make_from_ordering_doc convenience constructor for chaining onto the
    magnetic-orderings workflow: it pulls structures, per-atom energies and the parent
    structure out of a computed MagneticOrderingsDocument and re-attaches the magmom site
    property that HeisenbergMapper requires.
  • Input validation in make: structure/energy counts must match, every structure must
    carry a magmom site property, and orderings are sorted so the ground state is index 0.
  • New ExchangeDocument schema (atomate2/common/schemas/exchange.py) with formula,
    parent structure, the {cutoff, tol} Heisenberg settings, the Vampire settings actually
    used, the fit residual (RMS, meV per magnetic ion - intensive in cell size and number of
    orderings, so comparable between materials), ex_params, ex_mat, the serialized
    HeisenbergModel, and critical_temp / full VampireOutput when Vampire was run.
  • New atomate2.vampire subpackage vendoring pymatgen's VampireCaller /
    VampireOutput, which were removed from pymatgen in 2026.3.23 (Major reorganization of pymatgen repo pymatgen#4595).
    Provenance and every local change are documented in the module docstring.
    atomate2/vampire/jobs/run_vampire.py wraps it as a jobflow job.
  • Vendored caller adapted to the reworked HeisenbergModel API: per-ordering
    sublattice_ids and the igraph interaction graph replace the old unique_site_ids dict
    and _get_j_exc lookup, and the ground-state cell is read from magnetic_structures[0]
    rather than structures[0], which now retains the non-magnetic ions. The avg option is
    gone along with the <J> estimate (HeisenbergModel.javg) it read - the model now fits
    shell-resolved J_ij over every ordering and igraph carries them per bond in VAMPIRE's
    normalized-spin meV convention.
  • Fixes in the vendored caller:
    • The .ucf no longer contains non-magnetic ions, which previously entered the file as
      atoms and de-synchronised the interaction block's node indices.
    • Materials are now grouped per (sublattice, spin direction) and each is bound to its own
      unit-cell-category. Without that binding every material kept Vampire's default category
      0, all atoms collapsed into material 1, the magnetic sublattices vanished and the system
      never ordered.
    • An explicit alignment check rejects a model whose igraph, magnetic structure and
      sublattice_ids disagree in length, instead of silently writing a broken .ucf.
    • A non-zero return code from vampire-serial now raises instead of being ignored.
  • Tests (tests/vampire/test_vampire_caller.py): four tests over the .mat/.ucf
    writers, guarding the HeisenbergModel contract the caller relies on (magnetic-only cell,
    in-range interaction indices, .mat/.ucf material agreement, rejection of a misaligned
    model). They monkeypatch the vampire-serial subprocess, so no external binary is needed.
  • pyproject.toml: exclude the vendored vampire_caller.py from ruff so it stays a
    faithful copy of the upstream source, and declare the mutually incompatible
    strict-forcefields-* extras as [tool.uv] conflicts so uv sync can resolve the
    lockfile. The uv change is unrelated to the exchange workflow and can be split out if
    preferred.

Additional dependencies introduced (if any)

  • No new declared dependencies. The vendored vampire_caller.py imports pandas (used
    only to parse Vampire's stdout), which already arrives transitively via pymatgen; it is
    not added to dependencies here. Say the word if it should be declared explicitly.
  • External runtime requirement (optional): the Vampire step shells out to a compiled
    vampire-serial binary on PATH (https://vampire.york.ac.uk/download/). It is guarded by
    monty.dev.requires, and the rest of the flow runs without it via run_vampire=False.

TODO

This is a work-in-progress; the main blocker is upstream.

  • Requires an unreleased pymatgen. The flow and the vendored caller depend on the
    reworked HeisenbergMapper / HeisenbergModel API (magnetic_structures,
    per-ordering sublattice_ids, igraph, residual). The pymatgen change has to land and be
    released first, and the pymatgen>= pin here bumped accordingly, before this can merge.
  • Test coverage is partial: only the vendored input-file writers are tested. There are no
    tests yet for ExchangeMaker, the two jobs, make_from_ordering_doc, or
    ExchangeDocument.from_model.
  • No documentation page for the workflow yet.
  • VampireCaller writes its input files into the current working directory - upstream's
    ScratchDir block is still commented out, as it was in pymatgen.
  • make_from_ordering_doc needs a resolved MagneticOrderingsDocument (it inspects the
    structures while building the flow), so it cannot yet be chained dynamically onto a running
    magnetic-orderings flow via an output reference.

Checklist

  • Code is in the standard Python style
  • Doc strings have been added in the Numpy docstring format
    for the flow, jobs and schema - two small vendored-adjacent modules are still missing
    module-level docstrings.
  • Type annotations are used throughout the new atomate2 code (the vendored file keeps
    upstream's annotations as-is). mypy has not been run yet.
  • Tests have been added for the vendored input-file writers; the flow, jobs and schema
    are not yet covered.
  • All tests pass (the new tests pass only against the unreleased pymatgen
    branch above).

Luca Frey and others added 10 commits June 1, 2026 17:06
added a ex_mat field to the ExchangeDocument
The pymatgen fork's HeisenbergModel replaced the ground-state
unique_site_ids dict with per-ordering site_labels and dropped
_get_j_exc, which crashed run_vampire (TypeError in _create_mat).
_create_mat now groups sites into materials by (sublattice, spin sign)
straight from site_labels[0], and _create_ucf reads the per-bond J_ij
from the igraph edge weights. Also fixes the material-element lookup
(it indexed the structure with a sublattice id instead of a site index)
and drops the unused HeisenbergMapper construction path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…atgen and update ExchangeDocument to include vampire_settings; add tests for VampireCaller input-file writers.
…ler; update ExchangeDocument schema to include residuals and remove avg option.
@JaGeo

JaGeo commented Aug 18, 2026

Copy link
Copy Markdown
Member

@Luguza thanks! That's great! I am on vacation at the moment and back at the beginning of September. In case I don't react then, could you please ping me again?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

atomate1 parity: exchange workflow

2 participants