2 % Copyright (C) 2016 Peter Rakyta, Ph.D.
4 % This program is free software: you can redistribute it and/or modify
5 % it under the terms of the GNU General Public License as published by
6 % the Free Software Foundation, either version 3 of the License, or
7 % (at your option) any later version.
9 % This program is distributed in the hope that it will be useful,
10 % but WITHOUT ANY WARRANTY; without even the implied warranty of
11 % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 % GNU General Public License
for more details.
14 % You should have received a copy of the GNU General Public License
15 % along with
this program. If not, see http:
17 %> @addtogroup basic Basic Functionalities
20 %> @brief Class to solve the eigenproblem of a translational invariant leads and calculate the group velocities.
22 %> @brief Class to solve the eigenproblem of a translational invariant leads and calculate the group velocities.
24 %> EQuUs v4.8 or later
29 properties ( Access =
protected )
30 %>
true for calculating the retarded Green
function, or
false for the advanced Green
function.
32 %> The unsorted right-sided eigenstates.
34 %> The unsorted left-sided eigenstates.
36 %> The unsorted wave numbers in form exp(1i*k).
38 %> The unsorted group velocities.
40 %> The wave numbers of the eigenstates, that propagates or decays in the positive direction.
42 %> The wave numbers of the eigenstates in form exp(1i*k), that propagates or decays in the negative direction.
44 %> The group velocities of the eigenstates in form exp(1i*k), that propagates or decays in the positive direction.
46 %> The group velocities of the eigenstates, that propagates or decays in the negative direction.
48 %> The right sided wave functions of the eigenstates, that propagates or decays in the positive direction.
50 %> The right-sided wave functions of the eigenstates, that propagates or decays in the negative direction.
52 %> The left-sided wave numbers of the eigenstates, that propagates or decays in the positive direction.
54 %> The left-sided wave functions of the eigenstates, that propagates or decays in the negative direction.
56 %> The dual basis of the right-sided wave functions of the eigenstates, that propagates or decays in the positive direction.
58 %> The dual basis of the right-sided wave functions of the eigenstates, that propagates or decays in the negative direction.
60 %> A real number corresponding to the tolerance used to sort the left and right moving (decaying) modes.
62 %> A structure #
open_channels containing info on the open channels
64 %> Logical matrix containing the degenerate k subspaces
65 degenerate_k_subspaces
66 %> The energy value
for which the #TrukkosSajatertekek eigenvalue problem was solved.
73 methods ( Access =
public )
74 %% constructorof the
class 75 %> @brief Constructor of the
class.
79 %> @
return An instance of the
class 84 %% Determine_Open_Channels
85 %> @brief Determines the open channels in the lead. The data are storen within the attribute #
open_channels.
86 function Determine_Open_Channels( obj )
87 if isempty(obj.expk_p)
88 obj.display('Right and left going states were not determined yet. Use method
EigenProblemLead::szetvalaszto first.', 1);
91 propagating_indexes_p = logical( abs( abs(obj.expk_p) - 1 ) < obj.sort_tolerance );
92 propagating_indexes_m = logical( abs( abs(obj.expk_m) - 1 ) < obj.sort_tolerance );
99 coordinates = obj.Get_Effective_Coordinates();
102 if obj.isSuperconducting()
105 obj.
open_channels.BdG_u_incoming = logical(diag(obj.modusmtx_p(coordinates.BdG_u,:)'*obj.modusmtx_p(coordinates.BdG_u,:)));
106 obj.
open_channels.BdG_u_outgoing = logical(diag(obj.modusmtx_m(coordinates.BdG_u,:)'*obj.modusmtx_m(coordinates.BdG_u,:)));
116 %> @brief Sorts the left and right propagating (decaying) modes.
117 %> @
param tolerance The tolerance to be used during the sort.
118 function szetvalaszto( obj, tolerance )
120 if isempty(obj.csoportseb)
125 if ~exist('tolerance', 'var')
127 elseif tolerance < 1e-16
128 err = MException(['EQuUs:', class(obj), ':szetvalaszto'], 'Failed to separate the left and right-going states');
129 save(['EQuUs_', class(obj), '_szetvalaszto.mat']);
134 indexes = (real(obj.csoportseb*obj.Lead_Orientation) > 0 & abs(abs(obj.expk)-1) < tolerance) | (1-abs(obj.expk))*obj.Lead_Orientation > tolerance;
136 indexes = (real(obj.csoportseb*obj.Lead_Orientation) < 0 & abs(abs(obj.expk)-1) < tolerance) | (1-abs(obj.expk))*obj.Lead_Orientation > tolerance;
138 obj.expk_p = obj.expk(indexes);
139 obj.vcsop_p = obj.csoportseb(indexes);
140 obj.modusmtx_p = obj.modusmtx(:,indexes);
141 if ~obj.
Opt.usingDualModes
142 obj.modusmtx_p_left = obj.modusmtx_left(indexes,:);
145 obj.expk_m = obj.expk(~indexes);
146 obj.vcsop_m = obj.csoportseb(~indexes);
147 obj.modusmtx_m = obj.modusmtx(:,~indexes);
148 if ~obj.
Opt.usingDualModes
149 obj.modusmtx_m_left = obj.modusmtx_left(~indexes,:);
152 obj.sort_tolerance = tolerance;
153 if length(obj.expk_p) ~= length(obj.expk_m)
154 obj.szetvalaszto( obj.sort_tolerance/10 );
166 %> @brief Calculates the group velocities corresponding to the propagating states. The calculated group velocities are stored within the class.
169 usingDualModes = obj.
Opt.usingDualModes;
171 csoportseb = obj.csoportseb;
173 needs_to_be_diagonalized = false;
177 if needs_to_be_diagonalized
178 Diagonalize_Current_Operator();
182 obj.csoportseb = diag(csoportseb);
185 %------------------------------------------------------------------
187 function Diagonalize_Current_Operator()
189 [U, eigvals] = eig( full(csoportseb));
191 % rotate the wavefunctions
192 obj.modusmtx = obj.modusmtx*U;
194 obj.modusmtx_left = U'*obj.modusmtx_left;
198 % reordering the wavenumbers
199 obj.expk = diag(U'*diag(obj.expk)*U);
201 obj.degenerate_k_subspaces = logical(speye(length(obj.expk)));
204 %------------------------------------------------------------------
206 %------------------------------------------------------------------
209 [~, K1_eff, K1adj_eff] = obj.Get_Effective_Hamiltonians();
210 Neff = obj.Get_Neff();
211 csoportseb = sparse([],[],[], 2*Neff, 2*Neff);
213 adj_modusmtx = obj.modusmtx';
215 jdx_indexes = obj.degenerate_k_subspaces(idx,:);
216 if ~needs_to_be_diagonalized && length(csoportseb(idx, jdx_indexes)) >1
217 needs_to_be_diagonalized = true;
219 %Eq (18) in GNew J. Phys 093029 (2014), (modes are already normalized with the overlap integrals)
220 csoportseb(idx, jdx_indexes) = 1i*adj_modusmtx(idx,:)*(K1_eff*obj.expk(idx)-K1adj_eff*(1/obj.expk(idx)) )*obj.modusmtx(:,jdx_indexes);
224 %equation (A4) in PRB 78, 035407 (difference in the evanescent group velocities)
226 jdx_indexes = obj.degenerate_k_subspaces(idx,:);
227 if ~needs_to_be_diagonalized && length(csoportseb(idx, jdx_indexes)) >1
228 needs_to_be_diagonalized = true;
230 csoportseb(idx, jdx_indexes) = 1i*obj.modusmtx_left(idx,:)*(K1_eff*obj.expk(idx)-K1adj_eff*(1/obj.expk(idx)) )*obj.modusmtx(:,jdx_indexes);
234 % end nested functions
235 %------------------------------------------------------------------
242 %% TrukkosSajatertekek
243 %> @brief Calculates the wave numbers corresponding to the propagating states at given energy. The calculated wave numbers are stored by attribute
#expk. 244 %> @
param E The energy value used in the calculations.
245 function TrukkosSajatertekek(obj, E)
248 obj.retarted =
false;
255 % create effective
Hamiltonians with SVD regularization
if necessary
256 obj.Calc_Effective_Hamiltonians( E );
257 [K0_eff, K1_eff, K1adj_eff] = obj.Get_Effective_Hamiltonians();
258 Neff = obj.Get_Neff();
260 usingDualModes = obj.Opt.usingDualModes;
262 if obj.isSuperconducting() || ~obj.Opt.BdG
263 %
if normal system, or
if BdG Hamiltonian with nonzero pair potential
264 [obj.modusmtx,obj.expk, obj.modusmtx_left] = calcTrickyEigenvalues( K0_eff, K1_eff, K1adj_eff );
266 %
if BdG Hamiltonian with nonzero pair potential
268 K0_e = K0_eff(1:M0, 1:M0);
269 K0_h = K0_eff(M0+1:Neff, M0+1:Neff);
270 K1_e = K1_eff(1:M0, 1:M0);
271 K1_h = K1_eff(M0+1:Neff, M0+1:Neff);
272 K1adj_e = K1adj_eff(1:M0, 1:M0);
273 K1adj_h = K1adj_eff(M0+1:Neff, M0+1:Neff);
275 % eigenvalues
for electron-like part
276 [modusmtx_e, expk_e, modusmtx_left_e] = calcTrickyEigenvalues( K0_e, K1_e, K1adj_e );
278 %eigenvalues
for hole-like part
279 [modusmtx_h, expk_h, modusmtx_left_h] = calcTrickyEigenvalues( K0_h, K1_h, K1adj_h );
281 obj.modusmtx = [ modusmtx_e, zeros( size(modusmtx_e,1), size(modusmtx_e,2)); ...
282 zeros(size(modusmtx_h,1), size(modusmtx_e,2)), modusmtx_h ];
284 obj.expk = [expk_e;expk_h];
287 obj.modusmtx_left = [ modusmtx_left_e, zeros( size(modusmtx_left_e,1), size(modusmtx_left_e,2)); ...
288 zeros(size(modusmtx_left_h,1), size(modusmtx_left_e,2)), modusmtx_left_h ];
293 obj.NormalizeModes();
294 obj.Determine_Degenerate_k_subspaces();
298 obj.d_modusmtx_p = [];
299 obj.d_modusmtx_m = [];
305 %------------------------------------------------------------------
307 % calculates the tricky eigenvalue problem
308 function [modusmtx,expk, modusmtx_left] = calcTrickyEigenvalues( H0, H1, H1adj )
310 [H_eff,B_eff] = Effective_H(H0,H1,H1adj);
313 [modusmtx,expk] = eig(H_eff,B_eff);
317 [modusmtx, modusmtx_left, expk] = obj.eig(H_eff,B_eff);
321 % Eq (A3) in PRB 78, 035407
322 %normfactors = diag(modusmtx_left*B_eff*modusmtx);
323 %modusmtx_left = diag(1./normfactors)*modusmtx_left;
324 modusmtx_left = modusmtx_left(:,1:M);
325 modusmtx_left = diag(sqrt(expk))*modusmtx_left;
329 % Eq (7) in PRB 78, 035407
330 modusmtx = modusmtx(1:M,:);
331 modusmtx = modusmtx*diag(1./sqrt(expk));
333 %------------------------------------------------------------------
336 %------------------------------------------------------------------
337 % Eq (6) PRB 78 035407
338 function [H_eff,B_eff] = Effective_H(H0,H1,H1adj)
340 %H1inv = H1\eye(size(H1));%inv(H1);
341 H_eff = full([-H0,full(-H1adj);eye(M),zeros(M)]);
342 B_eff = full([ H1, zeros(M); zeros(M), eye(M)]);
345 %------------------------------------------------------------------
346 % end nested functions
351 %> @brief Adds on-site potential to the Hamiltonian H0.
352 %> @
param V The potential calculated on the
sites.
359 %> @brief Transforms the effective
Hamiltonians by a unitary transformation
360 %> @
param Umtx The matrix of the unitary transformation.
361 function Unitary_Transform(obj, Umtx)
365 if ~isempty(obj.modusmtx_p)
366 obj.modusmtx_p = Umtx*obj.modusmtx_p;
369 if ~isempty(obj.modusmtx_m)
370 obj.modusmtx_m = Umtx*obj.modusmtx_m;
373 if ~isempty(obj.modusmtx_p_left)
374 obj.modusmtx_p_left = Umtx*obj.modusmtx_p_left;
377 if ~isempty(obj.modusmtx_m_left)
378 obj.modusmtx_m_left = Umtx*obj.modusmtx_m_left;
381 if ~isempty(obj.d_modusmtx_p)
382 obj.d_modusmtx_p = obj.modusmtx_p*Umtx';
385 if ~isempty(obj.d_modusmtx_m)
386 obj.d_modusmtx_m = obj.modusmtx_m*Umtx';
393 %> @brief Creates a clone of the present
object.
394 %> @return Returns with the cloned class.
395 %> @
param varargin Cell array of optional parameters:
396 %> @
param 'empty' Set true to create an empty class, or false (default) to copy all the attributes.
397 %> @return Returns with an instance of the cloned class.
401 p.addParameter('empty', false );
403 p.parse(varargin{:});
404 empty = p.Results.empty;
407 'Hanyadik_Lead', obj.Hanyadik_Lead,...
408 'Lead_Orientation', obj.Lead_Orientation, ...
414 meta_data = metaclass(obj);
416 for idx = 1:length(meta_data.PropertyList)
417 prop_name = meta_data.PropertyList(idx).Name;
418 if strcmpi( prop_name, 'next_SVD_cycle' )
419 if ~isempty( obj.next_SVD_cycle )
420 ret.next_SVD_cycle = obj.next_SVD_cycle.CreateClone();
423 ret.Write( prop_name, obj.(prop_name));
430 %> @brief Resets all elements in the
object.
434 meta_data = metaclass(obj);
436 for idx = 1:length(meta_data.PropertyList)
437 prop_name = meta_data.PropertyList(idx).Name;
438 if strcmp(prop_name, '
Opt') || strcmp( prop_name, '
param') || strcmp(prop_name, 'varargin')
441 obj.Clear( prop_name );
450 %> @brief Sets the value of an attribute in the class.
451 %> @
param MemberName The name of the attribute to be set.
452 %> @
param input The value to be set.
453 function Write(obj, MemberName, input)
455 if strcmp(MemberName, '
param') || strcmp(MemberName, 'params')
460 obj.(MemberName) = input;
462 error(['EQuUs:', class(obj), ':Read'], ['No property to write with name: ', MemberName]);
468 %> @brief Query for the value of an attribute in the class.
469 %> @
param MemberName The name of the attribute to be set.
470 %> @return Returns with the value of the attribute.
471 function ret = Read(obj, MemberName)
473 if strcmp(MemberName, 'Hamiltonian2Dec')
478 ret = obj.(MemberName);
480 error(['EQuUs:', class(obj), ':Read'], ['No property to read with name: ', MemberName]);
486 %> @brief Clears the value of an attribute in the class.
487 %> @
param MemberName The name of the attribute to be cleared.
491 obj.(MemberName) = [];
493 error(['EQuUs:', class(obj), ':Clear'], ['No property to clear with name: ', MemberName]);
502 methods (Access=private)
504 %% Determine_Degenerate_k_subspaces
505 %> @brief Determine the degenerate k subspaces for which the current operator needs to be diagonalized.
506 function Determine_Degenerate_k_subspaces(obj)
508 degeneracy_tolerance = 1e-12;
510 obj.degenerate_k_subspaces = obj.expk*transpose(1./obj.expk);
511 obj.degenerate_k_subspaces = abs(obj.degenerate_k_subspaces - 1) < degeneracy_tolerance;
517 %> @brief Renormalizes the wave functions with the overlap integrals (Eq (9) in PRB 78 035407
519 usingDualModes = obj.
Opt.usingDualModes;
521 modusmtx_adj = obj.modusmtx';
522 [S0, S1, S1adj] = obj.Get_Effective_Overlaps();
524 for idx = 1:length(obj.expk)
525 expk = obj.expk(idx);
526 if length(obj.q) < 2 && ~isempty(obj.q) && ~obj.HamiltoniansDecimated
527 S0 = S0 + obj.S1_transverse*diag(exp(-1i*obj.q)) + obj.S1_transverse'*diag(exp(1i*obj.q));
531 S = S0 + S1*expk + S1adj*(1/expk);
533 l_n = modusmtx_adj(idx,:)*S*obj.modusmtx(:,idx);
534 obj.modusmtx(:,idx) = obj.modusmtx(:,idx)/sqrt(l_n);
536 % normalize the left sided eigenvectors
538 l_n = obj.modusmtx_left(idx,:)*S*obj.modusmtx(:,idx);
539 obj.modusmtx_left(idx,:) = obj.modusmtx_left(idx,:)/(l_n);
543 %no overlap integrals are present
544 normfactors = diag( modusmtx_adj*obj.modusmtx );
545 obj.modusmtx = obj.modusmtx*diag(1./sqrt(normfactors));
547 normfactors = diag( obj.modusmtx_left*obj.modusmtx );
548 obj.modusmtx_left = diag(1./(normfactors))*obj.modusmtx_left;
554 %% Extend_Wavefncs --- DEVELOPMENT
555 %> @brief Extend the reduced wave functions to the original basis before the SVD regularization (Eq (45) in PRB 78 035407) This
function is in a development stage.
557 wavefnc_extended = zeros(obj.M, obj.Get_Neff());
558 for idx = 1:length(obj.expk)
559 wavefnc_extended(:,idx) = obj.Extend_Wavefnc( obj.modusmtx(:,idx), obj.expk(idx) );
562 obj.modusmtx = wavefnc_extended;
568 end % methods private
571 methods (Access=protected)
574 %> @brief Initializes
object properties.
577 obj.sort_tolerance = 1e-6;
Structure hole contains the data about the antidot used in class antidot.
Structure Opt contains the basic computational parameters used in EQuUs.
Structure open_channels describes the open channel in the individual leads.
Class to create and store Hamiltonian of the translational invariant leads.
function Transport(Energy, B)
Calculates the conductance at a given energy value.
function Hamiltonians(varargin)
Function to create the custom Hamiltonians for the 1D chain.
Class to regulerize the H1 problem of the leads by SVD decompozition.
Structure param contains data structures describing the physical parameters of the scattering center ...
Structure sites contains data to identify the individual sites in a matrix.
function SVDregularizationLead(Opt, param, varargin)
Constructor of the class.
Class to solve the eigenproblem of a translational invariant leads and calculate the group velocities...
function structures(name)