diff --git a/previews/PR324/.documenter-siteinfo.json b/previews/PR324/.documenter-siteinfo.json index d06a11be9..661b973bd 100644 --- a/previews/PR324/.documenter-siteinfo.json +++ b/previews/PR324/.documenter-siteinfo.json @@ -1 +1 @@ -{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-10-10T18:13:33","documenter_version":"1.7.0"}} \ No newline at end of file +{"documenter":{"julia_version":"1.10.5","generation_timestamp":"2024-10-10T18:49:11","documenter_version":"1.7.0"}} \ No newline at end of file diff --git a/previews/PR324/examples/01_LSWT_CoRh2O4-1c8f950e.png b/previews/PR324/examples/01_LSWT_CoRh2O4-1c8f950e.png new file mode 100644 index 000000000..7151ea4c3 Binary files /dev/null and b/previews/PR324/examples/01_LSWT_CoRh2O4-1c8f950e.png differ diff --git a/previews/PR324/examples/01_LSWT_CoRh2O4-42b559ec.png b/previews/PR324/examples/01_LSWT_CoRh2O4-42b559ec.png new file mode 100644 index 000000000..10ecc3e6c Binary files /dev/null and b/previews/PR324/examples/01_LSWT_CoRh2O4-42b559ec.png differ diff --git a/previews/PR324/examples/01_LSWT_CoRh2O4-82f560df.png b/previews/PR324/examples/01_LSWT_CoRh2O4-82f560df.png deleted file mode 100644 index 0add8ffec..000000000 Binary files a/previews/PR324/examples/01_LSWT_CoRh2O4-82f560df.png and /dev/null differ diff --git a/previews/PR324/examples/01_LSWT_CoRh2O4-87f37c3a.png b/previews/PR324/examples/01_LSWT_CoRh2O4-87f37c3a.png deleted file mode 100644 index d655a357f..000000000 Binary files a/previews/PR324/examples/01_LSWT_CoRh2O4-87f37c3a.png and /dev/null differ diff --git a/previews/PR324/examples/01_LSWT_CoRh2O4-a1b4c67b.png b/previews/PR324/examples/01_LSWT_CoRh2O4-a1b4c67b.png new file mode 100644 index 000000000..a3967390b Binary files /dev/null and b/previews/PR324/examples/01_LSWT_CoRh2O4-a1b4c67b.png differ diff --git a/previews/PR324/examples/01_LSWT_CoRh2O4-aef97250.png b/previews/PR324/examples/01_LSWT_CoRh2O4-aef97250.png deleted file mode 100644 index fd4623aae..000000000 Binary files a/previews/PR324/examples/01_LSWT_CoRh2O4-aef97250.png and /dev/null differ diff --git a/previews/PR324/examples/01_LSWT_CoRh2O4-c4a5bbc8.png b/previews/PR324/examples/01_LSWT_CoRh2O4-c4a5bbc8.png new file mode 100644 index 000000000..847f5a88b Binary files /dev/null and b/previews/PR324/examples/01_LSWT_CoRh2O4-c4a5bbc8.png differ diff --git a/previews/PR324/examples/01_LSWT_CoRh2O4-ef6426f1.png b/previews/PR324/examples/01_LSWT_CoRh2O4-ef6426f1.png deleted file mode 100644 index fbd179af3..000000000 Binary files a/previews/PR324/examples/01_LSWT_CoRh2O4-ef6426f1.png and /dev/null differ diff --git a/previews/PR324/examples/01_LSWT_CoRh2O4.html b/previews/PR324/examples/01_LSWT_CoRh2O4.html index 60f52466c..3ee06c7ed 100644 --- a/previews/PR324/examples/01_LSWT_CoRh2O4.html +++ b/previews/PR324/examples/01_LSWT_CoRh2O4.html @@ -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?

+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?

diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-0ea8e7b4.png b/previews/PR324/examples/02_LLD_CoRh2O4-0ea8e7b4.png new file mode 100644 index 000000000..4fdaeca35 Binary files /dev/null and b/previews/PR324/examples/02_LLD_CoRh2O4-0ea8e7b4.png differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-289b979b.png b/previews/PR324/examples/02_LLD_CoRh2O4-289b979b.png new file mode 100644 index 000000000..f3c955664 Binary files /dev/null and b/previews/PR324/examples/02_LLD_CoRh2O4-289b979b.png differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-2f800393.png b/previews/PR324/examples/02_LLD_CoRh2O4-2f800393.png new file mode 100644 index 000000000..c29b3b597 Binary files /dev/null and b/previews/PR324/examples/02_LLD_CoRh2O4-2f800393.png differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-3076ed03.png b/previews/PR324/examples/02_LLD_CoRh2O4-3076ed03.png deleted file mode 100644 index 1e200bc6b..000000000 Binary files a/previews/PR324/examples/02_LLD_CoRh2O4-3076ed03.png and /dev/null differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-3e424d1d.png b/previews/PR324/examples/02_LLD_CoRh2O4-3e424d1d.png deleted file mode 100644 index 840de3e58..000000000 Binary files a/previews/PR324/examples/02_LLD_CoRh2O4-3e424d1d.png and /dev/null differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-4603908c.png b/previews/PR324/examples/02_LLD_CoRh2O4-4603908c.png new file mode 100644 index 000000000..a48c7bd39 Binary files /dev/null and b/previews/PR324/examples/02_LLD_CoRh2O4-4603908c.png differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-4e6bc0cd.png b/previews/PR324/examples/02_LLD_CoRh2O4-4e6bc0cd.png new file mode 100644 index 000000000..ba9fd5150 Binary files /dev/null and b/previews/PR324/examples/02_LLD_CoRh2O4-4e6bc0cd.png differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-573fadd8.png b/previews/PR324/examples/02_LLD_CoRh2O4-573fadd8.png deleted file mode 100644 index 273417ea0..000000000 Binary files a/previews/PR324/examples/02_LLD_CoRh2O4-573fadd8.png and /dev/null differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-74762939.png b/previews/PR324/examples/02_LLD_CoRh2O4-74762939.png deleted file mode 100644 index 6599f3730..000000000 Binary files a/previews/PR324/examples/02_LLD_CoRh2O4-74762939.png and /dev/null differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-b6b04b9e.png b/previews/PR324/examples/02_LLD_CoRh2O4-b6b04b9e.png deleted file mode 100644 index dd6b3b946..000000000 Binary files a/previews/PR324/examples/02_LLD_CoRh2O4-b6b04b9e.png and /dev/null differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-c9c23d40.png b/previews/PR324/examples/02_LLD_CoRh2O4-c9c23d40.png deleted file mode 100644 index f0faec96c..000000000 Binary files a/previews/PR324/examples/02_LLD_CoRh2O4-c9c23d40.png and /dev/null differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-deac559b.png b/previews/PR324/examples/02_LLD_CoRh2O4-deac559b.png new file mode 100644 index 000000000..4dedc8e6e Binary files /dev/null and b/previews/PR324/examples/02_LLD_CoRh2O4-deac559b.png differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-eb86ad5d.png b/previews/PR324/examples/02_LLD_CoRh2O4-eb86ad5d.png new file mode 100644 index 000000000..d548f6ecc Binary files /dev/null and b/previews/PR324/examples/02_LLD_CoRh2O4-eb86ad5d.png differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4-ffbceb87.png b/previews/PR324/examples/02_LLD_CoRh2O4-ffbceb87.png deleted file mode 100644 index 5b8147deb..000000000 Binary files a/previews/PR324/examples/02_LLD_CoRh2O4-ffbceb87.png and /dev/null differ diff --git a/previews/PR324/examples/02_LLD_CoRh2O4.html b/previews/PR324/examples/02_LLD_CoRh2O4.html index a418adeb2..8c21c53f3 100644 --- a/previews/PR324/examples/02_LLD_CoRh2O4.html +++ b/previews/PR324/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.04192 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.04129 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/PR324/examples/03_LSWT_SU3_FeI2.html b/previews/PR324/examples/03_LSWT_SU3_FeI2.html index 8c13534b7..60d558a6a 100644 --- a/previews/PR324/examples/03_LSWT_SU3_FeI2.html +++ b/previews/PR324/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/PR324/examples/04_GSD_FeI2-09a5ad7f.png b/previews/PR324/examples/04_GSD_FeI2-09a5ad7f.png new file mode 100644 index 000000000..12c141a2a Binary files /dev/null and b/previews/PR324/examples/04_GSD_FeI2-09a5ad7f.png differ diff --git a/previews/PR324/examples/04_GSD_FeI2-1601f2ab.png b/previews/PR324/examples/04_GSD_FeI2-1601f2ab.png new file mode 100644 index 000000000..1e8b88754 Binary files /dev/null and b/previews/PR324/examples/04_GSD_FeI2-1601f2ab.png differ diff --git a/previews/PR324/examples/04_GSD_FeI2-2308e968.png b/previews/PR324/examples/04_GSD_FeI2-2308e968.png deleted file mode 100644 index 942e6dbbf..000000000 Binary files a/previews/PR324/examples/04_GSD_FeI2-2308e968.png and /dev/null differ diff --git a/previews/PR324/examples/04_GSD_FeI2-4ae06900.png b/previews/PR324/examples/04_GSD_FeI2-4ae06900.png new file mode 100644 index 000000000..cb3907e92 Binary files /dev/null and b/previews/PR324/examples/04_GSD_FeI2-4ae06900.png differ diff --git a/previews/PR324/examples/04_GSD_FeI2-77759f56.png b/previews/PR324/examples/04_GSD_FeI2-77759f56.png deleted file mode 100644 index e8452780b..000000000 Binary files a/previews/PR324/examples/04_GSD_FeI2-77759f56.png and /dev/null differ diff --git a/previews/PR324/examples/04_GSD_FeI2-807db97a.png b/previews/PR324/examples/04_GSD_FeI2-807db97a.png new file mode 100644 index 000000000..dfeb8f518 Binary files /dev/null and b/previews/PR324/examples/04_GSD_FeI2-807db97a.png differ diff --git a/previews/PR324/examples/04_GSD_FeI2-87ecf2d2.png b/previews/PR324/examples/04_GSD_FeI2-87ecf2d2.png deleted file mode 100644 index ac9d006a6..000000000 Binary files a/previews/PR324/examples/04_GSD_FeI2-87ecf2d2.png and /dev/null differ diff --git a/previews/PR324/examples/04_GSD_FeI2-ec91d281.png b/previews/PR324/examples/04_GSD_FeI2-ec91d281.png deleted file mode 100644 index 4d83259b6..000000000 Binary files a/previews/PR324/examples/04_GSD_FeI2-ec91d281.png and /dev/null differ diff --git a/previews/PR324/examples/04_GSD_FeI2.html b/previews/PR324/examples/04_GSD_FeI2.html index 21885bbd0..ee1d60256 100644 --- a/previews/PR324/examples/04_GSD_FeI2.html +++ b/previews/PR324/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.0318 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.03084 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:
 
-    [0, -1/4, 1/4]         39.99% weight
-    [0, 1/4, -1/4]         39.99%
-    [1/8, -0.1875, 1/4]     0.11%
-    [-1/8, 0.1875, -1/4]    0.11%
-    [-0.1875, 0.1875, 1/4]    0.09%
-    [0.1875, -0.1875, -1/4]    0.09%
-    [0, 0.1875, 1/2]        0.08%
-    [0, -0.1875, 1/2]       0.08%
-    [0.1875, 1/8, 0]        0.07%
-    [-0.1875, -1/8, 0]      0.07%
-    [-0.3125, 1/8, 0]       0.07%
-    ...                     ...

Thermalization has not substantially altered the suggested dt.

suggest_timestep(sys, langevin; tol=1e-2)
Consider dt ≈ 0.03129 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]         39.62% weight
+    [0, 1/4, -1/4]         39.62%
+    [0.3125, 0, 1/2]        0.07%
+    [-0.3125, 0, 1/2]       0.07%
+    [0.3125, 1/4, 1/2]      0.07%
+    [-0.3125, -1/4, 1/2]    0.07%
+    [1/8, 0.0625, 1/4]      0.07%
+    [-1/8, -0.0625, -1/4]    0.07%
+    [-1/8, 0.3125, 1/4]     0.07%
+    [1/8, -0.3125, -1/4]    0.07%
+    [-1/8, -0.1875, 1/4]    0.06%
+    ...                     ...

