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 .NE. 0)
THEN
290 IF (ms_vib%f_range(1) .GT. 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 .GT. 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 .NE. 0)
THEN
326 IF (ms_vib%inv_range(1) .GT. 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) &
334 cpabort(
"no frequency, range or involved atoms specified ")
335 ionode = para_env%is_source()
338 ms_vib%initial_guess = 1
343 DO j = 1,
SIZE(tmplist)
348 natoms =
SIZE(particles)
349 ALLOCATE (map_atoms(natoms))
355 ALLOCATE (map_atoms(natoms))
359 DO j = 1,
SIZE(tmplist)
360 map_atoms(j) = tmplist(j)
367 ms_vib%delta_vec = 0._dp
373 jj = (map_atoms(j) - 1)*3 + k
374 ms_vib%b_vec(jj, i) = abs(globenv%gaussian_rng_stream%next())
377 norm = sqrt(dot_product(ms_vib%b_vec(:, i), ms_vib%b_vec(:, i)))
378 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
381 IF (nrep .GT. 1)
THEN
386 ms_vib%b_vec(:, j) = &
387 ms_vib%b_vec(:, j) - dot_product(ms_vib%b_vec(:, j), ms_vib%b_vec(:, i))*ms_vib%b_vec(:, i)
388 ms_vib%b_vec(:, j) = &
389 ms_vib%b_vec(:, j)/sqrt(dot_product(ms_vib%b_vec(:, j), ms_vib%b_vec(:, j)))
397 DO i = 1,
SIZE(ms_vib%b_vec, 1)
398 ms_vib%delta_vec(i, :) = ms_vib%b_vec(i, :)/mass(i)
402 ms_vib%initial_guess = 2
403 CALL bfgs_guess(ms_vib_section, ms_vib, particles, mass, para_env, nrep)
408 ms_vib%initial_guess = 3
409 ncoord = 3*
SIZE(particles)
410 CALL rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
414 ms_vib%initial_guess = 4
415 ncoord = 3*
SIZE(particles)
416 CALL rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
419 ms_vib%initial_guess = 5
420 ncoord = 3*
SIZE(particles)
421 CALL molden_guess(ms_vib_section, input, para_env, ms_vib, mass, ncoord, nrep, logger)
424 CALL para_env%bcast(ms_vib%b_vec)
425 CALL para_env%bcast(ms_vib%delta_vec)
427 ms_vib%step_r(i) = dx/sqrt(dot_product(ms_vib%delta_vec(:, i), ms_vib%delta_vec(:, i)))
428 ms_vib%step_b(i) = sqrt(dot_product(ms_vib%step_r(i)*ms_vib%b_vec(:, i), ms_vib%step_r(i)*ms_vib%b_vec(:, i)))
430 CALL timestop(handle)
432 END SUBROUTINE ms_initial_moves
444 SUBROUTINE bfgs_guess(ms_vib_section, ms_vib, particles, mass, para_env, nrep)
447 TYPE(ms_vib_type) :: ms_vib
449 REAL(kind=
dp),
DIMENSION(:) :: mass
453 CHARACTER(LEN=default_path_length) :: hes_filename
454 INTEGER :: hesunit, i, j, jj, k, natoms, ncoord, &
456 INTEGER,
DIMENSION(:),
POINTER :: tmplist
457 REAL(kind=
dp) :: my_val, norm
458 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp
464 natoms =
SIZE(particles)
467 ALLOCATE (ms_vib%hes_bfgs(ncoord, ncoord))
468 ALLOCATE (ms_vib%eig_bfgs(ncoord))
470 IF (para_env%is_source())
THEN
472 IF (hes_filename ==
"") hes_filename =
"HESSIAN"
473 CALL open_file(file_name=hes_filename, file_status=
"OLD", &
474 file_form=
"UNFORMATTED", file_action=
"READ", unit_number=hesunit)
475 ALLOCATE (tmp(ncoord))
476 ALLOCATE (tmplist(ncoord))
480 READ (unit=hesunit, iostat=stat) ms_vib%hes_bfgs(:, i)
483 IF (output_unit > 0)
THEN
485 WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading HESSIAN **"
487 WRITE (output_unit, fmt=
"(/,T2,A)") &
488 "*** Initial Hessian has been read successfully ***"
493 ms_vib%hes_bfgs(i, j) = ms_vib%hes_bfgs(i, j)/(mass(i)*mass(j))
497 CALL diamat_all(ms_vib%hes_bfgs, ms_vib%eig_bfgs)
499 IF (ms_vib%select_id == 1) my_val = (ms_vib%sel_freq/
vibfac)**2/
massunit
500 IF (ms_vib%select_id == 2) my_val = (((ms_vib%f_range(2) + ms_vib%f_range(1))*0.5_dp)/
vibfac)**2/
massunit
501 IF (ms_vib%select_id == 1 .OR. ms_vib%select_id == 2)
THEN
503 tmp(i) = abs(my_val - ms_vib%eig_bfgs(i))
505 ELSE IF (ms_vib%select_id == 3)
THEN
507 DO j = 1,
SIZE(ms_vib%inv_atoms)
509 jj = (ms_vib%inv_atoms(j) - 1)*3 + k
510 tmp(i) = tmp(i) + sqrt(ms_vib%hes_bfgs(jj, i)**2)
513 IF ((sign(1._dp, ms_vib%eig_bfgs(i))*sqrt(abs(ms_vib%eig_bfgs(i))*
massunit)*
vibfac) .LE. 400._dp) tmp(i) = 0._dp
517 CALL sort(tmp, ncoord, tmplist)
519 ms_vib%b_vec(:, i) = ms_vib%hes_bfgs(:, tmplist(i))
520 norm = sqrt(dot_product(ms_vib%b_vec(:, i), ms_vib%b_vec(:, i)))
521 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
523 DO i = 1,
SIZE(ms_vib%b_vec, 1)
524 ms_vib%delta_vec(i, :) = ms_vib%b_vec(i, :)/mass(i)
530 CALL para_env%bcast(ms_vib%b_vec)
531 CALL para_env%bcast(ms_vib%delta_vec)
533 DEALLOCATE (ms_vib%hes_bfgs)
534 DEALLOCATE (ms_vib%eig_bfgs)
537 END SUBROUTINE bfgs_guess
551 SUBROUTINE rest_guess(ms_vib_section, para_env, ms_vib, mass, ionode, particles, nrep, calc_intens)
555 TYPE(ms_vib_type) :: ms_vib
556 REAL(kind=
dp),
DIMENSION(:) :: mass
560 LOGICAL :: calc_intens
562 CHARACTER(LEN=default_path_length) :: ms_filename
563 INTEGER :: hesunit, i, j, mat, natoms, ncoord, &
564 output_unit, stat, statint
565 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ind
566 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval
567 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: approx_h
573 natoms =
SIZE(particles)
575 IF (calc_intens)
THEN
576 DEALLOCATE (ms_vib%dip_deriv)
582 IF (ms_filename ==
"") ms_filename =
"MS_RESTART"
584 file_status=
"UNKNOWN", &
585 file_form=
"UNFORMATTED", &
586 file_action=
"READ", &
588 READ (unit=hesunit, iostat=stat) mat
590 ms_vib%mat_size = mat
592 CALL para_env%bcast(ms_vib%mat_size)
593 ALLOCATE (ms_vib%b_mat(ncoord, ms_vib%mat_size))
594 ALLOCATE (ms_vib%s_mat(ncoord, ms_vib%mat_size))
595 IF (calc_intens)
THEN
596 ALLOCATE (ms_vib%dip_deriv(3, ms_vib%mat_size + nrep))
600 READ (unit=hesunit, iostat=stat) ms_vib%b_mat
601 READ (unit=hesunit, iostat=stat) ms_vib%s_mat
602 IF (calc_intens)
READ (unit=hesunit, iostat=statint) ms_vib%dip_deriv(:, 1:ms_vib%mat_size)
603 IF (statint /= 0 .AND. output_unit > 0)
WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading MS_RESTART,", &
604 "intensities are requested but not present in restart file **"
606 IF (output_unit > 0)
THEN
608 WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading MS_RESTART **"
610 WRITE (output_unit, fmt=
"(/,T2,A)")
"*** RESTART has been read successfully ***"
614 CALL para_env%bcast(ms_vib%b_mat)
615 CALL para_env%bcast(ms_vib%s_mat)
616 IF (calc_intens)
CALL para_env%bcast(ms_vib%dip_deriv)
617 ALLOCATE (approx_h(ms_vib%mat_size, ms_vib%mat_size))
618 ALLOCATE (eigenval(ms_vib%mat_size))
619 ALLOCATE (ind(ms_vib%mat_size))
621 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), &
622 ms_vib%s_mat,
SIZE(ms_vib%s_mat, 1), 0._dp, approx_h, ms_vib%mat_size)
625 CALL select_vector(ms_vib, nrep, mass, ncoord, approx_h, eigenval, ind, ms_vib%b_vec)
626 IF (ms_vib%initial_guess .NE. 4)
THEN
630 DO j = 1, ms_vib%mat_size
631 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i) + approx_h(j, ind(i))*ms_vib%b_mat(:, j)
633 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/sqrt(dot_product(ms_vib%b_vec(:, i), ms_vib%b_vec(:, i)))
636 DEALLOCATE (ms_vib%s_mat)
637 DEALLOCATE (ms_vib%b_mat)
638 IF (calc_intens)
THEN
639 DEALLOCATE (ms_vib%dip_deriv)
640 ALLOCATE (ms_vib%dip_deriv(3, nrep))
643 DEALLOCATE (approx_h)
644 DEALLOCATE (eigenval)
647 ms_vib%delta_vec(:, i) = ms_vib%b_vec(:, i)/mass(:)
650 END SUBROUTINE rest_guess
664 SUBROUTINE molden_guess(ms_vib_section, input, para_env, ms_vib, mass, ncoord, nrep, logger)
667 TYPE(ms_vib_type) :: ms_vib
668 REAL(kind=
dp),
DIMENSION(:) :: mass
669 INTEGER :: ncoord, nrep
672 CHARACTER(LEN=2) :: at_name
673 CHARACTER(LEN=default_path_length) :: ms_filename
674 CHARACTER(LEN=max_line_length) :: info
675 INTEGER :: i, istat, iw, j, jj, k, nvibs, &
676 output_molden, output_unit, stat
677 INTEGER,
DIMENSION(:),
POINTER :: tmplist
678 LOGICAL :: reading_vib
679 REAL(kind=
dp) :: my_val, norm
680 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: freq, tmp
681 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: modes
682 REAL(kind=
dp),
DIMENSION(3, ncoord/3) :: pos
687 IF (ms_filename ==
"") output_molden = &
689 extension=
".mol", file_status=
'UNKNOWN', &
691 IF (para_env%is_source())
THEN
693 IF (ms_filename ==
"")
THEN
696 CALL open_file(file_name=trim(ms_filename), &
697 file_status=
"UNKNOWN", &
698 file_form=
"FORMATTED", &
699 file_action=
"READ", &
703 READ (iw, *, iostat=stat) info
704 READ (iw, *, iostat=stat) info
707 reading_vib = .false.
709 READ (iw, *, iostat=stat) info
711 IF (trim(adjustl(info)) ==
"[FR-COORD]")
EXIT
715 IF (reading_vib) nvibs = nvibs + 1
716 IF (trim(adjustl(info)) ==
"[FREQ]") reading_vib = .true.
720 READ (iw, *, iostat=stat) info
722 READ (iw, *, iostat=stat) info
726 READ (iw, *, iostat=stat) info
729 IF (trim(adjustl(info)) ==
"[FREQ]")
EXIT
732 ALLOCATE (freq(nvibs))
733 ALLOCATE (modes(ncoord, nvibs))
736 READ (iw, *, iostat=stat) freq(i)
741 READ (iw, *, iostat=stat) at_name, pos(:, i)
750 READ (iw, *, iostat=stat) modes(k:k + 2, i)
755 IF (output_unit > 0)
THEN
757 WRITE (output_unit, fmt=
"(/,T2,A)")
"** Error while reading MOLDEN file **"
759 WRITE (output_unit, fmt=
"(/,T2,A)")
"*** MOLDEN file has been read successfully ***"
763 ALLOCATE (tmp(nvibs))
765 ALLOCATE (tmplist(nvibs))
766 IF (ms_vib%select_id == 1) my_val = ms_vib%sel_freq
767 IF (ms_vib%select_id == 2) my_val = (ms_vib%f_range(2) + ms_vib%f_range(1))*0.5_dp
768 IF (ms_vib%select_id == 1 .OR. ms_vib%select_id == 2)
THEN
770 tmp(i) = abs(my_val - freq(i))
772 ELSE IF (ms_vib%select_id == 3)
THEN
774 DO j = 1,
SIZE(ms_vib%inv_atoms)
776 jj = (ms_vib%inv_atoms(j) - 1)*3 + k
777 tmp(i) = tmp(i) + sqrt(modes(jj, i)**2)
780 IF (freq(i) .LE. 400._dp) tmp(i) = 0._dp
784 CALL sort(tmp, nvibs, tmplist)
786 ms_vib%b_vec(:, i) = modes(:, tmplist(i))*mass(:)
787 norm = sqrt(dot_product(ms_vib%b_vec(:, i), ms_vib%b_vec(:, i)))
788 ms_vib%b_vec(:, i) = ms_vib%b_vec(:, i)/norm
791 ms_vib%delta_vec(:, i) = ms_vib%b_vec(:, i)/mass(:)
800 CALL para_env%bcast(ms_vib%b_vec)
801 CALL para_env%bcast(ms_vib%delta_vec)
804 "VIBRATIONAL_ANALYSIS%PRINT%MOLDEN_VIB")
805 END SUBROUTINE molden_guess
823 SUBROUTINE evaluate_h_update_b(rep_env, ms_vib, input, nrep, &
827 calc_intens, output_unit_ms, logger)
829 TYPE(ms_vib_type) :: ms_vib
833 REAL(kind=
dp),
DIMENSION(:) :: mass
836 LOGICAL :: calc_intens
837 INTEGER :: output_unit_ms
840 INTEGER :: i, j, jj, k, natoms, ncoord
841 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: ind
842 LOGICAL :: dump_only_positive
843 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: eigenval, freq
844 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: approx_h, h_save, residuum, tmp_b, tmp_s
845 REAL(kind=
dp),
DIMENSION(2, nrep) :: criteria
846 REAL(kind=
dp),
DIMENSION(:),
POINTER :: intensities
848 natoms =
SIZE(particles)
850 nrep =
SIZE(rep_env%f, 2)
853 IF (ms_vib%mat_size .NE. 0)
THEN
855 ALLOCATE (tmp_b(3*natoms, ms_vib%mat_size))
856 ALLOCATE (tmp_s(3*natoms, ms_vib%mat_size))
858 tmp_b(:, :) = ms_vib%b_mat
859 tmp_s(:, :) = ms_vib%s_mat
861 DEALLOCATE (ms_vib%b_mat)
862 DEALLOCATE (ms_vib%s_mat)
865 ALLOCATE (ms_vib%b_mat(3*natoms, ms_vib%mat_size + nrep))
866 ALLOCATE (ms_vib%s_mat(3*natoms, ms_vib%mat_size + nrep))
868 ms_vib%s_mat = 0.0_dp
871 IF (ms_vib%mat_size .NE. 0)
THEN
872 DO j = 1, ms_vib%mat_size
873 ms_vib%b_mat(i, j) = tmp_b(i, j)
874 ms_vib%s_mat(i, j) = tmp_s(i, j)
878 ms_vib%b_mat(i, ms_vib%mat_size + j) = ms_vib%b_vec(i, j)
882 IF (ms_vib%mat_size .NE. 0)
THEN
887 ms_vib%mat_size = ms_vib%mat_size + nrep
889 ALLOCATE (approx_h(ms_vib%mat_size, ms_vib%mat_size))
890 ALLOCATE (h_save(ms_vib%mat_size, ms_vib%mat_size))
891 ALLOCATE (eigenval(ms_vib%mat_size))
897 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))
901 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), &
902 ms_vib%s_mat,
SIZE(ms_vib%s_mat, 1), 0._dp, approx_h, ms_vib%mat_size)
903 h_save(:, :) = approx_h
908 ALLOCATE (ind(ms_vib%mat_size))
909 ALLOCATE (residuum(
SIZE(ms_vib%s_mat, 1), nrep))
911 CALL select_vector(ms_vib, nrep, mass, ncoord, approx_h, eigenval, ind, residuum, criteria)
917 ms_vib%delta_vec(jj, i) = ms_vib%b_vec(jj, i)/mass(jj)
923 ms_vib%step_r(i) = dx/sqrt(dot_product(ms_vib%delta_vec(:, i), ms_vib%delta_vec(:, i)))
924 ms_vib%step_b(i) = sqrt(dot_product(ms_vib%step_r(i)*ms_vib%b_vec(:, i), ms_vib%step_r(i)*ms_vib%b_vec(:, i)))
927 IF (maxval(criteria(1, :)) .LE. ms_vib%eps(1) .AND. maxval(criteria(2, :)) &
928 .LE. ms_vib%eps(2) .OR. ms_vib%mat_size .GE. ncoord) converged = .true.
929 ALLOCATE (freq(nrep))
936 eigenval(:) = sign(1._dp, eigenval(:))*sqrt(abs(eigenval(:))*
massunit)*
vibfac
937 ALLOCATE (tmp_b(ncoord, ms_vib%mat_size))
939 ALLOCATE (tmp_s(3, ms_vib%mat_size))
941 IF (calc_intens)
THEN
942 ALLOCATE (intensities(ms_vib%mat_size))
945 DO i = 1, ms_vib%mat_size
946 DO j = 1, ms_vib%mat_size
947 tmp_b(:, i) = tmp_b(:, i) + approx_h(j, i)*ms_vib%b_mat(:, j)/mass(:)
949 tmp_b(:, i) = tmp_b(:, i)/sqrt(dot_product(tmp_b(:, i), tmp_b(:, i)))
951 IF (calc_intens)
THEN
952 DO i = 1, ms_vib%mat_size
953 DO j = 1, ms_vib%mat_size
954 tmp_s(:, i) = tmp_s(:, i) + ms_vib%dip_deriv(:, j)*approx_h(j, i)
956 IF (calc_intens) intensities(i) = sqrt(dot_product(tmp_s(:, i), tmp_s(:, i)))
959 IF (calc_intens)
THEN
960 CALL ms_out(output_unit_ms, converged, freq, criteria, ms_vib, &
961 input, nrep, approx_h, eigenval, calc_intens, &
962 intensities=intensities, logger=logger)
964 CALL ms_out(output_unit_ms, converged, freq, criteria, ms_vib, &
965 input, nrep, approx_h, eigenval, calc_intens, logger=logger)
967 dump_only_positive = ms_vib%low_freq .GT. 0.0_dp
969 dump_only_positive=dump_only_positive, logger=logger)
970 IF (calc_intens)
THEN
971 DEALLOCATE (intensities)
977 IF (.NOT. converged)
CALL ms_out(output_unit_ms, converged, freq, criteria, &
978 ms_vib, input, nrep, approx_h, eigenval, calc_intens, logger=logger)
981 DEALLOCATE (approx_h)
982 DEALLOCATE (eigenval)
983 DEALLOCATE (residuum)
986 END SUBROUTINE evaluate_h_update_b
1001 SUBROUTINE select_vector(ms_vib, nrep, mass, ncoord, approx_H, eigenval, ind, residuum, criteria)
1003 TYPE(ms_vib_type) :: ms_vib
1005 REAL(kind=
dp),
DIMENSION(:) :: mass
1007 REAL(kind=
dp),
DIMENSION(:, :) :: approx_h
1008 REAL(kind=
dp),
DIMENSION(:) :: eigenval
1009 INTEGER,
DIMENSION(:) :: ind
1010 REAL(kind=
dp),
DIMENSION(:, :) :: residuum
1011 REAL(kind=
dp),
DIMENSION(2, nrep),
OPTIONAL :: criteria
1013 INTEGER :: i, j, jj, k
1014 REAL(kind=
dp) :: my_val, norm
1015 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp
1016 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: tmp_b
1018 ALLOCATE (tmp(ms_vib%mat_size))
1020 SELECT CASE (ms_vib%select_id)
1023 DO i = 1, ms_vib%mat_size
1024 tmp(i) = abs(my_val - eigenval(i))
1026 CALL sort(tmp, (ms_vib%mat_size), ind)
1029 DO i = 1, ms_vib%mat_size
1030 residuum(:, j) = residuum(:, j) + approx_h(i, ind(j))*(ms_vib%s_mat(:, i) - eigenval(ind(j))*ms_vib%b_mat(:, i))
1034 CALL get_vibs_in_range(ms_vib, approx_h, eigenval, residuum, nrep, ind)
1037 ALLOCATE (tmp_b(ncoord, ms_vib%mat_size))
1040 DO i = 1, ms_vib%mat_size
1041 DO j = 1, ms_vib%mat_size
1042 tmp_b(:, i) = tmp_b(:, i) + approx_h(j, i)*ms_vib%b_mat(:, j)/mass(:)
1044 tmp_b(:, i) = tmp_b(:, i)/sqrt(dot_product(tmp_b(:, i), tmp_b(:, i)))
1047 DO i = 1, ms_vib%mat_size
1048 DO j = 1,
SIZE(ms_vib%inv_atoms)
1050 jj = (ms_vib%inv_atoms(j) - 1)*3 + k
1051 tmp(i) = tmp(i) + sqrt(tmp_b(jj, i)**2)
1054 IF (.NOT.
ASSOCIATED(ms_vib%inv_range))
THEN
1055 IF ((sign(1._dp, eigenval(i))*sqrt(abs(eigenval(i))*
massunit)*
vibfac) .LE. 400._dp) tmp(i) = 0._dp
1057 IF ((sign(1._dp, eigenval(i))*sqrt(abs(eigenval(i))*
massunit)*
vibfac) .LE. ms_vib%inv_range(1)) tmp(i) = 0._dp
1058 IF ((sign(1._dp, eigenval(i))*sqrt(abs(eigenval(i))*
massunit)*
vibfac) .GE. ms_vib%inv_range(2)) tmp(i) = 0._dp
1062 CALL sort(tmp, (ms_vib%mat_size), ind)
1063 residuum(:, :) = 0._dp
1066 DO i = 1, ms_vib%mat_size
1067 residuum(:, j) = residuum(:, j) + approx_h(i, ind(j))*(ms_vib%s_mat(:, i) - eigenval(ind(j))*ms_vib%b_mat(:, i))
1074 DO i = 1, ms_vib%mat_size
1075 residuum(:, j) = residuum(:, j) - dot_product(residuum(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
1078 IF (
PRESENT(criteria))
THEN
1080 criteria(1, i) = maxval((residuum(:, i)))
1081 criteria(2, i) = sqrt(dot_product(residuum(:, i), residuum(:, i)))
1086 norm = sqrt(dot_product(residuum(:, i), residuum(:, i)))
1087 residuum(:, i) = residuum(:, i)/norm
1092 DO i = 1, ms_vib%mat_size
1093 residuum(:, j) = residuum(:, j) - dot_product(residuum(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
1094 residuum(:, j) = residuum(:, j)/sqrt(dot_product(residuum(:, j), residuum(:, j)))
1096 IF (nrep .GT. 1)
THEN
1099 residuum(:, j) = residuum(:, j) - dot_product(residuum(:, j), residuum(:, i))*residuum(:, i)
1100 residuum(:, j) = residuum(:, j)/sqrt(dot_product(residuum(:, j), residuum(:, j)))
1106 ms_vib%b_vec = residuum
1108 END SUBROUTINE select_vector
1126 SUBROUTINE ms_out(iw, converged, freq, criter, ms_vib, input, nrep, &
1127 approx_H, eigenval, calc_intens, intensities, logger)
1130 LOGICAL :: converged
1131 REAL(kind=
dp),
DIMENSION(:) :: freq
1132 REAL(kind=
dp),
DIMENSION(:, :) :: criter
1133 TYPE(ms_vib_type) :: ms_vib
1136 REAL(kind=
dp),
DIMENSION(:, :) :: approx_h
1137 REAL(kind=
dp),
DIMENSION(:) :: eigenval
1138 LOGICAL :: calc_intens
1139 REAL(kind=
dp),
DIMENSION(:),
OPTIONAL :: intensities
1142 INTEGER :: i, j, msunit, stat
1143 REAL(kind=
dp) :: crit_a, crit_b, fint, gintval
1144 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: residuum
1148 "VIBRATIONAL_ANALYSIS%MODE_SELECTIVE")
1154 WRITE (iw,
'(T2,A)')
"MS| DAVIDSON ALGORITHM CONVERGED"
1156 WRITE (iw,
'(T2,"MS| TRACKED FREQUENCY (",I0,") IS:",F12.6,3X,A)') i, freq(i),
'cm-1'
1158 ALLOCATE (residuum(
SIZE(ms_vib%b_mat, 1)))
1159 WRITE (iw,
'( /, 1X, 79("-") )')
1160 WRITE (iw,
'( 25X, A)')
'FREQUENCY AND CONVERGENCE LIST'
1161 IF (
PRESENT(intensities))
THEN
1162 WRITE (iw,
'(3X,5(4X, A))')
'FREQUENCY',
'INT[KM/Mole]',
'MAXVAL CRITERIA',
'NORM CRITERIA',
'CONVERGENCE'
1164 WRITE (iw,
'(3X,5(4X, A))')
'FREQUENCY',
'MAXVAL CRITERIA',
'NORM CRITERIA',
'CONVERGENCE'
1166 DO i = 1,
SIZE(ms_vib%b_mat, 2)
1168 DO j = 1,
SIZE(ms_vib%b_mat, 2)
1169 residuum(:) = residuum(:) + approx_h(j, i)*(ms_vib%s_mat(:, j) - eigenval(i)*ms_vib%b_mat(:, j))
1171 DO j = 1, ms_vib%mat_size
1172 residuum(:) = residuum(:) - dot_product(residuum(:), ms_vib%b_mat(:, j))*ms_vib%b_mat(:, j)
1174 crit_a = maxval(residuum(:))
1175 crit_b = sqrt(dot_product(residuum, residuum))
1176 IF (
PRESENT(intensities))
THEN
1177 gintval = fint*intensities(i)**2
1178 IF (crit_a .LE. ms_vib%eps(1) .AND. crit_b .LE. ms_vib%eps(2))
THEN
1179 IF (eigenval(i) .GT. ms_vib%low_freq)
WRITE (iw,
'(2X,A,2X,F9.3,1X,F12.6,3X,E12.3,7X,E12.3,11X,A)') &
1180 'VIB|', eigenval(i), gintval, crit_a, crit_b,
'YES'
1182 IF (eigenval(i) .GT. ms_vib%low_freq)
WRITE (iw,
'(2X,A,2X,F9.3,1X,F12.6,3X,E12.3,7X,E12.3,11X,A)') &
1183 'VIB|', eigenval(i), gintval, crit_a, crit_b,
'NO'
1186 IF (crit_a .LE. ms_vib%eps(1) .AND. crit_b .LE. ms_vib%eps(2))
THEN
1187 IF (eigenval(i) .GT. ms_vib%low_freq)
WRITE (iw,
'(2X,A,2X,F9.3,5X,E12.6,5X,E12.3,11X,A)') &
1188 'VIB|', eigenval(i), crit_a, crit_b,
'YES'
1190 IF (eigenval(i) .GT. ms_vib%low_freq)
WRITE (iw,
'(2X,A,2X,F9.3,5X,E12.6,5X,E12.3,11X,A)') &
1191 'VIB|', eigenval(i), crit_a, crit_b,
'NO'
1195 DEALLOCATE (residuum)
1198 "PRINT%MS_RESTART", extension=
".bin", middle_name=
"MS_RESTART", &
1199 file_status=
"REPLACE", file_form=
"UNFORMATTED", &
1200 file_action=
"WRITE")
1202 IF (msunit > 0)
THEN
1203 WRITE (unit=msunit, iostat=stat) ms_vib%mat_size
1204 WRITE (unit=msunit, iostat=stat) ms_vib%b_mat
1205 WRITE (unit=msunit, iostat=stat) ms_vib%s_mat
1206 IF (calc_intens)
WRITE (unit=msunit, iostat=stat) ms_vib%dip_deriv
1215 "PRINT%MS_RESTART", extension=
".bin", middle_name=
"MS_RESTART", &
1216 file_status=
"REPLACE", file_form=
"UNFORMATTED", &
1217 file_action=
"WRITE")
1219 IF (msunit > 0)
THEN
1220 WRITE (unit=msunit, iostat=stat) ms_vib%mat_size
1221 WRITE (unit=msunit, iostat=stat) ms_vib%b_mat
1222 WRITE (unit=msunit, iostat=stat) ms_vib%s_mat
1223 IF (calc_intens)
WRITE (unit=msunit, iostat=stat) ms_vib%dip_deriv
1229 WRITE (iw,
'(T2,A,3X,I6)')
"MS| ITERATION STEP", ms_vib%mat_size/nrep
1231 IF (criter(1, i) .LE. 1e-7 .AND. (criter(2, i)) .LE. 1e-6)
THEN
1232 WRITE (iw,
'(T2,A,3X,F12.6,A)')
"MS| TRACKED MODE ", freq(i),
"cm-1 IS CONVERGED"
1234 WRITE (iw,
'(T2,A,3X,F12.6,A)')
"MS| TRACKED MODE ", freq(i),
"cm-1 NOT CONVERGED"
1240 END SUBROUTINE ms_out
1252 SUBROUTINE get_vibs_in_range(ms_vib, approx_H, eigenval, residuum, nrep, ind)
1254 TYPE(ms_vib_type) :: ms_vib
1255 REAL(kind=
dp),
DIMENSION(:, :) :: approx_h
1256 REAL(kind=
dp),
DIMENSION(:) :: eigenval
1257 REAL(kind=
dp),
DIMENSION(:, :) :: residuum
1259 INTEGER,
DIMENSION(:) :: ind
1261 INTEGER :: count1, count2, i, j
1262 INTEGER,
ALLOCATABLE,
DIMENSION(:) :: map2
1263 INTEGER,
ALLOCATABLE,
DIMENSION(:, :) :: map1
1264 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:) :: tmp, tmp1
1265 REAL(kind=
dp),
ALLOCATABLE,
DIMENSION(:, :) :: tmp_resid
1266 REAL(kind=
dp),
DIMENSION(2) :: myrange
1272 ms_vib%mat_size =
SIZE(ms_vib%b_mat, 2)
1273 ALLOCATE (map1(
SIZE(eigenval), 2))
1274 ALLOCATE (tmp(
SIZE(eigenval)))
1275 DO i = 1,
SIZE(eigenval)
1276 IF (abs(eigenval(i) - myrange(1)) + abs(eigenval(i) - myrange(2)) .LE. &
1277 abs(myrange(1) - myrange(2)) + myrange(1)*0.001_dp)
THEN
1283 tmp(count2) = min(abs(eigenval(i) - myrange(1)), abs(eigenval(i) - myrange(2)))
1287 IF (count1 .EQ. nrep)
THEN
1289 DO i = 1, ms_vib%mat_size
1290 residuum(:, j) = residuum(:, j) + approx_h(i, map1(j, 1))*(ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
1294 ELSE IF (count1 .GT. nrep)
THEN
1295 ALLOCATE (tmp_resid(
SIZE(ms_vib%b_mat, 1), count1))
1296 ALLOCATE (tmp1(count1))
1297 ALLOCATE (map2(count1))
1300 DO i = 1, ms_vib%mat_size
1301 tmp_resid(:, j) = tmp_resid(:, j) + approx_h(i, map1(j, 1))* &
1302 (ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
1307 DO i = 1, ms_vib%mat_size
1308 tmp_resid(:, j) = tmp_resid(:, j) - dot_product(tmp_resid(:, j), ms_vib%b_mat(:, i))*ms_vib%b_mat(:, i)
1310 tmp(j) = maxval(tmp_resid(:, j))
1312 CALL sort(tmp, count1, map2)
1314 residuum(:, j) = tmp_resid(:, map2(count1 + 1 - j))
1315 ind(j) = map1(map2(count1 + 1 - j), 1)
1317 DEALLOCATE (tmp_resid)
1320 ELSE IF (count1 .LT. nrep)
THEN
1322 ALLOCATE (map2(count2))
1323 IF (count1 .NE. 0)
THEN
1325 DO i = 1, ms_vib%mat_size
1326 residuum(:, j) = residuum(:, j) + approx_h(i, map1(j, 1))* &
1327 (ms_vib%s_mat(:, i) - eigenval(map1(j, 1))*ms_vib%b_mat(:, i))
1332 CALL sort(tmp, count2, map2)
1333 DO j = 1, nrep - count1
1334 DO i = 1, ms_vib%mat_size
1335 residuum(:, count1 + j) = residuum(:, count1 + j) + approx_h(i, map1(map2(j), 2)) &
1336 *(ms_vib%s_mat(:, i) - eigenval(map1(map2(j), 2))*ms_vib%b_mat(:, i))
1338 ind(count1 + j) = map1(map2(j), 2)
1347 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