C CCC  CCCCCCCCCCCCCCCCCCCC
C W.Quapp  24.10.2007
c GRADIENT etc to scratchfile - dat files - 
c under  GamessUS 
CCCCCCCCCCCCCCCCCCCCCCCCCCC 
      Real*8 En,Um,Gr(3),He(3,3),Bmat(3,12),Ginv(3,3),Gmat(3,3)
      Integer NAT,I,J,K,Ivar(3),Jnum(6),Istatus,Natoms(3),mass(9)
c c      logical omat_inv
      Character*2  CharAtoms(3),Zcoor(3)
      Character*7 Z7
      Character*22 Z21
      Data Zcoor/'hc','nc','w '/
      Data CharAtoms/'H ','C ','N '/
      Data Natoms/1,6,7/
      OPEN(71,FILE='Energyfile')
      OPEN(72,FILE='Gradfile')
      OPEN(73,FILE='Hessfile')
      OPEN(74,FILE='Bmatfile')
      OPEN(14,FILE='hcnVener.dat',status='unknown',access='append')
      OPEN(15,FILE='hcnVgrad.dat',status='unknown',access='append')
      OPEN(48,FILE='hcnVgmatr.dat',status='unknown',access='append')
      OPEN(20,FILE='hcnVhesse.dat',status='unknown',access='append')
      OPEN(51,FILE='hcnVbmatr.dat',status='unknown',access='append')
      OPEN(44,FILE='hcnVprotocol.txt',status='unknown',access='append')
      OPEN(58,FILE='hcnVistat.dat')
       NAT=3
       read(58,*) istatus
ccccccccccccccccccccccccccccccccccccccccccccccccccccc
c Energy       
       read(71,81,END=91) Z22, En
81     FORMAT(1X,A21,F14.10)
       if(istatus.eq.2) rewind 14 
       write(14,52) En 
cccccccccccccccccccccccccccccccccccccccccccccccccccccc 
c   Gradient:
       Do I=1,3
        read(72,82,END=92) 
       enddo
       Do I=1,NAT  
        read(72,82,END=92) Ivar(I), Z7, (Jnum(J),J=1,6), En, Gr(I)
cc      write(*,82)        Ivar(I), Z7, (Jnum(J),J=1,6), En, Gr(I)
       enddo 
82     FORMAT(1X,I5,1X,A7,1X,6I5,2F16.7)
       if(istatus.eq.2) rewind 15
       write(15,52) (Gr(I),I=1,NAT)
52     FORMAT(1X, 3F15.11)
cccccccccccccccccccccccccccccccccccccccccccccccccccccc 
c Hessian
       Do I=1,5
        read(73,83,END=93)
       enddo
       Do I=1,NAT
        read(73,83,END=93) Ivar(I), (He(I,J),J=1,NAT)
        enddo
83     FORMAT(1X,I4,1X,3(1X,F11.7))
       if(istatus.eq.2) rewind 20
       Do  I=1,NAT
        WRITE(20,53) (He(I,J),J=1,NAT)
       enddo
53     FORMAT(1X,3F15.10)
ccccccccccccccccccccccccccccccccccccccccccccccccccccccc
c  B Matrix
       if(istatus.eq.2) rewind 51
       Do I=1,5
        read(74,84,END=94)
       enddo
      Do I=1,NAT
       read(74,84,END=94) Ivar(I), (Bmat(I,J),J=1,5)
       write(51,84)       Ivar(I), (Bmat(I,J),J=1,5)
      enddo
c
      Do I=1,3
       read(74,*)
       write(51,*)
      enddo
      Do I=1,NAT
       read(74,84,END=94) Ivar(I), (Bmat(I,J),J=6,9)
       write(51,84)       Ivar(I), (Bmat(I,J),J=6,9)  
      enddo
       write(51,*)
       write(51,*)
84     FORMAT(1X,I4,1X,5(1X,F11.7))
cccccc for mass-weighting (not used)
       Do 22 K=1,NAT
        Do 23 J=1,3
         mass((K-1)*3+J)=1
