Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Module performing a Nudged Elastic Band Calculation
10 : !> \note
11 : !> Numerical accuracy for parallel runs:
12 : !> Each replica starts the SCF run from the one optimized
13 : !> in a previous run. It may happen then energies and derivatives
14 : !> of a serial run and a parallel run could be slightly different
15 : !> 'cause of a different starting density matrix.
16 : !> Exact results are obtained using:
17 : !> EXTRAPOLATION USE_GUESS in QS section (Teo 09.2006)
18 : !> \author Teodoro Laino 09.2006
19 : !> \par History
20 : !> - Teodoro Laino 10.2008 [tlaino] - University of Zurich
21 : !> Extension to a subspace of collective variables
22 : ! **************************************************************************************************
23 : MODULE neb_methods
24 : USE colvar_utils, ONLY: number_of_colvar
25 : USE cp_external_control, ONLY: external_control
26 : USE cp_log_handling, ONLY: cp_get_default_logger,&
27 : cp_logger_type,&
28 : cp_to_string
29 : USE cp_output_handling, ONLY: cp_add_iter_level,&
30 : cp_iterate,&
31 : cp_print_key_finished_output,&
32 : cp_print_key_unit_nr,&
33 : cp_rm_iter_level
34 : USE cp_subsys_types, ONLY: cp_subsys_type
35 : USE f77_interface, ONLY: f_env_add_defaults,&
36 : f_env_rm_defaults,&
37 : f_env_type
38 : USE force_env_types, ONLY: force_env_get
39 : USE global_types, ONLY: global_environment_type
40 : USE header, ONLY: band_header
41 : USE input_constants, ONLY: band_diis_opt,&
42 : band_md_opt,&
43 : do_rep_blocked,&
44 : do_sm
45 : USE input_section_types, ONLY: section_type,&
46 : section_vals_get_subs_vals,&
47 : section_vals_type,&
48 : section_vals_val_get
49 : USE kinds, ONLY: dp
50 : USE message_passing, ONLY: mp_para_env_type
51 : USE neb_io, ONLY: dump_neb_info,&
52 : neb_rep_env_map_info,&
53 : read_neb_section
54 : USE neb_md_utils, ONLY: control_vels_a,&
55 : control_vels_b
56 : USE neb_opt_utils, ONLY: accept_diis_step,&
57 : neb_ls
58 : USE neb_types, ONLY: neb_type,&
59 : neb_var_create,&
60 : neb_var_release,&
61 : neb_var_type
62 : USE neb_utils, ONLY: build_replica_coords,&
63 : check_convergence,&
64 : neb_calc_energy_forces,&
65 : reorient_images,&
66 : reparametrize_images
67 : USE particle_types, ONLY: particle_type
68 : USE physcon, ONLY: massunit
69 : USE replica_methods, ONLY: rep_env_create
70 : USE replica_types, ONLY: rep_env_release,&
71 : replica_env_type
72 : #include "../base/base_uses.f90"
73 :
74 : IMPLICIT NONE
75 : PRIVATE
76 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'neb_methods'
77 : LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .FALSE.
78 : PUBLIC :: neb
79 :
80 : CONTAINS
81 :
82 : ! **************************************************************************************************
83 : !> \brief Real subroutine for NEB calculations
84 : !> \param input ...
85 : !> \param input_declaration ...
86 : !> \param para_env ...
87 : !> \param globenv ...
88 : !> \author Teodoro Laino 09.2006
89 : !> \note
90 : !> Based on the use of replica_env
91 : ! **************************************************************************************************
92 102 : SUBROUTINE neb(input, input_declaration, para_env, globenv)
93 : TYPE(section_vals_type), POINTER :: input
94 : TYPE(section_type), POINTER :: input_declaration
95 : TYPE(mp_para_env_type), POINTER :: para_env
96 : TYPE(global_environment_type), POINTER :: globenv
97 :
98 : CHARACTER(len=*), PARAMETER :: routineN = 'neb'
99 :
100 : INTEGER :: handle, ierr, iw, iw2, nrep, &
101 : output_unit, prep, proc_dist_type
102 : LOGICAL :: check, row_force
103 : TYPE(cp_logger_type), POINTER :: logger
104 : TYPE(cp_subsys_type), POINTER :: subsys
105 : TYPE(f_env_type), POINTER :: f_env
106 : TYPE(neb_type), POINTER :: neb_env
107 : TYPE(neb_var_type), POINTER :: coords, forces, vels
108 34 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
109 : TYPE(replica_env_type), POINTER :: rep_env
110 : TYPE(section_vals_type), POINTER :: diis_section, force_env_section, &
111 : md_section, motion_section, &
112 : neb_section, print_section
113 :
114 34 : CALL timeset(routineN, handle)
115 34 : NULLIFY (logger, subsys, f_env, rep_env)
116 34 : NULLIFY (forces, coords, vels, neb_env)
117 34 : logger => cp_get_default_logger()
118 34 : CALL cp_add_iter_level(logger%iter_info, "BAND")
119 34 : motion_section => section_vals_get_subs_vals(input, "MOTION")
120 34 : print_section => section_vals_get_subs_vals(motion_section, "PRINT")
121 34 : neb_section => section_vals_get_subs_vals(motion_section, "BAND")
122 : output_unit = cp_print_key_unit_nr(logger, neb_section, "PROGRAM_RUN_INFO", &
123 34 : extension=".nebLog")
124 34 : CALL section_vals_val_get(neb_section, "NPROC_REP", i_val=prep)
125 34 : CALL section_vals_val_get(neb_section, "PROC_DIST_TYPE", i_val=proc_dist_type)
126 34 : row_force = (proc_dist_type == do_rep_blocked)
127 34 : nrep = MAX(1, para_env%num_pe/prep)
128 34 : IF (nrep*prep /= para_env%num_pe .AND. output_unit > 0) THEN
129 : CALL cp_warn(__LOCATION__, &
130 : "Number of totally requested processors ("//TRIM(ADJUSTL(cp_to_string(para_env%num_pe)))//") "// &
131 : "is not compatible with the number of processors requested per replica ("// &
132 : TRIM(ADJUSTL(cp_to_string(prep)))//") and the number of replicas ("// &
133 : TRIM(ADJUSTL(cp_to_string(nrep)))//") . ["// &
134 0 : TRIM(ADJUSTL(cp_to_string(para_env%num_pe - nrep*prep)))//"] processors will be wasted!")
135 : END IF
136 34 : force_env_section => section_vals_get_subs_vals(input, "FORCE_EVAL")
137 : ! Create Replica Environments
138 34 : IF (output_unit > 0) WRITE (output_unit, '(T2,"NEB|",A)') " Replica_env Setup. START"
139 : CALL rep_env_create(rep_env, para_env=para_env, input=input, &
140 34 : input_declaration=input_declaration, nrep=nrep, prep=prep, row_force=row_force)
141 34 : IF (output_unit > 0) WRITE (output_unit, '(T2,"NEB|",A)') " Replica_env Setup. END"
142 34 : IF (ASSOCIATED(rep_env)) THEN
143 34 : CPASSERT(SIZE(rep_env%local_rep_indices) == 1)
144 34 : CALL f_env_add_defaults(f_env_id=rep_env%f_env_id, f_env=f_env)
145 34 : CALL force_env_get(f_env%force_env, subsys=subsys)
146 34 : particle_set => subsys%particles%els
147 : ! Read NEB controlling parameters
148 34 : ALLOCATE (neb_env)
149 34 : neb_env%force_env => f_env%force_env
150 34 : neb_env%root_section => input
151 34 : neb_env%force_env_section => force_env_section
152 34 : neb_env%motion_print_section => print_section
153 34 : neb_env%neb_section => neb_section
154 34 : neb_env%nsize_xyz = rep_env%ndim
155 34 : neb_env%nsize_int = number_of_colvar(f_env%force_env)
156 34 : check = (neb_env%nsize_xyz >= neb_env%nsize_int)
157 34 : CPASSERT(check)
158 : ! Check that the used colvar are uniquely determined
159 : check = (number_of_colvar(f_env%force_env) == &
160 34 : number_of_colvar(f_env%force_env, unique=.TRUE.))
161 34 : CPASSERT(check)
162 34 : CALL read_neb_section(neb_env, neb_section)
163 : ! Print BAND header
164 34 : iw2 = cp_print_key_unit_nr(logger, neb_section, "BANNER", extension=".nebLog")
165 34 : CALL band_header(iw2, neb_env%number_of_replica, nrep, prep)
166 34 : CALL cp_print_key_finished_output(iw2, logger, neb_section, "BANNER")
167 : ! Allocate the principal vectors used in the BAND calculation
168 34 : CALL neb_var_create(coords, neb_env, full_allocation=.TRUE.)
169 34 : CALL neb_var_create(forces, neb_env)
170 34 : CALL neb_var_create(vels, neb_env)
171 : ! Collecting the coordinates of the starting replicas of the BAND calculation
172 34 : IF (output_unit > 0) WRITE (output_unit, '(T2,"NEB|",A)') " Building initial set of coordinates. START"
173 : iw = cp_print_key_unit_nr(logger, neb_section, "PROGRAM_RUN_INFO/INITIAL_CONFIGURATION_INFO", &
174 34 : extension=".nebLog")
175 : CALL build_replica_coords(neb_section, particle_set, coords, vels, neb_env, iw, globenv, &
176 34 : rep_env%para_env)
177 : CALL cp_print_key_finished_output(iw, logger, neb_section, &
178 34 : "PROGRAM_RUN_INFO/INITIAL_CONFIGURATION_INFO")
179 34 : IF (output_unit > 0) WRITE (output_unit, '(T2,"NEB|",A)') " Building initial set of coordinates. END"
180 : ! Print some additional info in the replica_env initialization file
181 34 : CALL neb_rep_env_map_info(rep_env, neb_env)
182 : ! Perform NEB optimization
183 50 : SELECT CASE (neb_env%opt_type)
184 : CASE (band_md_opt)
185 16 : neb_env%opt_type_label = "MOLECULAR DYNAMICS"
186 16 : md_section => section_vals_get_subs_vals(neb_section, "OPTIMIZE_BAND%MD")
187 : CALL neb_md(rep_env, neb_env, coords, vels, forces, particle_set, output_unit, &
188 16 : md_section, logger, globenv)
189 : CASE (band_diis_opt)
190 18 : neb_env%opt_type_label = "DIIS"
191 18 : diis_section => section_vals_get_subs_vals(neb_section, "OPTIMIZE_BAND%DIIS")
192 : CALL neb_diis(rep_env, neb_env, coords, vels, forces, particle_set, output_unit, &
193 52 : diis_section, logger, globenv)
194 : END SELECT
195 : ! Release force_eval
196 34 : CALL f_env_rm_defaults(f_env, ierr)
197 : ! Release coords, vels and forces
198 34 : CALL neb_var_release(coords)
199 34 : CALL neb_var_release(forces)
200 34 : CALL neb_var_release(vels)
201 : ! At the end let's destroy the environment of the BAND calculation
202 34 : DEALLOCATE (neb_env)
203 : END IF
204 34 : CALL rep_env_release(rep_env)
205 : CALL cp_print_key_finished_output(output_unit, logger, neb_section, &
206 34 : "PROGRAM_RUN_INFO")
207 34 : CALL cp_rm_iter_level(logger%iter_info, "BAND")
208 34 : CALL timestop(handle)
209 34 : END SUBROUTINE neb
210 :
211 : ! **************************************************************************************************
212 : !> \brief MD type optimization NEB
213 : !> \param rep_env ...
214 : !> \param neb_env ...
215 : !> \param coords ...
216 : !> \param vels ...
217 : !> \param forces ...
218 : !> \param particle_set ...
219 : !> \param output_unit ...
220 : !> \param md_section ...
221 : !> \param logger ...
222 : !> \param globenv ...
223 : !> \author Teodoro Laino 09.2006
224 : ! **************************************************************************************************
225 16 : SUBROUTINE neb_md(rep_env, neb_env, coords, vels, forces, particle_set, output_unit, &
226 : md_section, logger, globenv)
227 : TYPE(replica_env_type), POINTER :: rep_env
228 : TYPE(neb_type), OPTIONAL, POINTER :: neb_env
229 : TYPE(neb_var_type), POINTER :: coords, vels, forces
230 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
231 : INTEGER, INTENT(IN) :: output_unit
232 : TYPE(section_vals_type), POINTER :: md_section
233 : TYPE(cp_logger_type), POINTER :: logger
234 : TYPE(global_environment_type), POINTER :: globenv
235 :
236 : CHARACTER(len=*), PARAMETER :: routineN = 'neb_md'
237 :
238 : INTEGER :: handle, iatom, ic, is, istep, iw, &
239 : max_steps, natom, shell_index
240 : LOGICAL :: converged, should_stop
241 : REAL(KIND=dp) :: dt
242 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: distances, energies
243 16 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: mass
244 : TYPE(neb_var_type), POINTER :: Dcoords
245 : TYPE(section_vals_type), POINTER :: tc_section, vc_section
246 :
247 16 : CALL timeset(routineN, handle)
248 16 : NULLIFY (Dcoords, tc_section, vc_section)
249 16 : CPASSERT(ASSOCIATED(coords))
250 16 : CPASSERT(ASSOCIATED(vels))
251 : ! MD band for string methods type does not make anywa sense. Stop calculation.
252 16 : IF (neb_env%id_type == do_sm) THEN
253 0 : CPWARN("MD band optimization and String Method incompatible.")
254 : END IF
255 : ! Output unit
256 : iw = cp_print_key_unit_nr(logger, neb_env%neb_section, "REPLICA_INFO", &
257 16 : extension=".replicaLog")
258 16 : tc_section => section_vals_get_subs_vals(md_section, "TEMP_CONTROL")
259 16 : vc_section => section_vals_get_subs_vals(md_section, "VEL_CONTROL")
260 16 : CALL section_vals_val_get(md_section, "TIMESTEP", r_val=dt)
261 16 : CALL section_vals_val_get(md_section, "MAX_STEPS", i_val=max_steps)
262 : ! Initial setup for MD
263 16 : CALL neb_var_create(Dcoords, neb_env)
264 64 : ALLOCATE (mass(SIZE(coords%wrk, 1), neb_env%number_of_replica))
265 48 : ALLOCATE (energies(neb_env%number_of_replica))
266 48 : ALLOCATE (distances(neb_env%number_of_replica - 1))
267 : ! Setting up the mass array
268 16 : IF (neb_env%use_colvar) THEN
269 44 : mass(:, :) = 0.5_dp*dt/massunit
270 : ELSE
271 12 : natom = SIZE(particle_set)
272 216 : DO iatom = 1, natom
273 204 : ic = 3*(iatom - 1)
274 204 : shell_index = particle_set(iatom)%shell_index
275 216 : IF (shell_index == 0) THEN
276 4964 : mass(ic + 1:ic + 3, :) = 0.5_dp*dt/particle_set(iatom)%atomic_kind%mass
277 : ELSE
278 0 : is = 3*(natom + shell_index - 1)
279 0 : mass(ic + 1:ic + 3, :) = 0.5_dp*dt/particle_set(iatom)%atomic_kind%shell%mass_core
280 0 : mass(is + 1:is + 3, :) = 0.5_dp*dt/particle_set(iatom)%atomic_kind%shell%mass_shell
281 : END IF
282 : END DO
283 : END IF
284 : ! Initializing forces array
285 : CALL reorient_images(neb_env%rotate_frames, particle_set, coords, vels, &
286 16 : output_unit, distances, neb_env%number_of_replica)
287 90 : neb_env%avg_distance = SQRT(SUM(distances*distances)/REAL(SIZE(distances), KIND=dp))
288 : CALL neb_calc_energy_forces(rep_env, neb_env, coords, energies, forces, &
289 16 : particle_set, iw)
290 :
291 : CALL dump_neb_info(neb_env=neb_env, &
292 : coords=coords, &
293 : vels=vels, &
294 : forces=forces, &
295 : particle_set=particle_set, &
296 : logger=logger, &
297 : istep=0, &
298 : energies=energies, &
299 : distances=distances, &
300 16 : output_unit=output_unit)
301 176 : md_opt_loop: DO istep = 1, max_steps
302 160 : CALL cp_iterate(logger%iter_info, iter_nr=istep)
303 : ! Save the optimization step counter
304 160 : neb_env%istep = istep
305 : ! Velocity Verlet (first part)
306 83760 : vels%wrk(:, :) = vels%wrk(:, :) + mass(:, :)*forces%wrk(:, :)
307 : ! Control on velocity - I part [rescale, annealing]
308 : CALL control_vels_a(vels, particle_set, tc_section, vc_section, output_unit, &
309 160 : istep)
310 : ! Coordinate step
311 83760 : Dcoords%wrk(:, :) = dt*vels%wrk(:, :)
312 83760 : coords%wrk(:, :) = coords%wrk(:, :) + Dcoords%wrk(:, :)
313 :
314 : CALL reorient_images(neb_env%rotate_frames, particle_set, coords, vels, &
315 160 : output_unit, distances, neb_env%number_of_replica)
316 900 : neb_env%avg_distance = SQRT(SUM(distances*distances)/REAL(SIZE(distances), KIND=dp))
317 : CALL neb_calc_energy_forces(rep_env, neb_env, coords, energies, forces, &
318 160 : particle_set, iw)
319 : ! Check for an external exit command
320 160 : CALL external_control(should_stop, "NEB", globenv=globenv)
321 160 : IF (should_stop) EXIT
322 : ! Control on velocity - II part [check vels VS forces, Steepest Descent like]
323 160 : CALL control_vels_b(vels, forces, vc_section)
324 : ! Velocity Verlet (second part)
325 83760 : vels%wrk(:, :) = vels%wrk(:, :) + mass(:, :)*forces%wrk(:, :)
326 : ! Dump Infos
327 : CALL dump_neb_info(neb_env=neb_env, &
328 : coords=coords, &
329 : vels=vels, &
330 : forces=forces, &
331 : particle_set=particle_set, &
332 : logger=logger, &
333 : istep=istep, &
334 : energies=energies, &
335 : distances=distances, &
336 160 : output_unit=output_unit)
337 160 : converged = check_convergence(neb_env, Dcoords, forces)
338 336 : IF (converged) EXIT
339 : END DO md_opt_loop
340 :
341 16 : DEALLOCATE (mass)
342 16 : DEALLOCATE (energies)
343 16 : DEALLOCATE (distances)
344 16 : CALL neb_var_release(Dcoords)
345 : CALL cp_print_key_finished_output(iw, logger, neb_env%neb_section, &
346 16 : "REPLICA_INFO")
347 16 : CALL timestop(handle)
348 :
349 32 : END SUBROUTINE neb_md
350 :
351 : ! **************************************************************************************************
352 : !> \brief DIIS type optimization NEB
353 : !> \param rep_env ...
354 : !> \param neb_env ...
355 : !> \param coords ...
356 : !> \param vels ...
357 : !> \param forces ...
358 : !> \param particle_set ...
359 : !> \param output_unit ...
360 : !> \param diis_section ...
361 : !> \param logger ...
362 : !> \param globenv ...
363 : !> \author Teodoro Laino 09.2006
364 : ! **************************************************************************************************
365 18 : SUBROUTINE neb_diis(rep_env, neb_env, coords, vels, forces, particle_set, output_unit, &
366 : diis_section, logger, globenv)
367 : TYPE(replica_env_type), POINTER :: rep_env
368 : TYPE(neb_type), OPTIONAL, POINTER :: neb_env
369 : TYPE(neb_var_type), POINTER :: coords, vels, forces
370 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
371 : INTEGER, INTENT(IN) :: output_unit
372 : TYPE(section_vals_type), POINTER :: diis_section
373 : TYPE(cp_logger_type), POINTER :: logger
374 : TYPE(global_environment_type), POINTER :: globenv
375 :
376 : CHARACTER(len=*), PARAMETER :: routineN = 'neb_diis'
377 :
378 : INTEGER :: handle, istep, iw, iw2, max_sd_steps, &
379 : max_steps, n_diis
380 18 : INTEGER, DIMENSION(:), POINTER :: set_err
381 : LOGICAL :: check_diis, converged, diis_on, do_ls, &
382 : should_stop, skip_ls
383 : REAL(KIND=dp) :: max_stepsize, norm, stepsize, stepsize0
384 18 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: distances, energies
385 18 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: crr, err
386 : TYPE(neb_var_type), POINTER :: sline
387 :
388 18 : CALL timeset(routineN, handle)
389 18 : NULLIFY (sline, crr, err)
390 18 : neb_env%opt_type_label = "SD"
391 18 : do_ls = .TRUE.
392 18 : CPASSERT(ASSOCIATED(coords))
393 18 : CPASSERT(ASSOCIATED(vels))
394 18 : CPASSERT(ASSOCIATED(forces))
395 : iw = cp_print_key_unit_nr(logger, neb_env%neb_section, "REPLICA_INFO", &
396 18 : extension=".replicaLog")
397 18 : CALL section_vals_val_get(diis_section, "MAX_STEPS", i_val=max_steps)
398 18 : CALL section_vals_val_get(diis_section, "N_DIIS", i_val=n_diis)
399 18 : CALL section_vals_val_get(diis_section, "STEPSIZE", r_val=stepsize0)
400 18 : CALL section_vals_val_get(diis_section, "MAX_STEPSIZE", r_val=max_stepsize)
401 18 : CALL section_vals_val_get(diis_section, "NO_LS", l_val=skip_ls)
402 18 : CALL section_vals_val_get(diis_section, "MAX_SD_STEPS", i_val=max_sd_steps)
403 18 : CALL section_vals_val_get(diis_section, "CHECK_DIIS", l_val=check_diis)
404 : iw2 = cp_print_key_unit_nr(logger, diis_section, "DIIS_INFO", &
405 18 : extension=".diisLog")
406 : ! Initial setup for DIIS
407 18 : stepsize = stepsize0
408 : ! Allocate type for Line Search direction
409 18 : CALL neb_var_create(sline, neb_env, full_allocation=.TRUE.)
410 : ! Array of error vectors
411 108 : ALLOCATE (err(PRODUCT(coords%size_wrk), n_diis))
412 108 : ALLOCATE (crr(PRODUCT(coords%size_wrk), n_diis))
413 54 : ALLOCATE (set_err(n_diis))
414 54 : ALLOCATE (energies(neb_env%number_of_replica))
415 54 : ALLOCATE (distances(neb_env%number_of_replica - 1))
416 : ! Initializing forces array
417 : CALL reorient_images(neb_env%rotate_frames, particle_set, coords, vels, &
418 18 : output_unit, distances, neb_env%number_of_replica)
419 : CALL reparametrize_images(neb_env%reparametrize_frames, neb_env%spline_order, &
420 18 : neb_env%smoothing, coords%wrk, sline%wrk, distances)
421 122 : neb_env%avg_distance = SQRT(SUM(distances*distances)/REAL(SIZE(distances), KIND=dp))
422 : CALL neb_calc_energy_forces(rep_env, neb_env, coords, energies, forces, &
423 18 : particle_set, iw)
424 : ! Dump Infos
425 : CALL dump_neb_info(neb_env=neb_env, &
426 : coords=coords, &
427 : forces=forces, &
428 : particle_set=particle_set, &
429 : logger=logger, &
430 : istep=0, &
431 : energies=energies, &
432 : distances=distances, &
433 : vels=vels, &
434 18 : output_unit=output_unit)
435 : ! If rotation is requested let's apply it at the beginning of the
436 : ! Geometry optimization and then let's disable it
437 18 : neb_env%rotate_frames = .FALSE.
438 : ! Main SD/DIIS loop
439 104 : set_err = -1
440 398 : DO istep = 1, max_steps
441 384 : CALL cp_iterate(logger%iter_info, iter_nr=istep)
442 384 : neb_env%opt_type_label = "SD"
443 : ! Save the optimization step counter
444 384 : neb_env%istep = istep
445 : ! Perform one step of SD with line search
446 520346 : norm = SQRT(SUM(forces%wrk*forces%wrk))
447 384 : IF (norm < EPSILON(0.0_dp)) THEN
448 : ! Let's handle the case in which the band is already fully optimized
449 18 : converged = .TRUE.
450 : EXIT
451 : END IF
452 1040308 : sline%wrk = forces%wrk/norm
453 384 : IF (do_ls .AND. (.NOT. skip_ls)) THEN
454 : CALL neb_ls(stepsize, sline, rep_env, neb_env, coords, energies, forces, &
455 150 : vels, particle_set, iw, output_unit, distances, diis_section, iw2)
456 150 : IF (iw2 > 0) &
457 0 : WRITE (iw2, '(T2,A,T69,F12.6)') "SD| Stepsize in SD after linesearch", &
458 0 : stepsize
459 : ELSE
460 234 : stepsize = MIN(norm*stepsize0, max_stepsize)
461 234 : IF (iw2 > 0) &
462 0 : WRITE (iw2, '(T2,A,T69,F12.6)') "SD| Stepsize in SD no linesearch performed", &
463 0 : stepsize
464 : END IF
465 520346 : sline%wrk = stepsize*sline%wrk
466 : diis_on = accept_diis_step(istep > max_sd_steps, n_diis, err, crr, set_err, sline, coords, &
467 384 : check_diis, iw2)
468 384 : IF (diis_on) THEN
469 146 : neb_env%opt_type_label = "DIIS"
470 : END IF
471 384 : do_ls = .TRUE.
472 1978 : IF (COUNT(set_err == -1) == 1) do_ls = .FALSE.
473 1040308 : coords%wrk = coords%wrk + sline%wrk
474 : ! Compute forces
475 : CALL reorient_images(neb_env%rotate_frames, particle_set, coords, vels, &
476 384 : output_unit, distances, neb_env%number_of_replica)
477 : CALL reparametrize_images(neb_env%reparametrize_frames, neb_env%spline_order, &
478 384 : neb_env%smoothing, coords%wrk, sline%wrk, distances)
479 2462 : neb_env%avg_distance = SQRT(SUM(distances*distances)/REAL(SIZE(distances), KIND=dp))
480 : CALL neb_calc_energy_forces(rep_env, neb_env, coords, energies, forces, &
481 384 : particle_set, iw)
482 : ! Check for an external exit command
483 384 : CALL external_control(should_stop, "NEB", globenv=globenv)
484 384 : IF (should_stop) EXIT
485 : ! Dump Infos
486 : CALL dump_neb_info(neb_env=neb_env, &
487 : coords=coords, &
488 : forces=forces, &
489 : particle_set=particle_set, &
490 : logger=logger, &
491 : istep=istep, &
492 : energies=energies, &
493 : distances=distances, &
494 : vels=vels, &
495 384 : output_unit=output_unit)
496 :
497 384 : converged = check_convergence(neb_env, sline, forces)
498 782 : IF (converged) EXIT
499 : END DO
500 18 : DEALLOCATE (energies)
501 18 : DEALLOCATE (distances)
502 18 : DEALLOCATE (err)
503 18 : DEALLOCATE (crr)
504 18 : DEALLOCATE (set_err)
505 18 : CALL neb_var_release(sline)
506 18 : CALL timestop(handle)
507 54 : END SUBROUTINE neb_diis
508 :
509 : END MODULE neb_methods
|