Skip to content

Commit

Permalink
Spiral renamings (#303)
Browse files Browse the repository at this point in the history
Rename `SpiralSpinWaveTheory` → `SpinWaveTheorySpiral`
Rename `spiral_minimize_energy!` → `minimize_spiral_energy!`
  • Loading branch information
kbarros authored Aug 27, 2024
1 parent 134349b commit c181348
Show file tree
Hide file tree
Showing 14 changed files with 58 additions and 59 deletions.
27 changes: 13 additions & 14 deletions docs/src/structure-factor.md
Original file line number Diff line number Diff line change
Expand Up @@ -366,20 +366,19 @@ to $𝒮(𝐪, ω) / g^2$

## Calculations with spin wave theory

Calculation of the dynamical structure factor with linear
[`SpinWaveTheory`](@ref) is relatively straightforward and efficient. In the
traditional approach, quantum spin operators are expressed as Holstein-Primakoff
bosons, and dynamical correlations can be calculated to leading order in inverse
powers of the quantum spin-$s$. Sunny also supports a multi-flavor boson
generalization of this theory, which can offer more accurate treatment of
multipolar spin fluctuations. Another feature in Sunny is
[`SpiralSpinWaveTheory`](@ref), which enables calculations for generalized
spiral order. Finally, the experimental module [`SpinWaveTheoryKPM`](@ref)
implements [spin wave calculations using the kernel polynomial
method](https://arxiv.org/abs/2312.0834). In this approach, the computational
cost scales linearly in the magnetic cell size. Motivation for studying systems
with large magnetic cells include systems with long-wavelength structures, or
systems with quenched chemical disorder.
Calculating the dynamical structure factor with linear [`SpinWaveTheory`](@ref)
is relatively direct. In the traditional approach, quantum spin operators are
expressed with Holstein-Primakoff bosons, and dynamical correlations are
calculated to leading order in inverse powers of the quantum spin-$s$. For
systems constructed with `mode = :SUN`, Sunny automatically switches to a
multi-flavor boson variant of spin wave theory, which captures more single-ion
physics. Use [`SpinWaveTheorySpiral`](@ref) to study generalized spiral phases,
which allow for an incommensurate propagation wavevector. The experimental
module [`SpinWaveTheoryKPM`](@ref) implements [spin wave calculations using the
kernel polynomial method](https://arxiv.org/abs/2312.0834). In the KPM approach,
the computational cost scales linearly in the magnetic cell size. It can be
useful for studying systems with large magnetic cells include systems with
long-wavelength structures, or systems with quenched chemical disorder.


## Calculations with classical spin dynamics
Expand Down
2 changes: 1 addition & 1 deletion docs/src/versions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ This **major release** introduces breaking interface changes.
enables multi-panel plots.
* One should now specify a range of ``𝐪``-points with [`q_space_path`](@ref) or
[`q_space_grid`](@ref).
* [`SpiralSpinWaveTheory`](@ref) is available to perform calculations on
* [`SpinWaveTheorySpiral`](@ref) is available to perform calculations on
generalized spiral structures, which may be incommensurate.
* [`repeat_periodically_as_spiral`](@ref) replaces
`set_spiral_order_on_sublattice!` and `set_spiral_order!`.
Expand Down
6 changes: 3 additions & 3 deletions examples/spinw_tutorials/SW03_Frustrated_chain.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ set_exchange!(sys, J2, Bond(1, 1, [2, 0, 0]))

axis = [0, 0, 1]
randomize_spins!(sys)
k = spiral_minimize_energy!(sys, axis; k_guess=randn(3))
k = minimize_spiral_energy!(sys, axis; k_guess=randn(3))

# The first component of the order wavevector ``𝐤`` has a unique value up to
# reflection symmetry, ``𝐤 → -𝐤``. The second and third components of ``𝐤``
Expand All @@ -48,10 +48,10 @@ k = spiral_minimize_energy!(sys, axis; k_guess=randn(3))
sys_enlarged = repeat_periodically_as_spiral(sys, (8, 1, 1); k, axis)
plot_spins(sys_enlarged; ndims=2)

# Use [`SpiralSpinWaveTheory`](@ref) on the original `sys` to calculate the
# Use [`SpinWaveTheorySpiral`](@ref) on the original `sys` to calculate the
# dispersion and intensities for the incommensurate ordering wavevector.

swt = SpiralSpinWaveTheory(sys; measure=ssf_perp(sys), k, axis)
swt = SpinWaveTheorySpiral(sys; measure=ssf_perp(sys), k, axis)
qs = [[0,0,0], [1,0,0]]
path = q_space_path(cryst, qs, 400)
res = intensities_bands(swt, path)
Expand Down
2 changes: 1 addition & 1 deletion examples/spinw_tutorials/SW08_sqrt3_kagome_AFM.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fig = Figure(size=(768, 300))
swt = SpinWaveTheory(sys_enlarged; measure=ssf_perp(sys_enlarged))
res = intensities_bands(swt, path)
plot_intensities!(fig[1, 1], res; units, saturation=0.5, axisopts=(; title="Supercell method"))
swt = SpiralSpinWaveTheory(sys; measure=ssf_perp(sys), k, axis)
swt = SpinWaveTheorySpiral(sys; measure=ssf_perp(sys), k, axis)
res = intensities_bands(swt, path)
plot_intensities!(fig[1, 2], res; units, saturation=0.5, axisopts=(; title="Spiral method"))
fig
Expand Down
10 changes: 5 additions & 5 deletions examples/spinw_tutorials/SW15_Ba3NbFe3Si2O14.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,13 +59,13 @@ end

# This compound is known to have a spiral order with approximate propagation
# wavevector ``𝐤 ≈ [0, 0, 1/7]``. Search for this magnetic order with
# [`spiral_minimize_energy!`](@ref). Due to reflection symmetry, one of two
# [`minimize_spiral_energy!`](@ref). Due to reflection symmetry, one of two
# possible propagation wavevectors may appear, ``𝐤 = ± [0, 0, 0.1426...]``.
# Note that ``k_z = 0.1426...`` is very close to ``1/7 = 0.1428...``.

axis = [0, 0, 1]
randomize_spins!(sys)
k = spiral_minimize_energy!(sys, axis)
k = minimize_spiral_energy!(sys, axis)

# We can visualize the full magnetic cell using [`repeat_periodically_as_spiral`](@ref),
# which includes 7 rotated copies of the chemical cell.
Expand All @@ -74,12 +74,12 @@ sys_enlarged = repeat_periodically_as_spiral(sys, (1, 1, 7); k, axis)
plot_spins(sys_enlarged; color=[S[1] for S in sys_enlarged.dipoles])

# One could perform a spin wave calculation using either
# [`SpinWaveTheory`](@ref) on `sys_enlarged`, or [`SpiralSpinWaveTheory`](@ref)
# [`SpinWaveTheory`](@ref) on `sys_enlarged`, or [`SpinWaveTheorySpiral`](@ref)
# on the original `sys`. The latter has some restrictions on the interactions,
# but allows for our slightly incommensurate wavevector ``𝐤``.

measure = ssf_perp(sys)
swt = SpiralSpinWaveTheory(sys; measure, k, axis)
swt = SpinWaveTheorySpiral(sys; measure, k, axis)

# Calculate broadened intensities for a path ``[0, 1, L]`` through reciprocal
# space
Expand All @@ -100,7 +100,7 @@ plot_intensities(res; units, axisopts, saturation=0.7, colormap=:jet)
measure = ssf_custom_bm(sys; u=[0, 1, 0], v=[0, 0, 1]) do q, ssf
imag(ssf[2,3] - ssf[3,2])
end
swt = SpiralSpinWaveTheory(sys; measure, k, axis)
swt = SpinWaveTheorySpiral(sys; measure, k, axis)
res = intensities(swt, path; energies, kernel=gaussian(fwhm=0.25))
axisopts = (; title=L"$ϵ_T=-1$, $ϵ_Δ=-1$, $ϵ_H=+1$", titlesize=20)
plot_intensities(res; units, axisopts, saturation=0.8, allpositive=false)
8 changes: 4 additions & 4 deletions examples/spinw_tutorials/SW18_Distorted_kagome.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ set_exchange!(sys, Ja, Bond(3, 4, [0, 0, 0]))
set_exchange!(sys, Jab, Bond(1, 2, [0, 0, 0]))
set_exchange!(sys, Jip, Bond(3, 4, [0, 0, 1]))

# Use [`spiral_minimize_energy!`](@ref) to optimize the generalized spiral
# Use [`minimize_spiral_energy!`](@ref) to optimize the generalized spiral
# order. This determines the propagation wavevector `k`, and fits the spin
# values within the unit cell. One must provide a fixed `axis` perpendicular to
# the polarization plane. For this system, all interactions are rotationally
Expand All @@ -46,7 +46,7 @@ set_exchange!(sys, Jip, Bond(3, 4, [0, 0, 1]))

axis = [0, 0, 1]
randomize_spins!(sys)
k = spiral_minimize_energy!(sys, axis; k_guess=randn(3))
k = minimize_spiral_energy!(sys, axis; k_guess=randn(3))
plot_spins(sys; ndims=2)

# If successful, the optimization process will find one two propagation
Expand Down Expand Up @@ -80,11 +80,11 @@ qs = [[0,0,0], [1,0,0]]
path = q_space_path(cryst, qs, 400)

# Calculate intensities for the incommensurate spiral phase using
# [`SpiralSpinWaveTheory`](@ref). It is necessary to provide the original `sys`,
# [`SpinWaveTheorySpiral`](@ref). It is necessary to provide the original `sys`,
# consisting of a single chemical cell.

measure = ssf_perp(sys; apply_g=false)
swt = SpiralSpinWaveTheory(sys; measure, k, axis)
swt = SpinWaveTheorySpiral(sys; measure, k, axis)
res = intensities_bands(swt, path)
plot_intensities(res; units)

Expand Down
4 changes: 2 additions & 2 deletions src/Reshaping.jl
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,12 @@ be rotated according to the propagation wavevector `k` (in RLU) and the rotation
`axis` (in global Cartesian coordinates). Coincides with
[`repeat_periodically`](@ref) in the special case of `k = [0, 0, 0]`
See also [`spiral_minimize_energy!`](@ref) to find an energy-minimizing
See also [`minimize_spiral_energy!`](@ref) to find an energy-minimizing
wavevector `k` and spin dipole configuration.
# Example
```julia
k = spiral_minimize_energy!(sys, axis; k_guess=randn(3))
k = minimize_spiral_energy!(sys, axis; k_guess=randn(3))
repeat_periodically_as_spiral(sys, counts; k, axis)
```
"""
Expand Down
8 changes: 4 additions & 4 deletions src/SpinWaveTheory/DispersionAndIntensities.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ of `T` describe eigenvectors for ``-𝐪``. The return value is a vector with
similar grouping: the first ``L`` values are energies for ``𝐪``, and the next
``L`` values are the _negation_ of energies for ``-𝐪``.
excitations!(T, tmp, swt::SpiralSpinWaveTheory, q; branch)
excitations!(T, tmp, swt::SpinWaveTheorySpiral, q; branch)
Calculations on a [`SpiralSpinWaveTheory`](@ref) additionally require a `branch`
Calculations on a [`SpinWaveTheorySpiral`](@ref) additionally require a `branch`
index. The possible branches ``(1, 2, 3)`` correspond to scattering processes
``𝐪 - 𝐤, 𝐪, 𝐪 + 𝐤`` respectively, where ``𝐤`` is the ordering wavevector.
Each branch will contribute ``L`` excitations, where ``L`` is the number of
Expand All @@ -106,7 +106,7 @@ end

"""
excitations(swt::SpinWaveTheory, q)
excitations(swt::SpiralSpinWaveTheory, q; branch)
excitations(swt::SpinWaveTheorySpiral, q; branch)
Returns a pair `(energies, T)` providing the excitation energies and
eigenvectors. Prefer [`excitations!`](@ref) for performance, which avoids matrix
Expand Down Expand Up @@ -251,7 +251,7 @@ space.
Traditional spin wave theory calculations are performed with an instance of
[`SpinWaveTheory`](@ref). One can alternatively use
[`SpiralSpinWaveTheory`](@ref) to study generalized spiral orders with a single,
[`SpinWaveTheorySpiral`](@ref) to study generalized spiral orders with a single,
incommensurate-``𝐤`` ordering wavevector. Another alternative is
[`SpinWaveTheoryKPM`](@ref), which may be faster than `SpinWaveTheory` for
calculations on large magnetic cells (e.g., to study systems with disorder). In
Expand Down
2 changes: 1 addition & 1 deletion src/SpinWaveTheory/SpinWaveTheory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct SWTDataSUN
spins_localized :: Array{HermitianC64, 2} # Spins rotated to local frame (3 × nsites)
end

# To facilitate sharing some code with SpiralSpinWaveTheory
# To facilitate sharing some code with SpinWaveTheorySpiral
abstract type AbstractSpinWaveTheory end

"""
Expand Down
18 changes: 9 additions & 9 deletions src/Spiral/SpiralSWT.jl → src/Spiral/SpinWaveTheorySpiral.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"""
SpiralSpinWaveTheory(sys::System; k, axis, measure, regularization=1e-8)
SpinWaveTheorySpiral(sys::System; k, axis, measure, regularization=1e-8)
Analogous to [`SpinWaveTheory`](@ref), but interprets the provided system as
having a generalized spiral order. This order is described by a single
propagation wavevector `k`, which may be incommensurate. The `axis` vector
defines the polarization plane via its surface normal. Typically the spin
configuration in `sys` and the propagation wavevector `k` will be optimized
using [`spiral_minimize_energy!`](@ref). In contrast, `axis` will typically be
using [`minimize_spiral_energy!`](@ref). In contrast, `axis` will typically be
determined from symmetry considerations.
The resulting object can be used to calculate the spin wave
Expand All @@ -17,12 +17,12 @@ The algorithm for this calculation was developed in [Toth and Lake, J. Phys.:
Condens. Matter **27**, 166002 (2015)](https://arxiv.org/abs/1402.6069) and
implemented in the [SpinW code](https://spinw.org/).
"""
struct SpiralSpinWaveTheory <: AbstractSpinWaveTheory
struct SpinWaveTheorySpiral <: AbstractSpinWaveTheory
swt :: SpinWaveTheory
k :: Vec3
axis :: Vec3

function SpiralSpinWaveTheory(sys::System; k::AbstractVector, axis::AbstractVector, measure::Union{Nothing, MeasureSpec}, regularization=1e-8)
function SpinWaveTheorySpiral(sys::System; k::AbstractVector, axis::AbstractVector, measure::Union{Nothing, MeasureSpec}, regularization=1e-8)
return new(SpinWaveTheory(sys; measure, regularization), k, axis)
end
end
Expand All @@ -39,7 +39,7 @@ end

## Dispersion and intensities

function swt_hamiltonian_dipole_spiral!(H::Matrix{ComplexF64}, sswt::SpiralSpinWaveTheory, q_reshaped; branch)
function swt_hamiltonian_dipole_spiral!(H::Matrix{ComplexF64}, sswt::SpinWaveTheorySpiral, q_reshaped; branch)
(; swt, k, axis) = sswt
(; sys, data) = swt
(; local_rotations, stevens_coefs, sqrtS) = data
Expand Down Expand Up @@ -114,7 +114,7 @@ function swt_hamiltonian_dipole_spiral!(H::Matrix{ComplexF64}, sswt::SpiralSpinW
end
end

function excitations!(T, H, sswt::SpiralSpinWaveTheory, q; branch)
function excitations!(T, H, sswt::SpinWaveTheorySpiral, q; branch)
q_reshaped = to_reshaped_rlu(sswt.swt.sys, q)
swt_hamiltonian_dipole_spiral!(H, sswt, q_reshaped; branch)

Expand All @@ -125,7 +125,7 @@ function excitations!(T, H, sswt::SpiralSpinWaveTheory, q; branch)
end
end

function excitations(sswt::SpiralSpinWaveTheory, q; branch)
function excitations(sswt::SpinWaveTheorySpiral, q; branch)
L = nbands(sswt.swt)
H = zeros(ComplexF64, 2L, 2L)
T = zeros(ComplexF64, 2L, 2L)
Expand All @@ -134,7 +134,7 @@ function excitations(sswt::SpiralSpinWaveTheory, q; branch)
end


function dispersion(sswt::SpiralSpinWaveTheory, qpts)
function dispersion(sswt::SpinWaveTheorySpiral, qpts)
(; swt) = sswt
L = nbands(swt)
qpts = convert(AbstractQPoints, qpts)
Expand Down Expand Up @@ -176,7 +176,7 @@ function gs_as_scalar(swt::SpinWaveTheory, measure::MeasureSpec)
end


function intensities_bands(sswt::SpiralSpinWaveTheory, qpts; kT=0) # TODO: branch=nothing
function intensities_bands(sswt::SpinWaveTheorySpiral, qpts; kT=0) # TODO: branch=nothing
(; swt, axis) = sswt
(; sys, data, measure) = swt
isempty(measure.observables) && error("No observables! Construct SpinWaveTheorySpiral with a `measure` argument.")
Expand Down
6 changes: 3 additions & 3 deletions src/Spiral/SpiralEnergy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ the lattice vectors of the chemical cell.
The return value is the energy associated with one periodic copy of `sys`. The
special case ``𝐤 = 0`` yields result is identical to [`energy`](@ref).
See also [`spiral_minimize_energy!`](@ref) and [`repeat_periodically_as_spiral`](@ref).
See also [`minimize_spiral_energy!`](@ref) and [`repeat_periodically_as_spiral`](@ref).
"""
function spiral_energy(sys::System{0}; k, axis)
sys.mode in (:dipole, :dipole_large_s) || error("SU(N) mode not supported")
Expand Down Expand Up @@ -182,7 +182,7 @@ function spiral_g!(G, sys::System{0}, axis, params, λ)
end

"""
spiral_minimize_energy!(sys, axis; maxiters=10_000, k_guess=randn(sys.rng, 3))
minimize_spiral_energy!(sys, axis; maxiters=10_000, k_guess=randn(sys.rng, 3))
Finds a generalized spiral order that minimizes the [`spiral_energy`](@ref).
This involves optimization of the spin configuration in `sys`, and the
Expand All @@ -195,7 +195,7 @@ provided.
See also [`suggest_magnetic_supercell`](@ref) to find a system shape that is
approximately commensurate with the returned propagation wavevector ``𝐤``.
"""
function spiral_minimize_energy!(sys, axis; maxiters=10_000, k_guess=randn(sys.rng, 3))
function minimize_spiral_energy!(sys, axis; maxiters=10_000, k_guess=randn(sys.rng, 3))
axis = normalize(axis)

sys.mode in (:dipole, :dipole_large_s) || error("SU(N) mode not supported")
Expand Down
4 changes: 2 additions & 2 deletions src/Sunny.jl
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ export SpinWaveTheory, excitations, excitations!, dispersion, intensities, inten

include("Spiral/LuttingerTisza.jl")
include("Spiral/SpiralEnergy.jl")
include("Spiral/SpiralSWT.jl")
export SpiralSpinWaveTheory, spiral_minimize_energy!, spiral_energy, spiral_energy_per_site
include("Spiral/SpinWaveTheorySpiral.jl")
export minimize_spiral_energy!, spiral_energy, spiral_energy_per_site, SpinWaveTheorySpiral

include("KPM/Lanczos.jl")
include("KPM/Chebyshev.jl")
Expand Down
10 changes: 5 additions & 5 deletions test/test_chirality.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ end
@test res.disp[1,:] disp_ref
@test res.data[1,:] intens_ref

# Check SpiralSpinWaveTheory
# Check SpinWaveTheorySpiral

swt = SpiralSpinWaveTheory(sys; measure=ssf_trace(sys; apply_g=false), k=[0,0,0], axis=[0,0,1])
swt = SpinWaveTheorySpiral(sys; measure=ssf_trace(sys; apply_g=false), k=[0,0,0], axis=[0,0,1])
res = intensities_bands(swt, qs)
@test res.disp[1, :] res.disp[2, :] res.disp[3, :] [B + 2D*sin(2π*q[3]) for q in qs]
@test res.data [1 1; 0 0; 0 0]
Expand All @@ -61,15 +61,15 @@ end
set_field!(sys, [0, 0, 1])
axis = [0, 0, 1]
polarize_spins!(sys, [0.5, -0.2, 0.3])
k = spiral_minimize_energy!(sys, axis; k_guess=[0.1, 0.2, 0.9])
k = minimize_spiral_energy!(sys, axis; k_guess=[0.1, 0.2, 0.9])
@test k[3] 3/4
@test spiral_energy_per_site(sys; k, axis) -5/4

# Check SpiralSpinWaveTheory
# Check SpinWaveTheorySpiral

qs = [[0,0,-1/3], [0,0,1/3]]
formfactors = [1 => FormFactor("Fe2")]
swt = SpiralSpinWaveTheory(sys; measure=ssf_trace(sys; apply_g=false, formfactors), k, axis)
swt = SpinWaveTheorySpiral(sys; measure=ssf_trace(sys; apply_g=false, formfactors), k, axis)
res = intensities_bands(swt, qs)
disp_ref = [3.0133249314050294 3.013324931405025; 2.598076231555311 2.5980762315553187; 0.6479760935008405 0.6479760935008452]
intens_ref = [0.017051546888468827 0.3084140583919762; 0.2523273363813809 0.252327336381381; 0.5130396769375238 0.22167716543401594]
Expand Down
10 changes: 5 additions & 5 deletions test/test_spiral.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ end

axis = [0, 0, 1]
randomize_spins!(sys)
k = spiral_minimize_energy!(sys, axis; k_guess=randn(3))
k = minimize_spiral_energy!(sys, axis; k_guess=randn(3))
@test k[1:2] [0.5, 0.5]
@test isapprox(only(sys.dipoles)[3], h / (8J + 2D); atol=1e-6)

q = [0.12, 0.23, 0.34]
swt = SpiralSpinWaveTheory(sys; measure=nothing, k, axis)
swt = SpinWaveTheorySpiral(sys; measure=nothing, k, axis)
ϵq_num = dispersion(swt, [q])

# Analytical
Expand Down Expand Up @@ -108,7 +108,7 @@ end

axis = [0, 0, 1]
randomize_spins!(sys)
k = spiral_minimize_energy!(sys, axis; k_guess=randn(3))
k = minimize_spiral_energy!(sys, axis; k_guess=randn(3))
@test spiral_energy(sys; k, axis) -16.356697120589477

# There are two possible chiralities. Select just one.
Expand All @@ -120,7 +120,7 @@ end
@test spiral_energy(sys; k, axis) -16.356697120589477

measure = ssf_perp(sys; apply_g=false)
swt = SpiralSpinWaveTheory(sys; measure, k, axis)
swt = SpinWaveTheorySpiral(sys; measure, k, axis)
q = [0.41568,0.56382,0.76414]
res = intensities_bands(swt, [q])

Expand Down Expand Up @@ -185,7 +185,7 @@ end

axis = [0, 0, 1]
randomize_spins!(sys)
k = spiral_minimize_energy!(sys, axis; k_guess=randn(3))
k = minimize_spiral_energy!(sys, axis; k_guess=randn(3))
E = Sunny.luttinger_tisza_exchange(sys; k)
@test isapprox(E, E_ref; atol=1e-12)
@test isapprox(k, k_ref; atol=1e-6) || isapprox(k, k_ref_alt; atol=1e-6)
Expand Down

0 comments on commit c181348

Please sign in to comment.