The Elk Code
gradzfmt.f90
Go to the documentation of this file.
1 
2 ! Copyright (C) 2002-2009 J. K. Dewhurst, S. Sharma and C. Ambrosch-Draxl.
3 ! This file is distributed under the terms of the GNU Lesser General Public
4 ! License. See the file COPYING for license details.
5 
6 !BOP
7 ! !ROUTINE: gradzfmt
8 ! !INTERFACE:
9 subroutine gradzfmt(nr,nri,ri,wcr,zfmt,ld,gzfmt)
10 ! !USES:
11 use modmain
12 ! !INPUT/OUTPUT PARAMETERS:
13 ! nr : number of radial mesh points (in,integer)
14 ! nri : number of points on inner part of muffin-tin (in,integer)
15 ! ri : 1/r on the radial mesh (in,real(nr))
16 ! wcr : weights for spline coefficients on radial mesh (in,real(12,nr))
17 ! zfmt : complex muffin-tin function (in,complex(*))
18 ! ld : leading dimension (in,integer)
19 ! gzfmt : gradient of zfmt (out,complex(ld,3))
20 ! !DESCRIPTION:
21 ! Calculates the gradient of a complex muffin-tin function. In other words,
22 ! given the spherical harmonic expansion coefficients, $f_{lm}(r)$, of a
23 ! function $f({\bf r})$, the routine returns ${\bf F}_{lm}$ where
24 ! $$ \sum_{lm}{\bf F}_{lm}(r)Y_{lm}(\hat{\bf r})=\nabla f({\bf r}). $$
25 ! This is done using the gradient formula (see, for example, V. Devanathan,
26 ! {\em Angular Momentum Techniques In Quantum Mechanics})
27 ! \begin{align*}
28 ! \nabla f_{lm}(r)Y_{lm}(\hat{\bf r})&=-\sqrt{\frac{l+1}{2l+1}}
29 ! \left(\frac{d}{dr}-\frac{l}{r}\right)f_{lm}(r)
30 ! {\bf Y}_{lm}^{l+1}(\hat{\bf r})\\
31 ! &+\sqrt{\frac{l}{2l+1}}\left(\frac{d}{dr}+\frac{l+1}{r}\right)f_{lm}(r)
32 ! {\bf Y}_{lm}^{l-1}(\hat{\bf r}),
33 ! \end{align*}
34 ! where the vector spherical harmonics are determined from Clebsch-Gordan
35 ! coefficients as follows:
36 ! $$ {\bf Y}_{lm}^{l'}(\hat{\bf r})=\sum_{m'\mu}
37 ! \begin{bmatrix} l' & 1 & l \\ m' & \mu & m \end{bmatrix}
38 ! Y_{lm}(\hat{\bf r})\hat{\bf e}^{\mu} $$
39 ! and the (contravariant) spherical unit vectors are given by
40 ! $$ \hat{\bf e}_{+1}=-\frac{\hat{\bf x}+i\hat{\bf y}}{\sqrt{2}},
41 ! \qquad\hat{\bf e}_0=\hat{\bf z},\qquad
42 ! \hat{\bf e}_{-1}=\frac{\hat{\bf x}-i\hat{\bf y}}{\sqrt{2}}. $$
43 !
44 ! !REVISION HISTORY:
45 ! Rewritten May 2009 (JKD)
46 ! Modified, February 2020 (JKD)
47 !EOP
48 !BOC
49 implicit none
50 ! arguments
51 integer, intent(in) :: nr,nri
52 real(8), intent(in) :: ri(nr),wcr(12,nr)
53 complex(8), intent(in) :: zfmt(*)
54 integer, intent(in) :: ld
55 complex(8), intent(out) :: gzfmt(ld,3)
56 ! local variables
57 integer nro,iro,ir,mu
58 integer l,m,lm,lm1
59 integer np,np1,npi,npi1
60 integer i0,i1,j0,j1,i,k
61 ! real constant 1/√2
62 real(8), parameter :: c1=0.7071067811865475244d0
63 real(8) t1,t2,t3
64 complex(8) z1
65 ! automatic arrays
66 complex(8) f(nr),df(nr),drmt(ld)
67 ! external functions
68 real(8), external :: clebgor
69 nro=nr-nri
70 iro=nri+1
71 npi=lmmaxi*nri
72 npi1=npi-lmmaxi
73 np=npi+lmmaxo*nro
74 np1=np-lmmaxo
75 !----------------------------------------!
76 ! compute the radial derivatives !
77 !----------------------------------------!
78 do lm=1,lmmaxi
79  i1=npi1+lm; j0=npi+lm; j1=np1+lm
80  f(1:nri)=zfmt(lm:i1:lmmaxi)
81  f(iro:nr)=zfmt(j0:j1:lmmaxo)
82  call splined(nr,wcr,f,df)
83  drmt(lm:i1:lmmaxi)=df(1:nri)
84  drmt(j0:j1:lmmaxo)=df(iro:nr)
85 end do
86 do lm=lmmaxi+1,lmmaxo
87  i0=npi+lm; i1=np1+lm
88  f(iro:nr)=zfmt(i0:i1:lmmaxo)
89  call splined(nro,wcr(1,iro),f(iro),df(iro))
90  drmt(i0:i1:lmmaxo)=df(iro:nr)
91 end do
92 !-----------------------------------------------------!
93 ! compute the gradient in the spherical basis !
94 !-----------------------------------------------------!
95 ! zero the gradient array
96 gzfmt(1:np,1:3)=0.d0
97 ! inner part of muffin-tin
98 lm=0
99 do l=0,lmaxi
100  t1=-sqrt(dble(l+1)/dble(2*l+1))
101  t2=merge(sqrt(dble(l)/dble(2*l+1)),0.d0,l > 0)
102  do m=-l,l
103  lm=lm+1
104  i1=npi1+lm
105  k=1
106  do mu=-1,1
107  if (mu == 0) k=3
108  if (mu == 1) k=2
109  if (l+1 <= lmaxi) then
110 ! index to (l,m) is l*(l+1)+m+1, therefore index to (l+1,m-mu) is
111  lm1=(l+1)*(l+2)+(m-mu)+1
112  j1=npi1+lm1
113  t3=t1*clebgor(l+1,1,l,m-mu,mu,m)
114  gzfmt(lm1:j1:lmmaxi,k)=gzfmt(lm1:j1:lmmaxi,k) &
115  +t3*(drmt(lm:i1:lmmaxi)-l*ri(1:nri)*zfmt(lm:i1:lmmaxi))
116  end if
117  if (abs(m-mu) <= l-1) then
118 ! index to (l-1,m-mu)
119  lm1=(l-1)*l+(m-mu)+1
120  j1=npi1+lm1
121  t3=t2*clebgor(l-1,1,l,m-mu,mu,m)
122  gzfmt(lm1:j1:lmmaxi,k)=gzfmt(lm1:j1:lmmaxi,k) &
123  +t3*(drmt(lm:i1:lmmaxi)+(l+1)*ri(1:nri)*zfmt(lm:i1:lmmaxi))
124  end if
125  end do
126  end do
127 end do
128 ! outer part of muffin-tin
129 lm=0
130 do l=0,lmaxo
131  t1=-sqrt(dble(l+1)/dble(2*l+1))
132  t2=merge(sqrt(dble(l)/dble(2*l+1)),0.d0,l > 0)
133  do m=-l,l
134  lm=lm+1
135  i0=npi+lm; i1=np1+lm
136  k=1
137  do mu=-1,1
138  if (mu == 0) k=3
139  if (mu == 1) k=2
140  if (l+1 <= lmaxo) then
141  lm1=(l+1)*(l+2)+(m-mu)+1
142  j0=npi+lm1; j1=np1+lm1
143  t3=t1*clebgor(l+1,1,l,m-mu,mu,m)
144  gzfmt(j0:j1:lmmaxo,k)=gzfmt(j0:j1:lmmaxo,k) &
145  +t3*(drmt(i0:i1:lmmaxo)-l*ri(iro:nr)*zfmt(i0:i1:lmmaxo))
146  end if
147  if (abs(m-mu) <= l-1) then
148  lm1=(l-1)*l+(m-mu)+1
149  j0=npi+lm1; j1=np1+lm1
150  t3=t2*clebgor(l-1,1,l,m-mu,mu,m)
151  gzfmt(j0:j1:lmmaxo,k)=gzfmt(j0:j1:lmmaxo,k) &
152  +t3*(drmt(i0:i1:lmmaxo)+(l+1)*ri(iro:nr)*zfmt(i0:i1:lmmaxo))
153  end if
154  end do
155  end do
156 end do
157 !---------------------------------------------------!
158 ! convert from spherical to Cartesian basis !
159 !---------------------------------------------------!
160 ! note that the gradient transforms as a covariant vector, i.e. y -> -y
161 i=0
162 do ir=1,nri
163  do lm=1,lmmaxi
164  i=i+1
165  z1=gzfmt(i,1)
166  gzfmt(i,1)=c1*(z1-gzfmt(i,2))
167  z1=c1*(z1+gzfmt(i,2))
168  gzfmt(i,2)=cmplx(z1%im,-z1%re,8)
169  end do
170 end do
171 do ir=iro,nr
172  do lm=1,lmmaxo
173  i=i+1
174  z1=gzfmt(i,1)
175  gzfmt(i,1)=c1*(z1-gzfmt(i,2))
176  z1=c1*(z1+gzfmt(i,2))
177  gzfmt(i,2)=cmplx(z1%im,-z1%re,8)
178  end do
179 end do
180 
181 contains
182 
183 pure subroutine splined(n,wc,f,df)
184 implicit none
185 ! arguments
186 integer, intent(in) :: n
187 real(8), intent(in) :: wc(12,n)
188 complex(8), intent(in) :: f(n)
189 complex(8), intent(out) :: df(n)
190 ! local variables
191 integer i
192 df(1)=wc(1,1)*f(1)+wc(2,1)*f(2)+wc(3,1)*f(3)+wc(4,1)*f(4)
193 df(2)=wc(1,2)*f(1)+wc(2,2)*f(2)+wc(3,2)*f(3)+wc(4,2)*f(4)
194 do i=3,n-2
195  df(i)=wc(1,i)*f(i-1)+wc(2,i)*f(i)+wc(3,i)*f(i+1)+wc(4,i)*f(i+2)
196 end do
197 i=n-1
198 df(i)=wc(1,i)*f(n-3)+wc(2,i)*f(n-2)+wc(3,i)*f(n-1)+wc(4,i)*f(n)
199 df(n)=wc(1,n)*f(n-3)+wc(2,n)*f(n-2)+wc(3,n)*f(n-1)+wc(4,n)*f(n)
200 end subroutine
201 
202 end subroutine
203 !EOC
204 
integer lmmaxo
Definition: modmain.f90:205
subroutine gradzfmt(nr, nri, ri, wcr, zfmt, ld, gzfmt)
Definition: gradzfmt.f90:10
integer lmaxo
Definition: modmain.f90:203
integer lmmaxi
Definition: modmain.f90:209
pure subroutine splined(n, wc, f, df)
Definition: gensocfr.f90:66
integer lmaxi
Definition: modmain.f90:207