(git:6d276e9)
Loading...
Searching...
No Matches
dimer_methods.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 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
24 USE dimer_types, ONLY: dimer_env_type,&
26 USE dimer_utils, ONLY: get_theta
29 USE gopt_f_types, ONLY: gopt_f_type
35 USE kinds, ONLY: dp
36 USE motion_utils, ONLY: rot_ana,&
39#include "../base/base_uses.f90"
40
41 IMPLICIT NONE
42 PRIVATE
43
44 LOGICAL, PRIVATE, PARAMETER :: debug_this_module = .false.
45 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'dimer_methods'
46
47 PUBLIC :: cp_eval_at_ts
48
49CONTAINS
50
51! **************************************************************************************************
52!> \brief Computes the dimer energy/gradients (including the rotation of the dimer)
53!> \param gopt_env ...
54!> \param x ...
55!> \param f ...
56!> \param gradient ...
57!> \param calc_force ...
58!> \date 01.2008
59!> \par History
60!> none
61!> \author Luca Bellucci and Teodoro Laino - created [tlaino]
62! **************************************************************************************************
63 RECURSIVE SUBROUTINE cp_eval_at_ts(gopt_env, x, f, gradient, calc_force)
64 TYPE(gopt_f_type), POINTER :: gopt_env
65 REAL(kind=dp), DIMENSION(:), POINTER :: x
66 REAL(kind=dp), INTENT(OUT) :: f
67 REAL(kind=dp), DIMENSION(:), POINTER :: gradient
68 LOGICAL, INTENT(IN) :: calc_force
69
70 CHARACTER(len=*), PARAMETER :: routinen = 'cp_eval_at_ts'
71
72 INTEGER :: handle, iw
73 LOGICAL :: eval_analytical
74 REAL(kind=dp) :: angle1, angle2, f1, gm1, gm2, norm, swf
75 TYPE(cp_logger_type), POINTER :: logger
76 TYPE(dimer_env_type), POINTER :: dimer_env
77 TYPE(section_vals_type), POINTER :: print_section
78
79 NULLIFY (dimer_env, logger, print_section)
80 CALL timeset(routinen, handle)
81 logger => cp_get_default_logger()
82
83 cpassert(ASSOCIATED(gopt_env))
84 dimer_env => gopt_env%dimer_env
85 cpassert(ASSOCIATED(dimer_env))
86 iw = cp_print_key_unit_nr(logger, gopt_env%geo_section, "PRINT%PROGRAM_RUN_INFO", extension=".log")
87 ! Possibly rotate Dimer or just compute Gradients of point 0 for Translation
88 IF (gopt_env%dimer_rotation) THEN
89 IF (debug_this_module .AND. (iw > 0)) THEN
90 WRITE (iw, '(A)') "NVEC:"
91 WRITE (iw, '(3F15.9)') dimer_env%nvec
92 END IF
93 SELECT CASE (dimer_env%rot%rotation_step)
95 eval_analytical = .true.
96 IF ((dimer_env%rot%rotation_step == do_third_rotation_step) .AND. (dimer_env%rot%interpolate_gradient)) THEN
97 eval_analytical = .false.
98 END IF
99 IF (eval_analytical) THEN
100 ! Compute energy, gradients and rotation vector for R1
101 CALL cp_eval_at_ts_low(gopt_env, x, 1, dimer_env, calc_force, f1, dimer_env%rot%g1)
102 ELSE
103 angle1 = dimer_env%rot%angle1
104 angle2 = dimer_env%rot%angle2
105 dimer_env%rot%g1 = sin(angle1 - angle2)/sin(angle1)*dimer_env%rot%g1 + &
106 sin(angle2)/sin(angle1)*dimer_env%rot%g1p + &
107 (1.0_dp - cos(angle2) - sin(angle2)*tan(angle1/2.0_dp))*dimer_env%rot%g0
108 END IF
109
110 ! Determine the theta vector (i.e. the search direction for line minimization)
111 gradient = -2.0_dp*(dimer_env%rot%g1 - dimer_env%rot%g0)
112 IF (debug_this_module .AND. (iw > 0)) THEN
113 WRITE (iw, '(A)') "G1 vector:"
114 WRITE (iw, '(3F15.9)') dimer_env%rot%g1
115 WRITE (iw, '(A)') "-2*(G1-G0) vector:"
116 WRITE (iw, '(3F15.9)') gradient
117 END IF
118 CALL get_theta(gradient, dimer_env, norm)
119 f = norm
120 dimer_env%cg_rot%norm_theta_old = dimer_env%cg_rot%norm_theta
121 dimer_env%cg_rot%norm_theta = norm
122
123 IF (debug_this_module .AND. (iw > 0)) THEN
124 WRITE (iw, '(A,F20.10)') "Rotational Force step (1,3): module:", norm
125 WRITE (iw, '(3F15.9)') gradient
126 END IF
127
128 ! Compute curvature and derivative of the curvature w.r.t. the rotational angle
129 dimer_env%rot%curvature = dot_product(dimer_env%rot%g1 - dimer_env%rot%g0, dimer_env%nvec)/dimer_env%dr
130 dimer_env%rot%dCdp = 2.0_dp*dot_product(dimer_env%rot%g1 - dimer_env%rot%g0, gradient)/dimer_env%dr
131
132 dimer_env%rot%rotation_step = do_second_rotation_step
133 gradient = -gradient
135 ! Compute energy, gradients and rotation vector for R1
136 CALL cp_eval_at_ts_low(gopt_env, x, 1, dimer_env, calc_force, f1, dimer_env%rot%g1p)
137 dimer_env%rot%curvature = dot_product(dimer_env%rot%g1p - dimer_env%rot%g0, dimer_env%nvec)/dimer_env%dr
138 dimer_env%rot%rotation_step = do_third_rotation_step
139
140 ! Determine the theta vector (i.e. the search direction for line minimization)
141 ! This is never used for getting a new theta but is consistent in order to
142 ! give back the right value of f
143 gradient = -2.0_dp*(dimer_env%rot%g1p - dimer_env%rot%g0)
144 CALL get_theta(gradient, dimer_env, norm)
145 f = norm
146
147 IF (debug_this_module .AND. (iw > 0)) THEN
148 WRITE (iw, '(A)') "Rotational Force step (1,3):"
149 WRITE (iw, '(3F15.9)') gradient
150 END IF
151 END SELECT
152 ELSE
153 ! Compute energy, gradients and rotation vector for R0
154 CALL cp_eval_at_ts_low(gopt_env, x, 0, dimer_env, calc_force, f, dimer_env%rot%g0)
155
156 ! The dimer is rotated only when we are out of the translation line search
157 IF (.NOT. gopt_env%do_line_search) THEN
158 IF (debug_this_module .AND. (iw > 0)) THEN
159 WRITE (iw, '(A)') "Entering the rotation module"
160 WRITE (iw, '(A)') "G0 vector:"
161 WRITE (iw, '(3F15.9)') dimer_env%rot%g0
162 END IF
163 cpassert(ASSOCIATED(gopt_env%dimer_rotation_optimizer))
164 CALL gopt_env%dimer_rotation_optimizer(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:", norm2(gradient)
201 END IF
202 IF (.NOT. gopt_env%do_line_search) THEN
203 f = norm2(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 = norm2(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
332END MODULE dimer_methods
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public henkelman2014
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, cell_ref, use_ref_cell)
returns information about various attributes of the given subsys
Contains types used for a Dimer Method calculations.
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)
Contains types used for a Dimer Method calculations.
Definition dimer_types.F:14
subroutine, public dimer_fixed_atom_control(vec, subsys, unit)
Set parts of a given array vec to zero according to fixed atom constraints. When atoms are (partially...
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.
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, ipi_env)
returns various attributes about the force environment
contains a functional that calculates the energy and its derivatives for the geometry optimizer
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.
real(kind=dp), parameter, public thrs_motion
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...
represent a simple array based list of the given type
type of a logger, at the moment it contains just a print level starting at which level it should be l...
represents a system: atoms, molecules, their pos,vel,...
Defines the environment for a Dimer Method calculation.
calculates the potential energy of a system, and its derivatives