Beispiel #1
0
def read_or_write_energies_mu(sys, par, ppar):
    """
	Reads from file or calculates eigenenergies and eigenvectors as a function of only mu_values, for some constant biasenergy and par.Ez.

	Notes
	-----
	 - Using arr.argsort() to get indices that sorts the array arr. Here, using this on the eigenenergies in order to also be able to sort the eigenvectors, such that, later, one may access the k'th eigenvector.
	 - If ppar.pincher_SC_lead is True: In this case, the total Kwant system is the normal metal plus the SC pincher layer that runs along the long axis of the normal metal. But we want the energy of the normal metal wire only. Therefore, when ppar.pincher_SC_lead is True, then only the subhamiltonian at the sites of the normal metal are used to compute the energies of the system.
	"""
    print("%s: In read_or_write_energies_mu" %
          (misc.round_time(datetime.datetime.now(), round_to=60)))

    if ppar.generate_En_mu == False:

        if ppar.doubleres == False:
            par.energies_mu = np.load("Evsmu_" + ppar.filename + ".npy")
            print(" - loaded Evsmu datalog file")
            if ppar.Eonly == True:
                pass
            else:
                par.eigenvectors_mu = np.load("Eigenvectorsvsmu_" +
                                              ppar.filename + ".npy")
                print(" - loaded Eigenvectorsvsmu datalog file")
        else:
            par.energies_mu = np.load("Evsmu_" + ppar.filename_2 + ".npy")
            print(" - loaded Evsmu datalog file")
            if ppar.Eonly == True:
                pass
            else:
                par.eigenvectors_mu = np.load("Eigenvectorsvsmu_" +
                                              ppar.filename_2 + ".npy")
                print(" - loaded Eigenvectorsvsmu datalog file")

    else:
        calc.calc_energies_mu(sys, par, ppar)

    if ppar.doubleres == False:
        write_var(ppar, var=par.energies_mu, var_extra_title_str="Evsmu_")
        print("%s: - saved Evsmu datalog file" %
              (misc.round_time(datetime.datetime.now(), round_to=60)))
        write_var(ppar,
                  var=par.eigenvectors_mu,
                  var_extra_title_str="Eigenvectorsvsmu_")
        print("%s: - saved Eigenvectorsvsmu datalog file" %
              (misc.round_time(datetime.datetime.now(), round_to=60)))
    else:
        write_var_2(ppar, var=par.energies_mu, var_extra_title_str="Evsmu_")
        print("%s: - saved Evsmu datalog file" %
              (misc.round_time(datetime.datetime.now(), round_to=60)))
        write_var_2(ppar,
                    var=par.eigenvectors_mu,
                    var_extra_title_str="Eigenvectorsvsmu_")
        print("%s: - saved Eigenvectorsvsmu datalog file" %
              (misc.round_time(datetime.datetime.now(), round_to=60)))
Beispiel #2
0
def read_or_write_energies_mu_bias(sys, par, ppar):
    """
	Reads from file or calculated eigenenergies and eigenvectors as a function of mu and biasenergy for the system.

	Parameters
	----------
	sys : 	kwant.Builder.
	par : 	parameters of system.
	generate_En_mu_bias : 	Boolean (True/False)
	"""

    print(misc.round_time(datetime.datetime.now(), round_to=60),
          ": In read_or_write_energies_mu_bias")
    if ppar.generate_En_mu_bias == False:
        par.energies_mu_bias = np.load("Evsmubias_" + ppar.filename + ".npy")
        par.eigenvectors_mu_bias = np.load("Eigenvectorsvsmubias_" +
                                           ppar.filename + ".npy")
        par.Ez = par.Ez_values[0]

    else:
        par.energies_mu_bias = []
        par.eigenvectors_mu_bias = np.zeros(
            (len(par.mu_values), len(par.biasenergies), par.Ny * 2 * 2, par.k),
            dtype=np.complex_)
        for par.mu, i in zip(par.mu_values, range(len(par.mu_values))):
            print(" - %.0f'th mu-value" % i)
            for par.biasenergy, j in zip(par.biasenergies,
                                         range(len(par.biasenergies))):
                H = sys.hamiltonian_submatrix(args=[par], sparse=True)
                H = H.tocsc()
                Hpbias = H + np.array(par.biasenergy * np.ones(np.shape(H)))
                """Trying: just not sorting the energies:"""
                eigs = scipy.sparse.linalg.eigsh(Hpbias, k=par.k, sigma=0)
                # eigs = np.sort(np.array(eigs),axis=0).all()
                par.energies_mu_bias.append(np.sort(eigs[0]))
                par.eigenvectors_mu_bias[i, j, :, :] = eigs[1]

        write_var(ppar,
                  var=par.energies_mu_bias,
                  var_extra_title_str="Evsmubias_")
        print("%s: saved datalog file %s" %
              (misc.round_time(datetime.datetime.now(), round_to=60),
               ("Evsmubias_" + ppar.filename + ".npy")))
        write_var(ppar,
                  var=par.eigenvectors_mu_bias,
                  var_extra_title_str="Eigenvectorsvsmubias_")
        print("%s: saved datalog file %s" %
              (misc.round_time(datetime.datetime.now(), round_to=60),
               ("Eigenvectorsvsmubias_" + ppar.filename + ".npy")))
Beispiel #3
0
def make_1DNLeft_1DN_2DSMiddle_No_NRight_system(p,ppar):
	"""
	Makes system that is HN+HS:
			 - 1D HN wire
			 - 2D HS lead connecting along whole wire length
			 - 1D Left N lead attached
			 - No Right lead attached, because to compare to calibration system where G11 is considered in the first round of calibrations.
	"""

	print("%s: in make_1DNLeft_1DN_2DSMiddle_No_NRight_system()" %str(misc.round_time(datetime.datetime.now(),round_to=60)))

	import kwant

	sys = kwant.Builder()

	sys[(lat(x,y) for x in [0] for y in range(p.Ny))] = onsite_1D_semiconductor 
	sys[kwant.builder.HoppingKind((0,1),lat)] = hoppingy_1D_semiconductor

	"""Attaching leads to this "L" region:"""
	lead = make_lead_onesite_wide_1D(p)

	sys.attach_lead(lead)
	#sys.attach_lead(lead.reversed())

	""" 
	Adding SC lead last. In that way, the indexing of the smatrix will work as before when wanting to access the other leads. In order to access from the SC lead, acces the 2nd lead index in e.g. the smatrix.
	"""
	if ppar.SClead == True:
		SClead = make_SC_lead_Ny_wide(p)
		sys.attach_lead(SClead)
		print(" - Attached SC lead")

	return sys
Beispiel #4
0
def print_current_part(part_,i):
	"""
	Prints which part of the system that one is currently attaching to the Builder object sys=kwant.Builder(...).

	Parameters
	----------
	i : 	str.
			Name of the part one is currently building in.
	part_ : 	np.array, list or tuple.
				Contains all the site numbers of the part currently being built.
	"""
	
	if len(part_) == 0:	# if asymmetric device such that a part is simply removed, effectively rendering its length=0
		if part_ != par.right:
			print("%s: %s (site %s to %s)" %(str(misc.round_time(datetime.datetime.now(),round_to=60)),i,part_[0],part_[-1]))
		else:
			print("%s: R abscent" %str(misc.round_time(datetime.datetime.now(),round_to=60)))
	else:
		print("%s: %s (site %s to %s)" %(str(misc.round_time(datetime.datetime.now(),round_to=60)),i,part_[0],part_[-1]))
Beispiel #5
0
def read_or_write_energies_biasenergies(sys, par, ppar):
    """
	Reads from file or calculates eigenenergies and eigenvectors as a function of only biasenergies, for some constant par.mu and par.Ez.
	"""
    if ppar.use_energies_from_file_biasenergies == True:
        par.energies_biasenergies = np.load("Evsmu_" + ppar.filename + ".npy")
        par.eigenvectors_biasenergies = np.load("Eigenvectorsvsbiasenergies_" +
                                                ppar.filename + ".npy")
        par.Ez = par.Ez_values[0]

    else:
        par.energies_biasenergies = []
        par.eigenvectors_biasenergies = [
        ]  #np.zeros((len(par.mu_values),par.k))
        for par.biasenergy, i in zip(par.biasenergies,
                                     range(len(par.biasenergies))):
            print(i, par.biasenergy)

            H = sys.hamiltonian_submatrix(args=[par], sparse=True)
            H = H.tocsc()
            Hpbias = H + np.array(par.biasenergy * np.ones(np.shape(H)))

            eigs = scipy.sparse.linalg.eigsh(Hpbias, k=par.k, sigma=0)

            sorting_indices = eigs[0].argsort()
            evals = eigs[0][sorting_indices]
            evecs = eigs[1][:, sorting_indices]

            par.energies_mu.append(evals)
            par.eigenvectors_mu.append(evecs)

        write_var(ppar,
                  var=par.energies_biasenergies,
                  var_extra_title_str="Evsbiasenergies_")
        print("%s: saved datalog file %s" %
              (misc.round_time(datetime.datetime.now(), round_to=60),
               ("Evsbiasenergies_" + ppar.filename + ".npy")))
        write_var(ppar,
                  var=par.eigenvectors_biasenergies,
                  var_extra_title_str="Eigenvectorsvsbiasenergies_")
        print("%s: saved datalog file %s" %
              (misc.round_time(datetime.datetime.now(), round_to=60),
               ("Eigenvectorsvsbiasenergies_" + ppar.filename + ".npy")))
Beispiel #6
0
def calc_u2mv2_mu(evec_n, mu_values, Ny, filename_, filename):
    """
	Calculates u and v (Bogoliubon amplitudes) from the eigenvectors, which are in themselves functions of mu/Ez and are given for every site {0,...,Ny} in the 1D system of length Ny.
	 - Definition:
					u(i)^2 = |u_up(i)|^2 + |u_down(i)|^2
					v(i)^2 = |v_up(i)|^2 + |v_down(i)|^2
					where i = site number, up/down = spins and the eigenvectors in the sigma*tau (spin*particle/hole) basis are {|psi(i)>}, given by
					|psi(i)> = (u_up(i), u_down(i), v_down(i), -v_down(i)).
	
	Parameters
	----------
	evec_n : 	{|psi(site i, mu j)>|_n} with shape (par.mu_res,par.Ny*2*2)

	Variables
	---------
	uu, ud, vd, mvu : 	u_up, u_down, v_down, -v_up. Shape: (par.mu_res,par.Ny), not with par.Ny*2*2, since up/down and u/v already specifies the spin/p-h DOFs.
	"""

    print(misc.round_time(datetime.datetime.now(), round_to=60),
          ": in calc_u2mv2_var")

    uu = np.zeros((len(mu_values), Ny), dtype=np.complex_)
    ud = np.zeros((len(mu_values), Ny), dtype=np.complex_)
    mvd = np.zeros((len(mu_values), Ny), dtype=np.complex_)
    vu = np.zeros((len(mu_values), Ny), dtype=np.complex_)

    u2_mu_site = np.zeros((len(mu_values), Ny))  #,dtype=np.complex_)
    v2_mu_site = np.zeros((len(mu_values), Ny))  #,dtype=np.complex_)

    for i in range(len(mu_values)):
        print(" - mu_value number ", i)
        for j in range(Ny):

            [uu[i, j], mvd[i, j], ud[i, j],
             vu[i, j]] = evec_n[i, 4 * j:4 * (j + 1)]

            u2_mu_site[i, j] = np.abs(uu[i, j])**2 + np.abs(ud[i, j])**2
            v2_mu_site[i, j] = np.abs(mvd[i, j])**2 + np.abs(vu[i, j])**2

    u2_mu = np.sum(u2_mu_site, axis=1)
    v2_mu = np.sum(v2_mu_site, axis=1)

    ### Also saving the whole u/v2_mu_site file. Then, may access it later, and e.g. plot only for one given site:
    np.save("u2_mu_sites_" + filename_, u2_mu_site)
    np.save("v2_mu_sites_" + filename_, v2_mu_site)
    ######################################

    u2mv2_mu = u2_mu - v2_mu

    np.save(filename, u2mv2_mu)

    print(" - Saved datalog file: ", filename)

    return u2mv2_mu, u2_mu, v2_mu, u2_mu_site, v2_mu_site
