Statistiques
| Révision :

root / src / ConvGrad_Cart2Int.f90 @ 1

Historique | Voir | Annoter | Télécharger (4,35 ko)

1 1 equemene
      SUBROUTINE ConvGrad_Cart2Int(n,BMat,indzmat,GradCart,GradInt)
2 1 equemene
3 1 equemene
        use Io_module
4 1 equemene
        use Path_module, only : atome
5 1 equemene
6 1 equemene
        IMPLICIT NONE
7 1 equemene
8 1 equemene
!
9 1 equemene
        INTEGER(KINT), INTENT(IN) ::  n, indzmat(n,5)
10 1 equemene
        REAL(KREAL), INTENT(IN)  :: BMat(3,n,3,n), GradCart(3,n)
11 1 equemene
        REAL(KREAL), INTENT(INOUT)  :: GradInt(3,n)
12 1 equemene
13 1 equemene
14 1 equemene
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
15 1 equemene
!
16 1 equemene
! This routines converts a gradient in cartesian coordinates into
17 1 equemene
! the gradient in internal coordinates (either Zmat, Mixed or Baker)
18 1 equemene
!
19 1 equemene
! It uses a LAPACK subroutine (dgelsd) which purpose is:
20 1 equemene
21 1 equemene
! *  DGELSD computes the minimum-norm solution to a real linear least
22 1 equemene
! *  squares problem:
23 1 equemene
! *      minimize 2-norm(| b - A*x |)
24 1 equemene
! *  using the singular value decomposition (SVD) of A. A is an M-by-N
25 1 equemene
! *  matrix which may be rank-deficient.
26 1 equemene
27 1 equemene
! Variables:
28 1 equemene
! input  : n, number of atoms
29 1 equemene
!          BMat: the dZ/dx matrix
30 1 equemene
!          GradCart: Gradient in cartesian coordinates
31 1 equemene
!
32 1 equemene
! output : GradInt: Gradient in internal coordintaes
33 1 equemene
!
34 1 equemene
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
35 1 equemene
36 1 equemene
      logical    debug, init
37 1 equemene
      REAL(KREAL), parameter :: zero = 0d0, tol = 1d-8,  eps = 1d-12
38 1 equemene
39 1 equemene
      REAL(KREAL) , ALLOCATABLE :: AEigVec(:,:), AEigVal(:),ATA(:)
40 1 equemene
      INTEGER(KINT) :: n3, iat, k
41 1 equemene
      INTEGER(KINT) :: i
42 1 equemene
!
43 1 equemene
      save  debug, init
44 1 equemene
      data  init /.false./
45 1 equemene
46 1 equemene
!     .. Local Arrays  for LAPACK
47 1 equemene
      INTEGER(KINT) :: Info, LWork, Rank
48 1 equemene
      REAL(KREAL), ALLOCATABLE :: S(:), Work(:), GradCTmp(:,:)
49 1 equemene
50 1 equemene
!     IWORK dimension should be at least 3*MIN(M,N)*NLVL + 11*MIN(M,N),
51 1 equemene
!     where NLVL = MAX( 0, INT( LOG_2( MIN(M,N)/(SMLSIZ+1) ) )+1 )
52 1 equemene
!     and SMLSIZ = 25
53 1 equemene
      INTEGER(KINT) :: LIWork, NLVL, SMLSIZ=12 ! We take smaller value just to be sure
54 1 equemene
      INTEGER(KINT), ALLOCATABLE :: IWork(:) ! IWork
55 1 equemene
56 1 equemene
57 1 equemene
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
58 1 equemene
!
59 1 equemene
60 1 equemene
  INTERFACE
61 1 equemene
     function valid(string) result (isValid)
62 1 equemene
       CHARACTER(*), intent(in) :: string
63 1 equemene
       logical                  :: isValid
64 1 equemene
     END function VALID
65 1 equemene
66 1 equemene
     SUBROUTINE DGELSD( M, N, NRHS, A, LDA, B, LDB, S, RCOND, RANK, &
67 1 equemene
                        WORK, LWORK, IWORK, INFO )
68 1 equemene
! *
69 1 equemene
! *  -- LAPACK driver routine (version 3.2.2) --
70 1 equemene
! *  -- LAPACK is a software package provided by Univ. of Tennessee,    --
71 1 equemene
! *  -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
72 1 equemene
! *     June 2010
73 1 equemene
! *
74 1 equemene
! *     .. Scalar Arguments ..
75 1 equemene
      INTEGER            INFO, LDA, LDB, LWORK, M, N, NRHS, RANK
