root / src / Path.f90 @ 1
Historique | Voir | Annoter | Télécharger (85,97 ko)
1 | 1 | equemene | ! This programs generates and optimizes a reaction path |
---|---|---|---|
2 | 1 | equemene | ! between at least two endpoints. |
3 | 1 | equemene | ! |
4 | 1 | equemene | ! It uses NAMELIST for input, see below ! |
5 | 1 | equemene | ! |
6 | 1 | equemene | ! v3.0 |
7 | 1 | equemene | ! First version entirely in Fortran. |
8 | 1 | equemene | ! It uses routines from Cart (path creation and parameterisation) |
9 | 1 | equemene | ! and from IRC06, especially routines for point optimization. |
10 | 1 | equemene | ! |
11 | 1 | equemene | ! TO DO: |
12 | 1 | equemene | ! 1) Possibility to read and/or calculate some hessian structures |
13 | 1 | equemene | ! 2) Use of internal coordinate to estimate the hessian for stable |
14 | 1 | equemene | ! species in a much better way... |
15 | 1 | equemene | ! |
16 | 1 | equemene | !!!!!!!!!!!!!!! |
17 | 1 | equemene | ! v3.1 |
18 | 1 | equemene | ! The Hessian update includes neighbour points. |
19 | 1 | equemene | ! |
20 | 1 | equemene | ! v3.2 |
21 | 1 | equemene | ! We add the option Hinv that uses the BFGS update of the Hessian inverse |
22 | 1 | equemene | ! |
23 | 1 | equemene | ! v3.3 |
24 | 1 | equemene | ! We add the full option for ZMAT coordinates, where all is done using |
25 | 1 | equemene | ! internal coordinates. |
26 | 1 | equemene | ! v3.31 |
27 | 1 | equemene | ! The step size is controlled using the step norm and not the maximum step |
28 | 1 | equemene | ! component. |
29 | 1 | equemene | ! v3.5 |
30 | 1 | equemene | ! Big modifications of Calc_zmat_const_frag in order to be able |
31 | 1 | equemene | ! to treat VASP geometries. |
32 | 1 | equemene | ! For now, only XYZ geometries are read and written. VASP interface |
33 | 1 | equemene | ! has to be written. |
34 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
35 | 1 | equemene | ! v3.6 |
36 | 1 | equemene | ! Some minor modif in Calc_zmat_const_frag to have nicer programming |
37 | 1 | equemene | ! and a new mode added: Coord=MIXED where part of the system |
38 | 1 | equemene | ! is extrapolated in cartesian coordinates and the rest of it in zmat. |
39 | 1 | equemene | ! it might be Useful for VASP, or when lots of atoms are frozen |
40 | 1 | equemene | ! by default, when Coord=MIXED, all frozen atoms are described in cartesian |
41 | 1 | equemene | ! coordinates. |
42 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
43 | 1 | equemene | ! v3.61 |
44 | 1 | equemene | ! We move further and further to VASP program. New variables added to the 'path' namelist: |
45 | 1 | equemene | ! input: what is the program used for the geometries ? |
46 | 1 | equemene | ! Possible values: xyz (or cart) for Xmol format; VASP. Xyz should be used for Gaussian |
47 | 1 | equemene | ! prog: what is the program used for the calculations ? |
48 | 1 | equemene | ! Possible values for now: gaussian, vasp. |
49 | 1 | equemene | ! For now (02/2007), when prog='vasp' is used, only the initial path is created. |
50 | 1 | equemene | ! That means that we have only added input/output subroutines :-) |
51 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
52 | 1 | equemene | ! v3.7 |
53 | 1 | equemene | ! We try to improve the optimization steps. For that, we first modify many routines |
54 | 1 | equemene | ! so that the new step is calculated in the 'free' degrees of freedom, as it is done |
55 | 1 | equemene | ! in IRC07/ADF for example. That will allow us to impose constraints in an easier way. |
56 | 1 | equemene | ! |
57 | 1 | equemene | ! v3.701 |
58 | 1 | equemene | ! Add a new option for the initial extrapolation of the Hessian |
59 | 1 | equemene | ! |
60 | 1 | equemene | !v3.71 |
61 | 1 | equemene | ! The optimization step has been improved... but the vfree part has not yet been included. |
62 | 1 | equemene | ! This has still to be done :-) |
63 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
64 | 1 | equemene | ! v3.8 |
65 | 1 | equemene | ! I have included part of the vfree procedure: for now freemv returns the Id |
66 | 1 | equemene | ! matrix, that is used to project out the tangent vector. |
67 | 1 | equemene | ! This improves the optimization a lot, but I will have to implement |
68 | 1 | equemene | ! a real freemw subroutine to have constraints there ! |
69 | 1 | equemene | ! v3.81 Technical version |
70 | 1 | equemene | ! I have added a new program 'Ext'. When this one is used, Path creates a Ext.in file, |
71 | 1 | equemene | ! calls Ext.exe file to get a Ext.out file that contains the Energy and the gradient. |
72 | 1 | equemene | ! Format: |
73 | 1 | equemene | ! Ext.in : Xmol format. The second line (comment in Xmol) contains the COORD name. |
74 | 1 | equemene | ! Ext.out: Energy on firt line (1X,D25.15), then gradient in CARTESIAN coordinates |
75 | 1 | equemene | ! (3(1X,D25.15)) format. Natoms lines. |
76 | 1 | equemene | ! TO DO: Gradient could be given in COORD format, ie cartesian for COORD=CART, XYZ or HYBRID |
77 | 1 | equemene | ! ZMAT for CORD=ZMAT (in that case, 6 zeros are there at the begining !) |
78 | 1 | equemene | ! For MIXED, it is equivalent to CART :-) |
79 | 1 | equemene | ! v3.811 |
80 | 1 | equemene | ! I have added a prog="TEST" option, where egradient calls egrad_test subroutine. |
81 | 1 | equemene | ! It then calculates the energy and gradient as it wants and it returns the cartesian |
82 | 1 | equemene | ! gradient. The purpose is to have an analytical approximation of the PES of the system |
83 | 1 | equemene | ! under study to gain some time in testing the program. This is not documented :-) |
84 | 1 | equemene | ! |
85 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
86 | 1 | equemene | ! v3.9 |
87 | 1 | equemene | ! In order to be fully interfaced with VASP, I have to change the architecture |
88 | 1 | equemene | ! of the program. In particular, with VASP, one can use a Para8+NEB routine |
89 | 1 | equemene | ! of VASP to calculate energy+forces for all points of the path. |
90 | 1 | equemene | ! v3.91 |
91 | 1 | equemene | ! One small modification: in the cart list, one can freeze a whole sequence by |
92 | 1 | equemene | ! entering a negative number for the last atom of the sequence |
93 | 1 | equemene | ! for example : cart=1 -160 165 -170 will define atoms from 1 to 160 and from |
94 | 1 | equemene | ! 165 to 170 (included) as cartesian atoms. |
95 | 1 | equemene | ! Of course, Same applies to Frozen |
96 | 1 | equemene | ! v3.92 / v3.93 |
97 | 1 | equemene | ! Slight modifications. One noticeable: when using Vasp, the program analyses the |
98 | 1 | equemene | ! displacements to suggest which atoms could be described in CART. |
99 | 1 | equemene | ! v3.94 |
100 | 1 | equemene | ! VaspMode=Para now implemented. One needs to be careful in defining 'ProgExe'. |
101 | 1 | equemene | ! In particular, one must put the mpirun command in ProgExe !!! There is NO test. |
102 | 1 | equemene | ! v3.95 |
103 | 1 | equemene | ! When using internal coordinates (zmat, hybrid or mixes), Path calculates the number |
104 | 1 | equemene | ! of fragments for each geometry. The reference one (ie the one used to compute the internal |
105 | 1 | equemene | ! coordinates) is now the one with the least fragments. |
106 | 1 | equemene | ! user can also choose one geometry by specifying IGeomRef in the Path namelis. |
107 | 1 | equemene | ! v3.96 |
108 | 1 | equemene | ! I have added a test for the geometry step: it does not allow valence angle to |
109 | 1 | equemene | ! be negative or bigger than 180. I hope that this might help geometry optimization |
110 | 1 | equemene | ! when dealing with nearly linear molecules. |
111 | 1 | equemene | ! v3.961 |
112 | 1 | equemene | ! The options cart and frozen are now LOGICAL: |
113 | 1 | equemene | ! Fcart=T indicates that a &cartlist namelist should be read ! |
114 | 1 | equemene | ! Ffrozen=T indicates that a &frozenlist namelist should be read ! |
115 | 1 | equemene | ! TO DO: Autocart=T indicates that the atoms described in cartesian coordiantes should |
116 | 1 | equemene | ! be found automatically |
117 | 1 | equemene | ! v3.97 |
118 | 1 | equemene | ! Baker has been implemented by P. Dayal: we are interpolating Xint for now. |
119 | 1 | equemene | ! TO do: interpolate Umat ? |
120 | 1 | equemene | ! ----- |
121 | 1 | equemene | ! v3.971 |
122 | 1 | equemene | ! AutoCart=T is being implemented. Goal: having a 'black box' version for Vasp users. |
123 | 1 | equemene | ! Vmd: True if user wants to watch the path using VMD. Only used for VASP for now. |
124 | 1 | equemene | !------------ |
125 | 1 | equemene | ! v3.98 |
126 | 1 | equemene | ! Calc_zmat has been replaced by Calc_zmat_frag which is more robust. |
127 | 1 | equemene | ! Still missing: linear molecules and some tests. |
128 | 1 | equemene | ! |
129 | 1 | equemene | ! v3.981 |
130 | 1 | equemene | ! * Added a non document flag in .valid file that switch on the numerical |
131 | 1 | equemene | ! calculation of the hessian instead of the update. |
132 | 1 | equemene | ! * Added HesUpd variable in the namelist. Default value is MS for path |
133 | 1 | equemene | ! optimization because it does not imposes a positive hessian, and BFGS |
134 | 1 | equemene | ! for geometry optimization |
135 | 1 | equemene | ! v 4.0 |
136 | 1 | equemene | ! * This version has been made public within the CARTE project. |
137 | 1 | equemene | ! * Added: |
138 | 1 | equemene | ! - Step_method to choose the optimization method: RFO or Diis |
139 | 1 | equemene | ! - DynMaxStep: if TRUE, the maximum size of a step is updated at each step. |
140 | 1 | equemene | ! If energy goes up, Smax=Smax*0.8, if not Smax=Smax*1.2. |
141 | 1 | equemene | ! It is ensured that the dynamical Smax is within [0.5*SMax_0,2*Smax_0] |
142 | 1 | equemene | ! |
143 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!! |
144 | 1 | equemene | ! v4.1 |
145 | 1 | equemene | ! * Para mode has been partly implemented for Gaussian. |
146 | 1 | equemene | ! VaspMode is thus now 'RunMode' and can be Serial or Para |
147 | 1 | equemene | ! Only Gaussian and VASP are supported for Para mode now. |
148 | 1 | equemene | ! v4.12 |
149 | 1 | equemene | ! Some bugs in unconstrained zmat construction are corrected. |
150 | 1 | equemene | ! v4.13 |
151 | 1 | equemene | ! Prakash has implemented the GEDIIS optimization procedure. |
152 | 1 | equemene | ! v4.14 |
153 | 1 | equemene | ! There is a small problem for some inputs in VASP, where the |
154 | 1 | equemene | ! last geometry is not the one given by the user. |
155 | 1 | equemene | ! It seems to come from the fact that some people try to freeze |
156 | 1 | equemene | ! some unfrozen atoms |
157 | 1 | equemene | ! So some tests have been added to check that frozen atoms do not move. |
158 | 1 | equemene | !!! |
159 | 1 | equemene | ! v4.15 |
160 | 1 | equemene | ! There were some bugs when reading and expanding cartlist and frozenlist |
161 | 1 | equemene | ! I have changed the way frozen atoms are compared by adding partial alignment. |
162 | 1 | equemene | ! v4.16 |
163 | 1 | equemene | ! Some bugs were corrected. |
164 | 1 | equemene | ! v4.17 |
165 | 1 | equemene | ! Added MOPAC as a program. |
166 | 1 | equemene | ! v4.175 |
167 | 1 | equemene | ! Added Three more parameters for defining the input and output names for |
168 | 1 | equemene | ! the calculations. |
169 | 1 | equemene | ! CalcName: Prefix for the files used for the energy and gradient calculations |
170 | 1 | equemene | ! ISuffix: Suffix for the input file |
171 | 1 | equemene | ! OSuffix: suffix for the output file. |
172 | 1 | equemene | ! This maters for Gaussian for example. |
173 | 1 | equemene | ! |
174 | 1 | equemene | ! v4.177 (P) 2010 Nov 22 |
175 | 1 | equemene | ! - We add TurboMole as a new external code. |
176 | 1 | equemene | ! - Subtle change for Input: the default is XYZ whatever the code, except |
177 | 1 | equemene | ! for VASP. |
178 | 1 | equemene | ! |
179 | 1 | equemene | ! v4.178 (P) 2010 Nov 28 |
180 | 1 | equemene | ! - We add the possibility to call CHAMFRE reactive force field using |
181 | 1 | equemene | ! prog=TEST2 or CHAMFRE |
182 | 1 | equemene | ! |
183 | 1 | equemene | |
184 | 1 | equemene | |
185 | 1 | equemene | PROGRAM PathOpt |
186 | 1 | equemene | |
187 | 1 | equemene | use VarTypes |
188 | 1 | equemene | use Path_module |
189 | 1 | equemene | use Io_module |
190 | 1 | equemene | |
191 | 1 | equemene | IMPLICIT NONE |
192 | 1 | equemene | |
193 | 1 | equemene | CHARACTER(132) :: FileIn, FileOut, Line,Line2 |
194 | 1 | equemene | CHARACTER(32) :: Input,poscar |
195 | 1 | equemene | |
196 | 1 | equemene | INTEGER(KINT) :: I,J,K,IGeom,iat, IGeom0, IGeomF |
197 | 1 | equemene | INTEGER(KINT) :: IOpt |
198 | 1 | equemene | INTEGER(KINT) :: Idx, LineL,LenLine |
199 | 1 | equemene | INTEGER(KINT) :: N3at, NFree, Nfr |
200 | 1 | equemene | ! Temporary integer counter |
201 | 1 | equemene | INTEGER(KINT) :: NTmp |
202 | 1 | equemene | |
203 | 1 | equemene | INTEGER(KINT) :: List(2*MaxFroz) |
204 | 1 | equemene | |
205 | 1 | equemene | REAL(KREAL) :: E,FactStep,B(3) !E=Energy |
206 | 1 | equemene | REAL(KREAL) :: Alpha,sa,ca,norm,s,NormStep,NormGrad |
207 | 1 | equemene | REAL(KREAL) :: EReac,EProd,HP,HEAT ! HEAT=E |
208 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: GeomTmp(:),GradTmp(:),ZeroVec(:) !NCoord |
209 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: GradOld(:,:) ! (NGeomF,NCoord) |
210 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: GeomTmp2(:),GradTmp2(:) ! NCoord |
211 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: HessTmp(:,:) |
212 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: Hprim(:,:) !(NPrim,NPrim) |
213 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: HprimU(:,:) !(NPrim,3*Nat-6)) |
214 | 1 | equemene | LOGICAL, SAVE :: allocation_flag |
215 | 1 | equemene | |
216 | 1 | equemene | ! Flag to see if frozen atoms are frozen (see below) |
217 | 1 | equemene | LOGICAL :: FChkFrozen |
218 | 1 | equemene | |
219 | 1 | equemene | ! Energies for all points along the path at the previous iteration |
220 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: EPathold(:) ! NGeomF, where it is deallocated: Prakash |
221 | 1 | equemene | ! Maximum step allowed for this geometry |
222 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: MaxStep(:) ! NGeomF, where it is deallocated: Prakash |
223 | 1 | equemene | |
224 | 1 | equemene | LOGICAL, ALLOCATABLE :: FTmp(:) ! Nat |
225 | 1 | equemene | LOGICAL :: FFrozen,FCart |
226 | 1 | equemene | |
227 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
228 | 1 | equemene | ! |
229 | 1 | equemene | ! To analyse the frozen atoms |
230 | 1 | equemene | ! |
231 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: x1(:),y1(:),z1(:) ! nat |
232 | 1 | equemene | REAL(KREAL), ALLOCATABLE :: x2(:),y2(:),z2(:) ! nat |
233 | 1 | equemene | REAL(KREAL) :: MRot(3,3),Norm1,Norm2,Dist |
234 | 1 | equemene | LOGICAL, ALLOCATABLE :: ListAtFroz(:) |
235 | 1 | equemene | INTEGER(KINT) :: Iat1, Iat2, Iat3 |
236 | 1 | equemene | |
237 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
238 | 1 | equemene | ! |
239 | 1 | equemene | ! For VASP |
240 | 1 | equemene | ! |
241 | 1 | equemene | INTEGER(KINT), ALLOCATABLE :: NbAtType(:) !na |
242 | 1 | equemene | INTEGER(KINT) :: NbType, NbTypeUser |
243 | 1 | equemene | |
244 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
245 | 1 | equemene | |
246 | 1 | equemene | LOGICAL :: TChk |
247 | 1 | equemene | LOGICAL :: Debug, Fini,Flag_Opt_Geom |
248 | 1 | equemene | |
249 | 1 | equemene | ! INTEGER(KINT), EXTERNAL :: Iargc |
250 | 1 | equemene | INTEGER(KINT), EXTERNAL :: ConvertNumAt |
251 | 1 | equemene | |
252 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
253 | 1 | equemene | ! |
254 | 1 | equemene | ! For Debugging purposes |
255 | 1 | equemene | ! |
256 | 1 | equemene | LOGICAL :: FCalcHess |
257 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
258 | 1 | equemene | |
259 | 1 | equemene | |
260 | 1 | equemene | INTERFACE |
261 | 1 | equemene | function valid(string) result (isValid) |
262 | 1 | equemene | CHARACTER(*), intent(in) :: string |
263 | 1 | equemene | logical :: isValid |
264 | 1 | equemene | END function VALID |
265 | 1 | equemene | |
266 | 1 | equemene | SUBROUTINE Read_Geom(Input) |
267 | 1 | equemene | CHARACTER(32), INTENT(IN) :: input |
268 | 1 | equemene | END SUBROUTINE READ_GEOM |
269 | 1 | equemene | |
270 | 1 | equemene | subroutine hupdate_all (n, dx, dgrad, HessOld) |
271 | 1 | equemene | |
272 | 1 | equemene | IMPLICIT NONE |
273 | 1 | equemene | |
274 | 1 | equemene | INTEGER, PARAMETER :: KINT=KIND(1) |
275 | 1 | equemene | INTEGER, PARAMETER :: KREAL=KIND(1.0D0) |
276 | 1 | equemene | |
277 | 1 | equemene | INTEGER(KINT), INTENT(IN) :: n |
278 | 1 | equemene | real(KREAL) :: dx(n), dgrad(n), HessOld(n*n) |
279 | 1 | equemene | END subroutine hupdate_all |
280 | 1 | equemene | |
281 | 1 | equemene | SUBROUTINE Hinvup_BFGS_new(Nfree,ds,dgrad,Hess) |
282 | 1 | equemene | |
283 | 1 | equemene | IMPLICIT NONE |
284 | 1 | equemene | |
285 | 1 | equemene | INTEGER, PARAMETER :: KINT=KIND(1) |
286 | 1 | equemene | INTEGER, PARAMETER :: KREAL=KIND(1.D0) |
287 | 1 | equemene | |
288 | 1 | equemene | INTEGER(KINT), INTENT(IN) :: NFREE |
289 | 1 | equemene | REAL(KREAL), INTENT(INOUT) :: Hess(Nfree,Nfree) |
290 | 1 | equemene | REAL(KREAL), INTENT(IN) :: ds(Nfree) |
291 | 1 | equemene | REAL(KREAL), INTENT(IN) :: dGrad(Nfree) |
292 | 1 | equemene | |
293 | 1 | equemene | END subroutine Hinvup_BFGS_new |
294 | 1 | equemene | |
295 | 1 | equemene | |
296 | 1 | equemene | END INTERFACE |
297 | 1 | equemene | |
298 | 1 | equemene | Namelist/path/fact,r_cov,nat,ngeomi,ngeomf,debugFile, & |
299 | 1 | equemene | MW,mass,Ffrozen, renum, OptReac,OptProd,Coord,Step_method,MaxCyc, & |
300 | 1 | equemene | SMax, SThresh, GThresh,IReparam, IReparamT,Hinv, ISpline, PathOnly,Fcart, & |
301 | 1 | equemene | input,prog, ProgExe,RunMode, AtTypes,poscar,PathName, & |
302 | 1 | equemene | OptGeom,IniHup, HupNeighbour, hesUpd, & |
303 | 1 | equemene | FTan, EReac, EProd, IGeomRef, Vmd, AutoCart, DynMaxStep, & |
304 | 1 | equemene | NMaxPtPath, FrozTol, BoxTol,CalcName,ISuffix,OSuffix, WriteVasp, & |
305 | 1 | equemene | NGintMax, Align |
306 | 1 | equemene | |
307 | 1 | equemene | Namelist/cartlist/list |
308 | 1 | equemene | Namelist/frozenlist/list |
309 | 1 | equemene | |
310 | 1 | equemene | |
311 | 1 | equemene | Flag_Opt_Geom = .FALSE. ! Initialized. |
312 | 1 | equemene | |
313 | 1 | equemene | ! We read the files names |
314 | 1 | equemene | ! SELECT CASE (iargc()) |
315 | 1 | equemene | SELECT CASE (command_argument_count()) |
316 | 1 | equemene | CASE (2) |
317 | 1 | equemene | call getarg(1,FileIn) |
318 | 1 | equemene | OPEN(IOIN,FILE=FileIn,STATUS='UNKNOWN') |
319 | 1 | equemene | call getarg(2,FileOut) |
320 | 1 | equemene | OPEN(IOOUT,FILE=FileOut,STATUS='UNKNOWN') |
321 | 1 | equemene | CASE (1) |
322 | 1 | equemene | call getarg(1,FileIn) |
323 | 1 | equemene | IF ((FileIn=="-help").OR.(FileIn=="--help")) THEN |
324 | 1 | equemene | WRITE(*,*) "Path mini-help" |
325 | 1 | equemene | WRITE(*,*) "--------------" |
326 | 1 | equemene | WRITE(*,*) "" |
327 | 1 | equemene | WRITE(*,*) "Use: Path Input_file Output_file" |
328 | 1 | equemene | WRITE(*,*) "Input_file starts with a Namelist called path" |
329 | 1 | equemene | WRITE(*,*) "" |
330 | 1 | equemene | WRITE(*,*) "Compulsory variables are:" |
331 | 1 | equemene | WRITE(*,*) "NGeomi: Number of geometries defining the Initial path" |
332 | 1 | equemene | WRITE(*,*) "NGeomf: Number of geometries defining the Final path" |
333 | 1 | equemene | WRITE(*,*) "Nat : Number of atoms" |
334 | 1 | equemene | WRITE(*,*) "" |
335 | 1 | equemene | WRITE(*,*) "Other options" |
336 | 1 | equemene | WRITE(*,*) "Input: string that indicates the type of the input geometries." |
337 | 1 | equemene | WRITE(*,*) "Accepted values are: Cart (or Xmol or Xyz) or Vasp" |
338 | 1 | equemene | WRITE(*,*) "Prog: string that indicates the program that will be used for energy and gradient calculations." |
339 | 1 | equemene | WRITE(*,*) " Accepted values are: Gaussian, Vasp, Mopac or Ext" |
340 | 1 | equemene | WRITE(*,*) " In case of a Gaussian or Mopac calculations, input must be set to Cart." |
341 | 1 | equemene | WRITE(*,*) " One example of a gaussian/mopac input should be added at the end of the" |
342 | 1 | equemene | WRITE(*,*) " input file.See example file Test_G03.path or Test_Mopac.path" |
343 | 1 | equemene | WRITE(*,*) " In the case of a VASP calculation, if input is set to Cart, then" |
344 | 1 | equemene | WRITE(*,*) " the preamble of a VASP calculation should be added at the end of" |
345 | 1 | equemene | WRITE(*,*) " the input file. See example file Test_VASP_cart.path" |
346 | 1 | equemene | WRITE(*,*) " In the case of a VASP calculation, one should also give value of the " |
347 | 1 | equemene | WRITE(*,*) " Runmode variable" |
348 | 1 | equemene | WRITE(*,*) "Runmode: This indicates wether one should use VASP routine to calculate the energy" |
349 | 1 | equemene | WRITE(*,*) " and gradient of the whole path or not. If one wants to use VASP," |
350 | 1 | equemene | WRITE(*,*) " Runmode must be set to PARA." |
351 | 1 | equemene | WRITE(*,*) "PathName: Prefix used to save the path. Default is Path" |
352 | 1 | equemene | WRITE(*,*) "Poscar: string that will be used as the prefix for the different " |
353 | 1 | equemene | WRITE(*,*) " POSCAR files in a VASP calculations. Usefull only if PathOnly=.TRUE.," |
354 | 1 | equemene | WRITE(*,*) " not used for internal calculations." |
355 | 1 | equemene | WRITE(*,*) " CalcName: Prefix for the files used for the energy and gradient calculations" |
356 | 1 | equemene | WRITE(*,*) " ISuffix: Suffix for the input file." |
357 | 1 | equemene | WRITE(*,*) " OSuffix: suffix for the output file." |
358 | 1 | equemene | WRITE(*,*) "IGeomRef: Index of the geometry used to construct the internal coordinates." |
359 | 1 | equemene | WRITE(*,*) " Valid only for Coord=Zmat, Hybrid or Mixed" |
360 | 1 | equemene | WRITE(*,*) "Fact: REAL used to define if two atoms are linked." |
361 | 1 | equemene | WRITE(*,*) " If d(A,B)<=fact*(rcov(A)+rcov(B)), then A and B are considered Linked." |
362 | 1 | equemene | WRITE(*,*) "debugFile: Name of the file that indicates which subroutine should print debug info." |
363 | 1 | equemene | WRITE(*,*) "Coord: System of coordinates to use. Possible choices are:" |
364 | 1 | equemene | WRITE(*,*) " - CART (or Xyz): works in cartesian" |
365 | 1 | equemene | WRITE(*,*) " - Zmat: works in internal coordinates (Zmat)" |
366 | 1 | equemene | WRITE(*,*) " - Mixed: frozen atoms, as well as atoms defined by the " |
367 | 1 | equemene | WRITE(*,*) " 'cart' array(see below) are describe in CARTESIAN, whereas the" |
368 | 1 | equemene | WRITE(*,*) " others are described in Zmat" |
369 | 1 | equemene | WRITE(*,*) " - Baker: use of Baker coordinates, also called delocalized internal coordinates" |
370 | 1 | equemene | WRITE(*,*) " - Hybrid: geometries are described in zmat, but the gradient are used in cartesian" |
371 | 1 | equemene | WRITE(*,*) "Step_method: method to compute the step for optimizing a geometry; choices are:" |
372 | 1 | equemene | WRITE(*,*) " - RFO: Rational function optimization" |
373 | 1 | equemene | WRITE(*,*) " - GDIIS: Geometry optimization using direct inversion in the iterative supspace" |
374 | 1 | equemene | WRITE(*,*) " HesUpd: method to update the hessian. By default, it is Murtagh-Sargent" |
375 | 1 | equemene | WRITE(*,*) " Except for geometry optimization where it is BFGS." |
376 | 1 | equemene | WRITE(*,*) "MaxCyc: maximum number of iterations for the path optimization" |
377 | 1 | equemene | WRITE(*,*) "Smax: Maximum length of a step during path optimization" |
378 | 1 | equemene | WRITE(*,*) "SThresh: Step Threshold to consider that the path is stationary" |
379 | 1 | equemene | WRITE(*,*) "GThresh: Gradient Threshold to consider that the path is stationary, only orthogonal part is taken" |
380 | 1 | equemene | WRITE(*,*) "FTan: We moving the path, this gives the proportion of the displacement tangent to the path" |
381 | 1 | equemene | WRITE(*,*) " that is kept. FTan=1. corresponds to the full displacement, " |
382 | 1 | equemene | WRITE(*,*) " whereas FTan=0. gives a displacement orthogonal to the path." |
383 | 1 | equemene | WRITE(*,*) "IReparam: The path is not reparameterised at each iteration. This gives the frequency of reparameterization." |
384 | 1 | equemene | WRITE(*,*) "ISpline: By default, a linear interpolation is used to generate the path." |
385 | 1 | equemene | WRITE(*,*) " This option indicates the first step where spline interpolation is used." |
386 | 1 | equemene | WRITE(*,*) "" |
387 | 1 | equemene | WRITE(*,*) "Arrays:" |
388 | 1 | equemene | WRITE(*,*) "Rcov: Array containing the covalent radii of the first 80 elements." |
389 | 1 | equemene | WRITE(*,*) " You can modify it using, rcov(6)=0.8." |
390 | 1 | equemene | WRITE(*,*) "Mass: Array containing the atomic mass of the first 80 elements." |
391 | 1 | equemene | WRITE(*,*) "AtTypes: Name of the different atoms used in a VASP calculations." |
392 | 1 | equemene | WRITe(*,*) "If not given, Path will read the POTCAR file." |
393 | 1 | equemene | WRITE(*,*) "" |
394 | 1 | equemene | WRITE(*,*) "Flags:" |
395 | 1 | equemene | WRITE(*,*) "MW: Flag. True if one wants to work in Mass Weighted coordinates. Default=.TRUE." |
396 | 1 | equemene | WRITE(*,*) "Renum: Flag. True if one wants to reoder the atoms in the initial order. default is .TRUE. most of the time." |
397 | 1 | equemene | WRITE(*,*) "OptProd: True if one wants to optimize the geometry of the products." |
398 | 1 | equemene | WRITE(*,*) "OptReac: True if one wants to optimize the geometry of the reactants." |
399 | 1 | equemene | WRITE(*,*) "PathOnly:TRUE if one wants to generate the initial path, and stops." |
400 | 1 | equemene | WRITE(*,*) "Hinv: if True, then Hessian inversed is used." |
401 | 1 | equemene | WRITE(*,*) "IniHup: if True, then Hessian inverse is extrapolated using the initial path calculations." |
402 | 1 | equemene | WRITE(*,*) "HupNeighbour: if True, then Hessian inverse is extrapolated using the neighbouring points of the path." |
403 | 1 | equemene | WRITE(*,*) "FFrozen: True if one wants to freeze the positions of some atoms." |
404 | 1 | equemene | WRITE(*,*) " If True, a &frozenlist namelist containing the list of frozen atoms must be given." |
405 | 1 | equemene | WRITE(*,*) " If VASP is used, and frozen is not given" |
406 | 1 | equemene | WRITE(*,*) " here, the program will use the F flags of the input geometry" |
407 | 1 | equemene | WRITE(*,*) "FCart: True if one wants to describe some atoms using cartesian coordinates. " |
408 | 1 | equemene | WRITE(*,*) " *** Only used in 'mixed' calculations. ***" |
409 | 1 | equemene | WRITE(*,*) " If True, a &cartlist namelist containing the list of cart atoms must be given." |
410 | 1 | equemene | WRITE(*,*) " By default, only frozen atoms are described in cartesian coordinates." |
411 | 1 | equemene | WRITE(*,*) "" |
412 | 1 | equemene | WRITE(*,*) "DynMaxStep: if TRUE, the maximum allowed step is updated at each step, for each geometry." |
413 | 1 | equemene | WRITE(*,*) " If energy goes up, Smax=Smax*0.8, if not Smax=Smax*1.2. " |
414 | 1 | equemene | WRITE(*,*) " It is ensured that the dynamical Smax is within [0.5*SMax_0,2*Smax_0]" |
415 | 1 | equemene | WRITE(*,*) "Autocart: True if you want to let the program choosing the cartesian atoms." |
416 | 1 | equemene | WRITE(*,*) "VMD: TRUE if you want to use VMD to look at the Path. Used only for VASP for now" |
417 | 1 | equemene | WRITE(*,*) "WriteVASP: TRUE if you want to print the images coordinates in POSCAR files." |
418 | 1 | equemene | WRITE(*,*) "See also the POSCAR option. This can be used only if prog or input=VASP." |
419 | 1 | equemene | WRITE(*,*) "" |
420 | 1 | equemene | STOP |
421 | 1 | equemene | END IF |
422 | 1 | equemene | OPEN(IOIN,FILE=FileIn,STATUS='UNKNOWN') |
423 | 1 | equemene | IOOUT=6 |
424 | 1 | equemene | CASE (0) |
425 | 1 | equemene | IOIN=5 |
426 | 1 | equemene | IOOUT=6 |
427 | 1 | equemene | END SELECT |
428 | 1 | equemene | |
429 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!! |
430 | 1 | equemene | ! |
431 | 1 | equemene | ! We print the Version info in file |
432 | 1 | equemene | ! |
433 | 1 | equemene | WRITE(*,'(1X,A)') "Path v4.1793 (c) PFL/PD 2007-2010" |
434 | 1 | equemene | |
435 | 1 | equemene | |
436 | 1 | equemene | ! We initiliaze variables |
437 | 1 | equemene | Pi=dacos(-1.0d0) |
438 | 1 | equemene | Nat=1 |
439 | 1 | equemene | Fact=1.1 |
440 | 1 | equemene | IGeomRef=-1 |
441 | 1 | equemene | NGeomI=1 |
442 | 1 | equemene | NGeomF=8 |
443 | 1 | equemene | IReparam=5 |
444 | 1 | equemene | IReparamT=-1 |
445 | 1 | equemene | ISpline=5 |
446 | 1 | equemene | debug=.False. |
447 | 1 | equemene | MW=.TRUE. |
448 | 1 | equemene | bohr=.False. |
449 | 1 | equemene | Coord='ZMAT' |
450 | 1 | equemene | Step_method='RFO' |
451 | 1 | equemene | DebugFile='Path.valid' |
452 | 1 | equemene | PathName="Path" |
453 | 1 | equemene | MaxCyc=50 |
454 | 1 | equemene | SMax=0.1D0 |
455 | 1 | equemene | SThresh=-1. |
456 | 1 | equemene | GThresh=-1. |
457 | 1 | equemene | FTan=0. |
458 | 1 | equemene | Hinv=.TRUE. |
459 | 1 | equemene | IniHUp=.FALSE. |
460 | 1 | equemene | HupNeighbour=.FALSE. |
461 | 1 | equemene | HesUpd="MS" |
462 | 1 | equemene | FFrozen=.FALSE. |
463 | 1 | equemene | FCart=.FALSE. |
464 | 1 | equemene | List=0 |
465 | 1 | equemene | renum=.TRUE. |
466 | 1 | equemene | OptReac=.FALSE. |
467 | 1 | equemene | OptProd=.FALSE. |
468 | 1 | equemene | EReac=0.d0 |
469 | 1 | equemene | EProd=0.d0 |
470 | 1 | equemene | OptGeom=-1 |
471 | 1 | equemene | PathOnly=.FALSE. |
472 | 1 | equemene | Prog='EMPTY' |
473 | 1 | equemene | ProgExe='EMPTY' |
474 | 1 | equemene | Runmode='SERIAL' |
475 | 1 | equemene | Input='EMPTY' |
476 | 1 | equemene | Poscar="POSCAR" |
477 | 1 | equemene | AutoCart=.FALSE. |
478 | 1 | equemene | VMD=.TRUE. |
479 | 1 | equemene | WriteVASP=.FALSE. |
480 | 1 | equemene | DynMaxStep=.FALSE. |
481 | 1 | equemene | CalcName="EMPTY" |
482 | 1 | equemene | ISuffix="EMPTY" |
483 | 1 | equemene | OSuffix="EMPTY" |
484 | 1 | equemene | NGintMax=10 |
485 | 1 | equemene | Align=.TRUE. |
486 | 1 | equemene | |
487 | 1 | equemene | ! Number of point used to compute the length of the path, |
488 | 1 | equemene | ! and to reparameterize the path |
489 | 1 | equemene | NMaxPtPath=-1 |
490 | 1 | equemene | FrozTol=1e-4 |
491 | 1 | equemene | |
492 | 1 | equemene | ! Read the namelist |
493 | 1 | equemene | read (IOIN,path) |
494 | 1 | equemene | |
495 | 1 | equemene | debug=valid("Main") |
496 | 1 | equemene | FCalcHess=valid("CalcHess") |
497 | 1 | equemene | PathName=AdjustL(PathName) |
498 | 1 | equemene | Coord=AdjustL(Coord) |
499 | 1 | equemene | CALL UpCase(coord) |
500 | 1 | equemene | |
501 | 1 | equemene | Step_method=AdjustL(Step_method) |
502 | 1 | equemene | CALL UpCase(Step_method) |
503 | 1 | equemene | |
504 | 1 | equemene | Prog=AdjustL(Prog) |
505 | 1 | equemene | CALL UpCase(prog) |
506 | 1 | equemene | |
507 | 1 | equemene | Input=AdjustL(Input) |
508 | 1 | equemene | CALL UpCase(input) |
509 | 1 | equemene | |
510 | 1 | equemene | Runmode=AdjustL(Runmode) |
511 | 1 | equemene | Call UpCase(Runmode) |
512 | 1 | equemene | IF (Runmode(1:4).EQ.'PARA') Runmode="PARA" |
513 | 1 | equemene | |
514 | 1 | equemene | If (IReparamT<=0) IReparamT=IReparam |
515 | 1 | equemene | |
516 | 1 | equemene | IF (COORD.EQ.'CART') THEN |
517 | 1 | equemene | Renum=.FALSE. |
518 | 1 | equemene | IGeomRef=1 |
519 | 1 | equemene | END IF |
520 | 1 | equemene | |
521 | 1 | equemene | if (Prog.EQ.'EMPTY') THEN |
522 | 1 | equemene | Prog='GAUSSIAN' |
523 | 1 | equemene | If (ProgExe=="EMPTY") ProgExe="g09" |
524 | 1 | equemene | END IF |
525 | 1 | equemene | if (Prog.EQ.'G03') THEN |
526 | 1 | equemene | Prog='GAUSSIAN' |
527 | 1 | equemene | If (ProgExe=="EMPTY") ProgExe="g03" |
528 | 1 | equemene | END IF |
529 | 1 | equemene | if (Prog.EQ.'G09') THEN |
530 | 1 | equemene | Prog='GAUSSIAN' |
531 | 1 | equemene | If (ProgExe=="EMPTY") ProgExe="g09" |
532 | 1 | equemene | END IF |
533 | 1 | equemene | |
534 | 1 | equemene | if (Prog.EQ.'TM') Prog="TURBOMOLE" |
535 | 1 | equemene | if (Prog.EQ.'TEST2') Prog="CHAMFRE" |
536 | 1 | equemene | |
537 | 1 | equemene | |
538 | 1 | equemene | Select Case (Prog) |
539 | 1 | equemene | CASE ("EXT") |
540 | 1 | equemene | if (CalcName=="EMPTY") CalcName="Ext" |
541 | 1 | equemene | if (ISuffix=="EMPTY") ISuffix="in" |
542 | 1 | equemene | if (OSuffix=="EMPTY") OSuffix="out" |
543 | 1 | equemene | CASE ('MOPAC') |
544 | 1 | equemene | if (CalcName=="EMPTY") CalcName="Path" |
545 | 1 | equemene | if (ISuffix=="EMPTY") ISuffix="mop" |
546 | 1 | equemene | if (OSuffix=="EMPTY") OSuffix="out" |
547 | 1 | equemene | CASE ("GAUSSIAN") |
548 | 1 | equemene | if (CalcName=="EMPTY") CalcName="Path" |
549 | 1 | equemene | if (ISuffix=="EMPTY") ISuffix="com" |
550 | 1 | equemene | if (OSuffix=="EMPTY") OSuffix="log" |
551 | 1 | equemene | CASE DEFAULT |
552 | 1 | equemene | if (CalcName=="EMPTY") CalcName="Path" |
553 | 1 | equemene | if (ISuffix=="EMPTY") ISuffix="in" |
554 | 1 | equemene | if (OSuffix=="EMPTY") OSuffix="out" |
555 | 1 | equemene | END SELECT |
556 | 1 | equemene | |
557 | 1 | equemene | |
558 | 1 | equemene | if (Input.EQ.'EMPTY') THEN |
559 | 1 | equemene | Select Case (Prog) |
560 | 1 | equemene | CASE ("VASP") |
561 | 1 | equemene | Input=Prog |
562 | 1 | equemene | CASE ("CHAMFRE") |
563 | 1 | equemene | Input="VASP" |
564 | 1 | equemene | CASE DEFAULT |
565 | 1 | equemene | Input='XYZ' |
566 | 1 | equemene | END SELECT |
567 | 1 | equemene | WRITE(*,*) "Input has been set to the default: ",INPUT |
568 | 1 | equemene | END IF |
569 | 1 | equemene | |
570 | 1 | equemene | WriteVASP=WriteVASP.AND.((Prog=="VASP").OR.(Input=="VASP")) |
571 | 1 | equemene | |
572 | 1 | equemene | IF ((RunMode=="PARA").AND.((Prog/="GAUSSIAN").AND.(Prog/="VASP"))) THEN |
573 | 1 | equemene | WRITE(*,*) "Program=",TRIM(Prog)," not yet supported for Para mode." |
574 | 1 | equemene | STOP |
575 | 1 | equemene | END IF |
576 | 1 | equemene | |
577 | 1 | equemene | if (OptGeom.GE.1) THEN |
578 | 1 | equemene | HesUpd="BFGS" |
579 | 1 | equemene | IF (IGeomRef.LE.0) THEN |
580 | 1 | equemene | IGeomRef=OptGeom |
581 | 1 | equemene | ELSE |
582 | 1 | equemene | IF (IGeomRef.NE.OptGeom) THEN |
583 | 1 | equemene | WRITE(IOOUT,*) "STOP: IGeomRef and OptGeom both set... but to different values !" |
584 | 1 | equemene | WRITE(IOOUT,*) "Check it : IGeomRef=",IGeomRef," OptGeom=",OptGeom |
585 | 1 | equemene | |
586 | 1 | equemene | WRITE(*,*) "STOP: IGeomRef and OptGeom both set... but to different values !" |
587 | 1 | equemene | WRITE(*,*) "Check it : IGeomRef=",IGeomRef," OptGeom=",OptGeom |
588 | 1 | equemene | STOP |
589 | 1 | equemene | END IF |
590 | 1 | equemene | END IF |
591 | 1 | equemene | END IF |
592 | 1 | equemene | |
593 | 1 | equemene | IF (ProgExe.EQ.'EMPTY') THEN |
594 | 1 | equemene | SELECT CASE (PROG) |
595 | 1 | equemene | CASE ("GAUSSIAN") |
596 | 1 | equemene | ProgExe="g03" |
597 | 1 | equemene | CASE ("MOPAC") |
598 | 1 | equemene | ProgExe="mopac" |
599 | 1 | equemene | CASE ("EXT") |
600 | 1 | equemene | ProgExe="./Ext.exe" |
601 | 1 | equemene | CASE ("VASP") |
602 | 1 | equemene | ProgExe='VASP' |
603 | 1 | equemene | CASE ("TURBOMOLE") |
604 | 1 | equemene | ProgExe='jobex -c 1 -keep' |
605 | 1 | equemene | CASE ("TEST") |
606 | 1 | equemene | ProgExe="" |
607 | 1 | equemene | CASE ("CHAMFRE") |
608 | 1 | equemene | ProgExe="" |
609 | 1 | equemene | CASE DEFAULT |
610 | 1 | equemene | WRITE(*,*) "Prog=",Adjustl(trim(Prog))," not recognized. STOP" |
611 | 1 | equemene | STOP |
612 | 1 | equemene | END SELECT |
613 | 1 | equemene | END IF |
614 | 1 | equemene | |
615 | 1 | equemene | if (FCart.AND.FFrozen) THEN |
616 | 1 | equemene | ! We have to be carreful because user might use any order |
617 | 1 | equemene | ! to give the two lists CartList and FrozenList |
618 | 1 | equemene | READ(IOIN,'(A)') Line |
619 | 1 | equemene | Call Upcase(Line) |
620 | 1 | equemene | if (Index(Line,"CART").NE.0) THEN |
621 | 1 | equemene | ALLOCATE(Cart(Nat)) |
622 | 1 | equemene | BackSpace(IOIN) |
623 | 1 | equemene | List=0 |
624 | 1 | equemene | READ(IOIN,cartlist) |
625 | 1 | equemene | IF (COORD.NE.'CART') THEN |
626 | 1 | equemene | Cart=List(1:Nat) |
627 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path L512 Cart",Cart |
628 | 1 | equemene | ELSE |
629 | 1 | equemene | WRITE(*,*) "FCart=T is not allowed when Coord='CART'" |
630 | 1 | equemene | WRITE(*,*) "I will discard the cartlist" |
631 | 1 | equemene | Cart=0 |
632 | 1 | equemene | END IF |
633 | 1 | equemene | |
634 | 1 | equemene | ALLOCATE(Frozen(Nat)) |
635 | 1 | equemene | BACKSPACE(IOIN) |
636 | 1 | equemene | List=0 |
637 | 1 | equemene | READ(IOIN,Frozenlist) |
638 | 1 | equemene | Frozen=List(1:Nat) |
639 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path L517 Frozen",Frozen |
640 | 1 | equemene | ELSE |
641 | 1 | equemene | ALLOCATE(Frozen(Nat)) |
642 | 1 | equemene | BACKSPACE(IOIN) |
643 | 1 | equemene | List=0 |
644 | 1 | equemene | READ(IOIN,Frozenlist) |
645 | 1 | equemene | Frozen=List(1:Nat) |
646 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path L523 Frozen",Frozen |
647 | 1 | equemene | ALLOCATE(Cart(Nat)) |
648 | 1 | equemene | BackSpace(IOIN) |
649 | 1 | equemene | List=0 |
650 | 1 | equemene | READ(IOIN,cartlist) |
651 | 1 | equemene | IF (COORD.NE.'CART') THEN |
652 | 1 | equemene | Cart=List(1:Nat) |
653 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path L548 Cart",Cart |
654 | 1 | equemene | ELSE |
655 | 1 | equemene | WRITE(*,*) "FCart=T is not allowed when Coord='CART'" |
656 | 1 | equemene | WRITE(*,*) "I will discard the cartlist" |
657 | 1 | equemene | Cart=0 |
658 | 1 | equemene | END IF |
659 | 1 | equemene | END IF |
660 | 1 | equemene | ELSE |
661 | 1 | equemene | if (FCart) THEN |
662 | 1 | equemene | ALLOCATE(Cart(Nat)) |
663 | 1 | equemene | List=0 |
664 | 1 | equemene | READ(IOIN,cartlist) |
665 | 1 | equemene | IF (COORD.NE.'CART') THEN |
666 | 1 | equemene | Cart=List(1:Nat) |
667 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path L561 Cart",Cart |
668 | 1 | equemene | ELSE |
669 | 1 | equemene | WRITE(*,*) "FCart=T is not allowed when Coord='CART'" |
670 | 1 | equemene | WRITE(*,*) "I will discard the cartlist" |
671 | 1 | equemene | Cart=0 |
672 | 1 | equemene | END IF |
673 | 1 | equemene | ELSE |
674 | 1 | equemene | IF ((PROG=="VASP").OR.(AutoCart)) THEN |
675 | 1 | equemene | ALLOCATE(Cart(Nat)) |
676 | 1 | equemene | ELSE |
677 | 1 | equemene | ALLOCATE(Cart(1)) |
678 | 1 | equemene | END IF |
679 | 1 | equemene | Cart=0 |
680 | 1 | equemene | END IF |
681 | 1 | equemene | |
682 | 1 | equemene | if (FFrozen) THEN |
683 | 1 | equemene | ALLOCATE(Frozen(Nat)) |
684 | 1 | equemene | List=0 |
685 | 1 | equemene | READ(IOIN,Frozenlist) |
686 | 1 | equemene | Frozen=List(1:Nat) |
687 | 1 | equemene | WRITE(*,*) Frozen |
688 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path L549 Frozen",Frozen |
689 | 1 | equemene | ELSE |
690 | 1 | equemene | IF (PROG=="VASP") THEN |
691 | 1 | equemene | ALLOCATE(Frozen(Nat)) |
692 | 1 | equemene | ELSE |
693 | 1 | equemene | ALLOCATE(Frozen(1)) |
694 | 1 | equemene | END IF |
695 | 1 | equemene | Frozen=0 |
696 | 1 | equemene | END IF |
697 | 1 | equemene | END IF |
698 | 1 | equemene | |
699 | 1 | equemene | |
700 | 1 | equemene | If (FCart) Call Expand(Cart,NCart,Nat) |
701 | 1 | equemene | IF (FFrozen) Call Expand(Frozen,NFroz,Nat) |
702 | 1 | equemene | |
703 | 1 | equemene | if (debug) WRITE(*,*) "DBG Main L609, Ncart,Cart",NCart,Cart |
704 | 1 | equemene | if (debug) WRITE(*,*) "DBG Main L610, NFroz,Frozen", NFroz,Frozen |
705 | 1 | equemene | |
706 | 1 | equemene | if (NMaxPtPath.EQ.-1) then |
707 | 1 | equemene | NMaxPtPath=min(50*NGeomF,1000) |
708 | 1 | equemene | NMaxPtPath=max(20*NGeomF,NMaxPtPath) |
709 | 1 | equemene | end if |
710 | 1 | equemene | |
711 | 1 | equemene | ! NMaxPtPath=10000 |
712 | 1 | equemene | |
713 | 1 | equemene | ! We ensure that FTan is in [0.:1.] |
714 | 1 | equemene | FTan=min(abs(FTan),1.d0) |
715 | 1 | equemene | |
716 | 1 | equemene | if (debug) WRITE(IOOUT,path) |
717 | 1 | equemene | |
718 | 1 | equemene | FTan=1.-FTan |
719 | 1 | equemene | |
720 | 1 | equemene | !Thresholds... |
721 | 1 | equemene | if (SThresh.LE.0) SThresh=0.01d0 |
722 | 1 | equemene | If (GThresh.LE.0) GThresh=SThresh/4. |
723 | 1 | equemene | SThreshRms=Sthresh*2./3. |
724 | 1 | equemene | GThreshRms=Gthresh*2./3. |
725 | 1 | equemene | |
726 | 1 | equemene | ! First batch of allocations. Arrays that depend only on NGeomI, Nat |
727 | 1 | equemene | ALLOCATE(XyzGeomI(NGeomI,3,Nat), AtName(NAt)) |
728 | 1 | equemene | ALLOCATE(IndZmat(Nat,5),Order(Nat),Atome(Nat)) |
729 | 1 | equemene | ALLOCATE(MassAt(NAt),OrderInv(Nat)) |
730 | 1 | equemene | |
731 | 1 | equemene | ! We read the initial geometries |
732 | 1 | equemene | Call Read_Geom(input) |
733 | 1 | equemene | |
734 | 1 | equemene | ! We convert atome names into atom mass number |
735 | 1 | equemene | DO I=1,NAt |
736 | 1 | equemene | ! WRITE(*,*) 'I,AtName',I,AtName(I) |
737 | 1 | equemene | Atome(I)=ConvertNumAt(AtName(I)) |
738 | 1 | equemene | END DO |
739 | 1 | equemene | |
740 | 1 | equemene | |
741 | 1 | equemene | ! PFL 23 Sep 2008 -> |
742 | 1 | equemene | ! We check that frozen atoms are really frozen, ie that their coordinates do not change |
743 | 1 | equemene | ! between the first geometry and the others. |
744 | 1 | equemene | IF (NFroz.GT.0) THEN |
745 | 1 | equemene | ALLOCATE(ListAtFroz(Nat),x1(Nat),y1(nat),z1(nat)) |
746 | 1 | equemene | ALLOCATE(x2(nat),y2(nat),z2(nat)) |
747 | 1 | equemene | ListAtFroz=.FALSE. |
748 | 1 | equemene | |
749 | 1 | equemene | x1(1:Nat)=XyzgeomI(1,1,1:Nat) |
750 | 1 | equemene | y1(1:Nat)=XyzgeomI(1,2,1:Nat) |
751 | 1 | equemene | z1(1:Nat)=XyzgeomI(1,3,1:Nat) |
752 | 1 | equemene | |
753 | 1 | equemene | SELECT CASE (NFroz) |
754 | 1 | equemene | ! We have Frozen atoms |
755 | 1 | equemene | ! PFL 28 Oct 2008 -> |
756 | 1 | equemene | ! It might happen that the geometries are translated/rotated. |
757 | 1 | equemene | ! So if we have 3 (or more) frozen atoms, we re-orient the geometries, based on the first |
758 | 1 | equemene | ! three frozen atoms. |
759 | 1 | equemene | |
760 | 1 | equemene | CASE (3:) |
761 | 1 | equemene | DO I=1,NFroz |
762 | 1 | equemene | ListAtFroz(Frozen(I))=.TRUE. |
763 | 1 | equemene | END DO |
764 | 1 | equemene | CASE (2) |
765 | 1 | equemene | IAt1=Frozen(1) |
766 | 1 | equemene | IAt2=Frozen(2) |
767 | 1 | equemene | ListAtFroz(Iat1)=.TRUE. |
768 | 1 | equemene | ListAtFroz(Iat2)=.TRUE. |
769 | 1 | equemene | x2(1)=x1(Iat2)-x1(Iat1) |
770 | 1 | equemene | y2(1)=y1(Iat2)-y1(Iat1) |
771 | 1 | equemene | z2(1)=z1(Iat2)-z1(Iat1) |
772 | 1 | equemene | Norm1=sqrt(x2(1)**2+y2(1)**2+z2(1)**2) |
773 | 1 | equemene | Dist=-1. |
774 | 1 | equemene | ! We scan all atoms to find one that is not aligned with Iat1-Iat2 |
775 | 1 | equemene | DO I=1,Nat |
776 | 1 | equemene | if ((I.EQ.Iat1).OR.(I.EQ.Iat2)) Cycle |
777 | 1 | equemene | x2(2)=x1(Iat2)-x1(I) |
778 | 1 | equemene | y2(2)=y1(Iat2)-y1(I) |
779 | 1 | equemene | z2(2)=z1(Iat2)-z1(I) |
780 | 1 | equemene | Norm2=sqrt(x2(2)**2+y2(2)**2+z2(2)**2) |
781 | 1 | equemene | ca=(x2(1)*x2(2)+y2(1)*y2(2)+z2(1)*Z2(2))/(Norm1*Norm2) |
782 | 1 | equemene | if (abs(ca)<0.9) THEN |
783 | 1 | equemene | IF (Norm2>Dist) THEN |
784 | 1 | equemene | Iat3=I |
785 | 1 | equemene | Dist=Norm2 |
786 | 1 | equemene | END IF |
787 | 1 | equemene | END IF |
788 | 1 | equemene | END DO |
789 | 1 | equemene | ListAtFroz(Iat3)=.TRUE. |
790 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path, NFroz=2, third frozen=",Iat3 |
791 | 1 | equemene | CASE (1) |
792 | 1 | equemene | IAt1=Frozen(1) |
793 | 1 | equemene | ListAtFroz(Iat1)=.TRUE. |
794 | 1 | equemene | Dist=-1. |
795 | 1 | equemene | ! We scan all atoms to find one that is further from At1 |
796 | 1 | equemene | DO I=1,Nat |
797 | 1 | equemene | if (I.EQ.Iat1) Cycle |
798 | 1 | equemene | x2(1)=x1(Iat1)-x1(I) |
799 | 1 | equemene | y2(1)=y1(Iat1)-y1(I) |
800 | 1 | equemene | z2(1)=z1(Iat1)-z1(I) |
801 | 1 | equemene | Norm1=sqrt(x2(1)**2+y2(1)**2+z2(1)**2) |
802 | 1 | equemene | IF (Norm1>Dist) THEN |
803 | 1 | equemene | Iat2=I |
804 | 1 | equemene | Dist=Norm1 |
805 | 1 | equemene | END IF |
806 | 1 | equemene | END DO |
807 | 1 | equemene | IAt2=Frozen(2) |
808 | 1 | equemene | ListAtFroz(Iat2)=.TRUE. |
809 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path, NFroz=1, second frozen=",Iat2 |
810 | 1 | equemene | x2(1)=x1(Iat2)-x1(Iat1) |
811 | 1 | equemene | y2(1)=y1(Iat2)-y1(Iat1) |
812 | 1 | equemene | z2(1)=z1(Iat2)-z1(Iat1) |
813 | 1 | equemene | Norm1=sqrt(x2(1)**2+y2(1)**2+z2(1)**2) |
814 | 1 | equemene | Dist=-1. |
815 | 1 | equemene | ! We scan all atoms to find one that is not aligned with Iat1-Iat2 |
816 | 1 | equemene | DO I=1,Nat |
817 | 1 | equemene | if ((I.EQ.Iat1).OR.(I.EQ.Iat2)) Cycle |
818 | 1 | equemene | x2(2)=x1(Iat2)-x1(I) |
819 | 1 | equemene | y2(2)=y1(Iat2)-y1(I) |
820 | 1 | equemene | z2(2)=z1(Iat2)-z1(I) |
821 | 1 | equemene | Norm2=sqrt(x2(2)**2+y2(2)**2+z2(2)**2) |
822 | 1 | equemene | ca=(x2(1)*x2(2)+y2(1)*y2(2)+z2(1)*Z2(2))/(Norm1*Norm2) |
823 | 1 | equemene | if (abs(ca)<0.9) THEN |
824 | 1 | equemene | IF (Norm2>Dist) THEN |
825 | 1 | equemene | Iat3=I |
826 | 1 | equemene | Dist=Norm2 |
827 | 1 | equemene | END IF |
828 | 1 | equemene | END IF |
829 | 1 | equemene | END DO |
830 | 1 | equemene | ListAtFroz(Iat3)=.TRUE. |
831 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path, NFroz=1, third frozen=",Iat3 |
832 | 1 | equemene | END SELECT |
833 | 1 | equemene | |
834 | 1 | equemene | DO I=2,NGeomI |
835 | 1 | equemene | ! First, we align the Ith geometry on the first one, using only |
836 | 1 | equemene | ! the positions of the "frozen" atoms. (see above: it might be that |
837 | 1 | equemene | ! ListAtFroz contains non frozen atoms usd to align the geometries |
838 | 1 | equemene | x2(1:Nat)=XyzgeomI(I,1,1:Nat) |
839 | 1 | equemene | y2(1:Nat)=XyzgeomI(I,2,1:Nat) |
840 | 1 | equemene | z2(1:Nat)=XyzgeomI(I,3,1:Nat) |
841 | 1 | equemene | Call Alignpartial(Nat,x1,y1,z1,x2,y2,z2,ListAtFroz,MRot) |
842 | 1 | equemene | |
843 | 1 | equemene | |
844 | 1 | equemene | FChkFrozen=.FALSE. |
845 | 1 | equemene | DO J=1,NFroz |
846 | 1 | equemene | IAt=Frozen(J) |
847 | 1 | equemene | IF ((abs(X1(Iat)-X2(Iat)).GT.FrozTol).OR. & |
848 | 1 | equemene | (abs(y1(Iat)-y2(Iat)).GT.FrozTol).OR. & |
849 | 1 | equemene | (abs(z1(Iat)-z2(Iat)).GT.FrozTol)) THEN |
850 | 1 | equemene | IF (.NOT.FChkFrozen) WRITE(*,*) "*** WARNING ****" |
851 | 1 | equemene | FChkFrozen=.TRUE. |
852 | 1 | equemene | WRITE(*,*) "Atom ",Iat," is set to Frozen but its coordinates change" |
853 | 1 | equemene | WRITE(*,*) "from geometry 1 to geometry ",I |
854 | 1 | equemene | END IF |
855 | 1 | equemene | END DO |
856 | 1 | equemene | END DO |
857 | 1 | equemene | IF (FChkFrozen) THEN |
858 | 1 | equemene | WRITE(*,*) "Some frozen atoms are not frozen... check this and play again" |
859 | 1 | equemene | STOP |
860 | 1 | equemene | END IF |
861 | 1 | equemene | END IF |
862 | 1 | equemene | |
863 | 1 | equemene | |
864 | 1 | equemene | N3at=3*Nat |
865 | 1 | equemene | NFree=N3at-6 ! ATTENTION: THIS IS NOT VALID FOR ALL TYPES OF COORDINATES. |
866 | 1 | equemene | |
867 | 1 | equemene | ! if prog=gaussian, we have to read a full input |
868 | 1 | equemene | ! to mimic it later |
869 | 1 | equemene | if (prog=='GAUSSIAN') THEN |
870 | 1 | equemene | ! We read the Gaussian input file |
871 | 1 | equemene | ! First, the root |
872 | 1 | equemene | IF (DEBUG) WRITE(*,*) "Reading Gauss Root" |
873 | 1 | equemene | ALLOCATE(Gauss_Root) |
874 | 1 | equemene | NULLIFY(Gauss_Root%next) |
875 | 1 | equemene | Current => Gauss_root |
876 | 1 | equemene | LineL=1 |
877 | 1 | equemene | DO WHILE (LineL.NE.0) |
878 | 1 | equemene | READ(IOIN,'(A)') Line |
879 | 1 | equemene | Line=AdjustL(Line) |
880 | 1 | equemene | LineL=len(Trim(Line)) |
881 | 1 | equemene | Idx=INDEX(Line,"chk") |
882 | 1 | equemene | IF ((LineL.NE.0).AND.(Idx.EQ.0)) THEN |
883 | 1 | equemene | current%Line=TRIM(Line) |
884 | 1 | equemene | ALLOCATE(current%next) |
885 | 1 | equemene | Current => Current%next |
886 | 1 | equemene | Nullify(Current%next) |
887 | 1 | equemene | END IF |
888 | 1 | equemene | END DO |
889 | 1 | equemene | |
890 | 1 | equemene | ! Current => Gauss_root |
891 | 1 | equemene | ! DO WHILE (ASSOCIATED(Current%next)) |
892 | 1 | equemene | ! WRITE(*,'(1X,A)') Trim(current%line) |
893 | 1 | equemene | ! Current => current%next |
894 | 1 | equemene | ! END DO |
895 | 1 | equemene | |
896 | 1 | equemene | ! Now the comment... |
897 | 1 | equemene | IF (DEBUG) WRITE(*,*) "Reading Gauss Comment" |
898 | 1 | equemene | ALLOCATE(Gauss_Comment) |
899 | 1 | equemene | NuLLIFY(Gauss_Comment%Next) |
900 | 1 | equemene | Current => Gauss_comment |
901 | 1 | equemene | LineL=1 |
902 | 1 | equemene | DO WHILE (LineL.NE.0) |
903 | 1 | equemene | READ(IOIN,'(A)') Line |
904 | 1 | equemene | Line=AdjustL(Line) |
905 | 1 | equemene | LineL=len(Trim(Line)) |
906 | 1 | equemene | IF (LineL.NE.0) THEN |
907 | 1 | equemene | current%Line=TRIM(Line) |
908 | 1 | equemene | ALLOCATE(current%next) |
909 | 1 | equemene | Current => Current%next |
910 | 1 | equemene | Nullify(Current%next) |
911 | 1 | equemene | END IF |
912 | 1 | equemene | END DO |
913 | 1 | equemene | |
914 | 1 | equemene | ! Current => Gauss_comment |
915 | 1 | equemene | ! DO WHILE (ASSOCIATED(Current%next)) |
916 | 1 | equemene | ! WRITE(*,'(1X,A)') Trim(current%line) |
917 | 1 | equemene | ! Current => current%next |
918 | 1 | equemene | ! END DO |
919 | 1 | equemene | |
920 | 1 | equemene | ! Now the charge |
921 | 1 | equemene | IF (DEBUG) WRITE(*,*) "Reading Gauss Charge" |
922 | 1 | equemene | READ(IOIN,'(A)') Gauss_Charge |
923 | 1 | equemene | ! WRITE(*,*) Gauss_charge |
924 | 1 | equemene | ! We now read the Paste part... |
925 | 1 | equemene | ALLOCATE(Gauss_Paste(NAt)) |
926 | 1 | equemene | LenLine=1 |
927 | 1 | equemene | Iat=0 |
928 | 1 | equemene | Gauss_paste=" " |
929 | 1 | equemene | DO While (LenLine.GT.0) |
930 | 1 | equemene | READ(IOIN,'(A)') Line |
931 | 1 | equemene | Line=AdjustL(Line) |
932 | 1 | equemene | LenLine=Len_TRIM(Line) |
933 | 1 | equemene | IF (LenLine.GT.0) Iat=Iat+1 |
934 | 1 | equemene | Idx=Index(Line,'.',BACK=.TRUE.) |
935 | 1 | equemene | ! WRITE(*,*) Idx,TRIM(Line) |
936 | 1 | equemene | ! WRITE(*,*) Idx,TRIM(Line(Idx+1:)) |
937 | 1 | equemene | Line=ADJUSTL(Line(Idx+1:)) |
938 | 1 | equemene | Idx=Index(Line," ") |
939 | 1 | equemene | LineL=LEN_TRIM(Line(Idx:)) |
940 | 1 | equemene | ! WRITE(*,*) LineL,TRIM(Line(Idx:)) |
941 | 1 | equemene | IF (LineL.GT.0) THEN |
942 | 1 | equemene | Gauss_paste(Iat)=Line(Idx:) |
943 | 1 | equemene | END IF |
944 | 1 | equemene | END DO |
945 | 1 | equemene | IF (Iat.NE.Nat) THEN |
946 | 1 | equemene | WRITE(*,*) "I found ", Iat," lines for the geometry instead of ",Nat |
947 | 1 | equemene | WRITE(*,*) "ERROR. STOP" |
948 | 1 | equemene | WRITE(IOOUT,*) "I found ", Iat," lines for the geometry instead of ",Nat |
949 | 1 | equemene | WRITE(IOOUT,*) "ERROR. STOP" |
950 | 1 | equemene | STOP |
951 | 1 | equemene | END IF |
952 | 1 | equemene | ! We now read the last part |
953 | 1 | equemene | IF (DEBUG) WRITE(*,*) "Reading Gauss End" |
954 | 1 | equemene | ! READ(IOIN,'(A)') Line |
955 | 1 | equemene | ALLOCATE(Gauss_End) |
956 | 1 | equemene | NuLLIFY(Gauss_End%Next) |
957 | 1 | equemene | Current => Gauss_End |
958 | 1 | equemene | LineL=1 |
959 | 1 | equemene | DO WHILE (1.EQ.1) |
960 | 1 | equemene | READ(IOIN,'(A)',END=999) Line |
961 | 1 | equemene | Line=AdjustL(Line) |
962 | 1 | equemene | LineL=len(Trim(Line)) |
963 | 1 | equemene | current%Line=TRIM(Line) |
964 | 1 | equemene | ALLOCATE(current%next) |
965 | 1 | equemene | Current => Current%next |
966 | 1 | equemene | Nullify(Current%next) |
967 | 1 | equemene | END DO |
968 | 1 | equemene | 999 CONTINUE |
969 | 1 | equemene | |
970 | 1 | equemene | ! ! Write the gaussian input file for testing purposes |
971 | 1 | equemene | ! Current => Gauss_root |
972 | 1 | equemene | ! DO WHILE (ASSOCIATED(Current%next)) |
973 | 1 | equemene | ! WRITE(*,'(1X,A)') Trim(current%line) |
974 | 1 | equemene | ! Current => current%next |
975 | 1 | equemene | ! END DO |
976 | 1 | equemene | |
977 | 1 | equemene | ! WRITE(*,*) |
978 | 1 | equemene | ! WRITE(*,*) 'Comment original' |
979 | 1 | equemene | |
980 | 1 | equemene | ! Current => Gauss_comment |
981 | 1 | equemene | ! DO WHILE (ASSOCIATED(Current%next)) |
982 | 1 | equemene | ! WRITE(*,'(1X,A)') Trim(current%line) |
983 | 1 | equemene | ! Current => current%next |
984 | 1 | equemene | ! END DO |
985 | 1 | equemene | |
986 | 1 | equemene | ! WRITE(*,*) |
987 | 1 | equemene | ! WRITE(*,*) Trim(Gauss_charge) |
988 | 1 | equemene | |
989 | 1 | equemene | ! DO I=1,Nat |
990 | 1 | equemene | ! WRITE(*,'(1X,A10,3(1X,F15.8),A)') Trim(AtName(I)),XyzGeomI(1:3,I,1), TRIM(Gauss_Paste(I)) |
991 | 1 | equemene | ! END DO |
992 | 1 | equemene | |
993 | 1 | equemene | ! WRITE(*,*) |
994 | 1 | equemene | ! Current => Gauss_End |
995 | 1 | equemene | ! DO WHILE (ASSOCIATED(Current%next)) |
996 | 1 | equemene | ! WRITE(*,'(1X,A)') Trim(current%line) |
997 | 1 | equemene | ! Current => current%next |
998 | 1 | equemene | ! END DO |
999 | 1 | equemene | |
1000 | 1 | equemene | ! WRITE(*,*) |
1001 | 1 | equemene | |
1002 | 1 | equemene | END IF |
1003 | 1 | equemene | |
1004 | 1 | equemene | ! if prog=mopac, we have to read a full input to reproduce it later |
1005 | 1 | equemene | ! The structure is: |
1006 | 1 | equemene | ! A MOPAC data set normally consists of one line of keywords, two lines of user-defined text, then the coordinates |
1007 | 1 | equemene | ! Then a blank line or a line of 0. |
1008 | 1 | equemene | ! then the symmetry description. |
1009 | 1 | equemene | ! comment lines start with * and can be anywhere !!! |
1010 | 1 | equemene | |
1011 | 1 | equemene | if (prog=='MOPAC') THEN |
1012 | 1 | equemene | ! We read the Gaussian input file |
1013 | 1 | equemene | ! First, the root |
1014 | 1 | equemene | IF (DEBUG) WRITE(*,*) "Reading Mopac input" |
1015 | 1 | equemene | ALLOCATE(Mopac_Root) |
1016 | 1 | equemene | NULLIFY(Mopac_Root%next) |
1017 | 1 | equemene | ALLOCATE(Mopac_Comment) |
1018 | 1 | equemene | NULLIFY(Mopac_Comment%next) |
1019 | 1 | equemene | ALLOCATE(Mopac_End) |
1020 | 1 | equemene | NuLLIFY(Mopac_End%Next) |
1021 | 1 | equemene | Current => Mopac_root |
1022 | 1 | equemene | CurCom => Mopac_Comment |
1023 | 1 | equemene | LineL=1 |
1024 | 1 | equemene | NTmp=0 |
1025 | 1 | equemene | DO WHILE (NTmp.LT.3) |
1026 | 1 | equemene | READ(IOIN,'(A)') Line |
1027 | 1 | equemene | Line=AdjustL(Line) |
1028 | 1 | equemene | LineL=len(Trim(Line)) |
1029 | 1 | equemene | IF (Line(1:1)/="*") THEN |
1030 | 1 | equemene | IF (NTmp==0) THEN |
1031 | 1 | equemene | Line2=Line |
1032 | 1 | equemene | Call UpCase(Line2) |
1033 | 1 | equemene | Idx=Index(Line2,'GRADIENTS') |
1034 | 1 | equemene | If (Idx==0) Line=TRIM(Line) // " GRADIENTS" |
1035 | 1 | equemene | Idx=Index(Line2,'1SCF') |
1036 | 1 | equemene | If (Idx==0) Line=TRIM(Line) // " 1SCF" |
1037 | 1 | equemene | END IF |
1038 | 1 | equemene | current%Line=TRIM(Line) |
1039 | 1 | equemene | ALLOCATE(current%next) |
1040 | 1 | equemene | Current => Current%next |
1041 | 1 | equemene | Nullify(Current%next) |
1042 | 1 | equemene | NTmp=NTmp+1 |
1043 | 1 | equemene | ELSE |
1044 | 1 | equemene | CurCom%Line=TRIM(LINE) |
1045 | 1 | equemene | ALLOCATE(CurCom%Next) |
1046 | 1 | equemene | CurCom => CurCom%Next |
1047 | 1 | equemene | NULLIFY(CurCom%Next) |
1048 | 1 | equemene | END IF |
1049 | 1 | equemene | END DO |
1050 | 1 | equemene | |
1051 | 1 | equemene | ! Current => Mopac_root |
1052 | 1 | equemene | ! DO WHILE (ASSOCIATED(Current%next)) |
1053 | 1 | equemene | ! WRITE(*,'(1X,A)') Trim(current%line) |
1054 | 1 | equemene | ! Current => current%next |
1055 | 1 | equemene | ! END DO |
1056 | 1 | equemene | |
1057 | 1 | equemene | ! Now the geometry... that we just skip :) |
1058 | 1 | equemene | IF (DEBUG) WRITE(*,*) "Reading Mopac Geometry" |
1059 | 1 | equemene | Mopac_EndGeom="" |
1060 | 1 | equemene | LineL=1 |
1061 | 1 | equemene | DO WHILE (LineL.NE.0) |
1062 | 1 | equemene | READ(IOIN,'(A)',END=989) Line |
1063 | 1 | equemene | Line=AdjustL(Line) |
1064 | 1 | equemene | LineL=len(Trim(Line)) |
1065 | 1 | equemene | ! The last line might be either blank or filled with 0 |
1066 | 1 | equemene | IF (Line(1:1)=="0") THEN |
1067 | 1 | equemene | LineL=0 |
1068 | 1 | equemene | Mopac_EndGeom=Trim(Line) |
1069 | 1 | equemene | END IF |
1070 | 1 | equemene | IF (Line(1:1)=="*") THEN |
1071 | 1 | equemene | CurCom%Line=TRIM(LINE) |
1072 | 1 | equemene | ALLOCATE(CurCom%Next) |
1073 | 1 | equemene | CurCom => CurCom%Next |
1074 | 1 | equemene | NULLIFY(CurCom%Next) |
1075 | 1 | equemene | END IF |
1076 | 1 | equemene | END DO |
1077 | 1 | equemene | |
1078 | 1 | equemene | ! If we are here, there might be something else to read: Mopac_end |
1079 | 1 | equemene | |
1080 | 1 | equemene | ! We now read the last part |
1081 | 1 | equemene | IF (DEBUG) WRITE(*,*) "Reading Mopac End" |
1082 | 1 | equemene | ! READ(IOIN,'(A)') Line |
1083 | 1 | equemene | Current => Mopac_End |
1084 | 1 | equemene | LineL=1 |
1085 | 1 | equemene | DO WHILE (1.EQ.1) |
1086 | 1 | equemene | READ(IOIN,'(A)',END=989) Line |
1087 | 1 | equemene | Line=AdjustL(Line) |
1088 | 1 | equemene | LineL=len(Trim(Line)) |
1089 | 1 | equemene | IF (Line(1:1)/="*") THEN |
1090 | 1 | equemene | current%Line=TRIM(Line) |
1091 | 1 | equemene | ALLOCATE(current%next) |
1092 | 1 | equemene | Current => Current%next |
1093 | 1 | equemene | Nullify(Current%next) |
1094 | 1 | equemene | NTmp=NTmp+1 |
1095 | 1 | equemene | ELSE |
1096 | 1 | equemene | CurCom%Line=TRIM(LINE) |
1097 | 1 | equemene | ALLOCATE(CurCom%Next) |
1098 | 1 | equemene | CurCom => CurCom%Next |
1099 | 1 | equemene | NULLIFY(CurCom%Next) |
1100 | 1 | equemene | END IF |
1101 | 1 | equemene | END DO |
1102 | 1 | equemene | 989 CONTINUE |
1103 | 1 | equemene | |
1104 | 1 | equemene | END IF ! IF (PROG="MOPAC") |
1105 | 1 | equemene | |
1106 | 1 | equemene | if ((Prog=="VASP").AND.(input/="VASP")) THEN |
1107 | 1 | equemene | ! Input was not Vasp, so many parameters are missing like lattice |
1108 | 1 | equemene | ! constants... |
1109 | 1 | equemene | ! we read them now ! |
1110 | 1 | equemene | ALLOCATE(FFF(3,nat)) |
1111 | 1 | equemene | ! First geometry is a bit special for VASP as we have to set |
1112 | 1 | equemene | ! many things |
1113 | 1 | equemene | IF (DEBUG) WRITE(*,*) "Reading Vasp Parameters" |
1114 | 1 | equemene | READ(IOIN,'(A)') Vasp_Title |
1115 | 1 | equemene | READ(IOIN,*) Vasp_param |
1116 | 1 | equemene | |
1117 | 1 | equemene | READ(IOIN,*) Lat_a |
1118 | 1 | equemene | READ(IOIN,*) Lat_b |
1119 | 1 | equemene | READ(IOIN,*) Lat_c |
1120 | 1 | equemene | |
1121 | 1 | equemene | Lat_a=Lat_a*Vasp_param |
1122 | 1 | equemene | Lat_b=Lat_b*Vasp_param |
1123 | 1 | equemene | Lat_c=Lat_c*Vasp_param |
1124 | 1 | equemene | |
1125 | 1 | equemene | ALLOCATE(NbAtType(nat)) |
1126 | 1 | equemene | READ(IOIN,'(A)') Vasp_types |
1127 | 1 | equemene | ! First, how many different types ? |
1128 | 1 | equemene | NbAtType=0 |
1129 | 1 | equemene | READ(Vasp_types,*,END=998) NbAtType |
1130 | 1 | equemene | 998 CONTINUE |
1131 | 1 | equemene | NbType=0 |
1132 | 1 | equemene | DO WHILE (NbAtType(NbType+1).NE.0) |
1133 | 1 | equemene | NbType=NbType+1 |
1134 | 1 | equemene | END DO |
1135 | 1 | equemene | |
1136 | 1 | equemene | ! Do we know the atom types ? |
1137 | 1 | equemene | IF (AtTypes(1).EQ.' ') THEN |
1138 | 1 | equemene | ! user has not provided atom types... we have to find them ourselves |
1139 | 1 | equemene | ! by looking into the POTCAR file... |
1140 | 1 | equemene | INQUIRE(File="POTCAR", EXIST=Tchk) |
1141 | 1 | equemene | IF (.NOT.Tchk) THEN |
1142 | 1 | equemene | WRITE(*,*) "ERROR! No AtTypes provided, and POTCAR file not found" |
1143 | 1 | equemene | STOP |
1144 | 1 | equemene | END IF |
1145 | 1 | equemene | OPEN(IOTMP,File="POTCAR") |
1146 | 1 | equemene | DO I=1,NbType |
1147 | 1 | equemene | Line='Empty' |
1148 | 1 | equemene | DO WHILE (Line(1:2).NE.'US') |
1149 | 1 | equemene | READ(IOTMP,'(A)') Line |
1150 | 1 | equemene | Line=AdjustL(Line) |
1151 | 1 | equemene | END DO |
1152 | 1 | equemene | Line=adjustl(Line(3:)) |
1153 | 1 | equemene | AtTypes(I)=Line(1:2) |
1154 | 1 | equemene | END DO |
1155 | 1 | equemene | if (debug) WRITE(*,'(A,100(1X,A2))') "ReadG:VASP AtTypes",AtTypes(1:NbType) |
1156 | 1 | equemene | CLOSE(IOTMP) |
1157 | 1 | equemene | |
1158 | 1 | equemene | ELSE !AtTypes(1).EQ.' ' |
1159 | 1 | equemene | ! user has provided atom types |
1160 | 1 | equemene | NbTypeUser=0 |
1161 | 1 | equemene | DO WHILE (AtTypes(NbTypeUser+1).NE.' ') |
1162 | 1 | equemene | NbTypeUser=NbTypeUser+1 |
1163 | 1 | equemene | END DO |
1164 | 1 | equemene | IF (NbType.NE.NbTypeUser) THEN |
1165 | 1 | equemene | WRITE(*,*) "ERROR Read_Geom : NbType in POSCAR do not match AtTypes" |
1166 | 1 | equemene | STOP |
1167 | 1 | equemene | END IF |
1168 | 1 | equemene | END IF |
1169 | 1 | equemene | |
1170 | 1 | equemene | IAt=1 |
1171 | 1 | equemene | DO I=1,NbType |
1172 | 1 | equemene | DO J=1,NbAtType(I) |
1173 | 1 | equemene | AtName(Iat)=AtTypes(I) |
1174 | 1 | equemene | Iat=Iat+1 |
1175 | 1 | equemene | END DO |
1176 | 1 | equemene | END DO |
1177 | 1 | equemene | DEALLOCATE(NbAtType) |
1178 | 1 | equemene | |
1179 | 1 | equemene | NbTypes=NbType |
1180 | 1 | equemene | |
1181 | 1 | equemene | READ(IOIN,'(A)') Vasp_comment |
1182 | 1 | equemene | READ(IOIN,'(A)') Vasp_direct |
1183 | 1 | equemene | V_direct=Adjustl(Vasp_direct) |
1184 | 1 | equemene | Call UpCase(V_direct) |
1185 | 1 | equemene | |
1186 | 1 | equemene | END IF |
1187 | 1 | equemene | |
1188 | 1 | equemene | ! In the case of VASP there is always the problem of moving from one side |
1189 | 1 | equemene | ! of the box to the other... |
1190 | 1 | equemene | ! PFL 2010 Dec 2 -> |
1191 | 1 | equemene | ! Here we deal with input and not prog in fact |
1192 | 1 | equemene | ! if (prog.EQ.'VASP') THEN |
1193 | 1 | equemene | if (Input.EQ.'VASP') THEN |
1194 | 1 | equemene | ! <- PFL 2010 Dec 2 |
1195 | 1 | equemene | Renum=.TRUE. |
1196 | 1 | equemene | |
1197 | 1 | equemene | ! V_direct has been set in Read_geom |
1198 | 1 | equemene | IF (V_direct(1:6).EQ.'DIRECT') THEN |
1199 | 1 | equemene | Latr(1:3,1)=Lat_a |
1200 | 1 | equemene | Latr(1:3,2)=Lat_b |
1201 | 1 | equemene | Latr(1:3,3)=Lat_c |
1202 | 1 | equemene | B=1. |
1203 | 1 | equemene | CALL Gaussj(Latr,3,3,B,1,1) |
1204 | 1 | equemene | ELSE |
1205 | 1 | equemene | Latr=0. |
1206 | 1 | equemene | Latr(1,1)=1.d0 |
1207 | 1 | equemene | Latr(2,2)=1.d0 |
1208 | 1 | equemene | Latr(3,3)=1.d0 |
1209 | 1 | equemene | END IF |
1210 | 1 | equemene | |
1211 | 1 | equemene | ! Actualization of Frozen using the FFFF... |
1212 | 1 | equemene | ! Frozen has the advantage ie if given, it imposes _ALL_ the FFF flags. |
1213 | 1 | equemene | IF (Frozen(1).NE.0) THEN |
1214 | 1 | equemene | WRITE(IOOUT,*) "Frozen is given. Flags of the given POSCAR are overriden" |
1215 | 1 | equemene | FFF='T' |
1216 | 1 | equemene | |
1217 | 1 | equemene | NFroz=0 |
1218 | 1 | equemene | DO WHILE (Frozen(NFroz+1).NE.0) |
1219 | 1 | equemene | NFroz=NFroz+1 |
1220 | 1 | equemene | FFF(1:3,Frozen(NFroz))='F' |
1221 | 1 | equemene | END DO |
1222 | 1 | equemene | ELSE |
1223 | 1 | equemene | WRITE(IOOUT,*) "Frozen not given : using Flags of the given POSCAR" |
1224 | 1 | equemene | NFroz=0 |
1225 | 1 | equemene | Frozen=0 |
1226 | 1 | equemene | DO I=1,Nat |
1227 | 1 | equemene | IF ((FFF(1,I).EQ.'F').OR.(FFF(2,I).EQ.'F').OR.(FFF(3,I).EQ.'F')) THEN |
1228 | 1 | equemene | FFF(1:3,I)='F' |
1229 | 1 | equemene | NFroz=NFroz+1 |
1230 | 1 | equemene | Frozen(NFroz)=I |
1231 | 1 | equemene | END IF |
1232 | 1 | equemene | END DO |
1233 | 1 | equemene | WRITE(IOOUT,*) "Frozen atoms:",Frozen(1:NFroz) |
1234 | 1 | equemene | END IF |
1235 | 1 | equemene | |
1236 | 1 | equemene | |
1237 | 1 | equemene | END IF |
1238 | 1 | equemene | |
1239 | 1 | equemene | IF (Prog=="VASP") THEN |
1240 | 1 | equemene | IF (Vmd) THEN |
1241 | 1 | equemene | if (debug) WRITE(*,*) "DBG MAIN, L803, VMD=T,NbTypes,AtTypes",NbTypes,AtTypes(1:NbTypes) |
1242 | 1 | equemene | Line="" |
1243 | 1 | equemene | DO I=1,NbTypes |
1244 | 1 | equemene | Line=TRIM(Line) // " " // TRIM(AdjustL(AtTypes(I))) |
1245 | 1 | equemene | END DO |
1246 | 1 | equemene | Vasp_Title=Trim(Line) // " " // Trim(adjustL(Vasp_Title)) |
1247 | 1 | equemene | if (debug) WRITE(*,*) "DBG MAIN, L809, VMD=T, Vasp_Title=",TRIM(Vasp_Title) |
1248 | 1 | equemene | END IF |
1249 | 1 | equemene | Call CheckPeriodicBound |
1250 | 1 | equemene | END IF |
1251 | 1 | equemene | |
1252 | 1 | equemene | IF (COORD=="MIXED") Call TestCart(AutoCart) |
1253 | 1 | equemene | |
1254 | 1 | equemene | SELECT CASE(NFroz) |
1255 | 1 | equemene | CASE (2) |
1256 | 1 | equemene | IntFroz=1 |
1257 | 1 | equemene | CASE (3) |
1258 | 1 | equemene | IntFroz=3 |
1259 | 1 | equemene | CASE (4:) |
1260 | 1 | equemene | IntFroz=(NFroz-2)*3 !(NFroz-3)*3+3 |
1261 | 1 | equemene | END SELECT |
1262 | 1 | equemene | |
1263 | 1 | equemene | if (debug) WRITE(*,'(1X,A,A,5I5)') "DBG Path, L825, Coord, NCart, NCoord, N3at, NFroz: "& |
1264 | 1 | equemene | ,TRIM(COORD),Ncart,NCoord,N3at,NFroz |
1265 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path, L827, Cart",Cart |
1266 | 1 | equemene | |
1267 | 1 | equemene | if (((NCart+NFroz).EQ.0).AND.(Coord=="MIXED")) THEN |
1268 | 1 | equemene | WRITE(IOOUT,*) "Coord=MIXED but Cart list empty: taking Coord=ZMAT." |
1269 | 1 | equemene | COORD="ZMAT" |
1270 | 1 | equemene | END IF |
1271 | 1 | equemene | |
1272 | 1 | equemene | IF ((Coord=="MIXED").AND.(NFroz.NE.0)) IntFroz=3*NFroz |
1273 | 1 | equemene | |
1274 | 1 | equemene | SELECT CASE(COORD) |
1275 | 1 | equemene | CASE ('ZMAT') |
1276 | 1 | equemene | NCoord=Nfree |
1277 | 1 | equemene | ALLOCATE(dzdc(3,nat,3,nat)) |
1278 | 1 | equemene | CASE ('MIXED') |
1279 | 1 | equemene | SELECT CASE (NCart+NFroz) |
1280 | 1 | equemene | CASE (1) |
1281 | 1 | equemene | NCoord=N3At-3 |
1282 | 1 | equemene | CASE (2) |
1283 | 1 | equemene | NCoord=N3At-1 |
1284 | 1 | equemene | CASE (3:) |
1285 | 1 | equemene | NCoord=N3At |
1286 | 1 | equemene | END SELECT |
1287 | 1 | equemene | ALLOCATE(dzdc(3,nat,3,nat)) |
1288 | 1 | equemene | CASE ('BAKER') |
1289 | 1 | equemene | Symmetry_elimination=0 |
1290 | 1 | equemene | NCoord=3*Nat-6-Symmetry_elimination !NFree = 3*Nat-6 |
1291 | 1 | equemene | ALLOCATE(BMat_BakerT(3*Nat,NCoord)) |
1292 | 1 | equemene | ALLOCATE(BTransInv(NCoord,3*Nat)) |
1293 | 1 | equemene | ALLOCATE(BTransInv_local(NCoord,3*Nat)) |
1294 | 1 | equemene | CASE ('HYBRID') |
1295 | 1 | equemene | NCoord=N3at |
1296 | 1 | equemene | CASE ('CART') |
1297 | 1 | equemene | NCoord=N3at |
1298 | 1 | equemene | END SELECT |
1299 | 1 | equemene | |
1300 | 1 | equemene | if (debug) WRITE(*,*) "DBG Path, L826, Coord, NCart,NCoord, N3At",TRIM(COORD),Ncart, NCoord,N3at |
1301 | 1 | equemene | |
1302 | 1 | equemene | ALLOCATE(IntCoordI(NGeomI,NCoord),IntCoordF(NGeomF,NCoord)) |
1303 | 1 | equemene | ALLOCATE(XyzGeomF(NGeomF,3,Nat),XyzTangent(NGeomF,3*Nat)) |
1304 | 1 | equemene | ALLOCATE(Vfree(NCoord,NCoord),IntTangent(NGeomF,NCoord)) |
1305 | 1 | equemene | ALLOCATE(Energies(NgeomF),ZeroVec(NCoord)) ! Energies is declared in Path_module.f90 |
1306 | 1 | equemene | ALLOCATE(Grad(NGeomF,NCoord),GeomTmp(NCoord),GradTmp(NCoord)) |
1307 | 1 | equemene | ALLOCATE(GeomOld_all(NGeomF,NCoord),GradOld(NGeomF,NCoord)) |
1308 | 1 | equemene | ALLOCATE(Hess(NGeomF,NCoord,NCoord),SGeom(NGeomF)) ! SGeom is declared in Path_module.f90 |
1309 | 1 | equemene | ALLOCATE(EPathOld(NGeomF),MaxStep(NGeomF)) |
1310 | 1 | equemene | |
1311 | 1 | equemene | ZeroVec=0.d0 |
1312 | 1 | equemene | DO I =1, NGeomF |
1313 | 1 | equemene | IntTangent(I,:)=0.d0 |
1314 | 1 | equemene | END DO |
1315 | 1 | equemene | |
1316 | 1 | equemene | if (debug) THEN |
1317 | 1 | equemene | Print *, 'L886, IntTangent(1,:)=' |
1318 | 1 | equemene | Print *, IntTangent(1,:) |
1319 | 1 | equemene | END IF |
1320 | 1 | equemene | |
1321 | 1 | equemene | if (.NOT.OptReac) Energies(1)=Ereac |
1322 | 1 | equemene | if (.NOT.OptProd) Energies(NGeomF)=EProd |
1323 | 1 | equemene | MaxStep=SMax |
1324 | 1 | equemene | |
1325 | 1 | equemene | ! We initialize the mass array |
1326 | 1 | equemene | if (MW) THEN |
1327 | 1 | equemene | WRITE(*,*) 'Working in MW coordinates' |
1328 | 1 | equemene | DO I=1,Nat |
1329 | 1 | equemene | massAt(I)=Mass(Atome(I)) |
1330 | 1 | equemene | END DO |
1331 | 1 | equemene | ELSE |
1332 | 1 | equemene | DO I=1,Nat |
1333 | 1 | equemene | MassAt(I)=1.d0 |
1334 | 1 | equemene | END DO |
1335 | 1 | equemene | END IF |
1336 | 1 | equemene | |
1337 | 1 | equemene | WRITE(*,*) "Prog=",TRIM(PROG) |
1338 | 1 | equemene | |
1339 | 1 | equemene | ALLOCATE(FrozAtoms(Nat)) |
1340 | 1 | equemene | |
1341 | 1 | equemene | ! IF (debug) WRITe(*,*) "DBG Main L940 NFroz",NFroz |
1342 | 1 | equemene | ! IF (debug) WRITe(*,*) "DBG Main L940 Frozen",Frozen |
1343 | 1 | equemene | ! IF (debug) WRITe(*,*) "DBG Main L940 FrozAtoms",FrozAtoms |
1344 | 1 | equemene | IF (NFroz.EQ.0) THEN |
1345 | 1 | equemene | FrozAtoms=.TRUE. |
1346 | 1 | equemene | ELSE |
1347 | 1 | equemene | I=1 |
1348 | 1 | equemene | NFr=0 |
1349 | 1 | equemene | FrozAtoms=.False. |
1350 | 1 | equemene | DO WHILE (Frozen(I).NE.0) |
1351 | 1 | equemene | IF (Frozen(I).LT.0) THEN |
1352 | 1 | equemene | DO J=Frozen(I-1),abs(Frozen(I)) |
1353 | 1 | equemene | IF (.NOT.FrozAtoms(J)) THEN |
1354 | 1 | equemene | NFr=NFr+1 |
1355 | 1 | equemene | FrozAtoms(J)=.TRUE. |
1356 | 1 | equemene | END IF |
1357 | 1 | equemene | END DO |
1358 | 1 | equemene | ELSEIF (.NOT.FrozAtoms(Frozen(I))) THEN |
1359 | 1 | equemene | FrozAtoms(Frozen(I))=.TRUE. |
1360 | 1 | equemene | NFr=NFr+1 |
1361 | 1 | equemene | END IF |
1362 | 1 | equemene | I=I+1 |
1363 | 1 | equemene | END DO |
1364 | 1 | equemene | IF (NFr.NE.NFroz) THEN |
1365 | 1 | equemene | WRITE(*,*) "Pb in PATH: Number of Frozen atoms not good :-( ",NFroz,NFr |
1366 | 1 | equemene | STOP |
1367 | 1 | equemene | END IF |
1368 | 1 | equemene | END IF |
1369 | 1 | equemene | |
1370 | 1 | equemene | if (debug) THEN |
1371 | 1 | equemene | !Print *, 'L968, IntTangent(1,:)=' |
1372 | 1 | equemene | !Print *, IntTangent(1,:) |
1373 | 1 | equemene | END IF |
1374 | 1 | equemene | |
1375 | 1 | equemene | ! We have read everything we needed... time to work :-) |
1376 | 1 | equemene | IOpt=0 |
1377 | 1 | equemene | FirstTimePathCreate = .TRUE. ! Initialized. |
1378 | 1 | equemene | Call PathCreate(IOpt) ! IntTangent is also computed in PathCreate. |
1379 | 1 | equemene | FirstTimePathCreate = .FALSE. |
1380 | 1 | equemene | |
1381 | 1 | equemene | if (debug) THEN |
1382 | 1 | equemene | Print *, 'L980, IntTangent(1,:)=' |
1383 | 1 | equemene | Print *, IntTangent(1,:) |
1384 | 1 | equemene | END IF |
1385 | 1 | equemene | |
1386 | 1 | equemene | ! PFL 30 Mar 2008 -> |
1387 | 1 | equemene | ! The following is now allocated in Calc_Baker. This is more logical to me |
1388 | 1 | equemene | ! IF (COORD .EQ. "BAKER") Then |
1389 | 1 | equemene | ! ALLOCATE(XprimitiveF(NgeomF,NbCoords)) |
1390 | 1 | equemene | ! ALLOCATE(UMatF(NGeomF,NbCoords,NCoord)) |
1391 | 1 | equemene | ! ALLOCATE(BTransInvF(NGeomF,NCoord,3*Nat)) |
1392 | 1 | equemene | ! END IF |
1393 | 1 | equemene | ! <- PFL 30 mar 2008 |
1394 | 1 | equemene | |
1395 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
1396 | 1 | equemene | ! |
1397 | 1 | equemene | ! For Debugging purposes |
1398 | 1 | equemene | ! |
1399 | 1 | equemene | ! OptGeom is the index of the geometry which is to be optimized. |
1400 | 1 | equemene | IF (Optgeom.GT.0) THEN |
1401 | 1 | equemene | Flag_Opt_Geom=.TRUE. |
1402 | 1 | equemene | SELECT CASE(Coord) |
1403 | 1 | equemene | CASE ('CART','HYBRID') |
1404 | 1 | equemene | !!! CAUTION : PFL 29.AUG.2008 -> |
1405 | 1 | equemene | ! XyzGeomI/F stored in (NGeomI/F,3,Nat) and NOT (NGeomI/F,Nat,3) |
1406 | 1 | equemene | ! This should be made consistent !!!!!!!!!!!!!!! |
1407 | 1 | equemene | GeomTmp=Reshape(reshape(XyzGeomF(OptGeom,:,:),(/Nat,3/),ORDER=(/2,1/)),(/3*Nat/)) |
1408 | 1 | equemene | ! GeomTmp=Reshape(XyzGeomF(IGeom,:,:),(/3*Nat/)) |
1409 | 1 | equemene | !!! <- CAUTION : PFL 29.AUG.2008 |
1410 | 1 | equemene | CASE ('ZMAT','MIXED') |
1411 | 1 | equemene | !GeomTmp=IntCoordF(OptGeom,:) |
1412 | 1 | equemene | GeomTmp=IntCoordI(OptGeom,:) |
1413 | 1 | equemene | CASE ('BAKER') |
1414 | 1 | equemene | !GeomTmp=IntCoordF(OptGeom,:) |
1415 | 1 | equemene | GeomTmp=IntCoordI(OptGeom,:) |
1416 | 1 | equemene | CASE DEFAULT |
1417 | 1 | equemene | WRITE(*,*) "Coord=",TRIM(COORD)," not recognized in Path L935.STOP" |
1418 | 1 | equemene | STOP |
1419 | 1 | equemene | END SELECT |
1420 | 1 | equemene | |
1421 | 1 | equemene | ! NCoord = NFree, Coord = Type of coordinate; e.g.: Baker |
1422 | 1 | equemene | Flag_Opt_Geom = .TRUE. |
1423 | 1 | equemene | Call Opt_geom(OptGeom,Nat,Ncoord,Coord,GeomTmp,E,Flag_Opt_Geom,Step_method) |
1424 | 1 | equemene | |
1425 | 1 | equemene | WRITE(Line,"('Geometry ',I3,' optimized')") Optgeom |
1426 | 1 | equemene | WRITE(*,*) "Before PrintGeom, L1059, Path.f90" |
1427 | 1 | equemene | Call PrintGeom(Line,Nat,NCoord,GeomTmp,Coord,IoOut,Atome,Order,OrderInv,IndZmat) |
1428 | 1 | equemene | STOP |
1429 | 1 | equemene | END IF ! IF (Optgeom.GT.0) THEN |
1430 | 1 | equemene | |
1431 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
1432 | 1 | equemene | ! End of GeomOpt |
1433 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
1434 | 1 | equemene | |
1435 | 1 | equemene | IF (PathOnly) THEN |
1436 | 1 | equemene | WRITE(*,*) "PathOnly=.T. , Stop here" |
1437 | 1 | equemene | Call Write_path(-1) |
1438 | 1 | equemene | if ((prog.EQ.'VASP').OR.WriteVasp) Call Write_vasp(poscar) |
1439 | 1 | equemene | STOP |
1440 | 1 | equemene | END IF |
1441 | 1 | equemene | |
1442 | 1 | equemene | if ((debug.AND.(prog.EQ.'VASP')).OR.WriteVasp) Call Write_vasp(poscar) |
1443 | 1 | equemene | |
1444 | 1 | equemene | DEALLOCATE(XyzGeomI,IntCoordI) |
1445 | 1 | equemene | NGeomI=NGeomF |
1446 | 1 | equemene | ALLOCATE(XyzGeomI(NGeomF,3,Nat),IntCoordI(NGeomF,NCoord)) |
1447 | 1 | equemene | |
1448 | 1 | equemene | IF (DEBUG) WRITE(*,*) ' Back from PathCreate, L965, Path.f90' |
1449 | 1 | equemene | ! we print this path, which is the first one :-) called Iteration0 |
1450 | 1 | equemene | ! we now have to calculate the gradient for each point (and the energy |
1451 | 1 | equemene | ! if we work at 0K) |
1452 | 1 | equemene | |
1453 | 1 | equemene | if (DEBUG.AND.(COORD.EQ."BAKER")) THEN |
1454 | 1 | equemene | DO IGeom=1,NGeomF |
1455 | 1 | equemene | WRITE(*,*) "Before Calc_baker_allgeomf UMatF for IGeom=",IGeom |
1456 | 1 | equemene | DO I=1,3*Nat-6 |
1457 | 1 | equemene | WRITE(*,'(50(1X,F12.8))') UMatF(IGeom,:,I) |
1458 | 1 | equemene | END DO |
1459 | 1 | equemene | END DO |
1460 | 1 | equemene | END IF |
1461 | 1 | equemene | |
1462 | 1 | equemene | ! To calculate B^T^-1 for all extrapolated final geometries: |
1463 | 1 | equemene | ! PFL 18 Jan 2008 -> |
1464 | 1 | equemene | ! Added a test for COORD=BAKER before the call to calc_baker_allgeomF |
1465 | 1 | equemene | IF (COORD.EQ."BAKER") Call Calc_baker_allGeomF() |
1466 | 1 | equemene | ! <-- PFL 18 Jan 2008 |
1467 | 1 | equemene | |
1468 | 1 | equemene | if (DEBUG.AND.(COORD.EQ."BAKER")) THEN |
1469 | 1 | equemene | DO IGeom=1,NGeomF |
1470 | 1 | equemene | WRITE(*,*) "After Calc_baker_allgeomf UMatF for IGeom=",IGeom |
1471 | 1 | equemene | DO I=1,3*Nat-6 |
1472 | 1 | equemene | WRITE(*,'(50(1X,F12.8))') UMatF(IGeom,:,I) |
1473 | 1 | equemene | END DO |
1474 | 1 | equemene | END DO |
1475 | 1 | equemene | END IF |
1476 | 1 | equemene | |
1477 | 1 | equemene | IOpt=0 |
1478 | 1 | equemene | Call EgradPath(IOpt,Flag_Opt_Geom) |
1479 | 1 | equemene | |
1480 | 1 | equemene | if (debug) WRITE(*,*) "Calling Write_path, L1002, Path.f90, IOpt=",IOpt |
1481 | 1 | equemene | Call Write_path(IOpt) |
1482 | 1 | equemene | if ((debug.AND.(prog.EQ.'VASP')).OR.WriteVasp) Call Write_vasp(poscar) |
1483 | 1 | equemene | |
1484 | 1 | equemene | ! We have the geometries, the first gradients... we will generate the first hessian matrices :-) |
1485 | 1 | equemene | ! ... v3.71 Only if IniHUp=.TRUE. which is not the default. In this version, we take the hessian |
1486 | 1 | equemene | ! of end points as Unity matrices, and we update them along the path. |
1487 | 1 | equemene | |
1488 | 1 | equemene | ! By default, Hess=Id |
1489 | 1 | equemene | Hess=0. |
1490 | 1 | equemene | IF(Coord .EQ. "ZMAT") Then |
1491 | 1 | equemene | ! We use the fact that we know that approximate good hessian values |
1492 | 1 | equemene | ! are 0.5 for bonds, 0.1 for valence angle and 0.02 for dihedral angles |
1493 | 1 | equemene | DO IGeom=1,NGeomF |
1494 | 1 | equemene | Hess(IGeom,1,1)=0.5d0 |
1495 | 1 | equemene | Hess(IGeom,2,2)=0.5d0 |
1496 | 1 | equemene | Hess(IGeom,3,3)=0.1d0 |
1497 | 1 | equemene | DO J=1,Nat-3 |
1498 | 1 | equemene | Hess(IGeom,3*J+1,3*J+1)=0.5d0 |
1499 | 1 | equemene | Hess(IGeom,3*J+2,3*J+2)=0.1d0 |
1500 | 1 | equemene | Hess(IGeom,3*J+3,3*J+3)=0.02d0 |
1501 | 1 | equemene | END DO |
1502 | 1 | equemene | IF (HInv) THEN |
1503 | 1 | equemene | DO I=1,NCoord |
1504 | 1 | equemene | Hess(IGeom,I,I)=1.d0/Hess(IGeom,I,I) |
1505 | 1 | equemene | END DO |
1506 | 1 | equemene | END IF |
1507 | 1 | equemene | END DO |
1508 | 1 | equemene | ELSE |
1509 | 1 | equemene | DO I=1,NCoord |
1510 | 1 | equemene | DO J=1,NGeomF |
1511 | 1 | equemene | Hess(J,I,I)=1.d0 |
1512 | 1 | equemene | END DO |
1513 | 1 | equemene | END DO |
1514 | 1 | equemene | END IF |
1515 | 1 | equemene | |
1516 | 1 | equemene | IF (COORD .EQ. "BAKER") THEN |
1517 | 1 | equemene | ! UMat(NPrim,NCoord) |
1518 | 1 | equemene | ALLOCATE(Hprim(NPrim,NPrim),HprimU(NPrim,3*Nat-6)) |
1519 | 1 | equemene | Hprim=0.d0 |
1520 | 1 | equemene | ScanCoord=>Coordinate |
1521 | 1 | equemene | I=0 |
1522 | 1 | equemene | DO WHILE (Associated(ScanCoord%next)) |
1523 | 1 | equemene | I=I+1 |
1524 | 1 | equemene | SELECT CASE (ScanCoord%Type) |
1525 | 1 | equemene | CASE ('BOND') |
1526 | 1 | equemene | !DO J=1,NGeomF ! why all geometries?? Should be only 1st and NGeomF?? |
1527 | 1 | equemene | Hprim(I,I) = 0.5d0 |
1528 | 1 | equemene | !END DO |
1529 | 1 | equemene | CASE ('ANGLE') |
1530 | 1 | equemene | Hprim(I,I) = 0.2d0 |
1531 | 1 | equemene | CASE ('DIHEDRAL') |
1532 | 1 | equemene | Hprim(I,I) = 0.1d0 |
1533 | 1 | equemene | END SELECT |
1534 | 1 | equemene | ScanCoord => ScanCoord%next |
1535 | 1 | equemene | END DO |
1536 | 1 | equemene | |
1537 | 1 | equemene | ! HprimU = H^prim U: |
1538 | 1 | equemene | HprimU=0.d0 |
1539 | 1 | equemene | DO I=1, 3*Nat-6 |
1540 | 1 | equemene | DO J=1,NPrim |
1541 | 1 | equemene | HprimU(:,I) = HprimU(:,I) + Hprim(:,J)*UMat(J,I) |
1542 | 1 | equemene | END DO |
1543 | 1 | equemene | END DO |
1544 | 1 | equemene | |
1545 | 1 | equemene | ! Hess = U^T HprimU = U^T H^prim U: |
1546 | 1 | equemene | Hess=0.d0 |
1547 | 1 | equemene | DO I=1, 3*Nat-6 |
1548 | 1 | equemene | DO J=1,NPrim |
1549 | 1 | equemene | ! UMat^T is needed below. |
1550 | 1 | equemene | Hess(1,:,I) = Hess(1,:,I) + UMat(J,:)*HprimU(J,I) |
1551 | 1 | equemene | END DO |
1552 | 1 | equemene | END DO |
1553 | 1 | equemene | DO K=2,NGeomF |
1554 | 1 | equemene | Hess(K,:,:)=Hess(1,:,:) |
1555 | 1 | equemene | END DO |
1556 | 1 | equemene | DEALLOCATE(Hprim,HprimU) |
1557 | 1 | equemene | end if ! ends IF COORD=BAKER |
1558 | 1 | equemene | ALLOCATE(GradTmp2(NCoord),GeomTmp2(NCoord)) |
1559 | 1 | equemene | ALLOCATE(HessTmp(NCoord,NCoord)) |
1560 | 1 | equemene | |
1561 | 1 | equemene | IF (IniHUp) THEN |
1562 | 1 | equemene | IF (FCalcHess) THEN |
1563 | 1 | equemene | ! The numerical calculation of the Hessian has been switched on |
1564 | 1 | equemene | DO IGeom=1,NGeomF |
1565 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
1566 | 1 | equemene | GeomTmp=IntCoordF(IGeom,:) |
1567 | 1 | equemene | ELSE |
1568 | 1 | equemene | GeomTmp=Reshape(XyzGeomF(IGeom,:,:),(/3*Nat/)) |
1569 | 1 | equemene | END IF |
1570 | 1 | equemene | Call CalcHess(NCoord,GeomTmp,Hess(IGeom,:,:),IGeom,Iopt) |
1571 | 1 | equemene | END DO |
1572 | 1 | equemene | ELSE |
1573 | 1 | equemene | ! We generate a forward hessian and a backward one and we mix them. |
1574 | 1 | equemene | ! First, the forward way: |
1575 | 1 | equemene | DO IGeom=2,NGeomF-1 |
1576 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
1577 | 1 | equemene | GeomTmp=IntCoordF(IGeom,:)-IntCoordF(IGeom-1,:) |
1578 | 1 | equemene | ELSE |
1579 | 1 | equemene | GeomTmp=Reshape(XyzGeomF(IGeom,:,:),(/3*Nat/))-Reshape(XyzGeomF(IGeom-1,:,:),(/3*Nat/)) |
1580 | 1 | equemene | END IF |
1581 | 1 | equemene | GradTmp=Grad(IGeom-1,:)-Grad(IGeom,:) |
1582 | 1 | equemene | HessTmp=Hess(IGeom-1,:,:) |
1583 | 1 | equemene | Call Hupdate_all(NCoord,GeomTmp,GradTmp,HessTmp) |
1584 | 1 | equemene | Hess(IGeom,:,:)=HessTmp |
1585 | 1 | equemene | END DO |
1586 | 1 | equemene | |
1587 | 1 | equemene | ! Now, the backward way: |
1588 | 1 | equemene | HessTmp=Hess(NGeomF,:,:) |
1589 | 1 | equemene | DO IGeom=NGeomF-1,2,-1 |
1590 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
1591 | 1 | equemene | GeomTmp=IntCoordF(IGeom,:)-IntCoordF(IGeom+1,:) |
1592 | 1 | equemene | ELSE |
1593 | 1 | equemene | GeomTmp=Reshape(XyzGeomF(IGeom,:,:),(/3*Nat/))-Reshape(XyzGeomF(IGeom+1,:,:),(/3*Nat/)) |
1594 | 1 | equemene | END IF |
1595 | 1 | equemene | GradTmp=Grad(IGeom,:)-Grad(IGeom+1,:) |
1596 | 1 | equemene | Call Hupdate_all(NCoord,GeomTmp,GradTmp,HessTmp) |
1597 | 1 | equemene | alpha=0.5d0*Pi*(IGeom-1.)/(NGeomF-1.) |
1598 | 1 | equemene | ca=cos(alpha) |
1599 | 1 | equemene | sa=sin(alpha) |
1600 | 1 | equemene | Hess(IGeom,:,:)=ca*Hess(IGeom,:,:)+sa*HessTmp(:,:) |
1601 | 1 | equemene | END DO |
1602 | 1 | equemene | END IF ! matches IF (FCalcHess) |
1603 | 1 | equemene | END IF ! matches IF (IniHUp) THEN |
1604 | 1 | equemene | |
1605 | 1 | equemene | ! For debug purposes, we diagonalize the Hessian matrices |
1606 | 1 | equemene | IF (debug) THEN |
1607 | 1 | equemene | !WRITE(*,*) "DBG Main, L1104, - EigenSystem for Hessian matrices" |
1608 | 1 | equemene | DO I=1,NGeomF |
1609 | 1 | equemene | WRITE(*,*) "DBG Main - Point ",I |
1610 | 1 | equemene | Call Jacobi(Hess(I,:,:),NCoord,GradTmp2,HessTmp,NCoord) |
1611 | 1 | equemene | DO J=1,NCoord |
1612 | 1 | equemene | WRITE(*,'(1X,I3,1X,F10.6," : ",20(1X,F8.4))') J,GradTmp2(J),HessTmp(J,1:min(20,NCoord)) |
1613 | 1 | equemene | END DO |
1614 | 1 | equemene | END DO |
1615 | 1 | equemene | END IF ! matches IF (debug) THEN |
1616 | 1 | equemene | |
1617 | 1 | equemene | ! we have the hessian matrices and the gradients, we can start the optimizations ! |
1618 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
1619 | 1 | equemene | ! |
1620 | 1 | equemene | ! Main LOOP : Optimization of the Path |
1621 | 1 | equemene | ! |
1622 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
1623 | 1 | equemene | if (debug) Print *, 'NGeomF=', NGeomF |
1624 | 1 | equemene | allocation_flag = .TRUE. |
1625 | 1 | equemene | |
1626 | 1 | equemene | Fini=.FALSE. |
1627 | 1 | equemene | |
1628 | 1 | equemene | DO WHILE ((IOpt.LT.MaxCyc).AND.(.NOT. Fini)) |
1629 | 1 | equemene | if (debug) Print *, 'IOpt at the begining of the loop, L1128=', IOpt |
1630 | 1 | equemene | IOpt=IOpt+1 |
1631 | 1 | equemene | |
1632 | 1 | equemene | SELECT CASE (COORD) |
1633 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
1634 | 1 | equemene | GeomOld_all=IntCoordF |
1635 | 1 | equemene | CASE ('CART','HYBRID') |
1636 | 1 | equemene | GeomOld_all=Reshape(XyzGeomF,(/NGeomF,NCoord/)) |
1637 | 1 | equemene | CASE DEFAULT |
1638 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1149.STOP' |
1639 | 1 | equemene | STOP |
1640 | 1 | equemene | END SELECT |
1641 | 1 | equemene | |
1642 | 1 | equemene | IF (((COORD.EQ.'ZMAT').OR.(COORD.EQ.'BAKER').OR.(COORD.EQ.'MIXED')).AND. & |
1643 | 1 | equemene | valid("printtangent")) THEN |
1644 | 1 | equemene | WRITE(*,*) "Visualization of tangents" |
1645 | 1 | equemene | Idx=min(12,NCoord) |
1646 | 1 | equemene | DO I=1,NGeomF |
1647 | 1 | equemene | WRITE(*,'(12(1X,F12.5))') IntCoordF(I,1:Idx)-0.5d0*IntTangent(I,1:Idx) |
1648 | 1 | equemene | WRITE(*,'(12(1X,F12.5))') IntCoordF(I,1:Idx)+0.5d0*IntTangent(I,1:Idx) |
1649 | 1 | equemene | WRITE(*,*) |
1650 | 1 | equemene | END DO |
1651 | 1 | equemene | WRITE(*,*) "END of tangents" |
1652 | 1 | equemene | END IF |
1653 | 1 | equemene | |
1654 | 1 | equemene | IF (((COORD.EQ.'ZMAT').OR.(COORD.EQ.'BAKER').OR.(COORD.EQ.'MIXED')).AND. & |
1655 | 1 | equemene | valid("printgrad")) THEN |
1656 | 1 | equemene | WRITE(*,*) "Visualization of gradients" |
1657 | 1 | equemene | Idx=min(12,NCoord) |
1658 | 1 | equemene | DO I=1,NGeomF |
1659 | 1 | equemene | WRITE(*,'(12(1X,F12.5))') IntCoordF(I,1:Idx)-1.d0*Grad(I,1:Idx) |
1660 | 1 | equemene | WRITE(*,'(12(1X,F12.5))') IntCoordF(I,1:Idx)+1.d0*Grad(I,1:Idx) |
1661 | 1 | equemene | WRITe(*,*) |
1662 | 1 | equemene | END DO |
1663 | 1 | equemene | WRITE(*,*) "END of gradients" |
1664 | 1 | equemene | END IF |
1665 | 1 | equemene | |
1666 | 1 | equemene | Fini=.TRUE. |
1667 | 1 | equemene | IF (OptReac) THEN !OptReac: True if one wants to optimize the geometry of the reactants. Default is FALSE. |
1668 | 1 | equemene | IGeom=1 |
1669 | 1 | equemene | if (debug) WRITE(*,*) '**************************************' |
1670 | 1 | equemene | if (debug) WRITE(*,*) 'Optimizing reactant' |
1671 | 1 | equemene | if (debug) WRITE(*,*) '**************************************' |
1672 | 1 | equemene | SELECT CASE (COORD) |
1673 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
1674 | 1 | equemene | SELECT CASE (Step_method) |
1675 | 1 | equemene | CASE ('RFO') |
1676 | 1 | equemene | !GradTmp(NCoord) becomes Step in Step_RFO_all and has INTENT(OUT). |
1677 | 1 | equemene | Call Step_RFO_all(NCoord,GradTmp,1,IntCoordF(1,:),Grad(1,:),Hess(1,:,:),ZeroVec) |
1678 | 1 | equemene | Print *, GradTmp |
1679 | 1 | equemene | CASE ('GDIIS') |
1680 | 1 | equemene | ! GradTmp(NCoord) becomes "step" below and has INTENT(OUT).: |
1681 | 1 | equemene | Call Step_DIIS_all(NGeomF,1,GradTmp,IntCoordF(1,:),Grad(1,:),HP,HEAT,& |
1682 | 1 | equemene | Hess(1,:,:),NCoord,allocation_flag,ZeroVec) |
1683 | 1 | equemene | Print *, 'OptReac, Steps from GDIIS, GeomNew - IntCoordF(1,:)=' |
1684 | 1 | equemene | Print *, GradTmp |
1685 | 1 | equemene | CASE ('GEDIIS') |
1686 | 1 | equemene | ! GradTmp(NCoord) becomes "step" below and has INTENT(OUT).: |
1687 | 1 | equemene | ! Energies are updated in EgradPath.f90 |
1688 | 1 | equemene | Call Step_GEDIIS_All(NGeomF,1,GradTmp,IntCoordF(1,:),Grad(1,:),Energies(1),Hess(1,:,:),& |
1689 | 1 | equemene | NCoord,allocation_flag,ZeroVec) |
1690 | 1 | equemene | !Call Step_GEDIIS(GeomTmp,IntCoordF(1,:),Grad(1,:),Energies(1),Hess(1,:,:),NCoord,allocation_flag) |
1691 | 1 | equemene | !GradTmp = GeomTmp - IntCoordF(1,:) |
1692 | 1 | equemene | !Print *, 'Old Geometry:' |
1693 | 1 | equemene | !Print *, IntCoordF(1,:) |
1694 | 1 | equemene | Print *, 'OptReac, Steps from GEDIIS, GradTmp = GeomTmp - IntCoordF(1,:)=' |
1695 | 1 | equemene | Print *, GradTmp |
1696 | 1 | equemene | !Print *, 'GeomTmp:' |
1697 | 1 | equemene | !Print *, GeomTmp |
1698 | 1 | equemene | GeomTmp(:) = GradTmp(:) + IntCoordF(1,:) |
1699 | 1 | equemene | CASE DEFAULT |
1700 | 1 | equemene | WRITE (*,*) "Step_method=",TRIM(Step_method)," not recognized, Path.f90, L1194. Stop" |
1701 | 1 | equemene | STOP |
1702 | 1 | equemene | END SELECT |
1703 | 1 | equemene | CASE ('HYBRID','CART') |
1704 | 1 | equemene | Call Step_RFO_all(NCoord,GradTmp,1,XyzGeomF(1,:,:),Grad(1,:),Hess(1,:,:),ZeroVec) |
1705 | 1 | equemene | CASE DEFAULT |
1706 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1200. STOP' |
1707 | 1 | equemene | STOP |
1708 | 1 | equemene | END SELECT |
1709 | 1 | equemene | |
1710 | 1 | equemene | IF (debug) THEN |
1711 | 1 | equemene | WRITE(Line,*) 'DBG Path, L1227,', TRIM(Step_method), 'Step for IOpt=',IOpt, ', IGeom=1' |
1712 | 1 | equemene | Call PrintGeom(Line,Nat,NCoord,GeomTmp,Coord,6,Atome,Order,OrderInv,IndZmat) |
1713 | 1 | equemene | END IF |
1714 | 1 | equemene | |
1715 | 1 | equemene | ! we have the Newton+RFO step, we will check that the maximum displacement is not greater than Smax |
1716 | 1 | equemene | NormStep=sqrt(DOT_Product(GradTmp,GradTmp)) |
1717 | 1 | equemene | FactStep=min(1.d0,MaxStep(Igeom)/NormStep) |
1718 | 1 | equemene | Fini=(Fini.AND.(NormStep.LE.SThresh)) |
1719 | 1 | equemene | OptReac=(NormStep.GT.SThresh) |
1720 | 1 | equemene | IF (debug) WRITE(*,*) "NormStep, SThresh, OptReac=",NormStep, SThresh, OptReac |
1721 | 1 | equemene | NormGrad=sqrt(DOT_Product(reshape(Grad(1,:),(/Nfree/)),reshape(Grad(1,:),(/NFree/)))) |
1722 | 1 | equemene | Fini=(Fini.AND.(NormGrad.LE.GThresh)) |
1723 | 1 | equemene | OptReac=(OptReac.OR.(NormGrad.GT.GThresh)) |
1724 | 1 | equemene | !Print *, 'Grad(1,:):' |
1725 | 1 | equemene | !Print *, Grad(1,:) |
1726 | 1 | equemene | IF (debug) WRITE(*,*) "NormGrad, GThresh, OptReac=",NormGrad, GThresh, OptReac |
1727 | 1 | equemene | |
1728 | 1 | equemene | GradTmp=GradTmp*FactStep |
1729 | 1 | equemene | |
1730 | 1 | equemene | ! we take care that frozen atoms do not move. |
1731 | 1 | equemene | IF (NFroz.NE.0) THEN |
1732 | 1 | equemene | SELECT CASE (COORD) |
1733 | 1 | equemene | CASE ('ZMAT','MIXED') |
1734 | 1 | equemene | GradTmp(1:IntFroz)=0.d0 |
1735 | 1 | equemene | CASE ('CART','HYBRID') |
1736 | 1 | equemene | DO I=1,Nat |
1737 | 1 | equemene | IF (FrozAtoms(I)) THEN |
1738 | 1 | equemene | Iat=Order(I) |
1739 | 1 | equemene | GradTmp(3*Iat-2:3*Iat)=0.d0 |
1740 | 1 | equemene | END IF |
1741 | 1 | equemene | END DO |
1742 | 1 | equemene | CASE('BAKER') |
1743 | 1 | equemene | GradTmp(1:IntFroz)=0.d0 !GradTmp is "step" in Step_RFO_all(..) |
1744 | 1 | equemene | CASE DEFAULT |
1745 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1323.STOP' |
1746 | 1 | equemene | STOP |
1747 | 1 | equemene | END SELECT |
1748 | 1 | equemene | END IF ! matches IF (NFroz.NE.0) THEN |
1749 | 1 | equemene | |
1750 | 1 | equemene | IF (debug) THEN |
1751 | 1 | equemene | !WRITE(Line,*) 'DBG Path, L1244, Step for IOpt=',IOpt, ', IGeom=1' |
1752 | 1 | equemene | !Call PrintGeom(Line,Nat,NCoord,GradTmp,Coord,6,Atome,Order,OrderInv,IndZmat) |
1753 | 1 | equemene | END IF |
1754 | 1 | equemene | |
1755 | 1 | equemene | IF (debug) THEN |
1756 | 1 | equemene | !WRITE(*,*) "DBG Main, L1249, IOpt=",IOpt, ', IGeom=1' |
1757 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
1758 | 1 | equemene | WRITE(*,'(12(1X,F8.3))') IntCoordF(1,1:min(12,NFree)) |
1759 | 1 | equemene | ELSE |
1760 | 1 | equemene | DO Iat=1,Nat |
1761 | 1 | equemene | WRITE(*,'(1X,A5,3(1X,F11.6))') Nom(Atome(Iat)), & |
1762 | 1 | equemene | XyzGeomF(IGeom,1:3,Iat) |
1763 | 1 | equemene | END DO |
1764 | 1 | equemene | END IF |
1765 | 1 | equemene | END IF ! matches IF (debug) THEN |
1766 | 1 | equemene | |
1767 | 1 | equemene | SELECT CASE (COORD) |
1768 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
1769 | 1 | equemene | IntcoordF(1,:)=IntcoordF(1,:)+GradTmp(:) !IGeom=1 |
1770 | 1 | equemene | CASE ('HYBRID','CART') |
1771 | 1 | equemene | XyzGeomF(1,:,:)=XyzGeomF(1,:,:)+reshape(GradTmp(:),(/3,Nat/)) |
1772 | 1 | equemene | CASE DEFAULT |
1773 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1201.STOP' |
1774 | 1 | equemene | STOP |
1775 | 1 | equemene | END SELECT |
1776 | 1 | equemene | |
1777 | 1 | equemene | IF (debug) THEN |
1778 | 1 | equemene | WRITE(*,*) "DBG Main, L1271, IOpt=",IOpt, ', IGeom=1' |
1779 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
1780 | 1 | equemene | WRITE(*,'(12(1X,F8.3))') IntCoordF(1,1:min(12,NFree)) |
1781 | 1 | equemene | ELSE |
1782 | 1 | equemene | DO Iat=1,Nat |
1783 | 1 | equemene | |
1784 | 1 | equemene | !!!!!!!!!! There was an OrderInv here... should I put it back ? |
1785 | 1 | equemene | ! It was with indzmat. IndZmat cannot appear here... |
1786 | 1 | equemene | WRITE(*,'(1X,A5,3(1X,F11.6))') Nom(Atome(Iat)), & |
1787 | 1 | equemene | XyzGeomF(IGeom,1:3,Iat) |
1788 | 1 | equemene | END DO |
1789 | 1 | equemene | END IF |
1790 | 1 | equemene | END IF ! matches IF (debug) THEN |
1791 | 1 | equemene | |
1792 | 1 | equemene | IF (.NOT.OptReac) WRITE(*,*) "Reactants optimized" |
1793 | 1 | equemene | ELSE ! Optreac |
1794 | 1 | equemene | IF (debug) WRITE(*,*) "Reactants already optimized, Fini=",Fini |
1795 | 1 | equemene | END IF ! matches IF (OptReac) THEN |
1796 | 1 | equemene | |
1797 | 1 | equemene | IF (OptProd) THEN !OptProd: True if one wants to optimize the geometry of the products. Default is FALSE. |
1798 | 1 | equemene | IGeom=NGeomF |
1799 | 1 | equemene | if (debug) WRITE(*,*) '******************' |
1800 | 1 | equemene | if (debug) WRITE(*,*) 'Optimizing product' |
1801 | 1 | equemene | if (debug) WRITE(*,*) '******************' |
1802 | 1 | equemene | SELECT CASE (COORD) |
1803 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
1804 | 1 | equemene | Print *, 'Optimizing product' |
1805 | 1 | equemene | SELECT CASE (Step_method) |
1806 | 1 | equemene | CASE ('RFO') |
1807 | 1 | equemene | !GradTmp(NCoord)) becomes "Step" in Step_RFO_all and has INTENT(OUT). |
1808 | 1 | equemene | Call Step_RFO_all(NCoord,GradTmp,NGeomF,IntCoordF(NGeomF,:),Grad(NGeomF,:),Hess(NGeomF,:,:),ZeroVec) |
1809 | 1 | equemene | Print *, GradTmp |
1810 | 1 | equemene | CASE ('GDIIS') |
1811 | 1 | equemene | ! GradTmp becomes "step" below and has INTENT(OUT): |
1812 | 1 | equemene | Call Step_DIIS_all(NGeomF,NGeomF,GradTmp,IntCoordF(NGeomF,:),Grad(NGeomF,:),& |
1813 | 1 | equemene | HP,HEAT,Hess(NGeomF,:,:),NCoord,allocation_flag,ZeroVec) |
1814 | 1 | equemene | Print *, 'OptProd, Steps from GDIIS, GeomNew - IntCoordF(NGeomF,:)=' |
1815 | 1 | equemene | Print *, GradTmp |
1816 | 1 | equemene | CASE ('GEDIIS') |
1817 | 1 | equemene | ! GradTmp(NCoord) becomes "step" below and has INTENT(OUT): |
1818 | 1 | equemene | Call Step_GEDIIS_All(NGeomF,NGeomF,GradTmp,IntCoordF(NGeomF,:),Grad(NGeomF,:),Energies(NGeomF),& |
1819 | 1 | equemene | Hess(NGeomF,:,:),NCoord,allocation_flag,ZeroVec) |
1820 | 1 | equemene | Print *, 'OptProd, Steps from GEDIIS, GeomNew - IntCoordF(NGeomF,:)=' |
1821 | 1 | equemene | Print *, GradTmp |
1822 | 1 | equemene | CASE DEFAULT |
1823 | 1 | equemene | WRITE (*,*) "Step_method=",TRIM(Step_method)," not recognized, Path.f90, L1309. Stop" |
1824 | 1 | equemene | STOP |
1825 | 1 | equemene | END SELECT |
1826 | 1 | equemene | CASE ('HYBRID','CART') |
1827 | 1 | equemene | Call Step_RFO_all(NCoord,GradTmp,IGeom,XyzGeomF(NGeomF,:,:),Grad(NGeomF,:),Hess(NGeomF,:,:),ZeroVec) |
1828 | 1 | equemene | CASE DEFAULT |
1829 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1460.STOP' |
1830 | 1 | equemene | STOP |
1831 | 1 | equemene | END SELECT |
1832 | 1 | equemene | |
1833 | 1 | equemene | ! we have the Newton+RFO step, we will check that the displacement is not greater than Smax |
1834 | 1 | equemene | NormStep=sqrt(DOT_Product(GradTmp,GradTmp)) |
1835 | 1 | equemene | FactStep=min(1.d0,MaxStep(IGeom)/NormStep) |
1836 | 1 | equemene | Fini=(Fini.AND.(NormStep.LE.SThresh)) |
1837 | 1 | equemene | OptProd=.NOT.(NormStep.LE.SThresh) |
1838 | 1 | equemene | NormGrad=sqrt(DOT_Product(reshape(Grad(NGeomF,:),(/Nfree/)),reshape(Grad(NGeomF,:),(/NFree/)))) |
1839 | 1 | equemene | Fini=(Fini.AND.(NormGrad.LE.GThresh)) |
1840 | 1 | equemene | OptProd=(OptProd.OR.(NormGrad.GT.GThresh)) |
1841 | 1 | equemene | IF (debug) WRITE(*,*) "NormGrad, GThresh, OptProd=",NormGrad, GThresh, OptProd |
1842 | 1 | equemene | |
1843 | 1 | equemene | GradTmp=GradTmp*FactStep |
1844 | 1 | equemene | |
1845 | 1 | equemene | ! we take care that frozen atoms do not move |
1846 | 1 | equemene | IF (NFroz.NE.0) THEN |
1847 | 1 | equemene | SELECT CASE (COORD) |
1848 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
1849 | 1 | equemene | GradTmp(1:IntFroz)=0.d0 |
1850 | 1 | equemene | CASE ('CART','HYBRID') |
1851 | 1 | equemene | DO I=1,Nat |
1852 | 1 | equemene | IF (FrozAtoms(I)) THEN |
1853 | 1 | equemene | Iat=Order(I) |
1854 | 1 | equemene | GradTmp(3*Iat-2:3*Iat)=0.d0 |
1855 | 1 | equemene | END IF |
1856 | 1 | equemene | END DO |
1857 | 1 | equemene | CASE DEFAULT |
1858 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1045.STOP' |
1859 | 1 | equemene | STOP |
1860 | 1 | equemene | END SELECT |
1861 | 1 | equemene | END IF ! matches IF (NFroz.NE.0) THEN |
1862 | 1 | equemene | |
1863 | 1 | equemene | IF (debug) THEN |
1864 | 1 | equemene | WRITE(*,*) "DBG Main, L1354, IGeom=, IOpt=",IGeom,IOpt |
1865 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
1866 | 1 | equemene | WRITE(*,'(12(1X,F8.3))') IntCoordF(IGeom,1:min(12,NFree)) |
1867 | 1 | equemene | ELSE |
1868 | 1 | equemene | DO Iat=1,Nat |
1869 | 1 | equemene | WRITE(*,'(1X,A5,3(1X,F11.6))') Nom(Atome(Iat)), & |
1870 | 1 | equemene | XyzGeomF(IGeom,1:3,Iat) |
1871 | 1 | equemene | END DO |
1872 | 1 | equemene | END IF |
1873 | 1 | equemene | END IF |
1874 | 1 | equemene | |
1875 | 1 | equemene | SELECT CASE (COORD) |
1876 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
1877 | 1 | equemene | IntcoordF(NGeomF,:)=IntcoordF(NGeomF,:)+GradTmp(:) ! IGeom is NGeomF. |
1878 | 1 | equemene | CASE ('HYBRID','CART') |
1879 | 1 | equemene | XyzGeomF(IGeom,:,:)=XyzGeomF(IGeom,:,:)+reshape(GradTmp(:),(/3,Nat/)) |
1880 | 1 | equemene | CASE DEFAULT |
1881 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1050.STOP' |
1882 | 1 | equemene | STOP |
1883 | 1 | equemene | END SELECT |
1884 | 1 | equemene | |
1885 | 1 | equemene | IF (debug) THEN |
1886 | 1 | equemene | WRITE(*,*) "DBG Main, L1376, IGeom=, IOpt=",IGeom,IOpt |
1887 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
1888 | 1 | equemene | WRITE(*,'(12(1X,F8.3))') IntCoordF(IGeom,1:min(12,NFree)) |
1889 | 1 | equemene | ELSE |
1890 | 1 | equemene | DO Iat=1,Nat |
1891 | 1 | equemene | WRITE(*,'(1X,A5,3(1X,F11.6))') Nom(Atome(Iat)), & |
1892 | 1 | equemene | XyzGeomF(IGeom,1:3,Iat) |
1893 | 1 | equemene | END DO |
1894 | 1 | equemene | END IF |
1895 | 1 | equemene | END IF |
1896 | 1 | equemene | ELSE ! Optprod |
1897 | 1 | equemene | IF (debug) WRITE(*,*) "Product already optimized, Fini=",Fini |
1898 | 1 | equemene | END IF !matches IF (OptProd) THEN |
1899 | 1 | equemene | |
1900 | 1 | equemene | IF (debug) WRITE(*,*) "Fini before L1491 path:",Fini |
1901 | 1 | equemene | |
1902 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
1903 | 1 | equemene | ! |
1904 | 1 | equemene | ! Optimizing other geometries |
1905 | 1 | equemene | ! |
1906 | 1 | equemene | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! |
1907 | 1 | equemene | |
1908 | 1 | equemene | |
1909 | 1 | equemene | |
1910 | 1 | equemene | DO IGeom=2,NGeomF-1 ! matches at L1556 |
1911 | 1 | equemene | if (debug) WRITE(*,*) '****************************' |
1912 | 1 | equemene | if (debug) WRITE(*,*) 'All other geometries, IGeom=',IGeom |
1913 | 1 | equemene | if (debug) WRITE(*,*) '****************************' |
1914 | 1 | equemene | |
1915 | 1 | equemene | SELECT CASE (COORD) |
1916 | 1 | equemene | CASE ('ZMAT','BAKER','MIXED') |
1917 | 1 | equemene | GradTmp2=reshape(IntTangent(IGeom,:),(/NCoord/)) |
1918 | 1 | equemene | ! PFL 6 Apr 2008 -> |
1919 | 1 | equemene | ! Special case, if FTan=0. we do not consider Tangent at all. |
1920 | 1 | equemene | ! To DO: add the full treatment of FTan |
1921 | 1 | equemene | if (FTan==0.) GradTmp2=ZeroVec |
1922 | 1 | equemene | ! <- PFL 6 Apr 2008 |
1923 | 1 | equemene | if (debug) THEN |
1924 | 1 | equemene | Print *, 'L1500, IntTangent(',IGeom,',:)=' |
1925 | 1 | equemene | Print *, IntTangent(IGeom,:) |
1926 | 1 | equemene | END IF |
1927 | 1 | equemene | !GradTmp(NCoord)) is actually "Step" in Step_RFO_all and has INTENT(OUT). |
1928 | 1 | equemene | SELECT CASE (Step_method) |
1929 | 1 | equemene | CASE ('RFO') |
1930 | 1 | equemene | Call Step_RFO_all(NCoord,GradTmp,IGeom,IntCoordF(IGeom,:),Grad(IGeom,:),Hess(IGeom,:,:),GradTmp2) |
1931 | 1 | equemene | CASE ('GDIIS') |
1932 | 1 | equemene | !The following has no effect at IOpt==1 |
1933 | 1 | equemene | !Print *, 'Before call of Step_diis_all, All other geometries, IGeom=', IGeom |
1934 | 1 | equemene | Call Step_DIIS_all(NGeomF,IGeom,GradTmp,IntCoordF(IGeom,:),Grad(IGeom,:),HP,HEAT,& |
1935 | 1 | equemene | Hess(IGeom,:,:),NCoord,allocation_flag,GradTmp2) |
1936 | 1 | equemene | Print *, 'All others, Steps from GDIIS, GeomNew - IntCoordF(IGeom,:)=' |
1937 | 1 | equemene | Print *, GradTmp |
1938 | 1 | equemene | CASE ('GEDIIS') |
1939 | 1 | equemene | ! GradTmp(NCoord) becomes "step" below and has INTENT(OUT): |
1940 | 1 | equemene | Call Step_GEDIIS_All(NGeomF,IGeom,GradTmp,IntCoordF(IGeom,:),Grad(IGeom,:),Energies(IGeom),& |
1941 | 1 | equemene | Hess(IGeom,:,:),NCoord,allocation_flag,GradTmp2) |
1942 | 1 | equemene | Print *, 'All others, Steps from GEDIIS, GeomNew - IntCoordF(IGeom,:)=' |
1943 | 1 | equemene | Print *, GradTmp |
1944 | 1 | equemene | CASE DEFAULT |
1945 | 1 | equemene | WRITE (*,*) "Step_method=",TRIM(Step_method)," not recognized, Path.f90, L1430. Stop" |
1946 | 1 | equemene | STOP |
1947 | 1 | equemene | END SELECT |
1948 | 1 | equemene | CASE ('HYBRID','CART') |
1949 | 1 | equemene | ! XyzTangent is implicitely in Nat,3... but all the rest is 3,Nat |
1950 | 1 | equemene | ! so we change it |
1951 | 1 | equemene | DO I=1,Nat |
1952 | 1 | equemene | DO J=1,3 |
1953 | 1 | equemene | GradTmp2(J+(I-1)*3)=XyzTangent(IGeom,(J-1)*Nat+I) |
1954 | 1 | equemene | END DO |
1955 | 1 | equemene | END DO |
1956 | 1 | equemene | ! GradTmp2=XyzTangent(IGeom,:) |
1957 | 1 | equemene | ! PFL 6 Apr 2008 -> |
1958 | 1 | equemene | ! Special case, if FTan=0. we do not consider Tangent at all. |
1959 | 1 | equemene | ! To DO: add the full treatment of FTan |
1960 | 1 | equemene | if (FTan==0.) GradTmp2=ZeroVec |
1961 | 1 | equemene | ! <- PFL 6 Apr 2008 |
1962 | 1 | equemene | |
1963 | 1 | equemene | Call Step_RFO_all(NCoord,GradTmp,IGeom,XyzGeomF(IGeom,:,:),Grad(IGeom,:),Hess(IGeom,:,:),GradTmp2) |
1964 | 1 | equemene | CASE DEFAULT |
1965 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1083.STOP' |
1966 | 1 | equemene | STOP |
1967 | 1 | equemene | END SELECT |
1968 | 1 | equemene | |
1969 | 1 | equemene | ! we take care that frozen atoms do not move |
1970 | 1 | equemene | IF (NFroz.NE.0) THEN |
1971 | 1 | equemene | SELECT CASE (COORD) |
1972 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
1973 | 1 | equemene | IF (debug) THEN |
1974 | 1 | equemene | WRITE(*,*) 'Step computed. Coord=',Coord |
1975 | 1 | equemene | WRITE(*,*) 'Zeroing components for frozen atoms. Intfroz=', IntFroz |
1976 | 1 | equemene | END IF |
1977 | 1 | equemene | GradTmp(1:IntFroz)=0.d0 |
1978 | 1 | equemene | CASE ('CART','HYBRID') |
1979 | 1 | equemene | if (debug) THEN |
1980 | 1 | equemene | WRITE(*,*) "DBG Path Zeroing components L1771. Step before zeroing" |
1981 | 1 | equemene | DO I=1,Nat |
1982 | 1 | equemene | WRITe(*,*) I,GradTmp(3*I-2:3*I) |
1983 | 1 | equemene | END DO |
1984 | 1 | equemene | END IF |
1985 | 1 | equemene | DO I=1,Nat |
1986 | 1 | equemene | IF (FrozAtoms(I)) THEN |
1987 | 1 | equemene | if (debug) THEN |
1988 | 1 | equemene | write(*,*) 'Step Computed. Coord=',Coord |
1989 | 1 | equemene | WRITE(*,*) 'Atom',I,' is frozen. Zeroing',Order(I) |
1990 | 1 | equemene | END IF |
1991 | 1 | equemene | Iat=Order(I) |
1992 | 1 | equemene | GradTmp(3*Iat-2:3*Iat)=0.d0 |
1993 | 1 | equemene | END IF |
1994 | 1 | equemene | END DO |
1995 | 1 | equemene | |
1996 | 1 | equemene | if (debug) THEN |
1997 | 1 | equemene | WRITE(*,*) "DBG Path Zeroing components L1785. Step After zeroing" |
1998 | 1 | equemene | DO I=1,Nat |
1999 | 1 | equemene | WRITe(*,*) I,GradTmp(3*I-2:3*I) |
2000 | 1 | equemene | END DO |
2001 | 1 | equemene | END IF |
2002 | 1 | equemene | |
2003 | 1 | equemene | CASE DEFAULT |
2004 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1338.STOP' |
2005 | 1 | equemene | STOP |
2006 | 1 | equemene | END SELECT |
2007 | 1 | equemene | END IF !matches IF (NFroz.NE.0) THEN |
2008 | 1 | equemene | |
2009 | 1 | equemene | IF (debug) THEN |
2010 | 1 | equemene | SELECT CASE (COORD) |
2011 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
2012 | 1 | equemene | WRITE(*,'(A,12(1X,F8.3))') 'Step tan:',IntTangent(IGeom,1:min(12,NFree)) |
2013 | 1 | equemene | WRITE(*,'(A,12(1X,F8.3))') 'Ortho Step:',GradTmp(1:min(12,NFree)) |
2014 | 1 | equemene | CASE ('CART','HYBRID') |
2015 | 1 | equemene | WRITE(*,'(A,12(1X,F8.3))') 'Step tan:',XyzTangent(IGeom,1:min(12,NFree)) |
2016 | 1 | equemene | WRITE(*,'(A,12(1X,F8.3))') 'Ortho Step:',GradTmp(1:min(12,NFree)) |
2017 | 1 | equemene | CASE DEFAULT |
2018 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1588.STOP' |
2019 | 1 | equemene | STOP |
2020 | 1 | equemene | END SELECT |
2021 | 1 | equemene | END IF ! matches if (debug) THEN |
2022 | 1 | equemene | |
2023 | 1 | equemene | ! we check that the maximum displacement is not greater than Smax |
2024 | 1 | equemene | If (debug) WRITE(*,*) "Fini before test:",Fini |
2025 | 1 | equemene | NormStep=sqrt(DOT_Product(GradTmp,GradTmp)) |
2026 | 1 | equemene | FactStep=min(1.d0,maxStep(Igeom)/NormStep) |
2027 | 1 | equemene | Fini=(Fini.AND.(NormStep.LE.SThresh)) |
2028 | 1 | equemene | IF (debug) WRITE(*,*) "IGeom,NormStep, SThresh,Fini",IGeom,NormStep, SThresh, Fini |
2029 | 1 | equemene | |
2030 | 1 | equemene | GradTmp=GraDTmp*FactStep |
2031 | 1 | equemene | |
2032 | 1 | equemene | if (debug) WRITE(*,*) "DBG Main, L1475, FactStep=",FactStep |
2033 | 1 | equemene | if (debug.AND.(COORD.EQ.'ZMAT')) WRITE(*,'(A,12(1X,F10.6))') 'Scaled Step:',GradTmp(1:min(12,NFree)) |
2034 | 1 | equemene | |
2035 | 1 | equemene | IF (debug) THEN |
2036 | 1 | equemene | WRITE(*,*) "DBG Main, L1479, IGeom=, IOpt=",IGeom,IOpt |
2037 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
2038 | 1 | equemene | WRITE(*,'(12(1X,F8.3))') IntCoordF(IGeom,1:min(12,NFree)) |
2039 | 1 | equemene | ELSE |
2040 | 1 | equemene | DO Iat=1,Nat |
2041 | 1 | equemene | WRITE(*,'(1X,A5,3(1X,F11.6))') Nom(Atome(Iat)), & |
2042 | 1 | equemene | XyzGeomF(IGeom,1:3,Iat) |
2043 | 1 | equemene | END DO |
2044 | 1 | equemene | END IF |
2045 | 1 | equemene | END IF ! matches if (debug) THEN |
2046 | 1 | equemene | |
2047 | 1 | equemene | SELECT CASE (COORD) |
2048 | 1 | equemene | CASE ('ZMAT') |
2049 | 1 | equemene | IntcoordF(IGeom,:)=IntcoordF(IGeom,:)+GradTmp(:) |
2050 | 1 | equemene | if (debug) Print *, 'New Geom=IntcoordF(',IGeom,',:)=', IntcoordF(IGeom,:) |
2051 | 1 | equemene | WRITE(IOOUT,"('Geometry ',I3,'/',I3,' for iteration ',I3)") IGeom,NgeomF,IOpt |
2052 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(1,1)))) |
2053 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(2,1)))), & |
2054 | 1 | equemene | OrderInv(indzmat(2,2)),IntcoordF(IGeom,1) |
2055 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(3,1)))), & |
2056 | 1 | equemene | OrderInv(indzmat(3,2)),IntcoordF(IGeom,2), OrderInv(indzmat(3,3)),IntcoordF(IGeom,3)*180./Pi |
2057 | 1 | equemene | Idx=4 |
2058 | 1 | equemene | DO Iat=4,Nat |
2059 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(iat,1)))), & |
2060 | 1 | equemene | OrderInv(indzmat(iat,2)),IntcoordF(IGeom,Idx), & |
2061 | 1 | equemene | OrderInv(indzmat(iat,3)),IntcoordF(IGeom,Idx+1)*180./pi, & |
2062 | 1 | equemene | OrderInv(indzmat(iat,4)),IntcoordF(IGeom,Idx+2)*180/Pi |
2063 | 1 | equemene | Idx=Idx+3 |
2064 | 1 | equemene | END DO |
2065 | 1 | equemene | |
2066 | 1 | equemene | CASE ('BAKER') |
2067 | 1 | equemene | IntcoordF(IGeom,:)=IntcoordF(IGeom,:)+GradTmp(:) |
2068 | 1 | equemene | if (debug) Print *, 'New Geom=IntcoordF(',IGeom,',:)=', IntcoordF(IGeom,:) |
2069 | 1 | equemene | WRITE(IOOUT,"('Geometry ',I3,'/',I3,' for iteration ',I3)") IGeom,NgeomF,IOpt |
2070 | 1 | equemene | WRITE(IOOUT,*) "COORD=BAKER, printing IntCoordF is not meaningfull." |
2071 | 1 | equemene | |
2072 | 1 | equemene | CASE ('MIXED') |
2073 | 1 | equemene | IntcoordF(IGeom,:)=IntcoordF(IGeom,:)+GradTmp(:) |
2074 | 1 | equemene | if (debug) Print *, 'New Geom=IntcoordF(',IGeom,',:)=', IntcoordF(IGeom,:) |
2075 | 1 | equemene | WRITE(IOOUT,"('Geometry ',I3,'/',I3,' for iteration ',I3)") IGeom,NgeomF,IOpt |
2076 | 1 | equemene | DO Iat=1,NCart |
2077 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,F13.8))') Nom(Atome(OrderInv(indzmat(1,1)))),IntcoordF(IGeom,3*Iat-2:3*Iat) |
2078 | 1 | equemene | END DO |
2079 | 1 | equemene | Idx=3*NCart+1 |
2080 | 1 | equemene | IF (NCart.EQ.1) THEN |
2081 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(2,1)))), & |
2082 | 1 | equemene | OrderInv(indzmat(2,2)),IntcoordF(IGeom,4) |
2083 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(3,1)))), & |
2084 | 1 | equemene | OrderInv(indzmat(3,2)),IntcoordF(IGeom,5), OrderInv(indzmat(3,3)),IntcoordF(IGeom,6)*180./Pi |
2085 | 1 | equemene | |
2086 | 1 | equemene | Idx=7 |
2087 | 1 | equemene | END IF |
2088 | 1 | equemene | IF (NCart.EQ.2) THEN |
2089 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(3,1)))), & |
2090 | 1 | equemene | OrderInv(indzmat(3,2)),IntcoordF(IGeom,7), OrderInv(indzmat(3,3)),IntcoordF(IGeom,8)*180./Pi |
2091 | 1 | equemene | Idx=9 |
2092 | 1 | equemene | END IF |
2093 | 1 | equemene | |
2094 | 1 | equemene | |
2095 | 1 | equemene | DO Iat=max(NCart+1,4),Nat |
2096 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(iat,1)))), & |
2097 | 1 | equemene | OrderInv(indzmat(iat,2)),IntcoordF(IGeom,Idx), & |
2098 | 1 | equemene | OrderInv(indzmat(iat,3)),IntcoordF(IGeom,Idx+1)*180./pi, & |
2099 | 1 | equemene | OrderInv(indzmat(iat,4)),IntcoordF(IGeom,Idx+2)*180/Pi |
2100 | 1 | equemene | Idx=Idx+3 |
2101 | 1 | equemene | END DO |
2102 | 1 | equemene | if (debug) Print *, 'New Geom=IntcoordF(',IGeom,',:)=', IntcoordF(IGeom,:) |
2103 | 1 | equemene | |
2104 | 1 | equemene | CASE ('HYBRID','CART') |
2105 | 1 | equemene | XyzGeomF(IGeom,:,:)=XyzGeomF(IGeom,:,:)+reshape(GradTmp(:),(/3,Nat/)) |
2106 | 1 | equemene | CASE DEFAULT |
2107 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1537.STOP' |
2108 | 1 | equemene | STOP |
2109 | 1 | equemene | END SELECT |
2110 | 1 | equemene | |
2111 | 1 | equemene | IF (debug) THEN |
2112 | 1 | equemene | WRITE(*,*) "DBG Main, L1516, IGeom=, IOpt=",IGeom,IOpt |
2113 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
2114 | 1 | equemene | WRITE(*,'(12(1X,F8.3))') IntCoordF(IGeom,1:min(12,NFree)) |
2115 | 1 | equemene | ELSE |
2116 | 1 | equemene | DO Iat=1,Nat |
2117 | 1 | equemene | WRITE(*,'(1X,A5,3(1X,F11.6))') Nom(Atome(Iat)), & |
2118 | 1 | equemene | XyzGeomF(IGeom,1:3,Iat) |
2119 | 1 | equemene | END DO |
2120 | 1 | equemene | END IF |
2121 | 1 | equemene | END IF ! matches if (debug) THEN |
2122 | 1 | equemene | |
2123 | 1 | equemene | ! We project out the tangential part of the gradient to know if we are done |
2124 | 1 | equemene | GradTmp=Grad(IGeom,:) |
2125 | 1 | equemene | NormGrad=sqrt(dot_product(GradTmp,GradTmp)) |
2126 | 1 | equemene | if (debug) WRITE(*,*) "Norm Grad tot=",NormGrad |
2127 | 1 | equemene | SELECT CASE (COORD) |
2128 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
2129 | 1 | equemene | S=DOT_PRODUCT(GradTmp,IntTangent(IGeom,:)) |
2130 | 1 | equemene | Norm=DOT_PRODUCT(IntTangent(IGeom,:),IntTangent(IGeom,:)) |
2131 | 1 | equemene | GradTmp=GradTmp-S/Norm*IntTangent(IGeom,:) |
2132 | 1 | equemene | Ca=S/(sqrt(Norm)*NormGrad) |
2133 | 1 | equemene | S=DOT_PRODUCT(GradTmp,IntTangent(IGeom,:)) |
2134 | 1 | equemene | GradTmp=GradTmp-S/Norm*IntTangent(IGeom,:) |
2135 | 1 | equemene | CASE ('CART','HYBRID') |
2136 | 1 | equemene | S=DOT_PRODUCT(GradTmp,XyzTangent(IGeom,:)) |
2137 | 1 | equemene | Norm=DOT_PRODUCT(XyzTangent(IGeom,:),XyzTangent(IGeom,:)) |
2138 | 1 | equemene | Ca=S/(sqrt(Norm)*NormGrad) |
2139 | 1 | equemene | GradTmp=GradTmp-S/Norm*XyzTangent(IGeom,:) |
2140 | 1 | equemene | S=DOT_PRODUCT(GradTmp,XyzTangent(IGeom,:)) |
2141 | 1 | equemene | GradTmp=GradTmp-S/Norm*XyzTangent(IGeom,:) |
2142 | 1 | equemene | CASE DEFAULT |
2143 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1190.STOP' |
2144 | 1 | equemene | STOP |
2145 | 1 | equemene | END SELECT |
2146 | 1 | equemene | IF (debug) WRITE(*,'(1X,A,3(1X,F10.6))') "cos and angle between grad and tangent",ca, acos(ca), acos(ca)*180./pi |
2147 | 1 | equemene | NormGrad=sqrt(DOT_Product(GradTmp,GradTmp)) |
2148 | 1 | equemene | Fini=(Fini.AND.(NormGrad.LE.GThresh)) |
2149 | 1 | equemene | IF (debug) WRITE(*,*) "NormGrad_perp, GThresh, Fini=",NormGrad, GThresh, Fini |
2150 | 1 | equemene | |
2151 | 1 | equemene | END DO ! matches DO IGeom=2,NGeomF-1 |
2152 | 1 | equemene | ! we save the old gradients |
2153 | 1 | equemene | GradOld=Grad |
2154 | 1 | equemene | EPathOld=Energies |
2155 | 1 | equemene | |
2156 | 1 | equemene | ! Shall we re-parameterize the path ? |
2157 | 1 | equemene | ! PFL 2007/Apr/10 -> |
2158 | 1 | equemene | ! We call PathCreate in all cases, it will take care of the |
2159 | 1 | equemene | ! reparameterization, as well as calculating the tangents. |
2160 | 1 | equemene | ! IF (MOD(IOpt,IReparam).EQ.0) THEN |
2161 | 1 | equemene | XyzGeomI=XyzGeomF |
2162 | 1 | equemene | IntCoordI=IntCoordF |
2163 | 1 | equemene | |
2164 | 1 | equemene | Call PathCreate(IOpt) |
2165 | 1 | equemene | ! END IF |
2166 | 1 | equemene | ! <- PFL 2007/Apr/10 |
2167 | 1 | equemene | |
2168 | 1 | equemene | if (debug) WRITE(*,'(1X,A,I5,A,I5,A,L2)') 'Path.f90, L1415, IOpt=', IOpt, 'MaxCyc=', MaxCyc,' Fini=', Fini |
2169 | 1 | equemene | IF ((.NOT.Fini).AND.(IOpt.LT.MaxCyc)) THEN |
2170 | 1 | equemene | |
2171 | 1 | equemene | ! We have the new path, we calculate its energy and gradient |
2172 | 1 | equemene | |
2173 | 1 | equemene | Call EgradPath(IOpt,Flag_Opt_Geom) |
2174 | 1 | equemene | !IF(IOPT .EQ. 10) Then |
2175 | 1 | equemene | ! Print *, 'Stopping at my checkpoint.' |
2176 | 1 | equemene | ! STOP !This is my temporary checkpoint. |
2177 | 1 | equemene | !ENDIF |
2178 | 1 | equemene | |
2179 | 1 | equemene | ! PFL 31 Mar 2008 -> |
2180 | 1 | equemene | ! Taken from v3.99 but we added a flag... |
2181 | 1 | equemene | ! Added in v3.99 : MaxStep is modified according to the evolution of energies |
2182 | 1 | equemene | ! if Energies(IGeom)<=EPathOld then MaxStep is increased by 1.1 |
2183 | 1 | equemene | ! else it is decreased by 0.8 |
2184 | 1 | equemene | |
2185 | 1 | equemene | if (DynMaxStep) THEN |
2186 | 1 | equemene | if (debug) WRITE(*,*) "Dynamically updating the Maximum step" |
2187 | 1 | equemene | if (OptReac) THEN |
2188 | 1 | equemene | If (Energies(1)<EPathOld(1)) Then |
2189 | 1 | equemene | MaxStep(1)=min(1.1*MaxStep(1),2.*SMax) |
2190 | 1 | equemene | ELSE |
2191 | 1 | equemene | MaxStep(1)=max(0.8*MaxStep(1),SMax/2.) |
2192 | 1 | equemene | END IF |
2193 | 1 | equemene | END IF |
2194 | 1 | equemene | |
2195 | 1 | equemene | if (OptProd) THEN |
2196 | 1 | equemene | If (Energies(NGeomF)<EPathOld(NGeomF)) Then |
2197 | 1 | equemene | MaxStep(NGeomF)=min(1.1*MaxStep(NGeomF),2.*SMax) |
2198 | 1 | equemene | ELSE |
2199 | 1 | equemene | MaxStep(NGeomF)=max(0.8*MaxStep(NGeomF),SMax/2.) |
2200 | 1 | equemene | END IF |
2201 | 1 | equemene | END IF |
2202 | 1 | equemene | |
2203 | 1 | equemene | DO IGeom=2,NGeomF-1 |
2204 | 1 | equemene | If (Energies(IGeom)<EPathOld(IGeom)) Then |
2205 | 1 | equemene | MaxStep(IGeom)=min(1.1*MaxStep(IGeom),2.*SMax) |
2206 | 1 | equemene | ELSE |
2207 | 1 | equemene | MaxStep(IGeom)=max(0.8*MaxStep(IGeom),SMax/2.) |
2208 | 1 | equemene | END IF |
2209 | 1 | equemene | END DO |
2210 | 1 | equemene | if (debug) WRITE(*,*) "Maximum step",MaxStep(1:NgeomF) |
2211 | 1 | equemene | END IF ! test on DynMaxStep |
2212 | 1 | equemene | if (debug) WRITE(*,*) "Maximum step",MaxStep(1:NgeomF) |
2213 | 1 | equemene | ! <- PFL 31 MAr 2008 |
2214 | 1 | equemene | ! Also XyzGeomF is updated in EgradPath for Baker Case. |
2215 | 1 | equemene | ! It should get updated for other cases too. |
2216 | 1 | equemene | |
2217 | 1 | equemene | DO IGeom=1,NGeomF |
2218 | 1 | equemene | SELECT CASE (COORD) |
2219 | 1 | equemene | CASE('ZMAT') |
2220 | 1 | equemene | WRITE(IOOUT,"('Geometry ',I3,'/',I3,' for iteration ',I3)") IGeom,NgeomF,IOpt |
2221 | 1 | equemene | GeomTmp=IntCoordF(IGeom,:) |
2222 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(1,1)))) |
2223 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(2,1)))), & |
2224 | 1 | equemene | OrderInv(indzmat(2,2)),Geomtmp(1) |
2225 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(3,1)))), & |
2226 | 1 | equemene | OrderInv(indzmat(3,2)),Geomtmp(2), & |
2227 | 1 | equemene | OrderInv(indzmat(3,3)),Geomtmp(3)*180./Pi |
2228 | 1 | equemene | Idx=4 |
2229 | 1 | equemene | DO Iat=4,Nat |
2230 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,I4,1X,F11.6))') Nom(Atome(OrderInv(indzmat(iat,1)))), & |
2231 | 1 | equemene | OrderInv(indzmat(iat,2)),Geomtmp(Idx), & |
2232 | 1 | equemene | OrderInv(indzmat(iat,3)),Geomtmp(Idx+1)*180./pi, & |
2233 | 1 | equemene | OrderInv(indzmat(iat,4)),Geomtmp(Idx+2)*180/Pi |
2234 | 1 | equemene | Idx=Idx+3 |
2235 | 1 | equemene | END DO |
2236 | 1 | equemene | CASE('BAKER') |
2237 | 1 | equemene | !WRITE(IOOUT,"('Geometry ',I3,'/',I3,' for iteration ',I3)") IGeom,NgeomF,IOpt |
2238 | 1 | equemene | !GeomTmp=IntCoordF(IGeom,:) |
2239 | 1 | equemene | CASE('CART','HYBRID','MIXED') |
2240 | 1 | equemene | WRITE(IOOUT,'(1X,I5)') Nat |
2241 | 1 | equemene | WRITE(IOOUT,"('Geometry ',I3,'/',I3,' for iteration ',I3)") IGeom,NgeomF,IOpt |
2242 | 1 | equemene | GeomTmp=Reshape(XyzGeomF(IGeom,:,:),(/3*Nat/)) |
2243 | 1 | equemene | DO I=1,Nat |
2244 | 1 | equemene | Iat=I |
2245 | 1 | equemene | If (renum) Iat=OrderInv(I) |
2246 | 1 | equemene | WRITE(IOOUT,'(1X,A5,3(1X,F11.6))') Nom(Atome(iat)), Geomtmp(3*Iat-2:3*Iat) |
2247 | 1 | equemene | END DO |
2248 | 1 | equemene | CASE DEFAULT |
2249 | 1 | equemene | WRITE(*,*) 'Coord=',TRIM(COORD),' not recognized. Path L1356.STOP' |
2250 | 1 | equemene | STOP |
2251 | 1 | equemene | END SELECT |
2252 | 1 | equemene | END DO ! matches DO IGeom=1,NGeomF |
2253 | 1 | equemene | |
2254 | 1 | equemene | Call Write_path(IOpt) |
2255 | 1 | equemene | |
2256 | 1 | equemene | ! We update the Hessian matrices |
2257 | 1 | equemene | IF (debug) WRITE(*,*) "Updating Hessian matrices",NCoord |
2258 | 1 | equemene | ! First using the displacement from the old path |
2259 | 1 | equemene | IGeom0=2 |
2260 | 1 | equemene | IGeomF=NGeomF-1 |
2261 | 1 | equemene | IF (OptReac) IGeom0=1 |
2262 | 1 | equemene | IF (OptProd) IGeomF=NGeomF |
2263 | 1 | equemene | |
2264 | 1 | equemene | IF (FCalcHess) THEN |
2265 | 1 | equemene | DO IGeom=IGeom0,IGeomF |
2266 | 1 | equemene | SELECT CASE (COORD) |
2267 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
2268 | 1 | equemene | GeomTmp2=IntCoordF(IGeom,:) |
2269 | 1 | equemene | CASE ('CART','HYBRID') |
2270 | 1 | equemene | GeomTmp2=Reshape(XyzGeomF(IGeom,:,:),(/3*Nat/)) |
2271 | 1 | equemene | CASE DEFAULT |
2272 | 1 | equemene | WRITE(*,*) "Coord=",TRIM(COORD)," not recognized. PATH L1267.STOP" |
2273 | 1 | equemene | STOP |
2274 | 1 | equemene | END SELECT |
2275 | 1 | equemene | Call CalcHess(NCoord,GeomTmp2,Hess(IGeom,:,:),IGeom,Iopt) |
2276 | 1 | equemene | END DO |
2277 | 1 | equemene | ELSE |
2278 | 1 | equemene | DO IGeom=IGeom0,IGeomF |
2279 | 1 | equemene | GeomTmp=GeomOld_all(IGeom,:) |
2280 | 1 | equemene | SELECT CASE (COORD) |
2281 | 1 | equemene | CASE ('ZMAT','MIXED','BAKER') |
2282 | 1 | equemene | GeomTmp2=IntCoordF(IGeom,:) |
2283 | 1 | equemene | CASE ('CART','HYBRID') |
2284 | 1 | equemene | GeomTmp2=Reshape(XyzGeomF(IGeom,:,:),(/3*Nat/)) |
2285 | 1 | equemene | CASE DEFAULT |
2286 | 1 | equemene | WRITE(*,*) "Coord=",TRIM(COORD)," not recognized. PATH L1267.STOP" |
2287 | 1 | equemene | STOP |
2288 | 1 | equemene | END SELECT |
2289 | 1 | equemene | GeomTmp=GeomTmp2-GeomTmp |
2290 | 1 | equemene | GradTmp=Grad(IGeom,:)-GradOld(IGeom,:) |
2291 | 1 | equemene | HessTmp=Hess(IGeom,:,:) |
2292 | 1 | equemene | Call Hupdate_all(NCoord,GeomTmp,GradTmp,HessTmp) |
2293 | 1 | equemene | Hess(IGeom,:,:)=HessTmp |
2294 | 1 | equemene | END DO ! matches DO IGeom=IGeom0,IGeomF |
2295 | 1 | equemene | |
2296 | 1 | equemene | ! Second using the neighbour points |
2297 | 1 | equemene | IF (HupNeighbour) THEN |
2298 | 1 | equemene | ! Only one point for end points. |
2299 | 1 | equemene | IF (OptReac) THEN |
2300 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
2301 | 1 | equemene | GeomTmp=IntCoordF(1,:)-IntCoordF(2,:) |
2302 | 1 | equemene | ELSE |
2303 | 1 | equemene | GeomTmp=Reshape(XyzGeomF(1,:,:),(/3*Nat/))-Reshape(XyzGeomF(2,:,:),(/3*Nat/)) |
2304 | 1 | equemene | END IF |
2305 | 1 | equemene | GradTmp=Grad(1,:)-Grad(2,:) |
2306 | 1 | equemene | HessTmp=Hess(1,:,:) |
2307 | 1 | equemene | Call Hupdate_all(NCoord,GeomTmp,GradTmp,HessTmp) |
2308 | 1 | equemene | Hess(1,:,:)=HessTmp |
2309 | 1 | equemene | END IF |
2310 | 1 | equemene | |
2311 | 1 | equemene | IF (OptProd) THEN |
2312 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
2313 | 1 | equemene | GeomTmp=IntCoordF(NGeomF,:)-IntCoordF(NGeomF-1,:) |
2314 | 1 | equemene | ELSE |
2315 | 1 | equemene | GeomTmp=Reshape(XyzGeomF(NGeomF,:,:),(/3*Nat/))-Reshape(XyzGeomF(NGeomF-1,:,:),(/3*Nat/)) |
2316 | 1 | equemene | END IF |
2317 | 1 | equemene | GradTmp=Grad(NGeomF,:)-Grad(NGeomF-1,:) |
2318 | 1 | equemene | HessTmp=Hess(NGeomF,:,:) |
2319 | 1 | equemene | Call Hupdate_all(NCoord,GeomTmp,GradTmp,HessTmp) |
2320 | 1 | equemene | Hess(NGeomF,:,:)=HessTmp |
2321 | 1 | equemene | END IF |
2322 | 1 | equemene | |
2323 | 1 | equemene | ! Two points for the rest of the path |
2324 | 1 | equemene | DO IGeom=2,NGeomF-1 |
2325 | 1 | equemene | IF ((COORD.EQ.'ZMAT').OR.(COORD.EQ.'BAKER')) THEN |
2326 | 1 | equemene | GeomTmp=IntCoordF(IGeom,:)-IntCoordF(IGeom+1,:) |
2327 | 1 | equemene | ELSE |
2328 | 1 | equemene | GeomTmp=Reshape(XyzGeomF(IGeom,:,:),(/3*Nat/))-Reshape(XyzGeomF(IGeom+1,:,:),(/3*Nat/)) |
2329 | 1 | equemene | END IF |
2330 | 1 | equemene | GradTmp=Grad(IGeom,:)-Grad(IGeom+1,:) |
2331 | 1 | equemene | HessTmp=Hess(IGeom,:,:) |
2332 | 1 | equemene | Call Hupdate_all(NCoord,GeomTmp,GradTmp,HessTmp) |
2333 | 1 | equemene | |
2334 | 1 | equemene | IF ((COORD.EQ.'ZMAT') .OR. (COORD.EQ.'BAKER')) THEN |
2335 | 1 | equemene | GeomTmp=IntCoordF(IGeom,:)-IntCoordF(IGeom-1,:) |
2336 | 1 | equemene | ELSE |
2337 | 1 | equemene | GeomTmp=Reshape(XyzGeomF(IGeom,:,:),(/3*Nat/))-Reshape(XyzGeomF(IGeom-1,:,:),(/3*Nat/)) |
2338 | 1 | equemene | END IF |
2339 | 1 | equemene | GradTmp=Grad(IGeom,:)-Grad(IGeom-1,:) |
2340 | 1 | equemene | |
2341 | 1 | equemene | Call Hupdate_all(NCoord,GeomTmp,GradTmp,HessTmp) |
2342 | 1 | equemene | Hess(IGeom,:,:)=HessTmp |
2343 | 1 | equemene | END DO ! matches DO IGeom=2,NGeomF-1 |
2344 | 1 | equemene | END IF !matches IF (HupNeighbour) THEN |
2345 | 1 | equemene | END IF ! matches IF (FCalcHess) |
2346 | 1 | equemene | END IF ! If (not.fini.).AND.(IOpt.LE.MaxCyc) |
2347 | 1 | equemene | END DO ! matches DO WHILE ((IOpt.LT.MaxCyc).AND.(.NOT.Fini)) |
2348 | 1 | equemene | |
2349 | 1 | equemene | IF (PROG=="GAUSSIAN") THEN |
2350 | 1 | equemene | DEALLOCATE(Gauss_paste) |
2351 | 1 | equemene | DEALLOCATE(Gauss_root,Gauss_comment,Gauss_end,current) |
2352 | 1 | equemene | END IF |
2353 | 1 | equemene | DEALLOCATE(XyzGeomF, IntCoordF) |
2354 | 1 | equemene | DEALLOCATE(XyzGeomI, IntCoordI) |
2355 | 1 | equemene | DEALLOCATE(XyzTangent,IntTangent) |
2356 | 1 | equemene | DEALLOCATE(AtName,IndZmat,Order,Atome,MassAt) |
2357 | 1 | equemene | DEALLOCATE(GeomOld_all) |
2358 | 1 | equemene | |
2359 | 1 | equemene | if (PROG=="GAUSSIAN") THEN |
2360 | 1 | equemene | ! We de-allocate the Gauss_XX lists |
2361 | 1 | equemene | ! transverse the list and deallocate each node |
2362 | 1 | equemene | previous => Gauss_root ! make current point to head of list |
2363 | 1 | equemene | DO |
2364 | 1 | equemene | IF (.NOT. ASSOCIATED(previous)) EXIT ! exit if null pointer |
2365 | 1 | equemene | current => previous%next ! make list point to next node of head |
2366 | 1 | equemene | DEALLOCATE(previous) ! deallocate current head node |
2367 | 1 | equemene | previous => current ! make current point to new head |
2368 | 1 | equemene | END DO |
2369 | 1 | equemene | |
2370 | 1 | equemene | previous => Gauss_comment ! make current point to head of list |
2371 | 1 | equemene | DO |
2372 | 1 | equemene | IF (.NOT. ASSOCIATED(previous)) EXIT ! exit if null pointer |
2373 | 1 | equemene | current => previous%next ! make list point to next node of head |
2374 | 1 | equemene | DEALLOCATE(previous) ! deallocate current head node |
2375 | 1 | equemene | previous => current ! make current point to new head |
2376 | 1 | equemene | END DO |
2377 | 1 | equemene | |
2378 | 1 | equemene | previous => Gauss_end ! make current point to head of list |
2379 | 1 | equemene | DO |
2380 | 1 | equemene | IF (.NOT. ASSOCIATED(previous)) EXIT ! exit if null pointer |
2381 | 1 | equemene | current => previous%next ! make list point to next node of head |
2382 | 1 | equemene | DEALLOCATE(previous) ! deallocate current head node |
2383 | 1 | equemene | previous => current ! make current point to new head |
2384 | 1 | equemene | END DO |
2385 | 1 | equemene | |
2386 | 1 | equemene | DEALLOCATE(current) |
2387 | 1 | equemene | END IF |
2388 | 1 | equemene | |
2389 | 1 | equemene | DEALLOCATE(GeomTmp, Hess, GradTmp) |
2390 | 1 | equemene | IF (COORD.EQ.'ZMAT') DEALLOCATE(dzdc) |
2391 | 1 | equemene | IF (COORD.EQ.'BAKER') THEN |
2392 | 1 | equemene | DEALLOCATE(BMat_BakerT,BTransInv,BTransInv_local,Xprimitive_t) |
2393 | 1 | equemene | DEALLOCATE(XprimitiveF,UMatF,BTransInvF,UMat,UMat_local) |
2394 | 1 | equemene | END IF |
2395 | 1 | equemene | |
2396 | 1 | equemene | WRITE(IOOUT,*) "Exiting Path, IOpt=",IOpt |
2397 | 1 | equemene | |
2398 | 1 | equemene | END PROGRAM PathOpt |