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