root / src / Opt_Geom.f90
Historique | Voir | Annoter | Télécharger (20,22 ko)
1 |
|
---|---|
2 |
SUBROUTINE Opt_geom(IGeom,Nat,NCoord,Coord,Geom,E,Flag_Opt_Geom,Step_method) |
3 |
|
4 |
! This subroutine optimizes a geometry. |
5 |
! Initially, it was mainly here for debugging purposes.. |
6 |
!so It has been designed to be almost independent of the rest of the code. |
7 |
! It is now an (almost) officiel option. |
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 VarTypes |
41 |
use Path_module, only : maxcyc,sthresh,gthresh,Hinv,Smax,Nom,Atome,OrderInv,indzmat,& |
42 |
UMat,ScanCoord,Coordinate,NPrim,& |
43 |
BTransInv,BTransInv_local,Xprimitive_t,ScanCoord,& |
44 |
Coordinate,Pi,UMat_local,NCart, DynMaxStep,FPrintGeom,GeomFile, AtName,Renum,Order, & |
45 |
FormAna,NbVar, PrintGeomFactor,AnaGeom |
46 |
|
47 |
use Io_module |
48 |
|
49 |
IMPLICIT NONE |
50 |
|
51 |
INTEGER(KINT), INTENT(IN) :: Nat,NCoord,IGeom |
52 |
CHARACTER(32), INTENT(IN) :: Coord |
53 |
CHARACTER(32), INTENT(IN) :: Step_method |
54 |
REAL(KREAL), INTENT(INOUT) :: Geom(NCoord) |
55 |
REAL(KREAL), INTENT(OUT) :: E |
56 |
LOGICAL, INTENT(IN) :: Flag_Opt_Geom |
57 |
|
58 |
|
59 |
INTERFACE |
60 |
function valid(string) result (isValid) |
61 |
CHARACTER(*), intent(in) :: string |
62 |
logical :: isValid |
63 |
END function VALID |
64 |
|
65 |
subroutine Egrad(E,Geom,Grad,NCoord,IGeom,IOpt,GeomCart,FOptGeom,GeomOld,GeomCart_old) |
66 |
|
67 |
! This routines calculates the energy E and the gradient Grad of |
68 |
! a molecule with Geometry Geom (may be in internal coordinates), |
69 |
! using for now, either Gaussian or Ext, more general later. |
70 |
|
71 |
use Path_module, only : Nat,AtName,Coord,dzdc,indzmat,Nom,Atome,massat,unit, & |
72 |
prog,NCart,XyzGeomF,IntCoordF,BTransInv, XyzGeomI, & |
73 |
GeomOld_all,BTransInvF,BTransInv_local,UMatF,UMat_local & |
74 |
, BprimT,a0,ScanCoord, Coordinate,NPrim,BMat_BakerT,BBT,BBT_inv & |
75 |
, Order,OrderInv, XPrimitiveF |
76 |
|
77 |
! IntCoordF(NGeomF,NCoord),GeomOld_all(NGeomF,NCoord) |
78 |
! allocated in Path.f90 |
79 |
|
80 |
use Io_module |
81 |
|
82 |
! Energy (calculated if F300K=.F., else estimated) |
83 |
REAL(KREAL), INTENT (OUT) :: E |
84 |
! NCoord: Number of the degrees of freedom |
85 |
! IGeom: index of the geometry. |
86 |
INTEGER(KINT), INTENT (IN) :: NCoord, IGeom, IOpt |
87 |
! Geometry at which gradient is calculated (cf Factual also): |
88 |
REAL(KREAL), INTENT (INOUT) :: Geom(NCoord) |
89 |
! Gradient calculated at Geom geometry: |
90 |
REAL(KREAL), INTENT (OUT) :: Grad(NCoord) |
91 |
! Cartesian geometry corresponding to (Internal Geometry) Geom: |
92 |
REAL(KREAL), INTENT (OUT) :: GeomCart(Nat,3) |
93 |
!!! Optional, just for geometry optimization with Baker coordinates |
94 |
REAL(KREAL), INTENT (IN), OPTIONAL :: GeomCart_old(Nat,3) |
95 |
REAL(KREAL), INTENT (INOUT), OPTIONAL :: GeomOld(NCoord) |
96 |
! FOptGeom is a flag indicating if we are doing a geom optimization |
97 |
! it can be omitted so that we use a local flag: Flag_Opt_Geom |
98 |
LOGICAL,INTENT (IN), OPTIONAL :: FOptGeom |
99 |
! if FOptGeom is given Flag_Opt_Geom=FOptGeom, else Flag_Opt_Geom=F |
100 |
LOGICAL :: Flag_Opt_Geom |
101 |
|
102 |
END subroutine Egrad |
103 |
|
104 |
END INTERFACE |
105 |
|
106 |
|
107 |
LOGICAL :: debug |
108 |
LOGICAL :: FiniS,FiniG,Fini |
109 |
LOGICAL, SAVE :: FRST=.TRUE. |
110 |
|
111 |
! Variables |
112 |
INTEGER(KINT) :: IOpt, I,J,Iat, IBEG |
113 |
REAL(KREAL), ALLOCATABLE :: GradTmp(:),ZeroVec(:) ! 3*Nat or 3*Nat-6 |
114 |
REAL(KREAL), ALLOCATABLE :: Step(:) ! 3*Nat or 3*Nat-6 |
115 |
REAL(KREAL), ALLOCATABLE :: GeomOld(:),GradOld(:) ! (3*Nat or 3*Nat-6) |
116 |
REAL(KREAL), ALLOCATABLE :: GeomRef(:) ! (3*Nat or 3*Nat-6) |
117 |
REAL(KREAL), ALLOCATABLE :: GeomTmp2(:),GradTmp2(:) ! 3*Nat or 3*Nat-6 |
118 |
REAL(KREAL), ALLOCATABLE :: Hess_local(:,:) |
119 |
REAL(KREAL), ALLOCATABLE :: GeomCart(:,:) !(Nat,3) |
120 |
REAL(KREAL), ALLOCATABLE :: GeomCart_old(:,:) !(Nat,3) |
121 |
REAL(KREAL), ALLOCATABLE :: Hprim(:,:) !(NPrim,NPrim) |
122 |
REAL(KREAL), ALLOCATABLE :: HprimU(:,:) !(NPrim,3*Nat-6)) |
123 |
REAL(KREAL), ALLOCATABLE :: NewGeom(:) !NCoord=3*Nat-6 |
124 |
REAL(KREAL), ALLOCATABLE :: NewGradTmp(:) |
125 |
REAL(KREAL), ALLOCATABLE :: Hess_local_inv(:,:) ! used in diis |
126 |
REAL(KREAL) :: NormStep, FactStep, HP, MaxStep,NormGrad |
127 |
REAL(KREAL) :: Eold, Eini |
128 |
! Values contains the values for the geometry analizes |
129 |
REAL(KREAL), ALLOCATABLE :: Values(:) ! NbVar |
130 |
CHARACTER(LCHARS) :: Line |
131 |
|
132 |
debug=valid('OptGeom') |
133 |
|
134 |
E=0. |
135 |
Eold=0. |
136 |
Eini=0. |
137 |
MaxStep=SMax |
138 |
|
139 |
if (debug) Call Header("Entering Geom Optimization") |
140 |
|
141 |
ALLOCATE(GradTmp2(NCoord),GeomTmp2(NCoord),GradTmp(NCoord),Step(NCoord)) |
142 |
ALLOCATE(GradOld(NCoord),GeomOld(NCoord),ZeroVec(NCoord)) |
143 |
ALLOCATE(GeomRef(NCoord)) |
144 |
ALLOCATE(Hess_local(NCoord,NCoord)) |
145 |
ALLOCATE(GeomCart(Nat,3),GeomCart_old(Nat,3)) |
146 |
ALLOCATE(NewGeom(NCoord)) |
147 |
ALLOCATE(NewGradTmp(NCoord)) |
148 |
ALLOCATE(Hess_local_inv(NCoord,NCoord)) |
149 |
|
150 |
if (NbVar>0) THEN |
151 |
ALLOCATE(Values(NbVar)) |
152 |
END IF |
153 |
FormAna(5:8)=" I5 " |
154 |
IOpt=0 |
155 |
ZeroVec=0.d0 |
156 |
|
157 |
! Initialize the Hessian |
158 |
Hess_local=0. |
159 |
|
160 |
SELECT CASE (COORD) |
161 |
CASE ('ZMAT') |
162 |
! We use the fact that we know that approximate good hessian values |
163 |
! are 0.5 for bonds, 0.1 for valence angle and 0.02 for dihedral angles |
164 |
Hess_local(1,1)=0.5d0 |
165 |
Hess_local(2,2)=0.5d0 |
166 |
Hess_local(3,3)=0.1d0 |
167 |
DO J=1,Nat-3 |
168 |
Hess_local(3*J+1,3*J+1)=0.5d0 |
169 |
Hess_local(3*J+2,3*J+2)=0.1d0 |
170 |
Hess_local(3*J+3,3*J+3)=0.02d0 |
171 |
END DO |
172 |
IF (HInv) THEN |
173 |
DO I=1,NCoord |
174 |
Hess_local(I,I)=1.d0/Hess_local(I,I) |
175 |
END DO |
176 |
END IF |
177 |
|
178 |
IF (Step_method .EQ. "RFO") Then |
179 |
Hess_local=0. |
180 |
DO I=1,NCoord |
181 |
Hess_local(I,I)=1.d0 |
182 |
END DO |
183 |
END IF |
184 |
|
185 |
CASE ('BAKER') |
186 |
! UMat(NPrim,3*Nat-6) |
187 |
BTransInv_local = BTransInv |
188 |
UMat_local = UMat |
189 |
ALLOCATE(Hprim(NPrim,NPrim),HprimU(NPrim,NCoord)) |
190 |
Hprim=0.d0 |
191 |
ScanCoord=>Coordinate |
192 |
I=0 |
193 |
DO WHILE (Associated(ScanCoord%next)) |
194 |
I=I+1 |
195 |
SELECT CASE (ScanCoord%Type) |
196 |
CASE ('BOND') |
197 |
Hprim(I,I) = 0.5d0 |
198 |
CASE ('ANGLE') |
199 |
Hprim(I,I) = 0.2d0 |
200 |
CASE ('DIHEDRAL') |
201 |
Hprim(I,I) = 0.1d0 |
202 |
END SELECT |
203 |
ScanCoord => ScanCoord%next |
204 |
END DO |
205 |
|
206 |
! Hprim U: |
207 |
HprimU=0.d0 |
208 |
DO I=1, NCoord |
209 |
DO J=1,NPrim |
210 |
HprimU(:,I) = HprimU(:,I) + Hprim(:,J)*UMat(J,I) |
211 |
END DO |
212 |
END DO |
213 |
|
214 |
! Hess = U^T Hprim U: |
215 |
Hess_local=0.d0 |
216 |
DO I=1, NCoord |
217 |
DO J=1,NPrim |
218 |
! UMat^T is needed below. |
219 |
Hess_local(:,I) = Hess_local(:,I) + UMat(J,:)*HprimU(J,I) |
220 |
END DO |
221 |
END DO |
222 |
|
223 |
!Print *, 'Hprim=' |
224 |
DO I=1,NPrim |
225 |
! WRITE(*,'(10(1X,F6.3))') Hprim(I,:) |
226 |
END DO |
227 |
!Print *, 'UMat=' |
228 |
DO I=1,NPrim |
229 |
! WRITE(*,'(3(1X,F6.3))') UMat(I,1:3) |
230 |
END DO |
231 |
!Print *, 'HprimU=' |
232 |
DO I=1,NPrim |
233 |
! WRITE(*,'(3(1X,F6.3))') HprimU(I,1:3) |
234 |
END DO |
235 |
!Print *, 'Hess_local=' |
236 |
DO I=1,NCoord |
237 |
! WRITE(*,'(3(1X,F6.3))') Hess_local(I,1:3) |
238 |
END DO |
239 |
|
240 |
DEALLOCATE(Hprim,HprimU) |
241 |
|
242 |
IF (HInv) THEN |
243 |
Call GenInv(NCoord,Hess_local,Hess_local_inv,NCoord) |
244 |
Hess_local = Hess_local_inv |
245 |
END IF |
246 |
|
247 |
!Print *, 'Hess_local after inversion=' |
248 |
! DO I=1,NCoord |
249 |
! WRITE(*,'(3(1X,F6.3))') Hess_local(I,1:3) |
250 |
! END DO |
251 |
|
252 |
IF (Step_method .EQ. "RFO") Then |
253 |
Hess_local=0. |
254 |
DO I=1,NCoord |
255 |
Hess_local(I,I)=0.5d0 |
256 |
END DO |
257 |
END IF |
258 |
|
259 |
CASE ('MIXED','CART','HYBRID') |
260 |
DO J=1,NCoord |
261 |
Hess_local(J,J)=1. |
262 |
END DO |
263 |
CASE DEFAULT |
264 |
WRITE (*,*) "Coord=",TRIM(COORD)," not recognized, opt_Geom.f90, L164. Stop" |
265 |
STOP |
266 |
END SELECT |
267 |
|
268 |
! Go to optimization |
269 |
GeomOld=0.d0 ! Internal coordinates |
270 |
GeomCart_old=0.d0 ! Cartesian coordinates |
271 |
|
272 |
IF (FPrintGeom) THEN |
273 |
OPEN(IOGeom,File=GeomFile) |
274 |
END IF |
275 |
|
276 |
Fini=.FALSE. |
277 |
DO WHILE ((IOpt.LT.MaxCyc).AND.(.NOT.Fini)) |
278 |
IOpt=IOpt+1 |
279 |
|
280 |
Write(Line,'(1X,A,I5)') "Iteration ",Iopt |
281 |
Call Header(TRIM(Line)) |
282 |
WRITE(IoOut,*) "Current Geometry" |
283 |
Line="" |
284 |
Call PrintGeom(Line,Nat,NCoord,Geom,Coord,IOOUT,Atome,Order,OrderInv,IndZmat) |
285 |
if (COORD/="CART") THEN |
286 |
WRITE(IoOut,*) "Current Geometry in Cartesian coordinates" |
287 |
Call PrintGeom(Line,Nat,NCoord,GeomCart,"CART",IOOUT,Atome,Order,OrderInv,IndZmat) |
288 |
END IF |
289 |
|
290 |
WRITE(IoOut,*) "Computing energy and gradient" |
291 |
! Calculate the energy and gradient |
292 |
IF (debug) THEN |
293 |
WRITE(*,*) 'L134, DBG Opt_Geom, COORD=',TRIM(COORD),' IOpt=',IOpt |
294 |
WRITE(*,*) "Energy and Coordinates:" |
295 |
WRITE(*,'(F12.6,12(1X,F8.3))') E,Geom(1:min(NCoord,12)) |
296 |
WRITE(*,*) "Geom Old:" |
297 |
WRITE(*,'(F12.6,12(1X,F8.3))') GEomOld(1:min(NCoord,13)) |
298 |
WRITE(*,*) "Grad Old:" |
299 |
WRITE(*,'(F12.6,12(1X,F8.3))') GradOld(1:min(NCoord,13)) |
300 |
END IF |
301 |
|
302 |
!Call EGrad(E,Geom,GradTmp,NCoord) |
303 |
IF (COORD.EQ.'BAKER') THEN |
304 |
! GradTmp is gradient and calculated in Egrad.F, INTENT(OUT). |
305 |
! GeomCart has INTENT(OUT) |
306 |
! GeomRef is modified in Egrag_baker, so we should not use GeomOld variable |
307 |
GeomRef=GeomOld |
308 |
Call EGrad(E,Geom,GradTmp,NCoord,IGeom,IOpt,GeomCart,Flag_Opt_Geom, & |
309 |
GeomRef,GeomCart_old) |
310 |
GeomCart_old=GeomCart |
311 |
ELSE |
312 |
Call EGrad(E,Geom,GradTmp,NCoord,IGeom,IOpt,GeomCart) |
313 |
END IF |
314 |
!!!!!!!!!!! PFL March 2013 !!!!!!!!!!!!! |
315 |
! We have a pb with the format of GradTmp(Nat,3) whereas it is 3,Nat in Egrad |
316 |
! |
317 |
! This is a path for CART coordinates !!! |
318 |
IF (COORD=="CART") THEN |
319 |
Step=reshape(reshape(GradTmp,(/3,Nat/),ORDER=(/2,1/)),(/3*Nat/)) |
320 |
GradTmp=Step |
321 |
END IF |
322 |
!!!!!!!!!!!!!!!!!! PFL March 2013 !!!!!!!!!!!!!!!!!!!! |
323 |
|
324 |
WRITE(IoOut,'(1X," Energy E=",F15.6,A)') E,TRIM(UnitProg) |
325 |
WRITE(IoOut,*) "Gradient for current geometry" |
326 |
Call PrintGeom(Line,Nat,NCoord,GradTmp,Coord,IOOUT,Atome,Order,OrderInv,IndZmat) |
327 |
|
328 |
If (Iopt==1) EIni=E |
329 |
|
330 |
IF (debug) THEN |
331 |
WRITE(*,*) 'L198, DBG Opt_Geom, COORD=',TRIM(COORD),' IOpt=',IOpt |
332 |
WRITE(*,*) "Energy and Coordinates:" |
333 |
WRITE(*,'(F12.6,12(1X,F8.3))') E,Geom(1:min(NCoord,12)) |
334 |
WRITE(*,*) "Geom Old:" |
335 |
WRITE(*,'(F12.6,12(1X,F8.3))') GEomOld(1:min(NCoord,12)) |
336 |
WRITE(*,*) "Grad:" |
337 |
WRITE(*,'(F12.6,12(1X,F8.3))') GradTmp(1:min(NCoord,12)) |
338 |
END IF |
339 |
|
340 |
IF (FPrintGeom) THEN |
341 |
WRITE(IoGeom,*) Nat |
342 |
WRITE(IoGeom,"(' Geom. ',I5,' Energy= ',F15.6)") IOpt, E |
343 |
|
344 |
DO I=1,Nat |
345 |
If (renum) THEN |
346 |
Iat=Order(I) |
347 |
WRITE(IoGeom,'(1X,A10,3(1X,F15.8),5X,3(1X,F15.8))') Trim(AtName(I)),GeomCart(Iat,:),GradTmp(3*Iat-2:3*Iat) |
348 |
ELSE |
349 |
Iat=OrderInv(I) |
350 |
WRITE(IoGeom,'(1X,A10,3(1X,F15.8),5X,3(1X,F15.8))') Trim(AtName(Iat)),GeomCart(I,:),GradTmp(3*I-2:3*I) |
351 |
END IF |
352 |
END DO |
353 |
END IF |
354 |
|
355 |
! do we have to analyze geometries ? |
356 |
If (AnaGeom) THEN |
357 |
If (NbVar>0) THEN |
358 |
Call AnalyzeGeom(GeomCart,Values) |
359 |
WRITE(IoDat,FormAna) Iopt,Values*PrintGeomFactor,(E-Eini)*ConvE,E |
360 |
if (debug) WRITE(*,FormAna) Iopt,Values*PrintGeomFactor,(E-Eini)*ConvE,E |
361 |
ELSE |
362 |
WRITE(IoDat,FormAna) Iopt,(E-Eini)*ConvE,E |
363 |
if (debug) WRITE(*,FormAna) Iopt,(E-Eini)*ConvE,E |
364 |
END IF |
365 |
END IF |
366 |
|
367 |
|
368 |
IF (IOpt.GE.2) THEN |
369 |
! We have enough geometries and gradient to update the hessian (or its |
370 |
! inverse) |
371 |
GradTmp2=GradTmp-GradOld |
372 |
GeomTmp2=Geom-GeomOld |
373 |
|
374 |
if (debug) Write(*,*) "Call Hupdate_all, Geom" |
375 |
IF (debug) THEN |
376 |
WRITE(*,*) "dx before calling",SHAPE(GeomTmp2) |
377 |
WRITE(*,'(12(1X,F8.4))') GeomTmp2(1:NCoord) |
378 |
WRITE(*,*) "dgrad before calling",SHAPE(GradTmp2) |
379 |
WRITE(*,'(12(1X,F8.4))') GradTmp2(1:NCoord) |
380 |
END IF |
381 |
Call Hupdate_all(NCoord,GeomTmp2,GradTmp2,Hess_local) |
382 |
END IF ! matches IF (IOpt.GE.2) THEN |
383 |
|
384 |
GradOld=GradTmp |
385 |
GeomOld=Geom |
386 |
|
387 |
! GradTmp becomes Step in Step_RFO_all. |
388 |
SELECT CASE (Step_method) |
389 |
CASE ('RFO') |
390 |
Call Step_RFO_all(NCoord,Step,IGeom,Geom,GradTmp,Hess_local,ZeroVec) |
391 |
GradTmp=Step |
392 |
CASE ('GDIIS') |
393 |
Call Step_DIIS(NewGeom,Geom,NewGradTmp,GradTmp,HP,E,Hess_local,NCoord,FRST) |
394 |
! q_{m+1} = q'_{m+1} - H^{-1}g'_{m+1} |
395 |
Geom=0.d0 |
396 |
DO I=1, NCoord |
397 |
! If Hinv=.False., then we need to invert Hess_local |
398 |
Geom(:) = Geom(:) + Hess_local(:,I)*NewGradTmp(I) |
399 |
END DO |
400 |
Geom(:) = NewGeom(:) - Geom(:) |
401 |
! GradTmp now becomes "step" below: |
402 |
GradTmp = Geom - GeomOld |
403 |
CASE ('GDIIST') |
404 |
Call Step_GDIIS_Simple_Err(NewGeom,Geom,NewGradTmp,GradTmp,HP,E,NCoord,FRST) |
405 |
! q_{m+1} = q'_{m+1} - H^{-1}g'_{m+1} |
406 |
Geom=0.d0 |
407 |
DO I=1, NCoord |
408 |
! If Hinv=.False., then we need to invert Hess_local |
409 |
Geom(:) = Geom(:) + Hess_local(:,I)*NewGradTmp(I) |
410 |
END DO |
411 |
Geom(:) = NewGeom(:) - Geom(:) |
412 |
! GradTmp now becomes "step" below: |
413 |
GradTmp = Geom - GeomOld |
414 |
CASE ('GEDIIS') |
415 |
Call Step_GEDIIS(NewGeom,Geom,GradTmp,E,Hess_local,NCoord,FRST) |
416 |
! GradTmp is actually "step" below: |
417 |
GradTmp = NewGeom - GeomOld |
418 |
!Call Step_GEDIIS_All(3,1,GradTmp,Geom,GradTmp,E,Hess_local,NCoord,FRST,ZeroVec) |
419 |
CASE DEFAULT |
420 |
WRITE (*,*) "Step_method=",TRIM(Step_method)," not recognized, opt_Geom.f90, L225. Stop" |
421 |
STOP |
422 |
END SELECT |
423 |
|
424 |
Fini=.TRUE. |
425 |
! If (IOpt.LT.5) GradTmp=(IOpt*GradTmp+(5-IOpt)*0.01*Grad(IGeom,:))/5.d0 |
426 |
NormStep=sqrt(DOT_Product(GradTmp,GradTmp)) |
427 |
if (debug) WRITE(*,'(A,E10.4,1X,A,E10.4)') 'DBG OptGeom L215, NormStep=', NormStep, 'Step Threshold=', SThresh |
428 |
FactStep=min(1.d0,MaxStep/NormStep) |
429 |
FiniS=((NormStep*FactStep).LE.SThresh) |
430 |
NormGrad=sqrt(DOT_Product(GradOld,GradOld)) ! GradOld is the value of gradients. |
431 |
if (debug) WRITE(*,'(A,E10.4,1X,A,E10.4)') 'DBG OptGeom L219, NormGrad (Gradient)=', NormGrad, 'Gradient Threshold=', GThresh |
432 |
FiniG=(NormGrad.LE.GThresh) |
433 |
Fini=FiniS.AND.FiniG |
434 |
if (debug) WRITE(*,*) "DBG OptGeom FactStep=",FactStep |
435 |
GradTmp=GradTmp*FactStep ! GradTmp is step here, from Step_RFO_all. |
436 |
|
437 |
WRITE(IoOut,*) " Converged ?" |
438 |
WRITE(IoOut,'(1X,A18,1X,A15,1X,A13,5X,A3)') " Criterion","Current Value","Threshold","Ok?" |
439 |
IF (FiniS) THEN |
440 |
WRITE(IoOUT,'(1X,A20,5X,F8.3,6X,F8.3,6X,A3)') "Stepsize :",NormStep,SThresh,"YES" |
441 |
ELSE |
442 |
WRITE(IoOUT,'(1X,A20,5X,F8.3,6X,F8.3,6X,A3)') "Stepsize :",NormStep,SThresh,"NO" |
443 |
END IF |
444 |
IF (FiniG) THEN |
445 |
WRITE(IoOUT,'(1X,A20,5X,F8.3,6X,F8.3,6X,A3)') "Grad norm :",NormGrad,GThresh,"YES" |
446 |
ELSE |
447 |
WRITE(IoOUT,'(1X,A20,5X,F8.3,6X,F8.3,6X,A3)') "Grad norm :",NormGrad,GThresh,"NO" |
448 |
END IF |
449 |
|
450 |
if (DynMaxStep.AND.(IOpt>1)) THEN |
451 |
If (E<EOld) Then |
452 |
MaxStep=min(1.1*MaxStep,2.*SMax) |
453 |
ELSE |
454 |
MaxStep=max(0.8*MaxStep,SMax/2.) |
455 |
END IF |
456 |
if (debug) WRITE(*,*) "Dynamically updated Maximum step in Opt_Geom:",MaxStep,MaxStep/SMax |
457 |
|
458 |
END IF |
459 |
|
460 |
Call Check_step(Coord,Nat,NCoord,GeomOld,GradTmp) |
461 |
|
462 |
! We add the step to the old geom |
463 |
Geom=GeomOld+GradTmp |
464 |
|
465 |
EOld=E |
466 |
|
467 |
IF (debug) THEN |
468 |
WRITE(*,*) "L235, DBG OptGeom, IGeom=",IGeom," IOpt=", IOpt |
469 |
SELECT CASE (COORD) |
470 |
CASE ('ZMAT','BAKER') |
471 |
!WRITE(*,'(12(1X,F8.3))') Geom(1:min(12,NCoord)) |
472 |
CASE('CART','HYBRID') |
473 |
DO Iat=1,Nat |
474 |
! PFL 30 Apr 2008 -> |
475 |
! Deleted ref to orderinv that is created only for coord in zmat, baker, hybrid. |
476 |
! WRITE(*,'(1X,A5,3(1X,F11.6))') Nom(Atome(OrderInv(indzmat(iat,1)))), & |
477 |
WRITE(*,'(1X,A5,3(1X,F11.6))') Nom(Atome(iat)), & |
478 |
Geom(3*Iat-2:3*Iat) |
479 |
! <- PFL 30 Apr 2008 |
480 |
END DO |
481 |
CASE('MIXED') |
482 |
DO Iat=1,NCart |
483 |
WRITE(*,'(1X,A5,3(1X,F11.6))') Nom(Atome(OrderInv(indzmat(iat,1)))), & |
484 |
Geom(3*Iat-2:3*Iat) |
485 |
END DO |
486 |
|
487 |
SELECT CASE (NCart) |
488 |
CASE(1) |
489 |
if (NAt.GE.2) THEN |
490 |
WRITE(*,'(1X,A5,3(1X,I5,1X,F11.6))') Nom(Atome(OrderInv(indzmat(2,1)))), & |
491 |
IndZmat(2,2),Geom(4) |
492 |
IBEG=5 |
493 |
END IF |
494 |
IF (NAT.GE.3) THEN |
495 |
WRITE(*,'(1X,A5,3(1X,I5,1X,F11.6))') Nom(Atome(OrderInv(indzmat(3,1)))), & |
496 |
IndZmat(3,2),Geom(5),IndZmat(3,3),Geom(6) |
497 |
IBeg=7 |
498 |
END IF |
499 |
CASE(2) |
500 |
WRITE(*,'(1X,A5,3(1X,I5,1X,F11.6))') Nom(Atome(OrderInv(indzmat(3,1)))), & |
501 |
IndZmat(3,2),Geom(7),IndZmat(3,3),Geom(8) |
502 |
IBeg=9 |
503 |
CASE DEFAULT |
504 |
IBeg=3*NCart+1 |
505 |
END SELECT |
506 |
|
507 |
DO Iat=max(4,NCart),Nat |
508 |
WRITE(*,'(1X,A5,3(1X,I5,1X,F11.6))') Nom(Atome(OrderInv(indzmat(iat,1)))), & |
509 |
IndZmat(iat,1),Geom(IBeg),IndZmat(3,2),Geom(IBeg+1), & |
510 |
IndZmat(3,3),Geom(IBeg+2)*180./pi |
511 |
IBeg=IBeg+3 |
512 |
END DO |
513 |
|
514 |
CASE DEFAULT |
515 |
WRITE(*,*) "Coord=",TRIM(COORD)," not recognized in OptGeom. L294." |
516 |
STOP |
517 |
END SELECT |
518 |
END IF ! matches IF (debug) THEN |
519 |
|
520 |
END DO ! matches DO WHILE ((IOpt.LT.MaxCyc).AND.(.NOT.Fini)) |
521 |
|
522 |
IF (Fini) THEN |
523 |
WRITE(Line,'(1X,A,I5,A,I5,A,F15.8)') "Optimization for geom ",IGeom," converged in ",Iopt," cycles" |
524 |
ELSE |
525 |
WRITE(Line,'(1X,A,I5,A,I5,A,F15.8)') "Optimization for geom ",IGeom," *NOT* converged in ",Iopt," cycles" |
526 |
END IF |
527 |
Call Header(Line) |
528 |
WRITE(IoOut,*) "Last Energy E=",E |
529 |
|
530 |
! WRITE(*,*) "Initial Geometry:" |
531 |
! DO I=1, Nat |
532 |
! WRITE(*,'(3(1X,F8.4))') XyzGeomI(IGeom,:,I) |
533 |
! END DO |
534 |
WRITE(IoOut,*) "Final Geometry:" |
535 |
|
536 |
Line="" |
537 |
Call PrintGeom(Line,Nat,NCoord,Geom,Coord,IOOUT,Atome,Order,OrderInv,IndZmat) |
538 |
if (COORD/="CART") THEN |
539 |
WRITE(IoOut,*) "Last Geometry in Cartesian coordinates" |
540 |
Call PrintGeom(Line,Nat,NCoord,GeomCart,"CART",IOOUT,Atome,Order,OrderInv,IndZmat) |
541 |
END IF |
542 |
|
543 |
|
544 |
! DO I=1, Nat |
545 |
! WRITE(*,'(3(1X,F8.4))') GeomCart(I,:) |
546 |
!IF (I .GT. 1) Then |
547 |
! WRITE(*,'(F6.4)') Sqrt(((GeomCart(I,1)-GeomCart(I-1,1))*(GeomCart(I,1)-GeomCart(I-1,1)))& |
548 |
! + ((GeomCart(I,2)-GeomCart(I-1,2))*(GeomCart(I,2)-GeomCart(I-1,2)))& |
549 |
! + ((GeomCart(I,3)-GeomCart(I-1,3))*(GeomCart(I,3)-GeomCart(I-1,3)))) |
550 |
!END IF |
551 |
! END DO |
552 |
|
553 |
IF (COORD .EQ. "BAKER") Then |
554 |
I=0 ! index for the NPrim (NPrim is the number of primitive coordinates). |
555 |
ScanCoord=>Coordinate |
556 |
DO WHILE (Associated(ScanCoord%next)) |
557 |
I=I+1 |
558 |
SELECT CASE (ScanCoord%Type) |
559 |
CASE ('BOND') |
560 |
WRITE(*,'(1X,I3,":",I5," - ",I5," = ",F10.4)') I,ScanCoord%At1,ScanCoord%At2,Xprimitive_t(I) |
561 |
CASE ('ANGLE') |
562 |
WRITE(*,'(1X,I3,":",I5," - ",I5," - ",I5," = ",F10.4)') I,ScanCoord%At1, & |
563 |
ScanCoord%At2, ScanCoord%At3,Xprimitive_t(I)*180./Pi |
564 |
CASE ('DIHEDRAL') |
565 |
WRITE(*,'(1X,I3,":",I5," - ",I5," - ",I5," - ",I5," = ",F10.4)') I,ScanCoord%At1,& |
566 |
ScanCoord%At2, ScanCoord%At3,ScanCoord%At4,Xprimitive_t(I)*180./Pi |
567 |
END SELECT |
568 |
ScanCoord => ScanCoord%next |
569 |
END DO ! matches DO WHILE (Associated(ScanCoord%next)) |
570 |
END IF |
571 |
|
572 |
DEALLOCATE(GeomCart) |
573 |
DEALLOCATE(GradTmp2,GeomTmp2,GradTmp,Step) |
574 |
DEALLOCATE(GradOld,GeomOld) |
575 |
DEALLOCATE(Hess_local) |
576 |
DEALLOCATE(GeomCart_old) |
577 |
DEALLOCATE(NewGeom,NewGradTmp) |
578 |
DEALLOCATE(Hess_local_inv) |
579 |
|
580 |
if (debug) Call Header("Geom Optimization Over") |
581 |
|
582 |
END SUBROUTINE Opt_geom |