Skip to content

Commit

Permalink
Detect supercell interpenetration in dimensionality
Browse files Browse the repository at this point in the history
  • Loading branch information
Liozou committed Jul 5, 2023
1 parent d520aea commit 708afbe
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 24 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "PeriodicGraphs"
uuid = "18c5b727-b240-4874-878a-f2e242435bab"
authors = ["Lionel Zoubritzky [email protected]"]
version = "0.9.6"
version = "0.10.0"

[deps]
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
Expand Down
2 changes: 1 addition & 1 deletion docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"
Graphs = "86223c79-3864-5bf0-83f7-82e725a168b6"
Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306"

[compat]
Documenter = "0.27"
Expand Down
37 changes: 30 additions & 7 deletions src/algorithms/dimensionality.jl
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ Given a list of integer vectors of dimension `N`, return a tuple `(mat, D)` wher
invertible matrix whose `D` first columns form a basis of this spanned space, which
does not depend on the exact input.
If `D ≠ N`, the remaining columns are set so that `mat` be invertible. Nothing
else is specified about these columns, and in particular you should not assume that
they are independent of the input.
If `D ≠ N`, the remaining columns are set so that `mat` be invertible. These additional
columns will only contain one coefficient equal to 1, and all others to 0. No other
assumption should be made about these columns; in particular, they may depend on the input.
!!! warning
If modifiable, the input list will be modified in-place during this process.
Expand Down Expand Up @@ -236,14 +236,37 @@ end
dimensionality(g::PeriodicGraph{N}) where N
Determine the actual dimension of each connected component of `g`.
Return a dictionary where each entry `n => [l1, l2, ...]` means that
`li` is a list of vertices that form a connected component of dimension `n`.
Return a dictionary where each entry `n => [(l1,m1), (l2,m2), ...]` means that
`li` is a list of vertices that form a connected component of dimension `n`, and that
component is present `mi` times per unit cell.
In other words, the connected component `li` has a periodicity that can only be expressed
in a unit cell `mi` times larger than the current one.
## Examples
```jldoctest
julia> dimensionality(PeriodicGraph("2 1 1 1 0 2 2 -1 1 3 3 1 0 3 3 0 1"))
Dict{Int64, Vector{Tuple{Vector{Int64}, Int64}}} with 2 entries:
2 => [([3], 1)]
1 => [([1], 1), ([2], 1)]
julia> dimensionality(PeriodicGraph("1 1 1 2"))
Dict{Int64, Vector{Tuple{Vector{Int64}, Int64}}} with 1 entry:
1 => [([1], 2)]
```
"""
function dimensionality(g::PeriodicGraph)
dim = _dimensionality(g)
ret = Dict{Int,Vector{Vector{Int}}}()
ret = Dict{Int,Vector{Tuple{Vector{Int},Int}}}()
@inbounds for (d, x) in dim
ret[d] = first.(x)
retd = Vector{Tuple{Vector{Int},Int}}(undef, length(x))
for (k, (l, vec)) in enumerate(x)
nfoldmat, d2 = normal_basis(vec)
@assert d2 == d
nfold = abs(det(nfoldmat))
retd[k] = (l, nfold)
end
ret[d] = retd
end
return ret
end
Expand Down
35 changes: 20 additions & 15 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -679,37 +679,42 @@ end
@test g2 == gref
end

function equivalent_dict(d1, d2)
function check_dimensionality(g, d2)
d1 = dimensionality(g)
keys(d1) == keys(d2) || return false
for k in keys(d1)
s1 = Set(Set(x) for x in d1[k])
s2 = Set(Set(x) for x in d2[k])
s1 = Set((Set(l), m) for (l,m) in d1[k])
s2 = Set((Set(l), m) for (l,m) in d2[k])
s1 == s2 || return false
end
return true
end

@testset "Dimensionality" begin
@test dimensionality(PeriodicGraph{0}(5)) == Dict(0 => [collect(1:5)])
@test dimensionality(PeriodicGraph{0}(5)) == Dict(0 => [(collect(1:5),1)])
g::PeriodicGraph3D = PeriodicGraph3D([PeriodicEdge3D(1, 3, (0, 0, 1)),
PeriodicEdge3D(2, 3, (0, 1, 0)),
PeriodicEdge3D(2, 3, (0, -1, 0)),
PeriodicEdge3D(2, 3, (0, 0, 0)),
PeriodicEdge3D(4, 4, (1, 1, 0))])
@test equivalent_dict(dimensionality(g), Dict(1 => connected_components(g)))
@test add_edge!(g, PeriodicEdge(3, 2, (0,0,0)))
@test equivalent_dict(dimensionality(g), Dict(1 => connected_components(g)))
@test check_dimensionality(g, Dict(1 => [(x,1) for x in connected_components(g)]))
@test add_edge!(g, PeriodicEdge(2, 3, (0,-1,0)))
@test check_dimensionality(g, Dict(1 => [(x,1) for x in connected_components(g)]))
@test add_edge!(g, PeriodicEdge(2, 2, (0,0,1)))
@test equivalent_dict(dimensionality(g), Dict(1 => [[4]], 2 => [[1,2,3]]))
@test check_dimensionality(g, Dict(1 => [([4],1)], 2 => [([1,2,3],1)]))
@test rem_edge!(g, PeriodicEdge(1, 3, (0,0,1)))
@test equivalent_dict(dimensionality(g), Dict(0 => [[1]], 1 => [[4]], 2 => [[2,3]]))
@test check_dimensionality(g, Dict(0 => [([1],1)], 1 => [([4],1)], 2 => [([2,3],1)]))
@test rem_edge!(g, 3, PeriodicVertex(2, (0,0,0)))
@test equivalent_dict(dimensionality(g), Dict(0 => [[1]], 1 => [[4]], 2 => [[2,3]]))
@test check_dimensionality(g, Dict(0 => [([1],1)], 1 => [([4],1)], 2 => [([2,3],2)]))
@test rem_edge!(g, PeriodicEdge(2, 3, (0,1,0)))
@test equivalent_dict(dimensionality(g), Dict(0 => [[1]], 1 => [[2,3],[4]]))
@test check_dimensionality(g, Dict(0 => [([1],1)], 1 => [([2,3],1),([4],1)]))
@test add_edge!(g, 2, PeriodicVertex3D(3, (1,0,-1)))
@test equivalent_dict(dimensionality(g), Dict(0 => [[1]], 1 => [[4]], 2 => [[2,3]]))
@test check_dimensionality(g, Dict(0 => [([1],1)], 1 => [([4],1)], 2 => [([2,3],1)]))
@test add_edge!(g, 2, PeriodicVertex(3, (2,0,-1)))
@test equivalent_dict(dimensionality(g), Dict(0 => [[1]], 1 => [[4]], 3 => [[2,3]]))
@test check_dimensionality(g, Dict(0 => [([1],1)], 1 => [([4],1)], 3 => [([2,3],1)]))

@test check_dimensionality(PeriodicGraph("2 1 1 2 0 1 1 0 1"), Dict(2 => [([1],2)]))
@test check_dimensionality(PeriodicGraph("3 1 1 2 0 0 1 1 0 2 0"), Dict(2 => [([1],4)]))
@test check_dimensionality(PeriodicGraph("3 1 1 0 0 1 1 2 -1 0 0 1 2 0 -1 0 1 2 1 0 0"), Dict(3 => [([1,2],2)]))
end

@testset "Dimension change" begin
Expand All @@ -719,7 +724,7 @@ end
3 4 -1 0 0
4 1 0 0 1
4 4 0 0 1")
@test equivalent_dict(dimensionality(g), Dict(1 => [[1,2,3,4]]))
@test check_dimensionality(g, Dict(1 => [(1:4,1)]))
gg = PeriodicGraph1D(g)
@test string(gg) == "1 1 2 0 1 4 -1 2 3 0 3 4 0 4 4 1"
@test PeriodicGraph2D(gg) == PeriodicGraph2D(g) ==
Expand Down

2 comments on commit 708afbe

@Liozou
Copy link
Owner Author

@Liozou Liozou commented on 708afbe Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/86895

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.10.0 -m "<description of version>" 708afbe85957a755ebc86a1509b273afbf98da85
git push origin v0.10.0

Please sign in to comment.