Beispiel #7
0
def plot_G_1_G_2_varconst(par,G_1,G_2,index_of_varconst,filename,figtitle,xlabel,ylabel,legend,ylim,colors,**kwargs):
	"""

	Parameters
	----------
	**kwargs : 	optionally also setting a third conductance, G_3
	"""
	plt.hold("off")
	fig,ax = plt.subplots(1,1)
	fig.set_size_inches(3.5, 3.1)
	ax.tick_params(labelsize=12)

	plt.rcParams.update({'font.size': 12})
	ax.plot(par.biasenergies,G_1[index_of_varconst,:],colors[0])
	ax.hold("on")
	ax.plot(par.biasenergies,G_2[index_of_varconst,:],colors[1])

	if len(kwargs) == 1:
		print("len kwargs = 1")
		plt.hold("on")
		ax.plot(par.biasenergies,kwargs["G_3"][index_of_varconst,:],colors[2])
	if len(kwargs) == 2:
		print("len kwargs = 2")
		plt.hold("on")
		ax.plot(par.biasenergies,kwargs["G_3"][index_of_varconst,:],'--',color=colors[2])
		ax.hold("on")
		ax.plot(par.biasenergies,kwargs["G_4"][index_of_varconst,:],'--',color=colors[3])
	if len(kwargs) == 3:
		print("len kwargs = 3")
		plt.hold("on")
		ax.plot(par.biasenergies,kwargs["G_3"][index_of_varconst,:],colors[2])
		ax.hold("on")
		ax.plot(par.biasenergies,kwargs["G_4"][index_of_varconst,:],colors[3])
		ax.hold("on")
		ax.plot(par.biasenergies,kwargs["G_5"][index_of_varconst,:],colors[4])

	# from mpl_toolkits.axes_grid1.inset_locator import inset_axes

	# axins = ax.inset_axes(ax, width="40%", height="30%", loc=3)

	ax.set_title(figtitle,fontsize=12)
	ax.set_xlabel(xlabel,fontsize=12)
	ax.set_ylabel(ylabel,fontsize=12)
	ax.set_ylim(ylim)
	ax.ticklabel_format(style='sci',scilimits=(-3,4),fontsize=12)
	fig.subplots_adjust(left=0.21,bottom=0.16,right=0.99,top=0.99)

	ax.legend(legend,loc=4,fontsize=12)
	plt.grid("on")
	plt.show()

	fig.savefig(filename + ".pdf")	

	print("%s: Saved figure"%misc.round_time(datetime.datetime.now(),round_to=60), filename + ".pdf")
Beispiel #8
0
def make_system(p,ppar):

	"""
	Building the different parts by adding onsite/hoppings to sys:
	Since adding lead only to scattering region, I iterate over par.middle first; then I can use just one sys object to attach the leads in the first iteration, and keep the same sys object when continuing on adding the right and left parts.

	Parameters
	----------
	ppar.make_1DNLeft_1DN_2DS_2DSMiddle_No_NRight : 	Boolean.
							If True or 1, a 1D semiconducting wire is constructed with a 2D superconductor connected to it along the whole wire (along the y-direction), with a pincher layer of SC (???given by a 2D hamiltonian but only with one site in width for now ???ok???) at the boundary between the semiconductor and the superconducting lead.

	Notes
	-----
	If 1D pincher is to be added at the edges of the 1D system, this is taken care of in make_1D_system, given that p.pincher==True and a t-value p.t_pincher needs to have been defined.
	"""
	
	print("%s: in make_system()" %str(misc.round_time(datetime.datetime.now(),round_to=60)))

	if ppar.one_D == True:
		if ppar.make_1D_Heff_LR_leads:
			sys = make_1D_system(p,ppar)						# make 1D N-S-N system, where middle S is the effective Hamiltonian of the proximitized semiconductor, and there is no middle S lead, meaning that conductances above the gap obrained in this model are not accurate, as modes should in the real physical system have been able to escape through the middle S lead above the gap (where the middle S has available quasiparticle excitations).
		elif ppar.make_1DNLeft_1DN_2DSMiddle_No_NRight:
			sys = make_1DNLeft_1DN_2DSMiddle_No_NRight_system(p,ppar)
		elif ppar.make_1DNLeft_1DN_2DS_2DSMiddle_No_NRight:
			sys = make_1DNLeft_1DN_2DS_2DSMiddle_No_NRight_system(p,ppar)				# make 1D N-N(S)-N system, where middle N is 1D and middle S is 2D.
		elif ppar.make_1D_NLeft_1D_S_Heff_No_NRight:
			sys = make_1D_NLeft_1D_S_Heff_No_NRight(p,ppar) 	# make 1D N-S junction for calibration, where S has the effective Hamiltonian of the proximitized semiconductor
		elif ppar.make_1D_NLeft_1D_N_2D_S_2D_SMiddle_No_NRight:	# make 1D N-N(S) function to calibrate, where S is a 2D SC Hamiltonian that should induce the gap in the middle N
			sys = make_1D_Nleft_1D_N_2D_S_2D_SMiddle_No_NRight(p,ppar)
		
	else:
		"""Function building superconductor for parameters in SimpleNamespace object p."""
		sys = kwant.Builder()
		par.asymmetric = check_asymm_device(par)	# True/False, to be used when printing last blocks of Hamiltonian

		for i,part_ in zip(('M','L','R'),(p.middle, p.left, p.right)):
			"""Printing which part is being built at the current loop iteration:"""
			print_current_part(part_,i)
			"""Adding parts to the system:"""
			sys[(lat(x,y) for x in part_ for y in range(p.Ny))] = onsite #  Not input phase/gamma explicitly such that may specify variables such as Ez at later point in code after finalizing. I think that Kwant has this particular syntax in sys[lat..]=<function_name> without having to input arguments in the function.
			sys[kwant.builder.HoppingKind((1,0),lat)] = hoppingx
			sys[kwant.builder.HoppingKind((0,1),lat)] = hoppingy

			"""Attaching leads to the middle region, i.e. the scattering region:"""
			if i == 'M':
				lead = make_lead_onesite_wide(p) #make_lead(p)
				sys.attach_lead(lead)
				sys.attach_lead(lead.reversed())

	return sys
Beispiel #9
0
def hoppingy_t_(site0,site1,p):
	"""
	Hopping energy in 1D system for a, arbitrary hopping p.t_.

	Parameters
	----------
	p.t_ : 	Arbitrary hopping amplitude for which hopping is computed.

	Notes
	-----
	Used e.g. in implementing a pincher. In that case, e.g. t_=p.t_pincher_L or R.
	Since part of the hopping Hamiltonian for which Kwant demands have only the arguments site0, site1, p, t_ needs to be saved in p in order to use this functoin, and cannot be passed as an extra argument to hoppingy_t_.
	"""
	print("%s: in hopping_t_()" %str(misc.round_time(datetime.datetime.now(),round_to=60)))
	return -p.t_*tau_z - 1j*p.alphahbar/(2.*p.ay)*sigma_xtau_z
Beispiel #10
0
def make_1DNLeft_1DN_2DS_2DSMiddle_No_NRight_system(p,ppar):

	"""

	Notes
	-----
	 - x-coordinate of the 1D semiconducting system is taken to be zero.
	 - x-coordinate of the 2D pincher layer is taken to be at +1. So the pincher layer is 1D, but implemented as a 2D Hamiltonian because it needs to have couplings between it and the middle N.

	"""
	print("%s: in make_1DNLeft_1DN_2DS_2DSMiddle_No_NRight_system()" %str(misc.round_time(datetime.datetime.now(),round_to=60)))

	import kwant

	sys = kwant.Builder()

	sys[(lat(x,y) for x in [0] for y in range(p.Ny))] = onsite_1D_semiconductor 
	sys[kwant.builder.HoppingKind((0,1),lat)] = hoppingy_1D_semiconductor

	if ppar.pincher_SC_lead == True:
		print(" - Adding SC pincher at SM system - SC lead boundary.")
		"""Attaching extra sites with hoppings p.tx_SC_pincher and p.ty_SC_pincher:"""
		if ppar.SC_pincher_1D == True:
			sys[(lat(x,y) for x in [1] for y in range(p.Ny))] = onsite_1D_superconductor_pincher
			sys[kwant.builder.HoppingKind((0,1),lat)] = hoppingy_1D_superconductor_pincher

		else:
			sys[(lat(x,y) for x in [1] for y in range(p.Ny))] = onsite_2D_superconductor_pincher
			sys[kwant.builder.HoppingKind((1,0),lat)] = hoppingx_2D_superconductor_pincher
			sys[kwant.builder.HoppingKind((0,1),lat)] = hoppingy_2D_superconductor_pincher

	"""Attaching leads to this "L" region:"""
	lead = make_lead_onesite_wide_1D(p)

	sys.attach_lead(lead)
	sys.attach_lead(lead.reversed())

	""" 
	Adding SC lead last. In that way, the indexing of the smatrix will work as before when wanting to access the other leads. In order to access from the SC lead, acces the 2nd lead index in e.g. the smatrix.
	"""
	if ppar.SClead == True:
		SClead = make_SC_lead_Ny_wide(p)
		sys.attach_lead(SClead)
		print(" - Attached SC lead")

	return sys
Beispiel #11
0
def plot_map(dependent_var,x,y,filename,figtitle,xlabel,ylabel,cm,**kwargs):
	"""
	Plots general map of data of dependent_var vs independent_vars[0]=x_values, ---[1]=y_values, with filename, figtitle, labels and colormap cm.

	Parameters
	---------
		par: parameters. Take values of biasenergies used in calculation to plot against.
		independent_vars : 	list of two sets of independent variable values, to be plotted on the x and y axis.
		cm : 	colormap. E.g. "seismic" = red and blue, "PuBu" = pink/white to blue.

		**kwargs:	figsize_inches
					vmin
					vmax
	"""
	fig,ax = plt.subplots()
	X,Y = np.meshgrid(x,y)
	dependent_var = np.transpose(dependent_var)

	simplecontour = ax.contourf(X,Y,dependent_var)
	if "vmin_max" in kwargs:
		pcm = ax.pcolormesh(X,Y,dependent_var,cmap = cm,vmin=kwargs["vmin_max"][0],vmax=kwargs["vmin_max"][1])
	else:
		pcm = ax.pcolormesh(X,Y,dependent_var,cmap = cm)
	fig.colorbar(pcm)

	ax.set_title(figtitle,fontsize=16)
	ax.set_xlabel(xlabel,fontsize=16)
	ax.set_ylabel(ylabel,fontsize=16)

	if "figsize_inches" in kwargs:
		fig.set_size_inches(kwargs["figsize_inches"][0],kwargs["figsize_inches"][1])
	else:
		fig.set_size_inches(4,3)
	plt.tight_layout()

	if "add_vlines" in kwargs:
		for x_ in kwargs["add_vlines"]:
			plt.axvline(x=x_)


	plt.savefig(filename)	
	print("%s: Saved figure"%misc.round_time(datetime.datetime.now(),round_to=60), filename)	
Beispiel #12
0
def calc_u2mv2_mu_basisredef(evec_n, mu_values, Ny, filename):
    """

	Redef basis of calc_u2mv2_mu
	"""

    print(misc.round_time(datetime.datetime.now(), round_to=60),
          ": in calc_u2mv2_mu_basisredef")

    uu = np.zeros((len(mu_values), Ny), dtype=np.complex_)
    mvu = np.zeros((len(mu_values), Ny), dtype=np.complex_)
    ud = np.zeros((len(mu_values), Ny), dtype=np.complex_)
    vd = np.zeros((len(mu_values), Ny), dtype=np.complex_)

    u2_mu_site = np.zeros((len(mu_values), Ny))
    v2_mu_site = np.zeros((len(mu_values), Ny))

    for i in range(len(mu_values)):
        print(" - mu_value number ", i)
        for j in range(Ny):

            [uu[i, j], mvu[i, j], ud[i, j],
             vd[i, j]] = evec_n[i, 4 * j:4 * (j + 1)]

            u2_mu_site[i, j] = np.abs(uu[i, j])**2 + np.abs(ud[i, j])**2
            v2_mu_site[i, j] = np.abs(mvu[i, j])**2 + np.abs(vd[i, j])**2

    u2_mu = np.sum(u2_mu_site, axis=1)
    v2_mu = np.sum(v2_mu_site, axis=1)

    u2mv2_mu = u2_mu - v2_mu

    np.save(filename, u2mv2_mu)
    print(" - Saved datalog file: ", filename)

    return u2mv2_mu, u2_mu, v2_mu

    E1_mu, Em1_mu, evec1_mu, evecm1_mu = calc.calc_E1_Em1_from_E0_E0prime_mu(
        E0=par.energies_mu[:, n[0]], E0prime=par.energies_mu[:, n[1]])
