root / src / CalcHess.f90 @ 6
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 |