gedaskir / qmeq

QmeQ: an open-source Python package for calculations of transport through quantum dot devices.
Other
27 stars 13 forks source link

Ordering of Many Body States #5

Closed rdavies2980 closed 9 months ago

rdavies2980 commented 1 year ago

Not sure if this is still being maintained but thought I'd share the problem anyway in the hope of some help!

I'm trying to access particular many body states and have been having trouble with the ordering, with it appearing to order the occupation strings incorrectly. In the simplest case, I start with an already diagonalised Hamiltonian with five eigenstates all at different energies (just inputting hsingle as a diagonal matrix with entries {1,2,3,4,5} ). Using the 'Lin' indexing, solving, and then printing all the states,

Ordering

so the 11th state works with "01011" = 11 , but the 12th state has "10001" = 17, instead of "01100" (which is now at the 17th entry). The associated energy shows that it is referring to the state with the 5th and first eigenstate occupied rather than the third and fourth. There are also another three entries which do not correspond to the string I assumed they would be (14, 19, 21). For four or less sites, there are no issues.

Is this the intended ordering? Any response would be greatly appreciated!

pohly-phys commented 1 year ago

Hi, I'm not directly involved with the development of this package but just somewhat of a curious bystander trying to understand what the problem is here :-) I think I've been able to reproduce your two states there with the Hamiltonian you mention. What I don't yet fully understand is the problem here: 1) The state with label "11" is a state occupation of |11010>, i.e., the first, second, and fourth single-particle state being occupied. This also adds up from the energies. I don't see where you take the number 01011 from now? Are you reading the above state coefficients as inverted binary code? I.e., we have |11010> after mirroring of the numbers: 01011 <=> 11 in binary code? 2) The state with label 12 has the |10001>, meaning the first and fifth single-particle state are occupied, as you also write in your analysis of the energetics. Now 10001 is not supposed to be understood as binary code for 17, so I don't think anything is swapped there?

The labelling with integer numbers of these individual states is also somewhat arbitrary, from a physical perspective, no? Maybe you can explain the problem better for me to understand.

rdavies2980 commented 1 year ago

Hi, thanks for taking the time to respond!

Onto your points, yes I'm considering the state coefficients as inverted binary code. Checking the other entries when printing all states shows that inverting these occupation strings and converting the binary representation to decimal corresponds to the sorting label. Eg) |01000> -> "00010" -> sorting label: 2.

But, there are 5 states of the 2^5 possibilities that do not match up to this rule (corresponding to sorted labels: 12,14,17,19,21). I'll attach the full csv file, which will hopefully show this pattern more clearly! Oh, and in case it is important to mention, I'm considering two leads on the system with all states in the dot being coupled to both leads.

I completely agree that the labelling of the states is arbitrary from a physical perspective! The sorted label here however corresponds to the index to use in order to access the correct density matrix element. The end goal is to construct probabilities of occupying a specific eigenstate for a given number of particles, which would require summing over all relevant configurations. For example, if we want probability of the third state being occupied for two electrons in the system, the sum would be over states |10100>, |01100>, |00110>, |00101>. If the labelling is by these binary strings, picking out the correct density matrix elements is relatively easy. It is still possible to pick these states out without this ordering, by checking every state individually, but I wanted to check whether I was missing a trick in the ordering.

The documentation/arxiv paper in section 3.1.1 talks about the ordering and the choices of ordering that is available in the package. This makes me think that it should be ordered due its binary string representation, but also I am aware that the intended use was to have the sites corresponding to position and having hopping between them, rather than labelling eigenstates themselves. I don't know why this wouldn't match up, but it could be a possible source of the confusion.

Hope this clears up what my actual problem was!

testing_5levels.csv

gedaskir commented 1 year ago

Hi, this may seem like a bug from a first glance :-).

However, here the original label corresponds to an eigenstate label after the quantum dot Hamiltonian was diagonalized and it is not the label of the basis states. Roughly speaking, if we decompose the Hamiltonian as $H=PEP^{-1}$ the original label corresponds to a state with an eigenvalue $E$[original label] and is given by a relevant column of $P$[:, original label] (there are some extra details described below).

The expectation that for Lin indexing and diagonal Hamiltonian one would get the original label match up the basis state label is a reasonable one. However, even for a diagonal Hamiltonian the states can and will be shuffled up by the solver.

Here I outline the full indexing procedure and how one arrives at the output for the state with the original label 12. I will use the following single particle Hamiltonian

hsingle = np.diag([1,2,3,4,5])
  1. The basis states are chosen as Fock number states and are indexed using Lin indexing (integer label to binary number to get a state). To get the state from integer label use the method system.si.get_state(basis_integer_label). For basis label 12 we get
system.si.get_state(12)
[0, 1, 1, 0, 0]

Note that this corresponds to binary representation and is not reversed.

  1. The basis states are grouped by charge. The grouping can be retrieved from system.si.chargelst. For the considered example with 5 single particle states and charge=2, we get:
system.si.chargelst[charge]
[3, 5, 6, 9, 10, 12, 17, 18, 20, 24]

This charge grouping is not necessary for Lin indexing, but originally was done anyway to use charge symmetry of quantum dot Hamiltonian. It is worth considering to remove this restriction for Lin indexing, because the same thing is done for 'charge' indexing.

  1. The quantum dot Hamiltonian block for charge=2 is diagonalized and we get the following eigenvalues
system.qd.valslst[charge]
[3., 4., 5., 5., 6., 6., 7., 7., 8., 9.]

and eigenstates

system.qd.vecslst[charge].real
[[0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]
 [0. 0. 0. 0. 0. 0. 0. 0. 1. 0.]
 [0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]
 [0. 0. 0. 0. 0. 0. 0. 1. 0. 0.]
 [0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
 [0. 0. 1. 0. 0. 0. 0. 0. 0. 0.]
 [0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
 [0. 0. 0. 1. 0. 0. 0. 0. 0. 0.]
 [0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
 [1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]]
  1. The energies are assigned for all entries in system.si.chargelst[charge] as:
original_label = system.si.chargelst[charge][i]
system.qd.Ea[original_label] = system.qd.valslst[charge][i]

Here you can see how basis label ends up not corresponding to original label. For original label 12 we get i=5, which leads to the column

system.qd.vecslst[charge][:, 5]
[0. 0. 0. 0. 0. 0. 1. 0. 0. 0.]

This has weight 1.0 with index=6, which gives basis state label

system.si.charge_lst[charge][index]
17

We can check the state to find

system.si.get_state(17)
[1, 0, 0, 0, 1]

This is what you see in the report

  1. A good example how an original label will not correspond to a basis label is to print states for single particle Hamiltonians
hsingle = np.diag([1,10,100,1000,10000])

and

hsingle = np.diag([10000,1000,100,10,1])

In the first case the state with original label 1 is [1, 0, 0, 0, 0] and in the second case it is [0, 0, 0, 0, 1].

As pointed out by the previous answer the original label is arbitrary. The important thing to mention that density matrix calculations are done in the eigenbasis, which corresponds to original labels. I hope this information helps.

rdavies2980 commented 1 year ago

Thank you so much for the detailed response! I had been looking around in the code for the sorting of the states, but having it all laid out clearly here is a massive help.

So the "true" ordering is by the eigenvalues due to the output of linalg.solve(). The ordering variable in the builder class is a larger scale sorting that groups together subspaces, with the states within these subspaces being ordered by eigenvalue. In my case, the choice of Hamiltonian made this unclear!

Again thank you for replying!