Beispiel #13
0
def make_1D_NLeft_1D_S_Heff_No_NRight(p,ppar):
	""" 
	Make N-S(Heff) function for calibrating against

	"""
	print("%s: in make_1D_NLeft_1D_S_Heff_No_NRight()" %str(misc.round_time(datetime.datetime.now(),round_to=60)))

	sys = kwant.Builder()

	sys[(lat(x,y) for x in p.left for y in range(p.Ny))] = onsite_1D
	sys[kwant.builder.HoppingKind((0,1),lat)] = hoppingy

	if p.pincher == True:
		print(" - Adding pincher")
		"""Attaching extra sites with hoppings p.tL/R:"""
		sys[lat(p.left[0],p.Ny-1)] = onsite_1D_pincher
		sys[lat(p.left[0],0)] = onsite_1D_pincher

	"""Attaching leads to this "L" region:"""
	lead = make_lead_onesite_wide_1D(p)
	sys.attach_lead(lead)

	return sys
Beispiel #14
0
def calc_E1_Em1_from_E0_E0prime_var(E0,
                                    E0prime,
                                    evec0,
                                    evec0prime,
                                    var_values,
                                    N,
                                    filename,
                                    savefiles,
                                    tol=2):
    """
	Calculate electron/hole energies E1 and Em1 from cutting and pasting the energies E0 and E0prime whose values are in
			E0 >= 0, E0prime <= 0 for all values of the variable
	and whose period is half that of E1 and Em1. E1 and Em1 have max/min values
			max(E1 and Em1) = max(E0), min(E1 and Em1) = min(E0prime).

	Calculates the derivtive of the energies. When the derivative changes, that's where the cut needs to be done!

	Parameters
	----------
	E0 : 			lowest energy for the solved system, which in the topological phase corresponds to the positive values of the lowest energy pair of modes.

	E0prime : 		lowest absolute energy of the solved system, whose values are negative.

	evec0 : 		eigenvector with the energy E0.
					 - indexing : 	evec0[var_res,N]
					 				where N = 2*2*Ny in spinful system with p-h dofs and is 1D with length Ny. var_res is the number of points in the variable one is considering the energies/evecs a function of, which could be e.g. mu_res.

	evec0prime : 	eigenvector with the energy E0prime.
					 - indexing : 	same as with evec0.

	splineE0 : 					Fitted 'function' of E0. Used to find the derivative of E0.

	splineE0_derivative : 		derivative of fitted 'function' splineE0. Used to find the indices where the sign of the derivative changes, which corresponds to the indices where the energies E1 and Em1 cross.

	splineE0prime : 			equivalently to above.

	splineE0prime_derivative : 	equivalently to above.

	tol : 						tolerance in indices for which elements in sign_change_indices_E0max and sign_change_indices are considered to be the same. Necessary because they are calculated in different manners, and it thus turns out that when they are supposed to be the same, they vary slightly from each other. Example: for mu_res = 1500, tol=1 would do the job of excluding the points in sign_change_indices_E0max from sign_change_indices. Default value of tol is set to tol = 2.

	sign_change_indices : 		indices in var (e.g. mu_values) where the derivative of the energy E0 (or equivalently E0prime) changes.



	sign_change_indices_actual_E0max_withintol : 	Indices of sign_change_indices corresponding to the indices in sign_change_indices_E0max. They are calculated by cheching if the indices in sign_change_indices_E0max are inside sign_change_indices_actual_E0max_withintol within the tolerance set by tol.

	m : 											indexes in var (e.g. mu_values) for which the elements of sign_change_indices that are not equal to the elements of sign_change_indices_actual_E0max_withintol.

	Notes
	-----
	 - The sign of the derivative of the energy changes also in between the desired points where it changes. So we need to identify which points are the desired points and which to throw away. We can identify that the points we want are the ones where the energy is approximately zero, while the points to throw away are the ones where the absolute value of the energy is at its maxima.
	 - All elements of the energies E1 and Em1 that are less than m[0] and larger than m[-1] need to be set equal to the appropriate E0 and E0prime. The convention used here is that
	 			 - for indices < m[0] : 	E1 = E0prime, Em1 = E0.
	 Depending on whether len(m) is even or odd, we get that E0 and Em1 should be for indices > m[-1]:
	 			 - for indices > m[-1]:
		 			 - for len(m) even : 	E1 = E0	
		 			 - for len(m) odd : 	E1 = E0prime

	"""

    from scipy.interpolate import UnivariateSpline
    import numpy as np
    import scipy.signal
    from My_Costum_Packages_newest import misc
    import datetime

    print("%s: In calc.calc_E1_Em1_from_E0_E0prime_var()" %
          misc.round_time(datetime.datetime.now(), round_to=60))

    splineE0 = UnivariateSpline(var_values, E0, s=0)
    splineE0prime = UnivariateSpline(var_values, E0prime, s=0)

    splineE0_derivative = splineE0.derivative(n=1)
    splineE0prime_derivative = splineE0prime.derivative(n=1)

    sign_change_indices = []
    sign_change_indices_E0max = scipy.signal.argrelmax(np.abs(E0))
    sign_change_indices_E0max = np.array(sign_change_indices_E0max[0])

    for i in range(len(splineE0_derivative(var_values)) - 1):
        if np.sign(splineE0_derivative(var_values)[i]) != np.sign(
                splineE0_derivative(var_values)[i + 1]):
            sign_change_indices.append(i + 1)
    """Getting the actual indices in terms of the indices of sign_change_indices that correspond to the indices in sign_change_indices_E0max:"""
    sign_change_indices_actual_E0max_withintol = []

    for maximum in sign_change_indices_E0max:
        for delta in range(tol):
            # print(" - delta, ", delta)
            if maximum + delta in sign_change_indices:
                # print("hello", maximum)
                sign_change_indices_actual_E0max_withintol.append(maximum +
                                                                  delta)
            elif maximum - delta in sign_change_indices:
                # print("hello", maximum)
                sign_change_indices_actual_E0max_withintol.append(maximum -
                                                                  delta)

    mask = np.isin(sign_change_indices,
                   sign_change_indices_actual_E0max_withintol)

    m = []
    for mask_i, element in zip(mask, sign_change_indices):
        # if True, meaning different elements
        if mask_i == False:
            m.append(element)

    E1_cut = np.zeros(len(var_values))
    Em1_cut = np.zeros(len(var_values))

    evec1_cut = np.zeros((len(var_values), N), dtype=np.complex_)
    evecm1_cut = np.zeros((len(var_values), N), dtype=np.complex_)

    # if len(m) > 1:
    # for j in range(len(m)):
    # 	print("j is",j)
    # 	if j % 2 == 0: 	# if j is an even number
    # 		E1_cut[m[j]:m[j+1]] = E0[m[j]:m[j+1]]
    # 		Em1_cut[m[j]:m[j+1]] = E0prime[m[j]:m[j+1]]

    # 		evec1_cut[m[j]:m[j+1],:] = evec0[m[j]:m[j+1],:]
    # 		evecm1_cut[m[j]:m[j+1],:] = evec0prime[m[j]:m[j+1],:]

    # 	if j % 2 != 0:	# if j is an odd number
    # 		E1_cut[m[j]:m[j+1]] = E0prime[m[j]:m[j+1]]
    # 		Em1_cut[m[j]:m[j+1]] = E0[m[j]:m[j+1]]

    # 		evec1_cut[m[j]:m[j+1],:] = evec0prime[m[j]:m[j+1],:]
    # 		evecm1_cut[m[j]:m[j+1],:] = evec0[m[j]:m[j+1],:]
    """
	Assigning values for 
	 - indices < m[0] : 			E1_cut = E0, Em1_cut = E0prime 	| len(m) is odd
	 								opposite 						| len(m) is even
	 - odd/even indices > m[-1] : 	E1_cut = E0prime, Em1_cut = E0 	| len(m) is odd
	 								opposite 						| len(m) is even
	"""
    print(" - m is", m)
    if len(
            m
    ) % 2 != 0:  # odd means first and last assignment of E1_cut and Em1_cut is going to be different
        print(np.shape(E1_cut), np.shape(E0prime), np.shape(evec0prime))
        E1_cut[0:m[0]] = E0prime[0:m[0]]
        Em1_cut[0:m[0]] = E0[0:m[0]]

        evec1_cut[0:m[0]] = evec0prime[0:m[0], :]
        evecm1_cut[0:m[0]] = evec0[0:m[0], :]

        E1_cut[m[-1]:] = E0[m[-1]:]
        Em1_cut[m[-1]:] = E0prime[m[-1]:]

        evec1_cut[m[-1]:] = evec0[m[-1]:, :]
        evecm1_cut[m[-1]:] = evec0prime[m[-1]:, :]
        if len(m) > 1:
            for j in range(0, len(m) - 1):
                print(" - j is", j)
                if j % 2 != 0:  # if after an odd number of crossings
                    E1_cut[m[j]:m[j + 1]] = E0prime[m[j]:m[j + 1]]
                    Em1_cut[m[j]:m[j + 1]] = E0[m[j]:m[j + 1]]

                    evec1_cut[m[j]:m[j + 1], :] = evec0prime[m[j]:m[j + 1], :]
                    evecm1_cut[m[j]:m[j + 1], :] = evec0[m[j]:m[j + 1], :]
                else:  # if after an even number of crossings
                    E1_cut[m[j]:m[j + 1]] = E0[m[j]:m[j + 1]]
                    Em1_cut[m[j]:m[j + 1]] = E0prime[m[j]:m[j + 1]]

                    evec1_cut[m[j]:m[j + 1], :] = evec0[m[j]:m[j + 1], :]
                    evecm1_cut[m[j]:m[j + 1], :] = evec0prime[m[j]:m[j + 1], :]
    else:  # even menas first and last assignment of E1_cut and Em1_cut is going to be the same
        if len(m) > 1:
            E1_cut[0:m[0]] = E0prime[0:m[0]]
            Em1_cut[0:m[0]] = E0[0:m[0]]

            evec1_cut[0:m[0]] = evec0prime[0:m[0], :]
            evecm1_cut[0:m[0]] = evec0[0:m[0], :]

            E1_cut[m[-1]:] = E0prime[m[-1]:]
            Em1_cut[m[-1]:] = E0[m[-1]:]

            evec1_cut[m[-1]:] = evec0prime[m[-1]:, :]
            evecm1_cut[m[-1]:] = evec0[m[-1]:, :]

            for j in range(0, len(m) - 1):
                if j % 2 != 0:  # if after an odd number of crossings
                    E1_cut[m[j]:m[j + 1]] = E0prime[m[j]:m[j + 1]]
                    Em1_cut[m[j]:m[j + 1]] = E0[m[j]:m[j + 1]]

                    evec1_cut[m[j]:m[j + 1], :] = evec0prime[m[j]:m[j + 1], :]
                    evecm1_cut[m[j]:m[j + 1], :] = evec0[m[j]:m[j + 1], :]
                else:  # if after an even number of crossings
                    E1_cut[m[j]:m[j + 1]] = E0[m[j]:m[j + 1]]
                    Em1_cut[m[j]:m[j + 1]] = E0prime[m[j]:m[j + 1]]

                    evec1_cut[m[j]:m[j + 1], :] = evec0[m[j]:m[j + 1], :]
                    evecm1_cut[m[j]:m[j + 1], :] = evec0prime[m[j]:m[j + 1], :]

        else:
            E1_cut = E0prime
            Em1_cut = E0

            evec1_cut = evec0prime
            evecm1_cut = evec0
    # elif len(m) == 1:
    # 	print("length of E0prime:", len(E0prime))

    # 	E1_cut[0:m[0]] = E0prime[0:m[0]]
    # 	Em1_cut[0:m[0]] = E0[0:m[0]]

    # 	evec1_cut[0:m[0]] = evec0prime[0:m[0],:]
    # 	evecm1_cut[0:m[0]] = evec0[0:m[0],:]

    # 	E1_cut[m[0]:] = E0prime[m[0]:]
    # 	Em1_cut[m[0]:] = E0[m[0]:]

    # 	evec1_cut[m[0]:] = evec0prime[m[0]:,:]
    # 	evecm1_cut[m[0]:] = evec0[m[0]:,:]

    if savefiles == True:
        np.save("E1_" + filename + ".npy", E1_cut)
        np.save("Em1_" + filename + ".npy", Em1_cut)
        np.save("evec1_" + filename + ".npy", evec1_cut)
        np.save("evecm1_" + filename + ".npy", evecm1_cut)

    return E1_cut, Em1_cut, evec1_cut, evecm1_cut
