diff --git a/previews/PR318/.documenter-siteinfo.json b/previews/PR318/.documenter-siteinfo.json index c981fdee3..f254b145c 100644 --- a/previews/PR318/.documenter-siteinfo.json +++ b/previews/PR318/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-19T00:43:53","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-09-20T16:09:11","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/previews/PR318/assets/notebooks/01_LSWT_CoRh2O4.ipynb b/previews/PR318/assets/notebooks/01_LSWT_CoRh2O4.ipynb index 827763c61..7f3b0dfba 100644 --- a/previews/PR318/assets/notebooks/01_LSWT_CoRh2O4.ipynb +++ b/previews/PR318/assets/notebooks/01_LSWT_CoRh2O4.ipynb @@ -50,16 +50,16 @@ { "cell_type": "markdown", "source": [ - "### Units" + "### Units system" ], "metadata": {} }, { "cell_type": "markdown", "source": [ - "The `Units` object selects reference energy and length\n", - "scales, and uses these to provide physical constants. For example, `units.K`\n", - "returns one kelvin as 0.086 meV, where the Boltzmann constant is implicit." + "The `Units` object selects reference energy and length scales,\n", + "and uses these to provide physical constants. For example, `units.K` returns\n", + "one kelvin as 0.086 meV, where the Boltzmann constant is implicit." ], "metadata": {} }, diff --git a/previews/PR318/assets/notebooks/09_Disorder_KPM.ipynb b/previews/PR318/assets/notebooks/09_Disorder_KPM.ipynb index 1b6b8200e..888f18c1c 100644 --- a/previews/PR318/assets/notebooks/09_Disorder_KPM.ipynb +++ b/previews/PR318/assets/notebooks/09_Disorder_KPM.ipynb @@ -46,7 +46,7 @@ "\n", "randomize_spins!(sys)\n", "minimize_energy!(sys)\n", - "plot_spins(sys; color=[s[3] for s in sys.dipoles], ndims=2)" + "plot_spins(sys; color=[S[3] for S in sys.dipoles], ndims=2)" ], "metadata": {}, "execution_count": null @@ -129,7 +129,7 @@ "end\n", "\n", "minimize_energy!(sys_inhom, maxiters=5_000)\n", - "plot_spins(sys_inhom; color=[s[3] for s in sys_inhom.dipoles], ndims=2)" + "plot_spins(sys_inhom; color=[S[3] for S in sys_inhom.dipoles], ndims=2)" ], "metadata": {}, "execution_count": null diff --git a/previews/PR318/assets/scripts/09_Disorder_KPM.jl b/previews/PR318/assets/scripts/09_Disorder_KPM.jl index c4d894d6e..ece3fa348 100644 --- a/previews/PR318/assets/scripts/09_Disorder_KPM.jl +++ b/previews/PR318/assets/scripts/09_Disorder_KPM.jl @@ -7,7 +7,7 @@ set_exchange!(sys, +1.0, Bond(1, 1, [1,0,0])) randomize_spins!(sys) minimize_energy!(sys) -plot_spins(sys; color=[s[3] for s in sys.dipoles], ndims=2) +plot_spins(sys; color=[S[3] for S in sys.dipoles], ndims=2) qs = [[0, 0, 0], [1/3, 1/3, 0], [1/2, 0, 0], [0, 0, 0]] labels = ["Γ", "K", "M", "Γ"] @@ -27,7 +27,7 @@ for (site1, site2, offset) in symmetry_equivalent_bonds(sys_inhom, Bond(1,1,[1,0 end minimize_energy!(sys_inhom, maxiters=5_000) -plot_spins(sys_inhom; color=[s[3] for s in sys_inhom.dipoles], ndims=2) +plot_spins(sys_inhom; color=[S[3] for S in sys_inhom.dipoles], ndims=2) swt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.01) res = intensities(swt, path; energies, kernel) diff --git a/previews/PR318/examples/01_LSWT_CoRh2O4-031de806.png b/previews/PR318/examples/01_LSWT_CoRh2O4-031de806.png new file mode 100644 index 000000000..52e787180 Binary files /dev/null and b/previews/PR318/examples/01_LSWT_CoRh2O4-031de806.png differ diff --git a/previews/PR318/examples/01_LSWT_CoRh2O4-220e3b96.png b/previews/PR318/examples/01_LSWT_CoRh2O4-220e3b96.png deleted file mode 100644 index a38e9270a..000000000 Binary files a/previews/PR318/examples/01_LSWT_CoRh2O4-220e3b96.png and /dev/null differ diff --git a/previews/PR318/examples/01_LSWT_CoRh2O4-36441e97.png b/previews/PR318/examples/01_LSWT_CoRh2O4-36441e97.png deleted file mode 100644 index 4ad74cd07..000000000 Binary files a/previews/PR318/examples/01_LSWT_CoRh2O4-36441e97.png and /dev/null differ diff --git a/previews/PR318/examples/01_LSWT_CoRh2O4-3898fc52.png b/previews/PR318/examples/01_LSWT_CoRh2O4-3898fc52.png deleted file mode 100644 index 1233f61c8..000000000 Binary files a/previews/PR318/examples/01_LSWT_CoRh2O4-3898fc52.png and /dev/null differ diff --git a/previews/PR318/examples/01_LSWT_CoRh2O4-40e32b63.png b/previews/PR318/examples/01_LSWT_CoRh2O4-40e32b63.png new file mode 100644 index 000000000..c7f10231c Binary files /dev/null and b/previews/PR318/examples/01_LSWT_CoRh2O4-40e32b63.png differ diff --git a/previews/PR318/examples/01_LSWT_CoRh2O4-74ba0f8f.png b/previews/PR318/examples/01_LSWT_CoRh2O4-74ba0f8f.png new file mode 100644 index 000000000..f3ed24e93 Binary files /dev/null and b/previews/PR318/examples/01_LSWT_CoRh2O4-74ba0f8f.png differ diff --git a/previews/PR318/examples/01_LSWT_CoRh2O4-9a6df8c3.png b/previews/PR318/examples/01_LSWT_CoRh2O4-9a6df8c3.png new file mode 100644 index 000000000..422e6ee71 Binary files /dev/null and b/previews/PR318/examples/01_LSWT_CoRh2O4-9a6df8c3.png differ diff --git a/previews/PR318/examples/01_LSWT_CoRh2O4-bc63f5b5.png b/previews/PR318/examples/01_LSWT_CoRh2O4-bc63f5b5.png deleted file mode 100644 index e1348bf23..000000000 Binary files a/previews/PR318/examples/01_LSWT_CoRh2O4-bc63f5b5.png and /dev/null differ diff --git a/previews/PR318/examples/01_LSWT_CoRh2O4.html b/previews/PR318/examples/01_LSWT_CoRh2O4.html index 727dd7ba1..c92b1a886 100644 --- a/previews/PR318/examples/01_LSWT_CoRh2O4.html +++ b/previews/PR318/examples/01_LSWT_CoRh2O4.html @@ -1,5 +1,5 @@ -1. Spin wave simulations of CoRh₂O₄ · Sunny documentation

Download this example as Julia file or Jupyter notebook.

1. Spin wave simulations of CoRh₂O₄

This tutorial introduces Sunny through its features for performing conventional spin wave theory calculations. We consider the crystal CoRh₂O₄ and reproduce the calculations of Ge et al., Phys. Rev. B 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 guide. Sunny requires Julia 1.10 or later.

From the Julia prompt, load Sunny and also GLMakie for graphics.

using Sunny, GLMakie

If these packages are not yet installed, Julia will offer to install them. If executing this tutorial gives an error, you may need to update Sunny and GLMakie from the built-in package manager.

Units

The Units object selects reference energy and length scales, and uses these to provide physical constants. For example, units.K returns one kelvin as 0.086 meV, where the Boltzmann constant is implicit.

units = Units(:meV, :angstrom);

Crystal cell

A crystallographic cell may be loaded from a .cif file, or 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 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 # (Å)
+1. Spin wave simulations of CoRh₂O₄ · Sunny documentation

Download this example as Julia file or Jupyter notebook.

1. Spin wave simulations of CoRh₂O₄

This tutorial introduces Sunny through its features for performing conventional spin wave theory calculations. We consider the crystal CoRh₂O₄ and reproduce the calculations of Ge et al., Phys. Rev. B 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 guide. Sunny requires Julia 1.10 or later.

From the Julia prompt, load Sunny and also GLMakie for graphics.

using Sunny, GLMakie

If these packages are not yet installed, Julia will offer to install them. If executing this tutorial gives an error, you may need to update Sunny and GLMakie from the built-in package manager.

Units system

The Units object selects reference energy and length scales, and uses these to provide physical constants. For example, units.K returns one kelvin as 0.086 meV, where the Boltzmann constant is implicit.

units = Units(:meV, :angstrom);

Crystal cell

A crystallographic cell may be loaded from a .cif file, or 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 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)
3×3 StaticArraysCore.SMatrix{3, 3, Float64, 9} with indices SOneTo(3)×SOneTo(3):
  8.5031  0.0     0.0
  0.0     8.5031  0.0
@@ -24,11 +24,11 @@
 set_exchange!(sys, J, Bond(1, 3, [0, 0, 0]))
 view_crystal(sys)
Example block output

Optimizing spins

To search for the ground state, call randomize_spins! and minimize_energy! in sequence. For this problem, optimization converges rapidly to the expected Néel order. See this with plot_spins, 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])
Example block output

The diamond lattice is bipartite, allowing each spin to perfectly anti-align with its 4 nearest-neighbors. Each of these 4 bonds contribute $-J s^2$ to the total energy. Two sites participate in each bond, so the energy per site is $-2 J s^2$. Check this by calling energy_per_site.

@assert energy_per_site(sys) ≈ -2J*(3/2)^2

Reshaping the magnetic cell

The most compact magnetic cell for this Néel order is a primitive unit cell. Reduce the magnetic cell size using reshape_supercell, where columns of the shape matrix are primitive lattice vectors as multiples of the conventional cubic lattice vectors $(𝐚_1, 𝐚_2, 𝐚_3)$. One could alternatively use shape = cryst.latvecs \ cryst.prim_latvecs. Verify that the energy per site is unchanged after the reshaping the supercell.

shape = [0 1 1;
+plot_spins(sys; color=[S[3] for S in sys.dipoles])
Example block output

The diamond lattice is bipartite, allowing each spin to perfectly anti-align with its 4 nearest-neighbors. Each of these 4 bonds contribute $-J s^2$ to the total energy. Two sites participate in each bond, so the energy per site is $-2 J s^2$. Check this by calling energy_per_site.

@assert energy_per_site(sys) ≈ -2J*(3/2)^2

Reshaping the magnetic cell

The most compact magnetic cell for this Néel order is a primitive unit cell. Reduce the magnetic cell size using reshape_supercell, where columns of the shape matrix are primitive lattice vectors as multiples of the conventional cubic lattice vectors $(𝐚_1, 𝐚_2, 𝐚_3)$. One could alternatively use shape = cryst.latvecs \ cryst.prim_latvecs. Verify that the energy per site is unchanged after the reshaping the supercell.

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

Plotting sys_prim shows the two spins within the primitive cell, as well as the larger conventional cubic cell for context.

plot_spins(sys_prim; color=[S[3] for S in sys_prim.dipoles])
Example block output

Spin wave theory

With this primitive cell, we will perform a SpinWaveTheory calculation of the structure factor $\mathcal{S}(𝐪,ω)$. The measurement ssf_perp indicates projection of the spin structure factor $\mathcal{S}(𝐪,ω)$ perpendicular to the direction of momentum transfer, as appropriate for unpolarized neutron scattering. The isotropic FormFactor for Co²⁺ dampens intensities at large $𝐪$.

formfactors = [1 => FormFactor("Co2")]
+@assert energy_per_site(sys_prim) ≈ -2J*(3/2)^2

Plotting sys_prim shows the two spins within the primitive cell, as well as the larger conventional cubic cell for context.

plot_spins(sys_prim; color=[S[3] for S in sys_prim.dipoles])
Example block output

Spin wave theory

With this primitive cell, we will perform a SpinWaveTheory calculation of the structure factor $\mathcal{S}(𝐪,ω)$. The measurement ssf_perp indicates projection of the spin structure factor $\mathcal{S}(𝐪,ω)$ perpendicular to the direction of momentum transfer, as appropriate for unpolarized neutron scattering. The isotropic FormFactor for Co²⁺ dampens intensities at large $𝐪$.

formfactors = [1 => FormFactor("Co2")]
 measure = ssf_perp(sys_prim; formfactors)
 swt = SpinWaveTheory(sys_prim; measure)
SpinWaveTheory [Dipole mode]
   2 atoms
@@ -37,8 +37,8 @@
   [0, 0, 0] → [1/2, 0, 0] → [1/2, 1/2, 0] → [0, 0, 0]
 

Calculate single-crystal scattering intensities along this path, for energies between 0 and 6 meV. Use plot_intensities to visualize the result.

energies = range(0, 6, 300)
 res = intensities(swt, path; energies, kernel)
-plot_intensities(res; units, title="CoRh₂O₄ LSWT")
Example block output

Sometimes experimental data is only available as a powder average, i.e., as an average over all possible crystal orientations. Use powder_average to simulate these intensities. Each $𝐪$-magnitude defines a spherical shell in reciprocal space. Consider 200 radii from 0 to 3 inverse angstroms, and collect 2000 random samples per spherical shell. As configured, this calculation completes in about two seconds. Had we used the conventional cubic cell, the calculation would be an order of magnitude slower.

radii = range(0, 3, 200) # (1/Å)
+plot_intensities(res; units, title="CoRh₂O₄ LSWT")
Example block output

Sometimes experimental data is only available as a powder average, i.e., as an average over all possible crystal orientations. Use powder_average to simulate these intensities. Each $𝐪$-magnitude defines a spherical shell in reciprocal space. Consider 200 radii from 0 to 3 inverse angstroms, and collect 2000 random samples per spherical shell. As configured, this calculation completes in about two seconds. Had we used the conventional cubic cell, the calculation would be an order of magnitude slower.

radii = range(0, 3, 200) # (1/Å)
 res = powder_average(cryst, radii, 2000) do qs
     intensities(swt, qs; energies, kernel)
 end
-plot_intensities(res; units, saturation=1.0, title="CoRh₂O₄ Powder Average")
Example block output

This result can be compared to experimental neutron scattering data from Fig. 5 of Ge et al.

What's next?

  • For more spin wave calculations of this type, browse the SpinW tutorials ported to Sunny.
  • Spin wave theory neglects thermal fluctuations of the magnetic order. The next CoRh₂O₄ tutorial 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 the FeI₂ tutorial.
+plot_intensities(res; units, saturation=1.0, title="CoRh₂O₄ Powder Average")
Example block output

This result can be compared to experimental neutron scattering data from Fig. 5 of Ge et al.

What's next?

  • For more spin wave calculations of this type, browse the SpinW tutorials ported to Sunny.
  • Spin wave theory neglects thermal fluctuations of the magnetic order. The next CoRh₂O₄ tutorial 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 the FeI₂ tutorial.
diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-34218f8c.png b/previews/PR318/examples/02_LLD_CoRh2O4-34218f8c.png deleted file mode 100644 index 8d3c6fdb5..000000000 Binary files a/previews/PR318/examples/02_LLD_CoRh2O4-34218f8c.png and /dev/null differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-389c7e86.png b/previews/PR318/examples/02_LLD_CoRh2O4-389c7e86.png new file mode 100644 index 000000000..0b5c51ffe Binary files /dev/null and b/previews/PR318/examples/02_LLD_CoRh2O4-389c7e86.png differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-5a5e47ce.png b/previews/PR318/examples/02_LLD_CoRh2O4-5a5e47ce.png deleted file mode 100644 index 5e4d8a99d..000000000 Binary files a/previews/PR318/examples/02_LLD_CoRh2O4-5a5e47ce.png and /dev/null differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-66d7beff.png b/previews/PR318/examples/02_LLD_CoRh2O4-66d7beff.png deleted file mode 100644 index 4a3e433a3..000000000 Binary files a/previews/PR318/examples/02_LLD_CoRh2O4-66d7beff.png and /dev/null differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-687ccd73.png b/previews/PR318/examples/02_LLD_CoRh2O4-687ccd73.png new file mode 100644 index 000000000..184d17e21 Binary files /dev/null and b/previews/PR318/examples/02_LLD_CoRh2O4-687ccd73.png differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-833db2a2.png b/previews/PR318/examples/02_LLD_CoRh2O4-833db2a2.png new file mode 100644 index 000000000..d16b79225 Binary files /dev/null and b/previews/PR318/examples/02_LLD_CoRh2O4-833db2a2.png differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-866343c2.png b/previews/PR318/examples/02_LLD_CoRh2O4-866343c2.png deleted file mode 100644 index c8c4cda42..000000000 Binary files a/previews/PR318/examples/02_LLD_CoRh2O4-866343c2.png and /dev/null differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-867ba07b.png b/previews/PR318/examples/02_LLD_CoRh2O4-867ba07b.png deleted file mode 100644 index 2fb7c481e..000000000 Binary files a/previews/PR318/examples/02_LLD_CoRh2O4-867ba07b.png and /dev/null differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-8ae4e334.png b/previews/PR318/examples/02_LLD_CoRh2O4-8ae4e334.png deleted file mode 100644 index 4dcd5feab..000000000 Binary files a/previews/PR318/examples/02_LLD_CoRh2O4-8ae4e334.png and /dev/null differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-8beeef47.png b/previews/PR318/examples/02_LLD_CoRh2O4-8beeef47.png deleted file mode 100644 index 6faf58a93..000000000 Binary files a/previews/PR318/examples/02_LLD_CoRh2O4-8beeef47.png and /dev/null differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-8c71a528.png b/previews/PR318/examples/02_LLD_CoRh2O4-8c71a528.png new file mode 100644 index 000000000..6b577e986 Binary files /dev/null and b/previews/PR318/examples/02_LLD_CoRh2O4-8c71a528.png differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-8eca46a8.png b/previews/PR318/examples/02_LLD_CoRh2O4-8eca46a8.png new file mode 100644 index 000000000..7bcd733c7 Binary files /dev/null and b/previews/PR318/examples/02_LLD_CoRh2O4-8eca46a8.png differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-d608e0c1.png b/previews/PR318/examples/02_LLD_CoRh2O4-d608e0c1.png new file mode 100644 index 000000000..974a1260e Binary files /dev/null and b/previews/PR318/examples/02_LLD_CoRh2O4-d608e0c1.png differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4-ebc60cb1.png b/previews/PR318/examples/02_LLD_CoRh2O4-ebc60cb1.png new file mode 100644 index 000000000..e740bbc61 Binary files /dev/null and b/previews/PR318/examples/02_LLD_CoRh2O4-ebc60cb1.png differ diff --git a/previews/PR318/examples/02_LLD_CoRh2O4.html b/previews/PR318/examples/02_LLD_CoRh2O4.html index 0fb438df2..1b1bad9ee 100644 --- a/previews/PR318/examples/02_LLD_CoRh2O4.html +++ b/previews/PR318/examples/02_LLD_CoRh2O4.html @@ -11,16 +11,16 @@ set_exchange!(sys, J, Bond(1, 3, [0,0,0])) randomize_spins!(sys) minimize_energy!(sys) -plot_spins(sys; color=[S[3] for S in sys.dipoles])Example block output

Use repeat_periodically to extend the system to 10×10×10 chemical unit cells. The ground state Néel order is retained. Increasing the system size further would reduce finite-size artifacts and increase momentum-space resolution, but would also make the simulations slower.

sys = repeat_periodically(sys, (10, 10, 10))
-plot_spins(sys; color=[S[3] for S in sys.dipoles])
Example block output

Langevin dynamics for sampling

We will be using a Langevin spin dynamics to thermalize the system. This dynamics is a variant of the Landau-Lifshitz equation that incorporates noise and dissipation terms, which are linked by a fluctuation-dissipation theorem. The temperature 6 K ≈ 1.38 meV is slightly above ordering for this model. The dimensionless damping magnitude sets a timescale for coupling to the implicit thermal bath; 0.2 is usually a good choice.

langevin = Langevin(; damping=0.2, kT=16*units.K)
Langevin(<missing>; damping=0.2, kT=1.3787733219432283)
+plot_spins(sys; color=[S[3] for S in sys.dipoles])
Example block output

Use repeat_periodically to extend the system to 10×10×10 chemical unit cells. The ground state Néel order is retained. Increasing the system size further would reduce finite-size artifacts and increase momentum-space resolution, but would also make the simulations slower.

sys = repeat_periodically(sys, (10, 10, 10))
+plot_spins(sys; color=[S[3] for S in sys.dipoles])
Example block output

Langevin dynamics for sampling

We will be using a Langevin spin dynamics to thermalize the system. This dynamics is a variant of the Landau-Lifshitz equation that incorporates noise and dissipation terms, which are linked by a fluctuation-dissipation theorem. The temperature 6 K ≈ 1.38 meV is slightly above ordering for this model. The dimensionless damping magnitude sets a timescale for coupling to the implicit thermal bath; 0.2 is usually a good choice.

langevin = Langevin(; damping=0.2, kT=16*units.K)
Langevin(<missing>; damping=0.2, kT=1.3787733219432283)
 

Use suggest_timestep to select an integration timestep. A dimensionless error tolerance of 1e-2 is usually a good choice. The suggested timestep will vary according to the magnetic configuration. It is reasonable to start from an energy-minimized configuration.

suggest_timestep(sys, langevin; tol=1e-2)
 langevin.dt = 0.025;
Consider dt ≈ 0.02528 for this spin configuration at tol = 0.01.

Now run a Langevin trajectory to sample spin configurations. Keep track of the energy per site at each time step.

energies = [energy_per_site(sys)]
 for _ in 1:1000
     step!(sys, langevin)
     push!(energies, energy_per_site(sys))
 end

From the relaxed spin configuration, we can learn that dt was a little smaller than necessary; increasing it will make the remaining simulations faster.

suggest_timestep(sys, langevin; tol=1e-2)
-langevin.dt = 0.042;
Consider dt ≈ 0.042 for this spin configuration at tol = 0.01. Current value is dt = 0.025.

Plot energy versus time using the Makie lines function. The plateau suggests that the system has reached thermal equilibrium.

lines(energies, color=:blue, figure=(size=(600,300),), axis=(xlabel="Timesteps", ylabel="Energy (meV)"))
Example block output

Plot the spins colored by their alignment with a reference spin at the origin. The field sys.dipoles is a 4D array storing the spin dipole data. The first three indices of label the chemical cell, while the fourth index labels an atom within the cell. Note that Julia arrays use 1-based indexing. Thermal fluctuations are apparent in the plot.

S0 = sys.dipoles[1,1,1,1]
-plot_spins(sys; color=[S'*S0 for S in sys.dipoles])
Example block output

Static structure factor

Use SampledCorrelationsStatic to estimate spatial correlations for configurations in classical thermal equilibrium. Each call to add_sample! will accumulate data for the current spin snapshot.

formfactors = [1 => FormFactor("Co2")]
+langevin.dt = 0.042;
Consider dt ≈ 0.04207 for this spin configuration at tol = 0.01. Current value is dt = 0.025.

Plot energy versus time using the Makie lines function. The plateau suggests that the system has reached thermal equilibrium.

lines(energies, color=:blue, figure=(size=(600,300),), axis=(xlabel="Timesteps", ylabel="Energy (meV)"))
Example block output

Plot the spins colored by their alignment with a reference spin at the origin. The field sys.dipoles is a 4D array storing the spin dipole data. The first three indices of label the chemical cell, while the fourth index labels an atom within the cell. Note that Julia arrays use 1-based indexing. Thermal fluctuations are apparent in the plot.

S0 = sys.dipoles[1,1,1,1]
+plot_spins(sys; color=[S'*S0 for S in sys.dipoles])
Example block output

Static structure factor

Use SampledCorrelationsStatic to estimate spatial correlations for configurations in classical thermal equilibrium. Each call to add_sample! will accumulate data for the current spin snapshot.

formfactors = [1 => FormFactor("Co2")]
 measure = ssf_perp(sys; formfactors)
 sc = SampledCorrelationsStatic(sys; measure)
 add_sample!(sc, sys)    # Accumulate the newly sampled structure factor into `sf`

Collect 20 additional samples. Perform 100 Langevin time-steps between measurements to approximately decorrelate the sample in thermal equilibrium.

for _ in 1:20
@@ -29,7 +29,7 @@
     end
     add_sample!(sc, sys)
 end

Use q_space_grid to define a slice of momentum space $[H, K, 0]$, where $H$ and $K$ each range from -10 to 10 in RLU. This command produces a 200×200 grid of sample points.

grid = q_space_grid(cryst, [1, 0, 0], range(-10, 10, 200), [0, 1, 0], (-10, 10))
Sunny.QGrid{2} (200×200 samples)

Calculate and plot the instantaneous structure factor on the slice by integrating over all energy values ω. We employ the appropriate FormFactor for Co2⁺. Selecting saturation = 1.0 sets the color saturation point to the maximum intensity value. This is reasonable because we are above the ordering temperature, and do not have sharp Bragg peaks.

res = intensities_static(sc, grid)
-plot_intensities(res; saturation=1.0, title="Static Intensities at T = 16 K")
Example block output

Dynamical structure factor

To collect statistics for the dynamical structure factor intensities $\mathcal{S}(𝐪,ω)$ at finite temperature, use SampledCorrelations. It requires a range of energies to resolve, which will be associated with frequencies of the classical spin dynamics. The integration timestep dt can be somewhat larger than that used by the Langevin dynamics.

dt = 2*langevin.dt
+plot_intensities(res; saturation=1.0, title="Static Intensities at T = 16 K")
Example block output

Dynamical structure factor

To collect statistics for the dynamical structure factor intensities $\mathcal{S}(𝐪,ω)$ at finite temperature, use SampledCorrelations. It requires a range of energies to resolve, which will be associated with frequencies of the classical spin dynamics. The integration timestep dt can be somewhat larger than that used by the Langevin dynamics.

dt = 2*langevin.dt
 energies = range(0, 6, 50)
 sc = SampledCorrelations(sys; dt, energies, measure=ssf_perp(sys))
SampledCorrelations (612.974 MiB)
 [S(q,ω) | nω = 49, Δω = 0.1224 | 0 sample]
@@ -50,8 +50,8 @@
 path = q_space_path(cryst, qs, 500)
QPath (500 samples)
   [3/4, 3/4, 0] → [0, 0, 0] → [0, 1/2, 1/2] → [1/2, 1, 0] → [0, 1, 0] → [1/4, 1, 1/4] → [0, 1, 0] → [0, -4, 0]
 

Calculate and plot the intensities along this path.

res = intensities(sc, path; energies, langevin.kT)
-plot_intensities(res; units, title="Intensities at 16 K")
Example block output

Powder averaged intensity

Define spherical shells in reciprocal space via their radii, in absolute units of 1/Å. For each shell, calculate and average the intensities at 350 $𝐪$-points

radii = range(0, 3.5, 200) # (1/Å)
+plot_intensities(res; units, title="Intensities at 16 K")
Example block output

Powder averaged intensity

Define spherical shells in reciprocal space via their radii, in absolute units of 1/Å. For each shell, calculate and average the intensities at 350 $𝐪$-points

radii = range(0, 3.5, 200) # (1/Å)
 res = powder_average(cryst, radii, 350) do qs
     intensities(sc, qs; energies, langevin.kT)
 end
-plot_intensities(res; units, title="Powder Average at 16 K")
Example block output +plot_intensities(res; units, title="Powder Average at 16 K")Example block output diff --git a/previews/PR318/examples/03_LSWT_SU3_FeI2.html b/previews/PR318/examples/03_LSWT_SU3_FeI2.html index 5ac60ad1a..d85081ded 100644 --- a/previews/PR318/examples/03_LSWT_SU3_FeI2.html +++ b/previews/PR318/examples/03_LSWT_SU3_FeI2.html @@ -127,4 +127,4 @@ res = domain_average(cryst, path; rotations, weights) do path_rotated intensities(swt, path_rotated; energies, kernel) end -plot_intensities(res; units, colormap=:viridis, title="Domain Averaged Intensities")Example block output

This result can be directly compared to experimental neutron scattering data from Bai et al.

(The publication figure used a non-standard coordinate system to label the wave vectors.)

To get this agreement, the theory of SU(3) coherent states is essential. The lower band has large quadrupolar character, and arises from the strong easy-axis anisotropy of FeI₂.

An interesting exercise is to repeat the same study, but using :dipole mode instead of :SUN. That alternative choice would constrain the coherent state dynamics to the space of dipoles only, and the flat band of single-ion bound states would be missing.

+plot_intensities(res; units, colormap=:viridis, title="Domain Averaged Intensities")Example block output

This result can be directly compared to experimental neutron scattering data from Bai et al.

(The publication figure used a non-standard coordinate system to label the wave vectors.)

To get this agreement, the theory of SU(3) coherent states is essential. The lower band has large quadrupolar character, and arises from the strong easy-axis anisotropy of FeI₂.

An interesting exercise is to repeat the same study, but using :dipole mode instead of :SUN. That alternative choice would constrain the coherent state dynamics to the space of dipoles only, and the flat band of single-ion bound states would be missing.

diff --git a/previews/PR318/examples/04_GSD_FeI2-09ba6b72.png b/previews/PR318/examples/04_GSD_FeI2-09ba6b72.png new file mode 100644 index 000000000..387717e82 Binary files /dev/null and b/previews/PR318/examples/04_GSD_FeI2-09ba6b72.png differ diff --git a/previews/PR318/examples/04_GSD_FeI2-0bb90050.png b/previews/PR318/examples/04_GSD_FeI2-0bb90050.png new file mode 100644 index 000000000..de392c299 Binary files /dev/null and b/previews/PR318/examples/04_GSD_FeI2-0bb90050.png differ diff --git a/previews/PR318/examples/04_GSD_FeI2-7c067617.png b/previews/PR318/examples/04_GSD_FeI2-7c067617.png new file mode 100644 index 000000000..2a388b366 Binary files /dev/null and b/previews/PR318/examples/04_GSD_FeI2-7c067617.png differ diff --git a/previews/PR318/examples/04_GSD_FeI2-82d99c84.png b/previews/PR318/examples/04_GSD_FeI2-82d99c84.png deleted file mode 100644 index 2dde4a070..000000000 Binary files a/previews/PR318/examples/04_GSD_FeI2-82d99c84.png and /dev/null differ diff --git a/previews/PR318/examples/04_GSD_FeI2-9e62d67e.png b/previews/PR318/examples/04_GSD_FeI2-9e62d67e.png deleted file mode 100644 index 0ed29f1b1..000000000 Binary files a/previews/PR318/examples/04_GSD_FeI2-9e62d67e.png and /dev/null differ diff --git a/previews/PR318/examples/04_GSD_FeI2-acb9338e.png b/previews/PR318/examples/04_GSD_FeI2-acb9338e.png deleted file mode 100644 index c5fd3b224..000000000 Binary files a/previews/PR318/examples/04_GSD_FeI2-acb9338e.png and /dev/null differ diff --git a/previews/PR318/examples/04_GSD_FeI2-cd9a20b8.png b/previews/PR318/examples/04_GSD_FeI2-cd9a20b8.png new file mode 100644 index 000000000..cee5bc01f Binary files /dev/null and b/previews/PR318/examples/04_GSD_FeI2-cd9a20b8.png differ diff --git a/previews/PR318/examples/04_GSD_FeI2-ceb6e278.png b/previews/PR318/examples/04_GSD_FeI2-ceb6e278.png deleted file mode 100644 index 6a47da8c6..000000000 Binary files a/previews/PR318/examples/04_GSD_FeI2-ceb6e278.png and /dev/null differ diff --git a/previews/PR318/examples/04_GSD_FeI2.html b/previews/PR318/examples/04_GSD_FeI2.html index f016d4c8a..6415b0d8e 100644 --- a/previews/PR318/examples/04_GSD_FeI2.html +++ b/previews/PR318/examples/04_GSD_FeI2.html @@ -39,27 +39,27 @@

Use suggest_timestep to select an integration timestep for the error tolerance tol=1e-2. Initializing sys to some low-energy configuration usually works well.

randomize_spins!(sys)
 minimize_energy!(sys; maxiters=10)
 suggest_timestep(sys, langevin; tol=1e-2)
-langevin.dt = 0.03;
Consider dt ≈ 0.03019 for this spin configuration at tol = 0.01.

Run a Langevin trajectory for 10,000 time-steps and plot the spins. The magnetic order is present, but may be difficult to see.

for _ in 1:10_000
+langevin.dt = 0.03;
Consider dt ≈ 0.03038 for this spin configuration at tol = 0.01.

Run a Langevin trajectory for 10,000 time-steps and plot the spins. The magnetic order is present, but may be difficult to see.

for _ in 1:10_000
     step!(sys, langevin)
 end
-plot_spins(sys; color=[S[3] for S in sys.dipoles])
Example block output

Verify the expected two-up, two-down spiral magnetic order by calling print_wrapped_intensities. A single propagation wavevector $±𝐤$ dominates the static intensity in $\mathcal{S}(𝐪)$, indicating the expected 2 up, 2 down magnetic spiral order. A smaller amount of intensity is spread among many other wavevectors due to thermal fluctuations.

print_wrapped_intensities(sys)
Dominant wavevectors for spin sublattices:
+plot_spins(sys; color=[S[3] for S in sys.dipoles])
Example block output

Verify the expected two-up, two-down spiral magnetic order by calling print_wrapped_intensities. A single propagation wavevector $±𝐤$ dominates the static intensity in $\mathcal{S}(𝐪)$, indicating the expected 2 up, 2 down magnetic spiral order. A smaller amount of intensity is spread among many other wavevectors due to thermal fluctuations.

print_wrapped_intensities(sys)
Dominant wavevectors for spin sublattices:
 
-    [-1/4, 1/4, 1/4]       38.86% weight
-    [1/4, -1/4, -1/4]      38.86%
-    [0, 0, 1/2]             0.08%
-    [0.0625, 0.1875, 1/2]    0.07%
-    [-0.0625, -0.1875, 1/2]    0.07%
-    [-1/8, 3/8, 0]          0.07%
-    [1/8, -3/8, 0]          0.07%
-    [-1/8, 1/8, 0]          0.07%
-    [1/8, -1/8, 0]          0.07%
-    [0.0625, -0.3125, 1/4]    0.07%
-    [-0.0625, 0.3125, -1/4]    0.07%
-    ...                     ...

Thermalization has not substantially altered the suggested dt.

suggest_timestep(sys, langevin; tol=1e-2)
Consider dt ≈ 0.03154 for this spin configuration at tol = 0.01. Current value is dt = 0.03.

Structure factor in the paramagnetic phase

The remainder of this tutorial will focus on the paramagnetic phase. Re-thermalize the system to the temperature of 3.5 K ≈ 0.30 meV.

langevin.kT = 3.5 * units.K
+    [0, -1/4, 1/4]         37.60% weight
+    [0, 1/4, -1/4]         37.60%
+    [-0.3125, 1/4, 0]       0.10%
+    [0.3125, -1/4, 0]       0.10%
+    [1/8, 0.1875, 1/2]      0.09%
+    [-1/8, -0.1875, 1/2]    0.09%
+    [0, 0.1875, 1/2]        0.09%
+    [0, -0.1875, 1/2]       0.09%
+    [1/8, 0, 1/2]           0.08%
+    [-1/8, 0, 1/2]          0.08%
+    [1/8, -3/8, 1/4]        0.08%
+    ...                     ...

Thermalization has not substantially altered the suggested dt.

suggest_timestep(sys, langevin; tol=1e-2)
Consider dt ≈ 0.03189 for this spin configuration at tol = 0.01. Current value is dt = 0.03.

Structure factor in the paramagnetic phase

The remainder of this tutorial will focus on the paramagnetic phase. Re-thermalize the system to the temperature of 3.5 K ≈ 0.30 meV.

langevin.kT = 3.5 * units.K
 for _ in 1:10_000
     step!(sys, langevin)
 end

The suggested timestep has increased slightly. Following this suggestion will make the simulations a bit faster.

suggest_timestep(sys, langevin; tol=1e-2)
-langevin.dt = 0.040;
Consider dt ≈ 0.04003 for this spin configuration at tol = 0.01. Current value is dt = 0.03.

Collect dynamical spin structure factor data using SampledCorrelations. This procedure involves sampling spin configurations from thermal equilibrium and using the spin dynamics of SU(N) coherent states to estimate dynamical correlations. With proper classical-to-quantum corrections, the associated structure factor intensities $S^{αβ}(q,ω)$ can be compared with finite-temperature inelastic neutron scattering data. Incorporate the FormFactor appropriate to Fe²⁺.

dt = 2*langevin.dt
+langevin.dt = 0.040;
Consider dt ≈ 0.04017 for this spin configuration at tol = 0.01. Current value is dt = 0.03.

Collect dynamical spin structure factor data using SampledCorrelations. This procedure involves sampling spin configurations from thermal equilibrium and using the spin dynamics of SU(N) coherent states to estimate dynamical correlations. With proper classical-to-quantum corrections, the associated structure factor intensities $S^{αβ}(q,ω)$ can be compared with finite-temperature inelastic neutron scattering data. Incorporate the FormFactor appropriate to Fe²⁺.

dt = 2*langevin.dt
 energies = range(0, 7.5, 120)
 formfactors = [1 => FormFactor("Fe2"; g_lande=3/2)]
 sc = SampledCorrelations(sys; dt, energies, measure=ssf_perp(sys; formfactors))
SampledCorrelations (37.950 MiB)
@@ -74,7 +74,7 @@
 fig = lines(res.energies, res.data[:, 1]; axis=(xlabel="meV", ylabel="Intensity"), label="(0,0,0)")
 lines!(res.energies, res.data[:, 2]; label="(π,π,π)")
 axislegend()
-fig
Example block output

Next, we will measure intensities along a q_space_path that connects high symmetry points. Because this is a real-space calculation, data is only available for discrete $𝐪$ modes, with resolution that scales inversely to linear system size. Intensities at $ω = 0$ dominate, so to enhance visibility, we restrict the color range empirically.

qs = [[0,   0, 0],  # List of wave vectors that define a path
+fig
Example block output

Next, we will measure intensities along a q_space_path that connects high symmetry points. Because this is a real-space calculation, data is only available for discrete $𝐪$ modes, with resolution that scales inversely to linear system size. Intensities at $ω = 0$ dominate, so to enhance visibility, we restrict the color range empirically.

qs = [[0,   0, 0],  # List of wave vectors that define a path
       [1,   0, 0],
       [0,   1, 0],
       [1/2, 0, 0],
@@ -82,6 +82,6 @@
       [0,   0, 0]]
 qpath = q_space_path(cryst, qs, 500)
 res = intensities(sc, qpath; energies, langevin.kT)
-plot_intensities(res; colorrange=(0.0, 1.0), title="Intensities at T = 2.3 K")
Example block output

One can also view the intensity along a q_space_grid for a fixed energy value. Alternatively, use intensities_static to integrate over all available energies.

grid = q_space_grid(cryst, [1, 0, 0], range(-1.5, 1.5, 300), [0, 1, 0], (-1.5, 1.5); orthogonalize=true)
+plot_intensities(res; colorrange=(0.0, 1.0), title="Intensities at T = 2.3 K")
Example block output

One can also view the intensity along a q_space_grid for a fixed energy value. Alternatively, use intensities_static to integrate over all available energies.

grid = q_space_grid(cryst, [1, 0, 0], range(-1.5, 1.5, 300), [0, 1, 0], (-1.5, 1.5); orthogonalize=true)
 res = intensities(sc, grid; energies=[3.5], langevin.kT)
-plot_intensities(res; title="Intensity slice at ω = 3.5 meV")
Example block output +plot_intensities(res; title="Intensity slice at ω = 3.5 meV")Example block output diff --git a/previews/PR318/examples/05_MC_Ising.html b/previews/PR318/examples/05_MC_Ising.html index d434f622b..b0300c94d 100644 --- a/previews/PR318/examples/05_MC_Ising.html +++ b/previews/PR318/examples/05_MC_Ising.html @@ -13,4 +13,4 @@ sampler = LocalSampler(kT=Tc, propose=propose_flip) for i in 1:nsweeps step!(sys, sampler) -end

Plot the Ising spins by extracting the $z$-component of the dipoles

heatmap(reshape([S[3] for S in sys.dipoles], (L, L)))
Example block output +end

Plot the Ising spins by extracting the $z$-component of the dipoles

heatmap(reshape([S[3] for S in sys.dipoles], (L, L)))
Example block output diff --git a/previews/PR318/examples/06_CP2_Skyrmions-5666a209.png b/previews/PR318/examples/06_CP2_Skyrmions-5666a209.png new file mode 100644 index 000000000..7785797b9 Binary files /dev/null and b/previews/PR318/examples/06_CP2_Skyrmions-5666a209.png differ diff --git a/previews/PR318/examples/06_CP2_Skyrmions-8ebcdd0f.png b/previews/PR318/examples/06_CP2_Skyrmions-8ebcdd0f.png deleted file mode 100644 index c7a04c6bd..000000000 Binary files a/previews/PR318/examples/06_CP2_Skyrmions-8ebcdd0f.png and /dev/null differ diff --git a/previews/PR318/examples/06_CP2_Skyrmions.html b/previews/PR318/examples/06_CP2_Skyrmions.html index 5ca362564..e18f466a5 100644 --- a/previews/PR318/examples/06_CP2_Skyrmions.html +++ b/previews/PR318/examples/06_CP2_Skyrmions.html @@ -31,7 +31,7 @@ set_onsite_coupling!(sys, S -> D*S[3]^2, 1)

Initialize system to an infinite temperature (fully randomized) initial condition.

We will study a temperature quench process using a generalized Langevin spin dynamics. In this SU(3) treatment of quantum spin-1, the dynamics include coupled dipoles and quadrupoles. Select a relatively small damping magnitude to overcome local minima, and disable thermal fluctuations.

damping = 0.05
 kT = 0;

The first step is to estimate a reasonable integration timestep dt. In this case, a random spin configuration gives a tighter bound than does an energy-minimized configuration. A relatively large error tolerance is OK for this phenomenological study.

randomize_spins!(sys)
 integrator = Langevin(; damping, kT)
-suggest_timestep(sys, integrator; tol=0.05)
Consider dt ≈ 0.01097 for this spin configuration at tol = 0.05.

Apply the suggested timestep.

integrator.dt = 0.01;

Now run the dynamical quench starting from a randomized configuration. The field frames stores the system spin configuration, as SU(3) coherent states, at three different times during the quenching process.

randomize_spins!(sys)
+suggest_timestep(sys, integrator; tol=0.05)
Consider dt ≈ 0.01115 for this spin configuration at tol = 0.05.

Apply the suggested timestep.

integrator.dt = 0.01;

Now run the dynamical quench starting from a randomized configuration. The field frames stores the system spin configuration, as SU(3) coherent states, at three different times during the quenching process.

randomize_spins!(sys)
 τs = [4, 16, 256]   # Times to record snapshots
 frames = []         # Empty array to store snapshots
 for i in eachindex(τs)
@@ -53,4 +53,4 @@
 
 plot_triangular_plaquettes(sun_berry_curvature, frames; size=(600, 200),
     offset_spacing=10, texts=["\tt = "*string(τ) for τ in τs], text_offset=(0, 6)
-)
Example block output

The times are given in $\hbar/|J_1|$. The white background corresponds to a quantum paramagnetic state, where the local spin exhibits a strong quadrupole moment and little or no dipole moment. At late times, there are well-formed skyrmions of positive (red) and negative (blue) charge, and various metastable spin configurations. A full-sized version of this figure is available in Dahlbom et al..

+)Example block output

The times are given in $\hbar/|J_1|$. The white background corresponds to a quantum paramagnetic state, where the local spin exhibits a strong quadrupole moment and little or no dipole moment. At late times, there are well-formed skyrmions of positive (red) and negative (blue) charge, and various metastable spin configurations. A full-sized version of this figure is available in Dahlbom et al..

diff --git a/previews/PR318/examples/07_Dipole_Dipole.html b/previews/PR318/examples/07_Dipole_Dipole.html index 1c555adeb..bfc597de3 100644 --- a/previews/PR318/examples/07_Dipole_Dipole.html +++ b/previews/PR318/examples/07_Dipole_Dipole.html @@ -30,4 +30,4 @@ for c in eachrow(res3.disp) lines!(ax, eachindex(c), c; linestyle=:dash, color=:black) end -figExample block output +figExample block output diff --git a/previews/PR318/examples/08_Momentum_Conventions-2956b812.png b/previews/PR318/examples/08_Momentum_Conventions-2956b812.png new file mode 100644 index 000000000..eeb306e18 Binary files /dev/null and b/previews/PR318/examples/08_Momentum_Conventions-2956b812.png differ diff --git a/previews/PR318/examples/08_Momentum_Conventions-59ab413a.png b/previews/PR318/examples/08_Momentum_Conventions-59ab413a.png deleted file mode 100644 index c87ed8f41..000000000 Binary files a/previews/PR318/examples/08_Momentum_Conventions-59ab413a.png and /dev/null differ diff --git a/previews/PR318/examples/08_Momentum_Conventions-62fdd641.png b/previews/PR318/examples/08_Momentum_Conventions-62fdd641.png new file mode 100644 index 000000000..10a3daedd Binary files /dev/null and b/previews/PR318/examples/08_Momentum_Conventions-62fdd641.png differ diff --git a/previews/PR318/examples/08_Momentum_Conventions-6996d80b.png b/previews/PR318/examples/08_Momentum_Conventions-6996d80b.png deleted file mode 100644 index 01053fb41..000000000 Binary files a/previews/PR318/examples/08_Momentum_Conventions-6996d80b.png and /dev/null differ diff --git a/previews/PR318/examples/08_Momentum_Conventions.html b/previews/PR318/examples/08_Momentum_Conventions.html index e98a4e839..8f1466219 100644 --- a/previews/PR318/examples/08_Momentum_Conventions.html +++ b/previews/PR318/examples/08_Momentum_Conventions.html @@ -19,7 +19,7 @@ suggest_timestep(sys, langevin; tol=1e-2) for _ in 1:10_000 step!(sys, langevin) -end
Consider dt ≈ 0.0995 for this spin configuration at tol = 0.01. Current value is dt = 0.1.

The Zeeman coupling polarizes the magnetic moments in the $𝐁 ∝ ẑ$ direction. The spin dipoles, however, are anti-aligned with the magnetic moments, and therefore point towards $-ẑ$. This is shown below.

plot_spins(sys)
Example block output

Estimate the dynamical structure factor using classical dynamics.

sc = SampledCorrelations(sys; dt, energies=range(0, 15D, 100), measure=ssf_trace(sys))
+end
Consider dt ≈ 0.0995 for this spin configuration at tol = 0.01. Current value is dt = 0.1.

The Zeeman coupling polarizes the magnetic moments in the $𝐁 ∝ ẑ$ direction. The spin dipoles, however, are anti-aligned with the magnetic moments, and therefore point towards $-ẑ$. This is shown below.

plot_spins(sys)
Example block output

Estimate the dynamical structure factor using classical dynamics.

sc = SampledCorrelations(sys; dt, energies=range(0, 15D, 100), measure=ssf_trace(sys))
 add_sample!(sc, sys)
 nsamples = 100
 for _ in 1:nsamples
@@ -35,4 +35,4 @@
 res2 = intensities_bands(swt, path)
Sunny.BandIntensities{Float64, Sunny.QPath, 2} (1×400 elements)

This model system has a single magnon band with dispersion $ϵ(𝐪) = 1 - D/B \sin(2πq₃)$ and uniform intensity. Both calculation methods reproduce this analytical solution. Observe that $𝐪$ and $-𝐪$ are inequivalent. The structure factor calculated from classical dynamics additionally shows an elastic peak at $𝐪 = [0,0,0]$, reflecting the ferromagnetic ground state.

fig = Figure(size=(768, 300))
 plot_intensities!(fig[1, 1], res1; title="Classical dynamics")
 plot_intensities!(fig[1, 2], res2; title="Spin wave theory")
-fig
Example block output +figExample block output diff --git a/previews/PR318/examples/09_Disorder_KPM-1a680b53.png b/previews/PR318/examples/09_Disorder_KPM-1a680b53.png new file mode 100644 index 000000000..c4cf3dbea Binary files /dev/null and b/previews/PR318/examples/09_Disorder_KPM-1a680b53.png differ diff --git a/previews/PR318/examples/09_Disorder_KPM-1c325088.png b/previews/PR318/examples/09_Disorder_KPM-1c325088.png new file mode 100644 index 000000000..b6d88a922 Binary files /dev/null and b/previews/PR318/examples/09_Disorder_KPM-1c325088.png differ diff --git a/previews/PR318/examples/09_Disorder_KPM-30e19112.png b/previews/PR318/examples/09_Disorder_KPM-30e19112.png deleted file mode 100644 index 1fc984f14..000000000 Binary files a/previews/PR318/examples/09_Disorder_KPM-30e19112.png and /dev/null differ diff --git a/previews/PR318/examples/09_Disorder_KPM-446a3834.png b/previews/PR318/examples/09_Disorder_KPM-446a3834.png deleted file mode 100644 index 099dad0f6..000000000 Binary files a/previews/PR318/examples/09_Disorder_KPM-446a3834.png and /dev/null differ diff --git a/previews/PR318/examples/09_Disorder_KPM-4ac87ac3.png b/previews/PR318/examples/09_Disorder_KPM-4ac87ac3.png new file mode 100644 index 000000000..ed1d088c3 Binary files /dev/null and b/previews/PR318/examples/09_Disorder_KPM-4ac87ac3.png differ diff --git a/previews/PR318/examples/09_Disorder_KPM-51f8c300.png b/previews/PR318/examples/09_Disorder_KPM-51f8c300.png deleted file mode 100644 index e1aa6cbf6..000000000 Binary files a/previews/PR318/examples/09_Disorder_KPM-51f8c300.png and /dev/null differ diff --git a/previews/PR318/examples/09_Disorder_KPM-59413650.png b/previews/PR318/examples/09_Disorder_KPM-59413650.png new file mode 100644 index 000000000..604a44660 Binary files /dev/null and b/previews/PR318/examples/09_Disorder_KPM-59413650.png differ diff --git a/previews/PR318/examples/09_Disorder_KPM-6ee6257a.png b/previews/PR318/examples/09_Disorder_KPM-6ee6257a.png deleted file mode 100644 index 49c4925b9..000000000 Binary files a/previews/PR318/examples/09_Disorder_KPM-6ee6257a.png and /dev/null differ diff --git a/previews/PR318/examples/09_Disorder_KPM-8c3ef937.png b/previews/PR318/examples/09_Disorder_KPM-8c3ef937.png new file mode 100644 index 000000000..4c6180e9e Binary files /dev/null and b/previews/PR318/examples/09_Disorder_KPM-8c3ef937.png differ diff --git a/previews/PR318/examples/09_Disorder_KPM-b0c90ccf.png b/previews/PR318/examples/09_Disorder_KPM-b0c90ccf.png deleted file mode 100644 index 870c4157b..000000000 Binary files a/previews/PR318/examples/09_Disorder_KPM-b0c90ccf.png and /dev/null differ diff --git a/previews/PR318/examples/09_Disorder_KPM-c0b1b451.png b/previews/PR318/examples/09_Disorder_KPM-c0b1b451.png deleted file mode 100644 index d34c63b6b..000000000 Binary files a/previews/PR318/examples/09_Disorder_KPM-c0b1b451.png and /dev/null differ diff --git a/previews/PR318/examples/09_Disorder_KPM-f8b0e684.png b/previews/PR318/examples/09_Disorder_KPM-f8b0e684.png new file mode 100644 index 000000000..05c91b683 Binary files /dev/null and b/previews/PR318/examples/09_Disorder_KPM-f8b0e684.png differ diff --git a/previews/PR318/examples/09_Disorder_KPM.html b/previews/PR318/examples/09_Disorder_KPM.html index 0431d65cc..f10439852 100644 --- a/previews/PR318/examples/09_Disorder_KPM.html +++ b/previews/PR318/examples/09_Disorder_KPM.html @@ -6,13 +6,13 @@ randomize_spins!(sys) minimize_energy!(sys) -plot_spins(sys; color=[s[3] for s in sys.dipoles], ndims=2)Example block output

Select a $𝐪$-space path for the spin wave calculations.

qs = [[0, 0, 0], [1/3, 1/3, 0], [1/2, 0, 0], [0, 0, 0]]
+plot_spins(sys; color=[S[3] for S in sys.dipoles], ndims=2)
Example block output

Select a $𝐪$-space path for the spin wave calculations.

qs = [[0, 0, 0], [1/3, 1/3, 0], [1/2, 0, 0], [0, 0, 0]]
 labels = ["Γ", "K", "M", "Γ"]
 path = q_space_path(cryst, qs, 150; labels)
 kernel = lorentzian(fwhm=0.4);

Perform a traditional spin wave calculation. The spectrum shows sharp modes associated with coherent excitations about the K-point ordering wavevector, $𝐪 = [1/3, 1/3, 0]$.

energies = range(0.0, 3.0, 150)
 swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 res = intensities(swt, path; energies, kernel)
-plot_intensities(res)
Example block output

Use repeat_periodically to enlarge the system by a factor of 10 in each dimension. Use to_inhomogeneous to disable symmetry constraints, and allow for the addition of disordered interactions.

sys_inhom = to_inhomogeneous(repeat_periodically(sys, (10, 10, 1)))
System [Dipole mode]
+plot_intensities(res)
Example block output

Use repeat_periodically to enlarge the system by a factor of 10 in each dimension. Use to_inhomogeneous to disable symmetry constraints, and allow for the addition of disordered interactions.

sys_inhom = to_inhomogeneous(repeat_periodically(sys, (10, 10, 1)))
System [Dipole mode]
 Supercell (30×30×1)×1
 Energy per site -3/8
 

Use symmetry_equivalent_bonds to iterate over all nearest neighbor bonds of the inhomogeneous system. Modify each AFM exchange with a noise term that has variance of 1/3. The newly minimized energy configuration allows for long wavelength modulations on top of the original 120° order.

for (site1, site2, offset) in symmetry_equivalent_bonds(sys_inhom, Bond(1,1,[1,0,0]))
@@ -21,25 +21,25 @@
 end
 
 minimize_energy!(sys_inhom, maxiters=5_000)
-plot_spins(sys_inhom; color=[s[3] for s in sys_inhom.dipoles], ndims=2)
Example block output

Traditional spin wave theory calculations become impractical for large system sizes. Significant acceleration is possible with the kernel polynomial method. Enable it by selecting SpinWaveTheoryKPM in place of the traditional SpinWaveTheory. Using KPM, the cost of an intensities calculation becomes linear in system size and scales inversely with the width of the line broadening kernel. Error tolerance is controlled through the dimensionless tol parameter. A relatively small value, tol = 0.01, helps to resolve the large intensities near the ordering wavevector. The alternative choice tol = 0.1 would be twice faster, but would introduce significant numerical artifacts.

Observe from the KPM calculation that disorder in the nearest-neighbor exchange serves to broaden the discrete excitation bands into a continuum.

swt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.01)
+plot_spins(sys_inhom; color=[S[3] for S in sys_inhom.dipoles], ndims=2)
Example block output

Traditional spin wave theory calculations become impractical for large system sizes. Significant acceleration is possible with the kernel polynomial method. Enable it by selecting SpinWaveTheoryKPM in place of the traditional SpinWaveTheory. Using KPM, the cost of an intensities calculation becomes linear in system size and scales inversely with the width of the line broadening kernel. Error tolerance is controlled through the dimensionless tol parameter. A relatively small value, tol = 0.01, helps to resolve the large intensities near the ordering wavevector. The alternative choice tol = 0.1 would be twice faster, but would introduce significant numerical artifacts.

Observe from the KPM calculation that disorder in the nearest-neighbor exchange serves to broaden the discrete excitation bands into a continuum.

swt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.01)
 res = intensities(swt, path; energies, kernel)
-plot_intensities(res)
Example block output

Now apply a magnetic field of magnitude 7.5 (energy units) along the global $ẑ$ axis. This field fully polarizes the spins. Because gap opens, a larger tolerance of tol = 0.1 can be used to accelerate the KPM calculation without sacrificing much accuracy. The resulting spin wave spectrum shows a sharp mode at the Γ-point (zone center) that broadens into a continuum along the K and M points (zone boundary).

set_field!(sys_inhom, [0, 0, 7.5])
+plot_intensities(res)
Example block output

Now apply a magnetic field of magnitude 7.5 (energy units) along the global $ẑ$ axis. This field fully polarizes the spins. Because gap opens, a larger tolerance of tol = 0.1 can be used to accelerate the KPM calculation without sacrificing much accuracy. The resulting spin wave spectrum shows a sharp mode at the Γ-point (zone center) that broadens into a continuum along the K and M points (zone boundary).

set_field!(sys_inhom, [0, 0, 7.5])
 randomize_spins!(sys_inhom)
 minimize_energy!(sys_inhom)
 
 energies = range(0.0, 9.0, 150)
 swt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.1)
 res = intensities(swt, path; energies, kernel)
-plot_intensities(res)
Example block output

Add disorder to the $z$-component of each magnetic moment $g$-tensor. This further broadens intensities, now across the entire path. Some intensity modulation within the continuum is also apparent. This modulation is a finite-size effect, and would be mitigated by enlarging the system beyond 30×30 chemical cells.

for site in eachsite(sys_inhom)
+plot_intensities(res)
Example block output

Add disorder to the $z$-component of each magnetic moment $g$-tensor. This further broadens intensities, now across the entire path. Some intensity modulation within the continuum is also apparent. This modulation is a finite-size effect, and would be mitigated by enlarging the system beyond 30×30 chemical cells.

for site in eachsite(sys_inhom)
     noise = randn()/6
     sys_inhom.gs[site] = [1 0 0; 0 1 0; 0 0 1+noise]
 end
 
 swt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.1)
 res = intensities(swt, path; energies, kernel)
-plot_intensities(res)
Example block output

For reference, the equivalent non-disordered system shows a single coherent mode.

set_field!(sys, [0, 0, 7.5])
+plot_intensities(res)
Example block output

For reference, the equivalent non-disordered system shows a single coherent mode.

set_field!(sys, [0, 0, 7.5])
 randomize_spins!(sys)
 minimize_energy!(sys)
 swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 res = intensities(swt, path; energies, kernel)
-plot_intensities(res)
Example block output +plot_intensities(res)Example block output diff --git a/previews/PR318/examples/contributed/MgCr2O4-tutorial.html b/previews/PR318/examples/contributed/MgCr2O4-tutorial.html index 2ae9680e8..b66782333 100644 --- a/previews/PR318/examples/contributed/MgCr2O4-tutorial.html +++ b/previews/PR318/examples/contributed/MgCr2O4-tutorial.html @@ -360,4 +360,4 @@ Sq_mgcro = intensities_static(sc_mgcro, qpts_mgcro; kT);

We can plot the results below. It is useful to compare these to the plot above generated with an SampledCorrelationsStatic.

fig = Figure(; size=(1200,500))
 ax = plot_intensities!(fig[1,1], Sq_pyro; title="Pyrochlore")
 ax = plot_intensities!(fig[1,2], Sq_mgcro; title="MgCr₂O₄")
-fig

+fig

diff --git a/previews/PR318/examples/contributed/kappa_tutorial.html b/previews/PR318/examples/contributed/kappa_tutorial.html index 686735aa5..065c05b48 100644 --- a/previews/PR318/examples/contributed/kappa_tutorial.html +++ b/previews/PR318/examples/contributed/kappa_tutorial.html @@ -98,4 +98,4 @@ # Turn off κ renormalization before generating a new equilibrium sample. set_spin_rescaling!(sys, 1.0) -end

Finally, we evaluate the sum.

total_spectral_weight(sc; kT) / prod(sys.dims)
5.142433967821603

The result is something slightly greater than 5, substantially closer to the expected quantum sum rule. We can now adjust $\kappa$ and iterate until we reach a value sufficiently close to 16/3. In general, this should be done while collecting substantially more statistics.

Note that $\kappa (T)$ needs to be determined empirically for each model. A detailed example, demonstrating the calculations used in [3], is available here.

References

[1] - H. Zhang, C. D. Batista, "Classical spin dynamics based on SU(N) coherent states," PRB (2021)

[2] - T. Huberman, D. A. Tennant, R. A. Cowley, R. Coldea and C. D. Frost, "A study of the quantum classical crossover in the spin dynamics of the 2D S = 5/2 antiferromagnet Rb2MnF4: neutron scattering, computer simulations and analytic theories" (2008)

[3] - D. Dahlbom, D. Brooks, M. S. Wilson, S. Chi, A. I. Kolesnikov, M. B. Stone, H. Cao, Y.-W. Li, K. Barros, M. Mourigal, C. D. Batista, X. Bai, "Quantum to classical crossover in generalized spin systems," arXiv:2310.19905 (2023)

+end

Finally, we evaluate the sum.

total_spectral_weight(sc; kT) / prod(sys.dims)
5.142433967821603

The result is something slightly greater than 5, substantially closer to the expected quantum sum rule. We can now adjust $\kappa$ and iterate until we reach a value sufficiently close to 16/3. In general, this should be done while collecting substantially more statistics.

Note that $\kappa (T)$ needs to be determined empirically for each model. A detailed example, demonstrating the calculations used in [3], is available here.

References

[1] - H. Zhang, C. D. Batista, "Classical spin dynamics based on SU(N) coherent states," PRB (2021)

[2] - T. Huberman, D. A. Tennant, R. A. Cowley, R. Coldea and C. D. Frost, "A study of the quantum classical crossover in the spin dynamics of the 2D S = 5/2 antiferromagnet Rb2MnF4: neutron scattering, computer simulations and analytic theories" (2008)

[3] - D. Dahlbom, D. Brooks, M. S. Wilson, S. Chi, A. I. Kolesnikov, M. B. Stone, H. Cao, Y.-W. Li, K. Barros, M. Mourigal, C. D. Batista, X. Bai, "Quantum to classical crossover in generalized spin systems," arXiv:2310.19905 (2023)

diff --git a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-26ecd981.png b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-26ecd981.png deleted file mode 100644 index 947a97415..000000000 Binary files a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-26ecd981.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-4724cb4b.png b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-4724cb4b.png new file mode 100644 index 000000000..2e7a55ecc Binary files /dev/null and b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-4724cb4b.png differ diff --git a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-ab5269c5.png b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-ab5269c5.png deleted file mode 100644 index cb0992cd3..000000000 Binary files a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-ab5269c5.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-b1acd25b.png b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-b1acd25b.png deleted file mode 100644 index e02e9eae5..000000000 Binary files a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-b1acd25b.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-e0efb161.png b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-e0efb161.png new file mode 100644 index 000000000..ac69796b9 Binary files /dev/null and b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-e0efb161.png differ diff --git a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-f025c52d.png b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-f025c52d.png new file mode 100644 index 000000000..6948d9ad6 Binary files /dev/null and b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain-f025c52d.png differ diff --git a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain.html b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain.html index cfd81b6c3..55fb7a113 100644 --- a/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain.html +++ b/previews/PR318/examples/spinw/SW01_FM_Heseinberg_chain.html @@ -46,16 +46,16 @@

Set a nearest neighbor exchange interaction of $J = -1$ meV between neighboring atoms. That is, the total energy along each bond is $J S_i S_{i+1}$. The exchange interaction will be propagated to all symmetry equivalent bonds in the system.

J = -1
 set_exchange!(sys, J, Bond(1, 1, [1, 0, 0]))

Find the energy minimum, which is ferromagnetic. The energy per site is $-J$ for this unfrustrated FM order.

randomize_spins!(sys)
 minimize_energy!(sys)
-energy_per_site(sys)
-1.0

Because the interaction is Heisenberg (isotropic), the minimization procedure selects an arbitrary direction in spin-space.

plot_spins(sys; ndims=2, ghost_radius=8)
Example block output

Build a SpinWaveTheory object to measure the dynamical spin-spin structure factor (SSF). Select ssf_perp to project intensities onto the space perpendicular to the momentum transfer $𝐪$, which is appropriate for an unpolarized neutron beam.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
SpinWaveTheory [Dipole mode]
+energy_per_site(sys)
-1.0

Because the interaction is Heisenberg (isotropic), the minimization procedure selects an arbitrary direction in spin-space.

plot_spins(sys; ndims=2, ghost_radius=8)
Example block output

Build a SpinWaveTheory object to measure the dynamical spin-spin structure factor (SSF). Select ssf_perp to project intensities onto the space perpendicular to the momentum transfer $𝐪$, which is appropriate for an unpolarized neutron beam.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
SpinWaveTheory [Dipole mode]
   1 atoms
 

Define a path from $[0,0,0]$ to $[1,0,0]$ in reciprocal lattice units (RLU) containing 400 sampled $𝐪$-points.

qs = [[0,0,0], [1,0,0]]
 path = q_space_path(cryst, qs, 400)
QPath (400 samples)
   [0, 0, 0] → [1, 0, 0]
 

Calculate and plot the intensities along this path.

res = intensities_bands(swt, path)
-plot_intensities(res; units)
Example block output

Perform a powder average over the intensities for 200 radii between 0 and 2.5 inverse Å. Each radial distance defines a spherical shell in recripocal space, which will be sampled approximately uniformly, involving 1000 sample points. Measure intensities for 200 energy values between 0 and 5 meV. Gaussian line-broadening is applied with a full-width at half-maximum (FWHM) of 0.1 meV. With the above parameters, this calculation takes about a second on a modern laptop. To decrease stochastic error, one can increase the number of sample points on each spherical shell.

radii = range(0, 2.5, 200) # 1/Å
+plot_intensities(res; units)
Example block output

Perform a powder average over the intensities for 200 radii between 0 and 2.5 inverse Å. Each radial distance defines a spherical shell in recripocal space, which will be sampled approximately uniformly, involving 1000 sample points. Measure intensities for 200 energy values between 0 and 5 meV. Gaussian line-broadening is applied with a full-width at half-maximum (FWHM) of 0.1 meV. With the above parameters, this calculation takes about a second on a modern laptop. To decrease stochastic error, one can increase the number of sample points on each spherical shell.

radii = range(0, 2.5, 200) # 1/Å
 energies = range(0, 5, 200) # meV
 kernel = gaussian(fwhm=0.1)
 res = powder_average(cryst, radii, 1000) do qs
     intensities(swt, qs; energies, kernel)
 end
-plot_intensities(res; units)
Example block output +plot_intensities(res; units)Example block output diff --git a/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-207031a2.png b/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-207031a2.png new file mode 100644 index 000000000..2e947865b Binary files /dev/null and b/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-207031a2.png differ diff --git a/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-4603a611.png b/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-4603a611.png deleted file mode 100644 index 8d97d0726..000000000 Binary files a/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-4603a611.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-956b265a.png b/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-956b265a.png new file mode 100644 index 000000000..49d1bb03d Binary files /dev/null and b/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-956b265a.png differ diff --git a/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-f4399e9c.png b/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-f4399e9c.png deleted file mode 100644 index 0a89a8bb1..000000000 Binary files a/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain-f4399e9c.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain.html b/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain.html index ee771875e..058325f85 100644 --- a/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain.html +++ b/previews/PR318/examples/spinw/SW02_AFM_Heisenberg_chain.html @@ -9,10 +9,10 @@ set_exchange!(sys, J, Bond(1, 1, [1, 0, 0])) randomize_spins!(sys) minimize_energy!(sys) -plot_spins(sys; ndims=2, ghost_radius=8)Example block output

Perform a SpinWaveTheory calculation for a path between $[0,0,0]$ and $[1,0,0]$ in RLU.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
+plot_spins(sys; ndims=2, ghost_radius=8)
Example block output

Perform a SpinWaveTheory calculation for a path between $[0,0,0]$ and $[1,0,0]$ in RLU.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 qs = [[0,0,0], [1,0,0]]
 path = q_space_path(cryst, qs, 401)
 res = intensities_bands(swt, path)
 plot_intensities(res; units)
Example block output

This system includes two bands that are fully degenerate in their dispersion.

isapprox(res.disp[1, :], res.disp[2, :])
true

Plot the intensities summed over the two degenerate bands using the Makie lines function.

xs = [q[1] for q in path.qs]
 ys = log10.(res.data[1, :] + res.data[2, :])
-lines(xs, ys; axis=(; xlabel="[H, 0, 0]", ylabel="Log intensity (dimensionless)"))
Example block output +lines(xs, ys; axis=(; xlabel="[H, 0, 0]", ylabel="Log intensity (dimensionless)"))Example block output diff --git a/previews/PR318/examples/spinw/SW03_Frustrated_chain-290b636d.png b/previews/PR318/examples/spinw/SW03_Frustrated_chain-290b636d.png new file mode 100644 index 000000000..93344c767 Binary files /dev/null and b/previews/PR318/examples/spinw/SW03_Frustrated_chain-290b636d.png differ diff --git a/previews/PR318/examples/spinw/SW03_Frustrated_chain-3f7d75ab.png b/previews/PR318/examples/spinw/SW03_Frustrated_chain-3f7d75ab.png deleted file mode 100644 index 6a7567764..000000000 Binary files a/previews/PR318/examples/spinw/SW03_Frustrated_chain-3f7d75ab.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW03_Frustrated_chain.html b/previews/PR318/examples/spinw/SW03_Frustrated_chain.html index b9d9c11a2..0088a0ecb 100644 --- a/previews/PR318/examples/spinw/SW03_Frustrated_chain.html +++ b/previews/PR318/examples/spinw/SW03_Frustrated_chain.html @@ -9,12 +9,12 @@ set_exchange!(sys, J2, Bond(1, 1, [2, 0, 0]))

Assuming a spiral order, optimize the propagation wavevector $𝐤$ starting from a random initial guess. Because all interactions are isotropic in spin space, the polarization axis is arbitrary.

axis = [0, 0, 1]
 randomize_spins!(sys)
 k = minimize_spiral_energy!(sys, axis; k_guess=randn(3))
3-element StaticArraysCore.SVector{3, Float64} with indices SOneTo(3):
- 0.7699465438357583
- 0.9101404601168145
- 0.28124254506503327

The first component of the order wavevector $𝐤$ has a unique value up to reflection symmetry, $𝐤 → -𝐤$. The second and third components of $𝐤$ are arbitrary for this 1D chain system. In all cases, the minimized energy has a precise value of -33/16 in units of $|J₁|$.

@assert k[1] ≈ 0.2300534561 || k[1] ≈ 1 - 0.2300534561
+ 0.7699465438431946
+ 0.3414764709000855
+ 0.6981216190209888

The first component of the order wavevector $𝐤$ has a unique value up to reflection symmetry, $𝐤 → -𝐤$. The second and third components of $𝐤$ are arbitrary for this 1D chain system. In all cases, the minimized energy has a precise value of -33/16 in units of $|J₁|$.

@assert k[1] ≈ 0.2300534561 || k[1] ≈ 1 - 0.2300534561
 @assert spiral_energy_per_site(sys; k, axis) ≈ -33/16 * abs(J1)

To view part of the incommensurate spiral spin structure, one can construct an enlarged system with repeat_periodically_as_spiral.

sys_enlarged = repeat_periodically_as_spiral(sys, (8, 1, 1); k, axis)
-plot_spins(sys_enlarged; ndims=2)
Example block output

Use SpinWaveTheorySpiral on the original sys to calculate the dispersion and intensities for the incommensurate ordering wavevector.

swt = SpinWaveTheorySpiral(sys; measure=ssf_perp(sys), k, axis)
+plot_spins(sys_enlarged; ndims=2)
Example block output

Use SpinWaveTheorySpiral on the original sys to calculate the dispersion and intensities for the incommensurate ordering wavevector.

swt = SpinWaveTheorySpiral(sys; measure=ssf_perp(sys), k, axis)
 qs = [[0,0,0], [1,0,0]]
 path = q_space_path(cryst, qs, 401)
 res = intensities_bands(swt, path)
-plot_intensities(res; units)
Example block output +plot_intensities(res; units)Example block output diff --git a/previews/PR318/examples/spinw/SW04_Frustrated_square-65b5b86e.png b/previews/PR318/examples/spinw/SW04_Frustrated_square-65b5b86e.png deleted file mode 100644 index bac66bdfe..000000000 Binary files a/previews/PR318/examples/spinw/SW04_Frustrated_square-65b5b86e.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW04_Frustrated_square-7117a55f.png b/previews/PR318/examples/spinw/SW04_Frustrated_square-7117a55f.png deleted file mode 100644 index 279eaa534..000000000 Binary files a/previews/PR318/examples/spinw/SW04_Frustrated_square-7117a55f.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW04_Frustrated_square-b9400471.png b/previews/PR318/examples/spinw/SW04_Frustrated_square-b9400471.png new file mode 100644 index 000000000..9d78322aa Binary files /dev/null and b/previews/PR318/examples/spinw/SW04_Frustrated_square-b9400471.png differ diff --git a/previews/PR318/examples/spinw/SW04_Frustrated_square-c5795ef3.png b/previews/PR318/examples/spinw/SW04_Frustrated_square-c5795ef3.png new file mode 100644 index 000000000..612c89b54 Binary files /dev/null and b/previews/PR318/examples/spinw/SW04_Frustrated_square-c5795ef3.png differ diff --git a/previews/PR318/examples/spinw/SW04_Frustrated_square.html b/previews/PR318/examples/spinw/SW04_Frustrated_square.html index 2d87cc253..a4f01a9d2 100644 --- a/previews/PR318/examples/spinw/SW04_Frustrated_square.html +++ b/previews/PR318/examples/spinw/SW04_Frustrated_square.html @@ -9,8 +9,8 @@ set_exchange!(sys, J2, Bond(1, 1, [1, 1, 0])) randomize_spins!(sys) minimize_energy!(sys) -plot_spins(sys)Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
+plot_spins(sys)
Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 qs = [[0, 0, 0], [1/2, 0, 0], [1/2, 1/2, 0], [0, 0, 0]]
 path = q_space_path(cryst, qs, 400)
 res = intensities_bands(swt, path)
-plot_intensities(res; units)
Example block output +plot_intensities(res; units)Example block output diff --git a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-05d38520.png b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-05d38520.png deleted file mode 100644 index fd1058396..000000000 Binary files a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-05d38520.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-1c18c713.png b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-1c18c713.png deleted file mode 100644 index 02b3fd963..000000000 Binary files a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-1c18c713.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-2112605a.png b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-2112605a.png new file mode 100644 index 000000000..9e5844128 Binary files /dev/null and b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-2112605a.png differ diff --git a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-526ba3bc.png b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-526ba3bc.png new file mode 100644 index 000000000..983896406 Binary files /dev/null and b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-526ba3bc.png differ diff --git a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-c5025df6.png b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-c5025df6.png new file mode 100644 index 000000000..90a728484 Binary files /dev/null and b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-c5025df6.png differ diff --git a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-ea03dffc.png b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-ea03dffc.png deleted file mode 100644 index eb19107ee..000000000 Binary files a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM-ea03dffc.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM.html b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM.html index 440f3ed05..fc719b020 100644 --- a/previews/PR318/examples/spinw/SW05_Simple_kagome_FM.html +++ b/previews/PR318/examples/spinw/SW05_Simple_kagome_FM.html @@ -25,11 +25,11 @@ minimize_energy!(sys) energy_per_site(sys) @assert energy_per_site(sys) ≈ 4J/2 -plot_spins(sys; ndims=2)Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
+plot_spins(sys; ndims=2)
Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 qs = [[-1/2, 0, 0], [0, 0, 0], [1/2, 1/2, 0]]
 path = q_space_path(cryst, qs, 400)
 res = intensities_bands(swt, path)
-plot_intensities(res; units)
Example block output

Calculate and plot the powder average with two different magnitudes of Gaussian line-broadening. Pick an explicit intensity colorrange (as a density in meV) so that the two color scales are consistent.

radii = range(0, 2.5, 200)
+plot_intensities(res; units)
Example block output

Calculate and plot the powder average with two different magnitudes of Gaussian line-broadening. Pick an explicit intensity colorrange (as a density in meV) so that the two color scales are consistent.

radii = range(0, 2.5, 200)
 energies = range(0, 6.5, 200)
 res1 = powder_average(cryst, radii, 1000) do qs
     intensities(swt, qs; energies, kernel=gaussian(fwhm=0.02))
@@ -41,4 +41,4 @@
 fig = Figure(size=(768, 800))
 plot_intensities!(fig[1, 1], res1; units, colorrange=(0,10), title="FWHM 0.02 meV")
 plot_intensities!(fig[2, 1], res2; units, colorrange=(0,10), title="FWHM 0.25 meV")
-fig
Example block output +figExample block output diff --git a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-485bea61.png b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-485bea61.png new file mode 100644 index 000000000..725c4c331 Binary files /dev/null and b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-485bea61.png differ diff --git a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-5896106d.png b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-5896106d.png deleted file mode 100644 index ea6f5584a..000000000 Binary files a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-5896106d.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-7d2ea7dc.png b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-7d2ea7dc.png deleted file mode 100644 index 238582b69..000000000 Binary files a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-7d2ea7dc.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-e56cf449.png b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-e56cf449.png deleted file mode 100644 index e81d1fc0b..000000000 Binary files a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-e56cf449.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-e90c8452.png b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-e90c8452.png new file mode 100644 index 000000000..38b7c1ba1 Binary files /dev/null and b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-e90c8452.png differ diff --git a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-ef426e6e.png b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-ef426e6e.png new file mode 100644 index 000000000..45e14b574 Binary files /dev/null and b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM-ef426e6e.png differ diff --git a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM.html b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM.html index eeb2e9035..783b5e42f 100644 --- a/previews/PR318/examples/spinw/SW06_Complex_kagome_FM.html +++ b/previews/PR318/examples/spinw/SW06_Complex_kagome_FM.html @@ -12,14 +12,14 @@ set_exchange!(sys, J3a, Bond(2, 2, [1, 0, 0])) set_exchange!(sys, J3b, Bond(1, 1, [1, 0, 0]))

Interactively visualize the specified interactions. Red (blue) color indicates FM (AFM).

view_crystal(sys; ndims=2)
Example block output

Energy minimization favors ferromagnetic order.

randomize_spins!(sys)
 minimize_energy!(sys)
-plot_spins(sys; ndims=2)
Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
+plot_spins(sys; ndims=2)
Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 qs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]
 path = q_space_path(cryst, qs, 400)
 res = intensities_bands(swt, path)
-plot_intensities(res; units)
Example block output

Calculate and plot the powder averaged spectrum. Select an empirical colorrange that brings the lower-intensity features into focus.

radii = range(0, 2.5, 200)
+plot_intensities(res; units)
Example block output

Calculate and plot the powder averaged spectrum. Select an empirical colorrange that brings the lower-intensity features into focus.

radii = range(0, 2.5, 200)
 energies = range(0, 6.5, 200)
 kernel = gaussian(fwhm=0.02)
 res = powder_average(cryst, radii, 1000) do qs
     intensities(swt, qs; energies, kernel)
 end
-plot_intensities(res; units, colorrange=(0,10))
Example block output +plot_intensities(res; units, colorrange=(0,10))Example block output diff --git a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-0831315a.png b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-0831315a.png new file mode 100644 index 000000000..0cbe073f0 Binary files /dev/null and b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-0831315a.png differ diff --git a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-10161745.png b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-10161745.png new file mode 100644 index 000000000..da752f565 Binary files /dev/null and b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-10161745.png differ diff --git a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-1e464c9b.png b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-1e464c9b.png new file mode 100644 index 000000000..a7269f886 Binary files /dev/null and b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-1e464c9b.png differ diff --git a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-246c3892.png b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-246c3892.png deleted file mode 100644 index 27228bee4..000000000 Binary files a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-246c3892.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-75abaeb7.png b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-75abaeb7.png deleted file mode 100644 index eb3ee2382..000000000 Binary files a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-75abaeb7.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-f082b5e7.png b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-f082b5e7.png deleted file mode 100644 index fdfc5281f..000000000 Binary files a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM-f082b5e7.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM.html b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM.html index 2c601b575..fe99a09ab 100644 --- a/previews/PR318/examples/spinw/SW07_k0_kagome_AFM.html +++ b/previews/PR318/examples/spinw/SW07_k0_kagome_AFM.html @@ -9,14 +9,14 @@ set_exchange!(sys, J2, Bond(2, 1, [0, 0, 0])) randomize_spins!(sys) minimize_energy!(sys) -plot_spins(sys; ndims=2)Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
+plot_spins(sys; ndims=2)
Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 qs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]
 path = q_space_path(cryst, qs, 400)
 res = intensities_bands(swt, path)
-plot_intensities(res; units)
Example block output

Calculate and plot the powder averaged spectrum

radii = range(0, 2.5, 200)
+plot_intensities(res; units)
Example block output

Calculate and plot the powder averaged spectrum

radii = range(0, 2.5, 200)
 energies = range(0, 2.5, 200)
 kernel = gaussian(fwhm=0.02)
 res = powder_average(cryst, radii, 1000) do qs
     intensities(swt, qs; energies, kernel)
 end
-plot_intensities(res; units)
Example block output +plot_intensities(res; units)Example block output diff --git a/previews/PR318/examples/spinw/SW08_sqrt3_kagome_AFM.html b/previews/PR318/examples/spinw/SW08_sqrt3_kagome_AFM.html index d1639210b..14e619b7f 100644 --- a/previews/PR318/examples/spinw/SW08_sqrt3_kagome_AFM.html +++ b/previews/PR318/examples/spinw/SW08_sqrt3_kagome_AFM.html @@ -27,4 +27,4 @@ res = powder_average(cryst, radii, 200) do qs intensities(swt, qs; energies, kernel) end -plot_intensities(res; units, colorrange=(0,20))Example block output +plot_intensities(res; units, colorrange=(0,20))Example block output diff --git a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-36680164.png b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-36680164.png new file mode 100644 index 000000000..432c551d5 Binary files /dev/null and b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-36680164.png differ diff --git a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-4c40e0ff.png b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-4c40e0ff.png deleted file mode 100644 index 926f188c9..000000000 Binary files a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-4c40e0ff.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-94f06cff.png b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-94f06cff.png new file mode 100644 index 000000000..7c67bdaa8 Binary files /dev/null and b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-94f06cff.png differ diff --git a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-958ec5ba.png b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-958ec5ba.png deleted file mode 100644 index a65fb0e03..000000000 Binary files a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-958ec5ba.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-c34d467c.png b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-c34d467c.png new file mode 100644 index 000000000..ed7164801 Binary files /dev/null and b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-c34d467c.png differ diff --git a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-de519d75.png b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-de519d75.png deleted file mode 100644 index f35ed0fe5..000000000 Binary files a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM-de519d75.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM.html b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM.html index c77b44186..35ded3a9c 100644 --- a/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM.html +++ b/previews/PR318/examples/spinw/SW09_k0_kagome_AFM_DM.html @@ -9,14 +9,14 @@ 0.0 -0.0 1.0

As in in Tutorial 7, energy minimization determines a $𝐤 = 0$ magnetic order with 120° rotation between the three sublattices.

set_exchange!(sys, J, Bond(2, 3, [0, 0, 0]))
 randomize_spins!(sys)
 minimize_energy!(sys)
-plot_spins(sys; ndims=2)
Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
+plot_spins(sys; ndims=2)
Example block output

Calculate and plot intensities for a path through $𝐪$-space.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 qs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]
 path = q_space_path(cryst, qs, 400)
 res = intensities_bands(swt, path)
-plot_intensities(res; units)
Example block output

Calculate and plot the powder averaged spectrum. Because the intensities are dominated by a flat band at about 0.97 meV, select an empirical colorrange that brings the lower-intensity features into focus.

radii = range(0, 2.5, 200)
+plot_intensities(res; units)
Example block output

Calculate and plot the powder averaged spectrum. Because the intensities are dominated by a flat band at about 0.97 meV, select an empirical colorrange that brings the lower-intensity features into focus.

radii = range(0, 2.5, 200)
 energies = range(0, 2.5, 200)
 kernel = gaussian(fwhm=0.02)
 res = powder_average(cryst, radii, 1000) do qs
     intensities(swt, qs; energies, kernel)
 end
-plot_intensities(res; units, colorrange=(0,20))
Example block output +plot_intensities(res; units, colorrange=(0,20))Example block output diff --git a/previews/PR318/examples/spinw/SW10_Energy_cut-3d810752.png b/previews/PR318/examples/spinw/SW10_Energy_cut-3d810752.png new file mode 100644 index 000000000..e9aeffebe Binary files /dev/null and b/previews/PR318/examples/spinw/SW10_Energy_cut-3d810752.png differ diff --git a/previews/PR318/examples/spinw/SW10_Energy_cut-56128a6b.png b/previews/PR318/examples/spinw/SW10_Energy_cut-56128a6b.png deleted file mode 100644 index db2f97732..000000000 Binary files a/previews/PR318/examples/spinw/SW10_Energy_cut-56128a6b.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW10_Energy_cut-5a867675.png b/previews/PR318/examples/spinw/SW10_Energy_cut-5a867675.png new file mode 100644 index 000000000..a07c292d8 Binary files /dev/null and b/previews/PR318/examples/spinw/SW10_Energy_cut-5a867675.png differ diff --git a/previews/PR318/examples/spinw/SW10_Energy_cut-984ef9c8.png b/previews/PR318/examples/spinw/SW10_Energy_cut-984ef9c8.png new file mode 100644 index 000000000..984396afe Binary files /dev/null and b/previews/PR318/examples/spinw/SW10_Energy_cut-984ef9c8.png differ diff --git a/previews/PR318/examples/spinw/SW10_Energy_cut-b9531180.png b/previews/PR318/examples/spinw/SW10_Energy_cut-b9531180.png deleted file mode 100644 index dcb5d2ebd..000000000 Binary files a/previews/PR318/examples/spinw/SW10_Energy_cut-b9531180.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW10_Energy_cut-e282bac5.png b/previews/PR318/examples/spinw/SW10_Energy_cut-e282bac5.png deleted file mode 100644 index eefad775d..000000000 Binary files a/previews/PR318/examples/spinw/SW10_Energy_cut-e282bac5.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW10_Energy_cut.html b/previews/PR318/examples/spinw/SW10_Energy_cut.html index eefc4767a..f107b2959 100644 --- a/previews/PR318/examples/spinw/SW10_Energy_cut.html +++ b/previews/PR318/examples/spinw/SW10_Energy_cut.html @@ -11,7 +11,7 @@ set_exchange!(sys, 1.0, Bond(1, 1, [1, 0, 0])) randomize_spins!(sys) minimize_energy!(sys) -plot_spins(sys; ndims=2)Example block output

Define a 2D slice through $𝐪$-space with q_space_grid.

grid = q_space_grid(cryst, [1, 0, 0], range(0, 2, 201), [0, 1, 0], range(0, 2, 201))
Sunny.QGrid{2} (201×201 samples)

Calculate and plot a constant energy cut at the precise value of 3.75 meV. Apply a line broadening with a full-width half-max of 0.2 meV to approximately capture intensities between 3.5 and 4.0 meV.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
+plot_spins(sys; ndims=2)
Example block output

Define a 2D slice through $𝐪$-space with q_space_grid.

grid = q_space_grid(cryst, [1, 0, 0], range(0, 2, 201), [0, 1, 0], range(0, 2, 201))
Sunny.QGrid{2} (201×201 samples)

Calculate and plot a constant energy cut at the precise value of 3.75 meV. Apply a line broadening with a full-width half-max of 0.2 meV to approximately capture intensities between 3.5 and 4.0 meV.

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 res = intensities(swt, grid; energies=[3.75], kernel=gaussian(fwhm=0.2))
-plot_intensities(res; units)
Example block output

Integrate intensities between 3.5 and 4 meV using intensities_static with the bounds option.

res = intensities_static(swt, grid; bounds=(3.5, 4.01))
-plot_intensities(res; units)
Example block output +plot_intensities(res; units)Example block output

Integrate intensities between 3.5 and 4 meV using intensities_static with the bounds option.

res = intensities_static(swt, grid; bounds=(3.5, 4.01))
+plot_intensities(res; units)
Example block output diff --git a/previews/PR318/examples/spinw/SW11_La2CuO4-2b92fd75.png b/previews/PR318/examples/spinw/SW11_La2CuO4-2b92fd75.png new file mode 100644 index 000000000..f075263e7 Binary files /dev/null and b/previews/PR318/examples/spinw/SW11_La2CuO4-2b92fd75.png differ diff --git a/previews/PR318/examples/spinw/SW11_La2CuO4-3549f3ac.png b/previews/PR318/examples/spinw/SW11_La2CuO4-3549f3ac.png deleted file mode 100644 index c4d447944..000000000 Binary files a/previews/PR318/examples/spinw/SW11_La2CuO4-3549f3ac.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW11_La2CuO4-ae7a08e1.png b/previews/PR318/examples/spinw/SW11_La2CuO4-ae7a08e1.png deleted file mode 100644 index d46bd7e75..000000000 Binary files a/previews/PR318/examples/spinw/SW11_La2CuO4-ae7a08e1.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW11_La2CuO4-c3b22367.png b/previews/PR318/examples/spinw/SW11_La2CuO4-c3b22367.png new file mode 100644 index 000000000..127517f95 Binary files /dev/null and b/previews/PR318/examples/spinw/SW11_La2CuO4-c3b22367.png differ diff --git a/previews/PR318/examples/spinw/SW11_La2CuO4-d987828a.png b/previews/PR318/examples/spinw/SW11_La2CuO4-d987828a.png deleted file mode 100644 index 9cede2f6d..000000000 Binary files a/previews/PR318/examples/spinw/SW11_La2CuO4-d987828a.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW11_La2CuO4-f41e3a91.png b/previews/PR318/examples/spinw/SW11_La2CuO4-f41e3a91.png new file mode 100644 index 000000000..3833ec486 Binary files /dev/null and b/previews/PR318/examples/spinw/SW11_La2CuO4-f41e3a91.png differ diff --git a/previews/PR318/examples/spinw/SW11_La2CuO4.html b/previews/PR318/examples/spinw/SW11_La2CuO4.html index d526606b9..6643cf143 100644 --- a/previews/PR318/examples/spinw/SW11_La2CuO4.html +++ b/previews/PR318/examples/spinw/SW11_La2CuO4.html @@ -13,12 +13,12 @@ set_exchange!(sys, Jp-Jc/4, Bond(1, 1, [1, 1, 0])) set_exchange!(sys, Jpp, Bond(1, 1, [2, 0, 0]))

Energy minimization yields the expected Néel order

randomize_spins!(sys)
 minimize_energy!(sys)
-plot_spins(sys; ndims=2)
Example block output

Plot the spin wave spectrum for a path through $𝐪$-space. Apply a manual "quantum correction" that adjusts energy scale by the factor 1.18.

qs = [[3/4,1/4,0], [1/2, 1/2, 0], [1/2, 0, 0], [3/4, 1/4, 0], [1,0,0], [1/2 0 0]]
+plot_spins(sys; ndims=2)
Example block output

Plot the spin wave spectrum for a path through $𝐪$-space. Apply a manual "quantum correction" that adjusts energy scale by the factor 1.18.

qs = [[3/4,1/4,0], [1/2, 1/2, 0], [1/2, 0, 0], [3/4, 1/4, 0], [1,0,0], [1/2 0 0]]
 labels = ["P", "M", "X", "P", "Γ", "X"]
 path = q_space_path(cryst, qs, 400; labels)
 energies = range(0, 320, 400)
 swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 res = intensities(swt, path; energies, kernel=gaussian(fwhm=35))
 res.energies .*= 1.18
-plot_intensities(res; units)
Example block output

Plot instantaneous itensities, integrated over ω.

res = intensities_static(swt, path)
-plot_intensities(res; colorrange=(0,20), units)
Example block output +plot_intensities(res; units)Example block output

Plot instantaneous itensities, integrated over ω.

res = intensities_static(swt, path)
+plot_intensities(res; colorrange=(0,20), units)
Example block output diff --git a/previews/PR318/examples/spinw/SW12_Triangular_easy_plane-583f01ae.png b/previews/PR318/examples/spinw/SW12_Triangular_easy_plane-583f01ae.png new file mode 100644 index 000000000..4646e6fd8 Binary files /dev/null and b/previews/PR318/examples/spinw/SW12_Triangular_easy_plane-583f01ae.png differ diff --git a/previews/PR318/examples/spinw/SW12_Triangular_easy_plane-a13f31b8.png b/previews/PR318/examples/spinw/SW12_Triangular_easy_plane-a13f31b8.png deleted file mode 100644 index 46e65f89c..000000000 Binary files a/previews/PR318/examples/spinw/SW12_Triangular_easy_plane-a13f31b8.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW12_Triangular_easy_plane.html b/previews/PR318/examples/spinw/SW12_Triangular_easy_plane.html index bc579e344..3aaea8c57 100644 --- a/previews/PR318/examples/spinw/SW12_Triangular_easy_plane.html +++ b/previews/PR318/examples/spinw/SW12_Triangular_easy_plane.html @@ -14,7 +14,7 @@ set_onsite_coupling!(sys, S -> D*S[3]^2, 1) randomize_spins!(sys) minimize_energy!(sys) -plot_spins(sys; ndims=2)Example block output

Plot the spin wave spectrum for a path through $𝐪$-space.

qs = [[0, 0, 0], [1, 1, 0]]
+plot_spins(sys; ndims=2)
Example block output

Plot the spin wave spectrum for a path through $𝐪$-space.

qs = [[0, 0, 0], [1, 1, 0]]
 path = q_space_path(cryst, qs, 400)
 swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 res = intensities_bands(swt, path)
@@ -27,6 +27,6 @@
 swt = SpinWaveTheory(sys; measure)
 res = intensities_bands(swt, path)
 res.data[7, 10]
3×3 StaticArraysCore.SMatrix{3, 3, ComplexF64, 9} with indices SOneTo(3)×SOneTo(3):
-     0.241929+0.0im          …    1.691e-16+1.07222e-16im
- -4.26819e-15-0.241929im        1.07222e-16-1.691e-16im
-    1.691e-16-1.07222e-16im     1.65716e-31+0.0im
+ 0.241929+0.0im … 3.6854e-14-1.25919e-14im + -5.19375e-11+0.241929im 1.25919e-14+3.6854e-14im + 3.6854e-14+1.25919e-14im 6.26948e-27+0.0im diff --git a/previews/PR318/examples/spinw/SW13_LiNiPO4-c99ac705.png b/previews/PR318/examples/spinw/SW13_LiNiPO4-c99ac705.png deleted file mode 100644 index cc87caa8f..000000000 Binary files a/previews/PR318/examples/spinw/SW13_LiNiPO4-c99ac705.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW13_LiNiPO4-d500c0be.png b/previews/PR318/examples/spinw/SW13_LiNiPO4-d500c0be.png new file mode 100644 index 000000000..ec825da5c Binary files /dev/null and b/previews/PR318/examples/spinw/SW13_LiNiPO4-d500c0be.png differ diff --git a/previews/PR318/examples/spinw/SW13_LiNiPO4.html b/previews/PR318/examples/spinw/SW13_LiNiPO4.html index cfd416240..68c6d9ee5 100644 --- a/previews/PR318/examples/spinw/SW13_LiNiPO4.html +++ b/previews/PR318/examples/spinw/SW13_LiNiPO4.html @@ -25,7 +25,7 @@ set_exchange!(sys, Jac, Bond(4, 2, [0, 0, 0])) set_onsite_coupling!(sys, S -> Da*S[1]^2 + Db*S[2]^2, 1)

Energy minimization yields a co-linear order along the $c$ axis.

randomize_spins!(sys)
 minimize_energy!(sys)
-plot_spins(sys; color=[S[3] for S in sys.dipoles])
Example block output

Calculate the spectrum along path [ξ, 1, 0]

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
+plot_spins(sys; color=[S[3] for S in sys.dipoles])
Example block output

Calculate the spectrum along path [ξ, 1, 0]

swt = SpinWaveTheory(sys; measure=ssf_perp(sys))
 qs = [[0, 1, 0], [2, 1, 0]]
 path = q_space_path(cryst, qs, 400)
 res = intensities_bands(swt, path)
@@ -48,4 +48,4 @@
 lines!(ax, data_sorted[end, :]; label="Lower band")
 lines!(ax, data_sorted[end-1, :]; label="Upper band")
 axislegend(ax)
-fig
Example block output +figExample block output diff --git a/previews/PR318/examples/spinw/SW14_YVO3.html b/previews/PR318/examples/spinw/SW14_YVO3.html index f2a3a844b..a4e4aaa51 100644 --- a/previews/PR318/examples/spinw/SW14_YVO3.html +++ b/previews/PR318/examples/spinw/SW14_YVO3.html @@ -36,4 +36,4 @@ qs = [[0.75, 0.75, 0], [0.5, 0.5, 0], [0.5, 0.5, 1]] path = q_space_path(cryst, qs, 400) res = intensities_bands(swt, path) -plot_intensities(res; units)Example block output +plot_intensities(res; units)Example block output diff --git a/previews/PR318/examples/spinw/SW15_Ba3NbFe3Si2O14.html b/previews/PR318/examples/spinw/SW15_Ba3NbFe3Si2O14.html index 9e9743ca4..bd6777fbd 100644 --- a/previews/PR318/examples/spinw/SW15_Ba3NbFe3Si2O14.html +++ b/previews/PR318/examples/spinw/SW15_Ba3NbFe3Si2O14.html @@ -42,4 +42,4 @@ swt = SpinWaveTheorySpiral(sys; measure, k, axis) res = intensities(swt, path; energies, kernel=gaussian(fwhm=0.25)) plot_intensities(res; units, saturation=0.8, allpositive=false, - title="Im[S²³(q, ω) - S³²(q, ω)]")Example block output + title="Im[S²³(q, ω) - S³²(q, ω)]")Example block output diff --git a/previews/PR318/examples/spinw/SW18_Distorted_kagome-2360f54f.png b/previews/PR318/examples/spinw/SW18_Distorted_kagome-2360f54f.png new file mode 100644 index 000000000..8612c39f9 Binary files /dev/null and b/previews/PR318/examples/spinw/SW18_Distorted_kagome-2360f54f.png differ diff --git a/previews/PR318/examples/spinw/SW18_Distorted_kagome-29d862cc.png b/previews/PR318/examples/spinw/SW18_Distorted_kagome-29d862cc.png deleted file mode 100644 index e9946fdb1..000000000 Binary files a/previews/PR318/examples/spinw/SW18_Distorted_kagome-29d862cc.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW18_Distorted_kagome-5b0b2c97.png b/previews/PR318/examples/spinw/SW18_Distorted_kagome-5b0b2c97.png deleted file mode 100644 index d3d4d995c..000000000 Binary files a/previews/PR318/examples/spinw/SW18_Distorted_kagome-5b0b2c97.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW18_Distorted_kagome-999c535e.png b/previews/PR318/examples/spinw/SW18_Distorted_kagome-999c535e.png new file mode 100644 index 000000000..cebc7a95b Binary files /dev/null and b/previews/PR318/examples/spinw/SW18_Distorted_kagome-999c535e.png differ diff --git a/previews/PR318/examples/spinw/SW18_Distorted_kagome-b3343de1.png b/previews/PR318/examples/spinw/SW18_Distorted_kagome-b3343de1.png deleted file mode 100644 index 2281703bb..000000000 Binary files a/previews/PR318/examples/spinw/SW18_Distorted_kagome-b3343de1.png and /dev/null differ diff --git a/previews/PR318/examples/spinw/SW18_Distorted_kagome-d4983af5.png b/previews/PR318/examples/spinw/SW18_Distorted_kagome-d4983af5.png new file mode 100644 index 000000000..5d69d16a1 Binary files /dev/null and b/previews/PR318/examples/spinw/SW18_Distorted_kagome-d4983af5.png differ diff --git a/previews/PR318/examples/spinw/SW18_Distorted_kagome.html b/previews/PR318/examples/spinw/SW18_Distorted_kagome.html index 3214bb658..e4f18d848 100644 --- a/previews/PR318/examples/spinw/SW18_Distorted_kagome.html +++ b/previews/PR318/examples/spinw/SW18_Distorted_kagome.html @@ -18,7 +18,7 @@ set_exchange!(sys, Jip, Bond(3, 4, [0, 0, 1]))

Use minimize_spiral_energy! 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 invariant, and the axis vector is arbitrary. In other cases, a good axis will frequently be determined from symmetry considerations.

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

If successful, the optimization process will find one two propagation wavevectors, ±k_ref, with opposite chiralities. In this system, the spiral_energy_per_site is independent of chirality.

k_ref = [0.785902495, 0.0, 0.107048756]
+plot_spins(sys; ndims=2)
Example block output

If successful, the optimization process will find one two propagation wavevectors, ±k_ref, with opposite chiralities. In this system, the spiral_energy_per_site is independent of chirality.

k_ref = [0.785902495, 0.0, 0.107048756]
 k_ref_alt = [1, 0, 1] - k_ref
 @assert isapprox(k, k_ref; atol=1e-6) || isapprox(k, k_ref_alt; atol=1e-6)
 @assert spiral_energy_per_site(sys; k, axis) ≈ -0.78338383838

Check the energy with a real-space calculation using a large magnetic cell. First, we must determine a lattice size for which k becomes approximately commensurate.

suggest_magnetic_supercell([k_ref]; tol=1e-3)
Possible magnetic supercell in multiples of lattice vectors:
@@ -32,13 +32,13 @@
 randomize_spins!(sys2)
 minimize_energy!(sys2)
 energy_per_site(sys2)
-0.7791966901275341

Return to the original system (with a single chemical cell) and construct SpinWaveTheorySpiral for calculations on the incommensurate spiral phase.

measure = ssf_perp(sys; apply_g=false)
-swt = SpinWaveTheorySpiral(sys; measure, k, axis)
SpinWaveTheorySpiral(SpinWaveTheory(System([Dipole mode], Supercell (1×1×1)×6, Energy per site -0.3888), Sunny.SWTDataDipole(StaticArraysCore.SMatrix{3, 3, Float64, 9}[[0.8968983843028492 -0.35071995445604603 0.2693859717603873; -0.25088653597495814 0.09810579925659128 0.9630322934454023; -0.36418296816493934 -0.93132742131786 1.8373203908465183e-8], [0.9027848049999712 0.18286415476860296 0.3892817703950808; 0.38153350112659895 0.07728184961563786 -0.9211187237474143; -0.1985240120973871 0.9800960241837278 7.833586940803396e-8], [-0.014876621288285569 -0.06173834232498639 0.9979814944306372; 0.23378180848155808 0.9702129298505233 0.06350540743870992; -0.9721752682320906 0.23425466449534618 -1.890049953710513e-7], [0.22148266117793686 -0.6338628832310932 -0.7410555148296954; -0.24444443501134472 0.6995785833282517 -0.6714437608172565; 0.9440298453913011 0.32986004761171417 2.7197254565697346e-7], [-0.026845590971341052 -0.05755214417118523 0.9979814952927226; 0.4218733030521342 0.9044279855901285 0.0635053938911106; -0.9062572650286903 0.42272658963292337 -1.906049559794962e-7], [0.09113858298770851 -0.6652296222758068 -0.7410555366082762; -0.10058701925990927 0.7341972213882586 -0.6714437367808024; 0.9907451792703306 0.13573499825965332 2.295627200056842e-7]], StaticArraysCore.SVector{3, Float64}[[0.8968983843028492, -0.35071995445604603, 0.2693859717603873] [0.9027848049999712, 0.18286415476860296, 0.3892817703950808] … [-0.026845590971341052, -0.05755214417118523, 0.9979814952927226] [0.09113858298770851, -0.6652296222758068, -0.7410555366082762]; [-0.25088653597495814, 0.09810579925659128, 0.9630322934454023] [0.38153350112659895, 0.07728184961563786, -0.9211187237474143] … [0.4218733030521342, 0.9044279855901285, 0.0635053938911106] [-0.10058701925990927, 0.7341972213882586, -0.6714437367808024]; [-0.36418296816493934, -0.93132742131786, 1.8373203908465183e-8] [-0.1985240120973871, 0.9800960241837278, 7.833586940803396e-8] … [-0.9062572650286903, 0.42272658963292337, -1.906049559794962e-7] [0.9907451792703306, 0.13573499825965332, 2.295627200056842e-7]], Sunny.StevensExpansion[Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])], [0.7071067811865476, 0.7071067811865476, 0.7071067811865476, 0.7071067811865476, 0.7071067811865476, 0.7071067811865476]), MeasureSpec, 1.0e-8), [0.21409749868478137, -5.436203347585388e-9, 0.8929510740121326], [0.0, 0.0, 1.0])

Plot intensities for a path through $𝐪$-space.

qs = [[0,0,0], [1,0,0]]
+swt = SpinWaveTheorySpiral(sys; measure, k, axis)
SpinWaveTheorySpiral(SpinWaveTheory(System([Dipole mode], Supercell (1×1×1)×6, Energy per site -0.3888), Sunny.SWTDataDipole(StaticArraysCore.SMatrix{3, 3, Float64, 9}[[0.9849191345726432 -0.16138247642378048 0.06236982167686704; -0.06154905910649131 0.010085037387629217 0.9980531074767495; -0.1616972840705183 -0.9868404067143879 6.7157973128764024e-9], [0.7515485268333584 0.3268223254492507 0.5730287771155591; 0.5254916559368717 0.22851804949123292 -0.8195352467084298; -0.39878983356566844 0.917042348337669 -1.547497402273125e-9], [-0.007060590161184406 -0.27038943800519494 0.9627251424377627; 0.025130769633222614 0.9623970824454179 0.2704816077262729; -0.9996592381828007 0.02610378355300835 3.306298407449658e-9], [0.4216719602731813 -0.6931968977019013 -0.5845261490607868; -0.3037785547039683 0.49938903536001017 -0.811374870860669; 0.854348493076064 0.5197005410605795 1.7700304057490664e-9], [-0.0606379438160836 -0.2635969295188059 0.9627251417294634; 0.21582860719483027 0.938220502245797 0.27048161024732315; -0.9745465879505698 0.22418507513637653 -3.9434006558445435e-9], [0.27554963444993036 -0.7631523972147293 -0.5845261479009489; -0.19850992099794643 0.5497859845842845 -0.8113748716962327; 0.9405669621137556 0.33960828873880733 4.997405217591831e-9]], StaticArraysCore.SVector{3, Float64}[[0.9849191345726432, -0.16138247642378048, 0.06236982167686704] [0.7515485268333584, 0.3268223254492507, 0.5730287771155591] … [-0.0606379438160836, -0.2635969295188059, 0.9627251417294634] [0.27554963444993036, -0.7631523972147293, -0.5845261479009489]; [-0.06154905910649131, 0.010085037387629217, 0.9980531074767495] [0.5254916559368717, 0.22851804949123292, -0.8195352467084298] … [0.21582860719483027, 0.938220502245797, 0.27048161024732315] [-0.19850992099794643, 0.5497859845842845, -0.8113748716962327]; [-0.1616972840705183, -0.9868404067143879, 6.7157973128764024e-9] [-0.39878983356566844, 0.917042348337669, -1.547497402273125e-9] … [-0.9745465879505698, 0.22418507513637653, -3.9434006558445435e-9] [0.9405669621137556, 0.33960828873880733, 4.997405217591831e-9]], Sunny.StevensExpansion[Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]), Sunny.StevensExpansion(0, [0.0], [0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0])], [0.7071067811865476, 0.7071067811865476, 0.7071067811865476, 0.7071067811865476, 0.7071067811865476, 0.7071067811865476]), MeasureSpec, 1.0e-8), [0.21409750577191924, 5.436729343811647e-10, 0.892951245512463], [0.0, 0.0, 1.0])

Plot intensities for a path through $𝐪$-space.

qs = [[0,0,0], [1,0,0]]
 path = q_space_path(cryst, qs, 400)
 res = intensities_bands(swt, path)
-plot_intensities(res; units)
Example block output

Plot the powder-averaged intensities

radii = range(0, 2, 100) # (1/Å)
+plot_intensities(res; units)
Example block output

Plot the powder-averaged intensities

radii = range(0, 2, 100) # (1/Å)
 energies = range(0, 6, 200)
 kernel = gaussian(fwhm=0.05)
 res = powder_average(cryst, radii, 400) do qs
     intensities(swt, qs; energies, kernel)
 end
-plot_intensities(res; units)
Example block output +plot_intensities(res; units)Example block output diff --git a/previews/PR318/examples/spinw/SW19_Different_Ions.html b/previews/PR318/examples/spinw/SW19_Different_Ions.html index c78a14df5..1a526f017 100644 --- a/previews/PR318/examples/spinw/SW19_Different_Ions.html +++ b/previews/PR318/examples/spinw/SW19_Different_Ions.html @@ -41,4 +41,4 @@ -0.1369821596259615 -0.1369821596261806 -0.5783052943233933 - -0.5783052943242701 + -0.5783052943242701 diff --git a/previews/PR318/index.html b/previews/PR318/index.html index da8054470..76b5df648 100644 --- a/previews/PR318/index.html +++ b/previews/PR318/index.html @@ -1,2 +1,2 @@ -Overview · Sunny documentation

Overview

Sunny is a Julia package for modeling atomic-scale magnetism. It provides powerful tools to study equilibrium and non-equilibrium magnetic phenomena. In particular, it allows estimation of dynamical structure factor intensities, $\mathcal{S}(𝐪,ω)$, to support quantitative modeling of experimental scattering data.

Features include:

  • Generalized spin dynamics using SU(N) coherent states.
  • Ability to specify a crystal from a .cif file or its spacegroup symmetry. Magnetic structures can be read from .mcif files.
  • Interactive visualizations of the 3D crystals and magnetic ordering.
  • Symmetry analysis to classify allowed interaction terms, and to propagate them by symmetry.
  • Single-ion anisotropy at arbitrary order, which can be specified using Stevens operators or as a polynomial of spin operators.
  • Monte Carlo sampling of spin configurations in thermal equilibrium, and optimization tools.
  • Measurements of dynamical correlations. At low temperature, one can use linear spin wave theory and its multi-boson generalization. This generalizes to finite temperatures using the classical dynamics, which allows for strongly nonlinear effects.
  • Long-range dipole-dipole interactions accelerated with the fast Fourier transform (FFT).
  • Support for comparison with experimental data: form factor, dipole factor, temperature-dependent classical-to-quantum factors, etc.
+Overview · Sunny documentation

Overview

Sunny is a Julia package for modeling atomic-scale magnetism. It provides powerful tools to study equilibrium and non-equilibrium magnetic phenomena. In particular, it allows estimation of dynamical structure factor intensities, $\mathcal{S}(𝐪,ω)$, to support quantitative modeling of experimental scattering data.

Features include:

  • Generalized spin dynamics using SU(N) coherent states.
  • Ability to specify a crystal from a .cif file or its spacegroup symmetry. Magnetic structures can be read from .mcif files.
  • Interactive visualizations of the 3D crystals and magnetic ordering.
  • Symmetry analysis to classify allowed interaction terms, and to propagate them by symmetry.
  • Single-ion anisotropy at arbitrary order, which can be specified using Stevens operators or as a polynomial of spin operators.
  • Monte Carlo sampling of spin configurations in thermal equilibrium, and optimization tools.
  • Measurements of dynamical correlations. At low temperature, one can use linear spin wave theory and its multi-boson generalization. This generalizes to finite temperatures using the classical dynamics, which allows for strongly nonlinear effects.
  • Long-range dipole-dipole interactions accelerated with the fast Fourier transform (FFT).
  • Support for comparison with experimental data: form factor, dipole factor, temperature-dependent classical-to-quantum factors, etc.
diff --git a/previews/PR318/library.html b/previews/PR318/library.html index 69bacdd1c..3cf6a2c2b 100644 --- a/previews/PR318/library.html +++ b/previews/PR318/library.html @@ -1,7 +1,7 @@ -Library API · Sunny documentation

Library API

This page describes the public types and functions exported by Sunny. This documentation can be also be accessed using the Julia help system (enter ? at the Julia command prompt).

Sunny.SiteType
(cell1, cell2, cell3, i) :: Site

Four indices identifying a single site in a System. The first three indices select the unit cell and the last index selects the sublattice, i.e., the $i$th atom within the unit cell.

This object can be used to index dipoles and coherents fields of a System. A Site is also required to specify inhomogeneous interactions via functions such as set_field_at! or set_exchange_at!.

Note that the definition of a cell may change when a system is reshaped. In this case, it is convenient to construct the Site using position_to_site, which always takes a position in fractional coordinates of the original lattice vectors.

source
Sunny.BinningParametersType
BinningParameters(binstart,binend,binwidth;covectors = I(4))
+Library API · Sunny documentation

Library API

This page describes the public types and functions exported by Sunny. This documentation can be also be accessed using the Julia help system (enter ? at the Julia command prompt).

Sunny.SiteType
(cell1, cell2, cell3, i) :: Site

Four indices identifying a single site in a System. The first three indices select the unit cell and the last index selects the sublattice, i.e., the $i$th atom within the unit cell.

This object can be used to index dipoles and coherents fields of a System. A Site is also required to specify inhomogeneous interactions via functions such as set_field_at! or set_exchange_at!.

Note that the definition of a cell may change when a system is reshaped. In this case, it is convenient to construct the Site using position_to_site, which always takes a position in fractional coordinates of the original lattice vectors.

source
Sunny.BinningParametersType
BinningParameters(binstart,binend,binwidth;covectors = I(4))
 BinningParameters(binstart,binend;numbins,covectors = I(4))

Describes a 4D parallelepided histogram in a format compatible with experimental Inelasitic Neutron Scattering data. See generate_mantid_script_from_binning_parameters to convert BinningParameters to a format understandable by the Mantid software, or load_nxs to load BinningParameters from a Mantid .nxs file.

The coordinates of the histogram axes are specified by multiplication of (q,ω) with each row of the covectors matrix, with q given in [R.L.U.]. Since the default covectors matrix is the identity matrix, the default axes are (qx,qy,qz,ω) in absolute units.

The convention for the binning scheme is that:

  • The left edge of the first bin starts at binstart
  • The bin width is binwidth
  • The last bin contains binend
  • There are no "partial bins;" the last bin may contain values greater than binend.

A value can be binned by computing its bin index:

coords = covectors * value
-bin_ix = 1 .+ floor.(Int64,(coords .- binstart) ./ binwidth)
source
Sunny.BondType
Bond(i, j, n)

Represents a bond between atom indices i and j. n is a vector of three integers specifying unit cell displacement in terms of lattice vectors.

source
Sunny.CrystalType

An object describing a crystallographic unit cell and its space group symmetry. Constructors are as follows:

Crystal(filename; override_symmetry=false, symprec=nothing)

Reads the crystal from a .cif file located at the path filename. If override_symmetry=true, the spacegroup will be inferred based on atom positions and the returned unit cell may be reduced in size. For an mCIF file, the return value is the magnetic supercell, unless override_symmetry=true. If a precision for spacegroup symmetries cannot be inferred from the CIF file, it must be specified with symprec. The latvecs field of the returned Crystal will be in units of angstrom.

Crystal(latvecs, positions; types=nothing, symprec=1e-5)

Constructs a crystal from the complete list of atom positions positions, with coordinates (between 0 and 1) in units of lattice vectors latvecs. Spacegroup symmetry information is automatically inferred. The optional parameter types is a list of strings, one for each atom, and can be used to break symmetry-equivalence between atoms.

Crystal(latvecs, positions, spacegroup_number; types=nothing, setting=nothing, symprec=1e-5)

Builds a crystal by applying symmetry operators for a given international spacegroup number. For certain spacegroups, there are multiple possible unit cell settings; in this case, a warning message will be printed, and a list of crystals will be returned, one for every possible setting. Alternatively, the optional setting string will disambiguate between unit cell conventions.

Currently, crystals built using only the spacegroup number will be missing some symmetry information. It is generally preferred to build a crystal from a .cif file or from the full specification of the unit cell.

Examples

# Read a Crystal from a .cif file
+bin_ix = 1 .+ floor.(Int64,(coords .- binstart) ./ binwidth)
source
Sunny.BondType
Bond(i, j, n)

Represents a bond between atom indices i and j. n is a vector of three integers specifying unit cell displacement in terms of lattice vectors.

source
Sunny.CrystalType

An object describing a crystallographic unit cell and its space group symmetry. Constructors are as follows:

Crystal(filename; override_symmetry=false, symprec=nothing)

Reads the crystal from a .cif file located at the path filename. If override_symmetry=true, the spacegroup will be inferred based on atom positions and the returned unit cell may be reduced in size. For an mCIF file, the return value is the magnetic supercell, unless override_symmetry=true. If a precision for spacegroup symmetries cannot be inferred from the CIF file, it must be specified with symprec. The latvecs field of the returned Crystal will be in units of angstrom.

Crystal(latvecs, positions; types=nothing, symprec=1e-5)

Constructs a crystal from the complete list of atom positions positions, with coordinates (between 0 and 1) in units of lattice vectors latvecs. Spacegroup symmetry information is automatically inferred. The optional parameter types is a list of strings, one for each atom, and can be used to break symmetry-equivalence between atoms.

Crystal(latvecs, positions, spacegroup_number; types=nothing, setting=nothing, symprec=1e-5)

Builds a crystal by applying symmetry operators for a given international spacegroup number. For certain spacegroups, there are multiple possible unit cell settings; in this case, a warning message will be printed, and a list of crystals will be returned, one for every possible setting. Alternatively, the optional setting string will disambiguate between unit cell conventions.

Currently, crystals built using only the spacegroup number will be missing some symmetry information. It is generally preferred to build a crystal from a .cif file or from the full specification of the unit cell.

Examples

# Read a Crystal from a .cif file
 Crystal("filename.cif")
 
 # Build a BCC crystal in the conventional cubic unit cell by specifying both
@@ -19,7 +19,7 @@
 # atom position. This spacegroup has two possible settings ("1" or "2"), which
 # determine an overall unit cell translation.
 positions = [[1/4, 1/4, 1/4]]
-cryst = Crystal(latvecs, positions, 227; setting="1")

See also lattice_vectors.

source
Sunny.FormFactorMethod
FormFactor(ion::String; g_lande=2)

The magnetic form factor for a given magnetic ion and charge state. When passed to intensities, it rescales structure factor intensities based on the magnitude of the scattering vector, $|𝐪|$.

The parameter ion must be one of the following strings:

Am2, Am3, Am4, Am5, Am6, Am7, Au1, Au2, Au3, Au4, Au5, Ce2, Co0, Co1, Co2, Co3,
+cryst = Crystal(latvecs, positions, 227; setting="1")

See also lattice_vectors.

source
Sunny.FormFactorMethod
FormFactor(ion::String; g_lande=2)

The magnetic form factor for a given magnetic ion and charge state. When passed to intensities, it rescales structure factor intensities based on the magnitude of the scattering vector, $|𝐪|$.

The parameter ion must be one of the following strings:

Am2, Am3, Am4, Am5, Am6, Am7, Au1, Au2, Au3, Au4, Au5, Ce2, Co0, Co1, Co2, Co3,
 Co4, Cr0, Cr1, Cr2, Cr3, Cr4, Cu0, Cu1, Cu2, Cu3, Cu4, Dy2, Dy3, Er2, Er3, Eu2,
 Eu3, Fe0, Fe1, Fe2, Fe3, Fe4, Gd2, Gd3, Hf2, Hf3, Ho2, Ho3, Ir0a, Ir0b, Ir0c,
 Ir1a, Ir1b, Ir2, Ir3, Ir4, Ir5, Ir6, Mn0, Mn1, Mn2, Mn3, Mn4, Mn5, Mo0, Mo1, Nb0,
@@ -33,11 +33,11 @@
 ERROR: Disambiguate form factor according to electronic configuration:
     "Ir0a" -- 6s⁰5d⁹
     "Ir0b" -- 6s¹5d⁸
-    "Ir0c" -- 6s²5d⁷

In the dipolar approximation (small $|𝐪|$) the form factor is

$F(s) = ⟨j_0(s)⟩ + [(2-g)/g] ⟨j_2(s)⟩$,

involving $s = |𝐪|/4π$ and the Landé $g$-factor. The $⟨j_l(s)⟩$ are radial averages of the $l$th spherical Bessel function of the magnetic dipole. More details are provided in Ref. [1].

The standard approximation tables involve expansion in Gaussians,

\[⟨j_0(s)⟩ = A e^{-as^2} + B e^{-bs^2} + C e^{-cs^2} + D e^{-ds^2} + E\]

and

\[⟨j_2(s)⟩ = (A e^{-as^2} + B e^{-bs^2} + C e^{-cs^2} + D e^{-ds^2} + E) s^2.\]

For 3d, 4d, rare earth, and actinide ions, Sunny uses the revised tables of P. J. Brown, as documented in the McPhase package [2]. For 5d ions, Sunny uses the tables of Kobayashi, Nagao, Ito [3].

Two special, $𝐪$-independent form factor values are available: one(FormFactor) and zero(FormFactor). The first idealizes the magnetic ion as a perfect point particle, while the second zeros all contributions from the magnetic ion.

References:

  1. P. J. Brown, The Neutron Data Booklet, 2nd ed., Sec. 2.5 Magnetic Form Factors (2003)
  2. Coefficient tables in McPhase documentation
  3. K. Kobayashi, T. Nagao, M. Ito, Acta Cryst. A, 67 pp 473–480 (2011)
source
Sunny.LangevinType
Langevin(dt::Float64; damping::Float64, kT::Float64)

An integrator for Langevin spin dynamics using the explicit Heun method. The damping parameter controls the coupling to an implicit thermal bath. One call to the step! function will advance a System by dt units of time. Can be used to sample from the Boltzmann distribution at temperature kT. An alternative approach to sampling states from thermal equilibrium is LocalSampler, which proposes local Monte Carlo moves. For example, use LocalSampler instead of Langevin to sample Ising-like spins.

Setting damping = 0 disables coupling to the thermal bath, yielding an energy-conserving spin dynamics. The Langevin integrator uses an explicit numerical integrator which cannot prevent energy drift. Alternatively, the ImplicitMidpoint method can be used, which is more expensive but prevents energy drift through exact conservation of the symplectic 2-form.

If the System has mode = :dipole, then the dynamics is the stochastic Landau-Lifshitz equation,

\[ d𝐬/dt = -𝐬 × (ξ - 𝐁 + λ 𝐬 × 𝐁),\]

where $𝐁 = -dE/d𝐬$ is the effective field felt by the expected spin dipole $𝐬$. The components of $ξ$ are Gaussian white noise, with magnitude $√(2 k_B T λ)$ set by a fluctuation-dissipation theorem. The parameter damping sets the phenomenological coupling $λ$ to the thermal bath.

If the System has mode = :SUN, then this dynamics generalizes [1] to a stochastic nonlinear Schrödinger equation for SU(N) coherent states $𝐙$,

\[ d𝐙/dt = -i P [ζ + (1 - i λ̃) ℋ 𝐙].\]

Here, $P$ projects onto the space orthogonal to $𝐙$, and $ζ$ denotes complex Gaussian white noise with magnitude $√(2 k_B T λ̃)$. The local-Hamiltonian $ℋ$ embeds the energy gradient into the 𝔰𝔲(N) Lie algebra, and generates evolution of spin dipoles, quadrupoles, etc. The parameter damping here sets $λ̃$, which is analogous to $λ$ above.

When applied to SU(2) coherent states, the generalized spin dynamics reduces exactly to the stochastic Landau-Lifshitz equation. The mapping is as follows. Normalized coherent states $𝐙$ map to dipole expectation values $𝐬 = 𝐙^{†} Ŝ 𝐙$, where spin operators $Ŝ$ are a spin-$|𝐬|$ representation of SU(2). The local effective Hamiltonian $ℋ = -𝐁 ⋅ Ŝ$ generates rotation of the dipole in analogy to the vector cross product $S × 𝐁$. The coupling to the thermal bath maps as $λ̃ = |𝐬| λ$. Note, therefore, that the scaling of the damping parameter varies subtly between :dipole and :SUN modes.

References:

  1. D. Dahlbom et al., Phys. Rev. B 106, 235154 (2022).
source
Sunny.LocalSamplerType
LocalSampler(; kT, nsweeps=1.0, propose=propose_uniform)

Monte Carlo simulation involving Metropolis updates to individual spins. One call to the step! function will perform nsweeps of MCMC sampling for a provided System. The default value of 1.0 means that step! performs, on average, one trial update per spin.

Assuming ergodicity, the LocalSampler will sample from thermal equilibrium for the target temperature kT.

The trial spin updates are sampled using the propose function. Options include propose_uniform, propose_flip, and propose_delta. Multiple proposals can be mixed with the macro @mix_proposals.

The returned object stores fields ΔE and Δs, which represent the cumulative change to the net energy and dipole, respectively.

!!! warning "Efficiency considerations

A [`Langevin`](@ref) sampler is frequently much more efficient than a
+    "Ir0c" -- 6s²5d⁷

In the dipolar approximation (small $|𝐪|$) the form factor is

$F(s) = ⟨j_0(s)⟩ + [(2-g)/g] ⟨j_2(s)⟩$,

involving $s = |𝐪|/4π$ and the Landé $g$-factor. The $⟨j_l(s)⟩$ are radial averages of the $l$th spherical Bessel function of the magnetic dipole. More details are provided in Ref. [1].

The standard approximation tables involve expansion in Gaussians,

\[⟨j_0(s)⟩ = A e^{-as^2} + B e^{-bs^2} + C e^{-cs^2} + D e^{-ds^2} + E\]

and

\[⟨j_2(s)⟩ = (A e^{-as^2} + B e^{-bs^2} + C e^{-cs^2} + D e^{-ds^2} + E) s^2.\]

For 3d, 4d, rare earth, and actinide ions, Sunny uses the revised tables of P. J. Brown, as documented in the McPhase package [2]. For 5d ions, Sunny uses the tables of Kobayashi, Nagao, Ito [3].

Two special, $𝐪$-independent form factor values are available: one(FormFactor) and zero(FormFactor). The first idealizes the magnetic ion as a perfect point particle, while the second zeros all contributions from the magnetic ion.

References:

  1. P. J. Brown, The Neutron Data Booklet, 2nd ed., Sec. 2.5 Magnetic Form Factors (2003)
  2. Coefficient tables in McPhase documentation
  3. K. Kobayashi, T. Nagao, M. Ito, Acta Cryst. A, 67 pp 473–480 (2011)
source
Sunny.LangevinType
Langevin(dt::Float64; damping::Float64, kT::Float64)

An integrator for Langevin spin dynamics using the explicit Heun method. The damping parameter controls the coupling to an implicit thermal bath. One call to the step! function will advance a System by dt units of time. Can be used to sample from the Boltzmann distribution at temperature kT. An alternative approach to sampling states from thermal equilibrium is LocalSampler, which proposes local Monte Carlo moves. For example, use LocalSampler instead of Langevin to sample Ising-like spins.

Setting damping = 0 disables coupling to the thermal bath, yielding an energy-conserving spin dynamics. The Langevin integrator uses an explicit numerical integrator which cannot prevent energy drift. Alternatively, the ImplicitMidpoint method can be used, which is more expensive but prevents energy drift through exact conservation of the symplectic 2-form.

If the System has mode = :dipole, then the dynamics is the stochastic Landau-Lifshitz equation,

\[ d𝐬/dt = -𝐬 × (ξ - 𝐁 + λ 𝐬 × 𝐁),\]

where $𝐁 = -dE/d𝐬$ is the effective field felt by the expected spin dipole $𝐬$. The components of $ξ$ are Gaussian white noise, with magnitude $√(2 k_B T λ)$ set by a fluctuation-dissipation theorem. The parameter damping sets the phenomenological coupling $λ$ to the thermal bath.

If the System has mode = :SUN, then this dynamics generalizes [1] to a stochastic nonlinear Schrödinger equation for SU(N) coherent states $𝐙$,

\[ d𝐙/dt = -i P [ζ + (1 - i λ̃) ℋ 𝐙].\]

Here, $P$ projects onto the space orthogonal to $𝐙$, and $ζ$ denotes complex Gaussian white noise with magnitude $√(2 k_B T λ̃)$. The local-Hamiltonian $ℋ$ embeds the energy gradient into the 𝔰𝔲(N) Lie algebra, and generates evolution of spin dipoles, quadrupoles, etc. The parameter damping here sets $λ̃$, which is analogous to $λ$ above.

When applied to SU(2) coherent states, the generalized spin dynamics reduces exactly to the stochastic Landau-Lifshitz equation. The mapping is as follows. Normalized coherent states $𝐙$ map to dipole expectation values $𝐬 = 𝐙^{†} Ŝ 𝐙$, where spin operators $Ŝ$ are a spin-$|𝐬|$ representation of SU(2). The local effective Hamiltonian $ℋ = -𝐁 ⋅ Ŝ$ generates rotation of the dipole in analogy to the vector cross product $S × 𝐁$. The coupling to the thermal bath maps as $λ̃ = |𝐬| λ$. Note, therefore, that the scaling of the damping parameter varies subtly between :dipole and :SUN modes.

References:

  1. D. Dahlbom et al., Phys. Rev. B 106, 235154 (2022).
source
Sunny.LocalSamplerType
LocalSampler(; kT, nsweeps=1.0, propose=propose_uniform)

Monte Carlo simulation involving Metropolis updates to individual spins. One call to the step! function will perform nsweeps of MCMC sampling for a provided System. The default value of 1.0 means that step! performs, on average, one trial update per spin.

Assuming ergodicity, the LocalSampler will sample from thermal equilibrium for the target temperature kT.

The trial spin updates are sampled using the propose function. Options include propose_uniform, propose_flip, and propose_delta. Multiple proposals can be mixed with the macro @mix_proposals.

The returned object stores fields ΔE and Δs, which represent the cumulative change to the net energy and dipole, respectively.

!!! warning "Efficiency considerations

A [`Langevin`](@ref) sampler is frequently much more efficient than a
 `LocalSampler` for simulating Heisenberg-like spins that vary continuously. A
 `LocalSampler` is appropriate in the special case that the spin states are
 effectively discrete. E.g., [`propose_flip`](@ref) is very helpful simulating
-Ising-like spins that arise due to a strong easy-axis anisotropy.
source
Sunny.MomentType
Moment(; s, g)

Characterizes a effective spin magnetic moment on an atom. Quantum spin-s is a multiple of 1/2 in units of ħ. The g-factor or tensor defines the magnetic_moment $μ = - g 𝐒$ in units of the Bohr magneton.

Example

Moment(s=3/2, g=2)
source
Sunny.SampledCorrelationsMethod
SampledCorrelations(sys::System; measure, energies, dt)

An object to accumulate samples of dynamical pair correlations. The measure argument specifies a pair correlation type, e.g. ssf_perp. The energies must be evenly-spaced and starting from 0, e.g. energies = range(0, 3, 100). Select the integration time-step dt according to accuracy and speed considerations. suggest_timestep can help in selecting an appropriate value.

Dynamical correlations will be accumulated through calls to add_sample!, which expects a spin configuration in thermal equilibrium. A classical spin dynamics trajectory will be simulated of sufficient length to achieve the target energy resolution. The resulting data can can then be extracted as pair-correlation intensities with appropriate classical-to-quantum correction factors. See also intensities_static, which integrates over energy.

source
Sunny.SampledCorrelationsStaticType
SampledCorrelationsStatic(sys::System; measure)

An object to accumulate samples of static pair correlations. It is similar to SampledCorrelations, but no time-integration will be performed on calls to add_sample!. The resulting object can be used with intensities_static to calculate statistics from the classical Boltzmann distribution. Dynamical intensities data, however, will be unavailable. Similarly, classical-to-quantum corrections that rely on the excitation spectrum cannot be performed.

source
Sunny.SpinWaveTheoryType
SpinWaveTheory(sys::System; measure, regularization=1e-8)

Constructs an object to perform linear spin wave theory. The system must be in an energy minimizing configuration. Enables calculation of dispersion bands. If pair correlations are specified with correspec, one can also calculate intensities_bands and broadened intensities.

The spins in system must be energy-minimized, otherwise the Cholesky step of the Bogoliubov diagonalization procedure will fail. The parameter regularization adds a small positive shift to the diagonal of the dynamical matrix to avoid numerical issues with quasi-particle modes of vanishing energy. Physically, this shift can be interpreted as application of an inhomogeneous field aligned with the magnetic ordering.

source
Sunny.SpinWaveTheoryKPMType
SpinWaveTheoryKPM(sys::System; measure, regularization=1e-8, tol)

A variant of SpinWaveTheory that uses the kernel polynomial method (KPM) to perform intensities calculations [1]. Instead of explicitly diagonalizing the dynamical matrix, KPM approximates intensities using polynomial expansion truncated at order $M$. The reduces the computational cost from $𝒪(N^3)$ to $𝒪(N M)$, which is favorable for large system sizes $N$.

The polynomial order $M$ will be determined from the line broadening kernel and the specified error tolerance tol. Specifically, for each wavevector, $M$ scales like the spectral bandwidth of excitations, divided by the energy resolution of the broadening kernel, times the negative logarithm of tol.

The error tolerance tol should be tuned empirically for each calculation. Reasonable starting points are 1e-1 (more speed) or 1e-2 (more accuracy).

References:

  1. H. Lane et al., Kernel Polynomial Method for Linear Spin Wave Theory (2023) [arXiv:2312.08349v3].
source
Sunny.SpinWaveTheorySpiralType
SpinWaveTheorySpiral(sys::System; k, axis, measure, regularization=1e-8)

Analogous to SpinWaveTheory, 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 minimize_spiral_energy!. In contrast, axis will typically be determined from symmetry considerations.

The resulting object can be used to calculate the spin wave dispersion, or the structure factor via intensities_bands and intensities.

The algorithm for this calculation was developed in Toth and Lake, J. Phys.: Condens. Matter 27, 166002 (2015) and implemented in the SpinW code.

source
Sunny.SystemMethod
System(crystal::Crystal, moments, mode; dims=(1, 1, 1), seed=nothing)

A spin system is constructed from the Crystal unit cell, a specification of the spin moments symmetry-distinct sites, and a calculation mode. Interactions can be added to the system using, e.g., set_exchange!. The default supercell dimensions are 1×1×1 chemical cells, but this can be changed with dims.

Spin moments comprise a list of pairs, [i1 => Moment(...), i2 => ...], where i1, i2, ... are a complete set of symmetry-distinct atoms. Each Moment contains spin and $g$-factor information.

The two primary options for mode are :SUN and :dipole. In the former, each spin-$s$ degree of freedom is described as an SU(N) coherent state, i.e. a quantum superposition of $N = 2s + 1$ levels. This formalism can be useful to capture multipolar spin fluctuations or local entanglement effects.

Mode :dipole projects the SU(N) dynamics onto the restricted space of pure dipoles. In practice this means that Sunny will simulate Landau-Lifshitz dynamics, but single-ion anisotropy and biquadratic exchange interactions will be renormalized to improve accuracy. To disable this renormalization, use the mode :dipole_large_s which applies the $s → ∞$ classical limit. For details, see the documentation page: Interaction Renormalization.

An integer seed for the random number generator can optionally be specified to enable reproducible calculations.

All spins are initially polarized in the global $z$-direction.

source
Sunny.UnitsType
Units(energy, length)

Physical constants in units of reference energy and length scales. Possible lengths are [:angstrom, :nm]. For atomic scale modeling, it is preferable to work in units of length=:angstrom, which follows the CIF file standard. Possible energy units are [:meV, :K, :THz, :inverse_cm, :T]. Kelvin is converted to energy via the Boltzmann constant $k_B$. Similarly, hertz is converted via the Planck constant $h$, inverse cm via the speed of light $c$, and tesla (field strength) via the Bohr magneton $μ_B$. For a given Units system, one can access any of the length and energy scale symbols listed above.

Examples

# Unit system with [energy] = meV and [length] = Å
+Ising-like spins that arise due to a strong easy-axis anisotropy.
source
Sunny.MomentType
Moment(; s, g)

Characterizes a effective spin magnetic moment on an atom. Quantum spin-s is a multiple of 1/2 in units of ħ. The g-factor or tensor defines the magnetic_moment $μ = - g 𝐒$ in units of the Bohr magneton.

Example

Moment(s=3/2, g=2)
source
Sunny.SampledCorrelationsMethod
SampledCorrelations(sys::System; measure, energies, dt)

An object to accumulate samples of dynamical pair correlations. The measure argument specifies a pair correlation type, e.g. ssf_perp. The energies must be evenly-spaced and starting from 0, e.g. energies = range(0, 3, 100). Select the integration time-step dt according to accuracy and speed considerations. suggest_timestep can help in selecting an appropriate value.

Dynamical correlations will be accumulated through calls to add_sample!, which expects a spin configuration in thermal equilibrium. A classical spin dynamics trajectory will be simulated of sufficient length to achieve the target energy resolution. The resulting data can can then be extracted as pair-correlation intensities with appropriate classical-to-quantum correction factors. See also intensities_static, which integrates over energy.

source
Sunny.SampledCorrelationsStaticType
SampledCorrelationsStatic(sys::System; measure)

An object to accumulate samples of static pair correlations. It is similar to SampledCorrelations, but no time-integration will be performed on calls to add_sample!. The resulting object can be used with intensities_static to calculate statistics from the classical Boltzmann distribution. Dynamical intensities data, however, will be unavailable. Similarly, classical-to-quantum corrections that rely on the excitation spectrum cannot be performed.

source
Sunny.SpinWaveTheoryType
SpinWaveTheory(sys::System; measure, regularization=1e-8)

Constructs an object to perform linear spin wave theory. The system must be in an energy minimizing configuration. Enables calculation of dispersion bands. If pair correlations are specified with correspec, one can also calculate intensities_bands and broadened intensities.

The spins in system must be energy-minimized, otherwise the Cholesky step of the Bogoliubov diagonalization procedure will fail. The parameter regularization adds a small positive shift to the diagonal of the dynamical matrix to avoid numerical issues with quasi-particle modes of vanishing energy. Physically, this shift can be interpreted as application of an inhomogeneous field aligned with the magnetic ordering.

source
Sunny.SpinWaveTheoryKPMType
SpinWaveTheoryKPM(sys::System; measure, regularization=1e-8, tol)

A variant of SpinWaveTheory that uses the kernel polynomial method (KPM) to perform intensities calculations [1]. Instead of explicitly diagonalizing the dynamical matrix, KPM approximates intensities using polynomial expansion truncated at order $M$. The reduces the computational cost from $𝒪(N^3)$ to $𝒪(N M)$, which is favorable for large system sizes $N$.

The polynomial order $M$ will be determined from the line broadening kernel and the specified error tolerance tol. Specifically, for each wavevector, $M$ scales like the spectral bandwidth of excitations, divided by the energy resolution of the broadening kernel, times the negative logarithm of tol.

The error tolerance tol should be tuned empirically for each calculation. Reasonable starting points are 1e-1 (more speed) or 1e-2 (more accuracy).

Missing intensity at small quasi-particle energy

The KPM calculation may mask intensities at small energies $ω$. In particular, such artifacts may arise near the Goldstone modes of an ordered state with continuous symmetry.

References:

  1. H. Lane et al., Kernel Polynomial Method for Linear Spin Wave Theory (2023) [arXiv:2312.08349v3].
source
Sunny.SpinWaveTheorySpiralType
SpinWaveTheorySpiral(sys::System; k, axis, measure, regularization=1e-8)

Analogous to SpinWaveTheory, 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 minimize_spiral_energy!. In contrast, axis will typically be determined from symmetry considerations.

The resulting object can be used to calculate the spin wave dispersion, or the structure factor via intensities_bands and intensities.

The algorithm for this calculation was developed in Toth and Lake, J. Phys.: Condens. Matter 27, 166002 (2015) and implemented in the SpinW code.

source
Sunny.SystemMethod
System(crystal::Crystal, moments, mode; dims=(1, 1, 1), seed=nothing)

A spin system is constructed from the Crystal unit cell, a specification of the spin moments symmetry-distinct sites, and a calculation mode. Interactions can be added to the system using, e.g., set_exchange!. The default supercell dimensions are 1×1×1 chemical cells, but this can be changed with dims.

Spin moments comprise a list of pairs, [i1 => Moment(...), i2 => ...], where i1, i2, ... are a complete set of symmetry-distinct atoms. Each Moment contains spin and $g$-factor information.

The two primary options for mode are :SUN and :dipole. In the former, each spin-$s$ degree of freedom is described as an SU(N) coherent state, i.e. a quantum superposition of $N = 2s + 1$ levels. This formalism can be useful to capture multipolar spin fluctuations or local entanglement effects.

Mode :dipole projects the SU(N) dynamics onto the restricted space of pure dipoles. In practice this means that Sunny will simulate Landau-Lifshitz dynamics, but single-ion anisotropy and biquadratic exchange interactions will be renormalized to improve accuracy. To disable this renormalization, use the mode :dipole_large_s which applies the $s → ∞$ classical limit. For details, see the documentation page: Interaction Renormalization.

An integer seed for the random number generator can optionally be specified to enable reproducible calculations.

All spins are initially polarized in the global $z$-direction.

source
Sunny.UnitsType
Units(energy, length)

Physical constants in units of reference energy and length scales. Possible lengths are [:angstrom, :nm]. For atomic scale modeling, it is preferable to work in units of length=:angstrom, which follows the CIF file standard. Possible energy units are [:meV, :K, :THz, :inverse_cm, :T]. Kelvin is converted to energy via the Boltzmann constant $k_B$. Similarly, hertz is converted via the Planck constant $h$, inverse cm via the speed of light $c$, and tesla (field strength) via the Bohr magneton $μ_B$. For a given Units system, one can access any of the length and energy scale symbols listed above.

Examples

# Unit system with [energy] = meV and [length] = Å
 units = Units(:meV, :angstrom)
 
 # Use the Boltzmann constant kB to convert 1 kelvin into meV
@@ -53,45 +53,45 @@
 @assert units.T ≈ 0.05788381806
 
 # The physical constant μ0 μB² in units of ų meV.
-@assert u.vacuum_permeability ≈ 0.6745817653
source
Sunny.add_sample!Method
add_sample!(sc::SampledCorrelations, sys::System)
-add_sample!(sc::SampledCorrelationsStatic, sys::System)

Measure pair correlation data for the spin configuration in sys, and accumulate these statistics into sc. For a dynamical SampledCorrelations, this involves time-integration of the provided spin trajectory, recording correlations in both space and time. Conversely, SampledCorrelationsStatic, will record only spatial correlations for the single spin configuration that is provided.

Time-integration will update the spin configuration of sys in-place. To avoid this mutation, consider calling clone_system prior to add_sample!.

source
Sunny.clone_systemMethod
clone_system(sys::System)

Creates a full clone of the system, such that mutable updates to one copy will not affect the other, and thread safety is guaranteed.

source
Sunny.dispersionMethod
dispersion(swt::SpinWaveTheory, qpts)

Given a list of wavevectors qpts in reciprocal lattice units (RLU), returns excitation energies for each band. The return value ret is 2D array, and should be indexed as ret[band_index, q_index].

source
Sunny.dmvecMethod
dmvec(D)

Antisymmetric matrix representation of the Dzyaloshinskii-Moriya pseudo-vector,

  [  0    D[3] -D[2]
+@assert u.vacuum_permeability ≈ 0.6745817653
source
Sunny.add_sample!Method
add_sample!(sc::SampledCorrelations, sys::System)
+add_sample!(sc::SampledCorrelationsStatic, sys::System)

Measure pair correlation data for the spin configuration in sys, and accumulate these statistics into sc. For a dynamical SampledCorrelations, this involves time-integration of the provided spin trajectory, recording correlations in both space and time. Conversely, SampledCorrelationsStatic, will record only spatial correlations for the single spin configuration that is provided.

Time-integration will update the spin configuration of sys in-place. To avoid this mutation, consider calling clone_system prior to add_sample!.

source
Sunny.clone_systemMethod
clone_system(sys::System)

Creates a full clone of the system, such that mutable updates to one copy will not affect the other, and thread safety is guaranteed.

source
Sunny.dispersionMethod
dispersion(swt::SpinWaveTheory, qpts)

Given a list of wavevectors qpts in reciprocal lattice units (RLU), returns excitation energies for each band. The return value ret is 2D array, and should be indexed as ret[band_index, q_index].

source
Sunny.dmvecMethod
dmvec(D)

Antisymmetric matrix representation of the Dzyaloshinskii-Moriya pseudo-vector,

  [  0    D[3] -D[2]
    -D[3]   0    D[1]
-    D[2] -D[1]   0  ]

By construction, Si'*dmvec(D)*Sj ≈ D⋅(Si×Sj) for any dipoles Si and Sj. This helper function is intended for use with set_exchange!.

source
Sunny.domain_averageMethod
domain_average(f, cryst, qpts; rotations, weights)

Calculate an average intensity for the reciprocal-space points qpts under a discrete set of rotations. Rotations, in global coordinates, may be given either as an axis-angle pair or as a 3×3 rotation matrix. Each rotation is weighted according to the elements in weights. The function f should accept a list of rotated q-points and return an intensities calculation.

Example

# 0, 120, and 240 degree rotations about the global z-axis
+    D[2] -D[1]   0  ]

By construction, Si'*dmvec(D)*Sj ≈ D⋅(Si×Sj) for any dipoles Si and Sj. This helper function is intended for use with set_exchange!.

source
Sunny.domain_averageMethod
domain_average(f, cryst, qpts; rotations, weights)

Calculate an average intensity for the reciprocal-space points qpts under a discrete set of rotations. Rotations, in global coordinates, may be given either as an axis-angle pair or as a 3×3 rotation matrix. Each rotation is weighted according to the elements in weights. The function f should accept a list of rotated q-points and return an intensities calculation.

Example

# 0, 120, and 240 degree rotations about the global z-axis
 rotations = [([0,0,1], n*(2π/3)) for n in 0:2]
 weights = [1, 1, 1]
 res = domain_average(cryst, path; rotations, weights) do path_rotated
     intensities(swt, path_rotated; energies, kernel)
 end
-plot_intensities(res)
source
Sunny.enable_dipole_dipole!Method
enable_dipole_dipole!(sys::System, μ0_μB²)

Enables long-range interactions between magnetic dipole moments,

\[ -(μ_0/4π) ∑_{⟨ij⟩} [3 (μ_i⋅𝐫̂_{ij})(μ_j⋅𝐫̂_{ij}) - μ_i⋅μ_j] / r_{ij}^3\]

where the sum is over all pairs of spins (singly counted), including periodic images, regularized using the Ewald summation convention. The magnetic_moment is defined as $μ = -g μ_B 𝐒$, where $𝐒$ is the spin angular momentum dipole. The parameter μ0_μB² specifies the physical constant $μ_0 μ_B^2$, which has dimensions of length³-energy. Obtain this constant for a given system of Units via its vacuum_permeability property.

Example

units = Units(:meV, :angstrom)
-enable_dipole_dipole!(sys, units.vacuum_permeability)

See also modify_exchange_with_truncated_dipole_dipole!.

source
Sunny.excitations!Method
excitations!(T, tmp, swt::SpinWaveTheory, q)

Given a wavevector q, solves for the matrix T representing quasi-particle excitations, and returns a list of quasi-particle energies. Both T and tmp must be supplied as $2L×2L$ complex matrices, where $L$ is the number of bands for a single $𝐪$ value.

The columns of T are understood to be contracted with the Holstein-Primakoff bosons $[𝐛_𝐪, 𝐛_{-𝐪}^†]$. The first $L$ columns provide the eigenvectors of the quadratic Hamiltonian for the wavevector $𝐪$. The next $L$ columns 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::SpinWaveTheorySpiral, q; branch)

Calculations on a SpinWaveTheorySpiral 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 spins in the magnetic cell. This yields a total of $3L$ excitations for a given momentum transfer $𝐪$.

source
Sunny.excitationsMethod
excitations(swt::SpinWaveTheory, q)
-excitations(swt::SpinWaveTheorySpiral, q; branch)

Returns a pair (energies, T) providing the excitation energies and eigenvectors. Prefer excitations! for performance, which avoids matrix allocations. See the documentation of excitations! for more details.

source
Sunny.gaussianMethod
gaussian(; {fwhm, σ})

Returns the function exp(-x^2/2σ^2) / √(2π*σ^2). Either fwhm or σ must be specified, where fwhm = (2.355...) * σ is the full width at half maximum.

source
Sunny.generate_mantid_script_from_binning_parametersMethod
generate_mantid_script_from_binning_parameters(params::BinningParameters)

Generate a Mantid script which bins data according to the given BinningParameters.

Units

Take care to ensure the units are correct (R.L.U. or absolute). You may want to call Sunny.bin_rlu_as_absolute_units! or Sunny.bin_absolute_units_as_rlu! first.

source
Sunny.global_positionMethod
global_position(sys::System, site::Site)

Position of a Site in global coordinates.

To precompute a full list of positions, one can use eachsite as below:

pos = [global_position(sys, site) for site in eachsite(sys)]
source
Sunny.intensitiesMethod
intensities(swt::SpinWaveTheory, qpts; energies, kernel, kT=0)
-intensities(sc::SampledCorrelations, qpts; energies, kernel=nothing, kT)

Calculates dynamical pair correlation intensities for a set of $𝐪$-points in reciprocal space.

Linear spin wave theory calculations are performed with an instance of SpinWaveTheory. The alternative SpinWaveTheorySpiral allows to study generalized spiral orders with a single, incommensurate-$𝐤$ ordering wavevector. Another alternative SpinWaveTheoryKPM is favorable for calculations on large magnetic cells, and allows to study systems with disorder. An optional nonzero temperature kT will scale intensities by the quantum thermal occupation factor $|1 + n_B(ω)|$ where $n_B(ω) = 1/(e^{βω}-1)$ is the Bose function.

Intensities can also be calculated for SampledCorrelations associated with classical spin dynamics. In this case, thermal broadening will already be present, and the line-broadening kernel becomes optional. Conversely, the parameter kT becomes required. If positive, it will introduce an intensity correction factor $|βω (1 + n_B(ω))|$ that undoes the occupation factor for the classical Boltzmann distribution and applies the quantum thermal occupation factor. The special choice kT = nothing will suppress the classical-to-quantum correction factor, and yield statistics consistent with the classical Boltzmann distribution.

source
Sunny.intensities_bandsMethod
intensities_bands(swt::SpinWaveTheory, qpts; kT=0)

Calculate spin wave excitation bands for a set of q-points in reciprocal space. This calculation is analogous to intensities, but does not perform line broadening of the bands.

source
Sunny.intensities_staticMethod
intensities_static(swt::SpinWaveTheory, qpts; bounds=(-Inf, Inf), kernel=nothing, kT=0)
+plot_intensities(res)
source
Sunny.enable_dipole_dipole!Method
enable_dipole_dipole!(sys::System, μ0_μB²)

Enables long-range interactions between magnetic dipole moments,

\[ -(μ_0/4π) ∑_{⟨ij⟩} [3 (μ_i⋅𝐫̂_{ij})(μ_j⋅𝐫̂_{ij}) - μ_i⋅μ_j] / r_{ij}^3\]

where the sum is over all pairs of spins (singly counted), including periodic images, regularized using the Ewald summation convention. The magnetic_moment is defined as $μ = -g μ_B 𝐒$, where $𝐒$ is the spin angular momentum dipole. The parameter μ0_μB² specifies the physical constant $μ_0 μ_B^2$, which has dimensions of length³-energy. Obtain this constant for a given system of Units via its vacuum_permeability property.

Example

units = Units(:meV, :angstrom)
+enable_dipole_dipole!(sys, units.vacuum_permeability)

See also modify_exchange_with_truncated_dipole_dipole!.

source
Sunny.excitations!Method
excitations!(T, tmp, swt::SpinWaveTheory, q)

Given a wavevector q, solves for the matrix T representing quasi-particle excitations, and returns a list of quasi-particle energies. Both T and tmp must be supplied as $2L×2L$ complex matrices, where $L$ is the number of bands for a single $𝐪$ value.

The columns of T are understood to be contracted with the Holstein-Primakoff bosons $[𝐛_𝐪, 𝐛_{-𝐪}^†]$. The first $L$ columns provide the eigenvectors of the quadratic Hamiltonian for the wavevector $𝐪$. The next $L$ columns 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::SpinWaveTheorySpiral, q; branch)

Calculations on a SpinWaveTheorySpiral 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 spins in the magnetic cell. This yields a total of $3L$ excitations for a given momentum transfer $𝐪$.

source
Sunny.excitationsMethod
excitations(swt::SpinWaveTheory, q)
+excitations(swt::SpinWaveTheorySpiral, q; branch)

Returns a pair (energies, T) providing the excitation energies and eigenvectors. Prefer excitations! for performance, which avoids matrix allocations. See the documentation of excitations! for more details.

source
Sunny.gaussianMethod
gaussian(; {fwhm, σ})

Returns the function exp(-x^2/2σ^2) / √(2π*σ^2). Either fwhm or σ must be specified, where fwhm = (2.355...) * σ is the full width at half maximum.

source
Sunny.generate_mantid_script_from_binning_parametersMethod
generate_mantid_script_from_binning_parameters(params::BinningParameters)

Generate a Mantid script which bins data according to the given BinningParameters.

Units

Take care to ensure the units are correct (R.L.U. or absolute). You may want to call Sunny.bin_rlu_as_absolute_units! or Sunny.bin_absolute_units_as_rlu! first.

source
Sunny.global_positionMethod
global_position(sys::System, site::Site)

Position of a Site in global coordinates.

To precompute a full list of positions, one can use eachsite as below:

pos = [global_position(sys, site) for site in eachsite(sys)]
source
Sunny.intensitiesMethod
intensities(swt::SpinWaveTheory, qpts; energies, kernel, kT=0)
+intensities(sc::SampledCorrelations, qpts; energies, kernel=nothing, kT)

Calculates dynamical pair correlation intensities for a set of $𝐪$-points in reciprocal space.

Linear spin wave theory calculations are performed with an instance of SpinWaveTheory. The alternative SpinWaveTheorySpiral allows to study generalized spiral orders with a single, incommensurate-$𝐤$ ordering wavevector. Another alternative SpinWaveTheoryKPM is favorable for calculations on large magnetic cells, and allows to study systems with disorder. An optional nonzero temperature kT will scale intensities by the quantum thermal occupation factor $|1 + n_B(ω)|$ where $n_B(ω) = 1/(e^{βω}-1)$ is the Bose function.

Intensities can also be calculated for SampledCorrelations associated with classical spin dynamics. In this case, thermal broadening will already be present, and the line-broadening kernel becomes optional. Conversely, the parameter kT becomes required. If positive, it will introduce an intensity correction factor $|βω (1 + n_B(ω))|$ that undoes the occupation factor for the classical Boltzmann distribution and applies the quantum thermal occupation factor. The special choice kT = nothing will suppress the classical-to-quantum correction factor, and yield statistics consistent with the classical Boltzmann distribution.

source
Sunny.intensities_bandsMethod
intensities_bands(swt::SpinWaveTheory, qpts; kT=0)

Calculate spin wave excitation bands for a set of q-points in reciprocal space. This calculation is analogous to intensities, but does not perform line broadening of the bands.

source
Sunny.intensities_staticMethod
intensities_static(swt::SpinWaveTheory, qpts; bounds=(-Inf, Inf), kernel=nothing, kT=0)
 intensities_static(sc::SampledCorrelations, qpts; bounds=(-Inf, Inf), kT)
-intensities_static(sc::SampledCorrelationsStatic, qpts)

Like intensities, but integrates the dynamical correlations $\mathcal{S}(𝐪, ω)$ over a range of energies $ω$. By default, the integration bounds are $(-∞, ∞)$, yielding the instantaneous (equal-time) correlations.

In SpinWaveTheory, the integral will be realized as a sum over discrete bands. Alternative calculation methods are SpinWaveTheorySpiral and SpinWaveTheoryKPM.

Classical dynamics data in SampledCorrelations can also be used to calculate static intensities. In this case, the domain of integration will be a finite grid of available energies. Here, the parameter kT will be used to account for the quantum thermal occupation of excitations, as documented in intensities.

Static intensities calculated from SampledCorrelationsStatic are dynamics-independent. Instead, instantaneous correlations sampled from the classical Boltzmann distribution will be reported.

source
Sunny.lattice_paramsMethod
lattice_params(latvecs)

Compute the lattice parameters $(a, b, c, α, β, γ)$ for the three lattice vectors provided as columns of latvecs. The inverse mapping is lattice_vectors.

source
Sunny.lattice_vectorsMethod
lattice_vectors(a, b, c, α, β, γ)

Return the lattice vectors, as columns of the $3×3$ output matrix, that define the shape of a crystallographic cell in global Cartesian coordinates. Conversely, one can view the output matrix as defining the global Cartesian coordinate system with respect to the lattice system.

The lattice constants $(a, b, c)$ have units of length, and the angles $(α, β, γ)$ are in degrees. The inverse mapping is lattice_params.

Example

latvecs = lattice_vectors(1, 1, 2, 90, 90, 120)
+intensities_static(sc::SampledCorrelationsStatic, qpts)

Like intensities, but integrates the dynamical correlations $\mathcal{S}(𝐪, ω)$ over a range of energies $ω$. By default, the integration bounds are $(-∞, ∞)$, yielding the instantaneous (equal-time) correlations.

In SpinWaveTheory, the integral will be realized as a sum over discrete bands. Alternative calculation methods are SpinWaveTheorySpiral and SpinWaveTheoryKPM.

Classical dynamics data in SampledCorrelations can also be used to calculate static intensities. In this case, the domain of integration will be a finite grid of available energies. Here, the parameter kT will be used to account for the quantum thermal occupation of excitations, as documented in intensities.

Static intensities calculated from SampledCorrelationsStatic are dynamics-independent. Instead, instantaneous correlations sampled from the classical Boltzmann distribution will be reported.

source
Sunny.lattice_paramsMethod
lattice_params(latvecs)

Compute the lattice parameters $(a, b, c, α, β, γ)$ for the three lattice vectors provided as columns of latvecs. The inverse mapping is lattice_vectors.

source
Sunny.lattice_vectorsMethod
lattice_vectors(a, b, c, α, β, γ)

Return the lattice vectors, as columns of the $3×3$ output matrix, that define the shape of a crystallographic cell in global Cartesian coordinates. Conversely, one can view the output matrix as defining the global Cartesian coordinate system with respect to the lattice system.

The lattice constants $(a, b, c)$ have units of length, and the angles $(α, β, γ)$ are in degrees. The inverse mapping is lattice_params.

Example

latvecs = lattice_vectors(1, 1, 2, 90, 90, 120)
 a1, a2, a3 = eachcol(latvecs)
 @assert a1 ≈ [1, 0, 0]       # a1 always aligned with global x
 @assert a2 ≈ [-1/2, √3/2, 0] # a2 always in global (x,y) plane
-@assert a3 ≈ [0, 0, 2]       # a3 may generally be a combination of (x,y,z)
source
Sunny.load_nxsMethod
params, signal = load_nxs(filename; field="signal")

Given the name of a Mantid-exported MDHistoWorkspace file, load the BinningParameters and the signal from that file.

To load another field instead of the signal, specify e.g. field="errors_squared". Typical fields include errors_squared, mask, num_events, and signal.

source
Sunny.lorentzianMethod
lorentzian(; fwhm)

Returns the function (Γ/2) / (π*(x^2+(Γ/2)^2)) where Γ = fwhm is the full width at half maximum.

source
Sunny.magnetic_momentMethod
magnetic_moment(sys::System, site::Site)

Returns $- g 𝐒$, the local magnetic moment in units of the Bohr magneton. The spin dipole $𝐒$ and $g$-tensor may both be Site dependent.

source
Sunny.merge_correlationsMethod
merge_correlations(scs::Vector{SampledCorrelations)

Accumulate a list of SampledCorrelations into a single, summary SampledCorrelations. Useful for reducing the results of parallel computations.

source
Sunny.minimize_energy!Method
minimize_energy!(sys::System{N}; maxiters=1000, method=Optim.ConjugateGradient(),
-                 g_tol=1e-10, kwargs...) where N

Optimizes the spin configuration in sys to minimize energy. A total of maxiters iterations will be attempted. Convergence is reached when the root mean squared energy gradient goes below g_tol. The remaining kwargs will be forwarded to the optimize method of the Optim.jl package.

source
Sunny.minimize_spiral_energy!Method
minimize_spiral_energy!(sys, axis; maxiters=10_000, k_guess=randn(sys.rng, 3))

Finds a generalized spiral order that minimizes the spiral_energy. This involves optimization of the spin configuration in sys, and the propagation wavevector $𝐤$, which will be returned in reciprocal lattice units (RLU). The axis vector normal to the polarization plane should be provided in global Cartesian coordinates, and will usually be determined by symmetry configurations. The initial k_guess will be random, unless otherwise provided.

See also suggest_magnetic_supercell to find a system shape that is approximately commensurate with the returned propagation wavevector $𝐤$.

source
Sunny.modify_exchange_with_truncated_dipole_dipole!Method
modify_exchange_with_truncated_dipole_dipole!(sys::System, cutoff, μ0_μB²)

Like enable_dipole_dipole!, the purpose of this function is to introduce long-range dipole-dipole interactions between magnetic moments. Whereas enable_dipole_dipole! employs Ewald summation, this function instead employs real-space pair couplings with truncation at the specified cutoff distance. If the cutoff is relatively small, then this function may be faster than enable_dipole_dipole!.

Mutation of existing couplings

This function will modify existing bilinear couplings between spins by adding dipole-dipole interactions. It must therefore be called after all other pair couplings have been specified. Conversely, any calls to set_exchange!, set_pair_coupling!, etc. will irreversibly delete the dipole-dipole interactions that have been introduced by this function.

source
Sunny.position_to_siteMethod
position_to_site(sys::System, r)

Converts a position r to four indices of a Site. The coordinates of r are given in units of the lattice vectors for the original crystal. This function can be useful for working with systems that have been reshaped using reshape_supercell.

Example

# Find the `site` at the center of a unit cell which is displaced by four
+@assert a3 ≈ [0, 0, 2]       # a3 may generally be a combination of (x,y,z)
source
Sunny.load_nxsMethod
params, signal = load_nxs(filename; field="signal")

Given the name of a Mantid-exported MDHistoWorkspace file, load the BinningParameters and the signal from that file.

To load another field instead of the signal, specify e.g. field="errors_squared". Typical fields include errors_squared, mask, num_events, and signal.

source
Sunny.lorentzianMethod
lorentzian(; fwhm)

Returns the function (Γ/2) / (π*(x^2+(Γ/2)^2)) where Γ = fwhm is the full width at half maximum.

source
Sunny.magnetic_momentMethod
magnetic_moment(sys::System, site::Site)

Returns $- g 𝐒$, the local magnetic moment in units of the Bohr magneton. The spin dipole $𝐒$ and $g$-tensor may both be Site dependent.

source
Sunny.merge_correlationsMethod
merge_correlations(scs::Vector{SampledCorrelations)

Accumulate a list of SampledCorrelations into a single, summary SampledCorrelations. Useful for reducing the results of parallel computations.

source
Sunny.minimize_energy!Method
minimize_energy!(sys::System{N}; maxiters=1000, method=Optim.ConjugateGradient(),
+                 g_tol=1e-10, kwargs...) where N

Optimizes the spin configuration in sys to minimize energy. A total of maxiters iterations will be attempted. Convergence is reached when the root mean squared energy gradient goes below g_tol. The remaining kwargs will be forwarded to the optimize method of the Optim.jl package.

source
Sunny.minimize_spiral_energy!Method
minimize_spiral_energy!(sys, axis; maxiters=10_000, k_guess=randn(sys.rng, 3))

Finds a generalized spiral order that minimizes the spiral_energy. This involves optimization of the spin configuration in sys, and the propagation wavevector $𝐤$, which will be returned in reciprocal lattice units (RLU). The axis vector normal to the polarization plane should be provided in global Cartesian coordinates, and will usually be determined by symmetry configurations. The initial k_guess will be random, unless otherwise provided.

See also suggest_magnetic_supercell to find a system shape that is approximately commensurate with the returned propagation wavevector $𝐤$.

source
Sunny.modify_exchange_with_truncated_dipole_dipole!Method
modify_exchange_with_truncated_dipole_dipole!(sys::System, cutoff, μ0_μB²)

Like enable_dipole_dipole!, the purpose of this function is to introduce long-range dipole-dipole interactions between magnetic moments. Whereas enable_dipole_dipole! employs Ewald summation, this function instead employs real-space pair couplings with truncation at the specified cutoff distance. If the cutoff is relatively small, then this function may be faster than enable_dipole_dipole!.

Mutation of existing couplings

This function will modify existing bilinear couplings between spins by adding dipole-dipole interactions. It must therefore be called after all other pair couplings have been specified. Conversely, any calls to set_exchange!, set_pair_coupling!, etc. will irreversibly delete the dipole-dipole interactions that have been introduced by this function.

source
Sunny.position_to_siteMethod
position_to_site(sys::System, r)

Converts a position r to four indices of a Site. The coordinates of r are given in units of the lattice vectors for the original crystal. This function can be useful for working with systems that have been reshaped using reshape_supercell.

Example

# Find the `site` at the center of a unit cell which is displaced by four
 # multiples of the first lattice vector
 site = position_to_site(sys, [4.5, 0.5, 0.5])
 
 # Print the dipole at this site
-println(sys.dipoles[site])
source
Sunny.powder_averageMethod
powder_average(f, cryst, radii, n; seed=0)

Calculate a powder-average over structure factor intensities. The radii, with units of inverse length, define spherical shells in reciprocal space. The Fibonacci lattice yields n points on the sphere, with quasi-uniformity. Sample points on different shells are decorrelated through random rotations. A consistent random number seed will yield reproducible results. The function f should accept a list of q-points and call intensities.

Example

radii = range(0.0, 3.0, 200)
+println(sys.dipoles[site])
source
Sunny.powder_averageMethod
powder_average(f, cryst, radii, n; seed=0)

Calculate a powder-average over structure factor intensities. The radii, with units of inverse length, define spherical shells in reciprocal space. The Fibonacci lattice yields n points on the sphere, with quasi-uniformity. Sample points on different shells are decorrelated through random rotations. A consistent random number seed will yield reproducible results. The function f should accept a list of q-points and call intensities.

Example

radii = range(0.0, 3.0, 200)
 res = powder_average(cryst, radii, 500) do qs
     intensities(swt, qs; energies, kernel)
 end
-plot_intensities(res)
source
Sunny.primitive_cell_shapeMethod
primitive_cell_shape(cryst::Crystal)

Returns the shape of the primitive cell as a 3×3 matrix, in fractional coordinates of the conventional lattice vectors. May be useful for constructing inputs to reshape_supercell.

Examples

# Valid if `cryst` has not been reshaped
-@assert cryst.prim_latvecs ≈ cryst.latvecs * primitive_cell_shape(cryst)
source
Sunny.print_bondMethod
print_bond(cryst::Crystal, bond::Bond; b_ref::Bond)

Prints symmetry information for bond bond. A symmetry-equivalent reference bond b_ref can optionally be provided to fix the meaning of the coefficients A, B, ...

source
Sunny.print_siteMethod
print_site(cryst, i; R=I)

Print symmetry information for the site i, including allowed g-tensor and allowed anisotropy operator. An optional rotation matrix R can be provided to define the reference frame for expression of the anisotropy.

source
Sunny.print_stevens_expansionMethod
function print_stevens_expansion(op)

Prints a local Hermitian operator as a linear combination of Stevens operators. The operator op may be a finite-dimensional matrix or an abstract spin polynomial in the large-$s$ limit.

Examples

S = spin_matrices(2)
+plot_intensities(res)
source
Sunny.primitive_cell_shapeMethod
primitive_cell_shape(cryst::Crystal)

Returns the shape of the primitive cell as a 3×3 matrix, in fractional coordinates of the conventional lattice vectors. May be useful for constructing inputs to reshape_supercell.

Examples

# Valid if `cryst` has not been reshaped
+@assert cryst.prim_latvecs ≈ cryst.latvecs * primitive_cell_shape(cryst)
source
Sunny.print_bondMethod
print_bond(cryst::Crystal, bond::Bond; b_ref::Bond)

Prints symmetry information for bond bond. A symmetry-equivalent reference bond b_ref can optionally be provided to fix the meaning of the coefficients A, B, ...

source
Sunny.print_siteMethod
print_site(cryst, i; R=I)

Print symmetry information for the site i, including allowed g-tensor and allowed anisotropy operator. An optional rotation matrix R can be provided to define the reference frame for expression of the anisotropy.

source
Sunny.print_stevens_expansionMethod
function print_stevens_expansion(op)

Prints a local Hermitian operator as a linear combination of Stevens operators. The operator op may be a finite-dimensional matrix or an abstract spin polynomial in the large-$s$ limit.

Examples

S = spin_matrices(2)
 print_stevens_expansion(S[1]^4 + S[2]^4 + S[3]^4)
 # Prints: (1/20)𝒪₄₀ + (1/4)𝒪₄₄ + 102/5
 
 S = spin_matrices(Inf)
 print_stevens_expansion(S[1]^4 + S[2]^4 + S[3]^4)
-# Prints: (1/20)𝒪₄₀ + (1/4)𝒪₄₄ + (3/5)𝒮⁴
source
Sunny.print_suggested_frameMethod
print_suggested_frame(cryst, i)

Print a suggested reference frame, as a rotation matrix R, that can be used as input to print_site(). The purpose is to simplify the description of allowed anisotropies.

source
Sunny.print_symmetry_tableMethod
print_symmetry_table(cryst::Crystal, max_dist)

Print symmetry information for all equivalence classes of sites and bonds, up to a maximum bond distance of max_dist. Equivalent to calling print_bond(cryst, b) for every bond b in reference_bonds(cryst, max_dist), where Bond(i, i, [0,0,0]) refers to a single site i.

source
Sunny.print_wrapped_intensitiesMethod
print_wrapped_intensities(sys::System; nmax=10)

For Bravais lattices: Prints up to nmax wavevectors according to their instantaneous (static) structure factor intensities, listed in descending order. For non-Bravais lattices: Performs the same analysis for each spin sublattice independently; the output weights are naïvely averaged over sublattices, without incorporating phase shift information. This procedure therefore wraps all wavevectors into the first Brillouin zone. Each wavevector coordinate is given between $-1/2$ and $1/2$ in reciprocal lattice units (RLU). The output from this function will typically be used as input to suggest_magnetic_supercell.

Because this function does not incorporate phase information in its averaging over sublattices, the printed weights are not directly comparable with experiment. For that purpose, use SampledCorrelationsStatic instead.

source
Sunny.propose_deltaMethod
propose_delta(magnitude)

Generate a proposal function that adds a Gaussian perturbation to the existing spin state. In :dipole mode, the procedure is to first introduce a random three-vector perturbation $𝐬′ = 𝐬 + |𝐬| ξ$ and then return the properly normalized spin $|𝐬| (𝐬′/|𝐬′|)$. Each component of the random vector $ξ$ is Gaussian distributed with a standard deviation of magnitude; the latter is dimensionless and typically smaller than one.

In :SUN mode, the procedure is analogous, but now involving Gaussian perturbations to each of the $N$ complex components of an SU(N) coherent state.

In the limit of very large magnitude, this function coincides with propose_uniform.

Consider also Langevin sampling, which is rejection free.

source
Sunny.propose_flipMethod
propose_flip

Function to propose pure spin flip updates in the context of a LocalSampler. Dipoles are flipped as $𝐬 → -𝐬$. SU(N) coherent states are flipped using the time-reversal operator.

source
Sunny.propose_uniformFunction
propose_uniform

Function to propose a uniformly random spin update in the context of a LocalSampler. In :dipole mode, the result is a random three-vector with appropriate normalization. In :SUN mode, the result is a random SU(N) coherent state with appropriate normalization.

For low-temperature Monte Carlo simulations, uniform spin proposals can be very inefficient due to a high probability of rejection in the Metropolis accept/reject step. Consider also Langevin sampling, which is rejection free.

source
Sunny.q_space_gridMethod
q_space_grid(cryst::Crystal, axis1, range1, axis2, range2; offset=[0,0,0], orthogonalize=false)
-q_space_grid(cryst::Crystal, axis1, range1, axis2, range2, axis3, range3; orthogonalize=false)

Returns a 2D or 3D grid of q-points with uniform spacing. The volume shape is defined by (axis1, axis2, ...) in reciprocal lattice units (RLU). Elements of (range1, range2, ...) provide coefficients $c_i$ used to define grid positions,

    offset + c1 * axis1 + c2 * axis2 + ...

A nonzero offset is allowed only in the 2D case.

The first range parameter, range1, must be a regularly spaced list of coefficients, e.g., range1 = range(lo1, hi1, n). Subsequent range parameters may be a pair of bounds, without grid spacing information. For example, by selecting range2 = (lo2, hi2), an appropriate step-size will be inferred to provide an approximately uniform sampling density in global Cartesian coordinates.

The axes may be non-orthogonal. To extend to an orthohombic volume in global Cartesian coordinates, set orthogonalize=true.

For a 1D grid, use q_space_path instead.

source
Sunny.q_space_pathMethod
q_space_path(cryst::Crystal, qs, n; labels=nothing)

Returns a 1D path consisting of n wavevectors sampled piecewise-linearly between the qs. Although the qs are provided in reciprocal lattice units (RLU), consecutive samples are spaced uniformly in the global (inverse-length) coordinate system. Optional labels can be associated with each special q-point, and will be used in plotting functions.

See also q_space_grid.

source
Sunny.reference_bondsMethod
reference_bonds(cryst::Crystal, max_dist)

Returns a full list of bonds, one for each symmetry equivalence class, up to distance max_dist. The reference bond b for each equivalence class is selected according to a scoring system that prioritizes simplification of the elements in basis_for_symmetry_allowed_couplings(cryst, b).

source
Sunny.remove_periodicity!Method
remove_periodicity!(sys::System, flags)

Remove periodic interactions along each dimension d if flags[d] is true. The system must support inhomogeneous interactions via to_inhomogeneous.

Example

# Remove periodic boundaries along the 1st and 3rd dimensions
-remove_periodicity!(sys::System, (true, false, true))
source
Sunny.repeat_periodically_as_spiralMethod
repeat_periodically_as_spiral(sys::System, counts::NTuple{3, Int}; k, axis)

Repeats the magnetic cell of System a number of times along each system axis according to the specified counts. Spins in each system image will be rotated according to the propagation wavevector k (in RLU) and the rotation axis (in global Cartesian coordinates). Coincides with repeat_periodically in the special case of k = [0, 0, 0]

See also minimize_spiral_energy! to find an energy-minimizing wavevector k and spin dipole configuration.

Example

k = minimize_spiral_energy!(sys, axis; k_guess=randn(3))
-repeat_periodically_as_spiral(sys, counts; k, axis)
source
Sunny.reshape_supercellMethod
reshape_supercell(sys::System, shape)

Maps an existing System to a new one that has the shape and periodicity of a requested supercell. The columns of the $3×3$ integer matrix shape represent the supercell lattice vectors measured in units of the original crystal lattice vectors. Interactions, spins, and other settings will be inherited from sys.

In the special case that shape is a diagonal matrix, this function coincides with resize_supercell.

See also repeat_periodically.

source
Sunny.resize_supercellMethod
resize_supercell(sys::System, dims::NTuple{3, Int})

Creates a System with a given number of conventional unit cells in each lattice vector direction. Interactions, spins, and other settings will be inherited from sys.

Equivalent to:

reshape_supercell(sys, [dims[1] 0 0; 0 dims[2] 0; 0 0 dims[3]])

See also reshape_supercell and repeat_periodically.

source
Sunny.rotate_operatorMethod
rotate_operator(A, R)

Rotates the local quantum operator A according to the $3×3$ rotation matrix R.

source
Sunny.set_coherent!Method
set_coherent!(sys::System, Z, site::Site)

Set a coherent spin state at a Site using the $N$ complex amplitudes in Z.

For a single quantum spin-$s$, these amplitudes will be interpreted in the eigenbasis of $Ŝ^z$. That is, Z[1] represents the amplitude for the basis state fully polarized along the $ẑ$-direction, and subsequent components represent states with decreasing angular momentum along this axis ($m = s, s-1, …, -s$).

source
Sunny.set_dipoles_from_mcif!Method
set_dipoles_from_mcif!(sys::System, filename::AbstractString)

Load the magnetic supercell according to an mCIF file. System sys must already be resized to the correct supercell dimensions.

source
Sunny.set_exchange!Method
set_exchange!(sys::System, J, bond::Bond; biquad=0)

Sets an exchange interaction $𝐒_i⋅J 𝐒_j$ along the specified bond. This interaction will be propagated to equivalent bonds in consistency with crystal symmetry. Any previous interactions on these bonds will be overwritten. The parameter bond has the form Bond(i, j, offset), where i and j are atom indices within the unit cell, and offset is a displacement in unit cells.

As a convenience, scalar J can be used to specify a Heisenberg interaction. Also, the function dmvec(D) can be used to construct the antisymmetric part of the exchange, where D is the Dzyaloshinskii-Moriya pseudo-vector. The resulting interaction will be $𝐃⋅(𝐒_i×𝐒_j)$.

The optional numeric parameter biquad multiplies a scalar biquadratic interaction, $(𝐒_i⋅𝐒_j)^2$, with Interaction Renormalization if appropriate. For more general interactions, use set_pair_coupling! instead.

Examples

using LinearAlgebra
+# Prints: (1/20)𝒪₄₀ + (1/4)𝒪₄₄ + (3/5)𝒮⁴
source
Sunny.print_suggested_frameMethod
print_suggested_frame(cryst, i)

Print a suggested reference frame, as a rotation matrix R, that can be used as input to print_site(). The purpose is to simplify the description of allowed anisotropies.

source
Sunny.print_symmetry_tableMethod
print_symmetry_table(cryst::Crystal, max_dist)

Print symmetry information for all equivalence classes of sites and bonds, up to a maximum bond distance of max_dist. Equivalent to calling print_bond(cryst, b) for every bond b in reference_bonds(cryst, max_dist), where Bond(i, i, [0,0,0]) refers to a single site i.

source
Sunny.print_wrapped_intensitiesMethod
print_wrapped_intensities(sys::System; nmax=10)

For Bravais lattices: Prints up to nmax wavevectors according to their instantaneous (static) structure factor intensities, listed in descending order. For non-Bravais lattices: Performs the same analysis for each spin sublattice independently; the output weights are naïvely averaged over sublattices, without incorporating phase shift information. This procedure therefore wraps all wavevectors into the first Brillouin zone. Each wavevector coordinate is given between $-1/2$ and $1/2$ in reciprocal lattice units (RLU). The output from this function will typically be used as input to suggest_magnetic_supercell.

Because this function does not incorporate phase information in its averaging over sublattices, the printed weights are not directly comparable with experiment. For that purpose, use SampledCorrelationsStatic instead.

source
Sunny.propose_deltaMethod
propose_delta(magnitude)

Generate a proposal function that adds a Gaussian perturbation to the existing spin state. In :dipole mode, the procedure is to first introduce a random three-vector perturbation $𝐬′ = 𝐬 + |𝐬| ξ$ and then return the properly normalized spin $|𝐬| (𝐬′/|𝐬′|)$. Each component of the random vector $ξ$ is Gaussian distributed with a standard deviation of magnitude; the latter is dimensionless and typically smaller than one.

In :SUN mode, the procedure is analogous, but now involving Gaussian perturbations to each of the $N$ complex components of an SU(N) coherent state.

In the limit of very large magnitude, this function coincides with propose_uniform.

Consider also Langevin sampling, which is rejection free.

source
Sunny.propose_flipMethod
propose_flip

Function to propose pure spin flip updates in the context of a LocalSampler. Dipoles are flipped as $𝐬 → -𝐬$. SU(N) coherent states are flipped using the time-reversal operator.

source
Sunny.propose_uniformFunction
propose_uniform

Function to propose a uniformly random spin update in the context of a LocalSampler. In :dipole mode, the result is a random three-vector with appropriate normalization. In :SUN mode, the result is a random SU(N) coherent state with appropriate normalization.

For low-temperature Monte Carlo simulations, uniform spin proposals can be very inefficient due to a high probability of rejection in the Metropolis accept/reject step. Consider also Langevin sampling, which is rejection free.

source
Sunny.q_space_gridMethod
q_space_grid(cryst::Crystal, axis1, range1, axis2, range2; offset=[0,0,0], orthogonalize=false)
+q_space_grid(cryst::Crystal, axis1, range1, axis2, range2, axis3, range3; orthogonalize=false)

Returns a 2D or 3D grid of q-points with uniform spacing. The volume shape is defined by (axis1, axis2, ...) in reciprocal lattice units (RLU). Elements of (range1, range2, ...) provide coefficients $c_i$ used to define grid positions,

    offset + c1 * axis1 + c2 * axis2 + ...

A nonzero offset is allowed only in the 2D case.

The first range parameter, range1, must be a regularly spaced list of coefficients, e.g., range1 = range(lo1, hi1, n). Subsequent range parameters may be a pair of bounds, without grid spacing information. For example, by selecting range2 = (lo2, hi2), an appropriate step-size will be inferred to provide an approximately uniform sampling density in global Cartesian coordinates.

The axes may be non-orthogonal. To extend to an orthohombic volume in global Cartesian coordinates, set orthogonalize=true.

For a 1D grid, use q_space_path instead.

source
Sunny.q_space_pathMethod
q_space_path(cryst::Crystal, qs, n; labels=nothing)

Returns a 1D path consisting of n wavevectors sampled piecewise-linearly between the qs. Although the qs are provided in reciprocal lattice units (RLU), consecutive samples are spaced uniformly in the global (inverse-length) coordinate system. Optional labels can be associated with each special q-point, and will be used in plotting functions.

See also q_space_grid.

source
Sunny.reference_bondsMethod
reference_bonds(cryst::Crystal, max_dist)

Returns a full list of bonds, one for each symmetry equivalence class, up to distance max_dist. The reference bond b for each equivalence class is selected according to a scoring system that prioritizes simplification of the elements in basis_for_symmetry_allowed_couplings(cryst, b).

source
Sunny.remove_periodicity!Method
remove_periodicity!(sys::System, flags)

Remove periodic interactions along each dimension d if flags[d] is true. The system must support inhomogeneous interactions via to_inhomogeneous.

Example

# Remove periodic boundaries along the 1st and 3rd dimensions
+remove_periodicity!(sys::System, (true, false, true))
source
Sunny.repeat_periodically_as_spiralMethod
repeat_periodically_as_spiral(sys::System, counts::NTuple{3, Int}; k, axis)

Repeats the magnetic cell of System a number of times along each system axis according to the specified counts. Spins in each system image will be rotated according to the propagation wavevector k (in RLU) and the rotation axis (in global Cartesian coordinates). Coincides with repeat_periodically in the special case of k = [0, 0, 0]

See also minimize_spiral_energy! to find an energy-minimizing wavevector k and spin dipole configuration.

Example

k = minimize_spiral_energy!(sys, axis; k_guess=randn(3))
+repeat_periodically_as_spiral(sys, counts; k, axis)
source
Sunny.reshape_supercellMethod
reshape_supercell(sys::System, shape)

Maps an existing System to a new one that has the shape and periodicity of a requested supercell. The columns of the $3×3$ integer matrix shape represent the supercell lattice vectors measured in units of the original crystal lattice vectors. Interactions, spins, and other settings will be inherited from sys.

In the special case that shape is a diagonal matrix, this function coincides with resize_supercell.

See also repeat_periodically.

source
Sunny.resize_supercellMethod
resize_supercell(sys::System, dims::NTuple{3, Int})

Creates a System with a given number of conventional unit cells in each lattice vector direction. Interactions, spins, and other settings will be inherited from sys.

Equivalent to:

reshape_supercell(sys, [dims[1] 0 0; 0 dims[2] 0; 0 0 dims[3]])

See also reshape_supercell and repeat_periodically.

source
Sunny.rotate_operatorMethod
rotate_operator(A, R)

Rotates the local quantum operator A according to the $3×3$ rotation matrix R.

source
Sunny.set_coherent!Method
set_coherent!(sys::System, Z, site::Site)

Set a coherent spin state at a Site using the $N$ complex amplitudes in Z.

For a single quantum spin-$s$, these amplitudes will be interpreted in the eigenbasis of $Ŝ^z$. That is, Z[1] represents the amplitude for the basis state fully polarized along the $ẑ$-direction, and subsequent components represent states with decreasing angular momentum along this axis ($m = s, s-1, …, -s$).

source
Sunny.set_dipoles_from_mcif!Method
set_dipoles_from_mcif!(sys::System, filename::AbstractString)

Load the magnetic supercell according to an mCIF file. System sys must already be resized to the correct supercell dimensions.

source
Sunny.set_exchange!Method
set_exchange!(sys::System, J, bond::Bond; biquad=0)

Sets an exchange interaction $𝐒_i⋅J 𝐒_j$ along the specified bond. This interaction will be propagated to equivalent bonds in consistency with crystal symmetry. Any previous interactions on these bonds will be overwritten. The parameter bond has the form Bond(i, j, offset), where i and j are atom indices within the unit cell, and offset is a displacement in unit cells.

As a convenience, scalar J can be used to specify a Heisenberg interaction. Also, the function dmvec(D) can be used to construct the antisymmetric part of the exchange, where D is the Dzyaloshinskii-Moriya pseudo-vector. The resulting interaction will be $𝐃⋅(𝐒_i×𝐒_j)$.

The optional numeric parameter biquad multiplies a scalar biquadratic interaction, $(𝐒_i⋅𝐒_j)^2$, with Interaction Renormalization if appropriate. For more general interactions, use set_pair_coupling! instead.

Examples

using LinearAlgebra
 
 # Set a Heisenberg and DM interaction: 2Si⋅Sj + D⋅(Si×Sj)
 D = [0, 0, 3]
@@ -101,9 +101,9 @@
 J = [2 3 0;
     -3 2 0;
      0 0 2]
-set_exchange!(sys, J, bond)
source
Sunny.set_exchange_at!Method
set_exchange_at!(sys::System, J, site1::Site, site2::Site; biquad=0, offset=nothing)

Sets an exchange interaction `𝐒_i⋅J 𝐒_j along the single bond connecting two Sites, ignoring crystal symmetry. Any previous coupling on this bond will be overwritten. The system must support inhomogeneous interactions via to_inhomogeneous.

Use symmetry_equivalent_bonds to find (site1, site2, offset) values that are symmetry equivalent to a given Bond in the original system. For systems that are relatively small, the offset vector (in multiples of unit cells) will resolve ambiguities in the periodic wrapping.

See also set_exchange! for more details on specifying J and biquad. For more general couplings, use set_pair_coupling_at! instead.

source
Sunny.set_field!Method
set_field!(sys::System, B_μB)

Sets the external magnetic field $𝐁$ scaled by the Bohr magneton $μ_B$. This scaled field has units of energy and couples directly to the dimensionless magnetic_moment. At every site, the Zeeman coupling contributes an energy $+ (𝐁 μ_B) ⋅ (g 𝐒)$, involving the local $g$-tensor and spin angular momentum $𝐒$. Commonly, $g ≈ +2$ such that $𝐒$ is favored to anti-align with the applied field $𝐁$. Note that a given system of Units will implicitly use the Bohr magneton to convert between field and energy dimensions.

Example

# In units of meV, apply a 2 tesla field in the z-direction
+set_exchange!(sys, J, bond)
source
Sunny.set_exchange_at!Method
set_exchange_at!(sys::System, J, site1::Site, site2::Site; biquad=0, offset=nothing)

Sets an exchange interaction `𝐒_i⋅J 𝐒_j along the single bond connecting two Sites, ignoring crystal symmetry. Any previous coupling on this bond will be overwritten. The system must support inhomogeneous interactions via to_inhomogeneous.

Use symmetry_equivalent_bonds to find (site1, site2, offset) values that are symmetry equivalent to a given Bond in the original system. For systems that are relatively small, the offset vector (in multiples of unit cells) will resolve ambiguities in the periodic wrapping.

See also set_exchange! for more details on specifying J and biquad. For more general couplings, use set_pair_coupling_at! instead.

source
Sunny.set_field!Method
set_field!(sys::System, B_μB)

Sets the external magnetic field $𝐁$ scaled by the Bohr magneton $μ_B$. This scaled field has units of energy and couples directly to the dimensionless magnetic_moment. At every site, the Zeeman coupling contributes an energy $+ (𝐁 μ_B) ⋅ (g 𝐒)$, involving the local $g$-tensor and spin angular momentum $𝐒$. Commonly, $g ≈ +2$ such that $𝐒$ is favored to anti-align with the applied field $𝐁$. Note that a given system of Units will implicitly use the Bohr magneton to convert between field and energy dimensions.

Example

# In units of meV, apply a 2 tesla field in the z-direction
 units = Units(:meV, :angstrom)
-set_field!(sys, [0, 0, 2] * units.T)
source
Sunny.set_field_at!Method
set_field_at!(sys::System, B_μB, site::Site)

Sets the external magnetic field $𝐁$ scaled by the Bohr magneton $μ_B$ for a single Site. This scaled field has units of energy and couples directly to the dimensionless magnetic_moment. Note that a given system of Units will implicitly use the Bohr magneton to convert between field and energy dimensions.

See the documentation of set_field! for more information.

source
Sunny.set_onsite_coupling!Method
set_onsite_coupling!(sys::System, op, i::Int)

Set the single-ion anisotropy for the ith atom of every unit cell, as well as all symmetry-equivalent atoms. The operator op may be provided as an abstract function of the local spin operators, as a polynomial of spin_matrices, or as a linear combination of stevens_matrices.

Examples

# An easy axis anisotropy in the z-direction
+set_field!(sys, [0, 0, 2] * units.T)
source
Sunny.set_field_at!Method
set_field_at!(sys::System, B_μB, site::Site)

Sets the external magnetic field $𝐁$ scaled by the Bohr magneton $μ_B$ for a single Site. This scaled field has units of energy and couples directly to the dimensionless magnetic_moment. Note that a given system of Units will implicitly use the Bohr magneton to convert between field and energy dimensions.

See the documentation of set_field! for more information.

source
Sunny.set_onsite_coupling!Method
set_onsite_coupling!(sys::System, op, i::Int)

Set the single-ion anisotropy for the ith atom of every unit cell, as well as all symmetry-equivalent atoms. The operator op may be provided as an abstract function of the local spin operators, as a polynomial of spin_matrices, or as a linear combination of stevens_matrices.

Examples

# An easy axis anisotropy in the z-direction
 set_onsite_coupling!(sys, S -> -D*S[3]^3, i)
 
 # The unique quartic single-ion anisotropy for a site with cubic point group
@@ -112,35 +112,35 @@
 
 # An equivalent expression of this quartic anisotropy, up to a constant shift
 O = stevens_matrices(spin_label(sys, i))
-set_onsite_coupling!(sys, O[4,0] + 5*O[4,4], i)
source
Sunny.set_pair_coupling!Method
set_pair_coupling!(sys::System, op, bond)

Sets an arbitrary coupling op along bond. This coupling will be propagated to equivalent bonds in consistency with crystal symmetry. Any previous interactions on these bonds will be overwritten. The parameter bond has the form Bond(i, j, offset), where i and j are atom indices within the unit cell, and offset is a displacement in unit cells. The operator op may be provided as an anonymous function that accepts two spin dipole operators, or as a matrix that acts in the tensor product space of the two sites.

Examples

# Bilinear+biquadratic exchange involving 3×3 matrices J1 and J2
+set_onsite_coupling!(sys, O[4,0] + 5*O[4,4], i)
source
Sunny.set_pair_coupling!Method
set_pair_coupling!(sys::System, op, bond)

Sets an arbitrary coupling op along bond. This coupling will be propagated to equivalent bonds in consistency with crystal symmetry. Any previous interactions on these bonds will be overwritten. The parameter bond has the form Bond(i, j, offset), where i and j are atom indices within the unit cell, and offset is a displacement in unit cells. The operator op may be provided as an anonymous function that accepts two spin dipole operators, or as a matrix that acts in the tensor product space of the two sites.

Examples

# Bilinear+biquadratic exchange involving 3×3 matrices J1 and J2
 set_pair_coupling!(sys, (Si, Sj) -> Si'*J1*Sj + (Si'*J2*Sj)^2, bond)
 
 # Equivalent expression using an appropriate fixed matrix representation
 S = spin_matrices(1/2)
 Si, Sj = to_product_space(S, S)
-set_pair_coupling!(sys, Si'*J1*Sj + (Si'*J2*Sj)^2, bond)

See also spin_matrices, to_product_space.

source
Sunny.set_pair_coupling_at!Method
set_pair_coupling_at!(sys::System, op, bond)

Sets an arbitrary coupling along the single bond connecting two Sites, ignoring crystal symmetry. Any previous coupling on this bond will be overwritten. The system must support inhomogeneous interactions via to_inhomogeneous.

Use symmetry_equivalent_bonds to find (site1, site2, offset) values that are symmetry equivalent to a given Bond in the original system. For systems that are relatively small, the offset vector (in multiples of unit cells) will resolve ambiguities in the periodic wrapping.

The operator op may be provided as an anonymous function that accepts two spin dipole operators, or as a matrix that acts in the tensor product space of the two sites. The documentation for set_pair_coupling! provides examples constructing op.

source
Sunny.set_spin_rescaling!Method
set_spin_rescaling!(sys, α)

In dipole mode, rescale all spin magnitudes $S → α S$. In SU(N) mode, rescale all SU(N) coherent states $Z → √α Z$ such that every expectation value rescales like $⟨A⟩ → α ⟨A⟩$.

source
Sunny.set_vacancy_at!Method
set_vacancy_at!(sys::System, site::Site)

Make a single site nonmagnetic. Site includes a unit cell and a sublattice index.

source
Sunny.spin_labelMethod
spin_label(sys::System, i::Int)

If atom i carries a single spin-$s$ moment, then returns the half-integer label $s$. Otherwise, throws an error.

source
Sunny.spin_matricesMethod
spin_matrices(s)

Returns a triple of $N×N$ spin matrices, where $N = 2s+1$. These are the generators of SU(2) in the spin-s representation.

If s == Inf, then the return values are abstract symbols denoting infinite-dimensional matrices that commute. These can be useful for repeating historical studies, or modeling micromagnetic systems. A technical discussion appears in the Sunny documentation page: Interaction Renormalization.

Example

S = spin_matrices(3/2)
+set_pair_coupling!(sys, Si'*J1*Sj + (Si'*J2*Sj)^2, bond)

See also spin_matrices, to_product_space.

source
Sunny.set_pair_coupling_at!Method
set_pair_coupling_at!(sys::System, op, bond)

Sets an arbitrary coupling along the single bond connecting two Sites, ignoring crystal symmetry. Any previous coupling on this bond will be overwritten. The system must support inhomogeneous interactions via to_inhomogeneous.

Use symmetry_equivalent_bonds to find (site1, site2, offset) values that are symmetry equivalent to a given Bond in the original system. For systems that are relatively small, the offset vector (in multiples of unit cells) will resolve ambiguities in the periodic wrapping.

The operator op may be provided as an anonymous function that accepts two spin dipole operators, or as a matrix that acts in the tensor product space of the two sites. The documentation for set_pair_coupling! provides examples constructing op.

source
Sunny.set_spin_rescaling!Method
set_spin_rescaling!(sys, α)

In dipole mode, rescale all spin magnitudes $S → α S$. In SU(N) mode, rescale all SU(N) coherent states $Z → √α Z$ such that every expectation value rescales like $⟨A⟩ → α ⟨A⟩$.

source
Sunny.set_vacancy_at!Method
set_vacancy_at!(sys::System, site::Site)

Make a single site nonmagnetic. Site includes a unit cell and a sublattice index.

source
Sunny.spin_labelMethod
spin_label(sys::System, i::Int)

If atom i carries a single spin-$s$ moment, then returns the half-integer label $s$. Otherwise, throws an error.

source
Sunny.spin_matricesMethod
spin_matrices(s)

Returns a triple of $N×N$ spin matrices, where $N = 2s+1$. These are the generators of SU(2) in the spin-s representation.

If s == Inf, then the return values are abstract symbols denoting infinite-dimensional matrices that commute. These can be useful for repeating historical studies, or modeling micromagnetic systems. A technical discussion appears in the Sunny documentation page: Interaction Renormalization.

Example

S = spin_matrices(3/2)
 @assert S'*S ≈ (3/2)*(3/2+1)*I
 @assert S[1]*S[2] - S[2]*S[1] ≈ im*S[3]
 
 S = spin_matrices(Inf)
-@assert S[1]*S[2] - S[2]*S[1] == 0

See also print_stevens_expansion.

source
Sunny.spiral_energyMethod
spiral_energy(sys::System; k, axis)

Returns the energy of a generalized spiral phase associated with the propagation wavevector k (in reciprocal lattice units, RLU) and an axis vector that is normal to the polarization plane (in global Cartesian coordinates).

When $𝐤$ is incommensurate, this calculation can be viewed as creating an infinite number of periodic copies of sys. The spins on each periodic copy are rotated about the axis vector, with the angle $θ = 2π 𝐤⋅𝐫$, where 𝐫 denotes the displacement vector between periodic copies of sys in multiples of 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.

See also minimize_spiral_energy! and repeat_periodically_as_spiral.

source
Sunny.ssf_customMethod
ssf_custom(f, sys::System; apply_g=true, formfactors=nothing)

Specify measurement of the spin structure factor with a custom contraction function f. This function accepts a wavevector $𝐪$ in global Cartesian coordinates, and a 3×3 matrix with structure factor intensity components $\mathcal{S}^{αβ}(𝐪,ω)$. Indices $(α, β)$ denote dipole components in global coordinates. The return value of f can be any number or isbits type. With specific choices of f, one can obtain measurements such as defined in ssf_perp and ssf_trace.

By default, the g-factor or tensor is applied at each site, such that the structure factor components are correlations between the magnetic moment operators. Set apply_g = false to measure correlations between the bare spin operators.

The optional formfactors comprise a list of pairs [i1 => FormFactor(...), i2 => ...], where i1, i2, ... are a complete set of symmetry-distinct atoms, and each FormFactor implements $𝐪$-space attenuation for the given atom.

Intended for use with SpinWaveTheory and instances of SampledCorrelations.

Examples

# Measure all 3×3 structure factor components Sᵅᵝ
+@assert S[1]*S[2] - S[2]*S[1] == 0

See also print_stevens_expansion.

source
Sunny.spiral_energyMethod
spiral_energy(sys::System; k, axis)

Returns the energy of a generalized spiral phase associated with the propagation wavevector k (in reciprocal lattice units, RLU) and an axis vector that is normal to the polarization plane (in global Cartesian coordinates).

When $𝐤$ is incommensurate, this calculation can be viewed as creating an infinite number of periodic copies of sys. The spins on each periodic copy are rotated about the axis vector, with the angle $θ = 2π 𝐤⋅𝐫$, where 𝐫 denotes the displacement vector between periodic copies of sys in multiples of 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.

See also minimize_spiral_energy! and repeat_periodically_as_spiral.

source
Sunny.ssf_customMethod
ssf_custom(f, sys::System; apply_g=true, formfactors=nothing)

Specify measurement of the spin structure factor with a custom contraction function f. This function accepts a wavevector $𝐪$ in global Cartesian coordinates, and a 3×3 matrix with structure factor intensity components $\mathcal{S}^{αβ}(𝐪,ω)$. Indices $(α, β)$ denote dipole components in global coordinates. The return value of f can be any number or isbits type. With specific choices of f, one can obtain measurements such as defined in ssf_perp and ssf_trace.

By default, the g-factor or tensor is applied at each site, such that the structure factor components are correlations between the magnetic moment operators. Set apply_g = false to measure correlations between the bare spin operators.

The optional formfactors comprise a list of pairs [i1 => FormFactor(...), i2 => ...], where i1, i2, ... are a complete set of symmetry-distinct atoms, and each FormFactor implements $𝐪$-space attenuation for the given atom.

Intended for use with SpinWaveTheory and instances of SampledCorrelations.

Examples

# Measure all 3×3 structure factor components Sᵅᵝ
 measure = ssf_custom((q, ssf) -> ssf, sys)
 
 # Measure the structure factor trace Sᵅᵅ
-measure = ssf_custom((q, ssf) -> real(sum(ssf)), sys)

See also the Sunny documentation on Structure Factor Conventions.

source
Sunny.ssf_custom_bmMethod
ssf_custom_bm(f, sys::System; u, v, apply_g=true, formfactors=nothing)

Specify measurement of the spin structure factor with a custom contraction function f. The interface is identical to ssf_custom except that f here receives momentum $𝐪$ and the 3×3 structure factor data $\mathcal{S}^{αβ}(𝐪, ω)$ in the basis of the Blume-Maleev axis system. The wavevectors u and v, provided in reciprocal lattice units, will be used to define the scattering plane. In global Cartesian coordinates, the three orthonormal BM axes (e1, e2, e3) are defined as follows:

e3 = normalize(u × v)  # normal to the scattering plane (u, v)
+measure = ssf_custom((q, ssf) -> real(sum(ssf)), sys)

See also the Sunny documentation on Structure Factor Conventions.

source
Sunny.ssf_custom_bmMethod
ssf_custom_bm(f, sys::System; u, v, apply_g=true, formfactors=nothing)

Specify measurement of the spin structure factor with a custom contraction function f. The interface is identical to ssf_custom except that f here receives momentum $𝐪$ and the 3×3 structure factor data $\mathcal{S}^{αβ}(𝐪, ω)$ in the basis of the Blume-Maleev axis system. The wavevectors u and v, provided in reciprocal lattice units, will be used to define the scattering plane. In global Cartesian coordinates, the three orthonormal BM axes (e1, e2, e3) are defined as follows:

e3 = normalize(u × v)  # normal to the scattering plane (u, v)
 e1 = normalize(q)      # momentum transfer q within scattering plane
 e2 = normalize(e3 × q) # perpendicular to q and in the scattering plane

Example

# Measure imaginary part of S²³ - S³² in the Blume-Maleev axis system for
 # the scattering plane [0, K, L].
 measure = ssf_custom_bm(sys; u=[0, 1, 0], v=[0, 0, 1]) do q, ssf
     imag(ssf[2,3] - ssf[3,2])
-end
source
Sunny.ssf_perpMethod
ssf_perp(sys::System; apply_g=true, formfactors=nothing)

Specify measurement of the spin structure factor with contraction by $(I-𝐪⊗𝐪/q^2)$. The contracted value provides an estimate of unpolarized scattering intensity. In the singular limit $𝐪 → 0$, the contraction matrix is replaced by its rotational average, $(2/3) I$.

This function is a special case of ssf_custom.

Example

# Select Co²⁺ form factor for atom 1 and its symmetry equivalents
+end
source
Sunny.ssf_perpMethod
ssf_perp(sys::System; apply_g=true, formfactors=nothing)

Specify measurement of the spin structure factor with contraction by $(I-𝐪⊗𝐪/q^2)$. The contracted value provides an estimate of unpolarized scattering intensity. In the singular limit $𝐪 → 0$, the contraction matrix is replaced by its rotational average, $(2/3) I$.

This function is a special case of ssf_custom.

Example

# Select Co²⁺ form factor for atom 1 and its symmetry equivalents
 formfactors = [1 => FormFactor("Co2")]
-ssf_perp(sys; formfactors)
source
Sunny.ssf_traceMethod
ssf_trace(sys::System; apply_g=true, formfactors=nothing)

Specify measurement of the spin structure factor, with trace over spin components. This quantity can be useful for checking quantum sum rules.

This function is a special case of ssf_custom.

source
Sunny.standardizeMethod
standardize(cryst::Crystal; idealize=true)

Return the symmetry-inferred standardized crystal unit cell. If idealize=true, then the lattice vectors and site positions will be adapted. See "definitions and conventions" of the spglib documentation for more information.

source
Sunny.step!Function
step!(sys::System, dynamics)

Advance the spin configuration one dynamical time-step. The dynamics object may be a continuous spin dynamics, such as Langevin or ImplicitMidpoint, or it may be a discrete Monte Carlo sampling scheme such as LocalSampler.

source
Sunny.stevens_matricesMethod
stevens_matrices(s)

Returns a generator of Stevens operators in the spin-s representation. The return value O can be indexed as O[k,q], where $0 ≤ k ≤ 6$ labels an irrep of SO(3) and $-k ≤ q ≤ k$. This will produce an $N×N$ matrix where ``N = 2s

  • 1``. Linear combinations of Stevens operators can be used as a "physical

basis" for decomposing local observables. To see this decomposition, use print_stevens_expansion.

If s == Inf, then symbolic operators will be returned. In this infinite dimensional limit, the Stevens operators become homogeneous polynomials of commuting spin operators.

Example

O = stevens_matrices(2)
+ssf_perp(sys; formfactors)
source
Sunny.ssf_traceMethod
ssf_trace(sys::System; apply_g=true, formfactors=nothing)

Specify measurement of the spin structure factor, with trace over spin components. This quantity can be useful for checking quantum sum rules.

This function is a special case of ssf_custom.

source
Sunny.standardizeMethod
standardize(cryst::Crystal; idealize=true)

Return the symmetry-inferred standardized crystal unit cell. If idealize=true, then the lattice vectors and site positions will be adapted. See "definitions and conventions" of the spglib documentation for more information.

source
Sunny.step!Function
step!(sys::System, dynamics)

Advance the spin configuration one dynamical time-step. The dynamics object may be a continuous spin dynamics, such as Langevin or ImplicitMidpoint, or it may be a discrete Monte Carlo sampling scheme such as LocalSampler.

source
Sunny.stevens_matricesMethod
stevens_matrices(s)

Returns a generator of Stevens operators in the spin-s representation. The return value O can be indexed as O[k,q], where $0 ≤ k ≤ 6$ labels an irrep of SO(3) and $-k ≤ q ≤ k$. This will produce an $N×N$ matrix where ``N = 2s

  • 1``. Linear combinations of Stevens operators can be used as a "physical

basis" for decomposing local observables. To see this decomposition, use print_stevens_expansion.

If s == Inf, then symbolic operators will be returned. In this infinite dimensional limit, the Stevens operators become homogeneous polynomials of commuting spin operators.

Example

O = stevens_matrices(2)
 S = spin_matrices(2)
 
 A = (1/20)O[4,0] + (1/4)O[4,4] + (102/5)I
 B = S[1]^4 + S[2]^4 + S[3]^4
-@assert A ≈ B

See also spin_matrices and Interaction Renormalization.

source
Sunny.subcrystalMethod
subcrystal(cryst, types) :: Crystal

Filters sublattices of a Crystal by atom types, keeping the space group unchanged.

subcrystal(cryst, classes) :: Crystal

Filters sublattices of Crystal by equivalence classes, keeping the space group unchanged.

source
Sunny.suggest_magnetic_supercellMethod
suggest_magnetic_supercell(ks; tol=1e-12, maxsize=100)

Suggests a magnetic supercell, in units of the crystal lattice vectors, that is consistent with periodicity of the wavevectors ks in RLU. If the wavevectors are incommensurate (with respect to the maximum supercell size maxsize), one can select a larger error tolerance tol to find a supercell that is almost commensurate.

Prints a $3×3$ matrix of integers that is suitable for use in reshape_supercell.

Examples

# A magnetic supercell for a single-Q structure. Will print
+@assert A ≈ B

See also spin_matrices and Interaction Renormalization.

source
Sunny.subcrystalMethod
subcrystal(cryst, types) :: Crystal

Filters sublattices of a Crystal by atom types, keeping the space group unchanged.

subcrystal(cryst, classes) :: Crystal

Filters sublattices of Crystal by equivalence classes, keeping the space group unchanged.

source
Sunny.suggest_magnetic_supercellMethod
suggest_magnetic_supercell(ks; tol=1e-12, maxsize=100)

Suggests a magnetic supercell, in units of the crystal lattice vectors, that is consistent with periodicity of the wavevectors ks in RLU. If the wavevectors are incommensurate (with respect to the maximum supercell size maxsize), one can select a larger error tolerance tol to find a supercell that is almost commensurate.

Prints a $3×3$ matrix of integers that is suitable for use in reshape_supercell.

Examples

# A magnetic supercell for a single-Q structure. Will print
 k1 = [0, -1/4, 1/4]
 suggest_magnetic_supercell([k1])       # [1 0 0; 0 2 1; 0 -2 1]
 
@@ -153,17 +153,17 @@
 suggest_magnetic_supercell([[0, 0, 1/√5], [0, 0, 1/√7]]; tol=1e-2)
 
 # This prints [1 0 0; 0 1 0; 0 0 16], which becomes commensurate under the
-# approximations `1/√5 ≈ 7/16` and `1/√7 ≈ 3/8`.
source
Sunny.suggest_timestepMethod
suggest_timestep(sys, integrator; tol)

Suggests a timestep for the numerical integration of spin dynamics according to a given error tolerance tol. The integrator should be Langevin or ImplicitMidpoint. The suggested $dt$ will be inversely proportional to the magnitude of the effective field $|dE/d𝐬|$ arising from the current spin configuration in sys. The recommended timestep $dt$ scales like √tol, which assumes second-order accuracy of the integrator.

The system sys should be initialized to an equilibrium spin configuration for the target temperature. Alternatively, a reasonably timestep estimate can be obtained from any low-energy spin configuration. For this, one can use randomize_spins! and then minimize_energy!.

Large damping magnitude or target temperature kT will tighten the timestep bound. If damping exceeds 1, it will rescale the suggested timestep by an approximate the factor $1/damping$. If kT is the largest energy scale, then the suggested timestep will scale like 1/(damping*kT). Quantification of numerical error for stochastic dynamics is subtle. The stochastic Heun integration scheme is weakly convergent of order-1, such that errors in the estimates of averaged observables may scale like dt. This implies that the tol argument may actually scale like the square of the true numerical error, and should be selected with this in mind.

source
Sunny.symmetry_equivalent_bondsMethod
symmetry_equivalent_bonds(sys::System, bond::Bond)

Given a Bond for the original (unreshaped) crystal, return all symmetry equivalent bonds in the System. Each returned bond is represented as a pair of Sites, which may be used as input to set_exchange_at! or set_pair_coupling_at!. Reverse bonds are not included in the iterator (no double counting).

Example

for (site1, site2, offset) in symmetry_equivalent_bonds(sys, bond)
+# approximations `1/√5 ≈ 7/16` and `1/√7 ≈ 3/8`.
source
Sunny.suggest_timestepMethod
suggest_timestep(sys, integrator; tol)

Suggests a timestep for the numerical integration of spin dynamics according to a given error tolerance tol. The integrator should be Langevin or ImplicitMidpoint. The suggested $dt$ will be inversely proportional to the magnitude of the effective field $|dE/d𝐬|$ arising from the current spin configuration in sys. The recommended timestep $dt$ scales like √tol, which assumes second-order accuracy of the integrator.

The system sys should be initialized to an equilibrium spin configuration for the target temperature. Alternatively, a reasonably timestep estimate can be obtained from any low-energy spin configuration. For this, one can use randomize_spins! and then minimize_energy!.

Large damping magnitude or target temperature kT will tighten the timestep bound. If damping exceeds 1, it will rescale the suggested timestep by an approximate the factor $1/damping$. If kT is the largest energy scale, then the suggested timestep will scale like 1/(damping*kT). Quantification of numerical error for stochastic dynamics is subtle. The stochastic Heun integration scheme is weakly convergent of order-1, such that errors in the estimates of averaged observables may scale like dt. This implies that the tol argument may actually scale like the square of the true numerical error, and should be selected with this in mind.

source
Sunny.symmetry_equivalent_bondsMethod
symmetry_equivalent_bonds(sys::System, bond::Bond)

Given a Bond for the original (unreshaped) crystal, return all symmetry equivalent bonds in the System. Each returned bond is represented as a pair of Sites, which may be used as input to set_exchange_at! or set_pair_coupling_at!. Reverse bonds are not included in the iterator (no double counting).

Example

for (site1, site2, offset) in symmetry_equivalent_bonds(sys, bond)
     @assert site1 < site2
     set_exchange_at!(sys, J, site1, site2; offset)
-end
source
Sunny.to_product_spaceMethod
to_product_space(A, B, ...)

Given lists of operators acting on local Hilbert spaces individually, return the corresponding operators that act on the tensor product space. In typical usage, the inputs will represent local physical observables and the outputs will be used to define quantum couplings.

source
Sunny.@mix_proposalsMacro
@mix_proposals weight1 propose1 weight2 propose2 ...

Macro to generate a proposal function that randomly selects among the provided functions according to the provided probability weights. For use with LocalSampler.

Example

# A proposal function that proposes a spin flip 40% of the time, and a
+end
source
Sunny.to_product_spaceMethod
to_product_space(A, B, ...)

Given lists of operators acting on local Hilbert spaces individually, return the corresponding operators that act on the tensor product space. In typical usage, the inputs will represent local physical observables and the outputs will be used to define quantum couplings.

source
Sunny.@mix_proposalsMacro
@mix_proposals weight1 propose1 weight2 propose2 ...

Macro to generate a proposal function that randomly selects among the provided functions according to the provided probability weights. For use with LocalSampler.

Example

# A proposal function that proposes a spin flip 40% of the time, and a
 # Gaussian perturbation 60% of the time.
-@mix_proposals 0.4 propose_flip 0.6 propose_delta(0.2)
source

Optional Makie extensions

The following will be enabled through a package extension if either GLMakie or WGLMakie is loaded.

Sunny.plot_spinsFunction
plot_spins(sys::System; arrowscale=1.0, color=:red, colorfn=nothing,
+@mix_proposals 0.4 propose_flip 0.6 propose_delta(0.2)
source

Optional Makie extensions

The following will be enabled through a package extension if either GLMakie or WGLMakie is loaded.

Sunny.plot_spinsFunction
plot_spins(sys::System; arrowscale=1.0, color=:red, colorfn=nothing,
            colormap=:viridis, colorrange=nothing, show_cell=true, orthographic=false,
-           ghost_radius=0, ndims=3, compass=true)

Plot the spin configuration defined by sys. Optional parameters are:

  • arrowscale: Scale all arrows by dimensionless factor.
  • color: Arrow colors. May be symbolic or numeric. If scalar, will be shared among all sites.
  • colorfn: Function that dynamically maps from a site index to a numeric color value. Useful for animations.
  • colormap, colorrange: Used to populate colors from numbers following Makie conventions.
  • show_cell: Show original crystallographic unit cell.
  • orthographic: Use orthographic camera perspective.
  • ghost_radius: Show periodic images up to a given distance (length units).
  • ndims: Spatial dimensions of system (1, 2, or 3).
  • compass: If true, draw Cartesian axes in bottom left.

Calling notify on the return value will animate the figure.

source
Sunny.plot_spins!Function
plot_spins!(ax, sys::System; opts...)

Mutating variant of plot_spins that allows drawing into a single panel of a Makie figure.

Example

fig = Figure()
+           ghost_radius=0, ndims=3, compass=true)

Plot the spin configuration defined by sys. Optional parameters are:

  • arrowscale: Scale all arrows by dimensionless factor.
  • color: Arrow colors. May be symbolic or numeric. If scalar, will be shared among all sites.
  • colorfn: Function that dynamically maps from a site index to a numeric color value. Useful for animations.
  • colormap, colorrange: Used to populate colors from numbers following Makie conventions.
  • show_cell: Show original crystallographic unit cell.
  • orthographic: Use orthographic camera perspective.
  • ghost_radius: Show periodic images up to a given distance (length units).
  • ndims: Spatial dimensions of system (1, 2, or 3).
  • compass: If true, draw Cartesian axes in bottom left.

Calling notify on the return value will animate the figure.

source
Sunny.plot_spins!Function
plot_spins!(ax, sys::System; opts...)

Mutating variant of plot_spins that allows drawing into a single panel of a Makie figure.

Example

fig = Figure()
 plot_spins!(fig[1, 1], sys1)
 plot_spins!(fig[2, 1], sys2)
-display(fig)
source
Sunny.plot_intensitiesFunction
plot_intensities(res::BandIntensities; colormap=nothing, colorrange=nothing, allpositive=true,
+display(fig)
source
Sunny.plot_intensitiesFunction
plot_intensities(res::BandIntensities; colormap=nothing, colorrange=nothing, allpositive=true,
                  saturation=0.9, sensitivity=0.0025, fwhm=nothing, ylims=nothing, units=nothing,
                  into=nothing, title="")
 plot_intensities(res::Intensities; colormap=nothing, colorrange=nothing, allpositive=true, 
@@ -171,8 +171,8 @@
 plot_intensities(res::StaticIntensities; colormap=nothing, colorrange=nothing, allpositive=true, 
                  saturation=0.9, units=nothing, into=nothing, title="")
 plot_intensities(res::PowderIntensities; colormap=nothing, colorrange=nothing, allpositive=true, 
-                 saturation=0.9, units=nothing, into=nothing, title="")

Keyword arguments:

  • colormap: Color palette for plotting broadened intensities. See Makie docs for allowed values.
  • colorrange: A lower and upper bound on intensities. For heatmaps, these bounds define the intensity values that saturate the colormap.
  • allpositive: Should intensities be all positive, apart from numerical error? If true, the default colors will clip below zero intensity. If false, the default colors will be symmetric about zero intensity.
  • saturation: If colorrange is not explicitly set, this dimensionless parameter defines the upper saturated intensity value as a quantile of maximum intensities taken over wavevectors.
  • sensitivity: When plotting BandIntensities, this defines a lower bound on the visible intensities as a fraction of the upper saturated intensity value.
  • fwhm: When plotting BandIntensities, this overrides the full-width at half-maximum value used for Gaussian broadening.
  • ylims: Limits of the y-axis.
  • units: A Units instance for labeling axes and performing conversions.
  • into: A symbol for conversion into a new base energy unit (e.g. :meV, :K, etc.)
  • title: An optional title for the plot.
source
Sunny.plot_intensities!Function
plot_intensities!(panel, res::AbstractIntensities; opts...)

Mutating variant of plot_intensities that allows drawing into a single panel of a Makie figure.

Example

fig = Figure()
+                 saturation=0.9, units=nothing, into=nothing, title="")

Keyword arguments:

  • colormap: Color palette for plotting broadened intensities. See Makie docs for allowed values.
  • colorrange: A lower and upper bound on intensities. For heatmaps, these bounds define the intensity values that saturate the colormap.
  • allpositive: Should intensities be all positive, apart from numerical error? If true, the default colors will clip below zero intensity. If false, the default colors will be symmetric about zero intensity.
  • saturation: If colorrange is not explicitly set, this dimensionless parameter defines the upper saturated intensity value as a quantile of maximum intensities taken over wavevectors.
  • sensitivity: When plotting BandIntensities, this defines a lower bound on the visible intensities as a fraction of the upper saturated intensity value.
  • fwhm: When plotting BandIntensities, this overrides the full-width at half-maximum value used for Gaussian broadening.
  • ylims: Limits of the y-axis.
  • units: A Units instance for labeling axes and performing conversions.
  • into: A symbol for conversion into a new base energy unit (e.g. :meV, :K, etc.)
  • title: An optional title for the plot.
source
Sunny.plot_intensities!Function
plot_intensities!(panel, res::AbstractIntensities; opts...)

Mutating variant of plot_intensities that allows drawing into a single panel of a Makie figure.

Example

fig = Figure()
 plot_intensities!(fig[1, 1], res1; title="Panel 1")
 plot_intensities!(fig[2, 1], res2; title="Panel 2")
-display(fig)
source
Sunny.view_crystalFunction
view_crystal(crystal::Crystal; refbonds=10, orthographic=false, ghost_radius=nothing, ndims=3, compass=true)
-view_crystal(sys::System; ...)

Launches a graphical user interface to visualize the Crystal unit cell. If a System is provided, then the 3×3 exchange matrices for each bond will be depicted graphically.

  • refbonds: By default, calculate up to 10 reference bonds using the reference_bonds function. An explicit list of reference bonds may also be provided.
  • orthographic: Use orthographic camera perspective.
  • ghost_radius: Show periodic images up to a given distance. Defaults to the cell size.
  • ndims: Spatial dimensions of system (1, 2, or 3).
  • compass: If true, draw Cartesian axes in bottom left.
source

Optional WriteVTK extensions

The following will be enabled through a package extension if WriteVTK is loaded.

Sunny.export_vtkFunction
export_vtk(filename,params::BinningParameters,data)

Export a VTK-compatible file to filename (do not include file extension when specifying the file name) which contains the data as VTK Cell Data on a grid parameterized by params.

At least one axis of the BinningParameters must be integrated over, since VTK does not support 4D data. See integrate_axes!.

source
+display(fig)
source
Sunny.view_crystalFunction
view_crystal(crystal::Crystal; refbonds=10, orthographic=false, ghost_radius=nothing, ndims=3, compass=true)
+view_crystal(sys::System; ...)

Launches a graphical user interface to visualize the Crystal unit cell. If a System is provided, then the 3×3 exchange matrices for each bond will be depicted graphically.

  • refbonds: By default, calculate up to 10 reference bonds using the reference_bonds function. An explicit list of reference bonds may also be provided.
  • orthographic: Use orthographic camera perspective.
  • ghost_radius: Show periodic images up to a given distance. Defaults to the cell size.
  • ndims: Spatial dimensions of system (1, 2, or 3).
  • compass: If true, draw Cartesian axes in bottom left.
source

Optional WriteVTK extensions

The following will be enabled through a package extension if WriteVTK is loaded.

Sunny.export_vtkFunction
export_vtk(filename,params::BinningParameters,data)

Export a VTK-compatible file to filename (do not include file extension when specifying the file name) which contains the data as VTK Cell Data on a grid parameterized by params.

At least one axis of the BinningParameters must be integrated over, since VTK does not support 4D data. See integrate_axes!.

source
diff --git a/previews/PR318/objects.inv b/previews/PR318/objects.inv index 763576cfe..bf86d1b7c 100644 Binary files a/previews/PR318/objects.inv and b/previews/PR318/objects.inv differ diff --git a/previews/PR318/parallelism.html b/previews/PR318/parallelism.html index 266d4c36b..a73ac1585 100644 --- a/previews/PR318/parallelism.html +++ b/previews/PR318/parallelism.html @@ -69,4 +69,4 @@ end return sc -end

Finally, merge the results into a summary SampledCorrelations.

sc = merge_correlations(scs)
+end

Finally, merge the results into a summary SampledCorrelations.

sc = merge_correlations(scs)
diff --git a/previews/PR318/renormalization.html b/previews/PR318/renormalization.html index 3c9091b31..f0aa9d87d 100644 --- a/previews/PR318/renormalization.html +++ b/previews/PR318/renormalization.html @@ -49,4 +49,4 @@ \hat{\mathcal{O}}_{6,\pm2} & =\phi_{\pm}(\hat{S}_{+}^{2}\pm\hat{S}_{-}^{2})(33\hat{S}_{z}^{4}-(18X+123)\hat{S}_{z}^{2}+X^{2}+10X+102)+\mathrm{h.c.}\\ \hat{\mathcal{O}}_{6,\pm1} & =\phi_{\pm}(\hat{S}_{+}\pm\hat{S}_{-})(33\hat{S}_{z}^{5}-(30X-15)\hat{S}_{z}^{3}+(5X^{2}-10X+12)\hat{S}_{z})+\mathrm{h.c.}\\ \hat{\mathcal{O}}_{6,0} & =231\hat{S}_{z}^{6}-(315X-735)\hat{S}_{z}^{4}+(105X^{2}-525X+294)\hat{S}_{z}^{2}-5X^{3}+40X^{2}-60X -\end{align*}\]

Computer-generated tables of Stevens operators with $k > 6$ are available from C. Rudowicz and C. Y. Chung, J. Phys.: Condens. Matter 16, 5825 (2004), but these typically do not appear in magnetic simulations.

The case $k=1$ gives the dipole operators,

\[(\hat{\mathcal{O}}_{1,1}, \hat{\mathcal{O}}_{1,0}, \hat{\mathcal{O}}_{1,-1}) = (\hat{S}_{x}, \hat{S}_{z}, \hat{S}_{y}).\]

The case $k=2$ gives the quadrupole operators,

\[(\hat{\mathcal{O}}_{2,2}, \dots, \hat{\mathcal{O}}_{2,-2}) = \left(\hat{S}_x^2 - \hat{S}_y^2, \frac{\hat{S}_x \hat{S}_z + \hat{S}_z \hat{S}_x}{2}, 2\hat{S}_z^2-\hat{S}_x^2-\hat{S}_y^2, \frac{\hat{S}_y \hat{S}_z + \hat{S}_z \hat{S}_y}{2}, \hat{S}_x \hat{S}_y + \hat{S}_y \hat{S}_x\right).\]

For each $k$ value, the set of operators $\hat{\mathcal{O}}_{k,q'}$ for $q' = -k, \dots, k$ form an irreducible representation of the group of rotations O(3). That is, rotation will transform $\hat{\mathcal{O}}_{k,q}$ into a linear combination of $\hat{\mathcal{O}}_{k,q'}$ where $q'$ varies but $k$ remains fixed.

In taking the large-$s$ limit, each dipole operator is replaced by its expectation value $\boldsymbol{\Omega} = \langle \hat{\mathbf{S}} \rangle$, and only leading-order terms are retained. The operator $\hat{\mathcal{O}}_{k,q}$ becomes a homogeneous polynomial $O_{k,q}(\boldsymbol{\Omega})$ of order $k$ in the spin components $\Omega^\alpha$. One can see these polynomials by constructing stevens_matrices with the argument s = Inf. Due to the normalization constraint, each dipole can be expressed in polar angles, $(\theta, \phi)$. Then the Stevens functions $O_{k,q}(\boldsymbol{\Omega})$ correspond to the spherical harmonic functions $Y_l^m(\theta, \phi)$ where $l=k$ and $m=q$; this correspondence is valid up to $k$ and $q$-dependent rescaling factors.

+\end{align*}\]

Computer-generated tables of Stevens operators with $k > 6$ are available from C. Rudowicz and C. Y. Chung, J. Phys.: Condens. Matter 16, 5825 (2004), but these typically do not appear in magnetic simulations.

The case $k=1$ gives the dipole operators,

\[(\hat{\mathcal{O}}_{1,1}, \hat{\mathcal{O}}_{1,0}, \hat{\mathcal{O}}_{1,-1}) = (\hat{S}_{x}, \hat{S}_{z}, \hat{S}_{y}).\]

The case $k=2$ gives the quadrupole operators,

\[(\hat{\mathcal{O}}_{2,2}, \dots, \hat{\mathcal{O}}_{2,-2}) = \left(\hat{S}_x^2 - \hat{S}_y^2, \frac{\hat{S}_x \hat{S}_z + \hat{S}_z \hat{S}_x}{2}, 2\hat{S}_z^2-\hat{S}_x^2-\hat{S}_y^2, \frac{\hat{S}_y \hat{S}_z + \hat{S}_z \hat{S}_y}{2}, \hat{S}_x \hat{S}_y + \hat{S}_y \hat{S}_x\right).\]

For each $k$ value, the set of operators $\hat{\mathcal{O}}_{k,q'}$ for $q' = -k, \dots, k$ form an irreducible representation of the group of rotations O(3). That is, rotation will transform $\hat{\mathcal{O}}_{k,q}$ into a linear combination of $\hat{\mathcal{O}}_{k,q'}$ where $q'$ varies but $k$ remains fixed.

In taking the large-$s$ limit, each dipole operator is replaced by its expectation value $\boldsymbol{\Omega} = \langle \hat{\mathbf{S}} \rangle$, and only leading-order terms are retained. The operator $\hat{\mathcal{O}}_{k,q}$ becomes a homogeneous polynomial $O_{k,q}(\boldsymbol{\Omega})$ of order $k$ in the spin components $\Omega^\alpha$. One can see these polynomials by constructing stevens_matrices with the argument s = Inf. Due to the normalization constraint, each dipole can be expressed in polar angles, $(\theta, \phi)$. Then the Stevens functions $O_{k,q}(\boldsymbol{\Omega})$ correspond to the spherical harmonic functions $Y_l^m(\theta, \phi)$ where $l=k$ and $m=q$; this correspondence is valid up to $k$ and $q$-dependent rescaling factors.

diff --git a/previews/PR318/search_index.js b/previews/PR318/search_index.js index 1f487db69..c61742f61 100644 --- a/previews/PR318/search_index.js +++ b/previews/PR318/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"EditURL = \"../../../../examples/spinw_tutorials/SW13_LiNiPO4.jl\"","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html#SW13-LiNiPO","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"","category":"section"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"This is a Sunny port of SpinW Tutorial 13, originally authored by Sandor Toth. It calculates the spin wave spectrum of LiNiPO₄.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Load packages","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Build an orthorhombic lattice and populate the Ni atoms according to spacegroup 62 (Pnma).","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"units = Units(:meV, :angstrom)\na = 10.02\nb = 5.86\nc = 4.68\nlatvecs = lattice_vectors(a, b, c, 90, 90, 90)\npositions = [[1/4, 1/4, 0]]\ntypes = [\"Ni\"]\ncryst = Crystal(latvecs, positions, 62, setting=\"\"; types)\nview_crystal(cryst)","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Create a system with exchange parameters taken from T. Jensen, et al., PRB 79, 092413 (2009). The corrected anisotropy values are taken from the thesis of T. Jensen. The mode :dipole_large_s avoids a classical-to-quantum rescaling factor of anisotropy strengths, as needed for consistency with the original fits.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"S = 3/2\nsys = System(cryst, [1 => Moment(s=1, g=2)], :dipole_large_s)\nJbc = 1.036\nJb = 0.6701\nJc = -0.0469\nJac = -0.1121\nJab = 0.2977\nDa = 0.1969\nDb = 0.9097\nset_exchange!(sys, Jbc, Bond(2, 3, [0, 0, 0]))\nset_exchange!(sys, Jc, Bond(1, 1, [0, 0, -1]))\nset_exchange!(sys, Jb, Bond(1, 1, [0, 1, 0]))\nset_exchange!(sys, Jab, Bond(1, 2, [0, 0, 0]))\nset_exchange!(sys, Jab, Bond(3, 4, [0, 0, 0]))\nset_exchange!(sys, Jac, Bond(3, 1, [0, 0, 0]))\nset_exchange!(sys, Jac, Bond(4, 2, [0, 0, 0]))\nset_onsite_coupling!(sys, S -> Da*S[1]^2 + Db*S[2]^2, 1)","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Energy minimization yields a co-linear order along the c axis.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Calculate the spectrum along path [ξ, 1, 0]","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[0, 1, 0], [2, 1, 0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nfig = Figure(size=(768, 300))\nplot_intensities!(fig[1, 1], res; units);\nnothing #hide","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"There are two physical bands with nonvanishing intensity. To extract these intensity curves, we must filter out the additional bands with zero intensity. One way is to sort the data along dimension 1 (the band index) with the comparison operator \"is intensity less than 10^-12\". Doing so moves the physical bands to the end of the array axis. Call the Makie lines! function to make a custom plot.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"data_sorted = sort(res.data; dims=1, by= >(1e-12))\nax = Axis(fig[1, 2], xlabel=\"Momentum (r.l.u.)\", ylabel=\"Intensity\",\n xticks=res.qpts.xticks, xticklabelrotation=π/6)\nlines!(ax, data_sorted[end, :]; label=\"Lower band\")\nlines!(ax, data_sorted[end-1, :]; label=\"Upper band\")\naxislegend(ax)\nfig","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Make the same plots along path [0, 1, ξ]","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"qs = [[0, 1, 0], [0, 1, 2]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nfig = Figure(size=(768, 300))\nplot_intensities!(fig[1, 1], res; units)\n\ndata_sorted = sort(res.data; dims=1, by=x->abs(x)>1e-12)\nax = Axis(fig[1, 2], xlabel=\"Momentum (r.l.u.)\", ylabel=\"Intensity\",\n xticks=res.qpts.xticks, xticklabelrotation=π/6)\nlines!(ax, data_sorted[end, :]; label=\"Lower band\")\nlines!(ax, data_sorted[end-1, :]; label=\"Upper band\")\naxislegend(ax)\nfig","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"EditURL = \"../../../examples/03_LSWT_SU3_FeI2.jl\"","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#3.-Multi-flavor-spin-wave-simulations-of-FeI","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"This tutorial illustrates various advanced features such as symmetry analysis, energy minimization, and spin wave theory with multi-flavor bosons.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Our context will be FeI₂, an effective spin-1 material with strong single-ion anisotropy. Quadrupolar fluctuations give rise to a single-ion bound state that is observable in neutron scattering, and cannot be described by a dipole-only model. We will use the linear spin wave theory of SU(3) coherent states (i.e. 2-flavor bosons) to model the magnetic spectrum of FeI₂. The original study was performed in Bai et al., Nature Physics 17, 467–472 (2021).","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The Fe atoms are arranged in stacked triangular layers. The effective spin Hamiltonian takes the form,","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"mathcalH=sum_(ij) 𝐒_i J_ij 𝐒_j - Dsum_i left(S_i^zright)^2","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"where the exchange matrices J_ij between bonded sites (ij) include competing ferromagnetic and antiferromagnetic interactions. This model also includes a strong easy axis anisotropy, D 0.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Load packages.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Construct the chemical cell of FeI₂ by specifying the lattice vectors and the full set of atoms.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"units = Units(:meV, :angstrom)\na = b = 4.05012 # Lattice constants for triangular lattice (Å)\nc = 6.75214 # Spacing between layers (Å)\nlatvecs = lattice_vectors(a, b, c, 90, 90, 120)\npositions = [[0, 0, 0], [1/3, 2/3, 1/4], [2/3, 1/3, 3/4]]\ntypes = [\"Fe\", \"I\", \"I\"]\ncryst = Crystal(latvecs, positions; types)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Observe that the space group 'P -3 m 1' (164) has been inferred, as well as point group symmetries. Only the Fe atoms are magnetic, so we focus on them with subcrystal. Importantly, the new crystal retains the symmetry information for spacegroup 164.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"cryst = subcrystal(cryst, \"Fe\")\nview_crystal(cryst)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#Symmetry-analysis","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"Symmetry analysis","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The command print_symmetry_table provides a list of all the symmetry-allowed interactions out to 8 Å.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"print_symmetry_table(cryst, 8.0)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The allowed g-tensor is expressed as a 3×3 matrix in the free coefficients A, B, ... The allowed single-ion anisotropy is expressed as a linear combination of Stevens operators. The latter correspond to polynomials of the spin operators, as we will describe below.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The allowed exchange interactions are given as 3×3 matrices for representative bonds. The notation Bond(i, j, n) indicates a bond between atom indices i and j, with cell offset n. Note that the order of the pair (i j) is significant if the exchange tensor contains antisymmetric Dzyaloshinskii–Moriya (DM) interactions.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The bonds can be visualized in the view_crystal interface. By default, Bond(1, 1, [1,0,0]) is toggled on, to show the 6 nearest-neighbor Fe-Fe bonds on a triangular lattice layer. Toggling Bond(1, 1, [0,0,1]) shows the Fe-Fe bond between layers, etc.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#Defining-the-spin-model","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"Defining the spin model","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Construct a System with spin s=1 and g=2 for the Fe ions.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Recall that quantum spin-1 is, in reality, a linear combination of basis states m with well-defined angular momentum m = -1 0 1. FeI₂ has a strong easy-axis anisotropy, which stabilizes a single-ion bound state of zero angular momentum, m=0. Such a bound state is inaccessible to traditional spin wave theory, which works with dipole expectation values of fixed magnitude. This physics is, however, well captured with a theory of SU(N) coherent states, where N = 2S+1 = 3 is the number of levels. Activate this generalized theory by selecting :SUN mode instead of :dipole mode.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"An optional random number seed will make the calculations exactly reproducible.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :SUN, seed=2)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Set the exchange interactions for FeI₂ following the fits of Bai et al.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"J1pm = -0.236 # (meV)\nJ1pmpm = -0.161\nJ1zpm = -0.261\nJ2pm = 0.026\nJ3pm = 0.166\nJ′0pm = 0.037\nJ′1pm = 0.013\nJ′2apm = 0.068\n\nJ1zz = -0.236\nJ2zz = 0.113\nJ3zz = 0.211\nJ′0zz = -0.036\nJ′1zz = 0.051\nJ′2azz = 0.073\n\nJ1xx = J1pm + J1pmpm\nJ1yy = J1pm - J1pmpm\nJ1yz = J1zpm\n\nset_exchange!(sys, [J1xx 0.0 0.0;\n 0.0 J1yy J1yz;\n 0.0 J1yz J1zz], Bond(1,1,[1,0,0]))\nset_exchange!(sys, [J2pm 0.0 0.0;\n 0.0 J2pm 0.0;\n 0.0 0.0 J2zz], Bond(1,1,[1,2,0]))\nset_exchange!(sys, [J3pm 0.0 0.0;\n 0.0 J3pm 0.0;\n 0.0 0.0 J3zz], Bond(1,1,[2,0,0]))\nset_exchange!(sys, [J′0pm 0.0 0.0;\n 0.0 J′0pm 0.0;\n 0.0 0.0 J′0zz], Bond(1,1,[0,0,1]))\nset_exchange!(sys, [J′1pm 0.0 0.0;\n 0.0 J′1pm 0.0;\n 0.0 0.0 J′1zz], Bond(1,1,[1,0,1]))\nset_exchange!(sys, [J′2apm 0.0 0.0;\n 0.0 J′2apm 0.0;\n 0.0 0.0 J′2azz], Bond(1,1,[1,2,1]))","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The function set_onsite_coupling! assigns a single-ion anisotropy. The argument can be constructed using spin_matrices or stevens_matrices. Here we use Julia's anonymous function syntax to assign an easy-axis anisotropy along the direction hatz.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"D = 2.165 # (meV)\nset_onsite_coupling!(sys, S -> -D*S[3]^2, 1)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#Finding-the-ground-state","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"Finding the ground state","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"This model has been fitted so that energy minimization yields the physically correct ground state. Knowing this, we could set the magnetic configuration manually by calling set_dipole! on each site in the system. Another approach, as we will demonstrate, is to search for the ground-state via minimize_energy!.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"To reduce bias in the search, use resize_supercell to create a relatively large system of 4×4×4 chemical cells. Randomize all spins (represented as SU(3) coherent states) and minimize the energy.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"sys = resize_supercell(sys, (4, 4, 4))\nrandomize_spins!(sys)\nminimize_energy!(sys)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"A positive number above indicates that the procedure has converged to a local energy minimum. The configuration, however, may still have defects. This can be checked by visualizing the expected spin dipoles, colored according to their z-components.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"plot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"To better understand the spin configuration, we could inspect the static structure factor mathcalS(𝐪) in the 3D space of momenta 𝐪. The general tool for this analysis is SampledCorrelationsStatic. For the present purposes, however, it is more convenient to use print_wrapped_intensities, which reports mathcalS(𝐪) with periodic wrapping of all commensurate 𝐪 wavevectors into the first Brillouin zone.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"print_wrapped_intensities(sys)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The known zero-field energy-minimizing magnetic structure of FeI₂ is a two-up, two-down order. It can be described as a generalized spiral with a single propagation wavevector 𝐤. Rotational symmetry allows for three equivalent orientations: 𝐤 = 0 -14 14, 14 0 14, or -141414. Small systems can spontaneously break this symmetry, but for larger systems, defects and competing domains are to be expected. Nonetheless, print_wrapped_intensities shows large intensities consistent with a subset of the known ordering wavevectors.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Let's break the three-fold symmetry by hand. The function suggest_magnetic_supercell takes one or more 𝐤 modes, and suggests a magnetic cell shape that is commensurate.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"suggest_magnetic_supercell([[0, -1/4, 1/4]])","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Calling reshape_supercell yields a much smaller system, making it much easier to find the global energy minimum. Plot the system again, now including \"ghost\" spins out to 12Å, to verify that the magnetic order is consistent with FeI₂.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"sys_min = reshape_supercell(sys, [1 0 0; 0 2 1; 0 -2 1])\nrandomize_spins!(sys_min)\nminimize_energy!(sys_min);\nplot_spins(sys_min; color=[S[3] for S in sys_min.dipoles], ghost_radius=12)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#Spin-wave-theory","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"Spin wave theory","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Now that the system has been relaxed to an energy minimized ground state, we can calculate the spin wave spectrum. Because we are working with a system of SU(3) coherent states, this calculation will require a multi-flavor boson generalization of the usual spin wave theory.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"swt = SpinWaveTheory(sys_min; measure=ssf_perp(sys_min))","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Calculate and plot the spectrum along a momentum-space path that connects a sequence of high-symmetry 𝐪-points. This interface abstracts over the underlying calculator type.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"qs = [[0,0,0], [1,0,0], [0,1,0], [1/2,0,0], [0,1,0], [0,0,0]]\npath = q_space_path(cryst, qs, 500)\nres = intensities_bands(swt, path)\nplot_intensities(res; units, title=\"Single Crystal Bands\")","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"To make direct comparison with inelastic neutron scattering (INS) data, we must account for empirical broadening of the data. Model this using a lorentzian kernel, with a full-width at half-maximum of 0.3 meV.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"kernel = lorentzian(fwhm=0.3)\nenergies = range(0, 10, 300); # 0 < ω < 10 (meV)\nnothing #hide","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Also, a real FeI₂ sample will exhibit competing magnetic domains. We use domain_average to average over the three possible domain orientations. This involves 120° rotations about the axis hatz = 0 0 1 in global Cartesian coordinates.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"rotations = [([0,0,1], n*(2π/3)) for n in 0:2]\nweights = [1, 1, 1]\nres = domain_average(cryst, path; rotations, weights) do path_rotated\n intensities(swt, path_rotated; energies, kernel)\nend\nplot_intensities(res; units, colormap=:viridis, title=\"Domain Averaged Intensities\")","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"This result can be directly compared to experimental neutron scattering data from Bai et al.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"(The publication figure used a non-standard coordinate system to label the wave vectors.)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"To get this agreement, the theory of SU(3) coherent states is essential. The lower band has large quadrupolar character, and arises from the strong easy-axis anisotropy of FeI₂.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"An interesting exercise is to repeat the same study, but using :dipole mode instead of :SUN. That alternative choice would constrain the coherent state dynamics to the space of dipoles only, and the flat band of single-ion bound states would be missing.","category":"page"},{"location":"parallelism.html#Parallelizing-Calculations","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"","category":"section"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Calculating structure factors with classical dynamics is computationally expensive, and Sunny does not currently parallelize these calculations at a fine-grained level. However, Julia provides facilities that allow users to run multiple simulations in parallel with only a little extra effort. We will look at two approaches to doing this: multithreading and Julia's Distributed package. We'll present these approaches in a series of code snippets that can be copied and pasted into your preferred Julia development environment.","category":"page"},{"location":"parallelism.html#Review-of-the-serial-workflow","page":"Parallelizing Calculations","title":"Review of the serial workflow","text":"","category":"section"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"The serial approach to calculating a structure factor, covered in the FeI₂ tutorial, involves thermalizing a spin System and then calling add_sample!. 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 mathcalS(𝐪ω). This sequence is repeated to generate additional samples.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"To illustrate, we'll set up a a simple model: a spin-1 antiferromagnet on a BCC crystal. ","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"using Sunny, GLMakie\n\nfunction make_system(; seed=nothing)\n latvecs = lattice_vectors(1, 1, 1, 90, 90, 90)\n positions = [[0, 0, 0]/2, [1, 1, 1]/2]\n cryst = Crystal(latvecs, positions)\n sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(10, 10, 2), seed)\n set_exchange!(sys, 1.0, Bond(1, 1, [1, 0, 0]))\n return sys\nend\n\nsys = make_system()","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"A serial calculation of SampledCorrelations involving the Langevin sampling method can now be performed as follows:","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"# Thermalize the system\ndt = 0.05\nintegrator = Langevin(dt; damping=0.2, kT=0.5)\nfor _ in 1:5000\n step!(sys, integrator)\nend\n\n# Accumulator for S(q,ω) samples\n\nenergies = range(0.0, 10.0, 100)\nmeasure = ssf_perp(sys)\nsc = SampledCorrelations(sys; dt=0.1, energies, measure)\n\n# Collect 10 samples\nfor _ in 1:10\n for _ in 1:1000\n step!(sys, integrator)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"This will take a second or two on a modern workstation, resulting in a single SampledCorrelations that contains 10 samples.","category":"page"},{"location":"parallelism.html#Multithreading-approach","page":"Parallelizing Calculations","title":"Multithreading approach","text":"","category":"section"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"To use threads in Julia, you must launch your Julia environment appropriately.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"From the command line, launch Julia with julia --threads=auto. With this option, Julia will automatically use an optimal number of threads.\nJupyter notebook users will need to to set up a multithreaded Julia kernel and restart into this kernel. The kernel can be created inside Julia with the command IJulia.installkernel(\"Julia Multithreaded\", env=Dict(\"JULIA_NUM_THREADS\" => \"auto\")).\nVSCode users should open their settings and search for Julia: Additional Args. There will be link called Edit in settings.json. Click on this, add \"--threads=auto\" to the list julia.additionalArgs, and start a new REPL.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Before going further, make sure that Threads.nthreads() returns a number greater than 1.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"We will use multithreading in a very simple way, essentially employing a distributed memory approach to avoid conflicts around memory access. First preallocate a number of systems and correlations.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"npar = Threads.nthreads()\nsystems = [make_system(; seed=id) for id in 1:npar]\nscs = [SampledCorrelations(sys; dt=0.1, energies, measure) for _ in 1:npar]","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"warning: Dealing with memory constraints\nIf you have many threads available and are working with a large system, you may not have enough memory to store all these systems and correlations. In that case, simply reduce npar to a small enough value that you can make the necessary allocations.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"When the Threads.@threads macro is applied before a for loop, the iterations of the loop will execute in parallel using the available threads. We will put the entire thermalization and sampling process inside the loop, with each thread acting on a unique System and SampledCorrelations.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Threads.@threads for id in 1:npar\n integrator = Langevin(dt; damping=0.2, kT=0.5)\n for _ in 1:5000\n step!(systems[id], integrator)\n end\n for _ in 1:10\n for _ in 1:1000\n step!(systems[id], integrator)\n end\n add_sample!(scs[id], systems[id])\n end\nend","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"You may find this takes a little bit longer than the serial example, but, at the end of it, you will have generated npar correlation objects, each with 10 samples. We can merge these into a summary SampledCorrelations with 10*npar samples with merge_correlations:","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"sc = merge_correlations(scs)","category":"page"},{"location":"parallelism.html#Using-Distributed","page":"Parallelizing Calculations","title":"Using Distributed","text":"","category":"section"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Julia also provides a distributed memory approach to parallelism through the standard library package Distributed. This works by launching independent Julia environments on different \"processes.\" An advantage of this approach is that it scales naturally to clusters since the processes are easily distributed across many different compute nodes. A disadvantage, especially when working on a single computer, is the increased memory overhead associated with launching all these environments.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"We begin by importing the package,","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"using Distributed","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"and launching some new processes. It is often sensible to create as many processes as there are cores.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"ncores = length(Sys.cpu_info())\naddprocs(ncores)","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"You can think of each process as a separate computer running a fresh Julia environment, so we'll need to import Sunny and define functions in each of these environments. This is easily achieved with the @everywhere macro.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"@everywhere using Sunny\n\n@everywhere function make_system(; seed=nothing)\n latvecs = lattice_vectors(1, 1, 1, 90, 90, 90)\n positions = [[0, 0, 0]/2, [1, 1, 1]/2]\n cryst = Crystal(latvecs, positions)\n sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; seed)\n sys = resize_supercell(sys, (10, 10, 2))\n set_exchange!(sys, 1.0, Bond(1, 1, [1, 0, 0]))\n return sys\nend","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"A simple way to perform work on these processes is to use the parallel map function, pmap. This will apply a function to each element of some iterable, such as a list of numbers, and return a list of the results. It is a parallel map because these function calls may occur at the same time on different Julia processes. The pmap function takes care of distributing the work among the different processes and retrieving the results.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"In the example below, we give pmap a list of RNG seeds to iterate over, and we define the function that will be applied to each of these seeds in a do block. The contents of this block are essentially the same as what we put inside our parallel for loop in the multithreading example. The main difference is that the Systems and SampledCorrelations are not created in advance of the parallelization but are instead created inside each Julia process. The do block returns a SampledCorrelations, and the output of all the parallel computations are collected into list of SampledCorrelations called scs.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"scs = pmap(1:ncores) do id\n sys = make_system(; seed=id)\n sc = SampledCorrelations(sys; dt=0.1, energies, measure)\n integrator = Langevin(0.05; damping=0.2, kT=0.5)\n\n for _ in 1:5000\n step!(sys, integrator)\n end\n for _ in 1:10\n for _ in 1:1000 \n step!(sys, integrator)\n end\n add_sample!(sc, sys)\n end\n\n return sc\nend","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Finally, merge the results into a summary SampledCorrelations.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"sc = merge_correlations(scs)","category":"page"},{"location":"structure-factor.html#Structure-Factor-Conventions","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"","category":"section"},{"location":"structure-factor.html#Dynamical-correlations","page":"Structure Factor Conventions","title":"Dynamical correlations","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Dynamical correlations are a fundamental observable in condensed matter systems, and facilitate comparison between theory and experimental data.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Frequently, spin-spin correlations are of interest. More generally, one may consider correlations between arbitrary operator fields hatA and hatB. In the Heisenberg picture, operators evolve in time. Consider the dynamical correlation as an equilibrium expectation value,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐫 t) = int_V hatB^(𝐫₀ 0) hatA(𝐫₀ + 𝐫 t) d𝐫₀\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"where the integral runs over some macroscopic volume V . By construction, C(𝐫 t) is an extensive quantity. Ignoring surface effects, the correlation becomes an ordinary product in momentum-space,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐪 t) = hatB_𝐪^(0) hatA_𝐪(t)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Our convention for the Fourier transform from position 𝐫 to momentum 𝐪 is,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatA_𝐪 int_V e^+ i 𝐪𝐫 hatA(𝐫) d𝐫\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"For a Hermitian operator hatA^(𝐫) = hatA(𝐫), it follows that hatA_𝐪^ (hatA_𝐪)^ = hatA_-𝐪 in momentum space. ","category":"page"},{"location":"structure-factor.html#Lehmann-representation-in-frequency-space","page":"Structure Factor Conventions","title":"Lehmann representation in frequency space","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Dynamical correlations are most conveniently calculated in frequency space. We use the convention,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐪 ω) frac12π int_-^ e^-iωt C(𝐪 t) dt\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"On the right-hand side, substitute the definition of Heisenberg time evolution,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatA(t) e^i t hatH hatA e^-i t hatH\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"and the definition of the thermal average,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatO frac1mathcalZmathrmtr e^-β hatH hatO quad mathcalZ mathrmtr e^-β hatH\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Let ϵ_μ and μ denote the exact eigenvalues and eigenstates of the full Hamiltonian hatH. The eigenstates comprise a complete, orthonormal basis. The operator trace can be evaluated as a sum over eigenbasis states ν. Insert a resolution of the identity, μμ = 1, with implicit summation on the repeated μ index. Then, collecting results and applying,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nint_-^ e^-iωt dt = 2πδ(ω)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"the result is the Lehmann representation of dynamical correlations,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐪ω) = frac1mathcalZ e^-β ϵ_ν δ(ϵ_μ - ϵ_ν - ω) νhatB^_𝐪μμhatA_𝐪 ν\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"with implicit summation over eigenbasis indices μ and ν. This representation is the usual starting point for quantum calculations such as linear spin wave theory and its various generalizations.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Using the Lehmann representation, it can be shown that positive and negative frequencies are linked through a detailed balance condition,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC_BA^(𝐪-ω) = e^-β ω C_B^A(𝐪 ω)^*\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"This subscript notation indicates that the left-hand side is a correlation of Hermitian-conjugated operators. Typically hatA and hatB will be Hermitian in real-space, and then detailed balance becomes C(-𝐪-ω) = e^-β ω C(𝐪 ω)^*.","category":"page"},{"location":"structure-factor.html#Discrete-sums-on-the-lattice","page":"Structure Factor Conventions","title":"Discrete sums on the lattice","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"A chemical (crystallographic) unit cell is associated with three lattice vectors 𝐚_123. Site positions are","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\n𝐫_𝐦j m_1 𝐚_1 + m_2 𝐚_2 + m_3 𝐚_3 + δ𝐫_j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"for integers 𝐦 = m_1 m_2 m_3. If the crystal is decorated, then δ𝐫_j denotes the relative displacement of the Bravais sublattice j. ","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Let hatA(𝐫) be decomposed into discrete contributions hatA_𝐦j δ(𝐫-𝐫_𝐦j) at each lattice point 𝐫_𝐦j. The Fourier transform becomes a discrete sum,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatA_𝐪 = sum_j sum_𝐦 e^i 𝐪𝐫_𝐦j hatA_𝐦j sum_j hatA_𝐪j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The second equality above introduces hatA_𝐪j as the Fourier transform of hatA_𝐦j for single sublattice j. It can also be written,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatA_𝐪j = e^i 𝐪δ𝐫_j sum_𝐦 e^i 2π tilde𝐪𝐦 hatA_𝐦j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"where tilde𝐪 expresses momentum in dimensionless reciprocal lattice units (RLU),","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\n𝐪 = tildek_1 𝐛_1 + tildek_2 𝐛_2 + tildek_3 𝐛_3\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"and 𝐛_123 are the reciprocal lattice vectors. Equivalently, tildek_μ 𝐪 𝐚_μ 2π.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"It will be convenient to introduce a dynamical correlation for the operators on sublattices i and j only,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC_ij(𝐪t) hatB^_𝐪i(0) hatA_𝐪j(t)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"By the linearity of expectation values,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐪 t) = sum_ij C_ij(𝐪t)\nendequation","category":"page"},{"location":"structure-factor.html#Quantum-sum-rule","page":"Structure Factor Conventions","title":"Quantum sum rule","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Integrating over all frequencies ω yields the instant correlation at real-time t = 0,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nint_-^ C(𝐪ω) dω = C(𝐪 t=0) = sum_ij C_ij(𝐪 t=0)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Here, we will investigate spin-spin correlations. For this, select hatB_𝐪i = hat𝐒_𝐪i and A_𝐪j = hat𝐒_𝐪j, such that the dynamical correlations become tensor valued,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC_ij^αβ(𝐪 t=0) = hatS_𝐪i^α hatS_𝐪j^β\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"In the quantum spin-s representation, the spin dipole on one site satisfies","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhat𝐒^2 = hatS^α hatS^α = s(s+1)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"with implicit summation on the repeated α index.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Suppose that each site of sublattice j carries quantum spin of magnitude s_j. Then there is a quantum sum rule of the form,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nint_tildeV_mathrmBZ fracC_jj^αα(𝐪 t=0)N_mathrmcells dtilde𝐪 = s_j (s_j + 1)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"with summation on α, but not j, implied. The integral runs over the cubic volume in reciprocal lattice units tilde𝐪,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\ntildeV_mathrmBZ 01^3\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"This volume represents one unit cell on the reciprocal lattice, and has the shape of a parallelepiped in physical momentum units 𝐪. This volume is equivalent to the first Brillouin zone because of the reciprocal-space periodicity inherent to the Bravais sublattice. Note that the integral over tilde𝐪 tildeV_mathrmBZ could be converted to an integral over physical momentum 𝐪 by applying a Jacobian transformation factor, d tilde𝐪 = d𝐪 V_mathrmcell (2π)^3, where V_mathrmcell = 𝐚_1 (𝐚_2 𝐚_3) is the volume of the chemical unit cell. The scaling factor","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nN_mathrmcells V V_mathrmcell\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"denotes the number of chemical unit cells in the macroscopic volume V.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The derivation of the sum rule proceeds as follows. Substitute twice the definition,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatS^α_𝐪j e^i 𝐪δ𝐫_j sum_𝐦 e^i 2π tilde𝐪𝐦 hatS^α_𝐦j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Accounting for complex conjugation, the two phase factors e^i 𝐪δ𝐫_j cancel. The remaining 𝐪-dependence can be integrated to yield a Kronecker-δ,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nint_tildeV_mathrmBZ e^2πi tilde𝐪 (𝐦 - 𝐦) dtilde𝐪 = δ_𝐦 𝐦\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Note that hatS_𝐦j^α hatS_𝐦j^α = s_j(s_j+1) is constant, independent of the cell 𝐦. This leaves a double sum over integers 𝐦, which evaluates to sum_𝐦 𝐦 δ_𝐦 𝐦 = N_mathrmcells. Combined, these results verify the above-stated quantum sum rule for the sublattice j.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"One can also derive a quantum sum rule on the full dynamical correlation C^α β(𝐪 ω). Contributions from distinct sublattices i j introduce a phase factor e^- i 𝐪(δ𝐫_i - δ𝐫_j) that cancels when the momentum 𝐪 is averaged over a large number N_mathrmBZ of Brillouin zones. The final result is a sum over contributions C_jj(𝐪 t=0) for each sublattice j,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nfrac1N_mathrmBZ int_N_mathrmBZ tildeV_mathrmBZ int_-^ fracC^αα(𝐪 ω) N_mathrmcells dω dtilde𝐪 = sum_j s_j (s_j + 1)\nendequation","category":"page"},{"location":"structure-factor.html#Neutron-scattering-cross-section","page":"Structure Factor Conventions","title":"Neutron scattering cross section","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The magnetic moment of a neutron is hatboldsymbolμ_mathrmneutron = - 2 γ μ_N hat𝐒_mathrmneutron, where γ = 1913, μ_N is the nuclear magneton, and hat𝐒_mathrmneutron is spin-1/2 angular momentum. Neutrons interact with the magnetic moments of a material. These have the form hatboldsymbolμ = -μ_B g hat𝐒, where μ_B is the Bohr magneton and hat𝐒 is the effective angular momentum. For a single electron, g = 20023 is known to high precision. Within a crystal, however, the appropriate g_j for each sublattice j may be any 33 matrix consistent with point group symmetries.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Each idealized magnetic moment hatboldsymbolμ_𝐦j is, in reality, smoothly distributed around the site position 𝐫_𝐦 j. This can be modeled through convolution with a density function f_j(𝐫). Fourier transform the full magnetic density field 𝐌(𝐫) to obtain","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhat𝐌_𝐪 sum_j hat𝐌_𝐪j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"where,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhat𝐌_𝐪j - μ_B e^i 𝐪δ𝐫_j g_j sum_𝐦 e^i 2π tilde𝐪𝐦 hat𝐒_𝐦j f_j(𝐪)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"In Fourier space, f_j(𝐪) is called the magnetic form factor. Frequently, it will be approximated as an isotropic function of q = 𝐪. Tabulated formula, for various magnetic ions and charge states, are available in Sunny via the FormFactor function. The idealized case f_j(𝐪) = 1 would describe completely localized magnetic moments.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Neutron scattering intensities are given by the total differential cross-section, d^2 σ(𝐪 ω)dωdΩ, where 𝐪 = 𝐪_i - 𝐪_f is the momentum transfer to the sample, ω is the energy transfer to the sample, and Ω is the solid angle. Experimental intensity data will typically be provided in units of q_f q_i. Within the dipole approximation, the result for an unpolarized neutron beam is,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nfracd^2 σ(𝐪 ω)dω dΩ = fracq_fq_i left(fracγ r_02right)^2 sum_αβ left(δ_αβ - fracq^α q^βq^2right) fracmathcalS^αβ(𝐪 ω)μ_B^2\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The prefactor q_fq_i will be provided experimentally. Dimensions of area arise from the characteristic scattering length, γ r_0 2 26910^-5 mathrmÅ, where r_0 is the classical electron radius.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The structure factor is of central importance to neutron scattering,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nmathcalS^αβ(𝐪 ω) frac12π int_-^ e^-iωt hatM_𝐪^α(0) hatM_𝐪^β(t) dt\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"and describes dynamical correlations of magnetic moments. It will differ nontrivially from the spin-spin correlations if the g_j-tensor varies with sublattice j.","category":"page"},{"location":"structure-factor.html#Conventions-for-the-Sunny-calculated-structure-factor","page":"Structure Factor Conventions","title":"Conventions for the Sunny-calculated structure factor","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"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 as well as the complete Library API.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Through ssf_custom and related functions, Sunny will calculate the spin structure factor as a 3×3 matrix in dimensionless units,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\n𝒮^αβ(𝐪 ω) frac1N_mathrmcells μ_B^2 mathcalS^αβ(𝐪 ω)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"This is an intensive quantity because N_mathrmcells, the number of chemical cells in the macroscopic sample, is extensive. Note that the Sunny-calculated intensity will depend on the chemical cell convention: intensity scales linearly with chemical cell size.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Use ssf_perp to contract with δ_αβ - q^α q^βq^2, i.e., to project in the direction perpendicular to momentum transfer 𝐪.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Set apply_g = false to calculate the correlation C_𝐒𝐒(𝐪 ω) N_mathrmcells between pure spin operators, rather than between magnetic moments. In this special case that g is a uniform scalar, this is equivalent to 𝒮(𝐪 ω) g^2","category":"page"},{"location":"structure-factor.html#Calculations-with-spin-wave-theory","page":"Structure Factor Conventions","title":"Calculations with spin wave theory","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Calculating the dynamical structure factor with linear SpinWaveTheory 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 to study generalized spiral phases, which allow for an incommensurate propagation wavevector. The experimental module SpinWaveTheoryKPM implements spin wave calculations using the kernel polynomial method. 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.","category":"page"},{"location":"structure-factor.html#Calculations-with-classical-spin-dynamics","page":"Structure Factor Conventions","title":"Calculations with classical spin dynamics","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Finite temperature structure factor intensities can be estimated from the dynamical correlations of classical spin dynamics (e.g. Landau-Lifshitz, or its SU(N) generalization). This is fundamentally a Monte Carlo approach, as the trajectories must be initialized to a spin configuration that is sampled from the finite-temperature thermal equilibrium. Samples are accumulated into a SampledCorrelations, from which intensity information may be extracted.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Creating a SampledCorrelations requires specifying three keyword arguments. These will determine the dynamics used to calculate samples and, consequently, the ω information that will be available. ","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"energies: A uniform range of resolved energies.\ndt: The step size for dynamical time-integration. Larger may reduce simulation time, but the choice will be limited by the stability and accuracy requirements of the ImplicitMidpoint integration method. The function suggest_timestep can recommend a good value. The timestep may be adjusted downward so that the specified energies are sampled exactly.\nmeasure: Specification of the pair correlations. This will frequently be reduced from the spin structure factor using one of ssf_trace, ssf_perp, or ssf_custom_bm.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"A sample may be added by calling add_sample!. The input sys must be a spin configuration in good thermal equilibrium, e.g., using the continuous Langevin dynamics or using single spin flip trials with LocalSampler. The statistical quality of the 𝒮(𝐪ω) can be improved by repeatedly generating decorrelated spin configurations in sys and calling add_sample! on each configuration.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The outline of typical use case might look like this:","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"# Make a `SampledCorrelations`\nsc = SampledCorrelations(sys; dt=0.05, energies=range(0.0, 10.0, 100))\n\n# Add samples\nfor _ in 1:nsamples\n decorrelate_system(sys) # Perform some type of Monte Carlo simulation\n add_sample!(sc, sys) # Use spins to calculate trajectory and accumulate new sample of 𝒮(𝐪,ω)\nend","category":"page"},{"location":"structure-factor.html#Extracting-intensities-sampled-correlation-data","page":"Structure Factor Conventions","title":"Extracting intensities sampled correlation data","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Like in spin wave theory, the basic function for extracting intensities information from a SampledCorrelations is intensities. It takes a SampledCorrelations, a collection of 𝐪-vectors, a collection of energies, and possible other options.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Since classical dynamics simulation take place on a finite lattice, the fundamental intensities measurements are only available at a discrete grid of wave vectors. In reciprocal lattice units, available grid points are 𝐪 = fracn_1L_1 fracn_2L_2 fracn_3L_3, where n_i runs from (frac-L_i2+1) to fracL_i2 and L_i is the linear dimension of the lattice used in the calculation. (An internal function Sunny.available_wave_vectors provides access to this grid.) By default intensities will adjust each wavevector 𝐪 to the nearest available grid point. ","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Similarly, the resolution in energies is controlled the dynamical trajectory length in real-time. Because the dynamical trajectory is not periodic in time, some blurring between neighboring energy bins is unavoidable. Sunny's algorithm for estimating the structure factor from real-time dynamics is specified here.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The temperature parameter kT is required for SampledCorrelations calculations, and will be used to perform classical-to-quantum rescaling of intensities. If kT = nothing, then intensities will be provided according to the classical Boltzmann distribution.","category":"page"},{"location":"structure-factor.html#The-instantaneous-structure-factor","page":"Structure Factor Conventions","title":"The instantaneous structure factor","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Use intensities_static to calculate mathcalS(𝐪), i.e., correlations that are \"instantaneous\" in real-time. Mathematically, mathcalS(𝐪) denotes an integral of the dynamical structure factor mathcalS(𝐪 ω) over all energies ω. In SpinWaveTheory, the energy integral becomes a discrete sum over bands. In SampledCorrelations, a classical-to-quantum correction factor will be applied within intensities prior to energy integration.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Sunny also supports a mechanism to calculate static correlations without any spin dynamics. To collect such statistics, construct a SampledCorrelationsStatic object. In this case, intensities_static will return static correlations sampled from the classical Boltzmann distribution. This dynamics-free approach is faster, but may miss important features that derive from the quantum mechanical excitation spectrum.","category":"page"},{"location":"writevtk.html#ParaView-Rendering","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"section"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"The 4D correlation data produced by Sunny is too high-dimensional to visualize directly. This page describes how to export 3D slices of correlation data from Sunny to the Visual ToolKit (VTK) format, which is compatible with the ParaView visualization software. ParaView supports volumetric rendering:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html#Simulation-data","page":"ParaView Rendering","title":"Simulation data","text":"","category":"section"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"First, generate some correlation data in Sunny. We will use a 2D lattice, since the correlation data S(Q_xQ_yomega) is 3D and can be exported in its entirety. The following code sets up the system, thermalizes it, and records the correlation data in a SampledCorrelations called dsf.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"using Sunny\n\nlatvecs = lattice_vectors(8.,8.,12.,90,100,90)\npositions = [[0,0,0]]\ntypes = [\"Cu\"]\nformfactors = [FormFactor(\"Cu2\")]\nxtal = Crystal(latvecs, positions; types)\n\nsys = System(xtal, [1 => Moment(s=1/2, g=2)], :SUN; dims=(12, 12, 1), seed=1)\n\nJ = 10.\nset_exchange!(sys, J, Bond(1,1,[1,0,0]))\nset_exchange!(sys, J, Bond(1,1,[0,1,0]))\n\ndt = 0.01\nkT = 0.5\nlangevin = Langevin(dt; damping=0.5, kT)\nrandomize_spins!(sys)\nfor i in 1:10_000 # Long enough to reach equilibrium\n step!(sys, langevin)\nend \n\nωmax=10.\ndsf = SampledCorrelations(sys; dt, energies=range(0, ωmax, 48))\n\nnsamples = 10\nfor _ in 1:nsamples\n for _ in 1:1000 \n step!(sys, langevin)\n end\n add_sample!(dsf, sys)\nend","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"The default histogram BinningParameters are already integrated over the z direction because the system is 2D:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"unit_resolution_binning_parameters(dsf)","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"⊡ 12 bins from -0.042 to +0.958 along [+1.27 dx] (Δ = 0.065)\n⊡ 12 bins from -0.042 to +0.958 along [+1.27 dy] (Δ = 0.065)\n∫ Integrated from +0.000 to +0.000 along [-0.33 dx +1.88 dz] (Δ = 0.524)\n⊡ 48 bins from -0.107 to +10.134 along [+1.00 dE] (Δ = 0.213)","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"The histogram is very oblong; it's approximately 1x1x10. To make it a nicer shape, we will rescale the energy axis to be be fractions of ωmax:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"params = unit_resolution_binning_parameters(dsf)\nscale_factor = ωmax\nparams.binend[4] /= scale_factor\nparams.binstart[4] /= scale_factor\nparams.binwidth[4] /= scale_factor\nparams.covectors[4,:] ./= scale_factor","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Doing this changes the last axis of the histogram to fit in [0,1]:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"⊡ 49 bins from -0.011 to +1.013 along [+0.10 dE] (Δ = 0.213)","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Now that our histogram is a cube, we compute the intensity in the histogram bins using the usual intensities_binned:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"formula = intensity_formula(dsf, :trace)\nsignal, counts = intensities_binned(dsf, params; formula)\nintensity = signal ./ counts","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Now that we have our intensity data and the binning parameters, we can export to VTK format using export_vtk and move to ParaView for the visualization.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"# Importing WriteVTK enables Sunny's export-to-VTK functions\nimport WriteVTK\n\n# [1,2,4] specifies that the (x,y,z) axes in ParaView are (Qx,Qy,ω)\nexport_vtk(\"square_lattice\", params, intensity; dims_kept = [1,2,4])\n# Writes a file square_lattice.vti in the current directory","category":"page"},{"location":"writevtk.html#Loading-in-ParaView","page":"ParaView Rendering","title":"Loading in ParaView","text":"","category":"section"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"In ParaView, use File > Open to open square_lattice.vti. This will add the file to the Pipeline Browser with a closed eye icon, indicating that the data is ready to be loaded.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"In the Properties panel, both bin_centers and data will be selected for import by default. Uncheck bin_centers because we don't need that information for the visualization. Click the green Apply button to load the data.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"By default, only the outline of the data is shown in the 3D viewport. Since we adjusted the energy axis, the outline is a 1x1x1 cube. Optionally enable the axes grid under \"View\", and customize using the adjacent edit button.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"To enable the volumetric render:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Select \"Volume\" from the \"Representation\" drop-down menu under \"Display\".\nThe \"Coloring\" drop-down should automatically select data because it's the only data loaded.\nOpen the Color Map Editor to adjust the opacity of the fog, which may be too faint to see by default.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Depending on your computer and your dataset size, the volumetric rendering may be slow, but our dataset is relatively small, so the render should be fast.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"If nothing shows up at first, don't despair. Often, there are Bragg-like peaks in the correlation data which outshine everything else. To see this, enable Display Data Histogram in the Color Map Editor panel. To zoom in on the lower-intensity data, click and drag the right side handle of the opacity transfer function box to the middle a few times.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"After suitable color mapping, the dispersion curve should become visible:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html#Experiment-data","page":"ParaView Rendering","title":"Experiment data","text":"","category":"section"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Note that since only the data and binning parameters are required for exporting to VTK, experiment data can be exported in the same way. For example, to visualize S(Q_xQ_yQ_z), do this:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"# Load 4D histogram data from Mantid\nparams, signal = load_nxs(\"experiment_data.nxs\")\n\n# Integrate out the energy axis so we are 3D\nintegrate_axes!(params; axes = 4)\nsignal = sum(signal; dims = 4)\n\n# Export to ParaView\nexport_vtk(\"experiment_data_as_vtk\", params, signal)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"EditURL = \"../../../examples/01_LSWT_CoRh2O4.jl\"","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#1.-Spin-wave-simulations-of-CoRhO","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"This tutorial introduces Sunny through its features for performing conventional spin wave theory calculations. We consider the crystal CoRh₂O₄ and reproduce the calculations of Ge et al., Phys. Rev. B 96, 064413.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Get-Julia-and-Sunny","page":"1. Spin wave simulations of CoRh₂O₄","title":"Get Julia and Sunny","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"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 guide. Sunny requires Julia 1.10 or later.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"From the Julia prompt, load Sunny and also GLMakie for graphics.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"If these packages are not yet installed, Julia will offer to install them. If executing this tutorial gives an error, you may need to update Sunny and GLMakie from the built-in package manager.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Units","page":"1. Spin wave simulations of CoRh₂O₄","title":"Units","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"The Units object selects reference energy and length scales, and uses these to provide physical constants. For example, units.K returns one kelvin as 0.086 meV, where the Boltzmann constant is implicit.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"units = Units(:meV, :angstrom);\nnothing #hide","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Crystal-cell","page":"1. Spin wave simulations of CoRh₂O₄","title":"Crystal cell","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"A crystallographic cell may be loaded from a .cif file, or specified from atom positions and types.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"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 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 (hatx haty hatz) in components of the lattice vectors.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"a = 8.5031 # (Å)\nlatvecs = lattice_vectors(a, a, a, 90, 90, 90)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Construct the Crystal 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.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"positions = [[0, 0, 0]]\ncryst = Crystal(latvecs, positions, 227; types=[\"Co\"], setting=\"1\")","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"view_crystal launches an interface for interactive inspection and symmetry analysis.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"view_crystal(cryst)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Spin-system","page":"1. Spin wave simulations of CoRh₂O₄","title":"Spin system","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"A System will define the spin model. Each cobalt atom carries quantum spin s = 32, with a g-factor of 2. Specify this Moment data for cobalt atom 1. By symmetry, the same moment data also applies to cobalt atoms 2, 3, ... 7. The option :dipole indicates a traditional model type, for which quantum spin is modeled as a dipole expectation value.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"sys = System(cryst, [1 => Moment(s=3/2, g=2)], :dipole)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Ge et al. demonstrated that inelastic neutron scattering data for CoRh₂O₄ is well modeled by antiferromagnetic nearest neighbor exchange, J = 0.63 meV. Call set_exchange! with the bond that connects atom 1 to atom 3, and has zero displacement between chemical cells. Consistent with the symmetries of spacegroup 227, this interaction will be propagated to all other nearest-neighbor bonds. Calling view_crystal with sys now shows the antiferromagnetic Heisenberg interactions as blue polkadot spheres.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"J = +0.63 # (meV)\nset_exchange!(sys, J, Bond(1, 3, [0, 0, 0]))\nview_crystal(sys)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Optimizing-spins","page":"1. Spin wave simulations of CoRh₂O₄","title":"Optimizing spins","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"To search for the ground state, call randomize_spins! and minimize_energy! in sequence. For this problem, optimization converges rapidly to the expected Néel order. See this with plot_spins, where spins are colored according to their global z-component.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"The diamond lattice is bipartite, allowing each spin to perfectly anti-align with its 4 nearest-neighbors. Each of these 4 bonds contribute -J s^2 to the total energy. Two sites participate in each bond, so the energy per site is -2 J s^2. Check this by calling energy_per_site.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"@assert energy_per_site(sys) ≈ -2J*(3/2)^2","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Reshaping-the-magnetic-cell","page":"1. Spin wave simulations of CoRh₂O₄","title":"Reshaping the magnetic cell","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"The most compact magnetic cell for this Néel order is a primitive unit cell. Reduce the magnetic cell size using reshape_supercell, where columns of the shape matrix are primitive lattice vectors as multiples of the conventional cubic lattice vectors (𝐚_1 𝐚_2 𝐚_3). One could alternatively use shape = cryst.latvecs \\ cryst.prim_latvecs. Verify that the energy per site is unchanged after the reshaping the supercell.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"shape = [0 1 1;\n 1 0 1;\n 1 1 0] / 2\nsys_prim = reshape_supercell(sys, shape)\n@assert energy_per_site(sys_prim) ≈ -2J*(3/2)^2","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Plotting sys_prim shows the two spins within the primitive cell, as well as the larger conventional cubic cell for context.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"plot_spins(sys_prim; color=[S[3] for S in sys_prim.dipoles])","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Spin-wave-theory","page":"1. Spin wave simulations of CoRh₂O₄","title":"Spin wave theory","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"With this primitive cell, we will perform a SpinWaveTheory calculation of the structure factor mathcalS(𝐪ω). The measurement ssf_perp indicates projection of the spin structure factor mathcalS(𝐪ω) perpendicular to the direction of momentum transfer, as appropriate for unpolarized neutron scattering. The isotropic FormFactor for Co²⁺ dampens intensities at large 𝐪.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"formfactors = [1 => FormFactor(\"Co2\")]\nmeasure = ssf_perp(sys_prim; formfactors)\nswt = SpinWaveTheory(sys_prim; measure)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Select lorentzian broadening with a full-width at half-maximum (FWHM) of 0.8 meV.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"kernel = lorentzian(fwhm=0.8)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Define a q_space_path 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, 𝐛_12 + 𝐛_22. A total of 500 𝐪-points will be sampled along the path.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"qs = [[0, 0, 0], [1/2, 0, 0], [1/2, 1/2, 0], [0, 0, 0]]\npath = q_space_path(cryst, qs, 500)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Calculate single-crystal scattering intensities along this path, for energies between 0 and 6 meV. Use plot_intensities to visualize the result.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"energies = range(0, 6, 300)\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res; units, title=\"CoRh₂O₄ LSWT\")","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Sometimes experimental data is only available as a powder average, i.e., as an average over all possible crystal orientations. Use powder_average to simulate these intensities. Each 𝐪-magnitude defines a spherical shell in reciprocal space. Consider 200 radii from 0 to 3 inverse angstroms, and collect 2000 random samples per spherical shell. As configured, this calculation completes in about two seconds. Had we used the conventional cubic cell, the calculation would be an order of magnitude slower.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"radii = range(0, 3, 200) # (1/Å)\nres = powder_average(cryst, radii, 2000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units, saturation=1.0, title=\"CoRh₂O₄ Powder Average\")","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"This result can be compared to experimental neutron scattering data from Fig. 5 of Ge et al.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#What's-next?","page":"1. Spin wave simulations of CoRh₂O₄","title":"What's next?","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"For more spin wave calculations of this type, browse the SpinW tutorials ported to Sunny.\nSpin wave theory neglects thermal fluctuations of the magnetic order. The next CoRh₂O₄ tutorial demonstrates how to sample spins in thermal equilibrium, and measure dynamical correlations from the classical spin dynamics.\nSunny 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 the FeI₂ tutorial.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"EditURL = \"../../../examples/04_GSD_FeI2.jl\"","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/04_GSD_FeI2.html#4.-Generalized-spin-dynamics-of-FeI-at-finite-*T*","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"","category":"section"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The previous FeI₂ tutorial used multi-flavor spin wave theory to calculate the dynamical spin structure factor. This tutorial performs an analogous calculation at finite temperature using the classical dynamics of SU(N) coherent states.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Compared to spin wave theory, classical spin dynamics in real-space is typically much slower, and is limited in 𝐪-space resolution. The approach, however, allows for thermal fluctuations, can be used to explore finite temperature phases, and enables the study of highly non-equilibrium processes.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The structure of this tutorial largely follows the previous study of CoRh₂O₄ at finite T. The main difference is that CoRh₂O₄ can be well described with :dipole mode, whereas FeI₂ is best modeled using :SUN mode, owing to its strong easy-axis anisotropy.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Construct the FeI₂ system as previously described.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"using Sunny, GLMakie\n\nunits = Units(:meV, :angstrom)\na = b = 4.05012\nc = 6.75214\nlatvecs = lattice_vectors(a, b, c, 90, 90, 120)\ncryst = Crystal(latvecs, [[0,0,0]], 164; types=[\"Fe\"])\n\nsys = System(cryst, [1 => Moment(s=1, g=2)], :SUN)\nJ1pm = -0.236\nJ1pmpm = -0.161\nJ1zpm = -0.261\nJ2pm = 0.026\nJ3pm = 0.166\nJ′0pm = 0.037\nJ′1pm = 0.013\nJ′2apm = 0.068\nJ1zz = -0.236\nJ2zz = 0.113\nJ3zz = 0.211\nJ′0zz = -0.036\nJ′1zz = 0.051\nJ′2azz = 0.073\nJ1xx = J1pm + J1pmpm\nJ1yy = J1pm - J1pmpm\nJ1yz = J1zpm\nset_exchange!(sys, [J1xx 0.0 0.0; 0.0 J1yy J1yz; 0.0 J1yz J1zz], Bond(1,1,[1,0,0]))\nset_exchange!(sys, [J2pm 0.0 0.0; 0.0 J2pm 0.0; 0.0 0.0 J2zz], Bond(1,1,[1,2,0]))\nset_exchange!(sys, [J3pm 0.0 0.0; 0.0 J3pm 0.0; 0.0 0.0 J3zz], Bond(1,1,[2,0,0]))\nset_exchange!(sys, [J′0pm 0.0 0.0; 0.0 J′0pm 0.0; 0.0 0.0 J′0zz], Bond(1,1,[0,0,1]))\nset_exchange!(sys, [J′1pm 0.0 0.0; 0.0 J′1pm 0.0; 0.0 0.0 J′1zz], Bond(1,1,[1,0,1]))\nset_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]))\nD = 2.165\nset_onsite_coupling!(sys, S -> -D*S[3]^2, 1)","category":"page"},{"location":"examples/04_GSD_FeI2.html#Thermalization","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"Thermalization","text":"","category":"section"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"To study thermal fluctuations in real-space, use a large system size with 16×16×4 copies of the chemical cell.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"sys = resize_supercell(sys, (16, 16, 4))","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Direct optimization via minimize_energy! is susceptible to trapping in a local minimum. An alternative approach is to simulate the system using Langevin spin dynamics. This requires a bit more set-up, but allows sampling from thermal equilibrium at any target temperature. Select the temperature 2.3 K ≈ 0.2 meV. This temperature is small enough to magnetically order, but large enough so that the dynamics can readily overcome local energy barriers and annihilate defects.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"langevin = Langevin(; damping=0.2, kT=2.3*units.K)","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Use suggest_timestep to select an integration timestep for the error tolerance tol=1e-2. Initializing sys to some low-energy configuration usually works well.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"randomize_spins!(sys)\nminimize_energy!(sys; maxiters=10)\nsuggest_timestep(sys, langevin; tol=1e-2)\nlangevin.dt = 0.03;\nnothing #hide","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Run a Langevin trajectory for 10,000 time-steps and plot the spins. The magnetic order is present, but may be difficult to see.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"for _ in 1:10_000\n step!(sys, langevin)\nend\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Verify the expected two-up, two-down spiral magnetic order by calling print_wrapped_intensities. A single propagation wavevector 𝐤 dominates the static intensity in mathcalS(𝐪), indicating the expected 2 up, 2 down magnetic spiral order. A smaller amount of intensity is spread among many other wavevectors due to thermal fluctuations.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"print_wrapped_intensities(sys)","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Thermalization has not substantially altered the suggested dt.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"suggest_timestep(sys, langevin; tol=1e-2)","category":"page"},{"location":"examples/04_GSD_FeI2.html#Structure-factor-in-the-paramagnetic-phase","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"Structure factor in the paramagnetic phase","text":"","category":"section"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The remainder of this tutorial will focus on the paramagnetic phase. Re-thermalize the system to the temperature of 3.5 K ≈ 0.30 meV.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"langevin.kT = 3.5 * units.K\nfor _ in 1:10_000\n step!(sys, langevin)\nend","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The suggested timestep has increased slightly. Following this suggestion will make the simulations a bit faster.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"suggest_timestep(sys, langevin; tol=1e-2)\nlangevin.dt = 0.040;\nnothing #hide","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Collect dynamical spin structure factor data using SampledCorrelations. This procedure involves sampling spin configurations from thermal equilibrium and using the spin dynamics of SU(N) coherent states to estimate dynamical correlations. With proper classical-to-quantum corrections, the associated structure factor intensities S^αβ(qω) can be compared with finite-temperature inelastic neutron scattering data. Incorporate the FormFactor appropriate to Fe²⁺.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"dt = 2*langevin.dt\nenergies = range(0, 7.5, 120)\nformfactors = [1 => FormFactor(\"Fe2\"; g_lande=3/2)]\nsc = SampledCorrelations(sys; dt, energies, measure=ssf_perp(sys; formfactors))","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The function add_sample! will collect data by running a dynamical trajectory starting from the current system configuration.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"add_sample!(sc, sys)","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"To collect additional data, it is required to re-sample the spin configuration from the thermal distribution. Statistical error is reduced by fully decorrelating the spin configurations between calls to add_sample!.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"for _ in 1:2\n for _ in 1:1000 # Enough steps to decorrelate spins\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Perform an intensity calculation for two special 𝐪-points in reciprocal lattice units (RLU). A classical-to-quantum rescaling of normal mode occupations will be performed according to the temperature kT. The large statistical noise could be reduced by averaging over more thermal samples.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"res = intensities(sc, [[0, 0, 0], [0.5, 0.5, 0.5]]; energies, langevin.kT)\nfig = lines(res.energies, res.data[:, 1]; axis=(xlabel=\"meV\", ylabel=\"Intensity\"), label=\"(0,0,0)\")\nlines!(res.energies, res.data[:, 2]; label=\"(π,π,π)\")\naxislegend()\nfig","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Next, we will measure intensities along a q_space_path that connects high symmetry points. Because this is a real-space calculation, data is only available for discrete 𝐪 modes, with resolution that scales inversely to linear system size. Intensities at ω = 0 dominate, so to enhance visibility, we restrict the color range empirically.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"qs = [[0, 0, 0], # List of wave vectors that define a path\n [1, 0, 0],\n [0, 1, 0],\n [1/2, 0, 0],\n [0, 1, 0],\n [0, 0, 0]]\nqpath = q_space_path(cryst, qs, 500)\nres = intensities(sc, qpath; energies, langevin.kT)\nplot_intensities(res; colorrange=(0.0, 1.0), title=\"Intensities at T = 2.3 K\")","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"One can also view the intensity along a q_space_grid for a fixed energy value. Alternatively, use intensities_static to integrate over all available energies.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"grid = q_space_grid(cryst, [1, 0, 0], range(-1.5, 1.5, 300), [0, 1, 0], (-1.5, 1.5); orthogonalize=true)\nres = intensities(sc, grid; energies=[3.5], langevin.kT)\nplot_intensities(res; title=\"Intensity slice at ω = 3.5 meV\")","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"EditURL = \"../../../../examples/spinw_tutorials/SW08_sqrt3_kagome_AFM.jl\"","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html#SW08-33-kagome-antiferromagnet","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"","category":"section"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"This is a Sunny port of SpinW Tutorial 8, originally authored by Bjorn Fak and Sandor Toth. It calculates the linear spin wave theory spectrum for the sqrt3 times sqrt3 order of a kagome antiferromagnet.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Define the chemical cell of a kagome lattice with spacegroup 147 (P-3).","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 40, 90, 90, 120)\ncryst = Crystal(latvecs, [[1/2, 0, 0]], 147)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Construct a spin system with nearest neighbor antiferromagnetic exchange.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ = 1.0\nset_exchange!(sys, J, Bond(2, 3, [0, 0, 0]))","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Initialize to an energy minimizing magnetic structure, for which nearest-neighbor spins are at 120° angles.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"set_dipole!(sys, [cos(0), sin(0), 0], (1, 1, 1, 1))\nset_dipole!(sys, [cos(0), sin(0), 0], (1, 1, 1, 2))\nset_dipole!(sys, [cos(2π/3), sin(2π/3), 0], (1, 1, 1, 3))\nk = [-1/3, -1/3, 0]\naxis = [0, 0, 1]\nsys_enlarged = repeat_periodically_as_spiral(sys, (3, 3, 1); k, axis)\nplot_spins(sys_enlarged; ndims=2)","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Check energy per site. Each site participates in 4 bonds with energy Jcos(2π3). Factor of 1/2 avoids double counting. The two calculation methods agree.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"@assert energy_per_site(sys_enlarged) ≈ (4/2)*J*cos(2π/3)\n@assert spiral_energy_per_site(sys; k, axis) ≈ (4/2)*J*cos(2π/3)","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Calculate and plot intensities for a path through 𝐪-space using two calculation methods. The two methods agree in intensity, but the \"supercell method\" gives rise to ghost modes in the dispersion that have zero intensity.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"qs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]\npath = q_space_path(cryst, qs, 400)\n\nfig = Figure(size=(768, 300))\nswt = SpinWaveTheory(sys_enlarged; measure=ssf_perp(sys_enlarged))\nres = intensities_bands(swt, path)\nplot_intensities!(fig[1, 1], res; units, saturation=0.5,title=\"Supercell method\")\nswt = SpinWaveTheorySpiral(sys; measure=ssf_perp(sys), k, axis)\nres = intensities_bands(swt, path)\nplot_intensities!(fig[1, 2], res; units, saturation=0.5, title=\"Spiral method\")\nfig","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Calculate and plot the powder averaged spectrum. Continuing to use the \"spiral method\", this calculation executes in about two seconds. Because the intensities are dominated by a flat band at zero energy transfer, select an empirical colorrange that brings the lower-intensity features into focus.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 3, 200)\nkernel = gaussian(fwhm=0.05)\nres = powder_average(cryst, radii, 200) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units, colorrange=(0,20))","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"EditURL = \"../../../../examples/spinw_tutorials/SW10_Energy_cut.jl\"","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html#SW10-Energy-cut-on-square-lattice","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"","category":"section"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"This is a Sunny port of SpinW Tutorial 10, originally authored by Sandor Toth. It calculates the spin wave spectrum on a constant energy cut of the frustrated square lattice.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Define the chemical cell for the 2D square lattice.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(1.0, 1.0, 3.0, 90, 90, 90)\ncryst = Crystal(latvecs, [[0, 0, 0]])","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Construct a spin system with nearest-neighbor antiferomagnetic interactions of 1.0 meV. Energy minimization yields the expected Néel order on the 2×2 magnetic cell.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(2, 2, 1))\nset_exchange!(sys, 1.0, Bond(1, 1, [1, 0, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Define a 2D slice through 𝐪-space with q_space_grid.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"grid = q_space_grid(cryst, [1, 0, 0], range(0, 2, 201), [0, 1, 0], range(0, 2, 201))","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Calculate and plot a constant energy cut at the precise value of 3.75 meV. Apply a line broadening with a full-width half-max of 0.2 meV to approximately capture intensities between 3.5 and 4.0 meV.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities(swt, grid; energies=[3.75], kernel=gaussian(fwhm=0.2))\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Integrate intensities between 3.5 and 4 meV using intensities_static with the bounds option.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"res = intensities_static(swt, grid; bounds=(3.5, 4.01))\nplot_intensities(res; units)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"EditURL = \"../../../examples/08_Momentum_Conventions.jl\"","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/08_Momentum_Conventions.html#8.-Momentum-transfer-conventions","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"","category":"section"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"This example illustrates Sunny's conventions for dynamical structure factor intensities, mathcalS(𝐪ω), as documented in the page Structure Factor Conventions. The variables 𝐪 and ω describe momentum and energy transfer to the sample.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"For systems without inversion-symmetry, the structure factor intensities at 𝐪 may be inequivalent. To highlight this, consider a simple 1D chain that includes only Dzyaloshinskii–Moriya interactions between neighboring sites. Coupling to an external field then breaks time-reversal symmetry, giving rise to an inequivalence of intensities mathcalS(𝐪ω)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Selecting the P1 spacegroup will effectively disable all symmetry analysis. This can be a convenient way to avoid symmetry-imposed constraints on the couplings. A disadvantage is that all bonds are treated as inequivalent, and Sunny will therefore not be able to propagate any couplings between bonds.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"latvecs = lattice_vectors(2, 2, 1, 90, 90, 90)\ncryst = Crystal(latvecs, [[0,0,0]], \"P1\")","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Construct a 1D chain system that extends along the global Cartesian z axis. The Hamiltonian includes DM and Zeeman coupling terms, ℋ = _j D z (𝐒_j 𝐒_j+1) - _j 𝐁 μ_j, where μ_j = - g 𝐒_j is the magnetic_moment and 𝐁 z.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(1, 1, 25))\nD = 0.1\nB = 5D\nset_exchange!(sys, dmvec([0, 0, D]), Bond(1, 1, [0, 0, 1]))\nset_field!(sys, [0, 0, B])","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"The large external field fully polarizes the system. Here, the DM coupling contributes nothing, leaving only Zeeman coupling.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"randomize_spins!(sys)\nminimize_energy!(sys)\n@assert energy_per_site(sys) ≈ -10D","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Sample from the classical Boltzmann distribution at a low temperature.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"dt = 0.1\nkT = 0.02\ndamping = 0.1\nlangevin = Langevin(dt; kT, damping)\nsuggest_timestep(sys, langevin; tol=1e-2)\nfor _ in 1:10_000\n step!(sys, langevin)\nend","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"The Zeeman coupling polarizes the magnetic moments in the 𝐁 z direction. The spin dipoles, however, are anti-aligned with the magnetic moments, and therefore point towards -z. This is shown below.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"plot_spins(sys)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Estimate the dynamical structure factor using classical dynamics.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"sc = SampledCorrelations(sys; dt, energies=range(0, 15D, 100), measure=ssf_trace(sys))\nadd_sample!(sc, sys)\nnsamples = 100\nfor _ in 1:nsamples\n for _ in 1:1_000\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend\npath = q_space_path(cryst, [[0,0,-1/2], [0,0,+1/2]], 400)\nres1 = intensities(sc, path; energies=:available, kT)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Calculate the same quantity with linear spin wave theory at T = 0. Because the ground state is fully polarized, the required magnetic cell is a 111 grid of chemical unit cells.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"sys_small = resize_supercell(sys, (1,1,1))\nminimize_energy!(sys_small)\nswt = SpinWaveTheory(sys_small; measure=ssf_trace(sys_small))\nres2 = intensities_bands(swt, path)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"This model system has a single magnon band with dispersion ϵ(𝐪) = 1 - DB sin(2πq₃) and uniform intensity. Both calculation methods reproduce this analytical solution. Observe that 𝐪 and -𝐪 are inequivalent. The structure factor calculated from classical dynamics additionally shows an elastic peak at 𝐪 = 000, reflecting the ferromagnetic ground state.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"fig = Figure(size=(768, 300))\nplot_intensities!(fig[1, 1], res1; title=\"Classical dynamics\")\nplot_intensities!(fig[1, 2], res2; title=\"Spin wave theory\")\nfig","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"EditURL = \"../../../examples/06_CP2_Skyrmions.jl\"","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html#6.-Dynamical-quench-into-CP-skyrmion-liquid","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"","category":"section"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"This example demonstrates a non-equilibrium study of SU(3) spin dynamics leading to the formation of a CP² skyrmion liquid. As proposed in Zhang et al., Nature Communications 14, 3626 (2023), CP² skyrmions are topological defects that involve both the dipolar and quadrupolar parts of quantum spin-1, and can be studied using the formalism SU(3) coherent states.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"This study uses the SU(N) generalization of Landau-Lifshitz spin dynamics, with Langevin coupling to a thermal bath, as described in Dahlbom et al., Phys. Rev. B 106, 235154 (2022). Beginning from an initial high-temperature state, the dynamics following a rapid quench in temperature gives rise a disordered liquid of CP² skyrmions.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Begin with a Crystal cell for the triangular lattice.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"lat_vecs = lattice_vectors(1, 1, 10, 90, 90, 120)\npositions = [[0, 0, 0]]\ncryst = Crystal(lat_vecs, positions)","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Create a spin System containing LL cells. Following previous worse, select g=-1 so that the Zeeman coupling has the form -𝐁𝐬.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"L = 40\nsys = System(cryst, [1 => Moment(s=1, g=-1)], :SUN; dims=(L, L, 1))","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"The Hamiltonian,","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"mathcalH = sum_langle ij rangle J_ij( hatS_i^x hatS_j^x + hatS_i^y hatS_j^y + DeltahatS_i^z hatS_j^z) - hsum_ihatS_i^z + Dsum_i(hatS_i^z)^2","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"contains competing ferromagnetic first-neighbor and antiferromagnetic second-neighbor exchange terms on a triangular lattice. Both exchange matrices include anisotropy in the hatz direction. Additionally, there is an external magnetic field h and an easy-plane single-ion anisotropy D. Select parameters for a point in the Zhang et al. phase diagram where the CP² skyrmions are stable.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"J1 = -1 # Nearest-neighbor ferromagnetic\nJ2 = (2.0/(1+√5)) # Tune competing exchange to set skyrmion scale length\nΔ = 2.6 # Exchange anisotropy\n\nex1 = J1 * [1 0 0;\n 0 1 0;\n 0 0 Δ]\nex2 = J2 * [1 0 0;\n 0 1 0;\n 0 0 Δ]\nset_exchange!(sys, ex1, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, ex2, Bond(1, 1, [1, 2, 0]))\n\nh = 15.5 # External field in energy units\nfield = set_field!(sys, [0, 0, h])\n\nD = 19.0 # Easy-plane anisotropy\nset_onsite_coupling!(sys, S -> D*S[3]^2, 1)","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Initialize system to an infinite temperature (fully randomized) initial condition.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"We will study a temperature quench process using a generalized Langevin spin dynamics. In this SU(3) treatment of quantum spin-1, the dynamics include coupled dipoles and quadrupoles. Select a relatively small damping magnitude to overcome local minima, and disable thermal fluctuations.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"damping = 0.05\nkT = 0;\nnothing #hide","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"The first step is to estimate a reasonable integration timestep dt. In this case, a random spin configuration gives a tighter bound than does an energy-minimized configuration. A relatively large error tolerance is OK for this phenomenological study.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"randomize_spins!(sys)\nintegrator = Langevin(; damping, kT)\nsuggest_timestep(sys, integrator; tol=0.05)","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Apply the suggested timestep.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"integrator.dt = 0.01;\nnothing #hide","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Now run the dynamical quench starting from a randomized configuration. The field frames stores the system spin configuration, as SU(3) coherent states, at three different times during the quenching process.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"randomize_spins!(sys)\nτs = [4, 16, 256] # Times to record snapshots\nframes = [] # Empty array to store snapshots\nfor i in eachindex(τs)\n dur = i == 1 ? τs[1] : τs[i] - τs[i-1] # Determine the length of time to simulate\n numsteps = round(Int, dur/integrator.dt)\n for _ in 1:numsteps # Perform the integration\n step!(sys, integrator)\n end\n push!(frames, copy(sys.coherents)) # Save a snapshot spin configuration\nend","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Visualize the state of the system contained in each snapshot by plotting the SU(3) Berry phase curvature over triangular plaquettes. This is a measure of CP² skyrmion density. The function plot_triangular_plaquettes is not part of the core Sunny package, but rather something you could define yourself using Makie. Find this helper function at examples/extra/Plotting/.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"include(pkgdir(Sunny, \"examples\", \"extra\", \"Plotting\", \"plotting2d.jl\"))\n\nfunction sun_berry_curvature(z₁, z₂, z₃)\n z₁, z₂, z₃ = normalize.((z₁, z₂, z₃))\n n₁ = z₁ ⋅ z₂\n n₂ = z₂ ⋅ z₃\n n₃ = z₃ ⋅ z₁\n return angle(n₁ * n₂ * n₃)\nend\n\nplot_triangular_plaquettes(sun_berry_curvature, frames; size=(600, 200),\n offset_spacing=10, texts=[\"\\tt = \"*string(τ) for τ in τs], text_offset=(0, 6)\n)","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"The times are given in hbarJ_1. The white background corresponds to a quantum paramagnetic state, where the local spin exhibits a strong quadrupole moment and little or no dipole moment. At late times, there are well-formed skyrmions of positive (red) and negative (blue) charge, and various metastable spin configurations. A full-sized version of this figure is available in Dahlbom et al..","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"EditURL = \"../../../../examples/spinw_tutorials/SW02_AFM_Heisenberg_chain.jl\"","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html#SW02-AFM-Heisenberg-chain","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"","category":"section"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"This is a Sunny port of SpinW Tutorial 2, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the antiferromagnetic Heisenberg nearest-neighbor spin chain.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Define the chemical cell for a 1D chain following the previous tutorial.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(3, 8, 8, 90, 90, 90)\ncryst = Crystal(latvecs, [[0, 0, 0]])\nview_crystal(cryst; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Unlike in the previous tutorial, here the magnetic cell should include 2×1×1 chemical cells to support antiferromagnetic (Néel) order along the chain.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(2, 1, 1))","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Set a nearest neighbor interaction of J = +1 meV along the chain, and find the energy-minimizing Néel order. As before, a global rotation in spin-space is arbitrary.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"J = 1\nset_exchange!(sys, J, Bond(1, 1, [1, 0, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Perform a SpinWaveTheory calculation for a path between 000 and 100 in RLU.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 401)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"This system includes two bands that are fully degenerate in their dispersion.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"isapprox(res.disp[1, :], res.disp[2, :])","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Plot the intensities summed over the two degenerate bands using the Makie lines function.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"xs = [q[1] for q in path.qs]\nys = log10.(res.data[1, :] + res.data[2, :])\nlines(xs, ys; axis=(; xlabel=\"[H, 0, 0]\", ylabel=\"Log intensity (dimensionless)\"))","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"EditURL = \"../../../../examples/spinw_tutorials/SW11_La2CuO4.jl\"","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html#SW11-LaCuO","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"","category":"section"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"This is a Sunny port of SpinW Tutorial 11, originally authored by Sandor Toth. It calculates the spin wave spectrum of La₂CuO₄.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Load packages","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Build a square lattice for the the Cu²⁺ atoms. The lattice constant 1 Å is selected arbitrarily.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(1, 1, 10, 90, 90, 90)\npositions = [[0, 0, 0]]\ntypes = [\"Cu\"]\ncryst = Crystal(latvecs, positions; types)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Build a spin system using the exchange parameters from R. Coldea, Phys. Rev. Lett. 86, 5377 (2001).","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"sys = System(cryst, [1 => Moment(s=1/2, g=2)], :dipole; dims=(2, 2, 1))\nJ = 138.3\nJp = 2\nJpp = 2\nJc = 38\nset_exchange!(sys, J-Jc/2, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, Jp-Jc/4, Bond(1, 1, [1, 1, 0]))\nset_exchange!(sys, Jpp, Bond(1, 1, [2, 0, 0]))","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Energy minimization yields the expected Néel order","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Plot the spin wave spectrum for a path through 𝐪-space. Apply a manual \"quantum correction\" that adjusts energy scale by the factor 1.18.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"qs = [[3/4,1/4,0], [1/2, 1/2, 0], [1/2, 0, 0], [3/4, 1/4, 0], [1,0,0], [1/2 0 0]]\nlabels = [\"P\", \"M\", \"X\", \"P\", \"Γ\", \"X\"]\npath = q_space_path(cryst, qs, 400; labels)\nenergies = range(0, 320, 400)\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities(swt, path; energies, kernel=gaussian(fwhm=35))\nres.energies .*= 1.18\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Plot instantaneous itensities, integrated over ω.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"res = intensities_static(swt, path)\nplot_intensities(res; colorrange=(0,20), units)","category":"page"},{"location":"library.html#Library-API","page":"Library API","title":"Library API","text":"","category":"section"},{"location":"library.html","page":"Library API","title":"Library API","text":"This page describes the public types and functions exported by Sunny. This documentation can be also be accessed using the Julia help system (enter ? at the Julia command prompt).","category":"page"},{"location":"library.html","page":"Library API","title":"Library API","text":"","category":"page"},{"location":"library.html","page":"Library API","title":"Library API","text":"Modules = [Sunny]\nPrivate = false","category":"page"},{"location":"library.html#Sunny.Site","page":"Library API","title":"Sunny.Site","text":"(cell1, cell2, cell3, i) :: Site\n\nFour indices identifying a single site in a System. The first three indices select the unit cell and the last index selects the sublattice, i.e., the ith atom within the unit cell.\n\nThis object can be used to index dipoles and coherents fields of a System. A Site is also required to specify inhomogeneous interactions via functions such as set_field_at! or set_exchange_at!.\n\nNote that the definition of a cell may change when a system is reshaped. In this case, it is convenient to construct the Site using position_to_site, which always takes a position in fractional coordinates of the original lattice vectors.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.BinningParameters","page":"Library API","title":"Sunny.BinningParameters","text":"BinningParameters(binstart,binend,binwidth;covectors = I(4))\nBinningParameters(binstart,binend;numbins,covectors = I(4))\n\nDescribes a 4D parallelepided histogram in a format compatible with experimental Inelasitic Neutron Scattering data. See generate_mantid_script_from_binning_parameters to convert BinningParameters to a format understandable by the Mantid software, or load_nxs to load BinningParameters from a Mantid .nxs file.\n\nThe coordinates of the histogram axes are specified by multiplication of (q,ω) with each row of the covectors matrix, with q given in [R.L.U.]. Since the default covectors matrix is the identity matrix, the default axes are (qx,qy,qz,ω) in absolute units.\n\nThe convention for the binning scheme is that:\n\nThe left edge of the first bin starts at binstart\nThe bin width is binwidth\nThe last bin contains binend\nThere are no \"partial bins;\" the last bin may contain values greater than binend.\n\nA value can be binned by computing its bin index:\n\ncoords = covectors * value\nbin_ix = 1 .+ floor.(Int64,(coords .- binstart) ./ binwidth)\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.Bond","page":"Library API","title":"Sunny.Bond","text":"Bond(i, j, n)\n\nRepresents a bond between atom indices i and j. n is a vector of three integers specifying unit cell displacement in terms of lattice vectors.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.Crystal","page":"Library API","title":"Sunny.Crystal","text":"An object describing a crystallographic unit cell and its space group symmetry. Constructors are as follows:\n\nCrystal(filename; override_symmetry=false, symprec=nothing)\n\nReads the crystal from a .cif file located at the path filename. If override_symmetry=true, the spacegroup will be inferred based on atom positions and the returned unit cell may be reduced in size. For an mCIF file, the return value is the magnetic supercell, unless override_symmetry=true. If a precision for spacegroup symmetries cannot be inferred from the CIF file, it must be specified with symprec. The latvecs field of the returned Crystal will be in units of angstrom.\n\nCrystal(latvecs, positions; types=nothing, symprec=1e-5)\n\nConstructs a crystal from the complete list of atom positions positions, with coordinates (between 0 and 1) in units of lattice vectors latvecs. Spacegroup symmetry information is automatically inferred. The optional parameter types is a list of strings, one for each atom, and can be used to break symmetry-equivalence between atoms.\n\nCrystal(latvecs, positions, spacegroup_number; types=nothing, setting=nothing, symprec=1e-5)\n\nBuilds a crystal by applying symmetry operators for a given international spacegroup number. For certain spacegroups, there are multiple possible unit cell settings; in this case, a warning message will be printed, and a list of crystals will be returned, one for every possible setting. Alternatively, the optional setting string will disambiguate between unit cell conventions.\n\nCurrently, crystals built using only the spacegroup number will be missing some symmetry information. It is generally preferred to build a crystal from a .cif file or from the full specification of the unit cell.\n\nExamples\n\n# Read a Crystal from a .cif file\nCrystal(\"filename.cif\")\n\n# Build a BCC crystal in the conventional cubic unit cell by specifying both\n# atoms. The spacegroup 229 is inferred.\nlatvecs = lattice_vectors(1, 1, 1, 90, 90, 90)\npositions = [[0, 0, 0], [1/2, 1/2, 1/2]]\nCrystal(latvecs, positions)\n\n# Build a CsCl crystal (two simple cubic sublattices). Because of the distinct\n# atom types, the spacegroup number 221 is now inferred.\ntypes = [\"Na\", \"Cl\"]\ncryst = Crystal(latvecs, positions; types)\n\n# Build a diamond cubic crystal from its spacegroup number 227 and a single\n# atom position. This spacegroup has two possible settings (\"1\" or \"2\"), which\n# determine an overall unit cell translation.\npositions = [[1/4, 1/4, 1/4]]\ncryst = Crystal(latvecs, positions, 227; setting=\"1\")\n\nSee also lattice_vectors.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.FormFactor-Tuple{String}","page":"Library API","title":"Sunny.FormFactor","text":"FormFactor(ion::String; g_lande=2)\n\nThe magnetic form factor for a given magnetic ion and charge state. When passed to intensities, it rescales structure factor intensities based on the magnitude of the scattering vector, 𝐪.\n\nThe parameter ion must be one of the following strings:\n\nAm2, Am3, Am4, Am5, Am6, Am7, Au1, Au2, Au3, Au4, Au5, Ce2, Co0, Co1, Co2, Co3,\nCo4, Cr0, Cr1, Cr2, Cr3, Cr4, Cu0, Cu1, Cu2, Cu3, Cu4, Dy2, Dy3, Er2, Er3, Eu2,\nEu3, Fe0, Fe1, Fe2, Fe3, Fe4, Gd2, Gd3, Hf2, Hf3, Ho2, Ho3, Ir0a, Ir0b, Ir0c,\nIr1a, Ir1b, Ir2, Ir3, Ir4, Ir5, Ir6, Mn0, Mn1, Mn2, Mn3, Mn4, Mn5, Mo0, Mo1, Nb0,\nNb1, Nd2, Nd3, Ni0, Ni1, Ni2, Ni3, Ni4, Np3, Np4, Np5, Np6, Os0a, Os0b, Os0c,\nOs1a, Os1b, Os2, Os3, Os4, Os5, Os6, Os7, Pd0, Pd1, Pr3, Pt1, Pt2, Pt3, Pt4,\nPt5, Pt6, Pu3, Pu4, Pu5, Pu6, Re0a, Re0b, Re0c, Re1a, Re1b, Re2, Re3, Re4, Re5,\nRe6, Rh0, Rh1, Ru0, Ru1, Sc0, Sc1, Sc2, Sm2, Sm3, Ta2, Ta3, Ta4, Tb2, Tb3, Tc0,\nTc1, Ti0, Ti1, Ti2, Ti3, Tm2, Tm3, U3, U4, U5, V0, V1, V2, V3, V4, W0a, W0b,\nW0c, W1a, W1b, W2c, W3, W4, W5, Y0, Yb2, Yb3, Zr0, Zr1\n\nThe trailing number denotes ionization state. For example, \"Fe0\" denotes a neutral iron atom, while \"Fe2\" denotes Fe²⁺. If multiple electronic configurations are possible, they will be distinguished by a trailing letter (a, b, ...). Omitting this letter will print an informative error,\n\nFormFactor(\"Ir0\")\n\nERROR: Disambiguate form factor according to electronic configuration:\n \"Ir0a\" -- 6s⁰5d⁹\n \"Ir0b\" -- 6s¹5d⁸\n \"Ir0c\" -- 6s²5d⁷\n\nIn the dipolar approximation (small 𝐪) the form factor is\n\nF(s) = j_0(s) + (2-g)g j_2(s),\n\ninvolving s = 𝐪4π and the Landé g-factor. The j_l(s) are radial averages of the lth spherical Bessel function of the magnetic dipole. More details are provided in Ref. [1].\n\nThe standard approximation tables involve expansion in Gaussians,\n\nj_0(s) = A e^-as^2 + B e^-bs^2 + C e^-cs^2 + D e^-ds^2 + E\n\nand\n\nj_2(s) = (A e^-as^2 + B e^-bs^2 + C e^-cs^2 + D e^-ds^2 + E) s^2\n\nFor 3d, 4d, rare earth, and actinide ions, Sunny uses the revised tables of P. J. Brown, as documented in the McPhase package [2]. For 5d ions, Sunny uses the tables of Kobayashi, Nagao, Ito [3].\n\nTwo special, 𝐪-independent form factor values are available: one(FormFactor) and zero(FormFactor). The first idealizes the magnetic ion as a perfect point particle, while the second zeros all contributions from the magnetic ion.\n\nReferences:\n\nP. J. Brown, The Neutron Data Booklet, 2nd ed., Sec. 2.5 Magnetic Form Factors (2003)\nCoefficient tables in McPhase documentation\nK. Kobayashi, T. Nagao, M. Ito, Acta Cryst. A, 67 pp 473–480 (2011)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ImplicitMidpoint","page":"Library API","title":"Sunny.ImplicitMidpoint","text":"ImplicitMidpoint(dt::Float64; atol=1e-12) where N\n\nThe implicit midpoint method for integrating the Landau-Lifshitz spin dynamics or its generalization to SU(N) coherent states [1]. One call to the step! function will advance a System by dt units of time. This integration scheme is exactly symplectic and eliminates energy drift over arbitrarily long simulation trajectories.\n\nReferences:\n\nH. Zhang and C. D. Batista, Phys. Rev. B 104, 104409 (2021).\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.Langevin","page":"Library API","title":"Sunny.Langevin","text":"Langevin(dt::Float64; damping::Float64, kT::Float64)\n\nAn integrator for Langevin spin dynamics using the explicit Heun method. The damping parameter controls the coupling to an implicit thermal bath. One call to the step! function will advance a System by dt units of time. Can be used to sample from the Boltzmann distribution at temperature kT. An alternative approach to sampling states from thermal equilibrium is LocalSampler, which proposes local Monte Carlo moves. For example, use LocalSampler instead of Langevin to sample Ising-like spins.\n\nSetting damping = 0 disables coupling to the thermal bath, yielding an energy-conserving spin dynamics. The Langevin integrator uses an explicit numerical integrator which cannot prevent energy drift. Alternatively, the ImplicitMidpoint method can be used, which is more expensive but prevents energy drift through exact conservation of the symplectic 2-form.\n\nIf the System has mode = :dipole, then the dynamics is the stochastic Landau-Lifshitz equation,\n\n d𝐬dt = -𝐬 (ξ - 𝐁 + λ 𝐬 𝐁)\n\nwhere 𝐁 = -dEd𝐬 is the effective field felt by the expected spin dipole 𝐬. The components of ξ are Gaussian white noise, with magnitude (2 k_B T λ) set by a fluctuation-dissipation theorem. The parameter damping sets the phenomenological coupling λ to the thermal bath. \n\nIf the System has mode = :SUN, then this dynamics generalizes [1] to a stochastic nonlinear Schrödinger equation for SU(N) coherent states 𝐙,\n\n d𝐙dt = -i P ζ + (1 - i λ) ℋ 𝐙\n\nHere, P projects onto the space orthogonal to 𝐙, and ζ denotes complex Gaussian white noise with magnitude (2 k_B T λ). The local-Hamiltonian ℋ embeds the energy gradient into the 𝔰𝔲(N) Lie algebra, and generates evolution of spin dipoles, quadrupoles, etc. The parameter damping here sets λ, which is analogous to λ above.\n\nWhen applied to SU(2) coherent states, the generalized spin dynamics reduces exactly to the stochastic Landau-Lifshitz equation. The mapping is as follows. Normalized coherent states 𝐙 map to dipole expectation values 𝐬 = 𝐙^ S 𝐙, where spin operators S are a spin-𝐬 representation of SU(2). The local effective Hamiltonian ℋ = -𝐁 S generates rotation of the dipole in analogy to the vector cross product S 𝐁. The coupling to the thermal bath maps as λ = 𝐬 λ. Note, therefore, that the scaling of the damping parameter varies subtly between :dipole and :SUN modes.\n\nReferences:\n\nD. Dahlbom et al., Phys. Rev. B 106, 235154 (2022).\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.LocalSampler","page":"Library API","title":"Sunny.LocalSampler","text":"LocalSampler(; kT, nsweeps=1.0, propose=propose_uniform)\n\nMonte Carlo simulation involving Metropolis updates to individual spins. One call to the step! function will perform nsweeps of MCMC sampling for a provided System. The default value of 1.0 means that step! performs, on average, one trial update per spin.\n\nAssuming ergodicity, the LocalSampler will sample from thermal equilibrium for the target temperature kT. \n\nThe trial spin updates are sampled using the propose function. Options include propose_uniform, propose_flip, and propose_delta. Multiple proposals can be mixed with the macro @mix_proposals.\n\nThe returned object stores fields ΔE and Δs, which represent the cumulative change to the net energy and dipole, respectively.\n\n!!! warning \"Efficiency considerations\n\nA [`Langevin`](@ref) sampler is frequently much more efficient than a\n`LocalSampler` for simulating Heisenberg-like spins that vary continuously. A\n`LocalSampler` is appropriate in the special case that the spin states are\neffectively discrete. E.g., [`propose_flip`](@ref) is very helpful simulating\nIsing-like spins that arise due to a strong easy-axis anisotropy.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.Moment","page":"Library API","title":"Sunny.Moment","text":"Moment(; s, g)\n\nCharacterizes a effective spin magnetic moment on an atom. Quantum spin-s is a multiple of 1/2 in units of ħ. The g-factor or tensor defines the magnetic_moment μ = - g 𝐒 in units of the Bohr magneton.\n\nExample\n\nMoment(s=3/2, g=2)\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.SampledCorrelations-Tuple{System}","page":"Library API","title":"Sunny.SampledCorrelations","text":"SampledCorrelations(sys::System; measure, energies, dt)\n\nAn object to accumulate samples of dynamical pair correlations. The measure argument specifies a pair correlation type, e.g. ssf_perp. The energies must be evenly-spaced and starting from 0, e.g. energies = range(0, 3, 100). Select the integration time-step dt according to accuracy and speed considerations. suggest_timestep can help in selecting an appropriate value.\n\nDynamical correlations will be accumulated through calls to add_sample!, which expects a spin configuration in thermal equilibrium. A classical spin dynamics trajectory will be simulated of sufficient length to achieve the target energy resolution. The resulting data can can then be extracted as pair-correlation intensities with appropriate classical-to-quantum correction factors. See also intensities_static, which integrates over energy.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.SampledCorrelationsStatic","page":"Library API","title":"Sunny.SampledCorrelationsStatic","text":"SampledCorrelationsStatic(sys::System; measure)\n\nAn object to accumulate samples of static pair correlations. It is similar to SampledCorrelations, but no time-integration will be performed on calls to add_sample!. The resulting object can be used with intensities_static to calculate statistics from the classical Boltzmann distribution. Dynamical intensities data, however, will be unavailable. Similarly, classical-to-quantum corrections that rely on the excitation spectrum cannot be performed.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.SpinWaveTheory","page":"Library API","title":"Sunny.SpinWaveTheory","text":"SpinWaveTheory(sys::System; measure, regularization=1e-8)\n\nConstructs an object to perform linear spin wave theory. The system must be in an energy minimizing configuration. Enables calculation of dispersion bands. If pair correlations are specified with correspec, one can also calculate intensities_bands and broadened intensities.\n\nThe spins in system must be energy-minimized, otherwise the Cholesky step of the Bogoliubov diagonalization procedure will fail. The parameter regularization adds a small positive shift to the diagonal of the dynamical matrix to avoid numerical issues with quasi-particle modes of vanishing energy. Physically, this shift can be interpreted as application of an inhomogeneous field aligned with the magnetic ordering.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.SpinWaveTheoryKPM","page":"Library API","title":"Sunny.SpinWaveTheoryKPM","text":"SpinWaveTheoryKPM(sys::System; measure, regularization=1e-8, tol)\n\nA variant of SpinWaveTheory that uses the kernel polynomial method (KPM) to perform intensities calculations [1]. Instead of explicitly diagonalizing the dynamical matrix, KPM approximates intensities using polynomial expansion truncated at order M. The reduces the computational cost from 𝒪(N^3) to 𝒪(N M), which is favorable for large system sizes N.\n\nThe polynomial order M will be determined from the line broadening kernel and the specified error tolerance tol. Specifically, for each wavevector, M scales like the spectral bandwidth of excitations, divided by the energy resolution of the broadening kernel, times the negative logarithm of tol.\n\nThe error tolerance tol should be tuned empirically for each calculation. Reasonable starting points are 1e-1 (more speed) or 1e-2 (more accuracy).\n\nReferences:\n\nH. Lane et al., Kernel Polynomial Method for Linear Spin Wave Theory (2023) [arXiv:2312.08349v3].\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.SpinWaveTheorySpiral","page":"Library API","title":"Sunny.SpinWaveTheorySpiral","text":"SpinWaveTheorySpiral(sys::System; k, axis, measure, regularization=1e-8)\n\nAnalogous to SpinWaveTheory, 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 minimize_spiral_energy!. In contrast, axis will typically be determined from symmetry considerations.\n\nThe resulting object can be used to calculate the spin wave dispersion, or the structure factor via intensities_bands and intensities.\n\nThe algorithm for this calculation was developed in Toth and Lake, J. Phys.: Condens. Matter 27, 166002 (2015) and implemented in the SpinW code.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.System-Tuple{Crystal, Vector{Pair{Int64, Moment}}, Symbol}","page":"Library API","title":"Sunny.System","text":"System(crystal::Crystal, moments, mode; dims=(1, 1, 1), seed=nothing)\n\nA spin system is constructed from the Crystal unit cell, a specification of the spin moments symmetry-distinct sites, and a calculation mode. Interactions can be added to the system using, e.g., set_exchange!. The default supercell dimensions are 1×1×1 chemical cells, but this can be changed with dims.\n\nSpin moments comprise a list of pairs, [i1 => Moment(...), i2 => ...], where i1, i2, ... are a complete set of symmetry-distinct atoms. Each Moment contains spin and g-factor information.\n\nThe two primary options for mode are :SUN and :dipole. In the former, each spin-s degree of freedom is described as an SU(N) coherent state, i.e. a quantum superposition of N = 2s + 1 levels. This formalism can be useful to capture multipolar spin fluctuations or local entanglement effects. \n\nMode :dipole projects the SU(N) dynamics onto the restricted space of pure dipoles. In practice this means that Sunny will simulate Landau-Lifshitz dynamics, but single-ion anisotropy and biquadratic exchange interactions will be renormalized to improve accuracy. To disable this renormalization, use the mode :dipole_large_s which applies the s classical limit. For details, see the documentation page: Interaction Renormalization.\n\nAn integer seed for the random number generator can optionally be specified to enable reproducible calculations.\n\nAll spins are initially polarized in the global z-direction.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.Units","page":"Library API","title":"Sunny.Units","text":"Units(energy, length)\n\nPhysical constants in units of reference energy and length scales. Possible lengths are [:angstrom, :nm]. For atomic scale modeling, it is preferable to work in units of length=:angstrom, which follows the CIF file standard. Possible energy units are [:meV, :K, :THz, :inverse_cm, :T]. Kelvin is converted to energy via the Boltzmann constant k_B. Similarly, hertz is converted via the Planck constant h, inverse cm via the speed of light c, and tesla (field strength) via the Bohr magneton μ_B. For a given Units system, one can access any of the length and energy scale symbols listed above.\n\nExamples\n\n# Unit system with [energy] = meV and [length] = Å\nunits = Units(:meV, :angstrom)\n\n# Use the Boltzmann constant kB to convert 1 kelvin into meV\n@assert units.K ≈ 0.0861733326\n\n# Use the Planck constant h to convert 1 THz into meV\n@assert units.THz ≈ 4.135667696\n\n# Use the constant h c to convert 1 cm⁻¹ into meV\n@assert units.inverse_cm ≈ 0.1239841984\n\n# Use the Bohr magneton μB to convert 1 tesla into meV\n@assert units.T ≈ 0.05788381806\n\n# The physical constant μ0 μB² in units of ų meV.\n@assert u.vacuum_permeability ≈ 0.6745817653\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.add_sample!-Tuple{SampledCorrelations, System}","page":"Library API","title":"Sunny.add_sample!","text":"add_sample!(sc::SampledCorrelations, sys::System)\nadd_sample!(sc::SampledCorrelationsStatic, sys::System)\n\nMeasure pair correlation data for the spin configuration in sys, and accumulate these statistics into sc. For a dynamical SampledCorrelations, this involves time-integration of the provided spin trajectory, recording correlations in both space and time. Conversely, SampledCorrelationsStatic, will record only spatial correlations for the single spin configuration that is provided.\n\nTime-integration will update the spin configuration of sys in-place. To avoid this mutation, consider calling clone_system prior to add_sample!.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.clone_correlations-Tuple{SampledCorrelations}","page":"Library API","title":"Sunny.clone_correlations","text":"clone_correlations(sc::SampledCorrelations)\n\nCreate a copy of a SampledCorrelations.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.clone_system-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.clone_system","text":"clone_system(sys::System)\n\nCreates a full clone of the system, such that mutable updates to one copy will not affect the other, and thread safety is guaranteed.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.dispersion-Tuple{SpinWaveTheory, Any}","page":"Library API","title":"Sunny.dispersion","text":"dispersion(swt::SpinWaveTheory, qpts)\n\nGiven a list of wavevectors qpts in reciprocal lattice units (RLU), returns excitation energies for each band. The return value ret is 2D array, and should be indexed as ret[band_index, q_index].\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.dmvec-Tuple{Any}","page":"Library API","title":"Sunny.dmvec","text":"dmvec(D)\n\nAntisymmetric matrix representation of the Dzyaloshinskii-Moriya pseudo-vector,\n\n [ 0 D[3] -D[2]\n -D[3] 0 D[1]\n D[2] -D[1] 0 ]\n\nBy construction, Si'*dmvec(D)*Sj ≈ D⋅(Si×Sj) for any dipoles Si and Sj. This helper function is intended for use with set_exchange!.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.domain_average-Tuple{Any, Any, Any}","page":"Library API","title":"Sunny.domain_average","text":"domain_average(f, cryst, qpts; rotations, weights)\n\nCalculate an average intensity for the reciprocal-space points qpts under a discrete set of rotations. Rotations, in global coordinates, may be given either as an axis-angle pair or as a 3×3 rotation matrix. Each rotation is weighted according to the elements in weights. The function f should accept a list of rotated q-points and return an intensities calculation.\n\nExample\n\n# 0, 120, and 240 degree rotations about the global z-axis\nrotations = [([0,0,1], n*(2π/3)) for n in 0:2]\nweights = [1, 1, 1]\nres = domain_average(cryst, path; rotations, weights) do path_rotated\n intensities(swt, path_rotated; energies, kernel)\nend\nplot_intensities(res)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.eachsite-Tuple{System}","page":"Library API","title":"Sunny.eachsite","text":"eachsite(sys::System)\n\nAn iterator over all Sites in the system. \n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.enable_dipole_dipole!-Union{Tuple{System{N}}, Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.enable_dipole_dipole!","text":"enable_dipole_dipole!(sys::System, μ0_μB²)\n\nEnables long-range interactions between magnetic dipole moments,\n\n -(μ_04π) _ij 3 (μ_i𝐫_ij)(μ_j𝐫_ij) - μ_iμ_j r_ij^3\n\nwhere the sum is over all pairs of spins (singly counted), including periodic images, regularized using the Ewald summation convention. The magnetic_moment is defined as μ = -g μ_B 𝐒, where 𝐒 is the spin angular momentum dipole. The parameter μ0_μB² specifies the physical constant μ_0 μ_B^2, which has dimensions of length³-energy. Obtain this constant for a given system of Units via its vacuum_permeability property.\n\nExample\n\nunits = Units(:meV, :angstrom)\nenable_dipole_dipole!(sys, units.vacuum_permeability)\n\nSee also modify_exchange_with_truncated_dipole_dipole!.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.energy-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.energy","text":"energy(sys::System)\n\nThe total system energy. See also energy_per_site.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.energy_per_site-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.energy_per_site","text":"energy_per_site(sys::System)\n\nThe total system energy divided by the number of sites.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.excitations!-Tuple{Any, Any, SpinWaveTheory, Any}","page":"Library API","title":"Sunny.excitations!","text":"excitations!(T, tmp, swt::SpinWaveTheory, q)\n\nGiven a wavevector q, solves for the matrix T representing quasi-particle excitations, and returns a list of quasi-particle energies. Both T and tmp must be supplied as 2L2L complex matrices, where L is the number of bands for a single 𝐪 value.\n\nThe columns of T are understood to be contracted with the Holstein-Primakoff bosons 𝐛_𝐪 𝐛_-𝐪^. The first L columns provide the eigenvectors of the quadratic Hamiltonian for the wavevector 𝐪. The next L columns 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 -𝐪.\n\nexcitations!(T, tmp, swt::SpinWaveTheorySpiral, q; branch)\n\nCalculations on a SpinWaveTheorySpiral 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 spins in the magnetic cell. This yields a total of 3L excitations for a given momentum transfer 𝐪.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.excitations-Tuple{SpinWaveTheory, Any}","page":"Library API","title":"Sunny.excitations","text":"excitations(swt::SpinWaveTheory, q)\nexcitations(swt::SpinWaveTheorySpiral, q; branch)\n\nReturns a pair (energies, T) providing the excitation energies and eigenvectors. Prefer excitations! for performance, which avoids matrix allocations. See the documentation of excitations! for more details.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.gaussian-Tuple{}","page":"Library API","title":"Sunny.gaussian","text":"gaussian(; {fwhm, σ})\n\nReturns the function exp(-x^2/2σ^2) / √(2π*σ^2). Either fwhm or σ must be specified, where fwhm = (2.355...) * σ is the full width at half maximum.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.generate_mantid_script_from_binning_parameters-Tuple{Any}","page":"Library API","title":"Sunny.generate_mantid_script_from_binning_parameters","text":"generate_mantid_script_from_binning_parameters(params::BinningParameters)\n\nGenerate a Mantid script which bins data according to the given BinningParameters.\n\nwarning: Units\nTake care to ensure the units are correct (R.L.U. or absolute). You may want to call Sunny.bin_rlu_as_absolute_units! or Sunny.bin_absolute_units_as_rlu! first.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.global_position-Tuple{System, Any}","page":"Library API","title":"Sunny.global_position","text":"global_position(sys::System, site::Site)\n\nPosition of a Site in global coordinates.\n\nTo precompute a full list of positions, one can use eachsite as below:\n\npos = [global_position(sys, site) for site in eachsite(sys)]\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.intensities-Tuple{Sunny.AbstractSpinWaveTheory, Any}","page":"Library API","title":"Sunny.intensities","text":"intensities(swt::SpinWaveTheory, qpts; energies, kernel, kT=0)\nintensities(sc::SampledCorrelations, qpts; energies, kernel=nothing, kT)\n\nCalculates dynamical pair correlation intensities for a set of 𝐪-points in reciprocal space.\n\nLinear spin wave theory calculations are performed with an instance of SpinWaveTheory. The alternative SpinWaveTheorySpiral allows to study generalized spiral orders with a single, incommensurate-𝐤 ordering wavevector. Another alternative SpinWaveTheoryKPM is favorable for calculations on large magnetic cells, and allows to study systems with disorder. An optional nonzero temperature kT will scale intensities by the quantum thermal occupation factor 1 + n_B(ω) where n_B(ω) = 1(e^βω-1) is the Bose function.\n\nIntensities can also be calculated for SampledCorrelations associated with classical spin dynamics. In this case, thermal broadening will already be present, and the line-broadening kernel becomes optional. Conversely, the parameter kT becomes required. If positive, it will introduce an intensity correction factor βω (1 + n_B(ω)) that undoes the occupation factor for the classical Boltzmann distribution and applies the quantum thermal occupation factor. The special choice kT = nothing will suppress the classical-to-quantum correction factor, and yield statistics consistent with the classical Boltzmann distribution.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.intensities_bands-Tuple{SpinWaveTheory, Any}","page":"Library API","title":"Sunny.intensities_bands","text":"intensities_bands(swt::SpinWaveTheory, qpts; kT=0)\n\nCalculate spin wave excitation bands for a set of q-points in reciprocal space. This calculation is analogous to intensities, but does not perform line broadening of the bands.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.intensities_static-Tuple{Sunny.AbstractSpinWaveTheory, Any}","page":"Library API","title":"Sunny.intensities_static","text":"intensities_static(swt::SpinWaveTheory, qpts; bounds=(-Inf, Inf), kernel=nothing, kT=0)\nintensities_static(sc::SampledCorrelations, qpts; bounds=(-Inf, Inf), kT)\nintensities_static(sc::SampledCorrelationsStatic, qpts)\n\nLike intensities, but integrates the dynamical correlations mathcalS(𝐪 ω) over a range of energies ω. By default, the integration bounds are (- ), yielding the instantaneous (equal-time) correlations.\n\nIn SpinWaveTheory, the integral will be realized as a sum over discrete bands. Alternative calculation methods are SpinWaveTheorySpiral and SpinWaveTheoryKPM.\n\nClassical dynamics data in SampledCorrelations can also be used to calculate static intensities. In this case, the domain of integration will be a finite grid of available energies. Here, the parameter kT will be used to account for the quantum thermal occupation of excitations, as documented in intensities.\n\nStatic intensities calculated from SampledCorrelationsStatic are dynamics-independent. Instead, instantaneous correlations sampled from the classical Boltzmann distribution will be reported.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.lattice_params-Tuple{Any}","page":"Library API","title":"Sunny.lattice_params","text":"lattice_params(latvecs)\n\nCompute the lattice parameters (a b c α β γ) for the three lattice vectors provided as columns of latvecs. The inverse mapping is lattice_vectors.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.lattice_vectors-NTuple{6, Any}","page":"Library API","title":"Sunny.lattice_vectors","text":"lattice_vectors(a, b, c, α, β, γ)\n\nReturn the lattice vectors, as columns of the 33 output matrix, that define the shape of a crystallographic cell in global Cartesian coordinates. Conversely, one can view the output matrix as defining the global Cartesian coordinate system with respect to the lattice system.\n\nThe lattice constants (a b c) have units of length, and the angles (α β γ) are in degrees. The inverse mapping is lattice_params.\n\nExample\n\nlatvecs = lattice_vectors(1, 1, 2, 90, 90, 120)\na1, a2, a3 = eachcol(latvecs)\n@assert a1 ≈ [1, 0, 0] # a1 always aligned with global x\n@assert a2 ≈ [-1/2, √3/2, 0] # a2 always in global (x,y) plane\n@assert a3 ≈ [0, 0, 2] # a3 may generally be a combination of (x,y,z)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.load_nxs-Tuple{Any}","page":"Library API","title":"Sunny.load_nxs","text":"params, signal = load_nxs(filename; field=\"signal\")\n\nGiven the name of a Mantid-exported MDHistoWorkspace file, load the BinningParameters and the signal from that file.\n\nTo load another field instead of the signal, specify e.g. field=\"errors_squared\". Typical fields include errors_squared, mask, num_events, and signal.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.lorentzian-Tuple{}","page":"Library API","title":"Sunny.lorentzian","text":"lorentzian(; fwhm)\n\nReturns the function (Γ/2) / (π*(x^2+(Γ/2)^2)) where Γ = fwhm is the full width at half maximum.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.magnetic_moment-Tuple{System, Any}","page":"Library API","title":"Sunny.magnetic_moment","text":"magnetic_moment(sys::System, site::Site)\n\nReturns - g 𝐒, the local magnetic moment in units of the Bohr magneton. The spin dipole 𝐒 and g-tensor may both be Site dependent.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.merge_correlations-Tuple{Vector{SampledCorrelations}}","page":"Library API","title":"Sunny.merge_correlations","text":"merge_correlations(scs::Vector{SampledCorrelations)\n\nAccumulate a list of SampledCorrelations into a single, summary SampledCorrelations. Useful for reducing the results of parallel computations.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.minimize_energy!-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.minimize_energy!","text":"minimize_energy!(sys::System{N}; maxiters=1000, method=Optim.ConjugateGradient(),\n g_tol=1e-10, kwargs...) where N\n\nOptimizes the spin configuration in sys to minimize energy. A total of maxiters iterations will be attempted. Convergence is reached when the root mean squared energy gradient goes below g_tol. The remaining kwargs will be forwarded to the optimize method of the Optim.jl package.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.minimize_spiral_energy!-Tuple{Any, Any}","page":"Library API","title":"Sunny.minimize_spiral_energy!","text":"minimize_spiral_energy!(sys, axis; maxiters=10_000, k_guess=randn(sys.rng, 3))\n\nFinds a generalized spiral order that minimizes the spiral_energy. This involves optimization of the spin configuration in sys, and the propagation wavevector 𝐤, which will be returned in reciprocal lattice units (RLU). The axis vector normal to the polarization plane should be provided in global Cartesian coordinates, and will usually be determined by symmetry configurations. The initial k_guess will be random, unless otherwise provided.\n\nSee also suggest_magnetic_supercell to find a system shape that is approximately commensurate with the returned propagation wavevector 𝐤.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.modify_exchange_with_truncated_dipole_dipole!-Union{Tuple{N}, Tuple{System{N}, Any}, Tuple{System{N}, Any, Any}} where N","page":"Library API","title":"Sunny.modify_exchange_with_truncated_dipole_dipole!","text":"modify_exchange_with_truncated_dipole_dipole!(sys::System, cutoff, μ0_μB²)\n\nLike enable_dipole_dipole!, the purpose of this function is to introduce long-range dipole-dipole interactions between magnetic moments. Whereas enable_dipole_dipole! employs Ewald summation, this function instead employs real-space pair couplings with truncation at the specified cutoff distance. If the cutoff is relatively small, then this function may be faster than enable_dipole_dipole!.\n\nwarning: Mutation of existing couplings\nThis function will modify existing bilinear couplings between spins by adding dipole-dipole interactions. It must therefore be called after all other pair couplings have been specified. Conversely, any calls to set_exchange!, set_pair_coupling!, etc. will irreversibly delete the dipole-dipole interactions that have been introduced by this function.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.polarize_spins!-Union{Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.polarize_spins!","text":"polarize_spins!(sys::System, dir)\n\nPolarize all spins in the system along the direction dir.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.position_to_site-Tuple{System, Any}","page":"Library API","title":"Sunny.position_to_site","text":"position_to_site(sys::System, r)\n\nConverts a position r to four indices of a Site. The coordinates of r are given in units of the lattice vectors for the original crystal. This function can be useful for working with systems that have been reshaped using reshape_supercell.\n\nExample\n\n# Find the `site` at the center of a unit cell which is displaced by four\n# multiples of the first lattice vector\nsite = position_to_site(sys, [4.5, 0.5, 0.5])\n\n# Print the dipole at this site\nprintln(sys.dipoles[site])\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.powder_average-Tuple{Any, Any, Any, Int64}","page":"Library API","title":"Sunny.powder_average","text":"powder_average(f, cryst, radii, n; seed=0)\n\nCalculate a powder-average over structure factor intensities. The radii, with units of inverse length, define spherical shells in reciprocal space. The Fibonacci lattice yields n points on the sphere, with quasi-uniformity. Sample points on different shells are decorrelated through random rotations. A consistent random number seed will yield reproducible results. The function f should accept a list of q-points and call intensities.\n\nExample\n\nradii = range(0.0, 3.0, 200)\nres = powder_average(cryst, radii, 500) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.primitive_cell_shape-Tuple{Crystal}","page":"Library API","title":"Sunny.primitive_cell_shape","text":"primitive_cell_shape(cryst::Crystal)\n\nReturns the shape of the primitive cell as a 3×3 matrix, in fractional coordinates of the conventional lattice vectors. May be useful for constructing inputs to reshape_supercell.\n\nExamples\n\n# Valid if `cryst` has not been reshaped\n@assert cryst.prim_latvecs ≈ cryst.latvecs * primitive_cell_shape(cryst)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_bond-Tuple{Crystal, Bond}","page":"Library API","title":"Sunny.print_bond","text":"print_bond(cryst::Crystal, bond::Bond; b_ref::Bond)\n\nPrints symmetry information for bond bond. A symmetry-equivalent reference bond b_ref can optionally be provided to fix the meaning of the coefficients A, B, ...\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_site-Tuple{Any, Any}","page":"Library API","title":"Sunny.print_site","text":"print_site(cryst, i; R=I)\n\nPrint symmetry information for the site i, including allowed g-tensor and allowed anisotropy operator. An optional rotation matrix R can be provided to define the reference frame for expression of the anisotropy.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_stevens_expansion-Tuple{AbstractMatrix}","page":"Library API","title":"Sunny.print_stevens_expansion","text":"function print_stevens_expansion(op)\n\nPrints a local Hermitian operator as a linear combination of Stevens operators. The operator op may be a finite-dimensional matrix or an abstract spin polynomial in the large-s limit.\n\nExamples\n\nS = spin_matrices(2)\nprint_stevens_expansion(S[1]^4 + S[2]^4 + S[3]^4)\n# Prints: (1/20)𝒪₄₀ + (1/4)𝒪₄₄ + 102/5\n\nS = spin_matrices(Inf)\nprint_stevens_expansion(S[1]^4 + S[2]^4 + S[3]^4)\n# Prints: (1/20)𝒪₄₀ + (1/4)𝒪₄₄ + (3/5)𝒮⁴\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_suggested_frame-Tuple{Crystal, Int64}","page":"Library API","title":"Sunny.print_suggested_frame","text":"print_suggested_frame(cryst, i)\n\nPrint a suggested reference frame, as a rotation matrix R, that can be used as input to print_site(). The purpose is to simplify the description of allowed anisotropies.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_symmetry_table-Tuple{Crystal, Any}","page":"Library API","title":"Sunny.print_symmetry_table","text":"print_symmetry_table(cryst::Crystal, max_dist)\n\nPrint symmetry information for all equivalence classes of sites and bonds, up to a maximum bond distance of max_dist. Equivalent to calling print_bond(cryst, b) for every bond b in reference_bonds(cryst, max_dist), where Bond(i, i, [0,0,0]) refers to a single site i.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_wrapped_intensities-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.print_wrapped_intensities","text":"print_wrapped_intensities(sys::System; nmax=10)\n\nFor Bravais lattices: Prints up to nmax wavevectors according to their instantaneous (static) structure factor intensities, listed in descending order. For non-Bravais lattices: Performs the same analysis for each spin sublattice independently; the output weights are naïvely averaged over sublattices, without incorporating phase shift information. This procedure therefore wraps all wavevectors into the first Brillouin zone. Each wavevector coordinate is given between -12 and 12 in reciprocal lattice units (RLU). The output from this function will typically be used as input to suggest_magnetic_supercell.\n\nBecause this function does not incorporate phase information in its averaging over sublattices, the printed weights are not directly comparable with experiment. For that purpose, use SampledCorrelationsStatic instead.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.propose_delta-Tuple{Any}","page":"Library API","title":"Sunny.propose_delta","text":"propose_delta(magnitude)\n\nGenerate a proposal function that adds a Gaussian perturbation to the existing spin state. In :dipole mode, the procedure is to first introduce a random three-vector perturbation 𝐬 = 𝐬 + 𝐬 ξ and then return the properly normalized spin 𝐬 (𝐬𝐬). Each component of the random vector ξ is Gaussian distributed with a standard deviation of magnitude; the latter is dimensionless and typically smaller than one. \n\nIn :SUN mode, the procedure is analogous, but now involving Gaussian perturbations to each of the N complex components of an SU(N) coherent state.\n\nIn the limit of very large magnitude, this function coincides with propose_uniform.\n\nConsider also Langevin sampling, which is rejection free.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.propose_flip-Union{Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.propose_flip","text":"propose_flip\n\nFunction to propose pure spin flip updates in the context of a LocalSampler. Dipoles are flipped as 𝐬 -𝐬. SU(N) coherent states are flipped using the time-reversal operator.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.propose_uniform","page":"Library API","title":"Sunny.propose_uniform","text":"propose_uniform\n\nFunction to propose a uniformly random spin update in the context of a LocalSampler. In :dipole mode, the result is a random three-vector with appropriate normalization. In :SUN mode, the result is a random SU(N) coherent state with appropriate normalization.\n\nFor low-temperature Monte Carlo simulations, uniform spin proposals can be very inefficient due to a high probability of rejection in the Metropolis accept/reject step. Consider also Langevin sampling, which is rejection free.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.q_space_grid-Tuple{Crystal, Vararg{Any, 4}}","page":"Library API","title":"Sunny.q_space_grid","text":"q_space_grid(cryst::Crystal, axis1, range1, axis2, range2; offset=[0,0,0], orthogonalize=false)\nq_space_grid(cryst::Crystal, axis1, range1, axis2, range2, axis3, range3; orthogonalize=false)\n\nReturns a 2D or 3D grid of q-points with uniform spacing. The volume shape is defined by (axis1, axis2, ...) in reciprocal lattice units (RLU). Elements of (range1, range2, ...) provide coefficients c_i used to define grid positions,\n\n offset + c1 * axis1 + c2 * axis2 + ...\n\nA nonzero offset is allowed only in the 2D case. \n\nThe first range parameter, range1, must be a regularly spaced list of coefficients, e.g., range1 = range(lo1, hi1, n). Subsequent range parameters may be a pair of bounds, without grid spacing information. For example, by selecting range2 = (lo2, hi2), an appropriate step-size will be inferred to provide an approximately uniform sampling density in global Cartesian coordinates.\n\nThe axes may be non-orthogonal. To extend to an orthohombic volume in global Cartesian coordinates, set orthogonalize=true.\n\nFor a 1D grid, use q_space_path instead.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.q_space_path-Tuple{Crystal, Any, Any}","page":"Library API","title":"Sunny.q_space_path","text":"q_space_path(cryst::Crystal, qs, n; labels=nothing)\n\nReturns a 1D path consisting of n wavevectors sampled piecewise-linearly between the qs. Although the qs are provided in reciprocal lattice units (RLU), consecutive samples are spaced uniformly in the global (inverse-length) coordinate system. Optional labels can be associated with each special q-point, and will be used in plotting functions.\n\nSee also q_space_grid.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.randomize_spins!-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.randomize_spins!","text":"randomize_spins!(sys::System)\n\nRandomizes all spins under appropriate the uniform distribution.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.reference_bonds-Tuple{Crystal, Float64}","page":"Library API","title":"Sunny.reference_bonds","text":"reference_bonds(cryst::Crystal, max_dist)\n\nReturns a full list of bonds, one for each symmetry equivalence class, up to distance max_dist. The reference bond b for each equivalence class is selected according to a scoring system that prioritizes simplification of the elements in basis_for_symmetry_allowed_couplings(cryst, b).\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.remove_periodicity!-Union{Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.remove_periodicity!","text":"remove_periodicity!(sys::System, flags)\n\nRemove periodic interactions along each dimension d if flags[d] is true. The system must support inhomogeneous interactions via to_inhomogeneous.\n\nExample\n\n# Remove periodic boundaries along the 1st and 3rd dimensions\nremove_periodicity!(sys::System, (true, false, true))\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.repeat_periodically-Tuple{System, Tuple{Int64, Int64, Int64}}","page":"Library API","title":"Sunny.repeat_periodically","text":"repeat_periodically(sys::System, counts::NTuple{3, Int})\n\nCreates a System identical to sys but repeated a given number of times along each system axis according to the specified counts. This is a special case of the more general reshape_supercell.\n\nSee also repeat_periodically_as_spiral, which rotates the spins between periodic copies.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.repeat_periodically_as_spiral-Tuple{System, Tuple{Int64, Int64, Int64}}","page":"Library API","title":"Sunny.repeat_periodically_as_spiral","text":"repeat_periodically_as_spiral(sys::System, counts::NTuple{3, Int}; k, axis)\n\nRepeats the magnetic cell of System a number of times along each system axis according to the specified counts. Spins in each system image will be rotated according to the propagation wavevector k (in RLU) and the rotation axis (in global Cartesian coordinates). Coincides with repeat_periodically in the special case of k = [0, 0, 0]\n\nSee also minimize_spiral_energy! to find an energy-minimizing wavevector k and spin dipole configuration.\n\nExample\n\nk = minimize_spiral_energy!(sys, axis; k_guess=randn(3))\nrepeat_periodically_as_spiral(sys, counts; k, axis)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.reshape_supercell-Tuple{System, Any}","page":"Library API","title":"Sunny.reshape_supercell","text":"reshape_supercell(sys::System, shape)\n\nMaps an existing System to a new one that has the shape and periodicity of a requested supercell. The columns of the 33 integer matrix shape represent the supercell lattice vectors measured in units of the original crystal lattice vectors. Interactions, spins, and other settings will be inherited from sys.\n\nIn the special case that shape is a diagonal matrix, this function coincides with resize_supercell.\n\nSee also repeat_periodically.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.resize_supercell-Tuple{System, Tuple{Int64, Int64, Int64}}","page":"Library API","title":"Sunny.resize_supercell","text":"resize_supercell(sys::System, dims::NTuple{3, Int})\n\nCreates a System with a given number of conventional unit cells in each lattice vector direction. Interactions, spins, and other settings will be inherited from sys.\n\nEquivalent to:\n\nreshape_supercell(sys, [dims[1] 0 0; 0 dims[2] 0; 0 0 dims[3]])\n\nSee also reshape_supercell and repeat_periodically.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.rotate_operator-Tuple{LinearAlgebra.Hermitian{ComplexF64, Matrix{ComplexF64}}, Any}","page":"Library API","title":"Sunny.rotate_operator","text":"rotate_operator(A, R)\n\nRotates the local quantum operator A according to the 33 rotation matrix R.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_coherent!-Union{Tuple{N}, Tuple{System{N}, Any, Any}} where N","page":"Library API","title":"Sunny.set_coherent!","text":"set_coherent!(sys::System, Z, site::Site)\n\nSet a coherent spin state at a Site using the N complex amplitudes in Z.\n\nFor a single quantum spin-s, these amplitudes will be interpreted in the eigenbasis of S^z. That is, Z[1] represents the amplitude for the basis state fully polarized along the z-direction, and subsequent components represent states with decreasing angular momentum along this axis (m = s s-1 -s).\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_dipole!-Union{Tuple{N}, Tuple{System{N}, Any, Any}} where N","page":"Library API","title":"Sunny.set_dipole!","text":"set_dipole!(sys::System, dir, site::Site)\n\nPolarize the spin at a Site along the direction dir.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_dipoles_from_mcif!-Tuple{System, AbstractString}","page":"Library API","title":"Sunny.set_dipoles_from_mcif!","text":"set_dipoles_from_mcif!(sys::System, filename::AbstractString)\n\nLoad the magnetic supercell according to an mCIF file. System sys must already be resized to the correct supercell dimensions.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_exchange!-Union{Tuple{N}, Tuple{System{N}, Any, Bond}} where N","page":"Library API","title":"Sunny.set_exchange!","text":"set_exchange!(sys::System, J, bond::Bond; biquad=0)\n\nSets an exchange interaction 𝐒_iJ 𝐒_j along the specified bond. This interaction will be propagated to equivalent bonds in consistency with crystal symmetry. Any previous interactions on these bonds will be overwritten. The parameter bond has the form Bond(i, j, offset), where i and j are atom indices within the unit cell, and offset is a displacement in unit cells.\n\nAs a convenience, scalar J can be used to specify a Heisenberg interaction. Also, the function dmvec(D) can be used to construct the antisymmetric part of the exchange, where D is the Dzyaloshinskii-Moriya pseudo-vector. The resulting interaction will be 𝐃(𝐒_i𝐒_j).\n\nThe optional numeric parameter biquad multiplies a scalar biquadratic interaction, (𝐒_i𝐒_j)^2, with Interaction Renormalization if appropriate. For more general interactions, use set_pair_coupling! instead.\n\nExamples\n\nusing LinearAlgebra\n\n# Set a Heisenberg and DM interaction: 2Si⋅Sj + D⋅(Si×Sj)\nD = [0, 0, 3]\nset_exchange!(sys, 2I + dmvec(D), bond)\n\n# The same interaction as an explicit exchange matrix\nJ = [2 3 0;\n -3 2 0;\n 0 0 2]\nset_exchange!(sys, J, bond)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_exchange_at!-Union{Tuple{N}, Tuple{System{N}, Any, Union{NTuple{4, Int64}, CartesianIndex{4}}, Union{NTuple{4, Int64}, CartesianIndex{4}}}} where N","page":"Library API","title":"Sunny.set_exchange_at!","text":"set_exchange_at!(sys::System, J, site1::Site, site2::Site; biquad=0, offset=nothing)\n\nSets an exchange interaction `𝐒_i⋅J 𝐒_j along the single bond connecting two Sites, ignoring crystal symmetry. Any previous coupling on this bond will be overwritten. The system must support inhomogeneous interactions via to_inhomogeneous.\n\nUse symmetry_equivalent_bonds to find (site1, site2, offset) values that are symmetry equivalent to a given Bond in the original system. For systems that are relatively small, the offset vector (in multiples of unit cells) will resolve ambiguities in the periodic wrapping.\n\nSee also set_exchange! for more details on specifying J and biquad. For more general couplings, use set_pair_coupling_at! instead.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_field!-Tuple{System, Any}","page":"Library API","title":"Sunny.set_field!","text":"set_field!(sys::System, B_μB)\n\nSets the external magnetic field 𝐁 scaled by the Bohr magneton μ_B. This scaled field has units of energy and couples directly to the dimensionless magnetic_moment. At every site, the Zeeman coupling contributes an energy + (𝐁 μ_B) (g 𝐒), involving the local g-tensor and spin angular momentum 𝐒. Commonly, g +2 such that 𝐒 is favored to anti-align with the applied field 𝐁. Note that a given system of Units will implicitly use the Bohr magneton to convert between field and energy dimensions.\n\nExample\n\n# In units of meV, apply a 2 tesla field in the z-direction\nunits = Units(:meV, :angstrom)\nset_field!(sys, [0, 0, 2] * units.T)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_field_at!-Tuple{System, Any, Any}","page":"Library API","title":"Sunny.set_field_at!","text":"set_field_at!(sys::System, B_μB, site::Site)\n\nSets the external magnetic field 𝐁 scaled by the Bohr magneton μ_B for a single Site. This scaled field has units of energy and couples directly to the dimensionless magnetic_moment. Note that a given system of Units will implicitly use the Bohr magneton to convert between field and energy dimensions.\n\nSee the documentation of set_field! for more information.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_onsite_coupling!-Tuple{System, Any, Int64}","page":"Library API","title":"Sunny.set_onsite_coupling!","text":"set_onsite_coupling!(sys::System, op, i::Int)\n\nSet the single-ion anisotropy for the ith atom of every unit cell, as well as all symmetry-equivalent atoms. The operator op may be provided as an abstract function of the local spin operators, as a polynomial of spin_matrices, or as a linear combination of stevens_matrices.\n\nExamples\n\n# An easy axis anisotropy in the z-direction\nset_onsite_coupling!(sys, S -> -D*S[3]^3, i)\n\n# The unique quartic single-ion anisotropy for a site with cubic point group\n# symmetry\nset_onsite_coupling!(sys, S -> 20*(S[1]^4 + S[2]^4 + S[3]^4), i)\n\n# An equivalent expression of this quartic anisotropy, up to a constant shift\nO = stevens_matrices(spin_label(sys, i))\nset_onsite_coupling!(sys, O[4,0] + 5*O[4,4], i)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_onsite_coupling_at!-Tuple{System, Any, Union{NTuple{4, Int64}, CartesianIndex{4}}}","page":"Library API","title":"Sunny.set_onsite_coupling_at!","text":"set_onsite_coupling_at!(sys::System, op, site::Site)\n\nSets the single-ion anisotropy operator op for a single Site, ignoring crystal symmetry. The system must support inhomogeneous interactions via to_inhomogeneous.\n\nSee also set_onsite_coupling!.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_pair_coupling!-Union{Tuple{N}, Tuple{System{N}, AbstractMatrix, Any}} where N","page":"Library API","title":"Sunny.set_pair_coupling!","text":"set_pair_coupling!(sys::System, op, bond)\n\nSets an arbitrary coupling op along bond. This coupling will be propagated to equivalent bonds in consistency with crystal symmetry. Any previous interactions on these bonds will be overwritten. The parameter bond has the form Bond(i, j, offset), where i and j are atom indices within the unit cell, and offset is a displacement in unit cells. The operator op may be provided as an anonymous function that accepts two spin dipole operators, or as a matrix that acts in the tensor product space of the two sites.\n\nExamples\n\n# Bilinear+biquadratic exchange involving 3×3 matrices J1 and J2\nset_pair_coupling!(sys, (Si, Sj) -> Si'*J1*Sj + (Si'*J2*Sj)^2, bond)\n\n# Equivalent expression using an appropriate fixed matrix representation\nS = spin_matrices(1/2)\nSi, Sj = to_product_space(S, S)\nset_pair_coupling!(sys, Si'*J1*Sj + (Si'*J2*Sj)^2, bond)\n\nSee also spin_matrices, to_product_space.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_pair_coupling_at!-Union{Tuple{N}, Tuple{System{N}, AbstractMatrix, Union{NTuple{4, Int64}, CartesianIndex{4}}, Union{NTuple{4, Int64}, CartesianIndex{4}}}} where N","page":"Library API","title":"Sunny.set_pair_coupling_at!","text":"set_pair_coupling_at!(sys::System, op, bond)\n\nSets an arbitrary coupling along the single bond connecting two Sites, ignoring crystal symmetry. Any previous coupling on this bond will be overwritten. The system must support inhomogeneous interactions via to_inhomogeneous.\n\nUse symmetry_equivalent_bonds to find (site1, site2, offset) values that are symmetry equivalent to a given Bond in the original system. For systems that are relatively small, the offset vector (in multiples of unit cells) will resolve ambiguities in the periodic wrapping.\n\nThe operator op may be provided as an anonymous function that accepts two spin dipole operators, or as a matrix that acts in the tensor product space of the two sites. The documentation for set_pair_coupling! provides examples constructing op.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_spin_rescaling!-Tuple{System{0}, Any}","page":"Library API","title":"Sunny.set_spin_rescaling!","text":"set_spin_rescaling!(sys, α)\n\nIn dipole mode, rescale all spin magnitudes S α S. In SU(N) mode, rescale all SU(N) coherent states Z α Z such that every expectation value rescales like A α A.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_vacancy_at!-Union{Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.set_vacancy_at!","text":"set_vacancy_at!(sys::System, site::Site)\n\nMake a single site nonmagnetic. Site includes a unit cell and a sublattice index.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.spin_label-Tuple{System, Int64}","page":"Library API","title":"Sunny.spin_label","text":"spin_label(sys::System, i::Int)\n\nIf atom i carries a single spin-s moment, then returns the half-integer label s. Otherwise, throws an error.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.spin_matrices-Tuple{Any}","page":"Library API","title":"Sunny.spin_matrices","text":"spin_matrices(s)\n\nReturns a triple of NN spin matrices, where N = 2s+1. These are the generators of SU(2) in the spin-s representation.\n\nIf s == Inf, then the return values are abstract symbols denoting infinite-dimensional matrices that commute. These can be useful for repeating historical studies, or modeling micromagnetic systems. A technical discussion appears in the Sunny documentation page: Interaction Renormalization.\n\nExample\n\nS = spin_matrices(3/2)\n@assert S'*S ≈ (3/2)*(3/2+1)*I\n@assert S[1]*S[2] - S[2]*S[1] ≈ im*S[3]\n\nS = spin_matrices(Inf)\n@assert S[1]*S[2] - S[2]*S[1] == 0\n\nSee also print_stevens_expansion.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.spiral_energy-Tuple{System{0}}","page":"Library API","title":"Sunny.spiral_energy","text":"spiral_energy(sys::System; k, axis)\n\nReturns the energy of a generalized spiral phase associated with the propagation wavevector k (in reciprocal lattice units, RLU) and an axis vector that is normal to the polarization plane (in global Cartesian coordinates).\n\nWhen 𝐤 is incommensurate, this calculation can be viewed as creating an infinite number of periodic copies of sys. The spins on each periodic copy are rotated about the axis vector, with the angle θ = 2π 𝐤𝐫, where 𝐫 denotes the displacement vector between periodic copies of sys in multiples of the lattice vectors of the chemical cell.\n\nThe return value is the energy associated with one periodic copy of sys. The special case 𝐤 = 0 yields result is identical to energy.\n\nSee also minimize_spiral_energy! and repeat_periodically_as_spiral.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.spiral_energy_per_site-Tuple{System{0}}","page":"Library API","title":"Sunny.spiral_energy_per_site","text":"spiral_energy_per_site(sys::System; k, axis)\n\nThe spiral_energy divided by the number of sites in sys. The special case 𝐤 = 0 yields a result identical to energy_per_site.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ssf_custom-Tuple{Any, System}","page":"Library API","title":"Sunny.ssf_custom","text":"ssf_custom(f, sys::System; apply_g=true, formfactors=nothing)\n\nSpecify measurement of the spin structure factor with a custom contraction function f. This function accepts a wavevector 𝐪 in global Cartesian coordinates, and a 3×3 matrix with structure factor intensity components mathcalS^αβ(𝐪ω). Indices (α β) denote dipole components in global coordinates. The return value of f can be any number or isbits type. With specific choices of f, one can obtain measurements such as defined in ssf_perp and ssf_trace.\n\nBy default, the g-factor or tensor is applied at each site, such that the structure factor components are correlations between the magnetic moment operators. Set apply_g = false to measure correlations between the bare spin operators.\n\nThe optional formfactors comprise a list of pairs [i1 => FormFactor(...), i2 => ...], where i1, i2, ... are a complete set of symmetry-distinct atoms, and each FormFactor implements 𝐪-space attenuation for the given atom.\n\nIntended for use with SpinWaveTheory and instances of SampledCorrelations.\n\nExamples\n\n# Measure all 3×3 structure factor components Sᵅᵝ\nmeasure = ssf_custom((q, ssf) -> ssf, sys)\n\n# Measure the structure factor trace Sᵅᵅ\nmeasure = ssf_custom((q, ssf) -> real(sum(ssf)), sys)\n\nSee also the Sunny documentation on Structure Factor Conventions.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ssf_custom_bm-Tuple{Any, System}","page":"Library API","title":"Sunny.ssf_custom_bm","text":"ssf_custom_bm(f, sys::System; u, v, apply_g=true, formfactors=nothing)\n\nSpecify measurement of the spin structure factor with a custom contraction function f. The interface is identical to ssf_custom except that f here receives momentum 𝐪 and the 3×3 structure factor data mathcalS^αβ(𝐪 ω) in the basis of the Blume-Maleev axis system. The wavevectors u and v, provided in reciprocal lattice units, will be used to define the scattering plane. In global Cartesian coordinates, the three orthonormal BM axes (e1, e2, e3) are defined as follows:\n\ne3 = normalize(u × v) # normal to the scattering plane (u, v)\ne1 = normalize(q) # momentum transfer q within scattering plane\ne2 = normalize(e3 × q) # perpendicular to q and in the scattering plane\n\nExample\n\n# Measure imaginary part of S²³ - S³² in the Blume-Maleev axis system for\n# the scattering plane [0, K, L].\nmeasure = ssf_custom_bm(sys; u=[0, 1, 0], v=[0, 0, 1]) do q, ssf\n imag(ssf[2,3] - ssf[3,2])\nend\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ssf_perp-Tuple{System}","page":"Library API","title":"Sunny.ssf_perp","text":"ssf_perp(sys::System; apply_g=true, formfactors=nothing)\n\nSpecify measurement of the spin structure factor with contraction by (I-𝐪𝐪q^2). The contracted value provides an estimate of unpolarized scattering intensity. In the singular limit 𝐪 0, the contraction matrix is replaced by its rotational average, (23) I.\n\nThis function is a special case of ssf_custom.\n\nExample\n\n# Select Co²⁺ form factor for atom 1 and its symmetry equivalents\nformfactors = [1 => FormFactor(\"Co2\")]\nssf_perp(sys; formfactors)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ssf_trace-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.ssf_trace","text":"ssf_trace(sys::System; apply_g=true, formfactors=nothing)\n\nSpecify measurement of the spin structure factor, with trace over spin components. This quantity can be useful for checking quantum sum rules.\n\nThis function is a special case of ssf_custom.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.standardize-Tuple{Crystal}","page":"Library API","title":"Sunny.standardize","text":"standardize(cryst::Crystal; idealize=true)\n\nReturn the symmetry-inferred standardized crystal unit cell. If idealize=true, then the lattice vectors and site positions will be adapted. See \"definitions and conventions\" of the spglib documentation for more information.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.step!","page":"Library API","title":"Sunny.step!","text":"step!(sys::System, dynamics)\n\nAdvance the spin configuration one dynamical time-step. The dynamics object may be a continuous spin dynamics, such as Langevin or ImplicitMidpoint, or it may be a discrete Monte Carlo sampling scheme such as LocalSampler.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.stevens_matrices-Tuple{Any}","page":"Library API","title":"Sunny.stevens_matrices","text":"stevens_matrices(s)\n\nReturns a generator of Stevens operators in the spin-s representation. The return value O can be indexed as O[k,q], where 0 k 6 labels an irrep of SO(3) and -k q k. This will produce an NN matrix where ``N = 2s\n\n1``. Linear combinations of Stevens operators can be used as a \"physical\n\nbasis\" for decomposing local observables. To see this decomposition, use print_stevens_expansion.\n\nIf s == Inf, then symbolic operators will be returned. In this infinite dimensional limit, the Stevens operators become homogeneous polynomials of commuting spin operators.\n\nExample\n\nO = stevens_matrices(2)\nS = spin_matrices(2)\n\nA = (1/20)O[4,0] + (1/4)O[4,4] + (102/5)I\nB = S[1]^4 + S[2]^4 + S[3]^4\n@assert A ≈ B\n\nSee also spin_matrices and Interaction Renormalization.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.subcrystal-Union{Tuple{N}, Tuple{Crystal, Vararg{String, N}}} where N","page":"Library API","title":"Sunny.subcrystal","text":"subcrystal(cryst, types) :: Crystal\n\nFilters sublattices of a Crystal by atom types, keeping the space group unchanged.\n\nsubcrystal(cryst, classes) :: Crystal\n\nFilters sublattices of Crystal by equivalence classes, keeping the space group unchanged.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.suggest_magnetic_supercell-Tuple{Any}","page":"Library API","title":"Sunny.suggest_magnetic_supercell","text":"suggest_magnetic_supercell(ks; tol=1e-12, maxsize=100)\n\nSuggests a magnetic supercell, in units of the crystal lattice vectors, that is consistent with periodicity of the wavevectors ks in RLU. If the wavevectors are incommensurate (with respect to the maximum supercell size maxsize), one can select a larger error tolerance tol to find a supercell that is almost commensurate.\n\nPrints a 33 matrix of integers that is suitable for use in reshape_supercell.\n\nExamples\n\n# A magnetic supercell for a single-Q structure. Will print\nk1 = [0, -1/4, 1/4]\nsuggest_magnetic_supercell([k1]) # [1 0 0; 0 2 1; 0 -2 1]\n\n# A larger magnetic supercell for a double-Q structure\nk2 = [1/4, 0, 1/4]\nsuggest_magnetic_supercell([k1, k2]) # [1 2 2; -1 2 -2; -1 2 2]\n\n# If given incommensurate wavevectors, find an approximate supercell that\n# is exactly commensurate for nearby wavevectors.\nsuggest_magnetic_supercell([[0, 0, 1/√5], [0, 0, 1/√7]]; tol=1e-2)\n\n# This prints [1 0 0; 0 1 0; 0 0 16], which becomes commensurate under the\n# approximations `1/√5 ≈ 7/16` and `1/√7 ≈ 3/8`.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.suggest_timestep-Union{Tuple{N}, Tuple{System{N}, Union{ImplicitMidpoint, Langevin}}} where N","page":"Library API","title":"Sunny.suggest_timestep","text":"suggest_timestep(sys, integrator; tol)\n\nSuggests a timestep for the numerical integration of spin dynamics according to a given error tolerance tol. The integrator should be Langevin or ImplicitMidpoint. The suggested dt will be inversely proportional to the magnitude of the effective field dEd𝐬 arising from the current spin configuration in sys. The recommended timestep dt scales like √tol, which assumes second-order accuracy of the integrator.\n\nThe system sys should be initialized to an equilibrium spin configuration for the target temperature. Alternatively, a reasonably timestep estimate can be obtained from any low-energy spin configuration. For this, one can use randomize_spins! and then minimize_energy!.\n\nLarge damping magnitude or target temperature kT will tighten the timestep bound. If damping exceeds 1, it will rescale the suggested timestep by an approximate the factor 1damping. If kT is the largest energy scale, then the suggested timestep will scale like 1/(damping*kT). Quantification of numerical error for stochastic dynamics is subtle. The stochastic Heun integration scheme is weakly convergent of order-1, such that errors in the estimates of averaged observables may scale like dt. This implies that the tol argument may actually scale like the square of the true numerical error, and should be selected with this in mind.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.symmetry_equivalent_bonds-Tuple{System, Bond}","page":"Library API","title":"Sunny.symmetry_equivalent_bonds","text":"symmetry_equivalent_bonds(sys::System, bond::Bond)\n\nGiven a Bond for the original (unreshaped) crystal, return all symmetry equivalent bonds in the System. Each returned bond is represented as a pair of Sites, which may be used as input to set_exchange_at! or set_pair_coupling_at!. Reverse bonds are not included in the iterator (no double counting).\n\nExample\n\nfor (site1, site2, offset) in symmetry_equivalent_bonds(sys, bond)\n @assert site1 < site2\n set_exchange_at!(sys, J, site1, site2; offset)\nend\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.to_inhomogeneous-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.to_inhomogeneous","text":"to_inhomogeneous(sys::System)\n\nReturns a copy of the system that allows for inhomogeneous interactions, which can be set using set_onsite_coupling_at!, set_exchange_at!, and set_vacancy_at!.\n\nInhomogeneous systems do not support symmetry-propagation of interactions or system reshaping.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.to_product_space-Tuple{Any, Any, Vararg{Any}}","page":"Library API","title":"Sunny.to_product_space","text":"to_product_space(A, B, ...)\n\nGiven lists of operators acting on local Hilbert spaces individually, return the corresponding operators that act on the tensor product space. In typical usage, the inputs will represent local physical observables and the outputs will be used to define quantum couplings.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.@mix_proposals-Tuple","page":"Library API","title":"Sunny.@mix_proposals","text":"@mix_proposals weight1 propose1 weight2 propose2 ...\n\nMacro to generate a proposal function that randomly selects among the provided functions according to the provided probability weights. For use with LocalSampler.\n\nExample\n\n# A proposal function that proposes a spin flip 40% of the time, and a\n# Gaussian perturbation 60% of the time.\n@mix_proposals 0.4 propose_flip 0.6 propose_delta(0.2)\n\n\n\n\n\n","category":"macro"},{"location":"library.html#Optional-Makie-extensions","page":"Library API","title":"Optional Makie extensions","text":"","category":"section"},{"location":"library.html","page":"Library API","title":"Library API","text":"The following will be enabled through a package extension if either GLMakie or WGLMakie is loaded.","category":"page"},{"location":"library.html","page":"Library API","title":"Library API","text":"plot_spins\nplot_spins!\nplot_intensities\nplot_intensities!\nview_crystal","category":"page"},{"location":"library.html#Sunny.plot_spins","page":"Library API","title":"Sunny.plot_spins","text":"plot_spins(sys::System; arrowscale=1.0, color=:red, colorfn=nothing,\n colormap=:viridis, colorrange=nothing, show_cell=true, orthographic=false,\n ghost_radius=0, ndims=3, compass=true)\n\nPlot the spin configuration defined by sys. Optional parameters are:\n\narrowscale: Scale all arrows by dimensionless factor.\ncolor: Arrow colors. May be symbolic or numeric. If scalar, will be shared among all sites.\ncolorfn: Function that dynamically maps from a site index to a numeric color value. Useful for animations.\ncolormap, colorrange: Used to populate colors from numbers following Makie conventions.\nshow_cell: Show original crystallographic unit cell.\northographic: Use orthographic camera perspective.\nghost_radius: Show periodic images up to a given distance (length units).\nndims: Spatial dimensions of system (1, 2, or 3).\ncompass: If true, draw Cartesian axes in bottom left.\n\nCalling notify on the return value will animate the figure.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.plot_spins!","page":"Library API","title":"Sunny.plot_spins!","text":"plot_spins!(ax, sys::System; opts...)\n\nMutating variant of plot_spins that allows drawing into a single panel of a Makie figure.\n\nExample\n\nfig = Figure()\nplot_spins!(fig[1, 1], sys1)\nplot_spins!(fig[2, 1], sys2)\ndisplay(fig)\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.plot_intensities","page":"Library API","title":"Sunny.plot_intensities","text":"plot_intensities(res::BandIntensities; colormap=nothing, colorrange=nothing, allpositive=true,\n saturation=0.9, sensitivity=0.0025, fwhm=nothing, ylims=nothing, units=nothing,\n into=nothing, title=\"\")\nplot_intensities(res::Intensities; colormap=nothing, colorrange=nothing, allpositive=true, \n saturation=0.9, units=nothing, into=nothing, title=\"\")\nplot_intensities(res::StaticIntensities; colormap=nothing, colorrange=nothing, allpositive=true, \n saturation=0.9, units=nothing, into=nothing, title=\"\")\nplot_intensities(res::PowderIntensities; colormap=nothing, colorrange=nothing, allpositive=true, \n saturation=0.9, units=nothing, into=nothing, title=\"\")\n\nKeyword arguments:\n\ncolormap: Color palette for plotting broadened intensities. See Makie docs for allowed values.\ncolorrange: A lower and upper bound on intensities. For heatmaps, these bounds define the intensity values that saturate the colormap.\nallpositive: Should intensities be all positive, apart from numerical error? If true, the default colors will clip below zero intensity. If false, the default colors will be symmetric about zero intensity.\nsaturation: If colorrange is not explicitly set, this dimensionless parameter defines the upper saturated intensity value as a quantile of maximum intensities taken over wavevectors.\nsensitivity: When plotting BandIntensities, this defines a lower bound on the visible intensities as a fraction of the upper saturated intensity value.\nfwhm: When plotting BandIntensities, this overrides the full-width at half-maximum value used for Gaussian broadening.\nylims: Limits of the y-axis.\nunits: A Units instance for labeling axes and performing conversions.\ninto: A symbol for conversion into a new base energy unit (e.g. :meV, :K, etc.)\ntitle: An optional title for the plot.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.plot_intensities!","page":"Library API","title":"Sunny.plot_intensities!","text":"plot_intensities!(panel, res::AbstractIntensities; opts...)\n\nMutating variant of plot_intensities that allows drawing into a single panel of a Makie figure.\n\nExample\n\nfig = Figure()\nplot_intensities!(fig[1, 1], res1; title=\"Panel 1\")\nplot_intensities!(fig[2, 1], res2; title=\"Panel 2\")\ndisplay(fig)\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.view_crystal","page":"Library API","title":"Sunny.view_crystal","text":"view_crystal(crystal::Crystal; refbonds=10, orthographic=false, ghost_radius=nothing, ndims=3, compass=true)\nview_crystal(sys::System; ...)\n\nLaunches a graphical user interface to visualize the Crystal unit cell. If a System is provided, then the 3×3 exchange matrices for each bond will be depicted graphically.\n\nrefbonds: By default, calculate up to 10 reference bonds using the reference_bonds function. An explicit list of reference bonds may also be provided.\northographic: Use orthographic camera perspective.\nghost_radius: Show periodic images up to a given distance. Defaults to the cell size.\nndims: Spatial dimensions of system (1, 2, or 3).\ncompass: If true, draw Cartesian axes in bottom left.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Optional-WriteVTK-extensions","page":"Library API","title":"Optional WriteVTK extensions","text":"","category":"section"},{"location":"library.html","page":"Library API","title":"Library API","text":"The following will be enabled through a package extension if WriteVTK is loaded.","category":"page"},{"location":"library.html","page":"Library API","title":"Library API","text":"export_vtk","category":"page"},{"location":"library.html#Sunny.export_vtk","page":"Library API","title":"Sunny.export_vtk","text":"export_vtk(filename,params::BinningParameters,data)\n\nExport a VTK-compatible file to filename (do not include file extension when specifying the file name) which contains the data as VTK Cell Data on a grid parameterized by params.\n\nAt least one axis of the BinningParameters must be integrated over, since VTK does not support 4D data. See integrate_axes!.\n\n\n\n\n\n","category":"function"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"EditURL = \"../../../examples/05_MC_Ising.jl\"","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/05_MC_Ising.html#5.-Monte-Carlo-sampling-of-the-Ising-model","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"","category":"section"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"This tutorial illustrates simulation of the classical 2D Ising model.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"To model the 2D square lattice, create an elongated tetragonal cell with one atom.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"latvecs = lattice_vectors(1, 1, 10, 90, 90, 90)\ncrystal = Crystal(latvecs, [[0, 0, 0]])","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Create a System of spin dipoles. Following the Ising convention, we will restrict the dipoles to 1 along the global hatz-axis. Select g=-1 so that the Zeeman coupling between external field 𝐁 and spin dipole 𝐬 is -𝐁𝐬. The system size is 128×128.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"L = 128\nsys = System(crystal, [1 => Moment(s=1, g=-1)], :dipole; dims=(L, L, 1), seed=0)\npolarize_spins!(sys, (0, 0, 1))","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Use set_exchange! to include a ferromagnetic Heisenberg interaction along nearest-neighbor bonds. The Bond below connects two spins displaced by the lattice vector 𝐚₁. This interaction will be propagated to all nearest-neighbors bonds in the system, consistent with the symmetries of the square lattice.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"set_exchange!(sys, -1.0, Bond(1, 1, (1, 0, 0)))","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"If an external field is desired, it can be set using set_field!.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"B = 0\nset_field!(sys, (0, 0, B))","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"The critical temperature for the Ising model is known analytically.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Tc = 2/log(1+√2)","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Use a LocalSampler to perform nsweeps Monte Carlo sweeps. A sweep consists of, on average, one trial update per spin in the system. Each proposed update is accepted or rejected according to the Metropolis acceptance probability. As its name suggests, the propose_flip function will only propose pure spin flips, 𝐬 rightarrow -𝐬.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"nsweeps = 4000\nsampler = LocalSampler(kT=Tc, propose=propose_flip)\nfor i in 1:nsweeps\n step!(sys, sampler)\nend","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Plot the Ising spins by extracting the z-component of the dipoles","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"heatmap(reshape([S[3] for S in sys.dipoles], (L, L)))","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#MgCr2O4-at-Finite-Temperature","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Author: Martin Mourigal","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Date: September 9, 2022 (Updated August 29, 2024 using Sunny 0.7.0)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"In this tutorial, we will walk through an example in Sunny and calculate the spin dynamical properties of the Heisenberg pyrochlore antiferromagnet and apply this knowledge to MgCr2O4 and ZnCr2O4, which are known to approximate this model. Relevant publications include:","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"[1] P. H. Conlon and J. T. Chalker, Phys. Rev. Lett. 102, 237206 (2009)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"[2] P. H. Conlon and J. T. Chalker, Phys. Rev. B 81, 224413 (2010)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"[3] X. Bai, J. A. M. Paddison, et al. Phys. Rev. Lett. 122, 097201 (2019)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Setting-up-Julia","page":"MgCr2O4 at Finite Temperature","title":"Setting up Julia","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To run the examples in the tutorial, you will need a working installation of the Julia programming language and the Sunny package. Some useful references for getting started are:","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Getting started with Julia for Sunny\nSunny Docs","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We will begin by loading the relevant packages.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"using Sunny # The main package\nusing GLMakie # Plotting package","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Setting-up-the-crystal-structure","page":"MgCr2O4 at Finite Temperature","title":"Setting up the crystal structure","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Before specifying the interactions of our system, we first must set up the crystal. We will begin by specifying the pyrochlore lattice (illustrated below) in the manner that is typical of theorists.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Picture Credits: Theory of Quantum Matter Unit, OIST","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#\"Theorist\"-Method","page":"MgCr2O4 at Finite Temperature","title":"\"Theorist\" Method","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"In this approach, we directly define the lattice vectors and specify the position of each atom in fractional coordinates.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"latvecs = lattice_vectors(8.3342, 8.3342, 8.3342, 90, 90, 90)\npositions = [[0.875, 0.625, 0.375],\n [0.625, 0.125, 0.625],\n [0.875, 0.875, 0.125],\n [0.625, 0.875, 0.375],\n [0.875, 0.125, 0.875],\n [0.625, 0.625, 0.125],\n [0.875, 0.375, 0.625],\n [0.625, 0.375, 0.875],\n [0.375, 0.625, 0.875],\n [0.125, 0.125, 0.125],\n [0.375, 0.875, 0.625],\n [0.125, 0.875, 0.875],\n [0.375, 0.125, 0.375],\n [0.125, 0.625, 0.625],\n [0.375, 0.375, 0.125],\n [0.125, 0.375, 0.375]];\ntypes = [\"B\" for _ in positions]\nxtal_pyro = Crystal(latvecs, positions; types) # We will call this crystal the Theoretical Pyrochlore","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'F d -3 m' (227)\nLattice params a=8.334, b=8.334, c=8.334, α=90°, β=90°, γ=90°\nCell volume 578.9\nType 'B', Wyckoff 16c (point group '.-3m'):\n 1. [7/8, 5/8, 3/8]\n 2. [5/8, 1/8, 5/8]\n 3. [7/8, 7/8, 1/8]\n 4. [5/8, 7/8, 3/8]\n 5. [7/8, 1/8, 7/8]\n 6. [5/8, 5/8, 1/8]\n 7. [7/8, 3/8, 5/8]\n 8. [5/8, 3/8, 7/8]\n 9. [3/8, 5/8, 7/8]\n 10. [1/8, 1/8, 1/8]\n 11. [3/8, 7/8, 5/8]\n 12. [1/8, 7/8, 7/8]\n 13. [3/8, 1/8, 3/8]\n 14. [1/8, 5/8, 5/8]\n 15. [3/8, 3/8, 1/8]\n 16. [1/8, 3/8, 3/8]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To examine the result interactively, we can call view_crystal.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"view_crystal(xtal_pyro, 3.2)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#\"Experimentalist\"-Method-#1-(Incorrect)","page":"MgCr2O4 at Finite Temperature","title":"\"Experimentalist\" Method #1 (Incorrect)","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"A real crystal is more complicated than this, however, and we will now construct the system using the actual CIF file of MgCr2O4 from ICSD. This can be done by copying over the data from a CIF file by hand, but this can be dangerous, as shown below.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"latvecs = lattice_vectors(8.3342, 8.3342, 8.3342, 90, 90, 90)\npositions = [[0.1250, 0.1250, 0.1250],\n [0.5000, 0.5000, 0.5000],\n [0.2607, 0.2607, 0.2607]]\ntypes = [\"Mg\",\"Cr\",\"O\"]\nxtal_mgcro_1 = Crystal(latvecs, positions; types)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'R 3 m' (160)\nLattice params a=8.334, b=8.334, c=8.334, α=90°, β=90°, γ=90°\nCell volume 578.9\nType 'Mg', Wyckoff 3a (point group '3m'):\n 1. [1/8, 1/8, 1/8]\nType 'Cr', Wyckoff 3a (point group '3m'):\n 2. [1/2, 1/2, 1/2]\nType 'O', Wyckoff 3a (point group '3m'):\n 3. [0.2607, 0.2607, 0.2607]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Sunny returned a valid crystal, but it did get right space group for MgCr2O4. This can be fixed by modifying the input to include the space group and the setting.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#\"Experimentalist\"-Method-#2-(Correct)","page":"MgCr2O4 at Finite Temperature","title":"\"Experimentalist\" Method #2 (Correct)","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"As above, we will define the crystal structure of MgCr2O4 by copying the info from a CIF file, but we will also specify the space group and setting explicitly.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"latvecs = lattice_vectors(8.3342, 8.3342, 8.3342, 90, 90, 90)\npositions = [[0.1250, 0.1250, 0.1250],\n [0.5000, 0.5000, 0.5000],\n [0.2607, 0.2607, 0.2607]]\ntypes = [\"Mg\",\"Cr\",\"O\"]\nspacegroup = 227 # Space Group Number\nsetting = \"2\" # Space Group setting\nxtal_mgcro_2 = Crystal(latvecs, positions, spacegroup; types, setting)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'F d -3 m' (227)\nLattice params a=8.334, b=8.334, c=8.334, α=90°, β=90°, γ=90°\nCell volume 578.9\nType 'Mg', Wyckoff 8b (point group '-43m'):\n 1. [1/8, 1/8, 1/8]\n 2. [5/8, 5/8, 1/8]\n 3. [7/8, 3/8, 3/8]\n 4. [3/8, 7/8, 3/8]\n 5. [5/8, 1/8, 5/8]\n 6. [1/8, 5/8, 5/8]\n 7. [3/8, 3/8, 7/8]\n 8. [7/8, 7/8, 7/8]\nType 'Cr', Wyckoff 16c (point group '.-3m'):\n 9. [1/2, 0, 0]\n 10. [3/4, 1/4, 0]\n 11. [0, 1/2, 0]\n 12. [1/4, 3/4, 0]\n 13. [3/4, 0, 1/4]\n 14. [1/2, 1/4, 1/4]\n 15. [1/4, 1/2, 1/4]\n 16. [0, 3/4, 1/4]\n 17. [0, 0, 1/2]\n 18. [1/4, 1/4, 1/2]\n 19. [1/2, 1/2, 1/2]\n 20. [3/4, 3/4, 1/2]\n 21. [1/4, 0, 3/4]\n 22. [0, 1/4, 3/4]\n 23. [3/4, 1/2, 3/4]\n 24. [1/2, 3/4, 3/4]\nType 'O', Wyckoff 32e (point group '.3m'):\n 25. [0.7393, 0.0107, 0.0107]\n 26. [0.5107, 0.2393, 0.0107]\n 27. [0.2393, 0.5107, 0.0107]\n 28. [0.0107, 0.7393, 0.0107]\n 29. [0.5107, 0.0107, 0.2393]\n 30. [0.7393, 0.2393, 0.2393]\n 31. [0.0107, 0.5107, 0.2393]\n 32. [0.2393, 0.7393, 0.2393]\n 33. [0.2607, 0.2607, 0.2607]\n 34. [0.4893, 0.4893, 0.2607]\n 35. [0.7607, 0.7607, 0.2607]\n 36. [0.9893, 0.9893, 0.2607]\n 37. [0.4893, 0.2607, 0.4893]\n 38. [0.2607, 0.4893, 0.4893]\n 39. [0.9893, 0.7607, 0.4893]\n 40. [0.7607, 0.9893, 0.4893]\n 41. [0.2393, 0.0107, 0.5107]\n 42. [0.0107, 0.2393, 0.5107]\n 43. [0.7393, 0.5107, 0.5107]\n 44. [0.5107, 0.7393, 0.5107]\n 45. [0.0107, 0.0107, 0.7393]\n 46. [0.2393, 0.2393, 0.7393]\n 47. [0.5107, 0.5107, 0.7393]\n 48. [0.7393, 0.7393, 0.7393]\n 49. [0.7607, 0.2607, 0.7607]\n 50. [0.9893, 0.4893, 0.7607]\n 51. [0.2607, 0.7607, 0.7607]\n 52. [0.4893, 0.9893, 0.7607]\n 53. [0.9893, 0.2607, 0.9893]\n 54. [0.7607, 0.4893, 0.9893]\n 55. [0.4893, 0.7607, 0.9893]\n 56. [0.2607, 0.9893, 0.9893]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"This result is correct, but at this point we might as well import the CIF file directly, which we now proceed to do.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#\"Experimentalist\"-Method-#3-(Correct-–-if-your-CIF-file-is)","page":"MgCr2O4 at Finite Temperature","title":"\"Experimentalist\" Method #3 (Correct – if your CIF file is)","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To import a CIF file, simply give the path to Crystal. One may optionally specify a precision parameter to apply to the symmetry analysis.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"cif = joinpath(@__DIR__, \"MgCr2O4_160953_2009.cif\")\nxtal_mgcro_3 = Crystal(cif; symprec=0.001)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'F d -3 m' (227)\nLattice params a=8.333, b=8.333, c=8.333, α=90°, β=90°, γ=90°\nCell volume 578.6\nType 'Mg1', Wyckoff 8b (point group '-43m'):\n 1. [1/8, 1/8, 1/8]\n 2. [5/8, 5/8, 1/8]\n 3. [7/8, 3/8, 3/8]\n 4. [3/8, 7/8, 3/8]\n 5. [5/8, 1/8, 5/8]\n 6. [1/8, 5/8, 5/8]\n 7. [3/8, 3/8, 7/8]\n 8. [7/8, 7/8, 7/8]\nType 'Cr1', Wyckoff 16c (point group '.-3m'):\n 9. [1/2, 0, 0]\n 10. [3/4, 1/4, 0]\n 11. [0, 1/2, 0]\n 12. [1/4, 3/4, 0]\n 13. [3/4, 0, 1/4]\n 14. [1/2, 1/4, 1/4]\n 15. [1/4, 1/2, 1/4]\n 16. [0, 3/4, 1/4]\n 17. [0, 0, 1/2]\n 18. [1/4, 1/4, 1/2]\n 19. [1/2, 1/2, 1/2]\n 20. [3/4, 3/4, 1/2]\n 21. [1/4, 0, 3/4]\n 22. [0, 1/4, 3/4]\n 23. [3/4, 1/2, 3/4]\n 24. [1/2, 3/4, 3/4]\nType 'O1', Wyckoff 32e (point group '.3m'):\n 25. [0.7388, 0.0112, 0.0112]\n 26. [0.5112, 0.2388, 0.0112]\n 27. [0.2388, 0.5112, 0.0112]\n 28. [0.0112, 0.7388, 0.0112]\n 29. [0.5112, 0.0112, 0.2388]\n 30. [0.7388, 0.2388, 0.2388]\n 31. [0.0112, 0.5112, 0.2388]\n 32. [0.2388, 0.7388, 0.2388]\n 33. [0.2612, 0.2612, 0.2612]\n 34. [0.4888, 0.4888, 0.2612]\n 35. [0.7612, 0.7612, 0.2612]\n 36. [0.9888, 0.9888, 0.2612]\n 37. [0.4888, 0.2612, 0.4888]\n 38. [0.2612, 0.4888, 0.4888]\n 39. [0.9888, 0.7612, 0.4888]\n 40. [0.7612, 0.9888, 0.4888]\n 41. [0.2388, 0.0112, 0.5112]\n 42. [0.0112, 0.2388, 0.5112]\n 43. [0.7388, 0.5112, 0.5112]\n 44. [0.5112, 0.7388, 0.5112]\n 45. [0.0112, 0.0112, 0.7388]\n 46. [0.2388, 0.2388, 0.7388]\n 47. [0.5112, 0.5112, 0.7388]\n 48. [0.7388, 0.7388, 0.7388]\n 49. [0.7612, 0.2612, 0.7612]\n 50. [0.9888, 0.4888, 0.7612]\n 51. [0.2612, 0.7612, 0.7612]\n 52. [0.4888, 0.9888, 0.7612]\n 53. [0.9888, 0.2612, 0.9888]\n 54. [0.7612, 0.4888, 0.9888]\n 55. [0.4888, 0.7612, 0.9888]\n 56. [0.2612, 0.9888, 0.9888]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Finally, we wish to restrict attention to the magnetic atoms in the unit cell while maintaining symmetry information for the full crystal, which is required to determine the correct exchange and g-factor anisotropies. This can be achieved with the subcrystal function.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"xtal_mgcro = subcrystal(xtal_mgcro_2, \"Cr\")","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'F d -3 m' (227)\nLattice params a=8.334, b=8.334, c=8.334, α=90°, β=90°, γ=90°\nCell volume 578.9\nType 'Cr', Wyckoff 16c (point group '.-3m'):\n 1. [1/2, 0, 0]\n 2. [3/4, 1/4, 0]\n 3. [0, 1/2, 0]\n 4. [1/4, 3/4, 0]\n 5. [3/4, 0, 1/4]\n 6. [1/2, 1/4, 1/4]\n 7. [1/4, 1/2, 1/4]\n 8. [0, 3/4, 1/4]\n 9. [0, 0, 1/2]\n 10. [1/4, 1/4, 1/2]\n 11. [1/2, 1/2, 1/2]\n 12. [3/4, 3/4, 1/2]\n 13. [1/4, 0, 3/4]\n 14. [0, 1/4, 3/4]\n 15. [3/4, 1/2, 3/4]\n 16. [1/2, 3/4, 3/4]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Making-a-System-and-assigning-interactions","page":"MgCr2O4 at Finite Temperature","title":"Making a System and assigning interactions","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Making-a-System","page":"MgCr2O4 at Finite Temperature","title":"Making a System","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Before assigning any interactions, we first have to set up a System using our Crystal.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"dims = (6, 6, 6) # Supercell dimensions\nmomentinfo = [1 => Moment(s=3/2, g=2)] # Specify local moment information, note that all sites are symmetry equivalent\nsys_pyro = System(xtal_pyro, momentinfo, :dipole; dims) # Make a system in dipole (Landau-Lifshitz) mode on pyrochlore lattice\nsys_mgcro = System(xtal_mgcro, momentinfo, :dipole; dims); # Same on MgCr2O4 crystal","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To understand what interactions we may assign to this system, we have to understand the the symmetry properties of the crystal, which we turn to next.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Symmetry-analysis-for-exchange-and-single-ion-anisotropies","page":"MgCr2O4 at Finite Temperature","title":"Symmetry analysis for exchange and single-ion anisotropies","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"print_symmetry_table reports all the exchange interactions, single-site anisotropies, and g-factors allowed on our crystal. It takes a Cyrstal and a distance. We'll look at both the \"theorist's\" pyrochlore lattice,","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"print_symmetry_table(xtal_pyro, 5.9)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Atom 1\nType 'B', position [7/8, 5/8, 3/8], multiplicity 16\nAllowed g-tensor: [ A B -B\n B A B\n -B B A]\nAllowed anisotropy in Stevens operators:\n c₁*(𝒪[2,-2]+2𝒪[2,-1]-2𝒪[2,1]) +\n c₂*(7𝒪[4,-3]+2𝒪[4,-2]-𝒪[4,-1]+𝒪[4,1]+7𝒪[4,3]) + c₃*(𝒪[4,0]+5𝒪[4,4]) +\n c₄*(-11𝒪[6,-6]-8𝒪[6,-3]+𝒪[6,-2]-8𝒪[6,-1]+8𝒪[6,1]-8𝒪[6,3]) + c₅*(𝒪[6,0]-21𝒪[6,4]) + c₆*((9/5)𝒪[6,-6]+(24/5)𝒪[6,-5]+𝒪[6,-2]+(8/5)𝒪[6,-1]-(8/5)𝒪[6,1]-(24/5)𝒪[6,5])\n\nBond(1, 3, [0, 0, 0])\nDistance 2.9465846678825, coordination 6\nConnects 'B' at [7/8, 5/8, 3/8] to 'B' at [7/8, 7/8, 1/8]\nAllowed exchange matrix: [ A -D D\n D B C\n -D C B]\nAllowed DM vector: [0 -D -D]\n\nBond(1, 2, [0, 0, 0])\nDistance 5.1036343535759, coordination 12\nConnects 'B' at [7/8, 5/8, 3/8] to 'B' at [5/8, 1/8, 5/8]\nAllowed exchange matrix: [ A C-E D-F\n C+E B -C+E\n D+F -C-E A]\nAllowed DM vector: [E F -E]\n\nBond(2, 6, [0, 0, 0])\nDistance 5.8931693357649, coordination 6\nConnects 'B' at [5/8, 1/8, 5/8] to 'B' at [5/8, 5/8, 1/8]\nAllowed exchange matrix: [A D D\n D B C\n D C B]\n\nBond(1, 5, [0, 0, 0])\nDistance 5.8931693357649, coordination 6\nConnects 'B' at [7/8, 5/8, 3/8] to 'B' at [7/8, 1/8, 7/8]\nAllowed exchange matrix: [ A D -D\n D B C\n -D C B]\n\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"and for the the MgCrO4 crystal,","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"print_symmetry_table(xtal_mgcro, 6.0)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Atom 1\nType 'Cr', position [1/2, 0, 0], multiplicity 16\nAllowed g-tensor: [A B B\n B A B\n B B A]\nAllowed anisotropy in Stevens operators:\n c₁*(𝒪[2,-2]+2𝒪[2,-1]+2𝒪[2,1]) +\n c₂*(-7𝒪[4,-3]-2𝒪[4,-2]+𝒪[4,-1]+𝒪[4,1]+7𝒪[4,3]) + c₃*(𝒪[4,0]+5𝒪[4,4]) +\n c₄*(-11𝒪[6,-6]-8𝒪[6,-3]+𝒪[6,-2]-8𝒪[6,-1]-8𝒪[6,1]+8𝒪[6,3]) + c₅*(𝒪[6,0]-21𝒪[6,4]) + c₆*((9/5)𝒪[6,-6]+(24/5)𝒪[6,-5]+𝒪[6,-2]+(8/5)𝒪[6,-1]+(8/5)𝒪[6,1]+(24/5)𝒪[6,5])\n\nBond(1, 2, [0, 0, 0])\nDistance 2.9465846678825, coordination 6\nConnects 'Cr' at [1/2, 0, 0] to 'Cr' at [3/4, 1/4, 0]\nAllowed exchange matrix: [A C -D\n C A -D\n D D B]\nAllowed DM vector: [-D D 0]\n\nBond(1, 7, [0, 0, 0])\nDistance 5.1036343535759, coordination 12\nConnects 'Cr' at [1/2, 0, 0] to 'Cr' at [1/4, 1/2, 1/4]\nAllowed exchange matrix: [ A C-E D-F\n C+E B -C+E\n D+F -C-E A]\nAllowed DM vector: [E F -E]\n\nBond(1, 3, [0, 0, 0])\nDistance 5.8931693357649, coordination 6\nConnects 'Cr' at [1/2, 0, 0] to 'Cr' at [0, 1/2, 0]\nAllowed exchange matrix: [A D C\n D A C\n C C B]\n\nBond(1, 3, [1, 0, 0])\nDistance 5.8931693357649, coordination 6\nConnects 'Cr' at [1/2, 0, 0] to 'Cr' at [1, 1/2, 0]\nAllowed exchange matrix: [A D C\n D A C\n C C B]\n\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Note that the exchange anisotropies allowed on the the pyrochlore lattice are slightly different from those on the MgCr2O4 cyrstal due to the role of Mg and O in the bonds. Also note that Sunny has correctly identified the two inequivalent bonds 3a and 3b having the same length. A question may arises to know which bond is J3a and which is J3b, let's plot the structure.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"view_crystal(xtal_mgcro, 5.9)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"The crystal viewer shows that the second interaction – cyan color with distance of 5.89Å – is in fact the one hopping through a chromium site, meaning it is J3a! We will need to be careful with that later.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Building-the-exchange-interactions-for-our-system","page":"MgCr2O4 at Finite Temperature","title":"Building the exchange interactions for our system","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We begin by setting the scale of our exchange interactions on each bond.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"J1 = 3.27 # value of J1 in meV from Bai's PRL paper\nJ_pyro = [1.00,0.000,0.000,0.000]*J1 # pure nearest neighbor pyrochlore\nJ_mgcro = [1.00,0.0815,0.1050,0.085]*J1; # further neighbor pyrochlore relevant for MgCr2O4\n# val_J_mgcro = [1.00,0.000,0.025,0.025]*val_J1; # this is a funny setting from Conlon-Chalker","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"These values are then assigned to their corresponding bonds with set_exchange!.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"# === Assign exchange interactions to pyrochlore system ===\nset_exchange!(sys_pyro, J_pyro[1], Bond(1, 3, [0,0,0])) # J1\nset_exchange!(sys_pyro, J_pyro[2], Bond(1, 2, [0,0,0])) # J2\nset_exchange!(sys_pyro, J_pyro[3], Bond(2, 6, [0,0,0])) # J3a\nset_exchange!(sys_pyro, J_pyro[4], Bond(1, 5, [0,0,0])) # J3b\n\n# === Assign exchange interactions to MgCr2O4 system ===\nset_exchange!(sys_mgcro, J_mgcro[1], Bond(1, 2, [0,0,0])) # J1\nset_exchange!(sys_mgcro, J_mgcro[2], Bond(1, 7, [0,0,0])) # J2\nset_exchange!(sys_mgcro, J_mgcro[3], Bond(1, 3, [0,0,0])) # J3a -- Careful here!\nset_exchange!(sys_mgcro, J_mgcro[4], Bond(1, 3, [1,0,0])); # J3b -- And here!","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We will not be assigning any single-ion anisotropies, so we have finished specifying our models. For good measure, we will set both systems to a random (infinite temperature) initial condition.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"randomize_spins!(sys_pyro)\nrandomize_spins!(sys_mgcro);","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Cooling-our-System-amd-calculating-the-instantaneous-and-dynamic-structure-factors-at-the-final-temperature","page":"MgCr2O4 at Finite Temperature","title":"Cooling our System amd calculating the instantaneous and dynamic structure factors at the final temperature","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We begin by thermalizing our system at a particular temperature. We will accomplish this by running Langevin dynamics. To do this, we must set up a Langevin integrator.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"dt = 0.01 # Integration time step in meV^-1\ndamping = 0.1 # Phenomenological damping parameter\nkT = 1.8 # Desired temperature in meV\nlangevin = Langevin(dt; damping, kT); # Construct integrator","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We can now thermalize our systems by running the integrator.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"for _ in 1:5000\n step!(sys_pyro, langevin)\n step!(sys_mgcro, langevin)\nend","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"As a sanity check, we'll plot the real-space spin configurations of both systems after themalization. First the pyrochlore,","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"plot_spins(sys_pyro)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"and then the MgCr2O4,","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"plot_spins(sys_mgcro)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Instantaneous-Structure-Factor","page":"MgCr2O4 at Finite Temperature","title":"Instantaneous Structure Factor","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Next we can examine the instantaneous structure factor.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"isf_pyro = SampledCorrelationsStatic(sys_pyro; measure=ssf_perp(sys_pyro))\nisf_mgcro = SampledCorrelationsStatic(sys_mgcro; measure=ssf_perp(sys_mgcro));","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"These are currently empty. Let's add spin-spin correlation data from 10 sampled spin configurations at kT = 1.8 meV.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"for _ in 1:10\n # Run dynamics to decorrelate\n for _ in 1:500\n step!(sys_pyro, langevin)\n step!(sys_mgcro, langevin)\n end\n # Add samples\n add_sample!(isf_pyro, sys_pyro)\n add_sample!(isf_mgcro, sys_mgcro)\nend","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To retrieve the intensities, we call intensities_static on an array of wave vectors, which we can generate with q_space_grid.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"qpts_pyro = q_space_grid(xtal_pyro, [1, 0, 0], range(-4.0, 4.0, 200), [0, 1, 0], (-4, 4))\nqpts_mgcro = q_space_grid(xtal_mgcro, [1, 0, 0], range(-4.0, 4.0, 200), [0, 1, 0], (-4, 4))\n\nSq_pyro = intensities_static(isf_pyro, qpts_pyro)\nSq_mgcro = intensities_static(isf_mgcro, qpts_mgcro);","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Finally, plot the results.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"fig = Figure(; size=(1200,500))\nplot_intensities!(fig[1,1], Sq_pyro)\nplot_intensities!(fig[1,2], Sq_mgcro)\nfig","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Dynamical-Structure-Factor","page":"MgCr2O4 at Finite Temperature","title":"Dynamical Structure Factor","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We can also estimate the dynamical structure factor.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"energies = range(0, 10, 100)\nsc_pyro = SampledCorrelations(sys_pyro; dt, energies, measure=ssf_perp(sys_pyro))\nsc_mgcro = SampledCorrelations(sys_mgcro; dt, energies, measure=ssf_perp(sys_mgcro));","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Next we sample trajectories and calculate the spin-spin correlations of these. Unlike SampledCorrelationsStatic, these samples now include time (energy) information – and take significantly longer to calculate.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"for _ in 1:3\n # Run dynamics to decorrelate\n for _ in 1:500\n step!(sys_pyro, langevin)\n step!(sys_mgcro, langevin)\n end\n # Add samples\n add_sample!(sc_pyro, sys_pyro)\n add_sample!(sc_mgcro, sys_mgcro)\nend","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We can now examine the structure factor intensities along a path in momentum space. First examine the pyrochlore model.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"fig = Figure(; size=(1200,900))\nqbs = 0.0:0.5:1.5 # Determine q_b for each slice\nfor (i, qb) in enumerate(qbs)\n qpts_pyro = q_space_path(xtal_pyro, [[-4, qb, 0], [4, qb, 0]], 200)\n Sqw_pyro = intensities(sc_pyro, qpts_pyro; energies=:available, kT)\n plot_intensities!(fig[fldmod1(i, 2)...], Sqw_pyro; title=\"q_b = $qb\")\nend\nfig","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Next generate the results along the same path for MgCr2O4.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"fig = Figure(; size=(1200,900))\nfor (i, qb) in enumerate(qbs)\n qpts_mgcro = q_space_path(xtal_mgcro, [[-4, qb, 0], [4, qb, 0]], 200)\n Sqw_mgcro = intensities(sc_mgcro, qpts_mgcro; energies=:available, kT)\n plot_intensities!(fig[fldmod1(i, 2)...], Sqw_mgcro; title =\"q_b = $qb\")\nend\nfig","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Instantaneous-structure-factor-from-a-dynamical-structure-factor","page":"MgCr2O4 at Finite Temperature","title":"Instantaneous structure factor from a dynamical structure factor","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Finally, we note that the instant structure factor (what we generated with SampledCorrelationsStatic) can be calculated from the dynamical structure factor (generated with a SampledCorrelations). We simply call instant_static rather than intensities on the SampledCorrelations. This will calculate the instantaneous structure factor from from 𝒮(𝐪ω) by integrating out ω . An advantage of doing this (as opposed to using a SampledCorrelationsStatic) is that Sunny is able to apply a temperature- and energy-dependent intensity rescaling before integrating out the dynamical information. The results of this approach are more suitable for comparison with experimental data.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"qpts_pyro = q_space_grid(xtal_pyro, [1, 0, 0], range(-4, 4, 200), [0, 1, 0], (-4, 4))\nqpts_mgcro = q_space_grid(xtal_mgcro, [1, 0, 0], range(-4, 4, 200), [0, 1, 0], (-4, 4))\n\nSq_pyro = intensities_static(sc_pyro, qpts_pyro; kT)\nSq_mgcro = intensities_static(sc_mgcro, qpts_mgcro; kT);","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We can plot the results below. It is useful to compare these to the plot above generated with an SampledCorrelationsStatic.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"fig = Figure(; size=(1200,500))\nax = plot_intensities!(fig[1,1], Sq_pyro; title=\"Pyrochlore\")\nax = plot_intensities!(fig[1,2], Sq_mgcro; title=\"MgCr₂O₄\")\nfig","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"EditURL = \"../../../../examples/spinw_tutorials/SW18_Distorted_kagome.jl\"","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html#SW18-Distorted-kagome","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"","category":"section"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"This is a Sunny port of SpinW Tutorial 18, originally authored by Goran Nilsen and Sandor Toth. This tutorial illustrates spin wave calculations for KCu₃As₂O₇(OD)₃. The Cu ions are arranged in a distorted kagome lattice, and exhibit an incommensurate helical magnetic order, as described in G. J. Nilsen, et al., Phys. Rev. B 89, 140412 (2014). The model follows Toth and Lake, J. Phys.: Condens. Matter 27, 166002 (2015).","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Build the distorted kagome crystal, with spacegroup 12.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(10.2, 5.94, 7.81, 90, 117.7, 90)\npositions = [[0, 0, 0], [1/4, 1/4, 0]]\ntypes = [\"Cu1\", \"Cu2\"]\ncryst = Crystal(latvecs, positions, 12; types, setting=\"b1\")\nview_crystal(cryst)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Define the interactions.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"moments = [1 => Moment(s=1/2, g=2), 3 => Moment(s=1/2, g=2)]\nsys = System(cryst, moments, :dipole, seed=0)\nJ = -2\nJp = -1\nJab = 0.75\nJa = -J/.66 - Jab\nJip = 0.01\nset_exchange!(sys, J, Bond(1, 3, [0, 0, 0]))\nset_exchange!(sys, Jp, Bond(3, 5, [0, 0, 0]))\nset_exchange!(sys, Ja, Bond(3, 4, [0, 0, 0]))\nset_exchange!(sys, Jab, Bond(1, 2, [0, 0, 0]))\nset_exchange!(sys, Jip, Bond(3, 4, [0, 0, 1]))","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Use minimize_spiral_energy! 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 invariant, and the axis vector is arbitrary. In other cases, a good axis will frequently be determined from symmetry considerations.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"axis = [0, 0, 1]\nrandomize_spins!(sys)\nk = minimize_spiral_energy!(sys, axis; k_guess=randn(3))\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"If successful, the optimization process will find one two propagation wavevectors, ±k_ref, with opposite chiralities. In this system, the spiral_energy_per_site is independent of chirality.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"k_ref = [0.785902495, 0.0, 0.107048756]\nk_ref_alt = [1, 0, 1] - k_ref\n@assert isapprox(k, k_ref; atol=1e-6) || isapprox(k, k_ref_alt; atol=1e-6)\n@assert spiral_energy_per_site(sys; k, axis) ≈ -0.78338383838","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Check the energy with a real-space calculation using a large magnetic cell. First, we must determine a lattice size for which k becomes approximately commensurate.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"suggest_magnetic_supercell([k_ref]; tol=1e-3)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Resize the system as suggested, and perform a real-space calculation. Working with a commensurate wavevector increases the energy slightly. The precise value might vary from run-to-run due to trapping in a local energy minimum.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"new_shape = [14 0 1; 0 1 0; 0 0 2]\nsys2 = reshape_supercell(sys, new_shape)\nrandomize_spins!(sys2)\nminimize_energy!(sys2)\nenergy_per_site(sys2)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Return to the original system (with a single chemical cell) and construct SpinWaveTheorySpiral for calculations on the incommensurate spiral phase.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"measure = ssf_perp(sys; apply_g=false)\nswt = SpinWaveTheorySpiral(sys; measure, k, axis)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"qs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Plot the powder-averaged intensities","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"radii = range(0, 2, 100) # (1/Å)\nenergies = range(0, 6, 200)\nkernel = gaussian(fwhm=0.05)\nres = powder_average(cryst, radii, 400) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html#Enforcing-the-quantum-sum-rule-with-moment-renormalization","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"","category":"section"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"AUTHOR: David Dahlbom (dahlbomda@ornl.gov), DATE: August 29, 2024 (Sunny 0.7.0)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"One goal of the Sunny project is to extend classical techniques to incorporate a greater number of quantum effects. The generalization of the Landau-Lifshitz (LL) equations from SU(2) to SU(N) coherent states is the cornerstone of this approach [1], but Sunny includes a number of other \"classical-to-quantum\" corrections. For example, in the zero-temperature limit, there is a well-known correspondence between Linear Spin Wave Theory (LSWT) and the quantization of the normal modes of the linearized LL equations. This allows the dynamical spin structure factor (DSSF) that would be calculated with LSWT, mathcalS_mathrmQ(mathbfq omega), to be recovered from a DSSF that has been calculated classically, mathcalS_mathrmcl(mathbfq omega). This is achieved by applying a classical-to-quantum correspondence factor to mathcalS_mathrmcl(mathbfq omega):","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"mathcalS_mathrmQ(mathbfq omega)=frachbaromegak_mathrmB T left1+ n_mathrmB(omegaT) right mathcalS_mathrmcl(mathbfq omega)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Sunny automatically applies this correction when you call intensity_static on a SampledCorrelations and provide a temperature. This will be demonstrated in the code example below.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"The quantum structure factor satisfies a familiar \"zeroth-moment\" sum rule,","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"intint dmathbfqdomegamathcalS_mathrmQ(mathbfq omega) = N_S S(S+1)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"where N_S is the number of sites. An immediate consequence of the correspondence is that the \"corrected\" classical structure factor satisfies the same sum rule:","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"intint dmathbfqdomega frachbaromegak_mathrmB T left1+ n_mathrmB(omegaT) right mathcalS_mathrmcl(mathbfq omega) = N_S S(S+1)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Note, however, that this correspondence depends on a harmonic oscillator approximation and only applies near T=0. This is reflected in the fact that the correction factor,","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"frachbaromegak_mathrmB T left1+ n_mathrmB(omegaT) right","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"approaches unity for all omega whenever T grows large. In particular, this means that the corrected classical mathcalS_mathrmcl(mathbfq omega) will no longer satisfy the quantum sum rule at elevated temperatures. It will instead approach the \"classical sum rule\":","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"lim_Trightarrowinftyintint dmathbfqdomega frachbaromegak_mathrmB T left1+ n_mathrmB(omegaT) right mathcalS_mathrmcl(mathbfq omega) = N_S S^2\n","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"A simple approach to maintaining a classical-to-quantum correspondence at elevated temperatures is to renormalize the classical magnetic moments so that the quantum sum rule is satisfied. The renormalization factor can be determinied analytically in the infinite temperature limit [2]. For an arbitrary temperature, however, it must be determined empirically [3]. While determining an appropriate rescaling factor can be computationally expensive, Sunny makes it straightforward to evaluate spectral sums and apply moment renormalization, as shown below. One approach to determining the rescaling factors themselves is demonstrated in the sample code here.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html#Evaluating-spectral-sums-in-Sunny","page":"Enforcing the quantum sum rule with moment renormalization","title":"Evaluating spectral sums in Sunny","text":"","category":"section"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"We'll begin by building a spin system representing the effective Spin-1 compound FeI₂. The functions for doing this are imported from kappa_supplementals.jl, available for download here.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"using Sunny, LinearAlgebra\ninclude(joinpath(@__DIR__, \"kappa_supplementals.jl\"))\n\ndims = (8, 8, 4)\nseed = 102\nunits = Units(:meV, :angstrom)\nsys, cryst = FeI2_sys_and_cryst(dims; seed);","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"We will next estimate mathcalS_mathrmcl(mathbfq omega) using classical dynamics. (For more details on setting up such a calculation, see the tutorials in the official Sunny documentation.)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"# Parameters for generating equilbrium samples.\ndt_therm = 0.004 # Step size for Langevin integrator\ndur_therm = 10.0 # Safe thermalization time\ndamping = 0.1 # Phenomenological coupling to thermal bath\nkT = 0.3 * units.K\nlangevin = Langevin(dt_therm; damping, kT) # Langevin integrator\n\n# Parameters for sampling correlations.\ndt = 0.025 # Integrator step size for dissipationless trajectories\nnsamples = 3 # Number of dynamical trajectories to collect for estimating S(𝐪,ω)\nenergies = range(0, 10, 200); # Energies to resolve, in meV, when calculating the dynamics","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Since FeI₂ is a Spin-1 material, we will use the SU(2S+1=3) formalism and require a set of N^2-1=8 observables to calculate the total spectral weight.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Sx, Sy, Sz = spin_matrices(1) # Spin-1 representation of spin operators\nobservables = [\n\n # Dipoles\n Sx,\n Sy,\n Sz,\n\n # Quadrupoles\n -(Sx*Sz + Sz*Sx),\n -(Sy*Sz + Sz*Sy),\n Sx^2 - Sy^2,\n Sx*Sy + Sy*Sx,\n √3 * Sz^2 - I*2/√3,\n];","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"At the moment, Sunny does not expose a high-level interface for working with custom observables such as these. As a workaround, we will write low-level code that accesses the internal Sunny datastructure Sunny.MeasureSpec. The notation Sunny.* indicates that this functionality is not part of the public interface and is subject to change in future Sunny versions.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Building a Sunny.MeasureSpec requires the following:","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"An array containing a set of N observables for each site of the system.\nA vector of tuples (n m), with 1 = n m = N. Each tuple specifies a pair of observables. Together these determine which correlations will be calculated.\nA function for reducing these correlation pairs into a final intensity.\nA list of form factors.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"The Sunny.MeasureSpec below sums over the autocorrelations of each observable and disables form factor corrections.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"observable_field = fill(Hermitian(zeros(ComplexF64, 3, 3)), length(observables), size(sys.coherents)...);\nfor site in Sunny.eachsite(sys), μ in axes(observables, 1)\n observable_field[μ, site] = Hermitian(observables[μ])\nend\ncorr_pairs = [(i, i) for i in 1:length(observables)]\ncombiner(_, data) = real(sum(data))\nmeasure = Sunny.MeasureSpec(observable_field, corr_pairs, combiner, [one(FormFactor)]);","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Finally, we can construct a SampledCorrelations and perform the calculations.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"sc = SampledCorrelations(sys; dt, energies, measure)\n\n# Thermalize and add several samples\nfor _ in 1:5_000\n step!(sys, langevin)\nend\n\nfor _ in 1:nsamples\n # Decorrelate sample\n for _ in 1:2_000\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"sc now contains an estimate of mathcalS_mathrmcl(mathbfq omega). We next wish to evaluate the total spectral weight. We are working on a finite lattice and using discretized dynamics, so the integral will reduce to a sum. Since we'll be evaluating this sum repeatedly, we'll define a function to do this. (Note that this function only works on Bravais lattices – To evaluate spectral sums on a decorated lattice, the sum rule needs to be evaluated on each sublattice individually!)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"function total_spectral_weight(sc::SampledCorrelations; kT = nothing)\n # Retrieve all available discrete wave vectors in the equivalent of\n # one Brillouin zone.\n qs = Sunny.available_wave_vectors(sc)[:]\n\n # Calculate the intensities. Note that we must include negative energies to\n # evaluate the total spectral weight.\n is = intensities(sc, qs; energies=:available_with_negative, kT)\n\n return sum(is.data * sc.Δω)\nend;","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Now evaluate the total spectral weight without temperature corrections.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"total_spectral_weight(sc) / (prod(sys.dims))","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"1.333333333333334","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"The result is 4/3, which is the expected \"classical\" sum rule. This reference can be established by evaluating sum_alphalangle Zvert T^alpha vert Z rangle^2 for any SU(3) coherent state Z, with T^alpha a complete set of generators of SU(3) – for example, the observables above. However, the quantum sum rule is in fact 16/3, as can be determined by directly calculating sum_alpha(T^alpha)^2.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Now let's try again, this time applying the classical-to-quantum correspondence factor by providing the simulation temperature.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"total_spectral_weight(sc; kT) / prod(sys.dims)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"5.450820794092413","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"This is relatively close to 16/3. So, at low temperatures, application of the classical-to-quantum correspondence factor yields results that (approximately) satisfy the quantum sum rule.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"This will no longer hold at higher temperatures. Let's repeat the above experiment with a simulation temperature above T_N=305.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"sys, cryst = FeI2_sys_and_cryst(dims; seed)\nkT = 3.5 * units.K\nlangevin = Langevin(dt_therm; damping, kT)\nsc = SampledCorrelations(sys; dt, energies, measure)\n\n# Thermalize\nfor _ in 1:5_000\n step!(sys, langevin)\nend\n\nfor _ in 1:nsamples\n # Decorrelate sample\n for _ in 1:2_000\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Evaluating the sum without the classical-to-quantum correction factor will again give 4/3, as you can easily verify. Let's examine the result with the correction:","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"total_spectral_weight(sc; kT) / prod(sys.dims)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"2.9374993339227875","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"While this is larger than the classical value of 4/3, it is still substantially short of the quantum value of 16/3.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html#Implementing-moment-renormalization","page":"Enforcing the quantum sum rule with moment renormalization","title":"Implementing moment renormalization","text":"","category":"section"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"One way to enforce the quantum sum rule is by simply renormalizing the magnetic moments. In Sunny, this can be achieved by calling set_spin_rescaling!(sys, κ), where κ is the desired renormalization. Let's repeat the calculation above at the same temperature, this time setting κ=125.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"sys, cryst = FeI2_sys_and_cryst(dims; seed)\nsc = SampledCorrelations(sys; dt, energies, measure)\nκ = 1.25\n\n# Thermalize\nfor _ in 1:5_000\n step!(sys, langevin)\nend\n\nfor _ in 1:nsamples\n # Generate new equilibrium sample.\n for _ in 1:2_000\n step!(sys, langevin)\n end\n\n # Renormalize magnetic moments before collecting a time-evolved sample.\n set_spin_rescaling!(sys, κ)\n\n # Generate a trajectory and calculate correlations.\n add_sample!(sc, sys)\n\n # Turn off κ renormalization before generating a new equilibrium sample.\n set_spin_rescaling!(sys, 1.0)\nend","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Finally, we evaluate the sum.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"total_spectral_weight(sc; kT) / prod(sys.dims)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"5.142433967821603","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"The result is something slightly greater than 5, substantially closer to the expected quantum sum rule. We can now adjust kappa and iterate until we reach a value sufficiently close to 16/3. In general, this should be done while collecting substantially more statistics.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Note that kappa (T) needs to be determined empirically for each model. A detailed example, demonstrating the calculations used in [3], is available here.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html#References","page":"Enforcing the quantum sum rule with moment renormalization","title":"References","text":"","category":"section"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"[1] - H. Zhang, C. D. Batista, \"Classical spin dynamics based on SU(N) coherent states,\" PRB (2021)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"[2] - T. Huberman, D. A. Tennant, R. A. Cowley, R. Coldea and C. D. Frost, \"A study of the quantum classical crossover in the spin dynamics of the 2D S = 5/2 antiferromagnet Rb2MnF4: neutron scattering, computer simulations and analytic theories\" (2008)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"[3] - D. Dahlbom, D. Brooks, M. S. Wilson, S. Chi, A. I. Kolesnikov, M. B. Stone, H. Cao, Y.-W. Li, K. Barros, M. Mourigal, C. D. Batista, X. Bai, \"Quantum to classical crossover in generalized spin systems,\" arXiv:2310.19905 (2023)","category":"page"},{"location":"renormalization.html#Interaction-Renormalization","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"A unique feature of Sunny is its support for building classical models where quantum spin is represented as an N-level system, rather than just an expected dipole. This generalization can be important when modeling quantum spin Hamiltonians that include, e.g., a single-ion anisotropy, or a biquadratic coupling between sites. Sunny also supports constraining quantum spin to the space of pure dipoles; in this case, Sunny will automatically perform an interaction strength renormalization that maximizes accuracy.","category":"page"},{"location":"renormalization.html#Local-operators","page":"Interaction Renormalization","title":"Local operators","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"A quantum spin-s state has N = 2s + 1 levels. Each local spin operator hatS^xyz is faithfully represented as an NN matrix. These matrices can be accessed using spin_matrices for a given label s. For example, the Pauli matrices are associated with s = 12.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"When s 12, it is possible to construct multipole moments beyond the spin-dipole. For example,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"S = spin_matrices(3/2)\n@assert S[3] ≈ diagm([3/2, 1/2, -1/2, -3/2])\n@assert S[3]^2 ≈ diagm([9/4, 1/4, 1/4, 9/4])","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"If the operator -S[3]^2 is passed to set_onsite_coupling!, it would set an easy-axis anisotropy in the hatz direction.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Any Hermitian operator can be expanded in the basis of Stevens operators hatmathcalO_kq up to a constant shift. To see this expansion, use print_stevens_expansion:","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"print_stevens_expansion((S[1]^2 + S[2]^2)) # Prints -(1/3)𝒪₂₀ + 5/2","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Alternatively, the same operator could have been constructed directly from stevens_matrices:","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"O = stevens_matrices(3/2)\n@assert S[1]^2 + S[2]^2 ≈ -O[2, 0]/3 + (5/2)*I","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"See below for an explicit definition of Stevens operators as polynomials of the spin operators.","category":"page"},{"location":"renormalization.html#Renormalization-procedure-for-:dipole-mode","page":"Interaction Renormalization","title":"Renormalization procedure for :dipole mode","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Sunny will typically operate in one of two modes: :SUN or :dipole. The former faithfully represents quantum spin as an SU(N) coherent-state which, for our purposes, is an N-component complex vector. In contrast, :dipole mode constrains the coherent-state to the space of pure dipoles. Here, Sunny will automatically renormalize the magnitude of each Stevens operator to achieve maximal consistency with :SUN mode. This procedure was derived in D. Dahlbom et al., [arXiv:2304.03874].","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"By way of illustration, consider a quantum operator hatmathcalH_mathrmlocal giving a single-ion anisotropy for one site. In Stevens operators,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"hatmathcal H_mathrmlocal = sum_k q A_kq hatmathcalO_kq","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"for some coefficients A_kq.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"In :SUN mode, Sunny will faithfully represent hatmathcal H_mathrmlocal as an NN matrix. In :dipole mode, the expected energy langle hatmathcal H_mathrmlocal rangle must somehow be approximated using the expected dipole data.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"One approach is to formally take s to infty, and this yields the traditional classical limit of a spin system. In this limit spin operators commute and expectation values of polynomials become polynomials of expectation values. For example, langle hatS^alpha hatS^betarangle to langle hatS^alpha rangle langle hatS^betarangle, because any corrections are damped by the factor s^-1 to 0. The expectation of a Stevens operator langle hatmathcalO_kq rangle would then become a classical Stevens function mathcalO_kq(langlehatmathbfSrangle), i.e., a polynomial of the same form, but now applied to the expected dipole. Classical Stevens functions are constructed as homogeneous polynomials of order k, because lower-order terms would vanish in the limit s to infty.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"In a real magnetic compound, however, the spin magnitude s is not necessarily large. To obtain a better approximation, one should avoid the formal limit s to infty. Our approach is to start with the full dynamics of SU(N) coherent states, and then constrain it to the space of pure dipole states boldsymbolOmegarangle. The latter are defined as any states where the expected dipole 3-vector,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"boldsymbolOmega langle boldsymbolOmega hatmathbfS boldsymbolOmegarangle","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"has maximal magnitude boldsymbolOmega = s and arbitrary direction.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"For a pure dipole state, group theory dictates that expectations of the Stevens operators can be expressed as a renormalization of the classical Stevens functions,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"langle boldsymbolOmega hatmathcalO_kq boldsymbolOmegarangle = c_k mathcalO_kq(boldsymbolOmega)","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"At fixed k, the two sides must be proportional because they are both spin-k irreducible representations of SO(3). The renormalization factors can be calculated explicitly:","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"beginalign*\nc_1 = 1 \nc_2 = 1-frac12s^-1 \nc_3 = 1-frac32s^-1+frac12s^-2 \nc_4 = 1-3s^-1+frac114s^-2-frac34s^-3 \nc_5 = 1-5s^-1+frac354s^-2-frac254s^-3+frac32s^-4 \nc_6 = 1-frac152s^-1+frac854s^-2-frac2258s^-3+frac1378s^-4-frac154s^-5 \nvdots\nendalign*","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Constrained to the space of dipoles, the expected local energy becomes","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"E_mathrmlocal(boldsymbolOmega) = langle boldsymbolOmega hatmathcal H_mathrmlocal boldsymbolOmegarangle = sum_k q c_k A_kq mathcalO_kq(boldsymbolOmega)","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"It can be shown that SU(N) dynamics reduces to the usual Landau-Lifshitz dynamics of dipoles, but involving E_mathrmlocal(boldsymbolOmega) as the classical Hamiltonian. The renormalization factors c_k can therefore be interpreted as a correction to the traditional large-s classical limit.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Renormalization also applies to the coupling between different sites. In Sunny, couplings will often be expressed as a polynomial of spin operators using set_pair_coupling!, but any such coupling can be decomposed as sum of tensor products of Stevens operators. Without loss of generality, consider a single coupling between two Stevens operators hatmathcalH_mathrmcoupling = hatmathcalO_kq otimes hatmathcalO_kq along a bond connecting sites i and j. Upon constraining to pure dipole states boldsymbolOmega_irangle and boldsymbolOmega_jrangle, the expected energy takes the form E_mathrmcoupling = c_k c_k mathcalO_kq(boldsymbolOmega_i) mathcalO_kq(boldsymbolOmega_j), which now involves a product of renormalized Stevens functions. ","category":"page"},{"location":"renormalization.html#Use-:dipole_large_s-mode-to-disable-renormalization","page":"Interaction Renormalization","title":"Use :dipole_large_s mode to disable renormalization","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Although we generally recommend the above renormalization procedure, there are circumstances where it is not desirable. Examples include reproducing a model-system study, or describing a micromagnetic system for which the stoinfty limit is a good approximation. To simulate dipoles without interaction strength renormalization, construct a System using the mode :dipole_large_s instead of :dipole. Symbolic operators in the large-s limit can be constructed by passing Inf to either spin_matrices or stevens_matrices.","category":"page"},{"location":"renormalization.html#Definition-of-Stevens-operators","page":"Interaction Renormalization","title":"Definition of Stevens operators","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"The Stevens operators hatmathcalO_kq are defined as polynomials of angular momentum operators hatS_xyz in some spin-s representation.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Using","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"beginalign*\nX = mathbfhatS cdot mathbfhatS = s (s+1) \nhatS_pm = hatS_x pm i hatS_y \nphi_+ = frac14quad phi_- = frac14 i\nendalign*","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"the relevant Stevens operators are defined as,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"beginalign*\nhatmathcalO_00 =1\n\nhatmathcalO_1pm1 =phi_pm(hatS_+pmhatS_-)+mathrmhc\nhatmathcalO_10 =hatS_z\n\nhatmathcalO_2pm2 =phi_pm(hatS_+^2pmhatS_-^2)+mathrmhc\nhatmathcalO_2pm1 =phi_pm(hatS_+pmhatS_-)hatS_z+mathrmhc\nhatmathcalO_20 =3hatS_z^2-X\n\nhatmathcalO_3pm3 =phi_pm(hatS_+^3pmhatS_-^3)+mathrmhc\nhatmathcalO_3pm2 =phi_pm(hatS_+^2pmhatS_-^2)hatS_z+mathrmhc\nhatmathcalO_3pm1 =phi_pm(hatS_+pmhatS_-)(5hatS_z^2-X-12)+mathrmhc\nhatmathcalO_30 =5hatS_z^3-(3X-1)hatS_z\n\nhatmathcalO_4pm4 =phi_pm(hatS_+^4pmhatS_-^4)+mathrmhc\nhatmathcalO_4pm3 =phi_pm(hatS_+^3pmhatS_-^3)hatS_z+mathrmhc\nhatmathcalO_4pm2 =phi_pm(hatS_+^2pmhatS_-^2)(7hatS_z^2-(X+5))+mathrmhc\nhatmathcalO_4pm1 =phi_pm(hatS_+pmhatS_-)(7hatS_z^3-(3X+1)hatS_z)+mathrmhc\nhatmathcalO_40 =35hatS_z^4-(30X-25)hatS_z^2+(3X^2-6X)\n\nhatmathcalO_5pm5 =phi_pm(hatS_+^5pmhatS_-^5)+mathrmhc\nhatmathcalO_5pm4 =phi_pm(hatS_+^4pmhatS_-^4)hatS_z+mathrmhc\nhatmathcalO_5pm3 =phi_pm(hatS_+^3pmhatS_-^3)(9hatS_z^2-(X+332))+mathrmhc\nhatmathcalO_5pm2 =phi_pm(hatS_+^2pmhatS_-^2)(3hatS_z^3-(X+6)hatS_z)+mathrmhc\nhatmathcalO_5pm1 =phi_pm(hatS_+pmhatS_-)(21hatS_z^4-14XhatS_z^2+(X^2-X+32))+mathrmhc\nhatmathcalO_50 =63hatS_z^5-(70X-105)hatS_z^3+(15X^2-50X+12)hatS_z\n\nhatmathcalO_6pm6 =phi_pm(hatS_+^6pmhatS_-^6)+mathrmhc\nhatmathcalO_6pm5 =phi_pm(hatS_+^5pmhatS_-^5)hatS_z+mathrmhc\nhatmathcalO_6pm4 =phi_pm(hatS_+^4pmhatS_-^4)(11hatS_z^2-X-38)+mathrmhc\nhatmathcalO_6pm3 =phi_pm(hatS_+^3pmhatS_-^3)(11hatS_z^3-(3X+59)hatS_z)+mathrmhc\nhatmathcalO_6pm2 =phi_pm(hatS_+^2pmhatS_-^2)(33hatS_z^4-(18X+123)hatS_z^2+X^2+10X+102)+mathrmhc\nhatmathcalO_6pm1 =phi_pm(hatS_+pmhatS_-)(33hatS_z^5-(30X-15)hatS_z^3+(5X^2-10X+12)hatS_z)+mathrmhc\nhatmathcalO_60 =231hatS_z^6-(315X-735)hatS_z^4+(105X^2-525X+294)hatS_z^2-5X^3+40X^2-60X\nendalign*","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Computer-generated tables of Stevens operators with k 6 are available from C. Rudowicz and C. Y. Chung, J. Phys.: Condens. Matter 16, 5825 (2004), but these typically do not appear in magnetic simulations.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"The case k=1 gives the dipole operators,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"(hatmathcalO_11 hatmathcalO_10 hatmathcalO_1-1) = (hatS_x hatS_z hatS_y)","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"The case k=2 gives the quadrupole operators,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"(hatmathcalO_22 dots hatmathcalO_2-2) = left(hatS_x^2 - hatS_y^2 frachatS_x hatS_z + hatS_z hatS_x2 2hatS_z^2-hatS_x^2-hatS_y^2 frachatS_y hatS_z + hatS_z hatS_y2 hatS_x hatS_y + hatS_y hatS_xright)","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"For each k value, the set of operators hatmathcalO_kq for q = -k dots k form an irreducible representation of the group of rotations O(3). That is, rotation will transform hatmathcalO_kq into a linear combination of hatmathcalO_kq where q varies but k remains fixed. ","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"In taking the large-s limit, each dipole operator is replaced by its expectation value boldsymbolOmega = langle hatmathbfS rangle, and only leading-order terms are retained. The operator hatmathcalO_kq becomes a homogeneous polynomial O_kq(boldsymbolOmega) of order k in the spin components Omega^alpha. One can see these polynomials by constructing stevens_matrices with the argument s = Inf. Due to the normalization constraint, each dipole can be expressed in polar angles, (theta phi). Then the Stevens functions O_kq(boldsymbolOmega) correspond to the spherical harmonic functions Y_l^m(theta phi) where l=k and m=q; this correspondence is valid up to k and q-dependent rescaling factors.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"EditURL = \"../../../examples/09_Disorder_KPM.jl\"","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/09_Disorder_KPM.html#9.-Disordered-system-with-KPM","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"","category":"section"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"This example uses the kernel polynomial method (KPM) to efficiently calculate the neutron scattering spectrum of a disordered triangular antiferromagnet. The model is inspired by YbMgGaO4, as studied in Paddison et al, Nature Phys., 13, 117–122 (2017) and Zhu et al, Phys. Rev. Lett. 119, 157201 (2017). Disordered occupancy of non-magnetic Mg/Ga sites can be modeled as a stochastic distribution of exchange constants and g-factors. Including this disorder introduces broadening of the spin wave spectrum.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Set up minimal triangular lattice system. Include antiferromagnetic exchange interactions between nearest neighbor bonds. Energy minimization yields the magnetic ground state with 120° angles between spins in triangular plaquettes.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"latvecs = lattice_vectors(1, 1, 10, 90, 90, 120)\ncryst = Crystal(latvecs, [[0, 0, 0]])\nsys = System(cryst, [1 => Moment(s=1/2, g=1)], :dipole; dims=(3, 3, 1))\nset_exchange!(sys, +1.0, Bond(1, 1, [1,0,0]))\n\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; color=[s[3] for s in sys.dipoles], ndims=2)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Select a 𝐪-space path for the spin wave calculations.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"qs = [[0, 0, 0], [1/3, 1/3, 0], [1/2, 0, 0], [0, 0, 0]]\nlabels = [\"Γ\", \"K\", \"M\", \"Γ\"]\npath = q_space_path(cryst, qs, 150; labels)\nkernel = lorentzian(fwhm=0.4);\nnothing #hide","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Perform a traditional spin wave calculation. The spectrum shows sharp modes associated with coherent excitations about the K-point ordering wavevector, 𝐪 = 13 13 0.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"energies = range(0.0, 3.0, 150)\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Use repeat_periodically to enlarge the system by a factor of 10 in each dimension. Use to_inhomogeneous to disable symmetry constraints, and allow for the addition of disordered interactions.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"sys_inhom = to_inhomogeneous(repeat_periodically(sys, (10, 10, 1)))","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Use symmetry_equivalent_bonds to iterate over all nearest neighbor bonds of the inhomogeneous system. Modify each AFM exchange with a noise term that has variance of 1/3. The newly minimized energy configuration allows for long wavelength modulations on top of the original 120° order.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"for (site1, site2, offset) in symmetry_equivalent_bonds(sys_inhom, Bond(1,1,[1,0,0]))\n noise = randn()/3\n set_exchange_at!(sys_inhom, 1.0 + noise, site1, site2; offset)\nend\n\nminimize_energy!(sys_inhom, maxiters=5_000)\nplot_spins(sys_inhom; color=[s[3] for s in sys_inhom.dipoles], ndims=2)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Traditional spin wave theory calculations become impractical for large system sizes. Significant acceleration is possible with the kernel polynomial method. Enable it by selecting SpinWaveTheoryKPM in place of the traditional SpinWaveTheory. Using KPM, the cost of an intensities calculation becomes linear in system size and scales inversely with the width of the line broadening kernel. Error tolerance is controlled through the dimensionless tol parameter. A relatively small value, tol = 0.01, helps to resolve the large intensities near the ordering wavevector. The alternative choice tol = 0.1 would be twice faster, but would introduce significant numerical artifacts.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Observe from the KPM calculation that disorder in the nearest-neighbor exchange serves to broaden the discrete excitation bands into a continuum.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"swt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.01)\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Now apply a magnetic field of magnitude 7.5 (energy units) along the global z axis. This field fully polarizes the spins. Because gap opens, a larger tolerance of tol = 0.1 can be used to accelerate the KPM calculation without sacrificing much accuracy. The resulting spin wave spectrum shows a sharp mode at the Γ-point (zone center) that broadens into a continuum along the K and M points (zone boundary).","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"set_field!(sys_inhom, [0, 0, 7.5])\nrandomize_spins!(sys_inhom)\nminimize_energy!(sys_inhom)\n\nenergies = range(0.0, 9.0, 150)\nswt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.1)\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Add disorder to the z-component of each magnetic moment g-tensor. This further broadens intensities, now across the entire path. Some intensity modulation within the continuum is also apparent. This modulation is a finite-size effect, and would be mitigated by enlarging the system beyond 30×30 chemical cells.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"for site in eachsite(sys_inhom)\n noise = randn()/6\n sys_inhom.gs[site] = [1 0 0; 0 1 0; 0 0 1+noise]\nend\n\nswt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.1)\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"For reference, the equivalent non-disordered system shows a single coherent mode.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"set_field!(sys, [0, 0, 7.5])\nrandomize_spins!(sys)\nminimize_energy!(sys)\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"EditURL = \"../../../../examples/spinw_tutorials/SW07_k0_kagome_AFM.jl\"","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html#SW07-k0-kagome-antiferromagnet","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"","category":"section"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"This is a Sunny port of SpinW Tutorial 7, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the kagome lattice with antiferromagnetic interactions, with ordering wavevector of 𝐤 = 0, and relative rotation 120° between sublattices","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Define the chemical cell of a kagome lattice with spacegroup 147 (P-3).","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 8, 90, 90, 120)\ncryst = Crystal(latvecs, [[1/2, 0, 0]], 147)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Construct a spin system with nearest and next-nearest neighbor antiferromagnetic interactions. Energy minimization determines a 𝐤 = 0 magnetic order with 120° rotation between the three sublattices. The overall global rotation in spin-space is arbitrary.","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ1 = 1.0\nJ2 = 0.11\nset_exchange!(sys, J1, Bond(2, 3, [0, 0, 0]))\nset_exchange!(sys, J2, Bond(2, 1, [0, 0, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Calculate and plot the powder averaged spectrum","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 2.5, 200)\nkernel = gaussian(fwhm=0.02)\nres = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"EditURL = \"../../../../examples/spinw_tutorials/SW05_Simple_kagome_FM.jl\"","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html#SW05-Simple-kagome-ferromagnet","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"","category":"section"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"This is a Sunny port of SpinW Tutorial 5, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the kagome lattice with a nearest-neighbor ferromagnetic coupling.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Define the chemical cell. By specifying spacegroup 147 (P-3), Sunny will propagate the position [1/2, 0, 0] to the three symmetry-equivalent sites of the kagome unit cell.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 5, 90, 90, 120)\npositions = [[1/2, 0, 0]]\ncryst = Crystal(latvecs, positions, 147)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Another way to construct the kagome lattice is to provide all three site positions of the chemical cell, and allow Sunny to infer the largest possible group of symmetry operations. In this case, Sunny infers spacegroup 191 (P6/mmm). Because 191 has more symmetry operations than 147, it will impose more constraints on the allowed 3×3 exchange matrices. Isotropic Heisenberg exchange, however, is always allowed.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"positions = [[1/2, 0, 0], [0, 1/2, 0], [1/2, 1/2, 0]]\ncryst2 = Crystal(latvecs, positions)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"View the kagome lattice","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"view_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Construct a spin system with nearest-neighbor ferromagnetic interactions.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ = -1.0\nset_exchange!(sys, J, Bond(2, 3, [0, 0, 0]))","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Energy minimization yields the expected ferromagnetic order. Each site participates in 4 bonds, which contributes energy 4J/2.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nenergy_per_site(sys)\n@assert energy_per_site(sys) ≈ 4J/2\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[-1/2, 0, 0], [0, 0, 0], [1/2, 1/2, 0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Calculate and plot the powder average with two different magnitudes of Gaussian line-broadening. Pick an explicit intensity colorrange (as a density in meV) so that the two color scales are consistent.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 6.5, 200)\nres1 = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel=gaussian(fwhm=0.02))\nend\nres2 = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel=gaussian(fwhm=0.25))\nend\n\nfig = Figure(size=(768, 800))\nplot_intensities!(fig[1, 1], res1; units, colorrange=(0,10), title=\"FWHM 0.02 meV\")\nplot_intensities!(fig[2, 1], res2; units, colorrange=(0,10), title=\"FWHM 0.25 meV\")\nfig","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"EditURL = \"../../../../examples/spinw_tutorials/SW09_k0_kagome_AFM_DM.jl\"","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html#SW09-k0-kagome-AFM-and-DM","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"","category":"section"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"This is a Sunny port of SpinW Tutorial 9, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the kagome lattice with antiferromagnetic and DM interactions, with ordering wavevector of 𝐤 = 0, and relative rotation 120° between sublattices","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"using Sunny, GLMakie, LinearAlgebra","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Define the chemical cell of a kagome lattice with spacegroup 147 (P-3).","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 8, 90, 90, 120)\ncryst = Crystal(latvecs, [[1/2, 0, 0]], 147)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Construct a spin system with antiferromagnetic exchange and a Dzyaloshinskii-Moriya interaction along the first neighbor bond. The symbol I comes from Julia's LinearAlgebra package, and is used to promote the scalar exchange strength 1 meV to a 3×3 exchange matrix. The function dmvec promotes the DM interaction vector 0 0 -008 meV to a 3×3 antisymmetric matrix with nonzero (xy) components, defined with respect to the global Cartesian coordinate system.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ = 1.0*I + dmvec([0, 0, -0.08])","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"As in in Tutorial 7, energy minimization determines a 𝐤 = 0 magnetic order with 120° rotation between the three sublattices.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"set_exchange!(sys, J, Bond(2, 3, [0, 0, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Calculate and plot the powder averaged spectrum. Because the intensities are dominated by a flat band at about 0.97 meV, select an empirical colorrange that brings the lower-intensity features into focus.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 2.5, 200)\nkernel = gaussian(fwhm=0.02)\nres = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units, colorrange=(0,20))","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"EditURL = \"../../../../examples/spinw_tutorials/SW15_Ba3NbFe3Si2O14.jl\"","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html#SW15-BaNbFeSiO","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"","category":"section"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"This is a Sunny port of SpinW Tutorial 15, originally authored by Sandor Toth. It calculates the linear spin wave theory spectrum of Ba₃NbFe₃Si₂O₁₄.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Load packages","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Specify the Ba₃NbFe₃Si₂O₁₄ Crystal cell following Marty et al., Phys. Rev. Lett. 101, 247201 (2008).","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"units = Units(:meV, :angstrom)\na = b = 8.539 # (Å)\nc = 5.2414\nlatvecs = lattice_vectors(a, b, c, 90, 90, 120)\ntypes = [\"Fe\", \"Nb\", \"Ba\", \"Si\", \"O\", \"O\", \"O\"]\npositions = [[0.24964,0,0.5], [0,0,0], [0.56598,0,0], [2/3,1/3,0.5220],\n [2/3,1/3,0.2162], [0.5259,0.7024,0.3536], [0.7840,0.9002,0.7760]]\nlangasite = Crystal(latvecs, positions, 150; types)\ncryst = subcrystal(langasite, \"Fe\")\nview_crystal(cryst)","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Create a System and set exchange interactions as parametrized in Loire et al., Phys. Rev. Lett. 106, 207201 (2011).","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"sys = System(cryst, [1 => Moment(s=5/2, g=2)], :dipole; seed=0)\nJ₁ = 0.85\nJ₂ = 0.24\nJ₃ = 0.053\nJ₄ = 0.017\nJ₅ = 0.24\nset_exchange!(sys, J₁, Bond(3, 2, [1,1,0]))\nset_exchange!(sys, J₄, Bond(1, 1, [0,0,1]))\nset_exchange!(sys, J₂, Bond(1, 3, [0,0,0]))","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"The final two exchanges are setting according to the desired chirality ϵ_T of the magnetic structure.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"ϵT = -1\nif ϵT == -1\n set_exchange!(sys, J₃, Bond(2, 3, [-1,-1,1]))\n set_exchange!(sys, J₅, Bond(3, 2, [1,1,1]))\nelseif ϵT == 1\n set_exchange!(sys, J₅, Bond(2, 3, [-1,-1,1]))\n set_exchange!(sys, J₃, Bond(3, 2, [1,1,1]))\nelse\n error(\"Chirality must be ±1\")\nend","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"This compound is known to have a spiral order with approximate propagation wavevector 𝐤 0 0 17. Search for this magnetic order with minimize_spiral_energy!. Due to reflection symmetry, one of two possible propagation wavevectors may appear, 𝐤 = 0 0 01426. Note that k_z = 01426 is very close to 17 = 01428.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"axis = [0, 0, 1]\nrandomize_spins!(sys)\nk = minimize_spiral_energy!(sys, axis)","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"We can visualize the full magnetic cell using repeat_periodically_as_spiral, which includes 7 rotated copies of the chemical cell.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"sys_enlarged = repeat_periodically_as_spiral(sys, (1, 1, 7); k, axis)\nplot_spins(sys_enlarged; color=[S[1] for S in sys_enlarged.dipoles])","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"One could perform a spin wave calculation using either SpinWaveTheory on sys_enlarged, or SpinWaveTheorySpiral on the original sys. The latter has some restrictions on the interactions, but allows for our slightly incommensurate wavevector 𝐤.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"measure = ssf_perp(sys)\nswt = SpinWaveTheorySpiral(sys; measure, k, axis)","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Calculate broadened intensities for a path 0 1 L through reciprocal space","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"qs = [[0, 1, -1], [0, 1, -1+1], [0, 1, -1+2], [0, 1, -1+3]]\npath = q_space_path(cryst, qs, 400)\nenergies = range(0, 6, 400)\nres = intensities(swt, path; energies, kernel=gaussian(fwhm=0.25))\nplot_intensities(res; units, saturation=0.7, colormap=:jet, title=\"Scattering intensities\")","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Use ssf_custom_bm to calculate the imaginary part of mathcalS^2 3(𝐪 ω) - mathcalS^3 2(𝐪 ω). In polarized neutron scattering, it is conventional to express the 3×3 structure factor matrix mathcalS^α β(𝐪 ω) in the Blume-Maleev polarization axis system. Specify the scattering plane 0 K L via the spanning vectors 𝐮 = 0 1 0 and 𝐯 = 0 0 1.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"measure = ssf_custom_bm(sys; u=[0, 1, 0], v=[0, 0, 1]) do q, ssf\n imag(ssf[2,3] - ssf[3,2])\nend\nswt = SpinWaveTheorySpiral(sys; measure, k, axis)\nres = intensities(swt, path; energies, kernel=gaussian(fwhm=0.25))\nplot_intensities(res; units, saturation=0.8, allpositive=false,\n title=\"Im[S²³(q, ω) - S³²(q, ω)]\")","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"EditURL = \"../../../../examples/spinw_tutorials/SW06_Complex_kagome_FM.jl\"","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html#SW06-Complex-kagome-ferromagnet","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"","category":"section"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"This is a Sunny port of SpinW Tutorial 6, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the kagome lattice with multiple competing interactions.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Define the chemical cell of a kagome lattice with spacegroup 147 (P-3).","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 8, 90, 90, 120)\ncryst = Crystal(latvecs, [[1/2, 0, 0]], 147)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Construct a spin system with strongly ferromagnetic nearest-neighbor interactions, and two additional interactions. There are two symmetry-inequivalent exchange types at distance 6 Å (3rd nearest neighbor). The first type, associated with J3a, is a bond from atom 2 to atom 2 that passes over atom 3. The second type, associated with J3b, is a bond from atom 1 to atom 1 that passes through the center of an \"empty\" hexagon of the kagome lattice.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ1 = -1.0\nJ2 = 0.1\nJ3a = 0.00\nJ3b = 0.17\nset_exchange!(sys, J1, Bond(2, 3, [0, 0, 0]))\nset_exchange!(sys, J2, Bond(2, 1, [0, 0, 0]))\nset_exchange!(sys, J3a, Bond(2, 2, [1, 0, 0]))\nset_exchange!(sys, J3b, Bond(1, 1, [1, 0, 0]))","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Interactively visualize the specified interactions. Red (blue) color indicates FM (AFM).","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"view_crystal(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Energy minimization favors ferromagnetic order.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Calculate and plot the powder averaged spectrum. Select an empirical colorrange that brings the lower-intensity features into focus.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 6.5, 200)\nkernel = gaussian(fwhm=0.02)\nres = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units, colorrange=(0,10))","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"EditURL = \"../../../examples/02_LLD_CoRh2O4.jl\"","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#2.-Landau-Lifshitz-dynamics-of-CoRhO-at-finite-*T*","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"In the previous tutorial, we used spin wave theory to calculate the dynamical spin structure factor of CoRh₂O₄. Here, we perform a similar calculation using equilibrium samples from the Boltzmann distribution at finite T. For each sampled spin configuration, we will simulate the classical Landau-Lifshitz spin dynamics and extract dynamical spin-spin correlations. After applying a classical-to-quantum correction factor, the resulting intensities can be compared to inelastic neutron scattering data.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Construct the system as in the previous tutorial. For this antiferromagnetic model on the diamond cubic lattice, the ground state is unfrustrated Néel order.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"using Sunny, GLMakie\n\nunits = Units(:meV, :angstrom)\na = 8.5031 # (Å)\nlatvecs = lattice_vectors(a, a, a, 90, 90, 90)\ncryst = Crystal(latvecs, [[0,0,0]], 227, setting=\"1\")\n\nsys = System(cryst, [1 => Moment(s=3/2, g=2)], :dipole)\nJ = 0.63 # (meV)\nset_exchange!(sys, J, Bond(1, 3, [0,0,0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Use repeat_periodically to extend the system to 10×10×10 chemical unit cells. The ground state Néel order is retained. Increasing the system size further would reduce finite-size artifacts and increase momentum-space resolution, but would also make the simulations slower.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"sys = repeat_periodically(sys, (10, 10, 10))\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#Langevin-dynamics-for-sampling","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"Langevin dynamics for sampling","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"We will be using a Langevin spin dynamics to thermalize the system. This dynamics is a variant of the Landau-Lifshitz equation that incorporates noise and dissipation terms, which are linked by a fluctuation-dissipation theorem. The temperature 6 K ≈ 1.38 meV is slightly above ordering for this model. The dimensionless damping magnitude sets a timescale for coupling to the implicit thermal bath; 0.2 is usually a good choice.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"langevin = Langevin(; damping=0.2, kT=16*units.K)","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Use suggest_timestep to select an integration timestep. A dimensionless error tolerance of 1e-2 is usually a good choice. The suggested timestep will vary according to the magnetic configuration. It is reasonable to start from an energy-minimized configuration.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"suggest_timestep(sys, langevin; tol=1e-2)\nlangevin.dt = 0.025;\nnothing #hide","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Now run a Langevin trajectory to sample spin configurations. Keep track of the energy per site at each time step.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"energies = [energy_per_site(sys)]\nfor _ in 1:1000\n step!(sys, langevin)\n push!(energies, energy_per_site(sys))\nend","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"From the relaxed spin configuration, we can learn that dt was a little smaller than necessary; increasing it will make the remaining simulations faster.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"suggest_timestep(sys, langevin; tol=1e-2)\nlangevin.dt = 0.042;\nnothing #hide","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Plot energy versus time using the Makie lines function. The plateau suggests that the system has reached thermal equilibrium.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"lines(energies, color=:blue, figure=(size=(600,300),), axis=(xlabel=\"Timesteps\", ylabel=\"Energy (meV)\"))","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Plot the spins colored by their alignment with a reference spin at the origin. The field sys.dipoles is a 4D array storing the spin dipole data. The first three indices of label the chemical cell, while the fourth index labels an atom within the cell. Note that Julia arrays use 1-based indexing. Thermal fluctuations are apparent in the plot.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"S0 = sys.dipoles[1,1,1,1]\nplot_spins(sys; color=[S'*S0 for S in sys.dipoles])","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#Static-structure-factor","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"Static structure factor","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Use SampledCorrelationsStatic to estimate spatial correlations for configurations in classical thermal equilibrium. Each call to add_sample! will accumulate data for the current spin snapshot.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"formfactors = [1 => FormFactor(\"Co2\")]\nmeasure = ssf_perp(sys; formfactors)\nsc = SampledCorrelationsStatic(sys; measure)\nadd_sample!(sc, sys) # Accumulate the newly sampled structure factor into `sf`","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Collect 20 additional samples. Perform 100 Langevin time-steps between measurements to approximately decorrelate the sample in thermal equilibrium.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"for _ in 1:20\n for _ in 1:100\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Use q_space_grid to define a slice of momentum space H K 0, where H and K each range from -10 to 10 in RLU. This command produces a 200×200 grid of sample points.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"grid = q_space_grid(cryst, [1, 0, 0], range(-10, 10, 200), [0, 1, 0], (-10, 10))","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Calculate and plot the instantaneous structure factor on the slice by integrating over all energy values ω. We employ the appropriate FormFactor for Co2⁺. Selecting saturation = 1.0 sets the color saturation point to the maximum intensity value. This is reasonable because we are above the ordering temperature, and do not have sharp Bragg peaks.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"res = intensities_static(sc, grid)\nplot_intensities(res; saturation=1.0, title=\"Static Intensities at T = 16 K\")","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#Dynamical-structure-factor","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"Dynamical structure factor","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"To collect statistics for the dynamical structure factor intensities mathcalS(𝐪ω) at finite temperature, use SampledCorrelations. It requires a range of energies to resolve, which will be associated with frequencies of the classical spin dynamics. The integration timestep dt can be somewhat larger than that used by the Langevin dynamics.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"dt = 2*langevin.dt\nenergies = range(0, 6, 50)\nsc = SampledCorrelations(sys; dt, energies, measure=ssf_perp(sys))","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Like before, use Langevin dynamics to sample spin configurations from thermal equilibrium. Now, however, each call to add_sample! will run a classical spin dynamics trajectory and measure dynamical correlations. To make the tutorial run quickly, we average over just 5 trajectories. To make a publication quality figure, this number should be significantly increased for better statistics.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"for _ in 1:5\n for _ in 1:100\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Select points that define a piecewise-linear path through reciprocal space, and a sampling density.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"qs = [[3/4, 3/4, 0],\n [ 0, 0, 0],\n [ 0, 1/2, 1/2],\n [1/2, 1, 0],\n [ 0, 1, 0],\n [1/4, 1, 1/4],\n [ 0, 1, 0],\n [ 0, -4, 0]]\npath = q_space_path(cryst, qs, 500)","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Calculate and plot the intensities along this path.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"res = intensities(sc, path; energies, langevin.kT)\nplot_intensities(res; units, title=\"Intensities at 16 K\")","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#Powder-averaged-intensity","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"Powder averaged intensity","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Define spherical shells in reciprocal space via their radii, in absolute units of 1/Å. For each shell, calculate and average the intensities at 350 𝐪-points","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"radii = range(0, 3.5, 200) # (1/Å)\nres = powder_average(cryst, radii, 350) do qs\n intensities(sc, qs; energies, langevin.kT)\nend\nplot_intensities(res; units, title=\"Powder Average at 16 K\")","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"EditURL = \"../../../../examples/spinw_tutorials/SW19_Different_Ions.jl\"","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html#SW19-Different-magnetic-ions","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"","category":"section"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"This is a Sunny port of SpinW Tutorial 19, originally authored by Bjorn Fak and Sandor Toth. This tutorial illustrates how to eliminate magnetic contributions from a subset of ions via the special value zero(FormFactor).","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Build a crystal with Cu²⁺ and Fe²⁺ ions.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"units = Units(:meV, :angstrom)\na = 3.0\nb = 8.0\nc = 4.0\nlatvecs = lattice_vectors(a, b, c, 90, 90, 90)\npositions = [[0, 0, 0], [0, 1/2, 0]]\ntypes = [\"Cu2\", \"Fe2\"]\ncryst = Crystal(latvecs, positions, 1; types)\nview_crystal(cryst)","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Set exchange interactions.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"J_Cu_Cu = 1.0\nJ_Fe_Fe = 1.0\nJ_Cu_Fe = -0.1\nmoments = [1 => Moment(s=1/2, g=2), 2 => Moment(s=2, g=2)]\nsys = System(cryst, moments, :dipole; dims=(2, 1, 1), seed=0)\nset_exchange!(sys, J_Cu_Cu, Bond(1, 1, [-1, 0, 0]))\nset_exchange!(sys, J_Fe_Fe, Bond(2, 2, [-1, 0, 0]))\nset_exchange!(sys, J_Cu_Fe, Bond(2, 1, [0, 1, 0]))\nset_exchange!(sys, J_Cu_Fe, Bond(1, 2, [0, 0, 0]))","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Find and plot a minimum energy configuration.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys)","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Define a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"qs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 400)","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Plot different pair correlation intensities by varying the FormFactor on different atom types. Indices 1 and 2 refer to atoms in the original chemical, and are propagated by symmetry. The special \"zero\" form factor effectively removes the spin moment from the calculation.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"fig = Figure(size=(768,600))\n\nformfactors = [1 => FormFactor(\"Cu2\"), 2 => FormFactor(\"Fe2\")]\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys; formfactors))\nres = intensities_bands(swt, path)\nplot_intensities!(fig[1, 1], res; units, title=\"All correlations\")\n\nformfactors = [1 => FormFactor(\"Cu2\"), 2 => zero(FormFactor)]\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys; formfactors))\nres = intensities_bands(swt, path)\nplot_intensities!(fig[1, 2], res; units, title=\"Cu-Cu correlations\")\n\nformfactors = [1 => zero(FormFactor), 2 => FormFactor(\"Fe2\")]\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys; formfactors))\nres = intensities_bands(swt, path)\nplot_intensities!(fig[2, 2], res; units, title=\"Fe-Fe correlations\")\n\nfig","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Calculate quantum corrections δS to spin magnitude, which arise from the zero-point energy of the spin waves. The outputs are ordered following the Site indexing scheme for the system sys: (cell1, cell2, cell3, sublattice), with left-most indices fastest. The two corrections δS -0137 and δS -0578 apply to the Cu and Fe ions, respectively. The larger correction on Fe is due to the relatively weak interchain coupling.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Sunny.magnetization_lswt_correction_dipole(swt; atol=1e-4)","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"EditURL = \"../../../examples/07_Dipole_Dipole.jl\"","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/07_Dipole_Dipole.html#7.-Long-range-dipole-interactions","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"","category":"section"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"This example shows how long-range dipole-dipole interactions can affect a spin wave calculation. These interactions can be included two ways: Ewald summation or in real-space with a distance cutoff. The study follows Del Maestro and Gingras, J. Phys.: Cond. Matter, 16, 3339 (2004).","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a pyrochlore crystal from spacegroup 227.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"units = Units(:K, :angstrom)\nlatvecs = lattice_vectors(10.19, 10.19, 10.19, 90, 90, 90)\npositions = [[1/8, 1/8, 1/8]]\ncryst = Crystal(latvecs, positions, 227, setting=\"1\")\nview_crystal(cryst)","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a system and reshape to the primitive cell, which contains four atoms. Add antiferromagnetic nearest neighbor exchange interactions.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"primitive_cell = [1/2 1/2 0; 0 1/2 1/2; 1/2 0 1/2]\nsys = System(cryst, [1 => Moment(s=7/2, g=2)], :dipole; seed=0)\nsys = reshape_supercell(sys, primitive_cell)\nJ1 = 0.304 # (K)\nset_exchange!(sys, J1, Bond(1, 2, [0,0,0]))","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a copy of the system and enable long-range dipole-dipole interactions using Ewald summation.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"sys_lr = clone_system(sys)\nenable_dipole_dipole!(sys_lr, units.vacuum_permeability)","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a copy of the system and add long-range dipole-dipole interactions up to a 5 Å cutoff distance.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"sys_lr_cut = clone_system(sys)\nmodify_exchange_with_truncated_dipole_dipole!(sys_lr_cut, 5.0, units.vacuum_permeability)","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Find an energy minimizing spin configuration accounting for the long-range dipole-dipole interactions. This will arbitrarily select from a discrete set of possible ground states based on the system seed.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"randomize_spins!(sys_lr)\nminimize_energy!(sys_lr)\nplot_spins(sys_lr; ghost_radius=8, color=[:red, :blue, :yellow, :purple])","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Copy this configuration to the other two systems. Note that the original sys has a continuum of degenerate ground states.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"sys.dipoles .= sys_lr.dipoles\nsys_lr_cut.dipoles .= sys_lr.dipoles;\nnothing #hide","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Calculate dispersions for the three systems. The high-symmetry 𝐪-points are specified in reciprocal lattice units with respect to the conventional cubic cell.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"qs = [[0,0,0], [0,1,0], [1,1/2,0], [1/2,1/2,1/2], [3/4,3/4,0], [0,0,0]]\nlabels = [\"Γ\", \"X\", \"W\", \"L\", \"K\", \"Γ\"]\npath = q_space_path(cryst, qs, 500; labels)\n\nmeasure = ssf_trace(sys)\nswt = SpinWaveTheory(sys; measure)\nres1 = intensities_bands(swt, path)\n\nswt = SpinWaveTheory(sys_lr; measure)\nres2 = intensities_bands(swt, path)\n\nswt = SpinWaveTheory(sys_lr_cut; measure)\nres3 = intensities_bands(swt, path);\nnothing #hide","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a panel corresponding to Fig. 2 of Del Maestro and Gingras. Dashed lines show the effect of truncating dipole-dipole interactions at 5 Å. The Del Maestro and Gingras paper underreported the energy scale by a factor of two, and requires slight corrections to its third dispersion band.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"fig = Figure(size=(768, 300))\nplot_intensities!(fig[1, 1], res1; units, title=\"Without long-range dipole\")\nax = plot_intensities!(fig[1, 2], res2; units, title=\"With long-range dipole\")\nfor c in eachrow(res3.disp)\n lines!(ax, eachindex(c), c; linestyle=:dash, color=:black)\nend\nfig","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"EditURL = \"../../../../examples/spinw_tutorials/SW03_Frustrated_chain.jl\"","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html#SW03-Frustrated-J1-J2-chain","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"","category":"section"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"This is a Sunny port of SpinW Tutorial 3, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the frustrated J1-J2 chain.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Define the chemical cell for a 1D chain following the SW01 tutorial.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(3, 8, 8, 90, 90, 90)\ncryst = Crystal(latvecs, [[0, 0, 0]])\nview_crystal(cryst; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Construct a spin system with competing nearest-neighbor (FM) and next-nearest-neighbor (AFM) interactions.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ1 = -1\nJ2 = +2 * abs(J1)\nset_exchange!(sys, J1, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, J2, Bond(1, 1, [2, 0, 0]))","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Assuming a spiral order, optimize the propagation wavevector 𝐤 starting from a random initial guess. Because all interactions are isotropic in spin space, the polarization axis is arbitrary.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"axis = [0, 0, 1]\nrandomize_spins!(sys)\nk = minimize_spiral_energy!(sys, axis; k_guess=randn(3))","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"The first component of the order wavevector 𝐤 has a unique value up to reflection symmetry, 𝐤 -𝐤. The second and third components of 𝐤 are arbitrary for this 1D chain system. In all cases, the minimized energy has a precise value of -33/16 in units of J₁.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"@assert k[1] ≈ 0.2300534561 || k[1] ≈ 1 - 0.2300534561\n@assert spiral_energy_per_site(sys; k, axis) ≈ -33/16 * abs(J1)","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"To view part of the incommensurate spiral spin structure, one can construct an enlarged system with repeat_periodically_as_spiral.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"sys_enlarged = repeat_periodically_as_spiral(sys, (8, 1, 1); k, axis)\nplot_spins(sys_enlarged; ndims=2)","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Use SpinWaveTheorySpiral on the original sys to calculate the dispersion and intensities for the incommensurate ordering wavevector.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"swt = SpinWaveTheorySpiral(sys; measure=ssf_perp(sys), k, axis)\nqs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 401)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"EditURL = \"../../../../examples/spinw_tutorials/SW01_FM_Heseinberg_chain.jl\"","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html#SW01-FM-Heisenberg-chain","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"","category":"section"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"This is a Sunny port of SpinW Tutorial 1, originally authored by Goran Nilsen and Sandor Toth. It calculates the spin wave spectrum of the ferromagnetic Heisenberg nearest-neighbor spin chain.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Define a chemical cell for the spin chain lattice. It is tetrahedral, with a short dimension of 3 Å and two long dimensions of 8 Å. Observe that Sunny infers the spacegroup 'P 4/m m m' (123).","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"units = Units(:meV, :angstrom)\na = 3.0\nb = 8.0\nc = 8.0\nlatvecs = lattice_vectors(a, b, c, 90, 90, 90)\npositions = [[0, 0, 0]]\ncryst = Crystal(latvecs, positions)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"View the crystal in 2D. The nearest neighbor bond along the chain is visible, and labeled Bond(1, 1, [1, 0, 0]). The first two atom indices must be 1, because there is only a single atom in the chemical cell. The vector [1, 0, 0] indicates that the bond includes a displacement of 1 𝐚_1 + 0 𝐚_2 + 0 𝐚_3 between chemical cells.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"view_crystal(cryst; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Sunny will always perform symmetry analysis based on the provided crystallographic information. For example, one can see that there are three different symmetry-equivalent classes of bonds up to a distance of 8 Å, and the symmetry-allowed exchange matrices are strongly constrained.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"print_symmetry_table(cryst, 8)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Use the chemical cell to create a spin System with spin s = 1 and a magnetic form factor for Cu¹⁺. In this case, it is only necessary to simulate a single chemical cell. The option :dipole indicates that, following traditional spin wave theory, we are modeling quantum spins using only their expected dipole moments.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Set a nearest neighbor exchange interaction of J = -1 meV between neighboring atoms. That is, the total energy along each bond is J S_i S_i+1. The exchange interaction will be propagated to all symmetry equivalent bonds in the system.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"J = -1\nset_exchange!(sys, J, Bond(1, 1, [1, 0, 0]))","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Find the energy minimum, which is ferromagnetic. The energy per site is -J for this unfrustrated FM order.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nenergy_per_site(sys)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Because the interaction is Heisenberg (isotropic), the minimization procedure selects an arbitrary direction in spin-space.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"plot_spins(sys; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Build a SpinWaveTheory object to measure the dynamical spin-spin structure factor (SSF). Select ssf_perp to project intensities onto the space perpendicular to the momentum transfer 𝐪, which is appropriate for an unpolarized neutron beam.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Define a path from 000 to 100 in reciprocal lattice units (RLU) containing 400 sampled 𝐪-points.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"qs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 400)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Calculate and plot the intensities along this path.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"res = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Perform a powder average over the intensities for 200 radii between 0 and 2.5 inverse Å. Each radial distance defines a spherical shell in recripocal space, which will be sampled approximately uniformly, involving 1000 sample points. Measure intensities for 200 energy values between 0 and 5 meV. Gaussian line-broadening is applied with a full-width at half-maximum (FWHM) of 0.1 meV. With the above parameters, this calculation takes about a second on a modern laptop. To decrease stochastic error, one can increase the number of sample points on each spherical shell.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"radii = range(0, 2.5, 200) # 1/Å\nenergies = range(0, 5, 200) # meV\nkernel = gaussian(fwhm=0.1)\nres = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units)","category":"page"},{"location":"versions.html#Version-History","page":"Version History","title":"Version History","text":"","category":"section"},{"location":"versions.html#v0.7.3","page":"Version History","title":"v0.7.3","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(In development)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fix error in print_symmetry_table for slightly-distorted crystal cells (PR #317).\nStabilize SpinWaveTheoryKPM. It now automatically selects the polynomial order according to an error tolerance.","category":"page"},{"location":"versions.html#v0.7.2","page":"Version History","title":"v0.7.2","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 11, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fix error in SampledCorrelations with a coarse 𝐪-grid. (PR #314).\nFix colorbar in plot_intensities! when all data is uniform (PR #315).\nAn explicit colorrange can be used for plotting intensities_bands.","category":"page"},{"location":"versions.html#v0.7.1","page":"Version History","title":"v0.7.1","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 3, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Correctness fix for scalar biquadratic interactions specified with option biquad to set_exchange!.\nPrototype implementation of entangled units.","category":"page"},{"location":"versions.html#v0.7.0","page":"Version History","title":"v0.7.0","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 30, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"This major release introduces breaking interface changes.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The interface for calculating intensities has been revised to unify functionality across backends. The functions intensities_bands, intensities, and intensities_static no longer expect a \"formula\", and instead take keyword arguments directly. Pair correlations are now specified using ssf_perp and related functions. The constructors SampledCorrelations and SampledCorrelationsStatic replace dynamic_correlations and static_correlations, respectively.\nNew function plot_intensities enables convenient plotting for many types of intensities plots. Mutating variant plot_intensities! enables multi-panel plots.\nOne should now specify a range of 𝐪-points with q_space_path or q_space_grid.\nSpinWaveTheorySpiral is available to perform calculations on generalized spiral structures, which may be incommensurate.\nrepeat_periodically_as_spiral replaces set_spiral_order_on_sublattice! and set_spiral_order!.\nNew convenience functions powder_average and domain_average, which wrap intensities.\nSystem now expects supercell dimensions as a dims keyword argument. Moment replaces SpinInfo. Lower-case s now labels quantum spin. For example, use :dipole_large_s instead of :dipole_large_S.\nIn view_crystal and plot_spins use ndims instead of dims for the number of spatial dimensions.\nBinning features have been removed. Some functionality may be added back in a future release.\nExperimental SpinWaveTheoryKPM feature implements a new algorithm to enable intensities calculations at a computational cost that scales linearly in system size.","category":"page"},{"location":"versions.html#v0.6.1","page":"Version History","title":"v0.6.1","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 2, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Breaking changes: magnetic_moment is now reported in units of the Bohr magneton, μ_B. For model systems where the Zeeman coupling aligns spin dipole with field (e.g., the Ising model convention), create a SpinInfo with g=-1. (PR 284).\nMore flexible Units system. set_external_field! is deprecated in favor of set_field!, which now expects a field in energy units. enable_dipole_dipole! now expects a scale parameter μ_0 μ_B^2 that can be obtained from units.vacuum_permeability.","category":"page"},{"location":"versions.html#v0.6.0","page":"Version History","title":"v0.6.0","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Jun 18, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Various correctness fixes. The magnetic moment is now anti-aligned with the spin dipole (Issue 190), and the wavevector 𝐪 in structure factor intensities mathcalS(𝐪ω) now consistently represents momentum transfer to the sample (Issue 270). The new Example 8 demonstrates a model system where momentum transfers 𝐪 are inequivalent.\nDynamical structure factor intensities now have a precisely defined scale, independent of the calculator (Issue 264). Consequently, color ranges in plots may need to be rescaled.\nCrystal can now infer a chemical unit cell from an mCIF file. System now supports set_dipoles_from_mcif!. Through spglib, one can now standardize any Crystal, with an option to idealize site positions.","category":"page"},{"location":"versions.html#v0.5.11","page":"Version History","title":"v0.5.11","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Jun 2, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fixes for Makie 0.21.","category":"page"},{"location":"versions.html#v0.5.10","page":"Version History","title":"v0.5.10","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(May 27, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"view_crystal called on a System now shows interactions, and optionally the spin or magnetic dipoles.\nInteractions for enable_dipole_dipole! are now supported in linear spin wave theory, with proper Ewald summation. For a faster alternative, the experimental function modify_exchange_with_truncated_dipole_dipole! will accept a real-space cutoff.\nIntensities calculated with dynamic_correlations now avoid \"bleeding artifacts\" at low-energy (long-timescale) modes. See PR 246 for details. This eliminates the need for process_trajectory=:symmetrize.\nWhen passed to intensity_formula, the special value zero(FormFactor) can now be used to disable contributions from a given site. For an example, see the ported SpinW tutorial 19.\nBroadening kernels gaussian and lorentzian now expect a full width at half maximum (fwhm) keyword argument.\nExperimental support for calculations on generalized spiral phases. For an example, see the ported SpinW tutorial 18.\nCorrectness fix for the case where spin-S varies between sites in dipole-mode. In SU(N) mode, however, there is still no support for varying the Hilbert space dimension N between sites.\nCorrectness fix in long-range dipole-dipole interactions for systems with multiple cells.\nCorrectness fix in general biquadratic interactions (beyond scalar) for spin wave theory in dipole-mode.\nCorrectness fix for reading Mantid .nxs files.","category":"page"},{"location":"versions.html#v0.5.9","page":"Version History","title":"v0.5.9","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Mar 25, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Correctness fixes: Structure factor conventions are now uniform across modes and precisely specified. The g-tensor is applied by default (disable with apply_g = false). The intensity is additive with increasing number of magnetic ions in the chemical cell, consistent with SpinW. Issue #235.\nEnhancements to view_crystal. If a bond allows a DM interaction, its orientation will be shown visually. If a System argument is supplied, its exchange interactions will be shown..\nNew function suggest_timestep to assist in performing accurate and efficient simulation of classical spin dynamics. Issue #149.\nScalar biquadratic interactions can again be set in :dipole_large_S mode via the keyword argument biquad of set_exchange!.\nSignificantly speed up dynamic_correlations for crystals with many atoms in the unit cell. Issue #204.\nRenamings: dt replaces Δt and damping replaces λ. This affects Langevin, [ImplicitMidpoint], and dynamic_correlations functions.","category":"page"},{"location":"versions.html#v0.5.8","page":"Version History","title":"v0.5.8","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Jan 4, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Many bugs in the WGLMakie backend have become apparent, and are being tracked at Issue #211. Emit a warning if WGLMakie is detected, suggesting that GLMakie is preferred.\nVarious improvements to view_crystal. A distance parameter is no longer expected. Cartesian axes now appear as \"compass\" in bottom-left. Custom list of reference bonds can be passed. Toggle to view non-magnetic atoms in root crystal. Atoms now colored using CPK/JMol conventions.","category":"page"},{"location":"versions.html#v0.5.7","page":"Version History","title":"v0.5.7","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Nov 26, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Update form factor coefficients, which now include Mn5.\nFix merge_correlations and the Parallelizing Calculations tutorial.\nRemove internal functions *_primitive_crystal. Instead, it is recommended to use the conventional unit cell, and later call reshape_supercell.\nRequire Makie 0.20. An important new feature is resolution-independent scaling of font sizes. New figures expect size instead of resolution, and no longer accept rescale.","category":"page"},{"location":"versions.html#v0.5.6","page":"Version History","title":"v0.5.6","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Nov 8, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"This release initiates some major enhancements to the user interface in support of generalized SU(N) spin models. See this documentation page for an illustration of the new features. Most existing Sunny 0.5 models will continue to work with deprecation warnings, but these will become hard errors Sunny v0.6.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"General pair couplings are now supported in set_pair_coupling! and set_pair_coupling_at!. :SUN mode supports interactions of any order, but :dipole mode is limited to bilinear and biquadratic coupling of the spin.\nTo perform a calculation with dipoles in the large-S limit, use the new mode :dipole_large_S when constructing a System.\nDeprecate the option biquad to set_exchange!. Use instead set_pair_coupling!, which generalizes beyond the scalar biquadratic.\nDeprecate spin_operators, stevens_operators, large_S_spin_operators and large_S_stevens_operators. Use instead spin_matrices and stevens_matrices, which require a specific spin-S label. To infer this, one can use spin_label.\nRemove unused option energy_tol in SpinWaveTheory.\nAnimated spin dynamics is now possible. Call notify on the result of plot_spins to trigger redrawing of the frame. The argument colorfn to plot_spins supports animation of colors. See example usage for a Heisenberg ferromagnetic.\nAdd set_spin_rescaling! feature, which supports improved spectral measurements at finite-T. This follows the method proposed in Dahlbom et al., [arXiv:2310.19905].","category":"page"},{"location":"versions.html#v0.5.5","page":"Version History","title":"v0.5.5","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 29, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"reshape_supercell now allows reshaping to multiples of the primitive unit cell, which can speed up certain calculations. This is illustrated in the CoRh₂O₄ powder averaging tutorial.\nresize_supercell now allows all resizings.\nAdded energy_per_site.\nset_spiral_order_on_sublattice! cannot work on reshaped systems.\nVarious bug fixes. In particular, an intensity_formula with :full will now uniformly calculate a 3x3 matrix of complex numbers.","category":"page"},{"location":"versions.html#v0.5.4","page":"Version History","title":"v0.5.4","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 11, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Various enhancements to view_crystal. Atoms are now labeled by index, and bonds support interactive inspection (GLMakie only). Font sizes work correctly on Makie v0.20-beta. If using Makie v0.19 on a high-resolution display, pass rescale=1.5 to enlarge font sizes.\nThe function suggest_magnetic_supercell now requires only a list of wavevectors, and will return a 33 matrix that can be programmatically passed to reshape_supercell. The new tolerance parameter tol allows suggest_magnetic_supercell to approximate incommensurate wavevectors with nearby commensurate ones.\nNew functions set_spiral_order! and set_spiral_order_on_sublattice! can be used to initialize a spiral, single-Q order.\nSunny now retains all constant energy shifts that have been introduced by anisotropy operators.\nFix export_vtk functionality.","category":"page"},{"location":"versions.html#v0.5.3","page":"Version History","title":"v0.5.3","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 8, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Add large_S_spin_operators and large_S_stevens_operators to support single-ion anisotropies in dipole mode without renormalization. Set large_S=true in set_exchange! to avoid renormalization of biquadratics.\nview_crystal has been rewritten in Makie.\nplot_spins now expects ghost_radius in physical length units.\nSpinWaveTheory will (currently) error if provided a system with enable_dipole_dipole!.","category":"page"},{"location":"versions.html#v0.5.2","page":"Version History","title":"v0.5.2","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 30, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Form factors for 5d transition ions.\nDownload links for notebooks and scripts on each doc example\nVarious bug fixes.","category":"page"},{"location":"versions.html#v0.5.1","page":"Version History","title":"v0.5.1","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 23, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fix binning edge cases.\nplot_spins accepts resolution argument.","category":"page"},{"location":"versions.html#v0.5.0","page":"Version History","title":"v0.5.0","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 21, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"New features.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Support for Linear Spin Wave Theory in :dipole and :SUN modes. (Thanks Hao Zhang!)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"New function minimize_energy! to efficiently find an optimal configuration of spin dipoles or SU(N) coherent states.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Major refactors and enhancements to intensity calculations. This new interface allows unification between LSWT and classical spin dynamics calculations. This interface allows: Custom observables as local quantum operators, better support for linebroadening, and automatic binning to facilitate comparison with experimental data. See intensity_formula for documentation. Use load_nxs to load experimental neutron scattering data.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Breaking changes.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Require Julia 1.9.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Replace set_anisotropy! with a new function set_onsite_coupling! (and similarly set_onsite_coupling_at!). The latter expects an explicit matrix representation for the local Hamiltonian. This can be constructed, e.g., as a linear combination of stevens_operators, or as a polynomial of spin_operators. To understand the mapping between these two, the new function print_stevens_expansion acts on an arbitrary local operator.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Remove set_biquadratic!. Instead, use an optional keyword argument biquad to set_exchange!.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename DynamicStructureFactor to dynamic_correlations. Similarly, replace InstantStructureFactor with instant_correlations. The return type has been renamed SampledCorrelations to emphasize that the object may be holding thermodynamic samples, which are collected using add_sample!. Upon construction, the SampledCorrelations object will be empty (no initial sample).","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Remove intensities function. Instead, use one of intensities_interpolated or intensities_binned. These will require an intensity_formula, which defines a calculator (e.g., LSWT).","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename connected_path to reciprocal_space_path, which now returns an xticks object that can be used in plotting. Replace spherical_shell with reciprocal_space_shell that functions similarly.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename polarize_spin! to set_dipole! for consistency with set_coherent!. The behavior of the former function is unchanged: the spin at a given site will still be polarized along the provided direction.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename all_sites to eachsite consistent with Julia convention for iterators.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename reshape_geometry to reshape_supercell, which is the fundamental reshaping function. Rename resize_periodically to resize_supercell.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The constructor SpinInfo now requires a g-factor or tensor as a named argument.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The constructor FormFactor no longer accepts an atom index. Instead, the form factors are associated with site-symmetry classes in order of appearance.","category":"page"},{"location":"versions.html#v0.4.3","page":"Version History","title":"v0.4.3","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Jun 23, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Experimental support for linear SpinWaveTheory, implemented in SU(N) mode. This module may evolve rapidly.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Implement renormalization of single-ion anisotropy and biquadratic interactions when in :dipole mode. This makes the model more faithful to the quantum mechanical Hamiltonian, but is also a breaking change.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Various improvements and bugfixes for to_inhomogeneous. Setting inhomogeneous interactions via set_exchange_at! should now infer the correct bond offset direction, or will report an ambiguity error. Ambiguities can be resolved by passing an explicit offset.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The function remove_periodicity! disables periodicity along specified dimensions.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename StaticStructureFactor to InstantStructureFactor.","category":"page"},{"location":"versions.html#v0.4.2","page":"Version History","title":"v0.4.2","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Feb 27, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Introduce LocalSampler, a framework for MCMC sampling with local spin updates.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename print_dominant_wavevectors to print_wrapped_intensities to reduce confusion with the physical instantaneous intensities.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The function spherical_shell now takes a radius in physical units of inverse Å.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"New exported functions global_position, magnetic_moment, all_sites.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Remove all uses of Base.deepcopy which resolves crashes.","category":"page"},{"location":"versions.html#v0.4.1","page":"Version History","title":"v0.4.1","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Feb 13, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The function to_inhomogeneous creates a system that supports inhomogeneous interactions, which can be set using set_exchange_at!, etc.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"set_biquadratic! replaces set_exchange_with_biquadratic!.","category":"page"},{"location":"versions.html#v0.4.0","page":"Version History","title":"v0.4.0","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Feb 10, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"This update includes many breaking changes, and is missing some features of 0.3.0.","category":"page"},{"location":"versions.html#Creating-a-spin-System","page":"Version History","title":"Creating a spin System","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename SpinSystem to System. Its constructor now has the form,","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"System(crystal, dims, infos, mode)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The parameter infos is now a list of SpinInfo objects. Each defines spin angular momentum S = frac12 1 frac32 , and an optional g-factor or tensor.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The parameter mode is one of :SUN or :dipole.","category":"page"},{"location":"versions.html#Setting-interactions","page":"Version History","title":"Setting interactions","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Interactions are now added mutably to an existing System using the following functions: set_external_field!, set_exchange!, set_onsite_coupling!, enable_dipole_dipole!.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"As a convenience, one can use dmvec(D) to convert a DM vector to a 33 antisymmetric exchange matrix.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fully general single-ion anisotropy is now possible. The function set_onsite_coupling! expects the single ion anisotropy to be expressed as a polynomial in symbolic spin operators 𝒮, or as a linear combination of symbolic Stevens operators 𝒪. For example, an easy axis anisotropy in the direction n may be written D*(𝒮⋅n)^2.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"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.","category":"page"},{"location":"versions.html#Inhomogeneous-field","page":"Version History","title":"Inhomogeneous field","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"An external field can be applied to a single site with set_external_field_at!. ","category":"page"},{"location":"versions.html#Structure-factor-rewrite","page":"Version History","title":"Structure factor rewrite","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The calculation of structure factors has been completely rewritten. For the new interface see the documentation tutorials.","category":"page"},{"location":"versions.html#Various","page":"Version History","title":"Various","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The \"Sampler\" interface is in flux. Langevin replaces both LangevinHeunP and LangevinSampler. Local spin-flip Monte Carlo sampling methods are temporarily broken.\nrepeat_periodically replaces extend_periodically.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Additional related functions include resize_periodically and reshape_geometry, the latter being fundamental.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"print_symmetry_table replaces print_bond_table().","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The new function includes the list of symmetry-allowed single ion anisotropies in addition to exchange interactions.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"When reading CIF files, the field _atom_site_label is now used in place of the field _atom_site_type_symbol.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"This is required for correctness. The field _atom_site_label is guaranteed to be present, and is guaranteed to be a distinct label for each symmetry-inequivalent site. Code that explicitly referred to site labels (e.g. in calls to subcrystal) will need to be updated to use the new label.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"EditURL = \"../../../../examples/spinw_tutorials/SW14_YVO3.jl\"","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html#SW14-YVO","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"","category":"section"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"This is a Sunny port of SpinW Tutorial 14, originally authored by Sandor Toth. It calculates the spin wave spectrum of YVO₃.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Load packages","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Build an orthorhombic lattice and populate the V atoms according to the pseudocubic unit cell, doubled along the c-axis. The listed spacegroup of the YVO₃ chemical cell is international number 62. It has been observed, however, that the exchange interactions break this symmetry. For this reason, disable all symmetry analysis by selecting spacegroup 1 (P1).","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"units = Units(:meV, :angstrom)\na = 5.2821 / sqrt(2)\nb = 5.6144 / sqrt(2)\nc = 7.5283\nlatvecs = lattice_vectors(a, b, c, 90, 90, 90)\npositions = [[0, 0, 0], [0, 0, 1/2]]\ntypes = [\"V\", \"V\"]\ncryst = Crystal(latvecs, positions, 1; types)","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Create a system following the model of C. Ulrich, et al. PRL 91, 257202 (2003). The mode :dipole_large_s avoids a classical-to-quantum rescaling factor of anisotropy strengths, as needed for consistency with the original fits.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"sys = System(cryst, [1 => Moment(s=1/2, g=2), 2 => Moment(s=1/2, g=2)], :dipole_large_s; dims=(2,2,1))\nJab = 2.6\nJc = 3.1\nδ = 0.35\nK1 = 0.90\nK2 = 0.97\nd = 1.15\nJc1 = [-Jc*(1+δ)+K2 0 -d; 0 -Jc*(1+δ) 0; +d 0 -Jc*(1+δ)]\nJc2 = [-Jc*(1-δ)+K2 0 +d; 0 -Jc*(1-δ) 0; -d 0 -Jc*(1-δ)]\nset_exchange!(sys, Jab, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, Jab, Bond(2, 2, [1, 0, 0]))\nset_exchange!(sys, Jc1, Bond(1, 2, [0, 0, 0]))\nset_exchange!(sys, Jc2, Bond(2, 1, [0, 0, 1]))\nset_exchange!(sys, Jab, Bond(1, 1, [0, 1, 0]))\nset_exchange!(sys, Jab, Bond(2, 2, [0, 1, 0]))\nset_onsite_coupling!(sys, S -> -K1*S[1]^2, 1)\nset_onsite_coupling!(sys, S -> -K1*S[1]^2, 2)","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"When using spacegroup P1, there is no symmetry-propagation of interactions because all bonds are considered inequivalent. One can visualize the interactions in the system by clicking the toggles in the view_crystal GUI.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"view_crystal(sys)","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Energy minimization yields a Néel order with canting","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys)","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Plot the spin wave spectrum along a path","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[0.75, 0.75, 0], [0.5, 0.5, 0], [0.5, 0.5, 1]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"index.html#Overview","page":"Overview","title":"Overview","text":"","category":"section"},{"location":"index.html","page":"Overview","title":"Overview","text":"Sunny is a Julia package for modeling atomic-scale magnetism. It provides powerful tools to study equilibrium and non-equilibrium magnetic phenomena. In particular, it allows estimation of dynamical structure factor intensities, mathcalS(𝐪ω), to support quantitative modeling of experimental scattering data.","category":"page"},{"location":"index.html","page":"Overview","title":"Overview","text":"Features include:","category":"page"},{"location":"index.html","page":"Overview","title":"Overview","text":"Generalized spin dynamics using SU(N) coherent states.\nAbility to specify a crystal from a .cif file or its spacegroup symmetry. Magnetic structures can be read from .mcif files.\nInteractive visualizations of the 3D crystals and magnetic ordering.\nSymmetry analysis to classify allowed interaction terms, and to propagate them by symmetry.\nSingle-ion anisotropy at arbitrary order, which can be specified using Stevens operators or as a polynomial of spin operators.\nMonte Carlo sampling of spin configurations in thermal equilibrium, and optimization tools.\nMeasurements of dynamical correlations. At low temperature, one can use linear spin wave theory and its multi-boson generalization. This generalizes to finite temperatures using the classical dynamics, which allows for strongly nonlinear effects.\nLong-range dipole-dipole interactions accelerated with the fast Fourier transform (FFT).\nSupport for comparison with experimental data: form factor, dipole factor, temperature-dependent classical-to-quantum factors, etc.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"EditURL = \"../../../../examples/spinw_tutorials/SW12_Triangular_easy_plane.jl\"","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html#SW12-Triangular-lattice-with-easy-plane","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"","category":"section"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"This is a Sunny port of SpinW Tutorial 12, originally authored by Sandor Toth. It calculates the spin wave dispersion of a triangular lattice model with antiferromagnetic interactions and easy-plane single-ion anisotropy.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Load packages","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Build a triangular lattice with arbitrary lattice constant of 3 Å.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"latvecs = lattice_vectors(3, 3, 4, 90, 90, 120)\ncryst = Crystal(latvecs, [[0, 0, 0]])","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Build a system with exchange +1 meV along nearest neighbor bonds. Set the lattice size in anticipation of a magnetic ordering with 3×3 cells.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"s = 3/2\nJ1 = +1.0\nsys = System(cryst, [1 => Moment(; s, g=2)], :dipole; dims=(3, 3, 1))\nset_exchange!(sys, J1, Bond(1, 1, [1, 0, 0]))","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Set an easy-axis anisotropy operator +D S_z^2 using set_onsite_coupling!. Important note: When introducing a single-ion anisotropy in :dipole mode, Sunny will automatically include a classical-to-quantum correction factor, as described in the document Interaction Renormalization. For an anisotropy operator that is quadratic in the spin operators, Sunny will automatically renormalize the interaction strength as D (1 - 12s) D. We must \"undo\" Sunny's classical-to-quantum rescaling factor to reproduce the SpinW calculation. Alternatively, renormalization can be disabled by selecting the system mode :dipole_large_s instead of :dipole.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"undo_classical_to_quantum_rescaling = 1 / (1 - 1/2s)\nD = 0.2 * undo_classical_to_quantum_rescaling\nset_onsite_coupling!(sys, S -> D*S[3]^2, 1)\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Plot the spin wave spectrum for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"qs = [[0, 0, 0], [1, 1, 0]]\npath = q_space_path(cryst, qs, 400)\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities_bands(swt, path)\nplot_intensities(res)","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"To select a specific linear combination of spin structure factor (SSF) components in global Cartesian coordinates, one can use ssf_custom. Here we calculate and plot the real part of mathcalS^zz(𝐪 ω).","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"measure = ssf_custom(sys) do q, ssf\n return real(ssf[3, 3])\nend\nswt = SpinWaveTheory(sys; measure)\nres = intensities_bands(swt, path)\nplot_intensities(res)","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"It's also possible to get data for the full 3×3 SSF. For example, this is the SSF for the 7th energy band, at the 10th 𝐪-point along the path.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"measure = ssf_custom((q, ssf) -> ssf, sys)\nswt = SpinWaveTheory(sys; measure)\nres = intensities_bands(swt, path)\nres.data[7, 10]","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"EditURL = \"../../../../examples/spinw_tutorials/SW04_Frustrated_square.jl\"","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html#SW04-Frustrated-square-lattice","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"","category":"section"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"This is a Sunny port of SpinW Tutorial 4, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the frustrated square lattice.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"To model the 2D square lattice, create an elongated tetragonal cell with one atom.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(3.0, 3.0, 6.0, 90, 90, 90)\ncryst = Crystal(latvecs, [[0, 0, 0]])\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"Construct a spin system with competing nearest-neighbor (AFM) and next-nearest-neighbor (FM) interactions. The Néel magnetic order requires a supercell of 2×2 chemical cells.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(2, 2, 1))\nJ1 = 1.0\nJ2 = -0.1\nset_exchange!(sys, J1, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, J2, Bond(1, 1, [1, 1, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys)","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[0, 0, 0], [1/2, 0, 0], [1/2, 1/2, 0], [0, 0, 0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"}] +[{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"EditURL = \"../../../../examples/spinw_tutorials/SW13_LiNiPO4.jl\"","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html#SW13-LiNiPO","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"","category":"section"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"This is a Sunny port of SpinW Tutorial 13, originally authored by Sandor Toth. It calculates the spin wave spectrum of LiNiPO₄.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Load packages","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Build an orthorhombic lattice and populate the Ni atoms according to spacegroup 62 (Pnma).","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"units = Units(:meV, :angstrom)\na = 10.02\nb = 5.86\nc = 4.68\nlatvecs = lattice_vectors(a, b, c, 90, 90, 90)\npositions = [[1/4, 1/4, 0]]\ntypes = [\"Ni\"]\ncryst = Crystal(latvecs, positions, 62, setting=\"\"; types)\nview_crystal(cryst)","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Create a system with exchange parameters taken from T. Jensen, et al., PRB 79, 092413 (2009). The corrected anisotropy values are taken from the thesis of T. Jensen. The mode :dipole_large_s avoids a classical-to-quantum rescaling factor of anisotropy strengths, as needed for consistency with the original fits.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"S = 3/2\nsys = System(cryst, [1 => Moment(s=1, g=2)], :dipole_large_s)\nJbc = 1.036\nJb = 0.6701\nJc = -0.0469\nJac = -0.1121\nJab = 0.2977\nDa = 0.1969\nDb = 0.9097\nset_exchange!(sys, Jbc, Bond(2, 3, [0, 0, 0]))\nset_exchange!(sys, Jc, Bond(1, 1, [0, 0, -1]))\nset_exchange!(sys, Jb, Bond(1, 1, [0, 1, 0]))\nset_exchange!(sys, Jab, Bond(1, 2, [0, 0, 0]))\nset_exchange!(sys, Jab, Bond(3, 4, [0, 0, 0]))\nset_exchange!(sys, Jac, Bond(3, 1, [0, 0, 0]))\nset_exchange!(sys, Jac, Bond(4, 2, [0, 0, 0]))\nset_onsite_coupling!(sys, S -> Da*S[1]^2 + Db*S[2]^2, 1)","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Energy minimization yields a co-linear order along the c axis.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Calculate the spectrum along path [ξ, 1, 0]","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[0, 1, 0], [2, 1, 0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nfig = Figure(size=(768, 300))\nplot_intensities!(fig[1, 1], res; units);\nnothing #hide","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"There are two physical bands with nonvanishing intensity. To extract these intensity curves, we must filter out the additional bands with zero intensity. One way is to sort the data along dimension 1 (the band index) with the comparison operator \"is intensity less than 10^-12\". Doing so moves the physical bands to the end of the array axis. Call the Makie lines! function to make a custom plot.","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"data_sorted = sort(res.data; dims=1, by= >(1e-12))\nax = Axis(fig[1, 2], xlabel=\"Momentum (r.l.u.)\", ylabel=\"Intensity\",\n xticks=res.qpts.xticks, xticklabelrotation=π/6)\nlines!(ax, data_sorted[end, :]; label=\"Lower band\")\nlines!(ax, data_sorted[end-1, :]; label=\"Upper band\")\naxislegend(ax)\nfig","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"Make the same plots along path [0, 1, ξ]","category":"page"},{"location":"examples/spinw/SW13_LiNiPO4.html","page":"SW13 - LiNiPO₄","title":"SW13 - LiNiPO₄","text":"qs = [[0, 1, 0], [0, 1, 2]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nfig = Figure(size=(768, 300))\nplot_intensities!(fig[1, 1], res; units)\n\ndata_sorted = sort(res.data; dims=1, by=x->abs(x)>1e-12)\nax = Axis(fig[1, 2], xlabel=\"Momentum (r.l.u.)\", ylabel=\"Intensity\",\n xticks=res.qpts.xticks, xticklabelrotation=π/6)\nlines!(ax, data_sorted[end, :]; label=\"Lower band\")\nlines!(ax, data_sorted[end-1, :]; label=\"Upper band\")\naxislegend(ax)\nfig","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"EditURL = \"../../../examples/03_LSWT_SU3_FeI2.jl\"","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#3.-Multi-flavor-spin-wave-simulations-of-FeI","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"This tutorial illustrates various advanced features such as symmetry analysis, energy minimization, and spin wave theory with multi-flavor bosons.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Our context will be FeI₂, an effective spin-1 material with strong single-ion anisotropy. Quadrupolar fluctuations give rise to a single-ion bound state that is observable in neutron scattering, and cannot be described by a dipole-only model. We will use the linear spin wave theory of SU(3) coherent states (i.e. 2-flavor bosons) to model the magnetic spectrum of FeI₂. The original study was performed in Bai et al., Nature Physics 17, 467–472 (2021).","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The Fe atoms are arranged in stacked triangular layers. The effective spin Hamiltonian takes the form,","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"mathcalH=sum_(ij) 𝐒_i J_ij 𝐒_j - Dsum_i left(S_i^zright)^2","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"where the exchange matrices J_ij between bonded sites (ij) include competing ferromagnetic and antiferromagnetic interactions. This model also includes a strong easy axis anisotropy, D 0.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Load packages.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Construct the chemical cell of FeI₂ by specifying the lattice vectors and the full set of atoms.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"units = Units(:meV, :angstrom)\na = b = 4.05012 # Lattice constants for triangular lattice (Å)\nc = 6.75214 # Spacing between layers (Å)\nlatvecs = lattice_vectors(a, b, c, 90, 90, 120)\npositions = [[0, 0, 0], [1/3, 2/3, 1/4], [2/3, 1/3, 3/4]]\ntypes = [\"Fe\", \"I\", \"I\"]\ncryst = Crystal(latvecs, positions; types)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Observe that the space group 'P -3 m 1' (164) has been inferred, as well as point group symmetries. Only the Fe atoms are magnetic, so we focus on them with subcrystal. Importantly, the new crystal retains the symmetry information for spacegroup 164.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"cryst = subcrystal(cryst, \"Fe\")\nview_crystal(cryst)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#Symmetry-analysis","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"Symmetry analysis","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The command print_symmetry_table provides a list of all the symmetry-allowed interactions out to 8 Å.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"print_symmetry_table(cryst, 8.0)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The allowed g-tensor is expressed as a 3×3 matrix in the free coefficients A, B, ... The allowed single-ion anisotropy is expressed as a linear combination of Stevens operators. The latter correspond to polynomials of the spin operators, as we will describe below.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The allowed exchange interactions are given as 3×3 matrices for representative bonds. The notation Bond(i, j, n) indicates a bond between atom indices i and j, with cell offset n. Note that the order of the pair (i j) is significant if the exchange tensor contains antisymmetric Dzyaloshinskii–Moriya (DM) interactions.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The bonds can be visualized in the view_crystal interface. By default, Bond(1, 1, [1,0,0]) is toggled on, to show the 6 nearest-neighbor Fe-Fe bonds on a triangular lattice layer. Toggling Bond(1, 1, [0,0,1]) shows the Fe-Fe bond between layers, etc.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#Defining-the-spin-model","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"Defining the spin model","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Construct a System with spin s=1 and g=2 for the Fe ions.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Recall that quantum spin-1 is, in reality, a linear combination of basis states m with well-defined angular momentum m = -1 0 1. FeI₂ has a strong easy-axis anisotropy, which stabilizes a single-ion bound state of zero angular momentum, m=0. Such a bound state is inaccessible to traditional spin wave theory, which works with dipole expectation values of fixed magnitude. This physics is, however, well captured with a theory of SU(N) coherent states, where N = 2S+1 = 3 is the number of levels. Activate this generalized theory by selecting :SUN mode instead of :dipole mode.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"An optional random number seed will make the calculations exactly reproducible.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :SUN, seed=2)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Set the exchange interactions for FeI₂ following the fits of Bai et al.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"J1pm = -0.236 # (meV)\nJ1pmpm = -0.161\nJ1zpm = -0.261\nJ2pm = 0.026\nJ3pm = 0.166\nJ′0pm = 0.037\nJ′1pm = 0.013\nJ′2apm = 0.068\n\nJ1zz = -0.236\nJ2zz = 0.113\nJ3zz = 0.211\nJ′0zz = -0.036\nJ′1zz = 0.051\nJ′2azz = 0.073\n\nJ1xx = J1pm + J1pmpm\nJ1yy = J1pm - J1pmpm\nJ1yz = J1zpm\n\nset_exchange!(sys, [J1xx 0.0 0.0;\n 0.0 J1yy J1yz;\n 0.0 J1yz J1zz], Bond(1,1,[1,0,0]))\nset_exchange!(sys, [J2pm 0.0 0.0;\n 0.0 J2pm 0.0;\n 0.0 0.0 J2zz], Bond(1,1,[1,2,0]))\nset_exchange!(sys, [J3pm 0.0 0.0;\n 0.0 J3pm 0.0;\n 0.0 0.0 J3zz], Bond(1,1,[2,0,0]))\nset_exchange!(sys, [J′0pm 0.0 0.0;\n 0.0 J′0pm 0.0;\n 0.0 0.0 J′0zz], Bond(1,1,[0,0,1]))\nset_exchange!(sys, [J′1pm 0.0 0.0;\n 0.0 J′1pm 0.0;\n 0.0 0.0 J′1zz], Bond(1,1,[1,0,1]))\nset_exchange!(sys, [J′2apm 0.0 0.0;\n 0.0 J′2apm 0.0;\n 0.0 0.0 J′2azz], Bond(1,1,[1,2,1]))","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The function set_onsite_coupling! assigns a single-ion anisotropy. The argument can be constructed using spin_matrices or stevens_matrices. Here we use Julia's anonymous function syntax to assign an easy-axis anisotropy along the direction hatz.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"D = 2.165 # (meV)\nset_onsite_coupling!(sys, S -> -D*S[3]^2, 1)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#Finding-the-ground-state","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"Finding the ground state","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"This model has been fitted so that energy minimization yields the physically correct ground state. Knowing this, we could set the magnetic configuration manually by calling set_dipole! on each site in the system. Another approach, as we will demonstrate, is to search for the ground-state via minimize_energy!.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"To reduce bias in the search, use resize_supercell to create a relatively large system of 4×4×4 chemical cells. Randomize all spins (represented as SU(3) coherent states) and minimize the energy.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"sys = resize_supercell(sys, (4, 4, 4))\nrandomize_spins!(sys)\nminimize_energy!(sys)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"A positive number above indicates that the procedure has converged to a local energy minimum. The configuration, however, may still have defects. This can be checked by visualizing the expected spin dipoles, colored according to their z-components.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"plot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"To better understand the spin configuration, we could inspect the static structure factor mathcalS(𝐪) in the 3D space of momenta 𝐪. The general tool for this analysis is SampledCorrelationsStatic. For the present purposes, however, it is more convenient to use print_wrapped_intensities, which reports mathcalS(𝐪) with periodic wrapping of all commensurate 𝐪 wavevectors into the first Brillouin zone.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"print_wrapped_intensities(sys)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"The known zero-field energy-minimizing magnetic structure of FeI₂ is a two-up, two-down order. It can be described as a generalized spiral with a single propagation wavevector 𝐤. Rotational symmetry allows for three equivalent orientations: 𝐤 = 0 -14 14, 14 0 14, or -141414. Small systems can spontaneously break this symmetry, but for larger systems, defects and competing domains are to be expected. Nonetheless, print_wrapped_intensities shows large intensities consistent with a subset of the known ordering wavevectors.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Let's break the three-fold symmetry by hand. The function suggest_magnetic_supercell takes one or more 𝐤 modes, and suggests a magnetic cell shape that is commensurate.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"suggest_magnetic_supercell([[0, -1/4, 1/4]])","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Calling reshape_supercell yields a much smaller system, making it much easier to find the global energy minimum. Plot the system again, now including \"ghost\" spins out to 12Å, to verify that the magnetic order is consistent with FeI₂.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"sys_min = reshape_supercell(sys, [1 0 0; 0 2 1; 0 -2 1])\nrandomize_spins!(sys_min)\nminimize_energy!(sys_min);\nplot_spins(sys_min; color=[S[3] for S in sys_min.dipoles], ghost_radius=12)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html#Spin-wave-theory","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"Spin wave theory","text":"","category":"section"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Now that the system has been relaxed to an energy minimized ground state, we can calculate the spin wave spectrum. Because we are working with a system of SU(3) coherent states, this calculation will require a multi-flavor boson generalization of the usual spin wave theory.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"swt = SpinWaveTheory(sys_min; measure=ssf_perp(sys_min))","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Calculate and plot the spectrum along a momentum-space path that connects a sequence of high-symmetry 𝐪-points. This interface abstracts over the underlying calculator type.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"qs = [[0,0,0], [1,0,0], [0,1,0], [1/2,0,0], [0,1,0], [0,0,0]]\npath = q_space_path(cryst, qs, 500)\nres = intensities_bands(swt, path)\nplot_intensities(res; units, title=\"Single Crystal Bands\")","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"To make direct comparison with inelastic neutron scattering (INS) data, we must account for empirical broadening of the data. Model this using a lorentzian kernel, with a full-width at half-maximum of 0.3 meV.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"kernel = lorentzian(fwhm=0.3)\nenergies = range(0, 10, 300); # 0 < ω < 10 (meV)\nnothing #hide","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"Also, a real FeI₂ sample will exhibit competing magnetic domains. We use domain_average to average over the three possible domain orientations. This involves 120° rotations about the axis hatz = 0 0 1 in global Cartesian coordinates.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"rotations = [([0,0,1], n*(2π/3)) for n in 0:2]\nweights = [1, 1, 1]\nres = domain_average(cryst, path; rotations, weights) do path_rotated\n intensities(swt, path_rotated; energies, kernel)\nend\nplot_intensities(res; units, colormap=:viridis, title=\"Domain Averaged Intensities\")","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"This result can be directly compared to experimental neutron scattering data from Bai et al.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"(The publication figure used a non-standard coordinate system to label the wave vectors.)","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"To get this agreement, the theory of SU(3) coherent states is essential. The lower band has large quadrupolar character, and arises from the strong easy-axis anisotropy of FeI₂.","category":"page"},{"location":"examples/03_LSWT_SU3_FeI2.html","page":"3. Multi-flavor spin wave simulations of FeI₂","title":"3. Multi-flavor spin wave simulations of FeI₂","text":"An interesting exercise is to repeat the same study, but using :dipole mode instead of :SUN. That alternative choice would constrain the coherent state dynamics to the space of dipoles only, and the flat band of single-ion bound states would be missing.","category":"page"},{"location":"parallelism.html#Parallelizing-Calculations","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"","category":"section"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Calculating structure factors with classical dynamics is computationally expensive, and Sunny does not currently parallelize these calculations at a fine-grained level. However, Julia provides facilities that allow users to run multiple simulations in parallel with only a little extra effort. We will look at two approaches to doing this: multithreading and Julia's Distributed package. We'll present these approaches in a series of code snippets that can be copied and pasted into your preferred Julia development environment.","category":"page"},{"location":"parallelism.html#Review-of-the-serial-workflow","page":"Parallelizing Calculations","title":"Review of the serial workflow","text":"","category":"section"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"The serial approach to calculating a structure factor, covered in the FeI₂ tutorial, involves thermalizing a spin System and then calling add_sample!. 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 mathcalS(𝐪ω). This sequence is repeated to generate additional samples.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"To illustrate, we'll set up a a simple model: a spin-1 antiferromagnet on a BCC crystal. ","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"using Sunny, GLMakie\n\nfunction make_system(; seed=nothing)\n latvecs = lattice_vectors(1, 1, 1, 90, 90, 90)\n positions = [[0, 0, 0]/2, [1, 1, 1]/2]\n cryst = Crystal(latvecs, positions)\n sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(10, 10, 2), seed)\n set_exchange!(sys, 1.0, Bond(1, 1, [1, 0, 0]))\n return sys\nend\n\nsys = make_system()","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"A serial calculation of SampledCorrelations involving the Langevin sampling method can now be performed as follows:","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"# Thermalize the system\ndt = 0.05\nintegrator = Langevin(dt; damping=0.2, kT=0.5)\nfor _ in 1:5000\n step!(sys, integrator)\nend\n\n# Accumulator for S(q,ω) samples\n\nenergies = range(0.0, 10.0, 100)\nmeasure = ssf_perp(sys)\nsc = SampledCorrelations(sys; dt=0.1, energies, measure)\n\n# Collect 10 samples\nfor _ in 1:10\n for _ in 1:1000\n step!(sys, integrator)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"This will take a second or two on a modern workstation, resulting in a single SampledCorrelations that contains 10 samples.","category":"page"},{"location":"parallelism.html#Multithreading-approach","page":"Parallelizing Calculations","title":"Multithreading approach","text":"","category":"section"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"To use threads in Julia, you must launch your Julia environment appropriately.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"From the command line, launch Julia with julia --threads=auto. With this option, Julia will automatically use an optimal number of threads.\nJupyter notebook users will need to to set up a multithreaded Julia kernel and restart into this kernel. The kernel can be created inside Julia with the command IJulia.installkernel(\"Julia Multithreaded\", env=Dict(\"JULIA_NUM_THREADS\" => \"auto\")).\nVSCode users should open their settings and search for Julia: Additional Args. There will be link called Edit in settings.json. Click on this, add \"--threads=auto\" to the list julia.additionalArgs, and start a new REPL.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Before going further, make sure that Threads.nthreads() returns a number greater than 1.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"We will use multithreading in a very simple way, essentially employing a distributed memory approach to avoid conflicts around memory access. First preallocate a number of systems and correlations.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"npar = Threads.nthreads()\nsystems = [make_system(; seed=id) for id in 1:npar]\nscs = [SampledCorrelations(sys; dt=0.1, energies, measure) for _ in 1:npar]","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"warning: Dealing with memory constraints\nIf you have many threads available and are working with a large system, you may not have enough memory to store all these systems and correlations. In that case, simply reduce npar to a small enough value that you can make the necessary allocations.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"When the Threads.@threads macro is applied before a for loop, the iterations of the loop will execute in parallel using the available threads. We will put the entire thermalization and sampling process inside the loop, with each thread acting on a unique System and SampledCorrelations.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Threads.@threads for id in 1:npar\n integrator = Langevin(dt; damping=0.2, kT=0.5)\n for _ in 1:5000\n step!(systems[id], integrator)\n end\n for _ in 1:10\n for _ in 1:1000\n step!(systems[id], integrator)\n end\n add_sample!(scs[id], systems[id])\n end\nend","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"You may find this takes a little bit longer than the serial example, but, at the end of it, you will have generated npar correlation objects, each with 10 samples. We can merge these into a summary SampledCorrelations with 10*npar samples with merge_correlations:","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"sc = merge_correlations(scs)","category":"page"},{"location":"parallelism.html#Using-Distributed","page":"Parallelizing Calculations","title":"Using Distributed","text":"","category":"section"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Julia also provides a distributed memory approach to parallelism through the standard library package Distributed. This works by launching independent Julia environments on different \"processes.\" An advantage of this approach is that it scales naturally to clusters since the processes are easily distributed across many different compute nodes. A disadvantage, especially when working on a single computer, is the increased memory overhead associated with launching all these environments.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"We begin by importing the package,","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"using Distributed","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"and launching some new processes. It is often sensible to create as many processes as there are cores.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"ncores = length(Sys.cpu_info())\naddprocs(ncores)","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"You can think of each process as a separate computer running a fresh Julia environment, so we'll need to import Sunny and define functions in each of these environments. This is easily achieved with the @everywhere macro.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"@everywhere using Sunny\n\n@everywhere function make_system(; seed=nothing)\n latvecs = lattice_vectors(1, 1, 1, 90, 90, 90)\n positions = [[0, 0, 0]/2, [1, 1, 1]/2]\n cryst = Crystal(latvecs, positions)\n sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; seed)\n sys = resize_supercell(sys, (10, 10, 2))\n set_exchange!(sys, 1.0, Bond(1, 1, [1, 0, 0]))\n return sys\nend","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"A simple way to perform work on these processes is to use the parallel map function, pmap. This will apply a function to each element of some iterable, such as a list of numbers, and return a list of the results. It is a parallel map because these function calls may occur at the same time on different Julia processes. The pmap function takes care of distributing the work among the different processes and retrieving the results.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"In the example below, we give pmap a list of RNG seeds to iterate over, and we define the function that will be applied to each of these seeds in a do block. The contents of this block are essentially the same as what we put inside our parallel for loop in the multithreading example. The main difference is that the Systems and SampledCorrelations are not created in advance of the parallelization but are instead created inside each Julia process. The do block returns a SampledCorrelations, and the output of all the parallel computations are collected into list of SampledCorrelations called scs.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"scs = pmap(1:ncores) do id\n sys = make_system(; seed=id)\n sc = SampledCorrelations(sys; dt=0.1, energies, measure)\n integrator = Langevin(0.05; damping=0.2, kT=0.5)\n\n for _ in 1:5000\n step!(sys, integrator)\n end\n for _ in 1:10\n for _ in 1:1000 \n step!(sys, integrator)\n end\n add_sample!(sc, sys)\n end\n\n return sc\nend","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"Finally, merge the results into a summary SampledCorrelations.","category":"page"},{"location":"parallelism.html","page":"Parallelizing Calculations","title":"Parallelizing Calculations","text":"sc = merge_correlations(scs)","category":"page"},{"location":"structure-factor.html#Structure-Factor-Conventions","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"","category":"section"},{"location":"structure-factor.html#Dynamical-correlations","page":"Structure Factor Conventions","title":"Dynamical correlations","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Dynamical correlations are a fundamental observable in condensed matter systems, and facilitate comparison between theory and experimental data.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Frequently, spin-spin correlations are of interest. More generally, one may consider correlations between arbitrary operator fields hatA and hatB. In the Heisenberg picture, operators evolve in time. Consider the dynamical correlation as an equilibrium expectation value,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐫 t) = int_V hatB^(𝐫₀ 0) hatA(𝐫₀ + 𝐫 t) d𝐫₀\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"where the integral runs over some macroscopic volume V . By construction, C(𝐫 t) is an extensive quantity. Ignoring surface effects, the correlation becomes an ordinary product in momentum-space,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐪 t) = hatB_𝐪^(0) hatA_𝐪(t)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Our convention for the Fourier transform from position 𝐫 to momentum 𝐪 is,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatA_𝐪 int_V e^+ i 𝐪𝐫 hatA(𝐫) d𝐫\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"For a Hermitian operator hatA^(𝐫) = hatA(𝐫), it follows that hatA_𝐪^ (hatA_𝐪)^ = hatA_-𝐪 in momentum space. ","category":"page"},{"location":"structure-factor.html#Lehmann-representation-in-frequency-space","page":"Structure Factor Conventions","title":"Lehmann representation in frequency space","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Dynamical correlations are most conveniently calculated in frequency space. We use the convention,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐪 ω) frac12π int_-^ e^-iωt C(𝐪 t) dt\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"On the right-hand side, substitute the definition of Heisenberg time evolution,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatA(t) e^i t hatH hatA e^-i t hatH\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"and the definition of the thermal average,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatO frac1mathcalZmathrmtr e^-β hatH hatO quad mathcalZ mathrmtr e^-β hatH\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Let ϵ_μ and μ denote the exact eigenvalues and eigenstates of the full Hamiltonian hatH. The eigenstates comprise a complete, orthonormal basis. The operator trace can be evaluated as a sum over eigenbasis states ν. Insert a resolution of the identity, μμ = 1, with implicit summation on the repeated μ index. Then, collecting results and applying,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nint_-^ e^-iωt dt = 2πδ(ω)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"the result is the Lehmann representation of dynamical correlations,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐪ω) = frac1mathcalZ e^-β ϵ_ν δ(ϵ_μ - ϵ_ν - ω) νhatB^_𝐪μμhatA_𝐪 ν\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"with implicit summation over eigenbasis indices μ and ν. This representation is the usual starting point for quantum calculations such as linear spin wave theory and its various generalizations.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Using the Lehmann representation, it can be shown that positive and negative frequencies are linked through a detailed balance condition,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC_BA^(𝐪-ω) = e^-β ω C_B^A(𝐪 ω)^*\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"This subscript notation indicates that the left-hand side is a correlation of Hermitian-conjugated operators. Typically hatA and hatB will be Hermitian in real-space, and then detailed balance becomes C(-𝐪-ω) = e^-β ω C(𝐪 ω)^*.","category":"page"},{"location":"structure-factor.html#Discrete-sums-on-the-lattice","page":"Structure Factor Conventions","title":"Discrete sums on the lattice","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"A chemical (crystallographic) unit cell is associated with three lattice vectors 𝐚_123. Site positions are","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\n𝐫_𝐦j m_1 𝐚_1 + m_2 𝐚_2 + m_3 𝐚_3 + δ𝐫_j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"for integers 𝐦 = m_1 m_2 m_3. If the crystal is decorated, then δ𝐫_j denotes the relative displacement of the Bravais sublattice j. ","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Let hatA(𝐫) be decomposed into discrete contributions hatA_𝐦j δ(𝐫-𝐫_𝐦j) at each lattice point 𝐫_𝐦j. The Fourier transform becomes a discrete sum,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatA_𝐪 = sum_j sum_𝐦 e^i 𝐪𝐫_𝐦j hatA_𝐦j sum_j hatA_𝐪j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The second equality above introduces hatA_𝐪j as the Fourier transform of hatA_𝐦j for single sublattice j. It can also be written,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatA_𝐪j = e^i 𝐪δ𝐫_j sum_𝐦 e^i 2π tilde𝐪𝐦 hatA_𝐦j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"where tilde𝐪 expresses momentum in dimensionless reciprocal lattice units (RLU),","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\n𝐪 = tildek_1 𝐛_1 + tildek_2 𝐛_2 + tildek_3 𝐛_3\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"and 𝐛_123 are the reciprocal lattice vectors. Equivalently, tildek_μ 𝐪 𝐚_μ 2π.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"It will be convenient to introduce a dynamical correlation for the operators on sublattices i and j only,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC_ij(𝐪t) hatB^_𝐪i(0) hatA_𝐪j(t)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"By the linearity of expectation values,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC(𝐪 t) = sum_ij C_ij(𝐪t)\nendequation","category":"page"},{"location":"structure-factor.html#Quantum-sum-rule","page":"Structure Factor Conventions","title":"Quantum sum rule","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Integrating over all frequencies ω yields the instant correlation at real-time t = 0,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nint_-^ C(𝐪ω) dω = C(𝐪 t=0) = sum_ij C_ij(𝐪 t=0)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Here, we will investigate spin-spin correlations. For this, select hatB_𝐪i = hat𝐒_𝐪i and A_𝐪j = hat𝐒_𝐪j, such that the dynamical correlations become tensor valued,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nC_ij^αβ(𝐪 t=0) = hatS_𝐪i^α hatS_𝐪j^β\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"In the quantum spin-s representation, the spin dipole on one site satisfies","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhat𝐒^2 = hatS^α hatS^α = s(s+1)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"with implicit summation on the repeated α index.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Suppose that each site of sublattice j carries quantum spin of magnitude s_j. Then there is a quantum sum rule of the form,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nint_tildeV_mathrmBZ fracC_jj^αα(𝐪 t=0)N_mathrmcells dtilde𝐪 = s_j (s_j + 1)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"with summation on α, but not j, implied. The integral runs over the cubic volume in reciprocal lattice units tilde𝐪,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\ntildeV_mathrmBZ 01^3\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"This volume represents one unit cell on the reciprocal lattice, and has the shape of a parallelepiped in physical momentum units 𝐪. This volume is equivalent to the first Brillouin zone because of the reciprocal-space periodicity inherent to the Bravais sublattice. Note that the integral over tilde𝐪 tildeV_mathrmBZ could be converted to an integral over physical momentum 𝐪 by applying a Jacobian transformation factor, d tilde𝐪 = d𝐪 V_mathrmcell (2π)^3, where V_mathrmcell = 𝐚_1 (𝐚_2 𝐚_3) is the volume of the chemical unit cell. The scaling factor","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nN_mathrmcells V V_mathrmcell\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"denotes the number of chemical unit cells in the macroscopic volume V.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The derivation of the sum rule proceeds as follows. Substitute twice the definition,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhatS^α_𝐪j e^i 𝐪δ𝐫_j sum_𝐦 e^i 2π tilde𝐪𝐦 hatS^α_𝐦j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Accounting for complex conjugation, the two phase factors e^i 𝐪δ𝐫_j cancel. The remaining 𝐪-dependence can be integrated to yield a Kronecker-δ,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nint_tildeV_mathrmBZ e^2πi tilde𝐪 (𝐦 - 𝐦) dtilde𝐪 = δ_𝐦 𝐦\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Note that hatS_𝐦j^α hatS_𝐦j^α = s_j(s_j+1) is constant, independent of the cell 𝐦. This leaves a double sum over integers 𝐦, which evaluates to sum_𝐦 𝐦 δ_𝐦 𝐦 = N_mathrmcells. Combined, these results verify the above-stated quantum sum rule for the sublattice j.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"One can also derive a quantum sum rule on the full dynamical correlation C^α β(𝐪 ω). Contributions from distinct sublattices i j introduce a phase factor e^- i 𝐪(δ𝐫_i - δ𝐫_j) that cancels when the momentum 𝐪 is averaged over a large number N_mathrmBZ of Brillouin zones. The final result is a sum over contributions C_jj(𝐪 t=0) for each sublattice j,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nfrac1N_mathrmBZ int_N_mathrmBZ tildeV_mathrmBZ int_-^ fracC^αα(𝐪 ω) N_mathrmcells dω dtilde𝐪 = sum_j s_j (s_j + 1)\nendequation","category":"page"},{"location":"structure-factor.html#Neutron-scattering-cross-section","page":"Structure Factor Conventions","title":"Neutron scattering cross section","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The magnetic moment of a neutron is hatboldsymbolμ_mathrmneutron = - 2 γ μ_N hat𝐒_mathrmneutron, where γ = 1913, μ_N is the nuclear magneton, and hat𝐒_mathrmneutron is spin-1/2 angular momentum. Neutrons interact with the magnetic moments of a material. These have the form hatboldsymbolμ = -μ_B g hat𝐒, where μ_B is the Bohr magneton and hat𝐒 is the effective angular momentum. For a single electron, g = 20023 is known to high precision. Within a crystal, however, the appropriate g_j for each sublattice j may be any 33 matrix consistent with point group symmetries.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Each idealized magnetic moment hatboldsymbolμ_𝐦j is, in reality, smoothly distributed around the site position 𝐫_𝐦 j. This can be modeled through convolution with a density function f_j(𝐫). Fourier transform the full magnetic density field 𝐌(𝐫) to obtain","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhat𝐌_𝐪 sum_j hat𝐌_𝐪j\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"where,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nhat𝐌_𝐪j - μ_B e^i 𝐪δ𝐫_j g_j sum_𝐦 e^i 2π tilde𝐪𝐦 hat𝐒_𝐦j f_j(𝐪)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"In Fourier space, f_j(𝐪) is called the magnetic form factor. Frequently, it will be approximated as an isotropic function of q = 𝐪. Tabulated formula, for various magnetic ions and charge states, are available in Sunny via the FormFactor function. The idealized case f_j(𝐪) = 1 would describe completely localized magnetic moments.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Neutron scattering intensities are given by the total differential cross-section, d^2 σ(𝐪 ω)dωdΩ, where 𝐪 = 𝐪_i - 𝐪_f is the momentum transfer to the sample, ω is the energy transfer to the sample, and Ω is the solid angle. Experimental intensity data will typically be provided in units of q_f q_i. Within the dipole approximation, the result for an unpolarized neutron beam is,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nfracd^2 σ(𝐪 ω)dω dΩ = fracq_fq_i left(fracγ r_02right)^2 sum_αβ left(δ_αβ - fracq^α q^βq^2right) fracmathcalS^αβ(𝐪 ω)μ_B^2\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The prefactor q_fq_i will be provided experimentally. Dimensions of area arise from the characteristic scattering length, γ r_0 2 26910^-5 mathrmÅ, where r_0 is the classical electron radius.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The structure factor is of central importance to neutron scattering,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\nmathcalS^αβ(𝐪 ω) frac12π int_-^ e^-iωt hatM_𝐪^α(0) hatM_𝐪^β(t) dt\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"and describes dynamical correlations of magnetic moments. It will differ nontrivially from the spin-spin correlations if the g_j-tensor varies with sublattice j.","category":"page"},{"location":"structure-factor.html#Conventions-for-the-Sunny-calculated-structure-factor","page":"Structure Factor Conventions","title":"Conventions for the Sunny-calculated structure factor","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"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 as well as the complete Library API.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Through ssf_custom and related functions, Sunny will calculate the spin structure factor as a 3×3 matrix in dimensionless units,","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"beginequation\n𝒮^αβ(𝐪 ω) frac1N_mathrmcells μ_B^2 mathcalS^αβ(𝐪 ω)\nendequation","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"This is an intensive quantity because N_mathrmcells, the number of chemical cells in the macroscopic sample, is extensive. Note that the Sunny-calculated intensity will depend on the chemical cell convention: intensity scales linearly with chemical cell size.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Use ssf_perp to contract with δ_αβ - q^α q^βq^2, i.e., to project in the direction perpendicular to momentum transfer 𝐪.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Set apply_g = false to calculate the correlation C_𝐒𝐒(𝐪 ω) N_mathrmcells between pure spin operators, rather than between magnetic moments. In this special case that g is a uniform scalar, this is equivalent to 𝒮(𝐪 ω) g^2","category":"page"},{"location":"structure-factor.html#Calculations-with-spin-wave-theory","page":"Structure Factor Conventions","title":"Calculations with spin wave theory","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Calculating the dynamical structure factor with linear SpinWaveTheory 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 to study generalized spiral phases, which allow for an incommensurate propagation wavevector. The experimental module SpinWaveTheoryKPM implements spin wave calculations using the kernel polynomial method. 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.","category":"page"},{"location":"structure-factor.html#Calculations-with-classical-spin-dynamics","page":"Structure Factor Conventions","title":"Calculations with classical spin dynamics","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Finite temperature structure factor intensities can be estimated from the dynamical correlations of classical spin dynamics (e.g. Landau-Lifshitz, or its SU(N) generalization). This is fundamentally a Monte Carlo approach, as the trajectories must be initialized to a spin configuration that is sampled from the finite-temperature thermal equilibrium. Samples are accumulated into a SampledCorrelations, from which intensity information may be extracted.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Creating a SampledCorrelations requires specifying three keyword arguments. These will determine the dynamics used to calculate samples and, consequently, the ω information that will be available. ","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"energies: A uniform range of resolved energies.\ndt: The step size for dynamical time-integration. Larger may reduce simulation time, but the choice will be limited by the stability and accuracy requirements of the ImplicitMidpoint integration method. The function suggest_timestep can recommend a good value. The timestep may be adjusted downward so that the specified energies are sampled exactly.\nmeasure: Specification of the pair correlations. This will frequently be reduced from the spin structure factor using one of ssf_trace, ssf_perp, or ssf_custom_bm.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"A sample may be added by calling add_sample!. The input sys must be a spin configuration in good thermal equilibrium, e.g., using the continuous Langevin dynamics or using single spin flip trials with LocalSampler. The statistical quality of the 𝒮(𝐪ω) can be improved by repeatedly generating decorrelated spin configurations in sys and calling add_sample! on each configuration.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The outline of typical use case might look like this:","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"# Make a `SampledCorrelations`\nsc = SampledCorrelations(sys; dt=0.05, energies=range(0.0, 10.0, 100))\n\n# Add samples\nfor _ in 1:nsamples\n decorrelate_system(sys) # Perform some type of Monte Carlo simulation\n add_sample!(sc, sys) # Use spins to calculate trajectory and accumulate new sample of 𝒮(𝐪,ω)\nend","category":"page"},{"location":"structure-factor.html#Extracting-intensities-sampled-correlation-data","page":"Structure Factor Conventions","title":"Extracting intensities sampled correlation data","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Like in spin wave theory, the basic function for extracting intensities information from a SampledCorrelations is intensities. It takes a SampledCorrelations, a collection of 𝐪-vectors, a collection of energies, and possible other options.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Since classical dynamics simulation take place on a finite lattice, the fundamental intensities measurements are only available at a discrete grid of wave vectors. In reciprocal lattice units, available grid points are 𝐪 = fracn_1L_1 fracn_2L_2 fracn_3L_3, where n_i runs from (frac-L_i2+1) to fracL_i2 and L_i is the linear dimension of the lattice used in the calculation. (An internal function Sunny.available_wave_vectors provides access to this grid.) By default intensities will adjust each wavevector 𝐪 to the nearest available grid point. ","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Similarly, the resolution in energies is controlled the dynamical trajectory length in real-time. Because the dynamical trajectory is not periodic in time, some blurring between neighboring energy bins is unavoidable. Sunny's algorithm for estimating the structure factor from real-time dynamics is specified here.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"The temperature parameter kT is required for SampledCorrelations calculations, and will be used to perform classical-to-quantum rescaling of intensities. If kT = nothing, then intensities will be provided according to the classical Boltzmann distribution.","category":"page"},{"location":"structure-factor.html#The-instantaneous-structure-factor","page":"Structure Factor Conventions","title":"The instantaneous structure factor","text":"","category":"section"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Use intensities_static to calculate mathcalS(𝐪), i.e., correlations that are \"instantaneous\" in real-time. Mathematically, mathcalS(𝐪) denotes an integral of the dynamical structure factor mathcalS(𝐪 ω) over all energies ω. In SpinWaveTheory, the energy integral becomes a discrete sum over bands. In SampledCorrelations, a classical-to-quantum correction factor will be applied within intensities prior to energy integration.","category":"page"},{"location":"structure-factor.html","page":"Structure Factor Conventions","title":"Structure Factor Conventions","text":"Sunny also supports a mechanism to calculate static correlations without any spin dynamics. To collect such statistics, construct a SampledCorrelationsStatic object. In this case, intensities_static will return static correlations sampled from the classical Boltzmann distribution. This dynamics-free approach is faster, but may miss important features that derive from the quantum mechanical excitation spectrum.","category":"page"},{"location":"writevtk.html#ParaView-Rendering","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"section"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"The 4D correlation data produced by Sunny is too high-dimensional to visualize directly. This page describes how to export 3D slices of correlation data from Sunny to the Visual ToolKit (VTK) format, which is compatible with the ParaView visualization software. ParaView supports volumetric rendering:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html#Simulation-data","page":"ParaView Rendering","title":"Simulation data","text":"","category":"section"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"First, generate some correlation data in Sunny. We will use a 2D lattice, since the correlation data S(Q_xQ_yomega) is 3D and can be exported in its entirety. The following code sets up the system, thermalizes it, and records the correlation data in a SampledCorrelations called dsf.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"using Sunny\n\nlatvecs = lattice_vectors(8.,8.,12.,90,100,90)\npositions = [[0,0,0]]\ntypes = [\"Cu\"]\nformfactors = [FormFactor(\"Cu2\")]\nxtal = Crystal(latvecs, positions; types)\n\nsys = System(xtal, [1 => Moment(s=1/2, g=2)], :SUN; dims=(12, 12, 1), seed=1)\n\nJ = 10.\nset_exchange!(sys, J, Bond(1,1,[1,0,0]))\nset_exchange!(sys, J, Bond(1,1,[0,1,0]))\n\ndt = 0.01\nkT = 0.5\nlangevin = Langevin(dt; damping=0.5, kT)\nrandomize_spins!(sys)\nfor i in 1:10_000 # Long enough to reach equilibrium\n step!(sys, langevin)\nend \n\nωmax=10.\ndsf = SampledCorrelations(sys; dt, energies=range(0, ωmax, 48))\n\nnsamples = 10\nfor _ in 1:nsamples\n for _ in 1:1000 \n step!(sys, langevin)\n end\n add_sample!(dsf, sys)\nend","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"The default histogram BinningParameters are already integrated over the z direction because the system is 2D:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"unit_resolution_binning_parameters(dsf)","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"⊡ 12 bins from -0.042 to +0.958 along [+1.27 dx] (Δ = 0.065)\n⊡ 12 bins from -0.042 to +0.958 along [+1.27 dy] (Δ = 0.065)\n∫ Integrated from +0.000 to +0.000 along [-0.33 dx +1.88 dz] (Δ = 0.524)\n⊡ 48 bins from -0.107 to +10.134 along [+1.00 dE] (Δ = 0.213)","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"The histogram is very oblong; it's approximately 1x1x10. To make it a nicer shape, we will rescale the energy axis to be be fractions of ωmax:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"params = unit_resolution_binning_parameters(dsf)\nscale_factor = ωmax\nparams.binend[4] /= scale_factor\nparams.binstart[4] /= scale_factor\nparams.binwidth[4] /= scale_factor\nparams.covectors[4,:] ./= scale_factor","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Doing this changes the last axis of the histogram to fit in [0,1]:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"⊡ 49 bins from -0.011 to +1.013 along [+0.10 dE] (Δ = 0.213)","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Now that our histogram is a cube, we compute the intensity in the histogram bins using the usual intensities_binned:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"formula = intensity_formula(dsf, :trace)\nsignal, counts = intensities_binned(dsf, params; formula)\nintensity = signal ./ counts","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Now that we have our intensity data and the binning parameters, we can export to VTK format using export_vtk and move to ParaView for the visualization.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"# Importing WriteVTK enables Sunny's export-to-VTK functions\nimport WriteVTK\n\n# [1,2,4] specifies that the (x,y,z) axes in ParaView are (Qx,Qy,ω)\nexport_vtk(\"square_lattice\", params, intensity; dims_kept = [1,2,4])\n# Writes a file square_lattice.vti in the current directory","category":"page"},{"location":"writevtk.html#Loading-in-ParaView","page":"ParaView Rendering","title":"Loading in ParaView","text":"","category":"section"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"In ParaView, use File > Open to open square_lattice.vti. This will add the file to the Pipeline Browser with a closed eye icon, indicating that the data is ready to be loaded.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"In the Properties panel, both bin_centers and data will be selected for import by default. Uncheck bin_centers because we don't need that information for the visualization. Click the green Apply button to load the data.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"By default, only the outline of the data is shown in the 3D viewport. Since we adjusted the energy axis, the outline is a 1x1x1 cube. Optionally enable the axes grid under \"View\", and customize using the adjacent edit button.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"To enable the volumetric render:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Select \"Volume\" from the \"Representation\" drop-down menu under \"Display\".\nThe \"Coloring\" drop-down should automatically select data because it's the only data loaded.\nOpen the Color Map Editor to adjust the opacity of the fog, which may be too faint to see by default.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Depending on your computer and your dataset size, the volumetric rendering may be slow, but our dataset is relatively small, so the render should be fast.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"If nothing shows up at first, don't despair. Often, there are Bragg-like peaks in the correlation data which outshine everything else. To see this, enable Display Data Histogram in the Color Map Editor panel. To zoom in on the lower-intensity data, click and drag the right side handle of the opacity transfer function box to the middle a few times.","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"After suitable color mapping, the dispersion curve should become visible:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"","category":"page"},{"location":"writevtk.html#Experiment-data","page":"ParaView Rendering","title":"Experiment data","text":"","category":"section"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"Note that since only the data and binning parameters are required for exporting to VTK, experiment data can be exported in the same way. For example, to visualize S(Q_xQ_yQ_z), do this:","category":"page"},{"location":"writevtk.html","page":"ParaView Rendering","title":"ParaView Rendering","text":"# Load 4D histogram data from Mantid\nparams, signal = load_nxs(\"experiment_data.nxs\")\n\n# Integrate out the energy axis so we are 3D\nintegrate_axes!(params; axes = 4)\nsignal = sum(signal; dims = 4)\n\n# Export to ParaView\nexport_vtk(\"experiment_data_as_vtk\", params, signal)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"EditURL = \"../../../examples/01_LSWT_CoRh2O4.jl\"","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#1.-Spin-wave-simulations-of-CoRhO","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"This tutorial introduces Sunny through its features for performing conventional spin wave theory calculations. We consider the crystal CoRh₂O₄ and reproduce the calculations of Ge et al., Phys. Rev. B 96, 064413.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Get-Julia-and-Sunny","page":"1. Spin wave simulations of CoRh₂O₄","title":"Get Julia and Sunny","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"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 guide. Sunny requires Julia 1.10 or later.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"From the Julia prompt, load Sunny and also GLMakie for graphics.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"If these packages are not yet installed, Julia will offer to install them. If executing this tutorial gives an error, you may need to update Sunny and GLMakie from the built-in package manager.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Units-system","page":"1. Spin wave simulations of CoRh₂O₄","title":"Units system","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"The Units object selects reference energy and length scales, and uses these to provide physical constants. For example, units.K returns one kelvin as 0.086 meV, where the Boltzmann constant is implicit.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"units = Units(:meV, :angstrom);\nnothing #hide","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Crystal-cell","page":"1. Spin wave simulations of CoRh₂O₄","title":"Crystal cell","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"A crystallographic cell may be loaded from a .cif file, or specified from atom positions and types.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"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 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 (hatx haty hatz) in components of the lattice vectors.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"a = 8.5031 # (Å)\nlatvecs = lattice_vectors(a, a, a, 90, 90, 90)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Construct the Crystal 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.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"positions = [[0, 0, 0]]\ncryst = Crystal(latvecs, positions, 227; types=[\"Co\"], setting=\"1\")","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"view_crystal launches an interface for interactive inspection and symmetry analysis.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"view_crystal(cryst)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Spin-system","page":"1. Spin wave simulations of CoRh₂O₄","title":"Spin system","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"A System will define the spin model. Each cobalt atom carries quantum spin s = 32, with a g-factor of 2. Specify this Moment data for cobalt atom 1. By symmetry, the same moment data also applies to cobalt atoms 2, 3, ... 7. The option :dipole indicates a traditional model type, for which quantum spin is modeled as a dipole expectation value.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"sys = System(cryst, [1 => Moment(s=3/2, g=2)], :dipole)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Ge et al. demonstrated that inelastic neutron scattering data for CoRh₂O₄ is well modeled by antiferromagnetic nearest neighbor exchange, J = 0.63 meV. Call set_exchange! with the bond that connects atom 1 to atom 3, and has zero displacement between chemical cells. Consistent with the symmetries of spacegroup 227, this interaction will be propagated to all other nearest-neighbor bonds. Calling view_crystal with sys now shows the antiferromagnetic Heisenberg interactions as blue polkadot spheres.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"J = +0.63 # (meV)\nset_exchange!(sys, J, Bond(1, 3, [0, 0, 0]))\nview_crystal(sys)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Optimizing-spins","page":"1. Spin wave simulations of CoRh₂O₄","title":"Optimizing spins","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"To search for the ground state, call randomize_spins! and minimize_energy! in sequence. For this problem, optimization converges rapidly to the expected Néel order. See this with plot_spins, where spins are colored according to their global z-component.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"The diamond lattice is bipartite, allowing each spin to perfectly anti-align with its 4 nearest-neighbors. Each of these 4 bonds contribute -J s^2 to the total energy. Two sites participate in each bond, so the energy per site is -2 J s^2. Check this by calling energy_per_site.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"@assert energy_per_site(sys) ≈ -2J*(3/2)^2","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Reshaping-the-magnetic-cell","page":"1. Spin wave simulations of CoRh₂O₄","title":"Reshaping the magnetic cell","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"The most compact magnetic cell for this Néel order is a primitive unit cell. Reduce the magnetic cell size using reshape_supercell, where columns of the shape matrix are primitive lattice vectors as multiples of the conventional cubic lattice vectors (𝐚_1 𝐚_2 𝐚_3). One could alternatively use shape = cryst.latvecs \\ cryst.prim_latvecs. Verify that the energy per site is unchanged after the reshaping the supercell.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"shape = [0 1 1;\n 1 0 1;\n 1 1 0] / 2\nsys_prim = reshape_supercell(sys, shape)\n@assert energy_per_site(sys_prim) ≈ -2J*(3/2)^2","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Plotting sys_prim shows the two spins within the primitive cell, as well as the larger conventional cubic cell for context.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"plot_spins(sys_prim; color=[S[3] for S in sys_prim.dipoles])","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#Spin-wave-theory","page":"1. Spin wave simulations of CoRh₂O₄","title":"Spin wave theory","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"With this primitive cell, we will perform a SpinWaveTheory calculation of the structure factor mathcalS(𝐪ω). The measurement ssf_perp indicates projection of the spin structure factor mathcalS(𝐪ω) perpendicular to the direction of momentum transfer, as appropriate for unpolarized neutron scattering. The isotropic FormFactor for Co²⁺ dampens intensities at large 𝐪.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"formfactors = [1 => FormFactor(\"Co2\")]\nmeasure = ssf_perp(sys_prim; formfactors)\nswt = SpinWaveTheory(sys_prim; measure)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Select lorentzian broadening with a full-width at half-maximum (FWHM) of 0.8 meV.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"kernel = lorentzian(fwhm=0.8)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Define a q_space_path 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, 𝐛_12 + 𝐛_22. A total of 500 𝐪-points will be sampled along the path.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"qs = [[0, 0, 0], [1/2, 0, 0], [1/2, 1/2, 0], [0, 0, 0]]\npath = q_space_path(cryst, qs, 500)","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Calculate single-crystal scattering intensities along this path, for energies between 0 and 6 meV. Use plot_intensities to visualize the result.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"energies = range(0, 6, 300)\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res; units, title=\"CoRh₂O₄ LSWT\")","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"Sometimes experimental data is only available as a powder average, i.e., as an average over all possible crystal orientations. Use powder_average to simulate these intensities. Each 𝐪-magnitude defines a spherical shell in reciprocal space. Consider 200 radii from 0 to 3 inverse angstroms, and collect 2000 random samples per spherical shell. As configured, this calculation completes in about two seconds. Had we used the conventional cubic cell, the calculation would be an order of magnitude slower.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"radii = range(0, 3, 200) # (1/Å)\nres = powder_average(cryst, radii, 2000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units, saturation=1.0, title=\"CoRh₂O₄ Powder Average\")","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"This result can be compared to experimental neutron scattering data from Fig. 5 of Ge et al.","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"","category":"page"},{"location":"examples/01_LSWT_CoRh2O4.html#What's-next?","page":"1. Spin wave simulations of CoRh₂O₄","title":"What's next?","text":"","category":"section"},{"location":"examples/01_LSWT_CoRh2O4.html","page":"1. Spin wave simulations of CoRh₂O₄","title":"1. Spin wave simulations of CoRh₂O₄","text":"For more spin wave calculations of this type, browse the SpinW tutorials ported to Sunny.\nSpin wave theory neglects thermal fluctuations of the magnetic order. The next CoRh₂O₄ tutorial demonstrates how to sample spins in thermal equilibrium, and measure dynamical correlations from the classical spin dynamics.\nSunny 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 the FeI₂ tutorial.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"EditURL = \"../../../examples/04_GSD_FeI2.jl\"","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/04_GSD_FeI2.html#4.-Generalized-spin-dynamics-of-FeI-at-finite-*T*","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"","category":"section"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The previous FeI₂ tutorial used multi-flavor spin wave theory to calculate the dynamical spin structure factor. This tutorial performs an analogous calculation at finite temperature using the classical dynamics of SU(N) coherent states.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Compared to spin wave theory, classical spin dynamics in real-space is typically much slower, and is limited in 𝐪-space resolution. The approach, however, allows for thermal fluctuations, can be used to explore finite temperature phases, and enables the study of highly non-equilibrium processes.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The structure of this tutorial largely follows the previous study of CoRh₂O₄ at finite T. The main difference is that CoRh₂O₄ can be well described with :dipole mode, whereas FeI₂ is best modeled using :SUN mode, owing to its strong easy-axis anisotropy.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Construct the FeI₂ system as previously described.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"using Sunny, GLMakie\n\nunits = Units(:meV, :angstrom)\na = b = 4.05012\nc = 6.75214\nlatvecs = lattice_vectors(a, b, c, 90, 90, 120)\ncryst = Crystal(latvecs, [[0,0,0]], 164; types=[\"Fe\"])\n\nsys = System(cryst, [1 => Moment(s=1, g=2)], :SUN)\nJ1pm = -0.236\nJ1pmpm = -0.161\nJ1zpm = -0.261\nJ2pm = 0.026\nJ3pm = 0.166\nJ′0pm = 0.037\nJ′1pm = 0.013\nJ′2apm = 0.068\nJ1zz = -0.236\nJ2zz = 0.113\nJ3zz = 0.211\nJ′0zz = -0.036\nJ′1zz = 0.051\nJ′2azz = 0.073\nJ1xx = J1pm + J1pmpm\nJ1yy = J1pm - J1pmpm\nJ1yz = J1zpm\nset_exchange!(sys, [J1xx 0.0 0.0; 0.0 J1yy J1yz; 0.0 J1yz J1zz], Bond(1,1,[1,0,0]))\nset_exchange!(sys, [J2pm 0.0 0.0; 0.0 J2pm 0.0; 0.0 0.0 J2zz], Bond(1,1,[1,2,0]))\nset_exchange!(sys, [J3pm 0.0 0.0; 0.0 J3pm 0.0; 0.0 0.0 J3zz], Bond(1,1,[2,0,0]))\nset_exchange!(sys, [J′0pm 0.0 0.0; 0.0 J′0pm 0.0; 0.0 0.0 J′0zz], Bond(1,1,[0,0,1]))\nset_exchange!(sys, [J′1pm 0.0 0.0; 0.0 J′1pm 0.0; 0.0 0.0 J′1zz], Bond(1,1,[1,0,1]))\nset_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]))\nD = 2.165\nset_onsite_coupling!(sys, S -> -D*S[3]^2, 1)","category":"page"},{"location":"examples/04_GSD_FeI2.html#Thermalization","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"Thermalization","text":"","category":"section"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"To study thermal fluctuations in real-space, use a large system size with 16×16×4 copies of the chemical cell.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"sys = resize_supercell(sys, (16, 16, 4))","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Direct optimization via minimize_energy! is susceptible to trapping in a local minimum. An alternative approach is to simulate the system using Langevin spin dynamics. This requires a bit more set-up, but allows sampling from thermal equilibrium at any target temperature. Select the temperature 2.3 K ≈ 0.2 meV. This temperature is small enough to magnetically order, but large enough so that the dynamics can readily overcome local energy barriers and annihilate defects.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"langevin = Langevin(; damping=0.2, kT=2.3*units.K)","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Use suggest_timestep to select an integration timestep for the error tolerance tol=1e-2. Initializing sys to some low-energy configuration usually works well.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"randomize_spins!(sys)\nminimize_energy!(sys; maxiters=10)\nsuggest_timestep(sys, langevin; tol=1e-2)\nlangevin.dt = 0.03;\nnothing #hide","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Run a Langevin trajectory for 10,000 time-steps and plot the spins. The magnetic order is present, but may be difficult to see.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"for _ in 1:10_000\n step!(sys, langevin)\nend\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Verify the expected two-up, two-down spiral magnetic order by calling print_wrapped_intensities. A single propagation wavevector 𝐤 dominates the static intensity in mathcalS(𝐪), indicating the expected 2 up, 2 down magnetic spiral order. A smaller amount of intensity is spread among many other wavevectors due to thermal fluctuations.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"print_wrapped_intensities(sys)","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Thermalization has not substantially altered the suggested dt.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"suggest_timestep(sys, langevin; tol=1e-2)","category":"page"},{"location":"examples/04_GSD_FeI2.html#Structure-factor-in-the-paramagnetic-phase","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"Structure factor in the paramagnetic phase","text":"","category":"section"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The remainder of this tutorial will focus on the paramagnetic phase. Re-thermalize the system to the temperature of 3.5 K ≈ 0.30 meV.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"langevin.kT = 3.5 * units.K\nfor _ in 1:10_000\n step!(sys, langevin)\nend","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The suggested timestep has increased slightly. Following this suggestion will make the simulations a bit faster.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"suggest_timestep(sys, langevin; tol=1e-2)\nlangevin.dt = 0.040;\nnothing #hide","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Collect dynamical spin structure factor data using SampledCorrelations. This procedure involves sampling spin configurations from thermal equilibrium and using the spin dynamics of SU(N) coherent states to estimate dynamical correlations. With proper classical-to-quantum corrections, the associated structure factor intensities S^αβ(qω) can be compared with finite-temperature inelastic neutron scattering data. Incorporate the FormFactor appropriate to Fe²⁺.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"dt = 2*langevin.dt\nenergies = range(0, 7.5, 120)\nformfactors = [1 => FormFactor(\"Fe2\"; g_lande=3/2)]\nsc = SampledCorrelations(sys; dt, energies, measure=ssf_perp(sys; formfactors))","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"The function add_sample! will collect data by running a dynamical trajectory starting from the current system configuration.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"add_sample!(sc, sys)","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"To collect additional data, it is required to re-sample the spin configuration from the thermal distribution. Statistical error is reduced by fully decorrelating the spin configurations between calls to add_sample!.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"for _ in 1:2\n for _ in 1:1000 # Enough steps to decorrelate spins\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Perform an intensity calculation for two special 𝐪-points in reciprocal lattice units (RLU). A classical-to-quantum rescaling of normal mode occupations will be performed according to the temperature kT. The large statistical noise could be reduced by averaging over more thermal samples.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"res = intensities(sc, [[0, 0, 0], [0.5, 0.5, 0.5]]; energies, langevin.kT)\nfig = lines(res.energies, res.data[:, 1]; axis=(xlabel=\"meV\", ylabel=\"Intensity\"), label=\"(0,0,0)\")\nlines!(res.energies, res.data[:, 2]; label=\"(π,π,π)\")\naxislegend()\nfig","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"Next, we will measure intensities along a q_space_path that connects high symmetry points. Because this is a real-space calculation, data is only available for discrete 𝐪 modes, with resolution that scales inversely to linear system size. Intensities at ω = 0 dominate, so to enhance visibility, we restrict the color range empirically.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"qs = [[0, 0, 0], # List of wave vectors that define a path\n [1, 0, 0],\n [0, 1, 0],\n [1/2, 0, 0],\n [0, 1, 0],\n [0, 0, 0]]\nqpath = q_space_path(cryst, qs, 500)\nres = intensities(sc, qpath; energies, langevin.kT)\nplot_intensities(res; colorrange=(0.0, 1.0), title=\"Intensities at T = 2.3 K\")","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"One can also view the intensity along a q_space_grid for a fixed energy value. Alternatively, use intensities_static to integrate over all available energies.","category":"page"},{"location":"examples/04_GSD_FeI2.html","page":"4. Generalized spin dynamics of FeI₂ at finite T","title":"4. Generalized spin dynamics of FeI₂ at finite T","text":"grid = q_space_grid(cryst, [1, 0, 0], range(-1.5, 1.5, 300), [0, 1, 0], (-1.5, 1.5); orthogonalize=true)\nres = intensities(sc, grid; energies=[3.5], langevin.kT)\nplot_intensities(res; title=\"Intensity slice at ω = 3.5 meV\")","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"EditURL = \"../../../../examples/spinw_tutorials/SW08_sqrt3_kagome_AFM.jl\"","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html#SW08-33-kagome-antiferromagnet","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"","category":"section"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"This is a Sunny port of SpinW Tutorial 8, originally authored by Bjorn Fak and Sandor Toth. It calculates the linear spin wave theory spectrum for the sqrt3 times sqrt3 order of a kagome antiferromagnet.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Define the chemical cell of a kagome lattice with spacegroup 147 (P-3).","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 40, 90, 90, 120)\ncryst = Crystal(latvecs, [[1/2, 0, 0]], 147)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Construct a spin system with nearest neighbor antiferromagnetic exchange.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ = 1.0\nset_exchange!(sys, J, Bond(2, 3, [0, 0, 0]))","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Initialize to an energy minimizing magnetic structure, for which nearest-neighbor spins are at 120° angles.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"set_dipole!(sys, [cos(0), sin(0), 0], (1, 1, 1, 1))\nset_dipole!(sys, [cos(0), sin(0), 0], (1, 1, 1, 2))\nset_dipole!(sys, [cos(2π/3), sin(2π/3), 0], (1, 1, 1, 3))\nk = [-1/3, -1/3, 0]\naxis = [0, 0, 1]\nsys_enlarged = repeat_periodically_as_spiral(sys, (3, 3, 1); k, axis)\nplot_spins(sys_enlarged; ndims=2)","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Check energy per site. Each site participates in 4 bonds with energy Jcos(2π3). Factor of 1/2 avoids double counting. The two calculation methods agree.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"@assert energy_per_site(sys_enlarged) ≈ (4/2)*J*cos(2π/3)\n@assert spiral_energy_per_site(sys; k, axis) ≈ (4/2)*J*cos(2π/3)","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Calculate and plot intensities for a path through 𝐪-space using two calculation methods. The two methods agree in intensity, but the \"supercell method\" gives rise to ghost modes in the dispersion that have zero intensity.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"qs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]\npath = q_space_path(cryst, qs, 400)\n\nfig = Figure(size=(768, 300))\nswt = SpinWaveTheory(sys_enlarged; measure=ssf_perp(sys_enlarged))\nres = intensities_bands(swt, path)\nplot_intensities!(fig[1, 1], res; units, saturation=0.5,title=\"Supercell method\")\nswt = SpinWaveTheorySpiral(sys; measure=ssf_perp(sys), k, axis)\nres = intensities_bands(swt, path)\nplot_intensities!(fig[1, 2], res; units, saturation=0.5, title=\"Spiral method\")\nfig","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"Calculate and plot the powder averaged spectrum. Continuing to use the \"spiral method\", this calculation executes in about two seconds. Because the intensities are dominated by a flat band at zero energy transfer, select an empirical colorrange that brings the lower-intensity features into focus.","category":"page"},{"location":"examples/spinw/SW08_sqrt3_kagome_AFM.html","page":"SW08 - √3×√3 kagome antiferromagnet","title":"SW08 - √3×√3 kagome antiferromagnet","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 3, 200)\nkernel = gaussian(fwhm=0.05)\nres = powder_average(cryst, radii, 200) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units, colorrange=(0,20))","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"EditURL = \"../../../../examples/spinw_tutorials/SW10_Energy_cut.jl\"","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html#SW10-Energy-cut-on-square-lattice","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"","category":"section"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"This is a Sunny port of SpinW Tutorial 10, originally authored by Sandor Toth. It calculates the spin wave spectrum on a constant energy cut of the frustrated square lattice.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Define the chemical cell for the 2D square lattice.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(1.0, 1.0, 3.0, 90, 90, 90)\ncryst = Crystal(latvecs, [[0, 0, 0]])","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Construct a spin system with nearest-neighbor antiferomagnetic interactions of 1.0 meV. Energy minimization yields the expected Néel order on the 2×2 magnetic cell.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(2, 2, 1))\nset_exchange!(sys, 1.0, Bond(1, 1, [1, 0, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Define a 2D slice through 𝐪-space with q_space_grid.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"grid = q_space_grid(cryst, [1, 0, 0], range(0, 2, 201), [0, 1, 0], range(0, 2, 201))","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Calculate and plot a constant energy cut at the precise value of 3.75 meV. Apply a line broadening with a full-width half-max of 0.2 meV to approximately capture intensities between 3.5 and 4.0 meV.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities(swt, grid; energies=[3.75], kernel=gaussian(fwhm=0.2))\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"Integrate intensities between 3.5 and 4 meV using intensities_static with the bounds option.","category":"page"},{"location":"examples/spinw/SW10_Energy_cut.html","page":"SW10 - Energy cut on square lattice","title":"SW10 - Energy cut on square lattice","text":"res = intensities_static(swt, grid; bounds=(3.5, 4.01))\nplot_intensities(res; units)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"EditURL = \"../../../examples/08_Momentum_Conventions.jl\"","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/08_Momentum_Conventions.html#8.-Momentum-transfer-conventions","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"","category":"section"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"This example illustrates Sunny's conventions for dynamical structure factor intensities, mathcalS(𝐪ω), as documented in the page Structure Factor Conventions. The variables 𝐪 and ω describe momentum and energy transfer to the sample.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"For systems without inversion-symmetry, the structure factor intensities at 𝐪 may be inequivalent. To highlight this, consider a simple 1D chain that includes only Dzyaloshinskii–Moriya interactions between neighboring sites. Coupling to an external field then breaks time-reversal symmetry, giving rise to an inequivalence of intensities mathcalS(𝐪ω)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Selecting the P1 spacegroup will effectively disable all symmetry analysis. This can be a convenient way to avoid symmetry-imposed constraints on the couplings. A disadvantage is that all bonds are treated as inequivalent, and Sunny will therefore not be able to propagate any couplings between bonds.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"latvecs = lattice_vectors(2, 2, 1, 90, 90, 90)\ncryst = Crystal(latvecs, [[0,0,0]], \"P1\")","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Construct a 1D chain system that extends along the global Cartesian z axis. The Hamiltonian includes DM and Zeeman coupling terms, ℋ = _j D z (𝐒_j 𝐒_j+1) - _j 𝐁 μ_j, where μ_j = - g 𝐒_j is the magnetic_moment and 𝐁 z.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(1, 1, 25))\nD = 0.1\nB = 5D\nset_exchange!(sys, dmvec([0, 0, D]), Bond(1, 1, [0, 0, 1]))\nset_field!(sys, [0, 0, B])","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"The large external field fully polarizes the system. Here, the DM coupling contributes nothing, leaving only Zeeman coupling.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"randomize_spins!(sys)\nminimize_energy!(sys)\n@assert energy_per_site(sys) ≈ -10D","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Sample from the classical Boltzmann distribution at a low temperature.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"dt = 0.1\nkT = 0.02\ndamping = 0.1\nlangevin = Langevin(dt; kT, damping)\nsuggest_timestep(sys, langevin; tol=1e-2)\nfor _ in 1:10_000\n step!(sys, langevin)\nend","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"The Zeeman coupling polarizes the magnetic moments in the 𝐁 z direction. The spin dipoles, however, are anti-aligned with the magnetic moments, and therefore point towards -z. This is shown below.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"plot_spins(sys)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Estimate the dynamical structure factor using classical dynamics.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"sc = SampledCorrelations(sys; dt, energies=range(0, 15D, 100), measure=ssf_trace(sys))\nadd_sample!(sc, sys)\nnsamples = 100\nfor _ in 1:nsamples\n for _ in 1:1_000\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend\npath = q_space_path(cryst, [[0,0,-1/2], [0,0,+1/2]], 400)\nres1 = intensities(sc, path; energies=:available, kT)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"Calculate the same quantity with linear spin wave theory at T = 0. Because the ground state is fully polarized, the required magnetic cell is a 111 grid of chemical unit cells.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"sys_small = resize_supercell(sys, (1,1,1))\nminimize_energy!(sys_small)\nswt = SpinWaveTheory(sys_small; measure=ssf_trace(sys_small))\nres2 = intensities_bands(swt, path)","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"This model system has a single magnon band with dispersion ϵ(𝐪) = 1 - DB sin(2πq₃) and uniform intensity. Both calculation methods reproduce this analytical solution. Observe that 𝐪 and -𝐪 are inequivalent. The structure factor calculated from classical dynamics additionally shows an elastic peak at 𝐪 = 000, reflecting the ferromagnetic ground state.","category":"page"},{"location":"examples/08_Momentum_Conventions.html","page":"8. Momentum transfer conventions","title":"8. Momentum transfer conventions","text":"fig = Figure(size=(768, 300))\nplot_intensities!(fig[1, 1], res1; title=\"Classical dynamics\")\nplot_intensities!(fig[1, 2], res2; title=\"Spin wave theory\")\nfig","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"EditURL = \"../../../examples/06_CP2_Skyrmions.jl\"","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html#6.-Dynamical-quench-into-CP-skyrmion-liquid","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"","category":"section"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"This example demonstrates a non-equilibrium study of SU(3) spin dynamics leading to the formation of a CP² skyrmion liquid. As proposed in Zhang et al., Nature Communications 14, 3626 (2023), CP² skyrmions are topological defects that involve both the dipolar and quadrupolar parts of quantum spin-1, and can be studied using the formalism SU(3) coherent states.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"This study uses the SU(N) generalization of Landau-Lifshitz spin dynamics, with Langevin coupling to a thermal bath, as described in Dahlbom et al., Phys. Rev. B 106, 235154 (2022). Beginning from an initial high-temperature state, the dynamics following a rapid quench in temperature gives rise a disordered liquid of CP² skyrmions.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Begin with a Crystal cell for the triangular lattice.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"lat_vecs = lattice_vectors(1, 1, 10, 90, 90, 120)\npositions = [[0, 0, 0]]\ncryst = Crystal(lat_vecs, positions)","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Create a spin System containing LL cells. Following previous worse, select g=-1 so that the Zeeman coupling has the form -𝐁𝐬.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"L = 40\nsys = System(cryst, [1 => Moment(s=1, g=-1)], :SUN; dims=(L, L, 1))","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"The Hamiltonian,","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"mathcalH = sum_langle ij rangle J_ij( hatS_i^x hatS_j^x + hatS_i^y hatS_j^y + DeltahatS_i^z hatS_j^z) - hsum_ihatS_i^z + Dsum_i(hatS_i^z)^2","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"contains competing ferromagnetic first-neighbor and antiferromagnetic second-neighbor exchange terms on a triangular lattice. Both exchange matrices include anisotropy in the hatz direction. Additionally, there is an external magnetic field h and an easy-plane single-ion anisotropy D. Select parameters for a point in the Zhang et al. phase diagram where the CP² skyrmions are stable.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"J1 = -1 # Nearest-neighbor ferromagnetic\nJ2 = (2.0/(1+√5)) # Tune competing exchange to set skyrmion scale length\nΔ = 2.6 # Exchange anisotropy\n\nex1 = J1 * [1 0 0;\n 0 1 0;\n 0 0 Δ]\nex2 = J2 * [1 0 0;\n 0 1 0;\n 0 0 Δ]\nset_exchange!(sys, ex1, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, ex2, Bond(1, 1, [1, 2, 0]))\n\nh = 15.5 # External field in energy units\nfield = set_field!(sys, [0, 0, h])\n\nD = 19.0 # Easy-plane anisotropy\nset_onsite_coupling!(sys, S -> D*S[3]^2, 1)","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Initialize system to an infinite temperature (fully randomized) initial condition.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"We will study a temperature quench process using a generalized Langevin spin dynamics. In this SU(3) treatment of quantum spin-1, the dynamics include coupled dipoles and quadrupoles. Select a relatively small damping magnitude to overcome local minima, and disable thermal fluctuations.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"damping = 0.05\nkT = 0;\nnothing #hide","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"The first step is to estimate a reasonable integration timestep dt. In this case, a random spin configuration gives a tighter bound than does an energy-minimized configuration. A relatively large error tolerance is OK for this phenomenological study.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"randomize_spins!(sys)\nintegrator = Langevin(; damping, kT)\nsuggest_timestep(sys, integrator; tol=0.05)","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Apply the suggested timestep.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"integrator.dt = 0.01;\nnothing #hide","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Now run the dynamical quench starting from a randomized configuration. The field frames stores the system spin configuration, as SU(3) coherent states, at three different times during the quenching process.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"randomize_spins!(sys)\nτs = [4, 16, 256] # Times to record snapshots\nframes = [] # Empty array to store snapshots\nfor i in eachindex(τs)\n dur = i == 1 ? τs[1] : τs[i] - τs[i-1] # Determine the length of time to simulate\n numsteps = round(Int, dur/integrator.dt)\n for _ in 1:numsteps # Perform the integration\n step!(sys, integrator)\n end\n push!(frames, copy(sys.coherents)) # Save a snapshot spin configuration\nend","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"Visualize the state of the system contained in each snapshot by plotting the SU(3) Berry phase curvature over triangular plaquettes. This is a measure of CP² skyrmion density. The function plot_triangular_plaquettes is not part of the core Sunny package, but rather something you could define yourself using Makie. Find this helper function at examples/extra/Plotting/.","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"include(pkgdir(Sunny, \"examples\", \"extra\", \"Plotting\", \"plotting2d.jl\"))\n\nfunction sun_berry_curvature(z₁, z₂, z₃)\n z₁, z₂, z₃ = normalize.((z₁, z₂, z₃))\n n₁ = z₁ ⋅ z₂\n n₂ = z₂ ⋅ z₃\n n₃ = z₃ ⋅ z₁\n return angle(n₁ * n₂ * n₃)\nend\n\nplot_triangular_plaquettes(sun_berry_curvature, frames; size=(600, 200),\n offset_spacing=10, texts=[\"\\tt = \"*string(τ) for τ in τs], text_offset=(0, 6)\n)","category":"page"},{"location":"examples/06_CP2_Skyrmions.html","page":"6. Dynamical quench into CP² skyrmion liquid","title":"6. Dynamical quench into CP² skyrmion liquid","text":"The times are given in hbarJ_1. The white background corresponds to a quantum paramagnetic state, where the local spin exhibits a strong quadrupole moment and little or no dipole moment. At late times, there are well-formed skyrmions of positive (red) and negative (blue) charge, and various metastable spin configurations. A full-sized version of this figure is available in Dahlbom et al..","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"EditURL = \"../../../../examples/spinw_tutorials/SW02_AFM_Heisenberg_chain.jl\"","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html#SW02-AFM-Heisenberg-chain","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"","category":"section"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"This is a Sunny port of SpinW Tutorial 2, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the antiferromagnetic Heisenberg nearest-neighbor spin chain.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Define the chemical cell for a 1D chain following the previous tutorial.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(3, 8, 8, 90, 90, 90)\ncryst = Crystal(latvecs, [[0, 0, 0]])\nview_crystal(cryst; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Unlike in the previous tutorial, here the magnetic cell should include 2×1×1 chemical cells to support antiferromagnetic (Néel) order along the chain.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(2, 1, 1))","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Set a nearest neighbor interaction of J = +1 meV along the chain, and find the energy-minimizing Néel order. As before, a global rotation in spin-space is arbitrary.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"J = 1\nset_exchange!(sys, J, Bond(1, 1, [1, 0, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Perform a SpinWaveTheory calculation for a path between 000 and 100 in RLU.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 401)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"This system includes two bands that are fully degenerate in their dispersion.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"isapprox(res.disp[1, :], res.disp[2, :])","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"Plot the intensities summed over the two degenerate bands using the Makie lines function.","category":"page"},{"location":"examples/spinw/SW02_AFM_Heisenberg_chain.html","page":"SW02 - AFM Heisenberg chain","title":"SW02 - AFM Heisenberg chain","text":"xs = [q[1] for q in path.qs]\nys = log10.(res.data[1, :] + res.data[2, :])\nlines(xs, ys; axis=(; xlabel=\"[H, 0, 0]\", ylabel=\"Log intensity (dimensionless)\"))","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"EditURL = \"../../../../examples/spinw_tutorials/SW11_La2CuO4.jl\"","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html#SW11-LaCuO","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"","category":"section"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"This is a Sunny port of SpinW Tutorial 11, originally authored by Sandor Toth. It calculates the spin wave spectrum of La₂CuO₄.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Load packages","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Build a square lattice for the the Cu²⁺ atoms. The lattice constant 1 Å is selected arbitrarily.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(1, 1, 10, 90, 90, 90)\npositions = [[0, 0, 0]]\ntypes = [\"Cu\"]\ncryst = Crystal(latvecs, positions; types)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Build a spin system using the exchange parameters from R. Coldea, Phys. Rev. Lett. 86, 5377 (2001).","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"sys = System(cryst, [1 => Moment(s=1/2, g=2)], :dipole; dims=(2, 2, 1))\nJ = 138.3\nJp = 2\nJpp = 2\nJc = 38\nset_exchange!(sys, J-Jc/2, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, Jp-Jc/4, Bond(1, 1, [1, 1, 0]))\nset_exchange!(sys, Jpp, Bond(1, 1, [2, 0, 0]))","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Energy minimization yields the expected Néel order","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Plot the spin wave spectrum for a path through 𝐪-space. Apply a manual \"quantum correction\" that adjusts energy scale by the factor 1.18.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"qs = [[3/4,1/4,0], [1/2, 1/2, 0], [1/2, 0, 0], [3/4, 1/4, 0], [1,0,0], [1/2 0 0]]\nlabels = [\"P\", \"M\", \"X\", \"P\", \"Γ\", \"X\"]\npath = q_space_path(cryst, qs, 400; labels)\nenergies = range(0, 320, 400)\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities(swt, path; energies, kernel=gaussian(fwhm=35))\nres.energies .*= 1.18\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"Plot instantaneous itensities, integrated over ω.","category":"page"},{"location":"examples/spinw/SW11_La2CuO4.html","page":"SW11 - La₂CuO₄","title":"SW11 - La₂CuO₄","text":"res = intensities_static(swt, path)\nplot_intensities(res; colorrange=(0,20), units)","category":"page"},{"location":"library.html#Library-API","page":"Library API","title":"Library API","text":"","category":"section"},{"location":"library.html","page":"Library API","title":"Library API","text":"This page describes the public types and functions exported by Sunny. This documentation can be also be accessed using the Julia help system (enter ? at the Julia command prompt).","category":"page"},{"location":"library.html","page":"Library API","title":"Library API","text":"","category":"page"},{"location":"library.html","page":"Library API","title":"Library API","text":"Modules = [Sunny]\nPrivate = false","category":"page"},{"location":"library.html#Sunny.Site","page":"Library API","title":"Sunny.Site","text":"(cell1, cell2, cell3, i) :: Site\n\nFour indices identifying a single site in a System. The first three indices select the unit cell and the last index selects the sublattice, i.e., the ith atom within the unit cell.\n\nThis object can be used to index dipoles and coherents fields of a System. A Site is also required to specify inhomogeneous interactions via functions such as set_field_at! or set_exchange_at!.\n\nNote that the definition of a cell may change when a system is reshaped. In this case, it is convenient to construct the Site using position_to_site, which always takes a position in fractional coordinates of the original lattice vectors.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.BinningParameters","page":"Library API","title":"Sunny.BinningParameters","text":"BinningParameters(binstart,binend,binwidth;covectors = I(4))\nBinningParameters(binstart,binend;numbins,covectors = I(4))\n\nDescribes a 4D parallelepided histogram in a format compatible with experimental Inelasitic Neutron Scattering data. See generate_mantid_script_from_binning_parameters to convert BinningParameters to a format understandable by the Mantid software, or load_nxs to load BinningParameters from a Mantid .nxs file.\n\nThe coordinates of the histogram axes are specified by multiplication of (q,ω) with each row of the covectors matrix, with q given in [R.L.U.]. Since the default covectors matrix is the identity matrix, the default axes are (qx,qy,qz,ω) in absolute units.\n\nThe convention for the binning scheme is that:\n\nThe left edge of the first bin starts at binstart\nThe bin width is binwidth\nThe last bin contains binend\nThere are no \"partial bins;\" the last bin may contain values greater than binend.\n\nA value can be binned by computing its bin index:\n\ncoords = covectors * value\nbin_ix = 1 .+ floor.(Int64,(coords .- binstart) ./ binwidth)\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.Bond","page":"Library API","title":"Sunny.Bond","text":"Bond(i, j, n)\n\nRepresents a bond between atom indices i and j. n is a vector of three integers specifying unit cell displacement in terms of lattice vectors.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.Crystal","page":"Library API","title":"Sunny.Crystal","text":"An object describing a crystallographic unit cell and its space group symmetry. Constructors are as follows:\n\nCrystal(filename; override_symmetry=false, symprec=nothing)\n\nReads the crystal from a .cif file located at the path filename. If override_symmetry=true, the spacegroup will be inferred based on atom positions and the returned unit cell may be reduced in size. For an mCIF file, the return value is the magnetic supercell, unless override_symmetry=true. If a precision for spacegroup symmetries cannot be inferred from the CIF file, it must be specified with symprec. The latvecs field of the returned Crystal will be in units of angstrom.\n\nCrystal(latvecs, positions; types=nothing, symprec=1e-5)\n\nConstructs a crystal from the complete list of atom positions positions, with coordinates (between 0 and 1) in units of lattice vectors latvecs. Spacegroup symmetry information is automatically inferred. The optional parameter types is a list of strings, one for each atom, and can be used to break symmetry-equivalence between atoms.\n\nCrystal(latvecs, positions, spacegroup_number; types=nothing, setting=nothing, symprec=1e-5)\n\nBuilds a crystal by applying symmetry operators for a given international spacegroup number. For certain spacegroups, there are multiple possible unit cell settings; in this case, a warning message will be printed, and a list of crystals will be returned, one for every possible setting. Alternatively, the optional setting string will disambiguate between unit cell conventions.\n\nCurrently, crystals built using only the spacegroup number will be missing some symmetry information. It is generally preferred to build a crystal from a .cif file or from the full specification of the unit cell.\n\nExamples\n\n# Read a Crystal from a .cif file\nCrystal(\"filename.cif\")\n\n# Build a BCC crystal in the conventional cubic unit cell by specifying both\n# atoms. The spacegroup 229 is inferred.\nlatvecs = lattice_vectors(1, 1, 1, 90, 90, 90)\npositions = [[0, 0, 0], [1/2, 1/2, 1/2]]\nCrystal(latvecs, positions)\n\n# Build a CsCl crystal (two simple cubic sublattices). Because of the distinct\n# atom types, the spacegroup number 221 is now inferred.\ntypes = [\"Na\", \"Cl\"]\ncryst = Crystal(latvecs, positions; types)\n\n# Build a diamond cubic crystal from its spacegroup number 227 and a single\n# atom position. This spacegroup has two possible settings (\"1\" or \"2\"), which\n# determine an overall unit cell translation.\npositions = [[1/4, 1/4, 1/4]]\ncryst = Crystal(latvecs, positions, 227; setting=\"1\")\n\nSee also lattice_vectors.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.FormFactor-Tuple{String}","page":"Library API","title":"Sunny.FormFactor","text":"FormFactor(ion::String; g_lande=2)\n\nThe magnetic form factor for a given magnetic ion and charge state. When passed to intensities, it rescales structure factor intensities based on the magnitude of the scattering vector, 𝐪.\n\nThe parameter ion must be one of the following strings:\n\nAm2, Am3, Am4, Am5, Am6, Am7, Au1, Au2, Au3, Au4, Au5, Ce2, Co0, Co1, Co2, Co3,\nCo4, Cr0, Cr1, Cr2, Cr3, Cr4, Cu0, Cu1, Cu2, Cu3, Cu4, Dy2, Dy3, Er2, Er3, Eu2,\nEu3, Fe0, Fe1, Fe2, Fe3, Fe4, Gd2, Gd3, Hf2, Hf3, Ho2, Ho3, Ir0a, Ir0b, Ir0c,\nIr1a, Ir1b, Ir2, Ir3, Ir4, Ir5, Ir6, Mn0, Mn1, Mn2, Mn3, Mn4, Mn5, Mo0, Mo1, Nb0,\nNb1, Nd2, Nd3, Ni0, Ni1, Ni2, Ni3, Ni4, Np3, Np4, Np5, Np6, Os0a, Os0b, Os0c,\nOs1a, Os1b, Os2, Os3, Os4, Os5, Os6, Os7, Pd0, Pd1, Pr3, Pt1, Pt2, Pt3, Pt4,\nPt5, Pt6, Pu3, Pu4, Pu5, Pu6, Re0a, Re0b, Re0c, Re1a, Re1b, Re2, Re3, Re4, Re5,\nRe6, Rh0, Rh1, Ru0, Ru1, Sc0, Sc1, Sc2, Sm2, Sm3, Ta2, Ta3, Ta4, Tb2, Tb3, Tc0,\nTc1, Ti0, Ti1, Ti2, Ti3, Tm2, Tm3, U3, U4, U5, V0, V1, V2, V3, V4, W0a, W0b,\nW0c, W1a, W1b, W2c, W3, W4, W5, Y0, Yb2, Yb3, Zr0, Zr1\n\nThe trailing number denotes ionization state. For example, \"Fe0\" denotes a neutral iron atom, while \"Fe2\" denotes Fe²⁺. If multiple electronic configurations are possible, they will be distinguished by a trailing letter (a, b, ...). Omitting this letter will print an informative error,\n\nFormFactor(\"Ir0\")\n\nERROR: Disambiguate form factor according to electronic configuration:\n \"Ir0a\" -- 6s⁰5d⁹\n \"Ir0b\" -- 6s¹5d⁸\n \"Ir0c\" -- 6s²5d⁷\n\nIn the dipolar approximation (small 𝐪) the form factor is\n\nF(s) = j_0(s) + (2-g)g j_2(s),\n\ninvolving s = 𝐪4π and the Landé g-factor. The j_l(s) are radial averages of the lth spherical Bessel function of the magnetic dipole. More details are provided in Ref. [1].\n\nThe standard approximation tables involve expansion in Gaussians,\n\nj_0(s) = A e^-as^2 + B e^-bs^2 + C e^-cs^2 + D e^-ds^2 + E\n\nand\n\nj_2(s) = (A e^-as^2 + B e^-bs^2 + C e^-cs^2 + D e^-ds^2 + E) s^2\n\nFor 3d, 4d, rare earth, and actinide ions, Sunny uses the revised tables of P. J. Brown, as documented in the McPhase package [2]. For 5d ions, Sunny uses the tables of Kobayashi, Nagao, Ito [3].\n\nTwo special, 𝐪-independent form factor values are available: one(FormFactor) and zero(FormFactor). The first idealizes the magnetic ion as a perfect point particle, while the second zeros all contributions from the magnetic ion.\n\nReferences:\n\nP. J. Brown, The Neutron Data Booklet, 2nd ed., Sec. 2.5 Magnetic Form Factors (2003)\nCoefficient tables in McPhase documentation\nK. Kobayashi, T. Nagao, M. Ito, Acta Cryst. A, 67 pp 473–480 (2011)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ImplicitMidpoint","page":"Library API","title":"Sunny.ImplicitMidpoint","text":"ImplicitMidpoint(dt::Float64; atol=1e-12) where N\n\nThe implicit midpoint method for integrating the Landau-Lifshitz spin dynamics or its generalization to SU(N) coherent states [1]. One call to the step! function will advance a System by dt units of time. This integration scheme is exactly symplectic and eliminates energy drift over arbitrarily long simulation trajectories.\n\nReferences:\n\nH. Zhang and C. D. Batista, Phys. Rev. B 104, 104409 (2021).\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.Langevin","page":"Library API","title":"Sunny.Langevin","text":"Langevin(dt::Float64; damping::Float64, kT::Float64)\n\nAn integrator for Langevin spin dynamics using the explicit Heun method. The damping parameter controls the coupling to an implicit thermal bath. One call to the step! function will advance a System by dt units of time. Can be used to sample from the Boltzmann distribution at temperature kT. An alternative approach to sampling states from thermal equilibrium is LocalSampler, which proposes local Monte Carlo moves. For example, use LocalSampler instead of Langevin to sample Ising-like spins.\n\nSetting damping = 0 disables coupling to the thermal bath, yielding an energy-conserving spin dynamics. The Langevin integrator uses an explicit numerical integrator which cannot prevent energy drift. Alternatively, the ImplicitMidpoint method can be used, which is more expensive but prevents energy drift through exact conservation of the symplectic 2-form.\n\nIf the System has mode = :dipole, then the dynamics is the stochastic Landau-Lifshitz equation,\n\n d𝐬dt = -𝐬 (ξ - 𝐁 + λ 𝐬 𝐁)\n\nwhere 𝐁 = -dEd𝐬 is the effective field felt by the expected spin dipole 𝐬. The components of ξ are Gaussian white noise, with magnitude (2 k_B T λ) set by a fluctuation-dissipation theorem. The parameter damping sets the phenomenological coupling λ to the thermal bath. \n\nIf the System has mode = :SUN, then this dynamics generalizes [1] to a stochastic nonlinear Schrödinger equation for SU(N) coherent states 𝐙,\n\n d𝐙dt = -i P ζ + (1 - i λ) ℋ 𝐙\n\nHere, P projects onto the space orthogonal to 𝐙, and ζ denotes complex Gaussian white noise with magnitude (2 k_B T λ). The local-Hamiltonian ℋ embeds the energy gradient into the 𝔰𝔲(N) Lie algebra, and generates evolution of spin dipoles, quadrupoles, etc. The parameter damping here sets λ, which is analogous to λ above.\n\nWhen applied to SU(2) coherent states, the generalized spin dynamics reduces exactly to the stochastic Landau-Lifshitz equation. The mapping is as follows. Normalized coherent states 𝐙 map to dipole expectation values 𝐬 = 𝐙^ S 𝐙, where spin operators S are a spin-𝐬 representation of SU(2). The local effective Hamiltonian ℋ = -𝐁 S generates rotation of the dipole in analogy to the vector cross product S 𝐁. The coupling to the thermal bath maps as λ = 𝐬 λ. Note, therefore, that the scaling of the damping parameter varies subtly between :dipole and :SUN modes.\n\nReferences:\n\nD. Dahlbom et al., Phys. Rev. B 106, 235154 (2022).\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.LocalSampler","page":"Library API","title":"Sunny.LocalSampler","text":"LocalSampler(; kT, nsweeps=1.0, propose=propose_uniform)\n\nMonte Carlo simulation involving Metropolis updates to individual spins. One call to the step! function will perform nsweeps of MCMC sampling for a provided System. The default value of 1.0 means that step! performs, on average, one trial update per spin.\n\nAssuming ergodicity, the LocalSampler will sample from thermal equilibrium for the target temperature kT. \n\nThe trial spin updates are sampled using the propose function. Options include propose_uniform, propose_flip, and propose_delta. Multiple proposals can be mixed with the macro @mix_proposals.\n\nThe returned object stores fields ΔE and Δs, which represent the cumulative change to the net energy and dipole, respectively.\n\n!!! warning \"Efficiency considerations\n\nA [`Langevin`](@ref) sampler is frequently much more efficient than a\n`LocalSampler` for simulating Heisenberg-like spins that vary continuously. A\n`LocalSampler` is appropriate in the special case that the spin states are\neffectively discrete. E.g., [`propose_flip`](@ref) is very helpful simulating\nIsing-like spins that arise due to a strong easy-axis anisotropy.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.Moment","page":"Library API","title":"Sunny.Moment","text":"Moment(; s, g)\n\nCharacterizes a effective spin magnetic moment on an atom. Quantum spin-s is a multiple of 1/2 in units of ħ. The g-factor or tensor defines the magnetic_moment μ = - g 𝐒 in units of the Bohr magneton.\n\nExample\n\nMoment(s=3/2, g=2)\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.SampledCorrelations-Tuple{System}","page":"Library API","title":"Sunny.SampledCorrelations","text":"SampledCorrelations(sys::System; measure, energies, dt)\n\nAn object to accumulate samples of dynamical pair correlations. The measure argument specifies a pair correlation type, e.g. ssf_perp. The energies must be evenly-spaced and starting from 0, e.g. energies = range(0, 3, 100). Select the integration time-step dt according to accuracy and speed considerations. suggest_timestep can help in selecting an appropriate value.\n\nDynamical correlations will be accumulated through calls to add_sample!, which expects a spin configuration in thermal equilibrium. A classical spin dynamics trajectory will be simulated of sufficient length to achieve the target energy resolution. The resulting data can can then be extracted as pair-correlation intensities with appropriate classical-to-quantum correction factors. See also intensities_static, which integrates over energy.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.SampledCorrelationsStatic","page":"Library API","title":"Sunny.SampledCorrelationsStatic","text":"SampledCorrelationsStatic(sys::System; measure)\n\nAn object to accumulate samples of static pair correlations. It is similar to SampledCorrelations, but no time-integration will be performed on calls to add_sample!. The resulting object can be used with intensities_static to calculate statistics from the classical Boltzmann distribution. Dynamical intensities data, however, will be unavailable. Similarly, classical-to-quantum corrections that rely on the excitation spectrum cannot be performed.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.SpinWaveTheory","page":"Library API","title":"Sunny.SpinWaveTheory","text":"SpinWaveTheory(sys::System; measure, regularization=1e-8)\n\nConstructs an object to perform linear spin wave theory. The system must be in an energy minimizing configuration. Enables calculation of dispersion bands. If pair correlations are specified with correspec, one can also calculate intensities_bands and broadened intensities.\n\nThe spins in system must be energy-minimized, otherwise the Cholesky step of the Bogoliubov diagonalization procedure will fail. The parameter regularization adds a small positive shift to the diagonal of the dynamical matrix to avoid numerical issues with quasi-particle modes of vanishing energy. Physically, this shift can be interpreted as application of an inhomogeneous field aligned with the magnetic ordering.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.SpinWaveTheoryKPM","page":"Library API","title":"Sunny.SpinWaveTheoryKPM","text":"SpinWaveTheoryKPM(sys::System; measure, regularization=1e-8, tol)\n\nA variant of SpinWaveTheory that uses the kernel polynomial method (KPM) to perform intensities calculations [1]. Instead of explicitly diagonalizing the dynamical matrix, KPM approximates intensities using polynomial expansion truncated at order M. The reduces the computational cost from 𝒪(N^3) to 𝒪(N M), which is favorable for large system sizes N.\n\nThe polynomial order M will be determined from the line broadening kernel and the specified error tolerance tol. Specifically, for each wavevector, M scales like the spectral bandwidth of excitations, divided by the energy resolution of the broadening kernel, times the negative logarithm of tol.\n\nThe error tolerance tol should be tuned empirically for each calculation. Reasonable starting points are 1e-1 (more speed) or 1e-2 (more accuracy).\n\nwarning: Missing intensity at small quasi-particle energy\nThe KPM calculation may mask intensities at small energies ω. In particular, such artifacts may arise near the Goldstone modes of an ordered state with continuous symmetry.\n\nReferences:\n\nH. Lane et al., Kernel Polynomial Method for Linear Spin Wave Theory (2023) [arXiv:2312.08349v3].\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.SpinWaveTheorySpiral","page":"Library API","title":"Sunny.SpinWaveTheorySpiral","text":"SpinWaveTheorySpiral(sys::System; k, axis, measure, regularization=1e-8)\n\nAnalogous to SpinWaveTheory, 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 minimize_spiral_energy!. In contrast, axis will typically be determined from symmetry considerations.\n\nThe resulting object can be used to calculate the spin wave dispersion, or the structure factor via intensities_bands and intensities.\n\nThe algorithm for this calculation was developed in Toth and Lake, J. Phys.: Condens. Matter 27, 166002 (2015) and implemented in the SpinW code.\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.System-Tuple{Crystal, Vector{Pair{Int64, Moment}}, Symbol}","page":"Library API","title":"Sunny.System","text":"System(crystal::Crystal, moments, mode; dims=(1, 1, 1), seed=nothing)\n\nA spin system is constructed from the Crystal unit cell, a specification of the spin moments symmetry-distinct sites, and a calculation mode. Interactions can be added to the system using, e.g., set_exchange!. The default supercell dimensions are 1×1×1 chemical cells, but this can be changed with dims.\n\nSpin moments comprise a list of pairs, [i1 => Moment(...), i2 => ...], where i1, i2, ... are a complete set of symmetry-distinct atoms. Each Moment contains spin and g-factor information.\n\nThe two primary options for mode are :SUN and :dipole. In the former, each spin-s degree of freedom is described as an SU(N) coherent state, i.e. a quantum superposition of N = 2s + 1 levels. This formalism can be useful to capture multipolar spin fluctuations or local entanglement effects. \n\nMode :dipole projects the SU(N) dynamics onto the restricted space of pure dipoles. In practice this means that Sunny will simulate Landau-Lifshitz dynamics, but single-ion anisotropy and biquadratic exchange interactions will be renormalized to improve accuracy. To disable this renormalization, use the mode :dipole_large_s which applies the s classical limit. For details, see the documentation page: Interaction Renormalization.\n\nAn integer seed for the random number generator can optionally be specified to enable reproducible calculations.\n\nAll spins are initially polarized in the global z-direction.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.Units","page":"Library API","title":"Sunny.Units","text":"Units(energy, length)\n\nPhysical constants in units of reference energy and length scales. Possible lengths are [:angstrom, :nm]. For atomic scale modeling, it is preferable to work in units of length=:angstrom, which follows the CIF file standard. Possible energy units are [:meV, :K, :THz, :inverse_cm, :T]. Kelvin is converted to energy via the Boltzmann constant k_B. Similarly, hertz is converted via the Planck constant h, inverse cm via the speed of light c, and tesla (field strength) via the Bohr magneton μ_B. For a given Units system, one can access any of the length and energy scale symbols listed above.\n\nExamples\n\n# Unit system with [energy] = meV and [length] = Å\nunits = Units(:meV, :angstrom)\n\n# Use the Boltzmann constant kB to convert 1 kelvin into meV\n@assert units.K ≈ 0.0861733326\n\n# Use the Planck constant h to convert 1 THz into meV\n@assert units.THz ≈ 4.135667696\n\n# Use the constant h c to convert 1 cm⁻¹ into meV\n@assert units.inverse_cm ≈ 0.1239841984\n\n# Use the Bohr magneton μB to convert 1 tesla into meV\n@assert units.T ≈ 0.05788381806\n\n# The physical constant μ0 μB² in units of ų meV.\n@assert u.vacuum_permeability ≈ 0.6745817653\n\n\n\n\n\n","category":"type"},{"location":"library.html#Sunny.add_sample!-Tuple{SampledCorrelations, System}","page":"Library API","title":"Sunny.add_sample!","text":"add_sample!(sc::SampledCorrelations, sys::System)\nadd_sample!(sc::SampledCorrelationsStatic, sys::System)\n\nMeasure pair correlation data for the spin configuration in sys, and accumulate these statistics into sc. For a dynamical SampledCorrelations, this involves time-integration of the provided spin trajectory, recording correlations in both space and time. Conversely, SampledCorrelationsStatic, will record only spatial correlations for the single spin configuration that is provided.\n\nTime-integration will update the spin configuration of sys in-place. To avoid this mutation, consider calling clone_system prior to add_sample!.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.clone_correlations-Tuple{SampledCorrelations}","page":"Library API","title":"Sunny.clone_correlations","text":"clone_correlations(sc::SampledCorrelations)\n\nCreate a copy of a SampledCorrelations.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.clone_system-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.clone_system","text":"clone_system(sys::System)\n\nCreates a full clone of the system, such that mutable updates to one copy will not affect the other, and thread safety is guaranteed.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.dispersion-Tuple{SpinWaveTheory, Any}","page":"Library API","title":"Sunny.dispersion","text":"dispersion(swt::SpinWaveTheory, qpts)\n\nGiven a list of wavevectors qpts in reciprocal lattice units (RLU), returns excitation energies for each band. The return value ret is 2D array, and should be indexed as ret[band_index, q_index].\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.dmvec-Tuple{Any}","page":"Library API","title":"Sunny.dmvec","text":"dmvec(D)\n\nAntisymmetric matrix representation of the Dzyaloshinskii-Moriya pseudo-vector,\n\n [ 0 D[3] -D[2]\n -D[3] 0 D[1]\n D[2] -D[1] 0 ]\n\nBy construction, Si'*dmvec(D)*Sj ≈ D⋅(Si×Sj) for any dipoles Si and Sj. This helper function is intended for use with set_exchange!.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.domain_average-Tuple{Any, Any, Any}","page":"Library API","title":"Sunny.domain_average","text":"domain_average(f, cryst, qpts; rotations, weights)\n\nCalculate an average intensity for the reciprocal-space points qpts under a discrete set of rotations. Rotations, in global coordinates, may be given either as an axis-angle pair or as a 3×3 rotation matrix. Each rotation is weighted according to the elements in weights. The function f should accept a list of rotated q-points and return an intensities calculation.\n\nExample\n\n# 0, 120, and 240 degree rotations about the global z-axis\nrotations = [([0,0,1], n*(2π/3)) for n in 0:2]\nweights = [1, 1, 1]\nres = domain_average(cryst, path; rotations, weights) do path_rotated\n intensities(swt, path_rotated; energies, kernel)\nend\nplot_intensities(res)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.eachsite-Tuple{System}","page":"Library API","title":"Sunny.eachsite","text":"eachsite(sys::System)\n\nAn iterator over all Sites in the system. \n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.enable_dipole_dipole!-Union{Tuple{System{N}}, Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.enable_dipole_dipole!","text":"enable_dipole_dipole!(sys::System, μ0_μB²)\n\nEnables long-range interactions between magnetic dipole moments,\n\n -(μ_04π) _ij 3 (μ_i𝐫_ij)(μ_j𝐫_ij) - μ_iμ_j r_ij^3\n\nwhere the sum is over all pairs of spins (singly counted), including periodic images, regularized using the Ewald summation convention. The magnetic_moment is defined as μ = -g μ_B 𝐒, where 𝐒 is the spin angular momentum dipole. The parameter μ0_μB² specifies the physical constant μ_0 μ_B^2, which has dimensions of length³-energy. Obtain this constant for a given system of Units via its vacuum_permeability property.\n\nExample\n\nunits = Units(:meV, :angstrom)\nenable_dipole_dipole!(sys, units.vacuum_permeability)\n\nSee also modify_exchange_with_truncated_dipole_dipole!.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.energy-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.energy","text":"energy(sys::System)\n\nThe total system energy. See also energy_per_site.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.energy_per_site-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.energy_per_site","text":"energy_per_site(sys::System)\n\nThe total system energy divided by the number of sites.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.excitations!-Tuple{Any, Any, SpinWaveTheory, Any}","page":"Library API","title":"Sunny.excitations!","text":"excitations!(T, tmp, swt::SpinWaveTheory, q)\n\nGiven a wavevector q, solves for the matrix T representing quasi-particle excitations, and returns a list of quasi-particle energies. Both T and tmp must be supplied as 2L2L complex matrices, where L is the number of bands for a single 𝐪 value.\n\nThe columns of T are understood to be contracted with the Holstein-Primakoff bosons 𝐛_𝐪 𝐛_-𝐪^. The first L columns provide the eigenvectors of the quadratic Hamiltonian for the wavevector 𝐪. The next L columns 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 -𝐪.\n\nexcitations!(T, tmp, swt::SpinWaveTheorySpiral, q; branch)\n\nCalculations on a SpinWaveTheorySpiral 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 spins in the magnetic cell. This yields a total of 3L excitations for a given momentum transfer 𝐪.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.excitations-Tuple{SpinWaveTheory, Any}","page":"Library API","title":"Sunny.excitations","text":"excitations(swt::SpinWaveTheory, q)\nexcitations(swt::SpinWaveTheorySpiral, q; branch)\n\nReturns a pair (energies, T) providing the excitation energies and eigenvectors. Prefer excitations! for performance, which avoids matrix allocations. See the documentation of excitations! for more details.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.gaussian-Tuple{}","page":"Library API","title":"Sunny.gaussian","text":"gaussian(; {fwhm, σ})\n\nReturns the function exp(-x^2/2σ^2) / √(2π*σ^2). Either fwhm or σ must be specified, where fwhm = (2.355...) * σ is the full width at half maximum.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.generate_mantid_script_from_binning_parameters-Tuple{Any}","page":"Library API","title":"Sunny.generate_mantid_script_from_binning_parameters","text":"generate_mantid_script_from_binning_parameters(params::BinningParameters)\n\nGenerate a Mantid script which bins data according to the given BinningParameters.\n\nwarning: Units\nTake care to ensure the units are correct (R.L.U. or absolute). You may want to call Sunny.bin_rlu_as_absolute_units! or Sunny.bin_absolute_units_as_rlu! first.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.global_position-Tuple{System, Any}","page":"Library API","title":"Sunny.global_position","text":"global_position(sys::System, site::Site)\n\nPosition of a Site in global coordinates.\n\nTo precompute a full list of positions, one can use eachsite as below:\n\npos = [global_position(sys, site) for site in eachsite(sys)]\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.intensities-Tuple{Sunny.AbstractSpinWaveTheory, Any}","page":"Library API","title":"Sunny.intensities","text":"intensities(swt::SpinWaveTheory, qpts; energies, kernel, kT=0)\nintensities(sc::SampledCorrelations, qpts; energies, kernel=nothing, kT)\n\nCalculates dynamical pair correlation intensities for a set of 𝐪-points in reciprocal space.\n\nLinear spin wave theory calculations are performed with an instance of SpinWaveTheory. The alternative SpinWaveTheorySpiral allows to study generalized spiral orders with a single, incommensurate-𝐤 ordering wavevector. Another alternative SpinWaveTheoryKPM is favorable for calculations on large magnetic cells, and allows to study systems with disorder. An optional nonzero temperature kT will scale intensities by the quantum thermal occupation factor 1 + n_B(ω) where n_B(ω) = 1(e^βω-1) is the Bose function.\n\nIntensities can also be calculated for SampledCorrelations associated with classical spin dynamics. In this case, thermal broadening will already be present, and the line-broadening kernel becomes optional. Conversely, the parameter kT becomes required. If positive, it will introduce an intensity correction factor βω (1 + n_B(ω)) that undoes the occupation factor for the classical Boltzmann distribution and applies the quantum thermal occupation factor. The special choice kT = nothing will suppress the classical-to-quantum correction factor, and yield statistics consistent with the classical Boltzmann distribution.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.intensities_bands-Tuple{SpinWaveTheory, Any}","page":"Library API","title":"Sunny.intensities_bands","text":"intensities_bands(swt::SpinWaveTheory, qpts; kT=0)\n\nCalculate spin wave excitation bands for a set of q-points in reciprocal space. This calculation is analogous to intensities, but does not perform line broadening of the bands.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.intensities_static-Tuple{Sunny.AbstractSpinWaveTheory, Any}","page":"Library API","title":"Sunny.intensities_static","text":"intensities_static(swt::SpinWaveTheory, qpts; bounds=(-Inf, Inf), kernel=nothing, kT=0)\nintensities_static(sc::SampledCorrelations, qpts; bounds=(-Inf, Inf), kT)\nintensities_static(sc::SampledCorrelationsStatic, qpts)\n\nLike intensities, but integrates the dynamical correlations mathcalS(𝐪 ω) over a range of energies ω. By default, the integration bounds are (- ), yielding the instantaneous (equal-time) correlations.\n\nIn SpinWaveTheory, the integral will be realized as a sum over discrete bands. Alternative calculation methods are SpinWaveTheorySpiral and SpinWaveTheoryKPM.\n\nClassical dynamics data in SampledCorrelations can also be used to calculate static intensities. In this case, the domain of integration will be a finite grid of available energies. Here, the parameter kT will be used to account for the quantum thermal occupation of excitations, as documented in intensities.\n\nStatic intensities calculated from SampledCorrelationsStatic are dynamics-independent. Instead, instantaneous correlations sampled from the classical Boltzmann distribution will be reported.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.lattice_params-Tuple{Any}","page":"Library API","title":"Sunny.lattice_params","text":"lattice_params(latvecs)\n\nCompute the lattice parameters (a b c α β γ) for the three lattice vectors provided as columns of latvecs. The inverse mapping is lattice_vectors.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.lattice_vectors-NTuple{6, Any}","page":"Library API","title":"Sunny.lattice_vectors","text":"lattice_vectors(a, b, c, α, β, γ)\n\nReturn the lattice vectors, as columns of the 33 output matrix, that define the shape of a crystallographic cell in global Cartesian coordinates. Conversely, one can view the output matrix as defining the global Cartesian coordinate system with respect to the lattice system.\n\nThe lattice constants (a b c) have units of length, and the angles (α β γ) are in degrees. The inverse mapping is lattice_params.\n\nExample\n\nlatvecs = lattice_vectors(1, 1, 2, 90, 90, 120)\na1, a2, a3 = eachcol(latvecs)\n@assert a1 ≈ [1, 0, 0] # a1 always aligned with global x\n@assert a2 ≈ [-1/2, √3/2, 0] # a2 always in global (x,y) plane\n@assert a3 ≈ [0, 0, 2] # a3 may generally be a combination of (x,y,z)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.load_nxs-Tuple{Any}","page":"Library API","title":"Sunny.load_nxs","text":"params, signal = load_nxs(filename; field=\"signal\")\n\nGiven the name of a Mantid-exported MDHistoWorkspace file, load the BinningParameters and the signal from that file.\n\nTo load another field instead of the signal, specify e.g. field=\"errors_squared\". Typical fields include errors_squared, mask, num_events, and signal.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.lorentzian-Tuple{}","page":"Library API","title":"Sunny.lorentzian","text":"lorentzian(; fwhm)\n\nReturns the function (Γ/2) / (π*(x^2+(Γ/2)^2)) where Γ = fwhm is the full width at half maximum.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.magnetic_moment-Tuple{System, Any}","page":"Library API","title":"Sunny.magnetic_moment","text":"magnetic_moment(sys::System, site::Site)\n\nReturns - g 𝐒, the local magnetic moment in units of the Bohr magneton. The spin dipole 𝐒 and g-tensor may both be Site dependent.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.merge_correlations-Tuple{Vector{SampledCorrelations}}","page":"Library API","title":"Sunny.merge_correlations","text":"merge_correlations(scs::Vector{SampledCorrelations)\n\nAccumulate a list of SampledCorrelations into a single, summary SampledCorrelations. Useful for reducing the results of parallel computations.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.minimize_energy!-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.minimize_energy!","text":"minimize_energy!(sys::System{N}; maxiters=1000, method=Optim.ConjugateGradient(),\n g_tol=1e-10, kwargs...) where N\n\nOptimizes the spin configuration in sys to minimize energy. A total of maxiters iterations will be attempted. Convergence is reached when the root mean squared energy gradient goes below g_tol. The remaining kwargs will be forwarded to the optimize method of the Optim.jl package.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.minimize_spiral_energy!-Tuple{Any, Any}","page":"Library API","title":"Sunny.minimize_spiral_energy!","text":"minimize_spiral_energy!(sys, axis; maxiters=10_000, k_guess=randn(sys.rng, 3))\n\nFinds a generalized spiral order that minimizes the spiral_energy. This involves optimization of the spin configuration in sys, and the propagation wavevector 𝐤, which will be returned in reciprocal lattice units (RLU). The axis vector normal to the polarization plane should be provided in global Cartesian coordinates, and will usually be determined by symmetry configurations. The initial k_guess will be random, unless otherwise provided.\n\nSee also suggest_magnetic_supercell to find a system shape that is approximately commensurate with the returned propagation wavevector 𝐤.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.modify_exchange_with_truncated_dipole_dipole!-Union{Tuple{N}, Tuple{System{N}, Any}, Tuple{System{N}, Any, Any}} where N","page":"Library API","title":"Sunny.modify_exchange_with_truncated_dipole_dipole!","text":"modify_exchange_with_truncated_dipole_dipole!(sys::System, cutoff, μ0_μB²)\n\nLike enable_dipole_dipole!, the purpose of this function is to introduce long-range dipole-dipole interactions between magnetic moments. Whereas enable_dipole_dipole! employs Ewald summation, this function instead employs real-space pair couplings with truncation at the specified cutoff distance. If the cutoff is relatively small, then this function may be faster than enable_dipole_dipole!.\n\nwarning: Mutation of existing couplings\nThis function will modify existing bilinear couplings between spins by adding dipole-dipole interactions. It must therefore be called after all other pair couplings have been specified. Conversely, any calls to set_exchange!, set_pair_coupling!, etc. will irreversibly delete the dipole-dipole interactions that have been introduced by this function.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.polarize_spins!-Union{Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.polarize_spins!","text":"polarize_spins!(sys::System, dir)\n\nPolarize all spins in the system along the direction dir.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.position_to_site-Tuple{System, Any}","page":"Library API","title":"Sunny.position_to_site","text":"position_to_site(sys::System, r)\n\nConverts a position r to four indices of a Site. The coordinates of r are given in units of the lattice vectors for the original crystal. This function can be useful for working with systems that have been reshaped using reshape_supercell.\n\nExample\n\n# Find the `site` at the center of a unit cell which is displaced by four\n# multiples of the first lattice vector\nsite = position_to_site(sys, [4.5, 0.5, 0.5])\n\n# Print the dipole at this site\nprintln(sys.dipoles[site])\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.powder_average-Tuple{Any, Any, Any, Int64}","page":"Library API","title":"Sunny.powder_average","text":"powder_average(f, cryst, radii, n; seed=0)\n\nCalculate a powder-average over structure factor intensities. The radii, with units of inverse length, define spherical shells in reciprocal space. The Fibonacci lattice yields n points on the sphere, with quasi-uniformity. Sample points on different shells are decorrelated through random rotations. A consistent random number seed will yield reproducible results. The function f should accept a list of q-points and call intensities.\n\nExample\n\nradii = range(0.0, 3.0, 200)\nres = powder_average(cryst, radii, 500) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.primitive_cell_shape-Tuple{Crystal}","page":"Library API","title":"Sunny.primitive_cell_shape","text":"primitive_cell_shape(cryst::Crystal)\n\nReturns the shape of the primitive cell as a 3×3 matrix, in fractional coordinates of the conventional lattice vectors. May be useful for constructing inputs to reshape_supercell.\n\nExamples\n\n# Valid if `cryst` has not been reshaped\n@assert cryst.prim_latvecs ≈ cryst.latvecs * primitive_cell_shape(cryst)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_bond-Tuple{Crystal, Bond}","page":"Library API","title":"Sunny.print_bond","text":"print_bond(cryst::Crystal, bond::Bond; b_ref::Bond)\n\nPrints symmetry information for bond bond. A symmetry-equivalent reference bond b_ref can optionally be provided to fix the meaning of the coefficients A, B, ...\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_site-Tuple{Any, Any}","page":"Library API","title":"Sunny.print_site","text":"print_site(cryst, i; R=I)\n\nPrint symmetry information for the site i, including allowed g-tensor and allowed anisotropy operator. An optional rotation matrix R can be provided to define the reference frame for expression of the anisotropy.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_stevens_expansion-Tuple{AbstractMatrix}","page":"Library API","title":"Sunny.print_stevens_expansion","text":"function print_stevens_expansion(op)\n\nPrints a local Hermitian operator as a linear combination of Stevens operators. The operator op may be a finite-dimensional matrix or an abstract spin polynomial in the large-s limit.\n\nExamples\n\nS = spin_matrices(2)\nprint_stevens_expansion(S[1]^4 + S[2]^4 + S[3]^4)\n# Prints: (1/20)𝒪₄₀ + (1/4)𝒪₄₄ + 102/5\n\nS = spin_matrices(Inf)\nprint_stevens_expansion(S[1]^4 + S[2]^4 + S[3]^4)\n# Prints: (1/20)𝒪₄₀ + (1/4)𝒪₄₄ + (3/5)𝒮⁴\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_suggested_frame-Tuple{Crystal, Int64}","page":"Library API","title":"Sunny.print_suggested_frame","text":"print_suggested_frame(cryst, i)\n\nPrint a suggested reference frame, as a rotation matrix R, that can be used as input to print_site(). The purpose is to simplify the description of allowed anisotropies.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_symmetry_table-Tuple{Crystal, Any}","page":"Library API","title":"Sunny.print_symmetry_table","text":"print_symmetry_table(cryst::Crystal, max_dist)\n\nPrint symmetry information for all equivalence classes of sites and bonds, up to a maximum bond distance of max_dist. Equivalent to calling print_bond(cryst, b) for every bond b in reference_bonds(cryst, max_dist), where Bond(i, i, [0,0,0]) refers to a single site i.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.print_wrapped_intensities-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.print_wrapped_intensities","text":"print_wrapped_intensities(sys::System; nmax=10)\n\nFor Bravais lattices: Prints up to nmax wavevectors according to their instantaneous (static) structure factor intensities, listed in descending order. For non-Bravais lattices: Performs the same analysis for each spin sublattice independently; the output weights are naïvely averaged over sublattices, without incorporating phase shift information. This procedure therefore wraps all wavevectors into the first Brillouin zone. Each wavevector coordinate is given between -12 and 12 in reciprocal lattice units (RLU). The output from this function will typically be used as input to suggest_magnetic_supercell.\n\nBecause this function does not incorporate phase information in its averaging over sublattices, the printed weights are not directly comparable with experiment. For that purpose, use SampledCorrelationsStatic instead.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.propose_delta-Tuple{Any}","page":"Library API","title":"Sunny.propose_delta","text":"propose_delta(magnitude)\n\nGenerate a proposal function that adds a Gaussian perturbation to the existing spin state. In :dipole mode, the procedure is to first introduce a random three-vector perturbation 𝐬 = 𝐬 + 𝐬 ξ and then return the properly normalized spin 𝐬 (𝐬𝐬). Each component of the random vector ξ is Gaussian distributed with a standard deviation of magnitude; the latter is dimensionless and typically smaller than one. \n\nIn :SUN mode, the procedure is analogous, but now involving Gaussian perturbations to each of the N complex components of an SU(N) coherent state.\n\nIn the limit of very large magnitude, this function coincides with propose_uniform.\n\nConsider also Langevin sampling, which is rejection free.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.propose_flip-Union{Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.propose_flip","text":"propose_flip\n\nFunction to propose pure spin flip updates in the context of a LocalSampler. Dipoles are flipped as 𝐬 -𝐬. SU(N) coherent states are flipped using the time-reversal operator.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.propose_uniform","page":"Library API","title":"Sunny.propose_uniform","text":"propose_uniform\n\nFunction to propose a uniformly random spin update in the context of a LocalSampler. In :dipole mode, the result is a random three-vector with appropriate normalization. In :SUN mode, the result is a random SU(N) coherent state with appropriate normalization.\n\nFor low-temperature Monte Carlo simulations, uniform spin proposals can be very inefficient due to a high probability of rejection in the Metropolis accept/reject step. Consider also Langevin sampling, which is rejection free.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.q_space_grid-Tuple{Crystal, Vararg{Any, 4}}","page":"Library API","title":"Sunny.q_space_grid","text":"q_space_grid(cryst::Crystal, axis1, range1, axis2, range2; offset=[0,0,0], orthogonalize=false)\nq_space_grid(cryst::Crystal, axis1, range1, axis2, range2, axis3, range3; orthogonalize=false)\n\nReturns a 2D or 3D grid of q-points with uniform spacing. The volume shape is defined by (axis1, axis2, ...) in reciprocal lattice units (RLU). Elements of (range1, range2, ...) provide coefficients c_i used to define grid positions,\n\n offset + c1 * axis1 + c2 * axis2 + ...\n\nA nonzero offset is allowed only in the 2D case. \n\nThe first range parameter, range1, must be a regularly spaced list of coefficients, e.g., range1 = range(lo1, hi1, n). Subsequent range parameters may be a pair of bounds, without grid spacing information. For example, by selecting range2 = (lo2, hi2), an appropriate step-size will be inferred to provide an approximately uniform sampling density in global Cartesian coordinates.\n\nThe axes may be non-orthogonal. To extend to an orthohombic volume in global Cartesian coordinates, set orthogonalize=true.\n\nFor a 1D grid, use q_space_path instead.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.q_space_path-Tuple{Crystal, Any, Any}","page":"Library API","title":"Sunny.q_space_path","text":"q_space_path(cryst::Crystal, qs, n; labels=nothing)\n\nReturns a 1D path consisting of n wavevectors sampled piecewise-linearly between the qs. Although the qs are provided in reciprocal lattice units (RLU), consecutive samples are spaced uniformly in the global (inverse-length) coordinate system. Optional labels can be associated with each special q-point, and will be used in plotting functions.\n\nSee also q_space_grid.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.randomize_spins!-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.randomize_spins!","text":"randomize_spins!(sys::System)\n\nRandomizes all spins under appropriate the uniform distribution.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.reference_bonds-Tuple{Crystal, Float64}","page":"Library API","title":"Sunny.reference_bonds","text":"reference_bonds(cryst::Crystal, max_dist)\n\nReturns a full list of bonds, one for each symmetry equivalence class, up to distance max_dist. The reference bond b for each equivalence class is selected according to a scoring system that prioritizes simplification of the elements in basis_for_symmetry_allowed_couplings(cryst, b).\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.remove_periodicity!-Union{Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.remove_periodicity!","text":"remove_periodicity!(sys::System, flags)\n\nRemove periodic interactions along each dimension d if flags[d] is true. The system must support inhomogeneous interactions via to_inhomogeneous.\n\nExample\n\n# Remove periodic boundaries along the 1st and 3rd dimensions\nremove_periodicity!(sys::System, (true, false, true))\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.repeat_periodically-Tuple{System, Tuple{Int64, Int64, Int64}}","page":"Library API","title":"Sunny.repeat_periodically","text":"repeat_periodically(sys::System, counts::NTuple{3, Int})\n\nCreates a System identical to sys but repeated a given number of times along each system axis according to the specified counts. This is a special case of the more general reshape_supercell.\n\nSee also repeat_periodically_as_spiral, which rotates the spins between periodic copies.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.repeat_periodically_as_spiral-Tuple{System, Tuple{Int64, Int64, Int64}}","page":"Library API","title":"Sunny.repeat_periodically_as_spiral","text":"repeat_periodically_as_spiral(sys::System, counts::NTuple{3, Int}; k, axis)\n\nRepeats the magnetic cell of System a number of times along each system axis according to the specified counts. Spins in each system image will be rotated according to the propagation wavevector k (in RLU) and the rotation axis (in global Cartesian coordinates). Coincides with repeat_periodically in the special case of k = [0, 0, 0]\n\nSee also minimize_spiral_energy! to find an energy-minimizing wavevector k and spin dipole configuration.\n\nExample\n\nk = minimize_spiral_energy!(sys, axis; k_guess=randn(3))\nrepeat_periodically_as_spiral(sys, counts; k, axis)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.reshape_supercell-Tuple{System, Any}","page":"Library API","title":"Sunny.reshape_supercell","text":"reshape_supercell(sys::System, shape)\n\nMaps an existing System to a new one that has the shape and periodicity of a requested supercell. The columns of the 33 integer matrix shape represent the supercell lattice vectors measured in units of the original crystal lattice vectors. Interactions, spins, and other settings will be inherited from sys.\n\nIn the special case that shape is a diagonal matrix, this function coincides with resize_supercell.\n\nSee also repeat_periodically.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.resize_supercell-Tuple{System, Tuple{Int64, Int64, Int64}}","page":"Library API","title":"Sunny.resize_supercell","text":"resize_supercell(sys::System, dims::NTuple{3, Int})\n\nCreates a System with a given number of conventional unit cells in each lattice vector direction. Interactions, spins, and other settings will be inherited from sys.\n\nEquivalent to:\n\nreshape_supercell(sys, [dims[1] 0 0; 0 dims[2] 0; 0 0 dims[3]])\n\nSee also reshape_supercell and repeat_periodically.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.rotate_operator-Tuple{LinearAlgebra.Hermitian{ComplexF64, Matrix{ComplexF64}}, Any}","page":"Library API","title":"Sunny.rotate_operator","text":"rotate_operator(A, R)\n\nRotates the local quantum operator A according to the 33 rotation matrix R.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_coherent!-Union{Tuple{N}, Tuple{System{N}, Any, Any}} where N","page":"Library API","title":"Sunny.set_coherent!","text":"set_coherent!(sys::System, Z, site::Site)\n\nSet a coherent spin state at a Site using the N complex amplitudes in Z.\n\nFor a single quantum spin-s, these amplitudes will be interpreted in the eigenbasis of S^z. That is, Z[1] represents the amplitude for the basis state fully polarized along the z-direction, and subsequent components represent states with decreasing angular momentum along this axis (m = s s-1 -s).\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_dipole!-Union{Tuple{N}, Tuple{System{N}, Any, Any}} where N","page":"Library API","title":"Sunny.set_dipole!","text":"set_dipole!(sys::System, dir, site::Site)\n\nPolarize the spin at a Site along the direction dir.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_dipoles_from_mcif!-Tuple{System, AbstractString}","page":"Library API","title":"Sunny.set_dipoles_from_mcif!","text":"set_dipoles_from_mcif!(sys::System, filename::AbstractString)\n\nLoad the magnetic supercell according to an mCIF file. System sys must already be resized to the correct supercell dimensions.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_exchange!-Union{Tuple{N}, Tuple{System{N}, Any, Bond}} where N","page":"Library API","title":"Sunny.set_exchange!","text":"set_exchange!(sys::System, J, bond::Bond; biquad=0)\n\nSets an exchange interaction 𝐒_iJ 𝐒_j along the specified bond. This interaction will be propagated to equivalent bonds in consistency with crystal symmetry. Any previous interactions on these bonds will be overwritten. The parameter bond has the form Bond(i, j, offset), where i and j are atom indices within the unit cell, and offset is a displacement in unit cells.\n\nAs a convenience, scalar J can be used to specify a Heisenberg interaction. Also, the function dmvec(D) can be used to construct the antisymmetric part of the exchange, where D is the Dzyaloshinskii-Moriya pseudo-vector. The resulting interaction will be 𝐃(𝐒_i𝐒_j).\n\nThe optional numeric parameter biquad multiplies a scalar biquadratic interaction, (𝐒_i𝐒_j)^2, with Interaction Renormalization if appropriate. For more general interactions, use set_pair_coupling! instead.\n\nExamples\n\nusing LinearAlgebra\n\n# Set a Heisenberg and DM interaction: 2Si⋅Sj + D⋅(Si×Sj)\nD = [0, 0, 3]\nset_exchange!(sys, 2I + dmvec(D), bond)\n\n# The same interaction as an explicit exchange matrix\nJ = [2 3 0;\n -3 2 0;\n 0 0 2]\nset_exchange!(sys, J, bond)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_exchange_at!-Union{Tuple{N}, Tuple{System{N}, Any, Union{NTuple{4, Int64}, CartesianIndex{4}}, Union{NTuple{4, Int64}, CartesianIndex{4}}}} where N","page":"Library API","title":"Sunny.set_exchange_at!","text":"set_exchange_at!(sys::System, J, site1::Site, site2::Site; biquad=0, offset=nothing)\n\nSets an exchange interaction `𝐒_i⋅J 𝐒_j along the single bond connecting two Sites, ignoring crystal symmetry. Any previous coupling on this bond will be overwritten. The system must support inhomogeneous interactions via to_inhomogeneous.\n\nUse symmetry_equivalent_bonds to find (site1, site2, offset) values that are symmetry equivalent to a given Bond in the original system. For systems that are relatively small, the offset vector (in multiples of unit cells) will resolve ambiguities in the periodic wrapping.\n\nSee also set_exchange! for more details on specifying J and biquad. For more general couplings, use set_pair_coupling_at! instead.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_field!-Tuple{System, Any}","page":"Library API","title":"Sunny.set_field!","text":"set_field!(sys::System, B_μB)\n\nSets the external magnetic field 𝐁 scaled by the Bohr magneton μ_B. This scaled field has units of energy and couples directly to the dimensionless magnetic_moment. At every site, the Zeeman coupling contributes an energy + (𝐁 μ_B) (g 𝐒), involving the local g-tensor and spin angular momentum 𝐒. Commonly, g +2 such that 𝐒 is favored to anti-align with the applied field 𝐁. Note that a given system of Units will implicitly use the Bohr magneton to convert between field and energy dimensions.\n\nExample\n\n# In units of meV, apply a 2 tesla field in the z-direction\nunits = Units(:meV, :angstrom)\nset_field!(sys, [0, 0, 2] * units.T)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_field_at!-Tuple{System, Any, Any}","page":"Library API","title":"Sunny.set_field_at!","text":"set_field_at!(sys::System, B_μB, site::Site)\n\nSets the external magnetic field 𝐁 scaled by the Bohr magneton μ_B for a single Site. This scaled field has units of energy and couples directly to the dimensionless magnetic_moment. Note that a given system of Units will implicitly use the Bohr magneton to convert between field and energy dimensions.\n\nSee the documentation of set_field! for more information.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_onsite_coupling!-Tuple{System, Any, Int64}","page":"Library API","title":"Sunny.set_onsite_coupling!","text":"set_onsite_coupling!(sys::System, op, i::Int)\n\nSet the single-ion anisotropy for the ith atom of every unit cell, as well as all symmetry-equivalent atoms. The operator op may be provided as an abstract function of the local spin operators, as a polynomial of spin_matrices, or as a linear combination of stevens_matrices.\n\nExamples\n\n# An easy axis anisotropy in the z-direction\nset_onsite_coupling!(sys, S -> -D*S[3]^3, i)\n\n# The unique quartic single-ion anisotropy for a site with cubic point group\n# symmetry\nset_onsite_coupling!(sys, S -> 20*(S[1]^4 + S[2]^4 + S[3]^4), i)\n\n# An equivalent expression of this quartic anisotropy, up to a constant shift\nO = stevens_matrices(spin_label(sys, i))\nset_onsite_coupling!(sys, O[4,0] + 5*O[4,4], i)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_onsite_coupling_at!-Tuple{System, Any, Union{NTuple{4, Int64}, CartesianIndex{4}}}","page":"Library API","title":"Sunny.set_onsite_coupling_at!","text":"set_onsite_coupling_at!(sys::System, op, site::Site)\n\nSets the single-ion anisotropy operator op for a single Site, ignoring crystal symmetry. The system must support inhomogeneous interactions via to_inhomogeneous.\n\nSee also set_onsite_coupling!.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_pair_coupling!-Union{Tuple{N}, Tuple{System{N}, AbstractMatrix, Any}} where N","page":"Library API","title":"Sunny.set_pair_coupling!","text":"set_pair_coupling!(sys::System, op, bond)\n\nSets an arbitrary coupling op along bond. This coupling will be propagated to equivalent bonds in consistency with crystal symmetry. Any previous interactions on these bonds will be overwritten. The parameter bond has the form Bond(i, j, offset), where i and j are atom indices within the unit cell, and offset is a displacement in unit cells. The operator op may be provided as an anonymous function that accepts two spin dipole operators, or as a matrix that acts in the tensor product space of the two sites.\n\nExamples\n\n# Bilinear+biquadratic exchange involving 3×3 matrices J1 and J2\nset_pair_coupling!(sys, (Si, Sj) -> Si'*J1*Sj + (Si'*J2*Sj)^2, bond)\n\n# Equivalent expression using an appropriate fixed matrix representation\nS = spin_matrices(1/2)\nSi, Sj = to_product_space(S, S)\nset_pair_coupling!(sys, Si'*J1*Sj + (Si'*J2*Sj)^2, bond)\n\nSee also spin_matrices, to_product_space.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_pair_coupling_at!-Union{Tuple{N}, Tuple{System{N}, AbstractMatrix, Union{NTuple{4, Int64}, CartesianIndex{4}}, Union{NTuple{4, Int64}, CartesianIndex{4}}}} where N","page":"Library API","title":"Sunny.set_pair_coupling_at!","text":"set_pair_coupling_at!(sys::System, op, bond)\n\nSets an arbitrary coupling along the single bond connecting two Sites, ignoring crystal symmetry. Any previous coupling on this bond will be overwritten. The system must support inhomogeneous interactions via to_inhomogeneous.\n\nUse symmetry_equivalent_bonds to find (site1, site2, offset) values that are symmetry equivalent to a given Bond in the original system. For systems that are relatively small, the offset vector (in multiples of unit cells) will resolve ambiguities in the periodic wrapping.\n\nThe operator op may be provided as an anonymous function that accepts two spin dipole operators, or as a matrix that acts in the tensor product space of the two sites. The documentation for set_pair_coupling! provides examples constructing op.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_spin_rescaling!-Tuple{System{0}, Any}","page":"Library API","title":"Sunny.set_spin_rescaling!","text":"set_spin_rescaling!(sys, α)\n\nIn dipole mode, rescale all spin magnitudes S α S. In SU(N) mode, rescale all SU(N) coherent states Z α Z such that every expectation value rescales like A α A.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.set_vacancy_at!-Union{Tuple{N}, Tuple{System{N}, Any}} where N","page":"Library API","title":"Sunny.set_vacancy_at!","text":"set_vacancy_at!(sys::System, site::Site)\n\nMake a single site nonmagnetic. Site includes a unit cell and a sublattice index.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.spin_label-Tuple{System, Int64}","page":"Library API","title":"Sunny.spin_label","text":"spin_label(sys::System, i::Int)\n\nIf atom i carries a single spin-s moment, then returns the half-integer label s. Otherwise, throws an error.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.spin_matrices-Tuple{Any}","page":"Library API","title":"Sunny.spin_matrices","text":"spin_matrices(s)\n\nReturns a triple of NN spin matrices, where N = 2s+1. These are the generators of SU(2) in the spin-s representation.\n\nIf s == Inf, then the return values are abstract symbols denoting infinite-dimensional matrices that commute. These can be useful for repeating historical studies, or modeling micromagnetic systems. A technical discussion appears in the Sunny documentation page: Interaction Renormalization.\n\nExample\n\nS = spin_matrices(3/2)\n@assert S'*S ≈ (3/2)*(3/2+1)*I\n@assert S[1]*S[2] - S[2]*S[1] ≈ im*S[3]\n\nS = spin_matrices(Inf)\n@assert S[1]*S[2] - S[2]*S[1] == 0\n\nSee also print_stevens_expansion.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.spiral_energy-Tuple{System{0}}","page":"Library API","title":"Sunny.spiral_energy","text":"spiral_energy(sys::System; k, axis)\n\nReturns the energy of a generalized spiral phase associated with the propagation wavevector k (in reciprocal lattice units, RLU) and an axis vector that is normal to the polarization plane (in global Cartesian coordinates).\n\nWhen 𝐤 is incommensurate, this calculation can be viewed as creating an infinite number of periodic copies of sys. The spins on each periodic copy are rotated about the axis vector, with the angle θ = 2π 𝐤𝐫, where 𝐫 denotes the displacement vector between periodic copies of sys in multiples of the lattice vectors of the chemical cell.\n\nThe return value is the energy associated with one periodic copy of sys. The special case 𝐤 = 0 yields result is identical to energy.\n\nSee also minimize_spiral_energy! and repeat_periodically_as_spiral.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.spiral_energy_per_site-Tuple{System{0}}","page":"Library API","title":"Sunny.spiral_energy_per_site","text":"spiral_energy_per_site(sys::System; k, axis)\n\nThe spiral_energy divided by the number of sites in sys. The special case 𝐤 = 0 yields a result identical to energy_per_site.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ssf_custom-Tuple{Any, System}","page":"Library API","title":"Sunny.ssf_custom","text":"ssf_custom(f, sys::System; apply_g=true, formfactors=nothing)\n\nSpecify measurement of the spin structure factor with a custom contraction function f. This function accepts a wavevector 𝐪 in global Cartesian coordinates, and a 3×3 matrix with structure factor intensity components mathcalS^αβ(𝐪ω). Indices (α β) denote dipole components in global coordinates. The return value of f can be any number or isbits type. With specific choices of f, one can obtain measurements such as defined in ssf_perp and ssf_trace.\n\nBy default, the g-factor or tensor is applied at each site, such that the structure factor components are correlations between the magnetic moment operators. Set apply_g = false to measure correlations between the bare spin operators.\n\nThe optional formfactors comprise a list of pairs [i1 => FormFactor(...), i2 => ...], where i1, i2, ... are a complete set of symmetry-distinct atoms, and each FormFactor implements 𝐪-space attenuation for the given atom.\n\nIntended for use with SpinWaveTheory and instances of SampledCorrelations.\n\nExamples\n\n# Measure all 3×3 structure factor components Sᵅᵝ\nmeasure = ssf_custom((q, ssf) -> ssf, sys)\n\n# Measure the structure factor trace Sᵅᵅ\nmeasure = ssf_custom((q, ssf) -> real(sum(ssf)), sys)\n\nSee also the Sunny documentation on Structure Factor Conventions.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ssf_custom_bm-Tuple{Any, System}","page":"Library API","title":"Sunny.ssf_custom_bm","text":"ssf_custom_bm(f, sys::System; u, v, apply_g=true, formfactors=nothing)\n\nSpecify measurement of the spin structure factor with a custom contraction function f. The interface is identical to ssf_custom except that f here receives momentum 𝐪 and the 3×3 structure factor data mathcalS^αβ(𝐪 ω) in the basis of the Blume-Maleev axis system. The wavevectors u and v, provided in reciprocal lattice units, will be used to define the scattering plane. In global Cartesian coordinates, the three orthonormal BM axes (e1, e2, e3) are defined as follows:\n\ne3 = normalize(u × v) # normal to the scattering plane (u, v)\ne1 = normalize(q) # momentum transfer q within scattering plane\ne2 = normalize(e3 × q) # perpendicular to q and in the scattering plane\n\nExample\n\n# Measure imaginary part of S²³ - S³² in the Blume-Maleev axis system for\n# the scattering plane [0, K, L].\nmeasure = ssf_custom_bm(sys; u=[0, 1, 0], v=[0, 0, 1]) do q, ssf\n imag(ssf[2,3] - ssf[3,2])\nend\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ssf_perp-Tuple{System}","page":"Library API","title":"Sunny.ssf_perp","text":"ssf_perp(sys::System; apply_g=true, formfactors=nothing)\n\nSpecify measurement of the spin structure factor with contraction by (I-𝐪𝐪q^2). The contracted value provides an estimate of unpolarized scattering intensity. In the singular limit 𝐪 0, the contraction matrix is replaced by its rotational average, (23) I.\n\nThis function is a special case of ssf_custom.\n\nExample\n\n# Select Co²⁺ form factor for atom 1 and its symmetry equivalents\nformfactors = [1 => FormFactor(\"Co2\")]\nssf_perp(sys; formfactors)\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.ssf_trace-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.ssf_trace","text":"ssf_trace(sys::System; apply_g=true, formfactors=nothing)\n\nSpecify measurement of the spin structure factor, with trace over spin components. This quantity can be useful for checking quantum sum rules.\n\nThis function is a special case of ssf_custom.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.standardize-Tuple{Crystal}","page":"Library API","title":"Sunny.standardize","text":"standardize(cryst::Crystal; idealize=true)\n\nReturn the symmetry-inferred standardized crystal unit cell. If idealize=true, then the lattice vectors and site positions will be adapted. See \"definitions and conventions\" of the spglib documentation for more information.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.step!","page":"Library API","title":"Sunny.step!","text":"step!(sys::System, dynamics)\n\nAdvance the spin configuration one dynamical time-step. The dynamics object may be a continuous spin dynamics, such as Langevin or ImplicitMidpoint, or it may be a discrete Monte Carlo sampling scheme such as LocalSampler.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.stevens_matrices-Tuple{Any}","page":"Library API","title":"Sunny.stevens_matrices","text":"stevens_matrices(s)\n\nReturns a generator of Stevens operators in the spin-s representation. The return value O can be indexed as O[k,q], where 0 k 6 labels an irrep of SO(3) and -k q k. This will produce an NN matrix where ``N = 2s\n\n1``. Linear combinations of Stevens operators can be used as a \"physical\n\nbasis\" for decomposing local observables. To see this decomposition, use print_stevens_expansion.\n\nIf s == Inf, then symbolic operators will be returned. In this infinite dimensional limit, the Stevens operators become homogeneous polynomials of commuting spin operators.\n\nExample\n\nO = stevens_matrices(2)\nS = spin_matrices(2)\n\nA = (1/20)O[4,0] + (1/4)O[4,4] + (102/5)I\nB = S[1]^4 + S[2]^4 + S[3]^4\n@assert A ≈ B\n\nSee also spin_matrices and Interaction Renormalization.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.subcrystal-Union{Tuple{N}, Tuple{Crystal, Vararg{String, N}}} where N","page":"Library API","title":"Sunny.subcrystal","text":"subcrystal(cryst, types) :: Crystal\n\nFilters sublattices of a Crystal by atom types, keeping the space group unchanged.\n\nsubcrystal(cryst, classes) :: Crystal\n\nFilters sublattices of Crystal by equivalence classes, keeping the space group unchanged.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.suggest_magnetic_supercell-Tuple{Any}","page":"Library API","title":"Sunny.suggest_magnetic_supercell","text":"suggest_magnetic_supercell(ks; tol=1e-12, maxsize=100)\n\nSuggests a magnetic supercell, in units of the crystal lattice vectors, that is consistent with periodicity of the wavevectors ks in RLU. If the wavevectors are incommensurate (with respect to the maximum supercell size maxsize), one can select a larger error tolerance tol to find a supercell that is almost commensurate.\n\nPrints a 33 matrix of integers that is suitable for use in reshape_supercell.\n\nExamples\n\n# A magnetic supercell for a single-Q structure. Will print\nk1 = [0, -1/4, 1/4]\nsuggest_magnetic_supercell([k1]) # [1 0 0; 0 2 1; 0 -2 1]\n\n# A larger magnetic supercell for a double-Q structure\nk2 = [1/4, 0, 1/4]\nsuggest_magnetic_supercell([k1, k2]) # [1 2 2; -1 2 -2; -1 2 2]\n\n# If given incommensurate wavevectors, find an approximate supercell that\n# is exactly commensurate for nearby wavevectors.\nsuggest_magnetic_supercell([[0, 0, 1/√5], [0, 0, 1/√7]]; tol=1e-2)\n\n# This prints [1 0 0; 0 1 0; 0 0 16], which becomes commensurate under the\n# approximations `1/√5 ≈ 7/16` and `1/√7 ≈ 3/8`.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.suggest_timestep-Union{Tuple{N}, Tuple{System{N}, Union{ImplicitMidpoint, Langevin}}} where N","page":"Library API","title":"Sunny.suggest_timestep","text":"suggest_timestep(sys, integrator; tol)\n\nSuggests a timestep for the numerical integration of spin dynamics according to a given error tolerance tol. The integrator should be Langevin or ImplicitMidpoint. The suggested dt will be inversely proportional to the magnitude of the effective field dEd𝐬 arising from the current spin configuration in sys. The recommended timestep dt scales like √tol, which assumes second-order accuracy of the integrator.\n\nThe system sys should be initialized to an equilibrium spin configuration for the target temperature. Alternatively, a reasonably timestep estimate can be obtained from any low-energy spin configuration. For this, one can use randomize_spins! and then minimize_energy!.\n\nLarge damping magnitude or target temperature kT will tighten the timestep bound. If damping exceeds 1, it will rescale the suggested timestep by an approximate the factor 1damping. If kT is the largest energy scale, then the suggested timestep will scale like 1/(damping*kT). Quantification of numerical error for stochastic dynamics is subtle. The stochastic Heun integration scheme is weakly convergent of order-1, such that errors in the estimates of averaged observables may scale like dt. This implies that the tol argument may actually scale like the square of the true numerical error, and should be selected with this in mind.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.symmetry_equivalent_bonds-Tuple{System, Bond}","page":"Library API","title":"Sunny.symmetry_equivalent_bonds","text":"symmetry_equivalent_bonds(sys::System, bond::Bond)\n\nGiven a Bond for the original (unreshaped) crystal, return all symmetry equivalent bonds in the System. Each returned bond is represented as a pair of Sites, which may be used as input to set_exchange_at! or set_pair_coupling_at!. Reverse bonds are not included in the iterator (no double counting).\n\nExample\n\nfor (site1, site2, offset) in symmetry_equivalent_bonds(sys, bond)\n @assert site1 < site2\n set_exchange_at!(sys, J, site1, site2; offset)\nend\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.to_inhomogeneous-Union{Tuple{System{N}}, Tuple{N}} where N","page":"Library API","title":"Sunny.to_inhomogeneous","text":"to_inhomogeneous(sys::System)\n\nReturns a copy of the system that allows for inhomogeneous interactions, which can be set using set_onsite_coupling_at!, set_exchange_at!, and set_vacancy_at!.\n\nInhomogeneous systems do not support symmetry-propagation of interactions or system reshaping.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.to_product_space-Tuple{Any, Any, Vararg{Any}}","page":"Library API","title":"Sunny.to_product_space","text":"to_product_space(A, B, ...)\n\nGiven lists of operators acting on local Hilbert spaces individually, return the corresponding operators that act on the tensor product space. In typical usage, the inputs will represent local physical observables and the outputs will be used to define quantum couplings.\n\n\n\n\n\n","category":"method"},{"location":"library.html#Sunny.@mix_proposals-Tuple","page":"Library API","title":"Sunny.@mix_proposals","text":"@mix_proposals weight1 propose1 weight2 propose2 ...\n\nMacro to generate a proposal function that randomly selects among the provided functions according to the provided probability weights. For use with LocalSampler.\n\nExample\n\n# A proposal function that proposes a spin flip 40% of the time, and a\n# Gaussian perturbation 60% of the time.\n@mix_proposals 0.4 propose_flip 0.6 propose_delta(0.2)\n\n\n\n\n\n","category":"macro"},{"location":"library.html#Optional-Makie-extensions","page":"Library API","title":"Optional Makie extensions","text":"","category":"section"},{"location":"library.html","page":"Library API","title":"Library API","text":"The following will be enabled through a package extension if either GLMakie or WGLMakie is loaded.","category":"page"},{"location":"library.html","page":"Library API","title":"Library API","text":"plot_spins\nplot_spins!\nplot_intensities\nplot_intensities!\nview_crystal","category":"page"},{"location":"library.html#Sunny.plot_spins","page":"Library API","title":"Sunny.plot_spins","text":"plot_spins(sys::System; arrowscale=1.0, color=:red, colorfn=nothing,\n colormap=:viridis, colorrange=nothing, show_cell=true, orthographic=false,\n ghost_radius=0, ndims=3, compass=true)\n\nPlot the spin configuration defined by sys. Optional parameters are:\n\narrowscale: Scale all arrows by dimensionless factor.\ncolor: Arrow colors. May be symbolic or numeric. If scalar, will be shared among all sites.\ncolorfn: Function that dynamically maps from a site index to a numeric color value. Useful for animations.\ncolormap, colorrange: Used to populate colors from numbers following Makie conventions.\nshow_cell: Show original crystallographic unit cell.\northographic: Use orthographic camera perspective.\nghost_radius: Show periodic images up to a given distance (length units).\nndims: Spatial dimensions of system (1, 2, or 3).\ncompass: If true, draw Cartesian axes in bottom left.\n\nCalling notify on the return value will animate the figure.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.plot_spins!","page":"Library API","title":"Sunny.plot_spins!","text":"plot_spins!(ax, sys::System; opts...)\n\nMutating variant of plot_spins that allows drawing into a single panel of a Makie figure.\n\nExample\n\nfig = Figure()\nplot_spins!(fig[1, 1], sys1)\nplot_spins!(fig[2, 1], sys2)\ndisplay(fig)\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.plot_intensities","page":"Library API","title":"Sunny.plot_intensities","text":"plot_intensities(res::BandIntensities; colormap=nothing, colorrange=nothing, allpositive=true,\n saturation=0.9, sensitivity=0.0025, fwhm=nothing, ylims=nothing, units=nothing,\n into=nothing, title=\"\")\nplot_intensities(res::Intensities; colormap=nothing, colorrange=nothing, allpositive=true, \n saturation=0.9, units=nothing, into=nothing, title=\"\")\nplot_intensities(res::StaticIntensities; colormap=nothing, colorrange=nothing, allpositive=true, \n saturation=0.9, units=nothing, into=nothing, title=\"\")\nplot_intensities(res::PowderIntensities; colormap=nothing, colorrange=nothing, allpositive=true, \n saturation=0.9, units=nothing, into=nothing, title=\"\")\n\nKeyword arguments:\n\ncolormap: Color palette for plotting broadened intensities. See Makie docs for allowed values.\ncolorrange: A lower and upper bound on intensities. For heatmaps, these bounds define the intensity values that saturate the colormap.\nallpositive: Should intensities be all positive, apart from numerical error? If true, the default colors will clip below zero intensity. If false, the default colors will be symmetric about zero intensity.\nsaturation: If colorrange is not explicitly set, this dimensionless parameter defines the upper saturated intensity value as a quantile of maximum intensities taken over wavevectors.\nsensitivity: When plotting BandIntensities, this defines a lower bound on the visible intensities as a fraction of the upper saturated intensity value.\nfwhm: When plotting BandIntensities, this overrides the full-width at half-maximum value used for Gaussian broadening.\nylims: Limits of the y-axis.\nunits: A Units instance for labeling axes and performing conversions.\ninto: A symbol for conversion into a new base energy unit (e.g. :meV, :K, etc.)\ntitle: An optional title for the plot.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.plot_intensities!","page":"Library API","title":"Sunny.plot_intensities!","text":"plot_intensities!(panel, res::AbstractIntensities; opts...)\n\nMutating variant of plot_intensities that allows drawing into a single panel of a Makie figure.\n\nExample\n\nfig = Figure()\nplot_intensities!(fig[1, 1], res1; title=\"Panel 1\")\nplot_intensities!(fig[2, 1], res2; title=\"Panel 2\")\ndisplay(fig)\n\n\n\n\n\n","category":"function"},{"location":"library.html#Sunny.view_crystal","page":"Library API","title":"Sunny.view_crystal","text":"view_crystal(crystal::Crystal; refbonds=10, orthographic=false, ghost_radius=nothing, ndims=3, compass=true)\nview_crystal(sys::System; ...)\n\nLaunches a graphical user interface to visualize the Crystal unit cell. If a System is provided, then the 3×3 exchange matrices for each bond will be depicted graphically.\n\nrefbonds: By default, calculate up to 10 reference bonds using the reference_bonds function. An explicit list of reference bonds may also be provided.\northographic: Use orthographic camera perspective.\nghost_radius: Show periodic images up to a given distance. Defaults to the cell size.\nndims: Spatial dimensions of system (1, 2, or 3).\ncompass: If true, draw Cartesian axes in bottom left.\n\n\n\n\n\n","category":"function"},{"location":"library.html#Optional-WriteVTK-extensions","page":"Library API","title":"Optional WriteVTK extensions","text":"","category":"section"},{"location":"library.html","page":"Library API","title":"Library API","text":"The following will be enabled through a package extension if WriteVTK is loaded.","category":"page"},{"location":"library.html","page":"Library API","title":"Library API","text":"export_vtk","category":"page"},{"location":"library.html#Sunny.export_vtk","page":"Library API","title":"Sunny.export_vtk","text":"export_vtk(filename,params::BinningParameters,data)\n\nExport a VTK-compatible file to filename (do not include file extension when specifying the file name) which contains the data as VTK Cell Data on a grid parameterized by params.\n\nAt least one axis of the BinningParameters must be integrated over, since VTK does not support 4D data. See integrate_axes!.\n\n\n\n\n\n","category":"function"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"EditURL = \"../../../examples/05_MC_Ising.jl\"","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/05_MC_Ising.html#5.-Monte-Carlo-sampling-of-the-Ising-model","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"","category":"section"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"This tutorial illustrates simulation of the classical 2D Ising model.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"To model the 2D square lattice, create an elongated tetragonal cell with one atom.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"latvecs = lattice_vectors(1, 1, 10, 90, 90, 90)\ncrystal = Crystal(latvecs, [[0, 0, 0]])","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Create a System of spin dipoles. Following the Ising convention, we will restrict the dipoles to 1 along the global hatz-axis. Select g=-1 so that the Zeeman coupling between external field 𝐁 and spin dipole 𝐬 is -𝐁𝐬. The system size is 128×128.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"L = 128\nsys = System(crystal, [1 => Moment(s=1, g=-1)], :dipole; dims=(L, L, 1), seed=0)\npolarize_spins!(sys, (0, 0, 1))","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Use set_exchange! to include a ferromagnetic Heisenberg interaction along nearest-neighbor bonds. The Bond below connects two spins displaced by the lattice vector 𝐚₁. This interaction will be propagated to all nearest-neighbors bonds in the system, consistent with the symmetries of the square lattice.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"set_exchange!(sys, -1.0, Bond(1, 1, (1, 0, 0)))","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"If an external field is desired, it can be set using set_field!.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"B = 0\nset_field!(sys, (0, 0, B))","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"The critical temperature for the Ising model is known analytically.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Tc = 2/log(1+√2)","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Use a LocalSampler to perform nsweeps Monte Carlo sweeps. A sweep consists of, on average, one trial update per spin in the system. Each proposed update is accepted or rejected according to the Metropolis acceptance probability. As its name suggests, the propose_flip function will only propose pure spin flips, 𝐬 rightarrow -𝐬.","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"nsweeps = 4000\nsampler = LocalSampler(kT=Tc, propose=propose_flip)\nfor i in 1:nsweeps\n step!(sys, sampler)\nend","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"Plot the Ising spins by extracting the z-component of the dipoles","category":"page"},{"location":"examples/05_MC_Ising.html","page":"5. Monte Carlo sampling of the Ising model","title":"5. Monte Carlo sampling of the Ising model","text":"heatmap(reshape([S[3] for S in sys.dipoles], (L, L)))","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#MgCr2O4-at-Finite-Temperature","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Author: Martin Mourigal","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Date: September 9, 2022 (Updated August 29, 2024 using Sunny 0.7.0)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"In this tutorial, we will walk through an example in Sunny and calculate the spin dynamical properties of the Heisenberg pyrochlore antiferromagnet and apply this knowledge to MgCr2O4 and ZnCr2O4, which are known to approximate this model. Relevant publications include:","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"[1] P. H. Conlon and J. T. Chalker, Phys. Rev. Lett. 102, 237206 (2009)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"[2] P. H. Conlon and J. T. Chalker, Phys. Rev. B 81, 224413 (2010)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"[3] X. Bai, J. A. M. Paddison, et al. Phys. Rev. Lett. 122, 097201 (2019)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Setting-up-Julia","page":"MgCr2O4 at Finite Temperature","title":"Setting up Julia","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To run the examples in the tutorial, you will need a working installation of the Julia programming language and the Sunny package. Some useful references for getting started are:","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Getting started with Julia for Sunny\nSunny Docs","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We will begin by loading the relevant packages.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"using Sunny # The main package\nusing GLMakie # Plotting package","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Setting-up-the-crystal-structure","page":"MgCr2O4 at Finite Temperature","title":"Setting up the crystal structure","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Before specifying the interactions of our system, we first must set up the crystal. We will begin by specifying the pyrochlore lattice (illustrated below) in the manner that is typical of theorists.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Picture Credits: Theory of Quantum Matter Unit, OIST","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#\"Theorist\"-Method","page":"MgCr2O4 at Finite Temperature","title":"\"Theorist\" Method","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"In this approach, we directly define the lattice vectors and specify the position of each atom in fractional coordinates.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"latvecs = lattice_vectors(8.3342, 8.3342, 8.3342, 90, 90, 90)\npositions = [[0.875, 0.625, 0.375],\n [0.625, 0.125, 0.625],\n [0.875, 0.875, 0.125],\n [0.625, 0.875, 0.375],\n [0.875, 0.125, 0.875],\n [0.625, 0.625, 0.125],\n [0.875, 0.375, 0.625],\n [0.625, 0.375, 0.875],\n [0.375, 0.625, 0.875],\n [0.125, 0.125, 0.125],\n [0.375, 0.875, 0.625],\n [0.125, 0.875, 0.875],\n [0.375, 0.125, 0.375],\n [0.125, 0.625, 0.625],\n [0.375, 0.375, 0.125],\n [0.125, 0.375, 0.375]];\ntypes = [\"B\" for _ in positions]\nxtal_pyro = Crystal(latvecs, positions; types) # We will call this crystal the Theoretical Pyrochlore","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'F d -3 m' (227)\nLattice params a=8.334, b=8.334, c=8.334, α=90°, β=90°, γ=90°\nCell volume 578.9\nType 'B', Wyckoff 16c (point group '.-3m'):\n 1. [7/8, 5/8, 3/8]\n 2. [5/8, 1/8, 5/8]\n 3. [7/8, 7/8, 1/8]\n 4. [5/8, 7/8, 3/8]\n 5. [7/8, 1/8, 7/8]\n 6. [5/8, 5/8, 1/8]\n 7. [7/8, 3/8, 5/8]\n 8. [5/8, 3/8, 7/8]\n 9. [3/8, 5/8, 7/8]\n 10. [1/8, 1/8, 1/8]\n 11. [3/8, 7/8, 5/8]\n 12. [1/8, 7/8, 7/8]\n 13. [3/8, 1/8, 3/8]\n 14. [1/8, 5/8, 5/8]\n 15. [3/8, 3/8, 1/8]\n 16. [1/8, 3/8, 3/8]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To examine the result interactively, we can call view_crystal.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"view_crystal(xtal_pyro, 3.2)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#\"Experimentalist\"-Method-#1-(Incorrect)","page":"MgCr2O4 at Finite Temperature","title":"\"Experimentalist\" Method #1 (Incorrect)","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"A real crystal is more complicated than this, however, and we will now construct the system using the actual CIF file of MgCr2O4 from ICSD. This can be done by copying over the data from a CIF file by hand, but this can be dangerous, as shown below.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"latvecs = lattice_vectors(8.3342, 8.3342, 8.3342, 90, 90, 90)\npositions = [[0.1250, 0.1250, 0.1250],\n [0.5000, 0.5000, 0.5000],\n [0.2607, 0.2607, 0.2607]]\ntypes = [\"Mg\",\"Cr\",\"O\"]\nxtal_mgcro_1 = Crystal(latvecs, positions; types)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'R 3 m' (160)\nLattice params a=8.334, b=8.334, c=8.334, α=90°, β=90°, γ=90°\nCell volume 578.9\nType 'Mg', Wyckoff 3a (point group '3m'):\n 1. [1/8, 1/8, 1/8]\nType 'Cr', Wyckoff 3a (point group '3m'):\n 2. [1/2, 1/2, 1/2]\nType 'O', Wyckoff 3a (point group '3m'):\n 3. [0.2607, 0.2607, 0.2607]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Sunny returned a valid crystal, but it did get right space group for MgCr2O4. This can be fixed by modifying the input to include the space group and the setting.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#\"Experimentalist\"-Method-#2-(Correct)","page":"MgCr2O4 at Finite Temperature","title":"\"Experimentalist\" Method #2 (Correct)","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"As above, we will define the crystal structure of MgCr2O4 by copying the info from a CIF file, but we will also specify the space group and setting explicitly.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"latvecs = lattice_vectors(8.3342, 8.3342, 8.3342, 90, 90, 90)\npositions = [[0.1250, 0.1250, 0.1250],\n [0.5000, 0.5000, 0.5000],\n [0.2607, 0.2607, 0.2607]]\ntypes = [\"Mg\",\"Cr\",\"O\"]\nspacegroup = 227 # Space Group Number\nsetting = \"2\" # Space Group setting\nxtal_mgcro_2 = Crystal(latvecs, positions, spacegroup; types, setting)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'F d -3 m' (227)\nLattice params a=8.334, b=8.334, c=8.334, α=90°, β=90°, γ=90°\nCell volume 578.9\nType 'Mg', Wyckoff 8b (point group '-43m'):\n 1. [1/8, 1/8, 1/8]\n 2. [5/8, 5/8, 1/8]\n 3. [7/8, 3/8, 3/8]\n 4. [3/8, 7/8, 3/8]\n 5. [5/8, 1/8, 5/8]\n 6. [1/8, 5/8, 5/8]\n 7. [3/8, 3/8, 7/8]\n 8. [7/8, 7/8, 7/8]\nType 'Cr', Wyckoff 16c (point group '.-3m'):\n 9. [1/2, 0, 0]\n 10. [3/4, 1/4, 0]\n 11. [0, 1/2, 0]\n 12. [1/4, 3/4, 0]\n 13. [3/4, 0, 1/4]\n 14. [1/2, 1/4, 1/4]\n 15. [1/4, 1/2, 1/4]\n 16. [0, 3/4, 1/4]\n 17. [0, 0, 1/2]\n 18. [1/4, 1/4, 1/2]\n 19. [1/2, 1/2, 1/2]\n 20. [3/4, 3/4, 1/2]\n 21. [1/4, 0, 3/4]\n 22. [0, 1/4, 3/4]\n 23. [3/4, 1/2, 3/4]\n 24. [1/2, 3/4, 3/4]\nType 'O', Wyckoff 32e (point group '.3m'):\n 25. [0.7393, 0.0107, 0.0107]\n 26. [0.5107, 0.2393, 0.0107]\n 27. [0.2393, 0.5107, 0.0107]\n 28. [0.0107, 0.7393, 0.0107]\n 29. [0.5107, 0.0107, 0.2393]\n 30. [0.7393, 0.2393, 0.2393]\n 31. [0.0107, 0.5107, 0.2393]\n 32. [0.2393, 0.7393, 0.2393]\n 33. [0.2607, 0.2607, 0.2607]\n 34. [0.4893, 0.4893, 0.2607]\n 35. [0.7607, 0.7607, 0.2607]\n 36. [0.9893, 0.9893, 0.2607]\n 37. [0.4893, 0.2607, 0.4893]\n 38. [0.2607, 0.4893, 0.4893]\n 39. [0.9893, 0.7607, 0.4893]\n 40. [0.7607, 0.9893, 0.4893]\n 41. [0.2393, 0.0107, 0.5107]\n 42. [0.0107, 0.2393, 0.5107]\n 43. [0.7393, 0.5107, 0.5107]\n 44. [0.5107, 0.7393, 0.5107]\n 45. [0.0107, 0.0107, 0.7393]\n 46. [0.2393, 0.2393, 0.7393]\n 47. [0.5107, 0.5107, 0.7393]\n 48. [0.7393, 0.7393, 0.7393]\n 49. [0.7607, 0.2607, 0.7607]\n 50. [0.9893, 0.4893, 0.7607]\n 51. [0.2607, 0.7607, 0.7607]\n 52. [0.4893, 0.9893, 0.7607]\n 53. [0.9893, 0.2607, 0.9893]\n 54. [0.7607, 0.4893, 0.9893]\n 55. [0.4893, 0.7607, 0.9893]\n 56. [0.2607, 0.9893, 0.9893]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"This result is correct, but at this point we might as well import the CIF file directly, which we now proceed to do.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#\"Experimentalist\"-Method-#3-(Correct-–-if-your-CIF-file-is)","page":"MgCr2O4 at Finite Temperature","title":"\"Experimentalist\" Method #3 (Correct – if your CIF file is)","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To import a CIF file, simply give the path to Crystal. One may optionally specify a precision parameter to apply to the symmetry analysis.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"cif = joinpath(@__DIR__, \"MgCr2O4_160953_2009.cif\")\nxtal_mgcro_3 = Crystal(cif; symprec=0.001)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'F d -3 m' (227)\nLattice params a=8.333, b=8.333, c=8.333, α=90°, β=90°, γ=90°\nCell volume 578.6\nType 'Mg1', Wyckoff 8b (point group '-43m'):\n 1. [1/8, 1/8, 1/8]\n 2. [5/8, 5/8, 1/8]\n 3. [7/8, 3/8, 3/8]\n 4. [3/8, 7/8, 3/8]\n 5. [5/8, 1/8, 5/8]\n 6. [1/8, 5/8, 5/8]\n 7. [3/8, 3/8, 7/8]\n 8. [7/8, 7/8, 7/8]\nType 'Cr1', Wyckoff 16c (point group '.-3m'):\n 9. [1/2, 0, 0]\n 10. [3/4, 1/4, 0]\n 11. [0, 1/2, 0]\n 12. [1/4, 3/4, 0]\n 13. [3/4, 0, 1/4]\n 14. [1/2, 1/4, 1/4]\n 15. [1/4, 1/2, 1/4]\n 16. [0, 3/4, 1/4]\n 17. [0, 0, 1/2]\n 18. [1/4, 1/4, 1/2]\n 19. [1/2, 1/2, 1/2]\n 20. [3/4, 3/4, 1/2]\n 21. [1/4, 0, 3/4]\n 22. [0, 1/4, 3/4]\n 23. [3/4, 1/2, 3/4]\n 24. [1/2, 3/4, 3/4]\nType 'O1', Wyckoff 32e (point group '.3m'):\n 25. [0.7388, 0.0112, 0.0112]\n 26. [0.5112, 0.2388, 0.0112]\n 27. [0.2388, 0.5112, 0.0112]\n 28. [0.0112, 0.7388, 0.0112]\n 29. [0.5112, 0.0112, 0.2388]\n 30. [0.7388, 0.2388, 0.2388]\n 31. [0.0112, 0.5112, 0.2388]\n 32. [0.2388, 0.7388, 0.2388]\n 33. [0.2612, 0.2612, 0.2612]\n 34. [0.4888, 0.4888, 0.2612]\n 35. [0.7612, 0.7612, 0.2612]\n 36. [0.9888, 0.9888, 0.2612]\n 37. [0.4888, 0.2612, 0.4888]\n 38. [0.2612, 0.4888, 0.4888]\n 39. [0.9888, 0.7612, 0.4888]\n 40. [0.7612, 0.9888, 0.4888]\n 41. [0.2388, 0.0112, 0.5112]\n 42. [0.0112, 0.2388, 0.5112]\n 43. [0.7388, 0.5112, 0.5112]\n 44. [0.5112, 0.7388, 0.5112]\n 45. [0.0112, 0.0112, 0.7388]\n 46. [0.2388, 0.2388, 0.7388]\n 47. [0.5112, 0.5112, 0.7388]\n 48. [0.7388, 0.7388, 0.7388]\n 49. [0.7612, 0.2612, 0.7612]\n 50. [0.9888, 0.4888, 0.7612]\n 51. [0.2612, 0.7612, 0.7612]\n 52. [0.4888, 0.9888, 0.7612]\n 53. [0.9888, 0.2612, 0.9888]\n 54. [0.7612, 0.4888, 0.9888]\n 55. [0.4888, 0.7612, 0.9888]\n 56. [0.2612, 0.9888, 0.9888]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Finally, we wish to restrict attention to the magnetic atoms in the unit cell while maintaining symmetry information for the full crystal, which is required to determine the correct exchange and g-factor anisotropies. This can be achieved with the subcrystal function.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"xtal_mgcro = subcrystal(xtal_mgcro_2, \"Cr\")","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Crystal\nSpacegroup 'F d -3 m' (227)\nLattice params a=8.334, b=8.334, c=8.334, α=90°, β=90°, γ=90°\nCell volume 578.9\nType 'Cr', Wyckoff 16c (point group '.-3m'):\n 1. [1/2, 0, 0]\n 2. [3/4, 1/4, 0]\n 3. [0, 1/2, 0]\n 4. [1/4, 3/4, 0]\n 5. [3/4, 0, 1/4]\n 6. [1/2, 1/4, 1/4]\n 7. [1/4, 1/2, 1/4]\n 8. [0, 3/4, 1/4]\n 9. [0, 0, 1/2]\n 10. [1/4, 1/4, 1/2]\n 11. [1/2, 1/2, 1/2]\n 12. [3/4, 3/4, 1/2]\n 13. [1/4, 0, 3/4]\n 14. [0, 1/4, 3/4]\n 15. [3/4, 1/2, 3/4]\n 16. [1/2, 3/4, 3/4]\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Making-a-System-and-assigning-interactions","page":"MgCr2O4 at Finite Temperature","title":"Making a System and assigning interactions","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Making-a-System","page":"MgCr2O4 at Finite Temperature","title":"Making a System","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Before assigning any interactions, we first have to set up a System using our Crystal.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"dims = (6, 6, 6) # Supercell dimensions\nmomentinfo = [1 => Moment(s=3/2, g=2)] # Specify local moment information, note that all sites are symmetry equivalent\nsys_pyro = System(xtal_pyro, momentinfo, :dipole; dims) # Make a system in dipole (Landau-Lifshitz) mode on pyrochlore lattice\nsys_mgcro = System(xtal_mgcro, momentinfo, :dipole; dims); # Same on MgCr2O4 crystal","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To understand what interactions we may assign to this system, we have to understand the the symmetry properties of the crystal, which we turn to next.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Symmetry-analysis-for-exchange-and-single-ion-anisotropies","page":"MgCr2O4 at Finite Temperature","title":"Symmetry analysis for exchange and single-ion anisotropies","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"print_symmetry_table reports all the exchange interactions, single-site anisotropies, and g-factors allowed on our crystal. It takes a Cyrstal and a distance. We'll look at both the \"theorist's\" pyrochlore lattice,","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"print_symmetry_table(xtal_pyro, 5.9)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Atom 1\nType 'B', position [7/8, 5/8, 3/8], multiplicity 16\nAllowed g-tensor: [ A B -B\n B A B\n -B B A]\nAllowed anisotropy in Stevens operators:\n c₁*(𝒪[2,-2]+2𝒪[2,-1]-2𝒪[2,1]) +\n c₂*(7𝒪[4,-3]+2𝒪[4,-2]-𝒪[4,-1]+𝒪[4,1]+7𝒪[4,3]) + c₃*(𝒪[4,0]+5𝒪[4,4]) +\n c₄*(-11𝒪[6,-6]-8𝒪[6,-3]+𝒪[6,-2]-8𝒪[6,-1]+8𝒪[6,1]-8𝒪[6,3]) + c₅*(𝒪[6,0]-21𝒪[6,4]) + c₆*((9/5)𝒪[6,-6]+(24/5)𝒪[6,-5]+𝒪[6,-2]+(8/5)𝒪[6,-1]-(8/5)𝒪[6,1]-(24/5)𝒪[6,5])\n\nBond(1, 3, [0, 0, 0])\nDistance 2.9465846678825, coordination 6\nConnects 'B' at [7/8, 5/8, 3/8] to 'B' at [7/8, 7/8, 1/8]\nAllowed exchange matrix: [ A -D D\n D B C\n -D C B]\nAllowed DM vector: [0 -D -D]\n\nBond(1, 2, [0, 0, 0])\nDistance 5.1036343535759, coordination 12\nConnects 'B' at [7/8, 5/8, 3/8] to 'B' at [5/8, 1/8, 5/8]\nAllowed exchange matrix: [ A C-E D-F\n C+E B -C+E\n D+F -C-E A]\nAllowed DM vector: [E F -E]\n\nBond(2, 6, [0, 0, 0])\nDistance 5.8931693357649, coordination 6\nConnects 'B' at [5/8, 1/8, 5/8] to 'B' at [5/8, 5/8, 1/8]\nAllowed exchange matrix: [A D D\n D B C\n D C B]\n\nBond(1, 5, [0, 0, 0])\nDistance 5.8931693357649, coordination 6\nConnects 'B' at [7/8, 5/8, 3/8] to 'B' at [7/8, 1/8, 7/8]\nAllowed exchange matrix: [ A D -D\n D B C\n -D C B]\n\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"and for the the MgCrO4 crystal,","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"print_symmetry_table(xtal_mgcro, 6.0)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Atom 1\nType 'Cr', position [1/2, 0, 0], multiplicity 16\nAllowed g-tensor: [A B B\n B A B\n B B A]\nAllowed anisotropy in Stevens operators:\n c₁*(𝒪[2,-2]+2𝒪[2,-1]+2𝒪[2,1]) +\n c₂*(-7𝒪[4,-3]-2𝒪[4,-2]+𝒪[4,-1]+𝒪[4,1]+7𝒪[4,3]) + c₃*(𝒪[4,0]+5𝒪[4,4]) +\n c₄*(-11𝒪[6,-6]-8𝒪[6,-3]+𝒪[6,-2]-8𝒪[6,-1]-8𝒪[6,1]+8𝒪[6,3]) + c₅*(𝒪[6,0]-21𝒪[6,4]) + c₆*((9/5)𝒪[6,-6]+(24/5)𝒪[6,-5]+𝒪[6,-2]+(8/5)𝒪[6,-1]+(8/5)𝒪[6,1]+(24/5)𝒪[6,5])\n\nBond(1, 2, [0, 0, 0])\nDistance 2.9465846678825, coordination 6\nConnects 'Cr' at [1/2, 0, 0] to 'Cr' at [3/4, 1/4, 0]\nAllowed exchange matrix: [A C -D\n C A -D\n D D B]\nAllowed DM vector: [-D D 0]\n\nBond(1, 7, [0, 0, 0])\nDistance 5.1036343535759, coordination 12\nConnects 'Cr' at [1/2, 0, 0] to 'Cr' at [1/4, 1/2, 1/4]\nAllowed exchange matrix: [ A C-E D-F\n C+E B -C+E\n D+F -C-E A]\nAllowed DM vector: [E F -E]\n\nBond(1, 3, [0, 0, 0])\nDistance 5.8931693357649, coordination 6\nConnects 'Cr' at [1/2, 0, 0] to 'Cr' at [0, 1/2, 0]\nAllowed exchange matrix: [A D C\n D A C\n C C B]\n\nBond(1, 3, [1, 0, 0])\nDistance 5.8931693357649, coordination 6\nConnects 'Cr' at [1/2, 0, 0] to 'Cr' at [1, 1/2, 0]\nAllowed exchange matrix: [A D C\n D A C\n C C B]\n\n","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Note that the exchange anisotropies allowed on the the pyrochlore lattice are slightly different from those on the MgCr2O4 cyrstal due to the role of Mg and O in the bonds. Also note that Sunny has correctly identified the two inequivalent bonds 3a and 3b having the same length. A question may arises to know which bond is J3a and which is J3b, let's plot the structure.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"view_crystal(xtal_mgcro, 5.9)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"The crystal viewer shows that the second interaction – cyan color with distance of 5.89Å – is in fact the one hopping through a chromium site, meaning it is J3a! We will need to be careful with that later.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Building-the-exchange-interactions-for-our-system","page":"MgCr2O4 at Finite Temperature","title":"Building the exchange interactions for our system","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We begin by setting the scale of our exchange interactions on each bond.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"J1 = 3.27 # value of J1 in meV from Bai's PRL paper\nJ_pyro = [1.00,0.000,0.000,0.000]*J1 # pure nearest neighbor pyrochlore\nJ_mgcro = [1.00,0.0815,0.1050,0.085]*J1; # further neighbor pyrochlore relevant for MgCr2O4\n# val_J_mgcro = [1.00,0.000,0.025,0.025]*val_J1; # this is a funny setting from Conlon-Chalker","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"These values are then assigned to their corresponding bonds with set_exchange!.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"# === Assign exchange interactions to pyrochlore system ===\nset_exchange!(sys_pyro, J_pyro[1], Bond(1, 3, [0,0,0])) # J1\nset_exchange!(sys_pyro, J_pyro[2], Bond(1, 2, [0,0,0])) # J2\nset_exchange!(sys_pyro, J_pyro[3], Bond(2, 6, [0,0,0])) # J3a\nset_exchange!(sys_pyro, J_pyro[4], Bond(1, 5, [0,0,0])) # J3b\n\n# === Assign exchange interactions to MgCr2O4 system ===\nset_exchange!(sys_mgcro, J_mgcro[1], Bond(1, 2, [0,0,0])) # J1\nset_exchange!(sys_mgcro, J_mgcro[2], Bond(1, 7, [0,0,0])) # J2\nset_exchange!(sys_mgcro, J_mgcro[3], Bond(1, 3, [0,0,0])) # J3a -- Careful here!\nset_exchange!(sys_mgcro, J_mgcro[4], Bond(1, 3, [1,0,0])); # J3b -- And here!","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We will not be assigning any single-ion anisotropies, so we have finished specifying our models. For good measure, we will set both systems to a random (infinite temperature) initial condition.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"randomize_spins!(sys_pyro)\nrandomize_spins!(sys_mgcro);","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Cooling-our-System-amd-calculating-the-instantaneous-and-dynamic-structure-factors-at-the-final-temperature","page":"MgCr2O4 at Finite Temperature","title":"Cooling our System amd calculating the instantaneous and dynamic structure factors at the final temperature","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We begin by thermalizing our system at a particular temperature. We will accomplish this by running Langevin dynamics. To do this, we must set up a Langevin integrator.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"dt = 0.01 # Integration time step in meV^-1\ndamping = 0.1 # Phenomenological damping parameter\nkT = 1.8 # Desired temperature in meV\nlangevin = Langevin(dt; damping, kT); # Construct integrator","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We can now thermalize our systems by running the integrator.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"for _ in 1:5000\n step!(sys_pyro, langevin)\n step!(sys_mgcro, langevin)\nend","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"As a sanity check, we'll plot the real-space spin configurations of both systems after themalization. First the pyrochlore,","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"plot_spins(sys_pyro)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"and then the MgCr2O4,","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"plot_spins(sys_mgcro)","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Instantaneous-Structure-Factor","page":"MgCr2O4 at Finite Temperature","title":"Instantaneous Structure Factor","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Next we can examine the instantaneous structure factor.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"isf_pyro = SampledCorrelationsStatic(sys_pyro; measure=ssf_perp(sys_pyro))\nisf_mgcro = SampledCorrelationsStatic(sys_mgcro; measure=ssf_perp(sys_mgcro));","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"These are currently empty. Let's add spin-spin correlation data from 10 sampled spin configurations at kT = 1.8 meV.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"for _ in 1:10\n # Run dynamics to decorrelate\n for _ in 1:500\n step!(sys_pyro, langevin)\n step!(sys_mgcro, langevin)\n end\n # Add samples\n add_sample!(isf_pyro, sys_pyro)\n add_sample!(isf_mgcro, sys_mgcro)\nend","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"To retrieve the intensities, we call intensities_static on an array of wave vectors, which we can generate with q_space_grid.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"qpts_pyro = q_space_grid(xtal_pyro, [1, 0, 0], range(-4.0, 4.0, 200), [0, 1, 0], (-4, 4))\nqpts_mgcro = q_space_grid(xtal_mgcro, [1, 0, 0], range(-4.0, 4.0, 200), [0, 1, 0], (-4, 4))\n\nSq_pyro = intensities_static(isf_pyro, qpts_pyro)\nSq_mgcro = intensities_static(isf_mgcro, qpts_mgcro);","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Finally, plot the results.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"fig = Figure(; size=(1200,500))\nplot_intensities!(fig[1,1], Sq_pyro)\nplot_intensities!(fig[1,2], Sq_mgcro)\nfig","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Dynamical-Structure-Factor","page":"MgCr2O4 at Finite Temperature","title":"Dynamical Structure Factor","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We can also estimate the dynamical structure factor.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"energies = range(0, 10, 100)\nsc_pyro = SampledCorrelations(sys_pyro; dt, energies, measure=ssf_perp(sys_pyro))\nsc_mgcro = SampledCorrelations(sys_mgcro; dt, energies, measure=ssf_perp(sys_mgcro));","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Next we sample trajectories and calculate the spin-spin correlations of these. Unlike SampledCorrelationsStatic, these samples now include time (energy) information – and take significantly longer to calculate.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"for _ in 1:3\n # Run dynamics to decorrelate\n for _ in 1:500\n step!(sys_pyro, langevin)\n step!(sys_mgcro, langevin)\n end\n # Add samples\n add_sample!(sc_pyro, sys_pyro)\n add_sample!(sc_mgcro, sys_mgcro)\nend","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We can now examine the structure factor intensities along a path in momentum space. First examine the pyrochlore model.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"fig = Figure(; size=(1200,900))\nqbs = 0.0:0.5:1.5 # Determine q_b for each slice\nfor (i, qb) in enumerate(qbs)\n qpts_pyro = q_space_path(xtal_pyro, [[-4, qb, 0], [4, qb, 0]], 200)\n Sqw_pyro = intensities(sc_pyro, qpts_pyro; energies=:available, kT)\n plot_intensities!(fig[fldmod1(i, 2)...], Sqw_pyro; title=\"q_b = $qb\")\nend\nfig","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Next generate the results along the same path for MgCr2O4.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"fig = Figure(; size=(1200,900))\nfor (i, qb) in enumerate(qbs)\n qpts_mgcro = q_space_path(xtal_mgcro, [[-4, qb, 0], [4, qb, 0]], 200)\n Sqw_mgcro = intensities(sc_mgcro, qpts_mgcro; energies=:available, kT)\n plot_intensities!(fig[fldmod1(i, 2)...], Sqw_mgcro; title =\"q_b = $qb\")\nend\nfig","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html#Instantaneous-structure-factor-from-a-dynamical-structure-factor","page":"MgCr2O4 at Finite Temperature","title":"Instantaneous structure factor from a dynamical structure factor","text":"","category":"section"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"Finally, we note that the instant structure factor (what we generated with SampledCorrelationsStatic) can be calculated from the dynamical structure factor (generated with a SampledCorrelations). We simply call instant_static rather than intensities on the SampledCorrelations. This will calculate the instantaneous structure factor from from 𝒮(𝐪ω) by integrating out ω . An advantage of doing this (as opposed to using a SampledCorrelationsStatic) is that Sunny is able to apply a temperature- and energy-dependent intensity rescaling before integrating out the dynamical information. The results of this approach are more suitable for comparison with experimental data.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"qpts_pyro = q_space_grid(xtal_pyro, [1, 0, 0], range(-4, 4, 200), [0, 1, 0], (-4, 4))\nqpts_mgcro = q_space_grid(xtal_mgcro, [1, 0, 0], range(-4, 4, 200), [0, 1, 0], (-4, 4))\n\nSq_pyro = intensities_static(sc_pyro, qpts_pyro; kT)\nSq_mgcro = intensities_static(sc_mgcro, qpts_mgcro; kT);","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"We can plot the results below. It is useful to compare these to the plot above generated with an SampledCorrelationsStatic.","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"fig = Figure(; size=(1200,500))\nax = plot_intensities!(fig[1,1], Sq_pyro; title=\"Pyrochlore\")\nax = plot_intensities!(fig[1,2], Sq_mgcro; title=\"MgCr₂O₄\")\nfig","category":"page"},{"location":"examples/contributed/MgCr2O4-tutorial.html","page":"MgCr2O4 at Finite Temperature","title":"MgCr2O4 at Finite Temperature","text":"(Image: )","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"EditURL = \"../../../../examples/spinw_tutorials/SW18_Distorted_kagome.jl\"","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html#SW18-Distorted-kagome","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"","category":"section"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"This is a Sunny port of SpinW Tutorial 18, originally authored by Goran Nilsen and Sandor Toth. This tutorial illustrates spin wave calculations for KCu₃As₂O₇(OD)₃. The Cu ions are arranged in a distorted kagome lattice, and exhibit an incommensurate helical magnetic order, as described in G. J. Nilsen, et al., Phys. Rev. B 89, 140412 (2014). The model follows Toth and Lake, J. Phys.: Condens. Matter 27, 166002 (2015).","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Build the distorted kagome crystal, with spacegroup 12.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(10.2, 5.94, 7.81, 90, 117.7, 90)\npositions = [[0, 0, 0], [1/4, 1/4, 0]]\ntypes = [\"Cu1\", \"Cu2\"]\ncryst = Crystal(latvecs, positions, 12; types, setting=\"b1\")\nview_crystal(cryst)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Define the interactions.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"moments = [1 => Moment(s=1/2, g=2), 3 => Moment(s=1/2, g=2)]\nsys = System(cryst, moments, :dipole, seed=0)\nJ = -2\nJp = -1\nJab = 0.75\nJa = -J/.66 - Jab\nJip = 0.01\nset_exchange!(sys, J, Bond(1, 3, [0, 0, 0]))\nset_exchange!(sys, Jp, Bond(3, 5, [0, 0, 0]))\nset_exchange!(sys, Ja, Bond(3, 4, [0, 0, 0]))\nset_exchange!(sys, Jab, Bond(1, 2, [0, 0, 0]))\nset_exchange!(sys, Jip, Bond(3, 4, [0, 0, 1]))","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Use minimize_spiral_energy! 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 invariant, and the axis vector is arbitrary. In other cases, a good axis will frequently be determined from symmetry considerations.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"axis = [0, 0, 1]\nrandomize_spins!(sys)\nk = minimize_spiral_energy!(sys, axis; k_guess=randn(3))\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"If successful, the optimization process will find one two propagation wavevectors, ±k_ref, with opposite chiralities. In this system, the spiral_energy_per_site is independent of chirality.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"k_ref = [0.785902495, 0.0, 0.107048756]\nk_ref_alt = [1, 0, 1] - k_ref\n@assert isapprox(k, k_ref; atol=1e-6) || isapprox(k, k_ref_alt; atol=1e-6)\n@assert spiral_energy_per_site(sys; k, axis) ≈ -0.78338383838","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Check the energy with a real-space calculation using a large magnetic cell. First, we must determine a lattice size for which k becomes approximately commensurate.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"suggest_magnetic_supercell([k_ref]; tol=1e-3)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Resize the system as suggested, and perform a real-space calculation. Working with a commensurate wavevector increases the energy slightly. The precise value might vary from run-to-run due to trapping in a local energy minimum.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"new_shape = [14 0 1; 0 1 0; 0 0 2]\nsys2 = reshape_supercell(sys, new_shape)\nrandomize_spins!(sys2)\nminimize_energy!(sys2)\nenergy_per_site(sys2)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Return to the original system (with a single chemical cell) and construct SpinWaveTheorySpiral for calculations on the incommensurate spiral phase.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"measure = ssf_perp(sys; apply_g=false)\nswt = SpinWaveTheorySpiral(sys; measure, k, axis)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"qs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"Plot the powder-averaged intensities","category":"page"},{"location":"examples/spinw/SW18_Distorted_kagome.html","page":"SW18 - Distorted kagome","title":"SW18 - Distorted kagome","text":"radii = range(0, 2, 100) # (1/Å)\nenergies = range(0, 6, 200)\nkernel = gaussian(fwhm=0.05)\nres = powder_average(cryst, radii, 400) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html#Enforcing-the-quantum-sum-rule-with-moment-renormalization","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"","category":"section"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"AUTHOR: David Dahlbom (dahlbomda@ornl.gov), DATE: August 29, 2024 (Sunny 0.7.0)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"One goal of the Sunny project is to extend classical techniques to incorporate a greater number of quantum effects. The generalization of the Landau-Lifshitz (LL) equations from SU(2) to SU(N) coherent states is the cornerstone of this approach [1], but Sunny includes a number of other \"classical-to-quantum\" corrections. For example, in the zero-temperature limit, there is a well-known correspondence between Linear Spin Wave Theory (LSWT) and the quantization of the normal modes of the linearized LL equations. This allows the dynamical spin structure factor (DSSF) that would be calculated with LSWT, mathcalS_mathrmQ(mathbfq omega), to be recovered from a DSSF that has been calculated classically, mathcalS_mathrmcl(mathbfq omega). This is achieved by applying a classical-to-quantum correspondence factor to mathcalS_mathrmcl(mathbfq omega):","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"mathcalS_mathrmQ(mathbfq omega)=frachbaromegak_mathrmB T left1+ n_mathrmB(omegaT) right mathcalS_mathrmcl(mathbfq omega)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Sunny automatically applies this correction when you call intensity_static on a SampledCorrelations and provide a temperature. This will be demonstrated in the code example below.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"The quantum structure factor satisfies a familiar \"zeroth-moment\" sum rule,","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"intint dmathbfqdomegamathcalS_mathrmQ(mathbfq omega) = N_S S(S+1)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"where N_S is the number of sites. An immediate consequence of the correspondence is that the \"corrected\" classical structure factor satisfies the same sum rule:","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"intint dmathbfqdomega frachbaromegak_mathrmB T left1+ n_mathrmB(omegaT) right mathcalS_mathrmcl(mathbfq omega) = N_S S(S+1)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Note, however, that this correspondence depends on a harmonic oscillator approximation and only applies near T=0. This is reflected in the fact that the correction factor,","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"frachbaromegak_mathrmB T left1+ n_mathrmB(omegaT) right","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"approaches unity for all omega whenever T grows large. In particular, this means that the corrected classical mathcalS_mathrmcl(mathbfq omega) will no longer satisfy the quantum sum rule at elevated temperatures. It will instead approach the \"classical sum rule\":","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"lim_Trightarrowinftyintint dmathbfqdomega frachbaromegak_mathrmB T left1+ n_mathrmB(omegaT) right mathcalS_mathrmcl(mathbfq omega) = N_S S^2\n","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"A simple approach to maintaining a classical-to-quantum correspondence at elevated temperatures is to renormalize the classical magnetic moments so that the quantum sum rule is satisfied. The renormalization factor can be determinied analytically in the infinite temperature limit [2]. For an arbitrary temperature, however, it must be determined empirically [3]. While determining an appropriate rescaling factor can be computationally expensive, Sunny makes it straightforward to evaluate spectral sums and apply moment renormalization, as shown below. One approach to determining the rescaling factors themselves is demonstrated in the sample code here.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html#Evaluating-spectral-sums-in-Sunny","page":"Enforcing the quantum sum rule with moment renormalization","title":"Evaluating spectral sums in Sunny","text":"","category":"section"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"We'll begin by building a spin system representing the effective Spin-1 compound FeI₂. The functions for doing this are imported from kappa_supplementals.jl, available for download here.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"using Sunny, LinearAlgebra\ninclude(joinpath(@__DIR__, \"kappa_supplementals.jl\"))\n\ndims = (8, 8, 4)\nseed = 102\nunits = Units(:meV, :angstrom)\nsys, cryst = FeI2_sys_and_cryst(dims; seed);","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"We will next estimate mathcalS_mathrmcl(mathbfq omega) using classical dynamics. (For more details on setting up such a calculation, see the tutorials in the official Sunny documentation.)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"# Parameters for generating equilbrium samples.\ndt_therm = 0.004 # Step size for Langevin integrator\ndur_therm = 10.0 # Safe thermalization time\ndamping = 0.1 # Phenomenological coupling to thermal bath\nkT = 0.3 * units.K\nlangevin = Langevin(dt_therm; damping, kT) # Langevin integrator\n\n# Parameters for sampling correlations.\ndt = 0.025 # Integrator step size for dissipationless trajectories\nnsamples = 3 # Number of dynamical trajectories to collect for estimating S(𝐪,ω)\nenergies = range(0, 10, 200); # Energies to resolve, in meV, when calculating the dynamics","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Since FeI₂ is a Spin-1 material, we will use the SU(2S+1=3) formalism and require a set of N^2-1=8 observables to calculate the total spectral weight.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Sx, Sy, Sz = spin_matrices(1) # Spin-1 representation of spin operators\nobservables = [\n\n # Dipoles\n Sx,\n Sy,\n Sz,\n\n # Quadrupoles\n -(Sx*Sz + Sz*Sx),\n -(Sy*Sz + Sz*Sy),\n Sx^2 - Sy^2,\n Sx*Sy + Sy*Sx,\n √3 * Sz^2 - I*2/√3,\n];","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"At the moment, Sunny does not expose a high-level interface for working with custom observables such as these. As a workaround, we will write low-level code that accesses the internal Sunny datastructure Sunny.MeasureSpec. The notation Sunny.* indicates that this functionality is not part of the public interface and is subject to change in future Sunny versions.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Building a Sunny.MeasureSpec requires the following:","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"An array containing a set of N observables for each site of the system.\nA vector of tuples (n m), with 1 = n m = N. Each tuple specifies a pair of observables. Together these determine which correlations will be calculated.\nA function for reducing these correlation pairs into a final intensity.\nA list of form factors.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"The Sunny.MeasureSpec below sums over the autocorrelations of each observable and disables form factor corrections.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"observable_field = fill(Hermitian(zeros(ComplexF64, 3, 3)), length(observables), size(sys.coherents)...);\nfor site in Sunny.eachsite(sys), μ in axes(observables, 1)\n observable_field[μ, site] = Hermitian(observables[μ])\nend\ncorr_pairs = [(i, i) for i in 1:length(observables)]\ncombiner(_, data) = real(sum(data))\nmeasure = Sunny.MeasureSpec(observable_field, corr_pairs, combiner, [one(FormFactor)]);","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Finally, we can construct a SampledCorrelations and perform the calculations.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"sc = SampledCorrelations(sys; dt, energies, measure)\n\n# Thermalize and add several samples\nfor _ in 1:5_000\n step!(sys, langevin)\nend\n\nfor _ in 1:nsamples\n # Decorrelate sample\n for _ in 1:2_000\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"sc now contains an estimate of mathcalS_mathrmcl(mathbfq omega). We next wish to evaluate the total spectral weight. We are working on a finite lattice and using discretized dynamics, so the integral will reduce to a sum. Since we'll be evaluating this sum repeatedly, we'll define a function to do this. (Note that this function only works on Bravais lattices – To evaluate spectral sums on a decorated lattice, the sum rule needs to be evaluated on each sublattice individually!)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"function total_spectral_weight(sc::SampledCorrelations; kT = nothing)\n # Retrieve all available discrete wave vectors in the equivalent of\n # one Brillouin zone.\n qs = Sunny.available_wave_vectors(sc)[:]\n\n # Calculate the intensities. Note that we must include negative energies to\n # evaluate the total spectral weight.\n is = intensities(sc, qs; energies=:available_with_negative, kT)\n\n return sum(is.data * sc.Δω)\nend;","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Now evaluate the total spectral weight without temperature corrections.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"total_spectral_weight(sc) / (prod(sys.dims))","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"1.333333333333334","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"The result is 4/3, which is the expected \"classical\" sum rule. This reference can be established by evaluating sum_alphalangle Zvert T^alpha vert Z rangle^2 for any SU(3) coherent state Z, with T^alpha a complete set of generators of SU(3) – for example, the observables above. However, the quantum sum rule is in fact 16/3, as can be determined by directly calculating sum_alpha(T^alpha)^2.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Now let's try again, this time applying the classical-to-quantum correspondence factor by providing the simulation temperature.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"total_spectral_weight(sc; kT) / prod(sys.dims)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"5.450820794092413","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"This is relatively close to 16/3. So, at low temperatures, application of the classical-to-quantum correspondence factor yields results that (approximately) satisfy the quantum sum rule.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"This will no longer hold at higher temperatures. Let's repeat the above experiment with a simulation temperature above T_N=305.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"sys, cryst = FeI2_sys_and_cryst(dims; seed)\nkT = 3.5 * units.K\nlangevin = Langevin(dt_therm; damping, kT)\nsc = SampledCorrelations(sys; dt, energies, measure)\n\n# Thermalize\nfor _ in 1:5_000\n step!(sys, langevin)\nend\n\nfor _ in 1:nsamples\n # Decorrelate sample\n for _ in 1:2_000\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Evaluating the sum without the classical-to-quantum correction factor will again give 4/3, as you can easily verify. Let's examine the result with the correction:","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"total_spectral_weight(sc; kT) / prod(sys.dims)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"2.9374993339227875","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"While this is larger than the classical value of 4/3, it is still substantially short of the quantum value of 16/3.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html#Implementing-moment-renormalization","page":"Enforcing the quantum sum rule with moment renormalization","title":"Implementing moment renormalization","text":"","category":"section"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"One way to enforce the quantum sum rule is by simply renormalizing the magnetic moments. In Sunny, this can be achieved by calling set_spin_rescaling!(sys, κ), where κ is the desired renormalization. Let's repeat the calculation above at the same temperature, this time setting κ=125.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"sys, cryst = FeI2_sys_and_cryst(dims; seed)\nsc = SampledCorrelations(sys; dt, energies, measure)\nκ = 1.25\n\n# Thermalize\nfor _ in 1:5_000\n step!(sys, langevin)\nend\n\nfor _ in 1:nsamples\n # Generate new equilibrium sample.\n for _ in 1:2_000\n step!(sys, langevin)\n end\n\n # Renormalize magnetic moments before collecting a time-evolved sample.\n set_spin_rescaling!(sys, κ)\n\n # Generate a trajectory and calculate correlations.\n add_sample!(sc, sys)\n\n # Turn off κ renormalization before generating a new equilibrium sample.\n set_spin_rescaling!(sys, 1.0)\nend","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Finally, we evaluate the sum.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"total_spectral_weight(sc; kT) / prod(sys.dims)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"5.142433967821603","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"The result is something slightly greater than 5, substantially closer to the expected quantum sum rule. We can now adjust kappa and iterate until we reach a value sufficiently close to 16/3. In general, this should be done while collecting substantially more statistics.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"Note that kappa (T) needs to be determined empirically for each model. A detailed example, demonstrating the calculations used in [3], is available here.","category":"page"},{"location":"examples/contributed/kappa_tutorial.html#References","page":"Enforcing the quantum sum rule with moment renormalization","title":"References","text":"","category":"section"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"[1] - H. Zhang, C. D. Batista, \"Classical spin dynamics based on SU(N) coherent states,\" PRB (2021)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"[2] - T. Huberman, D. A. Tennant, R. A. Cowley, R. Coldea and C. D. Frost, \"A study of the quantum classical crossover in the spin dynamics of the 2D S = 5/2 antiferromagnet Rb2MnF4: neutron scattering, computer simulations and analytic theories\" (2008)","category":"page"},{"location":"examples/contributed/kappa_tutorial.html","page":"Enforcing the quantum sum rule with moment renormalization","title":"Enforcing the quantum sum rule with moment renormalization","text":"[3] - D. Dahlbom, D. Brooks, M. S. Wilson, S. Chi, A. I. Kolesnikov, M. B. Stone, H. Cao, Y.-W. Li, K. Barros, M. Mourigal, C. D. Batista, X. Bai, \"Quantum to classical crossover in generalized spin systems,\" arXiv:2310.19905 (2023)","category":"page"},{"location":"renormalization.html#Interaction-Renormalization","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"A unique feature of Sunny is its support for building classical models where quantum spin is represented as an N-level system, rather than just an expected dipole. This generalization can be important when modeling quantum spin Hamiltonians that include, e.g., a single-ion anisotropy, or a biquadratic coupling between sites. Sunny also supports constraining quantum spin to the space of pure dipoles; in this case, Sunny will automatically perform an interaction strength renormalization that maximizes accuracy.","category":"page"},{"location":"renormalization.html#Local-operators","page":"Interaction Renormalization","title":"Local operators","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"A quantum spin-s state has N = 2s + 1 levels. Each local spin operator hatS^xyz is faithfully represented as an NN matrix. These matrices can be accessed using spin_matrices for a given label s. For example, the Pauli matrices are associated with s = 12.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"When s 12, it is possible to construct multipole moments beyond the spin-dipole. For example,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"S = spin_matrices(3/2)\n@assert S[3] ≈ diagm([3/2, 1/2, -1/2, -3/2])\n@assert S[3]^2 ≈ diagm([9/4, 1/4, 1/4, 9/4])","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"If the operator -S[3]^2 is passed to set_onsite_coupling!, it would set an easy-axis anisotropy in the hatz direction.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Any Hermitian operator can be expanded in the basis of Stevens operators hatmathcalO_kq up to a constant shift. To see this expansion, use print_stevens_expansion:","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"print_stevens_expansion((S[1]^2 + S[2]^2)) # Prints -(1/3)𝒪₂₀ + 5/2","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Alternatively, the same operator could have been constructed directly from stevens_matrices:","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"O = stevens_matrices(3/2)\n@assert S[1]^2 + S[2]^2 ≈ -O[2, 0]/3 + (5/2)*I","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"See below for an explicit definition of Stevens operators as polynomials of the spin operators.","category":"page"},{"location":"renormalization.html#Renormalization-procedure-for-:dipole-mode","page":"Interaction Renormalization","title":"Renormalization procedure for :dipole mode","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Sunny will typically operate in one of two modes: :SUN or :dipole. The former faithfully represents quantum spin as an SU(N) coherent-state which, for our purposes, is an N-component complex vector. In contrast, :dipole mode constrains the coherent-state to the space of pure dipoles. Here, Sunny will automatically renormalize the magnitude of each Stevens operator to achieve maximal consistency with :SUN mode. This procedure was derived in D. Dahlbom et al., [arXiv:2304.03874].","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"By way of illustration, consider a quantum operator hatmathcalH_mathrmlocal giving a single-ion anisotropy for one site. In Stevens operators,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"hatmathcal H_mathrmlocal = sum_k q A_kq hatmathcalO_kq","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"for some coefficients A_kq.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"In :SUN mode, Sunny will faithfully represent hatmathcal H_mathrmlocal as an NN matrix. In :dipole mode, the expected energy langle hatmathcal H_mathrmlocal rangle must somehow be approximated using the expected dipole data.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"One approach is to formally take s to infty, and this yields the traditional classical limit of a spin system. In this limit spin operators commute and expectation values of polynomials become polynomials of expectation values. For example, langle hatS^alpha hatS^betarangle to langle hatS^alpha rangle langle hatS^betarangle, because any corrections are damped by the factor s^-1 to 0. The expectation of a Stevens operator langle hatmathcalO_kq rangle would then become a classical Stevens function mathcalO_kq(langlehatmathbfSrangle), i.e., a polynomial of the same form, but now applied to the expected dipole. Classical Stevens functions are constructed as homogeneous polynomials of order k, because lower-order terms would vanish in the limit s to infty.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"In a real magnetic compound, however, the spin magnitude s is not necessarily large. To obtain a better approximation, one should avoid the formal limit s to infty. Our approach is to start with the full dynamics of SU(N) coherent states, and then constrain it to the space of pure dipole states boldsymbolOmegarangle. The latter are defined as any states where the expected dipole 3-vector,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"boldsymbolOmega langle boldsymbolOmega hatmathbfS boldsymbolOmegarangle","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"has maximal magnitude boldsymbolOmega = s and arbitrary direction.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"For a pure dipole state, group theory dictates that expectations of the Stevens operators can be expressed as a renormalization of the classical Stevens functions,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"langle boldsymbolOmega hatmathcalO_kq boldsymbolOmegarangle = c_k mathcalO_kq(boldsymbolOmega)","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"At fixed k, the two sides must be proportional because they are both spin-k irreducible representations of SO(3). The renormalization factors can be calculated explicitly:","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"beginalign*\nc_1 = 1 \nc_2 = 1-frac12s^-1 \nc_3 = 1-frac32s^-1+frac12s^-2 \nc_4 = 1-3s^-1+frac114s^-2-frac34s^-3 \nc_5 = 1-5s^-1+frac354s^-2-frac254s^-3+frac32s^-4 \nc_6 = 1-frac152s^-1+frac854s^-2-frac2258s^-3+frac1378s^-4-frac154s^-5 \nvdots\nendalign*","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Constrained to the space of dipoles, the expected local energy becomes","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"E_mathrmlocal(boldsymbolOmega) = langle boldsymbolOmega hatmathcal H_mathrmlocal boldsymbolOmegarangle = sum_k q c_k A_kq mathcalO_kq(boldsymbolOmega)","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"It can be shown that SU(N) dynamics reduces to the usual Landau-Lifshitz dynamics of dipoles, but involving E_mathrmlocal(boldsymbolOmega) as the classical Hamiltonian. The renormalization factors c_k can therefore be interpreted as a correction to the traditional large-s classical limit.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Renormalization also applies to the coupling between different sites. In Sunny, couplings will often be expressed as a polynomial of spin operators using set_pair_coupling!, but any such coupling can be decomposed as sum of tensor products of Stevens operators. Without loss of generality, consider a single coupling between two Stevens operators hatmathcalH_mathrmcoupling = hatmathcalO_kq otimes hatmathcalO_kq along a bond connecting sites i and j. Upon constraining to pure dipole states boldsymbolOmega_irangle and boldsymbolOmega_jrangle, the expected energy takes the form E_mathrmcoupling = c_k c_k mathcalO_kq(boldsymbolOmega_i) mathcalO_kq(boldsymbolOmega_j), which now involves a product of renormalized Stevens functions. ","category":"page"},{"location":"renormalization.html#Use-:dipole_large_s-mode-to-disable-renormalization","page":"Interaction Renormalization","title":"Use :dipole_large_s mode to disable renormalization","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Although we generally recommend the above renormalization procedure, there are circumstances where it is not desirable. Examples include reproducing a model-system study, or describing a micromagnetic system for which the stoinfty limit is a good approximation. To simulate dipoles without interaction strength renormalization, construct a System using the mode :dipole_large_s instead of :dipole. Symbolic operators in the large-s limit can be constructed by passing Inf to either spin_matrices or stevens_matrices.","category":"page"},{"location":"renormalization.html#Definition-of-Stevens-operators","page":"Interaction Renormalization","title":"Definition of Stevens operators","text":"","category":"section"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"The Stevens operators hatmathcalO_kq are defined as polynomials of angular momentum operators hatS_xyz in some spin-s representation.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Using","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"beginalign*\nX = mathbfhatS cdot mathbfhatS = s (s+1) \nhatS_pm = hatS_x pm i hatS_y \nphi_+ = frac14quad phi_- = frac14 i\nendalign*","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"the relevant Stevens operators are defined as,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"beginalign*\nhatmathcalO_00 =1\n\nhatmathcalO_1pm1 =phi_pm(hatS_+pmhatS_-)+mathrmhc\nhatmathcalO_10 =hatS_z\n\nhatmathcalO_2pm2 =phi_pm(hatS_+^2pmhatS_-^2)+mathrmhc\nhatmathcalO_2pm1 =phi_pm(hatS_+pmhatS_-)hatS_z+mathrmhc\nhatmathcalO_20 =3hatS_z^2-X\n\nhatmathcalO_3pm3 =phi_pm(hatS_+^3pmhatS_-^3)+mathrmhc\nhatmathcalO_3pm2 =phi_pm(hatS_+^2pmhatS_-^2)hatS_z+mathrmhc\nhatmathcalO_3pm1 =phi_pm(hatS_+pmhatS_-)(5hatS_z^2-X-12)+mathrmhc\nhatmathcalO_30 =5hatS_z^3-(3X-1)hatS_z\n\nhatmathcalO_4pm4 =phi_pm(hatS_+^4pmhatS_-^4)+mathrmhc\nhatmathcalO_4pm3 =phi_pm(hatS_+^3pmhatS_-^3)hatS_z+mathrmhc\nhatmathcalO_4pm2 =phi_pm(hatS_+^2pmhatS_-^2)(7hatS_z^2-(X+5))+mathrmhc\nhatmathcalO_4pm1 =phi_pm(hatS_+pmhatS_-)(7hatS_z^3-(3X+1)hatS_z)+mathrmhc\nhatmathcalO_40 =35hatS_z^4-(30X-25)hatS_z^2+(3X^2-6X)\n\nhatmathcalO_5pm5 =phi_pm(hatS_+^5pmhatS_-^5)+mathrmhc\nhatmathcalO_5pm4 =phi_pm(hatS_+^4pmhatS_-^4)hatS_z+mathrmhc\nhatmathcalO_5pm3 =phi_pm(hatS_+^3pmhatS_-^3)(9hatS_z^2-(X+332))+mathrmhc\nhatmathcalO_5pm2 =phi_pm(hatS_+^2pmhatS_-^2)(3hatS_z^3-(X+6)hatS_z)+mathrmhc\nhatmathcalO_5pm1 =phi_pm(hatS_+pmhatS_-)(21hatS_z^4-14XhatS_z^2+(X^2-X+32))+mathrmhc\nhatmathcalO_50 =63hatS_z^5-(70X-105)hatS_z^3+(15X^2-50X+12)hatS_z\n\nhatmathcalO_6pm6 =phi_pm(hatS_+^6pmhatS_-^6)+mathrmhc\nhatmathcalO_6pm5 =phi_pm(hatS_+^5pmhatS_-^5)hatS_z+mathrmhc\nhatmathcalO_6pm4 =phi_pm(hatS_+^4pmhatS_-^4)(11hatS_z^2-X-38)+mathrmhc\nhatmathcalO_6pm3 =phi_pm(hatS_+^3pmhatS_-^3)(11hatS_z^3-(3X+59)hatS_z)+mathrmhc\nhatmathcalO_6pm2 =phi_pm(hatS_+^2pmhatS_-^2)(33hatS_z^4-(18X+123)hatS_z^2+X^2+10X+102)+mathrmhc\nhatmathcalO_6pm1 =phi_pm(hatS_+pmhatS_-)(33hatS_z^5-(30X-15)hatS_z^3+(5X^2-10X+12)hatS_z)+mathrmhc\nhatmathcalO_60 =231hatS_z^6-(315X-735)hatS_z^4+(105X^2-525X+294)hatS_z^2-5X^3+40X^2-60X\nendalign*","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"Computer-generated tables of Stevens operators with k 6 are available from C. Rudowicz and C. Y. Chung, J. Phys.: Condens. Matter 16, 5825 (2004), but these typically do not appear in magnetic simulations.","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"The case k=1 gives the dipole operators,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"(hatmathcalO_11 hatmathcalO_10 hatmathcalO_1-1) = (hatS_x hatS_z hatS_y)","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"The case k=2 gives the quadrupole operators,","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"(hatmathcalO_22 dots hatmathcalO_2-2) = left(hatS_x^2 - hatS_y^2 frachatS_x hatS_z + hatS_z hatS_x2 2hatS_z^2-hatS_x^2-hatS_y^2 frachatS_y hatS_z + hatS_z hatS_y2 hatS_x hatS_y + hatS_y hatS_xright)","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"For each k value, the set of operators hatmathcalO_kq for q = -k dots k form an irreducible representation of the group of rotations O(3). That is, rotation will transform hatmathcalO_kq into a linear combination of hatmathcalO_kq where q varies but k remains fixed. ","category":"page"},{"location":"renormalization.html","page":"Interaction Renormalization","title":"Interaction Renormalization","text":"In taking the large-s limit, each dipole operator is replaced by its expectation value boldsymbolOmega = langle hatmathbfS rangle, and only leading-order terms are retained. The operator hatmathcalO_kq becomes a homogeneous polynomial O_kq(boldsymbolOmega) of order k in the spin components Omega^alpha. One can see these polynomials by constructing stevens_matrices with the argument s = Inf. Due to the normalization constraint, each dipole can be expressed in polar angles, (theta phi). Then the Stevens functions O_kq(boldsymbolOmega) correspond to the spherical harmonic functions Y_l^m(theta phi) where l=k and m=q; this correspondence is valid up to k and q-dependent rescaling factors.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"EditURL = \"../../../examples/09_Disorder_KPM.jl\"","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/09_Disorder_KPM.html#9.-Disordered-system-with-KPM","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"","category":"section"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"This example uses the kernel polynomial method (KPM) to efficiently calculate the neutron scattering spectrum of a disordered triangular antiferromagnet. The model is inspired by YbMgGaO4, as studied in Paddison et al, Nature Phys., 13, 117–122 (2017) and Zhu et al, Phys. Rev. Lett. 119, 157201 (2017). Disordered occupancy of non-magnetic Mg/Ga sites can be modeled as a stochastic distribution of exchange constants and g-factors. Including this disorder introduces broadening of the spin wave spectrum.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Set up minimal triangular lattice system. Include antiferromagnetic exchange interactions between nearest neighbor bonds. Energy minimization yields the magnetic ground state with 120° angles between spins in triangular plaquettes.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"latvecs = lattice_vectors(1, 1, 10, 90, 90, 120)\ncryst = Crystal(latvecs, [[0, 0, 0]])\nsys = System(cryst, [1 => Moment(s=1/2, g=1)], :dipole; dims=(3, 3, 1))\nset_exchange!(sys, +1.0, Bond(1, 1, [1,0,0]))\n\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; color=[S[3] for S in sys.dipoles], ndims=2)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Select a 𝐪-space path for the spin wave calculations.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"qs = [[0, 0, 0], [1/3, 1/3, 0], [1/2, 0, 0], [0, 0, 0]]\nlabels = [\"Γ\", \"K\", \"M\", \"Γ\"]\npath = q_space_path(cryst, qs, 150; labels)\nkernel = lorentzian(fwhm=0.4);\nnothing #hide","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Perform a traditional spin wave calculation. The spectrum shows sharp modes associated with coherent excitations about the K-point ordering wavevector, 𝐪 = 13 13 0.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"energies = range(0.0, 3.0, 150)\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Use repeat_periodically to enlarge the system by a factor of 10 in each dimension. Use to_inhomogeneous to disable symmetry constraints, and allow for the addition of disordered interactions.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"sys_inhom = to_inhomogeneous(repeat_periodically(sys, (10, 10, 1)))","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Use symmetry_equivalent_bonds to iterate over all nearest neighbor bonds of the inhomogeneous system. Modify each AFM exchange with a noise term that has variance of 1/3. The newly minimized energy configuration allows for long wavelength modulations on top of the original 120° order.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"for (site1, site2, offset) in symmetry_equivalent_bonds(sys_inhom, Bond(1,1,[1,0,0]))\n noise = randn()/3\n set_exchange_at!(sys_inhom, 1.0 + noise, site1, site2; offset)\nend\n\nminimize_energy!(sys_inhom, maxiters=5_000)\nplot_spins(sys_inhom; color=[S[3] for S in sys_inhom.dipoles], ndims=2)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Traditional spin wave theory calculations become impractical for large system sizes. Significant acceleration is possible with the kernel polynomial method. Enable it by selecting SpinWaveTheoryKPM in place of the traditional SpinWaveTheory. Using KPM, the cost of an intensities calculation becomes linear in system size and scales inversely with the width of the line broadening kernel. Error tolerance is controlled through the dimensionless tol parameter. A relatively small value, tol = 0.01, helps to resolve the large intensities near the ordering wavevector. The alternative choice tol = 0.1 would be twice faster, but would introduce significant numerical artifacts.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Observe from the KPM calculation that disorder in the nearest-neighbor exchange serves to broaden the discrete excitation bands into a continuum.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"swt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.01)\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Now apply a magnetic field of magnitude 7.5 (energy units) along the global z axis. This field fully polarizes the spins. Because gap opens, a larger tolerance of tol = 0.1 can be used to accelerate the KPM calculation without sacrificing much accuracy. The resulting spin wave spectrum shows a sharp mode at the Γ-point (zone center) that broadens into a continuum along the K and M points (zone boundary).","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"set_field!(sys_inhom, [0, 0, 7.5])\nrandomize_spins!(sys_inhom)\nminimize_energy!(sys_inhom)\n\nenergies = range(0.0, 9.0, 150)\nswt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.1)\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"Add disorder to the z-component of each magnetic moment g-tensor. This further broadens intensities, now across the entire path. Some intensity modulation within the continuum is also apparent. This modulation is a finite-size effect, and would be mitigated by enlarging the system beyond 30×30 chemical cells.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"for site in eachsite(sys_inhom)\n noise = randn()/6\n sys_inhom.gs[site] = [1 0 0; 0 1 0; 0 0 1+noise]\nend\n\nswt = SpinWaveTheoryKPM(sys_inhom; measure=ssf_perp(sys_inhom), tol=0.1)\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"For reference, the equivalent non-disordered system shows a single coherent mode.","category":"page"},{"location":"examples/09_Disorder_KPM.html","page":"9. Disordered system with KPM","title":"9. Disordered system with KPM","text":"set_field!(sys, [0, 0, 7.5])\nrandomize_spins!(sys)\nminimize_energy!(sys)\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities(swt, path; energies, kernel)\nplot_intensities(res)","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"EditURL = \"../../../../examples/spinw_tutorials/SW07_k0_kagome_AFM.jl\"","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html#SW07-k0-kagome-antiferromagnet","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"","category":"section"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"This is a Sunny port of SpinW Tutorial 7, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the kagome lattice with antiferromagnetic interactions, with ordering wavevector of 𝐤 = 0, and relative rotation 120° between sublattices","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Define the chemical cell of a kagome lattice with spacegroup 147 (P-3).","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 8, 90, 90, 120)\ncryst = Crystal(latvecs, [[1/2, 0, 0]], 147)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Construct a spin system with nearest and next-nearest neighbor antiferromagnetic interactions. Energy minimization determines a 𝐤 = 0 magnetic order with 120° rotation between the three sublattices. The overall global rotation in spin-space is arbitrary.","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ1 = 1.0\nJ2 = 0.11\nset_exchange!(sys, J1, Bond(2, 3, [0, 0, 0]))\nset_exchange!(sys, J2, Bond(2, 1, [0, 0, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"Calculate and plot the powder averaged spectrum","category":"page"},{"location":"examples/spinw/SW07_k0_kagome_AFM.html","page":"SW07 - k=0 kagome antiferromagnet","title":"SW07 - k=0 kagome antiferromagnet","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 2.5, 200)\nkernel = gaussian(fwhm=0.02)\nres = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"EditURL = \"../../../../examples/spinw_tutorials/SW05_Simple_kagome_FM.jl\"","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html#SW05-Simple-kagome-ferromagnet","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"","category":"section"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"This is a Sunny port of SpinW Tutorial 5, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the kagome lattice with a nearest-neighbor ferromagnetic coupling.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Define the chemical cell. By specifying spacegroup 147 (P-3), Sunny will propagate the position [1/2, 0, 0] to the three symmetry-equivalent sites of the kagome unit cell.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 5, 90, 90, 120)\npositions = [[1/2, 0, 0]]\ncryst = Crystal(latvecs, positions, 147)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Another way to construct the kagome lattice is to provide all three site positions of the chemical cell, and allow Sunny to infer the largest possible group of symmetry operations. In this case, Sunny infers spacegroup 191 (P6/mmm). Because 191 has more symmetry operations than 147, it will impose more constraints on the allowed 3×3 exchange matrices. Isotropic Heisenberg exchange, however, is always allowed.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"positions = [[1/2, 0, 0], [0, 1/2, 0], [1/2, 1/2, 0]]\ncryst2 = Crystal(latvecs, positions)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"View the kagome lattice","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"view_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Construct a spin system with nearest-neighbor ferromagnetic interactions.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ = -1.0\nset_exchange!(sys, J, Bond(2, 3, [0, 0, 0]))","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Energy minimization yields the expected ferromagnetic order. Each site participates in 4 bonds, which contributes energy 4J/2.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nenergy_per_site(sys)\n@assert energy_per_site(sys) ≈ 4J/2\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[-1/2, 0, 0], [0, 0, 0], [1/2, 1/2, 0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"Calculate and plot the powder average with two different magnitudes of Gaussian line-broadening. Pick an explicit intensity colorrange (as a density in meV) so that the two color scales are consistent.","category":"page"},{"location":"examples/spinw/SW05_Simple_kagome_FM.html","page":"SW05 - Simple kagome ferromagnet","title":"SW05 - Simple kagome ferromagnet","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 6.5, 200)\nres1 = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel=gaussian(fwhm=0.02))\nend\nres2 = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel=gaussian(fwhm=0.25))\nend\n\nfig = Figure(size=(768, 800))\nplot_intensities!(fig[1, 1], res1; units, colorrange=(0,10), title=\"FWHM 0.02 meV\")\nplot_intensities!(fig[2, 1], res2; units, colorrange=(0,10), title=\"FWHM 0.25 meV\")\nfig","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"EditURL = \"../../../../examples/spinw_tutorials/SW09_k0_kagome_AFM_DM.jl\"","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html#SW09-k0-kagome-AFM-and-DM","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"","category":"section"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"This is a Sunny port of SpinW Tutorial 9, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the kagome lattice with antiferromagnetic and DM interactions, with ordering wavevector of 𝐤 = 0, and relative rotation 120° between sublattices","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"using Sunny, GLMakie, LinearAlgebra","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Define the chemical cell of a kagome lattice with spacegroup 147 (P-3).","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 8, 90, 90, 120)\ncryst = Crystal(latvecs, [[1/2, 0, 0]], 147)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Construct a spin system with antiferromagnetic exchange and a Dzyaloshinskii-Moriya interaction along the first neighbor bond. The symbol I comes from Julia's LinearAlgebra package, and is used to promote the scalar exchange strength 1 meV to a 3×3 exchange matrix. The function dmvec promotes the DM interaction vector 0 0 -008 meV to a 3×3 antisymmetric matrix with nonzero (xy) components, defined with respect to the global Cartesian coordinate system.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ = 1.0*I + dmvec([0, 0, -0.08])","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"As in in Tutorial 7, energy minimization determines a 𝐤 = 0 magnetic order with 120° rotation between the three sublattices.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"set_exchange!(sys, J, Bond(2, 3, [0, 0, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"Calculate and plot the powder averaged spectrum. Because the intensities are dominated by a flat band at about 0.97 meV, select an empirical colorrange that brings the lower-intensity features into focus.","category":"page"},{"location":"examples/spinw/SW09_k0_kagome_AFM_DM.html","page":"SW09 - k=0 kagome AFM and DM","title":"SW09 - k=0 kagome AFM and DM","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 2.5, 200)\nkernel = gaussian(fwhm=0.02)\nres = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units, colorrange=(0,20))","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"EditURL = \"../../../../examples/spinw_tutorials/SW15_Ba3NbFe3Si2O14.jl\"","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html#SW15-BaNbFeSiO","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"","category":"section"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"This is a Sunny port of SpinW Tutorial 15, originally authored by Sandor Toth. It calculates the linear spin wave theory spectrum of Ba₃NbFe₃Si₂O₁₄.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Load packages","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Specify the Ba₃NbFe₃Si₂O₁₄ Crystal cell following Marty et al., Phys. Rev. Lett. 101, 247201 (2008).","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"units = Units(:meV, :angstrom)\na = b = 8.539 # (Å)\nc = 5.2414\nlatvecs = lattice_vectors(a, b, c, 90, 90, 120)\ntypes = [\"Fe\", \"Nb\", \"Ba\", \"Si\", \"O\", \"O\", \"O\"]\npositions = [[0.24964,0,0.5], [0,0,0], [0.56598,0,0], [2/3,1/3,0.5220],\n [2/3,1/3,0.2162], [0.5259,0.7024,0.3536], [0.7840,0.9002,0.7760]]\nlangasite = Crystal(latvecs, positions, 150; types)\ncryst = subcrystal(langasite, \"Fe\")\nview_crystal(cryst)","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Create a System and set exchange interactions as parametrized in Loire et al., Phys. Rev. Lett. 106, 207201 (2011).","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"sys = System(cryst, [1 => Moment(s=5/2, g=2)], :dipole; seed=0)\nJ₁ = 0.85\nJ₂ = 0.24\nJ₃ = 0.053\nJ₄ = 0.017\nJ₅ = 0.24\nset_exchange!(sys, J₁, Bond(3, 2, [1,1,0]))\nset_exchange!(sys, J₄, Bond(1, 1, [0,0,1]))\nset_exchange!(sys, J₂, Bond(1, 3, [0,0,0]))","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"The final two exchanges are setting according to the desired chirality ϵ_T of the magnetic structure.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"ϵT = -1\nif ϵT == -1\n set_exchange!(sys, J₃, Bond(2, 3, [-1,-1,1]))\n set_exchange!(sys, J₅, Bond(3, 2, [1,1,1]))\nelseif ϵT == 1\n set_exchange!(sys, J₅, Bond(2, 3, [-1,-1,1]))\n set_exchange!(sys, J₃, Bond(3, 2, [1,1,1]))\nelse\n error(\"Chirality must be ±1\")\nend","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"This compound is known to have a spiral order with approximate propagation wavevector 𝐤 0 0 17. Search for this magnetic order with minimize_spiral_energy!. Due to reflection symmetry, one of two possible propagation wavevectors may appear, 𝐤 = 0 0 01426. Note that k_z = 01426 is very close to 17 = 01428.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"axis = [0, 0, 1]\nrandomize_spins!(sys)\nk = minimize_spiral_energy!(sys, axis)","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"We can visualize the full magnetic cell using repeat_periodically_as_spiral, which includes 7 rotated copies of the chemical cell.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"sys_enlarged = repeat_periodically_as_spiral(sys, (1, 1, 7); k, axis)\nplot_spins(sys_enlarged; color=[S[1] for S in sys_enlarged.dipoles])","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"One could perform a spin wave calculation using either SpinWaveTheory on sys_enlarged, or SpinWaveTheorySpiral on the original sys. The latter has some restrictions on the interactions, but allows for our slightly incommensurate wavevector 𝐤.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"measure = ssf_perp(sys)\nswt = SpinWaveTheorySpiral(sys; measure, k, axis)","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Calculate broadened intensities for a path 0 1 L through reciprocal space","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"qs = [[0, 1, -1], [0, 1, -1+1], [0, 1, -1+2], [0, 1, -1+3]]\npath = q_space_path(cryst, qs, 400)\nenergies = range(0, 6, 400)\nres = intensities(swt, path; energies, kernel=gaussian(fwhm=0.25))\nplot_intensities(res; units, saturation=0.7, colormap=:jet, title=\"Scattering intensities\")","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"Use ssf_custom_bm to calculate the imaginary part of mathcalS^2 3(𝐪 ω) - mathcalS^3 2(𝐪 ω). In polarized neutron scattering, it is conventional to express the 3×3 structure factor matrix mathcalS^α β(𝐪 ω) in the Blume-Maleev polarization axis system. Specify the scattering plane 0 K L via the spanning vectors 𝐮 = 0 1 0 and 𝐯 = 0 0 1.","category":"page"},{"location":"examples/spinw/SW15_Ba3NbFe3Si2O14.html","page":"SW15 - Ba₃NbFe₃Si₂O₁₄","title":"SW15 - Ba₃NbFe₃Si₂O₁₄","text":"measure = ssf_custom_bm(sys; u=[0, 1, 0], v=[0, 0, 1]) do q, ssf\n imag(ssf[2,3] - ssf[3,2])\nend\nswt = SpinWaveTheorySpiral(sys; measure, k, axis)\nres = intensities(swt, path; energies, kernel=gaussian(fwhm=0.25))\nplot_intensities(res; units, saturation=0.8, allpositive=false,\n title=\"Im[S²³(q, ω) - S³²(q, ω)]\")","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"EditURL = \"../../../../examples/spinw_tutorials/SW06_Complex_kagome_FM.jl\"","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html#SW06-Complex-kagome-ferromagnet","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"","category":"section"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"This is a Sunny port of SpinW Tutorial 6, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the kagome lattice with multiple competing interactions.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Define the chemical cell of a kagome lattice with spacegroup 147 (P-3).","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(6, 6, 8, 90, 90, 120)\ncryst = Crystal(latvecs, [[1/2, 0, 0]], 147)\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Construct a spin system with strongly ferromagnetic nearest-neighbor interactions, and two additional interactions. There are two symmetry-inequivalent exchange types at distance 6 Å (3rd nearest neighbor). The first type, associated with J3a, is a bond from atom 2 to atom 2 that passes over atom 3. The second type, associated with J3b, is a bond from atom 1 to atom 1 that passes through the center of an \"empty\" hexagon of the kagome lattice.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ1 = -1.0\nJ2 = 0.1\nJ3a = 0.00\nJ3b = 0.17\nset_exchange!(sys, J1, Bond(2, 3, [0, 0, 0]))\nset_exchange!(sys, J2, Bond(2, 1, [0, 0, 0]))\nset_exchange!(sys, J3a, Bond(2, 2, [1, 0, 0]))\nset_exchange!(sys, J3b, Bond(1, 1, [1, 0, 0]))","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Interactively visualize the specified interactions. Red (blue) color indicates FM (AFM).","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"view_crystal(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Energy minimization favors ferromagnetic order.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[-1/2,0,0], [0,0,0], [1/2,1/2,0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"Calculate and plot the powder averaged spectrum. Select an empirical colorrange that brings the lower-intensity features into focus.","category":"page"},{"location":"examples/spinw/SW06_Complex_kagome_FM.html","page":"SW06 - Complex kagome ferromagnet","title":"SW06 - Complex kagome ferromagnet","text":"radii = range(0, 2.5, 200)\nenergies = range(0, 6.5, 200)\nkernel = gaussian(fwhm=0.02)\nres = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units, colorrange=(0,10))","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"EditURL = \"../../../examples/02_LLD_CoRh2O4.jl\"","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#2.-Landau-Lifshitz-dynamics-of-CoRhO-at-finite-*T*","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"In the previous tutorial, we used spin wave theory to calculate the dynamical spin structure factor of CoRh₂O₄. Here, we perform a similar calculation using equilibrium samples from the Boltzmann distribution at finite T. For each sampled spin configuration, we will simulate the classical Landau-Lifshitz spin dynamics and extract dynamical spin-spin correlations. After applying a classical-to-quantum correction factor, the resulting intensities can be compared to inelastic neutron scattering data.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Construct the system as in the previous tutorial. For this antiferromagnetic model on the diamond cubic lattice, the ground state is unfrustrated Néel order.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"using Sunny, GLMakie\n\nunits = Units(:meV, :angstrom)\na = 8.5031 # (Å)\nlatvecs = lattice_vectors(a, a, a, 90, 90, 90)\ncryst = Crystal(latvecs, [[0,0,0]], 227, setting=\"1\")\n\nsys = System(cryst, [1 => Moment(s=3/2, g=2)], :dipole)\nJ = 0.63 # (meV)\nset_exchange!(sys, J, Bond(1, 3, [0,0,0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Use repeat_periodically to extend the system to 10×10×10 chemical unit cells. The ground state Néel order is retained. Increasing the system size further would reduce finite-size artifacts and increase momentum-space resolution, but would also make the simulations slower.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"sys = repeat_periodically(sys, (10, 10, 10))\nplot_spins(sys; color=[S[3] for S in sys.dipoles])","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#Langevin-dynamics-for-sampling","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"Langevin dynamics for sampling","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"We will be using a Langevin spin dynamics to thermalize the system. This dynamics is a variant of the Landau-Lifshitz equation that incorporates noise and dissipation terms, which are linked by a fluctuation-dissipation theorem. The temperature 6 K ≈ 1.38 meV is slightly above ordering for this model. The dimensionless damping magnitude sets a timescale for coupling to the implicit thermal bath; 0.2 is usually a good choice.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"langevin = Langevin(; damping=0.2, kT=16*units.K)","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Use suggest_timestep to select an integration timestep. A dimensionless error tolerance of 1e-2 is usually a good choice. The suggested timestep will vary according to the magnetic configuration. It is reasonable to start from an energy-minimized configuration.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"suggest_timestep(sys, langevin; tol=1e-2)\nlangevin.dt = 0.025;\nnothing #hide","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Now run a Langevin trajectory to sample spin configurations. Keep track of the energy per site at each time step.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"energies = [energy_per_site(sys)]\nfor _ in 1:1000\n step!(sys, langevin)\n push!(energies, energy_per_site(sys))\nend","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"From the relaxed spin configuration, we can learn that dt was a little smaller than necessary; increasing it will make the remaining simulations faster.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"suggest_timestep(sys, langevin; tol=1e-2)\nlangevin.dt = 0.042;\nnothing #hide","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Plot energy versus time using the Makie lines function. The plateau suggests that the system has reached thermal equilibrium.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"lines(energies, color=:blue, figure=(size=(600,300),), axis=(xlabel=\"Timesteps\", ylabel=\"Energy (meV)\"))","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Plot the spins colored by their alignment with a reference spin at the origin. The field sys.dipoles is a 4D array storing the spin dipole data. The first three indices of label the chemical cell, while the fourth index labels an atom within the cell. Note that Julia arrays use 1-based indexing. Thermal fluctuations are apparent in the plot.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"S0 = sys.dipoles[1,1,1,1]\nplot_spins(sys; color=[S'*S0 for S in sys.dipoles])","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#Static-structure-factor","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"Static structure factor","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Use SampledCorrelationsStatic to estimate spatial correlations for configurations in classical thermal equilibrium. Each call to add_sample! will accumulate data for the current spin snapshot.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"formfactors = [1 => FormFactor(\"Co2\")]\nmeasure = ssf_perp(sys; formfactors)\nsc = SampledCorrelationsStatic(sys; measure)\nadd_sample!(sc, sys) # Accumulate the newly sampled structure factor into `sf`","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Collect 20 additional samples. Perform 100 Langevin time-steps between measurements to approximately decorrelate the sample in thermal equilibrium.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"for _ in 1:20\n for _ in 1:100\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Use q_space_grid to define a slice of momentum space H K 0, where H and K each range from -10 to 10 in RLU. This command produces a 200×200 grid of sample points.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"grid = q_space_grid(cryst, [1, 0, 0], range(-10, 10, 200), [0, 1, 0], (-10, 10))","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Calculate and plot the instantaneous structure factor on the slice by integrating over all energy values ω. We employ the appropriate FormFactor for Co2⁺. Selecting saturation = 1.0 sets the color saturation point to the maximum intensity value. This is reasonable because we are above the ordering temperature, and do not have sharp Bragg peaks.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"res = intensities_static(sc, grid)\nplot_intensities(res; saturation=1.0, title=\"Static Intensities at T = 16 K\")","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#Dynamical-structure-factor","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"Dynamical structure factor","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"To collect statistics for the dynamical structure factor intensities mathcalS(𝐪ω) at finite temperature, use SampledCorrelations. It requires a range of energies to resolve, which will be associated with frequencies of the classical spin dynamics. The integration timestep dt can be somewhat larger than that used by the Langevin dynamics.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"dt = 2*langevin.dt\nenergies = range(0, 6, 50)\nsc = SampledCorrelations(sys; dt, energies, measure=ssf_perp(sys))","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Like before, use Langevin dynamics to sample spin configurations from thermal equilibrium. Now, however, each call to add_sample! will run a classical spin dynamics trajectory and measure dynamical correlations. To make the tutorial run quickly, we average over just 5 trajectories. To make a publication quality figure, this number should be significantly increased for better statistics.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"for _ in 1:5\n for _ in 1:100\n step!(sys, langevin)\n end\n add_sample!(sc, sys)\nend","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Select points that define a piecewise-linear path through reciprocal space, and a sampling density.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"qs = [[3/4, 3/4, 0],\n [ 0, 0, 0],\n [ 0, 1/2, 1/2],\n [1/2, 1, 0],\n [ 0, 1, 0],\n [1/4, 1, 1/4],\n [ 0, 1, 0],\n [ 0, -4, 0]]\npath = q_space_path(cryst, qs, 500)","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Calculate and plot the intensities along this path.","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"res = intensities(sc, path; energies, langevin.kT)\nplot_intensities(res; units, title=\"Intensities at 16 K\")","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html#Powder-averaged-intensity","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"Powder averaged intensity","text":"","category":"section"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"Define spherical shells in reciprocal space via their radii, in absolute units of 1/Å. For each shell, calculate and average the intensities at 350 𝐪-points","category":"page"},{"location":"examples/02_LLD_CoRh2O4.html","page":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","title":"2. Landau-Lifshitz dynamics of CoRh₂O₄ at finite T","text":"radii = range(0, 3.5, 200) # (1/Å)\nres = powder_average(cryst, radii, 350) do qs\n intensities(sc, qs; energies, langevin.kT)\nend\nplot_intensities(res; units, title=\"Powder Average at 16 K\")","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"EditURL = \"../../../../examples/spinw_tutorials/SW19_Different_Ions.jl\"","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html#SW19-Different-magnetic-ions","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"","category":"section"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"This is a Sunny port of SpinW Tutorial 19, originally authored by Bjorn Fak and Sandor Toth. This tutorial illustrates how to eliminate magnetic contributions from a subset of ions via the special value zero(FormFactor).","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Build a crystal with Cu²⁺ and Fe²⁺ ions.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"units = Units(:meV, :angstrom)\na = 3.0\nb = 8.0\nc = 4.0\nlatvecs = lattice_vectors(a, b, c, 90, 90, 90)\npositions = [[0, 0, 0], [0, 1/2, 0]]\ntypes = [\"Cu2\", \"Fe2\"]\ncryst = Crystal(latvecs, positions, 1; types)\nview_crystal(cryst)","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Set exchange interactions.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"J_Cu_Cu = 1.0\nJ_Fe_Fe = 1.0\nJ_Cu_Fe = -0.1\nmoments = [1 => Moment(s=1/2, g=2), 2 => Moment(s=2, g=2)]\nsys = System(cryst, moments, :dipole; dims=(2, 1, 1), seed=0)\nset_exchange!(sys, J_Cu_Cu, Bond(1, 1, [-1, 0, 0]))\nset_exchange!(sys, J_Fe_Fe, Bond(2, 2, [-1, 0, 0]))\nset_exchange!(sys, J_Cu_Fe, Bond(2, 1, [0, 1, 0]))\nset_exchange!(sys, J_Cu_Fe, Bond(1, 2, [0, 0, 0]))","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Find and plot a minimum energy configuration.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys)","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Define a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"qs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 400)","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Plot different pair correlation intensities by varying the FormFactor on different atom types. Indices 1 and 2 refer to atoms in the original chemical, and are propagated by symmetry. The special \"zero\" form factor effectively removes the spin moment from the calculation.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"fig = Figure(size=(768,600))\n\nformfactors = [1 => FormFactor(\"Cu2\"), 2 => FormFactor(\"Fe2\")]\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys; formfactors))\nres = intensities_bands(swt, path)\nplot_intensities!(fig[1, 1], res; units, title=\"All correlations\")\n\nformfactors = [1 => FormFactor(\"Cu2\"), 2 => zero(FormFactor)]\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys; formfactors))\nres = intensities_bands(swt, path)\nplot_intensities!(fig[1, 2], res; units, title=\"Cu-Cu correlations\")\n\nformfactors = [1 => zero(FormFactor), 2 => FormFactor(\"Fe2\")]\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys; formfactors))\nres = intensities_bands(swt, path)\nplot_intensities!(fig[2, 2], res; units, title=\"Fe-Fe correlations\")\n\nfig","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Calculate quantum corrections δS to spin magnitude, which arise from the zero-point energy of the spin waves. The outputs are ordered following the Site indexing scheme for the system sys: (cell1, cell2, cell3, sublattice), with left-most indices fastest. The two corrections δS -0137 and δS -0578 apply to the Cu and Fe ions, respectively. The larger correction on Fe is due to the relatively weak interchain coupling.","category":"page"},{"location":"examples/spinw/SW19_Different_Ions.html","page":"SW19 - Different magnetic ions","title":"SW19 - Different magnetic ions","text":"Sunny.magnetization_lswt_correction_dipole(swt; atol=1e-4)","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"EditURL = \"../../../examples/07_Dipole_Dipole.jl\"","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/07_Dipole_Dipole.html#7.-Long-range-dipole-interactions","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"","category":"section"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"This example shows how long-range dipole-dipole interactions can affect a spin wave calculation. These interactions can be included two ways: Ewald summation or in real-space with a distance cutoff. The study follows Del Maestro and Gingras, J. Phys.: Cond. Matter, 16, 3339 (2004).","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a pyrochlore crystal from spacegroup 227.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"units = Units(:K, :angstrom)\nlatvecs = lattice_vectors(10.19, 10.19, 10.19, 90, 90, 90)\npositions = [[1/8, 1/8, 1/8]]\ncryst = Crystal(latvecs, positions, 227, setting=\"1\")\nview_crystal(cryst)","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a system and reshape to the primitive cell, which contains four atoms. Add antiferromagnetic nearest neighbor exchange interactions.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"primitive_cell = [1/2 1/2 0; 0 1/2 1/2; 1/2 0 1/2]\nsys = System(cryst, [1 => Moment(s=7/2, g=2)], :dipole; seed=0)\nsys = reshape_supercell(sys, primitive_cell)\nJ1 = 0.304 # (K)\nset_exchange!(sys, J1, Bond(1, 2, [0,0,0]))","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a copy of the system and enable long-range dipole-dipole interactions using Ewald summation.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"sys_lr = clone_system(sys)\nenable_dipole_dipole!(sys_lr, units.vacuum_permeability)","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a copy of the system and add long-range dipole-dipole interactions up to a 5 Å cutoff distance.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"sys_lr_cut = clone_system(sys)\nmodify_exchange_with_truncated_dipole_dipole!(sys_lr_cut, 5.0, units.vacuum_permeability)","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Find an energy minimizing spin configuration accounting for the long-range dipole-dipole interactions. This will arbitrarily select from a discrete set of possible ground states based on the system seed.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"randomize_spins!(sys_lr)\nminimize_energy!(sys_lr)\nplot_spins(sys_lr; ghost_radius=8, color=[:red, :blue, :yellow, :purple])","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Copy this configuration to the other two systems. Note that the original sys has a continuum of degenerate ground states.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"sys.dipoles .= sys_lr.dipoles\nsys_lr_cut.dipoles .= sys_lr.dipoles;\nnothing #hide","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Calculate dispersions for the three systems. The high-symmetry 𝐪-points are specified in reciprocal lattice units with respect to the conventional cubic cell.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"qs = [[0,0,0], [0,1,0], [1,1/2,0], [1/2,1/2,1/2], [3/4,3/4,0], [0,0,0]]\nlabels = [\"Γ\", \"X\", \"W\", \"L\", \"K\", \"Γ\"]\npath = q_space_path(cryst, qs, 500; labels)\n\nmeasure = ssf_trace(sys)\nswt = SpinWaveTheory(sys; measure)\nres1 = intensities_bands(swt, path)\n\nswt = SpinWaveTheory(sys_lr; measure)\nres2 = intensities_bands(swt, path)\n\nswt = SpinWaveTheory(sys_lr_cut; measure)\nres3 = intensities_bands(swt, path);\nnothing #hide","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"Create a panel corresponding to Fig. 2 of Del Maestro and Gingras. Dashed lines show the effect of truncating dipole-dipole interactions at 5 Å. The Del Maestro and Gingras paper underreported the energy scale by a factor of two, and requires slight corrections to its third dispersion band.","category":"page"},{"location":"examples/07_Dipole_Dipole.html","page":"7. Long-range dipole interactions","title":"7. Long-range dipole interactions","text":"fig = Figure(size=(768, 300))\nplot_intensities!(fig[1, 1], res1; units, title=\"Without long-range dipole\")\nax = plot_intensities!(fig[1, 2], res2; units, title=\"With long-range dipole\")\nfor c in eachrow(res3.disp)\n lines!(ax, eachindex(c), c; linestyle=:dash, color=:black)\nend\nfig","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"EditURL = \"../../../../examples/spinw_tutorials/SW03_Frustrated_chain.jl\"","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html#SW03-Frustrated-J1-J2-chain","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"","category":"section"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"This is a Sunny port of SpinW Tutorial 3, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the frustrated J1-J2 chain.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Define the chemical cell for a 1D chain following the SW01 tutorial.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(3, 8, 8, 90, 90, 90)\ncryst = Crystal(latvecs, [[0, 0, 0]])\nview_crystal(cryst; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Construct a spin system with competing nearest-neighbor (FM) and next-nearest-neighbor (AFM) interactions.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)\nJ1 = -1\nJ2 = +2 * abs(J1)\nset_exchange!(sys, J1, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, J2, Bond(1, 1, [2, 0, 0]))","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Assuming a spiral order, optimize the propagation wavevector 𝐤 starting from a random initial guess. Because all interactions are isotropic in spin space, the polarization axis is arbitrary.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"axis = [0, 0, 1]\nrandomize_spins!(sys)\nk = minimize_spiral_energy!(sys, axis; k_guess=randn(3))","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"The first component of the order wavevector 𝐤 has a unique value up to reflection symmetry, 𝐤 -𝐤. The second and third components of 𝐤 are arbitrary for this 1D chain system. In all cases, the minimized energy has a precise value of -33/16 in units of J₁.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"@assert k[1] ≈ 0.2300534561 || k[1] ≈ 1 - 0.2300534561\n@assert spiral_energy_per_site(sys; k, axis) ≈ -33/16 * abs(J1)","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"To view part of the incommensurate spiral spin structure, one can construct an enlarged system with repeat_periodically_as_spiral.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"sys_enlarged = repeat_periodically_as_spiral(sys, (8, 1, 1); k, axis)\nplot_spins(sys_enlarged; ndims=2)","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"Use SpinWaveTheorySpiral on the original sys to calculate the dispersion and intensities for the incommensurate ordering wavevector.","category":"page"},{"location":"examples/spinw/SW03_Frustrated_chain.html","page":"SW03 - Frustrated J1-J2 chain","title":"SW03 - Frustrated J1-J2 chain","text":"swt = SpinWaveTheorySpiral(sys; measure=ssf_perp(sys), k, axis)\nqs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 401)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"EditURL = \"../../../../examples/spinw_tutorials/SW01_FM_Heseinberg_chain.jl\"","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html#SW01-FM-Heisenberg-chain","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"","category":"section"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"This is a Sunny port of SpinW Tutorial 1, originally authored by Goran Nilsen and Sandor Toth. It calculates the spin wave spectrum of the ferromagnetic Heisenberg nearest-neighbor spin chain.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Define a chemical cell for the spin chain lattice. It is tetrahedral, with a short dimension of 3 Å and two long dimensions of 8 Å. Observe that Sunny infers the spacegroup 'P 4/m m m' (123).","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"units = Units(:meV, :angstrom)\na = 3.0\nb = 8.0\nc = 8.0\nlatvecs = lattice_vectors(a, b, c, 90, 90, 90)\npositions = [[0, 0, 0]]\ncryst = Crystal(latvecs, positions)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"View the crystal in 2D. The nearest neighbor bond along the chain is visible, and labeled Bond(1, 1, [1, 0, 0]). The first two atom indices must be 1, because there is only a single atom in the chemical cell. The vector [1, 0, 0] indicates that the bond includes a displacement of 1 𝐚_1 + 0 𝐚_2 + 0 𝐚_3 between chemical cells.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"view_crystal(cryst; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Sunny will always perform symmetry analysis based on the provided crystallographic information. For example, one can see that there are three different symmetry-equivalent classes of bonds up to a distance of 8 Å, and the symmetry-allowed exchange matrices are strongly constrained.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"print_symmetry_table(cryst, 8)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Use the chemical cell to create a spin System with spin s = 1 and a magnetic form factor for Cu¹⁺. In this case, it is only necessary to simulate a single chemical cell. The option :dipole indicates that, following traditional spin wave theory, we are modeling quantum spins using only their expected dipole moments.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Set a nearest neighbor exchange interaction of J = -1 meV between neighboring atoms. That is, the total energy along each bond is J S_i S_i+1. The exchange interaction will be propagated to all symmetry equivalent bonds in the system.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"J = -1\nset_exchange!(sys, J, Bond(1, 1, [1, 0, 0]))","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Find the energy minimum, which is ferromagnetic. The energy per site is -J for this unfrustrated FM order.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nenergy_per_site(sys)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Because the interaction is Heisenberg (isotropic), the minimization procedure selects an arbitrary direction in spin-space.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"plot_spins(sys; ndims=2, ghost_radius=8)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Build a SpinWaveTheory object to measure the dynamical spin-spin structure factor (SSF). Select ssf_perp to project intensities onto the space perpendicular to the momentum transfer 𝐪, which is appropriate for an unpolarized neutron beam.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Define a path from 000 to 100 in reciprocal lattice units (RLU) containing 400 sampled 𝐪-points.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"qs = [[0,0,0], [1,0,0]]\npath = q_space_path(cryst, qs, 400)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Calculate and plot the intensities along this path.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"res = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"Perform a powder average over the intensities for 200 radii between 0 and 2.5 inverse Å. Each radial distance defines a spherical shell in recripocal space, which will be sampled approximately uniformly, involving 1000 sample points. Measure intensities for 200 energy values between 0 and 5 meV. Gaussian line-broadening is applied with a full-width at half-maximum (FWHM) of 0.1 meV. With the above parameters, this calculation takes about a second on a modern laptop. To decrease stochastic error, one can increase the number of sample points on each spherical shell.","category":"page"},{"location":"examples/spinw/SW01_FM_Heseinberg_chain.html","page":"SW01 - FM Heisenberg chain","title":"SW01 - FM Heisenberg chain","text":"radii = range(0, 2.5, 200) # 1/Å\nenergies = range(0, 5, 200) # meV\nkernel = gaussian(fwhm=0.1)\nres = powder_average(cryst, radii, 1000) do qs\n intensities(swt, qs; energies, kernel)\nend\nplot_intensities(res; units)","category":"page"},{"location":"versions.html#Version-History","page":"Version History","title":"Version History","text":"","category":"section"},{"location":"versions.html#v0.7.3","page":"Version History","title":"v0.7.3","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(In development)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fix error in print_symmetry_table for slightly-distorted crystal cells (PR #317).\nStabilize SpinWaveTheoryKPM. It now automatically selects the polynomial order according to an error tolerance.","category":"page"},{"location":"versions.html#v0.7.2","page":"Version History","title":"v0.7.2","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 11, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fix error in SampledCorrelations with a coarse 𝐪-grid. (PR #314).\nFix colorbar in plot_intensities! when all data is uniform (PR #315).\nAn explicit colorrange can be used for plotting intensities_bands.","category":"page"},{"location":"versions.html#v0.7.1","page":"Version History","title":"v0.7.1","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 3, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Correctness fix for scalar biquadratic interactions specified with option biquad to set_exchange!.\nPrototype implementation of entangled units.","category":"page"},{"location":"versions.html#v0.7.0","page":"Version History","title":"v0.7.0","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 30, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"This major release introduces breaking interface changes.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The interface for calculating intensities has been revised to unify functionality across backends. The functions intensities_bands, intensities, and intensities_static no longer expect a \"formula\", and instead take keyword arguments directly. Pair correlations are now specified using ssf_perp and related functions. The constructors SampledCorrelations and SampledCorrelationsStatic replace dynamic_correlations and static_correlations, respectively.\nNew function plot_intensities enables convenient plotting for many types of intensities plots. Mutating variant plot_intensities! enables multi-panel plots.\nOne should now specify a range of 𝐪-points with q_space_path or q_space_grid.\nSpinWaveTheorySpiral is available to perform calculations on generalized spiral structures, which may be incommensurate.\nrepeat_periodically_as_spiral replaces set_spiral_order_on_sublattice! and set_spiral_order!.\nNew convenience functions powder_average and domain_average, which wrap intensities.\nSystem now expects supercell dimensions as a dims keyword argument. Moment replaces SpinInfo. Lower-case s now labels quantum spin. For example, use :dipole_large_s instead of :dipole_large_S.\nIn view_crystal and plot_spins use ndims instead of dims for the number of spatial dimensions.\nBinning features have been removed. Some functionality may be added back in a future release.\nExperimental SpinWaveTheoryKPM feature implements a new algorithm to enable intensities calculations at a computational cost that scales linearly in system size.","category":"page"},{"location":"versions.html#v0.6.1","page":"Version History","title":"v0.6.1","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 2, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Breaking changes: magnetic_moment is now reported in units of the Bohr magneton, μ_B. For model systems where the Zeeman coupling aligns spin dipole with field (e.g., the Ising model convention), create a SpinInfo with g=-1. (PR 284).\nMore flexible Units system. set_external_field! is deprecated in favor of set_field!, which now expects a field in energy units. enable_dipole_dipole! now expects a scale parameter μ_0 μ_B^2 that can be obtained from units.vacuum_permeability.","category":"page"},{"location":"versions.html#v0.6.0","page":"Version History","title":"v0.6.0","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Jun 18, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Various correctness fixes. The magnetic moment is now anti-aligned with the spin dipole (Issue 190), and the wavevector 𝐪 in structure factor intensities mathcalS(𝐪ω) now consistently represents momentum transfer to the sample (Issue 270). The new Example 8 demonstrates a model system where momentum transfers 𝐪 are inequivalent.\nDynamical structure factor intensities now have a precisely defined scale, independent of the calculator (Issue 264). Consequently, color ranges in plots may need to be rescaled.\nCrystal can now infer a chemical unit cell from an mCIF file. System now supports set_dipoles_from_mcif!. Through spglib, one can now standardize any Crystal, with an option to idealize site positions.","category":"page"},{"location":"versions.html#v0.5.11","page":"Version History","title":"v0.5.11","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Jun 2, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fixes for Makie 0.21.","category":"page"},{"location":"versions.html#v0.5.10","page":"Version History","title":"v0.5.10","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(May 27, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"view_crystal called on a System now shows interactions, and optionally the spin or magnetic dipoles.\nInteractions for enable_dipole_dipole! are now supported in linear spin wave theory, with proper Ewald summation. For a faster alternative, the experimental function modify_exchange_with_truncated_dipole_dipole! will accept a real-space cutoff.\nIntensities calculated with dynamic_correlations now avoid \"bleeding artifacts\" at low-energy (long-timescale) modes. See PR 246 for details. This eliminates the need for process_trajectory=:symmetrize.\nWhen passed to intensity_formula, the special value zero(FormFactor) can now be used to disable contributions from a given site. For an example, see the ported SpinW tutorial 19.\nBroadening kernels gaussian and lorentzian now expect a full width at half maximum (fwhm) keyword argument.\nExperimental support for calculations on generalized spiral phases. For an example, see the ported SpinW tutorial 18.\nCorrectness fix for the case where spin-S varies between sites in dipole-mode. In SU(N) mode, however, there is still no support for varying the Hilbert space dimension N between sites.\nCorrectness fix in long-range dipole-dipole interactions for systems with multiple cells.\nCorrectness fix in general biquadratic interactions (beyond scalar) for spin wave theory in dipole-mode.\nCorrectness fix for reading Mantid .nxs files.","category":"page"},{"location":"versions.html#v0.5.9","page":"Version History","title":"v0.5.9","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Mar 25, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Correctness fixes: Structure factor conventions are now uniform across modes and precisely specified. The g-tensor is applied by default (disable with apply_g = false). The intensity is additive with increasing number of magnetic ions in the chemical cell, consistent with SpinW. Issue #235.\nEnhancements to view_crystal. If a bond allows a DM interaction, its orientation will be shown visually. If a System argument is supplied, its exchange interactions will be shown..\nNew function suggest_timestep to assist in performing accurate and efficient simulation of classical spin dynamics. Issue #149.\nScalar biquadratic interactions can again be set in :dipole_large_S mode via the keyword argument biquad of set_exchange!.\nSignificantly speed up dynamic_correlations for crystals with many atoms in the unit cell. Issue #204.\nRenamings: dt replaces Δt and damping replaces λ. This affects Langevin, [ImplicitMidpoint], and dynamic_correlations functions.","category":"page"},{"location":"versions.html#v0.5.8","page":"Version History","title":"v0.5.8","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Jan 4, 2024)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Many bugs in the WGLMakie backend have become apparent, and are being tracked at Issue #211. Emit a warning if WGLMakie is detected, suggesting that GLMakie is preferred.\nVarious improvements to view_crystal. A distance parameter is no longer expected. Cartesian axes now appear as \"compass\" in bottom-left. Custom list of reference bonds can be passed. Toggle to view non-magnetic atoms in root crystal. Atoms now colored using CPK/JMol conventions.","category":"page"},{"location":"versions.html#v0.5.7","page":"Version History","title":"v0.5.7","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Nov 26, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Update form factor coefficients, which now include Mn5.\nFix merge_correlations and the Parallelizing Calculations tutorial.\nRemove internal functions *_primitive_crystal. Instead, it is recommended to use the conventional unit cell, and later call reshape_supercell.\nRequire Makie 0.20. An important new feature is resolution-independent scaling of font sizes. New figures expect size instead of resolution, and no longer accept rescale.","category":"page"},{"location":"versions.html#v0.5.6","page":"Version History","title":"v0.5.6","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Nov 8, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"This release initiates some major enhancements to the user interface in support of generalized SU(N) spin models. See this documentation page for an illustration of the new features. Most existing Sunny 0.5 models will continue to work with deprecation warnings, but these will become hard errors Sunny v0.6.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"General pair couplings are now supported in set_pair_coupling! and set_pair_coupling_at!. :SUN mode supports interactions of any order, but :dipole mode is limited to bilinear and biquadratic coupling of the spin.\nTo perform a calculation with dipoles in the large-S limit, use the new mode :dipole_large_S when constructing a System.\nDeprecate the option biquad to set_exchange!. Use instead set_pair_coupling!, which generalizes beyond the scalar biquadratic.\nDeprecate spin_operators, stevens_operators, large_S_spin_operators and large_S_stevens_operators. Use instead spin_matrices and stevens_matrices, which require a specific spin-S label. To infer this, one can use spin_label.\nRemove unused option energy_tol in SpinWaveTheory.\nAnimated spin dynamics is now possible. Call notify on the result of plot_spins to trigger redrawing of the frame. The argument colorfn to plot_spins supports animation of colors. See example usage for a Heisenberg ferromagnetic.\nAdd set_spin_rescaling! feature, which supports improved spectral measurements at finite-T. This follows the method proposed in Dahlbom et al., [arXiv:2310.19905].","category":"page"},{"location":"versions.html#v0.5.5","page":"Version History","title":"v0.5.5","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 29, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"reshape_supercell now allows reshaping to multiples of the primitive unit cell, which can speed up certain calculations. This is illustrated in the CoRh₂O₄ powder averaging tutorial.\nresize_supercell now allows all resizings.\nAdded energy_per_site.\nset_spiral_order_on_sublattice! cannot work on reshaped systems.\nVarious bug fixes. In particular, an intensity_formula with :full will now uniformly calculate a 3x3 matrix of complex numbers.","category":"page"},{"location":"versions.html#v0.5.4","page":"Version History","title":"v0.5.4","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 11, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Various enhancements to view_crystal. Atoms are now labeled by index, and bonds support interactive inspection (GLMakie only). Font sizes work correctly on Makie v0.20-beta. If using Makie v0.19 on a high-resolution display, pass rescale=1.5 to enlarge font sizes.\nThe function suggest_magnetic_supercell now requires only a list of wavevectors, and will return a 33 matrix that can be programmatically passed to reshape_supercell. The new tolerance parameter tol allows suggest_magnetic_supercell to approximate incommensurate wavevectors with nearby commensurate ones.\nNew functions set_spiral_order! and set_spiral_order_on_sublattice! can be used to initialize a spiral, single-Q order.\nSunny now retains all constant energy shifts that have been introduced by anisotropy operators.\nFix export_vtk functionality.","category":"page"},{"location":"versions.html#v0.5.3","page":"Version History","title":"v0.5.3","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Sep 8, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Add large_S_spin_operators and large_S_stevens_operators to support single-ion anisotropies in dipole mode without renormalization. Set large_S=true in set_exchange! to avoid renormalization of biquadratics.\nview_crystal has been rewritten in Makie.\nplot_spins now expects ghost_radius in physical length units.\nSpinWaveTheory will (currently) error if provided a system with enable_dipole_dipole!.","category":"page"},{"location":"versions.html#v0.5.2","page":"Version History","title":"v0.5.2","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 30, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Form factors for 5d transition ions.\nDownload links for notebooks and scripts on each doc example\nVarious bug fixes.","category":"page"},{"location":"versions.html#v0.5.1","page":"Version History","title":"v0.5.1","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 23, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fix binning edge cases.\nplot_spins accepts resolution argument.","category":"page"},{"location":"versions.html#v0.5.0","page":"Version History","title":"v0.5.0","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Aug 21, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"New features.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Support for Linear Spin Wave Theory in :dipole and :SUN modes. (Thanks Hao Zhang!)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"New function minimize_energy! to efficiently find an optimal configuration of spin dipoles or SU(N) coherent states.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Major refactors and enhancements to intensity calculations. This new interface allows unification between LSWT and classical spin dynamics calculations. This interface allows: Custom observables as local quantum operators, better support for linebroadening, and automatic binning to facilitate comparison with experimental data. See intensity_formula for documentation. Use load_nxs to load experimental neutron scattering data.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Breaking changes.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Require Julia 1.9.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Replace set_anisotropy! with a new function set_onsite_coupling! (and similarly set_onsite_coupling_at!). The latter expects an explicit matrix representation for the local Hamiltonian. This can be constructed, e.g., as a linear combination of stevens_operators, or as a polynomial of spin_operators. To understand the mapping between these two, the new function print_stevens_expansion acts on an arbitrary local operator.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Remove set_biquadratic!. Instead, use an optional keyword argument biquad to set_exchange!.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename DynamicStructureFactor to dynamic_correlations. Similarly, replace InstantStructureFactor with instant_correlations. The return type has been renamed SampledCorrelations to emphasize that the object may be holding thermodynamic samples, which are collected using add_sample!. Upon construction, the SampledCorrelations object will be empty (no initial sample).","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Remove intensities function. Instead, use one of intensities_interpolated or intensities_binned. These will require an intensity_formula, which defines a calculator (e.g., LSWT).","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename connected_path to reciprocal_space_path, which now returns an xticks object that can be used in plotting. Replace spherical_shell with reciprocal_space_shell that functions similarly.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename polarize_spin! to set_dipole! for consistency with set_coherent!. The behavior of the former function is unchanged: the spin at a given site will still be polarized along the provided direction.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename all_sites to eachsite consistent with Julia convention for iterators.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename reshape_geometry to reshape_supercell, which is the fundamental reshaping function. Rename resize_periodically to resize_supercell.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The constructor SpinInfo now requires a g-factor or tensor as a named argument.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The constructor FormFactor no longer accepts an atom index. Instead, the form factors are associated with site-symmetry classes in order of appearance.","category":"page"},{"location":"versions.html#v0.4.3","page":"Version History","title":"v0.4.3","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Jun 23, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Experimental support for linear SpinWaveTheory, implemented in SU(N) mode. This module may evolve rapidly.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Implement renormalization of single-ion anisotropy and biquadratic interactions when in :dipole mode. This makes the model more faithful to the quantum mechanical Hamiltonian, but is also a breaking change.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Various improvements and bugfixes for to_inhomogeneous. Setting inhomogeneous interactions via set_exchange_at! should now infer the correct bond offset direction, or will report an ambiguity error. Ambiguities can be resolved by passing an explicit offset.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The function remove_periodicity! disables periodicity along specified dimensions.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename StaticStructureFactor to InstantStructureFactor.","category":"page"},{"location":"versions.html#v0.4.2","page":"Version History","title":"v0.4.2","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Feb 27, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Introduce LocalSampler, a framework for MCMC sampling with local spin updates.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename print_dominant_wavevectors to print_wrapped_intensities to reduce confusion with the physical instantaneous intensities.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The function spherical_shell now takes a radius in physical units of inverse Å.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"New exported functions global_position, magnetic_moment, all_sites.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Remove all uses of Base.deepcopy which resolves crashes.","category":"page"},{"location":"versions.html#v0.4.1","page":"Version History","title":"v0.4.1","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Feb 13, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The function to_inhomogeneous creates a system that supports inhomogeneous interactions, which can be set using set_exchange_at!, etc.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"set_biquadratic! replaces set_exchange_with_biquadratic!.","category":"page"},{"location":"versions.html#v0.4.0","page":"Version History","title":"v0.4.0","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"(Feb 10, 2023)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"This update includes many breaking changes, and is missing some features of 0.3.0.","category":"page"},{"location":"versions.html#Creating-a-spin-System","page":"Version History","title":"Creating a spin System","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Rename SpinSystem to System. Its constructor now has the form,","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"System(crystal, dims, infos, mode)","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The parameter infos is now a list of SpinInfo objects. Each defines spin angular momentum S = frac12 1 frac32 , and an optional g-factor or tensor.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The parameter mode is one of :SUN or :dipole.","category":"page"},{"location":"versions.html#Setting-interactions","page":"Version History","title":"Setting interactions","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Interactions are now added mutably to an existing System using the following functions: set_external_field!, set_exchange!, set_onsite_coupling!, enable_dipole_dipole!.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"As a convenience, one can use dmvec(D) to convert a DM vector to a 33 antisymmetric exchange matrix.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Fully general single-ion anisotropy is now possible. The function set_onsite_coupling! expects the single ion anisotropy to be expressed as a polynomial in symbolic spin operators 𝒮, or as a linear combination of symbolic Stevens operators 𝒪. For example, an easy axis anisotropy in the direction n may be written D*(𝒮⋅n)^2.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"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.","category":"page"},{"location":"versions.html#Inhomogeneous-field","page":"Version History","title":"Inhomogeneous field","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"An external field can be applied to a single site with set_external_field_at!. ","category":"page"},{"location":"versions.html#Structure-factor-rewrite","page":"Version History","title":"Structure factor rewrite","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The calculation of structure factors has been completely rewritten. For the new interface see the documentation tutorials.","category":"page"},{"location":"versions.html#Various","page":"Version History","title":"Various","text":"","category":"section"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The \"Sampler\" interface is in flux. Langevin replaces both LangevinHeunP and LangevinSampler. Local spin-flip Monte Carlo sampling methods are temporarily broken.\nrepeat_periodically replaces extend_periodically.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"Additional related functions include resize_periodically and reshape_geometry, the latter being fundamental.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"print_symmetry_table replaces print_bond_table().","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"The new function includes the list of symmetry-allowed single ion anisotropies in addition to exchange interactions.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"When reading CIF files, the field _atom_site_label is now used in place of the field _atom_site_type_symbol.","category":"page"},{"location":"versions.html","page":"Version History","title":"Version History","text":"This is required for correctness. The field _atom_site_label is guaranteed to be present, and is guaranteed to be a distinct label for each symmetry-inequivalent site. Code that explicitly referred to site labels (e.g. in calls to subcrystal) will need to be updated to use the new label.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"EditURL = \"../../../../examples/spinw_tutorials/SW14_YVO3.jl\"","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html#SW14-YVO","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"","category":"section"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"This is a Sunny port of SpinW Tutorial 14, originally authored by Sandor Toth. It calculates the spin wave spectrum of YVO₃.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Load packages","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Build an orthorhombic lattice and populate the V atoms according to the pseudocubic unit cell, doubled along the c-axis. The listed spacegroup of the YVO₃ chemical cell is international number 62. It has been observed, however, that the exchange interactions break this symmetry. For this reason, disable all symmetry analysis by selecting spacegroup 1 (P1).","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"units = Units(:meV, :angstrom)\na = 5.2821 / sqrt(2)\nb = 5.6144 / sqrt(2)\nc = 7.5283\nlatvecs = lattice_vectors(a, b, c, 90, 90, 90)\npositions = [[0, 0, 0], [0, 0, 1/2]]\ntypes = [\"V\", \"V\"]\ncryst = Crystal(latvecs, positions, 1; types)","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Create a system following the model of C. Ulrich, et al. PRL 91, 257202 (2003). The mode :dipole_large_s avoids a classical-to-quantum rescaling factor of anisotropy strengths, as needed for consistency with the original fits.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"sys = System(cryst, [1 => Moment(s=1/2, g=2), 2 => Moment(s=1/2, g=2)], :dipole_large_s; dims=(2,2,1))\nJab = 2.6\nJc = 3.1\nδ = 0.35\nK1 = 0.90\nK2 = 0.97\nd = 1.15\nJc1 = [-Jc*(1+δ)+K2 0 -d; 0 -Jc*(1+δ) 0; +d 0 -Jc*(1+δ)]\nJc2 = [-Jc*(1-δ)+K2 0 +d; 0 -Jc*(1-δ) 0; -d 0 -Jc*(1-δ)]\nset_exchange!(sys, Jab, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, Jab, Bond(2, 2, [1, 0, 0]))\nset_exchange!(sys, Jc1, Bond(1, 2, [0, 0, 0]))\nset_exchange!(sys, Jc2, Bond(2, 1, [0, 0, 1]))\nset_exchange!(sys, Jab, Bond(1, 1, [0, 1, 0]))\nset_exchange!(sys, Jab, Bond(2, 2, [0, 1, 0]))\nset_onsite_coupling!(sys, S -> -K1*S[1]^2, 1)\nset_onsite_coupling!(sys, S -> -K1*S[1]^2, 2)","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"When using spacegroup P1, there is no symmetry-propagation of interactions because all bonds are considered inequivalent. One can visualize the interactions in the system by clicking the toggles in the view_crystal GUI.","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"view_crystal(sys)","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Energy minimization yields a Néel order with canting","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"randomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys)","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"Plot the spin wave spectrum along a path","category":"page"},{"location":"examples/spinw/SW14_YVO3.html","page":"SW14 - YVO₃","title":"SW14 - YVO₃","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[0.75, 0.75, 0], [0.5, 0.5, 0], [0.5, 0.5, 1]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"},{"location":"index.html#Overview","page":"Overview","title":"Overview","text":"","category":"section"},{"location":"index.html","page":"Overview","title":"Overview","text":"Sunny is a Julia package for modeling atomic-scale magnetism. It provides powerful tools to study equilibrium and non-equilibrium magnetic phenomena. In particular, it allows estimation of dynamical structure factor intensities, mathcalS(𝐪ω), to support quantitative modeling of experimental scattering data.","category":"page"},{"location":"index.html","page":"Overview","title":"Overview","text":"Features include:","category":"page"},{"location":"index.html","page":"Overview","title":"Overview","text":"Generalized spin dynamics using SU(N) coherent states.\nAbility to specify a crystal from a .cif file or its spacegroup symmetry. Magnetic structures can be read from .mcif files.\nInteractive visualizations of the 3D crystals and magnetic ordering.\nSymmetry analysis to classify allowed interaction terms, and to propagate them by symmetry.\nSingle-ion anisotropy at arbitrary order, which can be specified using Stevens operators or as a polynomial of spin operators.\nMonte Carlo sampling of spin configurations in thermal equilibrium, and optimization tools.\nMeasurements of dynamical correlations. At low temperature, one can use linear spin wave theory and its multi-boson generalization. This generalizes to finite temperatures using the classical dynamics, which allows for strongly nonlinear effects.\nLong-range dipole-dipole interactions accelerated with the fast Fourier transform (FFT).\nSupport for comparison with experimental data: form factor, dipole factor, temperature-dependent classical-to-quantum factors, etc.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"EditURL = \"../../../../examples/spinw_tutorials/SW12_Triangular_easy_plane.jl\"","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html#SW12-Triangular-lattice-with-easy-plane","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"","category":"section"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"This is a Sunny port of SpinW Tutorial 12, originally authored by Sandor Toth. It calculates the spin wave dispersion of a triangular lattice model with antiferromagnetic interactions and easy-plane single-ion anisotropy.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Load packages","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Build a triangular lattice with arbitrary lattice constant of 3 Å.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"latvecs = lattice_vectors(3, 3, 4, 90, 90, 120)\ncryst = Crystal(latvecs, [[0, 0, 0]])","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Build a system with exchange +1 meV along nearest neighbor bonds. Set the lattice size in anticipation of a magnetic ordering with 3×3 cells.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"s = 3/2\nJ1 = +1.0\nsys = System(cryst, [1 => Moment(; s, g=2)], :dipole; dims=(3, 3, 1))\nset_exchange!(sys, J1, Bond(1, 1, [1, 0, 0]))","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Set an easy-axis anisotropy operator +D S_z^2 using set_onsite_coupling!. Important note: When introducing a single-ion anisotropy in :dipole mode, Sunny will automatically include a classical-to-quantum correction factor, as described in the document Interaction Renormalization. For an anisotropy operator that is quadratic in the spin operators, Sunny will automatically renormalize the interaction strength as D (1 - 12s) D. We must \"undo\" Sunny's classical-to-quantum rescaling factor to reproduce the SpinW calculation. Alternatively, renormalization can be disabled by selecting the system mode :dipole_large_s instead of :dipole.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"undo_classical_to_quantum_rescaling = 1 / (1 - 1/2s)\nD = 0.2 * undo_classical_to_quantum_rescaling\nset_onsite_coupling!(sys, S -> D*S[3]^2, 1)\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys; ndims=2)","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"Plot the spin wave spectrum for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"qs = [[0, 0, 0], [1, 1, 0]]\npath = q_space_path(cryst, qs, 400)\nswt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nres = intensities_bands(swt, path)\nplot_intensities(res)","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"To select a specific linear combination of spin structure factor (SSF) components in global Cartesian coordinates, one can use ssf_custom. Here we calculate and plot the real part of mathcalS^zz(𝐪 ω).","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"measure = ssf_custom(sys) do q, ssf\n return real(ssf[3, 3])\nend\nswt = SpinWaveTheory(sys; measure)\nres = intensities_bands(swt, path)\nplot_intensities(res)","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"It's also possible to get data for the full 3×3 SSF. For example, this is the SSF for the 7th energy band, at the 10th 𝐪-point along the path.","category":"page"},{"location":"examples/spinw/SW12_Triangular_easy_plane.html","page":"SW12 - Triangular lattice with easy plane","title":"SW12 - Triangular lattice with easy plane","text":"measure = ssf_custom((q, ssf) -> ssf, sys)\nswt = SpinWaveTheory(sys; measure)\nres = intensities_bands(swt, path)\nres.data[7, 10]","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"EditURL = \"../../../../examples/spinw_tutorials/SW04_Frustrated_square.jl\"","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"Download this example as Julia file or Jupyter notebook.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html#SW04-Frustrated-square-lattice","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"","category":"section"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"This is a Sunny port of SpinW Tutorial 4, originally authored by Bjorn Fak and Sandor Toth. It calculates the spin wave spectrum of the frustrated square lattice.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"Load Sunny and the GLMakie plotting package","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"using Sunny, GLMakie","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"To model the 2D square lattice, create an elongated tetragonal cell with one atom.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"units = Units(:meV, :angstrom)\nlatvecs = lattice_vectors(3.0, 3.0, 6.0, 90, 90, 90)\ncryst = Crystal(latvecs, [[0, 0, 0]])\nview_crystal(cryst; ndims=2)","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"Construct a spin system with competing nearest-neighbor (AFM) and next-nearest-neighbor (FM) interactions. The Néel magnetic order requires a supercell of 2×2 chemical cells.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole; dims=(2, 2, 1))\nJ1 = 1.0\nJ2 = -0.1\nset_exchange!(sys, J1, Bond(1, 1, [1, 0, 0]))\nset_exchange!(sys, J2, Bond(1, 1, [1, 1, 0]))\nrandomize_spins!(sys)\nminimize_energy!(sys)\nplot_spins(sys)","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"Calculate and plot intensities for a path through 𝐪-space.","category":"page"},{"location":"examples/spinw/SW04_Frustrated_square.html","page":"SW04 - Frustrated square lattice","title":"SW04 - Frustrated square lattice","text":"swt = SpinWaveTheory(sys; measure=ssf_perp(sys))\nqs = [[0, 0, 0], [1/2, 0, 0], [1/2, 1/2, 0], [0, 0, 0]]\npath = q_space_path(cryst, qs, 400)\nres = intensities_bands(swt, path)\nplot_intensities(res; units)","category":"page"}] } diff --git a/previews/PR318/structure-factor.html b/previews/PR318/structure-factor.html index 8b2fdc941..4aa0cc348 100644 --- a/previews/PR318/structure-factor.html +++ b/previews/PR318/structure-factor.html @@ -64,4 +64,4 @@ for _ in 1:nsamples decorrelate_system(sys) # Perform some type of Monte Carlo simulation add_sample!(sc, sys) # Use spins to calculate trajectory and accumulate new sample of 𝒮(𝐪,ω) -end

Extracting intensities sampled correlation data

Like in spin wave theory, the basic function for extracting intensities information from a SampledCorrelations is intensities. It takes a SampledCorrelations, a collection of $𝐪$-vectors, a collection of energies, and possible other options.

Since classical dynamics simulation take place on a finite lattice, the fundamental intensities measurements are only available at a discrete grid of wave vectors. In reciprocal lattice units, available grid points are $𝐪 = [\frac{n_1}{L_1}, \frac{n_2}{L_2}, \frac{n_3}{L_3}]$, where $n_i$ runs from $(\frac{-L_i}{2}+1)$ to $\frac{L_i}{2}$ and $L_i$ is the linear dimension of the lattice used in the calculation. (An internal function Sunny.available_wave_vectors provides access to this grid.) By default intensities will adjust each wavevector $𝐪$ to the nearest available grid point.

Similarly, the resolution in energies is controlled the dynamical trajectory length in real-time. Because the dynamical trajectory is not periodic in time, some blurring between neighboring energy bins is unavoidable. Sunny's algorithm for estimating the structure factor from real-time dynamics is specified here.

The temperature parameter kT is required for SampledCorrelations calculations, and will be used to perform classical-to-quantum rescaling of intensities. If kT = nothing, then intensities will be provided according to the classical Boltzmann distribution.

The instantaneous structure factor

Use intensities_static to calculate $\mathcal{S}(𝐪)$, i.e., correlations that are "instantaneous" in real-time. Mathematically, $\mathcal{S}(𝐪)$ denotes an integral of the dynamical structure factor $\mathcal{S}(𝐪, ω)$ over all energies $ω$. In SpinWaveTheory, the energy integral becomes a discrete sum over bands. In SampledCorrelations, a classical-to-quantum correction factor will be applied within intensities prior to energy integration.

Sunny also supports a mechanism to calculate static correlations without any spin dynamics. To collect such statistics, construct a SampledCorrelationsStatic object. In this case, intensities_static will return static correlations sampled from the classical Boltzmann distribution. This dynamics-free approach is faster, but may miss important features that derive from the quantum mechanical excitation spectrum.

+end

Extracting intensities sampled correlation data

Like in spin wave theory, the basic function for extracting intensities information from a SampledCorrelations is intensities. It takes a SampledCorrelations, a collection of $𝐪$-vectors, a collection of energies, and possible other options.

Since classical dynamics simulation take place on a finite lattice, the fundamental intensities measurements are only available at a discrete grid of wave vectors. In reciprocal lattice units, available grid points are $𝐪 = [\frac{n_1}{L_1}, \frac{n_2}{L_2}, \frac{n_3}{L_3}]$, where $n_i$ runs from $(\frac{-L_i}{2}+1)$ to $\frac{L_i}{2}$ and $L_i$ is the linear dimension of the lattice used in the calculation. (An internal function Sunny.available_wave_vectors provides access to this grid.) By default intensities will adjust each wavevector $𝐪$ to the nearest available grid point.

Similarly, the resolution in energies is controlled the dynamical trajectory length in real-time. Because the dynamical trajectory is not periodic in time, some blurring between neighboring energy bins is unavoidable. Sunny's algorithm for estimating the structure factor from real-time dynamics is specified here.

The temperature parameter kT is required for SampledCorrelations calculations, and will be used to perform classical-to-quantum rescaling of intensities. If kT = nothing, then intensities will be provided according to the classical Boltzmann distribution.

The instantaneous structure factor

Use intensities_static to calculate $\mathcal{S}(𝐪)$, i.e., correlations that are "instantaneous" in real-time. Mathematically, $\mathcal{S}(𝐪)$ denotes an integral of the dynamical structure factor $\mathcal{S}(𝐪, ω)$ over all energies $ω$. In SpinWaveTheory, the energy integral becomes a discrete sum over bands. In SampledCorrelations, a classical-to-quantum correction factor will be applied within intensities prior to energy integration.

Sunny also supports a mechanism to calculate static correlations without any spin dynamics. To collect such statistics, construct a SampledCorrelationsStatic object. In this case, intensities_static will return static correlations sampled from the classical Boltzmann distribution. This dynamics-free approach is faster, but may miss important features that derive from the quantum mechanical excitation spectrum.

diff --git a/previews/PR318/versions.html b/previews/PR318/versions.html index e66566a64..b2fdfdfd2 100644 --- a/previews/PR318/versions.html +++ b/previews/PR318/versions.html @@ -1,2 +1,2 @@ -Version History · Sunny documentation

Version History

v0.7.3

(In development)

  • Fix error in print_symmetry_table for slightly-distorted crystal cells (PR #317).
  • Stabilize SpinWaveTheoryKPM. It now automatically selects the polynomial order according to an error tolerance.

v0.7.2

(Sep 11, 2024)

  • Fix error in SampledCorrelations with a coarse $𝐪$-grid. (PR #314).
  • Fix colorbar in plot_intensities! when all data is uniform (PR #315).
  • An explicit colorrange can be used for plotting intensities_bands.

v0.7.1

(Sep 3, 2024)

  • Correctness fix for scalar biquadratic interactions specified with option biquad to set_exchange!.
  • Prototype implementation of entangled units.

v0.7.0

(Aug 30, 2024)

This major release introduces breaking interface changes.

  • The interface for calculating intensities has been revised to unify functionality across backends. The functions intensities_bands, intensities, and intensities_static no longer expect a "formula", and instead take keyword arguments directly. Pair correlations are now specified using ssf_perp and related functions. The constructors SampledCorrelations and SampledCorrelationsStatic replace dynamic_correlations and static_correlations, respectively.
  • New function plot_intensities enables convenient plotting for many types of intensities plots. Mutating variant plot_intensities! enables multi-panel plots.
  • One should now specify a range of $𝐪$-points with q_space_path or q_space_grid.
  • SpinWaveTheorySpiral is available to perform calculations on generalized spiral structures, which may be incommensurate.
  • repeat_periodically_as_spiral replaces set_spiral_order_on_sublattice! and set_spiral_order!.
  • New convenience functions powder_average and domain_average, which wrap intensities.
  • System now expects supercell dimensions as a dims keyword argument. Moment replaces SpinInfo. Lower-case s now labels quantum spin. For example, use :dipole_large_s instead of :dipole_large_S.
  • In view_crystal and plot_spins use ndims instead of dims for the number of spatial dimensions.
  • Binning features have been removed. Some functionality may be added back in a future release.
  • Experimental SpinWaveTheoryKPM feature implements a new algorithm to enable intensities calculations at a computational cost that scales linearly in system size.

v0.6.1

(Aug 2, 2024)

  • Breaking changes: magnetic_moment is now reported in units of the Bohr magneton, $μ_B$. For model systems where the Zeeman coupling aligns spin dipole with field (e.g., the Ising model convention), create a SpinInfo with g=-1. (PR 284).
  • More flexible Units system. set_external_field! is deprecated in favor of set_field!, which now expects a field in energy units. enable_dipole_dipole! now expects a scale parameter $μ_0 μ_B^2$ that can be obtained from units.vacuum_permeability.

v0.6.0

(Jun 18, 2024)

  • Various correctness fixes. The magnetic moment is now anti-aligned with the spin dipole (Issue 190), and the wavevector $𝐪$ in structure factor intensities $\mathcal{S}(𝐪,ω)$ now consistently represents momentum transfer to the sample (Issue 270). The new Example 8 demonstrates a model system where momentum transfers $±𝐪$ are inequivalent.
  • Dynamical structure factor intensities now have a precisely defined scale, independent of the calculator (Issue 264). Consequently, color ranges in plots may need to be rescaled.
  • Crystal can now infer a chemical unit cell from an mCIF file. System now supports set_dipoles_from_mcif!. Through spglib, one can now standardize any Crystal, with an option to idealize site positions.

v0.5.11

(Jun 2, 2024)

  • Fixes for Makie 0.21.

v0.5.10

(May 27, 2024)

  • view_crystal called on a System now shows interactions, and optionally the spin or magnetic dipoles.
  • Interactions for enable_dipole_dipole! are now supported in linear spin wave theory, with proper Ewald summation. For a faster alternative, the experimental function modify_exchange_with_truncated_dipole_dipole! will accept a real-space cutoff.
  • Intensities calculated with dynamic_correlations now avoid "bleeding artifacts" at low-energy (long-timescale) modes. See PR 246 for details. This eliminates the need for process_trajectory=:symmetrize.
  • When passed to intensity_formula, the special value zero(FormFactor) can now be used to disable contributions from a given site. For an example, see the ported SpinW tutorial 19.
  • Broadening kernels gaussian and lorentzian now expect a full width at half maximum (fwhm) keyword argument.
  • Experimental support for calculations on generalized spiral phases. For an example, see the ported SpinW tutorial 18.
  • Correctness fix for the case where spin-$S$ varies between sites in dipole-mode. In SU($N$) mode, however, there is still no support for varying the Hilbert space dimension $N$ between sites.
  • Correctness fix in long-range dipole-dipole interactions for systems with multiple cells.
  • Correctness fix in general biquadratic interactions (beyond scalar) for spin wave theory in dipole-mode.
  • Correctness fix for reading Mantid .nxs files.

v0.5.9

(Mar 25, 2024)

  • Correctness fixes: Structure factor conventions are now uniform across modes and precisely specified. The g-tensor is applied by default (disable with apply_g = false). The intensity is additive with increasing number of magnetic ions in the chemical cell, consistent with SpinW. Issue #235.
  • Enhancements to view_crystal. If a bond allows a DM interaction, its orientation will be shown visually. If a System argument is supplied, its exchange interactions will be shown..
  • New function suggest_timestep to assist in performing accurate and efficient simulation of classical spin dynamics. Issue #149.
  • Scalar biquadratic interactions can again be set in :dipole_large_S mode via the keyword argument biquad of set_exchange!.
  • Significantly speed up dynamic_correlations for crystals with many atoms in the unit cell. Issue #204.
  • Renamings: dt replaces Δt and damping replaces λ. This affects Langevin, [ImplicitMidpoint], and dynamic_correlations functions.

v0.5.8

(Jan 4, 2024)

  • Many bugs in the WGLMakie backend have become apparent, and are being tracked at Issue #211. Emit a warning if WGLMakie is detected, suggesting that GLMakie is preferred.
  • Various improvements to view_crystal. A distance parameter is no longer expected. Cartesian axes now appear as "compass" in bottom-left. Custom list of reference bonds can be passed. Toggle to view non-magnetic atoms in root crystal. Atoms now colored using CPK/JMol conventions.

v0.5.7

(Nov 26, 2023)

  • Update form factor coefficients, which now include Mn5.
  • Fix merge_correlations and the Parallelizing Calculations tutorial.
  • Remove internal functions *_primitive_crystal. Instead, it is recommended to use the conventional unit cell, and later call reshape_supercell.
  • Require Makie 0.20. An important new feature is resolution-independent scaling of font sizes. New figures expect size instead of resolution, and no longer accept rescale.

v0.5.6

(Nov 8, 2023)

This release initiates some major enhancements to the user interface in support of generalized SU(N) spin models. See this documentation page for an illustration of the new features. Most existing Sunny 0.5 models will continue to work with deprecation warnings, but these will become hard errors Sunny v0.6.

  • General pair couplings are now supported in set_pair_coupling! and set_pair_coupling_at!. :SUN mode supports interactions of any order, but :dipole mode is limited to bilinear and biquadratic coupling of the spin.
  • To perform a calculation with dipoles in the large-$S$ limit, use the new mode :dipole_large_S when constructing a System.
  • Deprecate the option biquad to set_exchange!. Use instead set_pair_coupling!, which generalizes beyond the scalar biquadratic.
  • Deprecate spin_operators, stevens_operators, large_S_spin_operators and large_S_stevens_operators. Use instead spin_matrices and stevens_matrices, which require a specific spin-$S$ label. To infer this, one can use spin_label.
  • Remove unused option energy_tol in SpinWaveTheory.
  • Animated spin dynamics is now possible. Call notify on the result of plot_spins to trigger redrawing of the frame. The argument colorfn to plot_spins supports animation of colors. See example usage for a Heisenberg ferromagnetic.
  • Add set_spin_rescaling! feature, which supports improved spectral measurements at finite-$T$. This follows the method proposed in Dahlbom et al., [arXiv:2310.19905].

v0.5.5

(Sep 29, 2023)

  • reshape_supercell now allows reshaping to multiples of the primitive unit cell, which can speed up certain calculations. This is illustrated in the CoRh₂O₄ powder averaging tutorial.
  • resize_supercell now allows all resizings.
  • Added energy_per_site.
  • set_spiral_order_on_sublattice! cannot work on reshaped systems.
  • Various bug fixes. In particular, an intensity_formula with :full will now uniformly calculate a 3x3 matrix of complex numbers.

v0.5.4

(Sep 11, 2023)

  • Various enhancements to view_crystal. Atoms are now labeled by index, and bonds support interactive inspection (GLMakie only). Font sizes work correctly on Makie v0.20-beta. If using Makie v0.19 on a high-resolution display, pass rescale=1.5 to enlarge font sizes.
  • The function suggest_magnetic_supercell now requires only a list of wavevectors, and will return a $3×3$ matrix that can be programmatically passed to reshape_supercell. The new tolerance parameter tol allows suggest_magnetic_supercell to approximate incommensurate wavevectors with nearby commensurate ones.
  • New functions set_spiral_order! and set_spiral_order_on_sublattice! can be used to initialize a spiral, single-$Q$ order.
  • Sunny now retains all constant energy shifts that have been introduced by anisotropy operators.
  • Fix export_vtk functionality.

v0.5.3

(Sep 8, 2023)

  • Add large_S_spin_operators and large_S_stevens_operators to support single-ion anisotropies in dipole mode without renormalization. Set large_S=true in set_exchange! to avoid renormalization of biquadratics.
  • view_crystal has been rewritten in Makie.
  • plot_spins now expects ghost_radius in physical length units.
  • SpinWaveTheory will (currently) error if provided a system with enable_dipole_dipole!.

v0.5.2

(Aug 30, 2023)

  • Form factors for 5d transition ions.
  • Download links for notebooks and scripts on each doc example
  • Various bug fixes.

v0.5.1

(Aug 23, 2023)

  • Fix binning edge cases.
  • plot_spins accepts resolution argument.

v0.5.0

(Aug 21, 2023)

New features.

Support for Linear Spin Wave Theory in :dipole and :SUN modes. (Thanks Hao Zhang!)

New function minimize_energy! to efficiently find an optimal configuration of spin dipoles or SU(N) coherent states.

Major refactors and enhancements to intensity calculations. This new interface allows unification between LSWT and classical spin dynamics calculations. This interface allows: Custom observables as local quantum operators, better support for linebroadening, and automatic binning to facilitate comparison with experimental data. See intensity_formula for documentation. Use load_nxs to load experimental neutron scattering data.

Breaking changes.

Require Julia 1.9.

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

Remove set_biquadratic!. Instead, use an optional keyword argument biquad to set_exchange!.

Rename DynamicStructureFactor to dynamic_correlations. Similarly, replace InstantStructureFactor with instant_correlations. The return type has been renamed SampledCorrelations to emphasize that the object may be holding thermodynamic samples, which are collected using add_sample!. Upon construction, the SampledCorrelations object will be empty (no initial sample).

Remove intensities function. Instead, use one of intensities_interpolated or intensities_binned. These will require an intensity_formula, which defines a calculator (e.g., LSWT).

Rename connected_path to reciprocal_space_path, which now returns an xticks object that can be used in plotting. Replace spherical_shell with reciprocal_space_shell that functions similarly.

Rename polarize_spin! to set_dipole! for consistency with set_coherent!. The behavior of the former function is unchanged: the spin at a given site will still be polarized along the provided direction.

Rename all_sites to eachsite consistent with Julia convention for iterators.

Rename reshape_geometry to reshape_supercell, which is the fundamental reshaping function. Rename resize_periodically to resize_supercell.

The constructor SpinInfo now requires a $g$-factor or tensor as a named argument.

The constructor FormFactor no longer accepts an atom index. Instead, the form factors are associated with site-symmetry classes in order of appearance.

v0.4.3

(Jun 23, 2023)

Experimental support for linear SpinWaveTheory, implemented in SU(N) mode. This module may evolve rapidly.

Implement renormalization of single-ion anisotropy and biquadratic interactions when in :dipole mode. This makes the model more faithful to the quantum mechanical Hamiltonian, but is also a breaking change.

Various improvements and bugfixes for to_inhomogeneous. Setting inhomogeneous interactions via set_exchange_at! should now infer the correct bond offset direction, or will report an ambiguity error. Ambiguities can be resolved by passing an explicit offset.

The function remove_periodicity! disables periodicity along specified dimensions.

Rename StaticStructureFactor to InstantStructureFactor.

v0.4.2

(Feb 27, 2023)

Introduce LocalSampler, a framework for MCMC sampling with local spin updates.

Rename print_dominant_wavevectors to print_wrapped_intensities to reduce confusion with the physical instantaneous intensities.

The function spherical_shell now takes a radius in physical units of inverse Å.

New exported functions global_position, magnetic_moment, all_sites.

Remove all uses of Base.deepcopy which resolves crashes.

v0.4.1

(Feb 13, 2023)

The function to_inhomogeneous creates a system that supports inhomogeneous interactions, which can be set using set_exchange_at!, etc.

set_biquadratic! replaces set_exchange_with_biquadratic!.

v0.4.0

(Feb 10, 2023)

This update includes many breaking changes, and is missing some features of 0.3.0.

Creating a spin System

Rename SpinSystem to System. Its constructor now has the form,

System(crystal, dims, infos, mode)

The parameter infos is now a list of SpinInfo objects. Each defines spin angular momentum $S = \frac{1}{2}, 1, \frac{3}{2}, …$, and an optional $g$-factor or tensor.

The parameter mode is one of :SUN or :dipole.

Setting interactions

Interactions are now added mutably to an existing System using the following functions: set_external_field!, set_exchange!, set_onsite_coupling!, enable_dipole_dipole!.

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

Fully general single-ion anisotropy is now possible. The function set_onsite_coupling! expects the single ion anisotropy to be expressed as a polynomial in symbolic spin operators 𝒮, or as a linear combination of symbolic Stevens operators 𝒪. 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.

Inhomogeneous field

An external field can be applied to a single site with set_external_field_at!.

Structure factor rewrite

The calculation of structure factors has been completely rewritten. For the new interface see the documentation tutorials.

Various

  • The "Sampler" interface is in flux. Langevin replaces both LangevinHeunP and LangevinSampler. Local spin-flip Monte Carlo sampling methods are temporarily broken.

  • repeat_periodically replaces extend_periodically.

Additional related functions include resize_periodically and reshape_geometry, the latter being fundamental.

The new function includes the list of symmetry-allowed single ion anisotropies in addition to exchange interactions.

  • When reading CIF files, the field _atom_site_label is now used in place of the field _atom_site_type_symbol.

This is required for correctness. The field _atom_site_label is guaranteed to be present, and is guaranteed to be a distinct label for each symmetry-inequivalent site. Code that explicitly referred to site labels (e.g. in calls to subcrystal) will need to be updated to use the new label.

+Version History · Sunny documentation

Version History

v0.7.3

(In development)

  • Fix error in print_symmetry_table for slightly-distorted crystal cells (PR #317).
  • Stabilize SpinWaveTheoryKPM. It now automatically selects the polynomial order according to an error tolerance.

v0.7.2

(Sep 11, 2024)

  • Fix error in SampledCorrelations with a coarse $𝐪$-grid. (PR #314).
  • Fix colorbar in plot_intensities! when all data is uniform (PR #315).
  • An explicit colorrange can be used for plotting intensities_bands.

v0.7.1

(Sep 3, 2024)

  • Correctness fix for scalar biquadratic interactions specified with option biquad to set_exchange!.
  • Prototype implementation of entangled units.

v0.7.0

(Aug 30, 2024)

This major release introduces breaking interface changes.

  • The interface for calculating intensities has been revised to unify functionality across backends. The functions intensities_bands, intensities, and intensities_static no longer expect a "formula", and instead take keyword arguments directly. Pair correlations are now specified using ssf_perp and related functions. The constructors SampledCorrelations and SampledCorrelationsStatic replace dynamic_correlations and static_correlations, respectively.
  • New function plot_intensities enables convenient plotting for many types of intensities plots. Mutating variant plot_intensities! enables multi-panel plots.
  • One should now specify a range of $𝐪$-points with q_space_path or q_space_grid.
  • SpinWaveTheorySpiral is available to perform calculations on generalized spiral structures, which may be incommensurate.
  • repeat_periodically_as_spiral replaces set_spiral_order_on_sublattice! and set_spiral_order!.
  • New convenience functions powder_average and domain_average, which wrap intensities.
  • System now expects supercell dimensions as a dims keyword argument. Moment replaces SpinInfo. Lower-case s now labels quantum spin. For example, use :dipole_large_s instead of :dipole_large_S.
  • In view_crystal and plot_spins use ndims instead of dims for the number of spatial dimensions.
  • Binning features have been removed. Some functionality may be added back in a future release.
  • Experimental SpinWaveTheoryKPM feature implements a new algorithm to enable intensities calculations at a computational cost that scales linearly in system size.

v0.6.1

(Aug 2, 2024)

  • Breaking changes: magnetic_moment is now reported in units of the Bohr magneton, $μ_B$. For model systems where the Zeeman coupling aligns spin dipole with field (e.g., the Ising model convention), create a SpinInfo with g=-1. (PR 284).
  • More flexible Units system. set_external_field! is deprecated in favor of set_field!, which now expects a field in energy units. enable_dipole_dipole! now expects a scale parameter $μ_0 μ_B^2$ that can be obtained from units.vacuum_permeability.

v0.6.0

(Jun 18, 2024)

  • Various correctness fixes. The magnetic moment is now anti-aligned with the spin dipole (Issue 190), and the wavevector $𝐪$ in structure factor intensities $\mathcal{S}(𝐪,ω)$ now consistently represents momentum transfer to the sample (Issue 270). The new Example 8 demonstrates a model system where momentum transfers $±𝐪$ are inequivalent.
  • Dynamical structure factor intensities now have a precisely defined scale, independent of the calculator (Issue 264). Consequently, color ranges in plots may need to be rescaled.
  • Crystal can now infer a chemical unit cell from an mCIF file. System now supports set_dipoles_from_mcif!. Through spglib, one can now standardize any Crystal, with an option to idealize site positions.

v0.5.11

(Jun 2, 2024)

  • Fixes for Makie 0.21.

v0.5.10

(May 27, 2024)

  • view_crystal called on a System now shows interactions, and optionally the spin or magnetic dipoles.
  • Interactions for enable_dipole_dipole! are now supported in linear spin wave theory, with proper Ewald summation. For a faster alternative, the experimental function modify_exchange_with_truncated_dipole_dipole! will accept a real-space cutoff.
  • Intensities calculated with dynamic_correlations now avoid "bleeding artifacts" at low-energy (long-timescale) modes. See PR 246 for details. This eliminates the need for process_trajectory=:symmetrize.
  • When passed to intensity_formula, the special value zero(FormFactor) can now be used to disable contributions from a given site. For an example, see the ported SpinW tutorial 19.
  • Broadening kernels gaussian and lorentzian now expect a full width at half maximum (fwhm) keyword argument.
  • Experimental support for calculations on generalized spiral phases. For an example, see the ported SpinW tutorial 18.
  • Correctness fix for the case where spin-$S$ varies between sites in dipole-mode. In SU($N$) mode, however, there is still no support for varying the Hilbert space dimension $N$ between sites.
  • Correctness fix in long-range dipole-dipole interactions for systems with multiple cells.
  • Correctness fix in general biquadratic interactions (beyond scalar) for spin wave theory in dipole-mode.
  • Correctness fix for reading Mantid .nxs files.

v0.5.9

(Mar 25, 2024)

  • Correctness fixes: Structure factor conventions are now uniform across modes and precisely specified. The g-tensor is applied by default (disable with apply_g = false). The intensity is additive with increasing number of magnetic ions in the chemical cell, consistent with SpinW. Issue #235.
  • Enhancements to view_crystal. If a bond allows a DM interaction, its orientation will be shown visually. If a System argument is supplied, its exchange interactions will be shown..
  • New function suggest_timestep to assist in performing accurate and efficient simulation of classical spin dynamics. Issue #149.
  • Scalar biquadratic interactions can again be set in :dipole_large_S mode via the keyword argument biquad of set_exchange!.
  • Significantly speed up dynamic_correlations for crystals with many atoms in the unit cell. Issue #204.
  • Renamings: dt replaces Δt and damping replaces λ. This affects Langevin, [ImplicitMidpoint], and dynamic_correlations functions.

v0.5.8

(Jan 4, 2024)

  • Many bugs in the WGLMakie backend have become apparent, and are being tracked at Issue #211. Emit a warning if WGLMakie is detected, suggesting that GLMakie is preferred.
  • Various improvements to view_crystal. A distance parameter is no longer expected. Cartesian axes now appear as "compass" in bottom-left. Custom list of reference bonds can be passed. Toggle to view non-magnetic atoms in root crystal. Atoms now colored using CPK/JMol conventions.

v0.5.7

(Nov 26, 2023)

  • Update form factor coefficients, which now include Mn5.
  • Fix merge_correlations and the Parallelizing Calculations tutorial.
  • Remove internal functions *_primitive_crystal. Instead, it is recommended to use the conventional unit cell, and later call reshape_supercell.
  • Require Makie 0.20. An important new feature is resolution-independent scaling of font sizes. New figures expect size instead of resolution, and no longer accept rescale.

v0.5.6

(Nov 8, 2023)

This release initiates some major enhancements to the user interface in support of generalized SU(N) spin models. See this documentation page for an illustration of the new features. Most existing Sunny 0.5 models will continue to work with deprecation warnings, but these will become hard errors Sunny v0.6.

  • General pair couplings are now supported in set_pair_coupling! and set_pair_coupling_at!. :SUN mode supports interactions of any order, but :dipole mode is limited to bilinear and biquadratic coupling of the spin.
  • To perform a calculation with dipoles in the large-$S$ limit, use the new mode :dipole_large_S when constructing a System.
  • Deprecate the option biquad to set_exchange!. Use instead set_pair_coupling!, which generalizes beyond the scalar biquadratic.
  • Deprecate spin_operators, stevens_operators, large_S_spin_operators and large_S_stevens_operators. Use instead spin_matrices and stevens_matrices, which require a specific spin-$S$ label. To infer this, one can use spin_label.
  • Remove unused option energy_tol in SpinWaveTheory.
  • Animated spin dynamics is now possible. Call notify on the result of plot_spins to trigger redrawing of the frame. The argument colorfn to plot_spins supports animation of colors. See example usage for a Heisenberg ferromagnetic.
  • Add set_spin_rescaling! feature, which supports improved spectral measurements at finite-$T$. This follows the method proposed in Dahlbom et al., [arXiv:2310.19905].

v0.5.5

(Sep 29, 2023)

  • reshape_supercell now allows reshaping to multiples of the primitive unit cell, which can speed up certain calculations. This is illustrated in the CoRh₂O₄ powder averaging tutorial.
  • resize_supercell now allows all resizings.
  • Added energy_per_site.
  • set_spiral_order_on_sublattice! cannot work on reshaped systems.
  • Various bug fixes. In particular, an intensity_formula with :full will now uniformly calculate a 3x3 matrix of complex numbers.

v0.5.4

(Sep 11, 2023)

  • Various enhancements to view_crystal. Atoms are now labeled by index, and bonds support interactive inspection (GLMakie only). Font sizes work correctly on Makie v0.20-beta. If using Makie v0.19 on a high-resolution display, pass rescale=1.5 to enlarge font sizes.
  • The function suggest_magnetic_supercell now requires only a list of wavevectors, and will return a $3×3$ matrix that can be programmatically passed to reshape_supercell. The new tolerance parameter tol allows suggest_magnetic_supercell to approximate incommensurate wavevectors with nearby commensurate ones.
  • New functions set_spiral_order! and set_spiral_order_on_sublattice! can be used to initialize a spiral, single-$Q$ order.
  • Sunny now retains all constant energy shifts that have been introduced by anisotropy operators.
  • Fix export_vtk functionality.

v0.5.3

(Sep 8, 2023)

  • Add large_S_spin_operators and large_S_stevens_operators to support single-ion anisotropies in dipole mode without renormalization. Set large_S=true in set_exchange! to avoid renormalization of biquadratics.
  • view_crystal has been rewritten in Makie.
  • plot_spins now expects ghost_radius in physical length units.
  • SpinWaveTheory will (currently) error if provided a system with enable_dipole_dipole!.

v0.5.2

(Aug 30, 2023)

  • Form factors for 5d transition ions.
  • Download links for notebooks and scripts on each doc example
  • Various bug fixes.

v0.5.1

(Aug 23, 2023)

  • Fix binning edge cases.
  • plot_spins accepts resolution argument.

v0.5.0

(Aug 21, 2023)

New features.

Support for Linear Spin Wave Theory in :dipole and :SUN modes. (Thanks Hao Zhang!)

New function minimize_energy! to efficiently find an optimal configuration of spin dipoles or SU(N) coherent states.

Major refactors and enhancements to intensity calculations. This new interface allows unification between LSWT and classical spin dynamics calculations. This interface allows: Custom observables as local quantum operators, better support for linebroadening, and automatic binning to facilitate comparison with experimental data. See intensity_formula for documentation. Use load_nxs to load experimental neutron scattering data.

Breaking changes.

Require Julia 1.9.

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

Remove set_biquadratic!. Instead, use an optional keyword argument biquad to set_exchange!.

Rename DynamicStructureFactor to dynamic_correlations. Similarly, replace InstantStructureFactor with instant_correlations. The return type has been renamed SampledCorrelations to emphasize that the object may be holding thermodynamic samples, which are collected using add_sample!. Upon construction, the SampledCorrelations object will be empty (no initial sample).

Remove intensities function. Instead, use one of intensities_interpolated or intensities_binned. These will require an intensity_formula, which defines a calculator (e.g., LSWT).

Rename connected_path to reciprocal_space_path, which now returns an xticks object that can be used in plotting. Replace spherical_shell with reciprocal_space_shell that functions similarly.

Rename polarize_spin! to set_dipole! for consistency with set_coherent!. The behavior of the former function is unchanged: the spin at a given site will still be polarized along the provided direction.

Rename all_sites to eachsite consistent with Julia convention for iterators.

Rename reshape_geometry to reshape_supercell, which is the fundamental reshaping function. Rename resize_periodically to resize_supercell.

The constructor SpinInfo now requires a $g$-factor or tensor as a named argument.

The constructor FormFactor no longer accepts an atom index. Instead, the form factors are associated with site-symmetry classes in order of appearance.

v0.4.3

(Jun 23, 2023)

Experimental support for linear SpinWaveTheory, implemented in SU(N) mode. This module may evolve rapidly.

Implement renormalization of single-ion anisotropy and biquadratic interactions when in :dipole mode. This makes the model more faithful to the quantum mechanical Hamiltonian, but is also a breaking change.

Various improvements and bugfixes for to_inhomogeneous. Setting inhomogeneous interactions via set_exchange_at! should now infer the correct bond offset direction, or will report an ambiguity error. Ambiguities can be resolved by passing an explicit offset.

The function remove_periodicity! disables periodicity along specified dimensions.

Rename StaticStructureFactor to InstantStructureFactor.

v0.4.2

(Feb 27, 2023)

Introduce LocalSampler, a framework for MCMC sampling with local spin updates.

Rename print_dominant_wavevectors to print_wrapped_intensities to reduce confusion with the physical instantaneous intensities.

The function spherical_shell now takes a radius in physical units of inverse Å.

New exported functions global_position, magnetic_moment, all_sites.

Remove all uses of Base.deepcopy which resolves crashes.

v0.4.1

(Feb 13, 2023)

The function to_inhomogeneous creates a system that supports inhomogeneous interactions, which can be set using set_exchange_at!, etc.

set_biquadratic! replaces set_exchange_with_biquadratic!.

v0.4.0

(Feb 10, 2023)

This update includes many breaking changes, and is missing some features of 0.3.0.

Creating a spin System

Rename SpinSystem to System. Its constructor now has the form,

System(crystal, dims, infos, mode)

The parameter infos is now a list of SpinInfo objects. Each defines spin angular momentum $S = \frac{1}{2}, 1, \frac{3}{2}, …$, and an optional $g$-factor or tensor.

The parameter mode is one of :SUN or :dipole.

Setting interactions

Interactions are now added mutably to an existing System using the following functions: set_external_field!, set_exchange!, set_onsite_coupling!, enable_dipole_dipole!.

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

Fully general single-ion anisotropy is now possible. The function set_onsite_coupling! expects the single ion anisotropy to be expressed as a polynomial in symbolic spin operators 𝒮, or as a linear combination of symbolic Stevens operators 𝒪. 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.

Inhomogeneous field

An external field can be applied to a single site with set_external_field_at!.

Structure factor rewrite

The calculation of structure factors has been completely rewritten. For the new interface see the documentation tutorials.

Various

  • The "Sampler" interface is in flux. Langevin replaces both LangevinHeunP and LangevinSampler. Local spin-flip Monte Carlo sampling methods are temporarily broken.

  • repeat_periodically replaces extend_periodically.

Additional related functions include resize_periodically and reshape_geometry, the latter being fundamental.

The new function includes the list of symmetry-allowed single ion anisotropies in addition to exchange interactions.

  • When reading CIF files, the field _atom_site_label is now used in place of the field _atom_site_type_symbol.

This is required for correctness. The field _atom_site_label is guaranteed to be present, and is guaranteed to be a distinct label for each symmetry-inequivalent site. Code that explicitly referred to site labels (e.g. in calls to subcrystal) will need to be updated to use the new label.

diff --git a/previews/PR318/writevtk.html b/previews/PR318/writevtk.html index 2ff739e9e..a592c92f2 100644 --- a/previews/PR318/writevtk.html +++ b/previews/PR318/writevtk.html @@ -53,4 +53,4 @@ signal = sum(signal; dims = 4) # Export to ParaView -export_vtk("experiment_data_as_vtk", params, signal) +export_vtk("experiment_data_as_vtk", params, signal)