How to add leads oblique to a square lattice?

Hello Kwant community, Given a square lattice Hamiltonian, I am trying to put a rectangular sample along an oblique direction to the x,y axes of the underlying square lattice, i.e., the rectangular sides are along new rotated X,Y axes. One can fix the site at the origin (0,0) in the rotation. I have done this successfully using commensurate rotation angles in the following code. The comments in the code explain in detail. The sample looks like this (https://www.dropbox.com/s/2rd9bjbd7ataosy/lattice_fig.pdf?dl=0).
Then I would like to attach leads along the new X-axis (just normally connect to the rectangular sample that doesn't need adding extra sites). I put the translation symmetry rotated to X and confine the lead shape in Y. I expected the lead would just connect to the sample with the interface in Y direction. However, many extra sites are added and the interface is rendered in the old y direction, although the lead does extend in X. The code below attaches only one lead in order to contrast the interface and the opposite unaffected sample edge. The system looks like this (https://www.dropbox.com/s/3wj6r2ws5ev20p5/lattice_fig0.pdf?dl=0).
So the question is how to attach leads in the expected way. Thanks!

Dear Jerry; I guess it might work if you add site family to your symmetry. *your_sym*.add_site_family(*your_latice*.sublattices[0], other_vectors=[*v*]), where v is a tuple and in your case it might be like *v=(-1, 2)* Best wishes, Adel
Le ven. 8 oct. 2021 à 05:37, Jerry xhm xiaoxiao.zhang@riken.jp a écrit :
Hello Kwant community, Given a square lattice Hamiltonian, I am trying to put a rectangular sample along an oblique direction to the x,y axes of the underlying square lattice, i.e., the rectangular sides are along new rotated X,Y axes. One can fix the site at the origin (0,0) in the rotation. I have done this successfully using commensurate rotation angles in the following code. The comments in the code explain in detail. The sample looks like this ( https://www.dropbox.com/s/2rd9bjbd7ataosy/lattice_fig.pdf?dl=0).
Then I would like to attach leads along the new X-axis (just normally connect to the rectangular sample that doesn't need adding extra sites). I put the translation symmetry rotated to X and confine the lead shape in Y. I expected the lead would just connect to the sample with the interface in Y direction. However, many extra sites are added and the interface is rendered in the old y direction, although the lead does extend in X. The code below attaches only one lead in order to contrast the interface and the opposite unaffected sample edge. The system looks like this ( https://www.dropbox.com/s/3wj6r2ws5ev20p5/lattice_fig0.pdf?dl=0).
So the question is how to attach leads in the expected way. Thanks!

Adel Belayadi wrote:
Jerry wrote :
Then I would like to attach leads along the new X-axis (just normally connect to the rectangular sample that doesn't need adding extra sites). I put the translation symmetry rotated to X and confine the lead shape in Y. I expected the lead would just connect to the sample with the interface in Y direction. However, many extra sites are added and the interface is rendered in the old y direction, although the lead does extend in X.
I guess it might work if you add site family to your symmetry. your_sym.add_site_family(your_latice.sublattices[0], other_vectors=[v]), where v is a tuple and in your case it might be like v=(-1, 2)
Thanks, Adel. The following thread offers background information: https://mail.python.org/archives/list/kwant-discuss@python.org/thread/M4PUQD...
Also note that the unwanted sites do not change the physics of the system since the Hamiltonian of the complete system (central region + leads) is the same no matter what the inclination of the lead unit cells is.
Still, I agree that it would be better if attach_lead would avoid adding sites to the central region whenever this is possible. If someone feels motivated to work on this, I’d be happy to lend a hand.
Here is an old and unfinished (but if I recall correctly mostly working) attempt to solve the problem: https://gitlab.kwant-project.org/cwg/kwant/-/commits/adrien_no_add
Christoph

Thank you Adel and Christoph! sym.add_site_family(lat, other_vectors=[v]) with v orthogonal to the translation symmetry vector places the lead in the way I expected. Still, there are one supercell's extra sites added in blue connecting the original central region and the lead (https://www.dropbox.com/s/3c1uioclcbsez4g/lattice2.pdf?dl=0). If I put disorder in the central region, I presume these added sites although in blue color will be the same as the lead Hamiltonian and thus do not have disorder? If so, I guess it might only very slightly affect the physics once the central region is not too small. And these extra sites are currently unavoidable?

Jerry xhm wrote:
sym.add_site_family(lat, other_vectors=[v]) with v orthogonal to the translation symmetry vector places the lead in the way I expected. Still, there are one supercell's extra sites added in blue connecting the original central region and the lead.
All you can do with ‘add_site_family’ and its ‘other_vectors’ parameter is change the orientation of the interface between unit cells. It will always remain straight and its particular rasterization will be according to the lattice module’s own idea.
For example, if you had a round central region and you insisted that ‘attach_lead’ adds no additional sites, that would mean that the delimitation between lead unit cells would have to be round and not straight. While this is supported by Kwant’s data structures it’s not something that the builder module can do currently. You would have to build your low-level system manually instead of finalizing a builder.
If I put disorder in the central region, I presume these added sites although in blue color will be the same as the lead Hamiltonian and thus do not have disorder? If so, I guess it might only very slightly affect the physics once the central region is not too small.
The physics should be absolutely identical since the Hamiltonian of the added sites is taken verbatim from the corresponding sites of the lead.
And these extra sites are currently unavoidable?
Everything is possible...
The fundamental problem is that the code that finalizes a lead (kwant.builder.InfiniteSystem.__init__) insists on modeling the unit cell of the finalized lead after the fundamental domain of the translational symmetry. (See, both concepts are in principle unrelated, but we thought back then that it was a nice simplification to do it this way, since the shape of the unit cell has no physical consequence.)
One way to resolve this would be to enhance said constructor (and the related ‘BuilderLead’) to support arbitrary user-specified shapes of unit cells.
Another way would be to add a custom symmetry (an alternative to ‘kwant.TranslationalSymmetry’) whose fundamental domain has the shape that you would like to have.
But both are not easy and require a good understanding of the internals of Kwant.
Perhaps in your particular case the best is to embrace the imposed shape of the unit cell and simply lay out your central system such that no padding is added.
Christoph

Dear Jerry, It seems that your structure is now correctly shaped as you expect. As was stated by Cristoph, the physics of the system with or without reshaping the system with sym.add_site_family(..) is the same. you said *Still, there are one supercell's extra sites added in blue connecting the original central region and the lead* I guess you mean an extra cell in the lead. This extracell would cause additional modes in the energy band which are not necessary and would affect more or less your transport calculation. Maybe if you write neg_direc[*1/2**direcI]) instead of neg_direc[direcI]) you will get the correct periodicity in the lead. I Hope this helps. Best, Adel
Le ven. 8 oct. 2021 à 15:22, Jerry xhm xiaoxiao.zhang@riken.jp a écrit :
Thank you Adel and Christoph! sym.add_site_family(lat, other_vectors=[v]) with v orthogonal to the translation symmetry vector places the lead in the way I expected. Still, there are one supercell's extra sites added in blue connecting the original central region and the lead ( https://www.dropbox.com/s/3c1uioclcbsez4g/lattice2.pdf?dl=0). If I put disorder in the central region, I presume these added sites although in blue color will be the same as the lead Hamiltonian and thus do not have disorder? If so, I guess it might only very slightly affect the physics once the central region is not too small. And these extra sites are currently unavoidable?

Hello Adel and Christoph, Thanks for the suggestion and explanation! I finally found a workaround to avoid any additionally added sites. Every lead is connected just as expected. The trick is to define each lead and attach their reversed() only. I put the modified part of the code here in case that anyone else finds it helpful.
neg_direc = [(-mx,-my),(my,-mx)] # (negative) X-axis & Y-axis rotated from old x- & y-axis pos_direc = [(mx,my),(-my,mx)] # (positive) X-axis & Y-axis rotated from old x- & y-axis direcI = 0 # lead along which rotated axis: 0 for X, 1 for Y direcIp = 1 # the other axis ... sym0 = kwant.TranslationalSymmetry(neg_direc[direcI]) sym0.add_site_family(lat, other_vectors=[neg_direc[direcIp]]) sym1 = kwant.TranslationalSymmetry(pos_direc[direcI]) sym1.add_site_family(lat, other_vectors=[pos_direc[direcIp]]) syms = [sym0, sym1] for sym in syms: lead = kwant.Builder(sym) lead[lat.shape(lead_reg, (0,0))] = 4*t # (0,0) should work for I-leads as they fully cover the boundary surface lead[kwant.builder.HoppingKind((1, 0), lat, lat)] = t lead[kwant.builder.HoppingKind((0, 1), lat, lat)] = t syst.attach_lead(lead.reversed()) # this avoids additionally added sites

Jerry xhm wrote:
I finally found a workaround to avoid any additionally added sites. Every lead is connected just as expected. The trick is to define each lead and attach their reversed() only. I put the modified part of the code here in case that anyone else finds it helpful.
Glad to hear that you found a workaround. However, it seems to me that this measure works for you only by chance, and is not a generic solution to the problem you faced.
It all depends on how you construct the central region (shaped as a rotated rectangle). If the sides of your rasterized [1] rectangle had exactly matched what Kwant’s lattice module imposes for a given angle, no extra sites had been added to the central region upon lead attachment.
Christoph

Oh, sorry I forgot the code in my post... Here is it.
from math import cos, sin, atan, atan2, pi import numpy as np import time import kwant from matplotlib import pyplot
mx=3 my=2 alpha=atan2(my,mx) # commensurate rotation angle neg_direc = [(-mx,-my),(my,-mx)] # (negative) X-axis & Y-axis rotated from old x- & y-axis newa=(mx**2+my**2)**0.5 # supercell length a_sys = [newa, newa] # supercell is square-like N_sys = [5, 3] # system size along the new XY-axes in units of newa L_sys = [(N_sys[i]-1)*a_sys[i] for i in range(2)] # real-space system size along the new XY-axes Rinvmat = np.array([[cos(alpha),-sin(alpha)],[sin(alpha),cos(alpha)]]) # rotation matrix Rmat = np.array([[cos(alpha),sin(alpha)],[-sin(alpha),cos(alpha)]]) # inverse rotation matrix
direcI = 0 # current/lead along which rotated axis: 0 for X, 1 for Y eta = 1.0e-7 # numerical accuracy bound
def checkedge(a,b,c): # range check that deals with numeric error (when a site sits exactly at the edge) return ((a<=b<=c) or (abs(b-c)<eta) or (abs(b-a)<eta))
def central_reg(pos): # set the rectangular central region rot_pos = Rmat.dot(pos) for i in range(2): if not checkedge(0, rot_pos[i], L_sys[i]): return False return True
def lead_reg(pos): # confine the lead region rot_pos = Rmat.dot(pos) for i in range(2): if direcI != i: if not checkedge(0, rot_pos[i], L_sys[i]): return False return True
def make_system(a=1, t=1): lat = kwant.lattice.square(a) syst = kwant.Builder()
syst[lat.shape(central_reg, (0,0))] = 4*t syst[kwant.builder.HoppingKind((1, 0), lat, lat)] = t syst[kwant.builder.HoppingKind((0, 1), lat, lat)] = t
lead0 = kwant.Builder(kwant.TranslationalSymmetry(neg_direc[direcI])) lead0[lat.shape(lead_reg, (0,0))] = 4*t # (0,0) should work for I-leads as they fully cover the boundary surface lead0[kwant.builder.HoppingKind((1, 0), lat, lat)] = t lead0[kwant.builder.HoppingKind((0, 1), lat, lat)] = t
#syst.attach_lead(lead0) # Kwant Lead 0 #syst.attach_lead(lead0.reversed()) # Kwant Lead 1
syst = syst.finalized() return syst
def main(): syst = make_system() # Check that the system looks as intended. kwant.plot(syst, file="lattice_fig.pdf")
if __name__ == '__main__': main()
participants (3)
-
Adel Belayadi
-
Christoph Groth
-
Jerry xhm