Eötvös Quantum Utilities  v4.9.146
Providing the Horsepowers in the Quantum Realm
Density.m
Go to the documentation of this file.
1 %% Eotvos Quantum Transport Utilities - Density
2 % Copyright (C) 2009-2017 Peter Rakyta, Ph.D.
3 %
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.
8 %
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.
13 %
14 % You should have received a copy of the GNU General Public License
15 % along with this program. If not, see http://www.gnu.org/licenses/.
16 %
17 %> @addtogroup utilities Utilities
18 %> @{
19 %> @file Density.m
20 %> @brief A class to calculate the onsite desnity useful for self-consistent calculations.
21 %> @}
22 %> @brief A class to calculate the onsite desnity useful for self-consistent calculations.
23 %> @Available
24 %> EQuUs v4.9 or later
25 %%
26 classdef Density < DOS %NEW superclass
27 
28  properties ( Access = public )
29 
30  end
31 
32 
33 
34 methods (Access=public)
35 
36 %% Contructor of the class
37 %> @brief Constructor of the class.
38 %> @param Opt An instance of structure #Opt.
39 %> @param varargin Cell array of optional parameters. For details see #InputParsing.
40 %> @return An instance of the class
41  function obj = Density( Opt, varargin )
42 
43  obj = obj@DOS( Opt, varargin{:} );
44 
45  if strcmpi(class(obj), 'Density')
46  obj.InputParsing( obj.varargin{:} );
47  end
48 
49 
50  end
51 
52 
53 
54 %% DensityCalc
55 %> @brief Calculates the onsite desnity using the method in Nanotechnology 25 (2014), 465201
56 %> @param varargin Cell array of optional parameters:
57 %> @param 'Edb' The number of the energy points over the contour integral.
58 %> @param 'DeltaPhi' A parameter to control the incident angle of the integration contour near the real axis. (Default value is $$\Delta\Phi=0.5\pi$$.
59 %> @param 'Evec' The complex energy points in case of custom integration path. (Overrides all other optional parameters.)
60 %> @param 'Emin' The minimum of the energy array.
61 %> @param 'JustScatter' Logical value. True if only an isolated scattering center should be considered in the self-consistent calculations, false otherwise.
62 %> @return An array of the calculated density and a structure describing the geometry of the sites.
63  function [density_vec, junction_sites] = DensityCalc( obj, varargin )
64 
65  p = inputParser;
66  p.addParameter('Edb', 511 ); % number of energy points on the contour
67  p.addParameter('DeltaPhi', 0.5*pi );
68  p.addParameter('Evec', [] );
69  p.addParameter('Emin', [] );
70  p.addParameter('JustScatter', false ); %logical value. True if only an isolated scattering center should be considered in the self-consistent calculations, false otherwise.
71 
72  p.parse(varargin{:});
73  Edb = p.Results.Edb;
74  Evec = p.Results.Evec;
75  DeltaPhi = p.Results.DeltaPhi;
76  Emin = p.Results.Emin;
77  JustScatter = p.Results.JustScatter;
78 
79  obj.create_Hamiltonians( 'junction', obj.junction )
80 
81  phivec = (0.5 + 0.5*sin( -0.5*pi:pi/(Edb+1):0.5*pi )) * DeltaPhi + (pi-DeltaPhi)/2;
82 
83  obj.display(['EQuUs:Utils:', class(obj), ':DensityCalc: Calculating the on-site density.'], 1)
84 
85  if JustScatter && isempty(Emin)
86  obj.create_scatter();
87  Hscatter = obj.junction.CreateH.Read('Hscatter');
88  Emin = -abs(eigs( Hscatter, 1, 'lm'))*1.05;
89  elseif isempty(Emin)
90  obj.getBandWidth();
91  Emin = min([-obj.BandWidth.Lead.Emax,-obj.BandWidth.Scatter.Emax])*1.2;
92  end
93 
94 
95  if isempty(Evec)
96  Emax = obj.junction.getFermiEnergy();
97 
98  if Emin >= Emax
99  density_vec = 0;
100  return
101  end
102 
103  radius = abs( Emax-Emin) /2;
104  R = radius/sin(DeltaPhi/2);
105 
106  Evec = R*(cos(phivec) + 1i*sin(phivec)) - radius + Emax - 1i*R*sin((pi-DeltaPhi)/2);
107  end
108  deltaEvec = [0, diff(Evec)];
109 
110  obj.display(['EQuUs:Utils:', class(obj), ':DensityCalc: Calculating the density between Emin = ', num2str(min(Evec)),' and Emax = ',num2str(max(Evec)),],1);
111 
112 
113 
114  %> determine the number of sites in the calculations to preallocate memory
115  if JustScatter
116  Hscatter = obj.junction.CreateH.Read('Hscatter');
117  number_of_sites = size(Hscatter,1);
118  else
119  Hscatter = obj.junction.CreateH.Read('Hscatter');
120  Leads = obj.junction.FL_handles.Read('Leads');
121  size_K0_leads = zeros(length(Leads), 1);
122  size_K0_interface = zeros(length(Leads), 1);
123  for kdx = 1:length(Leads)
124  Leads{kdx}.Calc_Effective_Hamiltonians( Evec(1) );
125  K0_lead = Leads{kdx}.Get_Effective_Hamiltonians();
126  size_K0_leads(kdx) = size(K0_lead,1);
127 
128  obj.junction.CreateInterface( kdx )
129  K0_interface = obj.junction.Interface_Regions{kdx}.Get_Effective_Hamiltonians();
130  size_K0_interface(kdx) = size(K0_interface,1);
131  end
132 
133  if obj.useSelfEnergy
134  number_of_sites = size(Hscatter,1) + sum(size_K0_interface); %2*interface region
135  else
136  number_of_sites = size(Hscatter,1) + sum(size_K0_interface) + sum(size_K0_leads); %2*lead + 2*interface region
137  end
138  end
139 
140  %> preallocate memory for Densitysurf
141  Densitysurf = complex(zeros( length(Evec), length(obj.T), number_of_sites ));
142 
143  % starting parallel pool
144  poolmanager = Parallel( obj.junction.FL_handles.Read('Opt') );
145  poolmanager.openPool();
146 
147  %> creating function handles for parallel for
148  hdisplay = @obj.display;
149  hSetEnergy = @obj.SetEnergy;
150  hcomplexDensity = @obj.complexDensity;
151  hcreate_scatter = @obj.create_scatter;
152 
153  junction_loc = obj.junction;
154 
155  junction_sites = cell(length(Evec),1);
156 
157  %for iidx = 1:length(Evec)
158  parfor (iidx = 1:length(Evec), poolmanager.NumWorkers)
159 
160  %> setting the current energy
161  feval(hSetEnergy, Evec(iidx), 'junction', junction_loc );
162 
163  %> creating the Hamiltonian of the scattering region
164  feval(hcreate_scatter, 'junction', junction_loc );
165 
166  try
167  %> evaluating the energy resolved density
168  [densityvec2int, junction_sites_tmp] = feval(hcomplexDensity, junction_loc, JustScatter);
169  catch errCause
170  feval(hdisplay, ['EQuUs:Utils:', class(obj), ':DensityCalc: Error at energy point E = ', num2str(Evec(iidx)), ' caused by:'], 1);
171  feval(hdisplay, errCause.identifier, 1 );
172  for jjjdx = 1:length(errCause.stack)
173  feval(hdisplay, ['file: ',errCause.stack(jjjdx).file], 1 );
174  feval(hdisplay, ['name: ',errCause.stack(jjjdx).name], 1 );
175  feval(hdisplay, ['line: ', num2str(errCause.stack(jjjdx).line)], 1 );
176  end
177  feval(hdisplay, ['EQuUs:Utils:', class(obj), ':DensityCalc: Giving NaN for the calculated current at the given energy point and phase difference.'], 1);
178  densityvec2int = NaN;
179  end
180 
181  Densitysurf( iidx, :, : ) = densityvec2int;
182 
183  if iidx == 1
184  junction_sites{iidx} = junction_sites_tmp;
185  end
186 
187  end
188 
189  %> closing the parallel pool
190  poolmanager.closePool();
191 
192 
193  %> calculating the contour integrals
194  density_vec = cell( size(obj.T) );
195  for kkdx = 1:length( obj.T )
196  density_vec{kkdx} = zeros(number_of_sites, 1);
197  for jjdx = 1:number_of_sites
198  densityvec2integrate = Densitysurf(:,kkdx,jjdx);
199  % omitting NaNs by substituting interpolated values
200  indexes = isnan(densityvec2integrate);
201  indexesall = 1:length(densityvec2integrate);
202 
203  densityvec2integrate(indexes) = interp1(indexesall(~indexes), densityvec2integrate(~indexes), indexesall(indexes), 'spline' );
204  density = imag(obj.SimphsonInt( densityvec2integrate.*transpose(deltaEvec) ))/(pi);
205  density_vec{kkdx}( jjdx ) = density_vec{kkdx}( jjdx ) + density;
206  end
207  end
208  if length(obj.T) == 1
209  density_vec = density_vec{1};
210  end
211 
212  obj.display(['EQuUs:Utils:', class(obj), ':DensityCalc: Process finished.'], 1)
213 
214  %reset the system for a new calculation
215  obj.InputParsing( obj.varargin{:} );
216 
217  % selecting the junction_sites from the cell array
219 
220 
221 
222 
223  end
224 
225 
226 
227 %% DensityCalcSmall
228 %> @brief Calculates the onsite desnity using the method in Nanotechnology 25 (2014), 465201. This method is usable for small isolated scattering centers for which an exact diagonalization can be performed
229 %> @param num_occupied_states Number of occupied states
230 %> @return An array of the calculated density and a structure describing the geometry of the sites.
231  function [density_vec, junction_sites, num_occupied_states] = DensityCalcSmall( obj, num_occupied_states )
232 
233  Max_size = 10000;
234  obj.create_scatter();
235  Hscatter = obj.junction.CreateH.Read('Hscatter');
236  coordinates = obj.junction.CreateH.Read('coordinates');
237 
238  if size(Hscatter,1) > Max_size
239  error('EQuUs:Utils:Density:DensityCalcSmall', 'Matrix size is too large');
240  density_vec = [];
241  junction_sites = [];
242  return
243  end
244 
245 
246  [eigenvectors, eigenvalues] = eig(full(Hscatter),'nobalance');
247 
248  eigenvalues = diag(eigenvalues);
249 
250  [eigenvalues,IX] = sort(eigenvalues, 'ascend');
251 
252  %eigenvalues = eigenvalues( 1:num_occupied_states );
253 
254  if ~exist( 'num_occupied_states', 'var') || isempty(num_occupied_states)
255  num_occupied_states = find(eigenvalues < obj.junction.EF, 1, 'last');
256  end
257 
258 
259  eigenvectors = eigenvectors( :, IX(1:num_occupied_states) );
260  density_vec = sum(transpose(eigenvectors.^2));
261  density_vec = reshape( density_vec, numel(density_vec), 1);
262 
263 
264  %>creating site indexes corresponding to the elements of the density vector
265  junction_sites = structures('junction_sites');
266  junction_sites.Scatter = structures('sites');
267  junction_sites.Scatter.coordinates = coordinates;
268  junction_sites.Scatter.site_indexes = 1:size(Hscatter,1);
269 
270 
271  end
272 
273 
274 
275 %% getBandWidth
276 %> @brief Determines the band width of the leads and of the scattering region.
277 %> @return ret An instance of structure BandWidth containing the bandwidths.
278  function ret = getBandWidth( obj )
279  obj.display('Getting Bandwidths', 1);
280 
281  if ~isempty(obj.BandWidth)
282  return
283  end
284 
285  poolmanager = Parallel( obj.junction.FL_handles.Read('Opt') );
286  poolmanager.openPool();
287 
288  Surface_1 = obj.junction.FL_handles.SurfaceGreenFunctionCalculator(1, 'Just_Create_Hamiltonians', true, 'q', obj.junction.q, 'leadmodel', obj.junction.leadmodel, ...
289  'CustomHamiltonian', obj.junction.cCustom_Hamiltonians);
290  W = BandWidthCalculator( Surface_1 );
291 
292  param = obj.junction.FL_handles.Read( 'param' );
293  pair_potential = min([abs(param.Leads{1}.pair_potential), abs(param.Leads{2}.pair_potential)]);
294 
295  obj.BandWidth.Lead = structures('BandWidthLimits');
296  obj.BandWidth.Lead.Emin = abs(pair_potential);
297  obj.BandWidth.Lead.Emax = W;
298 
299 
300  if strcmpi( class(obj.junction), 'Ribbon' )
301  obj.junction.CreateRibbon('justHamiltonians', true);
302  W = BandWidthCalculator( obj.junction.Scatter_UC );
303  elseif strcmpi( class(obj.junction), 'NTerminal' )
304  obj.junction.CreateScatter();
305  W = 1.3*BandWidthCalculatorMolecule( obj.junction.CreateH ); % multiplied by 1.3 just for sure to include normal bound states
306  else
307  W = 0;
308  end
309  obj.BandWidth.Scatter = structures('BandWidthLimits');
310  obj.BandWidth.Scatter.Emin = 0;
311  obj.BandWidth.Scatter.Emax = W;
312 
313  poolmanager.closePool();
314 
315  ret = obj.BandWidth;
316 
317  %--------------------------------------------
318  % nested functions
319  function W = BandWidthCalculator( Scatter_UC )
320 
321  H0 = Scatter_UC.Read('H0');
322  if ~isempty( obj.junction.q )
323  H1_transverse = Scatter_UC.Read('H1_transverse');
324  H0 = H0 + H1_transverse*exp(1i*obj.junction.q) + H1_transverse'*exp(-1i*obj.junction.q);
325  end
326  H1 = Scatter_UC.Read('H1');
327  u = rand(size(H0,1));
328  u = u/norm(u);
329 
330  hgetMaxEigenvalue = @getMaxEigenvalue;
331  hsecular_H = @secular_H;
332  k = -pi:2*pi/50:pi;
333  arnoldi = zeros( length(k),1);
334  parfor (idx = 1:length(k), poolmanager.NumWorkers)
335  Heff = feval(hsecular_H,H0,H1,k(idx));
336  arnoldi(idx) = abs(feval(hgetMaxEigenvalue, Heff ));
337  end
338  W = max( arnoldi );
339 
340 
341  % --------------------------------------
342  % Hamiltonian for the secular equation
343  function H = secular_H(H0,H1,k)
344  H = H0 + H1*exp(1i*k) + H1'*exp(-1i*k);
345  end
346 
347  %--------------------------------------------
348  % getting the maximal eigenvalue with Arnoldi iteration
349  % Numerical Linear Algebra" by Trefethen and Bau. (p250) or
350  % http://en.wikipedia.org/wiki/Arnoldi_iteration
351  function ret = getMaxEigenvalue( Heff )
352  %u = rand(size(H0,1));
353  %u = u/norm(u);
354  maxIter = 1e2;
355  tolerance = 1e-5;
356  ret = 0;
357  lambda = 1;
358  for iidx=1:maxIter
359  u_new = Heff*u;
360  norm_new = norm(u_new);
361  lambda_new = norm_new/norm(u);
362 
363  if abs((lambda - lambda_new)/lambda) < tolerance
364  ret = lambda;
365  return
366  end
367  u = u_new/norm_new;
368  lambda = lambda_new;
369  end
370  end
371  end
372 
373 
374  %--------------------------------------------
375  function W = BandWidthCalculatorMolecule( CreateH )
376  Hscatter = CreateH.Read('Hscatter');
377  W = abs(eigs(Hscatter,1));
378  end
379 
380  % end nested functions
381 
382  end
383 
384 
385  end % public methods
386 
387 
388  methods (Access=protected)
389 
390 %% complexDensity
391 %> @brief Calculates the density at a complex energy
392 %> @param junction_loc An instance of class #NTerminal or its subclass describing the junction.
393 %> @param JustScatter Logical value. True if only an isolated scattering center should be considered in the self-consistent calculations, false otherwise.
394  function [density, junction_sites] = complexDensity( obj, junction_loc, JustScatter )
395 
396 
397  [spectral_function, junction_sites] = obj.complexSpectral( junction_loc, JustScatter );
398 
399 
400  fE = obj.Fermi(junction_loc.getEnergy());
401 
402  density = zeros(length( fE ), length(spectral_function) );
403 
404  for idx = 1:length( fE )
405  spectral_function_tmp = spectral_function;
406  if junction_loc.Opt.BdG
407  coordinates = junction_loc.CreateH.Read('coordinates');
408  BdG_indexes = coordinates.BdG_u;
409  spectral_function_tmp( BdG_indexes) = spectral_function_tmp( BdG_indexes)*fE(idx);
410  spectral_function_tmp( ~BdG_indexes) = spectral_function_tmp( ~BdG_indexes)*(1-fE(idx));
411  else
412  spectral_function_tmp = spectral_function_tmp*fE(idx);
413  end
414 
415  density(idx,:) = spectral_function_tmp;
416 
417  end
418 
419  end
420 
421 
422 
423 
424 
425 %% InputParsing
426 %> @brief Parses the optional parameters for the class constructor.
427 %> @param varargin Cell array of optional parameters (https://www.mathworks.com/help/matlab/ref/varargin.html):
428 %> @param 'T' The absolute temperature in Kelvins.
429 %> @param 'silent' Set true to suppress output messages.
430 %> @param 'scatterPotential' A function handle y=f( #coordinates coords ) or y=f( #CreateHamiltonians CreateH, E ) of the potential across the junction.
431 %> @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.
432 %> @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).
433 %> @param 'junction' An instance of a class #NTerminal or its subclass describing the junction.
434  function InputParsing( obj, varargin )
435 
436  p = inputParser;
437  p.addParameter('T', obj.T);
438  p.addParameter('scatterPotential', []);
439  p.addParameter('useSelfEnergy', true);
440  p.addParameter('gfininvfromHamiltonian', false);
441  p.addParameter('junction', []);
442 
443  p.parse( varargin{:});
444 
445  InputParsing@DOS( obj, 'T', p.Results.T, ...
446  'junction', p.Results.junction, ...
447  'scatterPotential', p.Results.scatterPotential, ...
448  'gfininvfromHamiltonian', p.Results.gfininvfromHamiltonian, ...
449  'useSelfEnergy', p.Results.useSelfEnergy);
450 
451 
452 
453  end %
454 
455 
456 end % protected methods
457 end
A class describing an N-terminal geometry for equilibrium calculations mostly in the zero temperature...
Definition: NTerminal.m:38
lead_param Leads
A list of structures lead_param containing the physical parameters for the scattering region.
Definition: structures.m:49
A class for controlling the parallel pool for paralell computations.
Definition: Parallel.m:26
Structure Opt contains the basic computational parameters used in EQuUs.
Definition: structures.m:60
function Transport(Energy, B)
Calculates the conductance at a given energy value.
function DensityCalc(filling_factor)
Calculates the density using the predefined graphene lattice framework (Ribbon class)
Structure containg the energy resolved density of states.
Definition: structures.m:196
function secular_H(H0, H1, k)
Hamiltonian for the secular equation.
function()
Structure BandWidthLimits contains the bandwidth limits.
Definition: structures.m:139
A class to calculate the onsite desnity useful for self-consistent calculations.
Definition: Density.m:26
Structure param contains data structures describing the physical parameters of the scattering center ...
Definition: structures.m:45
site_indexes
An array containing the site indexes of the given system part.
Definition: structures.m:191
Structure BandWidth describes the bandwidth in the lead and in the scattering center.
Definition: structures.m:130
Structure sites contains data to identify the individual sites in a matrix.
Definition: structures.m:187
coordinates
An instance of structure coordinates describing the geometry.
Definition: structures.m:189
sites Scatter
Structure sites describing the geometry of the scattering region.
Definition: structures.m:180
function structures(name)
function openPool()
Opens a parallel pool for parallel computations.
Structure junction_sites contains data to identify the individual sites of the leads,...
Definition: structures.m:176
A class to create and store Hamiltonian of the scattering region.