Skip to content

scattering/pyspinw

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PySpinW

Python 3.9+ License: GPL v3

A Python implementation of SpinW for spin wave calculations using linear spin wave theory (LSWT).

Features

  • Crystal Structure: Define lattices with space group symmetry (P1, Pm-3m, Fd-3m, P-3, etc.)
  • Magnetic Atoms: Arbitrary spin quantum number S and g-tensor
  • Exchange Interactions: Heisenberg, anisotropic, Dzyaloshinskii-Moriya (DM)
  • Magnetic Structures: Ferromagnetic, antiferromagnetic, helical, spiral, 120° order
  • Spin Wave Theory: Full BdG Hamiltonian diagonalization via σz·H method
  • Neutron Scattering: S(Q,ω) with magnetic form factors
  • Multiple Backends: NumPy (CPU), PyTorch (GPU-accelerated)

Installation

From PyPI

pip install pyspinwave

From source

git clone https://github.com/scattering/pyspinw.git
cd pyspinw
pip install -e .

With GPU support

pip install pyspinwave[gpu]

Development installation

pip install -e ".[dev]"

Building and Publishing

The project includes a Docker-based build script for reproducible builds:

# Clean build artifacts
./scripts/build.sh clean

# Build package in Docker
./scripts/build.sh build

# Build and publish to PyPI
./scripts/build.sh publish

# Run tests in Docker
./scripts/build.sh test

Requires Docker (or OrbStack on macOS) to be running.

Quick Start

Example 1: Ferromagnetic Chain

import numpy as np
from pyspinw import SpinW

# Create spin model
sw = SpinW()
sw.genlattice(lat_const=[3, 8, 8], angled=[90, 90, 90])
sw.addatom(r=[0, 0, 0], S=1, label='Fe')
sw.gencoupling(max_distance=4)

# Add ferromagnetic exchange J = -1 meV
sw.addmatrix(label='J', value=-1.0)
sw.addcoupling(mat='J', bond=1)

# Set ferromagnetic ground state
sw.genmagstr(mode='direct', k=[0, 0, 0], S=np.array([[0, 0, 1]]))

# Calculate spin wave dispersion
spec = sw.spinwave([[0, 0, 0], [1, 0, 0]], n_pts=200)

# Plot
import matplotlib.pyplot as plt
q = np.linspace(0, 1, 200)
plt.plot(q, spec['omega'][:, 0])
plt.xlabel('q (r.l.u.)')
plt.ylabel('Energy (meV)')
plt.title('FM Chain Dispersion')
plt.show()

Example 2: Triangular Antiferromagnet with 120° Order

from pyspinw import SpinW, sw_model

# Use predefined model
sw = sw_model('triAF', J=1.0)  # J = 1 meV AFM

# Or build manually:
sw = SpinW()
sw.genlattice(lat_const=[4, 4, 6], angled=[90, 90, 120])
sw.addatom(r=[0, 0, 0], S=1.5, label='Mn')
sw.gencoupling(max_distance=5)
sw.addmatrix(label='J1', value=1.0)
sw.addcoupling(mat='J1', bond=1)

# 120° helical structure
sw.genmagstr(mode='helical', k=[1/3, 1/3, 0], n=[0, 0, 1])

# Calculate along Γ-K-M path
spec = sw.spinwave([[0, 0, 0], [1/3, 1/3, 0], [0.5, 0, 0]], n_pts=150)

Example 3: Square Lattice AFM with DM Interaction

from pyspinw import SpinW
import numpy as np

sw = SpinW()
sw.genlattice(lat_const=[4, 4, 10], angled=[90, 90, 90])
sw.addatom(r=[0, 0, 0], S=1, label='Cu')
sw.gencoupling(max_distance=5)

# Heisenberg exchange
sw.addmatrix(label='J', value=1.0)
sw.addcoupling(mat='J', bond=1)

# DM interaction D·(Si × Sj)
sw.addmatrix(label='D', value=[0, 0, 0.1])  # D_z = 0.1 meV
sw.addcoupling(mat='D', bond=1)

# Néel order
sw.genmagstr(mode='direct', k=[0.5, 0.5, 0], S=np.array([[0, 0, 1]]))

spec = sw.spinwave([[0, 0, 0], [0.5, 0.5, 0]], n_pts=100)

API Reference

SpinW Class

The main class for spin wave calculations.

Lattice Definition

sw.genlattice(lat_const=[a, b, c], angled=[α, β, γ], spgr='P 1')
  • lat_const: Lattice parameters [a, b, c] in Ångströms
  • angled: Lattice angles [α, β, γ] in degrees
  • spgr: Space group symbol (e.g., 'Fm-3m', 'P 63/mmc')

Adding Atoms

sw.addatom(r=[x, y, z], S=spin, label='atom_name')
  • r: Fractional coordinates [x, y, z]
  • S: Spin quantum number (e.g., 0.5, 1, 1.5)
  • label: Atom label for identification

Generating Couplings

sw.gencoupling(max_distance=10.0)

Generates all symmetry-equivalent bonds up to max_distance Å.

Adding Exchange Matrices

# Heisenberg (isotropic)
sw.addmatrix(label='J1', value=1.0)

# Anisotropic exchange
sw.addmatrix(label='J_aniso', value=[[Jxx, Jxy, Jxz],
                                      [Jxy, Jyy, Jyz],
                                      [Jxz, Jyz, Jzz]])

# Dzyaloshinskii-Moriya
sw.addmatrix(label='DM', value=[Dx, Dy, Dz])

Assigning Couplings

sw.addcoupling(mat='J1', bond=1)  # Assign J1 to nearest neighbors
sw.addcoupling(mat='J2', bond=2)  # Assign J2 to next-nearest neighbors

