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