Statistiques
| Révision :

root / src / CalcHess.f90 @ 2

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

1
      subroutine CalcHess (nfree,geom, hess,Igeom,Iopt)
2

    
3
! This routine calculate the Hessian (or its inverse) numerically using Egrad.
4
! It should be general and should work with any combination of Coord and Prog
5
! however, it has not been tested with Prog different from 'test'
6

    
7
! It comes mostly from the hess.f subroutine of the IRC package.
8

    
9

    
10
  use Path_module, only : Nat,Coord,Hinv
11

    
12
  use Io_module
13
!
14
      IMPLICIT NONE
15

    
16
!!!!!!!!!!! Parameters
17
  ! NFree==NCoord: Number of the degrees of freedom
18
  ! IGeom: index of the geometry.
19
  ! Iopt: step in the optimization process
20
  INTEGER(KINT), INTENT (IN) :: NFree, IGeom, IOpt
21
! Geometry at which Hessian is calculated (or its inverse)
22
   REAL(KREAL), INTENT(IN) :: Geom(Nfree)
23
! Hessian in compacted form
24
      REAL(KREAL), INTENT(OUT) ::  Hess(Nfree,Nfree)
25
!
26
! Parameters used to calculate the Hessian
27
! numerically with increasing accuray
28
      INTEGER(KINT), DIMENSION(6,0:3), PARAMETER :: IECOEF  &
29
      = RESHAPE(SOURCE=(/           &
30
          -1,1,0,0,0,0,             &
31
          -1,1,0,0,0,0,             &
32
          1,-8,8,-1,0,0,            & 
33
          -1,9,-45,45,-9,1          &
34
       /), SHAPE=(/6,4/))
35

    
36
      INTEGER(KINT), DIMENSION(6,0:3), PARAMETER :: ISCOEF   &
37
      = RESHAPE(SOURCE=(/    &
38
         0,1,0,0,0,0,         &
39
          -1,1,0,0,0,0,       & 
40
          -2,-1,1,2,0,0,      &
41
           -3,-2,-1,1,2,3     &
42
         /),SHAPE=(/6,4/))
43
      INTEGER(KINT), DIMENSION(0:3), PARAMETER :: NbDiv = (/1,2,12,60/)
44
      INTEGER(KINT), DIMENSION(0:3), PARAMETER :: NbCoef = (/2,2,4,6/)
45

    
46

    
47
      INTEGER(KINT), PARAMETER :: HessAcc=2
48
      REAL(KREAL), PARAMETER :: StepHess=0.01d0
49
! ======================================================================
50
      logical           :: debug
51

    
52
      REAL(KREAL) :: Ener
53
      INTEGER(KINT) :: I, J, IAT, JAT, IJ0, IJ1, IConst
54

    
55
       REAL(KREAL), ALLOCATABLE :: Temp(:),Temp2(:,:) 
56

    
57

    
58
       REAL(KREAL), ALLOCATABLE :: Value(:), ValueOld(:), GradTMP(:)
59
       REAL(KREAL), ALLOCATABLE :: RTmp1(:,:), RTmp3(:,:)  ! Nat,3
60
       REAL(KREAL), ALLOCATABLE :: RTmp2(:)  ! NFree
61
! ======================================================================
62

    
63
  INTERFACE
64
     function valid(string) result (isValid)
65
       CHARACTER(*), intent(in) :: string
66
       logical                  :: isValid
67
     END function VALID
68
  END INTERFACE
69

    
70
! ======================================================================
71

    
72
      hess=0.d0
73

    
74
      debug=valid('CALCHESS').OR.valid('hess')
75

    
76
      if (debug) THEN
77
         WRITE(*,*) 'Entering CalcHess'
78
         WRITE(*,*) 'StepHess=',StepHess
79
         WRITE(*,*) "HessAcc=",HessAcc
80
      END IF
81

    
82
      allocate(Value(Nfree), ValueOld(Nfree), GradTmp(Nfree))
83
      ALLOCATE(RTmp1(Nat,3),RTmp3(Nat,3),RTmp2(NFree))
84
      allocate(temp2(Nfree,Nfree))
85

    
86
      RTmp1=0.d0
87
      RTmp3=0.d0
88
      RTmp2=Geom
89

    
90
!     Now, we calculate the second derivatives for the active variables               
91
      Value=Geom
92
      ValueOld=Geom
93

    
94
      Do IConst=1,Nfree
95
            DO I=1,NbCoef(HessAcc)
96
               Value(IConst)=valueOld(IConst)+StepHess*ISCOEF(I,HessAcc)
97
!     We 'propagate this new value in the Zmatrix'
98
               call egrad(ener,value,gradtmp,NFree,IGeom,Iopt,RTmp1,RTmp2,RTmp3,.FALSE.)
99
               Hess(1:Nfree,IConst)= Hess(1:Nfree,IConst)+   &
100
                    gradtmp(1:Nfree)*IECOEF(I,HessAcc)
101
            end do
102
         END DO
103
        deallocate(Value, ValueOld, GradTmp)
104
         
105
        HESS=Hess/(NbDiv(HessAcc)*StepHess)
106

    
107
         if (debug) then
108
            WRITE(*,*) 'Non symmetrized hessian'
109
            DO iat=1,Nfree
110
               WRITE(*,'(15(1X,F12.5))') Hess(iat,1:Nfree)
111
            END DO
112
         END if
113

    
114
         DO i=1,Nfree
115
           Temp2(i,i)=Hess(i,i)
116
           DO j=i+1,Nfree
117
             Temp2(i,j)=0.5*(Hess(i,j)+Hess(j,i))
118
             Temp2(j,i)=Temp2(i,j)
119
           END DO
120
         END DO
121

    
122
         Hess=Hess-Temp2
123

    
124
         if (debug) then
125
            WRITE(*,*) 'Symmetrized hessian'
126
            DO iat=1,Nfree
127
               WRITE(*,'(15(1X,F12.5))') Temp2(iat,1:Nfree)
128
            END DO
129

    
130
            WRITE(*,*) 'Difference between non-syma and Symmetrized hessian'
131
            DO iat=1,Nfree
132
               WRITE(*,'(15(1X,F12.5))') Hess(iat,1:Nfree)
133
            END DO
134
         end if
135

    
136
! We calculate inverse of the Hessian only if HInv=T
137

    
138
         Hess=Temp2
139
      if (Hinv) then
140
        call Geninv(Nfree,Hess,Temp2,NFree)
141
        Hess=Temp2
142
      end if
143

    
144
      deallocate(RTmp1,RTmp2,RTmp3,Temp2)
145

    
146
! ======================================================================
147
      end subroutine CalcHess