Beispiel #15
0
def calc_E1_Em1_from_E0_E0prime_mu(E0,
                                   E0prime,
                                   evec0,
                                   evec0prime,
                                   mu_values,
                                   N,
                                   tol=2):
    """
	######## DISCLAIMER: ###############

	THIS IS AN OLD FUNCTION. YOU MAY USE AND UPDATE THE FUNCTION alc_E1_Em1_from_E0_E0prime_var INSTEAD.

	####################################

	Calculate electron/hole energies E1 and Em1 from cutting and pasting the energies E0 and E0prime whose values are in
			E0 >= 0, E0prime <= 0
	and whose period is half that of E1 and Em1. E1 and Em1 have max/min values
			max(E1 and Em1) = max(E0), min(E1 and Em1) = min(E0prime).

	This function calculates the derivtive of the energies. When the derivative changes, that's where the cut needs to be done!

	Parameters
	----------
	E0 : 			lowest absolute energy for the solved system, which corresponds to the positive values of the lowest energy pair of modes.

	E0prime : 		lowest absolute energy of the solved system, whose values are negative.

	evec0 : 		eigenvector with the energy E0.
					 - indexing : 	evec0[var_res,N]
					 				where N = 2*2*Ny in spinful system with p-h dofs and is 1D with length Ny. var_res is the number of points in the variable one is considering the energies/evecs a function of, which could be e.g. mu_res or Ez_res.

	evec0prime : 	eigenvector with the energy E0prime.
					 - indexing : 	same as with evec0.

	splineE0 : 					Fitted 'function' of E0. Used to find the derivative of E0.

	splineE0_derivative : 		derivative of fitted 'function' splineE0. Used to find the indices where the sign of the derivative changes, which corresponds to the indices where the energies E1 and Em1 cross as well as the indices where E0 and E0prime have maxima/minima.

	splineE0prime : 			equivalently to above.

	splineE0prime_derivative : 	equivalently to above.

	tol : 						tolerance in indices for which elements in sign_change_indices_E0max and sign_change_indices are considered to be the same. Necessary because they are calculated in different manners, and it thus turns out that when they are supposed to be the same, they vary slightly from each other. Example: for mu_res = 1500, tol=1 would do the job of excluding the points in sign_change_indices_E0max from sign_change_indices. Default value of tol is set to tol = 2.

	sign_change_indices : 		indices in variable (e.g. mu_values) where the derivative of the energy E0 (or equivalently E0prime) changes.

	sign_change_indices_actual_E0max_withintol : 	Indices of sign_change_indices corresponding to the indices in sign_change_indices_E0max. They are calculated by cheching if the indices in sign_change_indices_E0max are inside sign_change_indices_actual_E0max_withintol within the tolerance set by tol.

	m : 											indexes in variable (e.g. mu_values) for which the elements of sign_change_indices that are not equal to the elements of sign_change_indices_actual_E0max_withintol. These are the points where E0and E0prime cross, which is where the cutting and pasting procedure is to be performed.

	Notes
	-----
	 - The sign of the derivative of the energy changes also in between the desired points where it changes. So we need to identify which points are the desired points and which to throw away. We can identify that the points we want are the ones where the energy is approximately zero, while the points to throw away are the ones where the absolute value of the energy is at its maxima.
	 - All elements of the energies E1 and Em1 that are less than m[0] and larger than m[-1] need to be set equal to the appropriate E0 and E0prime. The convention used here is that
	 			 - for indices < m[0] : 	E1 = E0, Em1 = E0prime.
	 Depending on whether len(m) is even or odd, we get that E0 and Em1 should be for indices > m[-1]:
	 			 - indices < m[0] : 			E1_cut = E0prime, Em1_cut = E0.
				 - odd/even indices > m[-1] : 	opposite
	"""

    from scipy.interpolate import UnivariateSpline
    import numpy as np
    import scipy.signal
    from My_Costum_Packages_newest import misc
    import datetime

    print("%s: In calc.calc_E1_Em1_from_E0_E0prime_mu()" %
          misc.round_time(datetime.datetime.now(), round_to=60))

    splineE0 = UnivariateSpline(mu_values, E0, s=0)
    splineE0prime = UnivariateSpline(mu_values, E0prime, s=0)

    splineE0_derivative = splineE0.derivative(n=1)
    splineE0prime_derivative = splineE0prime.derivative(n=1)

    sign_change_indices = []
    sign_change_indices_E0max = scipy.signal.argrelmax(np.abs(E0))
    sign_change_indices_E0max = np.array(sign_change_indices_E0max[0])

    for i in range(len(splineE0_derivative(mu_values)) - 1):
        if np.sign(splineE0_derivative(mu_values)[i]) != np.sign(
                splineE0_derivative(mu_values)[i + 1]):
            sign_change_indices.append(i + 1)
    """Getting the actual indices in terms of the indices of sign_change_indices that correspond to the indices in sign_change_indices_E0max:"""
    sign_change_indices_actual_E0max_withintol = []

    for maximum in sign_change_indices_E0max:
        for delta in range(tol):
            # print(" - delta, ", delta)
            if maximum + delta in sign_change_indices:
                # print("hello", maximum)
                sign_change_indices_actual_E0max_withintol.append(maximum +
                                                                  delta)
            elif maximum - delta in sign_change_indices:
                # print("hello", maximum)
                sign_change_indices_actual_E0max_withintol.append(maximum -
                                                                  delta)

    mask = np.isin(sign_change_indices,
                   sign_change_indices_actual_E0max_withintol)

    m = []
    for mask_i, element in zip(mask, sign_change_indices):
        # if True, meaning different elements
        if mask_i == False:
            m.append(element)
    print("m is: ", m)

    if m == []:
        """ If no points where sign of energy changes, then keep the energies as they are """
        E1_cut = E0prime
        Em1_cut = E0
        evec1_cut = evec0prime
        evecm1_cut = evec0

        return E1_cut, Em1_cut, evec1_cut, evecm1_cut

    else:
        E1_cut = np.zeros(len(mu_values))
        Em1_cut = np.zeros(len(mu_values))

        evec1_cut = np.zeros((len(mu_values), N), dtype=np.complex_)
        evecm1_cut = np.zeros((len(mu_values), N), dtype=np.complex_)

        for j in range(len(m)):
            if j % 2 == 0:  # if j is an even number
                E1_cut[m[j]:m[j + 1]] = E0[m[j]:m[j + 1]]
                Em1_cut[m[j]:m[j + 1]] = E0prime[m[j]:m[j + 1]]

                evec1_cut[m[j]:m[j + 1], :] = evec0[m[j]:m[j + 1], :]
                evecm1_cut[m[j]:m[j + 1], :] = evec0prime[m[j]:m[j + 1], :]

            if j % 2 != 0:  # if j is an odd number
                E1_cut[m[j]:m[j + 1]] = E0prime[m[j]:m[j + 1]]
                Em1_cut[m[j]:m[j + 1]] = E0[m[j]:m[j + 1]]

                evec1_cut[m[j]:m[j + 1], :] = evec0prime[m[j]:m[j + 1], :]
                evecm1_cut[m[j]:m[j + 1], :] = evec0[m[j]:m[j + 1], :]
        """
		Assigning values for 
		 - indices < m[0] : 			E1_cut = E0, Em1_cut = E0prime.
		 - odd/even indices > m[-1] : 	

		"""

        E1_cut[0:m[0]] = E0[0:m[0]]
        Em1_cut[0:m[0]] = E0prime[0:m[0]]

        evec1_cut[0:m[0]] = evec0[0:m[0], :]
        evecm1_cut[0:m[0]] = evec0prime[0:m[0], :]

        E1_cut[m[-1]:] = E0[m[-1]:]
        Em1_cut[m[-1]:] = E0prime[m[-1]:]

        evec1_cut[m[-1]:] = evec0[m[-1]:, :]
        evecm1_cut[m[-1]:] = evec0prime[m[-1]:, :]

        return E1_cut, Em1_cut, evec1_cut, evecm1_cut
Beispiel #16
0
def calc_u2mv2_var(evec_n, var_values, Ny, filename, savefiles, **kwargs):
    """
	Calculates u and v (Bogoliubon amplitudes) from the eigenvectors, which are in themselves functions of mu/Ez and are given for every site {0,...,Ny} in the 1D system of length Ny.
	 - Definition:
					u(i)^2 = |u_up(i)|^2 + |u_down(i)|^2
					v(i)^2 = |v_up(i)|^2 + |v_down(i)|^2
					where i = site number, up/down = spins and the eigenvectors in the sigma*tau (spin*particle/hole) basis are {|psi(i)>}, given by
					|psi(i)> = (u_up(i), u_down(i), v_down(i), -v_down(i)).
	
	Parameters
	----------
	evec_n : 		{|psi(site i, mu j)>|_n} with shape (par.mu_res,par.Ny*2*2)

	**kwargs : 		

		write_u_v_var_LR : 	Any value, e.g. True or an int.
							If given, then u and v is also saved, as a function of the variable var, but summed over sites. Also, u and v values are returned for left and right leads. These are defined as the u and v-values at the first (site 0) and last lattice site (site Ny) when e.g. 1D.!!!

	Variables
	---------
	uu, ud, vd, mvu : 	u_up, u_down, v_down, -v_up. Shape: (par.mu_res,par.Ny), not with par.Ny*2*2, since up/down and u/v already specifies the spin/p-h DOFs.
	
	
	Returns
	-------
	if no kwargs given : 	u2mv2_var, u2_var, v2_var
	if one kwarg given : 	u2mv2_var, u2_var, v2_var, u_var, v_var

	"""

    from My_Costum_Packages_newest import misc
    import datetime
    import numpy as np

    print(misc.round_time(datetime.datetime.now(), round_to=60),
          ": in calc_u2mv2_var")

    uu = np.zeros((len(var_values), Ny), dtype=np.complex_)
    ud = np.zeros((len(var_values), Ny), dtype=np.complex_)
    mvd = np.zeros((len(var_values), Ny), dtype=np.complex_)
    vu = np.zeros((len(var_values), Ny), dtype=np.complex_)

    u2_var_site = np.zeros((len(var_values), Ny))  #,dtype=np.complex_)
    v2_var_site = np.zeros((len(var_values), Ny))  #,dtype=np.complex_)

    if len(kwargs) == 1:
        u_var_site = np.zeros((len(var_values), Ny), dtype=np.complex_)
        v_var_site = np.zeros((len(var_values), Ny), dtype=np.complex_)

        for i in range(len(var_values)):
            print(" - var_value number ", i)
            for j in range(Ny):

                [uu[i, j], mvd[i, j], ud[i, j],
                 vu[i, j]] = evec_n[i, 4 * j:4 * (j + 1)]

                u2_var_site[i, j] = np.abs(uu[i, j])**2 + np.abs(ud[i, j])**2
                v2_var_site[i, j] = np.abs(mvd[i, j])**2 + np.abs(vu[i, j])**2

                u_var_site[i,
                           j] = uu[i, j] + ud[i, j]  # ??? correct def right?
                v_var_site[i, j] = mvd[i, j] + vu[i, j]  # ??? same

    elif len(kwargs) == 0:
        for i in range(len(var_values)):
            print(" - var_value number ", i)
            for j in range(Ny):

                [uu[i, j], mvd[i, j], ud[i, j],
                 vu[i, j]] = evec_n[i, 4 * j:4 * (j + 1)]

                u2_var_site[i, j] = np.abs(uu[i, j])**2 + np.abs(ud[i, j])**2
                v2_var_site[i, j] = np.abs(mvd[i, j])**2 + np.abs(vu[i, j])**2

    else:
        raise ValueError(
            "kwargs in calc.calc_u2mv2_var is too long or type not understood."
        )

    u2_var = np.sum(u2_var_site, axis=1)
    v2_var = np.sum(v2_var_site, axis=1)

    if len(kwargs) == 1:
        u_var = np.sum(u_var_site, axis=1)
        v_var = np.sum(v_var_site, axis=1)

    u2mv2_var = u2_var - v2_var

    if savefiles == True:
        np.save("u2mv2_" + filename, u2mv2_var)
        np.save("u2_" + filename, u2_var)
        np.save("v2_" + filename, v2_var)

        print(" - Saved datalog files: ", "u2mv2_" + filename, "\n",
              "u2_" + filename, "\n", "v2_" + filename)

    if savefiles == True & len(kwargs) == 1:
        np.save("u_" + filename, u_var)
        np.save("v_" + filename, v_var)

        print(" - Saved datalog files: ", "u2mv2_" + filename, "\n",
              "u2_" + filename, "\n", "v2_" + filename, "\n", "u_" + filename,
              "\n", "v_" + filename)

    if len(kwargs) == 0:
        return u2mv2_var, u2_var, v2_var

    elif len(kwargs) == 1:
        return u2mv2_var, u2_var, v2_var, u_var, v_var, u_var_site[:,
                                                                   0], u_var_site[:,
                                                                                  Ny
                                                                                  -
                                                                                  1], v_var_site[:,
                                                                                                 0], v_var_site[:,
                                                                                                                Ny
                                                                                                                -
                                                                                                                1]
