The Elk Code
dos.f90
Go to the documentation of this file.
1 
2 ! Copyright (C) 2002-2008 J. K. Dewhurst, S. Sharma and C. Ambrosch-Draxl.
3 ! This file is distributed under the terms of the GNU General Public License.
4 ! See the file COPYING for license details.
5 
6 !BOP
7 ! !ROUTINE: dos
8 ! !INTERFACE:
9 subroutine dos(fext,tocc,occsvp)
10 ! !USES:
11 use modmain
12 use modomp
13 use modtest
14 ! !INPUT/OUTPUT PARAMETERS:
15 ! fext : filename extension (in,character(*))
16 ! tocc : .true. if just the occupied orbitals should contribute to the DOS
17 ! (in,logical)
18 ! occsvp : occupation numbers of second-variational orbitals
19 ! (in,real(nstsv,nkpt))
20 ! !DESCRIPTION:
21 ! Produces a total and partial density of states (DOS) for plotting. The total
22 ! DOS is written to the file {\tt TDOS.OUT} while the partial DOS is written
23 ! to the file {\tt PDOS\_Sss\_Aaaaa.OUT} for atom {\tt aaaa} of species
24 ! {\tt ss}. In the case of the partial DOS, each symmetrised
25 ! $(l,m)$-projection is written consecutively and separated by blank lines.
26 ! If the global variable {\tt lmirep} is {\tt .true.}, then the density matrix
27 ! from which the $(l,m)$-projections are obtained is first rotated into a
28 ! irreducible representation basis, i.e. one that block diagonalises all the
29 ! site symmetry matrices in the $Y_{lm}$ basis. Eigenvalues of a quasi-random
30 ! matrix in the $Y_{lm}$ basis which has been symmetrised with the site
31 ! symmetries are written to {\tt ELMIREP.OUT}. This allows for identification
32 ! of the irreducible representations of the site symmetries, for example $e_g$
33 ! or $t_{2g}$, by the degeneracies of the eigenvalues. In the plot, spin-up is
34 ! made positive and spin-down negative. See the routines {\tt gendmatk} and
35 ! {\tt brzint}.
36 !
37 ! !REVISION HISTORY:
38 ! Created January 2004 (JKD)
39 ! Parallelised and included sum over m, November 2009 (F. Cricchio)
40 !EOP
41 !BOC
42 implicit none
43 ! arguments
44 character(*), intent(in) :: fext
45 logical, intent(in) :: tocc
46 real(8), intent(in) :: occsvp(nstsv,nkpt)
47 ! local variables
48 logical tspndg,tlmdg
49 integer nsk(3),ik,jk,ist,iw
50 integer nsd,ispn,sps(2)
51 integer is,ia,ias,nthd
52 integer l0,l1,l,lm
53 real(8) dw,vl(3),vc(3)
54 complex(8) su2(2,2),b(2,2)
55 character(256) fname
56 ! allocatable arrays
57 ! low precision for band/spin character array saves memory
58 real(4), allocatable :: bc(:,:,:,:,:),sc(:,:,:)
59 real(8), allocatable :: w(:),e(:,:,:),f(:,:),g(:)
60 real(8), allocatable :: dt(:,:),dp(:,:,:),elm(:,:)
61 complex(8), allocatable :: ulm(:,:,:),dmat(:,:,:,:,:),sdmat(:,:,:)
62 complex(8), allocatable :: apwalm(:,:,:,:,:),evecfv(:,:,:),evecsv(:,:)
63 if (dosssum) then
64  nsd=1
65 else
66  nsd=nspinor
67 end if
68 if (dosmsum) then
69  l0=0; l1=lmaxdb
70 else
71  l0=1; l1=lmmaxdb
72 end if
73 ! calculate only the diagonal parts of the density matrices by default
74 tspndg=.true.
75 tlmdg=.true.
76 allocate(bc(lmmaxdb,nspinor,natmtot,nstsv,nkptnr))
77 allocate(sc(nspinor,nstsv,nkptnr))
78 ! generate unitary matrices which convert the Yₗₘ basis into the irreducible
79 ! representation basis of the symmetry group at each atomic site
80 if (lmirep) then
81  allocate(elm(lmmaxdb,natmtot),ulm(lmmaxdb,lmmaxdb,natmtot))
82  call genlmirep(elm,ulm)
83 ! write the eigenvalues of a pseudorandom matrix symmetrised by the site
84 ! symmetries in the Yₗₘ basis
85  call writeelmirep(fext,elm)
86  tlmdg=.false.
87 end if
88 ! compute the SU(2) operator used for rotating the density matrix to the
89 ! desired spin-quantisation axis
90 if (spinpol) call sqasu2(sqaxis,tspndg,su2)
91 ! begin parallel loop over k-points
92 call holdthd(nkptnr,nthd)
93 !$OMP PARALLEL DEFAULT(SHARED) &
94 !$OMP PRIVATE(apwalm,evecfv,evecsv,dmat,sdmat) &
95 !$OMP PRIVATE(jk,ispn,vl,vc) &
96 !$OMP PRIVATE(ias,is,ist,lm,b) &
97 !$OMP NUM_THREADS(nthd)
98 allocate(apwalm(ngkmax,apwordmax,lmmaxapw,natmtot,nspnfv))
99 allocate(evecfv(nmatmax,nstfv,nspnfv),evecsv(nstsv,nstsv))
100 allocate(dmat(lmmaxdb,nspinor,lmmaxdb,nspinor,nstsv))
101 allocate(sdmat(nspinor,nspinor,nstsv))
102 !$OMP DO SCHEDULE(DYNAMIC)
103 do ik=1,nkptnr
104 ! equivalent reduced k-point
105  jk=ivkik(ivk(1,ik),ivk(2,ik),ivk(3,ik))
106 ! loop over first-variational spins
107  do ispn=1,nspnfv
108  vl(:)=vkl(:,ik)
109  vc(:)=vkc(:,ik)
110 ! spin-spiral case
111  if (spinsprl) then
112  if (ispn == 1) then
113  vl(:)=vl(:)+0.5d0*vqlss(:)
114  vc(:)=vc(:)+0.5d0*vqcss(:)
115  else
116  vl(:)=vl(:)-0.5d0*vqlss(:)
117  vc(:)=vc(:)-0.5d0*vqcss(:)
118  end if
119  end if
120 ! find the matching coefficients
121  call match(ngk(ispn,ik),vgkc(:,:,ispn,ik),gkc(:,ispn,ik), &
122  sfacgk(:,:,ispn,ik),apwalm(:,:,:,:,ispn))
123  end do
124 ! get the eigenvectors from file for non-reduced k-point
125  call getevecfv('.OUT',0,vkl(:,ik),vgkl(:,:,:,ik),evecfv)
126  call getevecsv('.OUT',0,vkl(:,ik),evecsv)
127  do ias=1,natmtot
128  is=idxis(ias)
129 ! generate the density matrix for all states
130  call gendmatk(tspndg,tlmdg,0,lmaxdb,ias,nstsv,[0],ngk(:,ik),apwalm, &
131  evecfv,evecsv,lmmaxdb,dmat)
132 ! convert (l,m) part to an irreducible representation if required
133  if (.not.tlmdg) call dmatulm(ulm(:,:,ias),dmat)
134 ! spin rotate the density matrices to desired spin-quantisation axis
135  if (.not.tspndg) call dmatsu2(lmmaxdb,su2,dmat)
136 ! determine the band characters from the density matrix
137  do ist=1,nstsv
138  do ispn=1,nspinor
139  do lm=1,lmmaxdb
140  bc(lm,ispn,ias,ist,ik)=dmat(lm,ispn,lm,ispn,ist)%re
141  end do
142  end do
143  end do
144  end do
145 ! compute the spin density matrices of the second-variational states
146  call gensdmat(evecsv,sdmat)
147 ! spin rotate the density matrices to desired spin-quantisation axis
148  if (.not.tspndg) then
149  do ist=1,nstsv
150  call z2mm(su2,sdmat(:,:,ist),b)
151  call z2mmct(b,su2,sdmat(:,:,ist))
152  end do
153  end if
154  do ist=1,nstsv
155  do ispn=1,nspinor
156  sc(ispn,ist,ik)=sdmat(ispn,ispn,ist)%re
157  end do
158  end do
159 end do
160 !$OMP END DO
161 deallocate(apwalm,evecfv,evecsv,dmat,sdmat)
162 !$OMP END PARALLEL
163 call freethd(nthd)
164 allocate(w(nwplot),e(nstsv,nkptnr,nspinor))
165 allocate(dt(nwplot,nsd),dp(nwplot,l0:l1,nsd))
166 ! generate frequency grid
167 dw=(wplot(2)-wplot(1))/dble(nwplot)
168 do iw=1,nwplot
169  w(iw)=dw*dble(iw-1)+wplot(1)
170 end do
171 ! number of subdivisions used for interpolation in the Brillouin zone
172 nsk(:)=max(ngrkf/ngridk(:),1)
173 ! sign for spin in DOS plot
174 sps(1)=1; sps(2)=-1
175 !-------------------!
176 ! total DOS !
177 !-------------------!
178 allocate(f(nstsv,nkptnr),g(nwplot))
179 dt(:,:)=0.d0
180 do ispn=1,nspinor
181  do ik=1,nkptnr
182  jk=ivkik(ivk(1,ik),ivk(2,ik),ivk(3,ik))
183  do ist=1,nstsv
184 ! subtract the Fermi energy
185  e(ist,ik,ispn)=evalsv(ist,jk)-efermi
186 ! use diagonal of spin density matrix for weight
187  f(ist,ik)=sc(ispn,ist,ik)
188  if (tocc) then
189  f(ist,ik)=f(ist,ik)*occsvp(ist,jk)
190  else
191  f(ist,ik)=f(ist,ik)*occmax
192  end if
193  end do
194  end do
195 ! integrate over the Brillouin zone
196  call brzint(nswplot,ngridk,nsk,ivkiknr,nwplot,wplot,nstsv,nstsv,e(:,:,ispn), &
197  f,g)
198  if (dosssum) then
199  dt(:,1)=dt(:,1)+g(:)
200  else
201  dt(:,ispn)=g(:)
202  end if
203 end do
204 deallocate(f,g)
205 ! output to file
206 open(50,file='TDOS'//trim(fext),form='FORMATTED',action='WRITE')
207 do ispn=1,nsd
208  do iw=1,nwplot
209  write(50,'(2G18.10)') w(iw),dt(iw,ispn)*sps(ispn)
210  end do
211  write(50,*)
212 end do
213 close(50)
214 ! skip the partial DOS if required
215 if (.not.tpdos) goto 10
216 !---------------------!
217 ! partial DOS !
218 !---------------------!
219 call holdthd(lmaxdb+1,nthd)
220 !$OMP PARALLEL DEFAULT(SHARED) &
221 !$OMP PRIVATE(f,g,ias,is,ia,ispn) &
222 !$OMP PRIVATE(l,lm,ik,jk,ist) &
223 !$OMP NUM_THREADS(nthd)
224 allocate(f(nstsv,nkptnr),g(nwplot))
225 do ias=1,natmtot
226  is=idxis(ias)
227  ia=idxia(ias)
228 !$OMP BARRIER
229 !$OMP SINGLE
230  dp(:,:,:)=0.d0
231 !$OMP END SINGLE
232  do ispn=1,nspinor
233 !$OMP DO SCHEDULE(DYNAMIC)
234  do l=0,lmaxdb
235  do lm=l**2+1,(l+1)**2
236  do ik=1,nkptnr
237  jk=ivkik(ivk(1,ik),ivk(2,ik),ivk(3,ik))
238  do ist=1,nstsv
239  f(ist,ik)=bc(lm,ispn,ias,ist,ik)
240  if (tocc) then
241  f(ist,ik)=f(ist,ik)*occsvp(ist,jk)
242  else
243  f(ist,ik)=f(ist,ik)*occmax
244  end if
245  end do
246  end do
247  call brzint(nswplot,ngridk,nsk,ivkiknr,nwplot,wplot,nstsv,nstsv, &
248  e(:,:,ispn),f,g)
249  if (dosmsum) then
250  if (dosssum) then
251  dp(:,l,1)=dp(:,l,1)+g(:)
252  else
253  dp(:,l,ispn)=dp(:,l,ispn)+g(:)
254  end if
255  else
256  if (dosssum) then
257  dp(:,lm,1)=dp(:,lm,1)+g(:)
258  else
259  dp(:,lm,ispn)=g(:)
260  end if
261  end if
262 ! subtract from interstitial DOS
263 !$OMP CRITICAL(dos_)
264  if (dosssum) then
265  dt(:,1)=dt(:,1)-g(:)
266  else
267  dt(:,ispn)=dt(:,ispn)-g(:)
268  end if
269 !$OMP END CRITICAL(dos_)
270  end do
271  end do
272 !$OMP END DO
273  end do
274 ! output to file
275 !$OMP SINGLE
276  write(fname,'("PDOS_S",I2.2,"_A",I4.4)') is,ia
277  open(50,file=trim(fname)//trim(fext),form='FORMATTED',action='WRITE')
278  do ispn=1,nsd
279  do l=l0,l1
280  do iw=1,nwplot
281  write(50,'(2G18.10)') w(iw),dp(iw,l,ispn)*sps(ispn)
282  end do
283  write(50,*)
284  end do
285  end do
286  close(50)
287 !$OMP END SINGLE
288 end do
289 deallocate(f,g)
290 !$OMP END PARALLEL
291 call freethd(nthd)
292 !--------------------------!
293 ! interstitial DOS !
294 !--------------------------!
295 open(50,file='IDOS'//trim(fext),form='FORMATTED',action='WRITE')
296 do ispn=1,nsd
297  do iw=1,nwplot
298  write(50,'(2G18.10)') w(iw),dt(iw,ispn)*sps(ispn)
299  end do
300  write(50,*)
301 end do
302 close(50)
303 10 continue
304 ! write the total DOS to test file
305 call writetest(10,'total DOS',nv=nwplot*nsd,tol=2.d-2,rva=dt)
306 deallocate(bc,sc,w,e,dt,dp)
307 if (lmirep) deallocate(elm,ulm)
308 end subroutine
309 !EOC
310 
integer nmatmax
Definition: modmain.f90:853
integer ngrkf
Definition: modmain.f90:1075
real(8) efermi
Definition: modmain.f90:907
subroutine writetest(id, descr, nv, iv, iva, tol, rv, rva, zv, zva)
Definition: modtest.f90:16
pure subroutine gensdmat(evecsv, sdmat)
Definition: gensdmat.f90:10
subroutine getevecsv(fext, ikp, vpl, evecsv)
Definition: getevecsv.f90:7
real(8), dimension(:,:), allocatable evalsv
Definition: modmain.f90:921
logical spinpol
Definition: modmain.f90:228
integer lmmaxapw
Definition: modmain.f90:199
integer ngkmax
Definition: modmain.f90:499
subroutine getevecfv(fext, ikp, vpl, vgpl, evecfv)
Definition: getevecfv.f90:10
subroutine match(ngp, vgpc, gpc, sfacgp, apwalm)
Definition: match.f90:10
logical spinsprl
Definition: modmain.f90:283
Definition: modomp.f90:6
subroutine dmatulm(ulm, dmat)
Definition: dmatulm.f90:10
integer, dimension(:,:,:), allocatable ivkik
Definition: modmain.f90:467
subroutine brzint(nsm, ngridk, nsk, ivkik, nw, wint, n, ld, e, f, g)
Definition: brzint.f90:10
subroutine sqasu2(sqaxis, tsqaz, su2)
Definition: sqasu2.f90:7
real(8), dimension(3) vqlss
Definition: modmain.f90:293
integer nkptnr
Definition: modmain.f90:463
logical dosmsum
Definition: modmain.f90:1087
complex(8), dimension(:,:,:,:), allocatable sfacgk
Definition: modmain.f90:509
real(8), dimension(:,:), allocatable vkc
Definition: modmain.f90:473
subroutine genlmirep(elm, ulm)
Definition: genlmirep.f90:10
integer lmmaxdb
Definition: modmain.f90:1081
pure subroutine z2mm(a, b, c)
Definition: z2mm.f90:10
real(8), dimension(2) wplot
Definition: modmain.f90:1079
integer, dimension(:,:), allocatable ngk
Definition: modmain.f90:497
logical lmirep
Definition: modmain.f90:1098
real(8), dimension(3) sqaxis
Definition: modmain.f90:1101
real(8) occmax
Definition: modmain.f90:901
pure subroutine z2mmct(a, b, c)
Definition: z2mmct.f90:10
integer lmaxdb
Definition: modmain.f90:1081
real(8), dimension(:,:,:,:), allocatable vgkl
Definition: modmain.f90:503
integer, dimension(3) ngridk
Definition: modmain.f90:448
subroutine dos(fext, tocc, occsvp)
Definition: dos.f90:10
logical tpdos
Definition: modmain.f90:1085
integer nspinor
Definition: modmain.f90:267
real(8), dimension(:,:,:,:), allocatable vgkc
Definition: modmain.f90:505
subroutine gendmatk(tspndg, tlmdg, lmin, lmax, ias, nst, idx, ngp, apwalm, evecfv, evecsv, ld, dmat)
Definition: gendmatk.f90:8
real(8), dimension(:,:), allocatable vkl
Definition: modmain.f90:471
real(8), dimension(3) vqcss
Definition: modmain.f90:295
integer apwordmax
Definition: modmain.f90:760
integer, dimension(maxatoms *maxspecies) idxis
Definition: modmain.f90:44
logical dosssum
Definition: modmain.f90:1089
real(8), dimension(:,:,:), allocatable gkc
Definition: modmain.f90:507
subroutine writeelmirep(fext, elm)
Definition: writeelmirep.f90:7
integer nswplot
Definition: modmain.f90:1077
subroutine freethd(nthd)
Definition: modomp.f90:106
subroutine holdthd(nloop, nthd)
Definition: modomp.f90:78
integer, dimension(maxatoms *maxspecies) idxia
Definition: modmain.f90:45
integer natmtot
Definition: modmain.f90:40
integer nwplot
Definition: modmain.f90:1073
subroutine dmatsu2(lmmax, su2, dmat)
Definition: dmatsu2.f90:10
integer nstfv
Definition: modmain.f90:887
integer, dimension(:,:), allocatable ivk
Definition: modmain.f90:465
integer nspnfv
Definition: modmain.f90:289
integer, dimension(:,:,:), allocatable ivkiknr
Definition: modmain.f90:469