Line data Source code
1 : !!****f* ABINIT/nfourier
2 : !! NAME
3 : !! nfourier
4 : !!
5 : !! FUNCTION
6 : !!
7 : !! COPYRIGHT
8 : !! Copyright (C) 2014-2026 ABINIT group (XG)
9 : !! This file is distributed under the terms of the
10 : !! GNU General Public License, see ~abinit/COPYING
11 : !! or http://www.gnu.org/copyleft/gpl.txt .
12 : !!
13 : !! SOURCE
14 :
15 : #if defined HAVE_CONFIG_H
16 : #include "config.h"
17 : #endif
18 :
19 : #include "abi_common.h"
20 :
21 : MODULE m_lib_four
22 :
23 : use defs_basis
24 : use m_errors
25 : use m_abicore
26 :
27 : contains
28 :
29 : ! This routine contains direct and inverse fourier transformation
30 : ! It is a modification of a routine of the GNU GPL
31 : ! code available on http://dmft.rutgers.edu/ and
32 : ! described in the RMP 2006 paper written by
33 : ! G.Kotliar, S.Y.Savrasov, K.Haule, V.S.Oudovenko, O.Parcollet, C.A.Marianetti
34 : !=======+=========+=========+=========+=========+=========+=========+=$
35 : ! TYPE : SUBROUTINE
36 : ! PROGRAM: nfourier
37 : ! PURPOSE: fourier-transform the natural-spline interpolation
38 : ! of function Green(tau)
39 : ! calculate function Green(omega)
40 : ! I/O :
41 : ! VERSION: 2-16-92
42 : ! 29-Nov-95 removal of minimal bug concerning
43 : ! DIMENSION of rindata
44 : ! COMMENT: cf J. Stoer R. Bulirsch, Introduction to numerical
45 : ! analysis (Springer, New York, 1980)
46 : !=======+=========+=========+=========+=========+=========+=========+=$
47 : !
48 0 : SUBROUTINE nfourier(rindata,coutdata,iflag,Iwmax,L,Beta)
49 :
50 : !include 'param.dat'
51 : IMPLICIT DOUBLE PRECISION (A-H,O-Z)
52 : IMPLICIT INTEGER(I-N)
53 : integer Iwmax,L,iflag
54 : DIMENSION rindata(L)
55 0 : DIMENSION rincopy(L+1),a(L),b(L),c(L),d(L),u(L+1), q(L+1),XM(L+1)
56 : complex*16 :: coutdata(Iwmax+1)
57 : complex*16 cdummy,explus,ex
58 0 : xpi = ACOS(-One)
59 0 : delta = Beta/L
60 0 : DO i = 1,L
61 0 : rincopy(i) = rindata(i)
62 : ENDDO
63 0 : if(iflag==1) then
64 0 : rincopy(L+1) = -1-rindata(1)
65 : else
66 0 : rincopy(L+1) = -rindata(1)
67 : endif
68 : ! Three = Two+One
69 : ! six = Two*Three
70 :
71 : !c
72 : !c spline interpolation: the spline is given by
73 : !c G(tau) = a(i) + b(i) (tau-tau_i) + c(i) ( )^2 + d(i) ( )^3
74 : !c The following formulas are taken directly from Stoer and
75 : !c Bulirsch p. 102
76 : !c
77 0 : q(1) = Zero
78 0 : u(1) = Zero
79 0 : DO k = 2,L
80 0 : p = q(k-1)/Two+Two
81 0 : q(k)=-One/Two/p
82 0 : u(k)=Three/delta**2*(rincopy(k+1)+rincopy(k-1)-Two*rincopy(k))
83 0 : u(k)=(u(k)-u(k-1)/Two)/p
84 : ENDDO
85 0 : XM(L+1) = 0
86 0 : DO k = L,1,-1
87 0 : XM(k) = q(k)*XM(k+1)+u(k)
88 : ENDDO
89 : !c
90 : !c The following formulas are taken directly from Stoer and
91 : !c Bulirsch p. 98
92 : !c
93 0 : DO j = 1, L
94 0 : a(j) = rincopy(j)
95 0 : c(j) = XM(j)/Two
96 : b(j) = (rincopy(j+1)-rincopy(j))/delta - &
97 0 : & (Two*XM(j)+XM(j+1))*delta/6.
98 0 : d(j) = (XM(j+1)-XM(j))/(6.*delta)
99 : ENDDO
100 :
101 : !c
102 : !c The Spline multiplied by the exponential can now be exlicitely
103 : !c integrated. The following formulas were obtained using
104 : !c MATHEMATICA
105 : !c
106 0 : DO i = 0,Iwmax
107 0 : om = (Two*(i)+One)*xpi/Beta
108 0 : coutdata(i+1) = czero
109 0 : DO j = 1,L
110 0 : cdummy = j_dpc*om*delta*j
111 0 : explus = exp(cdummy)
112 0 : cdummy = j_dpc*om*delta*(j-1)
113 0 : ex = exp(cdummy)
114 : coutdata(i+1) = coutdata(i+1) + explus*(&
115 : & ( -six* d(j) )/om**4 + &
116 : & ( Two*j_dpc*c(j) + six*delta*j_dpc*d(j) )/om**3 +&
117 : & ( b(j)+ Two*delta*c(j)+ three*delta**2*d(j) )/om**2 +&
118 : & (- j_dpc*a(j) - delta*j_dpc*b(j) - delta**2*j_dpc*c(j) -&
119 0 : & delta**3*j_dpc*d(j))/om)
120 :
121 : coutdata(i+1) = coutdata(i+1) + ex*(&
122 : & six*d(j)/om**4 - Two*j_dpc*c(j)/om**3 &
123 0 : & -b(j)/om**2 + j_dpc*a(j)/om)
124 : ENDDO
125 : ENDDO
126 0 : end subroutine nfourier
127 : !!***
128 :
129 : ! This routine contains direct and inverse fourier transformation
130 : ! It is a modification of a routine of the GNU GPL
131 : ! code available on http://dmft.rutgers.edu/ and
132 : ! described in the RMP 2006 paper written by
133 : ! G.Kotliar, S.Y.Savrasov, K.Haule, V.S.Oudovenko, O.Parcollet, C.A.Marianetti
134 : !=======+=========+=========+=========+=========+=========+=========+=$
135 : ! TYPE : SUBROUTINE
136 : ! PROGRAM: nfourier
137 : ! PURPOSE: fourier-transform the natural-spline interpolation
138 : ! of function Green(tau)
139 : ! calculate function Green(omega)
140 : ! I/O :
141 : ! VERSION: 2-16-92
142 : ! 29-Nov-95 removal of minimal bug concerning
143 : ! DIMENSION of rindata
144 : ! COMMENT: cf J. Stoer R. Bulirsch, Introduction to numerical
145 : ! analysis (Springer, New York, 1980)
146 : !=======+=========+=========+=========+=========+=========+=========+=$
147 : !
148 1600 : SUBROUTINE nfourier2(rindata,coutdata,iflag,om,L,Beta)
149 : ! include 'param.dat'
150 : IMPLICIT DOUBLE PRECISION (A-H,O-Z)
151 : IMPLICIT INTEGER(I-N)
152 : integer L,iflag
153 : DIMENSION rindata(L)
154 3200 : DIMENSION rincopy(L+1),a(L),b(L),c(L),d(L),u(L+1), q(L+1),XM(L+1)
155 : complex*16 :: coutdata
156 : real*8 :: om
157 : complex*16 cdummy,explus,ex
158 1600 : xpi = ACOS(-One)
159 1600 : delta = Beta/L
160 104000 : DO i = 1,L
161 104000 : rincopy(i) = rindata(i)
162 : ENDDO
163 1600 : if(iflag==1 .and. L.ge.1) then
164 320 : rincopy(L+1) = -1-rindata(1)
165 1280 : elseif(iflag==0 .and. L.ge.1) then
166 1280 : rincopy(L+1) = -rindata(1)
167 : else
168 0 : write(std_out,*) "Warning : Check nfourier2"
169 : endif
170 : ! Three = Two+One
171 : ! six = Two*Three
172 :
173 : !c
174 : !c spline interpolation: the spline is given by
175 : !c G(tau) = a(i) + b(i) (tau-tau_i) + c(i) ( )^2 + d(i) ( )^3
176 : !c The following formulas are taken directly from Stoer and
177 : !c Bulirsch p. 102
178 : !c
179 1600 : q(1) = Zero
180 1600 : u(1) = Zero
181 102400 : DO k = 2,L
182 100800 : p = q(k-1)/Two+Two
183 100800 : q(k)=-One/Two/p
184 100800 : u(k)=Three/delta**2*(rincopy(k+1)+rincopy(k-1)-Two*rincopy(k))
185 102400 : u(k)=(u(k)-u(k-1)/Two)/p
186 : ENDDO
187 1600 : XM(L+1) = 0
188 104000 : DO k = L,1,-1
189 104000 : XM(k) = q(k)*XM(k+1)+u(k)
190 : ENDDO
191 : !c
192 : !c The following formulas are taken directly from Stoer and
193 : !c Bulirsch p. 98
194 : !c
195 104000 : DO j = 1, L
196 102400 : a(j) = rincopy(j)
197 102400 : c(j) = XM(j)/Two
198 : b(j) = (rincopy(j+1)-rincopy(j))/delta - &
199 102400 : & (Two*XM(j)+XM(j+1))*delta/6.
200 104000 : d(j) = (XM(j+1)-XM(j))/(6.*delta)
201 : ENDDO
202 :
203 : !c
204 : !c The Spline multiplied by the exponential can now be exlicitely
205 : !c integrated. The following formulas were obtained using
206 : !c MATHEMATICA
207 : !c
208 1600 : coutdata = czero
209 104000 : DO j = 1,L
210 102400 : cdummy = j_dpc*om*delta*j
211 102400 : explus = exp(cdummy)
212 102400 : cdummy = j_dpc*om*delta*(j-1)
213 102400 : ex = exp(cdummy)
214 : coutdata = coutdata + explus*(&
215 : & ( -six* d(j) )/om**4 + &
216 : & ( Two*j_dpc*c(j) + six*delta*j_dpc*d(j) )/om**3 +&
217 : & ( b(j)+ Two*delta*c(j)+ three*delta**2*d(j) )/om**2 +&
218 : & (- j_dpc*a(j) - delta*j_dpc*b(j) - delta**2*j_dpc*c(j) -&
219 102400 : & delta**3*j_dpc*d(j))/om)
220 :
221 : coutdata = coutdata + ex*(&
222 : & six*d(j)/om**4 - Two*j_dpc*c(j)/om**3 &
223 104000 : & -b(j)/om**2 + j_dpc*a(j)/om)
224 : ENDDO
225 1600 : end subroutine nfourier2
226 : !=======+=========+=========+=========+=========+=========+=========+=$
227 : ! TYPE : SUBROUTINE
228 : ! PROGRAM: invfourier
229 : ! PURPOSE: inverse fourier transform
230 : ! Greent, Greenw use physical definition
231 : ! Greent(i) = G((i-1)*deltau) for i = 1,...,L
232 : ! Greenw(n) = G(i w_n), for n = 0,L/2-1
233 : ! w_n = (2*n+1)pi/beta
234 : ! Symmetry property:
235 : ! G(iw_(-n) = G(iw_(n-1))*
236 : ! coupled to the impurity
237 : ! I/O :
238 : ! VERSION: 6-16-92
239 : ! COMMENT:
240 : !=======+=========+=========+=========+=========+=========+=========+=$
241 : !
242 50 : SUBROUTINE invfourier(cindata,routdata,Iwmax,L,iflag,beta)
243 :
244 : ! include 'param.dat'
245 : implicit none
246 : integer, intent(in) :: Iwmax
247 : complex*16, intent(in) :: cindata(1:Iwmax) !vz_d
248 : integer, intent(in) :: L
249 : complex*16, intent(inout) :: routdata(1:L) !vz_d
250 : integer, intent(in) :: iflag
251 : double precision, intent(in) :: beta
252 :
253 : double precision :: xpi
254 : double precision :: tau
255 : double precision :: om
256 : complex*16 :: cdummy,dummy
257 : integer :: i,j
258 :
259 50 : xpi = ACOS(-One)
260 3250 : DO 1 i = 1,L
261 3200 : routdata(i) = Zero
262 3200 : tau = (i-1)*beta/real(L)
263 64003200 : DO 2 j = 1,Iwmax
264 : ! om = mod((2*(j)+One)*xpi/Beta*tau,2*xpi)
265 64000000 : om = ((2*(j)-One)*xpi/Beta*tau)
266 64000000 : cdummy = CMPLX(Zero,om)
267 64000000 : dummy = cindata(j)*exp(-cdummy)
268 64000000 : routdata(i) = routdata(i)+Two/beta*dummy
269 3200 : 2 CONTINUE
270 : ! write(std_out,*) "FT",i,routdata(i)
271 50 : 1 CONTINUE
272 : !c
273 : !c special treatment for tau = 0
274 : !c
275 50 : if(iflag==1 .and. L.ge.1 ) then
276 10 : routdata(1) = -One/Two+routdata(1)
277 : endif
278 50 : END SUBROUTINE invfourier
279 :
280 : END MODULE m_lib_four
281 : !!***
|