Beispiel #17
0
def make_1D_system(p,ppar):

	"""Function building superconductor for parameters in SimpleNamespace object p.

	Parameters
	----------
	p.pincher : 	If True, make 1D system with an extra site attached with a different tunneling constant, tL and tR on the left and right, respectively. This models the pincher which is affecting this one additional site's hopping amplitude tL/R at the edge of the system.
	p.left : 	Left strip is implemented as the SC 1D system. So p.left = [0], while p.middle and p.right should be empty ([]) when making the 1D system using this function.

	Functions called
	----------------
	onsite_1D : 	onsite different now for 1D system. Not input phase/gamma explicitly such that may specify variables such as Ez at later point in code after finalizing. I think that Kwant has this particular syntax in sys[lat..]=<function_name> without having to input arguments in the function.

	Notes
	-----
	??? (see below)
	"""

	print("%s: in make_1D_system()" %str(misc.round_time(datetime.datetime.now(),round_to=60)))
	import kwant

	sys = kwant.Builder()

	#### v15 and (in written notes) v15_2: only hopping
	#### v15_1: hopping AND onsite
	#### v15_2_1: only hopping AND tp<0
	#### v16: pincher as (positive) onsite

	########### ONSITE ONLY: ############
	if ppar.pinchertype == "onsite":
		sys[(lat(x,y) for x in p.left for y in range(p.Ny))] = onsite_1D
		sys[kwant.builder.HoppingKind((0,1),lat)] = hoppingy

		if p.pincher == True:
			print(" - Adding pincher")

			########### ONSITE ONLY: ################
			# sys[(lat_pincher(x,y) for x in p.left for y in [0,p.Ny-1])] = onsite_1D_pincher # <-- proves problematic / does not give same result as with same lat for pincher. Maybe this is root of problem implementing tp as hopping only? [??? v16]
			sys[lat(p.left[0],p.Ny-1)] = onsite_1D_pincher
			sys[lat(p.left[0],0)] = onsite_1D_pincher
			# sys[(lat(x,y) for x in p.left[0] for y in [0,p.Ny-1])] = onsite_1D_pincher


	elif ppar.pinchertype == "hopping":
		####### HOPPING ONLY: ####### 
		if p.pincher == True:
			print(" - Adding pincher")

			lat_pincher = kwant.lattice.square()

			### HOPPING ONLY / HOPPING AND ONSITE : makes two last onsites on each edge of wire, then hopping between the (nearest) neighbors. ###
			sys[(lat_pincher(x,y) for x in p.left for y in [0,1,p.Ny-2,p.Ny-1])] = onsite_1D_pincher

			sys[lat_pincher.neighbors()] = hopping_1D_pincher		

		# i) adds onsite and hopping until next-to edge-sites in wire:
		sys[(lat(x,y) for x in p.left for y in range(1,p.Ny-1))] = onsite_1D
		sys[lat.neighbors()] = hoppingy
		# ii) adds onsite only on edge sites in wire:
		sys[(lat(x,y) for x in p.left for y in [0,p.Ny-1])] = onsite_1D


	elif ppar.pinchertype == "hopping and onsite":

		if p.pincher == True:
			print(" - Adding pincher")

			lat_pincher = kwant.lattice.square()

			### HOPPING ONLY / HOPPING AND ONSITE : makes two last onsites on each edge of wire, then hopping between the (nearest) neighbors. ###
			sys[(lat_pincher(x,y) for x in p.left for y in [0,1,p.Ny-2,p.Ny-1])] = onsite_1D_pincher

			sys[lat_pincher.neighbors()] = hopping_1D_pincher	
	
		sys[(lat(x,y) for x in p.left[0] for y in range(1,p.Ny-1))] = onsite_1D 
		sys[lat.neighbors()] = hoppingy
	

	"""Attaching leads to this "L" region:"""
	lead = make_lead_onesite_wide_1D(p)

	sys.attach_lead(lead)
	sys.attach_lead(lead.reversed())

	""" 
	Adding SC lead last. In that way, the indexing of the smatrix will work as before when wanting to access the other leads. In order to access from the SC lead, acces the 2nd lead index in e.g. the smatrix.
	"""
	if ppar.SClead == True:
		SClead = make_SC_lead_Ny_wide(p)
		sys.attach_lead(SClead)
		print(" - Attached SC lead")

	return sys
Beispiel #18
0
def read_or_write_G_11_12_S_A_var(sys, par, ppar, generating_G_11_12_S_A_var,
                                  biasenergies_asymm, var_name, filename_11,
                                  filename_12, filename_11_S, filename_11_A,
                                  filename_12_S, filename_12_A):
    """	Read or write conductances for a general variable named var_name.
		var_name: string of variable name. The variable has to be exactly the name of a parameter used when constructing the Hamiltonian in the Builder object sys.
		Suggested filename format: G_11_var_%g_%g_"%(par.mu_values[0],par.mu_values[-1]) + ppar.filename
	"""

    import time
    # from My_Costum_Packages import calc
    # import kwant

    print(
        "%s: in read_or_write_G_11_12_S_A_var, about to calc/get conductance(s) depending on %s"
        % (misc.round_time(datetime.datetime.now(), round_to=60), var_name))

    exec("par.var_values = par.%s_values" % var_name)

    G_11_var = np.zeros((len(par.var_values), len(par.biasenergies)))
    G_12_var = np.zeros((len(par.var_values), len(par.biasenergies)))
    G_11_A_var = np.zeros((len(par.var_values), len(par.biasenergies)))
    G_11_S_var = np.zeros((len(par.var_values), len(par.biasenergies)))
    G_12_A_var = np.zeros((len(par.var_values), len(par.biasenergies)))
    G_12_S_var = np.zeros((len(par.var_values), len(par.biasenergies)))

    if generating_G_11_12_S_A_var[0] == True:
        print(" - Generating conductances")
        if biasenergies_asymm == True:
            print(" - User input biasenergies_asymm=True.")
            if np.round(par.biasenergies[0],
                        10) == -np.round(par.biasenergies[-1], 10):
                print(" - Check: This is the case for first and last element.")
            else:
                Inputerror(
                    " - First element of p.biasenergies was not the negative of the last value. Ensure p.biasenergies has an odd number of entries and is antisymmetric about zero."
                )
        start_time = time.time()
        if ppar.oneNLead == True:  # one lead means G_12 not generated, so array axes won't match when executing the string in the 'else' block below.
            exec_str = "for par.%s, i in zip(par.%s_values,range(len(par.%s_values))):"%(var_name,var_name,var_name) + \
               "\n\telapsed_time = time.time() - start_time" + \
               "\n\t[G_11_var[i,:],G_12_var,G_11_S_var[i,:],G_11_A_var[i,:],G_12_S_var,G_12_A_var] = calc.calc_G_11_12_S_A(sys,par,ppar,i,var_name,elapsed_time,biasenergies_asymm=%s)" %(biasenergies_asymm)

        else:
            exec_str = "for par.%s, i in zip(par.%s_values,range(len(par.%s_values))):"%(var_name,var_name,var_name) + \
               "\n\telapsed_time = time.time() - start_time" + \
               "\n\t[G_11_var[i,:],G_12_var[i,:],G_11_S_var[i,:],G_11_A_var[i,:],G_12_S_var[i,:],G_12_A_var[i,:]] = calc.calc_G_11_12_S_A(sys,par,ppar,i,var_name,elapsed_time,biasenergies_asymm=%s)" %(biasenergies_asymm)

        exec(exec_str)
        np.save(filename_11, G_11_var)
        np.save(filename_12, G_12_var)
        np.save(filename_11_S, G_11_S_var)
        np.save(filename_11_A, G_11_A_var)
        np.save(filename_12_S, G_12_S_var)
        np.save(filename_12_A, G_12_A_var)

    if generating_G_11_12_S_A_var[0] == False:
        print(" - Reading conductances")
        if filename_12 == None:
            G_11_var = np.load(filename_11 + '.npy')
        else:
            G_11_var = np.load(filename_11 + '.npy')
            G_12_var = np.load(filename_12 + '.npy')
            G_11_S_var = np.load(filename_11_S + '.npy')
            G_11_A_var = np.load(filename_11_A + '.npy')
            G_12_S_var = np.load(filename_12_S + '.npy')
            G_12_A_var = np.load(filename_12_A + '.npy')

    return G_11_var, G_12_var, G_11_S_var, G_11_A_var, G_12_S_var, G_12_A_var
Beispiel #19
0
       # It is the index for which plot_G_1_G_2_varconst in main()
       # plots a line-cut of the conductance signal.
)

###
""" 
Setting const (simple namespace object containing the physical constants 
for the problem), par, and ppar :
"""
const, par, ppar = set_params.set_params(ppar)
# printing the tight-binding parameters and the theoretically predicted
# topological region for the corresponding infinite wire (see Oreg-Lutchyn model) :
#  - Number of sites in the x and y directions; lattice constant in the x and y directions :
print("Nx=%s, Ny=%.0f; ax=%g, ay=%g" % (par.Nx, par.Ny, par.ax, par.ay))
# The topological region when the chemical potential is the variable
# is for (chem. pot)^2 < (field)^2 - (induced superconducting gap)^2 :
print("Top region: mu<%s meV" % (np.sqrt(par.Ez_values[0]**2 - par.Gamma**2)))
# The starting time, used to time how long it takes to finish the main program :
t0 = time.time()
par.printtype = False  # Not printing blocks of the Hamiltonian (with Hprint.py) when False
"""Main program : """

main_En_gG12A(ppar)
"""After program : """

print("time taken to run main(): ", time.time() - t0)
ppar.counter += 1  # relevant parameter if Hprint.py is called (if par.printtype is not False).
print("Counter = ", ppar.counter)
print("Program finished %s" %
      str(misc.round_time(datetime.datetime.now(), round_to=60)))
