Problems to add disorder to the Kitaev chain
Hello Kwant community, I write since I am trying to simulate a Kitaev chain with disorder, here distributed uniformly in the range [1,-1], and I am experiencing troubles to implement the disorder itself. In the absence of disorder, the function that defines the tight-binding (open) Hamiltonian can be written e.g. as follows: def kitaev(L ,t, mu, Delta) : syst = kwant.Builder() lat = kwant.lattice.chain(norbs=2) syst[lat(0)] = - (mu/2)*pauli3 for i in range(1,L): syst[lat(i)] = -(mu/2)*pauli3 syst[lat(i), lat(i - 1)] = -(t/2)*pauli3 + 1j*(Delta/2)*pauli2 return syst where the Pauli matrices have been previously defined, t is the hopping, mu is the chemical potential, and Delta is the gap. Now, I want to add disorder, proportional to W and uniformly distributed in [-1,1]. The tutorial online for Kwant states that the function kwant.digest.uniform(input, salt='') creates a random offset in the interval [0,1]. Therefore I thought that the Hamiltonian could be changed e.g. as follows: def kitaev(L ,t, mu, Delta, W) : syst = kwant.Builder() lat = kwant.lattice.chain(norbs=2) syst[lat(0)] = -(1/2)*(mu + W*(2*onsite - 1))*pauli3 for i in range(1,L): syst[lat(i)] = -(1/2)*(mu + W*(2*onsite - 1))*pauli3 syst[lat(i), lat(i - 1)] = -(t/2)*pauli3 + 1j*(Delta/2)*pauli2 return syst after that the onsite function has been defined as def onsite(site, phi, salt): return uniform(repr(site), salt) (I am still trying to follow the tutorial). However, when trying to calculate eigenvalues and eigenvectors, via the code L = 50 W = 0 mub = 3 systb = kitaev(L ,1, mub, 1, W) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb) I encountered the problem ----------------------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-10-12a574eefcd0> in <module> 3 4 mub = 3 ----> 5 systb = kitaev(L ,1, mub, 1, W) 6 systb = systb.finalized() 7 hamatb = systb.hamiltonian_submatrix(sparse = False) <ipython-input-9-661d5ddb539a> in kitaev(L, t, mu, Delta, W) 4 lat = kwant.lattice.chain(norbs=2) 5 ----> 6 syst[lat(0)] = -(1/2)*(mu + W*(2*onsite - 1))*pauli3 7 8 for i in range(1,L): TypeError: unsupported operand type(s) for *: 'int' and 'function' —————————————————————————————------ that instead does no occur in the absence of disorder (then when the first definition above for the Kitaev chain is assumed). Probably I did not understand properly how to use the function uniform(repr(site), salt). Can you help me ? Thank you very much in advance and best regards L. L.
Hi Luca,
syst[lat(0)] = -(1/2)*(mu + W*(2*onsite - 1))*pauli3
for i in range(1,L):
syst[lat(i)] = -(1/2)*(mu + W*(2*onsite - 1))*pauli3
syst[lat(i), lat(i - 1)] = -(t/2)*pauli3 + 1j*(Delta/2)*pauli2
----------------------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-10-12a574eefcd0> in <module> 3 4 mub = 3 ----> 5 systb = kitaev(L ,1, mub, 1, W) 6 systb = systb.finalized() 7 hamatb = systb.hamiltonian_submatrix(sparse = False)
<ipython-input-9-661d5ddb539a> in kitaev(L, t, mu, Delta, W) 4 lat = kwant.lattice.chain(norbs=2) 5 ----> 6 syst[lat(0)] = -(1/2)*(mu + W*(2*onsite - 1))*pauli3 7 8 for i in range(1,L):
TypeError: unsupported operand type(s) for *: 'int' and 'function'
—————————————————————————————------
You get this error because in your code, 'onsite' is a function, and you are trying to multiply it by an integer (2). You should instead *call* the onsite function with the appropriate site: syst[lat(i)] = -(1/2) * (mu + W * ( 2 * onsite(lat(i), salt) - 1) * pauli3 where I have defined 'onsite' as: def onsite(site, salt): return uniform(repr(site)) Note that in your example 'onsite' took a parameter 'phi' which was not used (and hence unnecessary). In order for this to work, your 'kitaev' function will also have to take a 'salt' parameter. The disadvantage of this approach is that you have to re-build the system from scratch every time you want to change any of the parameters. If you want to do many calculations for different parameter values (but same system geometry; i.e. value of 'L' in your example) then I would recommend constructing the system only once, and using *functions* for the Hamiltonian values: def onsite(site, mu, W, salt): disorder = W * (2 * uniform(repr(site), salt) - 1) return -0.5 * (mu + disorder) * pauli3 def hopping(site1, site2, t, Delta): return -(t / 2) * pauli3 + 1j * (Delta / 2) * pauli2 def kitaev(L): syst = kwant.Builder() lat = kwant.lattice.chain(norbs=2) syst[(lat(i) for i in range(L))] = onsite syst[lat.neighbors()] = hopping return syst systb = kitaev(...).finalized() systb.hamiltonian_submatrix(params=dict(mu=..., W=..., t=..., Delta=..., salt=...)) Happy Kwanting, Joe
Dear Joe, thank you very much for your fast and compelling reply. Exploiting your advice, that means writing ----------------------------------------------------------------------------------------------- def onsite(site, salt): return uniform(repr(site)) def kitaev(L ,t, mu, Delta, W, salt) : syst = kwant.Builder() lat = kwant.lattice.chain(norbs=2) syst[lat(0)] = -(1/2)*(mu + W*(2*onsite(lat(0), salt) - 1))*pauli3 for i in range(1,L): syst[lat(i)] = -(1/2)*(mu + W*(2*onsite(lat(i), salt) - 1))*pauli3 syst[lat(i), lat(i - 1)] = -(t/2)*pauli3 + 1j*(Delta/2)*pauli2 return syst ----------------------------------------------------------------------------------------------- the code actually works, in the sense that no errors occur in the output of the calling string ----------------------------------------------------------------------------------------------- t = 1 Delta = 1 L = 50 W = 1 salt = 1 mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb) ----------------------------------------------------------------------------------------------- However, I still do not get the role of the parameter "salt" (here above I defined it conventionally salt = 1): how do I have to set it ? In the previous discussion page https://www.mail-archive.com/kwant-discuss@kwant-project.org/msg01497.html you claim that "the 'salt' parameter does not have any physical meaning; it's like the 'seed' that you typically specify to a random number generator." Then does it mean that the physical numbers must not to change with the set value for salt ? Last question: the string mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb) creates the Kitaev code with just one specific configuration for the random onsite offset, right ? Thank you very much again and best L.
Dear Luca, With the parameter salt (which can be a number or a string), you will be sure that each time you call your system (or hamiltonian) with the same parameter salt, you will have the same configuration: this means that the potential is random from one site to another, but the overall configuration does not change when you call your system many times. If you use the usual random function from numpy, you will have a different random configuration each time you call your system. I hope this helps, Adel On Mon, Feb 3, 2020 at 12:00 AM Luca Lepori <llepori81@gmail.com> wrote:
Dear Joe,
thank you very much for your fast and compelling reply.
Exploiting your advice, that means writing
-----------------------------------------------------------------------------------------------
def onsite(site, salt):
return uniform(repr(site))
def kitaev(L ,t, mu, Delta, W, salt) :
syst = kwant.Builder() lat = kwant.lattice.chain(norbs=2)
syst[lat(0)] = -(1/2)*(mu + W*(2*onsite(lat(0), salt) - 1))*pauli3
for i in range(1,L):
syst[lat(i)] = -(1/2)*(mu + W*(2*onsite(lat(i), salt) - 1))*pauli3
syst[lat(i), lat(i - 1)] = -(t/2)*pauli3 + 1j*(Delta/2)*pauli2
return syst
-----------------------------------------------------------------------------------------------
the code actually works, in the sense that no errors occur in the output of the calling string
-----------------------------------------------------------------------------------------------
t = 1 Delta = 1 L = 50 W = 1 salt = 1
mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb)
-----------------------------------------------------------------------------------------------
However, I still do not get the role of the parameter "salt" (here above I defined it conventionally salt = 1): how do I have to set it ?
In the previous discussion page
https://www.mail-archive.com/kwant-discuss@kwant-project.org/msg01497.html
you claim that
"the 'salt' parameter does not have any physical meaning; it's like the 'seed' that you typically specify to a random number generator."
Then does it mean that the physical numbers must not to change with the set value for salt ?
Last question: the string
mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb)
creates the Kitaev code with just one specific configuration for the random onsite offset, right ?
Thank you very much again and best
L.
-- Abbout Adel
Dear Adel and Joe, thanks again for your useful reply. If I understand correctly, then I am not sure how to simulate the physics of disorder. Indeed, that task requires to create various (in principle infinite in number) configurations, measure some physical quantity on each of them, and then to take the average of all these measurements on the created configurations. How can I create the different configurations ? Starting e.g. from the piece of code ------------------------------------------------------------------------------------------------ t = 1 Delta = 1 L = 50 W = 1 (salta = ?) mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb) ------------------------------------------------------------------------------------------------ is it sufficient to add a For cycle on the value of salt ? Say, from 1 to Nmax, where Nmax is the number of configurations that I want to consider ? Thank you very much again L. Il giorno lun 3 feb 2020 alle ore 11:48 Abbout Adel <abbout.adel@gmail.com> ha scritto:
Dear Luca,
With the parameter salt (which can be a number or a string), you will be sure that each time you call your system (or hamiltonian) with the same parameter salt, you will have the same configuration: this means that the potential is random from one site to another, but the overall configuration does not change when you call your system many times. If you use the usual random function from numpy, you will have a different random configuration each time you call your system.
I hope this helps, Adel
On Mon, Feb 3, 2020 at 12:00 AM Luca Lepori <llepori81@gmail.com> wrote:
Dear Joe,
thank you very much for your fast and compelling reply.
Exploiting your advice, that means writing
-----------------------------------------------------------------------------------------------
def onsite(site, salt):
return uniform(repr(site))
def kitaev(L ,t, mu, Delta, W, salt) :
syst = kwant.Builder() lat = kwant.lattice.chain(norbs=2)
syst[lat(0)] = -(1/2)*(mu + W*(2*onsite(lat(0), salt) - 1))*pauli3
for i in range(1,L):
syst[lat(i)] = -(1/2)*(mu + W*(2*onsite(lat(i), salt) - 1))*pauli3
syst[lat(i), lat(i - 1)] = -(t/2)*pauli3 + 1j*(Delta/2)*pauli2
return syst
-----------------------------------------------------------------------------------------------
the code actually works, in the sense that no errors occur in the output of the calling string
-----------------------------------------------------------------------------------------------
t = 1 Delta = 1 L = 50 W = 1 salt = 1
mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb)
-----------------------------------------------------------------------------------------------
However, I still do not get the role of the parameter "salt" (here above I defined it conventionally salt = 1): how do I have to set it ?
In the previous discussion page
https://www.mail-archive.com/kwant-discuss@kwant-project.org/msg01497.html
you claim that
"the 'salt' parameter does not have any physical meaning; it's like the 'seed' that you typically specify to a random number generator."
Then does it mean that the physical numbers must not to change with the set value for salt ?
Last question: the string
mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb)
creates the Kitaev code with just one specific configuration for the random onsite offset, right ?
Thank you very much again and best
L.
-- Abbout Adel
Dear Luca, That is an easy task: Just put a different parameter in your function. 1) Put the "salt" as a parameter in your onsite function and not in make_system def Onsite(site, salt="1"): …… …… 2) when you do your calculation, use params: params={"disorder"="1", B=2, Phi=4} for i in range(100): params["disorder"]=str(i) wave=kwant.wave_function(syst, params=params) #then calculate whatever you want for this configuration I hope this helps Adel On Mon, Feb 3, 2020 at 11:23 PM Luca Lepori <llepori81@gmail.com> wrote:
Dear Adel and Joe,
thanks again for your useful reply.
If I understand correctly, then I am not sure how to simulate the physics of disorder.
Indeed, that task requires to create various (in principle infinite in number) configurations, measure some physical quantity on each of them, and then to take the average of all these measurements on the created configurations.
How can I create the different configurations ? Starting e.g. from the piece of code
------------------------------------------------------------------------------------------------
t = 1 Delta = 1 L = 50 W = 1 (salta = ?)
mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb)
------------------------------------------------------------------------------------------------
is it sufficient to add a For cycle on the value of salt ? Say, from 1 to Nmax, where Nmax is the number of configurations that I want to consider ?
Thank you very much again
L.
Il giorno lun 3 feb 2020 alle ore 11:48 Abbout Adel <abbout.adel@gmail.com> ha scritto:
Dear Luca,
With the parameter salt (which can be a number or a string), you will be
sure that each time you call your system (or hamiltonian) with the same parameter salt, you will have the same configuration: this means that the potential is random from one site to another, but the overall configuration does not change when you call your system many times. If you use the usual random function from numpy, you will have a different random configuration each time you call your system.
I hope this helps, Adel
On Mon, Feb 3, 2020 at 12:00 AM Luca Lepori <llepori81@gmail.com> wrote:
Dear Joe,
thank you very much for your fast and compelling reply.
Exploiting your advice, that means writing
-----------------------------------------------------------------------------------------------
def onsite(site, salt):
return uniform(repr(site))
def kitaev(L ,t, mu, Delta, W, salt) :
syst = kwant.Builder() lat = kwant.lattice.chain(norbs=2)
syst[lat(0)] = -(1/2)*(mu + W*(2*onsite(lat(0), salt) - 1))*pauli3
for i in range(1,L):
syst[lat(i)] = -(1/2)*(mu + W*(2*onsite(lat(i), salt) -
1))*pauli3
syst[lat(i), lat(i - 1)] = -(t/2)*pauli3 + 1j*(Delta/2)*pauli2
return syst
the code actually works, in the sense that no errors occur in the output of the calling string
t = 1 Delta = 1 L = 50 W = 1 salt = 1
mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb)
However, I still do not get the role of the parameter "salt" (here above I defined it conventionally salt = 1): how do I have to set it ?
In the previous discussion page
https://www.mail-archive.com/kwant-discuss@kwant-project.org/msg01497.html
you claim that
"the 'salt' parameter does not have any physical meaning; it's like the 'seed' that you typically specify to a random number generator."
Then does it mean that the physical numbers must not to change with the set value for salt ?
Last question: the string
mub = 3 systb = kitaev(L,t,mub,Delta,W,salt) systb = systb.finalized() hamatb = systb.hamiltonian_submatrix(sparse = False) evalsb, evecsb = la.eigh(hamatb)
creates the Kitaev code with just one specific configuration for the random onsite offset, right ?
Thank you very much again and best
L.
-- Abbout Adel
-- Abbout Adel
Hi Luca,
thanks again for your useful reply.
If I understand correctly, then I am not sure how to simulate the physics of disorder.
Indeed, that task requires to create various (in principle infinite in number) configurations, measure some physical quantity on each of them, and then to take the average of all these measurements on the created configurations.
How can I create the different configurations ? Starting e.g. from the piece of code
Indeed, typically you'll want to take the average over different disorder configurations. This means using different values for the 'salt' parameter. The actual values used for 'salt' are not important, as long as they differ; 'kwant.digest.uniform' is a hash function (see https://en.wikipedia.org/wiki/Salt_(cryptography) ). You would do something like the following: syst = kitaev(L=...).finalized() params = dict(mu=..., W=..., t=..., Delta=...) # We (arbitrarily) choose the salts as the strings '0', '1', ... salts = map(str, range(100)) for params['salt'] in salts: ham = syst.hamiltonian_submatrix(params=params, sparse=False) evals = np.linalg.eigvalsh(ham) ... Happy Kwanting, Joe
participants (3)
-
Abbout Adel
-
Joseph Weston
-
Luca Lepori