Skip to content

Commit

Permalink
steps toward a new BandRep struct (called NewBandRep for now)
Browse files Browse the repository at this point in the history
- this also removes some fields from the original `BandRep`, namely the `decomposable` and `allpaths` fields; they are not used anywhere and cannot be easily recomputed in `calc_bandrep`.
  • Loading branch information
thchr committed Sep 13, 2024
1 parent 565003e commit 599b6e3
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 158 deletions.
6 changes: 0 additions & 6 deletions build/write_bandreps_from_bandrepset.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,6 @@ function bandrep2csv(io::IO, BRS::BandRepSet)
end
println(io)

print(io, "Decomposable")
for br in BRS
print(io, "|", br.decomposable)
end
println(io)

irlabs = BRS.irlabs
for (idx, (klab,kv)) in enumerate(zip(BRS.klabs, BRS.kvs))
print(io, klab, ":")
Expand Down
5 changes: 4 additions & 1 deletion src/Crystalline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ export SymOperation, # types
irreplabels, klabels, # ::BandRep & ::BandRepSet
isspinful

include("types_symmetry_vectors.jl")
export SymmetryVector, NewBandRep, Collection

include("notation.jl")
export schoenflies, iuc, centering, seitz, mulliken

Expand Down Expand Up @@ -103,7 +106,7 @@ include("assembly/generators/spacegroup.jl")
include("assembly/generators/subperiodicgroup.jl")
export generate, generators

include("show.jl") # custom printing for structs defined in src/types.jl
include("show.jl") # printing of structs from src/[types.jl, types_symmetry_vectors.jl]

include("orders.jl")