Beispiel #20
0
def main_En_gG12A(ppar):
    """
	Main function that focuses on calculating, saving/reading and plotting the following quantities 
	for a system defined by the parameters in par and the program specific parameters from ppar:
	        - The par.k lowest |Energy eigenvalues| (absolute value) and the corresponding eigenvectors 
	                 of the system. 
	        - The eigenenergies E_1 and E_m1 of the ppar.n'th states (ppar.n has to be an iterable 
	                of the lowest pair of energies that are symmetric around the lambda(chemical potential or
	                magnetic field)-axis, such that the energies can be correctly defined.)
	        - The Cooper charge u^2-v^2 of the ppar.n'th states (ppar.n is an iterable of integers or 
	                may in general be changed after determining E_1 and E_m1 to specify only one integer).
	        - The non-local antisymmetric conductance G_12A of the tight-binding (TB) model from Kwant, 
	                for the parameters in par.
	        - The non-local antisymmetric conductance g_12A of the analytical model for the same parameters 
	                (parameters in par).	
	Notes
	-----
	 - Both par and ppar are SimpleNamespace objects.
	 - filename: REMEMBER to update the filename if new parameters are introduced or similarly. 
	                If not, writing files will overwrite old ones, and reading files, you might read the wrong file.
	"""
    """ Creating a filename based on the rules specified in the following function : """
    misc.set_filename_skeleton(par, ppar)
    """ 'Building' system, using the Kwant package : 
			The way the system is created is specified in ppar (see bottom of this file).
			These parameters in ppar are input in the make_system function. This function
			will make different types of systems depending on how ppar is specified. """
    sys = make.make_system(par, ppar)
    sys = sys.finalized()
    print("%s: sys finalized" %
          misc.round_time(datetime.datetime.now(), round_to=60))
    par.N = 4 * len(
        sys.sites)  # par.N is used in calc_E1_Em1_from_E0_E0prime_var
    # in order to set correct dimension of evec1_cut and evecm1_cut.
    # - Plotting system graph :
    import matplotlib.pylab as plt
    from kwant import wraparound
    ax = kwant.plot(sys,
                    site_symbol='o',
                    hop_color=['orange'],
                    site_edgecolor='red',
                    site_lw=0.01,
                    hop_lw=misc.hopping_lw)
    ax.savefig("N-SC_sys.pdf")
    """	Calculating and loading, as a function of mu or Ez
		 - eigenenergies
		 - eigenvectors (if ppar.Eonly = False)
	"""
    ppar.Eonly = False
    if ppar.generate_En_mu != None:  # reading or writing energy data vs. chem. pot.
        if ppar.generate_En_mu == False:
            read_or_write.read_or_write_energies_mu(sys, par, ppar)
        elif ppar.generate_En_mu == True:
            for ppar.generate_En_mu in [True, False]:
                # first time in loop: generating energy data
                # second time in loop: reading the before generated energy data
                read_or_write.read_or_write_energies_mu(sys, par, ppar)
            ppar.generate_En_mu = True
        if ppar.doubleres == False:
            # plots energies on one set of mu-axes
            # (there is no second sets of data for the energy.
            # The user may use ppar.doubleres is True, if wanting
            # a second set of data that is zoomed in on one area in
            # mu-space)
            plt.figure()
            plt.tight_layout()
            plt.plot(par.mu_values, par.energies_mu)
            plt.xlabel("$\mu\ [meV]$")
            plt.ylabel("$E_n\ [meV]$")
            plt.savefig("energies_mu_%s.pdf" % ppar.filename)
            plt.plot(par.mu_values_2, par.energies_mu)
        # Cuts and pastes from the energies that are only positive,
    # with those that are only negative, for the pair of two
    # lowest energy modes, which oscillate around zero bias :
        read_or_write.read_or_write_E1m1(par, ppar)
    if ppar.generate_En_Ez != None:  # reading or writing energy data vs. field
        if ppar.generate_En_Ez == False:
            read_or_write.read_or_write_energies_Ez(sys, par, ppar)
        elif ppar.generate_En_Ez == True:
            for ppar.generate_En_Ez in [True, False]:
                # first time in loop: generating data
                # second time in loop: reading already generated data.
                read_or_write.read_or_write_energies_Ez(sys, par, ppar)
        # cuts and pastes from the energies as above :
        read_or_write.read_or_write_E1m1(par, ppar)
    """	Calculating/loading 
		 - g0_12_a : 	analytical conductance at zero temperature (see arXiv:1905.05438),
		 				inserted for TB-model parameters.
		 - E1, Em1, evec1, evecm1 : 	two lowest eigenenergies, 'cut and pasted' such that
		 								they oscillate around zero bias in the topological region.
										The corresponding eigenvectors, similarly 'cut and pasted'.
		 - u, v, u^2 - v^2 : 			Coherence factors and BCS charge for the two lowest energy
		 								eigenvectors above.
	"""
    # misc.addto_filename(ppar,"n")		## Optional
    if ppar.var_name == "mu":
        read_or_write.read_or_write_g012a_mu(sys, par, ppar)
    elif ppar.var_name == "Ez":
        read_or_write.read_or_write_g012a_Ez(sys, par, ppar)
    read_or_write.read_or_write_u2mv2_u2_v2(par, ppar)
    if ppar.generate_E1m1_mu == True:
        ppar.generate_E1m1_mu = False
        read_or_write.read_or_write_u2mv2_u2_v2(par, ppar)
    """ Plotting eigenenergies if they are read or generated, for mu 
			(can do similarly for field variable, Ez) : """
    if ppar.generate_En_mu != None:
        if ppar.doubleres == True:
            plot.pplot_E_vs_var(
                par,
                ppar,
                par.energies_mu,
                par.mu_values_2,
                figfilename="energies_mu_%s" % ppar.filename,
                xlim=[par.mu_values_2[0], par.mu_values_2[-1]],
                ylim=[np.min(par.energies_mu),
                      np.max(par.energies_mu)],
                title="",
                xlabel="$\mu\ [meV]$",
                ylabel="$E_n\ [meV]$",
                add_zoom=True,
                ylim_zoom=[-par.bias_maxmin, par.bias_maxmin],
                yticks=[-par.bias_maxmin, 0, par.bias_maxmin],
                file_extension=".pdf",
                u2mv2=par.u2mv2_E1_mu,
                u2_mu=[],
                v2_mu=[])
    """	Computing/reading 
		 - G_ij(_S/A) : 	
		 	local/nonlocal conductances as functions of some variable for some set of parameters, versus biasenergy 
				- all these variables are specified in the par SimpleNamespace object 
				- how the user chooses to calculate and represent the data is specified 
				in the ppar Simple namespace object : """
    # Specifying the constant and the independent variable in this manner
    # is general (the user may for instance change between mu and field being constant/variable) :
    exec("par.%s = %g" % (ppar.par_const_name, ppar.par_const))
    # Generating or reading the local and nonlocal conductances :
    exec_str = \
     "par.G_11_%s,par.G_12_%s,par.G_11_S_%s,par.G_11_A_%s,par.G_12_S_%s,par.G_12_A_%s = "\
       % (ppar.var_name, ppar.var_name, ppar.var_name, ppar.var_name, ppar.var_name, ppar.var_name) +\
      "read_or_write.read_or_write_G_11_12_S_A_var(	\
				sys,par,ppar,								\
				ppar.generating_G_11_12_S_A_var,			\
				ppar.generating_G_11_12_S_A_var,			\
				ppar.var_name,								\
				ppar.filename_11,							\
				ppar.filename_12,							\
				ppar.filename_11_S,							\
				ppar.filename_11_A,							\
				ppar.filename_12_S,							\
				ppar.filename_12_A)"

    exec(exec_str)
    # Plotting contour plot of the differential conductances and
    # their symmetry-decomposed versions, in chem.pot.-bias space :
    if ppar.generating_G_11_12_S_A_var[1] == True:
        for G_, G_filename_, G_title_str in zip(\
			# nonlocal conductance, local conductance, local antisymmetric conductance, local symmetric conductance,
			# nonlocal antisymmetric conductance, nonlocal symmetric conductance, respectively.


         [par.G_12_mu, par.G_11_mu, par.G_11_A_mu, par.G_11_S_mu, par.G_12_A_mu, par.G_12_S_mu],\
          ["G_12_vsEbias1mu_", "G_11_vsEbias1mu_", "G_11_A_vsEbias1mu_", "G_11_S_vsEbias1mu_", "G_12_A_vsEbias1mu_", "G_12_S_vsEbias1mu_"],\
           ["$G_{LR}^0\ [e^2/h]$", "$G_{LL}^0\ [e^2/h]$", \
            "$G_{LL}^{0,asym}\ [e^2/h]$","$G_{LL}^{0,sym}\ [e^2/h]$",\
             "$G_{LR}^{0,asym}\ [e^2/h]$", "$G_{LR}^{0,sym}\ [e^2/h]$"]\
             ):
            plot.plot_G_ij_var(par,
                               scaling="SymLogNorm",
                               G_ij=G_,
                               var_values_str="mu_values",
                               filename=G_filename_ + ppar.filename,
                               figtitle=G_title_str,
                               xlabel="$\mu\ [meV]$",
                               ylabel="$V\ [meV]$",
                               cm="seismic",
                               colorbar_ticks=[-1e-1, -1e-2, 0, 1e-2, 1e-1])
    """ mu_cut_index is the index in the chemical potential variable (mu), 
	where the user chooses to make a line-cut. This cut is then plotted 
	as a function of the biasenergy in the following. """
    G_full_absmax = np.max(
        np.abs(par.G_11_mu[ppar.mu_cut_index, :],
               par.G_12_mu[ppar.mu_cut_index, :]))
    # Line-cut plot of the total local and total nonlocal conductances :
    plot.plot_G_1_G_2_varconst(
        par,
        G_1=par.G_11_mu,  # total local cond.
        G_2=par.G_12_S_mu + par.G_12_A_mu,  # total nonlocal cond.
        index_of_varconst=ppar.mu_cut_index,
        filename="G_11_12_mu_0_vs_bias" + ppar.filename,
        figtitle=" ",
        xlabel=r"$V\ [meV]$",  # bias axis
        ylabel=r"$G_{\alpha \beta}^0(V)\ [e^2/h]$",
        legend=[r"$G_{LL}^0$", r"$G_{LR}^0$"],
        ylim=[-1.1 * G_full_absmax, 1.1 * G_full_absmax],
        colors=['--k', "C0"])
    # Line-cut plot of the symmetry-decomposed differential conductances :
    plot.plot_G_1_G_2_varconst(par,
           G_1=par.G_12_S_mu, # nonlocal symmetric
           G_2=par.G_12_A_mu, # nonlocal antisymmetric
           G_3=par.G_11_S_mu, # local symmetric
           G_4=par.G_11_A_mu, # local antisymmetric
           index_of_varconst=ppar.mu_cut_index,
           filename="G_11_12_A_S_mu_0_vs_bias",
           figtitle=" ",
           xlabel=r"$V\ [meV]$",
           ylabel=r"$G_{\alpha \beta}^{0,sym/asym}(V)\ [e^2/h]$",
           legend=[r"$G_{LR}^{0,sym}$", r"$G_{LR}^{0,asym}$", \
              r"$G_{LL}^{0,sym}$", r"$G_{LL}^{0,asym}$"],
           ylim=[-1.1*G_full_absmax, 1.1*G_full_absmax],
           colors=['C1', "C0", "k", "gray"]
           )
