Skip to content

Commit

Permalink
supercell selectors
Browse files Browse the repository at this point in the history
wip, fixes

fixes

fixes

fixes
  • Loading branch information
pablosanjose committed Sep 22, 2020
1 parent 2587888 commit ba52e6d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 39 deletions.
75 changes: 39 additions & 36 deletions src/lattice.jl
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,8 @@ end
# supercell
#######################################################################
"""
supercell(lat::AbstractLattice{E,L}, v::NTuple{L,Integer}...; region = missing, seed = missing)
supercell(lat::AbstractLattice{E,L}, sc::SMatrix{L,L´,Int}; region = missing, seed = missing)
supercell(lat::AbstractLattice{E,L}, v::NTuple{L,Integer}...; seed = missing, kw...)
supercell(lat::AbstractLattice{E,L}, sc::SMatrix{L,L´,Int}; seed = missing, kw...)
Generates a `Superlattice` from an `L`-dimensional lattice `lat` with Bravais vectors
`br´= br * sc`, where `sc::SMatrix{L,L´,Int}` is the integer supercell matrix with the `L´`
Expand Down Expand Up @@ -613,49 +613,54 @@ Superlattice{2,2,Float64,2} : 2D lattice in 2D space, filling a 2D supercell
# See also:
`unitcell`
"""
supercell(v::Union{SMatrix,Tuple,SVector,Integer}...; kw...) = lat -> supercell(lat, v...; kw...)

supercell(lat::AbstractLattice{E,L}, v::Tuple{} = (); kw...) where {E,L} =
supercell(lat, SMatrix{L,0,Int}(); kw...)
supercell(lat::AbstractLattice{E,L}, factors::Vararg{<:Integer,L}; kw...) where {E,L} =
_supercell(lat, factors...)
supercell(lat::AbstractLattice{E,L}, factors::Vararg{<:Integer,L´}; kw...) where {E,L,L´} =
throw(ArgumentError("Provide either a single scaling factor or one for each of the $L lattice dimensions"))
supercell(lat::AbstractLattice{E,L}, factor::Integer; kw...) where {E,L} =
_supercell(lat, ntuple(_ -> factor, Val(L))...)
supercell(lat::AbstractLattice, vecs::NTuple{L,Integer}...; region = missing, seed = missing) where {L} =
_supercell(lat, toSMatrix(Int, vecs), region, seed)
supercell(lat::AbstractLattice, s::SMatrix; region = missing, seed = missing) =
_supercell(lat, s, region, seed)

function _supercell(lat::AbstractLattice{E,L}, factors::Vararg{Integer,L}) where {E,L}
scmatrix = SMatrix{L,L,Int}(Diagonal(SVector(factors)))
supercell(v...; kw...) = lat -> supercell(lat, v...; kw...)

function supercell(lat::Lattice{E,L}, v...; seed = missing, kw...) where {E,L}
scmatrix = sanitize_supercell(v, Val(L))
selector = siteselector(; region = ribbonfunc(bravais(lat), scmatrix), kw...)
return _supercell(lat, scmatrix, selector, seed)
end

supercell(lat::Lattice{E,L}, factors::Vararg{Integer,L}) where {E,L} =
_supercell_fastpath(lat, factors)
supercell(lat::Lattice{E,L}, factor::Integer) where {E,L} =
_supercell_fastpath(lat, filltuple(factor, Val(L)))

sanitize_supercell(::Tuple{}, ::Val{L}) where {L} = SMatrix{L,0,Int}()
sanitize_supercell(::Tuple{Tuple{}}, ::Val{L}) where {L} = SMatrix{L,0,Int}() # v... = ()
sanitize_supercell(v::NTuple{L´,NTuple{L,Int}}, ::Val{L}) where {L,L´} = toSMatrix(Int, v)
sanitize_supercell(s::SMatrix{L}, ::Val{L}) where {L} = toSMatrix(Int, s)
sanitize_supercell(v::Int, ::Val{L}) where {L} = sanitize_supercell(filltuple(v, Val(L)), Val(L))
sanitize_supercell(ss::NTuple{L,Number}, ::Val{L}) where {L} = SMatrix{L,L,Int}(Diagonal(SVector(ss)))
sanitize_supercell(v, ::Val{L}) where {L} =
throw(ArgumentError("Improper supercell specification $v for an $L lattice dimensions, see `supercell`"))

