54#include "./base/base_uses.f90"
59 CHARACTER(len=*),
PARAMETER,
PRIVATE :: moduleN =
'mode_selective'
60 LOGICAL,
PARAMETER :: debug_this_module = .false.
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
101 SUBROUTINE ms_vb_anal(input, rep_env, para_env, globenv, particles, &
102 nrep, calc_intens, dx, output_unit, logger)
109 LOGICAL :: calc_intens
111 INTEGER :: output_unit
114 CHARACTER(len=*),
PARAMETER :: routinen =
'ms_vb_anal'
116 CHARACTER(LEN=default_string_length) :: description
117 INTEGER :: handle, i, ip1, j, natoms, ncoord
119 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: mass, pos0
120 REAL(kind=
dp),
DIMENSION(:, :),
POINTER :: tmp_deriv
121 REAL(kind=
dp),
DIMENSION(:, :, :),
POINTER :: tmp_dip
122 TYPE(ms_vib_type) :: ms_vib
124 CALL timeset(routinen, handle)
126 natoms =
SIZE(particles)
128 ALLOCATE (mass(3*natoms))
131 mass((i - 1)*3 + j) = particles(i)%atomic_kind%mass
132 mass((i - 1)*3 + j) = sqrt(mass((i - 1)*3 + j))
136 ALLOCATE (ms_vib%delta_vec(ncoord, nrep))
137 ALLOCATE (ms_vib%b_vec(ncoord, nrep))
138 ALLOCATE (ms_vib%step_r(nrep))
139 ALLOCATE (ms_vib%step_b(nrep))
140 IF (calc_intens)
THEN
141 description =
'[DIPOLE]'
142 ALLOCATE (tmp_dip(nrep, 3, 2))
143 ALLOCATE (ms_vib%dip_deriv(3, nrep))
145 CALL ms_initial_moves(para_env, nrep, input, globenv, ms_vib, &
151 ALLOCATE (pos0(ncoord))
152 ALLOCATE (ms_vib%ms_force(ncoord, nrep))
155 pos0((i - 1)*3 + j) = particles((i))%r(j)
160 ms_vib%ms_force = huge(0.0_dp)
163 rep_env%r(j, i) = pos0(j) + ms_vib%step_r(i)*ms_vib%delta_vec(j, i)
169 IF (calc_intens)
THEN
170 CALL get_results(results=rep_env%results(i)%results, &
171 description=description, &
173 CALL get_results(results=rep_env%results(i)%results, &
174 description=description, &
175 values=tmp_dip(i, :, 1), &
179 ms_vib%ms_force(j, i) = rep_env%f(j, i)
184 rep_env%r(j, i) = pos0(j) - ms_vib%step_r(i)*ms_vib%delta_vec(j, i)
188 IF (calc_intens)
THEN
190 CALL get_results(results=rep_env%results(i)%results, &
191 description=description, &
193 CALL get_results(results=rep_env%results(i)%results, &
194 description=description, &
195 values=tmp_dip(i, :, 2), &
197 ms_vib%dip_deriv(:, ms_vib%mat_size + i) = (tmp_dip(i, :, 1) - tmp_dip(i, :, 2))/(2*ms_vib%step_b(i))
201 CALL evaluate_h_update_b(rep_env, ms_vib, input, nrep, &
208 IF (calc_intens)
THEN
209 ALLOCATE (tmp_deriv(3, ms_vib%mat_size))
210 tmp_deriv = ms_vib%dip_deriv
211 DEALLOCATE (ms_vib%dip_deriv)
212 ALLOCATE (ms_vib%dip_deriv(3, ms_vib%mat_size + nrep))
213 ms_vib%dip_deriv(:, 1:ms_vib%mat_size) = tmp_deriv(:, 1:ms_vib%mat_size)
214 DEALLOCATE (tmp_deriv)
217 DEALLOCATE (ms_vib%ms_force)
219 DEALLOCATE (ms_vib%step_r)
220 DEALLOCATE (ms_vib%step_b)
221 DEALLOCATE (ms_vib%b_vec)
222 DEALLOCATE (ms_vib%delta_vec)
224 DEALLOCATE (ms_vib%b_mat)
225 DEALLOCATE (ms_vib%s_mat)
226 IF (ms_vib%select_id == 3)
THEN
227 DEALLOCATE (ms_vib%inv_atoms)
229 IF (
ASSOCIATED(ms_vib%eig_bfgs))
THEN
230 DEALLOCATE (ms_vib%eig_bfgs)
232 IF (
ASSOCIATED(ms_vib%hes_bfgs))
THEN
233 DEALLOCATE (ms_vib%hes_bfgs)
235 IF (calc_intens)
THEN
236 DEALLOCATE (ms_vib%dip_deriv)
239 CALL timestop(handle)
256 SUBROUTINE ms_initial_moves(para_env, nrep, input, globenv, ms_vib, particles, &
263 TYPE(ms_vib_type) :: ms_vib
265 REAL(kind=
dp),
DIMENSION(:) :: mass
267 LOGICAL :: calc_intens
270 CHARACTER(len=*),
PARAMETER :: routinen =
'MS_initial_moves'
272 INTEGER :: guess, handle, i, j, jj, k, m, &
273 n_rep_val, natoms, ncoord
274 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: map_atoms
275 INTEGER,
DIMENSION(:),
POINTER :: tmplist
276 LOGICAL :: do_involved_atoms, ionode
277 REAL(kind=
dp) :: my_val, norm
280 CALL timeset(routinen, handle)
281 NULLIFY (ms_vib%eig_bfgs, ms_vib%f_range, ms_vib%hes_bfgs, ms_vib%inv_range)
288 IF (n_rep_val /= 0)
THEN
290 IF (ms_vib%f_range(1) > ms_vib%f_range(2))
THEN
291 my_val = ms_vib%f_range(2)
292 ms_vib%f_range(2) = ms_vib%f_range(1)
293 ms_vib%f_range(1) = my_val
299 IF (ms_vib%sel_freq > 0._dp) ms_vib%select_id = 1
302 IF (do_involved_atoms)
THEN
307 DO j = 1,
SIZE(tmplist)
313 ALLOCATE (ms_vib%inv_atoms(natoms))
317 DO j = 1,
SIZE(tmplist)
318 ms_vib%inv_atoms(j) = tmplist(j)
324 IF (n_rep_val /= 0)
THEN
326 IF (ms_vib%inv_range(1) > ms_vib%inv_range(2))
THEN
327 ms_vib%inv_range(2) = my_val
328 ms_vib%inv_range(2) = ms_vib%inv_range(1)
329 ms_vib%inv_range(1) = my_val
333 IF (ms_vib%select_id == 0)
THEN
334 cpabort(
"no frequency, range or involved atoms specified ")
336 ionode = para_env%is_source()
339 ms_vib%initial_guess = 1
344 DO j = 1,
SIZE(tmplist)
349 natoms =
SIZE(particles)
350 ALLOCATE (map_atoms(natoms))
356 ALLOCATE (map_atoms(natoms))
360 DO j = 1,
SIZE(tmplist)
361 map_atoms(j) = tmplist(j)
368 ms_vib%delta_vec = 0._dp
374 jj = (map_atoms(j) - 1)*3 + k
375 ms_vib%b_vec(jj, i) = abs(globenv%gaussian_rng_stream%next())
378 norm = norm2(ms_vib%b_vec(:, i))
379 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
387 ms_vib%b_vec(:, j) = &
388 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 ms_vib%b_vec(:, j)/norm2(ms_vib%b_vec(:, j))
398 DO i = 1,
SIZE(ms_vib%b_vec, 1)
399 ms_vib%delta_vec(i, :) = ms_vib%b_vec(i, :)/mass(i)
403 ms_vib%initial_guess = 2
404 CALL bfgs_guess(ms_vib_section, ms_vib, particles, mass, para_env, nrep)
409 ms_vib%initial_guess = 3
410 ncoord = 3*
SIZE(particles)
411 CALL rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
415 ms_vib%initial_guess = 4
416 ncoord = 3*
SIZE(particles)
417 CALL rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
420 ms_vib%initial_guess = 5
421 ncoord = 3*
SIZE(particles)
422 CALL molden_guess(ms_vib_section, input, para_env, ms_vib, mass, ncoord, nrep, logger)
425 CALL para_env%bcast(ms_vib%b_vec)
426 CALL para_env%bcast(ms_vib%delta_vec)
428 ms_vib%step_r(i) = dx/norm2(ms_vib%delta_vec(:, i))
429 ms_vib%step_b(i) = norm2(ms_vib%step_r(i)*ms_vib%b_vec(:, i))
431 CALL timestop(handle)
433 END SUBROUTINE ms_initial_moves
445 SUBROUTINE bfgs_guess(ms_vib_section, ms_vib, particles, mass, para_env, nrep)
448 TYPE(ms_vib_type) :: ms_vib
450 REAL(kind=
dp),
DIMENSION(:) :: mass
454 CHARACTER(LEN=default_path_length) :: hes_filename
455 INTEGER :: hesunit, i, istat, j, jj, k, natoms, &
456 ncoord, output_unit, stat
457 INTEGER,
DIMENSION(:),
POINTER :: tmplist
458 REAL(kind=
dp) :: my_val, norm
459 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp
465 natoms =
SIZE(particles)
468 ALLOCATE (ms_vib%hes_bfgs(ncoord, ncoord))
469 ALLOCATE (ms_vib%eig_bfgs(ncoord))
471 IF (para_env%is_source())
THEN
473 IF (hes_filename ==
"") hes_filename =
"HESSIAN"
474 CALL open_file(file_name=hes_filename, file_status=
"OLD", &
475 file_form=
"UNFORMATTED", file_action=
"READ", unit_number=hesunit)
476 ALLOCATE (tmp(ncoord))
477 ALLOCATE (tmplist(ncoord))
482 READ (unit=hesunit, iostat=stat) ms_vib%hes_bfgs(:, i)
486 IF (output_unit > 0)
THEN
488 WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading HESSIAN **"
490 WRITE (output_unit, fmt=
"(/,T2,A)") &
491 "*** Initial Hessian has been read successfully ***"
496 ms_vib%hes_bfgs(i, j) = ms_vib%hes_bfgs(i, j)/(mass(i)*mass(j))
500 CALL diamat_all(ms_vib%hes_bfgs, ms_vib%eig_bfgs)
502 IF (ms_vib%select_id == 1) my_val = (ms_vib%sel_freq/
vibfac)**2/
massunit
503 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 IF (ms_vib%select_id == 1 .OR. ms_vib%select_id == 2)
THEN
506 tmp(i) = abs(my_val - ms_vib%eig_bfgs(i))
508 ELSE IF (ms_vib%select_id == 3)
THEN
510 DO j = 1,
SIZE(ms_vib%inv_atoms)
512 jj = (ms_vib%inv_atoms(j) - 1)*3 + k
513 tmp(i) = tmp(i) + sqrt(ms_vib%hes_bfgs(jj, i)**2)
516 IF ((sign(1._dp, ms_vib%eig_bfgs(i))*sqrt(abs(ms_vib%eig_bfgs(i))*
massunit)*
vibfac) <= 400._dp) tmp(i) = 0._dp
520 CALL sort(tmp, ncoord, tmplist)
522 ms_vib%b_vec(:, i) = ms_vib%hes_bfgs(:, tmplist(i))
523 norm = norm2(ms_vib%b_vec(:, i))
524 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
526 DO i = 1,
SIZE(ms_vib%b_vec, 1)
527 ms_vib%delta_vec(i, :) = ms_vib%b_vec(i, :)/mass(i)
533 CALL para_env%bcast(ms_vib%b_vec)
534 CALL para_env%bcast(ms_vib%delta_vec)
536 DEALLOCATE (ms_vib%hes_bfgs)
537 DEALLOCATE (ms_vib%eig_bfgs)
540 END SUBROUTINE bfgs_guess
554 SUBROUTINE rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
558 TYPE(ms_vib_type) :: ms_vib
559 REAL(kind=
dp),
DIMENSION(:) :: mass
563 LOGICAL :: calc_intens
565 CHARACTER(LEN=default_path_length) :: ms_filename
566 INTEGER :: hesunit, i, j, mat, natoms, ncoord, &
567 output_unit, stat, statint
568 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ind
569 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval
570 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: approx_h
576 natoms =
SIZE(particles)
578 IF (calc_intens)
THEN
579 DEALLOCATE (ms_vib%dip_deriv)
585 IF (ms_filename ==
"") ms_filename =
"MS_RESTART"
587 file_status=
"UNKNOWN", &
588 file_form=
"UNFORMATTED", &
589 file_action=
"READ", &
591 READ (unit=hesunit, iostat=stat) mat
593 ms_vib%mat_size = mat
595 CALL para_env%bcast(ms_vib%mat_size)
596 ALLOCATE (ms_vib%b_mat(ncoord, ms_vib%mat_size))
597 ALLOCATE (ms_vib%s_mat(ncoord, ms_vib%mat_size))
598 IF (calc_intens)
THEN
599 ALLOCATE (ms_vib%dip_deriv(3, ms_vib%mat_size + nrep))
603 READ (unit=hesunit) ms_vib%b_mat
604 READ (unit=hesunit, iostat=stat) ms_vib%s_mat
605 IF (stat /= 0 .AND. output_unit > 0)
THEN
606 WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading MS_RESTART **"
608 IF (calc_intens)
THEN
609 READ (unit=hesunit, iostat=statint) ms_vib%dip_deriv(:, 1:ms_vib%mat_size)
610 IF (statint /= 0 .AND. output_unit > 0)
WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading MS_RESTART,", &
611 "intensities are requested but not present in restart file **"
614 IF (stat == 0 .AND. statint == 0 .AND. output_unit > 0)
THEN
615 WRITE (output_unit, fmt=
"(/,T2,A)")
"*** MS_RESTART has been read successfully ***"
618 CALL para_env%bcast(ms_vib%b_mat)
619 CALL para_env%bcast(ms_vib%s_mat)
620 IF (calc_intens)
CALL para_env%bcast(ms_vib%dip_deriv)
621 ALLOCATE (approx_h(ms_vib%mat_size, ms_vib%mat_size))
622 ALLOCATE (eigenval(ms_vib%mat_size))
623 ALLOCATE (ind(ms_vib%mat_size))
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 ms_vib%s_mat,
SIZE(ms_vib%s_mat, 1), 0._dp, approx_h, ms_vib%mat_size)
629 CALL select_vector(ms_vib, nrep, mass, ncoord, approx_h, eigenval, ind, ms_vib%b_vec)
630 IF (ms_vib%initial_guess /= 4)
THEN
634 DO j = 1, ms_vib%mat_size
635 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i) + approx_h(j, ind(i))*ms_vib%b_mat(:, j)
637 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm2(ms_vib%b_vec(:, i))
640 DEALLOCATE (ms_vib%s_mat)
641 DEALLOCATE (ms_vib%b_mat)
642 IF (calc_intens)
THEN
643 DEALLOCATE (ms_vib%dip_deriv)
644 ALLOCATE (ms_vib%dip_deriv(3, nrep))
647 DEALLOCATE (approx_h)
648 DEALLOCATE (eigenval)
651 ms_vib%delta_vec(:, i) = ms_vib%b_vec(:, i)/mass(:)
654 END SUBROUTINE rest_guess
668 SUBROUTINE molden_guess(ms_vib_section, input, para_env, ms_vib, mass, ncoord, nrep, logger)
671 TYPE(ms_vib_type) :: ms_vib
672 REAL(kind=
dp),
DIMENSION(:) :: mass
673 INTEGER :: ncoord, nrep
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 INTEGER,
DIMENSION(:),
POINTER :: tmplist
682 LOGICAL :: reading_vib
683 REAL(kind=
dp) :: my_val, norm
684 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: freq, tmp
685 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: modes
686 REAL(kind=
dp),
DIMENSION(3, ncoord/3) :: pos
691 IF (ms_filename ==
"") output_molden = &
693 extension=
".mol", file_status=
'UNKNOWN', &
695 IF (para_env%is_source())
THEN
697 IF (ms_filename ==
"")
THEN
700 CALL open_file(file_name=trim(ms_filename), &
701 file_status=
"UNKNOWN", &
702 file_form=
"FORMATTED", &
703 file_action=
"READ", &
711 reading_vib = .false.
713 READ (iw, *, iostat=stat) info
715 IF (trim(adjustl(info)) ==
"[FR-COORD]")
EXIT
719 IF (reading_vib) nvibs = nvibs + 1
720 IF (trim(adjustl(info)) ==
"[FREQ]") reading_vib = .true.
724 READ (iw, *, iostat=stat) info
726 READ (iw, *, iostat=stat) info
730 READ (iw, *, iostat=stat) info
733 IF (trim(adjustl(info)) ==
"[FREQ]")
EXIT
736 ALLOCATE (freq(nvibs))
737 ALLOCATE (modes(ncoord, nvibs))
740 READ (iw, *, iostat=stat) freq(i)
745 READ (iw, *, iostat=stat) at_name, pos(:, i)
754 READ (iw, *, iostat=stat) modes(k:k + 2, i)
759 IF (output_unit > 0)
THEN
761 WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading MOLDEN file **"
763 WRITE (output_unit, fmt=
"(/,T2,A)")
"*** MOLDEN file has been read successfully ***"
767 ALLOCATE (tmp(nvibs))
769 ALLOCATE (tmplist(nvibs))
770 IF (ms_vib%select_id == 1) my_val = ms_vib%sel_freq
771 IF (ms_vib%select_id == 2) my_val = (ms_vib%f_range(2) + ms_vib%f_range(1))*0.5_dp
772 IF (ms_vib%select_id == 1 .OR. ms_vib%select_id == 2)
THEN
774 tmp(i) = abs(my_val - freq(i))
776 ELSE IF (ms_vib%select_id == 3)
THEN
778 DO j = 1,
SIZE(ms_vib%inv_atoms)
780 jj = (ms_vib%inv_atoms(j) - 1)*3 + k
781 tmp(i) = tmp(i) + sqrt(modes(jj, i)**2)
784 IF (freq(i) <= 400._dp) tmp(i) = 0._dp
788 CALL sort(tmp, nvibs, tmplist)
790 ms_vib%b_vec(:, i) = modes(:, tmplist(i))*mass(:)
791 norm = norm2(ms_vib%b_vec(:, i))
792 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
795 ms_vib%delta_vec(:, i) = ms_vib%b_vec(:, i)/mass(:)
804 CALL para_env%bcast(ms_vib%b_vec)
805 CALL para_env%bcast(ms_vib%delta_vec)
808 "VIBRATIONAL_ANALYSIS%PRINT%MOLDEN_VIB")
809 END SUBROUTINE molden_guess
827 SUBROUTINE evaluate_h_update_b(rep_env, ms_vib, input, nrep, &
831 calc_intens, output_unit_ms, logger)
833 TYPE(ms_vib_type) :: ms_vib
837 REAL(kind=
dp),
DIMENSION(:) :: mass
840 LOGICAL :: calc_intens
841 INTEGER :: output_unit_ms
844 INTEGER :: i, j, jj, k, natoms, ncoord
845 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ind
846 LOGICAL :: dump_only_positive
847 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval, freq
848 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: approx_h, h_save, residuum, tmp_b, tmp_s
849 REAL(kind=
dp),
DIMENSION(2, nrep) :: criteria
850 REAL(kind=
dp),
DIMENSION(:),
POINTER :: intensities
852 natoms =
SIZE(particles)
854 nrep =
SIZE(rep_env%f, 2)
857 IF (ms_vib%mat_size /= 0)
THEN
859 ALLOCATE (tmp_b(3*natoms, ms_vib%mat_size))
860 ALLOCATE (tmp_s(3*natoms, ms_vib%mat_size))
862 tmp_b(:, :) = ms_vib%b_mat
863 tmp_s(:, :) = ms_vib%s_mat
865 DEALLOCATE (ms_vib%b_mat)
866 DEALLOCATE (ms_vib%s_mat)
869 ALLOCATE (ms_vib%b_mat(3*natoms, ms_vib%mat_size + nrep))
870 ALLOCATE (ms_vib%s_mat(3*natoms, ms_vib%mat_size + nrep))
872 ms_vib%s_mat = 0.0_dp
875 IF (ms_vib%mat_size /= 0)
THEN
876 DO j = 1, ms_vib%mat_size
877 ms_vib%b_mat(i, j) = tmp_b(i, j)
878 ms_vib%s_mat(i, j) = tmp_s(i, j)
882 ms_vib%b_mat(i, ms_vib%mat_size + j) = ms_vib%b_vec(i, j)
886 IF (ms_vib%mat_size /= 0)
THEN
891 ms_vib%mat_size = ms_vib%mat_size + nrep
893 ALLOCATE (approx_h(ms_vib%mat_size, ms_vib%mat_size))
894 ALLOCATE (h_save(ms_vib%mat_size, ms_vib%mat_size))
895 ALLOCATE (eigenval(ms_vib%mat_size))
901 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))
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 ms_vib%s_mat,
SIZE(ms_vib%s_mat, 1), 0._dp, approx_h, ms_vib%mat_size)
907 h_save(:, :) = approx_h
912 ALLOCATE (ind(ms_vib%mat_size))
913 ALLOCATE (residuum(
SIZE(ms_vib%s_mat, 1), nrep))
915 CALL select_vector(ms_vib, nrep, mass, ncoord, approx_h, eigenval, ind, residuum, criteria)
921 ms_vib%delta_vec(jj, i) = ms_vib%b_vec(jj, i)/mass(jj)
927 ms_vib%step_r(i) = dx/norm2(ms_vib%delta_vec(:, i))
928 ms_vib%step_b(i) = norm2(ms_vib%step_r(i)*ms_vib%b_vec(:, i))
931 IF (maxval(criteria(1, :)) <= ms_vib%eps(1) .AND. maxval(criteria(2, :)) &
932 <= ms_vib%eps(2) .OR. ms_vib%mat_size >= ncoord) converged = .true.
933 ALLOCATE (freq(nrep))
940 eigenval(:) = sign(1._dp, eigenval(:))*sqrt(abs(eigenval(:))*
massunit)*
vibfac
941 ALLOCATE (tmp_b(ncoord, ms_vib%mat_size))
943 ALLOCATE (tmp_s(3, ms_vib%mat_size))
945 IF (calc_intens)
THEN
946 ALLOCATE (intensities(ms_vib%mat_size))
949 DO i = 1, ms_vib%mat_size
950 DO j = 1, ms_vib%mat_size
951 tmp_b(:, i) = tmp_b(:, i) + approx_h(j, i)*ms_vib%b_mat(:, j)/mass(:)
953 tmp_b(:, i) = tmp_b(:, i)/norm2(tmp_b(:, i))
955 IF (calc_intens)
THEN
956 DO i = 1, ms_vib%mat_size
957 DO j = 1, ms_vib%mat_size
958 tmp_s(:, i) = tmp_s(:, i) + ms_vib%dip_deriv(:, j)*approx_h(j, i)
960 IF (calc_intens) intensities(i) = norm2(tmp_s(:, i))
963 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 intensities=intensities, logger=logger)
968 CALL ms_out(output_unit_ms, converged, freq, criteria, ms_vib, &
969 input, nrep, approx_h, eigenval, calc_intens, logger=logger)
971 dump_only_positive = ms_vib%low_freq > 0.0_dp
973 dump_only_positive=dump_only_positive, logger=logger)
974 IF (calc_intens)
THEN
975 DEALLOCATE (intensities)
981 IF (.NOT. converged)
CALL ms_out(output_unit_ms, converged, freq, criteria, &
982 ms_vib, input, nrep, approx_h, eigenval, calc_intens, logger=logger)
985 DEALLOCATE (approx_h)
986 DEALLOCATE (eigenval)
987 DEALLOCATE (residuum)
990 END SUBROUTINE evaluate_h_update_b
1005 SUBROUTINE select_vector(ms_vib, nrep, mass, ncoord, approx_H, eigenval, ind, residuum, criteria)
1007 TYPE(ms_vib_type) :: ms_vib
1009 REAL(kind=
dp),
DIMENSION(:) :: mass
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
1017 INTEGER :: i, j, jj, k
1018 REAL(kind=
dp) :: my_val, norm
1019 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp
1020 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: tmp_b
1022 ALLOCATE (tmp(ms_vib%mat_size))
1024 SELECT CASE (ms_vib%select_id)
1027 DO i = 1, ms_vib%mat_size
1028 tmp(i) = abs(my_val - eigenval(i))
1030 CALL sort(tmp, (ms_vib%mat_size), ind)
1033 DO i = 1, ms_vib%mat_size
1034 residuum(:, j) = residuum(:, j) + approx_h(i, ind(j))*(ms_vib%s_mat(:, i) - eigenval(ind(j))*ms_vib%b_mat(:, i))
1038 CALL get_vibs_in_range(ms_vib, approx_h, eigenval, residuum, nrep, ind)
1041 ALLOCATE (tmp_b(ncoord, ms_vib%mat_size))
1044 DO i = 1, ms_vib%mat_size
1045 DO j = 1, ms_vib%mat_size
1046 tmp_b(:, i) = tmp_b(:, i) + approx_h(j, i)*ms_vib%b_mat(:, j)/mass(:)
1048 tmp_b(:, i) = tmp_b(:, i)/norm2(tmp_b(:, i))
1051 DO i = 1, ms_vib%mat_size
1052 DO j = 1,
SIZE(ms_vib%inv_atoms)
1054 jj = (ms_vib%inv_atoms(j) - 1)*3 + k
1055 tmp(i) = tmp(i) + sqrt(tmp_b(jj, i)**2)
1058 IF (.NOT.
ASSOCIATED(ms_vib%inv_range))
THEN
1059 IF ((sign(1._dp, eigenval(i))*sqrt(abs(eigenval(i))*
massunit)*
vibfac) <= 400._dp) tmp(i) = 0._dp
1061 IF ((sign(1._dp, eigenval(i))*sqrt(abs(eigenval(i))*
massunit)*
vibfac) <= ms_vib%inv_range(1)) tmp(i) = 0._dp
1062 IF ((sign(1._dp, eigenval(i))*sqrt(abs(eigenval(i))*
massunit)*
vibfac) >= ms_vib%inv_range(2)) tmp(i) = 0._dp
1066 CALL sort(tmp, (ms_vib%mat_size), ind)
1067 residuum(:, :) = 0._dp
1070 DO i = 1, ms_vib%mat_size
1071 residuum(:, j) = residuum(:, j) + approx_h(i, ind(j))*(ms_vib%s_mat(:, i) - eigenval(ind(j))*ms_vib%b_mat(:, i))
1078 DO i = 1, ms_vib%mat_size
1079 residuum(:, j) = residuum(:, j) - dot_product(residuum(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
1082 IF (
PRESENT(criteria))
THEN
1084 criteria(1, i) = maxval((residuum(:, i)))
1085 criteria(2, i) = norm2(residuum(:, i))
1090 norm = norm2(residuum(:, i))
1091 residuum(:, i) = residuum(:, i)/norm
1096 DO i = 1, ms_vib%mat_size
1097 residuum(:, j) = residuum(:, j) - dot_product(residuum(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
1098 residuum(:, j) = residuum(:, j)/norm2(residuum(:, j))
1103 residuum(:, j) = residuum(:, j) - dot_product(residuum(:, j), residuum(:, i))*residuum(:, i)
1104 residuum(:, j) = residuum(:, j)/norm2(residuum(:, j))
1110 ms_vib%b_vec = residuum
1112 END SUBROUTINE select_vector
1130 SUBROUTINE ms_out(iw, converged, freq, criter, ms_vib, input, nrep, &
1131 approx_H, eigenval, calc_intens, intensities, logger)
1134 LOGICAL :: converged
1135 REAL(kind=
dp),
DIMENSION(:) :: freq
1136 REAL(kind=
dp),
DIMENSION(:, :) :: criter
1137 TYPE(ms_vib_type) :: ms_vib
1140 REAL(kind=
dp),
DIMENSION(:, :) :: approx_h
1141 REAL(kind=
dp),
DIMENSION(:) :: eigenval
1142 LOGICAL :: calc_intens
1143 REAL(kind=
dp),
DIMENSION(:),
OPTIONAL :: intensities
1146 INTEGER :: i, j, msunit
1147 REAL(kind=
dp) :: crit_a, crit_b, fint, gintval
1148 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: residuum
1152 "VIBRATIONAL_ANALYSIS%MODE_SELECTIVE")
1158 WRITE (iw,
'(T2,A)')
"MS| DAVIDSON ALGORITHM CONVERGED"
1160 WRITE (iw,
'(T2,"MS| TRACKED FREQUENCY (",I0,") IS:",F12.6,3X,A)') i, freq(i),
'cm-1'
1162 ALLOCATE (residuum(
SIZE(ms_vib%b_mat, 1)))
1163 WRITE (iw,
'( /, 1X, 79("-") )')
1164 WRITE (iw,
'( 25X, A)')
'FREQUENCY AND CONVERGENCE LIST'
1165 IF (
PRESENT(intensities))
THEN
1166 WRITE (iw,
'(3X,5(4X, A))')
'FREQUENCY',
'INT[KM/Mole]',
'MAXVAL CRITERIA',
'NORM CRITERIA',
'CONVERGENCE'
1168 WRITE (iw,
'(3X,5(4X, A))')
'FREQUENCY',
'MAXVAL CRITERIA',
'NORM CRITERIA',
'CONVERGENCE'
1170 DO i = 1,
SIZE(ms_vib%b_mat, 2)
1172 DO j = 1,
SIZE(ms_vib%b_mat, 2)
1173 residuum(:) = residuum(:) + approx_h(j, i)*(ms_vib%s_mat(:, j) - eigenval(i)*ms_vib%b_mat(:, j))
1175 DO j = 1, ms_vib%mat_size
1176 residuum(:) = residuum(:) - dot_product(residuum(:), ms_vib%b_mat(:, j))*ms_vib%b_mat(:, j)
1178 crit_a = maxval(residuum(:))
1179 crit_b = norm2(residuum)
1180 IF (
PRESENT(intensities))
THEN
1181 gintval = fint*intensities(i)**2
1182 IF (crit_a <= ms_vib%eps(1) .AND. crit_b <= ms_vib%eps(2))
THEN
1183 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 'VIB|', eigenval(i), gintval, crit_a, crit_b,
'YES'
1186 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 'VIB|', eigenval(i), gintval, crit_a, crit_b,
'NO'
1190 IF (crit_a <= ms_vib%eps(1) .AND. crit_b <= ms_vib%eps(2))
THEN
1191 IF (eigenval(i) > ms_vib%low_freq)
WRITE (iw,
'(2X,A,2X,F9.3,5X,E12.6,5X,E12.3,11X,A)') &
1192 'VIB|', eigenval(i), crit_a, crit_b,
'YES'
1194 IF (eigenval(i) > ms_vib%low_freq)
WRITE (iw,
'(2X,A,2X,F9.3,5X,E12.6,5X,E12.3,11X,A)') &
1195 'VIB|', eigenval(i), crit_a, crit_b,
'NO'
1199 DEALLOCATE (residuum)
1202 "PRINT%MS_RESTART", extension=
".bin", middle_name=
"MS_RESTART", &
1203 file_status=
"REPLACE", file_form=
"UNFORMATTED", &
1204 file_action=
"WRITE")
1206 IF (msunit > 0)
THEN
1207 WRITE (unit=msunit) ms_vib%mat_size
1208 WRITE (unit=msunit) ms_vib%b_mat
1209 WRITE (unit=msunit) ms_vib%s_mat
1210 IF (calc_intens)
WRITE (unit=msunit) ms_vib%dip_deriv
1219 "PRINT%MS_RESTART", extension=
".bin", middle_name=
"MS_RESTART", &
1220 file_status=
"REPLACE", file_form=
"UNFORMATTED", &
1221 file_action=
"WRITE")
1223 IF (msunit > 0)
THEN
1224 WRITE (unit=msunit) ms_vib%mat_size
1225 WRITE (unit=msunit) ms_vib%b_mat
1226 WRITE (unit=msunit) ms_vib%s_mat
1227 IF (calc_intens)
WRITE (unit=msunit) ms_vib%dip_deriv
1233 WRITE (iw,
'(T2,A,3X,I6)')
"MS| ITERATION STEP", ms_vib%mat_size/nrep
1235 IF (criter(1, i) <= 1e-7 .AND. (criter(2, i)) <= 1e-6)
THEN
1236 WRITE (iw,
'(T2,A,3X,F12.6,A)')
"MS| TRACKED MODE ", freq(i),
"cm-1 IS CONVERGED"
1238 WRITE (iw,
'(T2,A,3X,F12.6,A)')
"MS| TRACKED MODE ", freq(i),
"cm-1 NOT CONVERGED"
1244 END SUBROUTINE ms_out
1256 SUBROUTINE get_vibs_in_range(ms_vib, approx_H, eigenval, residuum, nrep, ind)
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
1263 INTEGER,
DIMENSION(:) :: ind
1265 INTEGER :: count1, count2, i, j
1266 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: map2
1267 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: map1
1268 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp, tmp1
1269 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: tmp_resid
1270 REAL(kind=
dp),
DIMENSION(2) :: myrange
1276 ms_vib%mat_size =
SIZE(ms_vib%b_mat, 2)
1277 ALLOCATE (map1(
SIZE(eigenval), 2))
1278 ALLOCATE (tmp(
SIZE(eigenval)))
1279 DO i = 1,
SIZE(eigenval)
1280 IF (abs(eigenval(i) - myrange(1)) + abs(eigenval(i) - myrange(2)) <= &
1281 abs(myrange(1) - myrange(2)) + myrange(1)*0.001_dp)
THEN
1287 tmp(count2) = min(abs(eigenval(i) - myrange(1)), abs(eigenval(i) - myrange(2)))
1291 IF (count1 == nrep)
THEN
1293 DO i = 1, ms_vib%mat_size
1294 residuum(:, j) = residuum(:, j) + approx_h(i, map1(j, 1))*(ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
1298 ELSE IF (count1 > nrep)
THEN
1299 ALLOCATE (tmp_resid(
SIZE(ms_vib%b_mat, 1), count1))
1300 ALLOCATE (tmp1(count1))
1301 ALLOCATE (map2(count1))
1304 DO i = 1, ms_vib%mat_size
1305 tmp_resid(:, j) = tmp_resid(:, j) + approx_h(i, map1(j, 1))* &
1306 (ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
1311 DO i = 1, ms_vib%mat_size
1312 tmp_resid(:, j) = tmp_resid(:, j) - dot_product(tmp_resid(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
1314 tmp(j) = maxval(tmp_resid(:, j))
1316 CALL sort(tmp, count1, map2)
1318 residuum(:, j) = tmp_resid(:, map2(count1 + 1 - j))
1319 ind(j) = map1(map2(count1 + 1 - j), 1)
1321 DEALLOCATE (tmp_resid)
1324 ELSE IF (count1 < nrep)
THEN
1326 ALLOCATE (map2(count2))
1327 IF (count1 /= 0)
THEN
1329 DO i = 1, ms_vib%mat_size
1330 residuum(:, j) = residuum(:, j) + approx_h(i, map1(j, 1))* &
1331 (ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
1336 CALL sort(tmp, count2, map2)
1337 DO j = 1, nrep - count1
1338 DO i = 1, ms_vib%mat_size
1339 residuum(:, count1 + j) = residuum(:, count1 + j) + approx_h(i, map1(map2(j), 2)) &
1340 *(ms_vib%s_mat(:, i) - eigenval(map1(map2(j), 2))*ms_vib%b_mat(:, i))
1342 ind(count1 + j) = map1(map2(j), 2)
1351 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.
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)
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)
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 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