Beispiel #21
0
def plot_G_ij_var(par,scaling,G_ij,var_values_str,filename,figtitle,xlabel,ylabel,cm,biasenergies_2=[],Ez_values_2=[],u2mv2_factor=1.,rasterized=True,cmap_logscale=0.001,colorbar_ticks=[],**kwargs):#var_values_=[], E1_var=[], Em1_var=[], u2mv2_E1_var=[], u2mv2_Em1_var=[]):

	"""
	Parameters
	---------
		par: 		parameters. Take values of biasenergies used in calculation to plot against.
	
		scaling: 	"SymLogNorm", "PowerNorm" or "Linear".
	
		G_ij : 		array.
					conductance of choice.

		var_values_str: 	string name of variable_values to be plotted against, other than the biasenergies

		filename : 			str.

		figtitle : 			str.
							Conductance plotted.

		xlabel, ylabel : 	str.
							
		cm : 				str.
							colormap. E.g. "seismic", "PuBu"

		u2mv2_factor : 		int, float.
							Factor to scale the u2mv2-values such that their max value equals the max value of the energy of the corresponding state.

		colorbar_ticks : 	list.
							Specifies the ticks to be displayed in the colorbar. Default value : []. If the list is empty (default), the ticks displayed are determined automatically by matplotlib.

		**kwargs : 	
			legend : 			list, tuple.

			var_values_ : 		array.
								Variable values for which energies and u2mv2 are plotted against. Distinct from "par."var_values_str, enabeling one to plot with e.g. a higher resolution in the energies/u2mv2 than in the conductances, which may prove useful because valculation time of the conductances is highly limited by the chosen resolution in var_values_str.

			E1_var : 			array, list, tuple.
								Energy E_1, the lowest absolute value of energy. Partner to E_m1. Function of var_values.

			Em1_var : 			same.

			u2mv2_E1_var : 		array, list, tuple.
								u^2-v^2 for the E1 energy branch.
			
			biasenergies_2 : 	array.
								Other biasenergies for which the conductance is plotted against. Used when conductance resolution in bias is different from that of the energies.

			Ez_values_2 : 		Similarly.

			E_u2mv2_1_only : 	Boolean. If given and True, then only plotting E1 and u2mv21, for visual clarity.


	Example usage
	-------------
	 -> Plotting only conductance:
	 	--------------------------
	 	######## vs Ez:
		plot.plot_G_ij_var(par,scaling="Linear",G_ij=par.G_11_Ez,var_values_str="Ez_values",filename="G_11_vsEbias1mu_seismic_"+par.filename,figtitle="$G_{11}\ [e^2/h]$",xlabel="$E_z\ [meV]$",ylabel="$E_{bias,1}$",cm="seismic")
		############# vs mu:
		# plot.plot_G_ij_var(par,scaling="Linear",G_ij=par.G_11_mu,var_values_str="mu_values",filename="G_11_vsEbias1mu_seismic_"+par.filename,figtitle="$G_{11}\ [e^2/h]$",xlabel="$\mu\ [meV]$",ylabel="$E_{bias,1}$",cm="seismic")
	
	 -> Plotting both conductance, E_(m)1 and u2mv2_(m)1, with resolution 1 for Energies and Cooper charges and resolution 2 for conductance: 
	 	----------------------------------
		legend = ["$E_1\, [meV]$","$E_{-1}\, [meV]$","$(u^2_1-v^2_1)$","$(u^2_{-1}-v^2_{-1})$"]

		if ppar.doubleres == True:
			plot.plot_G_ij_var(par,scaling="Linear",G_ij=par.G_12_A_Ez,var_values_str="Ez_values",filename="G_12_A_vsEbias1mu_seismic_"+ppar.filename,figtitle="$G_{12}^A\ [e^2/h]$",xlabel="$E_z\ [meV]$",ylabel="$E_{bias,1}$",cm="seismic",biasenergies_2=par.biasenergies_2,Ez_values_2=par.Ez_values_2,u2mv2_factor=np.abs(np.max(par.E1_Ez))/np.abs(np.max(par.u2mv2_E1_Ez)),var_values_=par.Ez_values, E1_var=par.E1_Ez, Em1_var=par.Em1_Ez, u2mv2_E1_var=par.u2mv2_E1_Ez, u2mv2_Em1_var=par.u2mv2_Em1_Ez,legend=legend)
		else:
			plot.plot_G_ij_var(par,scaling="Linear",G_ij=par.G_12_A_Ez,var_values_str="Ez_values",filename="G_12_A_vsEbias1mu_seismic_"+ppar.filename,figtitle="$G_{12}^A\ [e^2/h]$",xlabel="$E_z\ [meV]$",ylabel="$E_{bias,1}$",cm="seismic",u2mv2_factor=np.abs(np.max(par.E1_Ez))/np.abs(np.max(par.u2mv2_E1_Ez)),var_values_=par.Ez_values, E1_var=par.E1_Ez, Em1_var=par.Em1_Ez, u2mv2_E1_var=par.u2mv2_E1_Ez, u2mv2_Em1_var=par.u2mv2_Em1_Ez,legend=legend)

		import matplotlib.pylab as plt
		plt.show()


	 -> Plotting for analytical model:
	 	------------------------------
	 	legend = ["$E_1\, [meV]$","$E_{-1}\, [meV]$","$(u^2_1-v^2_1)$","$(u^2_{-1}-v^2_{-1})$"]

		plot.plot_G_ij_var(par,scaling="Linear",G_ij=np.transpose(g0_12_a),var_values_str="mu_values",filename="g012a_nus_vsEbimu_seis_"+ppar.filename,figtitle="$g^0_{12,a}\ [e^2/h]$",xlabel="$\mu\ [meV]$",ylabel="$E_{bias}$",cm="seismic",u2mv2_factor=np.abs(np.max(par.E1_mu))/np.abs(np.max(par.u2mv2_E1_mu)),var_values_=par.mu_values, E1_var=par.E1_mu, Em1_var=par.Em1_mu, u2mv2_E1_var=par.u2mv2_E1_mu, u2mv2_Em1_var=par.u2mv2_Em1_mu,legend=legend)

		import matplotlib.pylab as plt
		plt.show()
	"""


	fig,ax = plt.subplots()

	# fig.set_size_inches(4.5, 4.3)
	fig.set_size_inches(3.5, 3.1)
	ax.tick_params(labelsize=12)

	G_ij=np.transpose(G_ij)

	cm = plt.cm.get_cmap(cm)
	cm.set_under("w")

	G_abs_max = np.max(np.abs(G_ij))

	if len(biasenergies_2) == 0:
		exec("global simplecontour; simplecontour = ax.contourf(par." + var_values_str + ",par.biasenergies,G_ij)")

	elif len(biasenergies_2) != 0:
		exec("global simplecontour; simplecontour = ax.contourf(par." + var_values_str + "_2,par.biasenergies_2,G_ij)")
	
	if scaling == "SymLogNorm":
		# commented out 30082019 : \
		# linthresh=0.0001,linscale=0.0001,vmin=G_ij.min(),vmax=G_ij.max()\
		#<percentsign>s,vmin=G_ij.min(),vmax=G_ij.max(),	linscale=0.01\
		exec('global pcm; pcm = ax.pcolormesh(par.%s,par.biasenergies,G_ij,\
						norm = colors.SymLogNorm(\
						%s,vmin=-G_abs_max,vmax=G_abs_max,linscale=0.05\
						),cmap=cm, rasterized=True)' %(var_values_str,cmap_logscale))

	elif scaling == "PowerNorm":
		exec('global pcm; pcm = ax.pcolormesh(par.%s,par.biasenergies,G_ij,\
							norm = colors.PowerNorm(gamma=1./4.),cmap=cm)' %(var_values_str))

	elif scaling == "Linear":
		if len(biasenergies_2) == 0:
			exec('global pcm; pcm = ax.pcolormesh(par.%s,par.biasenergies,G_ij,cmap=cm,vmin=-1*G_abs_max, vmax=G_abs_max)' %(var_values_str))
		elif len(biasenergies_2) != 0:
			exec('global pcm; pcm = ax.pcolormesh(par.%s_2,par.biasenergies_2,G_ij,cmap=cm,vmin=-1*G_abs_max, vmax=G_abs_max)' %(var_values_str))

		plt.gcf().subplots_adjust(bottom=0.15)
		plt.gcf().subplots_adjust(left=0.2)

	if len(kwargs)!=0: #len(var_values_) != 0 & len(E1_var) != 0 & len(Em1_var) != 0 & len(u2mv2_E1_var) != 0 & len(u2mv2_Em1_var) != 0 :
		print(" - adding energies and u2mv2 to conductance plot.")
		
		my_blue = plt.cm.get_cmap("PuBu",lut=100)(85)
		my_red = plt.cm.get_cmap("OrRd")(200)

		if kwargs["E_u2mv2_1_only"]:		# only E1 and u2mv21, for visual clarity
			ax.plot(kwargs["var_values_2_"], kwargs["E1_var"], color=my_blue, linewidth=1.5, label="$E_1\, [meV]$")
			ax.plot(kwargs["var_values_2_"], kwargs["u2mv2_E1_var"]*u2mv2_factor, color="black", linewidth=1.5,label="$(u^2_1-v^2_1)$"+"$\cdot %g$"%u2mv2_factor)
		elif kwargs["E_u2mv2_sum_site0_siteNy_1_only"]:





			### !!! should be in the calc module!
			normalization_allsites = par.u2_mu_sites_1+par.v2_mu_sites_1
			u2mv2_allsites = (par.u2_mu_sites_1-par.v2_mu_sites_1)/normalization_allsites

			u2mv2_factor_allsites = np.amax(np.abs(par.E1_mu))/np.amax(np.abs(u2mv2_allsites),axis=0)

			u2mv2_toplot = u2mv2_allsites*u2mv2_factor #np.multiply(u2mv2_allsites,u2mv2_factor_allsites) 	# same shape as u2mv2_allsites
			########!!!##############################




			ax.plot(kwargs["var_values_2_"], kwargs["E1_var"], color=my_blue, linewidth=1.5, label="$E_1\, [meV]$")
			ax.plot(kwargs["var_values_2_"], kwargs["u2mv2_E1_var"]*u2mv2_factor, color="black", linewidth=1.5,linestyle='--',label="$\sum_{i=0}^{N_y-1} (u^2_1-v^2_1)_i $"+"$\cdot %.2g$"%u2mv2_factor)
			# ax.plot(kwargs["var_values_"], u2mv2_site0*u2mv2_factor, color="green", linewidth=1.5, label="u2-v2 site 0")




			#######3 IM HERE

			# fig1, ax1 = plt.subplots()
			# ax1.plot(kwargs["var_values_2_"], u2mv2_toplot[:,0])
			# plt.show()

			######################



			for i in [0]:#,62]:#[0,23]:#[0,9,14,23]:#len(u2mv2_allsites[0,:])):
				ax.plot(kwargs["var_values_2_"], u2mv2_toplot[:,i], linewidth=1.5, linestyle='--', label="$(u^2_1-v^2_1)/(u^2_1+v^2_1)$"+"$\cdot %.2g$ site %s"%(u2mv2_factor,i))

				### !!! IM HERE



				###


			ax.grid("on")

		else:
			ax.plot(kwargs["var_values_2_"], kwargs["E1_var"], color=my_blue, linewidth=1.5, label=kwargs["legend"][0])
			ax.plot(kwargs["var_values_2_"], kwargs["Em1_var"], "--", color=my_red, linewidth=1.5,label=kwargs["legend"][1])
			ax.plot(kwargs["var_values_2_"], kwargs["u2mv2_E1_var"]*u2mv2_factor, color="black", linewidth=1.5,label=kwargs["legend"][2]+"$\cdot %s$"%u2mv2_factor)
			ax.plot(kwargs["var_values_2_"], kwargs["u2mv2_Em1_var"]*u2mv2_factor, "--", color="black", linewidth=1.5,label=kwargs["legend"][3]+"$\cdot %s$"%u2mv2_factor)
		
		box = ax.get_position()
		# making separate axis for colorbar
		cbaxes = fig.add_axes(ax)#[box.x0+box.width,box.y0+box.height*0.25,box.width*0.05,box.height*0.75]) 

		# cbaxes.set_position([box.x0+box.width,box.y0+box.height*0.25,box.width*0.05,box.height*0.75]) 
		
		# # Shrink current axis's height by 10% on the bottom

		ax.set_position([box.x0, box.y0 + box.height*0.25,
		                 box.width*0.75, box.height * 0.75])


		# Put a legend below current axis
		ax.legend(loc='upper center', bbox_to_anchor=(0.5, -0.25),
		          fancybox=True, ncol=2,fontsize=7)

	# # 30082019 : commented this
	# if len(kwargs) == 0: 		# if no energies or charges to be added to the plot
	# 	# cbaxes = fig.add_axes(ax)
	# 	# cb = fig.colorbar(pcm)#,extend='both')
	# 	# cb.formatter.set_powerlimits((-3, 4))
	# 	# cb.update_ticks()
	# 	print("hello")

	# If length of colorbar_ticks is non-zero, this sets the user-defined ticks:
	if len(colorbar_ticks)>0:
		cb = fig.colorbar(pcm, orientation='vertical',ax=ax, shrink=0.75, ticks=colorbar_ticks)
	else:
		cb = fig.colorbar(pcm, orientation='vertical',ax=ax, shrink=0.75)

	ax.set_title(figtitle,fontsize=15)
	ax.set_xlabel(xlabel,fontsize=12)
	ax.set_ylabel(ylabel,fontsize=12)
	ax.set_ylim(bottom=-par.bias_maxmin,top=par.bias_maxmin)

	ax.ticklabel_format(style='sci',scilimits=(-3,4))

	# fig.tight_layout()
	fig.subplots_adjust(left=0.19, bottom=0.16, right=0.93)

	cb.ax.tick_params(labelsize=12)


	ax.set_rasterized(rasterized)
	plt.savefig(filename + "_" + scaling + ".pdf",dpi=300)	
	print("%s: Saved figure"%misc.round_time(datetime.datetime.now(),round_to=60), filename + scaling + ".pdf")	
