Statistiques
| Révision :

root / src / CalcHess.f90

Historique | Voir | Annoter | Télécharger (5,79 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
!  Copyright 2003-2014 Ecole Normale Supérieure de Lyon, 
11
!  Centre National de la Recherche Scientifique,
12
!  Université Claude Bernard Lyon 1. All rights reserved.
13
!
14
!  This work is registered with the Agency for the Protection of Programs 
15
!  as IDDN.FR.001.100009.000.S.P.2014.000.30625
16
!
17
!  Authors: P. Fleurat-Lessard, P. Dayal
18
!  Contact: optnpath@gmail.com
19
!
20
! This file is part of "Opt'n Path".
21
!
22
!  "Opt'n Path" is free software: you can redistribute it and/or modify
23
!  it under the terms of the GNU Affero General Public License as
24
!  published by the Free Software Foundation, either version 3 of the License,
25
!  or (at your option) any later version.
26
!
27
!  "Opt'n Path" is distributed in the hope that it will be useful,
28
!  but WITHOUT ANY WARRANTY; without even the implied warranty of
29
!
30
!  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
31
!  GNU Affero General Public License for more details.
32
!
33
!  You should have received a copy of the GNU Affero General Public License
34
!  along with "Opt'n Path". If not, see <http://www.gnu.org/licenses/>.
35
!
36
! Contact The Office of Technology Licensing, valorisation@ens-lyon.fr,
37
! for commercial licensing opportunities.
38
!----------------------------------------------------------------------
39

    
40
  use Path_module, only : Nat,Hinv
41

    
42
  use Io_module
43
!
44
      IMPLICIT NONE
45

    
46
!!!!!!!!!!! Parameters
47
  ! NFree==NCoord: Number of the degrees of freedom
48
  ! IGeom: index of the geometry.
49
  ! Iopt: step in the optimization process
50
  INTEGER(KINT), INTENT (IN) :: NFree, IGeom, IOpt
51
! Geometry at which Hessian is calculated (or its inverse)
52
   REAL(KREAL), INTENT(IN) :: Geom(Nfree)
53
! Hessian in compacted form
54
      REAL(KREAL), INTENT(OUT) ::  Hess(Nfree,Nfree)
55
!
56
! Parameters used to calculate the Hessian
57
! numerically with increasing accuray
58
      INTEGER(KINT), DIMENSION(6,0:3), PARAMETER :: IECOEF  &
59
      = RESHAPE(SOURCE=(/           &
60
          -1,1,0,0,0,0,             &
61
          -1,1,0,0,0,0,             &
62
          1,-8,8,-1,0,0,            & 
63
          -1,9,-45,45,-9,1          &
64
       /), SHAPE=(/6,4/))
65

    
66
      INTEGER(KINT), DIMENSION(6,0:3), PARAMETER :: ISCOEF   &
67
      = RESHAPE(SOURCE=(/    &
68
         0,1,0,0,0,0,         &
69
          -1,1,0,0,0,0,       & 
70
          -2,-1,1,2,0,0,      &
71
           -3,-2,-1,1,2,3     &
72
         /),SHAPE=(/6,4/))
73
      INTEGER(KINT), DIMENSION(0:3), PARAMETER :: NbDiv = (/1,2,12,60/)
74
      INTEGER(KINT), DIMENSION(0:3), PARAMETER :: NbCoef = (/2,2,4,6/)
75

    
76

    
77
      INTEGER(KINT), PARAMETER :: HessAcc=2
78
      REAL(KREAL), PARAMETER :: StepHess=0.01d0
79
! ======================================================================
80
      logical           :: debug
81

    
82
      REAL(KREAL) :: Ener
83
      INTEGER(KINT) :: I, J, IAT, IConst
84

    
85
       REAL(KREAL), ALLOCATABLE :: Temp2(:, :) 
86

    
87

    
88
       REAL(KREAL), ALLOCATABLE :: Value(:), ValueOld(:), GradTMP(:)
89
       REAL(KREAL), ALLOCATABLE :: RTmp1(:,:), RTmp3(:,:)  ! Nat,3
90
       REAL(KREAL), ALLOCATABLE :: RTmp2(:)  ! NFree
91
! ======================================================================
92

    
93
  INTERFACE
94
     function valid(string) result (isValid)
95
       CHARACTER(*), intent(in) :: string
96
       logical                  :: isValid
97
     END function VALID
98
  END INTERFACE
99

    
100
! ======================================================================
101

    
102
      hess=0.d0
103

    
104
      debug=valid('CALCHESS').OR.valid('hess')
105

    
106
      if (debug) THEN
107
         WRITE(*,*) 'Entering CalcHess'
108
         WRITE(*,*) 'StepHess=',StepHess
109
         WRITE(*,*) "HessAcc=",HessAcc
110
      END IF
111

    
112
      allocate(Value(Nfree), ValueOld(Nfree), GradTmp(Nfree))
113
      ALLOCATE(RTmp1(Nat,3),RTmp3(Nat,3),RTmp2(NFree))
114
      allocate(temp2(Nfree,Nfree))
115

    
116
      RTmp1=0.d0
117
      RTmp3=0.d0
118
      RTmp2=Geom
119

    
120
!     Now, we calculate the second derivatives for the active variables               
121
      Value=Geom
122
      ValueOld=Geom
123

    
124
      Do IConst=1,Nfree
125
            DO I=1,NbCoef(HessAcc)
126
               Value(IConst)=valueOld(IConst)+StepHess*ISCOEF(I,HessAcc)
127
!     We 'propagate this new value in the Zmatrix'
128
               call egrad(ener,value,gradtmp,NFree,IGeom,Iopt,RTmp1,RTmp2,RTmp3,.FALSE.)
129
               Hess(1:Nfree,IConst)= Hess(1:Nfree,IConst)+   &
130
                    gradtmp(1:Nfree)*IECOEF(I,HessAcc)
131
            end do
132
         END DO
133
        deallocate(Value, ValueOld, GradTmp)
134
         
135
        HESS=Hess/(NbDiv(HessAcc)*StepHess)
136

    
137
         if (debug) then
138
            WRITE(*,*) 'Non symmetrized hessian'
139
            DO iat=1,Nfree
140
               WRITE(*,'(15(1X,F12.5))') Hess(iat,1:Nfree)
141
            END DO
142
         END if
143

    
144
         DO i=1,Nfree
145
           Temp2(i,i)=Hess(i,i)
146
           DO j=i+1,Nfree
147
             Temp2(i,j)=0.5*(Hess(i,j)+Hess(j,i))
148
             Temp2(j,i)=Temp2(i,j)
149
           END DO
150
         END DO
151

    
152
         Hess=Hess-Temp2
153

    
154
         if (debug) then
155
            WRITE(*,*) 'Symmetrized hessian'
156
            DO iat=1,Nfree
157
               WRITE(*,'(15(1X,F12.5))') Temp2(iat,1:Nfree)
158
            END DO
159

    
160
            WRITE(*,*) 'Difference between non-syma and Symmetrized hessian'
161
            DO iat=1,Nfree
162
               WRITE(*,'(15(1X,F12.5))') Hess(iat,1:Nfree)
163
            END DO
164
         end if
165

    
166
! We calculate inverse of the Hessian only if HInv=T
167

    
168
         Hess=Temp2
169
      if (Hinv) then
170
        call Geninv(Nfree,Hess,Temp2,NFree)
171
        Hess=Temp2
172
      end if
173

    
174
      deallocate(RTmp1,RTmp2,RTmp3,Temp2)
175

    
176
! ======================================================================
177
      end subroutine CalcHess