LCOV - code coverage report
Current view: top level - src/motion - neb_methods.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:85b8a9b) Lines: 92.9 % 211 196
Test Date: 2026-06-14 06:48:14 Functions: 100.0 % 3 3

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

Generated by: LCOV version 2.0-1