Skip to content

Commit

Permalink
Merge pull request #60 from thchr/calc_bandreps
Browse files Browse the repository at this point in the history
include & export `calc_bandreps` (supersedes and closes #37)

- also test the associated functionality
  • Loading branch information
thchr authored Aug 26, 2024
2 parents ef69580 + 48ac166 commit 5161c35
Show file tree
Hide file tree
Showing 7 changed files with 489 additions and 65 deletions.
3 changes: 3 additions & 0 deletions src/Crystalline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ export subduction_count
include("bandrep.jl")
export bandreps, matrix, classification, nontrivial_factors, basisdim

include("calc_bandreps.jl")
export calc_bandreps

include("deprecations.jl")
export get_littlegroups, get_lgirreps, get_pgirreps, WyckPos, kvec, wyck, kstar

Expand Down
79 changes: 58 additions & 21 deletions build/setup_2d_band_representations.jl → src/calc_bandreps.jl
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
using LinearAlgebra
using Crystalline
using Crystalline: irdim, constant, free, AbstractIrrep, iscorep,
_mulliken, DEFAULT_ATOL
import Crystalline: mulliken, realify, group
using StaticArrays
using DocStringExtensions
using LinearAlgebra: dot, \

# The implementation here follows Cano et al., Phys. Rev. B 97, 035139 (2018)
# (https://doi.org/10.1103/PhysRevB.97.035139), specifically, Sections II.C-D
Expand All @@ -19,14 +13,14 @@ of `f`. Effectively flattens a `Dict` of `Vector`s to a single `Vector`.
Note that application of `f` to vector-elements of `d` must return a stable type `T`.
"""
function reduce_dict_of_vectors(f::F, d::Dict{<:Any, <:Vector}) where F
function reduce_dict_of_vectors(f::F, d::Dict{<:Any, <:AbstractVector}) where F
# get element type of application of `f` to elements of vectors in `d`; assumed fixed
eltype = typeof(f(first(first(values(d)))))
# get total number of elements across vectors in `d`
N = sum(((_, v),) -> length(v), d)
# preallocate output vector
w = Vector{eltype}(undef, N)
start = 1
w = Vector{eltype}(undef, N)
start = 1
for v in values(d)
stop = start + length(v) - 1
@inbounds for (i, j) in enumerate(start:stop)
Expand All @@ -48,8 +42,9 @@ in a primitive basis (as determined by the centering type `cntr`). Returns the u
If `conv_or_prim = true` (default), the Wyckoff positions are returned in the original,
conventional basis; if `conv_or_prim = false`, they are returned in a primitive basis.
"""
function reduce_orbits!(orbits::Vector{WyckoffPosition{D}}, cntr::Char,
conv_or_prim::Bool=true) where D
function reduce_orbits!(
orbits::AbstractVector{WyckoffPosition{D}}, cntr::Char, conv_or_prim::Bool=true
) where D

orbits′ = primitivize.(orbits, cntr)
i = 2 # start from second element
Expand Down Expand Up @@ -97,7 +92,7 @@ end
# Bandrep related functions: induction/subduction

"""
induced_band_representation(siteir, h, kv)
induce_bandrep(siteir::SiteIrrep, h::SymOperation, kv::KVec)
Return the band representation induced by the provided `SiteIrrep` evaluated at `kv` and for
a `SymOperation` `h`.
Expand Down Expand Up @@ -128,29 +123,40 @@ function induce_bandrep(siteir::SiteIrrep{D}, h::SymOperation{D}, kv::KVec{D}) w
site_symmetry_index = findfirst((gα′⁻¹ggα′), siteg)
if site_symmetry_index !== nothing
χᴳₖ += cis(2π*dot(kv′, tα′α′)) * χs[site_symmetry_index]
# TODO: The sign in this `cis(...)` above is different from in Elcoro's. Why?
# NB: The sign in this `cis(...)` above is different from in Elcoro's.
# I think this is consistent with our overall sign convention (see #12),
# however, and flipping the sign causes problems for the calculation of some
# subductions to `LGIrrep`s, which would be consistent with this. I.e.,
# I'm fairly certain this is consistent and correct given our phase
# conventions for `LGIrrep`s.
end
end
return χᴳₖ
end

function subduce_onto_lgirreps(siteir::SiteIrrep{D}, lgirs::Vector{LGIrrep{D}}) where D
function subduce_onto_lgirreps(
siteir::SiteIrrep{D}, lgirs::AbstractVector{LGIrrep{D}}
) where D
lg = group(first(lgirs))
kv = position(lg)

# characters of induced site representation and little group irreps
site_χs = induce_bandrep.(Ref(siteir), lg, Ref(kv))
lgirs_χm = matrix(characters(lgirs))

# little group irrep multiplicities, after subduction
m = lgirs_χm\site_χs
m′ = round.(Int, real.(m)) # truncate to integers
isapprox(m, m′, atol=DEFAULT_ATOL) || error(DomainError(m, "failed to convert to integers"))
return m′
end

function calc_bandrep(siteir::SiteIrrep{D}, lgirsd::Dict{String, Vector{LGIrrep{D}}};
irlabs::Vector{String} = reduce_dict_of_vectors(label, lgirsd),
irdims::Vector{Int} = reduce_dict_of_vectors(irdim, lgirsd)) where D
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)
) where D

irvec = Int[]
for (_, lgirs) in lgirsd
Expand All @@ -169,9 +175,40 @@ function calc_bandrep(siteir::SiteIrrep{D}, lgirsd::Dict{String, Vector{LGIrrep{
end

# ---------------------------------------------------------------------------------------- #
# TODO: Doc-string
function calc_bandreps(sgnum::Integer, Dᵛ::Val{D}=Val(2);
allpaths::Bool=false, timereversal::Bool=true) where D
"""
calc_bandreps(sgnum::Integer, Dᵛ::Val{D}=Val(3);
timereversal::Bool=true,
allpaths::Bool=false)
Compute the band representations of space group `sgnum` in dimension `D`, returning a
`BandRepSet`.
## Keyword arguments
- `timereversal` (default, `true`): whether the irreps used to induce the band
representations are assumed to be time-reversal invariant (i.e., are coreps, see
[`realify`](@ref)).
- `allpaths` (default, `false`): whether the band representations are projected to all
distinct **k**-points returned by `lgirreps` (`allpaths = false`), including high-symmetry
**k**-lines and -plane, or only to the maximal **k**-points (`allpaths = true`), i.e.,
just to high-symmetry points.
## Notes
All band representations associated with maximal Wyckoff positions are returned,
irregardless of whether they are elementary (i.e., no regard is made to whether the band
representation is "composite"). As such, the returned band representations generally are
a superset of the set of elementary band representations (and so contain all elementary
band representations).
## Implementation
The implementation is based on Cano, Bradlyn, Wang, Elcoro, et al., [Phys. Rev. B **97**,
035139 (2018)](https://doi.org/10.1103/PhysRevB.97.035139), Sections II.C-D.
"""
function calc_bandreps(
sgnum::Integer,
Dᵛ::Val{D} = Val(3);
timereversal::Bool = true,
allpaths::Bool = false
) where D

# get all the little group irreps that we want to subduce onto
lgirsd = lgirreps(sgnum, Val(D))
Expand Down
Loading

0 comments on commit 5161c35

Please sign in to comment.