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)
 
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)