Thermalization has not substantially altered the suggested dt.

suggest_timestep(sys, langevin; tol=1e-2)
Consider dt ≈ 0.03136 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.04075 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.04014 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/PR324/examples/05_MC_Ising.html b/previews/PR324/examples/05_MC_Ising.html index d07756d9a..1638e4724 100644 --- a/previews/PR324/examples/05_MC_Ising.html +++ b/previews/PR324/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/PR324/examples/06_CP2_Skyrmions-36d5a361.png b/previews/PR324/examples/06_CP2_Skyrmions-36d5a361.png new file mode 100644 index 000000000..4f7d81458 Binary files /dev/null and b/previews/PR324/examples/06_CP2_Skyrmions-36d5a361.png differ diff --git a/previews/PR324/examples/06_CP2_Skyrmions-f07506e3.png b/previews/PR324/examples/06_CP2_Skyrmions-f07506e3.png deleted file mode 100644 index dd4564882..000000000 Binary files a/previews/PR324/examples/06_CP2_Skyrmions-f07506e3.png and /dev/null differ diff --git a/previews/PR324/examples/06_CP2_Skyrmions.html b/previews/PR324/examples/06_CP2_Skyrmions.html index 580eebac4..67e80f5e9 100644 --- a/previews/PR324/examples/06_CP2_Skyrmions.html +++ b/previews/PR324/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.01102 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.01095 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/PR324/examples/07_Dipole_Dipole.html b/previews/PR324/examples/07_Dipole_Dipole.html index 173998258..a2c22275e 100644 --- a/previews/PR324/examples/07_Dipole_Dipole.html +++ b/previews/PR324/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/PR324/examples/08_Momentum_Conventions-3991d3d6.png b/previews/PR324/examples/08_Momentum_Conventions-3991d3d6.png deleted file mode 100644 index 03d20f9b9..000000000 Binary files a/previews/PR324/examples/08_Momentum_Conventions-3991d3d6.png and /dev/null differ diff --git a/previews/PR324/examples/08_Momentum_Conventions-79844972.png b/previews/PR324/examples/08_Momentum_Conventions-79844972.png deleted file mode 100644 index 2045a06db..000000000 Binary files a/previews/PR324/examples/08_Momentum_Conventions-79844972.png and /dev/null differ diff --git a/previews/PR324/examples/08_Momentum_Conventions-88c96579.png b/previews/PR324/examples/08_Momentum_Conventions-88c96579.png new file mode 100644 index 000000000..24395f844 Binary files /dev/null and b/previews/PR324/examples/08_Momentum_Conventions-88c96579.png differ diff --git a/previews/PR324/examples/08_Momentum_Conventions-bc93c036.png b/previews/PR324/examples/08_Momentum_Conventions-bc93c036.png new file mode 100644 index 000000000..b44e9add4 Binary files /dev/null and b/previews/PR324/examples/08_Momentum_Conventions-bc93c036.png differ diff --git a/previews/PR324/examples/08_Momentum_Conventions.html b/previews/PR324/examples/08_Momentum_Conventions.html index 5e3be182d..e61b11f5e 100644 --- a/previews/PR324/examples/08_Momentum_Conventions.html +++ b/previews/PR324/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/PR324/examples/09_Disorder_KPM-00c3ca91.png b/previews/PR324/examples/09_Disorder_KPM-00c3ca91.png new file mode 100644 index 000000000..28d9ed277 Binary files /dev/null and b/previews/PR324/examples/09_Disorder_KPM-00c3ca91.png differ diff --git a/previews/PR324/examples/09_Disorder_KPM-145cf4e0.png b/previews/PR324/examples/09_Disorder_KPM-145cf4e0.png new file mode 100644 index 000000000..4cf40d1cc Binary files /dev/null and b/previews/PR324/examples/09_Disorder_KPM-145cf4e0.png differ diff --git a/previews/PR324/examples/09_Disorder_KPM-15adebaf.png b/previews/PR324/examples/09_Disorder_KPM-15adebaf.png deleted file mode 100644 index 5a2041d9f..000000000 Binary files a/previews/PR324/examples/09_Disorder_KPM-15adebaf.png and /dev/null differ diff --git a/previews/PR324/examples/09_Disorder_KPM-27f59254.png b/previews/PR324/examples/09_Disorder_KPM-27f59254.png new file mode 100644 index 000000000..f3e9c47dd Binary files /dev/null and b/previews/PR324/examples/09_Disorder_KPM-27f59254.png differ diff --git a/previews/PR324/examples/09_Disorder_KPM-321d2525.png b/previews/PR324/examples/09_Disorder_KPM-321d2525.png deleted file mode 100644 index 6191bff6d..000000000 Binary files a/previews/PR324/examples/09_Disorder_KPM-321d2525.png and /dev/null differ diff --git a/previews/PR324/examples/09_Disorder_KPM-8f02ce9a.png b/previews/PR324/examples/09_Disorder_KPM-8f02ce9a.png deleted file mode 100644 index ed9b2bb90..000000000 Binary files a/previews/PR324/examples/09_Disorder_KPM-8f02ce9a.png and /dev/null differ diff --git a/previews/PR324/examples/09_Disorder_KPM-9a8df39c.png b/previews/PR324/examples/09_Disorder_KPM-9a8df39c.png new file mode 100644 index 000000000..eeb36cd60 Binary files /dev/null and b/previews/PR324/examples/09_Disorder_KPM-9a8df39c.png differ diff --git a/previews/PR324/examples/09_Disorder_KPM-c8a6215e.png b/previews/PR324/examples/09_Disorder_KPM-c8a6215e.png deleted file mode 100644 index 60467e1fc..000000000 Binary files a/previews/PR324/examples/09_Disorder_KPM-c8a6215e.png and /dev/null differ diff --git a/previews/PR324/examples/09_Disorder_KPM-caaa44a5.png b/previews/PR324/examples/09_Disorder_KPM-caaa44a5.png new file mode 100644 index 000000000..99dbbcca0 Binary files /dev/null and b/previews/PR324/examples/09_Disorder_KPM-caaa44a5.png differ diff --git a/previews/PR324/examples/09_Disorder_KPM-cd781652.png b/previews/PR324/examples/09_Disorder_KPM-cd781652.png deleted file mode 100644 index f716c9660..000000000 Binary files a/previews/PR324/examples/09_Disorder_KPM-cd781652.png and /dev/null differ diff --git a/previews/PR324/examples/09_Disorder_KPM-d35345bb.png b/previews/PR324/examples/09_Disorder_KPM-d35345bb.png new file mode 100644 index 000000000..01c5fb535 Binary files /dev/null and b/previews/PR324/examples/09_Disorder_KPM-d35345bb.png differ diff --git a/previews/PR324/examples/09_Disorder_KPM-dac065b4.png b/previews/PR324/examples/09_Disorder_KPM-dac065b4.png deleted file mode 100644 index bc78bd2e4..000000000 Binary files a/previews/PR324/examples/09_Disorder_KPM-dac065b4.png and /dev/null differ diff --git a/previews/PR324/examples/09_Disorder_KPM.html b/previews/PR324/examples/09_Disorder_KPM.html index 8ffb8798a..030de3da0 100644 --- a/previews/PR324/examples/09_Disorder_KPM.html +++ b/previews/PR324/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/PR324/examples/contributed/MgCr2O4-tutorial.html b/previews/PR324/examples/contributed/MgCr2O4-tutorial.html index bbe7fcb01..d870a9e57 100644 --- a/previews/PR324/examples/contributed/MgCr2O4-tutorial.html +++ b/previews/PR324/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/PR324/examples/contributed/kappa_tutorial.html b/previews/PR324/examples/contributed/kappa_tutorial.html index f77dd38b9..52e3144ab 100644 --- a/previews/PR324/examples/contributed/kappa_tutorial.html +++ b/previews/PR324/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/PR324/examples/spinw/SW01_FM_Heseinberg_chain-0fdd4abf.png b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-0fdd4abf.png new file mode 100644 index 000000000..170aef8a0 Binary files /dev/null and b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-0fdd4abf.png differ diff --git a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-22b5b66d.png b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-22b5b66d.png new file mode 100644 index 000000000..8ac6bc002 Binary files /dev/null and b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-22b5b66d.png differ diff --git a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-595c584c.png b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-595c584c.png deleted file mode 100644 index 845cb1779..000000000 Binary files a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-595c584c.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-662a315a.png b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-662a315a.png deleted file mode 100644 index ab1adf42c..000000000 Binary files a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-662a315a.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-919bf467.png b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-919bf467.png new file mode 100644 index 000000000..71ec420ab Binary files /dev/null and b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-919bf467.png differ diff --git a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-d5834e42.png b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-d5834e42.png deleted file mode 100644 index 39b05fca3..000000000 Binary files a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain-d5834e42.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain.html b/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain.html index 5807c5b3c..8f5a1e6df 100644 --- a/previews/PR324/examples/spinw/SW01_FM_Heseinberg_chain.html +++ b/previews/PR324/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.0000000000000002

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/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-43cc43cd.png b/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-43cc43cd.png new file mode 100644 index 000000000..a90c4e93d Binary files /dev/null and b/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-43cc43cd.png differ diff --git a/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-47490f7f.png b/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-47490f7f.png new file mode 100644 index 000000000..b7913c63d Binary files /dev/null and b/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-47490f7f.png differ diff --git a/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-bb11367b.png b/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-bb11367b.png deleted file mode 100644 index 25d8e2353..000000000 Binary files a/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-bb11367b.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-d5696472.png b/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-d5696472.png deleted file mode 100644 index d35450cc5..000000000 Binary files a/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain-d5696472.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain.html b/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain.html index a05e78aa6..af54d1fe9 100644 --- a/previews/PR324/examples/spinw/SW02_AFM_Heisenberg_chain.html +++ b/previews/PR324/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/PR324/examples/spinw/SW03_Frustrated_chain-8426ec59.png b/previews/PR324/examples/spinw/SW03_Frustrated_chain-8426ec59.png new file mode 100644 index 000000000..6c19240e8 Binary files /dev/null and b/previews/PR324/examples/spinw/SW03_Frustrated_chain-8426ec59.png differ diff --git a/previews/PR324/examples/spinw/SW03_Frustrated_chain-cb36545b.png b/previews/PR324/examples/spinw/SW03_Frustrated_chain-cb36545b.png deleted file mode 100644 index 04c604fd7..000000000 Binary files a/previews/PR324/examples/spinw/SW03_Frustrated_chain-cb36545b.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW03_Frustrated_chain-a1114b52.png b/previews/PR324/examples/spinw/SW03_Frustrated_chain-f8942e32.png similarity index 99% rename from previews/PR324/examples/spinw/SW03_Frustrated_chain-a1114b52.png rename to previews/PR324/examples/spinw/SW03_Frustrated_chain-f8942e32.png index 027a97b07..d5a476276 100644 Binary files a/previews/PR324/examples/spinw/SW03_Frustrated_chain-a1114b52.png and b/previews/PR324/examples/spinw/SW03_Frustrated_chain-f8942e32.png differ diff --git a/previews/PR324/examples/spinw/SW03_Frustrated_chain.html b/previews/PR324/examples/spinw/SW03_Frustrated_chain.html index e2546df08..dd5a2f74e 100644 --- a/previews/PR324/examples/spinw/SW03_Frustrated_chain.html +++ b/previews/PR324/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.7699465438417114
- 0.9123010885693691
- 0.5533990312248818

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.7699465438366792
+ 0.021536911755733495
+ 0.4398350964579906

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/PR324/examples/spinw/SW04_Frustrated_square-1cb43940.png b/previews/PR324/examples/spinw/SW04_Frustrated_square-1cb43940.png new file mode 100644 index 000000000..042f01915 Binary files /dev/null and b/previews/PR324/examples/spinw/SW04_Frustrated_square-1cb43940.png differ diff --git a/previews/PR324/examples/spinw/SW04_Frustrated_square-3a9bcf38.png b/previews/PR324/examples/spinw/SW04_Frustrated_square-3a9bcf38.png new file mode 100644 index 000000000..c81201827 Binary files /dev/null and b/previews/PR324/examples/spinw/SW04_Frustrated_square-3a9bcf38.png differ diff --git a/previews/PR324/examples/spinw/SW04_Frustrated_square-42159e63.png b/previews/PR324/examples/spinw/SW04_Frustrated_square-42159e63.png deleted file mode 100644 index 6683b92c9..000000000 Binary files a/previews/PR324/examples/spinw/SW04_Frustrated_square-42159e63.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW04_Frustrated_square-ae7a4d4c.png b/previews/PR324/examples/spinw/SW04_Frustrated_square-ae7a4d4c.png deleted file mode 100644 index 7793c9f8c..000000000 Binary files a/previews/PR324/examples/spinw/SW04_Frustrated_square-ae7a4d4c.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW04_Frustrated_square.html b/previews/PR324/examples/spinw/SW04_Frustrated_square.html index e8b72d01b..7b55f1245 100644 --- a/previews/PR324/examples/spinw/SW04_Frustrated_square.html +++ b/previews/PR324/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/PR324/examples/spinw/SW05_Simple_kagome_FM-29e07dc7.png b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-29e07dc7.png deleted file mode 100644 index d1132d640..000000000 Binary files a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-29e07dc7.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-537df45a.png b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-537df45a.png new file mode 100644 index 000000000..0225c40a2 Binary files /dev/null and b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-537df45a.png differ diff --git a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-b12e736c.png b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-b12e736c.png deleted file mode 100644 index 7cd70c9ef..000000000 Binary files a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-b12e736c.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-bceec428.png b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-bceec428.png new file mode 100644 index 000000000..c735b60e3 Binary files /dev/null and b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-bceec428.png differ diff --git a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-c17c6655.png b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-c17c6655.png new file mode 100644 index 000000000..2b19f5405 Binary files /dev/null and b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-c17c6655.png differ diff --git a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-fa1f4001.png b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-fa1f4001.png deleted file mode 100644 index 391af8b54..000000000 Binary files a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM-fa1f4001.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM.html b/previews/PR324/examples/spinw/SW05_Simple_kagome_FM.html index 21c89e16f..2a2358986 100644 --- a/previews/PR324/examples/spinw/SW05_Simple_kagome_FM.html +++ b/previews/PR324/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/PR324/examples/spinw/SW06_Complex_kagome_FM-47b1a650.png b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-47b1a650.png deleted file mode 100644 index 1108fc225..000000000 Binary files a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-47b1a650.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-543a2c48.png b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-543a2c48.png new file mode 100644 index 000000000..0b4f1e4be Binary files /dev/null and b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-543a2c48.png differ diff --git a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-716fc4e5.png b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-716fc4e5.png deleted file mode 100644 index eedd1fd12..000000000 Binary files a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-716fc4e5.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-920f71f9.png b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-920f71f9.png new file mode 100644 index 000000000..2fa7ee586 Binary files /dev/null and b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-920f71f9.png differ diff --git a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-ebe751d6.png b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-ebe751d6.png new file mode 100644 index 000000000..3f8c4f17a Binary files /dev/null and b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-ebe751d6.png differ diff --git a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-ee0d1df1.png b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-ee0d1df1.png deleted file mode 100644 index cdd0b0ff7..000000000 Binary files a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM-ee0d1df1.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM.html b/previews/PR324/examples/spinw/SW06_Complex_kagome_FM.html index 709709ac1..593bfb295 100644 --- a/previews/PR324/examples/spinw/SW06_Complex_kagome_FM.html +++ b/previews/PR324/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/PR324/examples/spinw/SW07_k0_kagome_AFM-02ddb8e2.png b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-02ddb8e2.png deleted file mode 100644 index 3d05df83d..000000000 Binary files a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-02ddb8e2.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-484e3d86.png b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-484e3d86.png new file mode 100644 index 000000000..0b861678d Binary files /dev/null and b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-484e3d86.png differ diff --git a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-512db53b.png b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-512db53b.png new file mode 100644 index 000000000..f9e836c40 Binary files /dev/null and b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-512db53b.png differ diff --git a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-53e3b783.png b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-53e3b783.png deleted file mode 100644 index c64d92a68..000000000 Binary files a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-53e3b783.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-dd580323.png b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-dd580323.png deleted file mode 100644 index 868da41c5..000000000 Binary files a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-dd580323.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-df13adbf.png b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-df13adbf.png new file mode 100644 index 000000000..4c3a314cf Binary files /dev/null and b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM-df13adbf.png differ diff --git a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM.html b/previews/PR324/examples/spinw/SW07_k0_kagome_AFM.html index 84067a0f5..d5c541010 100644 --- a/previews/PR324/examples/spinw/SW07_k0_kagome_AFM.html +++ b/previews/PR324/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/PR324/examples/spinw/SW08_sqrt3_kagome_AFM.html b/previews/PR324/examples/spinw/SW08_sqrt3_kagome_AFM.html index 7736bdd02..74f943139 100644 --- a/previews/PR324/examples/spinw/SW08_sqrt3_kagome_AFM.html +++ b/previews/PR324/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/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-3788ef46.png b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-3788ef46.png new file mode 100644 index 000000000..617e62471 Binary files /dev/null and b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-3788ef46.png differ diff --git a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-483a9d68.png b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-483a9d68.png deleted file mode 100644 index 62fd9d21b..000000000 Binary files a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-483a9d68.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-92cad308.png b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-92cad308.png deleted file mode 100644 index 94369f623..000000000 Binary files a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-92cad308.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-d7ca942d.png b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-d7ca942d.png deleted file mode 100644 index 133e84647..000000000 Binary files a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-d7ca942d.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-e32384a1.png b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-e32384a1.png new file mode 100644 index 000000000..ac112f7a3 Binary files /dev/null and b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-e32384a1.png differ diff --git a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-e811945d.png b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-e811945d.png new file mode 100644 index 000000000..5f31824d7 Binary files /dev/null and b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM-e811945d.png differ diff --git a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM.html b/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM.html index 12564861b..848d33191 100644 --- a/previews/PR324/examples/spinw/SW09_k0_kagome_AFM_DM.html +++ b/previews/PR324/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/PR324/examples/spinw/SW10_Energy_cut-169a0fe1.png b/previews/PR324/examples/spinw/SW10_Energy_cut-169a0fe1.png new file mode 100644 index 000000000..3140d379d Binary files /dev/null and b/previews/PR324/examples/spinw/SW10_Energy_cut-169a0fe1.png differ diff --git a/previews/PR324/examples/spinw/SW10_Energy_cut-40145819.png b/previews/PR324/examples/spinw/SW10_Energy_cut-40145819.png new file mode 100644 index 000000000..f2a7db569 Binary files /dev/null and b/previews/PR324/examples/spinw/SW10_Energy_cut-40145819.png differ diff --git a/previews/PR324/examples/spinw/SW10_Energy_cut-7cae8963.png b/previews/PR324/examples/spinw/SW10_Energy_cut-7cae8963.png deleted file mode 100644 index 14b07bf95..000000000 Binary files a/previews/PR324/examples/spinw/SW10_Energy_cut-7cae8963.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW10_Energy_cut-aa6686db.png b/previews/PR324/examples/spinw/SW10_Energy_cut-aa6686db.png deleted file mode 100644 index 93c98d358..000000000 Binary files a/previews/PR324/examples/spinw/SW10_Energy_cut-aa6686db.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW10_Energy_cut-bd225a5f.png b/previews/PR324/examples/spinw/SW10_Energy_cut-bd225a5f.png new file mode 100644 index 000000000..bf28eaa85 Binary files /dev/null and b/previews/PR324/examples/spinw/SW10_Energy_cut-bd225a5f.png differ diff --git a/previews/PR324/examples/spinw/SW10_Energy_cut-ea4e8296.png b/previews/PR324/examples/spinw/SW10_Energy_cut-ea4e8296.png deleted file mode 100644 index ca75d40d2..000000000 Binary files a/previews/PR324/examples/spinw/SW10_Energy_cut-ea4e8296.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW10_Energy_cut.html b/previews/PR324/examples/spinw/SW10_Energy_cut.html index 745cee2df..22a161780 100644 --- a/previews/PR324/examples/spinw/SW10_Energy_cut.html +++ b/previews/PR324/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/PR324/examples/spinw/SW11_La2CuO4-3d30e33e.png b/previews/PR324/examples/spinw/SW11_La2CuO4-3d30e33e.png deleted file mode 100644 index f7a30caa1..000000000 Binary files a/previews/PR324/examples/spinw/SW11_La2CuO4-3d30e33e.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW11_La2CuO4-42079b4f.png b/previews/PR324/examples/spinw/SW11_La2CuO4-42079b4f.png new file mode 100644 index 000000000..7e6a3d5a2 Binary files /dev/null and b/previews/PR324/examples/spinw/SW11_La2CuO4-42079b4f.png differ diff --git a/previews/PR324/examples/spinw/SW11_La2CuO4-5f8388c1.png b/previews/PR324/examples/spinw/SW11_La2CuO4-5f8388c1.png deleted file mode 100644 index 72eaa3a32..000000000 Binary files a/previews/PR324/examples/spinw/SW11_La2CuO4-5f8388c1.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW11_La2CuO4-63b26945.png b/previews/PR324/examples/spinw/SW11_La2CuO4-63b26945.png new file mode 100644 index 000000000..ca5b834eb Binary files /dev/null and b/previews/PR324/examples/spinw/SW11_La2CuO4-63b26945.png differ diff --git a/previews/PR324/examples/spinw/SW11_La2CuO4-89bb1ad5.png b/previews/PR324/examples/spinw/SW11_La2CuO4-89bb1ad5.png new file mode 100644 index 000000000..cf34db2dc Binary files /dev/null and b/previews/PR324/examples/spinw/SW11_La2CuO4-89bb1ad5.png differ diff --git a/previews/PR324/examples/spinw/SW11_La2CuO4-97b78fc0.png b/previews/PR324/examples/spinw/SW11_La2CuO4-97b78fc0.png deleted file mode 100644 index ad1336f15..000000000 Binary files a/previews/PR324/examples/spinw/SW11_La2CuO4-97b78fc0.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW11_La2CuO4.html b/previews/PR324/examples/spinw/SW11_La2CuO4.html index 2bc53c747..23850e6a9 100644 --- a/previews/PR324/examples/spinw/SW11_La2CuO4.html +++ b/previews/PR324/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/PR324/examples/spinw/SW12_Triangular_easy_plane-0443c815.png b/previews/PR324/examples/spinw/SW12_Triangular_easy_plane-0443c815.png new file mode 100644 index 000000000..761605579 Binary files /dev/null and b/previews/PR324/examples/spinw/SW12_Triangular_easy_plane-0443c815.png differ diff --git a/previews/PR324/examples/spinw/SW12_Triangular_easy_plane-1422f4f7.png b/previews/PR324/examples/spinw/SW12_Triangular_easy_plane-1422f4f7.png deleted file mode 100644 index 50fbdb0a3..000000000 Binary files a/previews/PR324/examples/spinw/SW12_Triangular_easy_plane-1422f4f7.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW12_Triangular_easy_plane.html b/previews/PR324/examples/spinw/SW12_Triangular_easy_plane.html index d84b6843b..5954b147a 100644 --- a/previews/PR324/examples/spinw/SW12_Triangular_easy_plane.html +++ b/previews/PR324/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.13421e-12-5.20661e-13im
- -3.94492e-10-0.241929im        -5.20661e-13-1.13421e-12im
-  1.13421e-12+5.20661e-13im      6.43789e-24+0.0im
+ 0.241929+0.0im … 1.27623e-12+3.16678e-13im + -1.48359e-10-0.241929im 3.16678e-13-1.27623e-12im + 1.27623e-12-3.16678e-13im 7.14688e-24+0.0im diff --git a/previews/PR324/examples/spinw/SW13_LiNiPO4.html b/previews/PR324/examples/spinw/SW13_LiNiPO4.html index 7b8851a2f..284a80a31 100644 --- a/previews/PR324/examples/spinw/SW13_LiNiPO4.html +++ b/previews/PR324/examples/spinw/SW13_LiNiPO4.html @@ -47,4 +47,4 @@ lines!(ax, data_sorted[end, :]; label="Lower band") lines!(ax, data_sorted[end-1, :]; label="Upper band") axislegend(ax) -figExample block output +figExample block output diff --git a/previews/PR324/examples/spinw/SW14_YVO3.html b/previews/PR324/examples/spinw/SW14_YVO3.html index 90b82ac70..43ea1fe02 100644 --- a/previews/PR324/examples/spinw/SW14_YVO3.html +++ b/previews/PR324/examples/spinw/SW14_YVO3.html @@ -37,4 +37,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/PR324/examples/spinw/SW15_Ba3NbFe3Si2O14.html b/previews/PR324/examples/spinw/SW15_Ba3NbFe3Si2O14.html index 4d5e59a2a..682b64192 100644 --- a/previews/PR324/examples/spinw/SW15_Ba3NbFe3Si2O14.html +++ b/previews/PR324/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/PR324/examples/spinw/SW18_Distorted_kagome-1c295cc2.png b/previews/PR324/examples/spinw/SW18_Distorted_kagome-1c295cc2.png new file mode 100644 index 000000000..6eb990315 Binary files /dev/null and b/previews/PR324/examples/spinw/SW18_Distorted_kagome-1c295cc2.png differ diff --git a/previews/PR324/examples/spinw/SW18_Distorted_kagome-36546533.png b/previews/PR324/examples/spinw/SW18_Distorted_kagome-36546533.png deleted file mode 100644 index b571b666f..000000000 Binary files a/previews/PR324/examples/spinw/SW18_Distorted_kagome-36546533.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW18_Distorted_kagome-4ae164d4.png b/previews/PR324/examples/spinw/SW18_Distorted_kagome-4ae164d4.png new file mode 100644 index 000000000..8d2653682 Binary files /dev/null and b/previews/PR324/examples/spinw/SW18_Distorted_kagome-4ae164d4.png differ diff --git a/previews/PR324/examples/spinw/SW18_Distorted_kagome-a7cc16cb.png b/previews/PR324/examples/spinw/SW18_Distorted_kagome-a7cc16cb.png deleted file mode 100644 index 3e4943e5f..000000000 Binary files a/previews/PR324/examples/spinw/SW18_Distorted_kagome-a7cc16cb.png and /dev/null differ diff --git a/previews/PR324/examples/spinw/SW18_Distorted_kagome.html b/previews/PR324/examples/spinw/SW18_Distorted_kagome.html index 1a9a3e356..c2241fbcc 100644 --- a/previews/PR324/examples/spinw/SW18_Distorted_kagome.html +++ b/previews/PR324/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.8826980910582068 -0.36870195775674686 0.2913811016324502; -0.268868541296117 0.1123060723640469 0.9566070528756622; -0.38542676028461803 -0.9227384312233363 -1.8650900211434464e-9], [0.9152799761779687 0.16365821455287832 0.3680741148424066; 0.36232754545358264 0.06478660218442663 -0.9297964540602308; -0.17601509882177466 0.9843874668984571 5.317533692852246e-10], [-0.010418340252784014 -0.03926340731586708 0.9991745808577827; 0.25625678533743385 0.9657547840942091 0.04062212411571085; -0.9665525946139205 0.2564684811923215 -4.7401289054834536e-8], [0.20161424319760585 -0.6224501521042646 -0.7562456645067359; -0.23303179159337312 0.7194467938576276 -0.6542877768342942; 0.9513400449085696 0.3081430170446159 4.674212512062811e-8], [-0.018011101268494378 -0.036410947386817674 0.9991745809124102; 0.4430145685558199 0.8955936216771498 0.040622122772047874; -0.8963334715820875 0.44338054504184204 -4.72681650985316e-8], [0.07393362599732163 -0.6500971555169381 -0.7562456659946386; -0.08545465462683272 0.751402029101789 -0.6542877751145313; 0.9935951494192679 0.1129985798605483 4.869465392593272e-8]], StaticArraysCore.SVector{3, Float64}[[0.8826980910582068, -0.36870195775674686, 0.2913811016324502] [0.9152799761779687, 0.16365821455287832, 0.3680741148424066] … [-0.018011101268494378, -0.036410947386817674, 0.9991745809124102] [0.07393362599732163, -0.6500971555169381, -0.7562456659946386]; [-0.268868541296117, 0.1123060723640469, 0.9566070528756622] [0.36232754545358264, 0.06478660218442663, -0.9297964540602308] … [0.4430145685558199, 0.8955936216771498, 0.040622122772047874] [-0.08545465462683272, 0.751402029101789, -0.6542877751145313]; [-0.38542676028461803, -0.9227384312233363, -1.8650900211434464e-9] [-0.17601509882177466, 0.9843874668984571, 5.317533692852246e-10] … [-0.8963334715820875, 0.44338054504184204, -4.72681650985316e-8] [0.9935951494192679, 0.1129985798605483, 4.869465392593272e-8]], 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.21409750438249078, -3.517971182133808e-10, 0.8929512439353312], [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.8391630945100584 -0.41497527010281615 0.3515690913823321; -0.31514185390926724 0.15584106625029476 0.9361619379063655; -0.4432729551043396 -0.896386684011463 -4.540356029866034e-9], [0.9451971872892976 0.10760934894342389 0.30825720617752467; 0.30627868088898835 0.03486939622755482 -0.9513030509988009; -0.11311784462807688 0.993581578546371 5.79104614834368e-9], [0.0072805533675266276 0.021755151739640863 0.9997368188255586; 0.317275357889587 0.9480559341048832 -0.022941078539427895; -0.9483055102754054 0.31735888073489116 -1.7304859155040779e-9], [0.14946243318217914 -0.5861637136406485 -0.7962870599716327; -0.1967453708169943 0.7715985620388041 -0.6049189351654761; 0.9689954799323608 0.24707844881869806 1.3224943974967525e-9], [0.011457507403735277 0.01987507839958842 0.9997368187591691; 0.4993006147571852 0.8661250503742524 -0.02294108143258318; -0.8663530583008238 0.4994320558122091 -4.6860381628897176e-9], [0.030030383568355593 -0.6041730643796788 -0.7962870615178964; -0.03953058843855227 0.7953052350629335 -0.6049189331300467; 0.9987669941685295 0.049643643697463824 4.5092090674194605e-9]], StaticArraysCore.SVector{3, Float64}[[0.8391630945100584, -0.41497527010281615, 0.3515690913823321] [0.9451971872892976, 0.10760934894342389, 0.30825720617752467] … [0.011457507403735277, 0.01987507839958842, 0.9997368187591691] [0.030030383568355593, -0.6041730643796788, -0.7962870615178964]; [-0.31514185390926724, 0.15584106625029476, 0.9361619379063655] [0.30627868088898835, 0.03486939622755482, -0.9513030509988009] … [0.4993006147571852, 0.8661250503742524, -0.02294108143258318] [-0.03953058843855227, 0.7953052350629335, -0.6049189331300467]; [-0.4432729551043396, -0.896386684011463, -4.540356029866034e-9] [-0.11311784462807688, 0.993581578546371, 5.79104614834368e-9] … [-0.8663530583008238, 0.4994320558122091, -4.6860381628897176e-9] [0.9987669941685295, 0.049643643697463824, 4.5092090674194605e-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.21409750572126698, -6.479926307747066e-10, 0.89295126672753], [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/PR324/examples/spinw/SW19_Different_Ions.html b/previews/PR324/examples/spinw/SW19_Different_Ions.html index 9dbaec62e..77dfd0538 100644 --- a/previews/PR324/examples/spinw/SW19_Different_Ions.html +++ b/previews/PR324/examples/spinw/SW19_Different_Ions.html @@ -41,4 +41,4 @@ -0.1369821596259615 -0.1369821596261806 -0.5783052943233933 - -0.5783052943242701 + -0.5783052943242701 diff --git a/previews/PR324/index.html b/previews/PR324/index.html index 0e911466b..a26968d4a 100644 --- a/previews/PR324/index.html +++ b/previews/PR324/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/PR324/library.html b/previews/PR324/library.html index 9cd1deb69..29a51bbd6 100644 --- a/previews/PR324/library.html +++ b/previews/PR324/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,7 +33,7 @@
 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.

Efficiency considerations

Prefer Langevin sampling in most cases. Langevin dynamics will usually be much more efficient for sampling Heisenberg-like spins that vary continuously. LocalSampler is most useful for sampling from discrete spin states. In particular, propose_flip may be required for sampling Ising-like spins that arise due to a strong easy-axis anisotropy. For strong but finite single-ion anisotropy, consider alternating between Langevin and LocalSampler update steps.

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-calculated intensities are unreliable at small energies $ω$. In particular, KPM may mask intensities that 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_uncorrected, which corresponds to the formal $s → ∞$ 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] = Å
+    "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.

Efficiency considerations

Prefer Langevin sampling in most cases. Langevin dynamics will usually be much more efficient for sampling Heisenberg-like spins that vary continuously. LocalSampler is most useful for sampling from discrete spin states. In particular, propose_flip may be required for sampling Ising-like spins that arise due to a strong easy-axis anisotropy. For strong but finite single-ion anisotropy, consider alternating between Langevin and LocalSampler update steps.

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-calculated intensities are unreliable at small energies $ω$. In particular, KPM may mask intensities that 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_uncorrected, which corresponds to the formal $s → ∞$ 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
@@ -49,45 +49,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 sites (singly counted), including periodic images, regularized using the Ewald summation convention. Each magnetic moment is $μ = -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.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 sites (singly counted), including periodic images, regularized using the Ewald summation convention. Each magnetic moment is $μ = -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.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]
@@ -97,9 +97,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 would be symmetry equivalent to a given Bond in a homogeneous system. For smaller systems, 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 would be symmetry equivalent to a given Bond in a homogeneous system. For smaller systems, 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
@@ -108,35 +108,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)
Limitations arising from quantum spin operators

