Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor single ion anisotropies #93

Merged
merged 3 commits into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ version = "0.4.4"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
CrystalInfoFramework = "6007d9b0-c6b2-11e8-0510-1d10e825f3f1"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
DynamicPolynomials = "7c1d4256-1411-5781-91ec-d7bc3513ac07"
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
FilePathsBase = "48062228-2e41-5def-b9a4-89aafe57970f"
Inflate = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9"
Expand All @@ -29,7 +28,6 @@ StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
Colors = "0.12.8"
CrystalInfoFramework = "0.5.0"
DataStructures = "0.18.13"
DynamicPolynomials = "0.4.6"
FFTW = "1.4.5"
FilePathsBase = "0.9.18"
Inflate = "0.1.2"
Expand Down
1 change: 1 addition & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DynamicPolynomials = "7c1d4256-1411-5781-91ec-d7bc3513ac07"
Formatting = "59287772-0a20-5a39-b81b-1366585eb4c0"
GLMakie = "e9467ef8-e4e7-5192-8a1a-b1aee30e663a"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
Expand Down
3 changes: 3 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

using Literate, Documenter, Sunny

import DynamicPolynomials # get symbolic functions
import GLMakie # get plotting functions

execute = true # set `false` to disable cell evaluation

example_names = ["fei2_tutorial", "powder_averaging", "ising2d"]
Expand Down
2 changes: 1 addition & 1 deletion docs/src/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ The next steps are typically the following
crystal unit cells.
2. Add interactions to the system using functions like
[`set_external_field!`](@ref), [`set_exchange!`](@ref), and
[`set_anisotropy!`](@ref).
[`set_onsite!`](@ref).
3. Perform Monte Carlo simulation to equilibrate the spin configuration. Options
include the continuous [`Langevin`](@ref) dynamics, or single-spin flip
updates with [`LocalSampler`](@ref). The former can efficiently handle
Expand Down
27 changes: 23 additions & 4 deletions docs/src/versions.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
# Version 0.5.0

This version includes many **breaking changes**.

Replace `set_anisotropy!` with a new function [`set_onsite!`](@ref). The latter
expects an explicit matrix representation for the local Hamiltonian. This can be
constructed, e.g., as a linear combination of [`stevens_operators`](@ref), or as
a polynomial of [`spin_operators`](@ref). To understand the mapping between
these two, the new function [`print_stevens_expansion`](@ref) acts on an
arbitrary local operator.

Symbolic representations of operators are now hidden unless the package
`DynamicPolynomials` is explicitly loaded by the user. The functionality of
`print_anisotropy_as_stevens` has been replaced with
[`print_classical_stevens_expansion`](@ref), while
`print_anisotropy_as_classical_spins` has become
[`print_classical_spin_polynomial`](@ref).


# Version 0.4.3

**Experimental** support for linear [`SpinWaveTheory`](@ref), implemented in
Expand Down Expand Up @@ -50,7 +69,7 @@ This update includes many breaking changes, and is missing some features of

### Creating a spin `System`

`SpinSystem` has been renamed [`System`](@ref). Its constructor now has the form,
Rename `SpinSystem` to [`System`](@ref). Its constructor now has the form,

