75#include "../base/base_uses.f90"
79 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'neb_utils'
80 LOGICAL,
PARAMETER,
PRIVATE :: debug_this_module = .false.
101 SUBROUTINE neb_replica_distance(particle_set, coords, i0, i, distance, iw, rotate)
102 TYPE(particle_type),
DIMENSION(:),
OPTIONAL, &
103 POINTER :: particle_set
104 TYPE(neb_var_type),
POINTER :: coords
105 INTEGER,
INTENT(IN) :: i0, i
106 REAL(KIND=
dp),
INTENT(OUT) :: distance
107 INTEGER,
INTENT(IN) :: iw
108 LOGICAL,
INTENT(IN),
OPTIONAL :: rotate
113 IF (
PRESENT(rotate)) my_rotate = rotate
117 cpassert(
PRESENT(particle_set))
118 CALL rmsd3(particle_set, coords%xyz(:, i), coords%xyz(:, i0), &
119 iw, rotate=my_rotate)
121 distance = norm2(coords%wrk(:, i) - coords%wrk(:, i0))
123 END SUBROUTINE neb_replica_distance
138 coords, vels, neb_env, iw, globenv, para_env)
143 INTEGER,
INTENT(IN) :: iw
147 CHARACTER(len=*),
PARAMETER :: routinen =
'build_replica_coords'
149 CHARACTER(LEN=default_path_length) :: filename
150 INTEGER :: handle, i_rep, iatom, ic, input_nr_replica, is, ivar, j, jtarg, k, n_rep, natom, &
151 neb_nr_replica, nr_replica_to_interpolate, nval, nvar, shell_index
152 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: rep_map
153 LOGICAL :: check, explicit, skip_vel_section
154 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: distance
155 REAL(kind=
dp),
DIMENSION(3) :: r
156 REAL(kind=
dp),
DIMENSION(:),
POINTER :: initial_colvars, rptr
160 CALL timeset(routinen, handle)
161 cpassert(
ASSOCIATED(coords))
162 cpassert(
ASSOCIATED(vels))
163 neb_nr_replica = neb_env%number_of_replica
167 cpassert(input_nr_replica <= neb_nr_replica)
169 skip_vel_section = (input_nr_replica /= neb_nr_replica)
170 IF ((iw > 0) .AND. skip_vel_section)
THEN
171 WRITE (iw,
'(T2,A)')
'NEB| The number of replica in the input is different from the number', &
172 'NEB| of replica requested for NEB. More Replica will be interpolated.', &
173 'NEB| Therefore the possibly provided velocities will not be read.'
176 DO i_rep = 1, input_nr_replica
180 skip_vel_section = skip_vel_section .OR. (.NOT. explicit)
183 coords%xyz(:, :) = 0.0_dp
185 ALLOCATE (rep_map(neb_nr_replica))
187 DO i_rep = 1, input_nr_replica
191 rep_map(i_rep) = i_rep
196 cpassert((natom ==
SIZE(particle_set)))
199 i_rep_val=iatom, r_vals=rptr)
201 coords%xyz(ic + 1:ic + 3, i_rep) = rptr(1:3)*
bohr
203 shell_index = particle_set(iatom)%shell_index
204 IF (shell_index /= 0)
THEN
205 is = 3*(natom + shell_index - 1)
206 coords%xyz(is + 1:is + 3, i_rep) = coords%xyz(ic + 1:ic + 3, i_rep)
212 CHARACTER(LEN=default_string_length) :: dummy_char
215 i_rep_section=i_rep, c_val=filename)
216 cpassert(trim(filename) /=
"")
217 CALL parser_create(parser, filename, para_env=para_env, parse_white_lines=.true.)
221 cpassert((natom ==
SIZE(particle_set)))
227 CALL cp_abort(__location__, &
228 "Number of lines in XYZ format not equal to the number of atoms."// &
229 " Error in XYZ format for REPLICA coordinates. Very probably the"// &
230 " line with title is missing or is empty. Please check the XYZ file and rerun your job!")
232 READ (parser%input_line, *) dummy_char, r(1:3)
234 coords%xyz(ic + 1:ic + 3, i_rep) = r(1:3)*
bohr
236 shell_index = particle_set(iatom)%shell_index
237 IF (shell_index /= 0)
THEN
238 is = 3*(natom + shell_index - 1)
239 coords%xyz(is + 1:is + 3, i_rep) = coords%xyz(ic + 1:ic + 3, i_rep)
246 IF (neb_env%use_colvar)
THEN
248 i_rep_section=i_rep, n_rep_val=n_rep)
251 NULLIFY (initial_colvars)
253 i_rep_section=i_rep, r_vals=initial_colvars)
254 check = (neb_env%nsize_int ==
SIZE(initial_colvars))
256 coords%int(:, i_rep) = initial_colvars
259 CALL eval_colvar(neb_env%force_env, coords%xyz(:, i_rep), coords%int(:, i_rep))
265 IF (skip_vel_section)
THEN
267 i_rep, iw, globenv, neb_env)
274 IF (neb_env%use_colvar)
THEN
275 nvar =
SIZE(vels%wrk, 1)
276 cpassert(nval == nvar)
279 i_rep_val=ivar, r_vals=rptr)
280 vels%wrk(ivar, i_rep) = rptr(1)
283 natom =
SIZE(particle_set)
284 cpassert(nval == natom)
287 i_rep_val=iatom, r_vals=rptr)
289 vels%wrk(ic + 1:ic + 3, i_rep) = rptr(1:3)
291 shell_index = particle_set(iatom)%shell_index
292 IF (shell_index /= 0)
THEN
293 is = 3*(natom + shell_index - 1)
294 vels%wrk(is + 1:is + 3, i_rep) = vels%wrk(ic + 1:ic + 3, i_rep)
300 ALLOCATE (distance(neb_nr_replica - 1))
302 WRITE (iw,
'(T2,A)')
'NEB| Mapping between input and requested replica so far'
303 WRITE (iw,
'(T2,A)')
'NEB| 1, 2, ... = input replica in sections order,'
304 WRITE (iw,
'(T2,A)')
'NEB| -1, -2, ... = added replica in insertion order (if any),'
305 WRITE (iw,
'(T2,A)')
'NEB| 0 = yet to be completed replica (if any)'
306 DO j = 1, neb_nr_replica, 8
307 WRITE (iw,
'(T2,A,T9,8(1X,I8))')
'NEB|', rep_map(j:min(j + 7, neb_nr_replica))
310 IF (input_nr_replica < neb_nr_replica)
THEN
312 nr_replica_to_interpolate = neb_nr_replica - input_nr_replica
316 WRITE (iw,
'(T2,A,I0,A)')
'NEB| Interpolating ', nr_replica_to_interpolate,
' missing replica '// &
317 'by stepwise bisection of distance.'
319 DO WHILE (nr_replica_to_interpolate > 0)
322 DO j = 1, input_nr_replica - 1
323 CALL neb_replica_distance(particle_set, coords, j, j + 1, distance(j), iw, &
324 rotate=neb_env%align_frames)
326 jtarg = maxloc(distance(1:input_nr_replica), 1)
328 WRITE (iw,
'(/,T2,3(A,I0),A)')
'NEB| Interpolating Nr. ', &
329 nr_replica_to_interpolate,
' missing Replica; next between Replica Nr. ', &
330 jtarg,
' and ', jtarg + 1,
'.'
332 input_nr_replica = input_nr_replica + 1
333 nr_replica_to_interpolate = nr_replica_to_interpolate - 1
335 rep_map(jtarg + 2:input_nr_replica) = rep_map(jtarg + 1:input_nr_replica - 1)
336 IF (jtarg + 1 <= neb_nr_replica .AND. jtarg + 1 >= 1) rep_map(jtarg + 1) = -k
338 coords%xyz(:, jtarg + 2:input_nr_replica) = coords%xyz(:, jtarg + 1:input_nr_replica - 1)
339 coords%xyz(:, jtarg + 1) = (coords%xyz(:, jtarg) + coords%xyz(:, jtarg + 2))/2.0_dp
340 IF (neb_env%use_colvar)
THEN
345 coords%int(:, jtarg + 2:input_nr_replica) = coords%int(:, jtarg + 1:input_nr_replica - 1)
346 coords%int(:, jtarg + 1) = (coords%int(:, jtarg) + coords%int(:, jtarg + 2))/2.0_dp
348 vels%wrk(:, jtarg + 2:input_nr_replica) = vels%wrk(:, jtarg + 1:input_nr_replica - 1)
349 vels%wrk(:, jtarg + 1) = 0.0_dp
351 input_nr_replica, iw, neb_env%use_colvar)
353 jtarg + 1, iw, globenv, neb_env)
355 WRITE (iw,
'(T2,A)')
'NEB| Mapping between input and requested replica so far'
356 DO j = 1, neb_nr_replica, 8
357 WRITE (iw,
'(T2,A,T9,8(1X,I8))')
'NEB|', rep_map(j:min(j + 7, neb_nr_replica))
362 vels%wrk(:, 1) = 0.0_dp
363 vels%wrk(:, neb_nr_replica) = 0.0_dp
368 DO j = 1, input_nr_replica - 1
369 CALL neb_replica_distance(particle_set, coords, j, j + 1, distance(j), iw, &
370 rotate=neb_env%align_frames)
373 IF (maxval(distance)/minval(distance) > 1.5_dp)
THEN
375 WRITE (iw,
'(/,T2,A)')
'NEB| After interpolating replica, the maximum distance between adjacent replica'
376 WRITE (iw,
'(T2,A)')
'NEB| is still larger than 1.5 times the minimum distance. In order to make the'
377 WRITE (iw,
'(T2,A)')
'NEB| distribution of replica more uniform, consider providing more structures'
378 WRITE (iw,
'(T2,A)')
'NEB| with &BAND/&REPLICA sections or increasing &BAND/NUMBER_OF_REPLICA value.'
381 DEALLOCATE (distance)
384 CALL timestop(handle)
401 particle_set, output_unit)
402 TYPE(replica_env_type),
POINTER :: rep_env
403 TYPE(neb_type),
OPTIONAL,
POINTER :: neb_env
404 TYPE(neb_var_type),
POINTER :: coords
405 REAL(kind=dp),
DIMENSION(:),
INTENT(OUT) :: energies
406 TYPE(neb_var_type),
POINTER :: forces
407 TYPE(particle_type),
DIMENSION(:),
POINTER :: particle_set
408 INTEGER,
INTENT(IN) :: output_unit
410 CHARACTER(len=*),
PARAMETER :: routinen =
'neb_calc_energy_forces'
411 CHARACTER(LEN=1),
DIMENSION(3),
PARAMETER :: lab = [
"X",
"Y",
"Z"]
413 INTEGER :: handle, i, irep, j, n_int, n_rep, &
415 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:) :: tangent, tmp_a, tmp_b
416 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: cvalues, mmatrix, mmatrix_tmp
418 CALL timeset(routinen, handle)
419 n_int = neb_env%nsize_int
420 n_rep_neb = neb_env%number_of_replica
422 nsize_wrk = coords%size_wrk(1)
424 ALLOCATE (cvalues(n_int, n_rep))
425 ALLOCATE (mmatrix_tmp(n_int*n_int, n_rep))
426 ALLOCATE (mmatrix(n_int*n_int, n_rep_neb))
427 IF (output_unit > 0)
WRITE (output_unit,
'(/,T2,A)')
"NEB| Computing Energies and Forces"
428 DO irep = 1, n_rep_neb, n_rep
430 IF (irep + j <= n_rep_neb)
THEN
435 rep_env%r(:, j + 1) = coords%xyz(:, irep + j)
440 CALL handle_band_file_names(rep_env, irep, n_rep_neb, neb_env%istep)
442 SELECT CASE (neb_env%pot_type)
445 CALL rep_env_calc_e_f(rep_env, calc_f=.true.)
448 CALL perform_replica_md(rep_env, coords, irep, n_rep_neb, cvalues, mmatrix_tmp)
451 CALL perform_replica_geo(rep_env, coords, irep, n_rep_neb, cvalues, mmatrix_tmp)
455 IF (irep + j <= n_rep_neb)
THEN
457 forces%wrk(:, irep + j) = rep_env%f(1:nsize_wrk, j + 1)
458 energies(irep + j) = rep_env%f(rep_env%ndim + 1, j + 1)
459 SELECT CASE (neb_env%pot_type)
462 IF (output_unit > 0)
THEN
463 WRITE (output_unit,
'(T2,A,I5,A,I5,A)') &
464 "NEB| REPLICA Nr.", irep + j,
"- Energy and Forces"
465 WRITE (output_unit,
'(T2,A,T43,A,T57,F24.12)') &
466 "NEB|",
"Total energy:", rep_env%f(rep_env%ndim + 1, j + 1)
467 WRITE (output_unit,
'(T2,"NEB|",T10,"ATOM",T33,3(9X,A,7X))') lab(1), lab(2), lab(3)
468 DO i = 1,
SIZE(particle_set)
469 WRITE (output_unit,
'(T2,"NEB|",T12,A,T30,3(2X,F15.9))') &
470 particle_set(i)%atomic_kind%name, &
471 rep_env%f((i - 1)*3 + 1:(i - 1)*3 + 3, j + 1)
474 CASE (pot_neb_fe, pot_neb_me)
477 coords%xyz(:, irep + j) = rep_env%r(1:rep_env%ndim, j + 1)
478 mmatrix(:, irep + j) = mmatrix_tmp(:, j + 1)
479 IF (output_unit > 0)
THEN
480 WRITE (output_unit,
'(/,T2,A,I5,A,I5,A)') &
481 "NEB| REPLICA Nr.", irep + j,
"- Energy, Collective Variables, Forces"
482 WRITE (output_unit,
'(T2,A,T43,A,T57,F24.12)') &
483 "NEB|",
"Total energy:", rep_env%f(rep_env%ndim + 1, j + 1)
484 WRITE (output_unit, &
485 '(T2,"NEB|",T10,"CV Nr.",12X,"Expected COLVAR",5X,"Present COLVAR",10X,"Forces")')
487 WRITE (output_unit,
'(T2,"NEB|",T12,I2,7X,3(5X,F15.9))') &
488 i, coords%int(i, irep + j), cvalues(i, j + 1), rep_env%f(i, j + 1)
496 DEALLOCATE (mmatrix_tmp)
497 IF (
PRESENT(neb_env))
THEN
500 neb_env%nr_HE_image = maxloc(energies(2:n_rep_neb - 1), 1) + 1
501 ALLOCATE (tangent(nsize_wrk))
504 neb_env%spring_energy = 0.0_dp
505 IF (neb_env%optimize_end_points)
THEN
506 ALLOCATE (tmp_a(
SIZE(forces%wrk, 1)))
507 ALLOCATE (tmp_b(
SIZE(forces%wrk, 1)))
508 tmp_a(:) = forces%wrk(:, 1)
509 tmp_b(:) = forces%wrk(:,
SIZE(forces%wrk, 2))
511 DO i = 2, neb_env%number_of_replica
512 CALL get_tangent(neb_env, coords, i, tangent, energies, output_unit)
513 CALL get_neb_force(neb_env, tangent, coords, i, forces, mmatrix=mmatrix, &
516 IF (neb_env%optimize_end_points)
THEN
517 forces%wrk(:, 1) = tmp_a
518 forces%wrk(:,
SIZE(forces%wrk, 2)) = tmp_b
523 forces%wrk(:, 1) = 0.0_dp
524 forces%wrk(:,
SIZE(forces%wrk, 2)) = 0.0_dp
529 CALL timestop(handle)
543 SUBROUTINE perform_replica_md(rep_env, coords, irep, n_rep_neb, cvalues, Mmatrix)
544 TYPE(replica_env_type),
POINTER :: rep_env
545 TYPE(neb_var_type),
POINTER :: coords
546 INTEGER,
INTENT(IN) :: irep, n_rep_neb
547 REAL(kind=dp),
DIMENSION(:, :),
INTENT(OUT) :: cvalues, mmatrix
549 CHARACTER(len=*),
PARAMETER :: routinen =
'perform_replica_md'
551 INTEGER :: handle, handle2, ierr, j, n_el
553 TYPE(cp_logger_type),
POINTER :: logger
554 TYPE(f_env_type),
POINTER :: f_env
555 TYPE(global_environment_type),
POINTER :: globenv
556 TYPE(section_vals_type),
POINTER :: md_section, root_section
558 CALL timeset(routinen, handle)
559 CALL f_env_add_defaults(f_env_id=rep_env%f_env_id, f_env=f_env, &
561 logger => cp_get_default_logger()
562 CALL force_env_get(f_env%force_env, globenv=globenv, &
563 root_section=root_section)
564 j = rep_env%local_rep_indices(1) - 1
565 n_el = 3*rep_env%nparticle
568 CALL set_pos(rep_env%f_env_id, rep_env%r(:, j + 1), n_el, ierr)
571 IF (irep + j <= n_rep_neb)
THEN
572 logger%iter_info%iteration(2) = irep + j
573 CALL remove_restart_info(root_section)
574 md_section => section_vals_get_subs_vals(root_section,
"MOTION%MD")
575 CALL section_vals_get(md_section, explicit=explicit)
578 CALL set_colvars_target(coords%int(:, irep + j), f_env%force_env)
581 CALL qs_mol_dyn(f_env%force_env, globenv=globenv)
583 CALL get_pos(rep_env%f_env_id, rep_env%r(1:n_el, j + 1), n_el, ierr)
588 cpabort(
"implementation incomplete in perform_replica_md")
589 rep_env%f(:, j + 1) = 0.0_dp
592 rep_env%r(:, j + 1) = 0.0_dp
593 rep_env%f(:, j + 1) = 0.0_dp
594 cvalues(:, j + 1) = 0.0_dp
595 mmatrix(:, j + 1) = 0.0_dp
597 CALL rep_env_sync(rep_env, rep_env%f)
598 CALL rep_env_sync(rep_env, rep_env%r)
599 CALL rep_env_sync(rep_env, cvalues)
600 CALL rep_env_sync(rep_env, mmatrix)
601 CALL f_env_rm_defaults(f_env=f_env, ierr=ierr, handle=handle2)
603 CALL timestop(handle)
604 END SUBROUTINE perform_replica_md
618 SUBROUTINE perform_replica_geo(rep_env, coords, irep, n_rep_neb, cvalues, Mmatrix)
619 TYPE(replica_env_type),
POINTER :: rep_env
620 TYPE(neb_var_type),
POINTER :: coords
621 INTEGER,
INTENT(IN) :: irep, n_rep_neb
622 REAL(kind=dp),
DIMENSION(:, :),
INTENT(OUT) :: cvalues, mmatrix
624 CHARACTER(len=*),
PARAMETER :: routinen =
'perform_replica_geo'
626 INTEGER :: handle, handle2, ierr, j, n_el
628 TYPE(cp_logger_type),
POINTER :: logger
629 TYPE(f_env_type),
POINTER :: f_env
630 TYPE(global_environment_type),
POINTER :: globenv
631 TYPE(section_vals_type),
POINTER :: geoopt_section, root_section
633 CALL timeset(routinen, handle)
634 CALL f_env_add_defaults(f_env_id=rep_env%f_env_id, f_env=f_env, &
636 logger => cp_get_default_logger()
637 CALL force_env_get(f_env%force_env, globenv=globenv, &
638 root_section=root_section)
639 j = rep_env%local_rep_indices(1) - 1
640 n_el = 3*rep_env%nparticle
643 CALL set_pos(rep_env%f_env_id, rep_env%r(:, j + 1), n_el, ierr)
645 IF (irep + j <= n_rep_neb)
THEN
646 logger%iter_info%iteration(2) = irep + j
647 CALL remove_restart_info(root_section)
648 geoopt_section => section_vals_get_subs_vals(root_section,
"MOTION%GEO_OPT")
649 CALL section_vals_get(geoopt_section, explicit=explicit)
652 CALL set_colvars_target(coords%int(:, irep + j), f_env%force_env)
654 CALL cp_geo_opt(f_env%force_env, globenv=globenv)
657 CALL force_env_calc_energy_force(f_env%force_env, &
658 calc_force=.true., skip_external_control=.true.)
660 CALL get_pos(rep_env%f_env_id, rep_env%r(1:n_el, j + 1), n_el, ierr)
663 CALL get_force(rep_env%f_env_id, rep_env%f(1:n_el, j + 1), n_el, ierr)
666 CALL get_energy(rep_env%f_env_id, rep_env%f(n_el + 1, j + 1), ierr)
669 CALL get_clv_force(f_env%force_env, rep_env%f(1:n_el, j + 1), rep_env%r(1:n_el, j + 1), &
670 SIZE(coords%xyz, 1),
SIZE(coords%wrk, 1), cvalues(:, j + 1), mmatrix(:, j + 1))
672 rep_env%r(:, j + 1) = 0.0_dp
673 rep_env%f(:, j + 1) = 0.0_dp
674 cvalues(:, j + 1) = 0.0_dp
675 mmatrix(:, j + 1) = 0.0_dp
677 CALL rep_env_sync(rep_env, rep_env%f)
678 CALL rep_env_sync(rep_env, rep_env%r)
679 CALL rep_env_sync(rep_env, cvalues)
680 CALL rep_env_sync(rep_env, mmatrix)
681 CALL f_env_rm_defaults(f_env=f_env, ierr=ierr, handle=handle2)
683 CALL timestop(handle)
684 END SUBROUTINE perform_replica_geo
696 SUBROUTINE get_tangent(neb_env, coords, i, tangent, energies, iw)
697 TYPE(neb_type),
POINTER :: neb_env
698 TYPE(neb_var_type),
POINTER :: coords
699 INTEGER,
INTENT(IN) :: i
700 REAL(kind=dp),
DIMENSION(:),
INTENT(OUT) :: tangent
701 REAL(kind=dp),
DIMENSION(:),
INTENT(IN) :: energies
702 INTEGER,
INTENT(IN) :: iw
704 REAL(kind=dp) :: distance0, distance1, distance2, dvmax, &
707 cpassert(
ASSOCIATED(coords))
710 IF (i == neb_env%number_of_replica)
RETURN
712 SELECT CASE (neb_env%id_type)
716 CALL neb_replica_distance(coords=coords, i0=i, i=i - 1, distance=distance1, iw=iw, &
718 CALL neb_replica_distance(coords=coords, i0=i + 1, i=i, distance=distance2, iw=iw, &
720 tangent(:) = (coords%wrk(:, i) - coords%wrk(:, i - 1))/distance1 + &
721 (coords%wrk(:, i + 1) - coords%wrk(:, i))/distance2
722 CASE (do_it_neb, do_ci_neb, do_d_neb)
723 IF ((energies(i + 1) > energies(i)) .AND. (energies(i) > (energies(i - 1))))
THEN
724 tangent(:) = coords%wrk(:, i + 1) - coords%wrk(:, i)
725 ELSE IF ((energies(i + 1) < energies(i)) .AND. (energies(i) < (energies(i - 1))))
THEN
726 tangent(:) = coords%wrk(:, i) - coords%wrk(:, i - 1)
728 dvmax = max(abs(energies(i + 1) - energies(i)), abs(energies(i - 1) - energies(i)))
729 dvmin = min(abs(energies(i + 1) - energies(i)), abs(energies(i - 1) - energies(i)))
730 IF (energies(i + 1) >= energies(i - 1))
THEN
731 tangent(:) = (coords%wrk(:, i + 1) - coords%wrk(:, i))*dvmax + (coords%wrk(:, i) - coords%wrk(:, i - 1))*dvmin
733 tangent(:) = (coords%wrk(:, i + 1) - coords%wrk(:, i))*dvmin + (coords%wrk(:, i) - coords%wrk(:, i - 1))*dvmax
740 distance0 = norm2(tangent(:))
741 IF (distance0 /= 0.0_dp) tangent(:) = tangent(:)/distance0
742 END SUBROUTINE get_tangent
756 RECURSIVE SUBROUTINE get_neb_force(neb_env, tangent, coords, i, forces, tag, Mmatrix, &
758 TYPE(neb_type),
POINTER :: neb_env
759 REAL(kind=dp),
DIMENSION(:),
INTENT(IN) :: tangent
760 TYPE(neb_var_type),
POINTER :: coords
761 INTEGER,
INTENT(IN) :: i
762 TYPE(neb_var_type),
POINTER :: forces
763 INTEGER,
INTENT(IN),
OPTIONAL :: tag
764 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: mmatrix
765 INTEGER,
INTENT(IN) :: iw
767 INTEGER :: j, my_tag, nsize_wrk
768 REAL(kind=dp) :: distance1, distance2,
fac, tmp
769 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:) :: dtmp1, wrk
771 my_tag = neb_env%id_type
772 IF (
PRESENT(tag)) my_tag = tag
773 cpassert(
ASSOCIATED(forces))
774 cpassert(
ASSOCIATED(coords))
775 nsize_wrk = coords%size_wrk(1)
779 CASE (do_b_neb, do_it_neb, do_ci_neb, do_d_neb)
780 IF (i == neb_env%number_of_replica)
RETURN
785 CALL cite_reference(e2002)
789 ALLOCATE (wrk(nsize_wrk))
791 CALL neb_replica_distance(coords=coords, i0=i - 1, i=i, distance=distance1, iw=iw, &
793 tmp = distance1 - neb_env%avg_distance
794 neb_env%spring_energy = neb_env%spring_energy + 0.5_dp*neb_env%k*tmp**2
797 CALL cite_reference(elber1987)
800 ALLOCATE (dtmp1(nsize_wrk))
802 tmp = distance1 - neb_env%avg_distance
803 dtmp1(:) = 1.0_dp/distance1*(coords%wrk(:, i) - coords%wrk(:, i - 1))
804 wrk(:) = neb_env%k*tmp*dtmp1
805 forces%wrk(:, i) = forces%wrk(:, i) - wrk
806 forces%wrk(:, i - 1) = forces%wrk(:, i - 1) + wrk
808 fac = 1.0_dp/(neb_env%avg_distance*real(neb_env%number_of_replica - 1, kind=dp))
809 wrk(:) = neb_env%k*
fac*(coords%wrk(:, i) - coords%wrk(:, i - 1))
811 DO j = 2, neb_env%number_of_replica
812 CALL neb_replica_distance(coords=coords, i0=j - 1, i=j, distance=distance1, iw=iw, &
814 tmp = tmp + distance1 - neb_env%avg_distance
816 forces%wrk(:, i) = forces%wrk(:, i) + wrk*tmp
817 forces%wrk(:, i - 1) = forces%wrk(:, i - 1) - wrk*tmp
821 CALL cite_reference(jonsson1998)
822 wrk(:) = (coords%wrk(:, i + 1) - 2.0_dp*coords%wrk(:, i) + coords%wrk(:, i - 1))
823 tmp = neb_env%k*dot_product(wrk, tangent)
824 wrk(:) = forces%wrk(:, i) - dot_product_band(neb_env, forces%wrk(:, i), tangent, mmatrix)*tangent
825 forces%wrk(:, i) = wrk + tmp*tangent
828 CALL cite_reference(jonsson2000_1)
829 CALL neb_replica_distance(coords=coords, i0=i, i=i + 1, distance=distance1, iw=iw, &
831 CALL neb_replica_distance(coords=coords, i0=i - 1, i=i, distance=distance2, iw=iw, &
833 tmp = neb_env%k*(distance1 - distance2)
834 wrk(:) = forces%wrk(:, i) - dot_product_band(neb_env, forces%wrk(:, i), tangent, mmatrix)*tangent
835 forces%wrk(:, i) = wrk + tmp*tangent
838 CALL cite_reference(jonsson2000_2)
839 IF (neb_env%istep <= neb_env%nsteps_it .OR. i /= neb_env%nr_HE_image)
THEN
840 CALL get_neb_force(neb_env, tangent, coords, i, forces, do_it_neb, mmatrix, iw)
842 wrk(:) = forces%wrk(:, i)
843 tmp = -2.0_dp*dot_product_band(neb_env, wrk, tangent, mmatrix)
844 forces%wrk(:, i) = wrk + tmp*tangent
848 CALL cite_reference(wales2004)
849 ALLOCATE (dtmp1(nsize_wrk))
850 dtmp1(:) = forces%wrk(:, i) - dot_product_band(neb_env, forces%wrk(:, i), tangent, mmatrix)*tangent
851 forces%wrk(:, i) = dtmp1
853 dtmp1(:) = dtmp1(:)/tmp
856 wrk(:) = (coords%wrk(:, i + 1) - 2.0_dp*coords%wrk(:, i) + coords%wrk(:, i - 1))
857 tmp = dot_product(wrk, dtmp1)
858 dtmp1(:) = neb_env%k*(wrk(:) - tmp*dtmp1(:))
859 forces%wrk(:, i) = forces%wrk(:, i) + dtmp1(:)
863 END SUBROUTINE get_neb_force
876 FUNCTION dot_product_band(neb_env, array1, array2, array3)
RESULT(value)
877 TYPE(neb_type),
POINTER :: neb_env
878 REAL(kind=dp),
DIMENSION(:),
INTENT(IN) :: array1, array2
879 REAL(kind=dp),
DIMENSION(:, :),
INTENT(IN) :: array3
880 REAL(kind=dp) ::
value
885 IF (neb_env%use_colvar)
THEN
886 nsize_int = neb_env%nsize_int
887 check = ((
SIZE(array1) /=
SIZE(array2)) .OR. &
888 (
SIZE(array1) /= nsize_int) .OR. &
889 (
SIZE(array3) /= nsize_int*nsize_int))
892 value = dot_product(matmul(reshape(array3, [nsize_int, nsize_int]), array1), array2)
894 value = dot_product(array1, array2)
896 END FUNCTION dot_product_band
911 distances, number_of_replica)
912 LOGICAL,
INTENT(IN) :: rotate_frames
913 TYPE(particle_type),
DIMENSION(:),
OPTIONAL, &
914 POINTER :: particle_set
915 TYPE(neb_var_type),
POINTER :: coords, vels
916 INTEGER,
INTENT(IN) :: iw
917 REAL(kind=dp),
DIMENSION(:),
OPTIONAL :: distances
918 INTEGER,
INTENT(IN) :: number_of_replica
920 INTEGER :: i, k, kind
922 REAL(kind=dp) :: xtmp
923 REAL(kind=dp),
DIMENSION(3) :: tmp
924 REAL(kind=dp),
DIMENSION(3, 3) :: rot
930 DO i = 2, number_of_replica
933 IF (rotate_frames .AND. (coords%in_use == do_band_cartesian))
THEN
934 CALL rmsd3(particle_set, coords%xyz(:, i), coords%xyz(:, i - 1), iw, &
935 rotate=.true., rot=rot)
937 DO k = 1,
SIZE(vels%xyz, 1)/3
939 tmp = vels%xyz(kind + 1:kind + 3, i)
940 vels%xyz(kind + 1:kind + 3, i) = matmul(transpose(rot), tmp)
943 IF (
PRESENT(distances))
THEN
944 check =
SIZE(distances) == (number_of_replica - 1)
946 xtmp = dot_product(coords%wrk(:, i) - coords%wrk(:, i - 1), &
947 coords%wrk(:, i) - coords%wrk(:, i - 1))
948 distances(i - 1) = sqrt(xtmp)
964 coords, sline, distances)
966 LOGICAL,
INTENT(IN) :: reparametrize_frames
967 INTEGER,
INTENT(IN) :: spline_order
968 REAL(kind=dp),
INTENT(IN) :: smoothing
969 REAL(kind=dp),
DIMENSION(:, :),
POINTER :: coords, sline
970 REAL(kind=dp),
DIMENSION(:) :: distances
973 REAL(kind=dp) :: avg_distance, xtmp
974 REAL(kind=dp),
ALLOCATABLE,
DIMENSION(:, :) :: tmp_coords
976 IF (reparametrize_frames)
THEN
977 ALLOCATE (tmp_coords(
SIZE(coords, 1),
SIZE(coords, 2)))
978 tmp_coords(:, :) = coords
980 DO i = 2,
SIZE(coords, 2) - 1
981 coords(:, i) = tmp_coords(:, i)*(1.0_dp - 2.0_dp*smoothing) + &
982 tmp_coords(:, i - 1)*smoothing + tmp_coords(:, i + 1)*smoothing
984 sline = coords - tmp_coords + sline
985 tmp_coords(:, :) = coords
987 SELECT CASE (spline_order)
990 DO i = 2,
SIZE(coords, 2)
991 xtmp = dot_product(coords(:, i) - coords(:, i - 1), coords(:, i) - coords(:, i - 1))
992 distances(i - 1) = sqrt(xtmp)
994 avg_distance = sum(distances)/real(
SIZE(coords, 2) - 1, kind=dp)
996 DO i = 2,
SIZE(coords, 2) - 1
998 DO j = 1,
SIZE(coords, 2) - 1
999 xtmp = xtmp + distances(j)
1000 IF (xtmp > avg_distance*real(i - 1, kind=dp))
THEN
1001 xtmp = (xtmp - avg_distance*real(i - 1, kind=dp))/distances(j)
1002 coords(:, i) = (1.0_dp - xtmp)*tmp_coords(:, j + 1) + xtmp*tmp_coords(:, j)
1008 DO i = 2,
SIZE(coords, 2)
1009 xtmp = dot_product(coords(:, i) - coords(:, i - 1), coords(:, i) - coords(:, i - 1))
1010 distances(i - 1) = sqrt(xtmp)
1013 cpwarn(
"String Method: Spline order greater than 1 not implemented.")
1015 sline = coords - tmp_coords + sline
1016 DEALLOCATE (tmp_coords)
1030 TYPE(neb_type),
POINTER :: neb_env
1031 TYPE(neb_var_type),
POINTER :: dcoords, forces
1032 TYPE(cp_logger_type),
POINTER :: logger
1033 LOGICAL :: converged
1035 CHARACTER(LEN=3),
DIMENSION(4) :: labels
1037 REAL(kind=dp) :: max_dr, max_force, my_max_dr, &
1038 my_max_force, my_rms_dr, my_rms_force, &
1040 TYPE(section_vals_type),
POINTER :: cc_section
1042 NULLIFY (cc_section)
1043 cc_section => section_vals_get_subs_vals(neb_env%neb_section,
"CONVERGENCE_CONTROL")
1044 CALL section_vals_val_get(cc_section,
"MAX_DR", r_val=max_dr)
1045 CALL section_vals_val_get(cc_section,
"MAX_FORCE", r_val=max_force)
1046 CALL section_vals_val_get(cc_section,
"RMS_DR", r_val=rms_dr)
1047 CALL section_vals_val_get(cc_section,
"RMS_FORCE", r_val=rms_force)
1050 my_max_dr = maxval(abs(dcoords%wrk))
1051 my_max_force = maxval(abs(forces%wrk))
1052 my_rms_dr = sqrt(sum(dcoords%wrk*dcoords%wrk)/real(
SIZE(dcoords%wrk, 1)*
SIZE(dcoords%wrk, 2), kind=dp))
1053 my_rms_force = sqrt(sum(forces%wrk*forces%wrk)/real(
SIZE(forces%wrk, 1)*
SIZE(forces%wrk, 2), kind=dp))
1054 IF (my_max_dr < max_dr) labels(1) =
"YES"
1055 IF (my_max_force < max_force) labels(2) =
"YES"
1056 IF (my_rms_dr < rms_dr) labels(3) =
"YES"
1057 IF (my_rms_force < rms_force) labels(4) =
"YES"
1058 IF (all(labels ==
"YES")) converged = .true.
1060 iw = cp_print_key_unit_nr(logger, neb_env%neb_section,
"CONVERGENCE_INFO", &
1061 extension=
".nebLog")
1064 WRITE (iw, fmt=
'(A,A)')
' **************************************', &
1065 '*****************************************'
1066 WRITE (iw, fmt=
'(1X,A,2X,F16.10,5X,"[",F16.10,1X,"]",T76,"(",A,")")') &
1067 'RMS DISPLACEMENT =', my_rms_dr, rms_dr, labels(3), &
1068 'MAX DISPLACEMENT =', my_max_dr, max_dr, labels(1), &
1069 'RMS FORCE =', my_rms_force, rms_force, labels(4), &
1070 'MAX FORCE =', my_max_force, max_force, labels(2)
1071 WRITE (iw, fmt=
'(A,A)')
' **************************************', &
1072 '*****************************************'
1074 CALL cp_print_key_finished_output(iw, logger, neb_env%neb_section, &
static GRID_HOST_DEVICE double fac(const int i)
Factorial function, e.g. fac(5) = 5! = 120.
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public e2002
integer, save, public elber1987
integer, save, public jonsson2000_1
integer, save, public jonsson1998
integer, save, public jonsson2000_2
integer, save, public wales2004
evaluations of colvar for internal coordinates schemes
subroutine, public eval_colvar(force_env, coords, cvalues, bmatrix, massi, amatrix)
Computes the values of colvars and the Wilson matrix B and its invers A.
subroutine, public get_clv_force(force_env, forces, coords, nsize_xyz, nsize_int, cvalues, mmatrix)
Computes the forces in the frame of collective variables, and additional also the local metric tensor...
subroutine, public set_colvars_target(targets, force_env)
Set the value of target for constraints/restraints.
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,...
Utility routines to read data from files. Kept as close as possible to the old parser because.
subroutine, public parser_get_next_line(parser, nline, at_end)
Read the next input line and broadcast the input information. Skip (nline-1) lines and skip also all ...
Utility routines to read data from files. Kept as close as possible to the old parser because.
subroutine, public parser_release(parser)
releases the parser
subroutine, public parser_create(parser, file_name, unit_nr, para_env, end_section_label, separator_chars, comment_char, continuation_char, quote_char, section_char, parse_white_lines, initial_variables, apply_preprocessing)
Start a parser run. Initial variables allow to @SET stuff before opening the file.
interface to use cp2k as library
subroutine, public f_env_add_defaults(f_env_id, f_env, handle)
adds the default environments of the f_env to the stack of the defaults, and returns a new error and ...
subroutine, public get_energy(env_id, e_pot, ierr)
returns the energy of the last configuration calculated
subroutine, public get_pos(env_id, pos, n_el, ierr)
gets the positions of the particles
subroutine, public set_pos(env_id, new_pos, n_el, ierr)
sets the positions of the particles
subroutine, public f_env_rm_defaults(f_env, ierr, handle)
removes the default environments of the f_env to the stack of the defaults, and sets ierr accordingly...
subroutine, public get_force(env_id, frc, n_el, ierr)
gets the forces of the particles
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
performs geometry optimization
subroutine, public cp_geo_opt(force_env, globenv, eval_opt_geo, rm_restart_info)
Main driver to perform geometry optimization.
Define type storing the global information of a run. Keep the amount of stored data small....
Defines the basic variable types.
integer, parameter, public dp
integer, parameter, public default_string_length
integer, parameter, public default_path_length
Perform a molecular dynamics (MD) run using QUICKSTEP.
subroutine, public qs_mol_dyn(force_env, globenv, averages, rm_restart_info, hmc_e_initial, hmc_e_final, mdctrl)
Main driver module for Molecular Dynamics.
Interface to the message passing library MPI.
I/O Module for Nudged Elastic Band Calculation.
subroutine, public dump_replica_coordinates(particle_set, coords, i_rep, ienum, iw, use_colvar)
dump coordinates of a replica NEB
subroutine, public handle_band_file_names(rep_env, irep, n_rep, istep)
Handles the correct file names during a band calculation.
Module with utility to perform MD Nudged Elastic Band Calculation.
subroutine, public neb_initialize_velocity(vels, neb_section, particle_set, i_rep, iw, globenv, neb_env)
Initialize velocities of replica in an MD optimized algorithm within NEB.
Typo for Nudged Elastic Band Calculation.
Module with utility for Nudged Elastic Band Calculation.
subroutine, public neb_calc_energy_forces(rep_env, neb_env, coords, energies, forces, particle_set, output_unit)
Driver to compute energy and forces within a NEB, Based on the use of the replica_env.
subroutine, public build_replica_coords(neb_section, particle_set, coords, vels, neb_env, iw, globenv, para_env)
Constructs or Read the coordinates for all replica.
subroutine, public reorient_images(rotate_frames, particle_set, coords, vels, iw, distances, number_of_replica)
Reorient iteratively all images of the NEB chain in order to have always the smaller RMSD between two...
subroutine, public reparametrize_images(reparametrize_frames, spline_order, smoothing, coords, sline, distances)
Reparametrization of the replica for String Method with splines.
logical function, public check_convergence(neb_env, dcoords, forces, logger)
Checks for convergence criteria during a NEB run.
Define the data structure for the particle information.
Definition of physical constants:
real(kind=dp), parameter, public bohr
methods to setup replicas of the same system differing only by atom positions and velocities (as used...
subroutine, public rep_env_calc_e_f(rep_env, calc_f)
evaluates the forces
types used to handle many replica of the same system that differ only in atom positions,...
subroutine, public rep_env_sync(rep_env, vals)
sends the data from each replica to all the other on replica j/=i data from replica i overwrites val(...
Defines functions to perform rmsd in 3D.
subroutine, public rmsd3(particle_set, r, r0, output_unit, weights, my_val, rotate, transl, rot, drmsd3)
Computes the RMSD in 3D. Provides also derivatives.
type of a logger, at the moment it contains just a print level starting at which level it should be l...
contains the initially parsed file and the initial parallel environment
stores all the informations relevant to an mpi environment
keeps replicated information about the replicas