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

hamiltonian ignores some hopping terms #167

Closed
BacAmorim opened this issue Jun 2, 2021 · 9 comments
Closed

hamiltonian ignores some hopping terms #167

BacAmorim opened this issue Jun 2, 2021 · 9 comments

Comments

@BacAmorim
Copy link

I am trying to define the nearest neighbour TB model for graphene, without using any of the presets.

I define a lattice and a model as:

using Quantica

lat = lattice(
    sublat((0.0, 0.0), name = :A), 
    sublat((0.0, 1/sqrt(3)), name = :B);
    bravais = (
        (1/2, sqrt(3)/2),
        (-1/2, sqrt(2)/2)
    )
)

# I know there are better ways to build this
model = 
onsite(1.0; sublats = :A) + 
onsite(2.0; sublats = :B) +
hopping(3.0; sublats = (:B => :A, ), dn = (0, 0)) + 
hopping(4.0; sublats = (:B => :A, ), dn = (1, 0)) + 
hopping(5.0; sublats = (:B => :A, ), dn = (0, 1)) + 
hopping(6.0; sublats = (:A => :B, ), dn = (0, 0)) + 
hopping(7.0; sublats = (:A => :B, ), dn = (-1, 0)) + 
hopping(8.0; sublats = (:A => :B, ), dn = (0, -1))
# the value of the hoppings make no sense.

graphene = hamiltonian(lat, model; 
    orbitals = ((:pz, ), (:pz, ))
)

I get this:

Hamiltonian{<:Lattice} : Hamiltonian on a 2D Lattice in 2D space
  Bloch harmonics  : 3 (SparseMatrixCSC, sparse)
  Harmonic size    : 2 × 2
  Orbitals         : ((:pz,), (:pz,))
  Element type     : scalar (ComplexF64)
  Onsites          : 2
  Hoppings         : 2
  Coordination     : 1.0

There are 3 harmonics (I was expecting 5). When I inspect the harmonics, I get

> graphene.harmonics[1]
Quantica.HamiltonianHarmonic{2, ComplexF64, SparseMatrixCSC{ComplexF64, Int64}}([0, 0], 
 1.0+0.0im      ⋅    
     ⋅      2.0+0.0im)
> graphene.harmonics[2]
Quantica.HamiltonianHarmonic{2, ComplexF64, SparseMatrixCSC{ComplexF64, Int64}}([0, 1], 
     ⋅      5.0+0.0im
     ⋅          ⋅    )
> graphene.harmonics[3]
Quantica.HamiltonianHarmonic{2, ComplexF64, SparseMatrixCSC{ComplexF64, Int64}}([0, -1], 
     ⋅          ⋅    
 8.0+0.0im      ⋅    )

The hoppings along the directions dn = (1, 0) and dn = (-1, 0) were not included.
Why is that?

@pablosanjose
Copy link
Owner

The reason is that your lat has a typo. It should read

lat = lattice(
    sublat((0.0, 0.0), name = :A), 
    sublat((0.0, 1/sqrt(3)), name = :B);
    bravais = (
        (1/2, sqrt(3)/2),
        (-1/2, sqrt(3)/2)
    )
)

And the explanation: when you don't specify a range in hopping it defaults to nearest-neighbor hopping range, nrange(1). In your lattice, the nearest neighbor hopping was less than 1/√3, so that two of the hoppings were not applied. Note that you can adjust this behavior by specifying a different range.

I trust you know that the above example is unnecessarily verbose, and can be written much more succintly, yes?

I'm glad you're back to playing with Quantica, by the way!

@BacAmorim
Copy link
Author

Thanks for the clarification!
One question then: if range is not defined and the keyword dn is provided, shouldn't range just be ignored? It seems to me that dn should take precedence over range.

I trust you know that the above example is unnecessarily verbose, and can be written much more succintly, yes?

Yes, I am aware of that. I was just trying to understand how one could define Hamiltonians in a less "automagical" way.

@pablosanjose
Copy link
Owner

if range is not defined and the keyword dn is provided, shouldn't range just be ignored? It seems to me that dn should take precedence over range

This is indeed one possibility that I considered, but I'm not sure it is what you want as default behavior in general. Imagine your cell has many orbitals. Do you want the default hopping(1, dn = ...) to connect any site in cell zero to any site in cell dn? Or would you prefer the dn to act as an additional restriction to what you get with hopping(1), which is nearest neighbor by default? Note that you can very easily do the first thing by specifying hopping(1, dn = (0,1), range = Inf). Then you will hop to any site in cell dn regardless of distance.

@pablosanjose
Copy link
Owner

pablosanjose commented Jun 2, 2021

Yes, I am aware of that. I was just trying to understand how one could define Hamiltonians in a less "automagical" way.

I was toying with the idea of designing a HamiltonianBuilder type that you can use to build Hamiltonian like Kwant does, adding onsites and hoppings with setindex!, and then assembling at the end. I haven't found a case where that is preferable to the current functional approach, so this has low priority currently, but I would love to hear from you if you think otherwise.

@pablosanjose
Copy link
Owner

This could, by the way, join a Wannier90Builder, whenever we get to tackle that #4 issue of yours. Maybe our friend Rui will help me with that!

@pablosanjose
Copy link
Owner

pablosanjose commented Jun 2, 2021

Closing, but feel free to continue the conversation. I will reopen if you convince me there is something that should change in the default hopping behavior

@BacAmorim
Copy link
Author

Hi Pablo. Thank you for the explanation! You have convinced me that the current default makes the most sense. The problem was that in my mind, (in a single orbital per site model) the sublattice completely specified the Wannier orbital. That is, in a Hamiltonian of the form

I was thinking that sublattice = alpha, while in Quantica, alpha = (sublattice, site in sublattice, orbital in site). Am I correct?

I was toying with the idea of desining a HamiltonianBuilder type that you can use to build Hamiltonian like Kwant does, adding onsites and hoppings with setindex!, and then assembling at the end. I haven't found a case where that is preferable to the current functional approach, so this has low priority currently, but I would love to hear from you if you think otherwise.

I think the functional approach equally works. It is just a matter of being familiar with it.

This brings another issue to my mind, but it is better to move the conversation to another place.

@pablosanjose
Copy link
Owner

As we were discussing in #172, alpha is actually a unique site index (an integer), not a triple, and h^{α,β} is an SMatrix over the orbitals in sites α and β. The reason to store things like this, internally, is to make the most of the information we have on a specific model (i.e. we pack interorbital blocks together, because they tend to be dense, while we keep the matrix h itself sparse) while keeping within the limitations of Julia design (e.g. well-defined eltypes of arrays).

@BacAmorim
Copy link
Author

Makes sense. Thank you for the clarification

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

No branches or pull requests

2 participants