Commit 42591138ec882c4674db5641e0f153c33d0362bc

Authored by daniau
1 parent 9158e74d6b

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

Showing 1 changed file with 178 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->today
! 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 ;-) 22 22 ! if you find it usefull it would be kind to give credits ;-)
! 23 23 !
! svn version 24 24 ! svn version
25 ! January 2008 : added quadratic interpolation, gamma/factorial function,
26 ! a function which return identity matrix,
27 ! evaluation of nterm chebyshev series
! September 2007 : added sparse system solving by interfacing umfpack 25 28 ! September 2007 : added sparse system solving by interfacing umfpack
! June 2007 : added some complex trigonometric functions 26 29 ! June 2007 : added some complex trigonometric functions
! 27 30 !
! TO DO LIST : 28 31 ! TO DO LIST :
! + Order eigenvalues and vectors in decreasing eigenvalue's modulus order -> atm 29 32 ! + Order eigenvalues and vectors in decreasing eigenvalue's modulus order -> atm
! eigenvalues are given with no particular order. 30 33 ! eigenvalues are given with no particular order.
! + Generic interface for fvn_x_name family -> fvn_name 31 34 ! + Generic interface for fvn_x_name family -> fvn_name
! + Make some parameters optional, status for example 32 35 ! + Make some parameters optional, status for example
! + use f95 kinds "double complex" -> complex(kind=8) 33 36 ! + use f95 kinds "double complex" -> complex(kind=8)
! + unify quadpack routines 34 37 ! + unify quadpack routines
! + ... 35 38 ! + ...
! 36 39 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 37 40 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
38 41
implicit none 39 42 implicit none
! We define pi and i for the module 40 43 ! We define pi and i for the module
real(kind=8),parameter :: fvn_pi = 3.141592653589793_8 41 44 real(kind=8),parameter :: fvn_pi = 3.141592653589793_8
complex(kind=8),parameter :: fvn_i = (0._8,1._8) 42 45 complex(kind=8),parameter :: fvn_i = (0._8,1._8)
43 46
44 47
! All quadpack routines are private to the module 45 48 ! All quadpack routines are private to the module
private :: d1mach,dqag,dqag_2d_inner,dqag_2d_outer,dqage,dqage_2d_inner, & 46 49 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, & 47 50 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, & 48 51 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 49 52 dqk51,dqk51_2d_inner,dqk51_2d_outer,dqk61,dqk61_2d_inner,dqk61_2d_outer,dqpsrt
50 53
51 54
contains 52 55 contains
53 56
57 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
58 !
59 ! Identity Matrix
60 !
61 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
62 function fvn_d_ident(n)
63 implicit none
64 integer(kind=4) :: n
65 real(kind=8), dimension(n,n) :: fvn_d_ident
66
67 real(kind=8),dimension(n*n) :: vect
68 integer(kind=4) :: i
69
70 vect=0._8
71 vect(1:n*n:n+1) = 1._8
72 fvn_d_ident=reshape(vect, shape = (/ n,n /))
73 end function
74
75 function fvn_s_ident(n)
76 implicit none
77 integer(kind=4) :: n
78 real(kind=4), dimension(n,n) :: fvn_s_ident
79
80 real(kind=4),dimension(n*n) :: vect
81 integer(kind=4) :: i
82
83 vect=0._4
84 vect(1:n*n:n+1) = 1._4
85 fvn_s_ident=reshape(vect, shape = (/ n,n /))
86 end function
87
88 function fvn_c_ident(n)
89 implicit none
90 integer(kind=4) :: n
91 complex(kind=4), dimension(n,n) :: fvn_c_ident
92
93 complex(kind=4),dimension(n*n) :: vect
94 integer(kind=4) :: i
95
96 vect=(0._4,0._4)
97 vect(1:n*n:n+1) = (1._4,0._4)
98 fvn_c_ident=reshape(vect, shape = (/ n,n /))
99 end function
100
101 function fvn_z_ident(n)
102 implicit none
103 integer(kind=4) :: n
104 complex(kind=8), dimension(n,n) :: fvn_z_ident
105
106 complex(kind=8),dimension(n*n) :: vect
107 integer(kind=4) :: i
108
109 vect=(0._8,0._8)
110 vect(1:n*n:n+1) = (1._8,0._8)
111 fvn_z_ident=reshape(vect, shape = (/ n,n /))
112 end function
113
114
115
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 54 116 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 55 117 !
! Matrix inversion subroutines 56 118 ! Matrix inversion subroutines
! 57 119 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 58 120 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
subroutine fvn_s_matinv(d,a,inva,status) 59 121 subroutine fvn_s_matinv(d,a,inva,status)
! 60 122 !
! Matrix inversion of a real matrix using BLAS and LAPACK 61 123 ! Matrix inversion of a real matrix using BLAS and LAPACK
! 62 124 !
! d (in) : matrix rank 63 125 ! d (in) : matrix rank
! a (in) : input matrix 64 126 ! a (in) : input matrix
! inva (out) : inversed matrix 65 127 ! inva (out) : inversed matrix
! status (ou) : =0 if something failed 66 128 ! status (ou) : =0 if something failed
! 67 129 !
implicit none 68 130 implicit none
integer, intent(in) :: d 69 131 integer, intent(in) :: d
real, intent(in) :: a(d,d) 70 132 real, intent(in) :: a(d,d)
real, intent(out) :: inva(d,d) 71 133 real, intent(out) :: inva(d,d)
integer, intent(out) :: status 72 134 integer, intent(out) :: status
73 135
integer, allocatable :: ipiv(:) 74 136 integer, allocatable :: ipiv(:)
real, allocatable :: work(:) 75 137 real, allocatable :: work(:)
real twork(1) 76 138 real twork(1)
integer :: info 77 139 integer :: info
integer :: lwork 78 140 integer :: lwork
79 141
status=1 80 142 status=1
81 143
allocate(ipiv(d)) 82 144 allocate(ipiv(d))
! copy a into inva using BLAS 83 145 ! copy a into inva using BLAS
!call scopy(d*d,a,1,inva,1) 84 146 !call scopy(d*d,a,1,inva,1)
inva(:,:)=a(:,:) 85 147 inva(:,:)=a(:,:)
! LU factorization using LAPACK 86 148 ! LU factorization using LAPACK
call sgetrf(d,d,inva,d,ipiv,info) 87 149 call sgetrf(d,d,inva,d,ipiv,info)
! if info is not equal to 0, something went wrong we exit setting status to 0 88 150 ! if info is not equal to 0, something went wrong we exit setting status to 0
if (info /= 0) then 89 151 if (info /= 0) then
status=0 90 152 status=0
deallocate(ipiv) 91 153 deallocate(ipiv)
return 92 154 return
end if 93 155 end if
! we use the query fonction of xxxtri to obtain the optimal workspace size 94 156 ! we use the query fonction of xxxtri to obtain the optimal workspace size
call sgetri(d,inva,d,ipiv,twork,-1,info) 95 157 call sgetri(d,inva,d,ipiv,twork,-1,info)
lwork=int(twork(1)) 96 158 lwork=int(twork(1))
allocate(work(lwork)) 97 159 allocate(work(lwork))
! Matrix inversion using LAPACK 98 160 ! Matrix inversion using LAPACK
call sgetri(d,inva,d,ipiv,work,lwork,info) 99 161 call sgetri(d,inva,d,ipiv,work,lwork,info)
! again if info is not equal to 0, we exit setting status to 0 100 162 ! again if info is not equal to 0, we exit setting status to 0
if (info /= 0) then 101 163 if (info /= 0) then
status=0 102 164 status=0
end if 103 165 end if
deallocate(work) 104 166 deallocate(work)
deallocate(ipiv) 105 167 deallocate(ipiv)
end subroutine 106 168 end subroutine
107 169
subroutine fvn_d_matinv(d,a,inva,status) 108 170 subroutine fvn_d_matinv(d,a,inva,status)
! 109 171 !
! Matrix inversion of a double precision matrix using BLAS and LAPACK 110 172 ! Matrix inversion of a double precision matrix using BLAS and LAPACK
! 111 173 !
! d (in) : matrix rank 112 174 ! d (in) : matrix rank
! a (in) : input matrix 113 175 ! a (in) : input matrix
! inva (out) : inversed matrix 114 176 ! inva (out) : inversed matrix
! status (ou) : =0 if something failed 115 177 ! status (ou) : =0 if something failed
! 116 178 !
implicit none 117 179 implicit none
integer, intent(in) :: d 118 180 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 119 181 double precision, intent(in) :: a(d,d)
double precision, intent(out) :: inva(d,d) 120 182 double precision, intent(out) :: inva(d,d)
integer, intent(out) :: status 121 183 integer, intent(out) :: status
122 184
integer, allocatable :: ipiv(:) 123 185 integer, allocatable :: ipiv(:)
double precision, allocatable :: work(:) 124 186 double precision, allocatable :: work(:)
double precision :: twork(1) 125 187 double precision :: twork(1)
integer :: info 126 188 integer :: info
integer :: lwork 127 189 integer :: lwork
128 190
status=1 129 191 status=1
130 192
allocate(ipiv(d)) 131 193 allocate(ipiv(d))
! copy a into inva using BLAS 132 194 ! copy a into inva using BLAS
!call dcopy(d*d,a,1,inva,1) 133 195 !call dcopy(d*d,a,1,inva,1)
inva(:,:)=a(:,:) 134 196 inva(:,:)=a(:,:)
! LU factorization using LAPACK 135 197 ! LU factorization using LAPACK
call dgetrf(d,d,inva,d,ipiv,info) 136 198 call dgetrf(d,d,inva,d,ipiv,info)
! if info is not equal to 0, something went wrong we exit setting status to 0 137 199 ! if info is not equal to 0, something went wrong we exit setting status to 0
if (info /= 0) then 138 200 if (info /= 0) then
status=0 139 201 status=0
deallocate(ipiv) 140 202 deallocate(ipiv)
return 141 203 return
end if 142 204 end if
! we use the query fonction of xxxtri to obtain the optimal workspace size 143 205 ! we use the query fonction of xxxtri to obtain the optimal workspace size
call dgetri(d,inva,d,ipiv,twork,-1,info) 144 206 call dgetri(d,inva,d,ipiv,twork,-1,info)
lwork=int(twork(1)) 145 207 lwork=int(twork(1))
allocate(work(lwork)) 146 208 allocate(work(lwork))
! Matrix inversion using LAPACK 147 209 ! Matrix inversion using LAPACK
call dgetri(d,inva,d,ipiv,work,lwork,info) 148 210 call dgetri(d,inva,d,ipiv,work,lwork,info)
! again if info is not equal to 0, we exit setting status to 0 149 211 ! again if info is not equal to 0, we exit setting status to 0
if (info /= 0) then 150 212 if (info /= 0) then
status=0 151 213 status=0
end if 152 214 end if
deallocate(work) 153 215 deallocate(work)
deallocate(ipiv) 154 216 deallocate(ipiv)
end subroutine 155 217 end subroutine
156 218
subroutine fvn_c_matinv(d,a,inva,status) 157 219 subroutine fvn_c_matinv(d,a,inva,status)
! 158 220 !
! Matrix inversion of a complex matrix using BLAS and LAPACK 159 221 ! Matrix inversion of a complex matrix using BLAS and LAPACK
! 160 222 !
! d (in) : matrix rank 161 223 ! d (in) : matrix rank
! a (in) : input matrix 162 224 ! a (in) : input matrix
! inva (out) : inversed matrix 163 225 ! inva (out) : inversed matrix
! status (ou) : =0 if something failed 164 226 ! status (ou) : =0 if something failed
! 165 227 !
implicit none 166 228 implicit none
integer, intent(in) :: d 167 229 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 168 230 complex, intent(in) :: a(d,d)
complex, intent(out) :: inva(d,d) 169 231 complex, intent(out) :: inva(d,d)
integer, intent(out) :: status 170 232 integer, intent(out) :: status
171 233
integer, allocatable :: ipiv(:) 172 234 integer, allocatable :: ipiv(:)
complex, allocatable :: work(:) 173 235 complex, allocatable :: work(:)
complex :: twork(1) 174 236 complex :: twork(1)
integer :: info 175 237 integer :: info
integer :: lwork 176 238 integer :: lwork
177 239
status=1 178 240 status=1
179 241
allocate(ipiv(d)) 180 242 allocate(ipiv(d))
! copy a into inva using BLAS 181 243 ! copy a into inva using BLAS
!call ccopy(d*d,a,1,inva,1) 182 244 !call ccopy(d*d,a,1,inva,1)
inva(:,:)=a(:,:) 183 245 inva(:,:)=a(:,:)
184 246
! LU factorization using LAPACK 185 247 ! LU factorization using LAPACK
call cgetrf(d,d,inva,d,ipiv,info) 186 248 call cgetrf(d,d,inva,d,ipiv,info)
! if info is not equal to 0, something went wrong we exit setting status to 0 187 249 ! if info is not equal to 0, something went wrong we exit setting status to 0
if (info /= 0) then 188 250 if (info /= 0) then
status=0 189 251 status=0
deallocate(ipiv) 190 252 deallocate(ipiv)
return 191 253 return
end if 192 254 end if
! we use the query fonction of xxxtri to obtain the optimal workspace size 193 255 ! we use the query fonction of xxxtri to obtain the optimal workspace size
call cgetri(d,inva,d,ipiv,twork,-1,info) 194 256 call cgetri(d,inva,d,ipiv,twork,-1,info)
lwork=int(twork(1)) 195 257 lwork=int(twork(1))
allocate(work(lwork)) 196 258 allocate(work(lwork))
! Matrix inversion using LAPACK 197 259 ! Matrix inversion using LAPACK
call cgetri(d,inva,d,ipiv,work,lwork,info) 198 260 call cgetri(d,inva,d,ipiv,work,lwork,info)
! again if info is not equal to 0, we exit setting status to 0 199 261 ! again if info is not equal to 0, we exit setting status to 0
if (info /= 0) then 200 262 if (info /= 0) then
status=0 201 263 status=0
end if 202 264 end if
deallocate(work) 203 265 deallocate(work)
deallocate(ipiv) 204 266 deallocate(ipiv)
end subroutine 205 267 end subroutine
206 268
subroutine fvn_z_matinv(d,a,inva,status) 207 269 subroutine fvn_z_matinv(d,a,inva,status)
! 208 270 !
! Matrix inversion of a double complex matrix using BLAS and LAPACK 209 271 ! Matrix inversion of a double complex matrix using BLAS and LAPACK
! 210 272 !
! d (in) : matrix rank 211 273 ! d (in) : matrix rank
! a (in) : input matrix 212 274 ! a (in) : input matrix
! inva (out) : inversed matrix 213 275 ! inva (out) : inversed matrix
! status (ou) : =0 if something failed 214 276 ! status (ou) : =0 if something failed
! 215 277 !
implicit none 216 278 implicit none
integer, intent(in) :: d 217 279 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 218 280 double complex, intent(in) :: a(d,d)
double complex, intent(out) :: inva(d,d) 219 281 double complex, intent(out) :: inva(d,d)
integer, intent(out) :: status 220 282 integer, intent(out) :: status
221 283
integer, allocatable :: ipiv(:) 222 284 integer, allocatable :: ipiv(:)
double complex, allocatable :: work(:) 223 285 double complex, allocatable :: work(:)
double complex :: twork(1) 224 286 double complex :: twork(1)
integer :: info 225 287 integer :: info
integer :: lwork 226 288 integer :: lwork
227 289
status=1 228 290 status=1
229 291
allocate(ipiv(d)) 230 292 allocate(ipiv(d))
! copy a into inva using BLAS 231 293 ! copy a into inva using BLAS
!call zcopy(d*d,a,1,inva,1) 232 294 !call zcopy(d*d,a,1,inva,1)
inva(:,:)=a(:,:) 233 295 inva(:,:)=a(:,:)
234 296
! LU factorization using LAPACK 235 297 ! LU factorization using LAPACK
call zgetrf(d,d,inva,d,ipiv,info) 236 298 call zgetrf(d,d,inva,d,ipiv,info)
! if info is not equal to 0, something went wrong we exit setting status to 0 237 299 ! if info is not equal to 0, something went wrong we exit setting status to 0
if (info /= 0) then 238 300 if (info /= 0) then
status=0 239 301 status=0
deallocate(ipiv) 240 302 deallocate(ipiv)
return 241 303 return
end if 242 304 end if
! we use the query fonction of xxxtri to obtain the optimal workspace size 243 305 ! we use the query fonction of xxxtri to obtain the optimal workspace size
call zgetri(d,inva,d,ipiv,twork,-1,info) 244 306 call zgetri(d,inva,d,ipiv,twork,-1,info)
lwork=int(twork(1)) 245 307 lwork=int(twork(1))
allocate(work(lwork)) 246 308 allocate(work(lwork))
! Matrix inversion using LAPACK 247 309 ! Matrix inversion using LAPACK
call zgetri(d,inva,d,ipiv,work,lwork,info) 248 310 call zgetri(d,inva,d,ipiv,work,lwork,info)
! again if info is not equal to 0, we exit setting status to 0 249 311 ! again if info is not equal to 0, we exit setting status to 0
if (info /= 0) then 250 312 if (info /= 0) then
status=0 251 313 status=0
end if 252 314 end if
deallocate(work) 253 315 deallocate(work)
deallocate(ipiv) 254 316 deallocate(ipiv)
end subroutine 255 317 end subroutine
256 318
257 319
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 258 320 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 259 321 !
! Determinants 260 322 ! Determinants
! 261 323 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 262 324 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function fvn_s_det(d,a,status) 263 325 function fvn_s_det(d,a,status)
! 264 326 !
! Evaluate the determinant of a square matrix using lapack LU factorization 265 327 ! Evaluate the determinant of a square matrix using lapack LU factorization
! 266 328 !
! d (in) : matrix rank 267 329 ! d (in) : matrix rank
! a (in) : The Matrix 268 330 ! a (in) : The Matrix
! status (out) : =0 if LU factorization failed 269 331 ! status (out) : =0 if LU factorization failed
! 270 332 !
implicit none 271 333 implicit none
integer, intent(in) :: d 272 334 integer, intent(in) :: d
real, intent(in) :: a(d,d) 273 335 real, intent(in) :: a(d,d)
integer, intent(out) :: status 274 336 integer, intent(out) :: status
real :: fvn_s_det 275 337 real :: fvn_s_det
276 338
real, allocatable :: wc_a(:,:) 277 339 real, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 278 340 integer, allocatable :: ipiv(:)
integer :: info,i 279 341 integer :: info,i
280 342
status=1 281 343 status=1
allocate(wc_a(d,d)) 282 344 allocate(wc_a(d,d))
allocate(ipiv(d)) 283 345 allocate(ipiv(d))
wc_a(:,:)=a(:,:) 284 346 wc_a(:,:)=a(:,:)
call sgetrf(d,d,wc_a,d,ipiv,info) 285 347 call sgetrf(d,d,wc_a,d,ipiv,info)
if (info/= 0) then 286 348 if (info/= 0) then
status=0 287 349 status=0
fvn_s_det=0.e0 288 350 fvn_s_det=0.e0
deallocate(ipiv) 289 351 deallocate(ipiv)
deallocate(wc_a) 290 352 deallocate(wc_a)
return 291 353 return
end if 292 354 end if
fvn_s_det=1.e0 293 355 fvn_s_det=1.e0
do i=1,d 294 356 do i=1,d
if (ipiv(i)==i) then 295 357 if (ipiv(i)==i) then
fvn_s_det=fvn_s_det*wc_a(i,i) 296 358 fvn_s_det=fvn_s_det*wc_a(i,i)
else 297 359 else
fvn_s_det=-fvn_s_det*wc_a(i,i) 298 360 fvn_s_det=-fvn_s_det*wc_a(i,i)
end if 299 361 end if
end do 300 362 end do
deallocate(ipiv) 301 363 deallocate(ipiv)
deallocate(wc_a) 302 364 deallocate(wc_a)
303 365
end function 304 366 end function
305 367
function fvn_d_det(d,a,status) 306 368 function fvn_d_det(d,a,status)
! 307 369 !
! Evaluate the determinant of a square matrix using lapack LU factorization 308 370 ! Evaluate the determinant of a square matrix using lapack LU factorization
! 309 371 !
! d (in) : matrix rank 310 372 ! d (in) : matrix rank
! a (in) : The Matrix 311 373 ! a (in) : The Matrix
! status (out) : =0 if LU factorization failed 312 374 ! status (out) : =0 if LU factorization failed
! 313 375 !
implicit none 314 376 implicit none
integer, intent(in) :: d 315 377 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 316 378 double precision, intent(in) :: a(d,d)
integer, intent(out) :: status 317 379 integer, intent(out) :: status
double precision :: fvn_d_det 318 380 double precision :: fvn_d_det
319 381
double precision, allocatable :: wc_a(:,:) 320 382 double precision, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 321 383 integer, allocatable :: ipiv(:)
integer :: info,i 322 384 integer :: info,i
323 385
status=1 324 386 status=1
allocate(wc_a(d,d)) 325 387 allocate(wc_a(d,d))
allocate(ipiv(d)) 326 388 allocate(ipiv(d))
wc_a(:,:)=a(:,:) 327 389 wc_a(:,:)=a(:,:)
call dgetrf(d,d,wc_a,d,ipiv,info) 328 390 call dgetrf(d,d,wc_a,d,ipiv,info)
if (info/= 0) then 329 391 if (info/= 0) then
status=0 330 392 status=0
fvn_d_det=0.d0 331 393 fvn_d_det=0.d0
deallocate(ipiv) 332 394 deallocate(ipiv)
deallocate(wc_a) 333 395 deallocate(wc_a)
return 334 396 return
end if 335 397 end if
fvn_d_det=1.d0 336 398 fvn_d_det=1.d0
do i=1,d 337 399 do i=1,d
if (ipiv(i)==i) then 338 400 if (ipiv(i)==i) then
fvn_d_det=fvn_d_det*wc_a(i,i) 339 401 fvn_d_det=fvn_d_det*wc_a(i,i)
else 340 402 else
fvn_d_det=-fvn_d_det*wc_a(i,i) 341 403 fvn_d_det=-fvn_d_det*wc_a(i,i)
end if 342 404 end if
end do 343 405 end do
deallocate(ipiv) 344 406 deallocate(ipiv)
deallocate(wc_a) 345 407 deallocate(wc_a)
346 408
end function 347 409 end function
348 410
function fvn_c_det(d,a,status) ! 349 411 function fvn_c_det(d,a,status) !
! Evaluate the determinant of a square matrix using lapack LU factorization 350 412 ! Evaluate the determinant of a square matrix using lapack LU factorization
! 351 413 !
! d (in) : matrix rank 352 414 ! d (in) : matrix rank
! a (in) : The Matrix 353 415 ! a (in) : The Matrix
! status (out) : =0 if LU factorization failed 354 416 ! status (out) : =0 if LU factorization failed
! 355 417 !
implicit none 356 418 implicit none
integer, intent(in) :: d 357 419 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 358 420 complex, intent(in) :: a(d,d)
integer, intent(out) :: status 359 421 integer, intent(out) :: status
complex :: fvn_c_det 360 422 complex :: fvn_c_det
361 423
complex, allocatable :: wc_a(:,:) 362 424 complex, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 363 425 integer, allocatable :: ipiv(:)
integer :: info,i 364 426 integer :: info,i
365 427
status=1 366 428 status=1
allocate(wc_a(d,d)) 367 429 allocate(wc_a(d,d))
allocate(ipiv(d)) 368 430 allocate(ipiv(d))
wc_a(:,:)=a(:,:) 369 431 wc_a(:,:)=a(:,:)
call cgetrf(d,d,wc_a,d,ipiv,info) 370 432 call cgetrf(d,d,wc_a,d,ipiv,info)
if (info/= 0) then 371 433 if (info/= 0) then
status=0 372 434 status=0
fvn_c_det=(0.e0,0.e0) 373 435 fvn_c_det=(0.e0,0.e0)
deallocate(ipiv) 374 436 deallocate(ipiv)
deallocate(wc_a) 375 437 deallocate(wc_a)
return 376 438 return
end if 377 439 end if
fvn_c_det=(1.e0,0.e0) 378 440 fvn_c_det=(1.e0,0.e0)
do i=1,d 379 441 do i=1,d
if (ipiv(i)==i) then 380 442 if (ipiv(i)==i) then
fvn_c_det=fvn_c_det*wc_a(i,i) 381 443 fvn_c_det=fvn_c_det*wc_a(i,i)
else 382 444 else
fvn_c_det=-fvn_c_det*wc_a(i,i) 383 445 fvn_c_det=-fvn_c_det*wc_a(i,i)
end if 384 446 end if
end do 385 447 end do
deallocate(ipiv) 386 448 deallocate(ipiv)
deallocate(wc_a) 387 449 deallocate(wc_a)
388 450
end function 389 451 end function
390 452
function fvn_z_det(d,a,status) 391 453 function fvn_z_det(d,a,status)
! 392 454 !
! Evaluate the determinant of a square matrix using lapack LU factorization 393 455 ! Evaluate the determinant of a square matrix using lapack LU factorization
! 394 456 !
! d (in) : matrix rank 395 457 ! d (in) : matrix rank
! a (in) : The Matrix 396 458 ! a (in) : The Matrix
! det (out) : determinant 397 459 ! det (out) : determinant
! status (out) : =0 if LU factorization failed 398 460 ! status (out) : =0 if LU factorization failed
! 399 461 !
implicit none 400 462 implicit none
integer, intent(in) :: d 401 463 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 402 464 double complex, intent(in) :: a(d,d)
integer, intent(out) :: status 403 465 integer, intent(out) :: status
double complex :: fvn_z_det 404 466 double complex :: fvn_z_det
405 467
double complex, allocatable :: wc_a(:,:) 406 468 double complex, allocatable :: wc_a(:,:)
integer, allocatable :: ipiv(:) 407 469 integer, allocatable :: ipiv(:)
integer :: info,i 408 470 integer :: info,i
409 471
status=1 410 472 status=1
allocate(wc_a(d,d)) 411 473 allocate(wc_a(d,d))
allocate(ipiv(d)) 412 474 allocate(ipiv(d))
wc_a(:,:)=a(:,:) 413 475 wc_a(:,:)=a(:,:)
call zgetrf(d,d,wc_a,d,ipiv,info) 414 476 call zgetrf(d,d,wc_a,d,ipiv,info)
if (info/= 0) then 415 477 if (info/= 0) then
status=0 416 478 status=0
fvn_z_det=(0.d0,0.d0) 417 479 fvn_z_det=(0.d0,0.d0)
deallocate(ipiv) 418 480 deallocate(ipiv)
deallocate(wc_a) 419 481 deallocate(wc_a)
return 420 482 return
end if 421 483 end if
fvn_z_det=(1.d0,0.d0) 422 484 fvn_z_det=(1.d0,0.d0)
do i=1,d 423 485 do i=1,d
if (ipiv(i)==i) then 424 486 if (ipiv(i)==i) then
fvn_z_det=fvn_z_det*wc_a(i,i) 425 487 fvn_z_det=fvn_z_det*wc_a(i,i)
else 426 488 else
fvn_z_det=-fvn_z_det*wc_a(i,i) 427 489 fvn_z_det=-fvn_z_det*wc_a(i,i)
end if 428 490 end if
end do 429 491 end do
deallocate(ipiv) 430 492 deallocate(ipiv)
deallocate(wc_a) 431 493 deallocate(wc_a)
432 494
end function 433 495 end function
434 496
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 435 497 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 436 498 !
! Condition test 437 499 ! Condition test
! 438 500 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 439 501 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 1-norm 440 502 ! 1-norm
! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm 441 503 ! fonction lapack slange,dlange,clange,zlange pour obtenir la 1-norm
! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond 442 504 ! fonction lapack sgecon,dgecon,cgecon,zgecon pour calculer la rcond
! 443 505 !
subroutine fvn_s_matcon(d,a,rcond,status) 444 506 subroutine fvn_s_matcon(d,a,rcond,status)
! Matrix condition (reciprocal of condition number) 445 507 ! Matrix condition (reciprocal of condition number)
! 446 508 !
! d (in) : matrix rank 447 509 ! d (in) : matrix rank
! a (in) : The Matrix 448 510 ! a (in) : The Matrix
! rcond (out) : guess what 449 511 ! rcond (out) : guess what
! status (out) : =0 if something went wrong 450 512 ! status (out) : =0 if something went wrong
! 451 513 !
implicit none 452 514 implicit none
integer, intent(in) :: d 453 515 integer, intent(in) :: d
real, intent(in) :: a(d,d) 454 516 real, intent(in) :: a(d,d)
real, intent(out) :: rcond 455 517 real, intent(out) :: rcond
integer, intent(out) :: status 456 518 integer, intent(out) :: status
457 519
real, allocatable :: work(:) 458 520 real, allocatable :: work(:)
integer, allocatable :: iwork(:) 459 521 integer, allocatable :: iwork(:)
real :: anorm 460 522 real :: anorm
real, allocatable :: wc_a(:,:) ! working copy of a 461 523 real, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 462 524 integer :: info
integer, allocatable :: ipiv(:) 463 525 integer, allocatable :: ipiv(:)
464 526
real, external :: slange 465 527 real, external :: slange
466 528
467 529
status=1 468 530 status=1
469 531
anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm 470 532 anorm=slange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm
471 533
allocate(wc_a(d,d)) 472 534 allocate(wc_a(d,d))
!call scopy(d*d,a,1,wc_a,1) 473 535 !call scopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 474 536 wc_a(:,:)=a(:,:)
475 537
allocate(ipiv(d)) 476 538 allocate(ipiv(d))
call sgetrf(d,d,wc_a,d,ipiv,info) 477 539 call sgetrf(d,d,wc_a,d,ipiv,info)
if (info /= 0) then 478 540 if (info /= 0) then
status=0 479 541 status=0
deallocate(ipiv) 480 542 deallocate(ipiv)
deallocate(wc_a) 481 543 deallocate(wc_a)
return 482 544 return
end if 483 545 end if
allocate(work(4*d)) 484 546 allocate(work(4*d))
allocate(iwork(d)) 485 547 allocate(iwork(d))
call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) 486 548 call sgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info)
if (info /= 0) then 487 549 if (info /= 0) then
status=0 488 550 status=0
end if 489 551 end if
deallocate(iwork) 490 552 deallocate(iwork)
deallocate(work) 491 553 deallocate(work)
deallocate(ipiv) 492 554 deallocate(ipiv)
deallocate(wc_a) 493 555 deallocate(wc_a)
494 556
end subroutine 495 557 end subroutine
496 558
subroutine fvn_d_matcon(d,a,rcond,status) 497 559 subroutine fvn_d_matcon(d,a,rcond,status)
! Matrix condition (reciprocal of condition number) 498 560 ! Matrix condition (reciprocal of condition number)
! 499 561 !
! d (in) : matrix rank 500 562 ! d (in) : matrix rank
! a (in) : The Matrix 501 563 ! a (in) : The Matrix
! rcond (out) : guess what 502 564 ! rcond (out) : guess what
! status (out) : =0 if something went wrong 503 565 ! status (out) : =0 if something went wrong
! 504 566 !
implicit none 505 567 implicit none
integer, intent(in) :: d 506 568 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 507 569 double precision, intent(in) :: a(d,d)
double precision, intent(out) :: rcond 508 570 double precision, intent(out) :: rcond
integer, intent(out) :: status 509 571 integer, intent(out) :: status
510 572
double precision, allocatable :: work(:) 511 573 double precision, allocatable :: work(:)
integer, allocatable :: iwork(:) 512 574 integer, allocatable :: iwork(:)
double precision :: anorm 513 575 double precision :: anorm
double precision, allocatable :: wc_a(:,:) ! working copy of a 514 576 double precision, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 515 577 integer :: info
integer, allocatable :: ipiv(:) 516 578 integer, allocatable :: ipiv(:)
517 579
double precision, external :: dlange 518 580 double precision, external :: dlange
519 581
520 582
status=1 521 583 status=1
522 584
anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm 523 585 anorm=dlange('1',d,d,a,d,work) ! work is unallocated as it is only used when computing infinity norm
524 586
allocate(wc_a(d,d)) 525 587 allocate(wc_a(d,d))
!call dcopy(d*d,a,1,wc_a,1) 526 588 !call dcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 527 589 wc_a(:,:)=a(:,:)
528 590
allocate(ipiv(d)) 529 591 allocate(ipiv(d))
call dgetrf(d,d,wc_a,d,ipiv,info) 530 592 call dgetrf(d,d,wc_a,d,ipiv,info)
if (info /= 0) then 531 593 if (info /= 0) then
status=0 532 594 status=0
deallocate(ipiv) 533 595 deallocate(ipiv)
deallocate(wc_a) 534 596 deallocate(wc_a)
return 535 597 return
end if 536 598 end if
537 599
allocate(work(4*d)) 538 600 allocate(work(4*d))
allocate(iwork(d)) 539 601 allocate(iwork(d))
call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info) 540 602 call dgecon('1',d,wc_a,d,anorm,rcond,work,iwork,info)
if (info /= 0) then 541 603 if (info /= 0) then
status=0 542 604 status=0
end if 543 605 end if
deallocate(iwork) 544 606 deallocate(iwork)
deallocate(work) 545 607 deallocate(work)
deallocate(ipiv) 546 608 deallocate(ipiv)
deallocate(wc_a) 547 609 deallocate(wc_a)
548 610
end subroutine 549 611 end subroutine
550 612
subroutine fvn_c_matcon(d,a,rcond,status) 551 613 subroutine fvn_c_matcon(d,a,rcond,status)
! Matrix condition (reciprocal of condition number) 552 614 ! Matrix condition (reciprocal of condition number)
! 553 615 !
! d (in) : matrix rank 554 616 ! d (in) : matrix rank
! a (in) : The Matrix 555 617 ! a (in) : The Matrix
! rcond (out) : guess what 556 618 ! rcond (out) : guess what
! status (out) : =0 if something went wrong 557 619 ! status (out) : =0 if something went wrong
! 558 620 !
implicit none 559 621 implicit none
integer, intent(in) :: d 560 622 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 561 623 complex, intent(in) :: a(d,d)
real, intent(out) :: rcond 562 624 real, intent(out) :: rcond
integer, intent(out) :: status 563 625 integer, intent(out) :: status
564 626
real, allocatable :: rwork(:) 565 627 real, allocatable :: rwork(:)
complex, allocatable :: work(:) 566 628 complex, allocatable :: work(:)
integer, allocatable :: iwork(:) 567 629 integer, allocatable :: iwork(:)
real :: anorm 568 630 real :: anorm
complex, allocatable :: wc_a(:,:) ! working copy of a 569 631 complex, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 570 632 integer :: info
integer, allocatable :: ipiv(:) 571 633 integer, allocatable :: ipiv(:)
572 634
real, external :: clange 573 635 real, external :: clange
574 636
575 637
status=1 576 638 status=1
577 639
anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm 578 640 anorm=clange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm
579 641
allocate(wc_a(d,d)) 580 642 allocate(wc_a(d,d))
!call ccopy(d*d,a,1,wc_a,1) 581 643 !call ccopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 582 644 wc_a(:,:)=a(:,:)
583 645
allocate(ipiv(d)) 584 646 allocate(ipiv(d))
call cgetrf(d,d,wc_a,d,ipiv,info) 585 647 call cgetrf(d,d,wc_a,d,ipiv,info)
if (info /= 0) then 586 648 if (info /= 0) then
status=0 587 649 status=0
deallocate(ipiv) 588 650 deallocate(ipiv)
deallocate(wc_a) 589 651 deallocate(wc_a)
return 590 652 return
end if 591 653 end if
allocate(work(2*d)) 592 654 allocate(work(2*d))
allocate(rwork(2*d)) 593 655 allocate(rwork(2*d))
call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) 594 656 call cgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info)
if (info /= 0) then 595 657 if (info /= 0) then
status=0 596 658 status=0
end if 597 659 end if
deallocate(rwork) 598 660 deallocate(rwork)
deallocate(work) 599 661 deallocate(work)
deallocate(ipiv) 600 662 deallocate(ipiv)
deallocate(wc_a) 601 663 deallocate(wc_a)
end subroutine 602 664 end subroutine
603 665
subroutine fvn_z_matcon(d,a,rcond,status) 604 666 subroutine fvn_z_matcon(d,a,rcond,status)
! Matrix condition (reciprocal of condition number) 605 667 ! Matrix condition (reciprocal of condition number)
! 606 668 !
! d (in) : matrix rank 607 669 ! d (in) : matrix rank
! a (in) : The Matrix 608 670 ! a (in) : The Matrix
! rcond (out) : guess what 609 671 ! rcond (out) : guess what
! status (out) : =0 if something went wrong 610 672 ! status (out) : =0 if something went wrong
! 611 673 !
implicit none 612 674 implicit none
integer, intent(in) :: d 613 675 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 614 676 double complex, intent(in) :: a(d,d)
double precision, intent(out) :: rcond 615 677 double precision, intent(out) :: rcond
integer, intent(out) :: status 616 678 integer, intent(out) :: status
617 679
double complex, allocatable :: work(:) 618 680 double complex, allocatable :: work(:)
double precision, allocatable :: rwork(:) 619 681 double precision, allocatable :: rwork(:)
double precision :: anorm 620 682 double precision :: anorm
double complex, allocatable :: wc_a(:,:) ! working copy of a 621 683 double complex, allocatable :: wc_a(:,:) ! working copy of a
integer :: info 622 684 integer :: info
integer, allocatable :: ipiv(:) 623 685 integer, allocatable :: ipiv(:)
624 686
double precision, external :: zlange 625 687 double precision, external :: zlange
626 688
627 689
status=1 628 690 status=1
629 691
anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm 630 692 anorm=zlange('1',d,d,a,d,rwork) ! rwork is unallocated as it is only used when computing infinity norm
631 693
allocate(wc_a(d,d)) 632 694 allocate(wc_a(d,d))
!call zcopy(d*d,a,1,wc_a,1) 633 695 !call zcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 634 696 wc_a(:,:)=a(:,:)
635 697
allocate(ipiv(d)) 636 698 allocate(ipiv(d))
call zgetrf(d,d,wc_a,d,ipiv,info) 637 699 call zgetrf(d,d,wc_a,d,ipiv,info)
if (info /= 0) then 638 700 if (info /= 0) then
status=0 639 701 status=0
deallocate(ipiv) 640 702 deallocate(ipiv)
deallocate(wc_a) 641 703 deallocate(wc_a)
return 642 704 return
end if 643 705 end if
644 706
allocate(work(2*d)) 645 707 allocate(work(2*d))
allocate(rwork(2*d)) 646 708 allocate(rwork(2*d))
call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info) 647 709 call zgecon('1',d,wc_a,d,anorm,rcond,work,rwork,info)
if (info /= 0) then 648 710 if (info /= 0) then
status=0 649 711 status=0
end if 650 712 end if
deallocate(rwork) 651 713 deallocate(rwork)
deallocate(work) 652 714 deallocate(work)
deallocate(ipiv) 653 715 deallocate(ipiv)
deallocate(wc_a) 654 716 deallocate(wc_a)
end subroutine 655 717 end subroutine
656 718
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 657 719 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 658 720 !
! Valeurs propres/ Vecteurs propre 659 721 ! Valeurs propres/ Vecteurs propre
! 660 722 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 661 723 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
662 724
subroutine fvn_s_matev(d,a,evala,eveca,status) 663 725 subroutine fvn_s_matev(d,a,evala,eveca,status)
! 664 726 !
! integer d (in) : matrice rank 665 727 ! integer d (in) : matrice rank
! real a(d,d) (in) : The Matrix 666 728 ! real a(d,d) (in) : The Matrix
! complex evala(d) (out) : eigenvalues 667 729 ! complex evala(d) (out) : eigenvalues
! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 668 730 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 669 731 ! integer (out) : status =0 if something went wrong
! 670 732 !
! interfacing Lapack routine SGEEV 671 733 ! interfacing Lapack routine SGEEV
implicit none 672 734 implicit none
integer, intent(in) :: d 673 735 integer, intent(in) :: d
real, intent(in) :: a(d,d) 674 736 real, intent(in) :: a(d,d)
complex, intent(out) :: evala(d) 675 737 complex, intent(out) :: evala(d)
complex, intent(out) :: eveca(d,d) 676 738 complex, intent(out) :: eveca(d,d)
integer, intent(out) :: status 677 739 integer, intent(out) :: status
678 740
real, allocatable :: wc_a(:,:) ! a working copy of a 679 741 real, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 680 742 integer :: info
integer :: lwork 681 743 integer :: lwork
real, allocatable :: wr(:),wi(:) 682 744 real, allocatable :: wr(:),wi(:)
real :: vl ! unused but necessary for the call 683 745 real :: vl ! unused but necessary for the call
real, allocatable :: vr(:,:) 684 746 real, allocatable :: vr(:,:)
real, allocatable :: work(:) 685 747 real, allocatable :: work(:)
real :: twork(1) 686 748 real :: twork(1)
integer i 687 749 integer i
integer j 688 750 integer j
689 751
! making a working copy of a 690 752 ! making a working copy of a
allocate(wc_a(d,d)) 691 753 allocate(wc_a(d,d))
!call scopy(d*d,a,1,wc_a,1) 692 754 !call scopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 693 755 wc_a(:,:)=a(:,:)
694 756
allocate(wr(d)) 695 757 allocate(wr(d))
allocate(wi(d)) 696 758 allocate(wi(d))
allocate(vr(d,d)) 697 759 allocate(vr(d,d))
! query optimal work size 698 760 ! query optimal work size
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) 699 761 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
lwork=int(twork(1)) 700 762 lwork=int(twork(1))
allocate(work(lwork)) 701 763 allocate(work(lwork))
call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) 702 764 call sgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
703 765
if (info /= 0) then 704 766 if (info /= 0) then
status=0 705 767 status=0
deallocate(work) 706 768 deallocate(work)
deallocate(vr) 707 769 deallocate(vr)
deallocate(wi) 708 770 deallocate(wi)
deallocate(wr) 709 771 deallocate(wr)
deallocate(wc_a) 710 772 deallocate(wc_a)
return 711 773 return
end if 712 774 end if
713 775
! now fill in the results 714 776 ! now fill in the results
i=1 715 777 i=1
do while(i<=d) 716 778 do while(i<=d)
evala(i)=cmplx(wr(i),wi(i)) 717 779 evala(i)=cmplx(wr(i),wi(i))
if (wi(i) == 0.) then ! eigenvalue is real 718 780 if (wi(i) == 0.) then ! eigenvalue is real
eveca(:,i)=cmplx(vr(:,i),0.) 719 781 eveca(:,i)=cmplx(vr(:,i),0.)
else ! eigenvalue is complex 720 782 else ! eigenvalue is complex
evala(i+1)=cmplx(wr(i+1),wi(i+1)) 721 783 evala(i+1)=cmplx(wr(i+1),wi(i+1))
eveca(:,i)=cmplx(vr(:,i),vr(:,i+1)) 722 784 eveca(:,i)=cmplx(vr(:,i),vr(:,i+1))
eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1)) 723 785 eveca(:,i+1)=cmplx(vr(:,i),-vr(:,i+1))
i=i+1 724 786 i=i+1
end if 725 787 end if
i=i+1 726 788 i=i+1
enddo 727 789 enddo
deallocate(work) 728 790 deallocate(work)
deallocate(vr) 729 791 deallocate(vr)
deallocate(wi) 730 792 deallocate(wi)
deallocate(wr) 731 793 deallocate(wr)
deallocate(wc_a) 732 794 deallocate(wc_a)
733 795
end subroutine 734 796 end subroutine
735 797
subroutine fvn_d_matev(d,a,evala,eveca,status) 736 798 subroutine fvn_d_matev(d,a,evala,eveca,status)
! 737 799 !
! integer d (in) : matrice rank 738 800 ! integer d (in) : matrice rank
! double precision a(d,d) (in) : The Matrix 739 801 ! double precision a(d,d) (in) : The Matrix
! double complex evala(d) (out) : eigenvalues 740 802 ! double complex evala(d) (out) : eigenvalues
! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 741 803 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 742 804 ! integer (out) : status =0 if something went wrong
! 743 805 !
! interfacing Lapack routine DGEEV 744 806 ! interfacing Lapack routine DGEEV
implicit none 745 807 implicit none
integer, intent(in) :: d 746 808 integer, intent(in) :: d
double precision, intent(in) :: a(d,d) 747 809 double precision, intent(in) :: a(d,d)
double complex, intent(out) :: evala(d) 748 810 double complex, intent(out) :: evala(d)
double complex, intent(out) :: eveca(d,d) 749 811 double complex, intent(out) :: eveca(d,d)
integer, intent(out) :: status 750 812 integer, intent(out) :: status
751 813
double precision, allocatable :: wc_a(:,:) ! a working copy of a 752 814 double precision, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 753 815 integer :: info
integer :: lwork 754 816 integer :: lwork
double precision, allocatable :: wr(:),wi(:) 755 817 double precision, allocatable :: wr(:),wi(:)
double precision :: vl ! unused but necessary for the call 756 818 double precision :: vl ! unused but necessary for the call
double precision, allocatable :: vr(:,:) 757 819 double precision, allocatable :: vr(:,:)
double precision, allocatable :: work(:) 758 820 double precision, allocatable :: work(:)
double precision :: twork(1) 759 821 double precision :: twork(1)
integer i 760 822 integer i
integer j 761 823 integer j
762 824
! making a working copy of a 763 825 ! making a working copy of a
allocate(wc_a(d,d)) 764 826 allocate(wc_a(d,d))
!call dcopy(d*d,a,1,wc_a,1) 765 827 !call dcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 766 828 wc_a(:,:)=a(:,:)
767 829
allocate(wr(d)) 768 830 allocate(wr(d))
allocate(wi(d)) 769 831 allocate(wi(d))
allocate(vr(d,d)) 770 832 allocate(vr(d,d))
! query optimal work size 771 833 ! query optimal work size
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info) 772 834 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,twork,-1,info)
lwork=int(twork(1)) 773 835 lwork=int(twork(1))
allocate(work(lwork)) 774 836 allocate(work(lwork))
call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info) 775 837 call dgeev('N','V',d,wc_a,d,wr,wi,vl,1,vr,d,work,lwork,info)
776 838
if (info /= 0) then 777 839 if (info /= 0) then
status=0 778 840 status=0
deallocate(work) 779 841 deallocate(work)
deallocate(vr) 780 842 deallocate(vr)
deallocate(wi) 781 843 deallocate(wi)
deallocate(wr) 782 844 deallocate(wr)
deallocate(wc_a) 783 845 deallocate(wc_a)
return 784 846 return
end if 785 847 end if
786 848
! now fill in the results 787 849 ! now fill in the results
i=1 788 850 i=1
do while(i<=d) 789 851 do while(i<=d)
evala(i)=dcmplx(wr(i),wi(i)) 790 852 evala(i)=dcmplx(wr(i),wi(i))
if (wi(i) == 0.) then ! eigenvalue is real 791 853 if (wi(i) == 0.) then ! eigenvalue is real
eveca(:,i)=dcmplx(vr(:,i),0.) 792 854 eveca(:,i)=dcmplx(vr(:,i),0.)
else ! eigenvalue is complex 793 855 else ! eigenvalue is complex
evala(i+1)=dcmplx(wr(i+1),wi(i+1)) 794 856 evala(i+1)=dcmplx(wr(i+1),wi(i+1))
eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1)) 795 857 eveca(:,i)=dcmplx(vr(:,i),vr(:,i+1))
eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1)) 796 858 eveca(:,i+1)=dcmplx(vr(:,i),-vr(:,i+1))
i=i+1 797 859 i=i+1
end if 798 860 end if
i=i+1 799 861 i=i+1
enddo 800 862 enddo
801 863
deallocate(work) 802 864 deallocate(work)
deallocate(vr) 803 865 deallocate(vr)
deallocate(wi) 804 866 deallocate(wi)
deallocate(wr) 805 867 deallocate(wr)
deallocate(wc_a) 806 868 deallocate(wc_a)
807 869
end subroutine 808 870 end subroutine
809 871
subroutine fvn_c_matev(d,a,evala,eveca,status) 810 872 subroutine fvn_c_matev(d,a,evala,eveca,status)
! 811 873 !
! integer d (in) : matrice rank 812 874 ! integer d (in) : matrice rank
! complex a(d,d) (in) : The Matrix 813 875 ! complex a(d,d) (in) : The Matrix
! complex evala(d) (out) : eigenvalues 814 876 ! complex evala(d) (out) : eigenvalues
! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 815 877 ! complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 816 878 ! integer (out) : status =0 if something went wrong
! 817 879 !
! interfacing Lapack routine CGEEV 818 880 ! interfacing Lapack routine CGEEV
implicit none 819 881 implicit none
integer, intent(in) :: d 820 882 integer, intent(in) :: d
complex, intent(in) :: a(d,d) 821 883 complex, intent(in) :: a(d,d)
complex, intent(out) :: evala(d) 822 884 complex, intent(out) :: evala(d)
complex, intent(out) :: eveca(d,d) 823 885 complex, intent(out) :: eveca(d,d)
integer, intent(out) :: status 824 886 integer, intent(out) :: status
825 887
complex, allocatable :: wc_a(:,:) ! a working copy of a 826 888 complex, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 827 889 integer :: info
integer :: lwork 828 890 integer :: lwork
complex, allocatable :: work(:) 829 891 complex, allocatable :: work(:)
complex :: twork(1) 830 892 complex :: twork(1)
real, allocatable :: rwork(:) 831 893 real, allocatable :: rwork(:)
complex :: vl ! unused but necessary for the call 832 894 complex :: vl ! unused but necessary for the call
833 895
status=1 834 896 status=1
835 897
! making a working copy of a 836 898 ! making a working copy of a
allocate(wc_a(d,d)) 837 899 allocate(wc_a(d,d))
!call ccopy(d*d,a,1,wc_a,1) 838 900 !call ccopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 839 901 wc_a(:,:)=a(:,:)
840 902
841 903
! query optimal work size 842 904 ! query optimal work size
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) 843 905 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
lwork=int(twork(1)) 844 906 lwork=int(twork(1))
allocate(work(lwork)) 845 907 allocate(work(lwork))
allocate(rwork(2*d)) 846 908 allocate(rwork(2*d))
call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) 847 909 call cgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
848 910
if (info /= 0) then 849 911 if (info /= 0) then
status=0 850 912 status=0
end if 851 913 end if
deallocate(rwork) 852 914 deallocate(rwork)
deallocate(work) 853 915 deallocate(work)
deallocate(wc_a) 854 916 deallocate(wc_a)
855 917
end subroutine 856 918 end subroutine
857 919
subroutine fvn_z_matev(d,a,evala,eveca,status) 858 920 subroutine fvn_z_matev(d,a,evala,eveca,status)
! 859 921 !
! integer d (in) : matrice rank 860 922 ! integer d (in) : matrice rank
! double complex a(d,d) (in) : The Matrix 861 923 ! double complex a(d,d) (in) : The Matrix
! double complex evala(d) (out) : eigenvalues 862 924 ! double complex evala(d) (out) : eigenvalues
! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector 863 925 ! double complex eveca(d,d) (out) : eveca(:,j) = jth eigenvector
! integer (out) : status =0 if something went wrong 864 926 ! integer (out) : status =0 if something went wrong
! 865 927 !
! interfacing Lapack routine ZGEEV 866 928 ! interfacing Lapack routine ZGEEV
implicit none 867 929 implicit none
integer, intent(in) :: d 868 930 integer, intent(in) :: d
double complex, intent(in) :: a(d,d) 869 931 double complex, intent(in) :: a(d,d)
double complex, intent(out) :: evala(d) 870 932 double complex, intent(out) :: evala(d)
double complex, intent(out) :: eveca(d,d) 871 933 double complex, intent(out) :: eveca(d,d)
integer, intent(out) :: status 872 934 integer, intent(out) :: status
873 935
double complex, allocatable :: wc_a(:,:) ! a working copy of a 874 936 double complex, allocatable :: wc_a(:,:) ! a working copy of a
integer :: info 875 937 integer :: info
integer :: lwork 876 938 integer :: lwork
double complex, allocatable :: work(:) 877 939 double complex, allocatable :: work(:)
double complex :: twork(1) 878 940 double complex :: twork(1)
double precision, allocatable :: rwork(:) 879 941 double precision, allocatable :: rwork(:)
double complex :: vl ! unused but necessary for the call 880 942 double complex :: vl ! unused but necessary for the call
881 943
status=1 882 944 status=1
883 945
! making a working copy of a 884 946 ! making a working copy of a
allocate(wc_a(d,d)) 885 947 allocate(wc_a(d,d))
!call zcopy(d*d,a,1,wc_a,1) 886 948 !call zcopy(d*d,a,1,wc_a,1)
wc_a(:,:)=a(:,:) 887 949 wc_a(:,:)=a(:,:)
888 950
! query optimal work size 889 951 ! query optimal work size
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info) 890 952 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,twork,-1,rwork,info)
lwork=int(twork(1)) 891 953 lwork=int(twork(1))
allocate(work(lwork)) 892 954 allocate(work(lwork))
allocate(rwork(2*d)) 893 955 allocate(rwork(2*d))
call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info) 894 956 call zgeev('N','V',d,wc_a,d,evala,vl,1,eveca,d,work,lwork,rwork,info)
895 957
if (info /= 0) then 896 958 if (info /= 0) then
status=0 897 959 status=0
end if 898 960 end if
deallocate(rwork) 899 961 deallocate(rwork)
deallocate(work) 900 962 deallocate(work)
deallocate(wc_a) 901 963 deallocate(wc_a)
902 964
end subroutine 903 965 end subroutine
904 966
905 967
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 906 968 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 907 969 !
! Quadratic interpolation of tabulated function of 1,2 or 3 variables 908 970 ! Quadratic interpolation of tabulated function of 1,2 or 3 variables
! 909 971 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 910 972 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
911 973
subroutine fvn_s_find_interval(x,i,xdata,n) 912 974 subroutine fvn_s_find_interval(x,i,xdata,n)
implicit none 913 975 implicit none
! This routine find the indice i where xdata(i) <= x < xdata(i+1) 914 976 ! This routine find the indice i where xdata(i) <= x < xdata(i+1)
! xdata(n) must contains a set of increasingly ordered values 915 977 ! xdata(n) must contains a set of increasingly ordered values
! if x < xdata(1) i=0 is returned 916 978 ! if x < xdata(1) i=0 is returned
! if x > xdata(n) i=n is returned 917 979 ! if x > xdata(n) i=n is returned
! special case is where x=xdata(n) then n-1 is returned so 918 980 ! special case is where x=xdata(n) then n-1 is returned so
! we will not exclude the upper limit 919 981 ! we will not exclude the upper limit
! a simple dichotomy method is used 920 982 ! a simple dichotomy method is used
921 983
real(kind=4), intent(in) :: x 922 984 real(kind=4), intent(in) :: x
real(kind=4), intent(in), dimension(n) :: xdata 923 985 real(kind=4), intent(in), dimension(n) :: xdata
integer(kind=4), intent(in) :: n 924 986 integer(kind=4), intent(in) :: n
integer(kind=4), intent(out) :: i 925 987 integer(kind=4), intent(out) :: i
926 988
integer(kind=4) :: imin,imax,imoyen 927 989 integer(kind=4) :: imin,imax,imoyen
928 990
! special case is where x=xdata(n) then n-1 is returned so 929 991 ! special case is where x=xdata(n) then n-1 is returned so
! we will not exclude the upper limit 930 992 ! we will not exclude the upper limit
if (x == xdata(n)) then 931 993 if (x == xdata(n)) then
i=n-1 932 994 i=n-1
return 933 995 return
end if 934 996 end if
935 997
! if x < xdata(1) i=0 is returned 936 998 ! if x < xdata(1) i=0 is returned
if (x < xdata(1)) then 937 999 if (x < xdata(1)) then
i=0 938 1000 i=0
return 939 1001 return
end if 940 1002 end if
941 1003
! if x > xdata(n) i=n is returned 942 1004 ! if x > xdata(n) i=n is returned
if (x > xdata(n)) then 943 1005 if (x > xdata(n)) then
i=n 944 1006 i=n
return 945 1007 return
end if 946 1008 end if
947 1009
! here xdata(1) <= x <= xdata(n) 948 1010 ! here xdata(1) <= x <= xdata(n)
imin=0 949 1011 imin=0
imax=n+1 950 1012 imax=n+1
951 1013
do while((imax-imin) > 1) 952 1014 do while((imax-imin) > 1)
imoyen=(imax+imin)/2 953 1015 imoyen=(imax+imin)/2
if (x >= xdata(imoyen)) then 954 1016 if (x >= xdata(imoyen)) then
imin=imoyen 955 1017 imin=imoyen
else 956 1018 else
imax=imoyen 957 1019 imax=imoyen
end if 958 1020 end if
end do 959 1021 end do
960 1022
i=imin 961 1023 i=imin
962 1024
end subroutine 963 1025 end subroutine
964 1026
965 1027
subroutine fvn_d_find_interval(x,i,xdata,n) 966 1028 subroutine fvn_d_find_interval(x,i,xdata,n)
implicit none 967 1029 implicit none
! This routine find the indice i where xdata(i) <= x < xdata(i+1) 968 1030 ! This routine find the indice i where xdata(i) <= x < xdata(i+1)
! xdata(n) must contains a set of increasingly ordered values 969 1031 ! xdata(n) must contains a set of increasingly ordered values
! if x < xdata(1) i=0 is returned 970 1032 ! if x < xdata(1) i=0 is returned
! if x > xdata(n) i=n is returned 971 1033 ! if x > xdata(n) i=n is returned
! special case is where x=xdata(n) then n-1 is returned so 972 1034 ! special case is where x=xdata(n) then n-1 is returned so
! we will not exclude the upper limit 973 1035 ! we will not exclude the upper limit
! a simple dichotomy method is used 974 1036 ! a simple dichotomy method is used
975 1037
real(kind=8), intent(in) :: x 976 1038 real(kind=8), intent(in) :: x
real(kind=8), intent(in), dimension(n) :: xdata 977 1039 real(kind=8), intent(in), dimension(n) :: xdata
integer(kind=4), intent(in) :: n 978 1040 integer(kind=4), intent(in) :: n
integer(kind=4), intent(out) :: i 979 1041 integer(kind=4), intent(out) :: i
980 1042
integer(kind=4) :: imin,imax,imoyen 981 1043 integer(kind=4) :: imin,imax,imoyen
982 1044
! special case is where x=xdata(n) then n-1 is returned so 983 1045 ! special case is where x=xdata(n) then n-1 is returned so
! we will not exclude the upper limit 984 1046 ! we will not exclude the upper limit
if (x == xdata(n)) then 985 1047 if (x == xdata(n)) then
i=n-1 986 1048 i=n-1
return 987 1049 return
end if 988 1050 end if
989 1051
! if x < xdata(1) i=0 is returned 990 1052 ! if x < xdata(1) i=0 is returned
if (x < xdata(1)) then 991 1053 if (x < xdata(1)) then
i=0 992 1054 i=0
return 993 1055 return
end if 994 1056 end if
995 1057
! if x > xdata(n) i=n is returned 996 1058 ! if x > xdata(n) i=n is returned
if (x > xdata(n)) then 997 1059 if (x > xdata(n)) then
i=n 998 1060 i=n
return 999 1061 return
end if 1000 1062 end if
1001 1063
! here xdata(1) <= x <= xdata(n) 1002 1064 ! here xdata(1) <= x <= xdata(n)
imin=0 1003 1065 imin=0
imax=n+1 1004 1066 imax=n+1
1005 1067
do while((imax-imin) > 1) 1006 1068 do while((imax-imin) > 1)
imoyen=(imax+imin)/2 1007 1069 imoyen=(imax+imin)/2
if (x >= xdata(imoyen)) then 1008 1070 if (x >= xdata(imoyen)) then
imin=imoyen 1009 1071 imin=imoyen
else 1010 1072 else
imax=imoyen 1011 1073 imax=imoyen
end if 1012 1074 end if
end do 1013 1075 end do
1014 1076
i=imin 1015 1077 i=imin
1016 1078
end subroutine 1017 1079 end subroutine
1018 1080
1019 1081
function fvn_s_quad_interpol(x,n,xdata,ydata) 1020 1082 function fvn_s_quad_interpol(x,n,xdata,ydata)
implicit none 1021 1083 implicit none
! This function evaluate the value of a function defined by a set of points 1022 1084 ! This function evaluate the value of a function defined by a set of points
! and values, using a quadratic interpolation 1023 1085 ! and values, using a quadratic interpolation
! xdata must be increasingly ordered 1024 1086 ! xdata must be increasingly ordered
! x must be within xdata(1) and xdata(n) to actually do interpolation 1025 1087 ! x must be within xdata(1) and xdata(n) to actually do interpolation
! otherwise extrapolation is done 1026 1088 ! otherwise extrapolation is done
integer(kind=4), intent(in) :: n 1027 1089 integer(kind=4), intent(in) :: n
real(kind=4), intent(in), dimension(n) :: xdata,ydata 1028 1090 real(kind=4), intent(in), dimension(n) :: xdata,ydata
real(kind=4), intent(in) :: x 1029 1091 real(kind=4), intent(in) :: x
real(kind=4) :: fvn_s_quad_interpol 1030 1092 real(kind=4) :: fvn_s_quad_interpol
1031 1093
integer(kind=4) :: iinf,base,i,j 1032 1094 integer(kind=4) :: iinf,base,i,j
real(kind=4) :: p 1033 1095 real(kind=4) :: p
1034 1096
call fvn_s_find_interval(x,iinf,xdata,n) 1035 1097 call fvn_s_find_interval(x,iinf,xdata,n)
1036 1098
! Settings for extrapolation 1037 1099 ! Settings for extrapolation
if (iinf==0) then 1038 1100 if (iinf==0) then
! TODO -> Lower bound extrapolation warning 1039 1101 ! TODO -> Lower bound extrapolation warning
iinf=1 1040 1102 iinf=1
end if 1041 1103 end if
1042 1104
if (iinf==n) then 1043 1105 if (iinf==n) then
! TODO -> Higher bound extrapolation warning 1044 1106 ! TODO -> Higher bound extrapolation warning
iinf=n-1 1045 1107 iinf=n-1
end if 1046 1108 end if
1047 1109
! The three points we will use are iinf-1,iinf and iinf+1 with the 1048 1110 ! The three points we will use are iinf-1,iinf and iinf+1 with the
! exception of the first interval, where iinf=1 we will use 1,2 and 3 1049 1111 ! exception of the first interval, where iinf=1 we will use 1,2 and 3
if (iinf==1) then 1050 1112 if (iinf==1) then
base=0 1051 1113 base=0
else 1052 1114 else
base=iinf-2 1053 1115 base=iinf-2
end if 1054 1116 end if
1055 1117
! The three points we will use are : 1056 1118 ! The three points we will use are :
! xdata/ydata(base+1),xdata/ydata(base+2),xdata/ydata(base+3) 1057 1119 ! xdata/ydata(base+1),xdata/ydata(base+2),xdata/ydata(base+3)
1058 1120
! Straight forward Lagrange polynomial 1059 1121 ! Straight forward Lagrange polynomial
fvn_s_quad_interpol=0. 1060 1122 fvn_s_quad_interpol=0.
do i=1,3 1061 1123 do i=1,3
! polynome i 1062 1124 ! polynome i
p=ydata(base+i) 1063 1125 p=ydata(base+i)
do j=1,3 1064 1126 do j=1,3
if (j /= i) then 1065 1127 if (j /= i) then
p=p*(x-xdata(base+j))/(xdata(base+i)-xdata(base+j)) 1066 1128 p=p*(x-xdata(base+j))/(xdata(base+i)-xdata(base+j))
end if 1067 1129 end if
end do 1068 1130 end do
fvn_s_quad_interpol=fvn_s_quad_interpol+p 1069 1131 fvn_s_quad_interpol=fvn_s_quad_interpol+p
end do 1070 1132 end do
1071 1133
end function 1072 1134 end function
1073 1135
1074 1136
function fvn_d_quad_interpol(x,n,xdata,ydata) 1075 1137 function fvn_d_quad_interpol(x,n,xdata,ydata)
implicit none 1076 1138 implicit none
! This function evaluate the value of a function defined by a set of points 1077 1139 ! This function evaluate the value of a function defined by a set of points
! and values, using a quadratic interpolation 1078 1140 ! and values, using a quadratic interpolation
! xdata must be increasingly ordered 1079 1141 ! xdata must be increasingly ordered
! x must be within xdata(1) and xdata(n) to actually do interpolation 1080 1142 ! x must be within xdata(1) and xdata(n) to actually do interpolation
! otherwise extrapolation is done 1081 1143 ! otherwise extrapolation is done
integer(kind=4), intent(in) :: n 1082 1144 integer(kind=4), intent(in) :: n
real(kind=8), intent(in), dimension(n) :: xdata,ydata 1083 1145 real(kind=8), intent(in), dimension(n) :: xdata,ydata
real(kind=8), intent(in) :: x 1084 1146 real(kind=8), intent(in) :: x
real(kind=8) :: fvn_d_quad_interpol 1085 1147 real(kind=8) :: fvn_d_quad_interpol
1086 1148
integer(kind=4) :: iinf,base,i,j 1087 1149 integer(kind=4) :: iinf,base,i,j
real(kind=8) :: p 1088 1150 real(kind=8) :: p
1089 1151
call fvn_d_find_interval(x,iinf,xdata,n) 1090 1152 call fvn_d_find_interval(x,iinf,xdata,n)
1091 1153
! Settings for extrapolation 1092 1154 ! Settings for extrapolation
if (iinf==0) then 1093 1155 if (iinf==0) then
! TODO -> Lower bound extrapolation warning 1094 1156 ! TODO -> Lower bound extrapolation warning
iinf=1 1095 1157 iinf=1
end if 1096 1158 end if
1097 1159
if (iinf==n) then 1098 1160 if (iinf==n) then
! TODO Higher bound extrapolation warning 1099 1161 ! TODO Higher bound extrapolation warning
iinf=n-1 1100 1162 iinf=n-1
end if 1101 1163 end if
1102 1164
! The three points we will use are iinf-1,iinf and iinf+1 with the 1103 1165 ! The three points we will use are iinf-1,iinf and iinf+1 with the
! exception of the first interval, where iinf=1 we will use 1,2 and 3 1104 1166 ! exception of the first interval, where iinf=1 we will use 1,2 and 3
if (iinf==1) then 1105 1167 if (iinf==1) then
base=0 1106 1168 base=0
else 1107 1169 else
base=iinf-2 1108 1170 base=iinf-2
end if 1109 1171 end if
1110 1172
! The three points we will use are : 1111 1173 ! The three points we will use are :
! xdata/ydata(base+1),xdata/ydata(base+2),xdata/ydata(base+3) 1112 1174 ! xdata/ydata(base+1),xdata/ydata(base+2),xdata/ydata(base+3)
1113 1175
! Straight forward Lagrange polynomial 1114 1176 ! Straight forward Lagrange polynomial
fvn_d_quad_interpol=0. 1115 1177 fvn_d_quad_interpol=0.
do i=1,3 1116 1178 do i=1,3
! polynome i 1117 1179 ! polynome i
p=ydata(base+i) 1118 1180 p=ydata(base+i)
do j=1,3 1119 1181 do j=1,3
if (j /= i) then 1120 1182 if (j /= i) then
p=p*(x-xdata(base+j))/(xdata(base+i)-xdata(base+j)) 1121 1183 p=p*(x-xdata(base+j))/(xdata(base+i)-xdata(base+j))
end if 1122 1184 end if
end do 1123 1185 end do
fvn_d_quad_interpol=fvn_d_quad_interpol+p 1124 1186 fvn_d_quad_interpol=fvn_d_quad_interpol+p
end do 1125 1187 end do
1126 1188
end function 1127 1189 end function
1128 1190
1129 1191
function fvn_s_quad_2d_interpol(x,y,nx,xdata,ny,ydata,zdata) 1130 1192 function fvn_s_quad_2d_interpol(x,y,nx,xdata,ny,ydata,zdata)
implicit none 1131 1193 implicit none
! This function evaluate the value of a two variable function defined by a 1132 1194 ! This function evaluate the value of a two variable function defined by a
! set of points and values, using a quadratic interpolation 1133 1195 ! set of points and values, using a quadratic interpolation
! xdata and ydata must be increasingly ordered 1134 1196 ! xdata and ydata must be increasingly ordered
! the couple (x,y) must be as x within xdata(1) and xdata(nx) and 1135 1197 ! the couple (x,y) must be as x within xdata(1) and xdata(nx) and
! y within ydata(1) and ydata(ny) to actually do interpolation 1136 1198 ! y within ydata(1) and ydata(ny) to actually do interpolation
! otherwise extrapolation is done 1137 1199 ! otherwise extrapolation is done
integer(kind=4), intent(in) :: nx,ny 1138 1200 integer(kind=4), intent(in) :: nx,ny
real(kind=4), intent(in) :: x,y 1139 1201 real(kind=4), intent(in) :: x,y
real(kind=4), intent(in), dimension(nx) :: xdata 1140 1202 real(kind=4), intent(in), dimension(nx) :: xdata
real(kind=4), intent(in), dimension(ny) :: ydata 1141 1203 real(kind=4), intent(in), dimension(ny) :: ydata
real(kind=4), intent(in), dimension(nx,ny) :: zdata 1142 1204 real(kind=4), intent(in), dimension(nx,ny) :: zdata
real(kind=4) :: fvn_s_quad_2d_interpol 1143 1205 real(kind=4) :: fvn_s_quad_2d_interpol
1144 1206
integer(kind=4) :: ixinf,iyinf,basex,basey,i 1145 1207 integer(kind=4) :: ixinf,iyinf,basex,basey,i
real(kind=4),dimension(3) :: ztmp 1146 1208 real(kind=4),dimension(3) :: ztmp
!real(kind=4), external :: fvn_s_quad_interpol 1147 1209 !real(kind=4), external :: fvn_s_quad_interpol
1148 1210
call fvn_s_find_interval(x,ixinf,xdata,nx) 1149 1211 call fvn_s_find_interval(x,ixinf,xdata,nx)
call fvn_s_find_interval(y,iyinf,ydata,ny) 1150 1212 call fvn_s_find_interval(y,iyinf,ydata,ny)
1151 1213
! Settings for extrapolation 1152 1214 ! Settings for extrapolation
if (ixinf==0) then 1153 1215 if (ixinf==0) then
! TODO -> Lower x bound extrapolation warning 1154 1216 ! TODO -> Lower x bound extrapolation warning
ixinf=1 1155 1217 ixinf=1
end if 1156 1218 end if
1157 1219
if (ixinf==nx) then 1158 1220 if (ixinf==nx) then
! TODO -> Higher x bound extrapolation warning 1159 1221 ! TODO -> Higher x bound extrapolation warning
ixinf=nx-1 1160 1222 ixinf=nx-1
end if 1161 1223 end if
1162 1224
if (iyinf==0) then 1163 1225 if (iyinf==0) then
! TODO -> Lower y bound extrapolation warning 1164 1226 ! TODO -> Lower y bound extrapolation warning
iyinf=1 1165 1227 iyinf=1
end if 1166 1228 end if
1167 1229
if (iyinf==ny) then 1168 1230 if (iyinf==ny) then
! TODO -> Higher y bound extrapolation warning 1169 1231 ! TODO -> Higher y bound extrapolation warning
iyinf=ny-1 1170 1232 iyinf=ny-1
end if 1171 1233 end if
1172 1234
! The three points we will use are iinf-1,iinf and iinf+1 with the 1173 1235 ! The three points we will use are iinf-1,iinf and iinf+1 with the
! exception of the first interval, where iinf=1 we will use 1,2 and 3 1174 1236 ! exception of the first interval, where iinf=1 we will use 1,2 and 3
if (ixinf==1) then 1175 1237 if (ixinf==1) then
basex=0 1176 1238 basex=0
else 1177 1239 else
basex=ixinf-2 1178 1240 basex=ixinf-2
end if 1179 1241 end if
1180 1242
if (iyinf==1) then 1181 1243 if (iyinf==1) then
basey=0 1182 1244 basey=0
else 1183 1245 else
basey=iyinf-2 1184 1246 basey=iyinf-2
end if 1185 1247 end if
1186 1248
! First we make 3 interpolations for x at y(base+1),y(base+2),y(base+3) 1187 1249 ! First we make 3 interpolations for x at y(base+1),y(base+2),y(base+3)
! stored in ztmp(1:3) 1188 1250 ! stored in ztmp(1:3)
do i=1,3 1189 1251 do i=1,3
ztmp(i)=fvn_s_quad_interpol(x,nx,xdata,zdata(:,basey+i)) 1190 1252 ztmp(i)=fvn_s_quad_interpol(x,nx,xdata,zdata(:,basey+i))
end do 1191 1253 end do
1192 1254
! Then we make an interpolation for y using previous interpolations 1193 1255 ! Then we make an interpolation for y using previous interpolations
fvn_s_quad_2d_interpol=fvn_s_quad_interpol(y,3,ydata(basey+1:basey+3),ztmp) 1194 1256 fvn_s_quad_2d_interpol=fvn_s_quad_interpol(y,3,ydata(basey+1:basey+3),ztmp)
end function 1195 1257 end function
1196 1258
1197 1259
function fvn_d_quad_2d_interpol(x,y,nx,xdata,ny,ydata,zdata) 1198 1260 function fvn_d_quad_2d_interpol(x,y,nx,xdata,ny,ydata,zdata)
implicit none 1199 1261 implicit none
! This function evaluate the value of a two variable function defined by a 1200 1262 ! This function evaluate the value of a two variable function defined by a
! set of points and values, using a quadratic interpolation 1201 1263 ! set of points and values, using a quadratic interpolation
! xdata and ydata must be increasingly ordered 1202 1264 ! xdata and ydata must be increasingly ordered
! the couple (x,y) must be as x within xdata(1) and xdata(nx) and 1203 1265 ! the couple (x,y) must be as x within xdata(1) and xdata(nx) and
! y within ydata(1) and ydata(ny) to actually do interpolation 1204 1266 ! y within ydata(1) and ydata(ny) to actually do interpolation
! otherwise extrapolation is done 1205 1267 ! otherwise extrapolation is done
integer(kind=4), intent(in) :: nx,ny 1206 1268 integer(kind=4), intent(in) :: nx,ny
real(kind=8), intent(in) :: x,y 1207 1269 real(kind=8), intent(in) :: x,y
real(kind=8), intent(in), dimension(nx) :: xdata 1208 1270 real(kind=8), intent(in), dimension(nx) :: xdata
real(kind=8), intent(in), dimension(ny) :: ydata 1209 1271 real(kind=8), intent(in), dimension(ny) :: ydata
real(kind=8), intent(in), dimension(nx,ny) :: zdata 1210 1272 real(kind=8), intent(in), dimension(nx,ny) :: zdata
real(kind=8) :: fvn_d_quad_2d_interpol 1211 1273 real(kind=8) :: fvn_d_quad_2d_interpol
1212 1274
integer(kind=4) :: ixinf,iyinf,basex,basey,i 1213 1275 integer(kind=4) :: ixinf,iyinf,basex,basey,i
real(kind=8),dimension(3) :: ztmp 1214 1276 real(kind=8),dimension(3) :: ztmp
!real(kind=8), external :: fvn_d_quad_interpol 1215 1277 !real(kind=8), external :: fvn_d_quad_interpol
1216 1278
call fvn_d_find_interval(x,ixinf,xdata,nx) 1217 1279 call fvn_d_find_interval(x,ixinf,xdata,nx)
call fvn_d_find_interval(y,iyinf,ydata,ny) 1218 1280 call fvn_d_find_interval(y,iyinf,ydata,ny)
1219 1281
! Settings for extrapolation 1220 1282 ! Settings for extrapolation
if (ixinf==0) then 1221 1283 if (ixinf==0) then
! TODO -> Lower x bound extrapolation warning 1222 1284 ! TODO -> Lower x bound extrapolation warning
ixinf=1 1223 1285 ixinf=1
end if 1224 1286 end if
1225 1287
if (ixinf==nx) then 1226 1288 if (ixinf==nx) then
! TODO -> Higher x bound extrapolation warning 1227 1289 ! TODO -> Higher x bound extrapolation warning
ixinf=nx-1 1228 1290 ixinf=nx-1
end if 1229 1291 end if
1230 1292
if (iyinf==0) then 1231 1293 if (iyinf==0) then
! TODO -> Lower y bound extrapolation warning 1232 1294 ! TODO -> Lower y bound extrapolation warning
iyinf=1 1233 1295 iyinf=1
end if 1234 1296 end if
1235 1297
if (iyinf==ny) then 1236 1298 if (iyinf==ny) then
! TODO -> Higher y bound extrapolation warning 1237 1299 ! TODO -> Higher y bound extrapolation warning
iyinf=ny-1 1238 1300 iyinf=ny-1
end if 1239 1301 end if
1240 1302
! The three points we will use are iinf-1,iinf and iinf+1 with the 1241 1303 ! The three points we will use are iinf-1,iinf and iinf+1 with the
! exception of the first interval, where iinf=1 we will use 1,2 and 3 1242 1304 ! exception of the first interval, where iinf=1 we will use 1,2 and 3
if (ixinf==1) then 1243 1305 if (ixinf==1) then
basex=0 1244 1306 basex=0
else 1245 1307 else
basex=ixinf-2 1246 1308 basex=ixinf-2
end if 1247 1309 end if
1248 1310
if (iyinf==1) then 1249 1311 if (iyinf==1) then
basey=0 1250 1312 basey=0
else 1251 1313 else
basey=iyinf-2 1252 1314 basey=iyinf-2
end if 1253 1315 end if
1254 1316
! First we make 3 interpolations for x at y(base+1),y(base+2),y(base+3) 1255 1317 ! First we make 3 interpolations for x at y(base+1),y(base+2),y(base+3)
! stored in ztmp(1:3) 1256 1318 ! stored in ztmp(1:3)
do i=1,3 1257 1319 do i=1,3
ztmp(i)=fvn_d_quad_interpol(x,nx,xdata,zdata(:,basey+i)) 1258 1320 ztmp(i)=fvn_d_quad_interpol(x,nx,xdata,zdata(:,basey+i))
end do 1259 1321 end do
1260 1322
! Then we make an interpolation for y using previous interpolations 1261 1323 ! Then we make an interpolation for y using previous interpolations
fvn_d_quad_2d_interpol=fvn_d_quad_interpol(y,3,ydata(basey+1:basey+3),ztmp) 1262 1324 fvn_d_quad_2d_interpol=fvn_d_quad_interpol(y,3,ydata(basey+1:basey+3),ztmp)
end function 1263 1325 end function
1264 1326
1265 1327
function fvn_s_quad_3d_interpol(x,y,z,nx,xdata,ny,ydata,nz,zdata,tdata) 1266 1328 function fvn_s_quad_3d_interpol(x,y,z,nx,xdata,ny,ydata,nz,zdata,tdata)
implicit none 1267 1329 implicit none
! This function evaluate the value of a 3 variables function defined by a 1268 1330 ! This function evaluate the value of a 3 variables function defined by a
! set of points and values, using a quadratic interpolation 1269 1331 ! set of points and values, using a quadratic interpolation
! xdata, ydata and zdata must be increasingly ordered 1270 1332 ! xdata, ydata and zdata must be increasingly ordered
! The triplet (x,y,z) must be within xdata,ydata and zdata to actually 1271 1333 ! The triplet (x,y,z) must be within xdata,ydata and zdata to actually
! perform an interpolation, otherwise extrapolation is done 1272 1334 ! perform an interpolation, otherwise extrapolation is done
integer(kind=4), intent(in) :: nx,ny,nz 1273 1335 integer(kind=4), intent(in) :: nx,ny,nz
real(kind=4), intent(in) :: x,y,z 1274 1336 real(kind=4), intent(in) :: x,y,z
real(kind=4), intent(in), dimension(nx) :: xdata 1275 1337 real(kind=4), intent(in), dimension(nx) :: xdata
real(kind=4), intent(in), dimension(ny) :: ydata 1276 1338 real(kind=4), intent(in), dimension(ny) :: ydata
real(kind=4), intent(in), dimension(nz) :: zdata 1277 1339 real(kind=4), intent(in), dimension(nz) :: zdata
real(kind=4), intent(in), dimension(nx,ny,nz) :: tdata 1278 1340 real(kind=4), intent(in), dimension(nx,ny,nz) :: tdata
real(kind=4) :: fvn_s_quad_3d_interpol 1279 1341 real(kind=4) :: fvn_s_quad_3d_interpol
1280 1342
integer(kind=4) :: ixinf,iyinf,izinf,basex,basey,basez,i,j 1281 1343 integer(kind=4) :: ixinf,iyinf,izinf,basex,basey,basez,i,j
!real(kind=4), external :: fvn_s_quad_interpol,fvn_s_quad_2d_interpol 1282 1344 !real(kind=4), external :: fvn_s_quad_interpol,fvn_s_quad_2d_interpol
real(kind=4),dimension(3,3) :: ttmp 1283 1345 real(kind=4),dimension(3,3) :: ttmp
1284 1346
call fvn_s_find_interval(x,ixinf,xdata,nx) 1285 1347 call fvn_s_find_interval(x,ixinf,xdata,nx)
call fvn_s_find_interval(y,iyinf,ydata,ny) 1286 1348 call fvn_s_find_interval(y,iyinf,ydata,ny)
call fvn_s_find_interval(z,izinf,zdata,nz) 1287 1349 call fvn_s_find_interval(z,izinf,zdata,nz)
1288 1350
! Settings for extrapolation 1289 1351 ! Settings for extrapolation
if (ixinf==0) then 1290 1352 if (ixinf==0) then
! TODO -> Lower x bound extrapolation warning 1291 1353 ! TODO -> Lower x bound extrapolation warning
ixinf=1 1292 1354 ixinf=1
end if 1293 1355 end if
1294 1356
if (ixinf==nx) then 1295 1357 if (ixinf==nx) then
! TODO -> Higher x bound extrapolation warning 1296 1358 ! TODO -> Higher x bound extrapolation warning
ixinf=nx-1 1297 1359 ixinf=nx-1
end if 1298 1360 end if
1299 1361
if (iyinf==0) then 1300 1362 if (iyinf==0) then
! TODO -> Lower y bound extrapolation warning 1301 1363 ! TODO -> Lower y bound extrapolation warning
iyinf=1 1302 1364 iyinf=1
end if 1303 1365 end if
1304 1366
if (iyinf==ny) then 1305 1367 if (iyinf==ny) then
! TODO -> Higher y bound extrapolation warning 1306 1368 ! TODO -> Higher y bound extrapolation warning
iyinf=ny-1 1307 1369 iyinf=ny-1
end if 1308 1370 end if
1309 1371
if (izinf==0) then 1310 1372 if (izinf==0) then
! TODO -> Lower z bound extrapolation warning 1311 1373 ! TODO -> Lower z bound extrapolation warning
izinf=1 1312 1374 izinf=1
end if 1313 1375 end if
1314 1376
if (izinf==nz) then 1315 1377 if (izinf==nz) then
! TODO -> Higher z bound extrapolation warning 1316 1378 ! TODO -> Higher z bound extrapolation warning
izinf=nz-1 1317 1379 izinf=nz-1
end if 1318 1380 end if
1319 1381
! The three points we will use are iinf-1,iinf and iinf+1 with the 1320 1382 ! The three points we will use are iinf-1,iinf and iinf+1 with the
! exception of the first interval, where iinf=1 we will use 1,2 and 3 1321 1383 ! exception of the first interval, where iinf=1 we will use 1,2 and 3
if (ixinf==1) then 1322 1384 if (ixinf==1) then
basex=0 1323 1385 basex=0
else 1324 1386 else
basex=ixinf-2 1325 1387 basex=ixinf-2
end if 1326 1388 end if
1327 1389
if (iyinf==1) then 1328 1390 if (iyinf==1) then
basey=0 1329 1391 basey=0
else 1330 1392 else
basey=iyinf-2 1331 1393 basey=iyinf-2
end if 1332 1394 end if
1333 1395
if (izinf==1) then 1334 1396 if (izinf==1) then
basez=0 1335 1397 basez=0
else 1336 1398 else
basez=izinf-2 1337 1399 basez=izinf-2
end if 1338 1400 end if
1339 1401
! We first make 9 one dimensional interpolation on variable x. 1340 1402 ! We first make 9 one dimensional interpolation on variable x.
! results are stored in ttmp 1341 1403 ! results are stored in ttmp
do i=1,3 1342 1404 do i=1,3
do j=1,3 1343 1405 do j=1,3
ttmp(i,j)=fvn_s_quad_interpol(x,nx,xdata,tdata(:,basey+i,basez+j)) 1344 1406 ttmp(i,j)=fvn_s_quad_interpol(x,nx,xdata,tdata(:,basey+i,basez+j))
end do 1345 1407 end do
end do 1346 1408 end do
1347 1409
! We then make a 2 dimensionnal interpolation on variables y and z 1348 1410 ! We then make a 2 dimensionnal interpolation on variables y and z
fvn_s_quad_3d_interpol=fvn_s_quad_2d_interpol(y,z, & 1349 1411 fvn_s_quad_3d_interpol=fvn_s_quad_2d_interpol(y,z, &
3,ydata(basey+1:basey+3),3,zdata(basez+1:basez+3),ttmp) 1350 1412 3,ydata(basey+1:basey+3),3,zdata(basez+1:basez+3),ttmp)
end function 1351 1413 end function
1352 1414
1353 1415
function fvn_d_quad_3d_interpol(x,y,z,nx,xdata,ny,ydata,nz,zdata,tdata) 1354 1416 function fvn_d_quad_3d_interpol(x,y,z,nx,xdata,ny,ydata,nz,zdata,tdata)
implicit none 1355 1417 implicit none
! This function evaluate the value of a 3 variables function defined by a 1356 1418 ! This function evaluate the value of a 3 variables function defined by a
! set of points and values, using a quadratic interpolation 1357 1419 ! set of points and values, using a quadratic interpolation
! xdata, ydata and zdata must be increasingly ordered 1358 1420 ! xdata, ydata and zdata must be increasingly ordered
! The triplet (x,y,z) must be within xdata,ydata and zdata to actually 1359 1421 ! The triplet (x,y,z) must be within xdata,ydata and zdata to actually
! perform an interpolation, otherwise extrapolation is done 1360 1422 ! perform an interpolation, otherwise extrapolation is done
integer(kind=4), intent(in) :: nx,ny,nz 1361 1423 integer(kind=4), intent(in) :: nx,ny,nz
real(kind=8), intent(in) :: x,y,z 1362 1424 real(kind=8), intent(in) :: x,y,z
real(kind=8), intent(in), dimension(nx) :: xdata 1363 1425 real(kind=8), intent(in), dimension(nx) :: xdata
real(kind=8), intent(in), dimension(ny) :: ydata 1364 1426 real(kind=8), intent(in), dimension(ny) :: ydata
real(kind=8), intent(in), dimension(nz) :: zdata 1365 1427 real(kind=8), intent(in), dimension(nz) :: zdata
real(kind=8), intent(in), dimension(nx,ny,nz) :: tdata 1366 1428 real(kind=8), intent(in), dimension(nx,ny,nz) :: tdata
real(kind=8) :: fvn_d_quad_3d_interpol 1367 1429 real(kind=8) :: fvn_d_quad_3d_interpol
1368 1430
integer(kind=4) :: ixinf,iyinf,izinf,basex,basey,basez,i,j 1369 1431 integer(kind=4) :: ixinf,iyinf,izinf,basex,basey,basez,i,j
!real(kind=8), external :: fvn_d_quad_interpol,fvn_d_quad_2d_interpol 1370 1432 !real(kind=8), external :: fvn_d_quad_interpol,fvn_d_quad_2d_interpol
real(kind=8),dimension(3,3) :: ttmp 1371 1433 real(kind=8),dimension(3,3) :: ttmp
1372 1434
call fvn_d_find_interval(x,ixinf,xdata,nx) 1373 1435 call fvn_d_find_interval(x,ixinf,xdata,nx)
call fvn_d_find_interval(y,iyinf,ydata,ny) 1374 1436 call fvn_d_find_interval(y,iyinf,ydata,ny)
call fvn_d_find_interval(z,izinf,zdata,nz) 1375 1437 call fvn_d_find_interval(z,izinf,zdata,nz)
1376 1438
! Settings for extrapolation 1377 1439 ! Settings for extrapolation
if (ixinf==0) then 1378 1440 if (ixinf==0) then
! TODO -> Lower x bound extrapolation warning 1379 1441 ! TODO -> Lower x bound extrapolation warning
ixinf=1 1380 1442 ixinf=1
end if 1381 1443 end if
1382 1444
if (ixinf==nx) then 1383 1445 if (ixinf==nx) then
! TODO -> Higher x bound extrapolation warning 1384 1446 ! TODO -> Higher x bound extrapolation warning
ixinf=nx-1 1385 1447 ixinf=nx-1
end if 1386 1448 end if
1387 1449
if (iyinf==0) then 1388 1450 if (iyinf==0) then
! TODO -> Lower y bound extrapolation warning 1389 1451 ! TODO -> Lower y bound extrapolation warning
iyinf=1 1390 1452 iyinf=1
end if 1391 1453 end if
1392 1454
if (iyinf==ny) then 1393 1455 if (iyinf==ny) then
! TODO -> Higher y bound extrapolation warning 1394 1456 ! TODO -> Higher y bound extrapolation warning
iyinf=ny-1 1395 1457 iyinf=ny-1
end if 1396 1458 end if
1397 1459
if (izinf==0) then 1398 1460 if (izinf==0) then
! TODO -> Lower z bound extrapolation warning 1399 1461 ! TODO -> Lower z bound extrapolation warning
izinf=1 1400 1462 izinf=1
end if 1401 1463 end if
1402 1464
if (izinf==nz) then 1403 1465 if (izinf==nz) then
! TODO -> Higher z bound extrapolation warning 1404 1466 ! TODO -> Higher z bound extrapolation warning
izinf=nz-1 1405 1467 izinf=nz-1
end if 1406 1468 end if
1407 1469
! The three points we will use are iinf-1,iinf and iinf+1 with the 1408 1470 ! The three points we will use are iinf-1,iinf and iinf+1 with the
! exception of the first interval, where iinf=1 we will use 1,2 and 3 1409 1471 ! exception of the first interval, where iinf=1 we will use 1,2 and 3
if (ixinf==1) then 1410 1472 if (ixinf==1) then
basex=0 1411 1473 basex=0
else 1412 1474 else
basex=ixinf-2 1413 1475 basex=ixinf-2
end if 1414 1476 end if
1415 1477
if (iyinf==1) then 1416 1478 if (iyinf==1) then
basey=0 1417 1479 basey=0
else 1418 1480 else
basey=iyinf-2 1419 1481 basey=iyinf-2
end if 1420 1482 end if
1421 1483
if (izinf==1) then 1422 1484 if (izinf==1) then
basez=0 1423 1485 basez=0
else 1424 1486 else
basez=izinf-2 1425 1487 basez=izinf-2
end if 1426 1488 end if
1427 1489
! We first make 9 one dimensional interpolation on variable x. 1428 1490 ! We first make 9 one dimensional interpolation on variable x.
! results are stored in ttmp 1429 1491 ! results are stored in ttmp
do i=1,3 1430 1492 do i=1,3
do j=1,3 1431 1493 do j=1,3
ttmp(i,j)=fvn_d_quad_interpol(x,nx,xdata,tdata(:,basey+i,basez+j)) 1432 1494 ttmp(i,j)=fvn_d_quad_interpol(x,nx,xdata,tdata(:,basey+i,basez+j))
end do 1433 1495 end do
end do 1434 1496 end do
1435 1497
! We then make a 2 dimensionnal interpolation on variables y and z 1436 1498 ! We then make a 2 dimensionnal interpolation on variables y and z
fvn_d_quad_3d_interpol=fvn_d_quad_2d_interpol(y,z, & 1437 1499 fvn_d_quad_3d_interpol=fvn_d_quad_2d_interpol(y,z, &
3,ydata(basey+1:basey+3),3,zdata(basez+1:basez+3),ttmp) 1438 1500 3,ydata(basey+1:basey+3),3,zdata(basez+1:basez+3),ttmp)
end function 1439 1501 end function
1440 1502
1441 1503
1442 1504
1443 1505
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1444 1506 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 1445 1507 !
! Akima spline interpolation and spline evaluation 1446 1508 ! Akima spline interpolation and spline evaluation
! 1447 1509 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1448 1510 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1449 1511
! Single precision 1450 1512 ! Single precision
subroutine fvn_s_akima(n,x,y,br,co) 1451 1513 subroutine fvn_s_akima(n,x,y,br,co)
implicit none 1452 1514 implicit none
integer, intent(in) :: n 1453 1515 integer, intent(in) :: n
real, intent(in) :: x(n) 1454 1516 real, intent(in) :: x(n)
real, intent(in) :: y(n) 1455 1517 real, intent(in) :: y(n)
real, intent(out) :: br(n) 1456 1518 real, intent(out) :: br(n)
real, intent(out) :: co(4,n) 1457 1519 real, intent(out) :: co(4,n)
1458 1520
real, allocatable :: var(:),z(:) 1459 1521 real, allocatable :: var(:),z(:)
real :: wi_1,wi 1460 1522 real :: wi_1,wi
integer :: i 1461 1523 integer :: i
real :: dx,a,b 1462 1524 real :: dx,a,b
1463 1525
! br is just a copy of x 1464 1526 ! br is just a copy of x
br(:)=x(:) 1465 1527 br(:)=x(:)
1466 1528
allocate(var(n)) 1467 1529 allocate(var(n))
allocate(z(n)) 1468 1530 allocate(z(n))
! evaluate the variations 1469 1531 ! evaluate the variations
do i=1, n-1 1470 1532 do i=1, n-1
var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i)) 1471 1533 var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i))
end do 1472 1534 end do
var(n+2)=2.e0*var(n+1)-var(n) 1473 1535 var(n+2)=2.e0*var(n+1)-var(n)
var(n+3)=2.e0*var(n+2)-var(n+1) 1474 1536 var(n+3)=2.e0*var(n+2)-var(n+1)
var(2)=2.e0*var(3)-var(4) 1475 1537 var(2)=2.e0*var(3)-var(4)
var(1)=2.e0*var(2)-var(3) 1476 1538 var(1)=2.e0*var(2)-var(3)
1477 1539
do i = 1, n 1478 1540 do i = 1, n
wi_1=abs(var(i+3)-var(i+2)) 1479 1541 wi_1=abs(var(i+3)-var(i+2))
wi=abs(var(i+1)-var(i)) 1480 1542 wi=abs(var(i+1)-var(i))
if ((wi_1+wi).eq.0.e0) then 1481 1543 if ((wi_1+wi).eq.0.e0) then
z(i)=(var(i+2)+var(i+1))/2.e0 1482 1544 z(i)=(var(i+2)+var(i+1))/2.e0
else 1483 1545 else
z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi) 1484 1546 z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi)
end if 1485 1547 end if
end do 1486 1548 end do
1487 1549
do i=1, n-1 1488 1550 do i=1, n-1
dx=x(i+1)-x(i) 1489 1551 dx=x(i+1)-x(i)
a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd 1490 1552 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 1491 1553 b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd
co(1,i)=y(i) 1492 1554 co(1,i)=y(i)
co(2,i)=z(i) 1493 1555 co(2,i)=z(i)
!co(3,i)=-(a-3.*b)/dx**2 ! méthode wd 1494 1556 !co(3,i)=-(a-3.*b)/dx**2 ! méthode wd
!co(4,i)=(a-2.*b)/dx**3 ! méthode wd 1495 1557 !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 1496 1558 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 ! 1497 1559 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 1498 1560 ! 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 ... 1499 1561 ! etrangement la fonction csval corrige et donne la bonne valeur ...
end do 1500 1562 end do
co(1,n)=y(n) 1501 1563 co(1,n)=y(n)
co(2,n)=z(n) 1502 1564 co(2,n)=z(n)
co(3,n)=0.e0 1503 1565 co(3,n)=0.e0
co(4,n)=0.e0 1504 1566 co(4,n)=0.e0
1505 1567
deallocate(z) 1506 1568 deallocate(z)
deallocate(var) 1507 1569 deallocate(var)
1508 1570
end subroutine 1509 1571 end subroutine
1510 1572
! Double precision 1511 1573 ! Double precision
subroutine fvn_d_akima(n,x,y,br,co) 1512 1574 subroutine fvn_d_akima(n,x,y,br,co)
1513 1575
implicit none 1514 1576 implicit none
integer, intent(in) :: n 1515 1577 integer, intent(in) :: n
double precision, intent(in) :: x(n) 1516 1578 double precision, intent(in) :: x(n)
double precision, intent(in) :: y(n) 1517 1579 double precision, intent(in) :: y(n)
double precision, intent(out) :: br(n) 1518 1580 double precision, intent(out) :: br(n)
double precision, intent(out) :: co(4,n) 1519 1581 double precision, intent(out) :: co(4,n)
1520 1582
double precision, allocatable :: var(:),z(:) 1521 1583 double precision, allocatable :: var(:),z(:)
double precision :: wi_1,wi 1522 1584 double precision :: wi_1,wi
integer :: i 1523 1585 integer :: i
double precision :: dx,a,b 1524 1586 double precision :: dx,a,b
1525 1587
! br is just a copy of x 1526 1588 ! br is just a copy of x
br(:)=x(:) 1527 1589 br(:)=x(:)
1528 1590
allocate(var(n)) 1529 1591 allocate(var(n))
allocate(z(n)) 1530 1592 allocate(z(n))
! evaluate the variations 1531 1593 ! evaluate the variations
do i=1, n-1 1532 1594 do i=1, n-1
var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i)) 1533 1595 var(i+2)=(y(i+1)-y(i))/(x(i+1)-x(i))
end do 1534 1596 end do
var(n+2)=2.d0*var(n+1)-var(n) 1535 1597 var(n+2)=2.d0*var(n+1)-var(n)
var(n+3)=2.d0*var(n+2)-var(n+1) 1536 1598 var(n+3)=2.d0*var(n+2)-var(n+1)
var(2)=2.d0*var(3)-var(4) 1537 1599 var(2)=2.d0*var(3)-var(4)
var(1)=2.d0*var(2)-var(3) 1538 1600 var(1)=2.d0*var(2)-var(3)
1539 1601
do i = 1, n 1540 1602 do i = 1, n
wi_1=dabs(var(i+3)-var(i+2)) 1541 1603 wi_1=dabs(var(i+3)-var(i+2))
wi=dabs(var(i+1)-var(i)) 1542 1604 wi=dabs(var(i+1)-var(i))
if ((wi_1+wi).eq.0.d0) then 1543 1605 if ((wi_1+wi).eq.0.d0) then
z(i)=(var(i+2)+var(i+1))/2.d0 1544 1606 z(i)=(var(i+2)+var(i+1))/2.d0
else 1545 1607 else
z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi) 1546 1608 z(i)=(wi_1*var(i+1)+wi*var(i+2))/(wi_1+wi)
end if 1547 1609 end if
end do 1548 1610 end do
1549 1611
do i=1, n-1 1550 1612 do i=1, n-1
dx=x(i+1)-x(i) 1551 1613 dx=x(i+1)-x(i)
a=(z(i+1)-z(i))*dx ! coeff intermediaires pour calcul wd 1552 1614 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 1553 1615 b=y(i+1)-y(i)-z(i)*dx ! coeff intermediaires pour calcul wd
co(1,i)=y(i) 1554 1616 co(1,i)=y(i)
co(2,i)=z(i) 1555 1617 co(2,i)=z(i)
!co(3,i)=-(a-3.*b)/dx**2 ! méthode wd 1556 1618 !co(3,i)=-(a-3.*b)/dx**2 ! méthode wd
!co(4,i)=(a-2.*b)/dx**3 ! méthode wd 1557 1619 !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 1558 1620 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 ! 1559 1621 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 1560 1622 ! 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 ... 1561 1623 ! etrangement la fonction csval corrige et donne la bonne valeur ...
end do 1562 1624 end do
co(1,n)=y(n) 1563 1625 co(1,n)=y(n)
co(2,n)=z(n) 1564 1626 co(2,n)=z(n)
co(3,n)=0.d0 1565 1627 co(3,n)=0.d0
co(4,n)=0.d0 1566 1628 co(4,n)=0.d0
1567 1629
deallocate(z) 1568 1630 deallocate(z)
deallocate(var) 1569 1631 deallocate(var)
1570 1632
end subroutine 1571 1633 end subroutine
1572 1634
! 1573 1635 !
! Single precision spline evaluation 1574 1636 ! Single precision spline evaluation
! 1575 1637 !
function fvn_s_spline_eval(x,n,br,co) 1576 1638 function fvn_s_spline_eval(x,n,br,co)
implicit none 1577 1639 implicit none
real, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated 1578 1640 real, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated
integer, intent(in) :: n ! number of intervals 1579 1641 integer, intent(in) :: n ! number of intervals
real, intent(in) :: br(n+1) ! breakpoints 1580 1642 real, intent(in) :: br(n+1) ! breakpoints
real, intent(in) :: co(4,n+1) ! spline coeeficients 1581 1643 real, intent(in) :: co(4,n+1) ! spline coeeficients
real :: fvn_s_spline_eval 1582 1644 real :: fvn_s_spline_eval
1583 1645
integer :: i 1584 1646 integer :: i
real :: dx 1585 1647 real :: dx
1586 1648
if (x<=br(1)) then 1587 1649 if (x<=br(1)) then
i=1 1588 1650 i=1
else if (x>=br(n+1)) then 1589 1651 else if (x>=br(n+1)) then
i=n 1590 1652 i=n
else 1591 1653 else
i=1 1592 1654 i=1
do while(x>=br(i)) 1593 1655 do while(x>=br(i))
i=i+1 1594 1656 i=i+1
end do 1595 1657 end do
i=i-1 1596 1658 i=i-1
end if 1597 1659 end if
dx=x-br(i) 1598 1660 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 1599 1661 fvn_s_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3
1600 1662
end function 1601 1663 end function
1602 1664
! Double precision spline evaluation 1603 1665 ! Double precision spline evaluation
function fvn_d_spline_eval(x,n,br,co) 1604 1666 function fvn_d_spline_eval(x,n,br,co)
implicit none 1605 1667 implicit none
double precision, intent(in) :: x ! x must be br(1)<= x <= br(n+1) otherwise value is extrapolated 1606 1668 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 1607 1669 integer, intent(in) :: n ! number of intervals
double precision, intent(in) :: br(n+1) ! breakpoints 1608 1670 double precision, intent(in) :: br(n+1) ! breakpoints
double precision, intent(in) :: co(4,n+1) ! spline coeeficients 1609 1671 double precision, intent(in) :: co(4,n+1) ! spline coeeficients
double precision :: fvn_d_spline_eval 1610 1672 double precision :: fvn_d_spline_eval
1611 1673
integer :: i 1612 1674 integer :: i
double precision :: dx 1613 1675 double precision :: dx
1614 1676
1615 1677
if (x<=br(1)) then 1616 1678 if (x<=br(1)) then
i=1 1617 1679 i=1
else if (x>=br(n+1)) then 1618 1680 else if (x>=br(n+1)) then
i=n 1619 1681 i=n
else 1620 1682 else
i=1 1621 1683 i=1
do while(x>=br(i)) 1622 1684 do while(x>=br(i))
i=i+1 1623 1685 i=i+1
end do 1624 1686 end do
i=i-1 1625 1687 i=i-1
end if 1626 1688 end if
1627 1689
dx=x-br(i) 1628 1690 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 1629 1691 fvn_d_spline_eval=co(1,i)+co(2,i)*dx+co(3,i)*dx**2+co(4,i)*dx**3
1630 1692
end function 1631 1693 end function
1632 1694
1633 1695
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1634 1696 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 1635 1697 !
! Least square problem 1636 1698 ! Least square problem
! 1637 1699 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1638 1700 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 1639 1701 !
! 1640 1702 !
1641 1703
1642 1704
1643 1705
1644 1706
subroutine fvn_d_lspoly(np,x,y,deg,coeff,status) 1645 1707 subroutine fvn_d_lspoly(np,x,y,deg,coeff,status)
! 1646 1708 !
! Least square polynomial fitting 1647 1709 ! Least square polynomial fitting
! 1648 1710 !
! Find the coefficients of the least square polynomial of a given degree 1649 1711 ! Find the coefficients of the least square polynomial of a given degree
! for a set of coordinates. 1650 1712 ! for a set of coordinates.
! 1651 1713 !
! The degree must be lower than the number of points 1652 1714 ! The degree must be lower than the number of points
! 1653 1715 !
! np (in) : number of points 1654 1716 ! np (in) : number of points
! x(np) (in) : x data 1655 1717 ! x(np) (in) : x data
! y(np) (in) : y data 1656 1718 ! y(np) (in) : y data
! deg (in) : polynomial's degree 1657 1719 ! deg (in) : polynomial's degree
! coeff(deg+1) (out) : polynomial coefficients 1658 1720 ! coeff(deg+1) (out) : polynomial coefficients
! status (out) : =0 if a problem occurs 1659 1721 ! status (out) : =0 if a problem occurs
! 1660 1722 !
implicit none 1661 1723 implicit none
1662 1724
integer, intent(in) :: np,deg 1663 1725 integer, intent(in) :: np,deg
real(kind=8), intent(in), dimension(np) :: x,y 1664 1726 real(kind=8), intent(in), dimension(np) :: x,y
real(kind=8), intent(out), dimension(deg+1) :: coeff 1665 1727 real(kind=8), intent(out), dimension(deg+1) :: coeff
integer, intent(out) :: status 1666 1728 integer, intent(out) :: status
1667 1729
real(kind=8), allocatable, dimension(:,:) :: mat,bmat 1668 1730 real(kind=8), allocatable, dimension(:,:) :: mat,bmat
real(kind=8),dimension(:),allocatable :: work 1669 1731 real(kind=8),dimension(:),allocatable :: work
real(kind=8),dimension(1) :: twork 1670 1732 real(kind=8),dimension(1) :: twork
integer :: lwork,info 1671 1733 integer :: lwork,info
1672 1734
integer :: i,j 1673 1735 integer :: i,j
1674 1736
status=1 1675 1737 status=1
allocate(mat(np,deg+1),bmat(np,1)) 1676 1738 allocate(mat(np,deg+1),bmat(np,1))
1677 1739
! Design matrix valorisation 1678 1740 ! Design matrix valorisation
mat=reshape( (/ ((x(i)**(j-1),i=1,np),j=1,deg+1) /),shape=(/ np,deg+1 /) ) 1679 1741 mat=reshape( (/ ((x(i)**(j-1),i=1,np),j=1,deg+1) /),shape=(/ np,deg+1 /) )
1680 1742
! second member valorisation 1681 1743 ! second member valorisation
bmat=reshape ( (/ (y(i),i=1,np) /) ,shape = (/ np,1 /)) 1682 1744 bmat=reshape ( (/ (y(i),i=1,np) /) ,shape = (/ np,1 /))
1683 1745
! query workspace size 1684 1746 ! query workspace size
call dgels('N',np,deg+1,1,mat,np,bmat,np,twork,-1,info) 1685 1747 call dgels('N',np,deg+1,1,mat,np,bmat,np,twork,-1,info)
lwork=twork(1) 1686 1748 lwork=twork(1)
allocate(work(int(lwork))) 1687 1749 allocate(work(int(lwork)))
! real call 1688 1750 ! real call
call dgels('N',np,deg+1,1,mat,np,bmat,np,work,lwork,info) 1689 1751 call dgels('N',np,deg+1,1,mat,np,bmat,np,work,lwork,info)
1690 1752
if (info /= 0) then 1691 1753 if (info /= 0) then
status=0 1692 1754 status=0
end if 1693 1755 end if
1694 1756
coeff = (/ (bmat(i,1),i=1,deg+1) /) 1695 1757 coeff = (/ (bmat(i,1),i=1,deg+1) /)
1696 1758
deallocate(work) 1697 1759 deallocate(work)
deallocate(mat,bmat) 1698 1760 deallocate(mat,bmat)
end subroutine 1699 1761 end subroutine
1700 1762
subroutine fvn_s_lspoly(np,x,y,deg,coeff,status) 1701 1763 subroutine fvn_s_lspoly(np,x,y,deg,coeff,status)
! 1702 1764 !
! Least square polynomial fitting 1703 1765 ! Least square polynomial fitting
! 1704 1766 !
! Find the coefficients of the least square polynomial of a given degree 1705 1767 ! Find the coefficients of the least square polynomial of a given degree
! for a set of coordinates. 1706 1768 ! for a set of coordinates.
! 1707 1769 !
! The degree must be lower than the number of points 1708 1770 ! The degree must be lower than the number of points
! 1709 1771 !
! np (in) : number of points 1710 1772 ! np (in) : number of points
! x(np) (in) : x data 1711 1773 ! x(np) (in) : x data
! y(np) (in) : y data 1712 1774 ! y(np) (in) : y data
! deg (in) : polynomial's degree 1713 1775 ! deg (in) : polynomial's degree
! coeff(deg+1) (out) : polynomial coefficients 1714 1776 ! coeff(deg+1) (out) : polynomial coefficients
! status (out) : =0 if a problem occurs 1715 1777 ! status (out) : =0 if a problem occurs
! 1716 1778 !
implicit none 1717 1779 implicit none
1718 1780
integer, intent(in) :: np,deg 1719 1781 integer, intent(in) :: np,deg
real(kind=4), intent(in), dimension(np) :: x,y 1720 1782 real(kind=4), intent(in), dimension(np) :: x,y
real(kind=4), intent(out), dimension(deg+1) :: coeff 1721 1783 real(kind=4), intent(out), dimension(deg+1) :: coeff
integer, intent(out) :: status 1722 1784 integer, intent(out) :: status
1723 1785
real(kind=4), allocatable, dimension(:,:) :: mat,bmat 1724 1786 real(kind=4), allocatable, dimension(:,:) :: mat,bmat
real(kind=4),dimension(:),allocatable :: work 1725 1787 real(kind=4),dimension(:),allocatable :: work
real(kind=4),dimension(1) :: twork 1726 1788 real(kind=4),dimension(1) :: twork
integer :: lwork,info 1727 1789 integer :: lwork,info
1728 1790
integer :: i,j 1729 1791 integer :: i,j
1730 1792
status=1 1731 1793 status=1
allocate(mat(np,deg+1),bmat(np,1)) 1732 1794 allocate(mat(np,deg+1),bmat(np,1))
1733 1795
! Design matrix valorisation 1734 1796 ! Design matrix valorisation
mat=reshape( (/ ((x(i)**(j-1),i=1,np),j=1,deg+1) /),shape=(/ np,deg+1 /) ) 1735 1797 mat=reshape( (/ ((x(i)**(j-1),i=1,np),j=1,deg+1) /),shape=(/ np,deg+1 /) )
1736 1798
! second member valorisation 1737 1799 ! second member valorisation
bmat=reshape ( (/ (y(i),i=1,np) /) ,shape = (/ np,1 /)) 1738 1800 bmat=reshape ( (/ (y(i),i=1,np) /) ,shape = (/ np,1 /))
1739 1801
! query workspace size 1740 1802 ! query workspace size
call sgels('N',np,deg+1,1,mat,np,bmat,np,twork,-1,info) 1741 1803 call sgels('N',np,deg+1,1,mat,np,bmat,np,twork,-1,info)
lwork=twork(1) 1742 1804 lwork=twork(1)
allocate(work(int(lwork))) 1743 1805 allocate(work(int(lwork)))
! real call 1744 1806 ! real call
call sgels('N',np,deg+1,1,mat,np,bmat,np,work,lwork,info) 1745 1807 call sgels('N',np,deg+1,1,mat,np,bmat,np,work,lwork,info)
1746 1808
if (info /= 0) then 1747 1809 if (info /= 0) then
status=0 1748 1810 status=0
end if 1749 1811 end if
1750 1812
coeff = (/ (bmat(i,1),i=1,deg+1) /) 1751 1813 coeff = (/ (bmat(i,1),i=1,deg+1) /)
1752 1814
deallocate(work) 1753 1815 deallocate(work)
deallocate(mat,bmat) 1754 1816 deallocate(mat,bmat)
end subroutine 1755 1817 end subroutine
1756 1818
1757 1819
1758 1820
1759 1821
1760 1822
1761 1823
1762 1824
1763 1825
subroutine fvn_d_lspoly_svd(np,x,y,deg,coeff,status) 1764 1826 subroutine fvn_d_lspoly_svd(np,x,y,deg,coeff,status)
! 1765 1827 !
! Least square polynomial fitting 1766 1828 ! Least square polynomial fitting
! 1767 1829 !
! Find the coefficients of the least square polynomial of a given degree 1768 1830 ! Find the coefficients of the least square polynomial of a given degree
! for a set of coordinates. 1769 1831 ! for a set of coordinates.
! 1770 1832 !
! The degree must be lower than the number of points 1771 1833 ! The degree must be lower than the number of points
! 1772 1834 !
! np (in) : number of points 1773 1835 ! np (in) : number of points
! x(np) (in) : x data 1774 1836 ! x(np) (in) : x data
! y(np) (in) : y data 1775 1837 ! y(np) (in) : y data
! deg (in) : polynomial's degree 1776 1838 ! deg (in) : polynomial's degree
! coeff(deg+1) (out) : polynomial coefficients 1777 1839 ! coeff(deg+1) (out) : polynomial coefficients
! status (out) : =0 if a problem occurs 1778 1840 ! status (out) : =0 if a problem occurs
! 1779 1841 !
implicit none 1780 1842 implicit none
1781 1843
integer, intent(in) :: np,deg 1782 1844 integer, intent(in) :: np,deg
real(kind=8), intent(in), dimension(np) :: x,y 1783 1845 real(kind=8), intent(in), dimension(np) :: x,y
real(kind=8), intent(out), dimension(deg+1) :: coeff 1784 1846 real(kind=8), intent(out), dimension(deg+1) :: coeff
integer, intent(out) :: status 1785 1847 integer, intent(out) :: status
1786 1848
real(kind=8), allocatable, dimension(:,:) :: mat,bmat 1787 1849 real(kind=8), allocatable, dimension(:,:) :: mat,bmat
real(kind=8),dimension(:),allocatable :: work,singval 1788 1850 real(kind=8),dimension(:),allocatable :: work,singval
real(kind=8),dimension(1) :: twork 1789 1851 real(kind=8),dimension(1) :: twork
integer :: lwork,info,rank 1790 1852 integer :: lwork,info,rank
1791 1853
integer :: i,j 1792 1854 integer :: i,j
1793 1855
status=1 1794 1856 status=1
allocate(mat(np,deg+1),bmat(np,1),singval(deg+1)) 1795 1857 allocate(mat(np,deg+1),bmat(np,1),singval(deg+1))
1796 1858
! Design matrix valorisation 1797 1859 ! Design matrix valorisation
mat=reshape( (/ ((x(i)**(j-1),i=1,np),j=1,deg+1) /),shape=(/ np,deg+1 /) ) 1798 1860 mat=reshape( (/ ((x(i)**(j-1),i=1,np),j=1,deg+1) /),shape=(/ np,deg+1 /) )
1799 1861
! second member valorisation 1800 1862 ! second member valorisation
bmat=reshape ( (/ (y(i),i=1,np) /) ,shape = (/ np,1 /)) 1801 1863 bmat=reshape ( (/ (y(i),i=1,np) /) ,shape = (/ np,1 /))
1802 1864
! query workspace size 1803 1865 ! query workspace size
call dgelss(np,deg+1,1,mat,np,bmat,np,singval,-1.,rank,twork,-1,info) 1804 1866 call dgelss(np,deg+1,1,mat,np,bmat,np,singval,-1.,rank,twork,-1,info)
lwork=twork(1) 1805 1867 lwork=twork(1)
allocate(work(int(lwork))) 1806 1868 allocate(work(int(lwork)))
! real call 1807 1869 ! real call
call dgelss(np,deg+1,1,mat,np,bmat,np,singval,-1.,rank,work,lwork,info) 1808 1870 call dgelss(np,deg+1,1,mat,np,bmat,np,singval,-1.,rank,work,lwork,info)
1809 1871
if (info /= 0) then 1810 1872 if (info /= 0) then
status=0 1811 1873 status=0
end if 1812 1874 end if
1813 1875
coeff = (/ (bmat(i,1),i=1,deg+1) /) 1814 1876 coeff = (/ (bmat(i,1),i=1,deg+1) /)
1815 1877
deallocate(work) 1816 1878 deallocate(work)
deallocate(mat,bmat,singval) 1817 1879 deallocate(mat,bmat,singval)
end subroutine 1818 1880 end subroutine
1819 1881
subroutine fvn_s_lspoly_svd(np,x,y,deg,coeff,status) 1820 1882 subroutine fvn_s_lspoly_svd(np,x,y,deg,coeff,status)
! 1821 1883 !
! Least square polynomial fitting 1822 1884 ! Least square polynomial fitting
! 1823 1885 !
! Find the coefficients of the least square polynomial of a given degree 1824 1886 ! Find the coefficients of the least square polynomial of a given degree
! for a set of coordinates. 1825 1887 ! for a set of coordinates.
! 1826 1888 !
! The degree must be lower than the number of points 1827 1889 ! The degree must be lower than the number of points
! 1828 1890 !
! np (in) : number of points 1829 1891 ! np (in) : number of points
! x(np) (in) : x data 1830 1892 ! x(np) (in) : x data
! y(np) (in) : y data 1831 1893 ! y(np) (in) : y data
! deg (in) : polynomial's degree 1832 1894 ! deg (in) : polynomial's degree
! coeff(deg+1) (out) : polynomial coefficients 1833 1895 ! coeff(deg+1) (out) : polynomial coefficients
! status (out) : =0 if a problem occurs 1834 1896 ! status (out) : =0 if a problem occurs
! 1835 1897 !
implicit none 1836 1898 implicit none
1837 1899
integer, intent(in) :: np,deg 1838 1900 integer, intent(in) :: np,deg
real(kind=4), intent(in), dimension(np) :: x,y 1839 1901 real(kind=4), intent(in), dimension(np) :: x,y
real(kind=4), intent(out), dimension(deg+1) :: coeff 1840 1902 real(kind=4), intent(out), dimension(deg+1) :: coeff
integer, intent(out) :: status 1841 1903 integer, intent(out) :: status
1842 1904
real(kind=4), allocatable, dimension(:,:) :: mat,bmat 1843 1905 real(kind=4), allocatable, dimension(:,:) :: mat,bmat
real(kind=4),dimension(:),allocatable :: work,singval 1844 1906 real(kind=4),dimension(:),allocatable :: work,singval
real(kind=4),dimension(1) :: twork 1845 1907 real(kind=4),dimension(1) :: twork
integer :: lwork,info,rank 1846 1908 integer :: lwork,info,rank
1847 1909
integer :: i,j 1848 1910 integer :: i,j
1849 1911
status=1 1850 1912 status=1
allocate(mat(np,deg+1),bmat(np,1),singval(deg+1)) 1851 1913 allocate(mat(np,deg+1),bmat(np,1),singval(deg+1))
1852 1914
! Design matrix valorisation 1853 1915 ! Design matrix valorisation
mat=reshape( (/ ((x(i)**(j-1),i=1,np),j=1,deg+1) /),shape=(/ np,deg+1 /) ) 1854 1916 mat=reshape( (/ ((x(i)**(j-1),i=1,np),j=1,deg+1) /),shape=(/ np,deg+1 /) )
1855 1917
! second member valorisation 1856 1918 ! second member valorisation
bmat=reshape ( (/ (y(i),i=1,np) /) ,shape = (/ np,1 /)) 1857 1919 bmat=reshape ( (/ (y(i),i=1,np) /) ,shape = (/ np,1 /))
1858 1920
! query workspace size 1859 1921 ! query workspace size
call sgelss(np,deg+1,1,mat,np,bmat,np,singval,-1.,rank,twork,-1,info) 1860 1922 call sgelss(np,deg+1,1,mat,np,bmat,np,singval,-1.,rank,twork,-1,info)
lwork=twork(1) 1861 1923 lwork=twork(1)
allocate(work(int(lwork))) 1862 1924 allocate(work(int(lwork)))
! real call 1863 1925 ! real call
call sgelss(np,deg+1,1,mat,np,bmat,np,singval,-1.,rank,work,lwork,info) 1864 1926 call sgelss(np,deg+1,1,mat,np,bmat,np,singval,-1.,rank,work,lwork,info)
1865 1927
if (info /= 0) then 1866 1928 if (info /= 0) then
status=0 1867 1929 status=0
end if 1868 1930 end if
1869 1931
coeff = (/ (bmat(i,1),i=1,deg+1) /) 1870 1932 coeff = (/ (bmat(i,1),i=1,deg+1) /)
1871 1933
deallocate(work) 1872 1934 deallocate(work)
deallocate(mat,bmat,singval) 1873 1935 deallocate(mat,bmat,singval)
end subroutine 1874 1936 end subroutine
1875 1937
1876 1938
! 1877 1939 !
! Muller 1878 1940 ! Muller
! 1879 1941 !
! 1880 1942 !
! 1881 1943 !
! William Daniau 2007 1882 1944 ! William Daniau 2007
! 1883 1945 !
! This routine is a fortran 90 port of Hans D. Mittelmann's routine muller.f 1884 1946 ! This routine is a fortran 90 port of Hans D. Mittelmann's routine muller.f
! http://plato.asu.edu/ftp/other_software/muller.f 1885 1947 ! http://plato.asu.edu/ftp/other_software/muller.f
! 1886 1948 !
! it can be used as a replacement for imsl routine dzanly with minor changes 1887 1949 ! it can be used as a replacement for imsl routine dzanly with minor changes
! 1888 1950 !
!----------------------------------------------------------------------- 1889 1951 !-----------------------------------------------------------------------
! 1890 1952 !
! purpose - zeros of an analytic complex function 1891 1953 ! purpose - zeros of an analytic complex function
! using the muller method with deflation 1892 1954 ! using the muller method with deflation
! 1893 1955 !
! usage - call fvn_z_muller (f,eps,eps1,kn,n,nguess,x,itmax, 1894 1956 ! usage - call fvn_z_muller (f,eps,eps1,kn,n,nguess,x,itmax,
! infer,ier) 1895 1957 ! infer,ier)
! 1896 1958 !
! arguments f - a complex function subprogram, f(z), written 1897 1959 ! arguments f - a complex function subprogram, f(z), written
! by the user specifying the equation whose 1898 1960 ! by the user specifying the equation whose
! roots are to be found. f must appear in 1899 1961 ! roots are to be found. f must appear in
! an external statement in the calling pro- 1900 1962 ! an external statement in the calling pro-
! gram. 1901 1963 ! gram.
! eps - 1st stopping criterion. let fp(z)=f(z)/p 1902 1964 ! eps - 1st stopping criterion. let fp(z)=f(z)/p
! where p = (z-z(1))*(z-z(2))*,,,*(z-z(k-1)) 1903 1965 ! where p = (z-z(1))*(z-z(2))*,,,*(z-z(k-1))
! and z(1),...,z(k-1) are previously found 1904 1966 ! and z(1),...,z(k-1) are previously found
! roots. if ((cdabs(f(z)).le.eps) .and. 1905 1967 ! roots. if ((cdabs(f(z)).le.eps) .and.
! (cdabs(fp(z)).le.eps)), then z is accepted 1906 1968 ! (cdabs(fp(z)).le.eps)), then z is accepted
! as a root. (input) 1907 1969 ! as a root. (input)
! eps1 - 2nd stopping criterion. a root is accepted 1908 1970 ! eps1 - 2nd stopping criterion. a root is accepted
! if two successive approximations to a given 1909 1971 ! if two successive approximations to a given
! root agree within eps1. (input) 1910 1972 ! root agree within eps1. (input)
! note. if either or both of the stopping 1911 1973 ! note. if either or both of the stopping
! criteria are fulfilled, the root is 1912 1974 ! criteria are fulfilled, the root is
! accepted. 1913 1975 ! accepted.
! kn - the number of known roots which must be stored 1914 1976 ! kn - the number of known roots which must be stored
! in x(1),...,x(kn), prior to entry to muller 1915 1977 ! in x(1),...,x(kn), prior to entry to muller
! nguess - the number of initial guesses provided. these 1916 1978 ! nguess - the number of initial guesses provided. these
! guesses must be stored in x(kn+1),..., 1917 1979 ! guesses must be stored in x(kn+1),...,
! x(kn+nguess). nguess must be set equal 1918 1980 ! x(kn+nguess). nguess must be set equal
! to zero if no guesses are provided. (input) 1919 1981 ! to zero if no guesses are provided. (input)
! n - the number of new roots to be found by 1920 1982 ! n - the number of new roots to be found by
! muller (input) 1921 1983 ! muller (input)
! x - a complex vector of length kn+n. x(1),..., 1922 1984 ! x - a complex vector of length kn+n. x(1),...,
! x(kn) on input must contain any known 1923 1985 ! x(kn) on input must contain any known
! roots. x(kn+1),..., x(kn+n) on input may, 1924 1986 ! roots. x(kn+1),..., x(kn+n) on input may,
! on user option, contain initial guesses for 1925 1987 ! on user option, contain initial guesses for
! the n new roots which are to be computed. 1926 1988 ! the n new roots which are to be computed.
! if the user does not provide an initial 1927 1989 ! if the user does not provide an initial
! guess, zero is used. 1928 1990 ! guess, zero is used.
! on output, x(kn+1),...,x(kn+n) contain the 1929 1991 ! on output, x(kn+1),...,x(kn+n) contain the
! approximate roots found by muller. 1930 1992 ! approximate roots found by muller.
! itmax - the maximum allowable number of iterations 1931 1993 ! itmax - the maximum allowable number of iterations
! per root (input) 1932 1994 ! per root (input)
! infer - an integer vector of length kn+n. on 1933 1995 ! infer - an integer vector of length kn+n. on
! output infer(j) contains the number of 1934 1996 ! output infer(j) contains the number of
! iterations used in finding the j-th root 1935 1997 ! iterations used in finding the j-th root
! when convergence was achieved. if 1936 1998 ! when convergence was achieved. if
! convergence was not obtained in itmax 1937 1999 ! convergence was not obtained in itmax
! iterations, infer(j) will be greater than 1938 2000 ! iterations, infer(j) will be greater than
! itmax (output). 1939 2001 ! itmax (output).
! ier - error parameter (output) 1940 2002 ! ier - error parameter (output)
! warning error 1941 2003 ! warning error
! ier = 33 indicates failure to converge with- 1942 2004 ! ier = 33 indicates failure to converge with-
! in itmax iterations for at least one of 1943 2005 ! in itmax iterations for at least one of
! the (n) new roots. 1944 2006 ! the (n) new roots.
! 1945 2007 !
! 1946 2008 !
! remarks muller always returns the last approximation for root j 1947 2009 ! remarks muller always returns the last approximation for root j
! in x(j). if the convergence criterion is satisfied, 1948 2010 ! in x(j). if the convergence criterion is satisfied,
! then infer(j) is less than or equal to itmax. if the 1949 2011 ! then infer(j) is less than or equal to itmax. if the
! convergence criterion is not satisified, then infer(j) 1950 2012 ! convergence criterion is not satisified, then infer(j)
! is set to either itmax+1 or itmax+k, with k greater 1951 2013 ! is set to either itmax+1 or itmax+k, with k greater
! than 1. infer(j) = itmax+1 indicates that muller did 1952 2014 ! than 1. infer(j) = itmax+1 indicates that muller did
! not obtain convergence in the allowed number of iter- 1953 2015 ! not obtain convergence in the allowed number of iter-
! ations. in this case, the user may wish to set itmax 1954 2016 ! ations. in this case, the user may wish to set itmax
! to a larger value. infer(j) = itmax+k means that con- 1955 2017 ! to a larger value. infer(j) = itmax+k means that con-
! vergence was obtained (on iteration k) for the defla- 1956 2018 ! vergence was obtained (on iteration k) for the defla-
! ted function 1957 2019 ! ted function
! fp(z) = f(z)/((z-z(1)...(z-z(j-1))) 1958 2020 ! fp(z) = f(z)/((z-z(1)...(z-z(j-1)))
! 1959 2021 !
! but failed for f(z). in this case, better initial 1960 2022 ! but failed for f(z). in this case, better initial
! guesses might help or, it might be necessary to relax 1961 2023 ! guesses might help or, it might be necessary to relax
! the convergence criterion. 1962 2024 ! the convergence criterion.
! 1963 2025 !
!----------------------------------------------------------------------- 1964 2026 !-----------------------------------------------------------------------
! 1965 2027 !
subroutine fvn_z_muller (f,eps,eps1,kn,nguess,n,x,itmax,infer,ier) 1966 2028 subroutine fvn_z_muller (f,eps,eps1,kn,nguess,n,x,itmax,infer,ier)
implicit none 1967 2029 implicit none
double precision :: rzero,rten,rhun,rp01,ax,eps1,qz,eps,tpq 1968 2030 double precision :: rzero,rten,rhun,rp01,ax,eps1,qz,eps,tpq
double complex :: d,dd,den,fprt,frt,h,rt,t1,t2,t3, & 1969 2031 double complex :: d,dd,den,fprt,frt,h,rt,t1,t2,t3, &
tem,z0,z1,z2,bi,xx,xl,y0,y1,y2,x0, & 1970 2032 tem,z0,z1,z2,bi,xx,xl,y0,y1,y2,x0, &
zero,p1,one,four,p5 1971 2033 zero,p1,one,four,p5
1972 2034
double complex, external :: f 1973 2035 double complex, external :: f
integer :: ickmax,kn,nguess,n,itmax,ier,knp1,knpn,i,l,ic, & 1974 2036 integer :: ickmax,kn,nguess,n,itmax,ier,knp1,knpn,i,l,ic, &
knpng,jk,ick,nn,lm1,errcode 1975 2037 knpng,jk,ick,nn,lm1,errcode
double complex :: x(kn+n) 1976 2038 double complex :: x(kn+n)
integer :: infer(kn+n) 1977 2039 integer :: infer(kn+n)
1978 2040
1979 2041
data zero/(0.0,0.0)/,p1/(0.1,0.0)/, & 1980 2042 data zero/(0.0,0.0)/,p1/(0.1,0.0)/, &
one/(1.0,0.0)/,four/(4.0,0.0)/, & 1981 2043 one/(1.0,0.0)/,four/(4.0,0.0)/, &
p5/(0.5,0.0)/, & 1982 2044 p5/(0.5,0.0)/, &
rzero/0.0/,rten/10.0/,rhun/100.0/, & 1983 2045 rzero/0.0/,rten/10.0/,rhun/100.0/, &
ax/0.1/,ickmax/3/,rp01/0.01/ 1984 2046 ax/0.1/,ickmax/3/,rp01/0.01/
1985 2047
ier = 0 1986 2048 ier = 0
if (n .lt. 1) then ! What the hell are doing here then ... 1987 2049 if (n .lt. 1) then ! What the hell are doing here then ...
return 1988 2050 return
end if 1989 2051 end if
!eps1 = rten **(-nsig) 1990 2052 !eps1 = rten **(-nsig)
eps1 = min(eps1,rp01) 1991 2053 eps1 = min(eps1,rp01)
1992 2054
knp1 = kn+1 1993 2055 knp1 = kn+1
knpn = kn+n 1994 2056 knpn = kn+n
knpng = kn+nguess 1995 2057 knpng = kn+nguess
do i=1,knpn 1996 2058 do i=1,knpn
infer(i) = 0 1997 2059 infer(i) = 0
if (i .gt. knpng) x(i) = zero 1998 2060 if (i .gt. knpng) x(i) = zero
end do 1999 2061 end do
l= knp1 2000 2062 l= knp1
2001 2063
ic=0 2002 2064 ic=0
rloop: do while (l<=knpn) ! Main loop over new roots 2003 2065 rloop: do while (l<=knpn) ! Main loop over new roots
jk = 0 2004 2066 jk = 0
ick = 0 2005 2067 ick = 0
xl = x(l) 2006 2068 xl = x(l)
icloop: do 2007 2069 icloop: do
ic = 0 2008 2070 ic = 0
h = ax 2009 2071 h = ax
h = p1*h 2010 2072 h = p1*h
if (cdabs(xl) .gt. ax) h = p1*xl 2011 2073 if (cdabs(xl) .gt. ax) h = p1*xl
! first three points are 2012 2074 ! first three points are
! xl+h, xl-h, xl 2013 2075 ! xl+h, xl-h, xl
rt = xl+h 2014 2076 rt = xl+h
call deflated_work(errcode) 2015 2077 call deflated_work(errcode)
if (errcode == 1) then 2016 2078 if (errcode == 1) then
exit icloop 2017 2079 exit icloop
end if 2018 2080 end if
2019 2081
z0 = fprt 2020 2082 z0 = fprt
y0 = frt 2021 2083 y0 = frt
x0 = rt 2022 2084 x0 = rt
rt = xl-h 2023 2085 rt = xl-h
call deflated_work(errcode) 2024 2086 call deflated_work(errcode)
if (errcode == 1) then 2025 2087 if (errcode == 1) then
exit icloop 2026 2088 exit icloop
end if 2027 2089 end if
2028 2090
z1 = fprt 2029 2091 z1 = fprt
y1 = frt 2030 2092 y1 = frt
h = xl-rt 2031 2093 h = xl-rt
d = h/(rt-x0) 2032 2094 d = h/(rt-x0)
rt = xl 2033 2095 rt = xl
2034 2096
call deflated_work(errcode) 2035 2097 call deflated_work(errcode)
if (errcode == 1) then 2036 2098 if (errcode == 1) then
exit icloop 2037 2099 exit icloop
end if 2038 2100 end if
2039 2101
2040 2102
z2 = fprt 2041 2103 z2 = fprt
y2 = frt 2042 2104 y2 = frt
! begin main algorithm 2043 2105 ! begin main algorithm
iloop: do 2044 2106 iloop: do
dd = one + d 2045 2107 dd = one + d
t1 = z0*d*d 2046 2108 t1 = z0*d*d
t2 = z1*dd*dd 2047 2109 t2 = z1*dd*dd
xx = z2*dd 2048 2110 xx = z2*dd
t3 = z2*d 2049 2111 t3 = z2*d
bi = t1-t2+xx+t3 2050 2112 bi = t1-t2+xx+t3
den = bi*bi-four*(xx*t1-t3*(t2-xx)) 2051 2113 den = bi*bi-four*(xx*t1-t3*(t2-xx))
! use denominator of maximum amplitude 2052 2114 ! use denominator of maximum amplitude
t1 = cdsqrt(den) 2053 2115 t1 = cdsqrt(den)
qz = rhun*max(cdabs(bi),cdabs(t1)) 2054 2116 qz = rhun*max(cdabs(bi),cdabs(t1))
t2 = bi + t1 2055 2117 t2 = bi + t1
tpq = cdabs(t2)+qz 2056 2118 tpq = cdabs(t2)+qz
if (tpq .eq. qz) t2 = zero 2057 2119 if (tpq .eq. qz) t2 = zero
t3 = bi - t1 2058 2120 t3 = bi - t1
tpq = cdabs(t3) + qz 2059 2121 tpq = cdabs(t3) + qz
if (tpq .eq. qz) t3 = zero 2060 2122 if (tpq .eq. qz) t3 = zero
den = t2 2061 2123 den = t2
qz = cdabs(t3)-cdabs(t2) 2062 2124 qz = cdabs(t3)-cdabs(t2)
if (qz .gt. rzero) den = t3 2063 2125 if (qz .gt. rzero) den = t3
! test for zero denominator 2064 2126 ! test for zero denominator
if (cdabs(den) .eq. rzero) then 2065 2127 if (cdabs(den) .eq. rzero) then
call trans_rt() 2066 2128 call trans_rt()
call deflated_work(errcode) 2067 2129 call deflated_work(errcode)
if (errcode == 1) then 2068 2130 if (errcode == 1) then
exit icloop 2069 2131 exit icloop
end if 2070 2132 end if
z2 = fprt 2071 2133 z2 = fprt
y2 = frt 2072 2134 y2 = frt
cycle iloop 2073 2135 cycle iloop
end if 2074 2136 end if
2075 2137
2076 2138
d = -xx/den 2077 2139 d = -xx/den
d = d+d 2078 2140 d = d+d
h = d*h 2079 2141 h = d*h
rt = rt + h 2080 2142 rt = rt + h
! check convergence of the first kind 2081 2143 ! check convergence of the first kind
if (cdabs(h) .le. eps1*max(cdabs(rt),ax)) then 2082 2144 if (cdabs(h) .le. eps1*max(cdabs(rt),ax)) then
if (ic .ne. 0) then 2083 2145 if (ic .ne. 0) then
exit icloop 2084 2146 exit icloop
end if 2085 2147 end if
ic = 1 2086 2148 ic = 1
z0 = y1 2087 2149 z0 = y1
z1 = y2 2088 2150 z1 = y2
z2 = f(rt) 2089 2151 z2 = f(rt)
xl = rt 2090 2152 xl = rt
ick = ick+1 2091 2153 ick = ick+1
if (ick .le. ickmax) then 2092 2154 if (ick .le. ickmax) then
cycle iloop 2093 2155 cycle iloop
end if 2094 2156 end if
! warning error, itmax = maximum 2095 2157 ! warning error, itmax = maximum
jk = itmax + jk 2096 2158 jk = itmax + jk
ier = 33 2097 2159 ier = 33
end if 2098 2160 end if
if (ic .ne. 0) then 2099 2161 if (ic .ne. 0) then
cycle icloop 2100 2162 cycle icloop
end if 2101 2163 end if
call deflated_work(errcode) 2102 2164 call deflated_work(errcode)
if (errcode == 1) then 2103 2165 if (errcode == 1) then
exit icloop 2104 2166 exit icloop
end if 2105 2167 end if
2106 2168
do while ( (cdabs(fprt)-cdabs(z2)*rten) .ge. rzero) 2107 2169 do while ( (cdabs(fprt)-cdabs(z2)*rten) .ge. rzero)
! take remedial action to induce 2108 2170 ! take remedial action to induce
! convergence 2109 2171 ! convergence
d = d*p5 2110 2172 d = d*p5
h = h*p5 2111 2173 h = h*p5
rt = rt-h 2112 2174 rt = rt-h
call deflated_work(errcode) 2113 2175 call deflated_work(errcode)
if (errcode == 1) then 2114 2176 if (errcode == 1) then
exit icloop 2115 2177 exit icloop
end if 2116 2178 end if
end do 2117 2179 end do
z0 = z1 2118 2180 z0 = z1
z1 = z2 2119 2181 z1 = z2
z2 = fprt 2120 2182 z2 = fprt
y0 = y1 2121 2183 y0 = y1
y1 = y2 2122 2184 y1 = y2
y2 = frt 2123 2185 y2 = frt
end do iloop 2124 2186 end do iloop
end do icloop 2125 2187 end do icloop
x(l) = rt 2126 2188 x(l) = rt
infer(l) = jk 2127 2189 infer(l) = jk
l = l+1 2128 2190 l = l+1
end do rloop 2129 2191 end do rloop
2130 2192
contains 2131 2193 contains
subroutine trans_rt() 2132 2194 subroutine trans_rt()
tem = rten*eps1 2133 2195 tem = rten*eps1
if (cdabs(rt) .gt. ax) tem = tem*rt 2134 2196 if (cdabs(rt) .gt. ax) tem = tem*rt
rt = rt+tem 2135 2197 rt = rt+tem
d = (h+tem)*d/h 2136 2198 d = (h+tem)*d/h
h = h+tem 2137 2199 h = h+tem
end subroutine trans_rt 2138 2200 end subroutine trans_rt
2139 2201
subroutine deflated_work(errcode) 2140 2202 subroutine deflated_work(errcode)
! errcode=0 => no errors 2141 2203 ! errcode=0 => no errors
! errcode=1 => jk>itmax or convergence of second kind achieved 2142 2204 ! errcode=1 => jk>itmax or convergence of second kind achieved
integer :: errcode,flag 2143 2205 integer :: errcode,flag
2144 2206
flag=1 2145 2207 flag=1
loop1: do while(flag==1) 2146 2208 loop1: do while(flag==1)
errcode=0 2147 2209 errcode=0
jk = jk+1 2148 2210 jk = jk+1
if (jk .gt. itmax) then 2149 2211 if (jk .gt. itmax) then
ier=33 2150 2212 ier=33
errcode=1 2151 2213 errcode=1
return 2152 2214 return
end if 2153 2215 end if
frt = f(rt) 2154 2216 frt = f(rt)
fprt = frt 2155 2217 fprt = frt
if (l /= 1) then 2156 2218 if (l /= 1) then
lm1 = l-1 2157 2219 lm1 = l-1
do i=1,lm1 2158 2220 do i=1,lm1
tem = rt - x(i) 2159 2221 tem = rt - x(i)
if (cdabs(tem) .eq. rzero) then 2160 2222 if (cdabs(tem) .eq. rzero) then
!if (ic .ne. 0) go to 15 !! ?? possible? 2161 2223 !if (ic .ne. 0) go to 15 !! ?? possible?
call trans_rt() 2162 2224 call trans_rt()
cycle loop1 2163 2225 cycle loop1
end if 2164 2226 end if
fprt = fprt/tem 2165 2227 fprt = fprt/tem
end do 2166 2228 end do
end if 2167 2229 end if
flag=0 2168 2230 flag=0
end do loop1 2169 2231 end do loop1
2170 2232
if (cdabs(fprt) .le. eps .and. cdabs(frt) .le. eps) then 2171 2233 if (cdabs(fprt) .le. eps .and. cdabs(frt) .le. eps) then
errcode=1 2172 2234 errcode=1
return 2173 2235 return
end if 2174 2236 end if
2175 2237
end subroutine deflated_work 2176 2238 end subroutine deflated_work
2177 2239
end subroutine 2178 2240 end subroutine
2179 2241
2180 2242
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2181 2243 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 2182 2244 !
! Integration 2183 2245 ! Integration
! 2184 2246 !
! Only double precision coded atm 2185 2247 ! Only double precision coded atm
! 2186 2248 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2187 2249 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2188 2250
2189 2251
subroutine fvn_d_gauss_legendre(n,qx,qw) 2190 2252 subroutine fvn_d_gauss_legendre(n,qx,qw)
! 2191 2253 !
! This routine compute the n Gauss Legendre abscissas and weights 2192 2254 ! This routine compute the n Gauss Legendre abscissas and weights
! Adapted from Numerical Recipes routine gauleg 2193 2255 ! Adapted from Numerical Recipes routine gauleg
! 2194 2256 !
! n (in) : number of points 2195 2257 ! n (in) : number of points
! qx(out) : abscissas 2196 2258 ! qx(out) : abscissas
! qw(out) : weights 2197 2259 ! qw(out) : weights
! 2198 2260 !
implicit none 2199 2261 implicit none
double precision,parameter :: pi=3.141592653589793d0 2200 2262 double precision,parameter :: pi=3.141592653589793d0
integer, intent(in) :: n 2201 2263 integer, intent(in) :: n
double precision, intent(out) :: qx(n),qw(n) 2202 2264 double precision, intent(out) :: qx(n),qw(n)
2203 2265
integer :: m,i,j 2204 2266 integer :: m,i,j
double precision :: z,z1,p1,p2,p3,pp 2205 2267 double precision :: z,z1,p1,p2,p3,pp
m=(n+1)/2 2206 2268 m=(n+1)/2
do i=1,m 2207 2269 do i=1,m
z=cos(pi*(dble(i)-0.25d0)/(dble(n)+0.5d0)) 2208 2270 z=cos(pi*(dble(i)-0.25d0)/(dble(n)+0.5d0))
iloop: do 2209 2271 iloop: do
p1=1.d0 2210 2272 p1=1.d0
p2=0.d0 2211 2273 p2=0.d0
do j=1,n 2212 2274 do j=1,n
p3=p2 2213 2275 p3=p2
p2=p1 2214 2276 p2=p1
p1=((2.d0*dble(j)-1.d0)*z*p2-(dble(j)-1.d0)*p3)/dble(j) 2215 2277 p1=((2.d0*dble(j)-1.d0)*z*p2-(dble(j)-1.d0)*p3)/dble(j)
end do 2216 2278 end do
pp=dble(n)*(z*p1-p2)/(z*z-1.d0) 2217 2279 pp=dble(n)*(z*p1-p2)/(z*z-1.d0)
z1=z 2218 2280 z1=z
z=z1-p1/pp 2219 2281 z=z1-p1/pp
if (dabs(z-z1)<=epsilon(z)) then 2220 2282 if (dabs(z-z1)<=epsilon(z)) then
exit iloop 2221 2283 exit iloop
end if 2222 2284 end if
end do iloop 2223 2285 end do iloop
qx(i)=-z 2224 2286 qx(i)=-z
qx(n+1-i)=z 2225 2287 qx(n+1-i)=z
qw(i)=2.d0/((1.d0-z*z)*pp*pp) 2226 2288 qw(i)=2.d0/((1.d0-z*z)*pp*pp)
qw(n+1-i)=qw(i) 2227 2289 qw(n+1-i)=qw(i)
end do 2228 2290 end do
end subroutine 2229 2291 end subroutine
2230 2292
2231 2293
2232 2294
subroutine fvn_d_gl_integ(f,a,b,n,res) 2233 2295 subroutine fvn_d_gl_integ(f,a,b,n,res)
! 2234 2296 !
! This is a simple non adaptative integration routine 2235 2297 ! This is a simple non adaptative integration routine
! using n gauss legendre abscissas and weights 2236 2298 ! using n gauss legendre abscissas and weights
! 2237 2299 !
! f(in) : the function to integrate 2238 2300 ! f(in) : the function to integrate
! a(in) : lower bound 2239 2301 ! a(in) : lower bound
! b(in) : higher bound 2240 2302 ! b(in) : higher bound
! n(in) : number of gauss legendre pairs 2241 2303 ! n(in) : number of gauss legendre pairs
! res(out): the evaluation of the integral 2242 2304 ! res(out): the evaluation of the integral
! 2243 2305 !
double precision,external :: f 2244 2306 double precision,external :: f
double precision, intent(in) :: a,b 2245 2307 double precision, intent(in) :: a,b
integer, intent(in):: n 2246 2308 integer, intent(in):: n
double precision, intent(out) :: res 2247 2309 double precision, intent(out) :: res
2248 2310
double precision, allocatable :: qx(:),qw(:) 2249 2311 double precision, allocatable :: qx(:),qw(:)
double precision :: xm,xr 2250 2312 double precision :: xm,xr
integer :: i 2251 2313 integer :: i
2252 2314
! First compute n gauss legendre abs and weight 2253 2315 ! First compute n gauss legendre abs and weight
allocate(qx(n)) 2254 2316 allocate(qx(n))
allocate(qw(n)) 2255 2317 allocate(qw(n))
call fvn_d_gauss_legendre(n,qx,qw) 2256 2318 call fvn_d_gauss_legendre(n,qx,qw)
2257 2319
xm=0.5d0*(b+a) 2258 2320 xm=0.5d0*(b+a)
xr=0.5d0*(b-a) 2259 2321 xr=0.5d0*(b-a)
2260 2322
res=0.d0 2261 2323 res=0.d0
2262 2324
do i=1,n 2263 2325 do i=1,n
res=res+qw(i)*f(xm+xr*qx(i)) 2264 2326 res=res+qw(i)*f(xm+xr*qx(i))
end do 2265 2327 end do
2266 2328
res=xr*res 2267 2329 res=xr*res
2268 2330
deallocate(qw) 2269 2331 deallocate(qw)
deallocate(qx) 2270 2332 deallocate(qx)
2271 2333
end subroutine 2272 2334 end subroutine
2273 2335
!!!!!!!!!!!!!!!!!!!!!!!! 2274 2336 !!!!!!!!!!!!!!!!!!!!!!!!
! 2275 2337 !
! Simple and double adaptative Gauss Kronrod integration based on 2276 2338 ! Simple and double adaptative Gauss Kronrod integration based on
! a modified version of quadpack ( http://www.netlib.org/quadpack 2277 2339 ! a modified version of quadpack ( http://www.netlib.org/quadpack
! 2278 2340 !
! Common parameters : 2279 2341 ! Common parameters :
! 2280 2342 !
! key (in) 2281 2343 ! key (in)
! epsabs 2282 2344 ! epsabs
! epsrel 2283 2345 ! epsrel
! 2284 2346 !
! 2285 2347 !
!!!!!!!!!!!!!!!!!!!!!!!! 2286 2348 !!!!!!!!!!!!!!!!!!!!!!!!
2287 2349
subroutine fvn_d_integ_1_gk(f,a,b,epsabs,epsrel,key,res,abserr,ier,limit) 2288 2350 subroutine fvn_d_integ_1_gk(f,a,b,epsabs,epsrel,key,res,abserr,ier,limit)
! 2289 2351 !
! Evaluate the integral of function f(x) between a and b 2290 2352 ! Evaluate the integral of function f(x) between a and b
! 2291 2353 !
! f(in) : the function 2292 2354 ! f(in) : the function
! a(in) : lower bound 2293 2355 ! a(in) : lower bound
! b(in) : higher bound 2294 2356 ! b(in) : higher bound
! epsabs(in) : desired absolute error 2295 2357 ! epsabs(in) : desired absolute error
! epsrel(in) : desired relative error 2296 2358 ! epsrel(in) : desired relative error
! key(in) : gauss kronrod rule 2297 2359 ! key(in) : gauss kronrod rule
! 1: 7 - 15 points 2298 2360 ! 1: 7 - 15 points
! 2: 10 - 21 points 2299 2361 ! 2: 10 - 21 points
! 3: 15 - 31 points 2300 2362 ! 3: 15 - 31 points
! 4: 20 - 41 points 2301 2363 ! 4: 20 - 41 points
! 5: 25 - 51 points 2302 2364 ! 5: 25 - 51 points
! 6: 30 - 61 points 2303 2365 ! 6: 30 - 61 points
! 2304 2366 !
! limit(in) : maximum number of subintervals in the partition of the 2305 2367 ! limit(in) : maximum number of subintervals in the partition of the
! given integration interval (a,b). A value of 500 will give the same 2306 2368 ! given integration interval (a,b). A value of 500 will give the same
! behaviour as the imsl routine dqdag 2307 2369 ! behaviour as the imsl routine dqdag
! 2308 2370 !
! res(out) : estimated integral value 2309 2371 ! res(out) : estimated integral value
! abserr(out) : estimated absolute error 2310 2372 ! abserr(out) : estimated absolute error
! ier(out) : error flag from quadpack routines 2311 2373 ! ier(out) : error flag from quadpack routines
! 0 : no error 2312 2374 ! 0 : no error
! 1 : maximum number of subdivisions allowed 2313 2375 ! 1 : maximum number of subdivisions allowed
! has been achieved. one can allow more 2314 2376 ! has been achieved. one can allow more
! subdivisions by increasing the value of 2315 2377 ! subdivisions by increasing the value of
! limit (and taking the according dimension 2316 2378 ! limit (and taking the according dimension
! adjustments into account). however, if 2317 2379 ! adjustments into account). however, if
! this yield no improvement it is advised 2318 2380 ! this yield no improvement it is advised
! to analyze the integrand in order to 2319 2381 ! to analyze the integrand in order to
! determine the integration difficulaties. 2320 2382 ! determine the integration difficulaties.
! if the position of a local difficulty can 2321 2383 ! if the position of a local difficulty can
! be determined (i.e.singularity, 2322 2384 ! be determined (i.e.singularity,
! discontinuity within the interval) one 2323 2385 ! discontinuity within the interval) one
! will probably gain from splitting up the 2324 2386 ! will probably gain from splitting up the
! interval at this point and calling the 2325 2387 ! interval at this point and calling the
! integrator on the subranges. if possible, 2326 2388 ! integrator on the subranges. if possible,
! an appropriate special-purpose integrator 2327 2389 ! an appropriate special-purpose integrator
! should be used which is designed for 2328 2390 ! should be used which is designed for
! handling the type of difficulty involved. 2329 2391 ! handling the type of difficulty involved.
! 2 : the occurrence of roundoff error is 2330 2392 ! 2 : the occurrence of roundoff error is
! detected, which prevents the requested 2331 2393 ! detected, which prevents the requested
! tolerance from being achieved. 2332 2394 ! tolerance from being achieved.
! 3 : extremely bad integrand behaviour occurs 2333 2395 ! 3 : extremely bad integrand behaviour occurs
! at some points of the integration 2334 2396 ! at some points of the integration
! interval. 2335 2397 ! interval.
! 6 : the input is invalid, because 2336 2398 ! 6 : the input is invalid, because
! (epsabs.le.0 and 2337 2399 ! (epsabs.le.0 and
! epsrel.lt.max(50*rel.mach.acc.,0.5d-28)) 2338 2400 ! epsrel.lt.max(50*rel.mach.acc.,0.5d-28))
! or limit.lt.1 or lenw.lt.limit*4. 2339 2401 ! or limit.lt.1 or lenw.lt.limit*4.
! result, abserr, neval, last are set 2340 2402 ! result, abserr, neval, last are set
! to zero. 2341 2403 ! to zero.
! except when lenw is invalid, iwork(1), 2342 2404 ! except when lenw is invalid, iwork(1),
! work(limit*2+1) and work(limit*3+1) are 2343 2405 ! work(limit*2+1) and work(limit*3+1) are
! set to zero, work(1) is set to a and 2344 2406 ! set to zero, work(1) is set to a and
! work(limit+1) to b. 2345 2407 ! work(limit+1) to b.
2346 2408
implicit none 2347 2409 implicit none
double precision, external :: f 2348 2410 double precision, external :: f
double precision, intent(in) :: a,b,epsabs,epsrel 2349 2411 double precision, intent(in) :: a,b,epsabs,epsrel
integer, intent(in) :: key 2350 2412 integer, intent(in) :: key
integer, intent(in) :: limit 2351 2413 integer, intent(in) :: limit
double precision, intent(out) :: res,abserr 2352 2414 double precision, intent(out) :: res,abserr
integer, intent(out) :: ier 2353 2415 integer, intent(out) :: ier
2354 2416
double precision, allocatable :: work(:) 2355 2417 double precision, allocatable :: work(:)
integer, allocatable :: iwork(:) 2356 2418 integer, allocatable :: iwork(:)
integer :: lenw,neval,last 2357 2419 integer :: lenw,neval,last
2358 2420
! imsl value for limit is 500 2359 2421 ! imsl value for limit is 500
lenw=limit*4 2360 2422 lenw=limit*4
2361 2423
allocate(iwork(limit)) 2362 2424 allocate(iwork(limit))
allocate(work(lenw)) 2363 2425 allocate(work(lenw))
2364 2426
call dqag(f,a,b,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work) 2365 2427 call dqag(f,a,b,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work)
2366 2428
deallocate(work) 2367 2429 deallocate(work)
deallocate(iwork) 2368 2430 deallocate(iwork)
2369 2431
end subroutine 2370 2432 end subroutine
2371 2433
2372 2434
2373 2435
subroutine fvn_d_integ_2_gk(f,a,b,g,h,epsabs,epsrel,key,res,abserr,ier,limit) 2374 2436 subroutine fvn_d_integ_2_gk(f,a,b,g,h,epsabs,epsrel,key,res,abserr,ier,limit)
! 2375 2437 !
! Evaluate the double integral of function f(x,y) for x between a and b and y between g(x) and h(x) 2376 2438 ! Evaluate the double integral of function f(x,y) for x between a and b and y between g(x) and h(x)
! 2377 2439 !
! f(in) : the function 2378 2440 ! f(in) : the function
! a(in) : lower bound 2379 2441 ! a(in) : lower bound
! b(in) : higher bound 2380 2442 ! b(in) : higher bound
! g(in) : external function describing lower bound for y 2381 2443 ! g(in) : external function describing lower bound for y
! h(in) : external function describing higher bound for y 2382 2444 ! h(in) : external function describing higher bound for y
! epsabs(in) : desired absolute error 2383 2445 ! epsabs(in) : desired absolute error
! epsrel(in) : desired relative error 2384 2446 ! epsrel(in) : desired relative error
! key(in) : gauss kronrod rule 2385 2447 ! key(in) : gauss kronrod rule
! 1: 7 - 15 points 2386 2448 ! 1: 7 - 15 points
! 2: 10 - 21 points 2387 2449 ! 2: 10 - 21 points
! 3: 15 - 31 points 2388 2450 ! 3: 15 - 31 points
! 4: 20 - 41 points 2389 2451 ! 4: 20 - 41 points
! 5: 25 - 51 points 2390 2452 ! 5: 25 - 51 points
! 6: 30 - 61 points 2391 2453 ! 6: 30 - 61 points
! 2392 2454 !
! limit(in) : maximum number of subintervals in the partition of the 2393 2455 ! limit(in) : maximum number of subintervals in the partition of the
! given integration interval (a,b). A value of 500 will give the same 2394 2456 ! given integration interval (a,b). A value of 500 will give the same
! behaviour as the imsl routine dqdag 2395 2457 ! behaviour as the imsl routine dqdag
! 2396 2458 !
! res(out) : estimated integral value 2397 2459 ! res(out) : estimated integral value
! abserr(out) : estimated absolute error 2398 2460 ! abserr(out) : estimated absolute error
! ier(out) : error flag from quadpack routines 2399 2461 ! ier(out) : error flag from quadpack routines
! 0 : no error 2400 2462 ! 0 : no error
! 1 : maximum number of subdivisions allowed 2401 2463 ! 1 : maximum number of subdivisions allowed
! has been achieved. one can allow more 2402 2464 ! has been achieved. one can allow more
! subdivisions by increasing the value of 2403 2465 ! subdivisions by increasing the value of
! limit (and taking the according dimension 2404 2466 ! limit (and taking the according dimension
! adjustments into account). however, if 2405 2467 ! adjustments into account). however, if
! this yield no improvement it is advised 2406 2468 ! this yield no improvement it is advised
! to analyze the integrand in order to 2407 2469 ! to analyze the integrand in order to
! determine the integration difficulaties. 2408 2470 ! determine the integration difficulaties.
! if the position of a local difficulty can 2409 2471 ! if the position of a local difficulty can
! be determined (i.e.singularity, 2410 2472 ! be determined (i.e.singularity,
! discontinuity within the interval) one 2411 2473 ! discontinuity within the interval) one
! will probably gain from splitting up the 2412 2474 ! will probably gain from splitting up the
! interval at this point and calling the 2413 2475 ! interval at this point and calling the
! integrator on the subranges. if possible, 2414 2476 ! integrator on the subranges. if possible,
! an appropriate special-purpose integrator 2415 2477 ! an appropriate special-purpose integrator
! should be used which is designed for 2416 2478 ! should be used which is designed for
! handling the type of difficulty involved. 2417 2479 ! handling the type of difficulty involved.
! 2 : the occurrence of roundoff error is 2418 2480 ! 2 : the occurrence of roundoff error is
! detected, which prevents the requested 2419 2481 ! detected, which prevents the requested
! tolerance from being achieved. 2420 2482 ! tolerance from being achieved.
! 3 : extremely bad integrand behaviour occurs 2421 2483 ! 3 : extremely bad integrand behaviour occurs
! at some points of the integration 2422 2484 ! at some points of the integration
! interval. 2423 2485 ! interval.
! 6 : the input is invalid, because 2424 2486 ! 6 : the input is invalid, because
! (epsabs.le.0 and 2425 2487 ! (epsabs.le.0 and
! epsrel.lt.max(50*rel.mach.acc.,0.5d-28)) 2426 2488 ! epsrel.lt.max(50*rel.mach.acc.,0.5d-28))
! or limit.lt.1 or lenw.lt.limit*4. 2427 2489 ! or limit.lt.1 or lenw.lt.limit*4.
! result, abserr, neval, last are set 2428 2490 ! result, abserr, neval, last are set
! to zero. 2429 2491 ! to zero.
! except when lenw is invalid, iwork(1), 2430 2492 ! except when lenw is invalid, iwork(1),
! work(limit*2+1) and work(limit*3+1) are 2431 2493 ! work(limit*2+1) and work(limit*3+1) are
! set to zero, work(1) is set to a and 2432 2494 ! set to zero, work(1) is set to a and
! work(limit+1) to b. 2433 2495 ! work(limit+1) to b.
2434 2496
implicit none 2435 2497 implicit none
double precision, external:: f,g,h 2436 2498 double precision, external:: f,g,h
double precision, intent(in) :: a,b,epsabs,epsrel 2437 2499 double precision, intent(in) :: a,b,epsabs,epsrel
integer, intent(in) :: key,limit 2438 2500 integer, intent(in) :: key,limit
integer, intent(out) :: ier 2439 2501 integer, intent(out) :: ier
double precision, intent(out) :: res,abserr 2440 2502 double precision, intent(out) :: res,abserr
2441 2503
2442 2504
double precision, allocatable :: work(:) 2443 2505 double precision, allocatable :: work(:)
integer, allocatable :: iwork(:) 2444 2506 integer, allocatable :: iwork(:)
integer :: lenw,neval,last 2445 2507 integer :: lenw,neval,last
2446 2508
! imsl value for limit is 500 2447 2509 ! imsl value for limit is 500
lenw=limit*4 2448 2510 lenw=limit*4
allocate(work(lenw)) 2449 2511 allocate(work(lenw))
allocate(iwork(limit)) 2450 2512 allocate(iwork(limit))
2451 2513
call dqag_2d_outer(f,a,b,g,h,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work) 2452 2514 call dqag_2d_outer(f,a,b,g,h,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work)
2453 2515
deallocate(iwork) 2454 2516 deallocate(iwork)
deallocate(work) 2455 2517 deallocate(work)
end subroutine 2456 2518 end subroutine
2457 2519
2458 2520
2459 2521
subroutine fvn_d_integ_2_inner_gk(f,x,a,b,epsabs,epsrel,key,res,abserr,ier,limit) 2460 2522 subroutine fvn_d_integ_2_inner_gk(f,x,a,b,epsabs,epsrel,key,res,abserr,ier,limit)
! 2461 2523 !
! Evaluate the single integral of function f(x,y) for y between a and b with a 2462 2524 ! Evaluate the single integral of function f(x,y) for y between a and b with a
! given x value 2463 2525 ! given x value
! 2464 2526 !
! This function is used for the evaluation of the double integral fvn_d_integ_2_gk 2465 2527 ! This function is used for the evaluation of the double integral fvn_d_integ_2_gk
! 2466 2528 !
! f(in) : the function 2467 2529 ! f(in) : the function
! x(in) : x 2468 2530 ! x(in) : x
! a(in) : lower bound 2469 2531 ! a(in) : lower bound
! b(in) : higher bound 2470 2532 ! b(in) : higher bound
! epsabs(in) : desired absolute error 2471 2533 ! epsabs(in) : desired absolute error
! epsrel(in) : desired relative error 2472 2534 ! epsrel(in) : desired relative error
! key(in) : gauss kronrod rule 2473 2535 ! key(in) : gauss kronrod rule
! 1: 7 - 15 points 2474 2536 ! 1: 7 - 15 points
! 2: 10 - 21 points 2475 2537 ! 2: 10 - 21 points
! 3: 15 - 31 points 2476 2538 ! 3: 15 - 31 points
! 4: 20 - 41 points 2477 2539 ! 4: 20 - 41 points
! 5: 25 - 51 points 2478 2540 ! 5: 25 - 51 points
! 6: 30 - 61 points 2479 2541 ! 6: 30 - 61 points
! 2480 2542 !
! limit(in) : maximum number of subintervals in the partition of the 2481 2543 ! limit(in) : maximum number of subintervals in the partition of the
! given integration interval (a,b). A value of 500 will give the same 2482 2544 ! given integration interval (a,b). A value of 500 will give the same
! behaviour as the imsl routine dqdag 2483 2545 ! behaviour as the imsl routine dqdag
! 2484 2546 !
! res(out) : estimated integral value 2485 2547 ! res(out) : estimated integral value
! abserr(out) : estimated absolute error 2486 2548 ! abserr(out) : estimated absolute error
! ier(out) : error flag from quadpack routines 2487 2549 ! ier(out) : error flag from quadpack routines
! 0 : no error 2488 2550 ! 0 : no error
! 1 : maximum number of subdivisions allowed 2489 2551 ! 1 : maximum number of subdivisions allowed
! has been achieved. one can allow more 2490 2552 ! has been achieved. one can allow more
! subdivisions by increasing the value of 2491 2553 ! subdivisions by increasing the value of
! limit (and taking the according dimension 2492 2554 ! limit (and taking the according dimension
! adjustments into account). however, if 2493 2555 ! adjustments into account). however, if
! this yield no improvement it is advised 2494 2556 ! this yield no improvement it is advised
! to analyze the integrand in order to 2495 2557 ! to analyze the integrand in order to
! determine the integration difficulaties. 2496 2558 ! determine the integration difficulaties.
! if the position of a local difficulty can 2497 2559 ! if the position of a local difficulty can
! be determined (i.e.singularity, 2498 2560 ! be determined (i.e.singularity,
! discontinuity within the interval) one 2499 2561 ! discontinuity within the interval) one
! will probably gain from splitting up the 2500 2562 ! will probably gain from splitting up the
! interval at this point and calling the 2501 2563 ! interval at this point and calling the
! integrator on the subranges. if possible, 2502 2564 ! integrator on the subranges. if possible,
! an appropriate special-purpose integrator 2503 2565 ! an appropriate special-purpose integrator
! should be used which is designed for 2504 2566 ! should be used which is designed for
! handling the type of difficulty involved. 2505 2567 ! handling the type of difficulty involved.
! 2 : the occurrence of roundoff error is 2506 2568 ! 2 : the occurrence of roundoff error is
! detected, which prevents the requested 2507 2569 ! detected, which prevents the requested
! tolerance from being achieved. 2508 2570 ! tolerance from being achieved.
! 3 : extremely bad integrand behaviour occurs 2509 2571 ! 3 : extremely bad integrand behaviour occurs
! at some points of the integration 2510 2572 ! at some points of the integration
! interval. 2511 2573 ! interval.
! 6 : the input is invalid, because 2512 2574 ! 6 : the input is invalid, because
! (epsabs.le.0 and 2513 2575 ! (epsabs.le.0 and
! epsrel.lt.max(50*rel.mach.acc.,0.5d-28)) 2514 2576 ! epsrel.lt.max(50*rel.mach.acc.,0.5d-28))
! or limit.lt.1 or lenw.lt.limit*4. 2515 2577 ! or limit.lt.1 or lenw.lt.limit*4.
! result, abserr, neval, last are set 2516 2578 ! result, abserr, neval, last are set
! to zero. 2517 2579 ! to zero.
! except when lenw is invalid, iwork(1), 2518 2580 ! except when lenw is invalid, iwork(1),
! work(limit*2+1) and work(limit*3+1) are 2519 2581 ! work(limit*2+1) and work(limit*3+1) are
! set to zero, work(1) is set to a and 2520 2582 ! set to zero, work(1) is set to a and
! work(limit+1) to b. 2521 2583 ! work(limit+1) to b.
2522 2584
implicit none 2523 2585 implicit none
double precision, external:: f 2524 2586 double precision, external:: f
double precision, intent(in) :: x,a,b,epsabs,epsrel 2525 2587 double precision, intent(in) :: x,a,b,epsabs,epsrel
integer, intent(in) :: key,limit 2526 2588 integer, intent(in) :: key,limit
integer, intent(out) :: ier 2527 2589 integer, intent(out) :: ier
double precision, intent(out) :: res,abserr 2528 2590 double precision, intent(out) :: res,abserr
2529 2591
2530 2592
double precision, allocatable :: work(:) 2531 2593 double precision, allocatable :: work(:)
integer, allocatable :: iwork(:) 2532 2594 integer, allocatable :: iwork(:)
integer :: lenw,neval,last 2533 2595 integer :: lenw,neval,last
2534 2596
! imsl value for limit is 500 2535 2597 ! imsl value for limit is 500
lenw=limit*4 2536 2598 lenw=limit*4
allocate(work(lenw)) 2537 2599 allocate(work(lenw))
allocate(iwork(limit)) 2538 2600 allocate(iwork(limit))
2539 2601
call dqag_2d_inner(f,x,a,b,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work) 2540 2602 call dqag_2d_inner(f,x,a,b,epsabs,epsrel,key,res,abserr,neval,ier,limit,lenw,last,iwork,work)
2541 2603
deallocate(iwork) 2542 2604 deallocate(iwork)
deallocate(work) 2543 2605 deallocate(work)
end subroutine 2544 2606 end subroutine
2545 2607
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2546 2608 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Include the modified quadpack files 2547 2609 ! Include the modified quadpack files
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2548 2610 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
include "fvn_quadpack/dqag_2d_inner.f" 2549 2611 include "fvn_quadpack/dqag_2d_inner.f"
include "fvn_quadpack/dqk15_2d_inner.f" 2550 2612 include "fvn_quadpack/dqk15_2d_inner.f"
include "fvn_quadpack/dqk31_2d_outer.f" 2551 2613 include "fvn_quadpack/dqk31_2d_outer.f"
include "fvn_quadpack/d1mach.f" 2552 2614 include "fvn_quadpack/d1mach.f"
include "fvn_quadpack/dqk31_2d_inner.f" 2553 2615 include "fvn_quadpack/dqk31_2d_inner.f"
include "fvn_quadpack/dqage.f" 2554 2616 include "fvn_quadpack/dqage.f"
include "fvn_quadpack/dqk15.f" 2555 2617 include "fvn_quadpack/dqk15.f"
include "fvn_quadpack/dqk21.f" 2556 2618 include "fvn_quadpack/dqk21.f"
include "fvn_quadpack/dqk31.f" 2557 2619 include "fvn_quadpack/dqk31.f"
include "fvn_quadpack/dqk41.f" 2558 2620 include "fvn_quadpack/dqk41.f"
include "fvn_quadpack/dqk51.f" 2559 2621 include "fvn_quadpack/dqk51.f"
include "fvn_quadpack/dqk61.f" 2560 2622 include "fvn_quadpack/dqk61.f"
include "fvn_quadpack/dqk41_2d_outer.f" 2561 2623 include "fvn_quadpack/dqk41_2d_outer.f"
include "fvn_quadpack/dqk41_2d_inner.f" 2562 2624 include "fvn_quadpack/dqk41_2d_inner.f"
include "fvn_quadpack/dqag_2d_outer.f" 2563 2625 include "fvn_quadpack/dqag_2d_outer.f"
include "fvn_quadpack/dqpsrt.f" 2564 2626 include "fvn_quadpack/dqpsrt.f"
include "fvn_quadpack/dqag.f" 2565 2627 include "fvn_quadpack/dqag.f"
include "fvn_quadpack/dqage_2d_outer.f" 2566 2628 include "fvn_quadpack/dqage_2d_outer.f"
include "fvn_quadpack/dqage_2d_inner.f" 2567 2629 include "fvn_quadpack/dqage_2d_inner.f"
include "fvn_quadpack/dqk51_2d_outer.f" 2568 2630 include "fvn_quadpack/dqk51_2d_outer.f"
include "fvn_quadpack/dqk51_2d_inner.f" 2569 2631 include "fvn_quadpack/dqk51_2d_inner.f"
include "fvn_quadpack/dqk61_2d_outer.f" 2570 2632 include "fvn_quadpack/dqk61_2d_outer.f"
include "fvn_quadpack/dqk21_2d_outer.f" 2571 2633 include "fvn_quadpack/dqk21_2d_outer.f"
include "fvn_quadpack/dqk61_2d_inner.f" 2572 2634 include "fvn_quadpack/dqk61_2d_inner.f"
include "fvn_quadpack/dqk21_2d_inner.f" 2573 2635 include "fvn_quadpack/dqk21_2d_inner.f"
include "fvn_quadpack/dqk15_2d_outer.f" 2574 2636 include "fvn_quadpack/dqk15_2d_outer.f"
2575 2637
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2576 2638 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 2577 2639 !
! Trigonometric functions 2578 2640 ! Trigonometric functions
! 2579 2641 !
! fvn_z_acos, fvn_z_asin : complex arc cosine and sine 2580 2642 ! fvn_z_acos, fvn_z_asin : complex arc cosine and sine
! fvn_d_acosh : arc cosinus hyperbolic 2581 2643 ! fvn_d_acosh : arc cosinus hyperbolic
! fvn_d_asinh : arc sinus hyperbolic 2582 2644 ! fvn_d_asinh : arc sinus hyperbolic
! 2583 2645 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2584 2646 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
function fvn_z_acos(z) 2585 2647 function fvn_z_acos(z)
! double complex arccos function adapted from 2586 2648 ! double complex arccos function adapted from
! the c gsl library 2587 2649 ! the c gsl library
! http://www.gnu.org/software/gsl/ 2588 2650 ! http://www.gnu.org/software/gsl/
implicit none 2589 2651 implicit none
complex(kind=8) :: fvn_z_acos 2590 2652 complex(kind=8) :: fvn_z_acos
complex(kind=8) :: z 2591 2653 complex(kind=8) :: z
real(kind=8) :: rz,iz,x,y,a,b,y2,r,s,d,apx,am1 2592 2654 real(kind=8) :: rz,iz,x,y,a,b,y2,r,s,d,apx,am1
real(kind=8),parameter :: a_crossover=1.5_8,b_crossover = 0.6417_8 2593 2655 real(kind=8),parameter :: a_crossover=1.5_8,b_crossover = 0.6417_8
complex(kind=8),parameter :: i=(0._8,1._8) 2594 2656 complex(kind=8),parameter :: i=(0._8,1._8)
real(kind=8) :: r_res,i_res 2595 2657 real(kind=8) :: r_res,i_res
2596 2658
rz=dreal(z) 2597 2659 rz=dreal(z)
iz=dimag(z) 2598 2660 iz=dimag(z)
if ( iz == 0._8 ) then 2599 2661 if ( iz == 0._8 ) then
fvn_z_acos=fvn_z_acos_real(rz) 2600 2662 fvn_z_acos=fvn_z_acos_real(rz)
return 2601 2663 return
end if 2602 2664 end if
2603 2665
x=dabs(rz) 2604 2666 x=dabs(rz)
y=dabs(iz) 2605 2667 y=dabs(iz)
r=fvn_d_hypot(x+1.,y) 2606 2668 r=fvn_d_hypot(x+1.,y)
s=fvn_d_hypot(x-1.,y) 2607 2669 s=fvn_d_hypot(x-1.,y)
a=0.5*(r + s) 2608 2670 a=0.5*(r + s)
b=x/a 2609 2671 b=x/a
y2=y*y 2610 2672 y2=y*y
2611 2673
if (b <= b_crossover) then 2612 2674 if (b <= b_crossover) then
r_res=dacos(b) 2613 2675 r_res=dacos(b)
else 2614 2676 else
if (x <= 1.) then 2615 2677 if (x <= 1.) then
d=0.5*(a+x)*(y2/(r+x+1)+(s + (1 - x))) 2616 2678 d=0.5*(a+x)*(y2/(r+x+1)+(s + (1 - x)))
r_res=datan(dsqrt(d)/x) 2617 2679 r_res=datan(dsqrt(d)/x)
else 2618 2680 else
apx=a+x 2619 2681 apx=a+x
d=0.5*(apx/(r+x+1)+apx/(s + (x - 1))) 2620 2682 d=0.5*(apx/(r+x+1)+apx/(s + (x - 1)))
r_res=datan((y*dsqrt(d))/x); 2621 2683 r_res=datan((y*dsqrt(d))/x);
end if 2622 2684 end if
end if 2623 2685 end if
2624 2686
if (a <= a_crossover) then 2625 2687 if (a <= a_crossover) then
if (x < 1.) then 2626 2688 if (x < 1.) then
am1=0.5*(y2 / (r + (x + 1)) + y2 / (s + (1 - x))) 2627 2689 am1=0.5*(y2 / (r + (x + 1)) + y2 / (s + (1 - x)))
else 2628 2690 else
am1=0.5*(y2 / (r + (x + 1)) + (s + (x - 1))) 2629 2691 am1=0.5*(y2 / (r + (x + 1)) + (s + (x - 1)))
end if 2630 2692 end if
i_res = dlog(1.+(am1 + sqrt (am1 * (a + 1)))); 2631 2693 i_res = dlog(1.+(am1 + sqrt (am1 * (a + 1))));
else 2632 2694 else
i_res = dlog (a + dsqrt (a*a - 1.)); 2633 2695 i_res = dlog (a + dsqrt (a*a - 1.));
end if 2634 2696 end if
if (rz <0.) then 2635 2697 if (rz <0.) then
r_res=fvn_pi-r_res 2636 2698 r_res=fvn_pi-r_res
end if 2637 2699 end if
i_res=-sign(1._8,iz)*i_res 2638 2700 i_res=-sign(1._8,iz)*i_res
fvn_z_acos=dcmplx(r_res)+fvn_i*dcmplx(i_res) 2639 2701 fvn_z_acos=dcmplx(r_res)+fvn_i*dcmplx(i_res)
2640 2702
end function fvn_z_acos 2641 2703 end function fvn_z_acos
2642 2704
function fvn_z_acos_real(r) 2643 2705 function fvn_z_acos_real(r)
! return the double complex arc cosinus for a 2644 2706 ! return the double complex arc cosinus for a
! double precision argument 2645 2707 ! double precision argument
implicit none 2646 2708 implicit none
real(kind=8) :: r 2647 2709 real(kind=8) :: r
complex(kind=8) :: fvn_z_acos_real 2648 2710 complex(kind=8) :: fvn_z_acos_real
2649 2711
if (dabs(r)<=1._8) then 2650 2712 if (dabs(r)<=1._8) then
fvn_z_acos_real=dcmplx(dacos(r)) 2651 2713 fvn_z_acos_real=dcmplx(dacos(r))
return 2652 2714 return
end if 2653 2715 end if
if (r < 0._8) then 2654 2716 if (r < 0._8) then
fvn_z_acos_real=dcmplx(fvn_pi)-fvn_i*dcmplx(fvn_d_acosh(-r)) 2655 2717 fvn_z_acos_real=dcmplx(fvn_pi)-fvn_i*dcmplx(fvn_d_acosh(-r))
else 2656 2718 else
fvn_z_acos_real=fvn_i*dcmplx(fvn_d_acosh(r)) 2657 2719 fvn_z_acos_real=fvn_i*dcmplx(fvn_d_acosh(r))
end if 2658 2720 end if
end function 2659 2721 end function
2660 2722
2661 2723
function fvn_z_asin(z) 2662 2724 function fvn_z_asin(z)
! double complex arcsin function derived from 2663 2725 ! double complex arcsin function derived from
! the c gsl library 2664 2726 ! the c gsl library
! http://www.gnu.org/software/gsl/ 2665 2727 ! http://www.gnu.org/software/gsl/
implicit none 2666 2728 implicit none
complex(kind=8) :: fvn_z_asin 2667 2729 complex(kind=8) :: fvn_z_asin
complex(kind=8) :: z 2668 2730 complex(kind=8) :: z
real(kind=8) :: rz,iz,x,y,a,b,y2,r,s,d,apx,am1 2669 2731 real(kind=8) :: rz,iz,x,y,a,b,y2,r,s,d,apx,am1
real(kind=8),parameter :: a_crossover=1.5_8,b_crossover = 0.6417_8 2670 2732 real(kind=8),parameter :: a_crossover=1.5_8,b_crossover = 0.6417_8
real(kind=8) :: r_res,i_res 2671 2733 real(kind=8) :: r_res,i_res
2672 2734
rz=dreal(z) 2673 2735 rz=dreal(z)
iz=dimag(z) 2674 2736 iz=dimag(z)
if ( iz == 0._8 ) then 2675 2737 if ( iz == 0._8 ) then
! z is real 2676 2738 ! z is real
fvn_z_asin=fvn_z_asin_real(rz) 2677 2739 fvn_z_asin=fvn_z_asin_real(rz)
return 2678 2740 return
end if 2679 2741 end if
2680 2742
x=dabs(rz) 2681 2743 x=dabs(rz)
y=dabs(iz) 2682 2744 y=dabs(iz)
r=fvn_d_hypot(x+1.,y) 2683 2745 r=fvn_d_hypot(x+1.,y)
s=fvn_d_hypot(x-1.,y) 2684 2746 s=fvn_d_hypot(x-1.,y)
a=0.5*(r + s) 2685 2747 a=0.5*(r + s)
b=x/a 2686 2748 b=x/a
y2=y*y 2687 2749 y2=y*y
2688 2750
if (b <= b_crossover) then 2689 2751 if (b <= b_crossover) then
r_res=dasin(b) 2690 2752 r_res=dasin(b)
else 2691 2753 else
if (x <= 1.) then 2692 2754 if (x <= 1.) then
d=0.5*(a+x)*(y2/(r+x+1)+(s + (1 - x))) 2693 2755 d=0.5*(a+x)*(y2/(r+x+1)+(s + (1 - x)))
r_res=datan(x/dsqrt(d)) 2694 2756 r_res=datan(x/dsqrt(d))
else 2695 2757 else
apx=a+x 2696 2758 apx=a+x
d=0.5*(apx/(r+x+1)+apx/(s + (x - 1))) 2697 2759 d=0.5*(apx/(r+x+1)+apx/(s + (x - 1)))
r_res=datan(x/(y*dsqrt(d))); 2698 2760 r_res=datan(x/(y*dsqrt(d)));
end if 2699 2761 end if
end if 2700 2762 end if
2701 2763
if (a <= a_crossover) then 2702 2764 if (a <= a_crossover) then
if (x < 1.) then 2703 2765 if (x < 1.) then
am1=0.5*(y2 / (r + (x + 1)) + y2 / (s + (1 - x))) 2704 2766 am1=0.5*(y2 / (r + (x + 1)) + y2 / (s + (1 - x)))
else 2705 2767 else
am1=0.5*(y2 / (r + (x + 1)) + (s + (x - 1))) 2706 2768 am1=0.5*(y2 / (r + (x + 1)) + (s + (x - 1)))
end if 2707 2769 end if
i_res = dlog(1.+(am1 + sqrt (am1 * (a + 1)))); 2708 2770 i_res = dlog(1.+(am1 + sqrt (am1 * (a + 1))));
else 2709 2771 else
i_res = dlog (a + dsqrt (a*a - 1.)); 2710 2772 i_res = dlog (a + dsqrt (a*a - 1.));
end if 2711 2773 end if
r_res=sign(1._8,rz)*r_res 2712 2774 r_res=sign(1._8,rz)*r_res
i_res=sign(1._8,iz)*i_res 2713 2775 i_res=sign(1._8,iz)*i_res
fvn_z_asin=dcmplx(r_res)+fvn_i*dcmplx(i_res) 2714 2776 fvn_z_asin=dcmplx(r_res)+fvn_i*dcmplx(i_res)
2715 2777
end function fvn_z_asin 2716 2778 end function fvn_z_asin
2717 2779
function fvn_z_asin_real(r) 2718 2780 function fvn_z_asin_real(r)
! return the double complex arc sinus for a 2719 2781 ! return the double complex arc sinus for a
! double precision argument 2720 2782 ! double precision argument
implicit none 2721 2783 implicit none
real(kind=8) :: r 2722 2784 real(kind=8) :: r
complex(kind=8) :: fvn_z_asin_real 2723 2785 complex(kind=8) :: fvn_z_asin_real
2724 2786
if (dabs(r)<=1._8) then 2725 2787 if (dabs(r)<=1._8) then
fvn_z_asin_real=dcmplx(dasin(r)) 2726 2788 fvn_z_asin_real=dcmplx(dasin(r))
return 2727 2789 return
end if 2728 2790 end if
if (r < 0._8) then 2729 2791 if (r < 0._8) then
fvn_z_asin_real=dcmplx(-fvn_pi/2._8)+fvn_i*dcmplx(fvn_d_acosh(-r)) 2730 2792 fvn_z_asin_real=dcmplx(-fvn_pi/2._8)+fvn_i*dcmplx(fvn_d_acosh(-r))
else 2731 2793 else
fvn_z_asin_real=dcmplx(fvn_pi/2._8)-fvn_i*dcmplx(fvn_d_acosh(r)) 2732 2794 fvn_z_asin_real=dcmplx(fvn_pi/2._8)-fvn_i*dcmplx(fvn_d_acosh(r))
end if 2733 2795 end if
end function fvn_z_asin_real 2734 2796 end function fvn_z_asin_real
2735 2797
function fvn_d_acosh(r) 2736 2798 function fvn_d_acosh(r)
! return the arc hyperbolic cosine 2737 2799 ! return the arc hyperbolic cosine
implicit none 2738 2800 implicit none
real(kind=8) :: r 2739 2801 real(kind=8) :: r
real(kind=8) :: fvn_d_acosh 2740 2802 real(kind=8) :: fvn_d_acosh
if (r >=1) then 2741 2803 if (r >=1) then
fvn_d_acosh=dlog(r+dsqrt(r*r-1)) 2742 2804 fvn_d_acosh=dlog(r+dsqrt(r*r-1))
else 2743 2805 else
!! TODO : Better error handling!!!!!! 2744 2806 !! TODO : Better error handling!!!!!!
stop "Argument to fvn_d_acosh lesser than 1" 2745 2807 stop "Argument to fvn_d_acosh lesser than 1"
end if 2746 2808 end if
end function fvn_d_acosh 2747 2809 end function fvn_d_acosh
2748 2810
function fvn_d_asinh(r) 2749 2811 function fvn_d_asinh(r)
! return the arc hyperbolic sine 2750 2812 ! return the arc hyperbolic sine
implicit none 2751 2813 implicit none
real(kind=8) :: r 2752 2814 real(kind=8) :: r
real(kind=8) :: fvn_d_asinh 2753 2815 real(kind=8) :: fvn_d_asinh
fvn_d_asinh=dlog(r+dsqrt(r*r+1)) 2754 2816 fvn_d_asinh=dlog(r+dsqrt(r*r+1))
end function fvn_d_asinh 2755 2817 end function fvn_d_asinh
2756 2818
function fvn_d_hypot(a,b) 2757 2819 function fvn_d_hypot(a,b)
implicit none 2758 2820 implicit none
! return the euclidian norm of vector(a,b) 2759 2821 ! return the euclidian norm of vector(a,b)
real(kind=8) :: a,b 2760 2822 real(kind=8) :: a,b
real(kind=8) :: fvn_d_hypot 2761 2823 real(kind=8) :: fvn_d_hypot
fvn_d_hypot=dsqrt(a*a+b*b) 2762 2824 fvn_d_hypot=dsqrt(a*a+b*b)
end function 2763 2825 end function
2764 2826
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2765 2827 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 2766 2828 !
! SPARSE RESOLUTION 2767 2829 ! SPARSE RESOLUTION
! 2768 2830 !
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 2769 2831 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! 2770 2832 !
! Sparse resolution is done by interfaçing Tim Davi's UMFPACK 2771 2833 ! Sparse resolution is done by interfaçing Tim Davi's UMFPACK
! http://www.cise.ufl.edu/research/sparse/SuiteSparse/ 2772 2834 ! http://www.cise.ufl.edu/research/sparse/SuiteSparse/
! Used packages from SuiteSparse : AMD,UMFPACK,UFconfig 2773 2835 ! Used packages from SuiteSparse : AMD,UMFPACK,UFconfig
! 2774 2836 !
! Solve Ax=B using UMFPACK 2775 2837 ! Solve Ax=B using UMFPACK
! 2776 2838 !
! Where A is a sparse matrix given in its triplet form 2777 2839 ! Where A is a sparse matrix given in its triplet form
! T -> non zero elements 2778 2840 ! T -> non zero elements
! Ti,Tj -> row and column index (1-based) of the given elt 2779 2841 ! Ti,Tj -> row and column index (1-based) of the given elt
! n : rank of matrix A 2780 2842 ! n : rank of matrix A
! nz : number of non zero elts 2781 2843 ! nz : number of non zero elts
! 2782 2844 !
! fvn_*_sparse_solve 2783 2845 ! fvn_*_sparse_solve
! * = zl : double complex + integer(8) 2784 2846 ! * = zl : double complex + integer(8)
! * = zi : double complex + integer(4) 2785 2847 ! * = zi : double complex + integer(4)
! 2786 2848 !
subroutine fvn_zl_sparse_solve(n,nz,T,Ti,Tj,B,x,status) 2787 2849 subroutine fvn_zl_sparse_solve(n,nz,T,Ti,Tj,B,x,status)
implicit none 2788 2850 implicit none
integer(8), intent(in) :: n,nz 2789 2851 integer(8), intent(in) :: n,nz
complex(8),dimension(nz),intent(in) :: T 2790 2852 complex(8),dimension(nz),intent(in) :: T
integer(8),dimension(nz),intent(in) :: Ti,Tj 2791 2853 integer(8),dimension(nz),intent(in) :: Ti,Tj
complex(8),dimension(n),intent(in) :: B 2792 2854 complex(8),dimension(n),intent(in) :: B
complex(8),dimension(n),intent(out) :: x 2793 2855 complex(8),dimension(n),intent(out) :: x
integer(8), intent(out) :: status 2794 2856 integer(8), intent(out) :: status
2795 2857
integer(8),dimension(:),allocatable :: wTi,wTj 2796 2858 integer(8),dimension(:),allocatable :: wTi,wTj
real(8),dimension(:),allocatable :: Tx,Tz 2797 2859 real(8),dimension(:),allocatable :: Tx,Tz