LCOV - code coverage report
Current view: top level - src - mode_selective.F (source / functions) Coverage Total Hit
Test: CP2K Regtests (git:71c3ab0) Lines: 92.0 % 666 613
Test Date: 2026-07-25 06:35:44 Functions: 90.0 % 10 9

            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 mdoe selective vibrational analysis
      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 08.2006)
      18              : !> \author Florian Schiffmann 08.2006
      19              : ! **************************************************************************************************
      20              : MODULE mode_selective
      21              :    USE cp_files,                        ONLY: close_file,&
      22              :                                               open_file
      23              :    USE cp_log_handling,                 ONLY: cp_get_default_logger,&
      24              :                                               cp_logger_get_default_io_unit,&
      25              :                                               cp_logger_type
      26              :    USE cp_output_handling,              ONLY: cp_print_key_finished_output,&
      27              :                                               cp_print_key_unit_nr
      28              :    USE cp_result_methods,               ONLY: get_results
      29              :    USE global_types,                    ONLY: global_environment_type
      30              :    USE input_constants,                 ONLY: ms_guess_atomic,&
      31              :                                               ms_guess_bfgs,&
      32              :                                               ms_guess_molden,&
      33              :                                               ms_guess_restart,&
      34              :                                               ms_guess_restart_vec
      35              :    USE input_section_types,             ONLY: section_vals_get,&
      36              :                                               section_vals_get_subs_vals,&
      37              :                                               section_vals_type,&
      38              :                                               section_vals_val_get
      39              :    USE kinds,                           ONLY: default_path_length,&
      40              :                                               default_string_length,&
      41              :                                               dp,&
      42              :                                               max_line_length
      43              :    USE mathlib,                         ONLY: diamat_all
      44              :    USE message_passing,                 ONLY: mp_para_env_type
      45              :    USE molden_utils,                    ONLY: write_vibrations_molden
      46              :    USE particle_types,                  ONLY: particle_type
      47              :    USE physcon,                         ONLY: bohr,&
      48              :                                               debye,&
      49              :                                               massunit,&
      50              :                                               vibfac
      51              :    USE replica_methods,                 ONLY: rep_env_calc_e_f
      52              :    USE replica_types,                   ONLY: replica_env_type
      53              :    USE util,                            ONLY: sort
      54              : #include "./base/base_uses.f90"
      55              : 
      56              :    IMPLICIT NONE
      57              : 
      58              :    PRIVATE
      59              :    CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mode_selective'
      60              :    LOGICAL, PARAMETER                   :: debug_this_module = .FALSE.
      61              : 
      62              :    TYPE ms_vib_type
      63              :       INTEGER                                  :: mat_size = -1
      64              :       INTEGER                                  :: select_id = -1
      65              :       INTEGER, DIMENSION(:), POINTER           :: inv_atoms => NULL()
      66              :       REAL(KIND=dp)                            :: eps(2) = 0.0_dp
      67              :       REAL(KIND=dp)                            :: sel_freq = 0.0_dp
      68              :       REAL(KIND=dp)                            :: low_freq = 0.0_dp
      69              :       REAL(KIND=dp), POINTER, DIMENSION(:, :)    :: b_vec => NULL()
      70              :       REAL(KIND=dp), POINTER, DIMENSION(:, :)    :: delta_vec => NULL()
      71              :       REAL(KIND=dp), POINTER, DIMENSION(:, :)    :: ms_force => NULL()
      72              :       REAL(KIND=dp), DIMENSION(:), POINTER     :: eig_bfgs => NULL()
      73              :       REAL(KIND=dp), DIMENSION(:), POINTER     :: f_range => NULL()
      74              :       REAL(KIND=dp), DIMENSION(:), POINTER     :: inv_range => NULL()
      75              :       REAL(KIND=dp), POINTER, DIMENSION(:)     :: step_b => NULL()
      76              :       REAL(KIND=dp), POINTER, DIMENSION(:)     :: step_r => NULL()
      77              :       REAL(KIND=dp), DIMENSION(:, :), POINTER  :: b_mat => NULL()
      78              :       REAL(KIND=dp), DIMENSION(:, :), POINTER  :: dip_deriv => NULL()
      79              :       REAL(KIND=dp), DIMENSION(:, :), POINTER  :: hes_bfgs => NULL()
      80              :       REAL(KIND=dp), DIMENSION(:, :), POINTER  :: s_mat => NULL()
      81              :       INTEGER                                  :: initial_guess = -1
      82              :    END TYPE ms_vib_type
      83              : 
      84              :    PUBLIC :: ms_vb_anal
      85              : 
      86              : CONTAINS
      87              : ! **************************************************************************************************
      88              : !> \brief Module performing a vibrational analysis
      89              : !> \param input ...
      90              : !> \param rep_env ...
      91              : !> \param para_env ...
      92              : !> \param globenv ...
      93              : !> \param particles ...
      94              : !> \param nrep ...
      95              : !> \param calc_intens ...
      96              : !> \param dx ...
      97              : !> \param output_unit ...
      98              : !> \param logger ...
      99              : !> \author Teodoro Laino 08.2006
     100              : ! **************************************************************************************************
     101           24 :    SUBROUTINE ms_vb_anal(input, rep_env, para_env, globenv, particles, &
     102              :                          nrep, calc_intens, dx, output_unit, logger)
     103              :       TYPE(section_vals_type), POINTER                   :: input
     104              :       TYPE(replica_env_type), POINTER                    :: rep_env
     105              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     106              :       TYPE(global_environment_type), POINTER             :: globenv
     107              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particles
     108              :       INTEGER                                            :: nrep
     109              :       LOGICAL                                            :: calc_intens
     110              :       REAL(KIND=dp)                                      :: dx
     111              :       INTEGER                                            :: output_unit
     112              :       TYPE(cp_logger_type), POINTER                      :: logger
     113              : 
     114              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'ms_vb_anal'
     115              : 
     116              :       CHARACTER(LEN=default_string_length)               :: description
     117              :       INTEGER                                            :: handle, i, ip1, j, natoms, ncoord
     118              :       LOGICAL                                            :: converged
     119           24 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: mass, pos0
     120           24 :       REAL(KIND=dp), DIMENSION(:, :), POINTER            :: tmp_deriv
     121           24 :       REAL(KIND=dp), DIMENSION(:, :, :), POINTER         :: tmp_dip
     122              :       TYPE(ms_vib_type)                                  :: ms_vib
     123              : 
     124           24 :       CALL timeset(routineN, handle)
     125           24 :       converged = .FALSE.
     126           24 :       natoms = SIZE(particles)
     127           24 :       ncoord = 3*natoms
     128           96 :       ALLOCATE (mass(3*natoms))
     129          886 :       DO i = 1, natoms
     130         3472 :          DO j = 1, 3
     131         2586 :             mass((i - 1)*3 + j) = particles(i)%atomic_kind%mass
     132         3448 :             mass((i - 1)*3 + j) = SQRT(mass((i - 1)*3 + j))
     133              :          END DO
     134              :       END DO
     135              :       ! Allocate working arrays
     136           96 :       ALLOCATE (ms_vib%delta_vec(ncoord, nrep))
     137           72 :       ALLOCATE (ms_vib%b_vec(ncoord, nrep))
     138           72 :       ALLOCATE (ms_vib%step_r(nrep))
     139           48 :       ALLOCATE (ms_vib%step_b(nrep))
     140           24 :       IF (calc_intens) THEN
     141           20 :          description = '[DIPOLE]'
     142           80 :          ALLOCATE (tmp_dip(nrep, 3, 2))
     143           60 :          ALLOCATE (ms_vib%dip_deriv(3, nrep))
     144              :       END IF
     145              :       CALL MS_initial_moves(para_env, nrep, input, globenv, ms_vib, &
     146              :                             particles, &
     147              :                             mass, &
     148              :                             dx, &
     149           24 :                             calc_intens, logger)
     150           24 :       ncoord = 3*natoms
     151           72 :       ALLOCATE (pos0(ncoord))
     152           96 :       ALLOCATE (ms_vib%ms_force(ncoord, nrep))
     153          886 :       DO i = 1, natoms
     154         3472 :          DO j = 1, 3
     155         3448 :             pos0((i - 1)*3 + j) = particles((i))%r(j)
     156              :          END DO
     157              :       END DO
     158          162 :       ncoord = 3*natoms
     159              :       DO
     160        23178 :          ms_vib%ms_force = HUGE(0.0_dp)
     161          336 :          DO i = 1, nrep
     162        23178 :             DO j = 1, ncoord
     163        23016 :                rep_env%r(j, i) = pos0(j) + ms_vib%step_r(i)*ms_vib%delta_vec(j, i)
     164              :             END DO
     165              :          END DO
     166          162 :          CALL rep_env_calc_e_f(rep_env, calc_f=.TRUE.)
     167              : 
     168          336 :          DO i = 1, nrep
     169          174 :             IF (calc_intens) THEN
     170              :                CALL get_results(results=rep_env%results(i)%results, &
     171              :                                 description=description, &
     172          150 :                                 n_rep=ip1)
     173              :                CALL get_results(results=rep_env%results(i)%results, &
     174              :                                 description=description, &
     175              :                                 values=tmp_dip(i, :, 1), &
     176          150 :                                 nval=ip1)
     177              :             END IF
     178        23178 :             DO j = 1, ncoord
     179        23016 :                ms_vib%ms_force(j, i) = rep_env%f(j, i)
     180              :             END DO
     181              :          END DO
     182          336 :          DO i = 1, nrep
     183        23178 :             DO j = 1, ncoord
     184        23016 :                rep_env%r(j, i) = pos0(j) - ms_vib%step_r(i)*ms_vib%delta_vec(j, i)
     185              :             END DO
     186              :          END DO
     187          162 :          CALL rep_env_calc_e_f(rep_env, calc_f=.TRUE.)
     188          162 :          IF (calc_intens) THEN
     189          300 :             DO i = 1, nrep
     190              :                CALL get_results(results=rep_env%results(i)%results, &
     191              :                                 description=description, &
     192          150 :                                 n_rep=ip1)
     193              :                CALL get_results(results=rep_env%results(i)%results, &
     194              :                                 description=description, &
     195              :                                 values=tmp_dip(i, :, 2), &
     196          150 :                                 nval=ip1)
     197          900 :                ms_vib%dip_deriv(:, ms_vib%mat_size + i) = (tmp_dip(i, :, 1) - tmp_dip(i, :, 2))/(2*ms_vib%step_b(i))
     198              :             END DO
     199              :          END IF
     200              : 
     201              :          CALL evaluate_H_update_b(rep_env, ms_vib, input, nrep, &
     202              :                                   particles, &
     203              :                                   mass, &
     204              :                                   converged, &
     205              :                                   dx, calc_intens, &
     206          162 :                                   output_unit, logger)
     207          162 :          IF (converged) EXIT
     208          162 :          IF (calc_intens) THEN
     209          390 :             ALLOCATE (tmp_deriv(3, ms_vib%mat_size))
     210         3730 :             tmp_deriv = ms_vib%dip_deriv
     211          130 :             DEALLOCATE (ms_vib%dip_deriv)
     212          390 :             ALLOCATE (ms_vib%dip_deriv(3, ms_vib%mat_size + nrep))
     213         3730 :             ms_vib%dip_deriv(:, 1:ms_vib%mat_size) = tmp_deriv(:, 1:ms_vib%mat_size)
     214          130 :             DEALLOCATE (tmp_deriv)
     215              :          END IF
     216              :       END DO
     217           24 :       DEALLOCATE (ms_vib%ms_force)
     218           24 :       DEALLOCATE (pos0)
     219           24 :       DEALLOCATE (ms_vib%step_r)
     220           24 :       DEALLOCATE (ms_vib%step_b)
     221           24 :       DEALLOCATE (ms_vib%b_vec)
     222           24 :       DEALLOCATE (ms_vib%delta_vec)
     223           24 :       DEALLOCATE (mass)
     224           24 :       DEALLOCATE (ms_vib%b_mat)
     225           24 :       DEALLOCATE (ms_vib%s_mat)
     226           24 :       IF (ms_vib%select_id == 3) THEN
     227            8 :          DEALLOCATE (ms_vib%inv_atoms)
     228              :       END IF
     229           24 :       IF (ASSOCIATED(ms_vib%eig_bfgs)) THEN
     230            0 :          DEALLOCATE (ms_vib%eig_bfgs)
     231              :       END IF
     232           24 :       IF (ASSOCIATED(ms_vib%hes_bfgs)) THEN
     233            0 :          DEALLOCATE (ms_vib%hes_bfgs)
     234              :       END IF
     235           24 :       IF (calc_intens) THEN
     236           20 :          DEALLOCATE (ms_vib%dip_deriv)
     237           20 :          DEALLOCATE (tmp_dip)
     238              :       END IF
     239           24 :       CALL timestop(handle)
     240           72 :    END SUBROUTINE ms_vb_anal
     241              : ! **************************************************************************************************
     242              : !> \brief Generates the first displacement vector for a mode selctive vibrational
     243              : !>      analysis. At the moment this is a random number for selected atoms
     244              : !> \param para_env ...
     245              : !> \param nrep ...
     246              : !> \param input ...
     247              : !> \param globenv ...
     248              : !> \param ms_vib ...
     249              : !> \param particles ...
     250              : !> \param mass ...
     251              : !> \param dx ...
     252              : !> \param calc_intens ...
     253              : !> \param logger ...
     254              : !> \author Florian Schiffmann 11.2007
     255              : ! **************************************************************************************************
     256           24 :    SUBROUTINE MS_initial_moves(para_env, nrep, input, globenv, ms_vib, particles, &
     257           24 :                                mass, dx, &
     258              :                                calc_intens, logger)
     259              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     260              :       INTEGER                                            :: nrep
     261              :       TYPE(section_vals_type), POINTER                   :: input
     262              :       TYPE(global_environment_type), POINTER             :: globenv
     263              :       TYPE(ms_vib_type)                                  :: ms_vib
     264              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particles
     265              :       REAL(Kind=dp), DIMENSION(:)                        :: mass
     266              :       REAL(KIND=dp)                                      :: dx
     267              :       LOGICAL                                            :: calc_intens
     268              :       TYPE(cp_logger_type), POINTER                      :: logger
     269              : 
     270              :       CHARACTER(len=*), PARAMETER                        :: routineN = 'MS_initial_moves'
     271              : 
     272              :       INTEGER                                            :: guess, handle, i, j, jj, k, m, &
     273              :                                                             n_rep_val, natoms, ncoord
     274           24 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: map_atoms
     275           24 :       INTEGER, DIMENSION(:), POINTER                     :: tmplist
     276              :       LOGICAL                                            :: do_involved_atoms, ionode
     277              :       REAL(KIND=dp)                                      :: my_val, norm
     278              :       TYPE(section_vals_type), POINTER                   :: involved_at_section, ms_vib_section
     279              : 
     280           24 :       CALL timeset(routineN, handle)
     281           24 :       NULLIFY (ms_vib%eig_bfgs, ms_vib%f_range, ms_vib%hes_bfgs, ms_vib%inv_range)
     282           24 :       ms_vib_section => section_vals_get_subs_vals(input, "VIBRATIONAL_ANALYSIS%MODE_SELECTIVE")
     283           24 :       CALL section_vals_val_get(ms_vib_section, "INITIAL_GUESS", i_val=guess)
     284           24 :       CALL section_vals_val_get(ms_vib_section, "EPS_MAX_VAL", r_val=ms_vib%eps(1))
     285           24 :       CALL section_vals_val_get(ms_vib_section, "EPS_NORM", r_val=ms_vib%eps(2))
     286           24 :       CALL section_vals_val_get(ms_vib_section, "RANGE", n_rep_val=n_rep_val)
     287           24 :       ms_vib%select_id = 0
     288           24 :       IF (n_rep_val /= 0) THEN
     289            2 :          CALL section_vals_val_get(ms_vib_section, "RANGE", r_vals=ms_vib%f_range)
     290            2 :          IF (ms_vib%f_range(1) > ms_vib%f_range(2)) THEN
     291            0 :             my_val = ms_vib%f_range(2)
     292            0 :             ms_vib%f_range(2) = ms_vib%f_range(1)
     293            0 :             ms_vib%f_range(1) = my_val
     294              :          END IF
     295            2 :          ms_vib%select_id = 2
     296              :       END IF
     297           24 :       CALL section_vals_val_get(ms_vib_section, "FREQUENCY", r_val=ms_vib%sel_freq)
     298           24 :       CALL section_vals_val_get(ms_vib_section, "LOWEST_FREQUENCY", r_val=ms_vib%low_freq)
     299           24 :       IF (ms_vib%sel_freq > 0._dp) ms_vib%select_id = 1
     300           24 :       involved_at_section => section_vals_get_subs_vals(ms_vib_section, "INVOLVED_ATOMS")
     301           24 :       CALL section_vals_get(involved_at_section, explicit=do_involved_atoms)
     302           24 :       IF (do_involved_atoms) THEN
     303            8 :          CALL section_vals_val_get(involved_at_section, "INVOLVED_ATOMS", n_rep_val=n_rep_val)
     304            8 :          jj = 0
     305           16 :          DO k = 1, n_rep_val
     306            8 :             CALL section_vals_val_get(involved_at_section, "INVOLVED_ATOMS", i_rep_val=k, i_vals=tmplist)
     307           32 :             DO j = 1, SIZE(tmplist)
     308           24 :                jj = jj + 1
     309              :             END DO
     310              :          END DO
     311            8 :          IF (jj >= 1) THEN
     312            8 :             natoms = jj
     313           24 :             ALLOCATE (ms_vib%inv_atoms(natoms))
     314            8 :             jj = 0
     315           16 :             DO m = 1, n_rep_val
     316            8 :                CALL section_vals_val_get(involved_at_section, "INVOLVED_ATOMS", i_rep_val=m, i_vals=tmplist)
     317           32 :                DO j = 1, SIZE(tmplist)
     318           24 :                   ms_vib%inv_atoms(j) = tmplist(j)
     319              :                END DO
     320              :             END DO
     321            8 :             ms_vib%select_id = 3
     322              :          END IF
     323            8 :          CALL section_vals_val_get(involved_at_section, "RANGE", n_rep_val=n_rep_val)
     324            8 :          IF (n_rep_val /= 0) THEN
     325            0 :             CALL section_vals_val_get(involved_at_section, "RANGE", r_vals=ms_vib%inv_range)
     326            0 :             IF (ms_vib%inv_range(1) > ms_vib%inv_range(2)) THEN
     327            0 :                ms_vib%inv_range(2) = my_val
     328            0 :                ms_vib%inv_range(2) = ms_vib%inv_range(1)
     329            0 :                ms_vib%inv_range(1) = my_val
     330              :             END IF
     331              :          END IF
     332              :       END IF
     333           24 :       IF (ms_vib%select_id == 0) THEN
     334            0 :          CPABORT("no frequency, range or involved atoms specified ")
     335              :       END IF
     336           24 :       ionode = para_env%is_source()
     337           12 :       SELECT CASE (guess)
     338              :       CASE (ms_guess_atomic)
     339           12 :          ms_vib%initial_guess = 1
     340           12 :          CALL section_vals_val_get(ms_vib_section, "ATOMS", n_rep_val=n_rep_val)
     341           12 :          jj = 0
     342           22 :          DO k = 1, n_rep_val
     343           10 :             CALL section_vals_val_get(ms_vib_section, "ATOMS", i_rep_val=k, i_vals=tmplist)
     344           42 :             DO j = 1, SIZE(tmplist)
     345           30 :                jj = jj + 1
     346              :             END DO
     347              :          END DO
     348           12 :          IF (jj < 1) THEN
     349            2 :             natoms = SIZE(particles)
     350            6 :             ALLOCATE (map_atoms(natoms))
     351           14 :             DO j = 1, natoms
     352           14 :                map_atoms(j) = j
     353              :             END DO
     354              :          ELSE
     355           10 :             natoms = jj
     356           30 :             ALLOCATE (map_atoms(natoms))
     357           10 :             jj = 0
     358           20 :             DO m = 1, n_rep_val
     359           10 :                CALL section_vals_val_get(ms_vib_section, "ATOMS", i_rep_val=m, i_vals=tmplist)
     360           40 :                DO j = 1, SIZE(tmplist)
     361           30 :                   map_atoms(j) = tmplist(j)
     362              :                END DO
     363              :             END DO
     364              :          END IF
     365              : 
     366              :          ! apply random displacement along the mass weighted nuclear cartesian coordinates
     367          526 :          ms_vib%b_vec = 0._dp
     368          526 :          ms_vib%delta_vec = 0._dp
     369           12 :          jj = 0
     370              : 
     371           28 :          DO i = 1, nrep
     372           56 :             DO j = 1, natoms
     373          176 :                DO k = 1, 3
     374          120 :                   jj = (map_atoms(j) - 1)*3 + k
     375          160 :                   ms_vib%b_vec(jj, i) = ABS(globenv%gaussian_rng_stream%next())
     376              :                END DO
     377              :             END DO
     378          514 :             norm = NORM2(ms_vib%b_vec(:, i))
     379          526 :             ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
     380              :          END DO
     381              : 
     382           12 :          IF (nrep > 1) THEN
     383           44 :             DO k = 1, 10
     384          124 :                DO j = 1, nrep
     385          280 :                   DO i = 1, nrep
     386          240 :                      IF (i /= j) THEN
     387              :                         ms_vib%b_vec(:, j) = &
     388         1520 :                            ms_vib%b_vec(:, j) - DOT_PRODUCT(ms_vib%b_vec(:, j), ms_vib%b_vec(:, i))*ms_vib%b_vec(:, i)
     389              :                         ms_vib%b_vec(:, j) = &
     390         1520 :                            ms_vib%b_vec(:, j)/NORM2(ms_vib%b_vec(:, j))
     391              :                      END IF
     392              :                   END DO
     393              :                END DO
     394              :             END DO
     395              :          END IF
     396              : 
     397           12 :          ms_vib%mat_size = 0
     398          474 :          DO i = 1, SIZE(ms_vib%b_vec, 1)
     399          972 :             ms_vib%delta_vec(i, :) = ms_vib%b_vec(i, :)/mass(i)
     400              :          END DO
     401              :       CASE (ms_guess_bfgs)
     402              : 
     403            4 :          ms_vib%initial_guess = 2
     404            4 :          CALL bfgs_guess(ms_vib_section, ms_vib, particles, mass, para_env, nrep)
     405            4 :          ms_vib%mat_size = 0
     406              : 
     407              :       CASE (ms_guess_restart_vec)
     408              : 
     409            4 :          ms_vib%initial_guess = 3
     410              :          ncoord = 3*SIZE(particles)
     411            4 :          CALL rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
     412              : 
     413            4 :          ms_vib%mat_size = 0
     414              :       CASE (ms_guess_restart)
     415            0 :          ms_vib%initial_guess = 4
     416              :          ncoord = 3*SIZE(particles)
     417            0 :          CALL rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
     418              : 
     419              :       CASE (ms_guess_molden)
     420            4 :          ms_vib%initial_guess = 5
     421            4 :          ncoord = 3*SIZE(particles)
     422            4 :          CALL molden_guess(ms_vib_section, input, para_env, ms_vib, mass, ncoord, nrep, logger)
     423           28 :          ms_vib%mat_size = 0
     424              :       END SELECT
     425         5324 :       CALL para_env%bcast(ms_vib%b_vec)
     426         5324 :       CALL para_env%bcast(ms_vib%delta_vec)
     427           52 :       DO i = 1, nrep
     428         2650 :          ms_vib%step_r(i) = dx/NORM2(ms_vib%delta_vec(:, i))
     429         2674 :          ms_vib%step_b(i) = NORM2(ms_vib%step_r(i)*ms_vib%b_vec(:, i))
     430              :       END DO
     431           24 :       CALL timestop(handle)
     432              : 
     433           48 :    END SUBROUTINE MS_initial_moves
     434              : 
     435              : ! **************************************************************************************************
     436              : !> \brief ...
     437              : !> \param ms_vib_section ...
     438              : !> \param ms_vib ...
     439              : !> \param particles ...
     440              : !> \param mass ...
     441              : !> \param para_env ...
     442              : !> \param nrep ...
     443              : !> \author Florian Schiffmann 11.2007
     444              : ! **************************************************************************************************
     445            4 :    SUBROUTINE bfgs_guess(ms_vib_section, ms_vib, particles, mass, para_env, nrep)
     446              : 
     447              :       TYPE(section_vals_type), POINTER                   :: ms_vib_section
     448              :       TYPE(ms_vib_type)                                  :: ms_vib
     449              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particles
     450              :       REAL(Kind=dp), DIMENSION(:)                        :: mass
     451              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     452              :       INTEGER                                            :: nrep
     453              : 
     454              :       CHARACTER(LEN=default_path_length)                 :: hes_filename
     455              :       INTEGER                                            :: hesunit, i, istat, j, jj, k, natoms, &
     456              :                                                             ncoord, output_unit, stat
     457            4 :       INTEGER, DIMENSION(:), POINTER                     :: tmplist
     458              :       REAL(KIND=dp)                                      :: my_val, norm
     459            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: tmp
     460              :       TYPE(cp_logger_type), POINTER                      :: logger
     461              : 
     462            8 :       logger => cp_get_default_logger()
     463            4 :       output_unit = cp_logger_get_default_io_unit(logger)
     464              : 
     465            4 :       natoms = SIZE(particles)
     466            4 :       ncoord = 3*natoms
     467              : 
     468           16 :       ALLOCATE (ms_vib%hes_bfgs(ncoord, ncoord))
     469           12 :       ALLOCATE (ms_vib%eig_bfgs(ncoord))
     470              : 
     471            4 :       IF (para_env%is_source()) THEN
     472            2 :          CALL section_vals_val_get(ms_vib_section, "RESTART_FILE_NAME", c_val=hes_filename)
     473            2 :          IF (hes_filename == "") hes_filename = "HESSIAN"
     474              :          CALL open_file(file_name=hes_filename, file_status="OLD", &
     475            2 :                         file_form="UNFORMATTED", file_action="READ", unit_number=hesunit)
     476            6 :          ALLOCATE (tmp(ncoord))
     477            6 :          ALLOCATE (tmplist(ncoord))
     478              : 
     479              :          ! should use the cp_fm_read_unformatted...
     480            2 :          istat = 0
     481          356 :          DO i = 1, ncoord
     482          354 :             READ (UNIT=hesunit, IOSTAT=stat) ms_vib%hes_bfgs(:, i)
     483          356 :             istat = istat + stat
     484              :          END DO
     485            2 :          CALL close_file(hesunit)
     486            2 :          IF (output_unit > 0) THEN
     487            2 :             IF (istat /= 0) THEN
     488            0 :                WRITE (output_unit, FMT="(/,T2,A)") "**  Error while reading HESSIAN **"
     489              :             ELSE
     490              :                WRITE (output_unit, FMT="(/,T2,A)") &
     491            2 :                   "*** Initial Hessian has been read successfully ***"
     492              :             END IF
     493              :          END IF
     494          356 :          DO i = 1, ncoord
     495        63014 :             DO j = 1, ncoord
     496        63012 :                ms_vib%hes_bfgs(i, j) = ms_vib%hes_bfgs(i, j)/(mass(i)*mass(j))
     497              :             END DO
     498              :          END DO
     499              : 
     500            2 :          CALL diamat_all(ms_vib%hes_bfgs, ms_vib%eig_bfgs)
     501            2 :          tmp(:) = 0._dp
     502            2 :          IF (ms_vib%select_id == 1) my_val = (ms_vib%sel_freq/vibfac)**2/massunit
     503            2 :          IF (ms_vib%select_id == 2) my_val = (((ms_vib%f_range(2) + ms_vib%f_range(1))*0.5_dp)/vibfac)**2/massunit
     504            2 :          IF (ms_vib%select_id == 1 .OR. ms_vib%select_id == 2) THEN
     505          178 :             DO i = 1, ncoord
     506          178 :                tmp(i) = ABS(my_val - ms_vib%eig_bfgs(i))
     507              :             END DO
     508            1 :          ELSE IF (ms_vib%select_id == 3) THEN
     509          178 :             DO i = 1, ncoord
     510          531 :                DO j = 1, SIZE(ms_vib%inv_atoms)
     511         1593 :                   DO k = 1, 3
     512         1062 :                      jj = (ms_vib%inv_atoms(j) - 1)*3 + k
     513         1416 :                      tmp(i) = tmp(i) + SQRT(ms_vib%hes_bfgs(jj, i)**2)
     514              :                   END DO
     515              :                END DO
     516          178 :                IF ((SIGN(1._dp, ms_vib%eig_bfgs(i))*SQRT(ABS(ms_vib%eig_bfgs(i))*massunit)*vibfac) <= 400._dp) tmp(i) = 0._dp
     517              :             END DO
     518          178 :             tmp(:) = -tmp(:)
     519              :          END IF
     520            2 :          CALL sort(tmp, ncoord, tmplist)
     521            4 :          DO i = 1, nrep
     522          356 :             ms_vib%b_vec(:, i) = ms_vib%hes_bfgs(:, tmplist(i))
     523          356 :             norm = NORM2(ms_vib%b_vec(:, i))
     524          358 :             ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
     525              :          END DO
     526          356 :          DO i = 1, SIZE(ms_vib%b_vec, 1)
     527          710 :             ms_vib%delta_vec(i, :) = ms_vib%b_vec(i, :)/mass(i)
     528              :          END DO
     529            2 :          DEALLOCATE (tmp)
     530            2 :          DEALLOCATE (tmplist)
     531              :       END IF
     532              : 
     533         1428 :       CALL para_env%bcast(ms_vib%b_vec)
     534         1428 :       CALL para_env%bcast(ms_vib%delta_vec)
     535              : 
     536            4 :       DEALLOCATE (ms_vib%hes_bfgs)
     537            4 :       DEALLOCATE (ms_vib%eig_bfgs)
     538            4 :       ms_vib%mat_size = 0
     539              : 
     540            4 :    END SUBROUTINE bfgs_guess
     541              : 
     542              : ! **************************************************************************************************
     543              : !> \brief ...
     544              : !> \param ms_vib_section ...
     545              : !> \param para_env ...
     546              : !> \param ms_vib ...
     547              : !> \param mass ...
     548              : !> \param ionode ...
     549              : !> \param particles ...
     550              : !> \param nrep ...
     551              : !> \param calc_intens ...
     552              : !> \author Florian Schiffmann 11.2007
     553              : ! **************************************************************************************************
     554            4 :    SUBROUTINE rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
     555              : 
     556              :       TYPE(section_vals_type), POINTER                   :: ms_vib_section
     557              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     558              :       TYPE(ms_vib_type)                                  :: ms_vib
     559              :       REAL(Kind=dp), DIMENSION(:)                        :: mass
     560              :       LOGICAL                                            :: ionode
     561              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particles
     562              :       INTEGER                                            :: nrep
     563              :       LOGICAL                                            :: calc_intens
     564              : 
     565              :       CHARACTER(LEN=default_path_length)                 :: ms_filename
     566              :       INTEGER                                            :: hesunit, i, j, mat, natoms, ncoord, &
     567              :                                                             output_unit, stat, statint
     568            4 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ind
     569            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenval
     570            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: approx_H
     571              :       TYPE(cp_logger_type), POINTER                      :: logger
     572              : 
     573            4 :       logger => cp_get_default_logger()
     574            4 :       output_unit = cp_logger_get_default_io_unit(logger)
     575              : 
     576            4 :       natoms = SIZE(particles)
     577            4 :       ncoord = 3*natoms
     578            4 :       IF (calc_intens) THEN
     579            4 :          DEALLOCATE (ms_vib%dip_deriv)
     580              :       END IF
     581              : 
     582            4 :       IF (ionode) THEN
     583              : 
     584            2 :          CALL section_vals_val_get(ms_vib_section, "RESTART_FILE_NAME", c_val=ms_filename)
     585            2 :          IF (ms_filename == "") ms_filename = "MS_RESTART"
     586              :          CALL open_file(file_name=ms_filename, &
     587              :                         file_status="UNKNOWN", &
     588              :                         file_form="UNFORMATTED", &
     589              :                         file_action="READ", &
     590            2 :                         unit_number=hesunit)
     591            2 :          READ (UNIT=hesunit, IOSTAT=stat) mat
     592            2 :          CPASSERT(stat == 0)
     593            2 :          ms_vib%mat_size = mat
     594              :       END IF
     595            4 :       CALL para_env%bcast(ms_vib%mat_size)
     596           16 :       ALLOCATE (ms_vib%b_mat(ncoord, ms_vib%mat_size))
     597           12 :       ALLOCATE (ms_vib%s_mat(ncoord, ms_vib%mat_size))
     598            4 :       IF (calc_intens) THEN
     599           12 :          ALLOCATE (ms_vib%dip_deriv(3, ms_vib%mat_size + nrep))
     600              :       END IF
     601            4 :       IF (ionode) THEN
     602            2 :          statint = 0
     603         3384 :          READ (UNIT=hesunit) ms_vib%b_mat
     604         3384 :          READ (UNIT=hesunit, IOSTAT=stat) ms_vib%s_mat
     605            2 :          IF (stat /= 0 .AND. output_unit > 0) THEN
     606            0 :             WRITE (output_unit, FMT="(/,T2,A)") "**  Error while reading MS_RESTART **"
     607              :          END IF
     608            2 :          IF (calc_intens) THEN
     609            2 :             READ (UNIT=hesunit, IOSTAT=statint) ms_vib%dip_deriv(:, 1:ms_vib%mat_size)
     610            2 :             IF (statint /= 0 .AND. output_unit > 0) WRITE (output_unit, FMT="(/,T2,A)") "**  Error while reading MS_RESTART,", &
     611            0 :                "intensities are requested but not present in restart file **"
     612              :          END IF
     613            2 :          CALL close_file(hesunit)
     614            2 :          IF (stat == 0 .AND. statint == 0 .AND. output_unit > 0) THEN
     615            2 :             WRITE (output_unit, FMT="(/,T2,A)") "*** MS_RESTART has been read successfully ***"
     616              :          END IF
     617              :       END IF
     618        13532 :       CALL para_env%bcast(ms_vib%b_mat)
     619        13532 :       CALL para_env%bcast(ms_vib%s_mat)
     620          340 :       IF (calc_intens) CALL para_env%bcast(ms_vib%dip_deriv)
     621           16 :       ALLOCATE (approx_H(ms_vib%mat_size, ms_vib%mat_size))
     622           12 :       ALLOCATE (eigenval(ms_vib%mat_size))
     623           12 :       ALLOCATE (ind(ms_vib%mat_size))
     624              : 
     625              :       CALL dgemm('T', 'N', ms_vib%mat_size, ms_vib%mat_size, SIZE(ms_vib%s_mat, 1), 1._dp, ms_vib%b_mat, SIZE(ms_vib%b_mat, 1), &
     626            4 :                  ms_vib%s_mat, SIZE(ms_vib%s_mat, 1), 0._dp, approx_H, ms_vib%mat_size)
     627            4 :       CALL diamat_all(approx_H, eigenval)
     628              : 
     629            4 :       CALL select_vector(ms_vib, nrep, mass, ncoord, approx_H, eigenval, ind, ms_vib%b_vec)
     630            4 :       IF (ms_vib%initial_guess /= 4) THEN
     631              : 
     632          716 :          ms_vib%b_vec = 0._dp
     633            8 :          DO i = 1, nrep
     634           42 :             DO j = 1, ms_vib%mat_size
     635         6768 :                ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i) + approx_H(j, ind(i))*ms_vib%b_mat(:, j)
     636              :             END DO
     637         1424 :             ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/NORM2(ms_vib%b_vec(:, i))
     638              :          END DO
     639              : 
     640            4 :          DEALLOCATE (ms_vib%s_mat)
     641            4 :          DEALLOCATE (ms_vib%b_mat)
     642            4 :          IF (calc_intens) THEN
     643            4 :             DEALLOCATE (ms_vib%dip_deriv)
     644           12 :             ALLOCATE (ms_vib%dip_deriv(3, nrep))
     645              :          END IF
     646              :       END IF
     647            4 :       DEALLOCATE (approx_H)
     648            4 :       DEALLOCATE (eigenval)
     649            4 :       DEALLOCATE (ind)
     650            8 :       DO i = 1, nrep
     651          716 :          ms_vib%delta_vec(:, i) = ms_vib%b_vec(:, i)/mass(:)
     652              :       END DO
     653              : 
     654            4 :    END SUBROUTINE rest_guess
     655              : 
     656              : ! **************************************************************************************************
     657              : !> \brief ...
     658              : !> \param ms_vib_section ...
     659              : !> \param input ...
     660              : !> \param para_env ...
     661              : !> \param ms_vib ...
     662              : !> \param mass ...
     663              : !> \param ncoord ...
     664              : !> \param nrep ...
     665              : !> \param logger ...
     666              : !> \author Florian Schiffmann 11.2007
     667              : ! **************************************************************************************************
     668            4 :    SUBROUTINE molden_guess(ms_vib_section, input, para_env, ms_vib, mass, ncoord, nrep, logger)
     669              :       TYPE(section_vals_type), POINTER                   :: ms_vib_section, input
     670              :       TYPE(mp_para_env_type), POINTER                    :: para_env
     671              :       TYPE(ms_vib_type)                                  :: ms_vib
     672              :       REAL(Kind=dp), DIMENSION(:)                        :: mass
     673              :       INTEGER                                            :: ncoord, nrep
     674              :       TYPE(cp_logger_type), POINTER                      :: logger
     675              : 
     676              :       CHARACTER(LEN=2)                                   :: at_name
     677              :       CHARACTER(LEN=default_path_length)                 :: ms_filename
     678              :       CHARACTER(LEN=max_line_length)                     :: info
     679              :       INTEGER                                            :: i, istat, iw, j, jj, k, nvibs, &
     680              :                                                             output_molden, output_unit, stat
     681            4 :       INTEGER, DIMENSION(:), POINTER                     :: tmplist
     682              :       LOGICAL                                            :: reading_vib
     683              :       REAL(KIND=dp)                                      :: my_val, norm
     684            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: freq, tmp
     685            4 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: modes
     686            8 :       REAL(KIND=dp), DIMENSION(3, ncoord/3)              :: pos
     687              : 
     688            8 :       output_unit = cp_logger_get_default_io_unit(logger)
     689              : 
     690            4 :       CALL section_vals_val_get(ms_vib_section, "RESTART_FILE_NAME", c_val=ms_filename)
     691            4 :       IF (ms_filename == "") output_molden = &
     692              :          cp_print_key_unit_nr(logger, input, "VIBRATIONAL_ANALYSIS%PRINT%MOLDEN_VIB", &
     693              :                               extension=".mol", file_status='UNKNOWN', &
     694            0 :                               file_action="READ")
     695            4 :       IF (para_env%is_source()) THEN
     696              : 
     697            2 :          IF (ms_filename == "") THEN
     698            0 :             iw = output_molden
     699              :          ELSE
     700              :             CALL open_file(file_name=TRIM(ms_filename), &
     701              :                            file_status="UNKNOWN", &
     702              :                            file_form="FORMATTED", &
     703              :                            file_action="READ", &
     704            2 :                            unit_number=iw)
     705              :          END IF
     706            2 :          info = ""
     707            2 :          READ (iw, *) info
     708            2 :          READ (iw, *) info
     709            2 :          istat = 0
     710            2 :          nvibs = 0
     711            2 :          reading_vib = .FALSE.
     712          140 :          DO
     713          142 :             READ (iw, *, IOSTAT=stat) info
     714          142 :             istat = istat + stat
     715          142 :             IF (TRIM(ADJUSTL(info)) == "[FR-COORD]") EXIT
     716              : 
     717          140 :             CPASSERT(stat == 0)
     718              : 
     719          140 :             IF (reading_vib) nvibs = nvibs + 1
     720          140 :             IF (TRIM(ADJUSTL(info)) == "[FREQ]") reading_vib = .TRUE.
     721              :          END DO
     722            2 :          REWIND (iw)
     723            2 :          istat = 0
     724            2 :          READ (iw, *, IOSTAT=stat) info
     725            2 :          istat = istat + stat
     726            2 :          READ (iw, *, IOSTAT=stat) info
     727            2 :          istat = istat + stat
     728              :          ! Skip [Atoms] section
     729          118 :          DO
     730          120 :             READ (iw, *, IOSTAT=stat) info
     731          120 :             istat = istat + stat
     732          120 :             CPASSERT(stat == 0)
     733          120 :             IF (TRIM(ADJUSTL(info)) == "[FREQ]") EXIT
     734              :          END DO
     735              :          ! Read frequencies and modes
     736            6 :          ALLOCATE (freq(nvibs))
     737            8 :          ALLOCATE (modes(ncoord, nvibs))
     738              : 
     739           22 :          DO i = 1, nvibs
     740           20 :             READ (iw, *, IOSTAT=stat) freq(i)
     741           22 :             istat = istat + stat
     742              :          END DO
     743            2 :          READ (iw, *) info
     744          120 :          DO i = 1, ncoord/3
     745          118 :             READ (iw, *, IOSTAT=stat) at_name, pos(:, i)
     746          120 :             istat = istat + stat
     747              :          END DO
     748            2 :          READ (iw, *) info
     749           22 :          DO i = 1, nvibs
     750           20 :             READ (iw, *) info
     751           20 :             istat = istat + stat
     752         1202 :             DO j = 1, ncoord/3
     753         1180 :                k = (j - 1)*3 + 1
     754         1180 :                READ (iw, *, IOSTAT=stat) modes(k:k + 2, i)
     755         1200 :                istat = istat + stat
     756              :             END DO
     757              :          END DO
     758            2 :          IF (ms_filename /= "") CALL close_file(iw)
     759            2 :          IF (output_unit > 0) THEN
     760            2 :             IF (istat /= 0) THEN
     761            0 :                WRITE (output_unit, FMT="(/,T2,A)") "**  Error while reading MOLDEN file **"
     762              :             ELSE
     763            2 :                WRITE (output_unit, FMT="(/,T2,A)") "*** MOLDEN file has been read successfully ***"
     764              :             END IF
     765              :          END IF
     766              :          !!!!!!!    select modes     !!!!!!
     767            4 :          ALLOCATE (tmp(nvibs))
     768            2 :          tmp(:) = 0.0_dp
     769            6 :          ALLOCATE (tmplist(nvibs))
     770            2 :          IF (ms_vib%select_id == 1) my_val = ms_vib%sel_freq
     771            2 :          IF (ms_vib%select_id == 2) my_val = (ms_vib%f_range(2) + ms_vib%f_range(1))*0.5_dp
     772            2 :          IF (ms_vib%select_id == 1 .OR. ms_vib%select_id == 2) THEN
     773           11 :             DO i = 1, nvibs
     774           11 :                tmp(i) = ABS(my_val - freq(i))
     775              :             END DO
     776            1 :          ELSE IF (ms_vib%select_id == 3) THEN
     777           11 :             DO i = 1, nvibs
     778           30 :                DO j = 1, SIZE(ms_vib%inv_atoms)
     779           90 :                   DO k = 1, 3
     780           60 :                      jj = (ms_vib%inv_atoms(j) - 1)*3 + k
     781           80 :                      tmp(i) = tmp(i) + SQRT(modes(jj, i)**2)
     782              :                   END DO
     783              :                END DO
     784           11 :                IF (freq(i) <= 400._dp) tmp(i) = 0._dp
     785              :             END DO
     786           11 :             tmp(:) = -tmp(:)
     787              :          END IF
     788            2 :          CALL sort(tmp, nvibs, tmplist)
     789            4 :          DO i = 1, nrep
     790          356 :             ms_vib%b_vec(:, i) = modes(:, tmplist(i))*mass(:)
     791          356 :             norm = NORM2(ms_vib%b_vec(:, i))
     792          358 :             ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
     793              :          END DO
     794            4 :          DO i = 1, nrep
     795          358 :             ms_vib%delta_vec(:, i) = ms_vib%b_vec(:, i)/mass(:)
     796              :          END DO
     797              : 
     798            2 :          DEALLOCATE (freq)
     799            2 :          DEALLOCATE (modes)
     800            2 :          DEALLOCATE (tmp)
     801            2 :          DEALLOCATE (tmplist)
     802              : 
     803              :       END IF
     804         1428 :       CALL para_env%bcast(ms_vib%b_vec)
     805         1428 :       CALL para_env%bcast(ms_vib%delta_vec)
     806              : 
     807            4 :       IF (ms_filename == "") CALL cp_print_key_finished_output(output_molden, logger, input, &
     808            0 :                                                                "VIBRATIONAL_ANALYSIS%PRINT%MOLDEN_VIB")
     809            4 :    END SUBROUTINE molden_guess
     810              : 
     811              : ! **************************************************************************************************
     812              : !> \brief Davidson algorithm for to generate a approximate Hessian for mode
     813              : !>      selective vibrational analysis
     814              : !> \param rep_env ...
     815              : !> \param ms_vib ...
     816              : !> \param input ...
     817              : !> \param nrep ...
     818              : !> \param particles ...
     819              : !> \param mass ...
     820              : !> \param converged ...
     821              : !> \param dx ...
     822              : !> \param calc_intens ...
     823              : !> \param output_unit_ms ...
     824              : !> \param logger ...
     825              : !> \author Florian Schiffmann 11.2007
     826              : ! **************************************************************************************************
     827          162 :    SUBROUTINE evaluate_H_update_b(rep_env, ms_vib, input, nrep, &
     828              :                                   particles, &
     829          162 :                                   mass, &
     830              :                                   converged, dx, &
     831              :                                   calc_intens, output_unit_ms, logger)
     832              :       TYPE(replica_env_type), POINTER                    :: rep_env
     833              :       TYPE(ms_vib_type)                                  :: ms_vib
     834              :       TYPE(section_vals_type), POINTER                   :: input
     835              :       INTEGER                                            :: nrep
     836              :       TYPE(particle_type), DIMENSION(:), POINTER         :: particles
     837              :       REAL(Kind=dp), DIMENSION(:)                        :: mass
     838              :       LOGICAL                                            :: converged
     839              :       REAL(KIND=dp)                                      :: dx
     840              :       LOGICAL                                            :: calc_intens
     841              :       INTEGER                                            :: output_unit_ms
     842              :       TYPE(cp_logger_type), POINTER                      :: logger
     843              : 
     844              :       INTEGER                                            :: i, j, jj, k, natoms, ncoord
     845          162 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: ind
     846              :       LOGICAL                                            :: dump_only_positive
     847          162 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: eigenval, freq
     848          162 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: approx_H, H_save, residuum, tmp_b, tmp_s
     849          324 :       REAL(KIND=dp), DIMENSION(2, nrep)                  :: criteria
     850          162 :       REAL(Kind=dp), DIMENSION(:), POINTER               :: intensities
     851              : 
     852          162 :       natoms = SIZE(particles)
     853          162 :       ncoord = 3*natoms
     854          162 :       nrep = SIZE(rep_env%f, 2)
     855              : 
     856              :       !!!!!!!!   reallocate and update the davidson matrices   !!!!!!!!!!
     857          162 :       IF (ms_vib%mat_size /= 0) THEN
     858              : 
     859          690 :          ALLOCATE (tmp_b(3*natoms, ms_vib%mat_size))
     860          414 :          ALLOCATE (tmp_s(3*natoms, ms_vib%mat_size))
     861              : 
     862       153792 :          tmp_b(:, :) = ms_vib%b_mat
     863       153792 :          tmp_s(:, :) = ms_vib%s_mat
     864              : 
     865          138 :          DEALLOCATE (ms_vib%b_mat)
     866          138 :          DEALLOCATE (ms_vib%s_mat)
     867              :       END IF
     868              : 
     869          810 :       ALLOCATE (ms_vib%b_mat(3*natoms, ms_vib%mat_size + nrep))
     870          486 :       ALLOCATE (ms_vib%s_mat(3*natoms, ms_vib%mat_size + nrep))
     871              : 
     872       176832 :       ms_vib%s_mat = 0.0_dp
     873              : 
     874        22896 :       DO i = 1, 3*natoms
     875        22734 :          IF (ms_vib%mat_size /= 0) THEN
     876       172878 :             DO j = 1, ms_vib%mat_size
     877       152730 :                ms_vib%b_mat(i, j) = tmp_b(i, j)
     878       172878 :                ms_vib%s_mat(i, j) = tmp_s(i, j)
     879              :             END DO
     880              :          END IF
     881        45738 :          DO j = 1, nrep
     882        45576 :             ms_vib%b_mat(i, ms_vib%mat_size + j) = ms_vib%b_vec(i, j)
     883              :          END DO
     884              :       END DO
     885              : 
     886          162 :       IF (ms_vib%mat_size /= 0) THEN
     887          138 :          DEALLOCATE (tmp_s)
     888          138 :          DEALLOCATE (tmp_b)
     889              :       END IF
     890              : 
     891          162 :       ms_vib%mat_size = ms_vib%mat_size + nrep
     892              : 
     893          648 :       ALLOCATE (approx_H(ms_vib%mat_size, ms_vib%mat_size))
     894          486 :       ALLOCATE (H_save(ms_vib%mat_size, ms_vib%mat_size))
     895          486 :       ALLOCATE (eigenval(ms_vib%mat_size))
     896              : 
     897              :       !!!!!!!!!!!!  calculate the new derivativ and the approximate hessian
     898              : 
     899          336 :       DO i = 1, nrep
     900        23178 :          DO j = 1, 3*natoms
     901        23016 :             ms_vib%s_mat(j, ms_vib%mat_size - nrep + i) = -(ms_vib%ms_force(j, i) - rep_env%f(j, i))/(2*ms_vib%step_b(i)*mass(j))
     902              :          END DO
     903              :       END DO
     904              : 
     905              :       CALL dgemm('T', 'N', ms_vib%mat_size, ms_vib%mat_size, SIZE(ms_vib%s_mat, 1), 1._dp, ms_vib%b_mat, SIZE(ms_vib%b_mat, 1), &
     906          162 :                  ms_vib%s_mat, SIZE(ms_vib%s_mat, 1), 0._dp, approx_H, ms_vib%mat_size)
     907        14006 :       H_save(:, :) = approx_H
     908              : 
     909          162 :       CALL diamat_all(approx_H, eigenval)
     910              : 
     911              :       !!!!!!!!!!!! select eigenvalue(s) and vector(s) and calculate the new displacement vector
     912          486 :       ALLOCATE (ind(ms_vib%mat_size))
     913          648 :       ALLOCATE (residuum(SIZE(ms_vib%s_mat, 1), nrep))
     914              : 
     915          162 :       CALL select_vector(ms_vib, nrep, mass, ncoord, approx_H, eigenval, ind, residuum, criteria)
     916              : 
     917          336 :       DO i = 1, nrep
     918         7950 :          DO j = 1, natoms
     919        30630 :             DO k = 1, 3
     920        22842 :                jj = (j - 1)*3 + k
     921        30456 :                ms_vib%delta_vec(jj, i) = ms_vib%b_vec(jj, i)/mass(jj)
     922              :             END DO
     923              :          END DO
     924              :       END DO
     925              : 
     926          336 :       DO i = 1, nrep
     927        23016 :          ms_vib%step_r(i) = dx/NORM2(ms_vib%delta_vec(:, i))
     928        23178 :          ms_vib%step_b(i) = NORM2(ms_vib%step_r(i)*ms_vib%b_vec(:, i))
     929              :       END DO
     930          162 :       converged = .FALSE.
     931              :       IF (MAXVAL(criteria(1, :)) <= ms_vib%eps(1) .AND. MAXVAL(criteria(2, :)) &
     932          510 :           <= ms_vib%eps(2) .OR. ms_vib%mat_size >= ncoord) converged = .TRUE.
     933          486 :       ALLOCATE (freq(nrep))
     934          336 :       DO i = 1, nrep
     935          336 :          freq(i) = SQRT(ABS(eigenval(ind(i)))*massunit)*vibfac
     936              :       END DO
     937              : 
     938              :       !!!   write information and output   !!!
     939          162 :       IF (converged) THEN
     940          198 :          eigenval(:) = SIGN(1._dp, eigenval(:))*SQRT(ABS(eigenval(:))*massunit)*vibfac
     941           96 :          ALLOCATE (tmp_b(ncoord, ms_vib%mat_size))
     942           24 :          tmp_b = 0._dp
     943           72 :          ALLOCATE (tmp_s(3, ms_vib%mat_size))
     944           24 :          tmp_s = 0._dp
     945           24 :          IF (calc_intens) THEN
     946           60 :             ALLOCATE (intensities(ms_vib%mat_size))
     947          170 :             intensities = 0._dp
     948              :          END IF
     949          198 :          DO i = 1, ms_vib%mat_size
     950         2268 :             DO j = 1, ms_vib%mat_size
     951       331218 :                tmp_b(:, i) = tmp_b(:, i) + approx_H(j, i)*ms_vib%b_mat(:, j)/mass(:)
     952              :             END DO
     953        45882 :             tmp_b(:, i) = tmp_b(:, i)/NORM2(tmp_b(:, i))
     954              :          END DO
     955           24 :          IF (calc_intens) THEN
     956          170 :             DO i = 1, ms_vib%mat_size
     957         2100 :                DO j = 1, ms_vib%mat_size
     958         7950 :                   tmp_s(:, i) = tmp_s(:, i) + ms_vib%dip_deriv(:, j)*approx_H(j, i)
     959              :                END DO
     960          620 :                IF (calc_intens) intensities(i) = NORM2(tmp_s(:, i))
     961              :             END DO
     962              :          END IF
     963           24 :          IF (calc_intens) THEN
     964              :             CALL ms_out(output_unit_ms, converged, freq, criteria, ms_vib, &
     965              :                         input, nrep, approx_H, eigenval, calc_intens, &
     966           20 :                         intensities=intensities, logger=logger)
     967              :          ELSE
     968              :             CALL ms_out(output_unit_ms, converged, freq, criteria, ms_vib, &
     969            4 :                         input, nrep, approx_H, eigenval, calc_intens, logger=logger)
     970              :          END IF
     971           24 :          dump_only_positive = ms_vib%low_freq > 0.0_dp
     972              :          CALL write_vibrations_molden(input, particles, eigenval, tmp_b, intensities, calc_intens, &
     973           24 :                                       dump_only_positive=dump_only_positive, logger=logger)
     974           24 :          IF (calc_intens) THEN
     975           20 :             DEALLOCATE (intensities)
     976              :          END IF
     977           24 :          DEALLOCATE (tmp_b)
     978           24 :          DEALLOCATE (tmp_s)
     979              :       END IF
     980              : 
     981          162 :       IF (.NOT. converged) CALL ms_out(output_unit_ms, converged, freq, criteria, &
     982          138 :                                        ms_vib, input, nrep, approx_H, eigenval, calc_intens, logger=logger)
     983              : 
     984          162 :       DEALLOCATE (freq)
     985          162 :       DEALLOCATE (approx_H)
     986          162 :       DEALLOCATE (eigenval)
     987          162 :       DEALLOCATE (residuum)
     988          162 :       DEALLOCATE (ind)
     989              : 
     990          324 :    END SUBROUTINE evaluate_H_update_b
     991              : 
     992              : ! **************************************************************************************************
     993              : !> \brief writes the output for a mode tracking calculation
     994              : !> \param ms_vib ...
     995              : !> \param nrep ...
     996              : !> \param mass ...
     997              : !> \param ncoord ...
     998              : !> \param approx_H ...
     999              : !> \param eigenval ...
    1000              : !> \param ind ...
    1001              : !> \param residuum ...
    1002              : !> \param criteria ...
    1003              : !> \author Florian Schiffmann 11.2007
    1004              : ! **************************************************************************************************
    1005          166 :    SUBROUTINE select_vector(ms_vib, nrep, mass, ncoord, approx_H, eigenval, ind, residuum, criteria)
    1006              : 
    1007              :       TYPE(ms_vib_type)                                  :: ms_vib
    1008              :       INTEGER                                            :: nrep
    1009              :       REAL(Kind=dp), DIMENSION(:)                        :: mass
    1010              :       INTEGER                                            :: ncoord
    1011              :       REAL(KIND=dp), DIMENSION(:, :)                     :: approx_H
    1012              :       REAL(Kind=dp), DIMENSION(:)                        :: eigenval
    1013              :       INTEGER, DIMENSION(:)                              :: ind
    1014              :       REAL(KIND=dp), DIMENSION(:, :)                     :: residuum
    1015              :       REAL(KIND=dp), DIMENSION(2, nrep), OPTIONAL        :: criteria
    1016              : 
    1017              :       INTEGER                                            :: i, j, jj, k
    1018              :       REAL(KIND=dp)                                      :: my_val, norm
    1019          166 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: tmp
    1020          166 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: tmp_b
    1021              : 
    1022          498 :       ALLOCATE (tmp(ms_vib%mat_size))
    1023              : 
    1024          282 :       SELECT CASE (ms_vib%select_id)
    1025              :       CASE (1)
    1026          116 :          my_val = (ms_vib%sel_freq/(vibfac))**2/massunit
    1027         1006 :          DO i = 1, ms_vib%mat_size
    1028         1006 :             tmp(i) = ABS(my_val - eigenval(i))
    1029              :          END DO
    1030          116 :          CALL sort(tmp, (ms_vib%mat_size), ind)
    1031        15892 :          residuum = 0._dp
    1032          238 :          DO j = 1, nrep
    1033         1152 :             DO i = 1, ms_vib%mat_size
    1034       144040 :                residuum(:, j) = residuum(:, j) + approx_H(i, ind(j))*(ms_vib%s_mat(:, i) - eigenval(ind(j))*ms_vib%b_mat(:, i))
    1035              :             END DO
    1036              :          END DO
    1037              :       CASE (2)
    1038            6 :          CALL get_vibs_in_range(ms_vib, approx_H, eigenval, residuum, nrep, ind)
    1039              :       CASE (3)
    1040              : 
    1041          176 :          ALLOCATE (tmp_b(ncoord, ms_vib%mat_size))
    1042           44 :          tmp_b = 0._dp
    1043              : 
    1044          266 :          DO i = 1, ms_vib%mat_size
    1045         1728 :             DO j = 1, ms_vib%mat_size
    1046       268290 :                tmp_b(:, i) = tmp_b(:, i) + approx_H(j, i)*ms_vib%b_mat(:, j)/mass(:)
    1047              :             END DO
    1048        78854 :             tmp_b(:, i) = tmp_b(:, i)/NORM2(tmp_b(:, i))
    1049              :          END DO
    1050           44 :          tmp = 0._dp
    1051          266 :          DO i = 1, ms_vib%mat_size
    1052          666 :             DO j = 1, SIZE(ms_vib%inv_atoms)
    1053         1998 :                DO k = 1, 3
    1054         1332 :                   jj = (ms_vib%inv_atoms(j) - 1)*3 + k
    1055         1776 :                   tmp(i) = tmp(i) + SQRT(tmp_b(jj, i)**2)
    1056              :                END DO
    1057              :             END DO
    1058          266 :             IF (.NOT. ASSOCIATED(ms_vib%inv_range)) THEN
    1059          222 :                IF ((SIGN(1._dp, eigenval(i))*SQRT(ABS(eigenval(i))*massunit)*vibfac) <= 400._dp) tmp(i) = 0._dp
    1060              :             ELSE
    1061            0 :                IF ((SIGN(1._dp, eigenval(i))*SQRT(ABS(eigenval(i))*massunit)*vibfac) <= ms_vib%inv_range(1)) tmp(i) = 0._dp
    1062            0 :                IF ((SIGN(1._dp, eigenval(i))*SQRT(ABS(eigenval(i))*massunit)*vibfac) >= ms_vib%inv_range(2)) tmp(i) = 0._dp
    1063              :             END IF
    1064              :          END DO
    1065          266 :          tmp(:) = -tmp(:)
    1066           44 :          CALL sort(tmp, (ms_vib%mat_size), ind)
    1067         7876 :          residuum(:, :) = 0._dp
    1068              : 
    1069           88 :          DO j = 1, nrep
    1070          310 :             DO i = 1, ms_vib%mat_size
    1071        39560 :                residuum(:, j) = residuum(:, j) + approx_H(i, ind(j))*(ms_vib%s_mat(:, i) - eigenval(ind(j))*ms_vib%b_mat(:, i))
    1072              :             END DO
    1073              :          END DO
    1074          210 :          DEALLOCATE (tmp_b)
    1075              :       END SELECT
    1076              : 
    1077          344 :       DO j = 1, nrep
    1078         1528 :          DO i = 1, ms_vib%mat_size
    1079       366822 :             residuum(:, j) = residuum(:, j) - DOT_PRODUCT(residuum(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
    1080              :          END DO
    1081              :       END DO
    1082          166 :       IF (PRESENT(criteria)) THEN
    1083          336 :          DO i = 1, nrep
    1084        23016 :             criteria(1, i) = MAXVAL((residuum(:, i)))
    1085        23178 :             criteria(2, i) = NORM2(residuum(:, i))
    1086              :          END DO
    1087              :       END IF
    1088              : 
    1089          344 :       DO i = 1, nrep
    1090        23728 :          norm = NORM2(residuum(:, i))
    1091        23894 :          residuum(:, i) = residuum(:, i)/norm
    1092              :       END DO
    1093              : 
    1094         1826 :       DO k = 1, 10
    1095         3606 :          DO j = 1, nrep
    1096        13620 :             DO i = 1, ms_vib%mat_size
    1097      3666440 :                residuum(:, j) = residuum(:, j) - DOT_PRODUCT(residuum(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
    1098      3668220 :                residuum(:, j) = residuum(:, j)/NORM2(residuum(:, j))
    1099              :             END DO
    1100         3440 :             IF (nrep > 1) THEN
    1101          720 :                DO i = 1, nrep
    1102          720 :                   IF (i /= j) THEN
    1103         4560 :                      residuum(:, j) = residuum(:, j) - DOT_PRODUCT(residuum(:, j), residuum(:, i))*residuum(:, i)
    1104         4560 :                      residuum(:, j) = residuum(:, j)/NORM2(residuum(:, j))
    1105              :                   END IF
    1106              :                END DO
    1107              :             END IF
    1108              :          END DO
    1109              :       END DO
    1110        23894 :       ms_vib%b_vec = residuum
    1111          166 :       DEALLOCATE (tmp)
    1112          166 :    END SUBROUTINE select_vector
    1113              : 
    1114              : ! **************************************************************************************************
    1115              : !> \brief writes the output for a mode tracking calculation
    1116              : !> \param iw ...
    1117              : !> \param converged ...
    1118              : !> \param freq ...
    1119              : !> \param criter ...
    1120              : !> \param ms_vib ...
    1121              : !> \param input ...
    1122              : !> \param nrep ...
    1123              : !> \param approx_H ...
    1124              : !> \param eigenval ...
    1125              : !> \param calc_intens ...
    1126              : !> \param intensities ...
    1127              : !> \param logger ...
    1128              : !> \author Florian Schiffmann 11.2007
    1129              : ! **************************************************************************************************
    1130          162 :    SUBROUTINE ms_out(iw, converged, freq, criter, ms_vib, input, nrep, &
    1131          162 :                      approx_H, eigenval, calc_intens, intensities, logger)
    1132              : 
    1133              :       INTEGER                                            :: iw
    1134              :       LOGICAL                                            :: converged
    1135              :       REAL(KIND=dp), DIMENSION(:)                        :: freq
    1136              :       REAL(KIND=dp), DIMENSION(:, :)                     :: criter
    1137              :       TYPE(ms_vib_type)                                  :: ms_vib
    1138              :       TYPE(section_vals_type), POINTER                   :: input
    1139              :       INTEGER                                            :: nrep
    1140              :       REAL(KIND=dp), DIMENSION(:, :)                     :: approx_H
    1141              :       REAL(KIND=dp), DIMENSION(:)                        :: eigenval
    1142              :       LOGICAL                                            :: calc_intens
    1143              :       REAL(KIND=dp), DIMENSION(:), OPTIONAL              :: intensities
    1144              :       TYPE(cp_logger_type), POINTER                      :: logger
    1145              : 
    1146              :       INTEGER                                            :: i, j, msunit
    1147              :       REAL(KIND=dp)                                      :: crit_a, crit_b, fint, gintval
    1148          162 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: residuum
    1149              :       TYPE(section_vals_type), POINTER                   :: ms_vib_section
    1150              : 
    1151              :       ms_vib_section => section_vals_get_subs_vals(input, &
    1152          162 :                                                    "VIBRATIONAL_ANALYSIS%MODE_SELECTIVE")
    1153              : 
    1154          162 :       fint = 42.255_dp*massunit*debye**2*bohr**2
    1155              : 
    1156          162 :       IF (converged) THEN
    1157           24 :          IF (iw > 0) THEN
    1158           12 :             WRITE (iw, '(T2,A)') "MS| DAVIDSON ALGORITHM CONVERGED"
    1159           26 :             DO i = 1, nrep
    1160           26 :                WRITE (iw, '(T2,"MS| TRACKED FREQUENCY (",I0,") IS:",F12.6,3X,A)') i, freq(i), 'cm-1'
    1161              :             END DO
    1162           36 :             ALLOCATE (residuum(SIZE(ms_vib%b_mat, 1)))
    1163           12 :             WRITE (iw, '( /, 1X, 79("-") )')
    1164           12 :             WRITE (iw, '( 25X, A)') 'FREQUENCY AND CONVERGENCE LIST'
    1165           12 :             IF (PRESENT(intensities)) THEN
    1166           10 :                WRITE (iw, '(3X,5(4X, A))') 'FREQUENCY', 'INT[KM/Mole]', 'MAXVAL CRITERIA', 'NORM CRITERIA', 'CONVERGENCE'
    1167              :             ELSE
    1168            2 :                WRITE (iw, '(3X,5(4X, A))') 'FREQUENCY', 'MAXVAL CRITERIA', 'NORM CRITERIA', 'CONVERGENCE'
    1169              :             END IF
    1170           99 :             DO i = 1, SIZE(ms_vib%b_mat, 2)
    1171           87 :                residuum = 0._dp
    1172         1134 :                DO j = 1, SIZE(ms_vib%b_mat, 2)
    1173       165609 :                   residuum(:) = residuum(:) + approx_H(j, i)*(ms_vib%s_mat(:, j) - eigenval(i)*ms_vib%b_mat(:, j))
    1174              :                END DO
    1175         1134 :                DO j = 1, ms_vib%mat_size
    1176       330084 :                   residuum(:) = residuum(:) - DOT_PRODUCT(residuum(:), ms_vib%b_mat(:, j))*ms_vib%b_mat(:, j)
    1177              :                END DO
    1178        11508 :                crit_a = MAXVAL(residuum(:))
    1179        11508 :                crit_b = NORM2(residuum)
    1180           99 :                IF (PRESENT(intensities)) THEN
    1181           75 :                   gintval = fint*intensities(i)**2
    1182           75 :                   IF (crit_a <= ms_vib%eps(1) .AND. crit_b <= ms_vib%eps(2)) THEN
    1183           28 :                      IF (eigenval(i) > ms_vib%low_freq) WRITE (iw, '(2X,A,2X,F9.3,1X,F12.6,3X,E12.3,7X,E12.3,11X,A)') &
    1184           26 :                         'VIB|', eigenval(i), gintval, crit_a, crit_b, 'YES'
    1185              :                   ELSE
    1186           47 :                      IF (eigenval(i) > ms_vib%low_freq) WRITE (iw, '(2X,A,2X,F9.3,1X,F12.6,3X,E12.3,7X,E12.3,11X,A)') &
    1187           47 :                         'VIB|', eigenval(i), gintval, crit_a, crit_b, 'NO'
    1188              :                   END IF
    1189              :                ELSE
    1190           12 :                   IF (crit_a <= ms_vib%eps(1) .AND. crit_b <= ms_vib%eps(2)) THEN
    1191           12 :                      IF (eigenval(i) > ms_vib%low_freq) WRITE (iw, '(2X,A,2X,F9.3,5X,E12.6,5X,E12.3,11X,A)') &
    1192            6 :                         'VIB|', eigenval(i), crit_a, crit_b, 'YES'
    1193              :                   ELSE
    1194            0 :                      IF (eigenval(i) > ms_vib%low_freq) WRITE (iw, '(2X,A,2X,F9.3,5X,E12.6,5X,E12.3,11X,A)') &
    1195            0 :                         'VIB|', eigenval(i), crit_a, crit_b, 'NO'
    1196              :                   END IF
    1197              :                END IF
    1198              :             END DO
    1199           12 :             DEALLOCATE (residuum)
    1200              : 
    1201              :             msunit = cp_print_key_unit_nr(logger, ms_vib_section, &
    1202              :                                           "PRINT%MS_RESTART", extension=".bin", middle_name="MS_RESTART", &
    1203              :                                           file_status="REPLACE", file_form="UNFORMATTED", &
    1204           12 :                                           file_action="WRITE")
    1205              : 
    1206           12 :             IF (msunit > 0) THEN
    1207           12 :                WRITE (UNIT=msunit) ms_vib%mat_size
    1208        11520 :                WRITE (UNIT=msunit) ms_vib%b_mat
    1209        11520 :                WRITE (UNIT=msunit) ms_vib%s_mat
    1210          312 :                IF (calc_intens) WRITE (UNIT=msunit) ms_vib%dip_deriv
    1211              :             END IF
    1212              : 
    1213              :             CALL cp_print_key_finished_output(msunit, logger, ms_vib_section, &
    1214           12 :                                               "PRINT%MS_RESTART")
    1215              :          END IF
    1216              :       ELSE
    1217          138 :          IF (iw > 0) THEN
    1218              :             msunit = cp_print_key_unit_nr(logger, ms_vib_section, &
    1219              :                                           "PRINT%MS_RESTART", extension=".bin", middle_name="MS_RESTART", &
    1220              :                                           file_status="REPLACE", file_form="UNFORMATTED", &
    1221           69 :                                           file_action="WRITE")
    1222              : 
    1223           69 :             IF (msunit > 0) THEN
    1224           69 :                WRITE (UNIT=msunit) ms_vib%mat_size
    1225        76896 :                WRITE (UNIT=msunit) ms_vib%b_mat
    1226        76896 :                WRITE (UNIT=msunit) ms_vib%s_mat
    1227         1869 :                IF (calc_intens) WRITE (UNIT=msunit) ms_vib%dip_deriv
    1228              :             END IF
    1229              : 
    1230              :             CALL cp_print_key_finished_output(msunit, logger, ms_vib_section, &
    1231           69 :                                               "PRINT%MS_RESTART")
    1232              : 
    1233           69 :             WRITE (iw, '(T2,A,3X,I6)') "MS| ITERATION STEP", ms_vib%mat_size/nrep
    1234          142 :             DO i = 1, nrep
    1235          142 :                IF (criter(1, i) <= 1E-7 .AND. (criter(2, i)) <= 1E-6) THEN
    1236            1 :                   WRITE (iw, '(T2,A,3X,F12.6,A)') "MS| TRACKED MODE ", freq(i), "cm-1  IS  CONVERGED"
    1237              :                ELSE
    1238           72 :                   WRITE (iw, '(T2,A,3X,F12.6,A)') "MS| TRACKED MODE ", freq(i), "cm-1  NOT  CONVERGED"
    1239              :                END IF
    1240              :             END DO
    1241              :          END IF
    1242              :       END IF
    1243              : 
    1244          162 :    END SUBROUTINE ms_out
    1245              : 
    1246              : ! **************************************************************************************************
    1247              : !> \brief ...
    1248              : !> \param ms_vib ...
    1249              : !> \param approx_H ...
    1250              : !> \param eigenval ...
    1251              : !> \param residuum ...
    1252              : !> \param nrep ...
    1253              : !> \param ind ...
    1254              : !> \author Florian Schiffmann 11.2007
    1255              : ! **************************************************************************************************
    1256            6 :    SUBROUTINE get_vibs_in_range(ms_vib, approx_H, eigenval, residuum, nrep, ind)
    1257              : 
    1258              :       TYPE(ms_vib_type)                                  :: ms_vib
    1259              :       REAL(KIND=dp), DIMENSION(:, :)                     :: approx_H
    1260              :       REAL(KIND=dp), DIMENSION(:)                        :: eigenval
    1261              :       REAL(KIND=dp), DIMENSION(:, :)                     :: residuum
    1262              :       INTEGER                                            :: nrep
    1263              :       INTEGER, DIMENSION(:)                              :: ind
    1264              : 
    1265              :       INTEGER                                            :: count1, count2, i, j
    1266            6 :       INTEGER, ALLOCATABLE, DIMENSION(:)                 :: map2
    1267            6 :       INTEGER, ALLOCATABLE, DIMENSION(:, :)              :: map1
    1268            6 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:)           :: tmp, tmp1
    1269            6 :       REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :)        :: tmp_resid
    1270              :       REAL(KIND=dp), DIMENSION(2)                        :: myrange
    1271              : 
    1272           18 :       myrange(:) = (ms_vib%f_range(:)/(vibfac))**2/massunit
    1273            6 :       count1 = 0
    1274            6 :       count2 = 0
    1275          126 :       residuum = 0.0_dp
    1276            6 :       ms_vib%mat_size = SIZE(ms_vib%b_mat, 2)
    1277           18 :       ALLOCATE (map1(SIZE(eigenval), 2))
    1278           18 :       ALLOCATE (tmp(SIZE(eigenval)))
    1279           30 :       DO i = 1, SIZE(eigenval)
    1280           24 :          IF (ABS(eigenval(i) - myrange(1)) + ABS(eigenval(i) - myrange(2)) <= &
    1281            6 :              ABS(myrange(1) - myrange(2)) + myrange(1)*0.001_dp) THEN
    1282            0 :             count1 = count1 + 1
    1283            0 :             map1(count1, 1) = i
    1284              :          ELSE
    1285           24 :             count2 = count2 + 1
    1286           24 :             map1(count2, 2) = i
    1287           24 :             tmp(count2) = MIN(ABS(eigenval(i) - myrange(1)), ABS(eigenval(i) - myrange(2)))
    1288              :          END IF
    1289              :       END DO
    1290              : 
    1291            6 :       IF (count1 == nrep) THEN
    1292            0 :          DO j = 1, count1
    1293            0 :             DO i = 1, ms_vib%mat_size
    1294            0 :             residuum(:, j) = residuum(:, j) + approx_H(i, map1(j, 1))*(ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
    1295            0 :                ind(j) = map1(j, 1)
    1296              :             END DO
    1297              :          END DO
    1298            6 :       ELSE IF (count1 > nrep) THEN
    1299            0 :          ALLOCATE (tmp_resid(SIZE(ms_vib%b_mat, 1), count1))
    1300            0 :          ALLOCATE (tmp1(count1))
    1301            0 :          ALLOCATE (map2(count1))
    1302            0 :          tmp_resid = 0._dp
    1303            0 :          DO j = 1, count1
    1304            0 :             DO i = 1, ms_vib%mat_size
    1305              :                tmp_resid(:, j) = tmp_resid(:, j) + approx_H(i, map1(j, 1))* &
    1306            0 :                                  (ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
    1307              :             END DO
    1308              :          END DO
    1309              : 
    1310            0 :          DO j = 1, count1
    1311            0 :             DO i = 1, ms_vib%mat_size
    1312            0 :                tmp_resid(:, j) = tmp_resid(:, j) - DOT_PRODUCT(tmp_resid(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
    1313              :             END DO
    1314            0 :             tmp(j) = MAXVAL(tmp_resid(:, j))
    1315              :          END DO
    1316            0 :          CALL sort(tmp, count1, map2)
    1317            0 :          DO j = 1, nrep
    1318            0 :             residuum(:, j) = tmp_resid(:, map2(count1 + 1 - j))
    1319            0 :             ind(j) = map1(map2(count1 + 1 - j), 1)
    1320              :          END DO
    1321            0 :          DEALLOCATE (tmp_resid)
    1322            0 :          DEALLOCATE (tmp1)
    1323            0 :          DEALLOCATE (map2)
    1324            6 :       ELSE IF (count1 < nrep) THEN
    1325              : 
    1326           18 :          ALLOCATE (map2(count2))
    1327            6 :          IF (count1 /= 0) THEN
    1328            0 :             DO j = 1, count1
    1329            0 :                DO i = 1, ms_vib%mat_size
    1330              :                   residuum(:, j) = residuum(:, j) + approx_H(i, map1(j, 1))* &
    1331            0 :                                    (ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
    1332              :                END DO
    1333            0 :                ind(j) = map1(j, 1)
    1334              :             END DO
    1335              :          END IF
    1336            6 :          CALL sort(tmp, count2, map2)
    1337           18 :          DO j = 1, nrep - count1
    1338           60 :             DO i = 1, ms_vib%mat_size
    1339              :                residuum(:, count1 + j) = residuum(:, count1 + j) + approx_H(i, map1(map2(j), 2)) &
    1340          492 :                                          *(ms_vib%s_mat(:, i) - eigenval(map1(map2(j), 2))*ms_vib%b_mat(:, i))
    1341              :             END DO
    1342           18 :             ind(count1 + j) = map1(map2(j), 2)
    1343              :          END DO
    1344              : 
    1345            6 :          DEALLOCATE (map2)
    1346              :       END IF
    1347              : 
    1348            6 :       DEALLOCATE (map1)
    1349            6 :       DEALLOCATE (tmp)
    1350              : 
    1351            6 :    END SUBROUTINE get_vibs_in_range
    1352            0 : END MODULE mode_selective
        

Generated by: LCOV version 2.0-1