C C*********************************************************************** C SUBROUTINE DLABCM(N, NBAND, NL, NR, A, EIGVAL, 1 LDE, EIGVEC, ATOL, ARTOL, BOUND, ATEMP, D, VTEMP) C C THIS SUBROUTINE ORGANIZES THE CALCULATION OF THE EIGENVALUES C FOR THE BNDEIG PACKAGE. EIGENVALUES ARE COMPUTED BY C A MODIFIED RAYLEIGH QUOTIENT ITERATION. THE EIGENVALUE COUNT C OBTAINED BY EACH FACTORIZATION IS USED TO OCCASIONALLY OVERRIDE C THE COMPUTED RAYLEIGH QUOTIENT WITH A DIFFERENT SHIFT TO C INSURE CONVERGENCE TO THE DESIRED EIGENVALUES. C C FORMAL PARAMETERS. C INTEGER N, NBAND, NL, NR, LDE DOUBLE PRECISION A(NBAND,1), EIGVAL(1), 1 EIGVEC(LDE,1), ATOL, ARTOL, BOUND(2,1), ATEMP(1), 2 D(1), VTEMP(1) C C C LOCAL VARIABLES C LOGICAL FLAG INTEGER I, J, L, M, NUML, NUMVEC, NVAL DOUBLE PRECISION ERRB, GAP, RESID, RQ, SIGMA, VNORM C C C FUNCTIONS CALLED C INTEGER MIN0 DOUBLE PRECISION DMAX1, DMIN1, DDOT, DNRM2 C C SUBROUTINES CALLED C C DLABAX, DLABFC, DLARAN, DAXPY, DCOPY, DSCAL C C REPLACE ZERO VECTORS BY RANDOM C NVAL = NR - NL + 1 FLAG = .FALSE. DO 5 I = 1, NVAL IF(DDOT(N, EIGVEC(1,I), 1, EIGVEC(1,I), 1) .EQ. 0.0D0) 1 CALL DLARAN(N,EIGVEC(1,I)) 5 CONTINUE C C LOOP OVER EIGENVALUES C SIGMA = BOUND(2,NVAL+1) DO 400 J = 1, NVAL NUML = J C C PREPARE TO COMPUTE FIRST RAYLEIGH QUOTIENT C 10 CALL DLABAX(N, NBAND, A, EIGVEC(1,J), VTEMP) VNORM = DNRM2(N, VTEMP, 1) IF(VNORM .EQ. 0.0D0) GO TO 20 CALL DSCAL(N, 1.0D0/VNORM, VTEMP, 1) CALL DSCAL(N, 1.0D0/VNORM, EIGVEC(1,J), 1) CALL DAXPY(N, -SIGMA, EIGVEC(1,J), 1, VTEMP, 1) C C LOOP OVER SHIFTS C C COMPUTE RAYLEIGH QUOTIENT, RESIDUAL NORM, AND CURRENT TOLERANCE C 20 VNORM = DNRM2(N, EIGVEC(1,J), 1) IF(VNORM .NE. 0.0D0) GO TO 30 CALL DLARAN(N, EIGVEC(1,J)) GO TO 10 C 30 RQ = SIGMA + DDOT(N, EIGVEC(1,J), 1, VTEMP, 1) 1 /VNORM/VNORM CALL DAXPY(N, SIGMA-RQ, EIGVEC(1,J), 1, VTEMP, 1) RESID = DMAX1(ATOL, DNRM2(N, VTEMP, 1)/VNORM) CALL DSCAL(N, 1.0/VNORM, EIGVEC(1,J), 1) C C ACCEPT EIGENVALUE IF THE INTERVAL IS SMALL ENOUGH C IF(BOUND(2,J+1) - BOUND(1,J+1) .LT. 3.0D0*ATOL) GO TO 300 C C COMPUTE MINIMAL ERROR BOUND C ERRB = RESID GAP = DMIN1(BOUND(1,J+2) - RQ, RQ - BOUND(2,J)) IF(GAP .GT. RESID) ERRB = DMAX1(ATOL, RESID*RESID/GAP) C C TENTATIVE NEW SHIFT C SIGMA = 0.5D0*(BOUND(1,J+1) + BOUND(2,J+1)) C C CHECK FOR TERMINALTION C IF(RESID .GT. 2.0D0*ATOL) GO TO 40 IF(RQ - ERRB .GT. BOUND(2,J) .AND. 1 RQ + ERRB .LT. BOUND(1,J+2)) GO TO 310 C C RQ IS TO THE LEFT OF THE INTERVAL C 40 IF(RQ .GE. BOUND(1,J+1)) GO TO 50 IF(RQ - ERRB .GT. BOUND(2,J)) GO TO 100 IF(RQ + ERRB .LT. BOUND(1,J+1)) CALL DLARAN(N,EIGVEC(1,J)) GO TO 200 C C RQ IS TO THE RIGHT OF THE INTERVAL C 50 IF(RQ .LE. BOUND(2,J+1)) GO TO 100 IF(RQ + ERRB .LT. BOUND(1,J+2)) GO TO 100 C C SAVE THE REJECTED VECTOR IF INDICATED C IF(RQ - ERRB .LE. BOUND(2,J+1)) GO TO 200 DO 60 I = J, NVAL IF(BOUND(2,I+1) .GT. RQ) GO TO 70 60 CONTINUE GO TO 80 C 70 CALL DCOPY(N, EIGVEC(1,J), 1, EIGVEC(1,I), 1) C 80 CALL DLARAN(N, EIGVEC(1,J)) GO TO 200 C C PERTURB RQ TOWARD THE MIDDLE C 100 IF(SIGMA .LT. RQ) SIGMA = DMAX1(SIGMA, RQ-ERRB) IF(SIGMA .GT. RQ) SIGMA = DMIN1(SIGMA, RQ+ERRB) C C FACTOR AND SOLVE C 200 DO 210 I = J, NVAL IF(SIGMA .LT. BOUND(1,I+1)) GO TO 220 210 CONTINUE I = NVAL + 1 220 NUMVEC = I - J NUMVEC = MIN0(NUMVEC, NBAND + 2) IF(RESID .LT. ARTOL) NUMVEC = MIN0(1,NUMVEC) CALL DCOPY(N, EIGVEC(1,J), 1, VTEMP, 1) CALL DLABFC(N, NBAND, A, SIGMA, NUMVEC, LDE, 1 EIGVEC(1,J), NUML, 2*NBAND-1, ATEMP, D, ATOL) C C PARTIALLY SCALE EXTRA VECTORS TO PREVENT UNDERFLOW OR OVERFLOW C IF(NUMVEC .EQ. 1) GO TO 227 L = NUMVEC - 1 DO 225 I = 1,L M = J + I CALL DSCAL(N, 1.0D0/VNORM, EIGVEC(1,M), 1) 225 CONTINUE C C UPDATE INTERVALS C 227 NUML = NUML - NL + 1 IF(NUML .GE. 0) BOUND(2,1) = DMIN1(BOUND(2,1), SIGMA) DO 230 I = J, NVAL IF(SIGMA .LT. BOUND(1,I+1)) GO TO 20 IF(NUML .LT. I) BOUND(1,I+1) = SIGMA IF(NUML .GE. I) BOUND(2,I+1) = SIGMA 230 CONTINUE IF(NUML .LT. NVAL + 1) BOUND(1,NVAL+2) = DMAX1(SIGMA, 1 BOUND(1,NVAL+2)) GO TO 20 C C ACCEPT AN EIGENPAIR C 300 CALL DLARAN(N, EIGVEC(1,J)) FLAG = .TRUE. GO TO 310 C 305 FLAG = .FALSE. RQ = 0.5D0*(BOUND(1,J+1) + BOUND(2,J+1)) CALL DLABFC(N, NBAND, A, RQ, NUMVEC, LDE, 1 EIGVEC(1,J), NUML, 2*NBAND-1, ATEMP, D, ATOL) VNORM = DNRM2(N, EIGVEC(1,J), 1) IF(VNORM .NE. 0.0) CALL DSCAL(N, 1.0D0/VNORM, EIGVEC(1,J), 1) C C ORTHOGONALIZE THE NEW EIGENVECTOR AGAINST THE OLD ONES C 310 EIGVAL(J) = RQ IF(J .EQ. 1) GO TO 330 M = J - 1 DO 320 I = 1, M CALL DAXPY(N, -DDOT(N,EIGVEC(1,I),1,EIGVEC(1,J),1), 1 EIGVEC(1,I), 1, EIGVEC(1,J), 1) 320 CONTINUE 330 VNORM = DNRM2(N, EIGVEC(1,J), 1) IF(VNORM .EQ. 0.0D0) GO TO 305 CALL DSCAL(N, 1.0D0/VNORM, EIGVEC(1,J), 1) C C ORTHOGONALIZE LATER VECTORS AGAINST THE CONVERGED ONE C IF(FLAG) GO TO 305 IF(J .EQ. NVAL) RETURN M = J + 1 DO 340 I = M, NVAL CALL DAXPY(N, -DDOT(N,EIGVEC(1,J),1,EIGVEC(1,I),1), 1 EIGVEC(1,J), 1, EIGVEC(1,I), 1) 340 CONTINUE 400 CONTINUE RETURN C 500 CONTINUE END .