function _supercell_fastpath(lat, factors::NTuple{L,Integer}) where {L}
scmatrix = sanitize_supercell(factors, Val(L))
sites = 1:nsites(lat)
cells = CartesianIndices((i -> 0 : i - 1).(factors))
mask = missing
supercell = Supercell(scmatrix, sites, cells, mask)
return Superlattice(lat.bravais, lat.unitcell, supercell)
end

function _supercell(lat::AbstractLattice{E,L}, scmatrix::SMatrix{L,L´,Int}, region, seed) where {E,L,L´}
function _supercell(lat::AbstractLattice{E,L}, scmatrix::SMatrix{L,L´,Int}, selector, seed) where {E,L,L´}
brmatrix = bravais(lat)
regionfunc = region === missing ? ribbonfunc(brmatrix, scmatrix) : region
rsel = resolve(selector, lat)
in_supercell_func = is_perp_dir(scmatrix)
cells = supercell_cells(lat, regionfunc, in_supercell_func, seed)
cells = supercell_cells(lat, rsel, in_supercell_func, seed)
ns = nsites(lat)
mask = OffsetArray(BitArray(undef, ns, size(cells)...), 1:ns, cells.indices...)
mask = OffsetArray(falses(ns, size(cells)...), 1:ns, cells.indices...)
@inbounds for dn in cells
dntup = Tuple(dn)
dnvec = toSVector(Int, dntup)
dnvec = toSVector(dntup)
in_supercell = in_supercell_func(dnvec)
if !in_supercell
mask[:, dntup...] .= false
continue
end
r0 = brmatrix * dnvec
for (i, site) in enumerate(allsitepositions(lat))
r = site + r0
mask[i, dntup...] = in_supercell && regionfunc(r)
for s in sublats(rsel), i in siteindices(rsel, s, dnvec)
mask[i, dntup...] = in_supercell && (i, dnvec) in rsel
end
end
supercell = Supercell(scmatrix, 1:ns, cells, all(mask) ? missing : mask)
Expand All @@ -668,6 +673,7 @@ is_perp_dir(supercell) = let invs = pinvmultiple(supercell); dn -> iszero(new_dn
new_dn(oldndist, (pinvs, n)) = fld.(pinvs * oldndist, n)
new_dn(oldndist, ::Tuple{<:SMatrix{0,0},Int}) = SVector{0,Int}()

# This is a region comprising a unit cell in the non-periodic directions (L-L´)
function ribbonfunc(bravais::SMatrix{E,L,T}, supercell::SMatrix{L,L´}) where {E,L,T,L´}
L <=&& return r -> true
# real-space supercell axes + all space
Expand All @@ -684,21 +690,18 @@ function ribbonfunc(bravais::SMatrix{E,L,T}, supercell::SMatrix{L,L´}) where {E
return regionfunc
end

function supercell_cells(lat::Lattice{E,L}, regionfunc, in_supercell_func, seed) where {E,L}
br = bravais(lat)
seed´ = seed === missing ? zero(SVector{L,Int}) : seedcell(SVector{E}(seed), br)
function supercell_cells(lat::Lattice{E,L}, rsel, in_supercell_func, seed) where {E,L}
seed´ = seed === missing ? zero(SVector{L,Int}) : seedcell(SVector{E}(seed), bravais(lat))
iter = BoxIterator(seed´)
foundfirst = false
counter = 0
for dn in iter
found = false
counter += 1; counter == TOOMANYITERS &&
throw(ArgumentError("`region` seems unbounded (after $TOOMANYITERS iterations)"))
in_supercell = in_supercell_func(toSVector(Int, dn))
r0 = br * toSVector(Int, dn)
for site in allsitepositions(lat)
r = r0 + site
found = in_supercell && regionfunc(r)
in_supercell = in_supercell_func(dn)
for s in sublats(rsel), i in siteindices(rsel, s, dn)
found = in_supercell && (i, dn) in rsel
if found || !foundfirst
acceptcell!(iter, dn)
foundfirst = found
Expand Down
10 changes: 8 additions & 2 deletions src/model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -273,12 +273,16 @@ check_dn_dims(dns, lat::AbstractLattice{E,L}) where {E,L} =
return ((i, i), (dn0, dn0)) in rs
end

Base.in(((i, j), (dni, dnj))::Tuple, rs::ResolvedSelector{<:SiteSelector}) =
isonsite((i, j), (dni, dnj)) && isinindices(i, rs.selector.indices) &&
@inline Base.in(((i, j), (dni, dnj))::Tuple{Tuple,Tuple}, rs::ResolvedSelector{<:SiteSelector}) =
isonsite((i, j), (dni, dnj)) && (i, dni) in rs

Base.in((i, dni)::Tuple{Integer,SVector}, rs::ResolvedSelector{<:SiteSelector}) =
isinindices(i, rs.selector.indices) &&
isinregion(i, dni, rs.selector.region, rs.lattice) &&
isinsublats(sublat(rs.lattice, i), rs.selector.sublats)

Base.in((j, i)::Pair{<:Integer,<:Integer}, rs::ResolvedSelector{<:HopSelector}) = (i, j) in rs

function Base.in(is::Tuple{Integer,Integer}, rs::ResolvedSelector{<:HopSelector, LA}) where {E,L,LA<:AbstractLattice{E,L}}
dn0 = zero(SVector{L,Int})
return (is, (dn0, dn0)) in rs
Expand Down Expand Up @@ -392,6 +396,8 @@ siteindices(rs::ResolvedSelector{<:SiteSelector}) =
(i for i in siteindex_candidates(rs) if i in rs)
siteindices(rs::ResolvedSelector{<:SiteSelector}, sublat) =
(i for i in siteindex_candidates(rs, sublat) if i in rs)
siteindices(rs::ResolvedSelector{<:SiteSelector}, sublat, dn) =
(i for i in siteindex_candidates(rs, sublat) if (i, dn) in rs)

# Given a sublattice, which site indices should be checked by selector?
siteindex_candidates(rs) = eachindex(allsitepositions(rs.lattice))
Expand Down
4 changes: 3 additions & 1 deletion src/tools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ toSMatrix() = SMatrix{0,0,Float64}()
toSMatrix(s) = toSMatrix(tuple(s))
toSMatrix(ss::NTuple{M,NTuple{N,Number}}) where {N,M} = toSMatrix(SVector{N}.(ss))
toSMatrix(ss::NTuple{M,SVector{N}}) where {N,M} = hcat(ss...)
toSMatrix(::Type{T}, ss) where {T} = _toSMatrix(T, toSMatrix(ss))

toSMatrix(::Type{T}, ss) where {T<:Number} = _toSMatrix(T, toSMatrix(ss))
_toSMatrix(::Type{T}, s::SMatrix{N,M}) where {N,M,T} = convert(SMatrix{N,M,T}, s)
# Dynamic dispatch
toSMatrix(s::AbstractMatrix) = SMatrix{size(s,1), size(s,2)}(s)
toSMatrix(s::AbstractVector) = toSMatrix(Tuple(s))

toSVector(::Tuple{}) = SVector{0,Float64}()
toSVector(v::SVector) = v
Expand Down

0 comments on commit ba52e6d

Please sign in to comment.