index | modules | gitlab | page source

# Infrared intensities

`Infrared` is an extension of `Vibrations`, in addition to the vibrational modes, also the infrared intensities of the modes are calculated for an `Atoms` object.

class ase.vibrations.Infrared(atoms, indices=None, name='ir', delta=0.01, nfree=2, directions=None)

  Class for calculating vibrational modes and infrared intensities using finite difference.

  The vibrational modes are calculated from a finite difference approximation of the Dynamical matrix and the IR intensities from a finite difference approximation of the gradient of the dipole moment. The method is described in:

  > D. Porezag, M. R. Pederson: “Infrared intensities and Raman-scattering activities within density-functional theory”, Phys. Rev. B 54, 7830 (1996)

  The calculator object (calc) linked to the Atoms object (atoms) must have the attribute:

      >>> calc.get_dipole_moment(atoms)

  In addition to the methods included in the `Vibrations` class the `Infrared` class introduces two new methods; get_spectrum() and write_spectra(). The summary(), get_energies(), get_frequencies(), get_spectrum() and write_spectra() methods all take an optional method keyword. Use method=’Frederiksen’ to use the method described in:

  > T. Frederiksen, M. Paulsson, M. Brandbyge, A. P. Jauho: “Inelastic transport theory from first-principles: methodology and applications for nanoscale devices”, Phys. Rev. B 75, 205413 (2007)

  atoms: Atoms object

    The atoms to work on.

  indices: list of int

    List of indices of atoms to vibrate. Default behavior is to vibrate all atoms.

  name: str

    Name to use for files.

  delta: float

    Magnitude of displacements.

  nfree: int

    Number of displacements per degree of freedom, 2 or 4 are supported. Default is 2 which will displace each atom +delta and -delta in each cartesian direction.

  directions: list of int

    Cartesian coordinates to calculate the gradient of the dipole moment in. For example directions = 2 only dipole moment in the z-direction will be considered, whereas for directions = [0, 1] only the dipole moment in the xy-plane will be considered. Default behavior is to use the dipole moment in all directions.

  Example:

      >>> from ase.io import read
      >>> from ase.calculators.vasp import Vasp
      >>> from ase.vibrations import Infrared
      >>> water = read('water.traj')  # read pre-relaxed structure of water
      >>> calc = Vasp(prec='Accurate',
      ...             ediff=1E-8,
      ...             isym=0,
      ...             idipol=4,       # calculate the total dipole moment
      ...             dipol=water.get_center_of_mass(scaled=True),
      ...             ldipol=True)
      >>> water.calc = calc
      >>> ir = Infrared(water)
      >>> ir.run()
      >>> ir.summary()
      -------------------------------------
      Mode    Frequency        Intensity
      #    meV     cm^-1   (D/Å)^2 amu^-1
      -------------------------------------
      0   16.9i    136.2i     1.6108
      1   10.5i     84.9i     2.1682
      2    5.1i     41.1i     1.7327
      3    0.3i      2.2i     0.0080
      4    2.4      19.0      0.1186
      5   15.3     123.5      1.4956
      6  195.5    1576.7      1.6437
      7  458.9    3701.3      0.0284
      8  473.0    3814.6      1.1812
      -------------------------------------
      Zero-point energy: 0.573 eV
      Static dipole moment: 1.833 D
      Maximum force on atom in `equilibrium`: 0.0026 eV/Å

  This interface now also works for calculator ‘siesta’, (added get_dipole_moment for siesta).

  Example:

      >>> #!/usr/bin/env python3

      >>> from ase.io import read
      >>> from ase.calculators.siesta import Siesta
      >>> from ase.vibrations import Infrared

      >>> bud = read('bud1.xyz')

      >>> calc = Siesta(label='bud',
      ...       meshcutoff=250 * Ry,
      ...       basis='DZP',
      ...       kpts=[1, 1, 1])

      >>> calc.set_fdf('DM.MixingWeight', 0.08)
      >>> calc.set_fdf('DM.NumberPulay', 3)
      >>> calc.set_fdf('DM.NumberKick', 20)
      >>> calc.set_fdf('DM.KickMixingWeight', 0.15)
      >>> calc.set_fdf('SolutionMethod',      'Diagon')
      >>> calc.set_fdf('MaxSCFIterations', 500)
      >>> calc.set_fdf('PAO.BasisType',  'split')
      >>> #50 meV = 0.003674931 * Ry
      >>> calc.set_fdf('PAO.EnergyShift', 0.003674931 * Ry )
      >>> calc.set_fdf('LatticeConstant', 1.000000 * Ang)
      >>> calc.set_fdf('WriteCoorXmol',       'T')

      >>> bud.calc = calc

      >>> ir = Infrared(bud)
      >>> ir.run()
      >>> ir.summary()

  get_spectrum(start=800, end=4000, npts=None, width=4, type='Gaussian', method='standard', direction='central', intensity_unit='(D/A)2/amu', normalize=False)

    Get infrared spectrum.

    The method returns wavenumbers in cm^-1 with corresponding absolute infrared intensity. Start and end point, and width of the Gaussian/Lorentzian should be given in cm^-1. normalize=True ensures the integral over the peaks to give the intensity.

  write_spectra(out='ir-spectra.dat', start=800, end=4000, npts=None, width=10, type='Gaussian', method='standard', direction='central', intensity_unit='(D/A)2/amu', normalize=False)

    Write out infrared spectrum to file.

    First column is the wavenumber in cm^-1, the second column the absolute infrared intensities, and the third column the absorbance scaled so that data runs from 1 to 0. Start and end point, and width of the Gaussian/Lorentzian should be given in cm^-1.