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