Skip to content

Commit

Permalink
Update tutorials 1 through 4 (#299)
Browse files Browse the repository at this point in the history
Also:
* Disable `minimize_energy!` warnings which were unreliable.
* Simplify `latsize` printing of system ("reshaped" only relevant if unit cell has changed).
  • Loading branch information
kbarros authored Aug 24, 2024
1 parent 9cd8851 commit b582fb1
Show file tree
Hide file tree
Showing 12 changed files with 778 additions and 802 deletions.
13 changes: 5 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,15 @@

Sunny is a Julia package for modeling atomic-scale magnetism using classical spin dynamics with quantum corrections. It provides powerful tools to estimate dynamical structure factor intensities, $\mathcal{S}(𝐪,ω)$, enabling quantitative comparison with experimental scattering data, e.g., neutrons or x-rays.

A unique feature of Sunny is its treatment of spins as [SU(_N_) coherent states](https://doi.org/10.48550/arXiv.2106.14125). Each quantum spin-_S_ state is a superposition of $N=2S+1$ levels, and evolves under unitary, SU(_N_) transformations. When entanglement is neglected, the formalism allows to generalize the Landau-Lifshitz dynamics of spin dipoles to a dynamics of spin multipoles. The theory becomes especially useful for modeling materials with strong single-ion anisotropy effects (see our [FeI₂ tutorial](https://sunnysuite.github.io/Sunny.jl/dev/examples/01_LSWT_SU3_FeI2.html)). In the future, Sunny will also support explicit spin-orbit coupling, and 'units' of locally entangled spins.
A unique feature of Sunny is its treatment of spins as [SU(_N_) coherent states](https://arxiv.org/abs/2106.14125). This theory generalizes Landau-Lifshitz spin dynamics to a [nonlinear Schrödinger equation](https://arxiv.org/abs/2204.07563), which retains $N=2S+1$ levels for each quantum spin-_S_ state. The theory is effective for models with strong single-ion anisotropy (see our **[FeI₂ tutorial](https://sunnysuite.github.io/Sunny.jl/dev/examples/03_LSWT_SU3_FeI2.html)**) and for [localized "units" of strongly entangled spins](https://arxiv.org/abs/2405.16315). Efficient simulation is enabled by several algorithmic developments as listed on our [publications page](https://github.com/SunnySuite/Sunny.jl/wiki/Sunny-literature).

At low-temperatures, Sunny supports the usual linear spin wave theory for spin dipoles, and its ['multi-boson' generalization](https://doi.org/10.48550/arXiv.1307.7731). At finite temperatures, the full classical dynamics (with quantum correction factors) may be preferable to capture strongly nonlinear fluctuations. The [coupling of SU(_N_) spins to a thermal bath](https://doi.org/10.48550/arXiv.2209.01265) also makes possible the study of various non-equilibrium dynamics, e.g., thermal transport, pump-probe experiments, and spin-glass relaxation.

Sunny provides a number of tools to facilitate the specification and solution of spin Hamiltonians. This includes spacegroup symmetry analysis, powerful Monte Carlo sampling algorithms, and interactive 3D visualization. Efficient simulation is made possible by several algorithmic developments. See our [Sunny publications](https://github.com/SunnySuite/Sunny.jl/wiki/Sunny-literature) for more information.
At low-temperatures, Sunny supports the usual linear spin wave theory for spin dipoles, and its ['multi-boson' generalization](https://arxiv.org/abs/1307.7731). At finite temperatures, Sunny can calculate the dynamical structure factor using classical spin dynamics with quantum corrections. Langevin coupling to a thermal bath additionally makes possible the study of various non-equilibrium dynamics, e.g., thermal transport, pump-probe experiments, and spin-glass relaxation.

Sunny provides a number of tools to facilitate the specification and solution of spin Hamiltonians. This includes spacegroup symmetry analysis, powerful Monte Carlo sampling algorithms, and interactive 3D visualization.

## Try it out!

New Julia users should begin with our **[Getting Started](https://github.com/SunnySuite/Sunny.jl/wiki/Getting-started-with-Julia)** guide. A showcase for Sunny is the **[FeI₂ tutorial](https://sunnysuite.github.io/Sunny.jl/dev/examples/01_LSWT_SU3_FeI2.html)**. This compound has a strong easy-axis anisotropy which gives rise to a single-ion bound state, and serves to exemplify the power of simulating SU(_N_) coherent states. Regarding the traditional linear spin wave theory of dipoles, see our [adaptations of the SpinW tutorials](https://sunnysuite.github.io/Sunny.jl/dev/examples/spinw/SW08_Kagome_AFM.html).
New Julia users should begin with our **[Tutorials](https://sunnysuite.github.io/Sunny.jl/dev/examples/01_LSWT_CoRh2O4)**. For traditional linear spin wave theory, see also the **[SpinW ports](https://sunnysuite.github.io/Sunny.jl/dev/examples/spinw/SW01_FM_Heseinberg_chain.html)**.

Sunny is evolving rapidly. [Version History](https://sunnysuite.github.io/Sunny.jl/dev/versions/) lists the new features and breaking changes. To install a specific version of Sunny, say `v0.x`, use the command `add Sunny@0.x`.

Expand All @@ -53,9 +52,7 @@ Sunny is inspired by SpinW, especially regarding symmetry analysis, model specif
| Ewald summation for dipole-dipole ||||
| Programming language | C++ | Matlab | [Julia](https://julialang.org/) |

The classical SU(_N_) spin dynamics in Sunny generalizes the Landau-Lifshitz equation for $S > 1/2$ quantum spins. Linearizing and quantizing SU(_N_) dynamics yields a generalization of spin wave theory involving multi-flavor bosons.

Codes like [Spirit](https://github.com/spirit-code/spirit) and [Vampire](https://vampire.york.ac.uk/) focus less on capturing quantum effects, but may be good options for classical dynamics of pure dipoles.
Codes like [Spirit](https://github.com/spirit-code/spirit) and [Vampire](https://vampire.york.ac.uk/) focus less on capturing quantum effects, but may be better options for the dynamics of classical dipoles, e.g., in the micromagnetics context.

## Join our community

Expand Down
2 changes: 1 addition & 1 deletion docs/src/structure-factor.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ sublattice $j$.

Calculating the structure factor involves several steps, with various possible
settings. Sunny provides tools to facilitate this calculation and to extract
information from the results. For details, please see our [tutorials](@ref "2.
information from the results. For details, please see our [tutorials](@ref "1.
Spin wave simulations of CoRh₂O₄") as well as the complete [Library API](@ref).

Sunny will calculate the structure factor in dimensionless, intensive units,
Expand Down
192 changes: 192 additions & 0 deletions examples/01_LSWT_CoRh2O4.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# # 1. Spin wave simulations of CoRh₂O₄
#
# This tutorial introduces Sunny through its features for performing
# conventional spin wave theory calculations. For concreteness, we consider the
# crystal CoRh₂O₄ and reproduce the calculations of [Ge et al., Phys. Rev. B 96,
# 064413](https://doi.org/10.1103/PhysRevB.96.064413).

# ### Get Julia and Sunny
#
# Sunny is implemented in Julia, which allows for interactive development (like
# Python or Matlab) while also providing high numerical efficiency (like C++ or
# Fortran). New Julia users should begin with our **[Getting
# Started](https://github.com/SunnySuite/Sunny.jl/wiki/Getting-started-with-Julia)**
# guide. Sunny requires Julia 1.10 or later.
#
# From the Julia prompt, load both `Sunny` and `GLMakie`. The latter is needed
# for graphics.

using Sunny, GLMakie

# If these packages are not yet installed, Julia will offer to install them for
# you. If executing this script gives an error, you may need to `update` Sunny
# and GLMakie from the [built-in package
# manager](https://github.com/SunnySuite/Sunny.jl/wiki/Getting-started-with-Julia#the-built-in-julia-package-manager).

# ### Units

# The [`Units`](@ref) object defines physical constants for conversions. Select
# meV as the default energy scale and angstrom as the default length scale.

units = Units(:meV, :angstrom);

# ### Crystal cell
#
# A crystallographic cell may be loaded from a `.cif` file, or can be specified
# from atom positions and types.
#
# Start by defining the shape of the conventional chemical cell. CoRh₂O₄ has
# cubic spacegroup 227 (Fd-3m). Its lattice constants are 8.5 Å, and the cell
# angles are 90°. With this information, [`lattice_vectors`](@ref) constructs a
# 3×3 matrix `latvecs`. Columns of `latvecs` define the lattice vectors ``(𝐚_1,
# 𝐚_2, 𝐚_3)`` in the global Cartesian coordinate system. Conversely, columns
# of `inv(latvecs)` define the global Cartesian axes ``(\hat{x}, \hat{y},
# \hat{z})`` in components of the lattice vectors.

a = 8.5031 # (Å)
latvecs = lattice_vectors(a, a, a, 90, 90, 90)

# Construct the [`Crystal`](@ref) cell from the spacegroup number 227 and one
# representative atom of each occupied Wyckoff. In the standard setting of
# spacegroup 227, position `[0, 0, 0]` belongs to Wyckoff 8a, which is the
# diamond cubic crystal.

positions = [[0, 0, 0]]
cryst = Crystal(latvecs, positions, 227; types=["Co"], setting="1")

# [`view_crystal`](@ref) launches an interface for interactive inspection and
# symmetry analysis.

view_crystal(cryst)

# ### Spin system

# A [`System`](@ref) will define the spin model. This requires
# [`SpinInfo`](@ref) information for one representative atom per
# symmetry-distinct site. The cobalt atoms have quantum spin ``S = 3/2``. The
# ``g``-factor defines the magnetic moment ``μ = g 𝐒`` in units of the Bohr
# magneton. The option `:dipole` indicates a traditional model type, for which
# quantum spin is modeled as a dipole expectation value.

latsize = (1, 1, 1)
S = 3/2
sys = System(cryst, latsize, [SpinInfo(1; S, g=2)], :dipole)

# Previous work demonstrated that inelastic neutron scattering data for CoRh₂O₄
# is well described with a single antiferromagnetic nearest neighbor exchange,
# `J = 0.63` meV. Use [`set_exchange!`](@ref) with the bond that connects atom 1
# to atom 3, and has zero displacement between chemical cells. Applying the
# symmetries of spacegroup 227, Sunny will propagate this interaction to the
# other nearest-neighbor bonds. Calling [`view_crystal`](@ref) with `sys` now
# shows the antiferromagnetic Heisenberg interactions as blue polkadot spheres.

J = +0.63 # (meV)
set_exchange!(sys, J, Bond(1, 3, [0, 0, 0]))
view_crystal(sys)

# ### Optimizing spins

# To search for the ground state, call [`randomize_spins!`](@ref) and
# [`minimize_energy!`](@ref) in sequence. For this problem, optimization
# converges rapidly to the expected Néel order. See this with
# [`plot_spins`](@ref), where spins are colored according to their global
# ``z``-component.

randomize_spins!(sys)
minimize_energy!(sys)
plot_spins(sys; color=[s[3] for s in sys.dipoles])

# The diamond lattice is bipartite, allowing each spin to perfectly anti-align
# with its 4 nearest-neighbors. Each of these 4 bonds contribute ``-JS^2`` to
# the total energy. Two sites participate in each bond, so the energy per site
# is ``-2JS^2``. Check this by calling [`energy_per_site`](@ref).

@assert energy_per_site(sys) -2J*S^2

# ### Reshaping the magnetic cell

# The same Néel order can also be described with a magnetic cell that consists
# of the 2 cobalt atoms in the primitive cell. Columns of the 3×3 `shape` matrix
# below are the primitive lattice vectors in units of the conventional, cubic
# lattice vectors ``(𝐚_1, 𝐚_2, 𝐚_3)``. Use [`reshape_supercell`](@ref) to
# construct a system with this shape, and verify that the energy per site is
# unchanged.

shape = [0 1 1;
1 0 1;
1 1 0] / 2
sys_prim = reshape_supercell(sys, shape)
@assert energy_per_site(sys_prim) -2J*S^2

# Plotting the spins of `sys_prim` shows the primitive cell as a gray wireframe
# inside the conventional cubic cell.

plot_spins(sys_prim; color=[s[3] for s in sys_prim.dipoles])

# ### Spin wave theory

# With this primitive cell, we will perform a [`SpinWaveTheory`](@ref)
# calculation of the structure factor ``\mathcal{S}(𝐪,ω)``. The measurement
# [`ssf_perp`](@ref) indicates projection of the spin structure factor
# perpendicular to the direction of momentum transfer. This measurement is
# appropriate for unpolarized neutron scattering.

swt = SpinWaveTheory(sys_prim; measure=ssf_perp(sys_prim))

# Define a [`q_space_path`](@ref) that connects high-symmetry points in
# reciprocal space. The ``𝐪``-points are given in reciprocal lattice units
# (RLU) for the _original_ cubic cell. For example, `[1/2, 1/2, 0]` denotes the
# sum of the first two reciprocal lattice vectors, ``𝐛_1/2 + 𝐛_2/2``. A total
# of 500 ``𝐪``-points will be sampled along the path.

qs = [[0, 0, 0], [1/2, 0, 0], [1/2, 1/2, 0], [0, 0, 0]]
path = q_space_path(cryst, qs, 500)

# Select [`lorentzian`](@ref) broadening with a full-width at half-maximum
# (FWHM) of 0.8 meV. The isotropic [`FormFactor`](@ref) for Co²⁺ dampens
# intensities at large ``𝐪``.

kernel = lorentzian(fwhm=0.8)
formfactors = [FormFactor("Co2")];

# Calculate the single-crystal scattering [`intensities`](@ref)` along the path,
# for 300 energy points between 0 and 6 meV. Use [`plot_intensities`](@ref) to
# visualize the result.

energies = range(0, 6, 300)
res = intensities(swt, path; energies, kernel, formfactors)
plot_intensities(res; units)

# To directly compare with the available experimental data, perform a
# [`powder_average`](@ref) over all possible crystal orientations. Consider 200
# ``𝐪`` magnitudes ranging from 0 to 3 inverse angstroms. Each magnitude
# defines spherical shell in reciprocal space, to be sampled with `2000`
# ``𝐪``-points. The calculation completes in just a couple seconds because the
# magnetic cell size is small.

radii = range(0, 3, 200) # (1/Å)
res = powder_average(cryst, radii, 2000) do qs
intensities(swt, qs; energies, kernel, formfactors)
end
plot_intensities(res; units, saturation=1.0)

# This result can be compared to experimental neutron scattering data
# from Fig. 5 of [Ge et al.](https://doi.org/10.1103/PhysRevB.96.064413)
# ```@raw html
# <img width="95%" src="https://raw.githubusercontent.com/SunnySuite/Sunny.jl/main/docs/src/assets/CoRh2O4_intensity.jpg">
# ```


# ### What's next?
#
# * For more spin wave calculations of this traditional type, one can browse the
# [SpinW tutorials ported to Sunny](@ref "SW01 - FM Heisenberg chain").
# * Spin wave theory neglects thermal fluctuations of the magnetic order. Our
# [next tutorial](@ref "2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite *T*")
# demonstrates how to sample spins in thermal equilibrium, and measure
# dynamical correlations from the classical spin dynamics.
# * Sunny also offers features that go beyond the dipole approximation of a
# quantum spin via the theory of SU(_N_) coherent states. This can be
# especially useful for systems with strong single-ion anisotropy, as
# demonstrated in our [tutorial on FeI₂](@ref "3. Multi-flavor spin wave
# simulations of FeI₂").
Loading

0 comments on commit b582fb1

Please sign in to comment.