Skip to content

Commit 8cfbd1f

Browse files
authored
add atol to isapprox comparisons of RVecs (#88)
- this is to prevent issues relating to comparison of zero-vectors (previously, zero vectors with e.g. ~1e-16 deviations from 0 would compare as different from genuine zero vectors)
1 parent 1beb801 commit 8cfbd1f

3 files changed

Lines changed: 39 additions & 17 deletions

File tree

src/SymmetricTightBinding.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ using RowEchelon: rref, rref! # for `poormans_sparsification`
1111

1212
# --- Constants -------------------------------------------------------------------------- #
1313

14+
const VEC_CMP_ATOL = 1e-11 # for `isapprox` comparison of RVecs / KVecs
1415
const NULLSPACE_ATOL_DEFAULT = 1e-5
1516
const SPARSIFICATION_ATOL_DEFAULT = 1e-10
1617
const PRUNE_ATOL_DEFAULT = SPARSIFICATION_ATOL_DEFAULT

src/tightbinding.jl

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ function maybe_add_hoppings!(
9797
ops::AbstractVector{SymOperation{D}},
9898
) where {D}
9999
δ_idx = findfirst(h_orbits) do h_orbit
100-
isapproxin(δ, orbit(h_orbit), nothing, false) # check if δ is in existing h_orbits
100+
# check if δ is in existing h_orbits
101+
isapproxin(δ, orbit(h_orbit), nothing, false; atol = VEC_CMP_ATOL)
101102
end
102103
if isnothing(δ_idx)
103104
# if it wasn't already in `h_orbits`, we add it and its symmetry-related partners
@@ -142,14 +143,17 @@ function _maybe_add_hoppings!(
142143
# 1. R´ is a lattice translation, i.e., it is integer
143144
# 2. R´ doesn't have any free parameters - TODO: try to implement it for WPs with free parameters
144145
# 3. δ′ = qᵦ′ + R′ - qₐ′
145-
all(Rᵢ′ -> abs(Rᵢ′ - round(Rᵢ′)) < 1e-10, constant(R′)) ||
146+
all(Rᵢ′ -> abs(Rᵢ′ - round(Rᵢ′)) < VEC_CMP_ATOL, constant(R′)) ||
146147
error("arrived at non-integer lattice translation R′: should be impossible")
147148
isspecial(R′) || error(
148149
"arrived at non-special (nonzero free parameters) lattice translation R′: should be impossible",
149150
)
150-
isapprox(δ′, qᵦ′ + R′ - qₐ′, nothing, false) || error("δ′ ≠ qᵦ′ + R′ - qₐ′")
151+
isapprox(δ′, qᵦ′ + R′ - qₐ′, nothing, false; atol = VEC_CMP_ATOL) ||
152+
error("δ′ ≠ qᵦ′ + R′ - qₐ′")
151153

152-
idx_in_orbit = findfirst(δ′′ -> isapprox(δ′, δ′′, nothing, false), orbit(δ_orbit))
154+
idx_in_orbit = findfirst(orbit(δ_orbit)) do δ′′
155+
isapprox(δ′, δ′′, nothing, false; atol = VEC_CMP_ATOL)
156+
end
153157
if isnothing(idx_in_orbit)
154158
# δ′ is not already included in `orbit(δ_orbit)`
155159
push!(orbit(δ_orbit), δ′)
@@ -158,12 +162,11 @@ function _maybe_add_hoppings!(
158162
# δ′ already in `orbit(δ_orbit)` but hopping term might not be:
159163
# evaluate `(qₐ′, qᵦ′, R′) ∉ δ_orbit.hoppings[idx_in_orbit]`, w/
160164
# approximate equality comparison
161-
bool =
162-
!any(δ_orbit.hoppings[idx_in_orbit]) do (qₐ′′, qᵦ′′, R′′)
165+
bool = !any(δ_orbit.hoppings[idx_in_orbit]) do (qₐ′′, qᵦ′′, R′′)
163166
(
164-
isapprox(qₐ′, qₐ′′, nothing, false) &&
165-
isapprox(qᵦ′, qᵦ′′, nothing, false) &&
166-
isapprox(R′, R′′, nothing, false)
167+
isapprox(qₐ′, qₐ′′, nothing, false; atol = VEC_CMP_ATOL) &&
168+
isapprox(qᵦ′, qᵦ′′, nothing, false; atol = VEC_CMP_ATOL) &&
169+
isapprox(R′, R′′, nothing, false; atol = VEC_CMP_ATOL)
167170
)
168171
end
169172
if bool
@@ -194,15 +197,14 @@ function add_reversed_orbits!(h_orbits::Vector{HoppingOrbit{D}}) where {D}
194197
δs = orbit(h_orbit) # δs in the current orbit
195198

196199
# check if the orbit is already "good" (i.e., all δs have a -δ counterpart)
197-
if all-> isapproxin(-δ, δs, nothing, false), δs)
200+
if all-> isapproxin(-δ, δs, nothing, false; atol = VEC_CMP_ATOL), δs)
198201
# all δs have a -δ counterpart in the orbit: orbit is good as-is
199202
continue
200203
end
201204

202-
merge_idx = findfirst(
203-
h_orbit′ -> isapproxin(-δs[1], orbit(h_orbit′), nothing, false),
204-
@view h_orbits[n+1:end]
205-
)
205+
merge_idx = findfirst(@view h_orbits[n+1:end]) do h_orbit′
206+
isapproxin(-δs[1], orbit(h_orbit′), nothing, false; atol = VEC_CMP_ATOL)
207+
end
206208
if !isnothing(merge_idx)
207209
# at least one δ has a -δ counterpart in another orbit - we need to merge them
208210
# NB: We assume that if one δ has a -δ counterpart in another orbit, then all
@@ -220,7 +222,7 @@ function add_reversed_orbits!(h_orbits::Vector{HoppingOrbit{D}}) where {D}
220222
end
221223
# we now know that at least some δ doesn't have a -δ counterpart: we assume that
222224
# this implies that none of the δs have a -δ counterpart, so we need to add them all
223-
@assert all-> !isapproxin(-δ, δs, nothing, false), δs)
225+
@assert all-> !isapproxin(-δ, δs, nothing, false; atol = VEC_CMP_ATOL), δs)
224226

