-
Notifications
You must be signed in to change notification settings - Fork 19
/
SpinInfo.jl
43 lines (38 loc) · 1.67 KB
/
SpinInfo.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
"""
SpinInfo(atom::Int; S, g=2)
Characterizes the spin at a given `atom` index within the crystal unit cell. `S`
is an integer multiple of 1/2 and gives the spin angular momentum in units of ħ.
`g` is the g-factor or tensor, such that an angular momentum dipole ``s``
produces a magnetic moment ``g s`` in units of the Bohr magneton.
"""
struct SpinInfo
atom :: Int # Index of atom in unit cell
S :: Float64 # Spin magnitude in units of ħ
g :: Mat3 # Spin g-tensor
function SpinInfo(atom::Int; S, g)
if !isinteger(2S)
error("Spin $S for atom $atom is not a multiple of 1/2")
end
g = typeof(g) <: Number ? Mat3(I*g) : Mat3(g)
new(atom, S, g)
end
end
# Propagates spin magnitudes and symmetry-transformed g-tensors to all
# symmetry-equivalent atoms. Throws an error if two symmetry-equivalent atoms
# are provided in `infos`, or if some atoms remain unspecified.
function propagate_site_info(cryst::Crystal, infos::Vector{SpinInfo})
# Verify that all g tensors are consistent with the the site symmetries
for info in infos
if !is_coupling_valid(cryst, Bond(info.atom, info.atom, (0,0,0)), info.g)
error("g-tensor $(info.g) is inconsistent with the site symmetry of atom $(info.atom).")
end
end
ref_atoms = [info.atom for info in infos]
atom_to_ref_atom = propagate_reference_atoms(cryst, ref_atoms)
return map(enumerate(atom_to_ref_atom)) do (a, a′)
info = infos[findfirst(==(a′), ref_atoms)]
S = info.S
g = transform_coupling_for_bonds(cryst, Bond(a,a,(0,0,0)), Bond(a′,a′,(0,0,0)), info.g)
SpinInfo(a; S, g)
end
end