Skip to content

Commit

Permalink
Docs refactor (#182)
Browse files Browse the repository at this point in the history
* Rename tutorials per Martin's suggestion
* Add short version of the CoRh2O4 classical dynamics tutorial
* Various other improvements
  • Loading branch information
kbarros authored Nov 1, 2023
1 parent 9e4d25c commit ec1a509
Show file tree
Hide file tree
Showing 23 changed files with 259 additions and 1,761 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
docs/build/
docs/contributed-tmp/
docs/src/examples/
Manifest.toml
profile.pb.gz
.DS_Store
.vscode
*.ipynb
*.lyx~
*.lyx#
*.lyx#
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

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. Through neglect of entanglement, 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/fei2_tutorial.html)). In the future, the theory could also be used to model explicit spin-orbit coupling, or 'units' of locally entangled spins.
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. Through neglect of entanglement, 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, the theory could also be used to model explicit spin-orbit coupling, or 'units' of locally entangled spins.

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 effects. 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.

Expand All @@ -22,7 +22,7 @@ Sunny provides a number of tools to facilitate the specification and solution of

## Try it out!

To see Sunny in action, a good starting point is our **[FeI₂ tutorial](https://sunnysuite.github.io/Sunny.jl/dev/examples/fei2_tutorial.html)**. This compound includes effective spin-1 moments with strong easy-axis anisotropy, and exemplifies the power of simulating SU(3) coherent states.
A good starting point is our **[FeI₂ tutorial](https://sunnysuite.github.io/Sunny.jl/dev/examples/01_LSWT_SU3_FeI2.html)**. This compound includes effective spin-1 moments with strong easy-axis anisotropy, and exemplifies the power of simulating SU(3) coherent states.
<!--
In addition to the examples in the official [documentation](https://sunnysuite.github.io/Sunny.jl/dev/), a number of tutorials are available as Jupyter notebooks at the [SunnyTutorials](https://github.com/SunnySuite/SunnyTutorials/tree/main/Tutorials) repo. -->

Expand All @@ -38,7 +38,7 @@ Sunny is inspired by SpinW, especially regarding symmetry analysis, model specif
| -- | -- | -- | -- |
| Symmetry-guided modeling ||||
| Interactive graphics ||||
| General single-ion anisotropy ||||
| General spin-multipole interactions ||||
| [Interaction renormalization for dipoles](https://arxiv.org/abs/2304.03874) ||||
| [Multi-flavor spin wave theory](https://arxiv.org/abs/1307.7731) ||||
| [Classical SU(_N_) spin dynamics](https://arxiv.org/abs/2209.01265)</u> ||||
Expand Down
49 changes: 21 additions & 28 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Literate, Documenter, Git
using Sunny, GLMakie, WriteVTK # Load packages to enable Documenter references

draft = false # set `true` to disable cell evaluation
isdraft = false # set `true` to disable cell evaluation

# Remove existing Documenter `build` directory
build_path = joinpath(@__DIR__, "build")
Expand All @@ -13,10 +13,16 @@ notebooks_path = joinpath(build_path, "assets", "notebooks")
scripts_path = joinpath(build_path, "assets", "scripts")
mkpath.([notebooks_path, scripts_path])

ismarkdown(name) = splitext(name)[2] == ".md"
isjulia(name) = splitext(name)[2] == ".jl"


function build_examples(example_sources, destdir)
assetsdir = joinpath(fill("..", length(splitpath(destdir)))..., "assets")

destpath = joinpath(@__DIR__, "src", destdir)
isdir(destpath) && rm(destpath; recursive=true)

# Transform each Literate source file to Markdown for subsequent processing by
# Documenter.
for source in example_sources
Expand All @@ -33,8 +39,7 @@ function build_examples(example_sources, destdir)
""" * str
end
# Write to `src/$destpath/$name.md`
dest = joinpath(@__DIR__, "src", destdir)
Literate.markdown(source, dest; preprocess, credit=false)
Literate.markdown(source, destpath; preprocess, credit=false)
end

# Create Jupyter notebooks and Julia script for each Literate example. These
Expand All @@ -59,18 +64,12 @@ function build_examples(example_sources, destdir)
end
end


function prepare_contributed()
function is_markdown(name)
if split(name, ".")[end] == "md"
return true
end
false
end

# Perform a sparse checkout of the `build` directory from SunnyContributed.
# This directory contains the markdown files and images generated with
# Literate on the SunnyContributed repo.
# Perform a sparse checkout of the `build` directory from SunnyContributed.
# This directory contains the markdown files and images generated with
# Literate on the SunnyContributed repo. TODO: If directory exists, should
# we just `git pull` instead for speed?
isdir("contributed-tmp") && rm("contributed-tmp"; recursive=true, force=true)
mkpath("contributed-tmp")
cd("contributed-tmp")
run(`$(Git.git()) init`)
Expand All @@ -89,21 +88,19 @@ function prepare_contributed()

# Generate the base names for each contributed markdown file and prepare
# paths for Documenter (relative to `src/`)
contrib_names = filter(is_markdown, contrib_files)
contrib_names = filter(ismarkdown, contrib_files)
return [joinpath("examples", "contributed", name) for name in contrib_names]
end



example_names = ["fei2_tutorial", "out_of_equilibrium", "powder_averaging", "fei2_classical", "ising2d"]
example_sources = [pkgdir(Sunny, "examples", "$name.jl") for name in example_names]
example_sources = filter(isjulia, readdir(abspath(pkgdir(Sunny, "examples")), join=true))
example_names = [splitext(basename(src))[1] for src in example_sources]
example_mds = build_examples(example_sources, "examples")

spinw_names = ["08_Kagome_AFM", "15_Ba3NbFe3Si2O14"]
spinw_sources = [pkgdir(Sunny, "examples", "spinw_ports", "$name.jl") for name in spinw_names]
spinw_sources = filter(isjulia, readdir(abspath(pkgdir(Sunny, "examples", "spinw_tutorials")), join=true))
spinw_names = [splitext(basename(src))[1] for src in spinw_sources]
spinw_mds = build_examples(spinw_sources, joinpath("examples", "spinw"))

contributed_mds = prepare_contributed()
contributed_mds = isdraft ? [] : prepare_contributed()


# Build docs as HTML, including the `examples/name.md` markdown built above
Expand All @@ -114,7 +111,7 @@ Documenter.makedocs(;
"index.md",
"Examples" => [
example_mds...,
"SpinW ports" => spinw_mds,
"SpinW tutorials" => spinw_mds,
"Contributed" => contributed_mds,
"Advanced" => [
"parallelism.md",
Expand All @@ -137,13 +134,9 @@ Documenter.makedocs(;
size_threshold_warn = 200*1024, # 200KB -- library.html gets quite large
size_threshold = 300*2024, # 300KB
),
draft
draft = isdraft
)

# Remove the (sparsely checked out) SunnyContributed git repo. This is only
# necessary to enable repeated local builds. It has no effect on the CI.
rm("contributed-tmp"; force=true, recursive=true)

# Attempt to push to gh-pages branch for deployment
Documenter.deploydocs(
repo = "github.com/SunnySuite/Sunny.jl.git",
Expand Down
14 changes: 7 additions & 7 deletions docs/src/parallelism.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ copied and pasted into your preferred Julia development environment.

## Review of the serial workflow

The serial approach to calculating a structure factor, covered in [FeI₂ at
Finite Temperature](@ref), involves thermalizing a spin `System` and then
calling [`add_sample!`](@ref). `add_sample!` uses the state of the `System` as
an initial condition for the calculation of a dynamical trajectory. The
correlations of the trajectory are calculated and accumulated into a running
average of the ``𝒮(𝐪,ω)``. This sequence is repeated to generate additional
samples.
The serial approach to calculating a structure factor, covered in the [FeI₂
tutorial](@ref "4. Generalized spin dynamics of FeI₂ at finite *T*"), involves
thermalizing a spin `System` and then calling [`add_sample!`](@ref).
`add_sample!` uses the state of the `System` as an initial condition for the
calculation of a dynamical trajectory. The correlations of the trajectory are
calculated and accumulated into a running average of the ``𝒮(𝐪,ω)``. This
sequence is repeated to generate additional samples.

To illustrate, we'll set up a a simple model: a spin-1 antiferromagnet on an FCC
crystal.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/versions.md
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ An external field can be applied to a single site with
### Structure factor rewrite

The calculation of structure factors has been completely rewritten. For the new
interface, see the [FeI₂ at Finite Temperature](@ref) page.
interface see the documentation tutorials.


### Various
Expand Down
24 changes: 9 additions & 15 deletions examples/fei2_tutorial.jl → examples/01_LSWT_SU3_FeI2.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# # Case Study: FeI₂
# # 1. Multi-flavor spin wave simulations of FeI₂ (Showcase)
#
# FeI₂ is an effective spin-1 material with strong single-ion anisotropy.
# Quadrupolar fluctuations give rise to a single-ion bound state that cannot be
Expand Down Expand Up @@ -36,8 +36,8 @@
# guide. Sunny requires Julia 1.9 or later.
#
# From the Julia prompt, load `Sunny`. For plotting, one can choose either
# `GLMakie` (a pop-up window) or `WGLMakie` (inline plots for a Jupyter notebook
# or VSCode).
# `GLMakie` (a pop-up window) or `WGLMakie` (inline plots for a Jupyter
# notebook).

using Sunny, GLMakie

Expand Down Expand Up @@ -69,7 +69,7 @@ FeI2 = Crystal(latvecs, positions; types)

cryst = subcrystal(FeI2, "Fe")

# Observe that `cryst` retains the spacegroup symmetry of the full FeI₂ crystal.
# Importantly, `cryst` retains the spacegroup symmetry of the full FeI₂ crystal.
# This information will be used, for example, to propagate exchange interactions
# between symmetry-equivalent bonds.
#
Expand Down Expand Up @@ -363,18 +363,12 @@ disp, is = dssf(swt, path);
# The full SU(_N_) coherent state dynamics, with appropriate quantum correction
# factors, can be useful to model finite temperature scattering data. In
# particular, it captures certain anharmonic effects due to thermal
# fluctuations. This is the subject of our [FeI₂ at Finite Temperature](@ref)
# tutorial.
# fluctuations. See our [generalized spin dynamics tutorial](@ref "3.
# Generalized spin dynamics of FeI₂ at finite *T*").
#
# The classical dynamics is also a good starting point to study non-equilibrium
# phenomena. Empirical noise and damping terms can be used to model [coupling to
# a thermal bath](https://arxiv.org/abs/2209.01265). This yields a Langevin
# dynamics of SU(_N_) coherent states. Our [CP² Skyrmion Quench](@ref)
# tutorial shows how this dynamics gives rise to the formation of novel
# topological defects in a temperature quench.
#
# Relative to LSWT calculations, it can take much more time to estimate
# $\mathcal{S}(𝐪,ω)$ intensities using classical dynamics simulation. See the
# [SunnyTutorials
# notebooks](https://nbviewer.org/github/SunnySuite/SunnyTutorials/tree/main/Tutorials/)
# for examples of "production-scale" simulations.
# dynamics of SU(_N_) coherent states. Our [dynamical SU(_N_) quench](@ref "5.
# Dynamical quench into CP² skyrmion liquid") tutorial illustrates how a
# temperature quench can give rise to novel liquid phase of CP² skyrmions.
27 changes: 13 additions & 14 deletions examples/powder_averaging.jl → examples/02_LSWT_CoRh2O4.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# # Powder Averaged CoRh₂O₄
# # 2. Spin wave simulations of CoRh₂O₄
#
# This tutorial illustrates the calculation of the powder-averaged structure
# factor by performing an orientational average. We consider a simple model of
# the diamond-cubic crystal CoRh₂O₄, with parameters extracted from [Ge et al.,
# Phys. Rev. B 96, 064413](https://doi.org/10.1103/PhysRevB.96.064413).
# This tutorial illustrates the conventional spin wave theory of dipoles. We
# consider a simple model of the diamond-cubic crystal CoRh₂O₄, with parameters
# extracted from [Ge et al., Phys. Rev. B 96,
# 064413](https://doi.org/10.1103/PhysRevB.96.064413).

using Sunny, GLMakie

Expand All @@ -23,15 +23,14 @@ cryst = Crystal(latvecs, [[0,0,0]], 227, setting="1")

view_crystal(cryst, 8.0)

# Construct a [`System`](@ref) with an antiferromagnetic nearest neighbor
# interaction `J`. Because the diamond crystal is bipartite, the ground state
# will have unfrustrated Néel order. Selecting `latsize=(1,1,1)` is sufficient
# because the ground state is periodic over each cubic unit cell. By passing an
# explicit `seed`, the system's random number generator will give repeatable
# results.
# Construct a [`System`](@ref) with quantum spin ``S=3/2`` constrained to the
# space of dipoles. Including an antiferromagnetic nearest neighbor interaction
# `J` will favor Néel order. To optimize this magnetic structure, it is
# sufficient to employ a magnetic lattice consisting of a single crystal unit
# cell, `latsize=(1,1,1)`. Passing an explicit random number `seed` will ensure
# repeatable results.

latsize = (2, 2, 2)
seed = 0
latsize = (1, 1, 1)
S = 3/2
J = 7.5413*meV_per_K # (~ 0.65 meV)
sys = System(cryst, latsize, [SpinInfo(1; S, g=2)], :dipole; seed=0)
Expand Down Expand Up @@ -83,7 +82,7 @@ formula = intensity_formula(swt, :perp; kernel, formfactors)
# [`intensities_broadened`](@ref) function collects intensities along this path
# for the given set of energy values.

qpoints = [[0.0, 0.0, 0.0], [0.5, 0.0, 0.0], [0.5, 0.5, 0.0], [0.0, 0.0, 0.0]]
qpoints = [[0, 0, 0], [1/2, 0, 0], [1/2, 1/2, 0], [0, 0, 0]]
path, xticks = reciprocal_space_path(cryst, qpoints, 50)
energies = collect(0:0.01:6)
is = intensities_broadened(swt, path, energies, formula)
Expand Down
Loading

0 comments on commit ec1a509

Please sign in to comment.