Beispiel #22
0
def calc_E1_Em1_from_E0_E0prime_mu_(E0,
                                    E0prime,
                                    evec0,
                                    evec0prime,
                                    mu_values,
                                    N,
                                    tol=2):
    """
	Calculate electron/hole energies E1 and Em1 from cutting and pasting the energies E0 and E0prime whose values are in
			E0 >= 0, E0prime <= 0
	and whose period is half that of E1 and Em1. E1 and Em1 have max/min values
			max(E1 and Em1) = max(E0), min(E1 and Em1) = min(E0prime).

	Calculates the derivtive of the energies. When the derivative changes, that's where the cut needs to be done!

	Parameters
	----------
	E0 : 			lowest energy for the solved system, which in the topological phase corresponds to the positive values of the lowest energy pair of modes.

	E0prime : 		lowest absolute energy of the solved system, whose values are negative.

	evec0 : 		eigenvector with the energy E0.
					 - indexing : 	evec0[var_res,N]
					 				where N = 2*2*Ny in spinful system with p-h dofs and is 1D with length Ny. var_res is the number of points in the variable one is considering the energies/evecs a function of, which could be e.g. mu_res.

	evec0prime : 	eigenvector with the energy E0prime.
					 - indexing : 	same as with evec0.

	tol : 			tolerance in indices for which elements in sign_change_indices_E0max and sign_change_indices are considered to be the same. Necessary because they are calculated in different manners, and it thus turns out that when they are supposed to be the same, they vary slightly from each other. Example: for mu_res = 1500, tol=1 would do the job of excluding the points in sign_change_indices_E0max from sign_change_indices. Default value of tol is set to tol = 2.

	sign_change_indices : 	indices in var (e.g. mu_values) where the derivative of the energy E0 (or equivalently E0prime) changes.

	splineE0 : 				Fitted 'function' of E0. Used to find the derivative of E0.

	splineE0_derivative : 	derivative of fitted 'function' splineE0. Used to find the indices where the sign of the derivative changes, which corresponds to the indices where the energies E1 and Em1 cross.

	splineE0prime : 		equivalently to above.

	splineE0prime_derivative : 	equivalently to above.

	m : 					indexes in var (e.g. mu_values) for which the elements of sign_change_indices that are not equal to the elements of sign_change_indices_E0max, within the tolerance tol.

	Notes
	-----
	 - The sign of the derivative of the energy changes also in between the desired points where it changes. So we need to identify which points are the desired points and which to throw away. We can identify that the points we want are the ones where the energy is approximately zero, while the points to throw away are the ones where the absolute value of the energy is at its maxima.
	 - All elements of the energies E1 and Em1 that are less than m[0] and larger than m[-1] need to be set equal to the appropriate E0 and E0prime. The convention used here is that
	 			 - for indices < m[0] : 	E1 = E0, Em1 = E0prime.
	 Depending on whether len(m) is even or odd, we get that E0 and Em1 should be for indices > m[-1]:
	 			 - for indices > m[-1]:
		 			 - for len(m) even : 	E1 = E0prime	
		 			 - for len(m) odd : 	Em1 = E0


	"""

    from scipy.interpolate import UnivariateSpline
    import numpy as np
    import scipy.signal
    from My_Costum_Packages_newest import misc
    import datetime

    print("%s: In calc.calc_E1_Em1_from_E0_E0prime_mu()" %
          misc.round_time(datetime.datetime.now(), round_to=60))

    splineE0 = UnivariateSpline(mu_values, E0, s=0)
    splineE0prime = UnivariateSpline(mu_values, E0prime, s=0)

    m = np.array(scipy.signal.argrelextrema(np.abs(E0)))[0]
    m_ = np.array(scipy.signal.argrelextrema(np.abs(E0)))[0]

    E1_cut = np.zeros(len(mu_values))
    Em1_cut = np.zeros(len(mu_values))

    evec1_cut = np.zeros((len(mu_values), N), dtype=np.complex_)
    evecm1_cut = np.zeros((len(mu_values), N), dtype=np.complex_)

    for j in range(len(m) - 1):
        # print(j,m[j],m[j+1])
        if j % 2 == 0:  # if j is an even number
            E1_cut[m[j]:m[j + 1]] = E0[m[j]:m[j + 1]]
            Em1_cut[m[j]:m[j + 1]] = E0prime[m[j]:m[j + 1]]

        if j % 2 != 0:  # if j is an odd number
            E1_cut[m[j]:m[j + 1]] = E0prime[m[j]:m[j + 1]]
            Em1_cut[m[j]:m[j + 1]] = E0[m[j]:m[j + 1]]

    for n in range(len(m_) - 1):

        if n % 2 == 0:  # if n is an even number

            evec1_cut[m_[n]:m_[n + 1], :] = evec0[m_[n]:m_[n + 1], :]
            evecm1_cut[m_[n]:m_[n + 1], :] = evec0prime[m_[n]:m_[n + 1], :]

        if n % 2 != 0:  # if n is an odd number

            evec1_cut[m_[n]:m_[n + 1], :] = evec0prime[m_[n]:m_[n + 1], :]
            evecm1_cut[m_[n]:m_[n + 1], :] = evec0[m_[n]:m_[n + 1], :]
    """
	Assigning values for 
	 - indices < m[0] : 			E1_cut = E0, Em1_cut = E0prime.
	 - odd/even indices > m[-1] : 	

	"""

    E1_cut[m[-1]:] = E0[m[-1]:]
    Em1_cut[m[-1]:] = E0prime[m[-1]:]

    evec1_cut[m_[-1]:] = evec0[m_[-1]:, :]
    evecm1_cut[m_[-1]:] = evec0prime[m_[-1]:, :]

    return E1_cut, Em1_cut, evec1_cut, evecm1_cut
Beispiel #23
0
def calc_g0_12_asymm(sys, par, ppar, lambda_, t_L, t_R, omega, En, evec_n,
                     filename):
    """
	Loops over lambda variable and calculates g0_12_asymm for the biasenergy (float) or biasenergies (array) given as input omega, using the g0_12_asymm function.

	Parameters
	----------
	lambda_ : 			array.
						Variable that the eigenenergies/eigenstates are calculated as a function of. 
						E.g. mu or Ez.
	
	omega : 			float or array.
						Variable energy that each g0_12_asymm is calculated for / is a function of, for every lambda_.

	par : 				SimpleNamespace object.
						Contains parameters of the system.
						Used to get e.g. biasenergies and t_pincher.

	Calulated Parameters
	--------------------
	un : 				array.
						u-vector containing every u-value for the n'th state under consideration, for every lambda_-value / as a function of lambda_.

	nu : 				array.
						dos !!!???of system as function of lambda_.

	OPTIONALLY CALCULATED:	These are calculated if they are not already given in the par SimpleNamespace class.
	Gamma_L : 			array. 
						Gamma at lead L (1), specified directly in par.
						Could in future implementation make it a function of the density of states nu(lambda_) of the lead, making Gamma_L a function of lambda_, too. 
						Shape: len(lambda_)

	Gamma_R : 			array.
						Similarly.

	Notes
	-----
	 - "n" in En, un and vn symbolizes the index of the eigenstate / eigenenergy under consideration.
	 - ??? below: may want to somehow access the already made lead of the system sys. I haven't figured out how to do this yet.
	 - ??? below: Which of the four orbitals is nu of? sum of all?
	"""

    print(misc.round_time(datetime.datetime.now(), round_to=60),
          ": in calc_g0_12_asymm")

    u2mv2, u2, v2, u, v, un_L, un_R, vn_L, vn_R = calc_u2mv2_var(
        evec_n=evec_n,
        var_values=lambda_,
        Ny=par.Ny,
        filename=filename,
        savefiles=True,
        write_u_v_var_LR=True)

    # !!! for now, only for symmetric pincher:
    par.t_L = par.t_pincher
    par.t_R = par.t_pincher

    if ppar.doubleres == False:
        omega = par.biasenergies
    else:
        omega = par.biasenergies_2
    ###################### UNNECCESARY: NOT USED ANYMORE ####################
    # ###### nu of lead as function of lambda_: #######
    # nu = nu_1D_lead_directly(par, lambda_)
    # plot.plot_nu_nuorb_vs_mu(nu, mu=lambda_, filename=filename)

    # # Summing over the orbitals in nu:
    # nu = np.sum(nu,axis=1)

    # ###### nu of sys as function of lambda_: ######
    # nusys = nu_sys_directly(sys, par, lambda_)

    # plot.plot_nu_nuorb_vs_mu(nusys, mu=lambda_, filename=filename)

    ### !!!??? USING SYS DOS, NOT LEAD DOS ###
    # nu = np.sum(nusys,axis=1)
    #########################################################################

    # ??? 2*pi here instead of Karsten's pi convention since nu is divided by 2pi?
    if hasattr(par, 'Gamma_L'):
        pass
    else:
        Error("Gamma_L needs to be specified in par")
        # par.Gamma_L = np.pi*nu*np.abs(t_L)**2
    if hasattr(par, 'Gamma_R'):
        pass
    else:
        Error("Gamma_R needs to be specified in par")
        # par.Gamma_R = np.pi*nu*np.abs(t_R)**2

    par.q_L = par.Gamma_L * (np.abs(un_L)**2 - np.abs(vn_L)**2)
    par.q_R = par.Gamma_R * (np.abs(un_R)**2 - np.abs(vn_R)**2)

    g0_12_asym = g0_12_asymm(q_L=par.q_L,
                             q_R=par.q_R,
                             omega=omega,
                             En=En,
                             Gamma_L=par.Gamma_L,
                             Gamma_R=par.Gamma_R,
                             u_L=un_L,
                             u_R=un_R,
                             v_L=vn_L,
                             v_R=vn_R)

    np.save("g0_12_asym_" + filename, g0_12_asym)
    print("%s: Saved file %s" %
          (misc.round_time(datetime.datetime.now(),
                           round_to=60), "g0_12_asym_" + filename + ".npy"))

    return g0_12_asym
Beispiel #24
0
def read_or_write_energies_Ez(sys, par, ppar, *args):
    """
	Reads from file or calculates eigenenergies and eigenvectors as a function of the parallel applied magnetic field par.Ez.
	Parameters
	----------
	args : 	if want to specify other filename than EvsEz_ + ppar.filename.

	Notes
	-----
	 - Using arr.argsort() to get indices that sorts the array arr. Here, using this on the eigenenergies in order to also be able to sort the eigenvectors, such that, later, one may access the k'th eigenvector.
	"""
    if ppar.generate_En_Ez == False:  # NB: need to have generated file with appropriate filename before setting use_energies_from_file = True.
        par.energies_Ez = np.load(
            "EvsEz_" + ppar.filename +
            ".npy")  # .npy file faster to load with numpy
        par.Ez = par.Ez_values[
            0]  # just need this one defined in order for sys to work later
        if ppar.Eonly == True:
            pass
        else:
            par.eigenvectors_Ez = np.load("EigenvectorsvsEz_" + ppar.filename +
                                          ".npy")

    else:
        if par.printtype == True:  # if you want to print parts of the Hamiltonian. Only goes through the first iteration, when counter_Hprint = 0.
            Hprint(counter_Hprint)
        """Calculating energies for a range of applied fields, Ez"""
        par.energies_Ez = []
        par.eigenvectors_Ez = []
        for par.Ez, i in zip(
                par.Ez_values, range(len(par.Ez_values))
        ):  # par is the class '__main__.SimpleNamespace'. par.Ez in Ez_values adds Ez=Ez_values[0] etc. to the par dictionary. In the loop, this happens one by one, so B is written over for every iteration of the loop.

            print(" - Ez-value number:", i)

            H = sys.hamiltonian_submatrix(args=[par], sparse=True)
            H = H.tocsc()
            eigs = scipy.sparse.linalg.eigsh(H, k=par.k, sigma=0)

            sorting_indices = eigs[0].argsort()
            evals = eigs[0][sorting_indices]
            evecs = eigs[1][:, sorting_indices]

            par.energies_Ez.append(evals)
            par.eigenvectors_Ez.append(evecs)

        if ppar.doubleres == False:
            write_var(ppar, var=par.energies_Ez, var_extra_title_str="EvsEz_")
            print("%s: saved datalog file %s" %
                  (misc.round_time(datetime.datetime.now(), round_to=60),
                   ("EvsEz_" + ppar.filename + ".npy")))
            write_var(ppar,
                      var=par.eigenvectors_Ez,
                      var_extra_title_str="EigenvectorsvsEz_")
            print("%s: saved datalog file %s" %
                  (misc.round_time(datetime.datetime.now(), round_to=60),
                   ("EigenvectorsvsEz_" + ppar.filename + ".npy")))
        else:
            write_var_2(ppar,
                        var=par.energies_Ez,
                        var_extra_title_str="EvsEz_")
            print("%s: saved datalog file %s" %
                  (misc.round_time(datetime.datetime.now(), round_to=60),
                   ("EvsEz_" + ppar.filename + ".npy")))
            write_var_2(ppar,
                        var=par.eigenvectors_Ez,
                        var_extra_title_str="EigenvectorsvsEz_")
            print("%s: saved datalog file %s" %
                  (misc.round_time(datetime.datetime.now(), round_to=60),
                   ("EigenvectorsvsEz_" + ppar.filename + ".npy")))