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 |