From 36b361b43d7a3e59dcb4b23da0aa4990879c4d57 Mon Sep 17 00:00:00 2001 From: Kipton Barros Date: Fri, 20 Sep 2024 16:05:52 -0600 Subject: [PATCH] Rename :dipole_large_s to :dipole_uncorrected --- docs/src/renormalization.md | 33 ++++++++++--------- docs/src/versions.md | 4 ++- .../SW12_Triangular_easy_plane.jl | 2 +- examples/spinw_tutorials/SW13_LiNiPO4.jl | 4 +-- examples/spinw_tutorials/SW14_YVO3.jl | 5 +-- src/EntangledUnits/EntangledSpinWaveTheory.jl | 2 +- src/KPM/SpinWaveTheoryKPM.jl | 2 +- .../DispersionAndIntensities.jl | 2 +- src/SpinWaveTheory/LSWTCorrections.jl | 4 +-- src/SpinWaveTheory/SpinWaveTheory.jl | 2 +- src/Spiral/LuttingerTisza.jl | 2 +- src/Spiral/SpinWaveTheorySpiral.jl | 2 +- src/Spiral/SpiralEnergy.jl | 4 +-- src/System/Interactions.jl | 8 ++--- src/System/OnsiteCoupling.jl | 12 +++---- src/System/PairExchange.jl | 22 ++++++------- src/System/System.jl | 20 +++++------ src/System/Types.jl | 2 +- test/shared.jl | 4 +-- test/test_rescaling.jl | 6 ++-- 20 files changed, 73 insertions(+), 69 deletions(-) diff --git a/docs/src/renormalization.md b/docs/src/renormalization.md index b3622b0cf..84558a39d 100644 --- a/docs/src/renormalization.md +++ b/docs/src/renormalization.md @@ -80,12 +80,11 @@ same form, but now applied to the expected dipole. Classical Stevens functions are constructed as homogeneous polynomials of order $k$, because lower-order terms would vanish in the limit $s \to \infty$. -In a real magnetic compound, however, the spin magnitude $s$ is not necessarily -large. To obtain a better approximation, one should avoid the formal limit $s -\to \infty$. Our approach is to start with the full dynamics of SU(_N_) coherent -states, and then constrain it to the space of pure dipole states -$|\boldsymbol{\Omega}\rangle$. The latter are defined as any states where the -expected dipole 3-vector, +For real compounds with finite quantum spin-$s$, one can obtain a better +approximation by avoiding the formal $s \to \infty$ limit. Corrections can be +derived by starting from the full dynamics of SU(_N_) coherent states and then +constraining to the space of pure dipole states $|\boldsymbol{\Omega}\rangle$. +The latter are defined as any states where the expected dipole 3-vector, ```math \boldsymbol{\Omega} ≡ \langle \boldsymbol{\Omega}| \hat{\mathbf{S}} | \boldsymbol{\Omega}\rangle, ``` @@ -128,8 +127,8 @@ interpreted as a correction to the traditional large-$s$ classical limit. Renormalization also applies to the coupling between different sites. In Sunny, couplings will often be expressed as a polynomial of spin operators using -[`set_pair_coupling!`](@ref), but any such coupling can be decomposed as sum of -tensor products of Stevens operators. Without loss of generality, consider a +[`set_pair_coupling!`](@ref), but any such coupling can be decomposed as a sum +of tensor products of Stevens operators. Without loss of generality, consider a single coupling between two Stevens operators $\hat{\mathcal{H}}_\mathrm{coupling} = \hat{\mathcal{O}}_{k,q} \otimes \hat{\mathcal{O}}_{k',q'}$ along a bond connecting sites $i$ and $j$. Upon @@ -139,16 +138,18 @@ $E_\mathrm{coupling} = c_k c_k' \mathcal{O}_{k,q}(\boldsymbol{\Omega}_i) \mathcal{O}_{k',q'}(\boldsymbol{\Omega}_j)$, which now involves a product of renormalized Stevens functions. -## Use `:dipole_large_s` mode to disable renormalization +## Use `:dipole_uncorrected` mode to disable renormalization Although we generally recommend the above renormalization procedure, there are -circumstances where it is not desirable. Examples include reproducing a -model-system study, or describing a micromagnetic system for which the -$s\to\infty$ limit is a good approximation. To simulate dipoles without -interaction strength renormalization, construct a [`System`](@ref) using the -mode `:dipole_large_s` instead of `:dipole`. Symbolic operators in the large-$s$ -limit can be constructed by passing `Inf` to either [`spin_matrices`](@ref) or -[`stevens_matrices`](@ref). +cases where it is not desirable. Examples include reproducing a legacy study, or +modeling a micromagnetic system for which the $s\to\infty$ limit is a good +approximation. To simulate dipoles without interaction strength renormalization, +construct a [`System`](@ref) using the mode `:dipole_uncorrected` instead of +`:dipole`. The fundamental difference between the two modes is the type of +operator expected by [`set_onsite_coupling!`](@ref). The mode +`:dipole_uncorrected` expects infinite-dimensional operators in the $s → ∞$ +limit. These can be obtained by passing `Inf` to either [`spin_matrices`](@ref) +or [`stevens_matrices`](@ref). ## Definition of Stevens operators diff --git a/docs/src/versions.md b/docs/src/versions.md index 0256217d6..b173f0499 100644 --- a/docs/src/versions.md +++ b/docs/src/versions.md @@ -7,6 +7,8 @@ #317](https://github.com/SunnySuite/Sunny.jl/pull/317)). * Stabilize [`SpinWaveTheoryKPM`](@ref). 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) @@ -49,7 +51,7 @@ This **major release** introduces breaking interface changes. [`domain_average`](@ref), which wrap [`intensities`](@ref). * [`System`](@ref) now expects supercell dimensions as a `dims` keyword argument. [`Moment`](@ref) replaces `SpinInfo`. Lower-case `s` now labels - quantum spin. For example, use `:dipole_large_s` instead of `:dipole_large_S`. + quantum spin. * In [`view_crystal`](@ref) and [`plot_spins`](@ref) use `ndims` instead of `dims` for the number of spatial dimensions. * Binning features have been removed. Some functionality may be added back in a diff --git a/examples/spinw_tutorials/SW12_Triangular_easy_plane.jl b/examples/spinw_tutorials/SW12_Triangular_easy_plane.jl index 59e46cc5d..8b2c5637d 100644 --- a/examples/spinw_tutorials/SW12_Triangular_easy_plane.jl +++ b/examples/spinw_tutorials/SW12_Triangular_easy_plane.jl @@ -31,7 +31,7 @@ set_exchange!(sys, J1, Bond(1, 1, [1, 0, 0])) # interaction strength as ``D → (1 - 1/2s) D``. We must "undo" Sunny's # classical-to-quantum rescaling factor to reproduce the SpinW calculation. # Alternatively, renormalization can be disabled by selecting the system mode -# `:dipole_large_s` instead of `:dipole`. +# `:dipole_uncorrected` instead of `:dipole`. undo_classical_to_quantum_rescaling = 1 / (1 - 1/2s) D = 0.2 * undo_classical_to_quantum_rescaling diff --git a/examples/spinw_tutorials/SW13_LiNiPO4.jl b/examples/spinw_tutorials/SW13_LiNiPO4.jl index 0b44f34b8..872f579bc 100644 --- a/examples/spinw_tutorials/SW13_LiNiPO4.jl +++ b/examples/spinw_tutorials/SW13_LiNiPO4.jl @@ -24,11 +24,11 @@ view_crystal(cryst) # Create a system with exchange parameters taken from [T. Jensen, et al., PRB # **79**, 092413 (2009)](https://doi.org/10.1103/PhysRevB.79.092413). The # corrected anisotropy values are taken from the thesis of T. Jensen. The mode -# `:dipole_large_s` avoids a [classical-to-quantum rescaling factor](@ref +# `:dipole_uncorrected` avoids a [classical-to-quantum rescaling factor](@ref # "Interaction Renormalization") of anisotropy strengths, as needed for # consistency with the original fits. -sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole_large_s) +sys = System(cryst, [1 => Moment(s=1, g=2)], :dipole_uncorrected) Jbc = 1.036 Jb = 0.6701 Jc = -0.0469 diff --git a/examples/spinw_tutorials/SW14_YVO3.jl b/examples/spinw_tutorials/SW14_YVO3.jl index 21a46963e..bc697ece2 100644 --- a/examples/spinw_tutorials/SW14_YVO3.jl +++ b/examples/spinw_tutorials/SW14_YVO3.jl @@ -25,11 +25,12 @@ cryst = Crystal(latvecs, positions, 1; types) # Create a system following the model of [C. Ulrich, et al. PRL **91**, 257202 # (2003)](https://doi.org/10.1103/PhysRevLett.91.257202). The mode -# `:dipole_large_s` avoids a [classical-to-quantum rescaling factor](@ref +# `:dipole_uncorrected` avoids a [classical-to-quantum rescaling factor](@ref # "Interaction Renormalization") of anisotropy strengths, as needed for # consistency with the original fits. -sys = System(cryst, [1 => Moment(s=1/2, g=2), 2 => Moment(s=1/2, g=2)], :dipole_large_s; dims=(2,2,1)) +moments = [1 => Moment(s=1/2, g=2), 2 => Moment(s=1/2, g=2)] +sys = System(cryst, moments, :dipole_uncorrected; dims=(2,2,1)) Jab = 2.6 Jc = 3.1 δ = 0.35 diff --git a/src/EntangledUnits/EntangledSpinWaveTheory.jl b/src/EntangledUnits/EntangledSpinWaveTheory.jl index 0c5b134d1..636e5a097 100644 --- a/src/EntangledUnits/EntangledSpinWaveTheory.jl +++ b/src/EntangledUnits/EntangledSpinWaveTheory.jl @@ -235,7 +235,7 @@ function dynamical_matrix!(H, swt::EntangledSpinWaveTheory, q_reshaped) if swt.sys.mode == :SUN swt_hamiltonian_SUN!(H, swt, q_reshaped) else - @assert swt.sys.mode in (:dipole, :dipole_large_S) + @assert swt.sys.mode in (:dipole, :dipole_uncorrected) swt_hamiltonian_dipole!(H, swt, q_reshaped) end end diff --git a/src/KPM/SpinWaveTheoryKPM.jl b/src/KPM/SpinWaveTheoryKPM.jl index 63f83c6be..8d8f9ec8f 100644 --- a/src/KPM/SpinWaveTheoryKPM.jl +++ b/src/KPM/SpinWaveTheoryKPM.jl @@ -112,7 +112,7 @@ function intensities!(data, swt_kpm::SpinWaveTheoryKPM, qpts; energies, kernel:: end end else - @assert sys.mode in (:dipole, :dipole_large_s) + @assert sys.mode in (:dipole, :dipole_uncorrected) (; sqrtS, observables_localized) = swt.data::SWTDataDipole for i in 1:Na for μ in 1:Nobs diff --git a/src/SpinWaveTheory/DispersionAndIntensities.jl b/src/SpinWaveTheory/DispersionAndIntensities.jl index 9eb4678f5..9e6a0c1e5 100644 --- a/src/SpinWaveTheory/DispersionAndIntensities.jl +++ b/src/SpinWaveTheory/DispersionAndIntensities.jl @@ -199,7 +199,7 @@ function intensities_bands(swt::SpinWaveTheory, qpts; kT=0, with_negative=false) end end else - @assert sys.mode in (:dipole, :dipole_large_s) + @assert sys.mode in (:dipole, :dipole_uncorrected) data = swt.data::SWTDataDipole t = reshape(view(T, :, band), Na, 2) for i in 1:Na, μ in 1:Nobs diff --git a/src/SpinWaveTheory/LSWTCorrections.jl b/src/SpinWaveTheory/LSWTCorrections.jl index 326596366..7d809fe8d 100644 --- a/src/SpinWaveTheory/LSWTCorrections.jl +++ b/src/SpinWaveTheory/LSWTCorrections.jl @@ -97,7 +97,7 @@ end magnetization_lswt_correction(swt::SpinWaveTheory; opts...) Calculates the reduction in the classical dipole magnitude for all atoms in the -magnetic cell. In the case of `:dipole` and `:dipole_large_s` mode, the +magnetic cell. In the case of `:dipole` and `:dipole_uncorrected` mode, the classical dipole magnitude is constrained to spin-`s`. While in `:SUN` mode, the classical dipole magnitude can be smaller than `s` due to anisotropic interactions. @@ -113,7 +113,7 @@ function magnetization_lswt_correction(swt::SpinWaveTheory; opts...) if sys.mode == :SUN δS = magnetization_lswt_correction_sun(swt; opts...) else - @assert sys.mode in (:dipole, :dipole_large_s) + @assert sys.mode in (:dipole, :dipole_uncorrected) δS = magnetization_lswt_correction_dipole(swt; opts...) end return δS diff --git a/src/SpinWaveTheory/SpinWaveTheory.jl b/src/SpinWaveTheory/SpinWaveTheory.jl index 3e37804f9..1b51ee968 100644 --- a/src/SpinWaveTheory/SpinWaveTheory.jl +++ b/src/SpinWaveTheory/SpinWaveTheory.jl @@ -99,7 +99,7 @@ function dynamical_matrix!(H, swt::SpinWaveTheory, q_reshaped) if swt.sys.mode == :SUN swt_hamiltonian_SUN!(H, swt, q_reshaped) else - @assert swt.sys.mode in (:dipole, :dipole_large_s) + @assert swt.sys.mode in (:dipole, :dipole_uncorrected) swt_hamiltonian_dipole!(H, swt, q_reshaped) end end diff --git a/src/Spiral/LuttingerTisza.jl b/src/Spiral/LuttingerTisza.jl index 7b39fcadc..5a1670221 100644 --- a/src/Spiral/LuttingerTisza.jl +++ b/src/Spiral/LuttingerTisza.jl @@ -3,7 +3,7 @@ # wavevector k between Bravais lattice cells. This analysis ignores local # normalization constraints for the spins within the cell. function luttinger_tisza_exchange(sys::System; k, ϵ=0) - @assert sys.mode in (:dipole, :dipole_large_s) "SU(N) mode not supported" + @assert sys.mode in (:dipole, :dipole_uncorrected) "SU(N) mode not supported" @assert sys.dims == (1, 1, 1) "System must have only a single cell" Na = natoms(sys.crystal) diff --git a/src/Spiral/SpinWaveTheorySpiral.jl b/src/Spiral/SpinWaveTheorySpiral.jl index 32f0e68e7..3768c99b9 100644 --- a/src/Spiral/SpinWaveTheorySpiral.jl +++ b/src/Spiral/SpinWaveTheorySpiral.jl @@ -181,7 +181,7 @@ function intensities_bands(sswt::SpinWaveTheorySpiral, qpts; kT=0) # TODO: branc (; sys, data, measure) = swt isempty(measure.observables) && error("No observables! Construct SpinWaveTheorySpiral with a `measure` argument.") sys.mode == :SUN && error("SU(N) mode not supported for spiral calculation") - @assert sys.mode in (:dipole, :dipole_large_s) + @assert sys.mode in (:dipole, :dipole_uncorrected) qpts = convert(AbstractQPoints, qpts) cryst = orig_crystal(sys) diff --git a/src/Spiral/SpiralEnergy.jl b/src/Spiral/SpiralEnergy.jl index e746194fd..37e76a883 100644 --- a/src/Spiral/SpiralEnergy.jl +++ b/src/Spiral/SpiralEnergy.jl @@ -17,7 +17,7 @@ special case ``𝐤 = 0`` yields result is identical to [`energy`](@ref). See also [`minimize_spiral_energy!`](@ref) and [`repeat_periodically_as_spiral`](@ref). """ function spiral_energy(sys::System{0}; k, axis) - sys.mode in (:dipole, :dipole_large_s) || error("SU(N) mode not supported") + sys.mode in (:dipole, :dipole_uncorrected) || error("SU(N) mode not supported") sys.dims == (1, 1, 1) || error("System must have only a single cell") check_rotational_symmetry(sys; axis, θ=0.01) @@ -198,7 +198,7 @@ approximately commensurate with the returned propagation wavevector ``𝐤``. function minimize_spiral_energy!(sys, axis; maxiters=10_000, k_guess=randn(sys.rng, 3)) axis = normalize(axis) - sys.mode in (:dipole, :dipole_large_s) || error("SU(N) mode not supported") + sys.mode in (:dipole, :dipole_uncorrected) || error("SU(N) mode not supported") sys.dims == (1, 1, 1) || error("System must have only a single cell") norm([S × axis for S in sys.dipoles]) > 1e-12 || error("Spins cannot be exactly aligned with polarization axis") diff --git a/src/System/Interactions.jl b/src/System/Interactions.jl index 50066d44c..b37439a66 100644 --- a/src/System/Interactions.jl +++ b/src/System/Interactions.jl @@ -195,7 +195,7 @@ function local_energy_change(sys::System{N}, site, state::SpinState) where N # Biquadratic if !iszero(pc.biquad) - if sys.mode in (:dipole, :dipole_large_s) + if sys.mode in (:dipole, :dipole_uncorrected) ΔQ = quadrupole(S) - quadrupole(S₀) Qⱼ = quadrupole(Sⱼ) else @@ -315,7 +315,7 @@ function energy_aux(ints::Interactions, sys::System{N}, i::Int, cells) where N # Biquadratic if !iszero(pc.biquad) - if sys.mode in (:dipole, :dipole_large_s) + if sys.mode in (:dipole, :dipole_uncorrected) Qᵢ = quadrupole(Sᵢ) Qⱼ = quadrupole(Sⱼ) else @@ -386,7 +386,7 @@ end function set_energy_grad_dipoles_aux!(∇E, dipoles::Array{Vec3, 4}, ints::Interactions, sys::System{N}, i::Int, cells) where N # Single-ion anisotropy only contributes in dipole mode. In SU(N) mode, the # anisotropy matrix will be incorporated directly into local H matrix. - if sys.mode in (:dipole, :dipole_large_s) + if sys.mode in (:dipole, :dipole_uncorrected) stvexp = ints.onsite :: StevensExpansion for cell in cells S = dipoles[cell, i] @@ -409,7 +409,7 @@ function set_energy_grad_dipoles_aux!(∇E, dipoles::Array{Vec3, 4}, ints::Inter ∇E[cellⱼ, bond.j] += J' * Sᵢ # Biquadratic for dipole mode only (SU(N) handled differently) - if sys.mode in (:dipole, :dipole_large_s) + if sys.mode in (:dipole, :dipole_uncorrected) if !iszero(pc.biquad) Qᵢ = quadrupole(Sᵢ) Qⱼ = quadrupole(Sⱼ) diff --git a/src/System/OnsiteCoupling.jl b/src/System/OnsiteCoupling.jl index ede5626a7..fa2bcb542 100644 --- a/src/System/OnsiteCoupling.jl +++ b/src/System/OnsiteCoupling.jl @@ -4,7 +4,7 @@ function onsite_coupling(sys, site, matrep::AbstractMatrix) matrep ≈ matrep' || error("Operator is not Hermitian") if N == 2 && isapprox(matrep, matrep[1, 1] * I; atol=1e-8) - suggest = sys.mode == :dipole ? " (use :dipole_large_s to reproduce legacy calculations)" : "" + suggest = sys.mode == :dipole ? " (use :dipole_uncorrected for legacy calculations)" : "" @warn "Onsite coupling is always trivial for quantum spin s=1/2" * suggest end @@ -14,14 +14,14 @@ function onsite_coupling(sys, site, matrep::AbstractMatrix) s = spin_label(sys, to_atom(site)) c = matrix_to_stevens_coefficients(hermitianpart(matrep)) return StevensExpansion(rcs_factors(s) .* c) - elseif sys.mode == :dipole_large_s - error("System with mode `:dipole_large_s` requires a symbolic operator.") + elseif sys.mode == :dipole_uncorrected + error("System with mode `:dipole_uncorrected` requires a symbolic operator.") end end function onsite_coupling(sys, site, p::DP.AbstractPolynomialLike) - if sys.mode != :dipole_large_s - error("Symbolic operator only valid for system with mode `:dipole_large_s`.") + if sys.mode != :dipole_uncorrected + error("Symbolic operator only valid for system with mode `:dipole_uncorrected`.") end s = sys.κs[site] @@ -47,7 +47,7 @@ function rcs_factors(s) end function empty_anisotropy(mode, N) - if mode == :dipole || mode == :dipole_large_s + if mode in (:dipole, :dipole_uncorrected) c = map(k -> zeros(2k+1), OffsetArray(0:6, 0:6)) return StevensExpansion(c) elseif mode == :SUN diff --git a/src/System/PairExchange.jl b/src/System/PairExchange.jl index 24355b52c..8bc27a7fa 100644 --- a/src/System/PairExchange.jl +++ b/src/System/PairExchange.jl @@ -195,7 +195,7 @@ end function check_allowable_dipole_coupling(tensordec, mode) - if !isempty(tensordec.data) && mode in (:dipole, :dipole_large_s) + if !isempty(tensordec.data) && mode in (:dipole, :dipole_uncorrected) error(""" Invalid pair coupling. In dipole mode, the most general allowed form is (Si, Sj) -> Si'*J*Sj + [(Si'*K1*Si)*(Sj'*K2*Sj) + ...] @@ -290,8 +290,8 @@ function set_pair_coupling!(sys::System{N}, op::AbstractMatrix, bond; extract_pa op ≈ op' || error("Operator is not Hermitian") - if sys.mode == :dipole_large_s - error("Symbolic operators required for mode `:dipole_large_s`.") + if sys.mode == :dipole_uncorrected + error("Symbolic operators required for mode `:dipole_uncorrected`.") end Ni = Int(2spin_label(sys, bond.i)+1) @@ -303,8 +303,8 @@ function set_pair_coupling!(sys::System{N}, op::AbstractMatrix, bond; extract_pa end function set_pair_coupling!(sys::System{N}, fn::Function, bond; extract_parts=true) where N - if sys.mode == :dipole_large_s - error("General couplings not yet supported for mode `:dipole_large_s`.") + if sys.mode == :dipole_uncorrected + error("General couplings not supported for mode `:dipole_uncorrected`.") end si = spin_label(sys, bond.i) @@ -319,7 +319,7 @@ end # are the five Stevens quadrupoles, and g is the `scalar_biquad_metric`. The # parameter `biquad` is accepted as the coefficient to (Sᵢ⋅Sⱼ)², but is returned # as the coefficient to Qᵢ⋅g Qⱼ. This is achieved via a shift of the bilinear -# and scalar parts. In the special case of :dipole_large_s, the limiting +# and scalar parts. In the special case of :dipole_uncorrected, the limiting # behavior is Sᵢ²Sⱼ² → sᵢ²sⱼ² (just the spin labels squared), and 𝒪(s²) → 0 # (homogeneous in quartic order of spin). function adapt_for_biquad(scalar, bilin, biquad, sys, site1, site2) @@ -333,7 +333,7 @@ function adapt_for_biquad(scalar, bilin, biquad, sys, site1, site2) bilin -= (bilin isa Number) ? biquad/2 : (biquad/2)*I scalar += biquad * s1*(s1+1) * s2*(s2+1) / 3 else - @assert sys.mode == :dipole_large_s + @assert sys.mode == :dipole_uncorrected s1 = sys.κs[to_cartesian(site1)] s2 = sys.κs[to_cartesian(site2)] scalar += biquad * s1^2 * s2^2 / 3 @@ -491,8 +491,8 @@ two sites. The documentation for [`set_pair_coupling!`](@ref) provides examples constructing `op`. """ function set_pair_coupling_at!(sys::System{N}, op::AbstractMatrix, site1::Site, site2::Site; offset=nothing) where N - if sys.mode == :dipole_large_s - error("Symbolic operators required for mode `:dipole_large_s`.") + if sys.mode == :dipole_uncorrected + error("Symbolic operators required for mode `:dipole_uncorrected`.") end N1 = Int(2spin_label(sys, to_atom(site1))+1) @@ -504,8 +504,8 @@ function set_pair_coupling_at!(sys::System{N}, op::AbstractMatrix, site1::Site, end function set_pair_coupling_at!(sys::System{N}, fn::Function, site1::Site, site2::Site; offset=nothing) where N - if sys.mode == :dipole_large_s - error("General couplings not yet supported for mode `:dipole_large_s`.") + if sys.mode == :dipole_uncorrected + error("General couplings not yet supported for mode `:dipole_uncorrected`.") end s1 = spin_label(sys, to_atom(site1)) diff --git a/src/System/System.jl b/src/System/System.jl index b3973abb2..8326ee554 100644 --- a/src/System/System.jl +++ b/src/System/System.jl @@ -20,8 +20,8 @@ Mode `:dipole` projects the SU(_N_) dynamics onto the restricted space of pure dipoles. In practice this means that Sunny will simulate Landau-Lifshitz dynamics, but single-ion anisotropy and biquadratic exchange interactions will be renormalized to improve accuracy. To disable this renormalization, use the -mode `:dipole_large_s` which applies the ``s → ∞`` classical limit. For details, -see the documentation page: [Interaction Renormalization](@ref). +mode `:dipole_uncorrected`, which corresponds to the formal ``s → ∞`` limit. For +details, see the documentation page: [Interaction Renormalization](@ref). An integer `seed` for the random number generator can optionally be specified to enable reproducible calculations. @@ -33,13 +33,13 @@ function System(crystal::Crystal, moments::Vector{Pair{Int, Moment}}, mode::Symb if !isnothing(units) @warn "units argument to System is deprecated and will be ignored!" end - if mode == :dipole_large_S - @warn "Deprecation warning! Use :dipole_large_s instead of :dipole_large_S" - mode = :dipole_large_s + if mode in (:dipole_large_S, :dipole_large_s) + @warn "Deprecation warning! Use :dipole_uncorrected instead of $mode" + mode = :dipole_uncorrected end - if !in(mode, (:SUN, :dipole, :dipole_large_s)) - error("Mode must be `:SUN`, `:dipole`, or `:dipole_large_s`.") + if !in(mode, (:SUN, :dipole, :dipole_uncorrected)) + error("Mode must be `:SUN`, `:dipole`, or `:dipole_uncorrected`.") end # The lattice vectors of `crystal` must be conventional (`crystal` cannot be @@ -61,7 +61,7 @@ function System(crystal::Crystal, moments::Vector{Pair{Int, Moment}}, mode::Symb allequal(Ns) || error("Currently all spins S must be equal in SU(N) mode.") N = first(Ns) κs = fill(1.0, na) - elseif mode in (:dipole, :dipole_large_s) + elseif mode in (:dipole, :dipole_uncorrected) N = 0 # marker for :dipole mode κs = copy(Ss) end @@ -91,7 +91,7 @@ function mode_to_str(sys::System{N}) where N return "[SU($N)]" elseif sys.mode == :dipole return "[Dipole mode]" - elseif sys.mode == :dipole_large_s + elseif sys.mode == :dipole_uncorrected return "[Dipole mode, large-s]" else error() @@ -210,7 +210,7 @@ If atom `i` carries a single spin-``s`` moment, then returns the half-integer label ``s``. Otherwise, throws an error. """ function spin_label(sys::System, i::Int) - if sys.mode == :dipole_large_s + if sys.mode == :dipole_uncorrected return Inf else @assert sys.mode in (:dipole, :SUN) diff --git a/src/System/Types.jl b/src/System/Types.jl index 5653f3aa9..cdace1b23 100644 --- a/src/System/Types.jl +++ b/src/System/Types.jl @@ -85,7 +85,7 @@ end mutable struct System{N} const origin :: Union{Nothing, System{N}} # System for the original chemical cell - const mode :: Symbol # :SUN, :dipole, or :dipole_large_s + const mode :: Symbol # :SUN, :dipole, or :dipole_uncorrected const crystal :: Crystal const dims :: NTuple{3, Int} # Dimensions of lattice in unit cells diff --git a/test/shared.jl b/test/shared.jl index ecc77d766..b791901ac 100644 --- a/test/shared.jl +++ b/test/shared.jl @@ -28,7 +28,7 @@ function add_exchange_interactions!(sys, _) end function add_quadratic_interactions!(sys, mode) - if mode in (:dipole, :dipole_large_s) + if mode in (:dipole, :dipole_uncorrected) add_exchange_interactions!(sys, mode) else @assert mode == :SUN @@ -51,7 +51,7 @@ function add_quadratic_interactions!(sys, mode) end function add_quartic_interactions!(sys, mode) - if mode in (:dipole, :dipole_large_s) + if mode in (:dipole, :dipole_uncorrected) # Stevens operators O[4,q] are quartic in dipoles i = 3 O = stevens_matrices(spin_label(sys, i)) diff --git a/test/test_rescaling.jl b/test/test_rescaling.jl index 89727d819..092f8e5e6 100644 --- a/test/test_rescaling.jl +++ b/test/test_rescaling.jl @@ -98,7 +98,7 @@ end for k in (2, 4, 6) c = randn(2k+1) - E1, E2 = map([:dipole, :dipole_large_s]) do mode + E1, E2 = map([:dipole, :dipole_uncorrected]) do mode sys = System(cryst, [1 => Moment(; s, g=2)], mode) O = stevens_matrices(spin_label(sys, 1)) set_onsite_coupling!(sys, sum(c[k-q+1]*O[k, q] for q in -k:k), 1) @@ -113,7 +113,7 @@ end cryst = Sunny.square_crystal() s = 3/2 - sys1 = System(cryst, [1 => Moment(; s, g=2)], :dipole_large_s, seed=0) + sys1 = System(cryst, [1 => Moment(; s, g=2)], :dipole_uncorrected, seed=0) sys2 = System(cryst, [1 => Moment(; s, g=2)], :dipole, seed=0) # Reference scalar biquadratic without renormalization @@ -167,7 +167,7 @@ end @test E_dipole ≈ E_SUN_1 ≈ E_SUN_2 # Biquadratic energy in large-s limit is classical formula - sys = System(cryst, [1 => Moment(s=s1, g=-1), 2 => Moment(s=s2, g=-1)], :dipole_large_s) + sys = System(cryst, [1 => Moment(s=s1, g=-1), 2 => Moment(s=s2, g=-1)], :dipole_uncorrected) set_dipole!(sys, v1, (1, 1, 1, 1)) set_dipole!(sys, v2, (1, 1, 1, 2)) set_exchange!(sys, 0.0, bond; biquad)