Magnetic Structure

# Ferromagnetic
sw.genmagstr(mode='direct', k=[0, 0, 0], S=np.array([[0, 0, 1]]))

# Antiferromagnetic (Néel)
sw.genmagstr(mode='direct', k=[0.5, 0.5, 0], S=np.array([[0, 0, 1]]))

# Helical/Spiral
sw.genmagstr(mode='helical', k=[1/3, 1/3, 0], n=[0, 0, 1])
  • mode: 'direct' for explicit spins, 'helical' for spiral structures
  • k: Propagation vector in reciprocal lattice units
  • n: Rotation axis for helical structures
  • S: Spin vectors, shape (n_atoms, 3)

Spin Wave Calculation

spec = sw.spinwave(Q_path, n_pts=100, formfact=False)
  • Q_path: List of Q-points defining the path, e.g., [[0,0,0], [1,0,0]]
  • n_pts: Number of points along the path
  • formfact: Include magnetic form factor (default: False)

Returns dictionary with:

  • omega: Spin wave energies, shape (n_pts, n_modes)
  • Sab: Dynamical structure factor components
  • hkl: Q-points along path

Energy Calculation

E = sw.energy()  # Returns energy per site in meV

Utility Functions

Energy Broadening

from pyspinw.utils import sw_egrid

spec = sw_egrid(spec, dE=0.1, Emin=0, Emax=10, n_E=100)

Convolves with Gaussian of width dE meV.

Plotting

from pyspinw.utils import sw_plotspec

sw_plotspec(spec, mode='color')  # Color plot of S(Q,ω)
sw_plotspec(spec, mode='line')   # Line plot of dispersion

Predefined Models

from pyspinw import sw_model

sw = sw_model('chain', J=1.0)    # 1D antiferromagnetic chain
sw = sw_model('squareAF', J=1.0) # 2D square lattice AFM
sw = sw_model('triAF', J=1.0)    # 2D triangular lattice 120° AFM

Physics Background

Linear Spin Wave Theory

PySpinW implements linear spin wave theory (LSWT) following the Holstein-Primakoff transformation:

S⁺ ≈ √(2S) a
S⁻ ≈ √(2S) a†
Sᶻ = S - a†a

The spin Hamiltonian is expanded to quadratic order in bosonic operators, yielding a BdG Hamiltonian:

H = Σ_q [A(q) B(q) ] [a_q  ]
        [B*(q) A*(q)] [a†_{-q}]

Diagonalization via the σz·H method gives spin wave energies ω(q).

Validation

PySpinW has been validated against:

  • Analytical results: FM chain ω(q) = 2|J|S(1-cos(2πq)) with < 10⁻⁹ error
  • Sunny.jl: 6/6 SpinW tutorial ports pass (SW01-SW08, CoRh2O4)
  • spinw_torch: Minimalist PyTorch reference implementation

Project Structure

pyspinw/
├── pyspinw/             # Package directory (import as: from pyspinw import ...)
│   ├── __init__.py      # Package exports
│   ├── core/
│   │   ├── spinw.py     # Main SpinW class
│   │   ├── lswt.py      # Linear spin wave theory
│   │   ├── lattice.py   # Crystal lattice
│   │   ├── magnetic.py  # Magnetic structures
│   │   ├── coupling.py  # Exchange couplings
│   │   └── constants.py # Physical constants
│   ├── backends/
│   │   ├── numpy_backend.py  # CPU implementation
│   │   └── pytorch_backend.py # GPU implementation
│   └── utils/
│       ├── egrid.py     # Energy convolution
│       ├── plotting.py  # Visualization
│       └── neutron.py   # Neutron scattering
├── tests/               # Test suite
│   ├── test_spinw.py
│   └── test_sunny_comparison.py
├── examples/            # Example scripts and notebooks
│   ├── quickstart.ipynb
│   └── demos.py
├── scripts/
│   └── build.sh         # Docker build script
├── pyproject.toml       # Build configuration
├── README.md
├── CHANGELOG.md
└── CONTRIBUTING.md

Running Tests

# All tests
pytest

# With coverage
pytest --cov=pyspinw

# Specific test file
pytest tests/test_sunny_comparison.py -v

Known Limitations

  • Space groups: 9 of 230 implemented (P1, Pm-3m, Fm-3m, Fd-3m, P-3, P63/mmc, I4/mmm, R-3m, Pnma)
  • Form factors: Simplified dipole approximation
  • Single-ion anisotropy: Basic support only
  • Powder averaging: Not yet implemented
  • Inelastic neutron scattering: S(Q,ω) without resolution convolution

References

  • SpinW - Original MATLAB implementation
  • Sunny.jl - Julia spin dynamics package
  • Toth & Lake, J. Phys.: Condens. Matter 27, 166002 (2015)
  • Colpa, Physica 93A, 327 (1978)

License

GPL-3.0 (following the original SpinW license)

Contributing

Contributions welcome! Please see CONTRIBUTING.md and submit issues/PRs on GitHub.

Citation

If you use PySpinW in your research, please cite:

@software{PySpinW,
  title = {PySpinW: Python Spin Wave Calculator},
  url = {https://github.com/scattering/pyspinw},
  version = {0.1.0},
  year = {2025}
}

And the original SpinW paper:

@article{spinw,
  author = {Toth, S. and Lake, B.},
  title = {Linear spin wave theory for single-Q incommensurate magnetic structures},
  journal = {J. Phys.: Condens. Matter},
  volume = {27},
  pages = {166002},
  year = {2015},
  doi = {10.1088/0953-8984/27/16/166002}
}

About

No description, website, or topics provided.

Resources

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published