Statistiques
| Révision :

root / src / Opt_Geom.f90

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