Expand Down
21 changes: 13 additions & 8 deletions src/bandrep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ function array2struct(M::Matrix{String}, sgnum::Integer, allpaths::Bool=false, s

temp .= split_paren.(@view M[2,2:end]) # same size, so reuse array
label, dim = getindex.(temp, 1), parse.(Int, getindex.(temp, 2)) # label of bandrep

decomposable = parse.(Bool, vec(@view M[3,2:end])) # whether bandrep can be further decomposed

brtags = collect(eachcol(@view M[4:end, 2:end])) # set of irreps that jointly make up the bandrep

# whether M contains info on decomposability; we don't use this anymore, but need to
# know to parse the rest of the contents correctly (we used to always include this info
# but might not in the future; so protect against this)
has_decomposable_info = M[3,1] == "Decomposable"
# decomposable = parse.(Bool, vec(@view M[3,2:end])) # whether BR can be BR-decomposed

# set of irreps that jointly make up the bandrep
brtags = collect(eachcol(@view M[3+has_decomposable_info:end, 2:end]))
for br in brtags
br .= replace.(br, Ref(r"\([1-9]\)"=>"")) # get rid of irrep dimension info
end
Expand All @@ -34,15 +39,15 @@ function array2struct(M::Matrix{String}, sgnum::Integer, allpaths::Bool=false, s
else # single-valued irreps only (spinless systems)
delidxs = findall(map(isspinful, brtags))
end
for vars in (brtags, wyckpos, sitesym, label, dim, decomposable)
for vars in (brtags, wyckpos, sitesym, label, dim)
deleteat!(vars, delidxs)
end
irlabs, irvecs = get_irrepvecs(brtags)

BRs = BandRep.(wyckpos, sitesym, label, dim, decomposable, map(isspinful, brtags),
irvecs, Ref(irlabs))
BRs = BandRep.(wyckpos, sitesym, label, dim, map(isspinful, brtags), irvecs,
Ref(irlabs))

return BandRepSet(sgnum, BRs, kvs, klabs, irlabs, allpaths, spinful, timereversal)
return BandRepSet(sgnum, BRs, kvs, klabs, irlabs, spinful, timereversal)
end


Expand Down
64 changes: 31 additions & 33 deletions src/calc_bandreps.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ Return the band representation induced by the provided `SiteIrrep` evaluated at
a `SymOperation` `h`.
"""
function induce_bandrep(siteir::SiteIrrep{D}, h::SymOperation{D}, kv::KVec{D}) where D

siteg = group(siteir)
wp = position(siteg)
kv′ = constant(h*kv) # <-- TODO: Why only constant part?
Expand Down Expand Up @@ -151,27 +150,35 @@ function subduce_onto_lgirreps(
return m′
end

# ---------------------------------------------------------------------------------------- #

function calc_bandrep(
siteir::SiteIrrep{D},
lgirsd::Dict{String, <:AbstractVector{LGIrrep{D}}};
irlabs::Vector{String} = reduce_dict_of_vectors(label, lgirsd),
irdims::Vector{Int} = reduce_dict_of_vectors(irdim, lgirsd)
siteir :: SiteIrrep{D},
lgirsv :: AbstractVector{<:AbstractVector{LGIrrep{D}}},
timereversal :: Bool
) where D

irvec = Int[]
for (_, lgirs) in lgirsd
kv_array = subduce_onto_lgirreps(siteir, lgirs)
append!(irvec, Int.(kv_array))
end
multsv = [subduce_onto_lgirreps(siteir, lgirs) for lgirs in lgirsv]

irdims_Γmask = [irlab[1]=='Γ' for irlab in irlabs] .* irdims # masked w/ Γ-irreps only
brdim = dot(irvec, irdims_Γmask)
wycklab = label(position(group(siteir)))
spinful = false # NB: default; Crystalline currently doesn't have spinful irreps
decomposable = false # NB: placeholder, because we don't know the true answer presently

return BandRep(wycklab, siteir.pglabel, mulliken(siteir)*"↑G", brdim, decomposable,
spinful, irvec, irlabs)
occupation = sum(zip(first(multsv), first(lgirsv)); init=0) do (m, lgir)
m * irdim(lgir)
end
n = SymmetryVector(lgirsv, multsv, occupation)

spinful = false # NB: default; Crystalline currently doesn't have spinful irreps

return NewBandRep(siteir, n, timereversal, spinful)
end
function calc_bandrep(
siteir :: SiteIrrep{D};
timereversal :: Bool=true,
allpaths :: Bool=false
) where D
lgirsd = lgirreps(num(siteir), Val(D))
allpaths || filter!(((_, lgirs),) -> isspecial(first(lgirs)), lgirsd)
timereversal && realify!(lgirsd)
lgirsv = [lgirs for lgirs in values(lgirsd)]
return calc_bandrep(siteir, lgirsv, timereversal)
end

# ---------------------------------------------------------------------------------------- #
Expand Down Expand Up @@ -212,29 +219,20 @@ function calc_bandreps(

# get all the little group irreps that we want to subduce onto
lgirsd = lgirreps(sgnum, Val(D))
allpaths || filter!(((_, lgirs),) -> isspecial(first(lgirs)), lgirsd)
allpaths || filter!(((_, lgirs),) -> isspecial(first(lgirs)), lgirsd)
timereversal && realify!(lgirsd)

irlabs = reduce_dict_of_vectors(label, lgirsd)
irdims = reduce_dict_of_vectors(irdim, lgirsd)
lgirsv = [lgirs for lgirs in values(lgirsd)]

# get the bandreps induced by every maximal site symmetry irrep
wps = wyckoffs(sgnum, Dᵛ)
sg = spacegroup(sgnum, Dᵛ)
sitegs = findmaximal(sitegroup.(Ref(sg), wps))
brs = BandRep[]
brs = NewBandRep{D}[]
for siteg in sitegs
siteirs = siteirreps(siteg)
siteirs = siteirreps(siteg; mulliken=true)
timereversal && (siteirs = realify(siteirs))
append!(brs, calc_bandrep.(siteirs, Ref(lgirsd); irlabs=irlabs, irdims=irdims))
append!(brs, calc_bandrep.(siteirs, Ref(lgirsv), Ref(timereversal)))
end

# TODO: There's potentially some kind of bad implicit dependence/overreliance on fixed
# on iteration order of `Dict`s here and related methods; probably OK, but unwise
klabs = collect(keys(lgirsd))
kvs = position.(first.(values(lgirsd)))
spinful = false # NB: default; Crystalline currently doesn't have spinful irreps
decomposable = false # NB: placeholder, because we don't know the true answer presently

return BandRepSet(sgnum, brs, kvs, klabs, irlabs, allpaths, spinful, timereversal)
return Collection(brs)
end
133 changes: 33 additions & 100 deletions src/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -527,109 +527,42 @@ function show(io::IO, ::MIME"text/plain", BRS::BandRepSet)
)

# print k-vec labels
print(io, " KVecs (", hasnonmax(BRS) ? "incl. non-maximal" : "maximal only", "): ")
print(io, " KVecs: ")
join(io, klabels(BRS), ", ")

# EARLIER MANUAL LAYOUTS: DISCONTINUED

#=
# === EBRS-by-column layout ===
# prep-work to figure out how many bandreps we can write to the io
cols_avail = displaysize(io)[2] # available cols in io (cannot write to all of it; subtract 2)
indent = 3
μ_maxdigs = maximum(ndigits∘dim, BRS) # implicitly assuming this to be ≤2...
maxcols_irr = maximum(length, irreplabels(BRS))
cols_brlabs = length.(label.(BRS))
cumcols_brlabs = cumsum(cols_brlabs .+ 1)
cols_requi = cumcols_brlabs .+ (indent + maxcols_irr + 2)
@show cols_requi
room_for = findlast(≤(cols_avail), cols_requi)
abbreviate = room_for < length(BRS) ? true : false
rowend = abbreviate ? '…' : '║'
# print EBR header
print(io, ' '^(indent+maxcols_irr+1), '║')
for idxᵇʳ in 1:room_for
br = BRS[idxᵇʳ]
print(io, ' ', chop(label(br), tail=2),' ', idxᵇʳ ≠ room_for ? '│' : rowend)
end
println(io)
end

# print irrep content, line by line
for idxⁱʳʳ in 1:Nⁱʳʳ
irlab = irreplabels(BRS)[idxⁱʳʳ]
print(io, ' '^indent, irlab, ' '^(maxcols_irr + 1 - length(irlab)), '║')
for idxᵇʳ in 1:room_for
x = BRS[idxᵇʳ][idxⁱʳʳ]
addspace = div(cols_brlabs[idxᵇʳ], 2)
print(io, ' '^addspace)
iszero(x) ? print(io, '·') : print(io, x)
print(io, ' '^(cols_brlabs[idxᵇʳ] - addspace-1))
print(io, idxᵇʳ ≠ room_for ? '│' : rowend)
end
println(io)
end
# ---------------------------------------------------------------------------------------- #
# SymmetryVector

# print band filling
print(io, ' '^indent, 'μ', ' '^maxcols_irr, '║')
for idxᵇʳ in 1:room_for
μ = dim(BRS[idxᵇʳ])
addspace = div(cols_brlabs[idxᵇʳ], 2)+1
print(io, ' '^(addspace-ndigits(μ)), μ)
print(io, ' '^(cols_brlabs[idxᵇʳ] - addspace))
print(io, idxᵇʳ ≠ room_for ? '│' : rowend)
end
=#

#=
# === EBRs-by-rows layout ===
μ_maxdigs = maximum(ndigits∘dim, BRS)
cols_brlab = maximum(x->length(label(x)), BRS)+1
cols_irstart = cols_brlab+4
cols_avail = displaysize(io)[2]-2 # available cols in io (cannot write to all of it; subtract 2)
cols_requi = sum(x->length(x)+3, irreplabels(BRS))+cols_irstart+μ_maxdigs+3 # required cols for irrep labels & band reps
if cols_requi > cols_avail
cols_toomany = ceil(Int, (cols_requi-cols_avail)/2) + 2 # +2 is to make room for ' … ' extender
cols_midpoint = div(cols_requi-cols_irstart,2)+cols_irstart
cols_skipmin = cols_midpoint - cols_toomany
cols_skipmax = cols_midpoint + cols_toomany
cols_eachstart = [0; cumsum(length.(irreplabels(BRS)).+3)].+cols_irstart
iridx_skiprange = [idx for (idx, col_pos) in enumerate(cols_eachstart) if cols_skipmin ≤ col_pos ≤ cols_skipmax]
abbreviate = true
else
abbreviate = false
function Base.show(io :: IO, ::MIME"text/plain", n :: SymmetryVector)
print(io, length(n)-1, "-irrep ", typeof(n), ":\n ")
show(io, n)
end
function Base.show(io :: IO, n :: SymmetryVector)
print(io, "[")
for (i, (mults_k, lgirs_k)) in enumerate(zip(n.multsv, n.lgirsv))
printstyled(io,
Crystalline.symvec2string(mults_k, label.(lgirs_k); braces=false);
color=iseven(i) ? :normal : :light_blue)
i length(n.multsv) && print(io, ", ")
end
print(io, "]")
printstyled(io, " (", n.occupation, " band", n.occupation 1 ? "s" : "", ")";
color=:light_black)
end

print(io, " "^(cols_irstart-1),'║'); # align with spaces
for (iridx,lab) in enumerate(irreplabels(BRS)) # irrep labels
if abbreviate && iridx ∈ iridx_skiprange
if iridx == first(iridx_skiprange)
print(io, "\b … ")
end
else
print(io, ' ', lab, " │")
end
end
println(io, ' '^μ_maxdigs, "μ", " ║") # band-filling column header
# print each bandrep
for (bridx,BR) in enumerate(BRS)
μ = dim(BR)
print(io, " ", label(BR), # bandrep label
" "^(cols_brlab-length(label(BR))), '║')
for (iridx,x) in enumerate(BR) # iterate over vector representation of band rep
if abbreviate && iridx ∈ iridx_skiprange
if iridx == first(iridx_skiprange)
print(io, mod(bridx,4) == 0 ? "\b … " : "\b ")
end
else
print(io, " ")
!iszero(x) ? print(io, x) : print(io, '·')
print(io, " "^(length(irreplabels(BRS)[iridx])-1), '│') # assumes we will never have ndigit(x) != 1
end
end
print(io, ' '^(1+μ_maxdigs-ndigits(μ)), μ, " ║") # band-filling
if bridx != length(BRS); println(io); end
end
=#
# ---------------------------------------------------------------------------------------- #
# NewBandRep

function Base.show(io :: IO, ::MIME"text/plain", br :: NewBandRep)
print(io, length(br.n)-1, "-irrep ", typeof(br), ":\n ")
print(io, "(", )
printstyled(io, label(position(br.siteir)); bold=true)
print(io, "|")
printstyled(io, label(br.siteir); bold=true)
print(io, "): ")
show(io, br.n)
end
function Base.show(io :: IO, br :: NewBandRep)
print(io, "(", label(position(br.siteir)), "|", label(br.siteir), ")")
end
10 changes: 2 additions & 8 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -906,11 +906,10 @@ end
$(TYPEDEF)$(TYPEDFIELDS)
"""
struct BandRep <: AbstractVector{Int}
wyckpos::String # Wyckoff position that induces the BR (TODO: type as `::WyckoffPosition` instead of `::String`)
wyckpos::String # Wyckoff position that induces the BR
sitesym::String # Site-symmetry point group of Wyckoff pos (IUC notation)
label::String # Symbol ρ↑G, with ρ denoting the irrep of the site-symmetry group
dim::Int # Dimension (i.e. # of bands) in band rep
decomposable::Bool # Whether a given bandrep can be decomposed further
spinful::Bool # Whether a given bandrep involves spinful irreps ("\bar"'ed irreps)
irvec::Vector{Int} # Vector that references irlabs of a parent BandRepSet; nonzero
# entries correspond to an element in the band representation
Expand All @@ -925,11 +924,8 @@ irreplabels(BR::BandRep) = BR.irlabs
dim(BR::BandRep) --> Int
Return the number of bands included in the provided `BandRep`.
If the bands are "nondetachable" (i.e. if `BR.decomposable = false`), this is equal to a
band connectivity μ.
"""
dim(BR::BandRep) = BR.dim
dim(BR::BandRep) = BR.dim # TODO: Deprecate to `occupation` instead

# define the AbstractArray interface for BandRep
size(BR::BandRep) = (size(BR.irvec)[1] + 1,) # number of irreps sampled by BandRep + 1 (filling)
Expand All @@ -956,13 +952,11 @@ struct BandRepSet <: AbstractVector{BandRep}
kvs::Vector{<:KVec} # Vector of 𝐤-points # TODO: Make parametric
klabs::Vector{String} # Vector of associated 𝐤-labels (in CDML notation)
irlabs::Vector{String} # Vector of (sorted) CDML irrep labels at _all_ 𝐤-points
allpaths::Bool # Whether all paths (true) or only maximal 𝐤-points (false) are included
spinful::Bool # Whether the band rep set includes (true) or excludes (false) spinful irreps
timereversal::Bool # Whether the band rep set assumes time-reversal symmetry (true) or not (false)
end
num(BRS::BandRepSet) = BRS.sgnum
klabels(BRS::BandRepSet) = BRS.klabs
hasnonmax(BRS::BandRepSet) = BRS.allpaths
irreplabels(BRS::BandRepSet) = BRS.irlabs
isspinful(BRS::BandRepSet) = BRS.spinful
reps(BRS::BandRepSet) = BRS.bandreps
Expand Down
Loading

0 comments on commit 599b6e3

Please sign in to comment.