Single-ion anisotropy is physically impossible for local moments with quantum spin $s = 1/2$. Consider, for example, that any Pauli matrix squared gives the identity. More generally, one can verify that the $k$th order Stevens operators O[k, q] are zero whenever $s < k/2$. Consequently, an anisotropy quartic in the spin operators requires $s ≥ 2$ and an anisotropy of sixth order requires $s ≥ 3$. To circumvent this physical limitation, Sunny provides a mode :dipole_uncorrected that naïvely replaces quantum spin operators with classical moments. See the documentation page Interaction Renormalization for more information.

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)
Limitations arising from quantum spin operators

Single-ion anisotropy is physically impossible for local moments with quantum spin $s = 1/2$. Consider, for example, that any Pauli matrix squared gives the identity. More generally, one can verify that the $k$th order Stevens operators O[k, q] are zero whenever $s < k/2$. Consequently, an anisotropy quartic in the spin operators requires $s ≥ 2$ and an anisotropy of sixth order requires $s ≥ 3$. To circumvent this physical limitation, Sunny provides a mode :dipole_uncorrected that naïvely replaces quantum spin operators with classical moments. See the documentation page Interaction Renormalization for more information.

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, site1::Site, site2::Site; offset=nothing)

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 would be symmetry equivalent to a given Bond in a homogeneous system. For smaller systems, 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, site1::Site, site2::Site; offset=nothing)

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 would be symmetry equivalent to a given Bond in a homogeneous system. For smaller systems, 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 the 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 representation, 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 the 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 representation, 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]
 
