![]() |
Millepede-II
V04-00-00
|
00001 00002 ! Code converted using TO_F90 by Alan Miller 00003 ! Date: 2012-03-16 Time: 11:07:48 00004 00051 00052 !---------------------------------------------------------------------- 00071 00072 SUBROUTINE sqminv(v,b,n,nrank,diag,next) ! matrix inversion 00073 IMPLICIT NONE 00074 INTEGER :: i 00075 INTEGER :: ij 00076 INTEGER :: j 00077 INTEGER :: jj 00078 INTEGER :: jk 00079 INTEGER :: jl 00080 INTEGER :: k 00081 INTEGER :: kk 00082 INTEGER :: l 00083 INTEGER :: last 00084 INTEGER :: lk 00085 INTEGER :: next0 00086 00087 DOUBLE PRECISION, INTENT(IN OUT) :: v(*) 00088 DOUBLE PRECISION, INTENT(OUT) :: b(n) 00089 INTEGER, INTENT(IN) :: n 00090 INTEGER, INTENT(OUT) :: nrank 00091 DOUBLE PRECISION, INTENT(OUT) :: diag(n) 00092 INTEGER, INTENT(OUT) :: next(n) 00093 DOUBLE PRECISION :: vkk 00094 DOUBLE PRECISION :: vjk 00095 00096 DOUBLE PRECISION, PARAMETER :: eps=1.0D-10 00097 ! ... 00098 next0=1 00099 l=1 00100 DO i=1,n 00101 next(i)=i+1 ! set "next" pointer 00102 diag(i)=ABS(v((i*i+i)/2)) ! save abs of diagonal elements 00103 END DO 00104 next(n)=-1 ! end flag 00105 00106 nrank=0 00107 DO i=1,n ! start of loop 00108 k =0 00109 vkk=0.0D0 00110 00111 j=next0 00112 last=0 00113 05 IF(j > 0) THEN 00114 jj=(j*j+j)/2 00115 IF(ABS(v(jj)) > MAX(ABS(vkk),eps*diag(j))) THEN 00116 vkk=v(jj) 00117 k=j 00118 l=last 00119 END IF 00120 last=j 00121 j=next(last) 00122 GO TO 05 00123 END IF 00124 00125 IF(k /= 0) THEN ! pivot found 00126 kk=(k*k+k)/2 00127 IF(l == 0) THEN 00128 next0=next(k) 00129 ELSE 00130 next(l)=next(k) 00131 END IF 00132 next(k)=0 ! index is used, reset 00133 nrank=nrank+1 ! increase rank and ... 00134 vkk =1.0/vkk 00135 v(kk) =-vkk 00136 b(k) =b(k)*vkk 00137 jk =kk-k 00138 jl =0 00139 DO j=1,n ! elimination 00140 IF(j == k) THEN 00141 jk=kk 00142 jl=jl+j 00143 ELSE 00144 IF(j < k) THEN 00145 jk=jk+1 00146 ELSE 00147 jk=jk+j-1 00148 END IF 00149 vjk =v(jk) 00150 v(jk)=vkk*vjk 00151 b(j) =b(j)-b(k)*vjk 00152 lk =kk-k 00153 DO l=1,j 00154 jl=jl+1 00155 IF(l == k) THEN 00156 lk=kk 00157 ELSE 00158 IF(l < k) THEN 00159 lk=lk+1 00160 ELSE 00161 lk=lk+l-1 00162 END IF 00163 v(jl)=v(jl)-v(lk)*vjk 00164 END IF 00165 END DO 00166 END IF 00167 END DO 00168 ELSE 00169 DO k=1,n 00170 IF(next(k) /= 0) THEN 00171 b(k)=0.0D0 ! clear vector element 00172 DO j=1,k 00173 IF(next(j) /= 0) v((k*k-k)/2+j)=0.0D0 ! clear matrix row/col 00174 END DO 00175 END IF 00176 END DO 00177 GO TO 10 00178 END IF 00179 END DO ! end of loop 00180 10 DO ij=1,(n*n+n)/2 00181 v(ij)=-v(ij) ! finally reverse sign of all matrix elements 00182 END DO 00183 END SUBROUTINE sqminv 00184 00197 00198 SUBROUTINE sqminl(v,b,n,nrank,diag,next) ! 00199 USE mpdef 00200 00201 IMPLICIT NONE 00202 INTEGER :: i 00203 INTEGER :: j 00204 INTEGER :: k 00205 INTEGER :: l 00206 INTEGER :: last 00207 INTEGER :: next0 00208 00209 DOUBLE PRECISION, INTENT(IN OUT) :: v(*) 00210 DOUBLE PRECISION, INTENT(OUT) :: b(n) 00211 INTEGER, INTENT(IN) :: n 00212 INTEGER, INTENT(OUT) :: nrank 00213 DOUBLE PRECISION, INTENT(OUT) :: diag(n) 00214 INTEGER, INTENT(OUT) :: next(n) 00215 INTEGER*8 :: i8 00216 INTEGER*8 :: j8 00217 INTEGER*8 :: jj 00218 INTEGER*8 :: k8 00219 INTEGER*8 :: kk 00220 INTEGER*8 :: kkmk 00221 INTEGER*8 :: jk 00222 INTEGER*8 :: jl 00223 INTEGER*8 :: llk 00224 INTEGER*8 :: ljl 00225 00226 DOUBLE PRECISION :: vkk 00227 DOUBLE PRECISION :: vjk 00228 00229 DOUBLE PRECISION, PARAMETER :: eps=1.0D-10 00230 ! ... 00231 next0=1 00232 l=1 00233 DO i=1,n 00234 i8=int8(i) 00235 next(i)=i+1 ! set "next" pointer 00236 diag(i)=ABS(v((i8*i8+i8)/2)) ! save abs of diagonal elements 00237 END DO 00238 next(n)=-1 ! end flag 00239 00240 nrank=0 00241 DO i=1,n ! start of loop 00242 k =0 00243 vkk=0.0D0 00244 j=next0 00245 last=0 00246 05 IF(j > 0) THEN 00247 j8=int8(j) 00248 jj=(j8*j8+j8)/2 00249 IF(ABS(v(jj)) > MAX(ABS(vkk),eps*diag(j))) THEN 00250 vkk=v(jj) 00251 k=j 00252 l=last 00253 END IF 00254 last=j 00255 j=next(last) 00256 GO TO 05 00257 END IF 00258 00259 IF(k /= 0) THEN ! pivot found 00260 k8=int8(k) 00261 kk=(k8*k8+k8)/2 00262 kkmk=kk-k8 00263 IF(l == 0) THEN 00264 next0=next(k) 00265 ELSE 00266 next(l)=next(k) 00267 END IF 00268 next(k)=0 ! index is used, reset 00269 nrank=nrank+1 ! increase rank and ... 00270 vkk =1.0/vkk 00271 v(kk) =-vkk 00272 b(k) =b(k)*vkk 00273 ! elimination 00274 jk =kkmk 00275 DO j=1,n 00276 IF(j == k) THEN 00277 jk=kk 00278 ELSE 00279 IF(j < k) THEN 00280 jk=jk+1 00281 ELSE 00282 jk=jk+int8(j)-1 00283 END IF 00284 v(jk)=v(jk)*vkk 00285 END IF 00286 END DO 00287 ! parallelize row loop 00288 ! slot of 128 'J' for next idle thread 00289 !$OMP PARALLEL DO & 00290 !$OMP PRIVATE(JL,JK,L,LJL,LLK,VJK,J8) & 00291 !$OMP SCHEDULE(DYNAMIC,128) 00292 DO j=n,1,-1 00293 j8=int8(j) 00294 jl=j8*(j8-1)/2 00295 IF(j /= k) THEN 00296 IF(j < k) THEN 00297 jk=kkmk+j8 00298 ELSE 00299 jk=k8+jl 00300 END IF 00301 vjk =v(jk)/vkk 00302 b(j) =b(j)-b(k)*vjk 00303 ljl=jl 00304 llk=kkmk 00305 DO l=1,MIN(j,k-1) 00306 ljl=ljl+1 00307 llk=llk+1 00308 v(ljl)=v(ljl)-v(llk)*vjk 00309 END DO 00310 ljl=ljl+1 00311 llk=kk 00312 DO l=k+1,j 00313 ljl=ljl+1 00314 llk=llk+l-1 00315 v(ljl)=v(ljl)-v(llk)*vjk 00316 END DO 00317 END IF 00318 END DO 00319 !$OMP END PARALLEL DO 00320 ELSE 00321 DO k=1,n 00322 k8=int8(k) 00323 kk=(k8*k8-k8)/2 00324 IF(next(k) /= 0) THEN 00325 b(k)=0.0D0 ! clear vector element 00326 DO j=1,k 00327 IF(next(j) /= 0) v(kk+int8(j))=0.0D0 ! clear matrix row/col 00328 END DO 00329 END IF 00330 END DO 00331 GO TO 10 00332 END IF 00333 END DO ! end of loop 00334 10 DO jj=1,(int8(n)*int8(n)+int8(n))/2 00335 v(jj)=-v(jj) ! finally reverse sign of all matrix elements 00336 END DO 00337 END SUBROUTINE sqminl 00338 00350 00351 SUBROUTINE devrot(n,diag,u,v,work,iwork) ! diagonalization 00352 IMPLICIT NONE 00353 00354 INTEGER, INTENT(IN) :: n 00355 DOUBLE PRECISION, INTENT(OUT) :: diag(n) 00356 DOUBLE PRECISION, INTENT(OUT) :: u(n,n) 00357 DOUBLE PRECISION, INTENT(IN) :: v(*) 00358 DOUBLE PRECISION, INTENT(OUT) :: work(n) 00359 INTEGER, INTENT(OUT) :: iwork(n) 00360 00361 00362 INTEGER, PARAMETER :: itmax=30 00363 DOUBLE PRECISION, PARAMETER :: tol=1.0D-16 00364 DOUBLE PRECISION, PARAMETER :: eps=1.0D-16 00365 00366 DOUBLE PRECISION :: f 00367 DOUBLE PRECISION :: g 00368 DOUBLE PRECISION :: h 00369 DOUBLE PRECISION :: sh 00370 DOUBLE PRECISION :: hh 00371 DOUBLE PRECISION :: b 00372 DOUBLE PRECISION :: p 00373 DOUBLE PRECISION :: r 00374 DOUBLE PRECISION :: s 00375 DOUBLE PRECISION :: c 00376 DOUBLE PRECISION :: workd 00377 00378 INTEGER :: ij 00379 INTEGER :: i 00380 INTEGER :: j 00381 INTEGER :: k 00382 INTEGER :: l 00383 INTEGER :: m 00384 INTEGER :: ll 00385 ! ... 00386 ! 1. part: symmetric matrix V reduced to tridiagonal from 00387 ij=0 00388 DO i=1,n 00389 DO j=1,i 00390 ij=ij+1 00391 u(i,j)=v(ij) ! copy half of symmetric matirx 00392 END DO 00393 END DO 00394 00395 DO i=n,2,-1 00396 l=i-2 00397 f=u(i,i-1) 00398 g=0.0D0 00399 IF(l /= 0) THEN 00400 DO k=1,l 00401 IF(ABS(u(i,k)) > tol) g=g+u(i,k)*u(i,k) 00402 END DO 00403 h=g+f*f 00404 END IF 00405 IF(g < tol) THEN ! G too small 00406 work(i)=f ! skip transformation 00407 h =0.0D0 00408 ELSE 00409 l=l+1 00410 sh=SQRT(h) 00411 IF(f >= 0.0D0) sh=-sh 00412 g=sh 00413 work(i)=sh 00414 h=h-f*g 00415 u(i,i-1)=f-g 00416 f=0.0D0 00417 DO j=1,l 00418 u(j,i)=u(i,j)/h 00419 g=0.0D0 00420 ! form element of a u 00421 DO k=1,j 00422 IF(ABS(u(j,k)) > tol.AND.ABS(u(i,k)) > tol) THEN 00423 g=g+u(j,k)*u(i,k) 00424 END IF 00425 END DO 00426 DO k=j+1,l 00427 IF(ABS(u(k,j)) > tol.AND.ABS(u(i,k)) > tol) THEN 00428 g=g+u(k,j)*u(i,k) 00429 END IF 00430 END DO 00431 work(j)=g/h 00432 f=f+g*u(j,i) 00433 END DO 00434 ! form k 00435 hh=f/(h+h) 00436 ! form reduced a 00437 DO j=1,l 00438 f=u(i,j) 00439 work(j)=work(j)-hh*f 00440 g=work(j) 00441 DO k=1,j 00442 u(j,k)=u(j,k)-f*work(k)-g*u(i,k) 00443 END DO 00444 END DO 00445 END IF 00446 diag(i)=h 00447 END DO 00448 00449 diag(1)=0.0D0 00450 work(1)=0.0D0 00451 00452 ! accumulation of transformation matrices 00453 DO i=1,n 00454 IF(diag(i) /= 0.0) THEN 00455 DO j=1,i-1 00456 g=0.0D0 00457 DO k=1,i-1 00458 g=g+u(i,k)*u(k,j) 00459 END DO 00460 DO k=1,i-1 00461 u(k,j)=u(k,j)-g*u(k,i) 00462 END DO 00463 END DO 00464 END IF 00465 diag(i)=u(i,i) 00466 u(i,i)=1.0D0 00467 DO j=1,i-1 00468 u(i,j)=0.0D0 00469 u(j,i)=0.0D0 00470 END DO 00471 END DO 00472 00473 ! 2. part: diagonalization of tridiagonal matrix 00474 DO i=2,n 00475 work(i-1)=work(i) 00476 END DO 00477 work(n)=0.0D0 00478 b=0.0D0 00479 f=0.0D0 00480 00481 DO l=1,n 00482 j=0 00483 h=eps*(ABS(diag(l))+ABS(work(l))) 00484 IF(b < h) b=h 00485 DO m=l,n 00486 IF(ABS(work(m)) <= b) GO TO 10 ! look for small sub-diagonal element 00487 END DO 00488 m=l 00489 10 IF(m == l) GO TO 30 00490 ! next iteration 00491 20 IF(j == itmax) THEN 00492 WRITE(*,*) 'DEVROT: Iteration limit reached' 00493 STOP 00494 END IF 00495 j=j+1 00496 g=diag(l) 00497 p=(diag(l+1)-g)/(2.0D0*work(l)) 00498 r=SQRT(1.0D0+p*p) 00499 diag(l)=work(l) 00500 IF(p < 0.0D0) diag(l)=diag(l)/(p-r) 00501 IF(p >= 0.0D0) diag(l)=diag(l)/(p+r) 00502 h=g-diag(l) 00503 DO i=l+1,n 00504 diag(i)=diag(i)-h 00505 END DO 00506 f=f+h 00507 ! QL transformation 00508 p=diag(m) 00509 c=1.0D0 00510 s=0.0D0 00511 DO i=m-1,l,-1 ! reverse loop 00512 g=c*work(i) 00513 h=c*p 00514 IF(ABS(p) >= ABS(work(i))) THEN 00515 c=work(i)/p 00516 r=SQRT(1.0D0+c*c) 00517 work(i+1)=s*p*r 00518 s=c/r 00519 c=1.0D0/r 00520 ELSE 00521 c=p/work(i) 00522 r=SQRT(1.0D0+c*c) 00523 work(i+1)=s*work(i)*r 00524 s=1.0D0/r 00525 c=c/r 00526 END IF 00527 p=c*diag(i)-s*g 00528 diag(i+1)=h+s*(c*g+s*diag(i)) 00529 ! form vector 00530 DO k=1,n 00531 h=u(k,i+1) 00532 u(k,i+1)=s*u(k,i)+c*h 00533 u(k,i)=c*u(k,i)-s*h 00534 END DO 00535 END DO 00536 work(l)=s*p 00537 diag(l)=c*p 00538 IF(ABS(work(l)) > b) GO TO 20 ! next iteration 00539 30 diag(l)=diag(l)+f 00540 END DO 00541 DO i=1,n 00542 iwork(i)=i 00543 END DO 00544 00545 m=1 00546 40 m=1+3*m ! determine initial increment 00547 IF(m <= n) GO TO 40 00548 50 m=m/3 00549 DO j=1,n-m ! sort with increment M 00550 l=j 00551 60 IF(diag(iwork(l+m)) > diag(iwork(l))) THEN ! compare 00552 ll=iwork(l+m) ! exchange the two index values 00553 iwork(l+m)=iwork(l) 00554 iwork(l)=ll 00555 l=l-m 00556 IF(l > 0) GO TO 60 00557 END IF 00558 END DO 00559 IF(m > 1) GO TO 50 00560 00561 DO i=1,n 00562 IF(iwork(i) /= i) THEN 00563 ! move vector from position I to the work area 00564 workd=diag(i) 00565 DO l=1,n 00566 work(l)=u(l,i) 00567 END DO 00568 k=i 00569 70 j=k 00570 k=iwork(j) 00571 iwork(j)=j 00572 IF(k /= i) THEN 00573 ! move vector from position K to the (free) position J 00574 diag(j)=diag(k) 00575 DO l=1,n 00576 u(l,j)=u(l,k) 00577 END DO 00578 GO TO 70 00579 END IF 00580 ! move vector from the work area to position J 00581 diag(j)=workd 00582 DO l=1,n 00583 u(l,j)=work(l) 00584 END DO 00585 END IF 00586 END DO 00587 END SUBROUTINE devrot 00588 00590 SUBROUTINE devsig(n,diag,u,b,coef) 00591 IMPLICIT NONE 00592 00593 INTEGER, INTENT(IN) :: n 00594 DOUBLE PRECISION, INTENT(IN) :: diag(n) 00595 DOUBLE PRECISION, INTENT(IN) :: u(n,n) 00596 DOUBLE PRECISION, INTENT(IN) :: b(n) 00597 DOUBLE PRECISION, INTENT(OUT) :: coef(n) 00598 INTEGER :: i 00599 INTEGER :: j 00600 DOUBLE PRECISION :: dsum 00601 ! ... 00602 DO i=1,n 00603 coef(i)=0.0D0 00604 IF(diag(i) > 0.0D0) THEN 00605 dsum=0.0D0 00606 DO j=1,n 00607 dsum=dsum+u(j,i)*b(j) 00608 END DO 00609 coef(i)=ABS(dsum)/SQRT(diag(i)) 00610 END IF 00611 END DO 00612 END SUBROUTINE devsig 00613 00614 00625 00626 SUBROUTINE devsol(n,diag,u,b,x,work) 00627 IMPLICIT NONE 00628 00629 INTEGER, INTENT(IN) :: n 00630 DOUBLE PRECISION, INTENT(IN) :: diag(n) 00631 DOUBLE PRECISION, INTENT(IN) :: u(n,n) 00632 DOUBLE PRECISION, INTENT(IN) :: b(n) 00633 DOUBLE PRECISION, INTENT(OUT) :: x(n) 00634 DOUBLE PRECISION, INTENT(OUT) :: work(n) 00635 INTEGER :: i 00636 INTEGER :: j 00637 INTEGER :: jj 00638 DOUBLE PRECISION :: s 00639 ! ... 00640 DO j=1,n 00641 s=0.0D0 00642 work(j)=0.0D0 00643 IF(diag(j) /= 0.0D0) THEN 00644 DO i=1,n 00645 ! j-th eigenvector is U(.,J) 00646 s=s+u(i,j)*b(i) 00647 END DO 00648 work(j)=s/diag(j) 00649 END IF 00650 END DO 00651 00652 DO j=1,n 00653 s=0.0D0 00654 DO jj=1,n 00655 s=s+u(j,jj)*work(jj) 00656 END DO 00657 x(j)=s 00658 END DO 00659 ! WRITE(*,*) 'DEVSOL' 00660 ! WRITE(*,*) 'X ',X 00661 END SUBROUTINE devsol 00662 00670 00671 SUBROUTINE devinv(n,diag,u,v) 00672 00673 IMPLICIT NONE 00674 INTEGER :: i 00675 INTEGER :: ij 00676 INTEGER :: j 00677 INTEGER :: k 00678 00679 INTEGER, INTENT(IN) :: n 00680 DOUBLE PRECISION, INTENT(IN) :: diag(n) 00681 DOUBLE PRECISION, INTENT(IN) :: u(n,n) 00682 DOUBLE PRECISION, INTENT(OUT) :: v(*) 00683 DOUBLE PRECISION:: dsum 00684 ! ... 00685 ij=0 00686 DO i=1,n 00687 DO j=1,i 00688 ij=ij+1 00689 dsum=0.0D0 00690 DO k=1,n 00691 IF(diag(k) /= 0.0D0) THEN 00692 dsum=dsum+u(i,k)*u(j,k)/diag(k) 00693 END IF 00694 END DO 00695 v(ij)=dsum 00696 END DO 00697 END DO 00698 END SUBROUTINE devinv 00699 00700 00719 SUBROUTINE choldc(g,n) 00720 IMPLICIT NONE 00721 INTEGER :: i 00722 INTEGER :: ii 00723 INTEGER :: j 00724 INTEGER :: jj 00725 INTEGER :: k 00726 INTEGER :: kk 00727 00728 DOUBLE PRECISION, INTENT(IN OUT) :: g(*) 00729 INTEGER, INTENT(IN) :: n 00730 00731 DOUBLE PRECISION :: ratio 00732 ! ... 00733 ii=0 00734 DO i=1,n 00735 ii=ii+i 00736 IF(g(ii) /= 0.0) g(ii)=1.0/g(ii) ! (I,I) div ! 00737 jj=ii 00738 DO j=i+1,n 00739 ratio=g(i+jj)*g(ii) ! (I,J) (I,I) 00740 kk=jj 00741 DO k=j,n 00742 g(kk+j)=g(kk+j)-g(kk+i)*ratio ! (K,J) (K,I) 00743 kk=kk+k 00744 END DO ! K 00745 g(i+jj)=ratio ! (I,J) 00746 jj=jj+j 00747 END DO ! J 00748 END DO ! I 00749 RETURN 00750 END SUBROUTINE choldc 00751 00763 SUBROUTINE cholsl(g,x,n) 00764 IMPLICIT NONE 00765 DOUBLE PRECISION :: dsum 00766 INTEGER :: i 00767 INTEGER :: ii 00768 INTEGER :: k 00769 INTEGER :: kk 00770 00771 DOUBLE PRECISION, INTENT(IN) :: g(*) 00772 DOUBLE PRECISION, INTENT(IN OUT) :: x(n) 00773 INTEGER, INTENT(IN) :: n 00774 00775 ii=0 00776 DO i=1,n 00777 dsum=x(i) 00778 DO k=1,i-1 00779 dsum=dsum-g(k+ii)*x(k) ! (K,I) 00780 END DO 00781 x(i)=dsum 00782 ii=ii+i 00783 END DO 00784 DO i=n,1,-1 00785 dsum=x(i)*g(ii) ! (I,I) 00786 kk=ii 00787 DO k=i+1,n 00788 dsum=dsum-g(kk+i)*x(k) ! (K,I) 00789 kk=kk+k 00790 END DO 00791 x(i)=dsum 00792 ii=ii-i 00793 END DO 00794 RETURN 00795 END SUBROUTINE cholsl 00796 00807 SUBROUTINE cholin(g,v,n) 00808 IMPLICIT NONE 00809 DOUBLE PRECISION :: dsum 00810 INTEGER :: i 00811 INTEGER :: ii 00812 INTEGER :: j 00813 INTEGER :: k 00814 INTEGER :: l 00815 INTEGER :: m 00816 00817 DOUBLE PRECISION, INTENT(IN) :: g(*) 00818 DOUBLE PRECISION, INTENT( OUT) :: v(*) 00819 INTEGER, INTENT(IN) :: n 00820 00821 ii=(n*n-n)/2 00822 DO i=n,1,-1 00823 dsum=g(ii+i) ! (I,I) 00824 DO j=i,1,-1 00825 DO k=j+1,n 00826 l=MIN(i,k) 00827 m=MAX(i,k) 00828 dsum=dsum-g(j+(k*k-k)/2)*v(l+(m*m-m)/2) ! (J,K) (I,K) 00829 END DO 00830 v(ii+j)=dsum ! (I,J) 00831 dsum=0.0D0 00832 END DO 00833 ii=ii-i+1 00834 END DO 00835 END SUBROUTINE cholin 00836 00837 ! variable band matrix operations ---------------------------------- 00838 00859 00860 SUBROUTINE vabdec(n,val,ilptr) 00861 IMPLICIT NONE 00862 00863 INTEGER :: i 00864 INTEGER :: in 00865 INTEGER :: j 00866 INTEGER :: k 00867 INTEGER :: kj 00868 INTEGER :: mj 00869 INTEGER :: mk 00870 DOUBLE PRECISION :: sn 00871 DOUBLE PRECISION :: beta 00872 DOUBLE PRECISION :: delta 00873 DOUBLE PRECISION :: theta 00874 00875 INTEGER, INTENT(IN) :: n 00876 DOUBLE PRECISION, INTENT(IN OUT) :: val(*) 00877 INTEGER, INTENT(IN) :: ilptr(n) 00878 00879 DOUBLE PRECISION :: dgamma 00880 DOUBLE PRECISION :: xi 00881 DOUBLE PRECISION :: eps 00882 DOUBLE PRECISION :: prd 00883 DOUBLE PRECISION :: valkj 00884 00885 DOUBLE PRECISION, PARAMETER :: one=1.0D0 00886 DOUBLE PRECISION, PARAMETER :: two=2.0D0 00887 ! DATA EPS/0.0D0/ 00888 DATA eps/2.22044605E-16/ 00889 SAVE eps 00890 ! ... 00891 IF(eps == 0.0D0) THEN 00892 eps = two**(-12) 00893 10 eps = eps/two 00894 prd=one 00895 prd=prd+one*eps ! CALL dbaxpy(1,one,eps,prd) 00896 IF(prd > one) GO TO 10 00897 eps=eps*two ! EPS is machine presision 00898 WRITE(*,*) 'Machine precision is ',eps 00899 END IF 00900 00901 WRITE(*,*) 'Variable band matrix Cholesky decomposition' 00902 00903 dgamma=0.0D0 00904 i=1 00905 DO j=1,ilptr(n) ! loop thrugh all matrix elements 00906 IF(ilptr(i) == j) THEN ! diagonal element 00907 IF(val(j) <= 0.0D0) GO TO 01 ! exit loop for negative diag 00908 dgamma=MAX(dgamma,ABS(val(j))) ! max diagonal element 00909 i=i+1 00910 END IF 00911 END DO 00912 i=n+1 00913 01 in=i-1 ! IN positive diagonal elements 00914 WRITE(*,*) ' ',in,' positive diagonal elements' 00915 xi=0.0D0 00916 i=1 00917 DO j=1,ilptr(in) ! loop for positive diagonal elements 00918 ! through all matrix elements 00919 IF(ilptr(i) == j) THEN ! diagonal element 00920 i=i+1 00921 ELSE 00922 xi=MAX(xi,ABS(val(j))) ! Xi = abs(max) off-diagonal element 00923 END IF 00924 END DO 00925 00926 delta=eps*MAX(1.0D0,dgamma+xi) 00927 sn=1.0D0 00928 IF(n > 1) sn=1.0D0/SQRT(dfloat(n*n-1)) 00929 beta=SQRT(MAX(eps,dgamma,xi*sn)) ! beta 00930 WRITE(*,*) ' DELTA and BETA ',delta,beta 00931 00932 DO k=2,n 00933 mk=k-ilptr(k)+ilptr(k-1)+1 00934 00935 theta=0.0D0 00936 00937 DO j=mk,k 00938 mj=j-ilptr(j)+ilptr(j-1)+1 00939 kj=ilptr(k)-k+j ! index kj 00940 00941 DO i=MAX(mj,mk),j-1 00942 val(kj)=val(kj) & ! L_kj := L_kj - L_ki D_ii L_ji 00943 -val(ilptr(k)-k+i)*val(ilptr(i))*val(ilptr(j)-j+i) 00944 00945 END DO ! 00946 00947 theta=MAX(theta,ABS(val(kj))) ! maximum value of row 00948 00949 IF(j /= k) THEN 00950 IF(val(ilptr(j)) /= 0.0D0) THEN 00951 val(kj)=val(kj)/val(ilptr(j)) 00952 ELSE 00953 val(kj)=0.0D0 00954 END IF 00955 END IF ! L_kj := L_kj/D_jj ! D_kk 00956 00957 IF(j == k) THEN 00958 valkj=val(kj) 00959 IF(k <= in) THEN 00960 val(kj)=MAX(ABS(val(kj)),(theta/beta)**2,delta) 00961 IF(valkj /= val(kj)) THEN 00962 WRITE(*,*) ' Index K=',k 00963 WRITE(*,*) ' ',valkj,val(kj), (theta/beta)**2,delta,theta 00964 END IF 00965 END IF 00966 END IF 00967 END DO ! J 00968 00969 END DO ! K 00970 00971 DO k=1,n 00972 IF(val(ilptr(k)) /= 0.0D0) val(ilptr(k))=1.0D0/val(ilptr(k)) 00973 END DO 00974 00975 RETURN 00976 END SUBROUTINE vabdec 00977 00983 00984 SUBROUTINE vabmmm(n,val,ilptr) 00985 IMPLICIT NONE 00986 INTEGER :: k 00987 INTEGER :: kp 00988 INTEGER :: kr 00989 INTEGER :: ks 00990 INTEGER, INTENT(IN) :: n 00991 DOUBLE PRECISION, INTENT(IN OUT) :: val(*) 00992 INTEGER, INTENT(IN) :: ilptr(n) 00993 kr=1 00994 ks=1 00995 kp=1 00996 DO k=1,n 00997 IF(val(ilptr(k)) > val(ilptr(ks))) ks=k 00998 IF(val(ilptr(k)) < val(ilptr(kr))) kr=k 00999 IF(val(ilptr(k)) > 0.0.AND.val(ilptr(k)) < val(ilptr(kp))) kp=k 01000 END DO 01001 WRITE(*,*) ' Index value ',ks,val(ilptr(ks)) 01002 WRITE(*,*) ' Index value ',kp,val(ilptr(kp)) 01003 WRITE(*,*) ' Index value ',kr,val(ilptr(kr)) 01004 01005 RETURN 01006 END SUBROUTINE vabmmm 01007 01018 01019 SUBROUTINE vabslv(n,val,ilptr,x) 01020 IMPLICIT NONE 01021 INTEGER :: j 01022 INTEGER :: k 01023 INTEGER :: mk 01024 01025 INTEGER, INTENT(IN) :: n 01026 DOUBLE PRECISION, INTENT(IN OUT) :: val(*) 01027 INTEGER, INTENT(IN) :: ilptr(n) 01028 DOUBLE PRECISION, INTENT(IN OUT) :: x(n) 01029 ! ... 01030 DO k=1,n ! forward loop 01031 mk=k-ilptr(k)+ilptr(k-1)+1 01032 DO j=mk,k-1 01033 x(k)=x(k)-val(ilptr(k)-k+j)*x(j) ! X_k := X_k - L_kj B_j 01034 END DO 01035 END DO ! K 01036 01037 DO k=1,n ! divide by diagonal elements 01038 x(k)=x(k)*val(ilptr(k)) ! X_k := X_k*D_kk 01039 END DO 01040 01041 DO k=n,1,-1 ! backward loop 01042 mk=k-ilptr(k)+ilptr(k-1)+1 01043 DO j=mk,k-1 01044 x(j)=x(j)-val(ilptr(k)-k+j)*x(k) ! X_j := X_j - L_kj X_k 01045 END DO 01046 END DO ! K 01047 END SUBROUTINE vabslv 01048 01049 ! matrix/vector products ------------------------------------------- 01050 01057 01058 DOUBLE PRECISION FUNCTION dbdot(n,dx,dy) 01059 IMPLICIT NONE 01060 INTEGER:: i 01061 DOUBLE PRECISION :: dtemp 01062 01063 INTEGER, INTENT(IN) :: n 01064 DOUBLE PRECISION, INTENT(IN) :: dx(*) 01065 DOUBLE PRECISION, INTENT(IN) :: dy(*) 01066 ! ... 01067 dtemp=0.0D0 01068 DO i = 1,MOD(n,5) 01069 dtemp=dtemp+dx(i)*dy(i) 01070 END DO 01071 DO i =MOD(n,5)+1,n,5 01072 dtemp=dtemp+dx(i)*dy(i)+dx(i+1)*dy(i+1)+dx(i+2)*dy(i+2) & 01073 +dx(i+3)*dy(i+3)+dx(i+4)*dy(i+4) 01074 END DO 01075 dbdot=dtemp 01076 END FUNCTION dbdot 01077 01086 01087 SUBROUTINE dbaxpy(n,da,dx,dy) 01088 IMPLICIT NONE 01089 INTEGER:: i 01090 01091 INTEGER, INTENT(IN) :: n 01092 DOUBLE PRECISION, INTENT(IN) :: dx(*) 01093 DOUBLE PRECISION, INTENT(IN OUT) :: dy(*) 01094 DOUBLE PRECISION, INTENT(IN) :: da 01095 ! ... 01096 DO i=1,MOD(n,4) 01097 dy(i)=dy(i)+da*dx(i) 01098 END DO 01099 DO i=MOD(n,4)+1,n,4 01100 dy(i )=dy(i )+da*dx(i ) 01101 dy(i+1)=dy(i+1)+da*dx(i+1) 01102 dy(i+2)=dy(i+2)+da*dx(i+2) 01103 dy(i+3)=dy(i+3)+da*dx(i+3) 01104 END DO 01105 END SUBROUTINE dbaxpy 01106 01115 01116 SUBROUTINE dbsvx(v,a,b,n) ! 01117 IMPLICIT NONE 01118 INTEGER:: i 01119 INTEGER:: ij 01120 INTEGER:: ijs 01121 INTEGER:: j 01122 01123 ! B := V * A 01124 ! N N*N N 01125 01126 INTEGER, INTENT(IN) :: n 01127 DOUBLE PRECISION, INTENT(IN) :: v(*) 01128 DOUBLE PRECISION, INTENT(IN) :: a(*) 01129 DOUBLE PRECISION, INTENT(OUT) :: b(*) 01130 01131 DOUBLE PRECISION:: dsum 01132 ijs=1 01133 DO i=1,n 01134 dsum=0.0 01135 ij=ijs 01136 DO j=1,n 01137 dsum=dsum+v(ij)*a(j) 01138 IF(j < i) THEN 01139 ij=ij+1 01140 ELSE 01141 ij=ij+j 01142 END IF 01143 END DO 01144 b(i)=dsum 01145 ijs=ijs+i 01146 END DO 01147 END SUBROUTINE dbsvx 01148 01157 01158 SUBROUTINE dbsvxl(v,a,b,n) ! LARGE symm. matrix, vector 01159 IMPLICIT NONE 01160 INTEGER:: i 01161 INTEGER:: j 01162 01163 ! B := V * A 01164 ! N N*N N 01165 01166 INTEGER, INTENT(IN) :: n 01167 DOUBLE PRECISION, INTENT(IN) :: v(*) 01168 DOUBLE PRECISION, INTENT(IN) :: a(*) 01169 DOUBLE PRECISION, INTENT(OUT) :: b(*) 01170 01171 DOUBLE PRECISION:: dsum 01172 INTEGER*8 :: ij 01173 INTEGER*8 :: ijs 01174 ijs=1 01175 DO i=1,n 01176 dsum=0.0 01177 ij=ijs 01178 DO j=1,n 01179 dsum=dsum+v(ij)*a(j) 01180 IF(j < i) THEN 01181 ij=ij+1 01182 ELSE 01183 ij=ij+int8(j) 01184 END IF 01185 END DO 01186 b(i)=dsum 01187 ijs=ijs+int8(i) 01188 END DO 01189 END SUBROUTINE dbsvxl 01190 01198 01199 SUBROUTINE dbgax(a,x,y,m,n) 01200 IMPLICIT NONE 01201 INTEGER :: i 01202 INTEGER :: ij 01203 INTEGER :: j 01204 01205 DOUBLE PRECISION, INTENT(IN) :: a(*) 01206 DOUBLE PRECISION, INTENT(IN) :: x(*) 01207 DOUBLE PRECISION, INTENT(OUT) :: y(*) 01208 INTEGER, INTENT(IN) :: m 01209 INTEGER, INTENT(IN) :: n 01210 01211 ! ... 01212 ij=0 01213 DO i=1,m 01214 y(i)=0.0D0 01215 DO j=1,n 01216 ij=ij+1 01217 y(i)=y(i)+a(ij)*x(j) 01218 END DO 01219 END DO 01220 END SUBROUTINE dbgax 01221 01234 SUBROUTINE dbavat(v,a,w,n,ms) 01235 IMPLICIT NONE 01236 INTEGER :: i 01237 INTEGER :: ij 01238 INTEGER :: ijs 01239 INTEGER :: il 01240 INTEGER :: j 01241 INTEGER :: jk 01242 INTEGER :: k 01243 INTEGER :: l 01244 INTEGER :: lk 01245 INTEGER :: lkl 01246 INTEGER :: m 01247 01248 DOUBLE PRECISION, INTENT(IN) :: v(*) 01249 DOUBLE PRECISION, INTENT(IN) :: a(*) 01250 DOUBLE PRECISION, INTENT(INOUT) :: w(*) 01251 INTEGER, INTENT(IN) :: n 01252 INTEGER, INTENT(IN) :: ms 01253 01254 DOUBLE PRECISION :: cik 01255 ! ... 01256 m=ms 01257 IF (m > 0) THEN 01258 DO i=1,(m*m+m)/2 01259 w(i)=0.0D0 ! reset output matrix 01260 END DO 01261 ELSE 01262 m=-m 01263 END IF 01264 01265 il=-n 01266 ijs=0 01267 DO i=1,m ! do I 01268 ijs=ijs+i-1 ! 01269 il=il+n ! 01270 lkl=0 ! 01271 DO k=1,n ! do K 01272 cik=0.0D0 ! 01273 lkl=lkl+k-1 ! 01274 lk=lkl ! 01275 DO l=1,k ! do L 01276 lk=lk+1 ! . 01277 cik=cik+a(il+l)*v(lk) ! . 01278 END DO ! end do L 01279 DO l=k+1,n ! do L 01280 lk=lk+l-1 ! . 01281 cik=cik+a(il+l)*v(lk) ! . 01282 END DO ! end do L 01283 jk=k ! 01284 ij=ijs ! 01285 DO j=1,i ! do J 01286 ij=ij+1 ! . 01287 w(ij)=w(ij)+cik*a(jk) ! . 01288 jk=jk+n ! . 01289 END DO ! end do J 01290 END DO ! end do K 01291 END DO ! end do I 01292 END SUBROUTINE dbavat 01293 01303 01304 SUBROUTINE dbmprv(lun,x,v,n) 01305 IMPLICIT NONE 01306 INTEGER :: i 01307 INTEGER :: ii 01308 INTEGER :: ij 01309 INTEGER :: j 01310 INTEGER :: jj 01311 INTEGER :: l 01312 INTEGER :: m 01313 INTEGER :: mc(15) 01314 REAL :: pd 01315 REAL :: rho 01316 REAL :: err 01317 01318 INTEGER, INTENT(IN) :: lun 01319 DOUBLE PRECISION, INTENT(IN) :: x(*) 01320 DOUBLE PRECISION, INTENT(IN) :: v(*) 01321 INTEGER, INTENT(IN) :: n 01322 01323 WRITE(lun,103) 01324 WRITE(lun,101) 01325 ii=0 01326 DO i=1,n 01327 ij=ii 01328 ii=ii+i 01329 ERR=0.0 01330 IF(v(ii) > 0.0) ERR=SQRT(REAL(v(ii))) 01331 l=0 01332 jj=0 01333 DO j=1,i 01334 jj=jj+j 01335 ij=ij+1 01336 rho=0.0 01337 pd=REAL(v(ii)*v(jj)) 01338 IF(pd > 0.0) rho=REAL(v(ij))/SQRT(pd) 01339 l=l+1 01340 mc(l)=INT(100.0*ABS(rho)+0.5) 01341 IF(rho < 0.0) mc(l)=-mc(l) 01342 IF(j == i.OR.l == 15) THEN 01343 IF(j <= 15) THEN 01344 IF(j == i) THEN 01345 WRITE(lun,102) i,x(i),ERR,(mc(m),m=1,l-1) 01346 ELSE 01347 WRITE(lun,102) i,x(i),ERR,(mc(m),m=1,l) 01348 END IF 01349 ELSE 01350 IF(j == i) THEN 01351 WRITE(lun,103) (mc(m),m=1,l-1) 01352 ELSE 01353 WRITE(lun,103) (mc(m),m=1,l) 01354 END IF 01355 l=0 01356 END IF 01357 END IF 01358 END DO 01359 END DO 01360 WRITE(lun,104) 01361 ! 100 RETURN 01362 RETURN 01363 101 FORMAT(9X,'Param',7X,'error',7X,'correlation coefficients'/) 01364 102 FORMAT(1X,i5,2G12.4,1X,15I5) 01365 103 FORMAT(31X,15I5) 01366 104 FORMAT(33X,'(correlation coefficients in percent)') 01367 END SUBROUTINE dbmprv 01368 01376 01377 SUBROUTINE dbprv(lun,v,n) 01378 IMPLICIT NONE 01379 INTEGER, PARAMETER :: istp=6 01380 INTEGER :: i 01381 INTEGER :: ip 01382 INTEGER :: ipe 01383 INTEGER :: ipn 01384 INTEGER :: ips 01385 INTEGER :: k 01386 01387 INTEGER, INTENT(IN) :: lun 01388 DOUBLE PRECISION, INTENT(IN) :: v(*) 01389 INTEGER, INTENT(IN) :: n 01390 01391 WRITE(lun,101) 01392 01393 DO i=1,n 01394 ips=(i*i-i)/2 01395 ipe=ips+i 01396 ip =ips 01397 100 CONTINUE 01398 ipn=ip+istp 01399 WRITE(lun,102), i, ip+1-ips, (v(k),k=ip+1,MIN(ipn,ipe)) 01400 IF (ipn < ipe) THEN 01401 ip=ipn 01402 GO TO 100 01403 END IF 01404 END DO 01405 RETURN 01406 101 FORMAT(1X,'--- DBPRV -----------------------------------') 01407 102 FORMAT(1X,2I3,6G12.4) 01408 END SUBROUTINE dbprv 01409 01410 ! sort ------------------------------------------------------------- 01411 01418 01419 SUBROUTINE heapf(a,n) 01420 IMPLICIT NONE 01421 ! 01422 INTEGER :: i 01423 INTEGER :: j 01424 INTEGER :: l 01425 INTEGER :: r 01426 REAL :: at ! pivot key value 01427 01428 REAL, INTENT(IN OUT) :: a(*) 01429 INTEGER, INTENT(IN) :: n 01430 ! ... 01431 IF(n <= 1) RETURN 01432 l=n/2+1 01433 r=n 01434 10 IF(l > 1) THEN 01435 l=l-1 01436 at =a(l) 01437 ELSE 01438 at =a(r) 01439 a(r)=a(1) 01440 r=r-1 01441 IF(r == 1) THEN 01442 a(1)=at 01443 RETURN 01444 END IF 01445 END IF 01446 i=l 01447 j=l+l 01448 20 IF(j <= r) THEN 01449 IF(j < r) THEN 01450 IF(a(j) < a(j+1)) j=j+1 01451 END IF 01452 IF(at < a(j)) THEN 01453 a(i)=a(j) 01454 i=j 01455 j=j+j 01456 ELSE 01457 j=r+1 01458 END IF 01459 GO TO 20 01460 END IF 01461 a(i)=at 01462 GO TO 10 01463 END SUBROUTINE heapf 01464 01471 01472 SUBROUTINE sort1k(a,n) 01473 IMPLICIT NONE 01474 INTEGER :: nlev ! stack size 01475 PARAMETER (nlev=2*32) ! ... for N = 2**32 = 4.3 10**9 01476 INTEGER :: i 01477 INTEGER :: j 01478 INTEGER :: l 01479 INTEGER :: r 01480 INTEGER :: lev 01481 INTEGER :: lr(nlev) 01482 INTEGER :: lrh 01483 INTEGER :: maxlev 01484 INTEGER :: a1 ! pivot key 01485 INTEGER :: at ! pivot key 01486 01487 INTEGER, INTENT(IN OUT) :: a(*) 01488 INTEGER, INTENT(IN) :: n 01489 ! ... 01490 IF (n <= 0) RETURN 01491 maxlev=0 01492 lev=0 01493 l=1 01494 r=n 01495 10 IF(r-l == 1) THEN ! sort two elements L and R 01496 IF(a(l) > a(r)) THEN 01497 at=a(l) ! exchange L <-> R 01498 a(l)=a(r) 01499 a(r)=at 01500 END IF 01501 r=l 01502 END IF 01503 IF(r == l) THEN 01504 IF(lev <= 0) THEN 01505 ! WRITE(*,*) 'SORT1K (quicksort): maxlevel used/available =', 01506 ! + MAXLEV,'/64' 01507 RETURN 01508 END IF 01509 lev=lev-2 01510 l=lr(lev+1) 01511 r=lr(lev+2) 01512 ELSE 01513 ! LRH=(L+R)/2 01514 lrh=(l/2)+(r/2) ! avoid bit overflow 01515 IF(MOD(l,2) == 1.AND.MOD(r,2) == 1) lrh=lrh+1 01516 a1=a(lrh) ! middle 01517 i=l-1 ! find limits [J,I] with [L,R] 01518 j=r+1 01519 20 i=i+1 01520 IF(a(i) < a1) GO TO 20 01521 30 j=j-1 01522 IF(a(j) > a1) GO TO 30 01523 IF(i <= j) THEN 01524 at=a(i) ! exchange I <-> J 01525 a(i)=a(j) 01526 a(j)=at 01527 GO TO 20 01528 END IF 01529 IF(lev+2 > nlev) STOP 'SORT1K (quicksort): stack overflow' 01530 IF(r-i < j-l) THEN 01531 lr(lev+1)=l 01532 lr(lev+2)=j 01533 l=i 01534 ELSE 01535 lr(lev+1)=i 01536 lr(lev+2)=r 01537 r=j 01538 END IF 01539 lev=lev+2 01540 maxlev=MAX(maxlev,lev) 01541 END IF 01542 GO TO 10 01543 END SUBROUTINE sort1k 01544 01551 01552 SUBROUTINE sort2k(a,n) 01553 IMPLICIT NONE 01554 INTEGER:: nlev ! stack size 01555 PARAMETER (nlev=2*32) ! ... for N = 2**32 = 4.3 10**9 01556 INTEGER:: i 01557 INTEGER::j 01558 INTEGER::l 01559 INTEGER::r 01560 INTEGER::lev 01561 INTEGER::lr(nlev) 01562 INTEGER::lrh 01563 INTEGER::maxlev 01564 INTEGER::a1 ! pivot key 01565 INTEGER::a2 ! pivot key 01566 INTEGER::at ! pivot key 01567 01568 INTEGER, INTENT(IN OUT) :: a(2,*) 01569 INTEGER, INTENT(IN) :: n 01570 ! ... 01571 maxlev=0 01572 lev=0 01573 l=1 01574 r=n 01575 10 IF(r-l == 1) THEN ! sort two elements L and R 01576 IF(a(1,l) > a(1,r).OR.( a(1,l) == a(1,r).AND.a(2,l) > a(2,r))) THEN 01577 at=a(1,l) ! exchange L <-> R 01578 a(1,l)=a(1,r) 01579 a(1,r)=at 01580 at=a(2,l) 01581 a(2,l)=a(2,r) 01582 a(2,r)=at 01583 END IF 01584 r=l 01585 END IF 01586 IF(r == l) THEN 01587 IF(lev <= 0) THEN 01588 WRITE(*,*) 'SORT2K (quicksort): maxlevel used/available =', maxlev,'/64' 01589 RETURN 01590 END IF 01591 lev=lev-2 01592 l=lr(lev+1) 01593 r=lr(lev+2) 01594 ELSE 01595 ! LRH=(L+R)/2 01596 lrh=(l/2)+(r/2) ! avoid bit overflow 01597 IF(MOD(l,2) == 1.AND.MOD(r,2) == 1) lrh=lrh+1 01598 a1=a(1,lrh) ! middle 01599 a2=a(2,lrh) 01600 i=l-1 ! find limits [J,I] with [L,R] 01601 j=r+1 01602 20 i=i+1 01603 IF(a(1,i) < a1) GO TO 20 01604 IF(a(1,i) == a1.AND.a(2,i) < a2) GO TO 20 01605 30 j=j-1 01606 IF(a(1,j) > a1) GO TO 30 01607 IF(a(1,j) == a1.AND.a(2,j) > a2) GO TO 30 01608 IF(i <= j) THEN 01609 at=a(1,i) ! exchange I <-> J 01610 a(1,i)=a(1,j) 01611 a(1,j)=at 01612 at=a(2,i) 01613 a(2,i)=a(2,j) 01614 a(2,j)=at 01615 GO TO 20 01616 END IF 01617 IF(lev+2 > nlev) STOP 'SORT2K (quicksort): stack overflow' 01618 IF(r-i < j-l) THEN 01619 lr(lev+1)=l 01620 lr(lev+2)=j 01621 l=i 01622 ELSE 01623 lr(lev+1)=i 01624 lr(lev+2)=r 01625 r=j 01626 END IF 01627 lev=lev+2 01628 maxlev=MAX(maxlev,lev) 01629 END IF 01630 GO TO 10 01631 END SUBROUTINE sort2k 01632 01640 01641 REAL FUNCTION chindl(n,nd) 01642 IMPLICIT NONE 01643 INTEGER :: m 01644 INTEGER, INTENT(IN) :: n 01645 INTEGER, INTENT(IN) :: nd 01646 ! 01647 REAL:: sn(3) 01648 REAL::table(30,3) 01649 ! REAL PN(3) 01650 ! DATA PN/0.31731,0.0455002785,2.69985E-3/ ! probabilities 01651 DATA sn/0.47523,1.690140,2.782170/ 01652 DATA table/ 1.0000, 1.1479, 1.1753, 1.1798, 1.1775, 1.1730, 1.1680, 1.1630, & 01653 1.1581, 1.1536, 1.1493, 1.1454, 1.1417, 1.1383, 1.1351, 1.1321, & 01654 1.1293, 1.1266, 1.1242, 1.1218, 1.1196, 1.1175, 1.1155, 1.1136, & 01655 1.1119, 1.1101, 1.1085, 1.1070, 1.1055, 1.1040, & 01656 4.0000, 3.0900, 2.6750, 2.4290, 2.2628, 2.1415, 2.0481, 1.9736, & 01657 1.9124, 1.8610, 1.8171, 1.7791, 1.7457, 1.7161, 1.6897, 1.6658, & 01658 1.6442, 1.6246, 1.6065, 1.5899, 1.5745, 1.5603, 1.5470, 1.5346, & 01659 1.5230, 1.5120, 1.5017, 1.4920, 1.4829, 1.4742, & 01660 9.0000, 5.9146, 4.7184, 4.0628, 3.6410, 3.3436, 3.1209, 2.9468, & 01661 2.8063, 2.6902, 2.5922, 2.5082, 2.4352, 2.3711, 2.3143, 2.2635, & 01662 2.2178, 2.1764, 2.1386, 2.1040, 2.0722, 2.0428, 2.0155, 1.9901, & 01663 1.9665, 1.9443, 1.9235, 1.9040, 1.8855, 1.8681/ 01664 SAVE sn,table 01665 ! ... 01666 IF(nd < 1) THEN 01667 chindl=0.0 01668 ELSE 01669 m=MAX(1,MIN(n,3)) ! 1, 2 or 3 sigmas 01670 IF(nd <= 30) THEN 01671 chindl=table(nd,m) ! from table 01672 ELSE ! approximation for ND > 30 01673 chindl=(sn(m)+SQRT(FLOAT(nd+nd-1)))**2/FLOAT(nd+nd) 01674 END IF 01675 END IF 01676 END FUNCTION chindl 01677 01711 01712 SUBROUTINE lltdec(n,c,india,nrkd) 01713 IMPLICIT NONE 01714 INTEGER :: i 01715 INTEGER :: j 01716 INTEGER :: k 01717 INTEGER :: kj 01718 INTEGER :: mj 01719 INTEGER :: mk 01720 DOUBLE PRECISION::diag 01721 01722 INTEGER, INTENT(IN) :: n 01723 DOUBLE PRECISION, INTENT(IN OUT) :: c(*) 01724 INTEGER, INTENT(IN) :: india(n) 01725 INTEGER, INTENT(OUT) :: nrkd 01726 01727 ! ... 01728 nrkd=0 01729 diag=0.0D0 01730 IF(c(india(1)) > 0.0) THEN 01731 c(india(1))=1.0D0/SQRT(c(india(1))) ! square root 01732 ELSE 01733 c(india(1))=0.0D0 01734 nrkd=-1 01735 END IF 01736 01737 DO k=2,n 01738 mk=k-india(k)+india(k-1)+1 ! first index in row K 01739 DO j=mk,k ! loop over row K with index J 01740 mj=1 01741 IF(j > 1) mj=j-india(j)+india(j-1)+1 ! first index in row J 01742 kj=india(k)-k+j ! index kj 01743 diag=c(india(j)) ! j-th diagonal element 01744 01745 DO i=MAX(mj,mk),j-1 01746 ! L_kj = L_kj - L_ki *D_ii *L_ji 01747 c(kj)=c(kj) - c(india(k)-k+i)*c(india(j)-j+i) 01748 END DO ! I 01749 01750 IF(j /= k) c(kj)=c(kj)*diag 01751 END DO ! J 01752 01753 IF(diag+c(india(k)) > diag) THEN ! test for linear dependence 01754 c(india(k))=1.0D0/SQRT(c(india(k))) ! square root 01755 ELSE 01756 DO j=mk,k ! reset row K 01757 c(india(k)-k+j)=0.0D0 01758 END DO ! J 01759 IF(nrkd == 0) THEN 01760 nrkd=-k 01761 ELSE 01762 IF(nrkd < 0) nrkd=1 01763 nrkd=nrkd+1 01764 END IF 01765 END IF 01766 01767 END DO ! K 01768 RETURN 01769 END SUBROUTINE lltdec 01770 01771 01783 01784 SUBROUTINE lltfwd(n,c,india,x) 01785 IMPLICIT NONE 01786 INTEGER :: j 01787 INTEGER :: k 01788 01789 INTEGER, INTENT(IN) :: n 01790 DOUBLE PRECISION, INTENT(IN) :: c(*) 01791 INTEGER, INTENT(IN) :: india(n) 01792 DOUBLE PRECISION, INTENT(IN OUT) :: x(n) 01793 01794 x(1)=x(1)*c(india(1)) 01795 DO k=2,n ! forward loop 01796 DO j=k-india(k)+india(k-1)+1,k-1 01797 x(k)=x(k)-c(india(k)-k+j)*x(j) ! X_k := X_k - L_kj * B_j 01798 END DO ! J 01799 x(k)=x(k)*c(india(k)) 01800 END DO ! K 01801 RETURN 01802 END SUBROUTINE lltfwd 01803 01815 01816 SUBROUTINE lltbwd(n,c,india,x) 01817 IMPLICIT NONE 01818 INTEGER :: j 01819 INTEGER :: k 01820 01821 INTEGER, INTENT(IN) :: n 01822 DOUBLE PRECISION, INTENT(IN) :: c(*) 01823 INTEGER, INTENT(IN) :: india(n) 01824 DOUBLE PRECISION, INTENT(IN OUT) :: x(n) 01825 01826 DO k=n,2,-1 ! backward loop 01827 x(k)=x(k)*c(india(k)) 01828 DO j=k-india(k)+india(k-1)+1,k-1 01829 x(j)=x(j)-c(india(k)-k+j)*x(k) ! X_j := X_j - L_kj * X_k 01830 END DO ! J 01831 END DO ! K 01832 x(1)=x(1)*c(india(1)) 01833 END SUBROUTINE lltbwd 01834 01851 SUBROUTINE equdec(n,m,c,india,nrkd,nrkd2) 01852 IMPLICIT NONE 01853 REAL:: eps 01854 INTEGER:: i 01855 INTEGER:: j 01856 INTEGER:: jk 01857 INTEGER:: k 01858 INTEGER:: ntotal 01859 01860 INTEGER, INTENT(IN) :: n 01861 INTEGER, INTENT(IN) :: m 01862 DOUBLE PRECISION, INTENT(IN OUT) :: c(*) 01863 INTEGER, INTENT(IN OUT) :: india(n+m) 01864 INTEGER, INTENT(OUT) :: nrkd 01865 INTEGER, INTENT(OUT) :: nrkd2 01866 01867 01868 PARAMETER (eps=2.22044605E-16) 01869 ! ... 01870 ntotal=n+n*m+(m*m+m)/2 01871 01872 CALL lltdec(n,c,india,nrkd) ! decomposition G G^T 01873 DO i=1,m 01874 CALL lltfwd(n,c,india,c(india(n)+(i-1)*n+1)) ! forward solution K 01875 END DO 01876 01877 jk=india(n)+n*m 01878 DO j=1,m 01879 DO k=1,j 01880 jk=jk+1 01881 c(jk)=0.0D0 ! product K K^T 01882 DO i=1,n 01883 c(jk)=c(jk)+c(india(n)+(j-1)*n+i)*c(india(n)+(k-1)*n+i) 01884 END DO 01885 END DO 01886 END DO 01887 01888 india(n+1)=1 01889 DO i=2,m 01890 india(n+i)=india(n+i-1)+MIN(i,m) ! pointer for K K^T 01891 END DO 01892 01893 CALL lltdec(m,c(india(n)+n*m+1),india(n+1),nrkd2) ! decomp. H H^T 01894 01895 ntotal=n+n*m+(m*m+m)/2 01896 01897 RETURN 01898 END SUBROUTINE equdec 01899 01915 SUBROUTINE equslv(n,m,c,india,x) ! solution vector 01916 IMPLICIT NONE 01917 INTEGER :: i 01918 INTEGER :: j 01919 01920 INTEGER, INTENT(IN) :: n 01921 INTEGER, INTENT(IN) :: m 01922 DOUBLE PRECISION, INTENT(IN) :: c(*) 01923 INTEGER, INTENT(IN) :: india(n+m) 01924 DOUBLE PRECISION, INTENT(IN OUT) :: x(n+m) 01925 01926 CALL lltfwd(n,c,india,x) ! result is u 01927 DO i=1,m 01928 DO j=1,n 01929 x(n+i)=x(n+i)-x(j)*c(india(n)+(i-1)*n+j) ! g - K u 01930 END DO 01931 END DO 01932 CALL lltfwd(m,c(india(n)+n*m+1),india(n+1),x(n+1)) ! result is v 01933 01934 01935 CALL lltbwd(m,c(india(n)+n*m+1),india(n+1),x(n+1)) ! result is -y 01936 DO i=1,m 01937 x(n+i)=-x(n+i) ! result is +y 01938 END DO 01939 01940 DO i=1,n 01941 DO j=1,m 01942 x(i)=x(i)-x(n+j)*c(india(n)+(j-1)*n+i) ! u - K^T y 01943 END DO 01944 END DO 01945 CALL lltbwd(n,c,india,x) ! result is x 01946 END SUBROUTINE equslv 01947 01976 01977 SUBROUTINE precon(p,n,c,cu,a,s) 01978 IMPLICIT NONE 01979 INTEGER :: i 01980 INTEGER :: ii 01981 INTEGER :: j 01982 INTEGER :: jj 01983 INTEGER :: jk 01984 INTEGER :: k 01985 INTEGER :: kk 01986 01987 INTEGER, INTENT(IN) :: p 01988 INTEGER, INTENT(IN) :: n 01989 DOUBLE PRECISION, INTENT(IN) :: c(n) 01990 DOUBLE PRECISION, INTENT(OUT) :: cu(n) 01991 DOUBLE PRECISION, INTENT(IN OUT) :: a(n,p) 01992 DOUBLE PRECISION, INTENT(OUT) :: s((p*p+p)/2) 01993 01994 DOUBLE PRECISION :: div 01995 DOUBLE PRECISION :: ratio 01996 01997 DO i=1,(p*p+p)/2 01998 s(i)=0.0D0 01999 END DO 02000 DO i=1,n 02001 jk=0 02002 div=c(i) ! copy 02003 IF (div > 0.0D0) THEN 02004 cu(i)=1.0D0/DSQRT(div) 02005 ELSE 02006 cu(i)=0.0D0 02007 END IF 02008 DO j=1,p 02009 a(i,j)=a(i,j)*cu(i) ! K = A C^{-1/2} 02010 DO k=1,j 02011 jk=jk+1 02012 s(jk)=s(jk)+a(i,j)*a(i,k) ! S = symmetric matrix K K^T 02013 END DO 02014 END DO 02015 END DO 02016 02017 ii=0 02018 DO i=1,p ! S -> H D H^T (Cholesky) 02019 ii=ii+i 02020 IF(s(ii) /= 0.0D0) s(ii)=1.0D0/s(ii) 02021 jj=ii 02022 DO j=i+1,p 02023 ratio=s(i+jj)*s(ii) 02024 kk=jj 02025 DO k=j,p 02026 s(kk+j)=s(kk+j)-s(kk+i)*ratio 02027 kk=kk+k 02028 END DO ! K 02029 s(i+jj)=ratio 02030 jj=jj+j 02031 END DO ! J 02032 END DO ! I 02033 RETURN 02034 END SUBROUTINE precon 02035 02045 02046 SUBROUTINE presol(p,n,cu,a,s,x,y) ! solution 02047 IMPLICIT NONE 02048 INTEGER :: i 02049 INTEGER :: j 02050 INTEGER :: jj 02051 INTEGER :: k 02052 INTEGER :: kk 02053 02054 INTEGER, INTENT(IN) :: p 02055 INTEGER, INTENT(IN) :: n 02056 02057 DOUBLE PRECISION, INTENT(IN) :: cu(n) 02058 DOUBLE PRECISION, INTENT(IN) :: a(n,p) 02059 DOUBLE PRECISION, INTENT(IN) :: s((p*p+p)/2) 02060 DOUBLE PRECISION, INTENT(OUT) :: x(n+p) 02061 DOUBLE PRECISION, INTENT(IN) :: y(n+p) 02062 02063 DOUBLE PRECISION :: dsum 02064 02065 DO i=1,n+p 02066 x(i)=y(i) 02067 END DO 02068 DO i=1,n 02069 x(i)=x(i)*cu(i) ! u =C^{-1/2} y 02070 DO j=1,p 02071 x(n+j)=x(n+j)-a(i,j)*x(i) ! d - K u 02072 END DO 02073 END DO 02074 02075 jj=0 02076 DO j=1,p ! Cholesky solution for v 02077 dsum=x(n+j) 02078 DO k=1,j-1 02079 dsum=dsum-s(k+jj)*x(n+k) ! H v = d - K u 02080 END DO 02081 x(n+j)=dsum ! -> v 02082 jj=jj+j 02083 END DO 02084 02085 DO j=p,1,-1 ! solution for lambda 02086 dsum=x(n+j)*s(jj) 02087 kk=jj 02088 DO k=j+1,p 02089 dsum=dsum+s(kk+j)*x(n+k) ! D H^T lambda = -v 02090 kk=kk+k 02091 END DO 02092 x(n+j)=-dsum ! -> lambda 02093 jj=jj-j 02094 END DO 02095 02096 DO i=1,n ! u - K^T lambda 02097 DO j=1,p 02098 x(i)=x(i)-a(i,j)*x(n+j) 02099 END DO 02100 END DO 02101 DO i=1,n 02102 x(i)=x(i)*cu(i) ! x = C^{-1/2} u 02103 END DO 02104 02105 END SUBROUTINE presol 02106 02107 02108 ! 090817 C. Kleinwort, DESY-FH1 02153 SUBROUTINE sqmibb(v,b,n,nbdr,nbnd,inv,nrank,vbnd,vbdr,aux,vbk,vzru,scdiag,scflag) 02154 ! Double precision scratch arrays: 02155 ! VBND(N*(NBND+1)) = storage of band part 02156 ! VBDR(N* NBDR) = storage of border part 02157 ! AUX (N* NBDR) = intermediate results 02158 02159 ! cost[dot ops] ~= (N-NBDR)*(NBDR+NBND+1)**2 + NBDR**3/3 (leading term, solution only) 02160 02161 IMPLICIT NONE 02162 INTEGER:: i 02163 INTEGER:: ib 02164 INTEGER:: ij 02165 INTEGER:: ioff 02166 INTEGER:: ip 02167 INTEGER:: ip1 02168 INTEGER:: ip2 02169 INTEGER:: is 02170 INTEGER:: j 02171 INTEGER:: j0 02172 INTEGER:: jb 02173 INTEGER:: joff 02174 INTEGER:: mp1 02175 INTEGER:: nb1 02176 INTEGER:: nmb 02177 INTEGER:: npri 02178 INTEGER:: nrankb 02179 02180 DOUBLE PRECISION, INTENT(IN OUT) :: v(*) 02181 DOUBLE PRECISION, INTENT(OUT) :: b(n) 02182 INTEGER, INTENT(IN) :: n 02183 INTEGER, INTENT(IN) :: nbdr 02184 INTEGER, INTENT(IN) :: nbnd 02185 INTEGER, INTENT(IN) :: inv 02186 INTEGER, INTENT(OUT) :: nrank 02187 02188 DOUBLE PRECISION, INTENT(OUT) :: vbnd(n*(nbnd+1)) 02189 DOUBLE PRECISION, INTENT(OUT) :: vbdr(n*nbdr) 02190 DOUBLE PRECISION, INTENT(OUT) :: aux(n*nbdr) 02191 DOUBLE PRECISION, INTENT(OUT) :: vbk((nbdr*nbdr+nbdr)/2) 02192 DOUBLE PRECISION, INTENT(OUT) :: vzru(nbdr) 02193 DOUBLE PRECISION, INTENT(OUT) :: scdiag(nbdr) 02194 INTEGER, INTENT(OUT) :: scflag(nbdr) 02195 02196 SAVE npri 02197 DATA npri / 100 / 02198 ! ... 02199 nrank=0 02200 nb1=nbdr+1 02201 mp1=nbnd+1 02202 nmb=n-nbdr 02203 ! copy band part 02204 DO i=nb1,n 02205 ip=(i*(i+1))/2 02206 is=0 02207 DO j=i,MIN(n,i+nbnd) 02208 ip=ip+is 02209 is=j 02210 ib=j-i+1 02211 vbnd(ib+(i-nb1)*mp1)=v(ip) 02212 END DO 02213 END DO 02214 ! copy border part 02215 IF (nbdr > 0) THEN 02216 ioff=0 02217 DO i=1,nbdr 02218 ip=(i*(i+1))/2 02219 is=0 02220 DO j=i,n 02221 ip=ip+is 02222 is=j 02223 vbdr(ioff+j)=v(ip) 02224 END DO 02225 ioff=ioff+n 02226 END DO 02227 END IF 02228 02229 CALL dbcdec(vbnd,mp1,nmb,aux) 02230 ! use? CALL DBFDEC(VBND,MP1,NMB) ! modified decomp., numerically more stable 02231 ! CALL DBCPRB(VBND,MP1,NMB) 02232 ip=1 02233 DO i=1, nmb 02234 IF (vbnd(ip) <= 0.0D0) THEN 02235 npri=npri-1 02236 IF (npri >= 0) THEN 02237 IF (vbnd(ip) == 0.0D0) THEN 02238 PRINT *, ' SQMIBB matrix singular', n, nbdr, nbnd 02239 ELSE 02240 PRINT *, ' SQMIBB matrix not positive definite', n, nbdr, nbnd 02241 END IF 02242 END IF 02243 ! return zeros 02244 DO ip=1,n 02245 b(ip)=0.0D0 02246 END DO 02247 DO ip=1,(n*n+n)/2 02248 v(ip)=0.0D0 02249 END DO 02250 RETURN 02251 END IF 02252 ip=ip+mp1 02253 END DO 02254 nrank=nmb 02255 02256 IF (nbdr == 0) THEN ! special case NBDR=0 02257 02258 CALL dbcslv(vbnd,mp1,nmb,b,b) 02259 IF (inv > 0) THEN 02260 IF (inv > 1) THEN 02261 CALL dbcinv(vbnd,mp1,nmb,v) 02262 ELSE 02263 CALL dbcinb(vbnd,mp1,nmb,v) 02264 END IF 02265 END IF 02266 02267 ELSE ! general case NBDR>0 02268 02269 ioff=nb1 02270 DO ib=1,nbdr 02271 ! solve for aux. vectors 02272 CALL dbcslv(vbnd,mp1,nmb,vbdr(ioff),aux(ioff)) 02273 ! zT ru 02274 vzru(ib)=b(ib) 02275 DO i=0,nmb-1 02276 vzru(ib)=vzru(ib)-b(nb1+i)*aux(ioff+i) 02277 END DO 02278 ioff=ioff+n 02279 END DO 02280 ! solve for band part only 02281 CALL dbcslv(vbnd,mp1,nmb,b(nb1),b(nb1)) 02282 ! Ck - cT z 02283 ip=0 02284 ioff=nb1 02285 DO ib=1,nbdr 02286 joff=nb1 02287 DO jb=1,ib 02288 ip=ip+1 02289 vbk(ip)=v(ip) 02290 DO i=0,nmb-1 02291 vbk(ip)=vbk(ip)-vbdr(ioff+i)*aux(joff+i) 02292 END DO 02293 joff=joff+n 02294 END DO 02295 ioff=ioff+n 02296 END DO 02297 ! solve border part 02298 CALL sqminv(vbk,vzru,nbdr,nrankb,scdiag,scflag) 02299 IF (nrankb == nbdr) THEN 02300 nrank=nrank+nbdr 02301 ELSE 02302 npri=npri-1 02303 IF (npri >= 0) PRINT *, ' SQMIBB undef border ', n, nbdr, nbnd, nrankb 02304 DO ib=1,nbdr 02305 vzru(ib)=0.0D0 02306 END DO 02307 DO ip=(nbdr*nbdr+nbdr)/2,1,-1 02308 vbk(ip)=0.0D0 02309 END DO 02310 END IF 02311 ! smoothed data points 02312 ioff=nb1 02313 DO ib=1, nbdr 02314 b(ib) = vzru(ib) 02315 DO i=0,nmb-1 02316 b(nb1+i)=b(nb1+i)-b(ib)*aux(ioff+i) 02317 END DO 02318 ioff=ioff+n 02319 END DO 02320 ! inverse requested ? 02321 IF (inv > 0) THEN 02322 IF (inv > 1) THEN 02323 CALL dbcinv(vbnd,mp1,nmb,v) 02324 ELSE 02325 CALL dbcinb(vbnd,mp1,nmb,v) 02326 END IF 02327 ! expand/correct from NMB to N 02328 ip1=(nmb*nmb+nmb)/2 02329 ip2=(n*n+n)/2 02330 DO i=nmb-1,0,-1 02331 j0=0 02332 IF (inv == 1) j0=MAX(0,i-nbnd) 02333 DO j=i,j0,-1 02334 v(ip2)=v(ip1) 02335 ioff=nb1 02336 DO ib=1,nbdr 02337 joff=nb1 02338 DO jb=1,nbdr 02339 ij=MAX(ib,jb) 02340 ij=(ij*ij-ij)/2+MIN(ib,jb) 02341 v(ip2)=v(ip2)+vbk(ij)*aux(ioff+i)*aux(joff+j) 02342 joff=joff+n 02343 END DO 02344 ioff=ioff+n 02345 END DO 02346 ip1=ip1-1 02347 ip2=ip2-1 02348 END DO 02349 ip1=ip1-j0 02350 ip2=ip2-j0 02351 02352 DO ib=nbdr,1,-1 02353 v(ip2)=0.0D0 02354 joff=nb1 02355 DO jb=1,nbdr 02356 ij=MAX(ib,jb) 02357 ij=(ij*ij-ij)/2+MIN(ib,jb) 02358 v(ip2)=v(ip2)-vbk(ij)*aux(i+joff) 02359 joff=joff+n 02360 END DO 02361 ip2=ip2-1 02362 END DO 02363 END DO 02364 02365 DO ip=(nbdr*nbdr+nbdr)/2,1,-1 02366 v(ip2)=vbk(ip) 02367 ip2=ip2-1 02368 END DO 02369 02370 END IF 02371 END IF 02372 02373 END SUBROUTINE sqmibb