Commit ef002e0aa8946d1a2c09d106b627a3093d1033d8

Authored by daniau
1 parent ea0bc1fe35

git-svn-id: https://lxsd.femto-st.fr/svn/fvn@3 b657c933-2333-4658-acf2-d3c7c2708721

Showing 1 changed file with 1 additions and 1 deletions Inline Diff

1 1
module fvn 2 2 module fvn
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 3 3 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 4 4 !
! fvn : a f95 module replacement for some imsl routines 5 5 ! fvn : a f95 module replacement for some imsl routines
! it uses lapack for linear algebra 6 6 ! it uses lapack for linear algebra
! it uses modified quadpack for integration 7 7 ! it uses modified quadpack for integration
! 8 8 !
! William Daniau 2007 9 9 ! William Daniau 2007
! william.daniau@femto-st.fr 10 10 ! william.daniau@femto-st.fr
! 11 11 !
! Routines naming scheme : 12 12 ! Routines naming scheme :
! 13 13 !
! fvn_x_name 14 14 ! fvn_x_name
! where x can be s : real 15 15 ! where x can be s : real
! d : real double precision 16 16 ! d : real double precision
! c : complex 17 17 ! c : complex
! z : double complex 18 18 ! z : double complex
! 19 19 !
! 20 20 !
! This piece of code is totally free! Do whatever you want with it. However 21 21 ! This piece of code is totally free! Do whatever you want with it. However
! if you find it usefull it would be kind to give credits ;-) Nevertheless, you 22 22 ! if you find it usefull it would be kind to give credits ;-) Nevertheless, you
! may give credits to quadpack authors. 23 23 ! may give credits to quadpack authors.
! 24 24 !
! Version 1.1 25 25 ! Version 1.1
! 26 26 !
! TO DO LIST : 27 27 ! TO DO LIST :
! + Order eigenvalues and vectors in decreasing eigenvalue's modulus order -> atm 28 28 ! + Order eigenvalues and vectors in decreasing eigenvalue's modulus order -> atm
! eigenvalues are given with no particular order. 29 29 ! eigenvalues are given with no particular order.
! + Generic interface for fvn_x_name family -> fvn_name 30 30 ! + Generic interface for fvn_x_name family -> fvn_name
! + Make some parameters optional, status for example 31 31 ! + Make some parameters optional, status for example
! + use f95 kinds "double complex" -> complex(kind=8) 32 32 ! + use f95 kinds "double complex" -> complex(kind=8)
! + unify quadpack routines 33 33 ! + unify quadpack routines
! + ... 34 34 ! + ...
! 35 35 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 36 36 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
37 37
implicit none 38 38 implicit none
! All quadpack routines are private to the module 39 39 ! All quadpack routines are private to the module
private :: d1mach,dqag,dqag_2d_inner,dqag_2d_outer,dqage,dqage_2d_inner, & 40 40 private :: d1mach,dqag,dqag_2d_inner,dqag_2d_outer,dqage,dqage_2d_inner, &
dqage_2d_outer,dqk15,dqk15_2d_inner,dqk15_2d_outer,dqk21,dqk21_2d_inner,dqk21_2d_outer, & 41 41 dqage_2d_outer,dqk15,dqk15_2d_inner,dqk15_2d_outer,dqk21,dqk21_2d_inner,dqk21_2d_outer, &
dqk31,dqk31_2d_inner,dqk31_2d_outer,dqk41,dqk41_2d_inner,dqk41_2d_outer, & 42 42 dqk31,dqk31_2d_inner,dqk31_2d_outer,dqk41,dqk41_2d_inner,dqk41_2d_outer, &
dqk51,dqk51_2d_inner,dqk51_2d_outer,dqk61,dqk61_2d_inner,dqk61_2d_outer,dqpsrt 43 43 dqk51,dqk51_2d_inner,dqk51_2d_outer,dqk61,dqk61_2d_inner,dqk61_2d_outer,dqpsrt
44 44
45 45
contains 46 46 contains
47 47
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 48 48 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 49 49 !
! Matrix inversion subroutines 50 50 ! Matrix inversion subroutines
! 51 51 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 52 52 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine fvn_s_matinv(d,a,inva,status) 53 53 subroutine fvn_s_matinv(d,a,inva,status)
! 54 54 !
! Matrix inversion of a real matrix using BLAS and LAPACK 55 55 ! Matrix inversion of a real matrix using BLAS and LAPACK
! 56 56 !
! d (in) : matrix rank 57 57 ! d (in) : matrix rank
! a (in) : input matrix 58 58 ! a (in) : input matrix
! inva (out) : inversed matrix 59 59 ! inva (out) : inversed matrix
! status (ou) : =0 if something failed 60 60 ! status (ou) : =0 if something failed
! 61 61 !
integer, intent(in) :: d 62 62 integer, intent(in) :: d
real, intent(in) :: a(d,d) 63 63 real, intent(in) :: a(d,d)
real, intent(out) :: inva(d,d) 64 64 real, intent(out) :: inva(d,d)
integer, intent(out) :: status 65 65 integer, intent(out) :: status
66 66
integer, allocatable :: ipiv(:) 67 67 integer, allocatable :: ipiv(:)
real, allocatable :: work(:) 68 68 real, allocatable :: work(:)
real twork(1) 69 69 real twork(1)
integer :: info 70 70 integer :: info
integer :: lwork 71 71 integer :: lwork
72 72
status=1 73 73 status=1
74 74
allocate(ipiv(d)) 75 75 allocate(ipiv(d))
! copy a into inva using BLAS 76 76 ! copy a into inva using BLAS
!call scopy(d*d,a,1,inva,1) 77 77 !call scopy(d*d,a,1,inva,1)
inva(:,:)=a(:,:) 78 78 inva(:,:)=a(:,:)
! LU factorization using LAPACK 79 79 ! LU factorization using LAPACK
call sgetrf(d,d,inva,d,ipiv,info) 80 80 call sgetrf(d,d,inva,d,ipiv,info)
! if info is not equal to 0, something went wrong we exit setting status to 0 81 81 ! if info is not equal to 0, something went wrong we exit setting status to 0
if (info /= 0) then 82 82 if (info /= 0) then
status=0 83 83 status=0
deallocate(ipiv) 84 84 deallocate(ipiv)
return 85 85 return
end if 86 86 end if
! we use the query fonction of xxxtri to obtain the optimal workspace size 87 87 ! we use the query fonction of xxxtri to obtain the optimal workspace size
call sgetri(d,inva,d,ipiv,twork,-1,info) 88 88 call sgetri(d,inva,d,ipiv,twork,-1,info)
lwork=int(twork(1)) 89 89 lwork=int(twork(1))
allocate(work(lwork)) 90 90 allocate(work(lwork))
! Matrix inversion using LAPACK 91 91 ! Matrix inversion using LAPACK
call sgetri(d,inva,d,ipiv,work,lwork,info) 92 92 call sgetri(d,inva,d,ipiv,work,lwork,info)
! again if info is not equal to 0, we exit setting status to 0 93 93 ! again if info is not equal to 0, we exit setting status to 0
if (info /= 0) then 94 94 if (info /= 0) then
status=0 95 95 status=0
end if 96 96 end if
deallocate(work) 97 97 deallocate(work)
deallocate(ipiv) 98 98 deallocate(ipiv)
end subroutine 99 99 end subroutine
100 100
subroutine fvn_d_matinv(d,a,inva,status) 101 101 subroutine fvn_d_matinv(d,a,inva,status)
! 102 102 !
! Matrix inversion of a double precision matrix using BLAS and LAPACK 103 103 ! Matrix inversion of a double precision matrix using BLAS and LAPACK
! 104 104 !
! d (in) : matrix rank 105 105 ! d (in) : matrix rank
! a (in) : input matrix 106 106 ! a (in) : input matrix
! inva (out) : inversed matrix 107 107 ! inva (out) : inversed matrix
! status (ou) : =0 if something failed 108 108 ! status (ou) : =0 if something failed
! 109 109 !
integer, intent(in) :: d 110 110 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 111 111 double precision, intent(in) :: a(d,d)
double precision, intent(out) :: inva(d,d) 112 112 double precision, intent(out) :: inva(d,d)
integer, intent(out) :: status 113 113 integer, intent(out) :: status
114 114
integer, allocatable :: ipiv(:) 115 115 integer, allocatable :: ipiv(:)
double precision, allocatable :: work(:) 116 116 double precision, allocatable :: work(:)
double precision :: twork(1) 117 117 double precision :: twork(1)
integer :: info 118 118 integer :: info
integer :: lwork 119 119 integer :: lwork
120 120
status=1 121 121 status=1
122 122
allocate(ipiv(d)) 123 123 allocate(ipiv(d))
! copy a into inva using BLAS 124 124 ! copy a into inva using BLAS
!call dcopy(d*d,a,1,inva,1) 125 125 !call dcopy(d*d,a,1,inva,1)
inva(:,:)=a(:,:) 126 126 inva(:,:)=a(:,:)
! LU factorization using LAPACK 127 127 ! LU factorization using LAPACK
call dgetrf(d,d,inva,d,ipiv,info) 128 128 call dgetrf(d,d,inva,d,ipiv,info)
! if info is not equal to 0, something went wrong we exit setting status to 0 129 129 ! if info is not equal to 0, something went wrong we exit setting status to 0
if (info /= 0) then 130 130 if (info /= 0) then
status=0 131 131 status=0
deallocate(ipiv) 132 132 deallocate(ipiv)
return 133 133 return
end if 134 134 end if
! we use the query fonction of xxxtri to obtain the optimal workspace size 135 135 ! we use the query fonction of xxxtri to obtain the optimal workspace size
call dgetri(d,inva,d,ipiv,twork,-1,info) 136 136 call dgetri(d,inva,d,ipiv,twork,-1,info)
lwork=int(twork(1)) 137 137 lwork=int(twork(1))
allocate(work(lwork)) 138 138 allocate(work(lwork))
! Matrix inversion using LAPACK 139 139 ! Matrix inversion using LAPACK
call dgetri(d,inva,d,ipiv,work,lwork,info) 140 140 call dgetri(d,inva,d,ipiv,work,lwork,info)
! again if info is not equal to 0, we exit setting status to 0 141 141 ! again if info is not equal to 0, we exit setting status to 0
if (info /= 0) then 142 142 if (info /= 0) then
status=0 143 143 status=0
end if 144 144 end if
deallocate(work) 145 145 deallocate(work)
deallocate(ipiv) 146 146 deallocate(ipiv)
end subroutine 147 147 end subroutine
148 148
subroutine fvn_c_matinv(d,a,inva,status) 149 149 subroutine fvn_c_matinv(d,a,inva,status)
! 150 150 !
! Matrix inversion of a complex matrix using BLAS and LAPACK 151 151 ! Matrix inversion of a complex matrix using BLAS and LAPACK
! 152 152 !
! d (in) : matrix rank 153 153 ! d (in) : matrix rank
! a (in) : input matrix 154 154 ! a (in) : input matrix
! inva (out) : inversed matrix 155 155 ! inva (out) : inversed matrix
! status (ou) : =0 if something failed 156 156 ! status (ou) : =0 if something failed
! 157 157 !
integer, intent(in) :: d 158 158 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 159 159 complex, intent(in) :: a(d,d)
complex, intent(out) :: inva(d,d) 160 160 complex, intent(out) :: inva(d,d)
integer, intent(out) :: status 161 161 integer, intent(out) :: status
162 162
integer, allocatable :: ipiv(:) 163 163 integer, allocatable :: ipiv(:)
complex, allocatable :: work(:) 164 164 complex, allocatable :: work(:)
complex :: twork(1) 165 165 complex :: twork(1)
integer :: info 166 166 integer :: info
integer :: lwork 167 167 integer :: lwork
168 168
status=1 169 169 status=1
170 170
allocate(ipiv(d)) 171 171 allocate(ipiv(d))
! copy a into inva using BLAS 172 172 ! copy a into inva using BLAS
!call ccopy(d*d,a,1,inva,1) 173 173 !call ccopy(d*d,a,1,inva,1)
inva(:,:)=a(:,:) 174 174 inva(:,:)=a(:,:)
175 175
! LU factorization using LAPACK 176 176 ! LU factorization using LAPACK
call cgetrf(d,d,inva,d,ipiv,info) 177 177 call cgetrf(d,d,inva,d,ipiv,info)
! if info is not equal to 0, something went wrong we exit setting status to 0 178 178 ! if info is not equal to 0, something went wrong we exit setting status to 0
if (info /= 0) then 179 179 if (info /= 0) then
status=0 180 180 status=0
deallocate(ipiv) 181 181 deallocate(ipiv)
return 182 182 return
end if 183 183 end if
! we use the query fonction of xxxtri to obtain the optimal workspace size 184 184 ! we use the query fonction of xxxtri to obtain the optimal workspace size
call cgetri(d,inva,d,ipiv,twork,-1,info) 185 185 call cgetri(d,inva,d,ipiv,twork,-1,info)
lwork=int(twork(1)) 186 186 lwork=int(twork(1))
allocate(work(lwork)) 187 187 allocate(work(lwork))
! Matrix inversion using LAPACK 188 188 ! Matrix inversion using LAPACK
call cgetri(d,inva,d,ipiv,work,lwork,info) 189 189 call cgetri(d,inva,d,ipiv,work,lwork,info)
! again if info is not equal to 0, we exit setting status to 0 190 190 ! again if info is not equal to 0, we exit setting status to 0
if (info /= 0) then 191 191 if (info /= 0) then
status=0 192 192 status=0
end if 193 193 end if
deallocate(work) 194 194 deallocate(work)
deallocate(ipiv) 195 195 deallocate(ipiv)
end subroutine 196 196 end subroutine
197 197
subroutine fvn_z_matinv(d,a,inva,status) 198 198 subroutine fvn_z_matinv(d,a,inva,status)
! 199 199 !
! Matrix inversion of a double complex matrix using BLAS and LAPACK 200 200 ! Matrix inversion of a double complex matrix using BLAS and LAPACK
! 201 201 !
! d (in) : matrix rank 202 202 ! d (in) : matrix rank
! a (in) : input matrix 203 203 ! a (in) : input matrix
! inva (out) : inversed matrix 204 204 ! inva (out) : inversed matrix
! status (ou) : =0 if something failed 205 205 ! status (ou) : =0 if something failed
! 206 206 !
integer, intent(in) :: d 207 207 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 208 208 double complex, intent(in) :: a(d,d)
double complex, intent(out) :: inva(d,d) 209 209 double complex, intent(out) :: inva(d,d)
integer, intent(out) :: status 210 210 integer, intent(out) :: status
211 211
integer, allocatable :: ipiv(:) 212 212 integer, allocatable :: ipiv(:)
double complex, allocatable :: work(:) 213 213 double complex, allocatable :: work(:)
double complex :: twork(1) 214 214 double complex :: twork(1)
integer :: info 215 215 integer :: info
integer :: lwork 216 216 integer :: lwork
217 217
status=1 218 218 status=1
219 219
allocate(ipiv(d)) 220 220 allocate(ipiv(d))
! copy a into inva using BLAS 221 221 ! copy a into inva using BLAS
!call zcopy(d*d,a,1,inva,1) 222 222 !call zcopy(d*d,a,1,inva,1)
inva(:,:)=a(:,:) 223 223 inva(:,:)=a(:,:)
224 224
! LU factorization using LAPACK 225 225 ! LU factorization using LAPACK
call zgetrf(d,d,inva,d,ipiv,info) 226 226 call zgetrf(d,d,inva,d,ipiv,info)
! if info is not equal to 0, something went wrong we exit setting status to 0 227 227 ! if info is not equal to 0, something went wrong we exit setting status to 0
if (info /= 0) then 228 228 if (info /= 0) then
status=0 229 229 status=0
deallocate(ipiv) 230 230 deallocate(ipiv)
return 231 231 return
end if 232 232 end if
! we use the query fonction of xxxtri to obtain the optimal workspace size 233 233 ! we use the query fonction of xxxtri to obtain the optimal workspace size
call zgetri(d,inva,d,ipiv,twork,-1,info) 234 234 call zgetri(d,inva,d,ipiv,twork,-1,info)
lwork=int(twork(1)) 235 235 lwork=int(twork(1))
allocate(work(lwork)) 236 236 allocate(work(lwork))
! Matrix inversion using LAPACK 237 237 ! Matrix inversion using LAPACK
call zgetri(d,inva,d,ipiv,work,lwork,info) 238 238 call zgetri(d,inva,d,ipiv,work,lwork,info)
! again if info is not equal to 0, we exit setting status to 0 239 239 ! again if info is not equal to 0, we exit setting status to 0
if (info /= 0) then 240 240 if (info /= 0) then
status=0 241 241 status=0
end if 242 242 end if
deallocate(work) 243 243 deallocate(work)
deallocate(ipiv) 244 244 deallocate(ipiv)
end subroutine 245 245 end subroutine
246 246
247 247
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 248 248 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 249 249 !
! Determinants 250 250 ! Determinants
! 251 251 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 252 252 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function fvn_s_det(d,a,status) 253 253 function fvn_s_det(d,a,status)
! 254 254 !
! Evaluate the determinant of a square matrix using lapack LU factorization 255 255 ! Evaluate the determinant of a square matrix using lapack LU factorization
! 256 256 !
! d (in) : matrix rank 257 257 ! d (in) : matrix rank
! a (in) : The Matrix 258 258 ! a (in) : The Matrix
! status (out) : =0 if LU factorization failed 259 259 ! status (out) : =0 if LU factorization failed
! 260 260 !
integer, intent(in) :: d 261 261 integer, intent(in) :: d
real, intent(in) :: a(d,d) 262 262 real, intent(in) :: a(d,d)
integer, intent(out) :: status 263 263 integer, intent(out) :: status
real :: fvn_s_det 264 264 real :: fvn_s_det
265 265
real, allocatable :: wc_a(:,:) 266 266 real, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 267 267 integer, allocatable :: ipiv(:)
integer :: info,i 268 268 integer :: info,i
269 269
status=1 270 270 status=1
allocate(wc_a(d,d)) 271 271 allocate(wc_a(d,d))
allocate(ipiv(d)) 272 272 allocate(ipiv(d))
wc_a(:,:)=a(:,:) 273 273 wc_a(:,:)=a(:,:)
call sgetrf(d,d,wc_a,d,ipiv,info) 274 274 call sgetrf(d,d,wc_a,d,ipiv,info)
if (info/= 0) then 275 275 if (info/= 0) then
status=0 276 276 status=0
fvn_s_det=0.e0 277 277 fvn_s_det=0.e0
deallocate(ipiv) 278 278 deallocate(ipiv)
deallocate(wc_a) 279 279 deallocate(wc_a)
return 280 280 return
end if 281 281 end if
fvn_s_det=1.e0 282 282 fvn_s_det=1.e0
do i=1,d 283 283 do i=1,d
if (ipiv(i)==i) then 284 284 if (ipiv(i)==i) then
fvn_s_det=fvn_s_det*wc_a(i,i) 285 285 fvn_s_det=fvn_s_det*wc_a(i,i)
else 286 286 else
fvn_s_det=-fvn_s_det*wc_a(i,i) 287 287 fvn_s_det=-fvn_s_det*wc_a(i,i)
end if 288 288 end if
end do 289 289 end do
deallocate(ipiv) 290 290 deallocate(ipiv)
deallocate(wc_a) 291 291 deallocate(wc_a)
292 292
end function 293 293 end function
294 294
function fvn_d_det(d,a,status) 295 295 function fvn_d_det(d,a,status)
! 296 296 !
! Evaluate the determinant of a square matrix using lapack LU factorization 297 297 ! Evaluate the determinant of a square matrix using lapack LU factorization
! 298 298 !
! d (in) : matrix rank 299 299 ! d (in) : matrix rank
! a (in) : The Matrix 300 300 ! a (in) : The Matrix
! status (out) : =0 if LU factorization failed 301 301 ! status (out) : =0 if LU factorization failed
! 302 302 !
integer, intent(in) :: d 303 303 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 304 304 double precision, intent(in) :: a(d,d)
integer, intent(out) :: status 305 305 integer, intent(out) :: status
double precision :: fvn_d_det 306 306 double precision :: fvn_d_det
307 307
double precision, allocatable :: wc_a(:,:) 308 308 double precision, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 309 309 integer, allocatable :: ipiv(:)
integer :: info,i 310 310 integer :: info,i
311 311
status=1 312 312 status=1
allocate(wc_a(d,d)) 313 313 allocate(wc_a(d,d))
allocate(ipiv(d)) 314 314 allocate(ipiv(d))
wc_a(:,:)=a(:,:) 315 315 wc_a(:,:)=a(:,:)
call dgetrf(d,d,wc_a,d,ipiv,info) 316 316 call dgetrf(d,d,wc_a,d,ipiv,info)
if (info/= 0) then 317 317 if (info/= 0) then
status=0 318 318 status=0
fvn_d_det=0.d0 319 319 fvn_d_det=0.d0
deallocate(ipiv) 320 320 deallocate(ipiv)
deallocate(wc_a) 321 321 deallocate(wc_a)
return 322 322 return
end if 323 323 end if
fvn_d_det=1.d0 324 324 fvn_d_det=1.d0
do i=1,d 325 325 do i=1,d
if (ipiv(i)==i) then 326 326 if (ipiv(i)==i) then
fvn_d_det=fvn_d_det*wc_a(i,i) 327 327 fvn_d_det=fvn_d_det*wc_a(i,i)
else 328 328 else
fvn_d_det=-fvn_d_det*wc_a(i,i) 329 329 fvn_d_det=-fvn_d_det*wc_a(i,i)
end if 330 330 end if
end do 331 331 end do
deallocate(ipiv) 332 332 deallocate(ipiv)
deallocate(wc_a) 333 333 deallocate(wc_a)
334 334
end function 335 335 end function
336 336
function fvn_c_det(d,a,status) ! 337 337 function fvn_c_det(d,a,status) !
! Evaluate the determinant of a square matrix using lapack LU factorization 338 338 ! Evaluate the determinant of a square matrix using lapack LU factorization
! 339 339 !
! d (in) : matrix rank 340 340 ! d (in) : matrix rank
! a (in) : The Matrix 341 341 ! a (in) : The Matrix
! status (out) : =0 if LU factorization failed 342 342 ! status (out) : =0 if LU factorization failed
! 343 343 !
integer, intent(in) :: d 344 344 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 345 345 complex, intent(in) :: a(d,d)
integer, intent(out) :: status 346 346 integer, intent(out) :: status
complex :: fvn_c_det 347 347 complex :: fvn_c_det
348 348
complex, allocatable :: wc_a(:,:) 349 349 complex, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 350 350 integer, allocatable :: ipiv(:)
integer :: info,i 351 351 integer :: info,i
352 352
status=1 353 353 status=1
allocate(wc_a(d,d)) 354 354 allocate(wc_a(d,d))
allocate(ipiv(d)) 355 355 allocate(ipiv(d))
wc_a(:,:)=a(:,:) 356 356 wc_a(:,:)=a(:,:)
call cgetrf(d,d,wc_a,d,ipiv,info) 357 357 call cgetrf(d,d,wc_a,d,ipiv,info)
if (info/= 0) then 358 358 if (info/= 0) then
status=0 359 359 status=0
fvn_c_det=(0.e0,0.e0) 360 360 fvn_c_det=(0.e0,0.e0)
deallocate(ipiv) 361 361 deallocate(ipiv)
deallocate(wc_a) 362 362 deallocate(wc_a)
return 363 363 return
end if 364 364 end if
fvn_c_det=(1.e0,0.e0) 365 365 fvn_c_det=(1.e0,0.e0)
do i=1,d 366 366 do i=1,d
if (ipiv(i)==i) then 367 367 if (ipiv(i)==i) then
fvn_c_det=fvn_c_det*wc_a(i,i) 368 368 fvn_c_det=fvn_c_det*wc_a(i,i)
else 369 369 else
fvn_c_det=-fvn_c_det*wc_a(i,i) 370 370 fvn_c_det=-fvn_c_det*wc_a(i,i)
end if 371 371 end if
end do 372 372 end do
deallocate(ipiv) 373 373 deallocate(ipiv)
deallocate(wc_a) 374 374 deallocate(wc_a)
375 375
end function 376 376 end function
377 377
function fvn_z_det(d,a,status) 378 378 function fvn_z_det(d,a,status)
! 379 379 !
! Evaluate the determinant of a square matrix using lapack LU factorization 380 380 ! Evaluate the determinant of a square matrix using lapack LU factorization
! 381 381 !
! d (in) : matrix rank 382 382 ! d (in) : matrix rank
! a (in) : The Matrix 383 383 ! a (in) : The Matrix
! det (out) : determinant 384 384 ! det (out) : determinant
! status (out) : =0 if LU factorization failed 385 385 ! status (out) : =0 if LU factorization failed
! 386 386 !
integer, intent(in) :: d 387 387 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 388 388 double complex, intent(in) :: a(d,d)
integer, intent(out) :: status 389 389 integer, intent(out) :: status
double complex :: fvn_z_det 390 390 double complex :: fvn_z_det
391 391
double complex, allocatable :: wc_a(:,:) 392 392 double complex, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 393 393 integer, allocatable :: ipiv(:)
integer :: info,i 394 394 integer :: info,i
395 395
status=1 396 396 status=1
allocate(wc_a(d,d)) 397 397 allocate(wc_a(d,d))
allocate(ipiv(d)) 398 398 allocate(ipiv(d))
wc_a(:,:)=a(:,:) 399 399 wc_a(:,:)=a(:,:)
call zgetrf(d,d,wc_a,d,ipiv,info) 400 400 call zgetrf(d,d,wc_a,d,ipiv,info)
if (info/= 0) then 401 401 if (info/= 0) then
status=0 402 402 status=0
fvn_z_det=(0.d0,0.d0) 403 403 fvn_z_det=(0.d0,0.d0)
deallocate(ipiv) 404 404 deallocate(ipiv)
deallocate(wc_a) 405 405 deallocate(wc_a)
return 406 406 return
end if 407 407 end if
fvn_z_det=(1.d0,0.d0) 408 408 fvn_z_det=(1.d0,0.d0)
do i=1,d 409 409 do i=1,d
if (ipiv(i)==i) then 410 410 if (ipiv(i)==i) then
fvn_z_det=fvn_z_det*wc_a(i,i) 411 411 fvn_z_det=fvn_z_det*wc_a(i,i)
else 412 412 else
fvn_z_det=-fvn_z_det*wc_a(i,i) 413 413 fvn_z_det=-fvn_z_det*wc_a(i,i)
end if 414 414 end if
end do 415 415 end do
deallocate(ipiv) 416 416 deallocate(ipiv)
deallocate(wc_a) 417 417 deallocate(wc_a)
418 418
end function 419 419 end function
420 420
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 421 421 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 422 422 !
! Condition test 423 423 ! Condition test
! 424 424 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 425 425 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 1-norm 426 426 ! 1-norm
! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm 427 427 ! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm
! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond 428 428 ! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond
! 429 429 !
subroutine fvn_s_matcon(d,a,rcond,status) 430 430 subroutine fvn_s_matcon(d,a,rcond,status)
! Matrix condition (reciprocal of condition number) 431 431 ! Matrix condition (reciprocal of condition number)
! 432 432 !
! d (in) : matrix rank 433 433 ! d (in) : matrix rank
! a (in) : The Matrix 434 434 ! a (in) : The Matrix
! rcond (out) : guess what 435 435 ! rcond (out) : guess what
! status (out) : =0 if something went wrong 436 436 ! status (out) : =0 if something went wrong
! 437 437 !
integer, intent(in) :: d 438 438 integer, intent(in) :: d
real, intent(in) :: a(d,d) 439 439 real, intent(in) :: a(d,d)
real, intent(out) :: rcond 440 440 real, intent(out) :: rcond
integer, intent(out) :: status 441 441 integer, intent(out) :: status
442 442
real, allocatable :: work(:) 443 443 real, allocatable :: work(:)
integer, allocatable :: iwork(:) 444 444 integer, allocatable :: iwork(:)
real :: anorm 445 445 real :: anorm
real, allocatable :: wc_a(:,:) ! working copy of a 446 446 real, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 447 447 integer :: info
integer, allocatable :: ipiv(:) 448 448 integer, allocatable :: ipiv(:)
449 449
real, external :: slange 450 450 real, external :: slange
451 451
452 452
status=1 453 453 status=1
454 454
anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm 455 455 anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm
456 456
allocate(wc_a(d,d)) 457 457 allocate(wc_a(d,d))
!call scopy(d*d,a,1,wc_a,1) 458 458 !call scopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 459 459 wc_a(:,:)=a(:,:)
460 460
allocate(ipiv(d)) 461 461 allocate(ipiv(d))
call sgetrf(d,d,wc_a,d,ipiv,info) 462 462 call sgetrf(d,d,wc_a,d,ipiv,info)
if (info /= 0) then 463 463 if (info /= 0) then
status=0 464 464 status=0
deallocate(ipiv) 465 465 deallocate(ipiv)
deallocate(wc_a) 466 466 deallocate(wc_a)
return 467 467 return
end if 468 468 end if
allocate(work(4*d)) 469 469 allocate(work(4*d))
allocate(iwork(d)) 470 470 allocate(iwork(d))
call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) 471 471 call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info)
if (info /= 0) then 472 472 if (info /= 0) then
status=0 473 473 status=0
end if 474 474 end if
deallocate(iwork) 475 475 deallocate(iwork)
deallocate(work) 476 476 deallocate(work)
deallocate(ipiv) 477 477 deallocate(ipiv)
deallocate(wc_a) 478 478 deallocate(wc_a)
479 479
end subroutine 480 480 end subroutine
481 481
subroutine fvn_d_matcon(d,a,rcond,status) 482 482 subroutine fvn_d_matcon(d,a,rcond,status)
! Matrix condition (reciprocal of condition number) 483 483 ! Matrix condition (reciprocal of condition number)
! 484 484 !
! d (in) : matrix rank 485 485 ! d (in) : matrix rank
! a (in) : The Matrix 486 486 ! a (in) : The Matrix
! rcond (out) : guess what 487 487 ! rcond (out) : guess what
! status (out) : =0 if something went wrong 488 488 ! status (out) : =0 if something went wrong
! 489 489 !
integer, intent(in) :: d 490 490 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 491 491 double precision, intent(in) :: a(d,d)
double precision, intent(out) :: rcond 492 492 double precision, intent(out) :: rcond
integer, intent(out) :: status 493 493 integer, intent(out) :: status
494 494
double precision, allocatable :: work(:) 495 495 double precision, allocatable :: work(:)
integer, allocatable :: iwork(:) 496 496 integer, allocatable :: iwork(:)
double precision :: anorm 497 497 double precision :: anorm
double precision, allocatable :: wc_a(:,:) ! working copy of a 498 498 double precision, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 499 499 integer :: info
integer, allocatable :: ipiv(:) 500 500 integer, allocatable :: ipiv(:)
501 501
double precision, external :: dlange 502 502 double precision, external :: dlange
503 503
504 504
status=1 505 505 status=1
506 506
anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm 507 507 anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm
508 508
allocate(wc_a(d,d)) 509 509 allocate(wc_a(d,d))
!call dcopy(d*d,a,1,wc_a,1) 510 510 !call dcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 511 511 wc_a(:,:)=a(:,:)
512 512
allocate(ipiv(d)) 513 513 allocate(ipiv(d))
call dgetrf(d,d,wc_a,d,ipiv,info) 514 514 call dgetrf(d,d,wc_a,d,ipiv,info)
if (info /= 0) then 515 515 if (info /= 0) then
status=0 516 516 status=0
deallocate(ipiv) 517 517 deallocate(ipiv)
deallocate(wc_a) 518 518 deallocate(wc_a)
return 519 519 return
end if 520 520 end if
521 521
allocate(work(4*d)) 522 522 allocate(work(4*d))
allocate(iwork(d)) 523 523 allocate(iwork(d))
call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) 524 524 call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info)
if (info /= 0) then 525 525 if (info /= 0) then
status=0 526 526 status=0
end if 527 527 end if
deallocate(iwork) 528 528 deallocate(iwork)
deallocate(work) 529 529 deallocate(work)
deallocate(ipiv) 530 530 deallocate(ipiv)
deallocate(wc_a) 531 531 deallocate(wc_a)
532 532
end subroutine 533 533 end subroutine
534 534
subroutine fvn_c_matcon(d,a,rcond,status) 535 535 subroutine fvn_c_matcon(d,a,rcond,status)
! Matrix condition (reciprocal of condition number) 536 536 ! Matrix condition (reciprocal of condition number)
! 537 537 !
! d (in) : matrix rank 538 538 ! d (in) : matrix rank
! a (in) : The Matrix 539 539 ! a (in) : The Matrix
! rcond (out) : guess what 540 540 ! rcond (out) : guess what
! status (out) : =0 if something went wrong 541 541 ! status (out) : =0 if something went wrong
! 542 542 !
integer, intent(in) :: d 543 543 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 544 544 complex, intent(in) :: a(d,d)
real, intent(out) :: rcond 545 545 real, intent(out) :: rcond
integer, intent(out) :: status 546 546 integer, intent(out) :: status
547 547
real, allocatable :: rwork(:) 548 548 real, allocatable :: rwork(:)
complex, allocatable :: work(:) 549 549 complex, allocatable :: work(:)
integer, allocatable :: iwork(:) 550 550 integer, allocatable :: iwork(:)
real :: anorm 551 551 real :: anorm
complex, allocatable :: wc_a(:,:) ! working copy of a 552 552 complex, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 553 553 integer :: info
integer, allocatable :: ipiv(:) 554 554 integer, allocatable :: ipiv(:)
555 555
real, external :: clange 556 556 real, external :: clange
557 557
558 558
status=1 559 559 status=1
560 560
anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm 561 561 anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm
562 562
allocate(wc_a(d,d)) 563 563 allocate(wc_a(d,d))
!call ccopy(d*d,a,1,wc_a,1) 564 564 !call ccopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 565 565 wc_a(:,:)=a(:,:)
566 566
allocate(ipiv(d)) 567 567 allocate(ipiv(d))
call cgetrf(d,d,wc_a,d,ipiv,info) 568 568 call cgetrf(d,d,wc_a,d,ipiv,info)
if (info /= 0) then 569 569 if (info /= 0) then
status=0 570 570 status=0
deallocate(ipiv) 571 571 deallocate(ipiv)
deallocate(wc_a) 572 572 deallocate(wc_a)
return 573 573 return
end if 574 574 end if
allocate(work(2*d)) 575 575 allocate(work(2*d))
allocate(rwork(2*d)) 576 576 allocate(rwork(2*d))
call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) 577 577 call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info)
if (info /= 0) then 578 578 if (info /= 0) then
status=0 579 579 status=0
end if 580 580 end if
deallocate(rwork) 581 581 deallocate(rwork)
deallocate(work) 582 582 deallocate(work)
deallocate(ipiv) 583 583 deallocate(ipiv)
deallocate(wc_a) 584 584 deallocate(wc_a)
end subroutine 585 585 end subroutine
586 586
subroutine fvn_z_matcon(d,a,rcond,status) 587 587 subroutine fvn_z_matcon(d,a,rcond,status)
! Matrix condition (reciprocal of condition number) 588 588 ! Matrix condition (reciprocal of condition number)
! 589 589 !
! d (in) : matrix rank 590 590 ! d (in) : matrix rank
! a (in) : The Matrix 591 591 ! a (in) : The Matrix
! rcond (out) : guess what 592 592 ! rcond (out) : guess what
! status (out) : =0 if something went wrong 593 593 ! status (out) : =0 if something went wrong
! 594 594 !
integer, intent(in) :: d 595 595 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 596 596 double complex, intent(in) :: a(d,d)
double precision, intent(out) :: rcond 597 597 double precision, intent(out) :: rcond
integer, intent(out) :: status 598 598 integer, intent(out) :: status
599 599
double complex, allocatable :: work(:) 600 600 double complex, allocatable :: work(:)
double precision, allocatable :: rwork(:) 601 601 double precision, allocatable :: rwork(:)
double precision :: anorm 602 602 double precision :: anorm
double complex, allocatable :: wc_a(:,:) ! working copy of a 603 603 double complex, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 604 604 integer :: info
integer, allocatable :: ipiv(:) 605 605 integer, allocatable :: ipiv(:)
606 606
double precision, external :: zlange 607 607 double precision, external :: zlange
608 608
609 609
status=1 610 610 status=1
611 611
anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm 612 612 anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm
613 613
allocate(wc_a(d,d)) 614 614 allocate(wc_a(d,d))
!call zcopy(d*d,a,1,wc_a,1) 615 615 !call zcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 616 616 wc_a(:,:)=a(:,:)
617 617
allocate(ipiv(d)) 618 618 allocate(ipiv(d))
call zgetrf(d,d,wc_a,d,ipiv,info) 619 619 call zgetrf(d,d,wc_a,d,ipiv,info)
if (info /= 0) then 620 620 if (info /= 0) then
status=0 621 621 status=0
deallocate(ipiv) 622 622 deallocate(ipiv)
deallocate(wc_a) 623 623 deallocate(wc_a)
return 624 624 return
end if 625 625 end if
626 626
allocate(work(2*d)) 627 627 allocate(work(2*d))
allocate(rwork(2*d)) 628 628 allocate(rwork(2*d))
call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) 629 629 call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info)
if (info /= 0) then 630 630 if (info /= 0) then
status=0 631 631 status=0
end if 632 632 end if
deallocate(rwork) 633 633 deallocate(rwork)
deallocate(work) 634 634 deallocate(work)
deallocate(ipiv) 635 635 deallocate(ipiv)
deallocate(wc_a) 636 636 deallocate(wc_a)
end subroutine 637 637 end subroutine
638 638
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 639 639 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 640 640 !
! Valeurs propres/ Vecteurs propre 641 641 ! Valeurs propres/ Vecteurs propre
! 642 642 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 643 643 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
644 644
subroutine fvn_s_matev(d,a,evala,eveca,status) 645 645 subroutine fvn_s_matev(d,a,evala,eveca,status)
! 646 646 !
! integer d (in) : matrice rank 647 647 ! integer d (in) : matrice rank
! real a(d,d) (in) : The Matrix 648 648 ! real a(d,d) (in) : The Matrix
! complex evala(d) (out) : eigenvalues 649 649 ! complex evala(d) (out) : eigenvalues
! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 650 650 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 651 651 ! integer (out) : status =0 if something went wrong
! 652 652 !
! interfacing Lapack routine SGEEV 653 653 ! interfacing Lapack routine SGEEV
654 654
integer, intent(in) :: d 655 655 integer, intent(in) :: d
real, intent(in) :: a(d,d) 656 656 real, intent(in) :: a(d,d)
complex, intent(out) :: evala(d) 657 657 complex, intent(out) :: evala(d)
complex, intent(out) :: eveca(d,d) 658 658 complex, intent(out) :: eveca(d,d)
integer, intent(out) :: status 659 659 integer, intent(out) :: status
660 660
real, allocatable :: wc_a(:,:) ! a working copy of a 661 661 real, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 662 662 integer :: info
integer :: lwork 663 663 integer :: lwork
real, allocatable :: wr(:),wi(:) 664 664 real, allocatable :: wr(:),wi(:)
real :: vl ! unused but necessary for the call 665 665 real :: vl ! unused but necessary for the call
real, allocatable :: vr(:,:) 666 666 real, allocatable :: vr(:,:)
real, allocatable :: work(:) 667 667 real, allocatable :: work(:)
real :: twork(1) 668 668 real :: twork(1)
integer i 669 669 integer i
integer j 670 670 integer j
671 671
! making a working copy of a 672 672 ! making a working copy of a
allocate(wc_a(d,d)) 673 673 allocate(wc_a(d,d))
!call scopy(d*d,a,1,wc_a,1) 674 674 !call scopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 675 675 wc_a(:,:)=a(:,:)
676 676
allocate(wr(d)) 677 677 allocate(wr(d))
allocate(wi(d)) 678 678 allocate(wi(d))
allocate(vr(d,d)) 679 679 allocate(vr(d,d))
! query optimal work size 680 680 ! query optimal work size
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) 681 681 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
lwork=int(twork(1)) 682 682 lwork=int(twork(1))
allocate(work(lwork)) 683 683 allocate(work(lwork))
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) 684 684 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
685 685
if (info /= 0) then 686 686 if (info /= 0) then
status=0 687 687 status=0
deallocate(work) 688 688 deallocate(work)
deallocate(vr) 689 689 deallocate(vr)
deallocate(wi) 690 690 deallocate(wi)
deallocate(wr) 691 691 deallocate(wr)
deallocate(wc_a) 692 692 deallocate(wc_a)
return 693 693 return
end if 694 694 end if
695 695
! now fill in the results 696 696 ! now fill in the results
i=1 697 697 i=1
do while(i<=d) 698 698 do while(i<=d)
evala(i)=cmplx(wr(i),wi(i)) 699 699 evala(i)=cmplx(wr(i),wi(i))
if (wi(i) == 0.) then ! eigenvalue is real 700 700 if (wi(i) == 0.) then ! eigenvalue is real
eveca(:,i)=cmplx(vr(:,i),0.) 701 701 eveca(:,i)=cmplx(vr(:,i),0.)
else ! eigenvalue is complex 702 702 else ! eigenvalue is complex
evala(i+1)=cmplx(wr(i+1),wi(i+1)) 703 703 evala(i+1)=cmplx(wr(i+1),wi(i+1))
eveca(:,i)=cmplx(vr(:,i),vr(:,i+1)) 704 704 eveca(:,i)=cmplx(vr(:,i),vr(:,i+1))
eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1)) 705 705 eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1))
i=i+1 706 706 i=i+1
end if 707 707 end if
i=i+1 708 708 i=i+1
enddo 709 709 enddo
deallocate(work) 710 710 deallocate(work)
deallocate(vr) 711 711 deallocate(vr)
deallocate(wi) 712 712 deallocate(wi)
deallocate(wr) 713 713 deallocate(wr)
deallocate(wc_a) 714 714 deallocate(wc_a)
715 715
end subroutine 716 716 end subroutine
717 717
subroutine fvn_d_matev(d,a,evala,eveca,status) 718 718 subroutine fvn_d_matev(d,a,evala,eveca,status)
! 719 719 !
! integer d (in) : matrice rank 720 720 ! integer d (in) : matrice rank
! double precision a(d,d) (in) : The Matrix 721 721 ! double precision a(d,d) (in) : The Matrix
! double complex evala(d) (out) : eigenvalues 722 722 ! double complex evala(d) (out) : eigenvalues
! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 723 723 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 724 724 ! integer (out) : status =0 if something went wrong
! 725 725 !
! interfacing Lapack routine DGEEV 726 726 ! interfacing Lapack routine DGEEV
integer, intent(in) :: d 727 727 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 728 728 double precision, intent(in) :: a(d,d)
double complex, intent(out) :: evala(d) 729 729 double complex, intent(out) :: evala(d)
double complex, intent(out) :: eveca(d,d) 730 730 double complex, intent(out) :: eveca(d,d)
integer, intent(out) :: status 731 731 integer, intent(out) :: status
732 732
double precision, allocatable :: wc_a(:,:) ! a working copy of a 733 733 double precision, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 734 734 integer :: info
integer :: lwork 735 735 integer :: lwork
double precision, allocatable :: wr(:),wi(:) 736 736 double precision, allocatable :: wr(:),wi(:)
double precision :: vl ! unused but necessary for the call 737 737 double precision :: vl ! unused but necessary for the call
double precision, allocatable :: vr(:,:) 738 738 double precision, allocatable :: vr(:,:)
double precision, allocatable :: work(:) 739 739 double precision, allocatable :: work(:)
double precision :: twork(1) 740 740 double precision :: twork(1)
integer i 741 741 integer i
integer j 742 742 integer j
743 743
! making a working copy of a 744 744 ! making a working copy of a
allocate(wc_a(d,d)) 745 745 allocate(wc_a(d,d))
!call dcopy(d*d,a,1,wc_a,1) 746 746 !call dcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 747 747 wc_a(:,:)=a(:,:)
748 748
allocate(wr(d)) 749 749 allocate(wr(d))
allocate(wi(d)) 750 750 allocate(wi(d))
allocate(vr(d,d)) 751 751 allocate(vr(d,d))
! query optimal work size 752 752 ! query optimal work size
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) 753 753 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
lwork=int(twork(1)) 754 754 lwork=int(twork(1))
allocate(work(lwork)) 755 755 allocate(work(lwork))
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) 756 756 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
757 757
if (info /= 0) then 758 758 if (info /= 0) then
status=0 759 759 status=0
deallocate(work) 760 760 deallocate(work)
deallocate(vr) 761 761 deallocate(vr)
deallocate(wi) 762 762 deallocate(wi)
deallocate(wr) 763 763 deallocate(wr)
deallocate(wc_a) 764 764 deallocate(wc_a)
return 765 765 return
end if 766 766 end if
767 767
! now fill in the results 768 768 ! now fill in the results
i=1 769 769 i=1
do while(i<=d) 770 770 do while(i<=d)
evala(i)=dcmplx(wr(i),wi(i)) 771 771 evala(i)=dcmplx(wr(i),wi(i))
if (wi(i) == 0.) then ! eigenvalue is real 772 772 if (wi(i) == 0.) then ! eigenvalue is real
eveca(:,i)=dcmplx(vr(:,i),0.) 773 773 eveca(:,i)=dcmplx(vr(:,i),0.)
else ! eigenvalue is complex 774 774 else ! eigenvalue is complex
evala(i+1)=dcmplx(wr(i+1),wi(i+1)) 775 775 evala(i+1)=dcmplx(wr(i+1),wi(i+1))
eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1)) 776 776 eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1))
eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1)) 777 777 eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1))
i=i+1 778 778 i=i+1
end if 779 779 end if
i=i+1 780 780 i=i+1
enddo 781 781 enddo
782 782
deallocate(work) 783 783 deallocate(work)
deallocate(vr) 784 784 deallocate(vr)
deallocate(wi) 785 785 deallocate(wi)
deallocate(wr) 786 786 deallocate(wr)
deallocate(wc_a) 787 787 deallocate(wc_a)
788 788
end subroutine 789 789 end subroutine
790 790
subroutine fvn_c_matev(d,a,evala,eveca,status) 791 791 subroutine fvn_c_matev(d,a,evala,eveca,status)
! 792 792 !
! integer d (in) : matrice rank 793 793 ! integer d (in) : matrice rank
! complex a(d,d) (in) : The Matrix 794 794 ! complex a(d,d) (in) : The Matrix
! complex evala(d) (out) : eigenvalues 795 795 ! complex evala(d) (out) : eigenvalues
! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 796 796 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 797 797 ! integer (out) : status =0 if something went wrong
! 798 798 !
! interfacing Lapack routine CGEEV 799 799 ! interfacing Lapack routine CGEEV
800 800
integer, intent(in) :: d 801 801 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 802 802 complex, intent(in) :: a(d,d)
complex, intent(out) :: evala(d) 803 803 complex, intent(out) :: evala(d)
complex, intent(out) :: eveca(d,d) 804 804 complex, intent(out) :: eveca(d,d)
integer, intent(out) :: status 805 805 integer, intent(out) :: status
806 806
complex, allocatable :: wc_a(:,:) ! a working copy of a 807 807 complex, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 808 808 integer :: info
integer :: lwork 809 809 integer :: lwork
complex, allocatable :: work(:) 810 810 complex, allocatable :: work(:)
complex :: twork(1) 811 811 complex :: twork(1)
real, allocatable :: rwork(:) 812 812 real, allocatable :: rwork(:)
complex :: vl ! unused but necessary for the call 813 813 complex :: vl ! unused but necessary for the call
814 814
status=1 815 815 status=1
816 816
! making a working copy of a 817 817 ! making a working copy of a
allocate(wc_a(d,d)) 818 818 allocate(wc_a(d,d))
!call ccopy(d*d,a,1,wc_a,1) 819 819 !call ccopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 820 820 wc_a(:,:)=a(:,:)
821 821
822 822
! query optimal work size 823 823 ! query optimal work size
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) 824 824 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
lwork=int(twork(1)) 825 825 lwork=int(twork(1))
allocate(work(lwork)) 826 826 allocate(work(lwork))
allocate(rwork(2*d)) 827 827 allocate(rwork(2*d))
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) 828 828 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
829 829
if (info /= 0) then 830 830 if (info /= 0) then
status=0 831 831 status=0
end if 832 832 end if
deallocate(rwork) 833 833 deallocate(rwork)
deallocate(work) 834 834 deallocate(work)
deallocate(wc_a) 835 835 deallocate(wc_a)
836 836
end subroutine 837 837 end subroutine
838 838
subroutine fvn_z_matev(d,a,evala,eveca,status) 839 839 subroutine fvn_z_matev(d,a,evala,eveca,status)
! 840 840 !
! integer d (in) : matrice rank 841 841 ! integer d (in) : matrice rank
! double complex a(d,d) (in) : The Matrix 842 842 ! double complex a(d,d) (in) : The Matrix
! double complex evala(d) (out) : eigenvalues 843 843 ! double complex evala(d) (out) : eigenvalues
! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 844 844 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 845 845 ! integer (out) : status =0 if something went wrong
! 846 846 !
! interfacing Lapack routine ZGEEV 847 847 ! interfacing Lapack routine ZGEEV
848 848
integer, intent(in) :: d 849 849 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 850 850 double complex, intent(in) :: a(d,d)
double complex, intent(out) :: evala(d) 851 851 double complex, intent(out) :: evala(d)
double complex, intent(out) :: eveca(d,d) 852 852 double complex, intent(out) :: eveca(d,d)
integer, intent(out) :: status 853 853 integer, intent(out) :: status
854 854
double complex, allocatable :: wc_a(:,:) ! a working copy of a 855 855 double complex, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 856 856 integer :: info
integer :: lwork 857 857 integer :: lwork
double complex, allocatable :: work(:) 858 858 double complex, allocatable :: work(:)
double complex :: twork(1) 859 859 double complex :: twork(1)
double precision, allocatable :: rwork(:) 860 860 double precision, allocatable :: rwork(:)
double complex :: vl ! unused but necessary for the call 861 861 double complex :: vl ! unused but necessary for the call
862 862
status=1 863 863 status=1
864 864
! making a working copy of a 865 865 ! making a working copy of a
allocate(wc_a(d,d)) 866 866 allocate(wc_a(d,d))
!call zcopy(d*d,a,1,wc_a,1) 867 867 !call zcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 868 868 wc_a(:,:)=a(:,:)
869 869
! query optimal work size 870 870 ! query optimal work size
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) 871 871 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
lwork=int(twork(1)) 872 872 lwork=int(twork(1))
allocate(work(lwork)) 873 873 allocate(work(lwork))
allocate(rwork(2*d)) 874 874 allocate(rwork(2*d))
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) 875 875 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
876 876
if (info /= 0) then 877 877 if (info /= 0) then
status=0 878 878 status=0
end if 879 879 end if
deallocate(rwork) 880 880 deallocate(rwork)
deallocate(work) 881 881 deallocate(work)
deallocate(wc_a) 882 882 deallocate(wc_a)
883 883
end subroutine 884 884 end subroutine
885 885
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 886 886 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 887 887 !
! Akima spline interpolation and spline evaluation 888 888 ! Akima spline interpolation and spline evaluation
! 889 889 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 890 890 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
891 891
! Single precision 892 892 ! Single precision
subroutine fvn_s_akima(n,x,y,br,co) 893 893 subroutine fvn_s_akima(n,x,y,br,co)
implicit none 894 894 implicit none
integer, intent(in) :: n 895 895 integer, intent(in) :: n
real, intent(in) :: x(n) 896 896 real, intent(in) :: x(n)
real, intent(in) :: y(n) 897 897 real, intent(in) :: y(n)
real, intent(out) :: br(n) 898 898 real, intent(out) :: br(n)
real, intent(out) :: co(4,n) 899 899 real, intent(out) :: co(4,n)
900 900
real, allocatable :: var(:),z(:) 901 901 real, allocatable :: var(:),z(:)
real :: wi_1,wi 902 902 real :: wi_1,wi
integer :: i 903 903 integer :: i
real :: dx,a,b 904 904 real :: dx,a,b
905 905
! br is just a copy of x 906 906 ! br is just a copy of x
br(:)=x(:) 907 907 br(:)=x(:)
908 908
allocate(var(n)) 909 909 allocate(var(n))
allocate(z(n)) 910 910 allocate(z(n))
! evaluate the variations 911 911 ! evaluate the variations
do i=1, n-1 912 912 do i=1, n-1
var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i)) 913 913 var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i))
end do 914 914 end do
var(n+2)=2.e0*var(n+1)-var(n) 915 915 var(n+2)=2.e0*var(n+1)-var(n)
var(n+3)=2.e0*var(n+2)-var(n+1) 916 916 var(n+3)=2.e0*var(n+2)-var(n+1)
var(2)=2.e0*var(3)-var(4) 917 917 var(2)=2.e0*var(3)-var(4)
var(1)=2.e0*var(2)-var(3) 918 918 var(1)=2.e0*var(2)-var(3)
919 919
do i = 1, n 920 920 do i = 1, n
wi_1=abs(var(i+3)-var(i+2)) 921 921 wi_1=abs(var(i+3)-var(i+2))
wi=abs(var(i+1)-var(i)) 922 922 wi=abs(var(i+1)-var(i))
if ((wi_1+wi).eq.0.e0) then 923 923 if ((wi_1+wi).eq.0.e0) then
z(i)=(var(i+2)+var(i+1))/2.e0 924 924 z(i)=(var(i+2)+var(i+1))/2.e0
else 925 925 else
z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi) 926 926 z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi)
end if 927 927 end if
end do 928 928 end do
929 929
do i=1, n-1 930 930 do i=1, n-1
dx=x(i+1)-x(i) 931 931 dx=x(i+1)-x(i)
a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd 932 932 a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd
b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd 933 933 b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd
co(1,i)=y(i) 934 934 co(1,i)=y(i)
co(2,i)=z(i) 935 935 co(2,i)=z(i)
!co(3,i)=-(a-3.*b)/dx**2 ! mรฉthode wd 936 936 !co(3,i)=-(a-3.*b)/dx**2 ! mรฉthode wd
!co(4,i)=(a-2.*b)/dx**3 ! mรฉthode wd 937 937 !co(4,i)=(a-2.*b)/dx**3 ! mรฉthode wd
co(3,i)=(3.e0*var(i+2)-2.e0*z(i)-z(i+1))/dx ! mรฉthode JP Moreau 938 938 co(3,i)=(3.e0*var(i+2)-2.e0*z(i)-z(i+1))/dx ! mรฉthode JP Moreau
co(4,i)=(z(i)+z(i+1)-2.e0*var(i+2))/dx**2 ! 939 939 co(4,i)=(z(i)+z(i+1)-2.e0*var(i+2))/dx**2 !
! les coefficients donnรฉs par imsl sont co(3,i)*2 et co(4,i)*6 940 940 ! les coefficients donnรฉs par imsl sont co(3,i)*2 et co(4,i)*6
! etrangement la fonction csval corrige et donne la bonne valeur ... 941 941 ! etrangement la fonction csval corrige et donne la bonne valeur ...
end do 942 942 end do
co(1,n)=y(n) 943 943 co(1,n)=y(n)
co(2,n)=z(n) 944 944 co(2,n)=z(n)
co(3,n)=0.e0 945 945 co(3,n)=0.e0
co(4,n)=0.e0 946 946 co(4,n)=0.e0
947 947
deallocate(z) 948 948 deallocate(z)
deallocate(var) 949 949 deallocate(var)
950 950
end subroutine 951 951 end subroutine
952 952
! Double precision 953 953 ! Double precision
subroutine fvn_d_akima(n,x,y,br,co) 954 954 subroutine fvn_d_akima(n,x,y,br,co)
955 955
implicit none 956 956 implicit none
integer, intent(in) :: n 957 957 integer, intent(in) :: n
double precision, intent(in) :: x(n) 958 958 double precision, intent(in) :: x(n)
double precision, intent(in) :: y(n) 959 959 double precision, intent(in) :: y(n)
double precision, intent(out) :: br(n) 960 960 double precision, intent(out) :: br(n)
double precision, intent(out) :: co(4,n) 961 961 double precision, intent(out) :: co(4,n)
962 962
double precision, allocatable :: var(:),z(:) 963 963 double precision, allocatable :: var(:),z(:)
double precision :: wi_1,wi 964 964 double precision :: wi_1,wi
integer :: i 965 965 integer :: i
double precision :: dx,a,b 966 966 double precision :: dx,a,b
967 967
! br is just a copy of x 968 968 ! br is just a copy of x
br(:)=x(:) 969 969 br(:)=x(:)
970 970
allocate(var(n)) 971 971 allocate(var(n))
allocate(z(n)) 972 972 allocate(z(n))
! evaluate the variations 973 973 ! evaluate the variations
do i=1, n-1 974 974 do i=1, n-1
var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i)) 975 975 var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i))
end do 976 976 end do
var(n+2)=2.d0*var(n+1)-var(n) 977 977 var(n+2)=2.d0*var(n+1)-var(n)
var(n+3)=2.d0*var(n+2)-var(n+1) 978 978 var(n+3)=2.d0*var(n+2)-var(n+1)
var(2)=2.d0*var(3)-var(4) 979 979 var(2)=2.d0*var(3)-var(4)
var(1)=2.d0*var(2)-var(3) 980 980 var(1)=2.d0*var(2)-var(3)
981 981
do i = 1, n 982 982 do i = 1, n
wi_1=dabs(var(i+3)-var(i+2)) 983 983 wi_1=dabs(var(i+3)-var(i+2))
wi=dabs(var(i+1)-var(i)) 984 984 wi=dabs(var(i+1)-var(i))
if ((wi_1+wi).eq.0.d0) then 985 985 if ((wi_1+wi).eq.0.d0) then
z(i)=(var(i+2)+var(i+1))/2.d0 986 986 z(i)=(var(i+2)+var(i+1))/2.d0
else 987 987 else
z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi) 988 988 z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi)
end if 989 989 end if
end do 990 990 end do
991 991
do i=1, n-1 992 992 do i=1, n-1
dx=x(i+1)-x(i) 993 993 dx=x(i+1)-x(i)
a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd 994 994 a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd
b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd 995 995 b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd
co(1,i)=y(i) 996 996 co(1,i)=y(i)
co(2,i)=z(i) 997 997 co(2,i)=z(i)
!co(3,i)=-(a-3.*b)/dx**2 ! mรฉthode wd 998 998 !co(3,i)=-(a-3.*b)/dx**2 ! mรฉthode wd
!co(4,i)=(a-2.*b)/dx**3 ! mรฉthode wd 999 999 !co(4,i)=(a-2.*b)/dx**3 ! mรฉthode wd
co(3,i)=(3.d0*var(i+2)-2.d0*z(i)-z(i+1))/dx ! mรฉthode JP Moreau 1000 1000 co(3,i)=(3.d0*var(i+2)-2.d0*z(i)-z(i+1))/dx ! mรฉthode JP Moreau
co(4,i)=(z(i)+z(i+1)-2.d0*var(i+2))/dx**2 ! 1001 1001 co(4,i)=(z(i)+z(i+1)-2.d0*var(i+2))/dx**2 !
! les coefficients donnรฉs par imsl sont co(3,i)*2 et co(4,i)*6 1002 1002 ! les coefficients donnรฉs par imsl sont co(3,i)*2 et co(4,i)*6
! etrangement la fonction csval corrige et donne la bonne valeur ... 1003 1003 ! etrangement la fonction csval corrige et donne la bonne valeur ...
end do 1004 1004 end do
co(1,n)=y(n) 1005 1005 co(1,n)=y(n)
co(2,n)=z(n) 1006 1006 co(2,n)=z(n)
co(3,n)=0.d0 1007 1007 co(3,n)=0.d0
co(4,n)=0.d0 1008 1008 co(4,n)=0.d0
1009 1009
deallocate(z) 1010 1010 deallocate(z)
deallocate(var) 1011 1011 deallocate(var)
1012 1012
end subroutine 1013 1013 end subroutine
1014 1014
! 1015 1015 !
! Single precision spline evaluation 1016 1016 ! Single precision spline evaluation
! 1017 1017 !
function fvn_s_spline_eval(x,n,br,co) 1018 1018 function fvn_s_spline_eval(x,n,br,co)
implicit none 1019 1019 implicit none
real, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated 1020 1020 real, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated
integer, intent(in) :: n ! number of intervals 1021 1021 integer, intent(in) :: n ! number of intervals
real, intent(in) :: br(n+1) ! breakpoints 1022 1022 real, intent(in) :: br(n+1) ! breakpoints
real, intent(in) :: co(4,n+1) ! spline coeeficients 1023 1023 real, intent(in) :: co(4,n+1) ! spline coeeficients
real :: fvn_s_spline_eval 1024 1024 real :: fvn_s_spline_eval
1025 1025
integer :: i 1026 1026 integer :: i
real :: dx 1027 1027 real :: dx
1028 1028
if (x<=br(1)) then 1029 1029 if (x<=br(1)) then
i=1 1030 1030 i=1
else if (x>=br(n+1)) then 1031 1031 else if (x>=br(n+1)) then
i=n 1032 1032 i=n
else 1033 1033 else
i=1 1034 1034 i=1
do while(x>=br(i)) 1035 1035 do while(x>=br(i))
i=i+1 1036 1036 i=i+1
end do 1037 1037 end do
i=i-1 1038 1038 i=i-1
end if 1039 1039 end if
dx=x-br(i) 1040 1040 dx=x-br(i)
fvn_s_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3 1041 1041 fvn_s_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3
1042 1042
end function 1043 1043 end function
1044 1044
! Double precision spline evaluation 1045 1045 ! Double precision spline evaluation
function fvn_d_spline_eval(x,n,br,co) 1046 1046 function fvn_d_spline_eval(x,n,br,co)
implicit none 1047 1047 implicit none
double precision, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated 1048 1048 double precision, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated
integer, intent(in) :: n ! number of intervals 1049 1049 integer, intent(in) :: n ! number of intervals
double precision, intent(in) :: br(n+1) ! breakpoints 1050 1050 double precision, intent(in) :: br(n+1) ! breakpoints
double precision, intent(in) :: co(4,n+1) ! spline coeeficients 1051 1051 double precision, intent(in) :: co(4,n+1) ! spline coeeficients
double precision :: fvn_d_spline_eval 1052 1052 double precision :: fvn_d_spline_eval
1053 1053
integer :: i 1054 1054 integer :: i
double precision :: dx 1055 1055 double precision :: dx
1056 1056
1057 1057
if (x<=br(1)) then 1058 1058 if (x<=br(1)) then
i=1 1059 1059 i=1
else if (x>=br(n+1)) then 1060 1060 else if (x>=br(n+1)) then
i=n 1061 1061 i=n
else 1062 1062 else
i=1 1063 1063 i=1
do while(x>=br(i)) 1064 1064 do while(x>=br(i))
i=i+1 1065 1065 i=i+1
end do 1066 1066 end do
i=i-1 1067 1067 i=i-1
end if 1068 1068 end if
1069 1069
dx=x-br(i) 1070 1070 dx=x-br(i)
fvn_d_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3 1071 1071 fvn_d_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3
1072 1072
end function 1073 1073 end function
1074 1074
1075 1075
! 1076 1076 !
! Muller 1077 1077 ! Muller
! 1078 1078 !
! 1079 1079 !
! 1080 1080 !
! William Daniau 2007 1081 1081 ! William Daniau 2007
! 1082 1082 !
! This routine is a fortran 90 port of Hans D. Mittelmann's routine muller.f 1083 1083 ! This routine is a fortran 90 port of Hans D. Mittelmann's routine muller.f
! http://plato.asu.edu/ftp/other_software/muller.f 1084 1084 ! http://plato.asu.edu/ftp/other_software/muller.f
! 1085 1085 !
! it can be used as a replacement for imsl routine dzanly with minor changes 1086 1086 ! it can be used as a replacement for imsl routine dzanly with minor changes
! 1087 1087 !
!----------------------------------------------------------------------- 1088 1088 !-----------------------------------------------------------------------
! 1089 1089 !
! purpose - zeros of an analytic complex function 1090 1090 ! purpose - zeros of an analytic complex function
! using the muller method with deflation 1091 1091 ! using the muller method with deflation
! 1092 1092 !
! usage - call fvn_z_muller (f,eps,eps1,kn,n,nguess,x,itmax, 1093 1093 ! usage - call fvn_z_muller (f,eps,eps1,kn,n,nguess,x,itmax,
! infer,ier) 1094 1094 ! infer,ier)
! 1095 1095 !
! arguments f - a complex function subprogram, f(z), written 1096 1096 ! arguments f - a complex function subprogram, f(z), written
! by the user specifying the equation whose 1097 1097 ! by the user specifying the equation whose
! roots are to be found. f must appear in 1098 1098 ! roots are to be found. f must appear in
! an external statement in the calling pro- 1099 1099 ! an external statement in the calling pro-
! gram. 1100 1100 ! gram.
! eps - 1st stopping criterion. let fp(z)=f(z)/p 1101 1101 ! eps - 1st stopping criterion. let fp(z)=f(z)/p
! where p = (z-z(1))*(z-z(2))*,,,*(z-z(k-1)) 1102 1102 ! where p = (z-z(1))*(z-z(2))*,,,*(z-z(k-1))
! and z(1),...,z(k-1) are previously found 1103 1103 ! and z(1),...,z(k-1) are previously found
! roots. if ((cdabs(f(z)).le.eps) .and. 1104 1104 ! roots. if ((cdabs(f(z)).le.eps) .and.
! (cdabs(fp(z)).le.eps)), then z is accepted 1105 1105 ! (cdabs(fp(z)).le.eps)), then z is accepted
! as a root. (input) 1106 1106 ! as a root. (input)
! eps1 - 2nd stopping criterion. a root is accepted 1107 1107 ! eps1 - 2nd stopping criterion. a root is accepted
! if two successive approximations to a given 1108 1108 ! if two successive approximations to a given
! root agree within eps1. (input) 1109 1109 ! root agree within eps1. (input)
! note. if either or both of the stopping 1110 1110 ! note. if either or both of the stopping
! criteria are fulfilled, the root is 1111 1111 ! criteria are fulfilled, the root is
! accepted. 1112 1112 ! accepted.
! kn - the number of known roots which must be stored 1113 1113 ! kn - the number of known roots which must be stored
! in x(1),...,x(kn), prior to entry to muller 1114 1114 ! in x(1),...,x(kn), prior to entry to muller
! nguess - the number of initial guesses provided. these 1115 1115 ! nguess - the number of initial guesses provided. these
! guesses must be stored in x(kn+1),..., 1116 1116 ! guesses must be stored in x(kn+1),...,
! x(kn+nguess). nguess must be set equal 1117 1117 ! x(kn+nguess). nguess must be set equal
! to zero if no guesses are provided. (input) 1118 1118 ! to zero if no guesses are provided. (input)
! n - the number of new roots to be found by 1119 1119 ! n - the number of new roots to be found by
! muller (input) 1120 1120 ! muller (input)
! x - a complex vector of length kn+n. x(1),..., 1121 1121 ! x - a complex vector of length kn+n. x(1),...,
! x(kn) on input must contain any known 1122 1122 ! x(kn) on input must contain any known
! roots. x(kn+1),..., x(kn+n) on input may, 1123 1123 ! roots. x(kn+1),..., x(kn+n) on input may,
! on user option, contain initial guesses for 1124 1124 ! on user option, contain initial guesses for
! the n new roots which are to be computed. 1125 1125 ! the n new roots which are to be computed.
! if the user does not provide an initial 1126 1126 ! if the user does not provide an initial
! guess, zero is used. 1127 1127 ! guess, zero is used.
! on output, x(kn+1),...,x(kn+n) contain the 1128 1128 ! on output, x(kn+1),...,x(kn+n) contain the
! approximate roots found by muller. 1129 1129 ! approximate roots found by muller.
! itmax - the maximum allowable number of iterations 1130 1130 ! itmax - the maximum allowable number of iterations
! per root (input) 1131 1131 ! per root (input)
! infer - an integer vector of length kn+n. on 1132 1132 ! infer - an integer vector of length kn+n. on
! output infer(j) contains the number of 1133 1133 ! output infer(j) contains the number of
! iterations used in finding the j-th root 1134 1134 ! iterations used in finding the j-th root
! when convergence was achieved. if 1135 1135 ! when convergence was achieved. if
! convergence was not obtained in itmax 1136 1136 ! convergence was not obtained in itmax
! iterations, infer(j) will be greater than 1137 1137 ! iterations, infer(j) will be greater than
! itmax (output). 1138 1138 ! itmax (output).
! ier - error parameter (output) 1139 1139 ! ier - error parameter (output)
! warning error 1140 1140 ! warning error
! ier = 33 indicates failure to converge with- 1141 1141 ! ier = 33 indicates failure to converge with-
! in itmax iterations for at least one of 1142 1142 ! in itmax iterations for at least one of
! the (n) new roots. 1143 1143 ! the (n) new roots.
! 1144 1144 !
! 1145 1145 !
! remarks muller always returns the last approximation for root j 1146 1146 ! remarks muller always returns the last approximation for root j
! in x(j). if the convergence criterion is satisfied, 1147 1147 ! in x(j). if the convergence criterion is satisfied,
! then infer(j) is less than or equal to itmax. if the 1148 1148 ! then infer(j) is less than or equal to itmax. if the
! convergence criterion is not satisified, then infer(j) 1149 1149 ! convergence criterion is not satisified, then infer(j)
! is set to either itmax+1 or itmax+k, with k greater 1150 1150 ! is set to either itmax+1 or itmax+k, with k greater
! than 1. infer(j) = itmax+1 indicates that muller did 1151 1151 ! than 1. infer(j) = itmax+1 indicates that muller did
! not obtain convergence in the allowed number of iter- 1152 1152 ! not obtain convergence in the allowed number of iter-
! ations. in this case, the user may wish to set itmax 1153 1153 ! ations. in this case, the user may wish to set itmax
! to a larger value. infer(j) = itmax+k means that con- 1154 1154 ! to a larger value. infer(j) = itmax+k means that con-
! vergence was obtained (on iteration k) for the defla- 1155 1155 ! vergence was obtained (on iteration k) for the defla-
! ted function 1156 1156 ! ted function
! fp(z) = f(z)/((z-z(1)...(z-z(j-1))) 1157 1157 ! fp(z) = f(z)/((z-z(1)...(z-z(j-1)))
! 1158 1158 !
! but failed for f(z). in this case, better initial 1159 1159 ! but failed for f(z). in this case, better initial
! guesses might help or, it might be necessary to relax 1160 1160 ! guesses might help or, it might be necessary to relax
! the convergence criterion. 1161 1161 ! the convergence criterion.
! 1162 1162 !
!----------------------------------------------------------------------- 1163 1163 !-----------------------------------------------------------------------
! 1164 1164 !
subroutine fvn_z_muller (f,eps,eps1,kn,nguess,n,x,itmax,infer,ier) 1165 1165 subroutine fvn_z_muller (f,eps,eps1,kn,nguess,n,x,itmax,infer,ier)
implicit none 1166 1166 implicit none
double precision :: rzero,rten,rhun,rp01,ax,eps1,qz,eps,tpq 1167 1167 double precision :: rzero,rten,rhun,rp01,ax,eps1,qz,eps,tpq
double complex :: d,dd,den,fprt,frt,h,rt,t1,t2,t3, & 1168 1168 double complex :: d,dd,den,fprt,frt,h,rt,t1,t2,t3, &
tem,z0,z1,z2,bi,xx,xl,y0,y1,y2,x0, & 1169 1169 tem,z0,z1,z2,bi,xx,xl,y0,y1,y2,x0, &
zero,p1,one,four,p5 1170 1170 zero,p1,one,four,p5
1171 1171
double complex, external :: f 1172 1172 double complex, external :: f
integer :: ickmax,kn,nguess,n,itmax,ier,knp1,knpn,i,l,ic, & 1173 1173 integer :: ickmax,kn,nguess,n,itmax,ier,knp1,knpn,i,l,ic, &
knpng,jk,ick,nn,lm1,errcode 1174 1174 knpng,jk,ick,nn,lm1,errcode
double complex :: x(kn+n) 1175 1175 double complex :: x(kn+n)
integer :: infer(kn+n) 1176 1176 integer :: infer(kn+n)
1177 1177
1178 1178
data zero/(0.0,0.0)/,p1/(0.1,0.0)/, & 1179 1179 data zero/(0.0,0.0)/,p1/(0.1,0.0)/, &
one/(1.0,0.0)/,four/(4.0,0.0)/, & 1180 1180 one/(1.0,0.0)/,four/(4.0,0.0)/, &
p5/(0.5,0.0)/, & 1181 1181 p5/(0.5,0.0)/, &
rzero/0.0/,rten/10.0/,rhun/100.0/, & 1182 1182 rzero/0.0/,rten/10.0/,rhun/100.0/, &
ax/0.1/,ickmax/3/,rp01/0.01/ 1183 1183 ax/0.1/,ickmax/3/,rp01/0.01/
1184 1184
ier = 0 1185 1185 ier = 0
if (n .lt. 1) then ! What the hell are doing here then ... 1186 1186 if (n .lt. 1) then ! What the hell are doing here then ...
return 1187 1187 return
end if 1188 1188 end if
!eps1 = rten **(-nsig) 1189 1189 !eps1 = rten **(-nsig)
eps1 = min(eps1,rp01) 1190 1190 eps1 = min(eps1,rp01)
1191 1191
knp1 = kn+1 1192 1192 knp1 = kn+1
knpn = kn+n 1193 1193 knpn = kn+n
knpng = kn+nguess 1194 1194 knpng = kn+nguess
do i=1,knpn 1195 1195 do i=1,knpn
infer(i) = 0 1196 1196 infer(i) = 0
if (i .gt. knpng) x(i) = zero 1197 1197 if (i .gt. knpng) x(i) = zero
end do 1198 1198 end do
l= knp1 1199 1199 l= knp1
1200 1200
ic=0 1201 1201 ic=0
rloop: do while (l<=knpn) ! Main loop over new roots 1202 1202 rloop: do while (l<=knpn) ! Main loop over new roots
jk = 0 1203 1203 jk = 0
ick = 0 1204 1204 ick = 0
xl = x(l) 1205 1205 xl = x(l)
icloop: do 1206 1206 icloop: do
ic = 0 1207 1207 ic = 0
h = ax 1208 1208 h = ax
h = p1*h 1209 1209 h = p1*h
if (cdabs(xl) .gt. ax) h = p1*xl 1210 1210 if (cdabs(xl) .gt. ax) h = p1*xl
! first three points are 1211 1211 ! first three points are
! xl+h, xl-h, xl 1212 1212 ! xl+h, xl-h, xl
rt = xl+h 1213 1213 rt = xl+h
call deflated_work(errcode) 1214 1214 call deflated_work(errcode)
if (errcode == 1) then 1215 1215 if (errcode == 1) then
exit icloop 1216 1216 exit icloop
end if 1217 1217 end if
1218 1218
z0 = fprt 1219 1219 z0 = fprt
y0 = frt 1220 1220 y0 = frt
x0 = rt 1221 1221 x0 = rt
rt = xl-h 1222 1222 rt = xl-h
call deflated_work(errcode) 1223 1223 call deflated_work(errcode)
if (errcode == 1) then 1224 1224 if (errcode == 1) then
exit icloop 1225 1225 exit icloop
end if 1226 1226 end if
1227 1227
z1 = fprt 1228 1228 z1 = fprt
y1 = frt 1229 1229 y1 = frt
h = xl-rt 1230 1230 h = xl-rt
d = h/(rt-x0) 1231 1231 d = h/(rt-x0)
rt = xl 1232 1232 rt = xl
1233 1233
call deflated_work(errcode) 1234 1234 call deflated_work(errcode)
if (errcode == 1) then 1235 1235 if (errcode == 1) then
exit icloop 1236 1236 exit icloop
end if 1237 1237 end if
1238 1238
1239 1239
z2 = fprt 1240 1240 z2 = fprt
y2 = frt 1241 1241 y2 = frt
! begin main algorithm 1242 1242 ! begin main algorithm
iloop: do 1243 1243 iloop: do
dd = one + d 1244 1244 dd = one + d
t1 = z0*d*d 1245 1245 t1 = z0*d*d
t2 = z1*dd*dd 1246 1246 t2 = z1*dd*dd
xx = z2*dd 1247 1247 xx = z2*dd
t3 = z2*d 1248 1248 t3 = z2*d
bi = t1-t2+xx+t3 1249 1249 bi = t1-t2+xx+t3
den = bi*bi-four*(xx*t1-t3*(t2-xx)) 1250 1250 den = bi*bi-four*(xx*t1-t3*(t2-xx))
! use denominator of maximum amplitude 1251 1251 ! use denominator of maximum amplitude
t1 = cdsqrt(den) 1252 1252 t1 = cdsqrt(den)
qz = rhun*max(cdabs(bi),cdabs(t1)) 1253 1253 qz = rhun*max(cdabs(bi),cdabs(t1))
t2 = bi + t1 1254 1254 t2 = bi + t1
tpq = cdabs(t2)+qz 1255 1255 tpq = cdabs(t2)+qz
if (tpq .eq. qz) t2 = zero 1256 1256 if (tpq .eq. qz) t2 = zero
t3 = bi - t1 1257 1257 t3 = bi - t1
tpq = cdabs(t3) + qz 1258 1258 tpq = cdabs(t3) + qz
if (tpq .eq. qz) t3 = zero 1259 1259 if (tpq .eq. qz) t3 = zero
den = t2 1260 1260 den = t2
qz = cdabs(t3)-cdabs(t2) 1261 1261 qz = cdabs(t3)-cdabs(t2)
if (qz .gt. rzero) den = t3 1262 1262 if (qz .gt. rzero) den = t3
! test for zero denominator 1263 1263 ! test for zero denominator
if (cdabs(den) .eq. rzero) then 1264 1264 if (cdabs(den) .eq. rzero) then
call trans_rt() 1265 1265 call trans_rt()
call deflated_work(errcode) 1266 1266 call deflated_work(errcode)
if (errcode == 1) then 1267 1267 if (errcode == 1) then
exit icloop 1268 1268 exit icloop
end if 1269 1269 end if
z2 = fprt 1270 1270 z2 = fprt
y2 = frt 1271 1271 y2 = frt
cycle iloop 1272 1272 cycle iloop
end if 1273 1273 end if
1274 1274
1275 1275
d = -xx/den 1276 1276 d = -xx/den
d = d+d 1277 1277 d = d+d
h = d*h 1278 1278 h = d*h
rt = rt + h 1279 1279 rt = rt + h
! check convergence of the first kind 1280 1280 ! check convergence of the first kind
if (cdabs(h) .le. eps1*max(cdabs(rt),ax)) then 1281 1281 if (cdabs(h) .le. eps1*max(cdabs(rt),ax)) then
if (ic .ne. 0) then 1282 1282 if (ic .ne. 0) then
exit icloop 1283 1283 exit icloop
end if 1284 1284 end if
ic = 1 1285 1285 ic = 1
z0 = y1 1286 1286 z0 = y1
z1 = y2 1287 1287 z1 = y2
z2 = f(rt) 1288 1288 z2 = f(rt)
xl = rt 1289 1289 xl = rt
ick = ick+1 1290 1290 ick = ick+1
if (ick .le. ickmax) then 1291 1291 if (ick .le. ickmax) then
cycle iloop 1292 1292 cycle iloop
end if 1293 1293 end if
! warning error, itmax = maximum 1294 1294 ! warning error, itmax = maximum
jk = itmax + jk 1295 1295 jk = itmax + jk
ier = 33 1296 1296 ier = 33
end if 1297 1297 end if
if (ic .ne. 0) then 1298 1298 if (ic .ne. 0) then
cycle icloop 1299 1299 cycle icloop
end if 1300 1300 end if
call deflated_work(errcode) 1301 1301 call deflated_work(errcode)
if (errcode == 1) then 1302 1302 if (errcode == 1) then
exit icloop 1303 1303 exit icloop
end if 1304 1304 end if
1305 1305
do while ( (cdabs(fprt)-cdabs(z2)*rten) .ge. rzero) 1306 1306 do while ( (cdabs(fprt)-cdabs(z2)*rten) .ge. rzero)
! take remedial action to induce 1307 1307 ! take remedial action to induce
! convergence 1308 1308 ! convergence
d = d*p5 1309 1309 d = d*p5
h = h*p5 1310 1310 h = h*p5
rt = rt-h 1311 1311 rt = rt-h
call deflated_work(errcode) 1312 1312 call deflated_work(errcode)
if (errcode == 1) then 1313 1313 if (errcode == 1) then
exit icloop 1314 1314 exit icloop
end if 1315 1315 end if
end do 1316 1316 end do
z0 = z1 1317 1317 z0 = z1
z1 = z2 1318 1318 z1 = z2
z2 = fprt 1319 1319 z2 = fprt
y0 = y1 1320 1320 y0 = y1
y1 = y2 1321 1321 y1 = y2
y2 = frt 1322 1322 y2 = frt
end do iloop 1323 1323 end do iloop
end do icloop 1324 1324 end do icloop
x(l) = rt 1325 1325 x(l) = rt
infer(l) = jk 1326 1326 infer(l) = jk
l = l+1 1327 1327 l = l+1
end do rloop 1328 1328 end do rloop
1329 1329
contains 1330 1330 contains
subroutine trans_rt() 1331 1331 subroutine trans_rt()
tem = rten*eps1 1332 1332 tem = rten*eps1
if (cdabs(rt) .gt. ax) tem = tem*rt 1333 1333 if (cdabs(rt) .gt. ax) tem = tem*rt
rt = rt+tem 1334 1334 rt = rt+tem
d = (h+tem)*d/h 1335 1335 d = (h+tem)*d/h
h = h+tem 1336 1336 h = h+tem
end subroutine trans_rt 1337 1337 end subroutine trans_rt
1338 1338
subroutine deflated_work(errcode) 1339 1339 subroutine deflated_work(errcode)
! errcode=0 => no errors 1340 1340 ! errcode=0 => no errors
! errcode=1 => jk>itmax or convergence of second kind achieved 1341 1341 ! errcode=1 => jk>itmax or convergence of second kind achieved
integer :: errcode,flag 1342 1342 integer :: errcode,flag
1343 1343
flag=1 1344 1344 flag=1
loop1: do while(flag==1) 1345 1345 loop1: do while(flag==1)
errcode=0 1346 1346 errcode=0
jk = jk+1 1347 1347 jk = jk+1
if (jk .gt. itmax) then 1348 1348 if (jk .gt. itmax) then
ier=33 1349 1349 ier=33
errcode=1 1350 1350 errcode=1
return 1351 1351 return
end if 1352 1352 end if
frt = f(rt) 1353 1353 frt = f(rt)
fprt = frt 1354 1354 fprt = frt
if (l /= 1) then 1355 1355 if (l /= 1) then
lm1 = l-1 1356 1356 lm1 = l-1
do i=1,lm1 1357 1357 do i=1,lm1
tem = rt - x(i) 1358 1358 tem = rt - x(i)
if (cdabs(tem) .eq. rzero) then 1359 1359 if (cdabs(tem) .eq. rzero) then
!if (ic .ne. 0) go to 15 !! ?? possible? 1360 1360 !if (ic .ne. 0) go to 15 !! ?? possible?
call trans_rt() 1361 1361 call trans_rt()
cycle loop1 1362 1362 cycle loop1
end if 1363 1363 end if
fprt = fprt/tem 1364 1364 fprt = fprt/tem
end do 1365 1365 end do
end if 1366 1366 end if
flag=0 1367 1367 flag=0
end do loop1 1368 1368 end do loop1
1369 1369
if (cdabs(fprt) .le. eps .and. cdabs(frt) .le. eps) then 1370 1370 if (cdabs(fprt) .le. eps .and. cdabs(frt) .le. eps) then
errcode=1 1371 1371 errcode=1
return 1372 1372 return
end if 1373 1373 end if
1374 1374
end subroutine deflated_work 1375 1375 end subroutine deflated_work
1376 1376
end subroutine 1377 1377 end subroutine
1378 1378
1379 1379
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1380 1380 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 1381 1381 !
! Integration 1382 1382 ! Integration
! 1383 1383 !
! Only double precision coded atm 1384 1384 ! Only double precision coded atm
! 1385 1385 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1386 1386 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1387 1387
1388 1388
subroutine fvn_d_gauss_legendre(n,qx,qw) 1389 1389 subroutine fvn_d_gauss_legendre(n,qx,qw)
! 1390 1390 !
! This routine compute the n Gauss Legendre abscissas and weights 1391 1391 ! This routine compute the n Gauss Legendre abscissas and weights
! Adapted from Numerical Recipes routine gauleg 1392 1392 ! Adapted from Numerical Recipes routine gauleg
! 1393 1393 !
! n (in) : number of points 1394 1394 ! n (in) : number of points
! qx(out) : abscissas 1395 1395 ! qx(out) : abscissas
! qw(out) : weights 1396 1396 ! qw(out) : weights
! 1397 1397 !
implicit none 1398 1398 implicit none
double precision,parameter :: pi=3.141592653589793d0 1399 1399 double precision,parameter :: pi=3.141592653589793d0
integer, intent(in) :: n 1400 1400 integer, intent(in) :: n
double precision, intent(out) :: qx(n),qw(n) 1401 1401 double precision, intent(out) :: qx(n),qw(n)
1402 1402
integer :: m,i,j 1403 1403 integer :: m,i,j
double precision :: z,z1,p1,p2,p3,pp 1404 1404 double precision :: z,z1,p1,p2,p3,pp
m=(n+1)/2 1405 1405 m=(n+1)/2
do i=1,m 1406 1406 do i=1,m
z=cos(pi*(dble(i)-0.25d0)/(dble(n)+0.5d0)) 1407 1407 z=cos(pi*(dble(i)-0.25d0)/(dble(n)+0.5d0))
iloop: do 1408 1408 iloop: do
p1=1.d0 1409 1409 p1=1.d0
p2=0.d0 1410 1410 p2=0.d0
do j=1,n 1411 1411 do j=1,n
p3=p2 1412 1412 p3=p2
p2=p1 1413 1413 p2=p1
p1=((2.d0*dble(j)-1.d0)*z*p2-(dble(j)-1.d0)*p3)/dble(j) 1414 1414 p1=((2.d0*dble(j)-1.d0)*z*p2-(dble(j)-1.d0)*p3)/dble(j)
end do 1415 1415 end do
pp=dble(n)*(z*p1-p2)/(z*z-1.d0) 1416 1416 pp=dble(n)*(z*p1-p2)/(z*z-1.d0)
z1=z 1417 1417 z1=z
z=z1-p1/pp 1418 1418 z=z1-p1/pp
if (dabs(z-z1)<=epsilon(z)) then 1419 1419 if (dabs(z-z1)<=epsilon(z)) then
exit iloop 1420 1420 exit iloop
end if 1421 1421 end if
end do iloop 1422 1422 end do iloop
qx(i)=-z 1423 1423 qx(i)=-z
qx(n+1-i)=z 1424 1424 qx(n+1-i)=z
qw(i)=2.d0/((1.d0-z*z)*pp*pp) 1425 1425 qw(i)=2.d0/((1.d0-z*z)*pp*pp)
qw(n+1-i)=qw(i) 1426 1426 qw(n+1-i)=qw(i)
end do 1427 1427 end do
end subroutine 1428 1428 end subroutine
1429 1429
1430 1430
1431 1431
subroutine fvn_d_gl_integ(f,a,b,n,res) 1432 1432 subroutine fvn_d_gl_integ(f,a,b,n,res)
! 1433 1433 !
! This is a simple non adaptative integration routine 1434 1434 ! This is a simple non adaptative integration routine
! using n gauss legendre abscissas and weights 1435 1435 ! using n gauss legendre abscissas and weights
! 1436 1436 !
! f(in) : the function to integrate 1437 1437 ! f(in) : the function to integrate
! a(in) : lower bound 1438 1438 ! a(in) : lower bound
! b(in) : higher bound 1439 1439 ! b(in) : higher bound
! n(in) : number of gauss legendre pairs 1440 1440 ! n(in) : number of gauss legendre pairs
! res(out): the evaluation of the integral 1441 1441 ! res(out): the evaluation of the integral
! 1442 1442 !
double precision,external :: f 1443 1443 double precision,external :: f
double precision, intent(in) :: a,b 1444 1444 double precision, intent(in) :: a,b
integer, intent(in):: n 1445 1445 integer, intent(in):: n
double precision, intent(out) :: res 1446 1446 double precision, intent(out) :: res
1447 1447
double precision, allocatable :: qx(:),qw(:) 1448 1448 double precision, allocatable :: qx(:),qw(:)
double precision :: xm,xr 1449 1449 double precision :: xm,xr
integer :: i 1450 1450 integer :: i
1451 1451
! First compute n gauss legendre abs and weight 1452 1452 ! First compute n gauss legendre abs and weight
allocate(qx(n)) 1453 1453 allocate(qx(n))
allocate(qw(n)) 1454 1454 allocate(qw(n))
call fvn_d_gauss_legendre(n,qx,qw) 1455 1455 call fvn_d_gauss_legendre(n,qx,qw)
1456 1456
xm=0.5d0*(b+a) 1457 1457 xm=0.5d0*(b+a)
xr=0.5d0*(b-a) 1458 1458 xr=0.5d0*(b-a)
1459 1459
res=0.d0 1460 1460 res=0.d0
1461 1461
do i=1,n 1462 1462 do i=1,n
res=res+qw(i)*f(xm+xr*qx(i)) 1463 1463 res=res+qw(i)*f(xm+xr*qx(i))
end do 1464 1464 end do
1465 1465
res=xr*res 1466 1466 res=xr*res
1467 1467
deallocate(qw) 1468 1468 deallocate(qw)
deallocate(qx) 1469 1469 deallocate(qx)
1470 1470
end subroutine 1471 1471 end subroutine
1472 1472
!!!!!!!!!!!!!!!!!!!!!!!! 1473 1473 !!!!!!!!!!!!!!!!!!!!!!!!
! 1474 1474 !
! Simple and double adaptative Gauss Kronrod integration based on 1475 1475 ! Simple and double adaptative Gauss Kronrod integration based on
! a modified version of quadpack ( http://www.netlib.org/quadpack 1476 1476 ! a modified version of quadpack ( http://www.netlib.org/quadpack
! 1477 1477 !
! Common parameters : 1478 1478 ! Common parameters :
! 1479 1479 !
! key (in) 1480 1480 ! key (in)
! epsabs 1481 1481 ! epsabs
! epsrel 1482 1482 ! epsrel
! 1483 1483 !
! 1484 1484 !
!!!!!!!!!!!!!!!!!!!!!!!! 1485 1485 !!!!!!!!!!!!!!!!!!!!!!!!
1486 1486
subroutine fvn_d_integ_1_gk(f,a,b,epsabs,epsrel,key,res,abserr,ier,limit) 1487 1487 subroutine fvn_d_integ_1_gk(f,a,b,epsabs,epsrel,key,res,abserr,ier,limit)
! 1488 1488 !
! Evaluate the integral of function f(x) between a and b 1489 1489 ! Evaluate the integral of function f(x) between a and b
! 1490 1490 !
! f(in) : the function 1491 1491 ! f(in) : the function
! a(in) : lower bound 1492 1492 ! a(in) : lower bound
! b(in) : higher bound 1493 1493 ! b(in) : higher bound
! epsabs(in) : desired absolute error 1494 1494 ! epsabs(in) : desired absolute error
! epsrel(in) : desired relative error 1495 1495 ! epsrel(in) : desired relative error
! key(in) : gauss kronrod rule 1496 1496 ! key(in) : gauss kronrod rule
! 1: 7 - 15 points 1497 1497 ! 1: 7 - 15 points
! 2: 10 - 21 points 1498 1498 ! 2: 10 - 21 points
! 3: 15 - 31 points 1499 1499 ! 3: 15 - 31 points
! 4: 20 - 41 points 1500 1500 ! 4: 20 - 41 points
! 5: 25 - 51 points 1501 1501 ! 5: 25 - 51 points
! 6: 30 - 61 points 1502 1502 ! 6: 30 - 61 points
! 1503 1503 !
! limit(in) : maximum number of subintervals in the partition of the 1504 1504 ! limit(in) : maximum number of subintervals in the partition of the
! given integration interval (a,b). A value of 500 will give the same 1505 1505 ! given integration interval (a,b). A value of 500 will give the same
! behaviour as the imsl routine dqdag 1506 1506 ! behaviour as the imsl routine dqdag
! 1507 1507 !
! res(out) : estimated integral value 1508 1508 ! res(out) : estimated integral value
! abserr(out) : estimated absolute error 1509 1509 ! abserr(out) : estimated absolute error
! ier(out) : error flag from quadpack routines 1510 1510 ! ier(out) : error flag from quadpack routines
! 0 : no error 1511 1511 ! 0 : no error
! 1 : maximum number of subdivisions allowed 1512 1512 ! 1 : maximum number of subdivisions allowed
! has been achieved. one can allow more 1513 1513 ! has been achieved. one can allow more
! subdivisions by increasing the value of 1514 1514 ! subdivisions by increasing the value of
! limit (and taking the according dimension 1515 1515 ! limit (and taking the according dimension
! adjustments into account). however, if 1516 1516 ! adjustments into account). however, if
! this yield no improvement it is advised 1517 1517 ! this yield no improvement it is advised
! to analyze the integrand in order to 1518 1518 ! to analyze the integrand in order to
! determine the integration difficulaties. 1519 1519 ! determine the integration difficulaties.
! if the position of a local difficulty can 1520 1520 ! if the position of a local difficulty can
! be determined (i.e.singularity, 1521 1521 ! be determined (i.e.singularity,
! discontinuity within the interval) one 1522 1522 ! discontinuity within the interval) one
! will probably gain from splitting up the 1523 1523 ! will probably gain from splitting up the
! interval at this point and calling the 1524 1524 ! interval at this point and calling the
! integrator on the subranges. if possible, 1525 1525 ! integrator on the subranges. if possible,
! an appropriate special-purpose integrator 1526 1526 ! an appropriate special-purpose integrator
! should be used which is designed for 1527 1527 ! should be used which is designed for
! handling the type of difficulty involved. 1528 1528 ! handling the type of difficulty involved.
! 2 : the occurrence of roundoff error is 1529 1529 ! 2 : the occurrence of roundoff error is
! detected, which prevents the requested 1530 1530 ! detected, which prevents the requested
! tolerance from being achieved. 1531 1531 ! tolerance from being achieved.
! 3 : extremely bad integrand behaviour occurs 1532 1532 ! 3 : extremely bad integrand behaviour occurs
! at some points of the integration 1533 1533 ! at some points of the integration
! interval. 1534 1534 ! interval.
! 6 : the input is invalid, because 1535 1535 ! 6 : the input is invalid, because
! (epsabs.le.0 and 1536 1536 ! (epsabs.le.0 and
! epsrel.lt.max(50*rel.mach.acc.,0.5d-28)) 1537 1537 ! epsrel.lt.max(50*rel.mach.acc.,0.5d-28))
! or limit.lt.1 or lenw.lt.limit*4. 1538 1538 ! or limit.lt.1 or lenw.lt.limit*4.
! result, abserr, neval, last are set 1539 1539 ! result, abserr, neval, last are set
! to zero. 1540 1540 ! to zero.
! except when lenw is invalid, iwork(1), 1541 1541 ! except when lenw is invalid, iwork(1),
! work(limit*2+1) and work(limit*3+1) are 1542 1542 ! work(limit*2+1) and work(limit*3+1) are
! set to zero, work(1) is set to a and 1543 1543 ! set to zero, work(1) is set to a and
! work(limit+1) to b. 1544 1544 ! work(limit+1) to b.
1545 1545
implicit none 1546 1546 implicit none
double precision, external :: f 1547 1547 double precision, external :: f
double precision, intent(in) :: a,b,epsabs,epsrel 1548 1548 double precision, intent(in) :: a,b,epsabs,epsrel
integer, intent(in) :: key 1549 1549 integer, intent(in) :: key
integer, intent(in) :: limit 1550 1550 integer, intent(in) :: limit
double precision, intent(out) :: res,abserr 1551 1551 double precision, intent(out) :: res,abserr
integer, intent(out) :: ier 1552 1552 integer, intent(out) :: ier
1553 1553
double precision, allocatable :: work(:) 1554 1554 double precision, allocatable :: work(:)
integer, allocatable :: iwork(:) 1555 1555 integer, allocatable :: iwork(:)
integer :: lenw,neval,last 1556 1556 integer :: lenw,neval,last
1557 1557
! imsl value for limit is 500 1558 1558 ! imsl value for limit is 500
lenw=limit*4 1559 1559 lenw=limit*4
1560 1560
allocate(iwork(limit)) 1561 1561 allocate(iwork(limit))
allocate(work(lenw)) 1562 1562 allocate(work(lenw))
1563 1563
call dqag(f,a,b,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work) 1564 1564 call dqag(f,a,b,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work)
1565 1565
deallocate(work) 1566 1566 deallocate(work)
deallocate(iwork) 1567 1567 deallocate(iwork)
1568 1568
end subroutine 1569 1569 end subroutine
1570 1570
1571 1571
1572 1572