55#include "./base/base_uses.f90"
60 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mode_selective'
61 LOGICAL,
PARAMETER :: debug_this_module = .false.
64 INTEGER :: mat_size = -1
65 INTEGER :: select_id = -1
66 INTEGER,
DIMENSION(:),
POINTER :: inv_atoms => null()
67 REAL(KIND=
dp) :: eps(2) = 0.0_dp
68 REAL(KIND=
dp) :: sel_freq = 0.0_dp
69 REAL(KIND=
dp) :: low_freq = 0.0_dp
70 REAL(KIND=
dp),
POINTER,
DIMENSION(:, :) :: b_vec => null()
71 REAL(KIND=
dp),
POINTER,
DIMENSION(:, :) :: delta_vec => null()
72 REAL(KIND=
dp),
POINTER,
DIMENSION(:, :) :: ms_force => null()
73 REAL(KIND=
dp),
DIMENSION(:),
POINTER :: eig_bfgs => null()
74 REAL(KIND=
dp),
DIMENSION(:),
POINTER :: f_range => null()
75 REAL(KIND=
dp),
DIMENSION(:),
POINTER :: inv_range => null()
76 REAL(KIND=
dp),
POINTER,
DIMENSION(:) :: step_b => null()
77 REAL(KIND=
dp),
POINTER,
DIMENSION(:) :: step_r => null()
78 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: b_mat => null()
79 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: dip_deriv => null()
80 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: hes_bfgs => null()
81 REAL(KIND=
dp),
DIMENSION(:, :),
POINTER :: s_mat => null()
82 INTEGER :: initial_guess = -1
103 SUBROUTINE ms_vb_anal(input, rep_env, para_env, globenv, particles, &
104 nrep, calc_intens, dx, output_unit, logger, cell)
111 LOGICAL :: calc_intens
113 INTEGER :: output_unit
117 CHARACTER(len=*),
PARAMETER :: routinen =
'ms_vb_anal'
119 CHARACTER(LEN=default_string_length) :: description
120 INTEGER :: handle, i, ip1, j, natoms, ncoord
122 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: mass, pos0
123 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: tmp_deriv
124 REAL(kind=
dp),
DIMENSION(:, :, :),
POINTER :: tmp_dip
125 TYPE(ms_vib_type) :: ms_vib
127 CALL timeset(routinen, handle)
129 natoms =
SIZE(particles)
131 ALLOCATE (mass(3*natoms))
134 mass((i - 1)*3 + j) = particles(i)%atomic_kind%mass
135 mass((i - 1)*3 + j) = sqrt(mass((i - 1)*3 + j))
139 ALLOCATE (ms_vib%delta_vec(ncoord, nrep))
140 ALLOCATE (ms_vib%b_vec(ncoord, nrep))
141 ALLOCATE (ms_vib%step_r(nrep))
142 ALLOCATE (ms_vib%step_b(nrep))
143 IF (calc_intens)
THEN
144 description =
'[DIPOLE]'
145 ALLOCATE (tmp_dip(nrep, 3, 2))
146 ALLOCATE (ms_vib%dip_deriv(3, nrep))
148 CALL ms_initial_moves(para_env, nrep, input, globenv, ms_vib, &
154 ALLOCATE (pos0(ncoord))
155 ALLOCATE (ms_vib%ms_force(ncoord, nrep))
158 pos0((i - 1)*3 + j) = particles((i))%r(j)
163 ms_vib%ms_force = huge(0.0_dp)
166 rep_env%r(j, i) = pos0(j) + ms_vib%step_r(i)*ms_vib%delta_vec(j, i)
172 IF (calc_intens)
THEN
173 CALL get_results(results=rep_env%results(i)%results, &
174 description=description, &
176 CALL get_results(results=rep_env%results(i)%results, &
177 description=description, &
178 values=tmp_dip(i, :, 1), &
182 ms_vib%ms_force(j, i) = rep_env%f(j, i)
187 rep_env%r(j, i) = pos0(j) - ms_vib%step_r(i)*ms_vib%delta_vec(j, i)
191 IF (calc_intens)
THEN
193 CALL get_results(results=rep_env%results(i)%results, &
194 description=description, &
196 CALL get_results(results=rep_env%results(i)%results, &
197 description=description, &
198 values=tmp_dip(i, :, 2), &
200 ms_vib%dip_deriv(:, ms_vib%mat_size + i) = (tmp_dip(i, :, 1) - tmp_dip(i, :, 2))/(2*ms_vib%step_b(i))
204 CALL evaluate_h_update_b(rep_env, ms_vib, input, nrep, &
209 output_unit, logger, cell)
211 IF (calc_intens)
THEN
212 ALLOCATE (tmp_deriv(3, ms_vib%mat_size))
213 tmp_deriv = ms_vib%dip_deriv
214 DEALLOCATE (ms_vib%dip_deriv)
215 ALLOCATE (ms_vib%dip_deriv(3, ms_vib%mat_size + nrep))
216 ms_vib%dip_deriv(:, 1:ms_vib%mat_size) = tmp_deriv(:, 1:ms_vib%mat_size)
217 DEALLOCATE (tmp_deriv)
220 DEALLOCATE (ms_vib%ms_force)
222 DEALLOCATE (ms_vib%step_r)
223 DEALLOCATE (ms_vib%step_b)
224 DEALLOCATE (ms_vib%b_vec)
225 DEALLOCATE (ms_vib%delta_vec)
227 DEALLOCATE (ms_vib%b_mat)
228 DEALLOCATE (ms_vib%s_mat)
229 IF (ms_vib%select_id == 3)
THEN
230 DEALLOCATE (ms_vib%inv_atoms)
232 IF (
ASSOCIATED(ms_vib%eig_bfgs))
THEN
233 DEALLOCATE (ms_vib%eig_bfgs)
235 IF (
ASSOCIATED(ms_vib%hes_bfgs))
THEN
236 DEALLOCATE (ms_vib%hes_bfgs)
238 IF (calc_intens)
THEN
239 DEALLOCATE (ms_vib%dip_deriv)
242 CALL timestop(handle)
259 SUBROUTINE ms_initial_moves(para_env, nrep, input, globenv, ms_vib, particles, &
266 TYPE(ms_vib_type) :: ms_vib
268 REAL(kind=
dp),
DIMENSION(:) :: mass
270 LOGICAL :: calc_intens
273 CHARACTER(len=*),
PARAMETER :: routinen =
'MS_initial_moves'
275 INTEGER :: guess, handle, i, j, jj, k, m, &
276 n_rep_val, natoms, ncoord
277 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: map_atoms
278 INTEGER,
DIMENSION(:),
POINTER :: tmplist
279 LOGICAL :: do_involved_atoms, ionode
280 REAL(kind=
dp) :: my_val, norm
283 CALL timeset(routinen, handle)
284 NULLIFY (ms_vib%eig_bfgs, ms_vib%f_range, ms_vib%hes_bfgs, ms_vib%inv_range)
291 IF (n_rep_val /= 0)
THEN
293 IF (ms_vib%f_range(1) > ms_vib%f_range(2))
THEN
294 my_val = ms_vib%f_range(2)
295 ms_vib%f_range(2) = ms_vib%f_range(1)
296 ms_vib%f_range(1) = my_val
302 IF (ms_vib%sel_freq > 0._dp) ms_vib%select_id = 1
305 IF (do_involved_atoms)
THEN
310 DO j = 1,
SIZE(tmplist)
316 ALLOCATE (ms_vib%inv_atoms(natoms))
320 DO j = 1,
SIZE(tmplist)
321 ms_vib%inv_atoms(j) = tmplist(j)
327 IF (n_rep_val /= 0)
THEN
329 IF (ms_vib%inv_range(1) > ms_vib%inv_range(2))
THEN
330 ms_vib%inv_range(2) = my_val
331 ms_vib%inv_range(2) = ms_vib%inv_range(1)
332 ms_vib%inv_range(1) = my_val
336 IF (ms_vib%select_id == 0)
THEN
337 cpabort(
"no frequency, range or involved atoms specified ")
339 ionode = para_env%is_source()
342 ms_vib%initial_guess = 1
347 DO j = 1,
SIZE(tmplist)
352 natoms =
SIZE(particles)
353 ALLOCATE (map_atoms(natoms))
359 ALLOCATE (map_atoms(natoms))
363 DO j = 1,
SIZE(tmplist)
364 map_atoms(j) = tmplist(j)
371 ms_vib%delta_vec = 0._dp
377 jj = (map_atoms(j) - 1)*3 + k
378 ms_vib%b_vec(jj, i) = abs(globenv%gaussian_rng_stream%next())
381 norm = norm2(ms_vib%b_vec(:, i))
382 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
390 ms_vib%b_vec(:, j) = &
391 ms_vib%b_vec(:, j) - dot_product(ms_vib%b_vec(:, j), ms_vib%b_vec(:, i))*ms_vib%b_vec(:, i)
392 ms_vib%b_vec(:, j) = &
393 ms_vib%b_vec(:, j)/norm2(ms_vib%b_vec(:, j))
401 DO i = 1,
SIZE(ms_vib%b_vec, 1)
402 ms_vib%delta_vec(i, :) = ms_vib%b_vec(i, :)/mass(i)
406 ms_vib%initial_guess = 2
407 CALL bfgs_guess(ms_vib_section, ms_vib, particles, mass, para_env, nrep)
412 ms_vib%initial_guess = 3
413 ncoord = 3*
SIZE(particles)
414 CALL rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
418 ms_vib%initial_guess = 4
419 ncoord = 3*
SIZE(particles)
420 CALL rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
423 ms_vib%initial_guess = 5
424 ncoord = 3*
SIZE(particles)
425 CALL molden_guess(ms_vib_section, input, para_env, ms_vib, mass, ncoord, nrep, logger)
428 CALL para_env%bcast(ms_vib%b_vec)
429 CALL para_env%bcast(ms_vib%delta_vec)
431 ms_vib%step_r(i) = dx/norm2(ms_vib%delta_vec(:, i))
432 ms_vib%step_b(i) = norm2(ms_vib%step_r(i)*ms_vib%b_vec(:, i))
434 CALL timestop(handle)
436 END SUBROUTINE ms_initial_moves
448 SUBROUTINE bfgs_guess(ms_vib_section, ms_vib, particles, mass, para_env, nrep)
451 TYPE(ms_vib_type) :: ms_vib
453 REAL(kind=
dp),
DIMENSION(:) :: mass
457 CHARACTER(LEN=default_path_length) :: hes_filename
458 INTEGER :: hesunit, i, istat, j, jj, k, natoms, &
459 ncoord, output_unit, stat
460 INTEGER,
DIMENSION(:),
POINTER :: tmplist
461 REAL(kind=
dp) :: my_val, norm
462 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp
468 natoms =
SIZE(particles)
471 ALLOCATE (ms_vib%hes_bfgs(ncoord, ncoord))
472 ALLOCATE (ms_vib%eig_bfgs(ncoord))
474 IF (para_env%is_source())
THEN
476 IF (hes_filename ==
"") hes_filename =
"HESSIAN"
477 CALL open_file(file_name=hes_filename, file_status=
"OLD", &
478 file_form=
"UNFORMATTED", file_action=
"READ", unit_number=hesunit)
479 ALLOCATE (tmp(ncoord))
480 ALLOCATE (tmplist(ncoord))
485 READ (unit=hesunit, iostat=stat) ms_vib%hes_bfgs(:, i)
489 IF (output_unit > 0)
THEN
491 WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading HESSIAN **"
493 WRITE (output_unit, fmt=
"(/,T2,A)") &
494 "*** Initial Hessian has been read successfully ***"
499 ms_vib%hes_bfgs(i, j) = ms_vib%hes_bfgs(i, j)/(mass(i)*mass(j))
503 CALL diamat_all(ms_vib%hes_bfgs, ms_vib%eig_bfgs)
505 IF (ms_vib%select_id == 1) my_val = (ms_vib%sel_freq/
vibfac)**2/
massunit
506 IF (ms_vib%select_id == 2) my_val = (((ms_vib%f_range(2) + ms_vib%f_range(1))*0.5_dp)/
vibfac)**2/
massunit
507 IF (ms_vib%select_id == 1 .OR. ms_vib%select_id == 2)
THEN
509 tmp(i) = abs(my_val - ms_vib%eig_bfgs(i))
511 ELSE IF (ms_vib%select_id == 3)
THEN
513 DO j = 1,
SIZE(ms_vib%inv_atoms)
515 jj = (ms_vib%inv_atoms(j) - 1)*3 + k
516 tmp(i) = tmp(i) + sqrt(ms_vib%hes_bfgs(jj, i)**2)
519 IF ((sign(1._dp, ms_vib%eig_bfgs(i))*sqrt(abs(ms_vib%eig_bfgs(i))*
massunit)*
vibfac) <= 400._dp) tmp(i) = 0._dp
523 CALL sort(tmp, ncoord, tmplist)
525 ms_vib%b_vec(:, i) = ms_vib%hes_bfgs(:, tmplist(i))
526 norm = norm2(ms_vib%b_vec(:, i))
527 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
529 DO i = 1,
SIZE(ms_vib%b_vec, 1)
530 ms_vib%delta_vec(i, :) = ms_vib%b_vec(i, :)/mass(i)
536 CALL para_env%bcast(ms_vib%b_vec)
537 CALL para_env%bcast(ms_vib%delta_vec)
539 DEALLOCATE (ms_vib%hes_bfgs)
540 DEALLOCATE (ms_vib%eig_bfgs)
543 END SUBROUTINE bfgs_guess
557 SUBROUTINE rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
561 TYPE(ms_vib_type) :: ms_vib
562 REAL(kind=
dp),
DIMENSION(:) :: mass
566 LOGICAL :: calc_intens
568 CHARACTER(LEN=default_path_length) :: ms_filename
569 INTEGER :: hesunit, i, j, mat, natoms, ncoord, &
570 output_unit, stat, statint
571 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ind
572 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval
573 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: approx_h
579 natoms =
SIZE(particles)
581 IF (calc_intens)
THEN
582 DEALLOCATE (ms_vib%dip_deriv)
588 IF (ms_filename ==
"") ms_filename =
"MS_RESTART"
590 file_status=
"UNKNOWN", &
591 file_form=
"UNFORMATTED", &
592 file_action=
"READ", &
594 READ (unit=hesunit, iostat=stat) mat
596 ms_vib%mat_size = mat
598 CALL para_env%bcast(ms_vib%mat_size)
599 ALLOCATE (ms_vib%b_mat(ncoord, ms_vib%mat_size))
600 ALLOCATE (ms_vib%s_mat(ncoord, ms_vib%mat_size))
601 IF (calc_intens)
THEN
602 ALLOCATE (ms_vib%dip_deriv(3, ms_vib%mat_size + nrep))
606 READ (unit=hesunit) ms_vib%b_mat
607 READ (unit=hesunit, iostat=stat) ms_vib%s_mat
608 IF (stat /= 0 .AND. output_unit > 0)
THEN
609 WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading MS_RESTART **"
611 IF (calc_intens)
THEN
612 READ (unit=hesunit, iostat=statint) ms_vib%dip_deriv(:, 1:ms_vib%mat_size)
613 IF (statint /= 0 .AND. output_unit > 0)
WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading MS_RESTART,", &
614 "intensities are requested but not present in restart file **"
617 IF (stat == 0 .AND. statint == 0 .AND. output_unit > 0)
THEN
618 WRITE (output_unit, fmt=
"(/,T2,A)")
"*** MS_RESTART has been read successfully ***"
621 CALL para_env%bcast(ms_vib%b_mat)
622 CALL para_env%bcast(ms_vib%s_mat)
623 IF (calc_intens)
CALL para_env%bcast(ms_vib%dip_deriv)
624 ALLOCATE (approx_h(ms_vib%mat_size, ms_vib%mat_size))
625 ALLOCATE (eigenval(ms_vib%mat_size))
626 ALLOCATE (ind(ms_vib%mat_size))
628 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), &
629 ms_vib%s_mat,
SIZE(ms_vib%s_mat, 1), 0._dp, approx_h, ms_vib%mat_size)
632 CALL select_vector(ms_vib, nrep, mass, ncoord, approx_h, eigenval, ind, ms_vib%b_vec)
633 IF (ms_vib%initial_guess /= 4)
THEN
637 DO j = 1, ms_vib%mat_size
638 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i) + approx_h(j, ind(i))*ms_vib%b_mat(:, j)
640 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm2(ms_vib%b_vec(:, i))
643 DEALLOCATE (ms_vib%s_mat)
644 DEALLOCATE (ms_vib%b_mat)
645 IF (calc_intens)
THEN
646 DEALLOCATE (ms_vib%dip_deriv)
647 ALLOCATE (ms_vib%dip_deriv(3, nrep))
650 DEALLOCATE (approx_h)
651 DEALLOCATE (eigenval)
654 ms_vib%delta_vec(:, i) = ms_vib%b_vec(:, i)/mass(:)
657 END SUBROUTINE rest_guess
671 SUBROUTINE molden_guess(ms_vib_section, input, para_env, ms_vib, mass, ncoord, nrep, logger)
674 TYPE(ms_vib_type) :: ms_vib
675 REAL(kind=
dp),
DIMENSION(:) :: mass
676 INTEGER :: ncoord, nrep
679 CHARACTER(LEN=2) :: at_name
680 CHARACTER(LEN=default_path_length) :: ms_filename
681 CHARACTER(LEN=max_line_length) :: info
682 INTEGER :: i, istat, iw, j, jj, k, nvibs, &
683 output_molden, output_unit, stat
684 INTEGER,
DIMENSION(:),
POINTER :: tmplist
685 LOGICAL :: reading_vib
686 REAL(kind=
dp) :: my_val, norm
687 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: freq, tmp
688 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: modes
689 REAL(kind=
dp),
DIMENSION(3, ncoord/3) :: pos
694 IF (ms_filename ==
"") output_molden = &
696 extension=
".mol", file_status=
'UNKNOWN', &
698 IF (para_env%is_source())
THEN
700 IF (ms_filename ==
"")
THEN
703 CALL open_file(file_name=trim(ms_filename), &
704 file_status=
"UNKNOWN", &
705 file_form=
"FORMATTED", &
706 file_action=
"READ", &
714 reading_vib = .false.
716 READ (iw, *, iostat=stat) info
718 IF (trim(adjustl(info)) ==
"[FR-COORD]")
EXIT
722 IF (reading_vib) nvibs = nvibs + 1
723 IF (trim(adjustl(info)) ==
"[FREQ]") reading_vib = .true.
727 READ (iw, *, iostat=stat) info
729 READ (iw, *, iostat=stat) info
733 READ (iw, *, iostat=stat) info
736 IF (trim(adjustl(info)) ==
"[FREQ]")
EXIT
739 ALLOCATE (freq(nvibs))
740 ALLOCATE (modes(ncoord, nvibs))
743 READ (iw, *, iostat=stat) freq(i)
748 READ (iw, *, iostat=stat) at_name, pos(:, i)
757 READ (iw, *, iostat=stat) modes(k:k + 2, i)
762 IF (output_unit > 0)
THEN
764 WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading MOLDEN file **"
766 WRITE (output_unit, fmt=
"(/,T2,A)")
"*** MOLDEN file has been read successfully ***"
770 ALLOCATE (tmp(nvibs))
772 ALLOCATE (tmplist(nvibs))
773 IF (ms_vib%select_id == 1) my_val = ms_vib%sel_freq
774 IF (ms_vib%select_id == 2) my_val = (ms_vib%f_range(2) + ms_vib%f_range(1))*0.5_dp
775 IF (ms_vib%select_id == 1 .OR. ms_vib%select_id == 2)
THEN
777 tmp(i) = abs(my_val - freq(i))
779 ELSE IF (ms_vib%select_id == 3)
THEN
781 DO j = 1,
SIZE(ms_vib%inv_atoms)
783 jj = (ms_vib%inv_atoms(j) - 1)*3 + k
784 tmp(i) = tmp(i) + sqrt(modes(jj, i)**2)
787 IF (freq(i) <= 400._dp) tmp(i) = 0._dp
791 CALL sort(tmp, nvibs, tmplist)
793 ms_vib%b_vec(:, i) = modes(:, tmplist(i))*mass(:)
794 norm = norm2(ms_vib%b_vec(:, i))
795 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
798 ms_vib%delta_vec(:, i) = ms_vib%b_vec(:, i)/mass(:)
807 CALL para_env%bcast(ms_vib%b_vec)
808 CALL para_env%bcast(ms_vib%delta_vec)
811 "VIBRATIONAL_ANALYSIS%PRINT%MOLDEN_VIB")
812 END SUBROUTINE molden_guess
831 SUBROUTINE evaluate_h_update_b(rep_env, ms_vib, input, nrep, &
835 calc_intens, output_unit_ms, logger, cell)
837 TYPE(ms_vib_type) :: ms_vib
841 REAL(kind=
dp),
DIMENSION(:) :: mass
844 LOGICAL :: calc_intens
845 INTEGER :: output_unit_ms
849 INTEGER :: i, j, jj, k, natoms, ncoord
850 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ind
851 LOGICAL :: dump_only_positive
852 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval, freq
853 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: approx_h, h_save, residuum, tmp_b, tmp_s
854 REAL(kind=
dp),
DIMENSION(2, nrep) :: criteria
855 REAL(kind=
dp),
DIMENSION(:),
POINTER :: intensities
857 natoms =
SIZE(particles)
859 nrep =
SIZE(rep_env%f, 2)
862 IF (ms_vib%mat_size /= 0)
THEN
864 ALLOCATE (tmp_b(3*natoms, ms_vib%mat_size))
865 ALLOCATE (tmp_s(3*natoms, ms_vib%mat_size))
867 tmp_b(:, :) = ms_vib%b_mat
868 tmp_s(:, :) = ms_vib%s_mat
870 DEALLOCATE (ms_vib%b_mat)
871 DEALLOCATE (ms_vib%s_mat)
874 ALLOCATE (ms_vib%b_mat(3*natoms, ms_vib%mat_size + nrep))
875 ALLOCATE (ms_vib%s_mat(3*natoms, ms_vib%mat_size + nrep))
877 ms_vib%s_mat = 0.0_dp
880 IF (ms_vib%mat_size /= 0)
THEN
881 DO j = 1, ms_vib%mat_size
882 ms_vib%b_mat(i, j) = tmp_b(i, j)
883 ms_vib%s_mat(i, j) = tmp_s(i, j)
887 ms_vib%b_mat(i, ms_vib%mat_size + j) = ms_vib%b_vec(i, j)
891 IF (ms_vib%mat_size /= 0)
THEN
896 ms_vib%mat_size = ms_vib%mat_size + nrep
898 ALLOCATE (approx_h(ms_vib%mat_size, ms_vib%mat_size))
899 ALLOCATE (h_save(ms_vib%mat_size, ms_vib%mat_size))
900 ALLOCATE (eigenval(ms_vib%mat_size))
906 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))
910 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), &
911 ms_vib%s_mat,
SIZE(ms_vib%s_mat, 1), 0._dp, approx_h, ms_vib%mat_size)
912 h_save(:, :) = approx_h
917 ALLOCATE (ind(ms_vib%mat_size))
918 ALLOCATE (residuum(
SIZE(ms_vib%s_mat, 1), nrep))
920 CALL select_vector(ms_vib, nrep, mass, ncoord, approx_h, eigenval, ind, residuum, criteria)
926 ms_vib%delta_vec(jj, i) = ms_vib%b_vec(jj, i)/mass(jj)
932 ms_vib%step_r(i) = dx/norm2(ms_vib%delta_vec(:, i))
933 ms_vib%step_b(i) = norm2(ms_vib%step_r(i)*ms_vib%b_vec(:, i))
936 IF (maxval(criteria(1, :)) <= ms_vib%eps(1) .AND. maxval(criteria(2, :)) &
937 <= ms_vib%eps(2) .OR. ms_vib%mat_size >= ncoord) converged = .true.
938 ALLOCATE (freq(nrep))
945 eigenval(:) = sign(1._dp, eigenval(:))*sqrt(abs(eigenval(:))*
massunit)*
vibfac
946 ALLOCATE (tmp_b(ncoord, ms_vib%mat_size))
948 ALLOCATE (tmp_s(3, ms_vib%mat_size))
950 IF (calc_intens)
THEN
951 ALLOCATE (intensities(ms_vib%mat_size))
954 DO i = 1, ms_vib%mat_size
955 DO j = 1, ms_vib%mat_size
956 tmp_b(:, i) = tmp_b(:, i) + approx_h(j, i)*ms_vib%b_mat(:, j)/mass(:)
958 tmp_b(:, i) = tmp_b(:, i)/norm2(tmp_b(:, i))
960 IF (calc_intens)
THEN
961 DO i = 1, ms_vib%mat_size
962 DO j = 1, ms_vib%mat_size
963 tmp_s(:, i) = tmp_s(:, i) + ms_vib%dip_deriv(:, j)*approx_h(j, i)
965 IF (calc_intens) intensities(i) = norm2(tmp_s(:, i))
968 IF (calc_intens)
THEN
969 CALL ms_out(output_unit_ms, converged, freq, criteria, ms_vib, &
970 input, nrep, approx_h, eigenval, calc_intens, &
971 intensities=intensities, logger=logger)
973 CALL ms_out(output_unit_ms, converged, freq, criteria, ms_vib, &
974 input, nrep, approx_h, eigenval, calc_intens, logger=logger)
976 dump_only_positive = ms_vib%low_freq > 0.0_dp
978 dump_only_positive=dump_only_positive, logger=logger, cell=cell)
979 IF (calc_intens)
THEN
980 DEALLOCATE (intensities)
986 IF (.NOT. converged)
CALL ms_out(output_unit_ms, converged, freq, criteria, &
987 ms_vib, input, nrep, approx_h, eigenval, calc_intens, logger=logger)
990 DEALLOCATE (approx_h)
991 DEALLOCATE (eigenval)
992 DEALLOCATE (residuum)
995 END SUBROUTINE evaluate_h_update_b
1010 SUBROUTINE select_vector(ms_vib, nrep, mass, ncoord, approx_H, eigenval, ind, residuum, criteria)
1012 TYPE(ms_vib_type) :: ms_vib
1014 REAL(kind=
dp),
DIMENSION(:) :: mass
1016 REAL(kind=
dp),
DIMENSION(:, :) :: approx_h
1017 REAL(kind=
dp),
DIMENSION(:) :: eigenval
1018 INTEGER,
DIMENSION(:) :: ind
1019 REAL(kind=
dp),
DIMENSION(:, :) :: residuum
1020 REAL(kind=
dp),
DIMENSION(2, nrep),
OPTIONAL :: criteria
1022 INTEGER :: i, j, jj, k
1023 REAL(kind=
dp) :: my_val, norm
1024 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp
1025 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: tmp_b
1027 ALLOCATE (tmp(ms_vib%mat_size))
1029 SELECT CASE (ms_vib%select_id)
1032 DO i = 1, ms_vib%mat_size
1033 tmp(i) = abs(my_val - eigenval(i))
1035 CALL sort(tmp, (ms_vib%mat_size), ind)
1038 DO i = 1, ms_vib%mat_size
1039 residuum(:, j) = residuum(:, j) + approx_h(i, ind(j))*(ms_vib%s_mat(:, i) - eigenval(ind(j))*ms_vib%b_mat(:, i))
1043 CALL get_vibs_in_range(ms_vib, approx_h, eigenval, residuum, nrep, ind)
1046 ALLOCATE (tmp_b(ncoord, ms_vib%mat_size))
1049 DO i = 1, ms_vib%mat_size
1050 DO j = 1, ms_vib%mat_size
1051 tmp_b(:, i) = tmp_b(:, i) + approx_h(j, i)*ms_vib%b_mat(:, j)/mass(:)
1053 tmp_b(:, i) = tmp_b(:, i)/norm2(tmp_b(:, i))
1056 DO i = 1, ms_vib%mat_size
1057 DO j = 1,
SIZE(ms_vib%inv_atoms)
1059 jj = (ms_vib%inv_atoms(j) - 1)*3 + k
1060 tmp(i) = tmp(i) + sqrt(tmp_b(jj, i)**2)
1063 IF (.NOT.
ASSOCIATED(ms_vib%inv_range))
THEN
1064 IF ((sign(1._dp, eigenval(i))*sqrt(abs(eigenval(i))*
massunit)*
vibfac) <= 400._dp) tmp(i) = 0._dp
1066 IF ((sign(1._dp, eigenval(i))*sqrt(abs(eigenval(i))*
massunit)*
vibfac) <= ms_vib%inv_range(1)) tmp(i) = 0._dp
1067 IF ((sign(1._dp, eigenval(i))*sqrt(abs(eigenval(i))*
massunit)*
vibfac) >= ms_vib%inv_range(2)) tmp(i) = 0._dp
1071 CALL sort(tmp, (ms_vib%mat_size), ind)
1072 residuum(:, :) = 0._dp
1075 DO i = 1, ms_vib%mat_size
1076 residuum(:, j) = residuum(:, j) + approx_h(i, ind(j))*(ms_vib%s_mat(:, i) - eigenval(ind(j))*ms_vib%b_mat(:, i))
1083 DO i = 1, ms_vib%mat_size
1084 residuum(:, j) = residuum(:, j) - dot_product(residuum(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
1087 IF (
PRESENT(criteria))
THEN
1089 criteria(1, i) = maxval((residuum(:, i)))
1090 criteria(2, i) = norm2(residuum(:, i))
1095 norm = norm2(residuum(:, i))
1096 residuum(:, i) = residuum(:, i)/norm
1101 DO i = 1, ms_vib%mat_size
1102 residuum(:, j) = residuum(:, j) - dot_product(residuum(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
1103 residuum(:, j) = residuum(:, j)/norm2(residuum(:, j))
1108 residuum(:, j) = residuum(:, j) - dot_product(residuum(:, j), residuum(:, i))*residuum(:, i)
1109 residuum(:, j) = residuum(:, j)/norm2(residuum(:, j))
1115 ms_vib%b_vec = residuum
1117 END SUBROUTINE select_vector
1135 SUBROUTINE ms_out(iw, converged, freq, criter, ms_vib, input, nrep, &
1136 approx_H, eigenval, calc_intens, intensities, logger)
1139 LOGICAL :: converged
1140 REAL(kind=
dp),
DIMENSION(:) :: freq
1141 REAL(kind=
dp),
DIMENSION(:, :) :: criter
1142 TYPE(ms_vib_type) :: ms_vib
1145 REAL(kind=
dp),
DIMENSION(:, :) :: approx_h
1146 REAL(kind=
dp),
DIMENSION(:) :: eigenval
1147 LOGICAL :: calc_intens
1148 REAL(kind=
dp),
DIMENSION(:),
OPTIONAL :: intensities
1151 INTEGER :: i, j, msunit
1152 REAL(kind=
dp) :: crit_a, crit_b, fint, gintval
1153 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: residuum
1157 "VIBRATIONAL_ANALYSIS%MODE_SELECTIVE")
1163 WRITE (iw,
'(T2,A)')
"MS| DAVIDSON ALGORITHM CONVERGED"
1165 WRITE (iw,
'(T2,"MS| TRACKED FREQUENCY (",I0,") IS:",F12.6,3X,A)') i, freq(i),
'cm-1'
1167 ALLOCATE (residuum(
SIZE(ms_vib%b_mat, 1)))
1168 WRITE (iw,
'( /, 1X, 79("-") )')
1169 WRITE (iw,
'( 25X, A)')
'FREQUENCY AND CONVERGENCE LIST'
1170 IF (
PRESENT(intensities))
THEN
1171 WRITE (iw,
'(3X,5(4X, A))')
'FREQUENCY',
'INT[KM/Mole]',
'MAXVAL CRITERIA',
'NORM CRITERIA',
'CONVERGENCE'
1173 WRITE (iw,
'(3X,5(4X, A))')
'FREQUENCY',
'MAXVAL CRITERIA',
'NORM CRITERIA',
'CONVERGENCE'
1175 DO i = 1,
SIZE(ms_vib%b_mat, 2)
1177 DO j = 1,
SIZE(ms_vib%b_mat, 2)
1178 residuum(:) = residuum(:) + approx_h(j, i)*(ms_vib%s_mat(:, j) - eigenval(i)*ms_vib%b_mat(:, j))
1180 DO j = 1, ms_vib%mat_size
1181 residuum(:) = residuum(:) - dot_product(residuum(:), ms_vib%b_mat(:, j))*ms_vib%b_mat(:, j)
1183 crit_a = maxval(residuum(:))
1184 crit_b = norm2(residuum)
1185 IF (
PRESENT(intensities))
THEN
1186 gintval = fint*intensities(i)**2
1187 IF (crit_a <= ms_vib%eps(1) .AND. crit_b <= ms_vib%eps(2))
THEN
1188 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)') &
1189 'VIB|', eigenval(i), gintval, crit_a, crit_b,
'YES'
1191 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)') &
1192 'VIB|', eigenval(i), gintval, crit_a, crit_b,
'NO'
1195 IF (crit_a <= ms_vib%eps(1) .AND. crit_b <= ms_vib%eps(2))
THEN
1196 IF (eigenval(i) > ms_vib%low_freq)
WRITE (iw,
'(2X,A,2X,F9.3,5X,E12.6,5X,E12.3,11X,A)') &
1197 'VIB|', eigenval(i), crit_a, crit_b,
'YES'
1199 IF (eigenval(i) > ms_vib%low_freq)
WRITE (iw,
'(2X,A,2X,F9.3,5X,E12.6,5X,E12.3,11X,A)') &
1200 'VIB|', eigenval(i), crit_a, crit_b,
'NO'
1204 DEALLOCATE (residuum)
1207 "PRINT%MS_RESTART", extension=
".bin", middle_name=
"MS_RESTART", &
1208 file_status=
"REPLACE", file_form=
"UNFORMATTED", &
1209 file_action=
"WRITE")
1211 IF (msunit > 0)
THEN
1212 WRITE (unit=msunit) ms_vib%mat_size
1213 WRITE (unit=msunit) ms_vib%b_mat
1214 WRITE (unit=msunit) ms_vib%s_mat
1215 IF (calc_intens)
WRITE (unit=msunit) ms_vib%dip_deriv
1224 "PRINT%MS_RESTART", extension=
".bin", middle_name=
"MS_RESTART", &
1225 file_status=
"REPLACE", file_form=
"UNFORMATTED", &
1226 file_action=
"WRITE")
1228 IF (msunit > 0)
THEN
1229 WRITE (unit=msunit) ms_vib%mat_size
1230 WRITE (unit=msunit) ms_vib%b_mat
1231 WRITE (unit=msunit) ms_vib%s_mat
1232 IF (calc_intens)
WRITE (unit=msunit) ms_vib%dip_deriv
1238 WRITE (iw,
'(T2,A,3X,I6)')
"MS| ITERATION STEP", ms_vib%mat_size/nrep
1240 IF (criter(1, i) <= 1e-7 .AND. (criter(2, i)) <= 1e-6)
THEN
1241 WRITE (iw,
'(T2,A,3X,F12.6,A)')
"MS| TRACKED MODE ", freq(i),
"cm-1 IS CONVERGED"
1243 WRITE (iw,
'(T2,A,3X,F12.6,A)')
"MS| TRACKED MODE ", freq(i),
"cm-1 NOT CONVERGED"
1249 END SUBROUTINE ms_out
1261 SUBROUTINE get_vibs_in_range(ms_vib, approx_H, eigenval, residuum, nrep, ind)
1263 TYPE(ms_vib_type) :: ms_vib
1264 REAL(kind=
dp),
DIMENSION(:, :) :: approx_h
1265 REAL(kind=
dp),
DIMENSION(:) :: eigenval
1266 REAL(kind=
dp),
DIMENSION(:, :) :: residuum
1268 INTEGER,
DIMENSION(:) :: ind
1270 INTEGER :: count1, count2, i, j
1271 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: map2
1272 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: map1
1273 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp, tmp1
1274 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: tmp_resid
1275 REAL(kind=
dp),
DIMENSION(2) :: myrange
1281 ms_vib%mat_size =
SIZE(ms_vib%b_mat, 2)
1282 ALLOCATE (map1(
SIZE(eigenval), 2))
1283 ALLOCATE (tmp(
SIZE(eigenval)))
1284 DO i = 1,
SIZE(eigenval)
1285 IF (abs(eigenval(i) - myrange(1)) + abs(eigenval(i) - myrange(2)) <= &
1286 abs(myrange(1) - myrange(2)) + myrange(1)*0.001_dp)
THEN
1292 tmp(count2) = min(abs(eigenval(i) - myrange(1)), abs(eigenval(i) - myrange(2)))
1296 IF (count1 == nrep)
THEN
1298 DO i = 1, ms_vib%mat_size
1299 residuum(:, j) = residuum(:, j) + approx_h(i, map1(j, 1))*(ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
1303 ELSE IF (count1 > nrep)
THEN
1304 ALLOCATE (tmp_resid(
SIZE(ms_vib%b_mat, 1), count1))
1305 ALLOCATE (tmp1(count1))
1306 ALLOCATE (map2(count1))
1309 DO i = 1, ms_vib%mat_size
1310 tmp_resid(:, j) = tmp_resid(:, j) + approx_h(i, map1(j, 1))* &
1311 (ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
1316 DO i = 1, ms_vib%mat_size
1317 tmp_resid(:, j) = tmp_resid(:, j) - dot_product(tmp_resid(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
1319 tmp(j) = maxval(tmp_resid(:, j))
1321 CALL sort(tmp, count1, map2)
1323 residuum(:, j) = tmp_resid(:, map2(count1 + 1 - j))
1324 ind(j) = map1(map2(count1 + 1 - j), 1)
1326 DEALLOCATE (tmp_resid)
1329 ELSE IF (count1 < nrep)
THEN
1331 ALLOCATE (map2(count2))
1332 IF (count1 /= 0)
THEN
1334 DO i = 1, ms_vib%mat_size
1335 residuum(:, j) = residuum(:, j) + approx_h(i, map1(j, 1))* &
1336 (ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
1341 CALL sort(tmp, count2, map2)
1342 DO j = 1, nrep - count1
1343 DO i = 1, ms_vib%mat_size
1344 residuum(:, count1 + j) = residuum(:, count1 + j) + approx_h(i, map1(map2(j), 2)) &
1345 *(ms_vib%s_mat(:, i) - eigenval(map1(map2(j), 2))*ms_vib%b_mat(:, i))
1347 ind(count1 + j) = map1(map2(j), 2)
1356 END SUBROUTINE get_vibs_in_range
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Handles all functions related to the CELL.
Utility routines to open and close files. Tracking of preconnections.
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
various routines to log and control the output. The idea is that decisions about where to log should ...
integer function, public cp_logger_get_default_io_unit(logger)
returns the unit nr for the ionode (-1 on all other processors) skips as well checks if the procs cal...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
set of type/routines to handle the storage of results in force_envs
Define type storing the global information of a run. Keep the amount of stored data small....
Defines the basic variable types.
integer, parameter, public max_line_length
integer, parameter, public dp
integer, parameter, public default_string_length
integer, parameter, public default_path_length
Collection of simple mathematical functions and subroutines.
subroutine, public diamat_all(a, eigval, dac)
Diagonalize the symmetric n by n matrix a using the LAPACK library. Only the upper triangle of matrix...
Interface to the message passing library MPI.
Module performing a mdoe selective vibrational analysis.
subroutine, public ms_vb_anal(input, rep_env, para_env, globenv, particles, nrep, calc_intens, dx, output_unit, logger, cell)
Module performing a vibrational analysis.
Functions handling the MOLDEN format. Split from mode_selective.
subroutine, public write_vibrations_molden(input, particles, freq, eigen_vec, intensities, calc_intens, dump_only_positive, logger, list, cell)
writes the output for vibrational analysis in MOLDEN format
Define the data structure for the particle information.
Definition of physical constants:
real(kind=dp), parameter, public vibfac
real(kind=dp), parameter, public massunit
real(kind=dp), parameter, public bohr
real(kind=dp), parameter, public debye
methods to setup replicas of the same system differing only by atom positions and velocities (as used...
subroutine, public rep_env_calc_e_f(rep_env, calc_f)
evaluates the forces
types used to handle many replica of the same system that differ only in atom positions,...
All kind of helpful little routines.
Type defining parameters related to the simulation cell.
type of a logger, at the moment it contains just a print level starting at which level it should be l...
contains the initially parsed file and the initial parallel environment
stores all the informations relevant to an mpi environment
keeps replicated information about the replicas