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