2 % Copyright (C) 2009-2017 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 utilities Utilities
20 %> @brief A
class to process transport calculations on quantum dots. Based on the real-time diagrammatic method of PRB 50, 18439
22 %> @brief A
class to process transport calculations on quantum dots. Based on the real-time diagrammatic method of PRB 50, 18439
24 %> EQuUs v4.9 or later
28 properties ( Access =
public )
29 %> The charging energy
34 properties ( Access =
protected )
35 %> Array of partition functions of 1<N<StatesNum occupied one-electron states ( Z = sum_n(exp(-beta*En)) )
36 PartitionFunctionsOneElectron
37 %> Occupation probabilities of an isolated, the N-occupied QD in thermal equilibrium
38 ThermalOccupationProbabilities
39 %> Occupation probabilities of the QD connected to the leads occupied by N-N0 excess charge
40 OccupationProbabilities
41 %> The calculated transition rates between the individual N-occupations states of the QD
43 %> The calculated tunneling rates between the individual leads and the QD
45 %> The calculated current
operator between the QD and a chosen lead. (see method DetermineCurrentOperator)
47 %> Array containing the occupation numbers
49 %> An array containing the chamical potentials corresponding to the occupation numbers of OccNumbers
51 %> Number of states utilized in the calculations.
57 methods (Access=
public)
60 %> @brief Constructor of the
class.
62 %> @
param varargin Cell array of optional parameters. For details see #InputParsing.
63 %> @
return An instance of the
class 68 obj = obj@
IV(
Opt, varargin{:} );
77 %% DetermineDensityOfStates
78 %> @brief Calculates the
DOS to deremine the one-electron occupation levels. This must be done manually.
79 %> @
param Emin The minimum of the energy array.
80 %> @
param Emax The maximum of the energy array.
81 %> @
param Edb The number of the energy points in the energy array.
82 function DetermineDensityOfStates( obj, Emin, Emax, Edb )
84 %creating the energy array
85 Evec = Emin:(Emax-Emin)/Edb:Emax;
87 % calculating the desnity of states
92 plot( obj.DOSdata.Evec, obj.DOSdata.DOS )
97 %% DetermineThermalOccupationProbabilities
98 %> @brief Determines the equilibrium occupation probabilities PN (see Eq (8) in Eur. Phys. J B 10, 119)
99 %> @
param gateVoltage The back gate voltage in units of the energy unit used in the Hamiltonian parameters.
100 function DetermineThermalOccupationProbabilities( obj, gateVoltage )
102 % determine partition functions for the occupied one-electron states
103 % obj.DeterminePartitionFunction();
105 N0 = length(obj.OccNumbers);
107 % sum for the occupation numbers
108 OccupationProbabilities_tmp = zeros( N0, 1);
110 total_charging_energy = obj.Ec/2*(obj.OccNumbers(idx) - gateVoltage/obj.Ec)^2;
112 %OccupationProbabilities(idx) = obj.PartitionFunctionsOneElectron(idx) * exp( -obj.beta*total_charging_energy );
113 OccupationProbabilities_tmp(idx) = exp( -obj.beta*total_charging_energy );
117 OccupationProbabilities_tmp = OccupationProbabilities_tmp/sum(OccupationProbabilities_tmp);
118 obj.ThermalOccupationProbabilities = OccupationProbabilities_tmp;
124 %% DetermineOccupationProbabilities
125 %> @brief Determines the non-equilibrium occupation probabilities P_N (see Eq (8) in Eur. Phys. J B 10, 119)
126 %> @return Returns with the calculated occupation probabilities
127 function ret = DetermineOccupationProbabilities( obj )
129 SelfEnergy_tmp = obj.SelfEnergy;
131 % an arbitrary chosen index. See Eq (6) in PRB 68, 115105
134 SelfEnergy_tmp(:,idx0) = 1;
136 obj.OccupationProbabilities = inv(SelfEnergy_tmp);
137 obj.OccupationProbabilities = obj.OccupationProbabilities(idx0, :);
139 % check the definition of the probability distribution
141 if sum( obj.OccupationProbabilities < -tolerance ) > 0
142 error('EQuUs:Utils:
QuantumDot:DetermineOccupationProbabilities', 'Negative probability obtained during the calculations.')
145 if abs(sum(obj.OccupationProbabilities) - 1) > tolerance
146 error('EQuUs:Utils:
QuantumDot:DetermineOccupationProbabilities', 'The sum of the probabilities is not equal to one.')
149 ret = obj.OccupationProbabilities;
151 % disp(obj.OccupationProbabilities)
157 %> @brief Calculates the current (in units of e^2/hbar) through a lead leadnum at gate voltage gateVoltage and at bias bias.
158 %> @
param bias The bias voltage applied through the leads in units of the energy unit used in the Hamiltonian parameters.
159 %> @
param gateVoltage The back gate voltage in units of the energy unit used in the Hamiltonian parameters.
160 %> @
param leadnum Identification number of the lead. (see attribute
#CreateLeadHamiltonians.Hanyadik_Lead). 161 %> @
return Returns with the calculated current in units of \f$ e^2/\hbar \f$
162 function Current = DetermineCurrent( obj, bias, gateVoltage, leadnum )
164 % calculating the tunneling current
165 if isempty( obj.CurrentOp )
166 obj.DetermineCurrentOperator( bias, gateVoltage, leadnum );
169 % calculating the occupation probabilities
170 if isempty( obj.OccupationProbabilities )
171 obj.DetermineOccupationProbabilities();
174 % calculating the current
175 Current = sum( obj.OccupationProbabilities*obj.CurrentOp );
178 % Check the imaginary part of the current
180 if abs(Current) > tolerance && abs( imag(Current)/real(Current)) > tolerance
181 warning('EQuUs:Utils:
QuantumDot:DetermineCurrent', 'The current has to large imaginary part')
184 Current = real(Current);
188 %% DetermineCurrentOperator
189 %> @brief Determine the current operator (in units of \f$ e^2/\hbar \f$) to calculate the current through a lead leadnum at gate voltage gateVoltage and at bias bias.
190 %> @
param bias The bias voltage applied through the leads in units of the energy unit used in the Hamiltonian parameters.
191 %> @
param gateVoltage The back gate voltage in units of the energy unit used in the Hamiltonian parameters.
192 %> @
param leadnum Identification number of the lead. (see attribute
#CreateLeadHamiltonians.Hanyadik_Lead). 193 function DetermineCurrentOperator( obj, bias, gateVoltage, leadnum )
195 bias_lead = (-1)^leadnum*bias/2;
197 % calculating the tunneling rates
198 if isempty( obj.TunnelingRates )
199 obj.CalcTunnelingRates( gateVoltage );
203 % calculating Fermi-Dirac distribution functions in the chosen lead
204 FD_lead_p = obj.Fermi(obj.Evec - bias_lead);
205 FD_lead_m = 1 - FD_lead_p;
207 % preallocating array
208 CurrentOp = zeros( obj.StatesNum, obj.StatesNum);
211 % calculate the transition rates (only the first order of the perturbation series)
213 % The first order matrix elements are calculated by the diagrammatic rules in PRB 50, 18439
214 deltaEvec = [0, diff(obj.Evec)];
215 for idx = 1:obj.StatesNum
217 for jdx = 1:obj.StatesNum
220 % calculating Fermi-Dirac distribution functions in the QD
221 mu_N = obj.mu_QD(jdx);
222 FD_QD_p = obj.Fermi(obj.Evec-mu_N-obj.Ec);
225 %Calculating the matrix elements
226 tmp = - 2*1i*obj.TunnelingRates{leadnum}(idx,:).*FD_lead_p.*FD_QD_m;
227 tmp = obj.SimphsonInt( tmp.*deltaEvec );
228 CurrentOp(jdx, idx) = CurrentOp(jdx, idx) + tmp;
232 % calculating Fermi-Dirac distribution functions in the QD
233 mu_N = obj.mu_QD(jdx);
234 FD_QD_p = obj.Fermi(obj.Evec-mu_N);
237 %Calculating the matrix elements
238 tmp = 2*1i*obj.TunnelingRates{leadnum}(jdx,:).*FD_lead_m.*FD_QD_p;
239 tmp = obj.SimphsonInt( tmp.*deltaEvec );
240 CurrentOp(jdx, idx) = CurrentOp(jdx, idx) + tmp;
248 CurrentOp = -1i*CurrentOp; % in units of e^2/hbar
250 obj.CurrentOp = CurrentOp;
256 %% DetermineSelfEnergy
257 %> @brief Determine the
self-energy matrix elements describing the transition rates between the N occupated states of the QD. (see the diagrammatic rules in PRB 50, 18439)
258 %> @
param bias The bias voltage applied through the leads in units of the energy unit used in the Hamiltonian parameters.
259 %> @
param gateVoltage The back gate voltage in units of the energy unit used in the Hamiltonian parameters.
260 %> @
return The calulated
self-energy (transition rates between the N occupated states of the QD.)
261 function SelfEnergy = DetermineSelfEnergy( obj, bias, gateVoltage )
263 bias_lead = [ -bias/2 bias/2];
265 % calculating the tunneling rates
266 if isempty( obj.TunnelingRates )
267 obj.CalcTunnelingRates( gateVoltage );
272 % calculating Fermi-Dirac distribution functions in the leads
273 FD_lead_p = cell( length( obj.junction.Interface_Regions ), 1);
274 FD_lead_m = cell( length( obj.junction.Interface_Regions ), 1);
275 for idx = 1:length( obj.junction.Interface_Regions )
276 FD_lead_p{idx} = obj.Fermi(obj.Evec - bias_lead(idx));
277 FD_lead_m{idx} = 1 - FD_lead_p{idx};
280 % preallocating array
281 SelfEnergy = zeros( obj.StatesNum, obj.StatesNum);
284 % calculate the transition rates (only the first order of the perturbation series)
286 % The first order matrix elements are calculated by the diagrammatic rules in PRB 50, 18439
287 deltaEvec = [0, diff(obj.Evec)];
288 for idx = 1:obj.StatesNum
290 for jdx = 1:obj.StatesNum
292 % calculating Fermi-Dirac distribution functions in the QD
293 mu_N = obj.mu_QD(jdx);
294 FD_QD_p = obj.Fermi(obj.Evec-mu_N-obj.Ec);
297 % calculating the matrix elements
298 % summation
for the leads
299 for kdx = 1:length( obj.junction.Interface_Regions )
300 tmp = 2*1i*obj.TunnelingRates{kdx}(idx,:).*FD_lead_p{kdx}.*FD_QD_m;
301 tmp = obj.SimphsonInt( tmp.*deltaEvec );
302 SelfEnergy(jdx, idx) = SelfEnergy(jdx, idx) + tmp;
305 % calculating Fermi-Dirac distribution functions in the QD
306 mu_N = obj.mu_QD(jdx);
307 FD_QD_p = obj.Fermi(obj.Evec-mu_N);
310 % calculating the matrix elements
311 % summation
for the leads
312 for kdx = 1:length( obj.junction.Interface_Regions )
313 tmp = 2*1i*obj.TunnelingRates{kdx}(jdx,:).*FD_lead_m{kdx}.*FD_QD_p;
314 tmp = obj.SimphsonInt( tmp.*deltaEvec );
315 SelfEnergy(jdx, idx) = SelfEnergy(jdx, idx) + tmp;
320 % calculating the matrix elements
321 % summation
for the leads
322 for kdx = 1:length( obj.junction.Interface_Regions )
323 % calculating Fermi-Dirac distribution functions in the QD
324 mu_N = obj.mu_QD(jdx);
325 FD_QD_p = obj.Fermi(obj.Evec-mu_N);
327 tmp = -2*1i*obj.TunnelingRates{kdx}(jdx,:).*FD_lead_m{kdx}.*FD_QD_p;
329 if idx < obj.StatesNum
330 mu_N = obj.mu_QD(jdx);
331 FD_QD_p = obj.Fermi(obj.Evec-mu_N-obj.Ec);
333 tmp = tmp - 2*1i*obj.TunnelingRates{kdx}(idx+1,:).*FD_lead_p{kdx}.*FD_QD_m;
335 tmp = obj.SimphsonInt( tmp.*deltaEvec );
336 SelfEnergy(jdx, idx) = SelfEnergy(jdx, idx) + tmp;
344 obj.SelfEnergy = SelfEnergy;
349 %% CalcTunnelingRates
350 %> @brief Determine the tunneling rates
for all energy values in the energy array Evec
for a given gateVoltage
351 %> @
param gateVoltage The back gate voltage in units of the energy unit used in the Hamiltonian parameters.
352 function CalcTunnelingRates( obj, gateVoltage )
354 % create energy array
if it is empty
355 if isempty( obj.Evec )
356 obj.CreateEnergyArray( 'tuned_contact', 'symmetric' );
359 lead_num = length( obj.junction.Interface_Regions );
361 % preallocating arrays for the energy resolved tunneling rates
362 TunnelingRates = zeros( length(obj.Evec), obj.StatesNum, lead_num );
366 % creating handles and temporary variables
368 junction_loc = obj.junction;
369 hCalcTunnelingRate = @obj.CalcTunnelingRate;
371 % starting parallel pool
372 poolmanager =
Parallel( obj.junction.FL_handles.Read('
Opt') );
373 poolmanager.openPool();
376 % calculating the tunneling rates
377 %for idx = 1:length(Evec)
378 parfor (idx = 1:length(Evec), poolmanager.NumWorkers)
381 TunnelingRates_tmp = feval( hCalcTunnelingRate, Energy, gateVoltage, 'junction', junction_loc );
383 % contact resolved tunneling rates
384 for iidx = 1:lead_num
385 TunnelingRates(idx, :, iidx) = TunnelingRates_tmp(:,iidx);
390 %> closing the parallel pool
391 poolmanager.closePool();
393 obj.TunnelingRates = cell( lead_num, 1);
394 for iidx = 1:length( obj.junction.Interface_Regions )
395 obj.TunnelingRates{iidx} = transpose(TunnelingRates(:,:,iidx));
401 %
for kdx = 1:obj.StatesNum
402 % plot( obj.Evec, real(obj.TunnelingRates{1}(kdx,:)))
408 %> @brief Determine the tunneling rate
for a given Energy and gateVoltage
409 %> @
param Energy The current energy value in units of the energy unit used in the Hamiltonian parameters.
410 %> @
param gateVoltage The back gate voltage in units of the energy unit used in the Hamiltonian parameters.
411 %> @
param varargin Cell array of optional parameters (https:
412 %> @
param 'junction' An instance of
class #
NTerminal (or its derived
class) representing the junction.
413 function TunnelingRates = CalcTunnelingRate( obj, Energy, gateVoltage, varargin )
416 p.addParameter(
'junction', obj.junction); %
for parallel computations
417 p.parse(varargin{:});
418 junction_loc = p.Results.junction;
421 obj.SetEnergy( Energy,
'junction', junction_loc )
423 recalculateSurface = 1:length( junction_loc.Interface_Regions );
425 % preallocating arrays
426 TunnelingRates = zeros( obj.StatesNum, length( junction_loc.Interface_Regions ) );
428 for idx = 1:obj.StatesNum
430 % creating
function handle for the charging energy effective one-electron potential
431 hChargingPotential = @(coordinates)( ones(length(coordinates.x),1)*obj.Ec*( obj.OccNumbers(idx)-gateVoltage/obj.Ec) );
433 % calculating the surface Green
operator of the QD
434 junction_loc.CalcFiniteGreensFunctionFromHamiltonian(
'scatterPotential', {obj.scatterPotential, hChargingPotential},
'onlyGinv',
true)
436 % Calculate the total Green Operator
438 'decimate',
false,
'constant_channels',
false,
'recalculateSurface', recalculateSurface, ...
439 'SelfEnergy', obj.useSelfEnergy);
441 % leads are recalculated only
for idx=1
442 recalculateSurface = [];
444 % Calculate the spectral funciton
445 Spectral = (G - G
')/(2*pi*1i); %check this relation 447 % determine the sites corresponding to the leads 448 scatter_sites = junction_sites.Scatter.site_indexes; 450 for iidx = 1:length(junction_sites.Leads) 451 % determine the sites corresponding to the leads 452 lead_sites = junction_sites.Leads{iidx}.site_indexes; 454 % determine the coupling matrix and its adjungate 455 coupling = Ginverz( lead_sites, scatter_sites); 456 coupling_adj = Ginverz( scatter_sites, lead_sites); 458 % calculating the tunneling rate 459 TunnelingRates(idx, iidx) = trace( coupling_adj* Spectral(lead_sites, lead_sites) * coupling* Spectral(scatter_sites, scatter_sites)); 469 %% SetChemicalPotentials 470 %> @brief Manually sets the chemical potentials corresponding to the given single-electron doping levels. 471 %> @param doping_levels The user defined single-electron doping levels obatined from the calculated density of states. 472 %> @param gateVoltage The back gate voltage in units of the energy unit used in the Hamiltonian parameters. 473 function SetChemicalPotentials( obj, doping_levels, gateVoltage ) 475 % setting the number of energy levels relevant in the calculations 476 obj.StatesNum = length(doping_levels); 478 % setting the occupation numbers 479 % charge neutral occupation is set to be the closest to the zero energy level. 480 [~, charge_neutral_index] = min( abs(doping_levels) ); 481 obj.OccNumbers = (1:obj.StatesNum) - charge_neutral_index; 483 % calculating the chemical potentials icluding the charging energy 484 obj.mu_QD = doping_levels + obj.Ec*(obj.OccNumbers - gateVoltage/obj.Ec); 492 %> @brief Initializes class attributes. 493 function Initialize(obj) 498 obj.bias_max = 10*obj.k_B*obj.T; 501 obj.InputParsing( obj.varargin{:} ); 513 methods (Access=protected) 517 %> @brief Parses the optional parameters for the class constructor. 518 %> @param varargin Cell array of optional parameters (https://www.mathworks.com/help/matlab/ref/varargin.html): 519 %> @param 'T
' The absolute temperature in Kelvins. 520 %> @param 'silent
' Set true to suppress output messages. 521 %> @param 'scatterPotential
' A function handle y=f( #coordinates coords ) or y=f( #CreateHamiltonians CreateH, E ) of the potential across the junction. 522 %> @param 'useSelfEnergy
' Logical value. Set true (default) to solve the Dyson equation with the self energies of the leads, or false to use the surface Green operators. 523 %> @param 'gfininvfromHamiltonian
' Logical value. Set true calculate the surface Greens function of the scattering region from the Hamiltonaian of the scattering region, or false (default) to calculate it by the fast way (see Phys. Rev. B 90, 125428 (2014) for details). 524 %> @param 'junction
' An instance of a class #NTerminal or its subclass describing the junction. 525 %> @param 'bias_max
' The maximal bias to be used in the calculations 526 %> @param 'Edb
' The number of the energy points in the attribute #Evec 527 %> @param 'Ec
' The charging energy in the same units as the Hamiltonians. 528 function InputParsing( obj, varargin ) 531 p.addParameter('T
', obj.T); 532 p.addParameter('silent
', 0); 533 p.addParameter('scatterPotential
', []); 534 p.addParameter('junction
', []); 535 p.addParameter('gfininvfromHamiltonian
', false); 536 p.addParameter('useSelfEnergy
', true); 537 p.addParameter('Ec
', obj.Ec); 538 p.addParameter('bias_max
', obj.bias_max); % The maximal bias to be used in the calculations 539 p.addParameter('Edb
', obj.Edb); % The number of the energy points in the attribute Evec 542 p.parse( varargin{:}); 544 InputParsing@Density( obj, 'T
', p.Results.T, ... 545 'junction
', p.Results.junction, ... 546 'scatterPotential
', p.Results.scatterPotential, ... 547 'gfininvfromHamiltonian
', p.Results.gfininvfromHamiltonian, ... 548 'useSelfEnergy
', p.Results.useSelfEnergy); 550 obj.Ec = p.Results.Ec; 551 obj.bias_max = p.Results.bias_max; 552 obj.Edb = p.Results.Edb; 555 error(['EQuUs:Utils:
', class(obj.junction), ':InputParsing
'], 'Maximal bias should be greater than zero.
'); 562 end % protected methods A class describing an N-terminal geometry for equilibrium calculations mostly in the zero temperature...
A class for controlling the parallel pool for paralell computations.
Structure Opt contains the basic computational parameters used in EQuUs.
A class to process transport calculations on quantum dots.
A class to calculate the I-V curve for a two terminal setup, based on the non-equilibrium Greens func...
function Transport(Energy, B)
Calculates the conductance at a given energy value.
Structure containg the energy resolved density of states.
A class to calculate the onsite desnity useful for self-consistent calculations.
Structure param contains data structures describing the physical parameters of the scattering center ...
Structure junction_sites contains data to identify the individual sites of the leads,...