c        If(Natoms(K).eq.1) then
c          mass((K-1)*3+J)=1
c        else
c          mass((K-1)*3+J)=Natoms(K)*2
c        endif
23      continue
22     continue
cc
ccc Make Metric G^ij=B*B^T, this is mathematically ginv matrix
cc
      DO 16  I=1,NAT
      DO 16  J=1,NAT
        UM=0.0d0
       DO K=1,3*NAT
        UM=UM+Bmat(I,K)/mass(K)*Bmat(J,K)
       enddo                                                                                                                 17      CONTINUE
16     Ginv(I,J)=UM                                                                                                                
      if(istatus.eq.2) rewind 48
      Do 37, I=1,NAT
c c c testprint     WRITE(44,50) (Ginv(I,J),J=1,NAT)
37    WRITE(48,50) (Ginv(I,J),J=1,NAT)
50    FORMAT(1X,3F20.10)
      WRITE(48,*) 'gmat = g_{ij} '
cccccccccccccccc
c alternate: but it gives the same gmat matrix
      call SVDCMP(Ginv,NAT,NAT,NAT,NAT,Gr,He)
c      WRITE(44,*)
       Um=10.1d0**10
       En=1.0d0 
       Do J=1,NAT
        IF(gr(J).lt.Um) Um=gr(J)
        En=En*gr(J)
       enddo
c       WRITE(44,*)
c       WRITE(44,*) ' smallest SVD of ginv  is ', Um
c       WRITE(44,*) ' product of SVD        is ', En                                     
c       WRITE(44,*) ' vector of singular values '
c       WRITE(44,50) (Gr(J),J=1,NAT)
c  gmat by svd:
       Do 55 K=1,NAT
         Gr(K)=1.0d0/Gr(K)
55     continue
       Do 111 I=1,NAT
        Do K=1,NAT
         Ginv(I,K)=Ginv(I,K)*Gr(K)
        enddo
111    continue
       Do 112 I=1,NAT
        Do 110 J=1,NAT
         gmat(I,J)=0.0d0
         Do 109 K=1,NAT
109      gmat(I,J)= gmat(I,J)+Ginv(I,K)*He(J,K)
110     continue
112    continue
       Do 3381, J=1,NAT
3381   WRITE(48,50) (gmat(J,I),I=1,NAT)
       WRITE(48,*)
      goto 11
ccccccccccccccccccccccccccccccccccccccccccccccccccccccc
91     continue
      write(6,*) 'Stop without Energy '
      write(44,*) ' ERROR !!! Energy is missing !!! '
       goto1
92    continue
       write(6,*) 'Stop without Gradient '
       write(44,*) ' ERROR !!! Gradient is missing !!! '
       goto1
93    continue
       write(6,*) 'Stop without Hessian '
       write(44,*) ' ERROR !!! Hessian is missing !!! '
       goto1
94    continue
       write(6,*) 'Stop without Metric '
       write(44,*) ' ERROR !!! Metric is missing !!! '
1     continue
      istatus=10
      rewind 58
      WRITE(58,*) istatus
      WRITE(*,*)' Exit-Status DATEN ', istatus
      WRITE(44,*)' Exit-Status DATEN ', istatus
11    continue
      call exit(istatus)
       STOP      
      End
c ------------------------------------------------------------------------
      SUBROUTINE SVDCMP(A,M,N,Mp,Np,W,V)
      IMPLICIT NONE
      INTEGER M, N, Mp, Np
      DOUBLE PRECISION A(Mp, Np), W(Np), V(Np,Np)
