The Elk Code
tddftlru.f90
Go to the documentation of this file.
1 
2 ! Copyright (C) 2026 Wenhan Chen, J. K. Dewhurst and S. Sharma.
3 ! This file is distributed under the terms of the GNU General Public License.
4 ! See the file COPYING for license details.
5 
6 subroutine tddftlru
7 use modmain
8 use modulr
9 use modmpi
10 use modomp
11 implicit none
12 ! local variables
13 integer ik0,ik,iw,nm
14 integer ioc,i,j,n,nthd
15 character(128) fname
16 ! allocatable arrays
17 integer(omp_lock_kind), allocatable :: lock(:)
18 complex(8), allocatable :: evecu(:,:),pmat(:,:,:),vchi0(:,:,:)
19 complex(4), allocatable :: vchi0_sp(:,:,:)
20 complex(8), allocatable :: eps0(:,:,:),epsi(:,:,:),epsm(:,:,:)
21 ! no k-point reduction
23 reducek=0
24 ! initialise global variables
25 call init0
26 call init1
27 call init3
28 ! read the regular Kohn-Sham potential from file
29 call readstate
30 ! generate the first- and second-variational eigenvectors and eigenvalues for
31 ! the k+κ-point set
32 call genvsig
33 call linengy
34 call genapwlofr
35 call gensocfr
36 call genevfsv
37 ! initialise the ultra long-range variables
38 call initulr
39 ! read in the potential STATE_ULR.OUT
40 call readstulr
41 ! initialise the external Coulomb potential
42 call vclqinit
43 ! apply required local operations to the potential and magnetic field
44 call vblocalu
45 ! determine v¹⸍² (used for the symmetric form of v χ₀)
46 gclq(2:nqpt)=sqrt(gclq(2:nqpt))
47 ! matrix size
48 nm=nqpt+2
49 ! initialise the OpenMP locks
50 allocate(lock(nwrf))
51 do iw=1,nwrf
52  call omp_init_lock(lock(iw))
53 end do
54 ! compute v¹⸍² χ₀ v¹⸍² in single-precision
55 allocate(vchi0_sp(nm,nm,nwrf))
56 vchi0_sp(1:nm,1:nm,1:nwrf)=0.e0
57 ! begin parallel loop over k-points
58 call holdthd(nkpt0/np_mpi,nthd)
59 !$OMP PARALLEL DEFAULT(SHARED) &
60 !$OMP PRIVATE(evecu,pmat,ik) &
61 !$OMP NUM_THREADS(nthd)
62 allocate(evecu(nstulr,nstulr),pmat(nstsv,nstsv,3))
63 !$OMP DO SCHEDULE(DYNAMIC)
64 do ik0=1,nkpt0
65 ! distribute among MPI processes
66  if (mod(ik0-1,np_mpi) /= lp_mpi) cycle
67 !$OMP CRITICAL(tddftlru_)
68  write(*,'("Info(tddftlru): ",I0," of ",I0," k-points")') ik0,nkpt0
69 !$OMP END CRITICAL(tddftlru_)
70 ! central k-point
71  ik=(ik0-1)*nkpa+1
72 ! solve the ultra long-range eigenvalue equation
73  call eveqnulr(ik0,evecu)
74 ! get the occupation numbers from file
75  call getocculr(ik0)
76 ! generate the momentum matrix elements at the central k-point
77  call genpmatk(ik,pmat)
78 ! add to v¹⸍² χ₀ v¹⸍²
79  call genvchi0u(ik0,lock,pmat,evecu,vchi0_sp)
80 end do
81 !$OMP END DO
82 deallocate(evecu,pmat)
83 !$OMP END PARALLEL
84 call freethd(nthd)
85 ! destroy the OpenMP locks
86 do iw=1,nwrf
87  call omp_destroy_lock(lock(iw))
88 end do
89 deallocate(lock)
90 ! add vchi0_sp from each process and redistribute
91 if (np_mpi > 1) then
92  n=nm*nm*nwrf
93  call mpi_allreduce(mpi_in_place,vchi0_sp,n,mpi_complex,mpi_sum,mpicom,ierror)
94 end if
95 ! copy to double-precision array
96 allocate(vchi0(nm,nm,nwrf))
97 vchi0(1:nm,1:nm,1:nwrf)=vchi0_sp(1:nm,1:nm,1:nwrf)
98 deallocate(vchi0_sp)
99 allocate(eps0(nm,nm,nwrf),epsi(nm,nm,nwrf))
100 ! calculate symmetric ϵ₀ = 1 - v¹⸍² χ₀ v¹⸍²
101 eps0(1:nm,1:nm,1:nwrf)=-vchi0(1:nm,1:nm,1:nwrf)
102 do i=1,nm
103  eps0(i,i,1:nwrf)=eps0(i,i,1:nwrf)+1.d0
104 end do
105 ! begin loop over frequencies
106 do iw=1,nwrf
107 ! invert ϵ₀
108  call zminv(nm,eps0(:,:,iw))
109 ! left multiply by v¹⸍² χ₀ v¹⸍²
110  call zgemm('N','N',nm,nm,nm,zone,vchi0(:,:,iw),nm,eps0(:,:,iw),nm,zzero, &
111  epsi(:,:,iw),nm)
112 ! compute ϵ⁻¹ = 1 + v¹⸍² χ v¹⸍²
113  do i=1,nm
114  epsi(i,i,iw)=1.d0+epsi(i,i,iw)
115  end do
116 end do
117 if (mp_mpi) then
118 ! find the macroscopic part of ϵ by inverting the 3 × 3 head only
119  allocate(epsm(3,3,nwrf))
120  do iw=1,nwrf
121  epsm(1:3,1:3,iw)=epsi(1:3,1:3,iw)
122  call zminv(3,epsm(:,:,iw))
123  end do
124 ! write out the macroscopic components
125  do ioc=1,noptcomp
126  i=optcomp(1,ioc)
127  j=optcomp(2,ioc)
128  write(fname,'("EPSM_ULR_",2I1,".OUT")') i,j
129  open(50,file=trim(fname),form='FORMATTED')
130  do iw=2,nwrf
131  write(50,'(2G18.10)') wrf(iw)%re,epsm(i,j,iw)%re
132  end do
133  write(50,*)
134  do iw=2,nwrf
135  write(50,'(2G18.10)') wrf(iw)%re,epsm(i,j,iw)%im
136  end do
137  close(50)
138  end do
139  write(*,*)
140  write(*,'("Info(tddftlru):")')
141  write(*,'(" Macroscopic dielectric tensor written to EPSM_ULR_ij.OUT")')
142  write(*,'(" for components")')
143  do ioc=1,noptcomp
144  write(*,'(" i = ",I1,", j = ",I1)') optcomp(1:2,ioc)
145  end do
146  deallocate(epsm)
147 end if
148 deallocate(vchi0,eps0,epsi)
149 ! restore original parameters
151 end subroutine
152 
subroutine readstulr
Definition: readstulr.f90:7
subroutine genevfsv
Definition: genevfsv.f90:7
integer nwrf
Definition: modmain.f90:1168
subroutine tddftlru
Definition: tddftlru.f90:7
logical mp_mpi
Definition: modmpi.f90:17
integer nqpt
Definition: modmain.f90:528
integer nstulr
Definition: modulr.f90:97
integer reducek0
Definition: modmain.f90:458
Definition: modomp.f90:6
complex(8), dimension(:), allocatable wrf
Definition: modmain.f90:1170
integer nkpt0
Definition: modulr.f90:18
complex(8), parameter zone
Definition: modmain.f90:1240
subroutine genvsig
Definition: genvsig.f90:10
subroutine genapwlofr
Definition: genapwlofr.f90:7
subroutine gensocfr
Definition: gensocfr.f90:10
integer np_mpi
Definition: modmpi.f90:13
subroutine linengy
Definition: linengy.f90:10
integer nstsv
Definition: modmain.f90:885
subroutine getocculr(ik0)
Definition: getocculr.f90:7
subroutine vclqinit
Definition: vclqinit.f90:7
subroutine init3
Definition: init3.f90:7
integer, dimension(3, 27) optcomp
Definition: modmain.f90:1095
subroutine genvchi0u(ik0, lock, pmat, evecu, vchi0)
Definition: genvchi0u.f90:7
subroutine init1
Definition: init1.f90:10
complex(8), parameter zzero
Definition: modmain.f90:1240
integer noptcomp
Definition: modmain.f90:1093
Definition: modmpi.f90:6
subroutine readstate
Definition: readstate.f90:10
real(8), dimension(:), allocatable gclq
Definition: modmain.f90:558
integer lp_mpi
Definition: modmpi.f90:15
subroutine freethd(nthd)
Definition: modomp.f90:112
subroutine holdthd(nloop, nthd)
Definition: modomp.f90:78
subroutine genpmatk(ik, pmat)
Definition: genpmatk.f90:7
subroutine zminv(n, a)
Definition: zminv.f90:7
subroutine vblocalu
Definition: vblocalu.f90:7
integer reducek
Definition: modmain.f90:458
subroutine init0
Definition: init0.f90:10
Definition: modulr.f90:6
subroutine eveqnulr(ik0, evecu)
Definition: eveqnulr.f90:7
integer nkpa
Definition: modulr.f90:24
integer mpicom
Definition: modmpi.f90:11
subroutine initulr
Definition: initulr.f90:7
integer ierror
Definition: modmpi.f90:19