```julia
System(crystal, latsize, infos, mode)
Expand All @@ -66,21 +85,21 @@ The parameter `mode` is one of `:SUN` or `:dipole`.

Interactions are now added mutably to an existing `System` using the following
functions: [`set_external_field!`](@ref), [`set_exchange!`](@ref),
[`set_anisotropy!`](@ref), [`enable_dipole_dipole!`](@ref).
[`set_onsite!`](@ref), [`enable_dipole_dipole!`](@ref).

As a convenience, one can use [`dmvec(D)`](@ref) to convert a DM vector to a
$3×3$ antisymmetric exchange matrix.

Fully general single-ion anisotropy is now possible. The function
[`set_anisotropy!`](@ref) expects the single ion anisotropy to be expressed as a
[`set_onsite!`](@ref) expects the single ion anisotropy to be expressed as a
polynomial in symbolic spin operators [`𝒮`](@ref), or as a linear combination
of symbolic Stevens operators [`𝒪`](@ref). For example, an easy axis anisotropy
in the direction `n` may be written `D*(𝒮⋅n)^2`.

Stevens operators `𝒪[k,q]` admit polynomial expression in spin operators
`𝒮[α]`. Conversely, a polynomial of spin operators can be expressed as a linear
combination of Stevens operators. To see this expansion use
[`print_anisotropy_as_stevens`](@ref).
`print_anisotropy_as_stevens`.


### Inhomogeneous field
Expand Down
16 changes: 7 additions & 9 deletions examples/fei2_tutorial.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
# Begin by importing `Sunny` and `GLMakie`, a plotting package.

using Sunny, GLMakie
#md Makie.inline!(true); #hide
#nb Sunny.offline_viewers() # Inject Javascript code for additional plotting capabilities

# If you see an error `Package <X> not found in current path`, add the package
Expand Down Expand Up @@ -145,18 +144,17 @@ set_exchange!(sys, [J′2apm 0.0 0.0;
0.0 J′2apm 0.0;
0.0 0.0 J′2azz], Bond(1,1,[1,2,1]))

# The function [`set_anisotropy!`](@ref) assigns a single-ion anisotropy. It
# takes an abstract operator and an atom index. The operator may be a polynomial
# of spin operators or a linear combination of Stevens operators. Sunny provides
# special symbols for their construction: [`𝒮`](@ref) is a vector of the three
# spin operators and [`𝒪`](@ref) are the symbolic Stevens operators. Here we
# construct an easy-axis anisotropy.
# The function [`set_onsite!`](@ref) assigns a single-ion anisotropy
# operator. It can be constructed, e.g., from the matrices given by
# [`spin_operators`](@ref) or [`stevens_operators`](@ref). Here we construct an
# easy-axis anisotropy along the direction $\hat{z}$.

D = 2.165
set_anisotropy!(sys, -D*𝒮[3]^2, 1)
S = spin_operators(sys, 1)
set_onsite!(sys, -D*S[3]^2, 1)

# Any anisotropy operator can be converted to a linear combination of Stevens
# operators with [`print_anisotropy_as_stevens`](@ref).
# operators with [`print_stevens_expansion`](@ref).

# # Calculating structure factor intensities
# In the remainder of this tutorial, we will examine Sunny's tools for
Expand Down
1 change: 0 additions & 1 deletion examples/powder_averaging.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

using Sunny, GLMakie
using Statistics: mean
#md Makie.inline!(true); #hide
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this a no-op?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was previously needed as a workaround for this bug MakieOrg/Makie.jl#2805.


dims = (8,8,8) # Lattice dimensions
seed = 1 # RNG seed for repeatable behavior
Expand Down
8 changes: 7 additions & 1 deletion src/Operators/Spin.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# Construct spin operators, i.e. generators of su(2), of dimension N
"""
spin_matrices(N)

Constructs the three spin operators, i.e. the generators of SU(2), in the
`N`-dimensional irrep. See also [`spin_operators`](@ref), which determines the
appropriate value of `N` for a given site index.
"""
function spin_matrices(N::Int)
if N == 0
return fill(zeros(ComplexF64,0,0), 3)
Expand Down
63 changes: 63 additions & 0 deletions src/Operators/Stevens.jl
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,66 @@ function rotate_stevens_coefficients(c, R::Mat3)
@assert norm(imag(c′)) < 1e-12
return real(c′)
end


# Builds matrix representation of Stevens operators on demand
struct StevensMatrices
N::Int
end
function Base.getindex(this::StevensMatrices, k::Int, q::Int)
k < 0 && error("Stevens operators 𝒪[k,q] require k >= 0.")
k > 6 && error("Stevens operators 𝒪[k,q] currently require k <= 6.")
!(-k <= q <= k) && error("Stevens operators 𝒪[k,q] require -k <= q <= k.")
if k == 0
return Matrix{ComplexF64}(I, this.N, this.N)
else
# Stevens operators are stored in descending order: k, k-1, ... -k.
# Therefore q=k should be the first index, q_idx=1.
q_idx = k - q + 1
# Build all (2k+1) matrices and extract the desired one. This seems a
# bit wasteful, but presumably this function won't be called in
# performance sensitive contexts.
return stevens_matrices(k; this.N)[q_idx]
end
end


"""
function print_stevens_expansion(op)

Prints a local Hermitian operator as a linear combination of Stevens operators.
This function works on explicit matrix representations. The analogous function
in the large-``S`` classical limit is
[`print_classical_stevens_expansion`](@ref).

# Examples

```julia
S = spin_matrices(5)
print_stevens_expansion(S[1]^4 + S[2]^4 + S[3]^4)
# Prints: (1/20)𝒪₄₀ + (1/4)𝒪₄₄ + 102/5
```
"""
function print_stevens_expansion(op::Matrix{ComplexF64})
op ≈ op' || error("Requires Hermitian operator")
terms = String[]

# Decompose op into Stevens coefficients
c = matrix_to_stevens_coefficients(op)
for k in 1:6
for (c_km, m) in zip(reverse(c[k]), -k:k)
abs(c_km) < 1e-12 && continue
push!(terms, *(coefficient_to_math_string(c_km), "𝒪", int_to_underscore_string.((k,m))...))
end
end

# Handle linear shift specially
c_00 = real(tr(op))/size(op, 1)
abs(c_00) > 1e-12 && push!(terms, number_to_math_string(c_00))

# Concatenate with plus signs
str = join(terms, " + ")
# Remove redundant plus signs and print
str = replace(str, "+ -" => "- ")
println(str)
end
Loading
Loading