c Routine to do singular value decomposition of the matrix A.
c Based on the Press et al. routine (Numerical Recipes)
      INTEGER NMAX
      PARAMETER (NMAX=100)
      DOUBLE PRECISION rv1(NMAX)
      DOUBLE PRECISION anorm, c, f, g, h, s, scale, x, y, z
      INTEGER i, its, j, k, l, nm, jj, l1
      g = 0.0d0
      scale = 0.0d0
      anorm = 0.0d0
      DO i = 1 , N
         l = i + 1
         rv1(i) = scale*g
         g = 0.0d0
         s = 0.0d0
         scale = 0.0d0
         IF ( i.LE.M ) THEN
            DO k = i , M
               scale = scale + ABS(A(k,i))
            ENDDO
            IF ( scale .NE. 0.0d0 ) THEN
               DO k = i , M
                  A(k,i) = A(k,i)/scale
                  s = s + A(k,i)*A(k,i)
               ENDDO
               f = A(i,i)
               g = -SIGN(SQRT(s),f)
               h = f*g - s
               A(i,i) = f - g
               IF ( i.NE.N ) THEN
                  DO j = l , N
                     s = 0.0d0
                     DO k = i , M
                        s = s + A(k,i)*A(k,j)
                     ENDDO
                     f = s/h
                     DO k = i , M
                        A(k,j) = A(k,j) + f*A(k,i)
                     ENDDO
                  ENDDO
               ENDIF
               DO k = i , M
                  A(k,i) = scale*A(k,i)
               ENDDO
            ENDIF
         ENDIF
         W(i) = scale*g
         g = 0.0d0
         s = 0.0d0
         scale = 0.0d0
         IF ( (i.LE.M) .AND. (i.NE.N) ) THEN
            DO k = l , N
               scale = scale + ABS(A(i,k))
            ENDDO
            IF ( scale .NE. 0.0d0 ) THEN
               DO k = l , N
                  A(i,k) = A(i,k)/scale
                  s = s + A(i,k)*A(i,k)
               ENDDO
               f = A(i,l)
               g = -SIGN(SQRT(s),f)
               h = f*g - s
               A(i,l) = f - g
               DO k = l , N
                  rv1(k) = A(i,k)/h
               ENDDO
               IF ( i.NE.M ) THEN
                  DO j = l , M
                     s = 0.0d0
                     DO k = l , N
                        s = s + A(j,k)*A(i,k)
                     ENDDO
                     DO k = l , N
                        A(j,k) = A(j,k) + s*rv1(k)
                     ENDDO
                  ENDDO
               ENDIF
               DO k = l , N
                  A(i,k) = scale*A(i,k)
               ENDDO
            ENDIF
         ENDIF
         anorm = MAX(anorm,(ABS(W(i))+ABS(rv1(i))))
      ENDDO

      DO i = N , 1 , -1
         IF ( i.LT.N ) THEN
            IF ( g .NE. 0.0d0 ) THEN
               DO j = l , N
                  V(j,i) = (A(i,j)/A(i,l))/g
               ENDDO
               DO j = l , N
                  s = 0.0d0
                  DO k = l , N
                     s = s + A(i,k)*V(k,j)
                  ENDDO
                  DO k = l , N
                     V(k,j) = V(k,j) + s*V(k,i)
                  ENDDO
               ENDDO
            ENDIF
            DO j = l , N
               V(i,j) = 0.0d0
               V(j,i) = 0.0d0
            ENDDO
         ENDIF
         V(i,i) = 1.0
         g = rv1(i)
         l = i
      ENDDO


      DO i = N , 1 , -1
         l = i + 1
         g = W(i)
         IF ( i.LT.N ) THEN
            DO j = l , N
               A(i,j) = 0.0d0
            ENDDO
         ENDIF
         IF ( g .NE. 0.0d0 ) THEN
            g = 1.0/g
            IF ( i.NE.N ) THEN
               DO j = l , N
                  s = 0.0d0
                  DO k = l , M
                     s = s + A(k,i)*A(k,j)
                  ENDDO
                  f = (s/A(i,i))*g
                  DO k = i , M
                     A(k,j) = A(k,j) + f*A(k,i)
                  ENDDO
               ENDDO
            ENDIF
            DO j = i , M
               A(j,i) = A(j,i)*g
            ENDDO
         ELSE
            DO j = i , M
               A(j,i) = 0.0d0
            ENDDO
         ENDIF
         A(i,i) = A(i,i) + 1.0
      ENDDO


      DO k = N , 1 , -1
         DO its = 1 , 30
            DO l = k , 1 , -1
               l1 = l
               nm = l - 1
               IF ( (ABS(rv1(l))+anorm).EQ.anorm ) GOTO 380
               IF ( (ABS(W(nm))+anorm).EQ.anorm ) GOTO 340
            ENDDO
 340        CONTINUE
            l = l1
            c = 0.0d0
            s = 1.0d0
            DO i = l , k
               f = s*rv1(i)
               rv1(i) = c*rv1(i)
               IF ( (ABS(f)+anorm).NE.anorm ) THEN
                  g = W(i)
                  h = SQRT(f*f+g*g)
                  W(i) = h
                  h = 1.0d0/h
                  c = (g*h)
                  s = -(f*h)
                  DO j = 1 , M
                     y = A(j,nm)
                     z = A(j,i)
                     A(j,nm) = (y*c) + (z*s)
                     A(j,i) = -(y*s) + (z*c)
                  ENDDO
               ENDIF
 360        ENDDO
 380        CONTINUE
            z = W(k)
            IF ( l.EQ.k ) THEN
               IF ( z .LT. 0.0d0 ) THEN
                  W(k) = -z
                  DO j = 1 , N
                     V(j,k) = -V(j,k)
                  ENDDO
               ENDIF
               GOTO 500
            ENDIF
            IF ( its .EQ. 30 ) write(*,*) 
     &               'SVDCMP: No convergence in 30 iterations'
            x = W(l)
            nm = k - 1
            y = W(nm)
            g = rv1(nm)
            h = rv1(k)
            f = ((y-z)*(y+z)+(g-h)*(g+h))/(2.0d0*h*y)
            g = SQRT(f*f+1.0d0)
            f = ((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x
            c = 1.0d0
            s = 1.0d0
            DO j = l , nm
               i = j + 1
               g = rv1(i)
               y = W(i)
               h = s*g
               g = c*g
               z = SQRT(f*f+h*h)
               rv1(j) = z
               c = f/z
               s = h/z
               f = (x*c) + (g*s)
               g = -(x*s) + (g*c)
               h = y*s
               y = y*c
               DO jj = 1 , N
                  x = V(jj,j)
                  z = V(jj,i)
                  V(jj,j) = (x*c) + (z*s)
                  V(jj,i) = -(x*s) + (z*c)
               ENDDO
               z = SQRT(f*f+h*h)
               W(j) = z
               IF ( z .NE. 0.0d0 ) THEN
                  z = 1.0d0/z
                  c = f*z
                  s = h*z
               ENDIF
               f = (c*g) + (s*y)
               x = -(s*g) + (c*y)
               DO jj = 1 , M
                  y = A(jj,j)
                  z = A(jj,i)
                  A(jj,j) = (y*c) + (z*s)
                  A(jj,i) = -(y*s) + (z*c)
               ENDDO
            ENDDO
            rv1(l) = 0.0d0
            rv1(k) = f
            W(k) = x
         ENDDO
 500     CONTINUE
      ENDDO
      RETURN
      END
cc ccccccccccccccccccccccccccccccccccccccccccccccccccc
      subroutine ginvers(in,NAT,out,omat_inv)
c    calculates the inverse matrix of IN
      real*8 in,out
      logical omat_inv
      integer NAT,i,j,k
      dimension in(NAT,NAT),out(NAT,NAT)
      do 1,k=1,NAT
      do 1,j=1,NAT
  1   out(j,k)=in(j,k)
c
      do 10,k=1,NAT
         if (out(k,k).eq.0.0d0) then
            omat_inv=.false.
            return
         endif
         out(k,k)=1.0d0/out(k,k)
         do 20,i=1,NAT
             if (i.ne.k) out(i,k)=-(out(i,k)*out(k,k))
   20    continue
         do 30,j=1,NAT
             if (j.ne.k) then
                do 40,i=1,NAT
                      if (i.ne.k) out(i,j)=out(i,j)+out(i,k)*out(k,j)
   40           continue
                out(k,j)=out(k,j)*out(k,k)
             endif
   30    continue
   10 continue
      omat_inv=.true.
      return
      end
C cccccccccc
