55 integer,
public :: num_modes
56 integer,
public :: ndim
57 integer,
public :: natoms
58 real(real64),
allocatable,
public :: dyn_matrix(:,:)
59 real(real64),
allocatable,
public :: infrared(:,:)
60 real(real64),
allocatable,
public :: normal_mode(:,:)
61 real(real64),
allocatable,
public :: freq(:)
62 real(real64),
public :: disp
63 real(real64) :: total_mass
64 real(real64),
pointer :: mass(:) => null()
65 character (len=2) :: suffix
66 character (len=80) :: filename_dynmat
67 type(unit_t) :: unit_dynmat
68 type(namespace_t),
pointer,
public :: namespace
74 subroutine vibrations_init(this, space, natoms, mass, suffix, namespace)
75 type(vibrations_t),
intent(out) :: this
76 class(space_t),
intent(in) :: space
77 integer,
intent(in) :: natoms
78 real(real64),
target,
intent(in) :: mass(:)
79 character (len=2),
intent(in) :: suffix
80 type(namespace_t),
target,
intent(in) :: namespace
86 this%num_modes = natoms*space%dim
87 this%namespace => namespace
88 safe_allocate(this%dyn_matrix(1:this%num_modes, 1:this%num_modes))
89 safe_allocate(this%infrared(1:this%num_modes, 1:this%ndim))
90 safe_allocate(this%normal_mode(1:this%num_modes, 1:this%num_modes))
91 safe_allocate(this%freq(1:this%num_modes))
94 this%total_mass = sum(mass)
101 this%filename_dynmat =
vib_modes_dir//
'dynamical_matrix_'//trim(this%suffix)
104 call io_rm(this%filename_dynmat, namespace)
114 type(vibrations_t),
intent(inout) :: this
118 safe_deallocate_a(this%dyn_matrix)
119 safe_deallocate_a(this%infrared)
120 safe_deallocate_a(this%freq)
121 safe_deallocate_a(this%normal_mode)
128 character(len=2) pure function vibrations_get_suffix(this)
129 type(vibrations_t),
intent(in) :: this
131 vibrations_get_suffix = this%suffix
138 type(vibrations_t),
intent(inout) :: this
140 integer :: imat, jmat
141 real(real64) :: average, maxdiff
148 do imat = 1, this%num_modes
149 do jmat = imat + 1, this%num_modes
150 average = m_half * (this%dyn_matrix(imat, jmat) + this%dyn_matrix(jmat, imat))
151 maxdiff = max(maxdiff, abs(this%dyn_matrix(imat, jmat) - this%dyn_matrix(jmat, imat)))
152 this%dyn_matrix(imat, jmat) = average
153 this%dyn_matrix(jmat, imat) = average
157 write(message(1),
'(a)')
'Info: Symmetrizing dynamical matrix.'
158 write(message(2),
'(a,es13.6,a,a)')
'Info: Maximum discrepancy from symmetry: ', &
159 units_from_atomic(this%unit_dynmat, maxdiff), &
160 " ", trim(units_abbrev(this%unit_dynmat))
161 call messages_info(2, namespace=this%namespace)
170 integer :: iatom, idir, jatom, jdir, imat, jmat
174 do iatom = 1, this%natoms
175 do idir = 1, this%ndim
179 do jatom = 1, this%natoms
180 do jdir = 1, this%ndim
184 this%dyn_matrix(jmat, imat) = &
199 integer,
intent(in) :: iatom
200 integer,
intent(in) :: jatom
203 sqrt(this%mass(iatom) * this%mass(jatom))
211 integer,
intent(in) :: imat
213 integer :: iatom, idir, jatom, jdir, jmat, iunit
215 if (.not. mpi_grp_is_root(mpi_world))
return
222 iunit = io_open(this%filename_dynmat, this%namespace, action=
'write', position=
'append')
224 do jmat = 1, this%num_modes
228 write(iunit,
'(2(i8, i6), e25.12)') &
229 jatom, jdir, iatom, idir, units_from_atomic(this%unit_dynmat, this%dyn_matrix(jmat, imat))
242 if (.not. mpi_grp_is_root(mpi_world))
return
246 iunit = io_open(this%filename_dynmat, namespace=this%namespace, action=
'write')
247 write(iunit,
'(2(a8, a6), a25)')
'atom',
'dir',
'atom',
'dir', &
248 '[' // trim(units_abbrev(this%unit_dynmat)) //
']'
263 this%normal_mode = m_zero
265 this%normal_mode = this%dyn_matrix
266 call lalg_eigensolve(this%num_modes, this%normal_mode, this%freq)
269 this%freq(1:this%num_modes) = -this%freq(1:this%num_modes) / this%total_mass
271 if (any(this%freq(1:this%num_modes) < -m_epsilon))
then
272 message(1) =
"There are imaginary vibrational frequencies (represented as negative)."
273 call messages_warning(1, namespace=this%namespace)
276 do imode = 1, this%num_modes
277 this%freq(imode) = sign(
sqrt(abs(this%freq(imode))), this%freq(imode))
280 if (maxval(this%normal_mode(:, imode)) - abs(minval(this%normal_mode(:, imode))) < -m_epsilon)
then
281 this%normal_mode(:, imode) = -this%normal_mode(:, imode)
292 integer,
intent(in) :: iatom
293 integer,
intent(in) :: idim
302 integer,
intent(in) :: index
311 integer,
intent(in) :: index
322 integer :: iunit, imat, jmat
324 if (.not. mpi_grp_is_root(mpi_world))
return
329 iunit = io_open(vib_modes_dir//
'normal_frequencies_'//trim(this%suffix), this%namespace, action=
'write')
330 write(iunit,
'(a)')
"# Mode Frequency [cm-1]"
331 do imat = 1, this%num_modes
332 write(iunit,
'(i6,f17.8)') imat, units_from_atomic(unit_invcm, this%freq(imat))
337 iunit = io_open(vib_modes_dir//
'normal_modes_'//trim(this%suffix), this%namespace, action=
'write')
338 do imat = 1, this%num_modes
339 write(iunit,
'(i6)', advance=
'no') imat
340 do jmat = 1, this%num_modes
341 write(iunit,
'(es14.5)', advance=
'no') this%normal_mode(jmat, imat)
double sqrt(double __x) __attribute__((__nothrow__
character(len= *), parameter, public vib_modes_dir
subroutine, public io_rm(fname, namespace)
subroutine, public io_mkdir(fname, namespace, parents)
logical function mpi_grp_is_root(grp)
Is the current MPI process of grpcomm, root.
type(mpi_grp_t), public mpi_world
brief This module defines the class unit_t which is used by the unit_systems_oct_m module.
This module defines the unit system, used for input and output.
type(unit_system_t), public units_out
character(len=2) pure function, public vibrations_get_suffix(this)
subroutine, public vibrations_out_dyn_matrix_header(this)
real(real64) pure function, public vibrations_norm_factor(this, iatom, jatom)
subroutine, public vibrations_diag_dyn_matrix(this)
Diagonalize the dynamical matrix.
subroutine, public vibrations_out_dyn_matrix_row(this, imat)
Outputs one row of the dynamical matrix.
subroutine, public vibrations_init(this, space, natoms, mass, suffix, namespace)
integer pure function, public vibrations_get_dir(this, index)
subroutine, public vibrations_normalize_dyn_matrix(this)
subroutine, public vibrations_symmetrize_dyn_matrix(this)
Symmetrize the dynamical matric, which is real symmetric matrix.
integer pure function, public vibrations_get_index(this, iatom, idim)
subroutine, public vibrations_output(this)
Outputs the eigenvectors and eigenenergies of the dynamical matrix.
subroutine, public vibrations_end(this)
integer pure function, public vibrations_get_atom(this, index)