Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NeighborRange default for hopping range #89

Merged
merged 4 commits into from
Sep 20, 2020
Merged

Conversation

pablosanjose
Copy link
Owner

This implements a new default behavior for the range keyword in hopping. This default used to be hard-coded to range = 1, which is rather arbitrary and can lead to surprises, as discussed in #85.

With this PR, the default for hopping is range = nrange(1), where nrange(n) creates a NeighborRange object that represents the distance between nᵗʰ-order nearest-neighbors of a lattice's sites. nrange is a new exported function.

The default behavior for something like hopping(1) then corresponds to nearest neighbors only (nrange(1))

julia> h = LatticePresets.honeycomb(a0 = 0.24) |> hamiltonian(hopping(1))
Hamiltonian{<:Lattice} : Hamiltonian on a 2D Lattice in 2D space
  Bloch harmonics  : 5 (SparseMatrixCSC, sparse)
  Harmonic size    : 2 × 2
  Orbitals         : ((:a,), (:a,))
  Element type     : scalar (Complex{Float64})
  Onsites          : 0
  Hoppings         : 6
  Coordination     : 3.0

We can also choose to specify hoppings up to second-nearest neighbors with

julia> h = LatticePresets.honeycomb(a0 = 0.24) |> hamiltonian(hopping(1, range = nrange(2)))
Hamiltonian{<:Lattice} : Hamiltonian on a 2D Lattice in 2D space
  Bloch harmonics  : 7 (SparseMatrixCSC, sparse)
  Harmonic size    : 2 × 2
  Orbitals         : ((:a,), (:a,))
  Element type     : scalar (Complex{Float64})
  Onsites          : 0
  Hoppings         : 18
  Coordination     : 9.0

Since #87 we can also specify (inclusive) range intervals. This ability extends to NeighborRanges now.

julia> h = LatticePresets.honeycomb() |> hamiltonian(hopping(1, range = (nrange(2), nrange(3))))
Hamiltonian{<:Lattice} : Hamiltonian on a 2D Lattice in 2D space
  Bloch harmonics  : 9 (SparseMatrixCSC, sparse)
  Harmonic size    : 2 × 2
  Orbitals         : ((:a,), (:a,))
  Element type     : scalar (Complex{Float64})
  Onsites          : 0
  Hoppings         : 18
  Coordination     : 9.0

julia> h = LatticePresets.honeycomb() |> hamiltonian(hopping(1, range = (nrange(3), nrange(3))))
Hamiltonian{<:Lattice} : Hamiltonian on a 2D Lattice in 2D space
  Bloch harmonics  : 5 (SparseMatrixCSC, sparse)
  Harmonic size    : 2 × 2
  Orbitals         : ((:a,), (:a,))
  Element type     : scalar (Complex{Float64})
  Onsites          : 0
  Hoppings         : 6
  Coordination     : 3.0

Apart from nrange(n::Int), nrange has a second method nrange(n::Int, lat::AbstractLattice) that computes said distance for a given lattice. So, for example

julia> lat = LatticePresets.honeycomb(a0 = 1); nrange(1, lat) ≈ 1/√3
true

julia> lat = LatticePresets.honeycomb(a0 = 2); nrange(1, lat) ≈ 2/√3
true

julia> lat = LatticePresets.honeycomb(a0 = 2); nrange(2, lat) ≈ 2
true

@codecov-commenter
Copy link

codecov-commenter commented Sep 18, 2020

Codecov Report

Merging #89 into master will decrease coverage by 0.12%.
The diff coverage is 61.33%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #89      +/-   ##
==========================================
- Coverage   63.06%   62.93%   -0.13%     
==========================================
  Files          16       16              
  Lines        2694     2763      +69     
==========================================
+ Hits         1699     1739      +40     
- Misses        995     1024      +29     
Impacted Files Coverage Δ
src/Quantica.jl 100.00% <ø> (ø)
src/tools.jl 62.66% <0.00%> (-2.81%) ⬇️
src/model.jl 74.02% <67.79%> (-1.87%) ⬇️
src/hamiltonian.jl 75.11% <100.00%> (+0.03%) ⬆️
src/lattice.jl 68.22% <100.00%> (+0.19%) ⬆️
src/iterators.jl 75.29% <0.00%> (+0.14%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2844154...cb6e303. Read the comment docs.

@pablosanjose
Copy link
Owner Author

This PR was born from discussions with @BacAmorim on Slack. Some more explanations of the rationale behind this PR are maybe in order.

Originally Bruno and I planned to have a special case whereby a missing dn and range would have a special behavior analogous to range = nrange(1). I tried that in #85, but the hopselector mechanism is used quite widely, so the special-case unfortunately interfered with hopselectors in parametric Hamiltonians and ElementModifiers (where we don't want to constraint the parametric modification of existing hoppings by default). After reflecting on the problem it became clear to me that giving a special meaning to the combinationdn == range == missing was confusing and a recipe for disaster down the road. What we really want is a sane default for hopping range that is never divergent (but not an arbitrary range = 1), while leaving the hopselector default (of more general use) totally unconstrained. The solution is first-nearest-neighbors.

The implementation to resolve what that range means for an arbitrary lattice is not trivial at all. Here we employ a brute force O(N^2) search strategy for small N, and a KDTree O(N log N) approach for larger N (using NearestNeighbors.jl). The threshold between the two strategies is chosen heuristically and is not thoroughly optimized yet.

As a bonus we have also the nrange(n > 1) option, which was considered in discussions with @BacAmorim.

@pablosanjose
Copy link
Owner Author

Merging because I need this for further work

@pablosanjose pablosanjose merged commit 976cc7d into master Sep 20, 2020
@pablosanjose pablosanjose deleted the range_default branch September 21, 2020 14:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants