(git:b195825)
dimer_methods.F
Go to the documentation of this file.
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 Contains types used for a Dimer Method calculations
10 !> \par History
11 !> -Luca Bellucci 11.2017 - CNR-NANO, Pisa
12 !> add K-DIMER from doi:10.1063/1.4898664
13 !> \author Luca Bellucci and Teodoro Laino - created [tlaino] - 01.2008
14 ! **************************************************************************************************
16  USE bibliography, ONLY: henkelman2014,&
17  cite_reference
19  cp_logger_type
22  USE cp_subsys_types, ONLY: cp_subsys_get,&
23  cp_subsys_type
24  USE dimer_types, ONLY: dimer_env_type,&
26  USE dimer_utils, ONLY: get_theta
29  USE geo_opt, ONLY: cp_rot_opt
30  USE gopt_f_types, ONLY: gopt_f_type
35  section_vals_type
36  USE kinds, ONLY: dp
37  USE motion_utils, ONLY: rot_ana,&
39  USE particle_list_types, ONLY: particle_list_type
40 #include "../base/base_uses.f90"
41 
42  IMPLICIT NONE
43  PRIVATE
44 
45  LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .false.
46  CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dimer_methods'
47 
48  PUBLIC :: cp_eval_at_ts
49 
50 CONTAINS
51 
52 ! **************************************************************************************************
53 !> \brief Computes the dimer energy/gradients (including the rotation of the dimer)
54 !> \param gopt_env ...
55 !> \param x ...
56 !> \param f ...
57 !> \param gradient ...
58 !> \param calc_force ...
59 !> \date 01.2008
60 !> \par History
61 !> none
62 !> \author Luca Bellucci and Teodoro Laino - created [tlaino]
63 ! **************************************************************************************************
64  RECURSIVE SUBROUTINE cp_eval_at_ts(gopt_env, x, f, gradient, calc_force)
65  TYPE(gopt_f_type), POINTER :: gopt_env
66  REAL(kind=dp), DIMENSION(:), POINTER :: x
67  REAL(kind=dp), INTENT(OUT) :: f
68  REAL(kind=dp), DIMENSION(:), POINTER :: gradient
69  LOGICAL, INTENT(IN) :: calc_force
70 
71  CHARACTER(len=*), PARAMETER :: routinen = 'cp_eval_at_ts'
72 
73  INTEGER :: handle, iw
74  LOGICAL :: eval_analytical
75  REAL(kind=dp) :: angle1, angle2, f1, gm1, gm2, norm, swf
76  TYPE(cp_logger_type), POINTER :: logger
77  TYPE(dimer_env_type), POINTER :: dimer_env
78  TYPE(section_vals_type), POINTER :: print_section
79 
80  NULLIFY (dimer_env, logger, print_section)
81  CALL timeset(routinen, handle)
82  logger => cp_get_default_logger()
83 
84  cpassert(ASSOCIATED(gopt_env))
85  dimer_env => gopt_env%dimer_env
86  cpassert(ASSOCIATED(dimer_env))
87  iw = cp_print_key_unit_nr(logger, gopt_env%geo_section, "PRINT%PROGRAM_RUN_INFO", extension=".log")
88  ! Possibly rotate Dimer or just compute Gradients of point 0 for Translation
89  IF (gopt_env%dimer_rotation) THEN
90  IF (debug_this_module .AND. (iw > 0)) THEN
91  WRITE (iw, '(A)') "NVEC:"
92  WRITE (iw, '(3F15.9)') dimer_env%nvec
93  END IF
94  SELECT CASE (dimer_env%rot%rotation_step)
96  eval_analytical = .true.
97  IF ((dimer_env%rot%rotation_step == do_third_rotation_step) .AND. (dimer_env%rot%interpolate_gradient)) THEN
98  eval_analytical = .false.
99  END IF
100  IF (eval_analytical) THEN
101  ! Compute energy, gradients and rotation vector for R1
102  CALL cp_eval_at_ts_low(gopt_env, x, 1, dimer_env, calc_force, f1, dimer_env%rot%g1)
103  ELSE
104  angle1 = dimer_env%rot%angle1
105  angle2 = dimer_env%rot%angle2
106  dimer_env%rot%g1 = sin(angle1 - angle2)/sin(angle1)*dimer_env%rot%g1 + &
107  sin(angle2)/sin(angle1)*dimer_env%rot%g1p + &
108  (1.0_dp - cos(angle2) - sin(angle2)*tan(angle1/2.0_dp))*dimer_env%rot%g0
109  END IF
110 
111  ! Determine the theta vector (i.e. the search direction for line minimization)
112  gradient = -2.0_dp*(dimer_env%rot%g1 - dimer_env%rot%g0)
113  IF (debug_this_module .AND. (iw > 0)) THEN
114  WRITE (iw, '(A)') "G1 vector:"
115  WRITE (iw, '(3F15.9)') dimer_env%rot%g1
116  WRITE (iw, '(A)') "-2*(G1-G0) vector:"
117  WRITE (iw, '(3F15.9)') gradient
118  END IF
119  CALL get_theta(gradient, dimer_env, norm)
120  f = norm
121  dimer_env%cg_rot%norm_theta_old = dimer_env%cg_rot%norm_theta
122  dimer_env%cg_rot%norm_theta = norm
123 
124  IF (debug_this_module .AND. (iw > 0)) THEN
125  WRITE (iw, '(A,F20.10)') "Rotational Force step (1,3): module:", norm
126  WRITE (iw, '(3F15.9)') gradient
127  END IF
128 
129  ! Compute curvature and derivative of the curvature w.r.t. the rotational angle
130  dimer_env%rot%curvature = dot_product(dimer_env%rot%g1 - dimer_env%rot%g0, dimer_env%nvec)/dimer_env%dr
131  dimer_env%rot%dCdp = 2.0_dp*dot_product(dimer_env%rot%g1 - dimer_env%rot%g0, gradient)/dimer_env%dr
132 
133  dimer_env%rot%rotation_step = do_second_rotation_step
134  gradient = -gradient
136  ! Compute energy, gradients and rotation vector for R1
137  CALL cp_eval_at_ts_low(gopt_env, x, 1, dimer_env, calc_force, f1, dimer_env%rot%g1p)
138  dimer_env%rot%curvature = dot_product(dimer_env%rot%g1p - dimer_env%rot%g0, dimer_env%nvec)/dimer_env%dr
139  dimer_env%rot%rotation_step = do_third_rotation_step
140 
141  ! Determine the theta vector (i.e. the search direction for line minimization)
142  ! This is never used for getting a new theta but is consistent in order to
143  ! give back the right value of f
144  gradient = -2.0_dp*(dimer_env%rot%g1p - dimer_env%rot%g0)
145  CALL get_theta(gradient, dimer_env, norm)
146  f = norm
147 
148  IF (debug_this_module .AND. (iw > 0)) THEN
149  WRITE (iw, '(A)') "Rotational Force step (1,3):"
150  WRITE (iw, '(3F15.9)') gradient
151  END IF
152  END SELECT
153  ELSE
154  ! Compute energy, gradients and rotation vector for R0
155  CALL cp_eval_at_ts_low(gopt_env, x, 0, dimer_env, calc_force, f, dimer_env%rot%g0)
156 
157  ! The dimer is rotated only when we are out of the translation line search
158  IF (.NOT. gopt_env%do_line_search) THEN
159  IF (debug_this_module .AND. (iw > 0)) THEN
160  WRITE (iw, '(A)') "Entering the rotation module"
161  WRITE (iw, '(A)') "G0 vector:"
162  WRITE (iw, '(3F15.9)') dimer_env%rot%g0
163  END IF
164  CALL cp_rot_opt(gopt_env%gopt_dimer_env, x, gopt_env%gopt_dimer_param, &
165  gopt_env%gopt_dimer_env%geo_section)
166  dimer_env%rot%rotation_step = do_first_rotation_step
167  END IF
168 
169  print_section => section_vals_get_subs_vals(gopt_env%gopt_dimer_env%geo_section, "PRINT")
170 
171  ! Correcting gradients for Translation K-DIMER or STANDARD
172  IF (dimer_env%kdimer) THEN
173  CALL cite_reference(henkelman2014)
174  ! K-DIMER
175  IF (iw > 0) THEN
176  WRITE (iw, '(T2,A)') "DIMER| Correcting gradients for Translation with K-DIMER method"
177  END IF
178  swf = 1.0_dp + exp(dimer_env%beta*dimer_env%rot%curvature)
179  gm2 = 1.0_dp - (1.0_dp/swf)
180  gm1 = (2.0_dp/swf) - 1.0_dp
181  gradient = gm2*(dimer_env%rot%g0 - 2.0_dp*dot_product(dimer_env%rot%g0, dimer_env%nvec)*dimer_env%nvec) &
182  - gm1*(dot_product(dimer_env%rot%g0, dimer_env%nvec)*dimer_env%nvec)
183  CALL remove_rot_transl_component(gopt_env, gradient, print_section)
184  IF (debug_this_module .AND. (iw > 0)) WRITE (iw, *) "K-DIMER", dimer_env%beta, dimer_env%rot%curvature, &
185  dimer_env%rot%dCdp, gm1, gm2, swf
186  ELSE
187  IF (iw > 0) THEN
188  WRITE (iw, '(T2,A)') "DIMER| Correcting gradients for Translation with standard method"
189  END IF
190  IF (dimer_env%rot%curvature > 0) THEN
191  gradient = -dot_product(dimer_env%rot%g0, dimer_env%nvec)*dimer_env%nvec
192  CALL remove_rot_transl_component(gopt_env, gradient, print_section)
193  ELSE
194  gradient = dimer_env%rot%g0 - 2.0_dp*dot_product(dimer_env%rot%g0, dimer_env%nvec)*dimer_env%nvec
195  CALL remove_rot_transl_component(gopt_env, gradient, print_section)
196  END IF
197  END IF
198  IF (debug_this_module .AND. (iw > 0)) THEN
199  WRITE (iw, *) "final gradient:", gradient
200  WRITE (iw, '(A,F20.10)') "norm gradient:", sqrt(dot_product(gradient, gradient))
201  END IF
202  IF (.NOT. gopt_env%do_line_search) THEN
203  f = sqrt(dot_product(gradient, gradient))
204  ELSE
205  f = -dot_product(gradient, dimer_env%tsl%tls_vec)
206  END IF
207  END IF
208  CALL cp_print_key_finished_output(iw, logger, gopt_env%geo_section, "PRINT%PROGRAM_RUN_INFO")
209  CALL timestop(handle)
210  END SUBROUTINE cp_eval_at_ts
211 
212 ! **************************************************************************************************
213 !> \brief This function removes translational forces after project of the gradient
214 !> \param gopt_env ...
215 !> \param gradient ...
216 !> \param print_section ...
217 !> \par History
218 !> 2016/03/02 [LTong] added fixed atom constraint for gradient
219 !> \author Luca Bellucci and Teodoro Laino - created [tlaino] - 01.2008
220 ! **************************************************************************************************
221  SUBROUTINE remove_rot_transl_component(gopt_env, gradient, print_section)
222  TYPE(gopt_f_type), POINTER :: gopt_env
223  REAL(kind=dp), DIMENSION(:) :: gradient
224  TYPE(section_vals_type), POINTER :: print_section
225 
226  CHARACTER(len=*), PARAMETER :: routinen = 'remove_rot_transl_component'
227 
228  INTEGER :: dof, handle, i, j, natoms
229  REAL(kind=dp) :: norm, norm_gradient_old
230  REAL(kind=dp), DIMENSION(:, :), POINTER :: d, mat
231  TYPE(cp_subsys_type), POINTER :: subsys
232  TYPE(particle_list_type), POINTER :: particles
233 
234  CALL timeset(routinen, handle)
235  NULLIFY (mat)
236  CALL force_env_get(gopt_env%force_env, subsys=subsys)
237  CALL cp_subsys_get(subsys, particles=particles)
238 
239  natoms = particles%n_els
240  norm_gradient_old = sqrt(dot_product(gradient, gradient))
241  IF (norm_gradient_old > 0.0_dp) THEN
242  IF (natoms > 1) THEN
243  CALL rot_ana(particles%els, mat, dof, print_section, keep_rotations=.false., &
244  mass_weighted=.false., natoms=natoms)
245 
246  ! Orthogonalize gradient with respect to the full set of Roto-Trasl vectors
247  ALLOCATE (d(3*natoms, dof))
248  ! Check First orthogonality in the first element of the basis set
249  DO i = 1, dof
250  d(:, i) = mat(:, i)
251  DO j = i + 1, dof
252  norm = dot_product(mat(:, i), mat(:, j))
253  cpassert(abs(norm) < thrs_motion)
254  END DO
255  END DO
256  DO i = 1, dof
257  norm = dot_product(gradient, d(:, i))
258  gradient = gradient - norm*d(:, i)
259  END DO
260  DEALLOCATE (d)
261  DEALLOCATE (mat)
262  END IF
263  END IF
264  ! apply constraint
265  CALL dimer_fixed_atom_control(gradient, subsys)
266  CALL timestop(handle)
267  END SUBROUTINE remove_rot_transl_component
268 
269 ! **************************************************************************************************
270 !> \brief ...
271 !> \param gopt_env ...
272 !> \param x ...
273 !> \param dimer_index ...
274 !> \param dimer_env ...
275 !> \param calc_force ...
276 !> \param f ...
277 !> \param gradient ...
278 !> \par History
279 !> none
280 !> \author Luca Bellucci and Teodoro Laino - created [tlaino] - 01.2008
281 ! **************************************************************************************************
282  SUBROUTINE cp_eval_at_ts_low(gopt_env, x, dimer_index, dimer_env, calc_force, &
283  f, gradient)
284  TYPE(gopt_f_type), POINTER :: gopt_env
285  REAL(kind=dp), DIMENSION(:), POINTER :: x
286  INTEGER, INTENT(IN) :: dimer_index
287  TYPE(dimer_env_type), POINTER :: dimer_env
288  LOGICAL, INTENT(IN) :: calc_force
289  REAL(kind=dp), INTENT(OUT), OPTIONAL :: f
290  REAL(kind=dp), DIMENSION(:), OPTIONAL :: gradient
291 
292  CHARACTER(len=*), PARAMETER :: routinen = 'cp_eval_at_ts_low'
293 
294  INTEGER :: handle, idg, idir, ip
295  TYPE(cp_subsys_type), POINTER :: subsys
296  TYPE(particle_list_type), POINTER :: particles
297 
298  CALL timeset(routinen, handle)
299  idg = 0
300  CALL force_env_get(gopt_env%force_env, subsys=subsys)
301  CALL cp_subsys_get(subsys, particles=particles)
302  DO ip = 1, particles%n_els
303  DO idir = 1, 3
304  idg = idg + 1
305  particles%els(ip)%r(idir) = x(idg) + real(dimer_index, kind=dp)*dimer_env%nvec(idg)*dimer_env%dr
306  END DO
307  END DO
308 
309  ! Compute energy and forces
310  CALL force_env_calc_energy_force(gopt_env%force_env, calc_force=calc_force)
311 
312  ! Possibly take the potential energy
313  IF (PRESENT(f)) THEN
314  CALL force_env_get(gopt_env%force_env, potential_energy=f)
315  END IF
316 
317  ! Possibly take the gradients
318  IF (PRESENT(gradient)) THEN
319  idg = 0
320  CALL cp_subsys_get(subsys, particles=particles)
321  DO ip = 1, particles%n_els
322  DO idir = 1, 3
323  idg = idg + 1
324  cpassert(SIZE(gradient) >= idg)
325  gradient(idg) = -particles%els(ip)%f(idir)
326  END DO
327  END DO
328  END IF
329  CALL timestop(handle)
330  END SUBROUTINE cp_eval_at_ts_low
331 
332 END MODULE dimer_methods
collects all references to literature in CP2K as new algorithms / method are included from literature...
Definition: bibliography.F:28
integer, save, public henkelman2014
Definition: bibliography.F:43
various routines to log and control the output. The idea is that decisions about where to log should ...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
types that represent a subsys, i.e. a part of the system
subroutine, public cp_subsys_get(subsys, ref_count, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell)
returns information about various attributes of the given subsys
Contains types used for a Dimer Method calculations.
Definition: dimer_methods.F:15
recursive subroutine, public cp_eval_at_ts(gopt_env, x, f, gradient, calc_force)
Computes the dimer energy/gradients (including the rotation of the dimer)
Definition: dimer_methods.F:65
Contains types used for a Dimer Method calculations.
Definition: dimer_types.F:14
subroutine, public dimer_fixed_atom_control(vec, subsys)
Set parts of a given array vec to zero according to fixed atom constraints. When atoms are (partially...
Definition: dimer_types.F:266
Contains utilities for a Dimer Method calculations.
Definition: dimer_utils.F:14
subroutine, public get_theta(gradient, dimer_env, norm)
This function orthonormalize the vector for the rotational search.
Definition: dimer_utils.F:118
Interface for the force calculations.
recursive subroutine, public force_env_calc_energy_force(force_env, calc_force, consistent_energies, skip_external_control, eval_energy_forces, require_consistent_energy_force, linres, calc_stress_tensor)
Interface routine for force and energy calculations.
Interface for the force calculations.
recursive subroutine, public force_env_get(force_env, in_use, fist_env, qs_env, meta_env, fp_env, subsys, para_env, potential_energy, additional_potential, kinetic_energy, harmonic_shell, kinetic_shell, cell, sub_force_env, qmmm_env, qmmmx_env, eip_env, pwdft_env, globenv, input, force_env_section, method_name_id, root_section, mixed_env, nnp_env, embed_env)
returns various attributes about the force environment
performs geometry optimization
Definition: geo_opt.F:13
subroutine, public cp_rot_opt(gopt_env, x0, gopt_param, geo_section)
Main driver to perform rotation optimization for Dimer.
Definition: geo_opt.F:115
contains a functional that calculates the energy and its derivatives for the geometry optimizer
Definition: gopt_f_types.F:15
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public do_second_rotation_step
integer, parameter, public do_first_rotation_step
integer, parameter, public do_third_rotation_step
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
Defines the basic variable types.
Definition: kinds.F:23
integer, parameter, public dp
Definition: kinds.F:34
Output Utilities for MOTION_SECTION.
Definition: motion_utils.F:13
real(kind=dp), parameter, public thrs_motion
Definition: motion_utils.F:60
subroutine, public rot_ana(particles, mat, dof, print_section, keep_rotations, mass_weighted, natoms, rot_dof, inertia)
Performs an analysis of the principal inertia axis Getting back the generators of the translating and...
Definition: motion_utils.F:81
represent a simple array based list of the given type