@@ -149,17 +149,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 and an offset, 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 and an offset, 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, 
@@ -167,8 +167,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/PR324/parallelism.html b/previews/PR324/parallelism.html index 90b281fd0..198f1e1b8 100644 --- a/previews/PR324/parallelism.html +++ b/previews/PR324/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/PR324/renormalization.html b/previews/PR324/renormalization.html index e4b366d80..0829cd852 100644 --- a/previews/PR324/renormalization.html +++ b/previews/PR324/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/PR324/structure-factor.html b/previews/PR324/structure-factor.html index a37e93ae9..93b51d842 100644 --- a/previews/PR324/structure-factor.html +++ b/previews/PR324/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/PR324/versions.html b/previews/PR324/versions.html index 537e97b58..822aec29b 100644 --- a/previews/PR324/versions.html +++ b/previews/PR324/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.
  • Rename mode :dipole_large_S to :dipole_uncorrected to emphasize that corrections are missing.

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.
  • 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.
  • Rename mode :dipole_large_S to :dipole_uncorrected to emphasize that corrections are missing.

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.
  • 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/PR324/writevtk.html b/previews/PR324/writevtk.html index 8a78ae2f1..9b2ba3dcc 100644 --- a/previews/PR324/writevtk.html +++ b/previews/PR324/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)