76 1 equemene
      DOUBLE PRECISION   RCOND
77 1 equemene
!*     ..
78 1 equemene
!*     .. Array Arguments ..
79 1 equemene
      INTEGER            IWORK( * )
80 1 equemene
      DOUBLE PRECISION   A( LDA, * ), B( LDB, * ), S( * ), WORK( * )
81 1 equemene
82 1 equemene
    END SUBROUTINE DGELSD
83 1 equemene
84 1 equemene
85 1 equemene
86 1 equemene
87 1 equemene
  END INTERFACE
88 1 equemene
89 1 equemene
!
90 1 equemene
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
91 1 equemene
92 1 equemene
93 1 equemene
      if (.not.init) then
94 1 equemene
        init = .true.
95 1 equemene
        debug = valid ('GEOSTEP').OR.valid('ConvGrad')
96 1 equemene
      endif
97 1 equemene
98 1 equemene
!
99 1 equemene
      Allocate(GradCTmp(3,n))
100 1 equemene
101 1 equemene
      if (debug) WRITE(*,*) "================ Entering ConvGrad_Cart2Int ============="
102 1 equemene
!
103 1 equemene
      n3 = 3 * n
104 1 equemene
!
105 1 equemene
106 1 equemene
      NLVL= MAX( 0, INT( LOG( n3*1.d0/(SMLSIZ+1))/LOG(2.d0) ) +1 )
107 1 equemene
      LIWork=Max(1,3*n3*NLVL + 11*n3+1)
108 1 equemene
109 1 equemene
      Allocate(IWork(LIWork),WOrk(1))
110 1 equemene
111 1 equemene
      LWork=-1
112 1 equemene
      GradInt=0.d0
113 1 equemene
114 1 equemene
        call DGELSD( n3, n3, 1, BMat, n3, GradCart, n3, GradInt, Tol, RANK, &
115 1 equemene
                        WORK, LWORK, IWORK, INFO )
116 1 equemene
117 1 equemene
        LWork=Work(1)
118 1 equemene
        if (debug) WRITE(*,*) "DEBUG CONVGRAD_CART2INT LWORK,N3=",LWORK,N3
119 1 equemene
120 1 equemene
        DEALLOCATE(Work)
121 1 equemene
        ALLOCATE(Work(LWork))
122 1 equemene
123 1 equemene
        call DGELSD( n3, n3, 1, BMat, n3, GradCart, n3, GradInt, Tol, RANK, &
124 1 equemene
                        WORK, LWORK, IWORK, INFO )
125 1 equemene
126 1 equemene
        GradInt=GradCart
127 1 equemene
      if (debug) then
128 1 equemene
         WRITE(*,*) "DEBUG CONVGRAD_CART2INT -- GradInt after DGELSD"
129 1 equemene
         WRITE(*,*) "INFO=",INFO
130 1 equemene
         DO I=1,N
131 1 equemene
            WRITE(*,'(1X,I5,3(1X,F13.6))') I, GradInt(1:3,I)
132 1 equemene
         END DO
133 1 equemene
      END IF
134 1 equemene
135 1 equemene
136 1 equemene
! In case we used a Zmat, we might have dummy atoms.
137 1 equemene
! We are extra cautious and put their gradient components to 0
138 1 equemene
139 1 equemene
      do iat = 1, n
140 1 equemene
        do k = 1, 3
141 1 equemene
          if (atome(indzmat(iat,1)) == 0) then
142 1 equemene
            GradInt(k,iat) = zero
143 1 equemene
          endif
144 1 equemene
        end do
145 1 equemene
      end do
146 1 equemene
147 1 equemene
      where (abs(GradInt)<=eps) GradInt=zero
148 1 equemene
149 1 equemene
      if (debug) write (*,*) "DBG ConvGrad_Cart2Int GradInt=",GradInt
150 1 equemene
151 1 equemene
      DEALLOCATE(IWork,Work,GradCTmp)
152 1 equemene
!
153 1 equemene
!
154 1 equemene
      if (debug) WRITE(*,*) "================  ConvGrad_Cart2Int Over ============="
155 1 equemene
      return
156 1 equemene
! ======================================================================
157 1 equemene
158 1 equemene
    end SUBROUTINE ConvGrad_Cart2Int