Skip to content

Commit

Permalink
Renamings
Browse files Browse the repository at this point in the history
  • Loading branch information
kbarros committed Oct 10, 2024
1 parent 2dfa530 commit a3a26f7
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 51 deletions.
2 changes: 1 addition & 1 deletion src/Sunny.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ include("Symmetry/LatticeUtils.jl")
include("Symmetry/SymOp.jl")
include("Symmetry/MSymOp.jl")
include("Symmetry/SpacegroupData.jl")
include("Symmetry/SiteSymmetry.jl")
include("Symmetry/WyckoffData.jl")
include("Symmetry/Crystal.jl")
include("Symmetry/Bond.jl")
include("Symmetry/SymmetryAnalysis.jl")
Expand Down
67 changes: 33 additions & 34 deletions src/Symmetry/Crystal.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,19 @@ cryst = Crystal(latvecs, positions, 227; setting="1")
See also [`lattice_vectors`](@ref).
"""
struct Crystal
root :: Union{Nothing, Crystal} # Root crystal (invariant under `subcrystal` and reshaping)
latvecs :: Mat3 # Lattice vectors as columns
prim_latvecs :: Mat3 # Primitive lattice vectors
recipvecs :: Mat3 # Reciprocal lattice vectors (conventional)
positions :: Vector{Vec3} # Positions in fractional coords
types :: Vector{String} # Types
classes :: Vector{Int} # Class indices
sitesyms :: Union{Nothing, Vector{SiteSymmetry}} # Optional site symmetries
symops :: Vector{SymOp} # Symmetry operations
sg_label :: String # Description of space group
sg_number :: Union{Nothing, Int} # International spacegroup number (1..230)
sg_setting :: Union{Nothing, SymOp} # Operator P that maps to standard setting, xₛ = P x (ITA or Spglib)
symprec :: Float64 # Tolerance to imperfections in symmetry
root :: Union{Nothing, Crystal} # Root crystal (invariant under `subcrystal` and reshaping)
latvecs :: Mat3 # Lattice vectors as columns
prim_latvecs :: Mat3 # Primitive lattice vectors
recipvecs :: Mat3 # Reciprocal lattice vectors (conventional)
positions :: Vector{Vec3} # Positions in fractional coords
types :: Vector{String} # Types
classes :: Vector{Int} # Class indices
wyckoffs :: Union{Nothing, Vector{Wyckoff}} # Wyckoff data
symops :: Vector{SymOp} # Symmetry operations
sg_label :: String # Description of space group
sg_number :: Union{Nothing, Int} # International spacegroup number (1..230)
sg_setting :: Union{Nothing, SymOp} # Operator P that maps to standard setting, xₛ = P x (ITA or Spglib)
symprec :: Float64 # Tolerance to imperfections in symmetry
end

# Constructs a crystal from the complete list of atom positions `positions`,
Expand Down Expand Up @@ -140,8 +140,8 @@ function permute_sites!(cryst::Crystal, p)
cryst.positions .= cryst.positions[p]
cryst.classes .= cryst.classes[p]
cryst.types .= cryst.types[p]
if !isnothing(cryst.sitesyms)
cryst.sitesyms .= cryst.sitesyms[p]
if !isnothing(cryst.wyckoffs)
cryst.wyckoffs .= cryst.wyckoffs[p]
end
end

Expand Down Expand Up @@ -309,10 +309,9 @@ function crystal_from_inferred_symmetry(latvecs::Mat3, positions::Vector{Vec3},
# sum over all equivalent atoms in the primitive cell
sum(counts)
end
wyckoffs = Wyckoff.(multiplicities, d.wyckoffs, d.site_symmetry_symbols)

sitesyms = SiteSymmetry.(d.site_symmetry_symbols, multiplicities, d.wyckoffs)

ret = Crystal(nothing, latvecs, d.primitive_lattice, recipvecs, positions, types, classes, sitesyms, symops, sg_label, sg_number, sg_setting, symprec)
ret = Crystal(nothing, latvecs, d.primitive_lattice, recipvecs, positions, types, classes, wyckoffs, symops, sg_label, sg_number, sg_setting, symprec)
validate(ret)
return ret
end
Expand Down Expand Up @@ -441,7 +440,7 @@ function crystal_from_symops(latvecs::Mat3, positions::Vector{Vec3}, types::Vect
if isnothing(sg_number) || isnothing(sg_setting)
# This data is unavailable
prim_latvecs = latvecs
sitesyms = nothing
wyckoffs = nothing
else
# Primitive lattice vectors in units of standard lattice vectors
prim_shape = standard_primitive_basis[standard_centerings[sg_number]]
Expand All @@ -450,18 +449,18 @@ function crystal_from_symops(latvecs::Mat3, positions::Vector{Vec3}, types::Vect
# Primitive lattice vectors
prim_latvecs = std_latvecs * prim_shape

class_to_sitesym = map(unique(classes)) do c
class_to_wyckoff = map(unique(classes)) do c
rs = all_positions[findall(==(c), classes)]
rs_std = [transform(sg_setting, r) for r in rs]
sitesym = search_site_symmetry(sg_number, rs_std; symprec)
@assert sitesym.multiplicity length(rs) / det(sg_setting.R)
c => sitesym
wyckoff = find_wyckoff_for_orbit(sg_number, rs_std; symprec)
@assert wyckoff.multiplicity length(rs) / det(sg_setting.R)
c => wyckoff
end
sitesyms = getindex.(Ref(Dict(class_to_sitesym)), classes)
wyckoffs = getindex.(Ref(Dict(class_to_wyckoff)), classes)
end

recipvecs = 2π*Mat3(inv(latvecs)')
ret = Crystal(nothing, latvecs, prim_latvecs, recipvecs, all_positions, all_types, classes, sitesyms, symops, sg_label, sg_number, sg_setting, symprec)
ret = Crystal(nothing, latvecs, prim_latvecs, recipvecs, all_positions, all_types, classes, wyckoffs, symops, sg_label, sg_number, sg_setting, symprec)
sort_sites!(ret)
validate(ret)

Expand Down Expand Up @@ -557,7 +556,7 @@ function reshape_crystal(cryst::Crystal, new_shape::Mat3)
new_positions = Vec3[]
new_types = String[]
new_classes = Int[]
new_sitesyms = isnothing(cryst.sitesyms) ? nothing : SiteSymmetry[]
new_wyckoffs = isnothing(cryst.wyckoffs) ? nothing : Wyckoff[]

for i in 1:natoms(cryst)
for n1 in -nmax[1]:nmax[1], n2 in -nmax[2]:nmax[2], n3 in -nmax[3]:nmax[3]
Expand All @@ -572,7 +571,7 @@ function reshape_crystal(cryst::Crystal, new_shape::Mat3)
push!(new_positions, y)
push!(new_types, cryst.types[i])
push!(new_classes, cryst.classes[i])
!isnothing(cryst.sitesyms) && push!(new_sitesyms, cryst.sitesyms[i])
!isnothing(cryst.wyckoffs) && push!(new_wyckoffs, cryst.wyckoffs[i])
end
end
end
Expand All @@ -588,7 +587,7 @@ function reshape_crystal(cryst::Crystal, new_shape::Mat3)
new_symops = SymOp[]

return Crystal(root, new_latvecs, root.prim_latvecs, new_recipvecs, new_positions, new_types, new_classes,
new_sitesyms, new_symops, root.sg_label, root.sg_number, root.sg_setting, new_symprec)
new_wyckoffs, new_symops, root.sg_label, root.sg_number, root.sg_setting, new_symprec)
end


Expand Down Expand Up @@ -626,14 +625,14 @@ function subcrystal(cryst::Crystal, classes::Vararg{Int, N}) where N
new_positions = cryst.positions[atoms]
new_types = cryst.types[atoms]
new_classes = cryst.classes[atoms]
new_sitesyms = isnothing(cryst.sitesyms) ? nothing : cryst.sitesyms[atoms]
new_wyckoffs = isnothing(cryst.wyckoffs) ? nothing : cryst.wyckoffs[atoms]

if atoms != 1:maximum(atoms)
@info "Atoms have been renumbered in subcrystal."
end

ret = Crystal(root, cryst.latvecs, cryst.prim_latvecs, cryst.recipvecs, new_positions, new_types,
new_classes, new_sitesyms, cryst.symops, cryst.sg_label, cryst.sg_number, cryst.sg_setting, cryst.symprec)
new_classes, new_wyckoffs, cryst.symops, cryst.sg_label, cryst.sg_number, cryst.sg_setting, cryst.symprec)
return ret
end

Expand Down Expand Up @@ -664,9 +663,9 @@ function Base.show(io::IO, ::MIME"text/plain", cryst::Crystal)
if cryst.types[i] != ""
push!(descr, "Type '$(cryst.types[i])'")
end
if !isnothing(cryst.sitesyms)
(; symbol, multiplicity, wyckoff) = cryst.sitesyms[i]
push!(descr, "Wyckoff $multiplicity$wyckoff (site sym. '$symbol')")
if !isnothing(cryst.wyckoffs)
(; multiplicity, letter, sitesym) = cryst.wyckoffs[i]
push!(descr, "Wyckoff $multiplicity$letter (site sym. '$sitesym')")
end
if isempty(descr)
push!(descr, "Class $c")
Expand Down Expand Up @@ -786,7 +785,7 @@ function hyperkagome_crystal(; a=1.0)
x = 0.141
p = [1/8, x, x+1/4]
cryst = Crystal(latvecs, [p], 213)
@assert !isnothing(cryst.sitesyms)
@assert !isnothing(cryst.wyckoffs)
return cryst
end

Expand Down
18 changes: 9 additions & 9 deletions src/Symmetry/SiteSymmetry.jl → src/Symmetry/WyckoffData.jl
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
struct SiteSymmetry
symbol :: String
struct Wyckoff
multiplicity :: Int
wyckoff :: Char
letter :: Char
sitesym :: String
end

function search_site_symmetry(sg_number, rs; symprec)
function find_wyckoff_for_orbit(sg_number, rs; symprec)
for w in reverse(wyckoff_table[sg_number])
(mult, letter, symbol, pos) = w
(mult, letter, sitesym, pos) = w
wp = parse_wyckoff_position(pos)
if any(r -> belongs_to_wyckoff(r, wp; symprec), rs)
return SiteSymmetry(symbol, mult, letter)
if any(r -> position_belongs_to_wyckoff(r, wp; symprec), rs)
return Wyckoff(mult, letter, sitesym)
end
end
@assert false
end

# Parses F θ + c for θ = ["x", "y", "z"]. Returns (c, F).
# Parses "(F θ + c)" for θ = [x, y, z]. Returns (c, F).
function parse_wyckoff_position(str)
s = SymOp(str[begin+1:end-1])
return (; c=s.T, F=s.R)
Expand All @@ -25,7 +25,7 @@ end
# F θ + c = r be satisfied modulo 1 for some θ = [x, y, z]? Let F⁺ denote the
# pseudo-inverse of F and b = r - c. Multiply both sides by F F⁺, and use the
# property F F⁺ F = F, to find the constraint F F⁺ b = b mod 1.
function belongs_to_wyckoff(r, wp; symprec=1e-8)
function position_belongs_to_wyckoff(r, wp; symprec=1e-8)
(; c, F) = wp
b = c - r
return all_integer(F * pinv(F) * b - b; symprec)
Expand Down
14 changes: 7 additions & 7 deletions test/test_symmetry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
positions = [[0, 0, 0], [0.5, 0.5, 0], [0.5, 0, 0.5], [0, 0.5, 0.5]]
cryst′ = Crystal(latvecs, positions)

@test cryst.sitesyms[1] == cryst′.sitesyms[1]
@test cryst.wyckoffs[1] == cryst′.wyckoffs[1]

# Calculate interaction table
ref_bonds = reference_bonds(cryst, 2.)
Expand Down Expand Up @@ -136,7 +136,7 @@ end
# Trigonal spacegroup in standard hexagonal setting
latvecs = lattice_vectors(1, 1, 1.2, 90, 90, 120)
cryst = Crystal(latvecs, [[0, 0, 0]], 160)
@test cryst.sitesyms[1].symbol == "3m"
@test cryst.wyckoffs[1].sitesym == "3m"

# Same spacegroup in rhombohedral setting, which is the primitive cell
cryst2 = Crystal(cryst.prim_latvecs, [[0, 0, 0]], 160)
Expand All @@ -150,23 +150,23 @@ end
# Inference of Wyckoff symbols
lat_vecs = lattice_vectors(1, 1, 1.2, 90, 90, 120)
cryst = Crystal(lat_vecs, [[0.2, 0.2, 1/2]], 164)
@test cryst.sitesyms[1].multiplicity == 6
@test cryst.sitesyms[1].wyckoff == 'h'
@test cryst.sitesyms[1].symbol == ".2."
@test cryst.wyckoffs[1].multiplicity == 6
@test cryst.wyckoffs[1].letter == 'h'
@test cryst.wyckoffs[1].sitesym == ".2."

### Check settings for monoclinic spacegroup

# Standard setting for monoclinic spacegroup 5
latvecs = lattice_vectors(1, 1.1, 1.2, 90, 100, 90)
cryst = Crystal(latvecs, [[0, 0.2, 1/2]], "C 1 2 1")
@test cryst.sg_label == "'C 2 = C 1 2 1' (5)"
@test cryst.sitesyms[1].wyckoff == 'b'
@test cryst.wyckoffs[1].letter == 'b'

# Alternative setting
latvecs2 = reduce(hcat, eachcol(latvecs)[[3, 1, 2]])
cryst2 = Crystal(latvecs2, [[1/2, 0, 0.2]], "A 1 1 2")
@test cryst2.sg_label == "'C 2 = A 1 1 2' (5)"
@test cryst.sitesyms[1].wyckoff == 'b'
@test cryst.wyckoffs[1].letter == 'b'

# Verify `cryst` is already in standard setting
@test cryst.sg_setting.R I
Expand Down

0 comments on commit a3a26f7

Please sign in to comment.