root / src / Step_RFO_all.f90 @ 1
Historique | Voir | Annoter | Télécharger (7,97 ko)
1 | 1 | equemene | SUBROUTINE Step_RFO_all(NCoord,Step,IGeom,Geom,Grad,Hess,Tangent) |
---|---|---|---|
2 | 1 | equemene | |
3 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
4 | 1 | equemene | ! |
5 | 1 | equemene | !This subroutine calculates new coordinates given a Hessian, the forces |
6 | 1 | equemene | ! and the old coordinates |
7 | 1 | equemene | ! |
8 | 1 | equemene | !!!!!!!!!! |
9 | 1 | equemene | ! v1.0 |
10 | 1 | equemene | ! Uses only basic RFO step |
11 | 1 | equemene | ! |
12 | 1 | equemene | !!!!!!!!!! |
13 | 1 | equemene | ! v 2.0 |
14 | 1 | equemene | ! We add the test of ADF here, so that it should be more efficient. |
15 | 1 | equemene | ! This version uses HInv to decide wether it should work with the Hessian |
16 | 1 | equemene | ! or its inverse. |
17 | 1 | equemene | ! |
18 | 1 | equemene | ! v 3.0 |
19 | 1 | equemene | ! Uses DIIS. Done by P. Dayal. |
20 | 1 | equemene | ! |
21 | 1 | equemene | ! v3.1 |
22 | 1 | equemene | ! Back to origins ! We remove the ADF test here to see what we loose... |
23 | 1 | equemene | ! untill of course its replacement by something more efficient... and free :) |
24 | 1 | equemene | !!!!!!!!!!!!!!!!! |
25 | 1 | equemene | ! |
26 | 1 | equemene | ! Input: |
27 | 1 | equemene | ! - NCoord: INTEGER(KINT), Number of degrees of freedom |
28 | 1 | equemene | ! - IGeom : INTEGER(KINT), Index of the geometry along the path |
29 | 1 | equemene | ! - Geom : REAL(KREAL)(NCOORD), Geometry expressed in full coordinates |
30 | 1 | equemene | ! - Hess : REAL(KREAL)(Ncoord,NCoord), Hessian at the current geometry |
31 | 1 | equemene | ! |
32 | 1 | equemene | ! |
33 | 1 | equemene | ! Output: |
34 | 1 | equemene | ! - Step : REAL(KREAL)(Ncoord), Calculated step |
35 | 1 | equemene | ! |
36 | 1 | equemene | ! In/Out: |
37 | 1 | equemene | ! - Tangent: REAL(KREAL)(Ncoord), Tangent to the path, at the current point |
38 | 1 | equemene | ! if Tangent=0, then we are optimizing a minimum, tangent is not considered. |
39 | 1 | equemene | ! Input: Expressed in full coordinates. |
40 | 1 | equemene | ! Output: Replaced by the tangent expressed in Free vectors |
41 | 1 | equemene | ! (Changes by PFL 3 Jan 2008) |
42 | 1 | equemene | ! - Grad: READ(KREAL) (NCoord), Gradient at the current point |
43 | 1 | equemene | ! Input: Expressed in full coordinates. |
44 | 1 | equemene | ! PFL 18 Jan 2008: Grad is no longer changed on output -> |
45 | 1 | equemene | ! Output: Replaced by the gradient expressed in Free vector, in the subspace orthogonal to the tangent. |
46 | 1 | equemene | ! <- PFL 18 Jan 2008: Grad is no longer changed on output |
47 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
48 | 1 | equemene | |
49 | 1 | equemene | use Io_module, only : IoOut |
50 | 1 | equemene | |
51 | 1 | equemene | use Path_module, only : NGeomF, Hinv,Coord,Vfree, NGintMax |
52 | 1 | equemene | ! VFree(Ncoord,Ncoord) |
53 | 1 | equemene | |
54 | 1 | equemene | IMPLICIT NONE |
55 | 1 | equemene | |
56 | 1 | equemene | INTEGER, PARAMETER :: KINT=KIND(1) |
57 | 1 | equemene | INTEGER, PARAMETER :: KREAL=KIND(1.D0) |
58 | 1 | equemene | |
59 | 1 | equemene | INTEGER(KINT), INTENT(IN) :: NCoord,IGeom |
60 | 1 | equemene | REAL(KREAL), INTENT(IN) :: Hess(NCoord,NCoord) |
61 | 1 | equemene | REAL(KREAL), INTENT(IN) :: Grad(NCoord),Geom(NCoord) |
62 | 1 | equemene | REAL(KREAL), INTENT(INOUT) :: Tangent(Ncoord) ! Destroyed on output |
63 | 1 | equemene | REAL(KREAL), INTENT(OUT) :: Step(NCoord) |
64 | 1 | equemene | |
65 | 1 | equemene | INTEGER(KINT) :: NFree |
66 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: eigval(:), eigvec(:,:), eigvli(:) |
67 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: Tanf(:) |
68 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: Grad_f(:),Step_f(:) ! NFree |
69 | 1 | equemene | |
70 | 1 | equemene | REAL(KREAL), PARAMETER :: tiny=1e-20, zero=0., dele3=1e-6, eps=1e-12 |
71 | 1 | equemene | REAL(KREAL), PARAMETER :: crit=1e-8 |
72 | 1 | equemene | INTEGER(KINT) :: n, i, j, isignx, im, idx,k, isch |
73 | 1 | equemene | REAL(KREAL) :: grd, evl, eval,e1,e2, norm |
74 | 1 | equemene | REAL(KREAL) :: dg, dx |
75 | 1 | equemene | CHARACTER(120) :: fmt, fmt2, Line |
76 | 1 | equemene | |
77 | 1 | equemene | LOGICAL :: Debug |
78 | 1 | equemene | |
79 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: HFree(:,:) ! NFree,NFree |
80 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: Htmp(:,:) ! NCoord,NFree |
81 | 1 | equemene | |
82 | 1 | equemene | LOGICAL, SAVE :: LFirst=.TRUE. |
83 | 1 | equemene | |
84 | 1 | equemene | INTERFACE |
85 | 1 | equemene | function valid(string) result (isValid) |
86 | 1 | equemene | CHARACTER(*), intent(in) :: string |
87 | 1 | equemene | logical :: isValid |
88 | 1 | equemene | END function VALID |
89 | 1 | equemene | END INTERFACE |
90 | 1 | equemene | |
91 | 1 | equemene | debug=valid("step_rfo_all") |
92 | 1 | equemene | if (debug) WRITE(*,*) "=========================== Entering Step_RFO_All ====================" |
93 | 1 | equemene | if (debug) WRITE(*,*) "=========================== IGeom=",IGeom," ====================" |
94 | 1 | equemene | |
95 | 1 | equemene | ! PFL 22.Nov.2007 -> |
96 | 1 | equemene | ! Nfree is equal to Ncoord-1 only when optimizing in the plane |
97 | 1 | equemene | ! orthogonal to the tangent. |
98 | 1 | equemene | ! In the case of a regular opt, NFree=Ncoord. |
99 | 1 | equemene | ! Next line has been moved later |
100 | 1 | equemene | ! NFree=Ncoord-1 |
101 | 1 | equemene | ! <- PFL 22.Nov.2007 |
102 | 1 | equemene | |
103 | 1 | equemene | IF (debug) THEN |
104 | 1 | equemene | WRITE(*,*) 'DBG Step_RFO_All Hess' |
105 | 1 | equemene | WRITE(*,*) 'DBG Step_RFO_All NCoord=',NCoord |
106 | 1 | equemene | |
107 | 1 | equemene | Idx=min(12,NCoord) |
108 | 1 | equemene | DO I=1,NCoord |
109 | 1 | equemene | WRITE(*,'(12(1X,F10.4))') Hess(I,1:Idx) |
110 | 1 | equemene | END DO |
111 | 1 | equemene | WRITE(*,*) 'DBG Step_RFO_All Grad' |
112 | 1 | equemene | WRITE(*,'(12(1X,F10.4))') Grad(1:Idx) |
113 | 1 | equemene | WRITE(*,*) 'DBG Step_RFO_All Coord' |
114 | 1 | equemene | WRITE(*,'(12(1X,F10.4))') Geom(1:Idx) |
115 | 1 | equemene | WRITE(*,*) 'DBG Step_RFO_All Tangent' |
116 | 1 | equemene | WRITE(*,'(12(1X,F10.4))') tangent(1:Idx) |
117 | 1 | equemene | |
118 | 1 | equemene | END IF |
119 | 1 | equemene | |
120 | 1 | equemene | Call FreeMv(NCoord,Vfree) ! VFree(Ncoord,Ncoord) |
121 | 1 | equemene | ! we orthogonalize Vfree to the tangent vector of this geom |
122 | 1 | equemene | ! 2007/05/29 Only if Tangent/=0.d0 |
123 | 1 | equemene | Norm=sqrt(dot_product(Tangent,Tangent)) |
124 | 1 | equemene | IF (Norm.GT.eps) THEN |
125 | 1 | equemene | ALLOCATE(Tanf(NCoord)) |
126 | 1 | equemene | |
127 | 1 | equemene | ! We normalize Tangent |
128 | 1 | equemene | Tangent=Tangent/Norm |
129 | 1 | equemene | |
130 | 1 | equemene | ! We convert Tangent into vfree only displacements |
131 | 1 | equemene | ! This is useless for now (2007.Apr.23) as vfree=Id matrix |
132 | 1 | equemene | ! but it will be usefull as soon as we introduce Constraints |
133 | 1 | equemene | DO I=1,NCoord |
134 | 1 | equemene | Tanf(I)=dot_product(reshape(vfree(:,I),(/NCoord/)),Tangent) |
135 | 1 | equemene | END DO |
136 | 1 | equemene | Tangent=0.d0 |
137 | 1 | equemene | DO I=1,NCoord |
138 | 1 | equemene | Tangent=Tangent+Tanf(i)*vfree(:,I) |
139 | 1 | equemene | END DO |
140 | 1 | equemene | |
141 | 1 | equemene | ! first we substract Tangent from vfree |
142 | 1 | equemene | DO I=1,NCoord |
143 | 1 | equemene | Norm=dot_product(reshape(vfree(:,i),(/NCoord/)),Tangent) |
144 | 1 | equemene | Vfree(:,I)=vfree(:,i)-Norm*Tangent |
145 | 1 | equemene | END DO |
146 | 1 | equemene | |
147 | 1 | equemene | Idx=0. |
148 | 1 | equemene | ! Schmidt orthogonalization of the vfree vectors |
149 | 1 | equemene | DO I=1,NCoord |
150 | 1 | equemene | ! We substract the first vectors |
151 | 1 | equemene | ! we do it twice as the Schmidt procedure is not numerically stable |
152 | 1 | equemene | DO isch=1,2 |
153 | 1 | equemene | DO J=1,Idx |
154 | 1 | equemene | Norm=dot_product(reshape(vfree(:,I),(/NCoord/)),reshape(vfree(:,J),(/NCoord/))) |
155 | 1 | equemene | vfree(:,I)=vfree(:,I)-Norm*vfree(:,J) |
156 | 1 | equemene | END DO |
157 | 1 | equemene | END DO |
158 | 1 | equemene | Norm=dot_product(reshape(vfree(:,I),(/NCoord/)),reshape(vfree(:,I),(/NCoord/))) |
159 | 1 | equemene | IF (Norm.GE.crit) THEN |
160 | 1 | equemene | idx=idx+1 |
161 | 1 | equemene | vfree(:,idx)=vfree(:,i)/sqrt(Norm) |
162 | 1 | equemene | END IF |
163 | 1 | equemene | END DO |
164 | 1 | equemene | |
165 | 1 | equemene | If (Idx/= NCoord-1) THEN |
166 | 1 | equemene | WRITE(*,*) "Pb in orthogonalizing vfree to tangent for geom",IGeom |
167 | 1 | equemene | WRITE(Ioout,*) "Pb in orthogonalizing vfree to tangent for geom",IGeom |
168 | 1 | equemene | STOP |
169 | 1 | equemene | END IF |
170 | 1 | equemene | |
171 | 1 | equemene | DEALLOCATE(Tanf) |
172 | 1 | equemene | |
173 | 1 | equemene | NFree=Idx |
174 | 1 | equemene | |
175 | 1 | equemene | ELSE ! Tangent =0, matches IF (Norm.GT.eps) THEN |
176 | 1 | equemene | if (debug) WRITE(*,*) "Tangent=0, using full displacement" |
177 | 1 | equemene | NFree=NCoord |
178 | 1 | equemene | END IF !IF (Norm.GT.eps) THEN |
179 | 1 | equemene | |
180 | 1 | equemene | if (debug) WRITE(*,*) 'DBG Step_RFO_All NFree=',NFree |
181 | 1 | equemene | |
182 | 1 | equemene | |
183 | 1 | equemene | ! We now calculate the new step |
184 | 1 | equemene | ! we project the hessian onto the free vectors |
185 | 1 | equemene | ALLOCATE(hfree(NFree,NFree),htmp(NCoord,NFree),Grad_f(NFree),Step_f(NFree)) |
186 | 1 | equemene | DO J=1,NFree |
187 | 1 | equemene | DO I=1,NCoord |
188 | 1 | equemene | Htmp(I,J)=0.d0 |
189 | 1 | equemene | DO K=1,NCoord |
190 | 1 | equemene | Htmp(I,J)=htmp(I,J)+Hess(I,K)*vfree(K,J) |
191 | 1 | equemene | END DO |
192 | 1 | equemene | END DO |
193 | 1 | equemene | END DO |
194 | 1 | equemene | DO J=1,NFree |
195 | 1 | equemene | DO I=1,NFree |
196 | 1 | equemene | HFree(i,j)=0.d0 |
197 | 1 | equemene | DO K=1,NCoord |
198 | 1 | equemene | HFree(i,j)=hfree(i,j)+vfree(k,i)*htmp(k,j) |
199 | 1 | equemene | END DO |
200 | 1 | equemene | END DO |
201 | 1 | equemene | END DO |
202 | 1 | equemene | |
203 | 1 | equemene | ! We diagonalize the hessian or its inverse |
204 | 1 | equemene | ALLOCATE(eigval(NFree), eigvec(NFree,NFree), eigvli(NFree)) |
205 | 1 | equemene | |
206 | 1 | equemene | call Jacobi(Hfree,NFree,eigvli,eigvec,NFree) |
207 | 1 | equemene | |
208 | 1 | equemene | if (debug) THEN |
209 | 1 | equemene | WRITE(*,*) 'Eigensystem, Step_RFO_all.f90, L225' |
210 | 1 | equemene | fmt2='(I5,":",F8.3," -", (1X,F10.4))' |
211 | 1 | equemene | WRITE(fmt2(19:20),'(I2)') min(NFree,99) |
212 | 1 | equemene | DO I=1,NFree |
213 | 1 | equemene | WRITE(*,fmt2) I,Eigvli(I),eigvec(:,I) |
214 | 1 | equemene | END DO |
215 | 1 | equemene | END IF |
216 | 1 | equemene | |
217 | 1 | equemene | ! We inverse the eigenvalues if Hess corresponds to Hessian inverse |
218 | 1 | equemene | IF (Hinv) THEN |
219 | 1 | equemene | do J=1,NFree |
220 | 1 | equemene | if (abs(eigvli(j)) <= tiny) eigvli(j) = zero |
221 | 1 | equemene | eigval(j) = sign (eigvli(j)**2 / (dele3 + abs(eigvli(j))**3), eigvli(j)) |
222 | 1 | equemene | if (abs(eigval(j)) <= tiny) eigval(j) = zero |
223 | 1 | equemene | end do |
224 | 1 | equemene | ELSE |
225 | 1 | equemene | eigval=eigvli |
226 | 1 | equemene | END IF |
227 | 1 | equemene | |
228 | 1 | equemene | call trie(NFree,eigval,eigvec,NFree) |
229 | 1 | equemene | |
230 | 1 | equemene | DO I=1,NFree |
231 | 1 | equemene | Grad_f(I)=dot_product(reshape(vfree(:,I),(/NCoord/)),grad) |
232 | 1 | equemene | END DO |
233 | 1 | equemene | |
234 | 1 | equemene | ! We now construct the step |
235 | 1 | equemene | |
236 | 1 | equemene | Step_f=0.d0 |
237 | 1 | equemene | DO I=1,NFree |
238 | 1 | equemene | grd= dot_product(grad_f,reshape(eigvec(:,i),(/NFree/))) |
239 | 1 | equemene | eval = 0.5 * (abs(eigval(i)) + sqrt (eigval(i)**2 + 4.*grd**2)) |
240 | 1 | equemene | dx = (-grd) / eval |
241 | 1 | equemene | step_f = step_f + dx * eigvec(:,i) |
242 | 1 | equemene | if (debug) write (*,*) i,eigval(i),eval,grd,dx |
243 | 1 | equemene | END DO |
244 | 1 | equemene | |
245 | 1 | equemene | Step=0.d0 |
246 | 1 | equemene | ! PFL 04 Apr 2008 -> |
247 | 1 | equemene | ! Grad is once again modified |
248 | 1 | equemene | ! Grad=0.d0 |
249 | 1 | equemene | DO I=1,NFree |
250 | 1 | equemene | Step=Step+ step_f(i)*vfree(:,i) |
251 | 1 | equemene | ! Grad=Grad+ Grad_f(i)*vfree(:,i) |
252 | 1 | equemene | END DO |
253 | 1 | equemene | ! <- PFL 04 Apr 2008 |
254 | 1 | equemene | |
255 | 1 | equemene | DEALLOCATE(eigval,eigvec,eigvli,hfree,htmp,grad_f,step_f) |
256 | 1 | equemene | |
257 | 1 | equemene | if (debug) THEN |
258 | 1 | equemene | WRITE(*,*) 'DBG Step_RFO_All Step' |
259 | 1 | equemene | WRITE(*,'(12(1X,F8.4))') Step(1:Idx) |
260 | 1 | equemene | END IF |
261 | 1 | equemene | |
262 | 1 | equemene | if (debug) WRITE(*,*) "=========================== Step_RFO_All Over ====================" |
263 | 1 | equemene | |
264 | 1 | equemene | END SUBROUTINE STEP_RFO_ALL |
265 | 1 | equemene |