225227
# first append the new δs into the orbit
226228
append!(δs, -δs)
@@ -362,7 +364,8 @@ function construct_M_matrix(
362364
offset0 = (r - 1) * E * Q
363365
for (x, hop) in enumerate(hops)
364366
q′, w′ = hop[1], hop[2]
365-
if isapprox(q′, q, nothing, false) && isapprox(w′, w, nothing, false)
367+
if (isapprox(q′, q, nothing, false; atol = VEC_CMP_ATOL) &&
368+
isapprox(w′, w, nothing, false; atol = VEC_CMP_ATOL))
366369
offset1 = (x - 1) * Q
367370
c = offset0 + offset1 + (j - 1) * Q1 + i
368371
Mm[r, c, α, β] = 1
@@ -733,7 +736,9 @@ function _permute_symmetry_related_hoppings_under_symmetry_operation(
733736
# we implement a simple trick: ([R⁻¹]ᵀ k)·r = R⁻¹ᵢⱼ kᵢ rⱼ = k·(R⁻¹ r)
734737
R⁻¹ = SymOperation(inv(rotation(op))) # rotation-only part of `op`
735738
δᵢ′ = compose(R⁻¹, δᵢ)
736-
j = findfirst(δ′′ -> isapprox(δᵢ′, δ′′, nothing, false), orbit(h_orbit))
739+
j = findfirst(orbit(h_orbit)) do δ′′
740+
isapprox(δᵢ′, δ′′, nothing, false; atol = VEC_CMP_ATOL)
741+
end
737742
isnothing(j) &&
738743
error(lazy"hopping element $δᵢ not closed under $op in $(orbit(h_orbit))")
739744
P[i, j] = 1

test/runtests.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,20 @@ end
5959
@test length(h_orbits[1].orbit) == 1 # on-site
6060
@test length(h_orbits[2].orbit) == 4 # hopping; combination of two orbits, merged by TR
6161
end
62+
end
63+
64+
@testset "Finnicky case in space group 153 (PR 88)" begin
65+
# issue related to a zero translation vector R being detected as different across
66+
# hopping terms, due to small numerical floating point differences; fixed in PR #87
67+
sgnum = 153
68+
brs = calc_bandreps(sgnum, Val(3))
69+
cbr = @composite brs[3]
70+
br = brs[3]
71+
h_orbits = obtain_symmetry_related_hoppings([[0,0,0]], br, br)
72+
for h_orbit in h_orbits
73+
# check we have consistent number (i.e., the same) of hoppings per orbit element
74+
hoppings = h_orbit.hoppings
75+
N = length(first(hoppings))
76+
@test all(h -> length(h) == N, hoppings)
77+
end
6278
end

0 commit comments

Comments
 (0)