Exemplo n.º 1
0
 def load(fname):
     with open(fname, 'rb') as fl:
         f = pickleload(fl)
     if not hasattr(f, 'shape'):
         # output from InfraRed
         return f[0]
     return f
Exemplo n.º 2
0
def readbee(fname, all=False):
    if not fname.endswith('.bee'):
        fname += '.bee'
    with open(fname, 'rb') as f:
        e, de, contribs, seed, xc = pickleload(f)
    if all:
        return e, de, contribs, seed, xc
    else:
        return e + de
Exemplo n.º 3
0
    def check_eq_forces(self):
        """Check maximum size of forces in the equilibrium structure."""

        fname = '%s.eq.pckl' % self.name
        feq_av = pickleload(open(fname, 'rb'))

        fmin = feq_av.max()
        fmax = feq_av.min()
        i_min = np.where(feq_av == fmin)
        i_max = np.where(feq_av == fmax)

        return fmin, fmax, i_min, i_max
Exemplo n.º 4
0
    def check_eq_forces(self):
        """Check maximum size of forces in the equilibrium structure."""

        fname = '%s.eq.pckl' % self.name
        with open(fname, 'rb') as fd:
            feq_av = pickleload(fd)

        fmin = feq_av.max()
        fmax = feq_av.min()
        i_min = np.where(feq_av == fmin)
        i_max = np.where(feq_av == fmax)

        return fmin, fmax, i_min, i_max
Exemplo n.º 5
0
 def load(fname, combined_data=None):
     if combined_data is None:
         with open(fname, 'rb') as fl:
             f = pickleload(fl)
     else:
         try:
             f = combined_data[op.basename(fname)]
         except KeyError:
             f = combined_data[fname]  # Old version
     if not hasattr(f, 'shape') and not hasattr(f, 'keys'):
         # output from InfraRed
         return f[0]
     return f
Exemplo n.º 6
0
    def read_born_charges(self, name=None, neutrality=True):
        r"""Read Born charges and dieletric tensor from pickle file.

        The charge neutrality sum-rule::

                   _ _
                   \    a
                    )  Z   = 0
                   /__  ij
                    a

        Parameters:

        neutrality: bool
            Restore charge neutrality condition on calculated Born effective
            charges.

        """

        # Load file with Born charges and dielectric tensor for atoms in the
        # unit cell
        if name is None:
            filename = '%s.born.pckl' % self.name
        else:
            filename = name

        with open(filename, 'rb') as fd:
            Z_avv, eps_vv = pickleload(fd)

        # Neutrality sum-rule
        if neutrality:
            Z_mean = Z_avv.sum(0) / len(Z_avv)
            Z_avv -= Z_mean

        self.Z_avv = Z_avv[self.indices]
        self.eps_vv = eps_vv
Exemplo n.º 7
0
    def read_born_charges(self, name=None, neutrality=True):
        """Read Born charges and dieletric tensor from pickle file.

        The charge neutrality sum-rule::

                   _ _
                   \    a
                    )  Z   = 0
                   /__  ij
                    a

        Parameters:

        neutrality: bool
            Restore charge neutrality condition on calculated Born effective
            charges.

        """

        # Load file with Born charges and dielectric tensor for atoms in the
        # unit cell
        if name is None:
            filename = '%s.born.pckl' % self.name
        else:
            filename = name

        with open(filename, 'rb') as fd:
            Z_avv, eps_vv = pickleload(fd)

        # Neutrality sum-rule
        if neutrality:
            Z_mean = Z_avv.sum(0) / len(Z_avv)
            Z_avv -= Z_mean

        self.Z_avv = Z_avv[self.indices]
        self.eps_vv = eps_vv
Exemplo n.º 8
0
 def load(fname, combined_data=None):
     if combined_data is not None:
         return combined_data[fname]
     return pickleload(open(fname, 'rb'))
Exemplo n.º 9
0
    def read(self,
             method='Frederiksen',
             symmetrize=3,
             acoustic=True,
             cutoff=None,
             born=False,
             **kwargs):
        """Read forces from pickle files and calculate force constants.

        Extra keyword arguments will be passed to ``read_born_charges``.

        Parameters:

        method: str
            Specify method for evaluating the atomic forces.
        symmetrize: int
            Symmetrize force constants (see doc string at top) when
            ``symmetrize != 0`` (default: 3). Since restoring the acoustic sum
            rule breaks the symmetry, the symmetrization must be repeated a few
            times until the changes a insignificant. The integer gives the
            number of iterations that will be carried out.
        acoustic: bool
            Restore the acoustic sum rule on the force constants.
        cutoff: None or float
            Zero elements in the dynamical matrix between atoms with an
            interatomic distance larger than the cutoff.
        born: bool
            Read in Born effective charge tensor and high-frequency static
            dielelctric tensor from file.

        """

        method = method.lower()
        assert method in ['standard', 'frederiksen']
        if cutoff is not None:
            cutoff = float(cutoff)

        # Read Born effective charges and optical dielectric tensor
        if born:
            self.read_born_charges(**kwargs)

        # Number of atoms
        natoms = len(self.indices)
        # Number of unit cells
        N = np.prod(self.N_c)
        # Matrix of force constants as a function of unit cell index in units
        # of eV / Ang**2
        C_xNav = np.empty((natoms * 3, N, natoms, 3), dtype=float)

        # Loop over all atomic displacements and calculate force constants
        for i, a in enumerate(self.indices):
            for j, v in enumerate('xyz'):
                # Atomic forces for a displacement of atom a in direction v
                basename = '%s.%d%s' % (self.name, a, v)
                fminus_av = pickleload(open(basename + '-.pckl', 'rb'))
                fplus_av = pickleload(open(basename + '+.pckl', 'rb'))

                if method == 'frederiksen':
                    fminus_av[a] -= fminus_av.sum(0)
                    fplus_av[a] -= fplus_av.sum(0)

                # Finite difference derivative
                C_av = fminus_av - fplus_av
                C_av /= 2 * self.delta

                # Slice out included atoms
                C_Nav = C_av.reshape((N, len(self.atoms), 3))[:, self.indices]
                index = 3 * i + j
                C_xNav[index] = C_Nav

        # Make unitcell index the first and reshape
        C_N = C_xNav.swapaxes(0, 1).reshape((N, ) + (3 * natoms, 3 * natoms))

        # Cut off before symmetry and acoustic sum rule are imposed
        if cutoff is not None:
            self.apply_cutoff(C_N, cutoff)

        # Symmetrize force constants
        if symmetrize:
            for i in range(symmetrize):
                # Symmetrize
                C_N = self.symmetrize(C_N)
                # Restore acoustic sum-rule
                if acoustic:
                    self.acoustic(C_N)
                else:
                    break

        # Store force constants and dynamical matrix
        self.C_N = C_N
        self.D_N = C_N.copy()

        # Add mass prefactor
        m_a = self.atoms.get_masses()
        self.m_inv_x = np.repeat(m_a[self.indices]**-0.5, 3)
        M_inv = np.outer(self.m_inv_x, self.m_inv_x)
        for D in self.D_N:
            D *= M_inv
Exemplo n.º 10
0
    def read(self, method='standard', direction='central'):
        self.method = method.lower()
        self.direction = direction.lower()
        assert self.method in ['standard', 'frederiksen']
        if direction != 'central':
            raise NotImplementedError(
                'Only central difference is implemented at the moment.')

        # Get "static" dipole moment and forces
        name = '%s.eq.pckl' % self.name
        [forces_zero, dipole_zero] = pickleload(open(name, 'rb'))
        self.dipole_zero = (sum(dipole_zero**2)**0.5) / units.Debye
        self.force_zero = max(
            [sum((forces_zero[j])**2)**0.5 for j in self.indices])

        ndof = 3 * len(self.indices)
        H = np.empty((ndof, ndof))
        dpdx = np.empty((ndof, 3))
        r = 0
        for a in self.indices:
            for i in 'xyz':
                name = '%s.%d%s' % (self.name, a, i)
                [fminus, dminus] = pickleload(open(name + '-.pckl', 'rb'))
                [fplus, dplus] = pickleload(open(name + '+.pckl', 'rb'))
                if self.nfree == 4:
                    [fminusminus,
                     dminusminus] = pickleload(open(name + '--.pckl', 'rb'))
                    [fplusplus,
                     dplusplus] = pickleload(open(name + '++.pckl', 'rb'))
                if self.method == 'frederiksen':
                    fminus[a] += -fminus.sum(0)
                    fplus[a] += -fplus.sum(0)
                    if self.nfree == 4:
                        fminusminus[a] += -fminus.sum(0)
                        fplusplus[a] += -fplus.sum(0)
                if self.nfree == 2:
                    H[r] = (fminus - fplus)[self.indices].ravel() / 2.0
                    dpdx[r] = (dminus - dplus)
                if self.nfree == 4:
                    H[r] = (-fminusminus + 8 * fminus - 8 * fplus +
                            fplusplus)[self.indices].ravel() / 12.0
                    dpdx[r] = (-dplusplus + 8 * dplus - 8 * dminus +
                               dminusminus) / 6.0
                H[r] /= 2 * self.delta
                dpdx[r] /= 2 * self.delta
                for n in range(3):
                    if n not in self.directions:
                        dpdx[r][n] = 0
                        dpdx[r][n] = 0
                r += 1
        # Calculate eigenfrequencies and eigenvectors
        m = self.atoms.get_masses()
        H += H.copy().T
        self.H = H
        m = self.atoms.get_masses()
        self.im = np.repeat(m[self.indices]**-0.5, 3)
        omega2, modes = np.linalg.eigh(self.im[:, None] * H * self.im)
        self.modes = modes.T.copy()

        # Calculate intensities
        dpdq = np.array([
            dpdx[j] / sqrt(m[self.indices[j // 3]] * units._amu / units._me)
            for j in range(ndof)
        ])
        dpdQ = np.dot(dpdq.T, modes)
        dpdQ = dpdQ.T
        intensities = np.array([sum(dpdQ[j]**2) for j in range(ndof)])
        # Conversion factor:
        s = units._hbar * 1e10 / sqrt(units._e * units._amu)
        self.hnu = s * omega2.astype(complex)**0.5
        # Conversion factor from atomic units to (D/Angstrom)^2/amu.
        conv = (1.0 / units.Debye)**2 * units._amu / units._me
        self.intensities = intensities * conv
Exemplo n.º 11
0
    def read(self, method='Frederiksen', symmetrize=3, acoustic=True,
             cutoff=None, born=False, **kwargs):
        """Read forces from pickle files and calculate force constants.

        Extra keyword arguments will be passed to ``read_born_charges``.

        Parameters:

        method: str
            Specify method for evaluating the atomic forces.
        symmetrize: int
            Symmetrize force constants (see doc string at top) when
            ``symmetrize != 0`` (default: 3). Since restoring the acoustic sum
            rule breaks the symmetry, the symmetrization must be repeated a few
            times until the changes a insignificant. The integer gives the
            number of iterations that will be carried out.
        acoustic: bool
            Restore the acoustic sum rule on the force constants.
        cutoff: None or float
            Zero elements in the dynamical matrix between atoms with an
            interatomic distance larger than the cutoff.
        born: bool
            Read in Born effective charge tensor and high-frequency static
            dielelctric tensor from file.

        """

        method = method.lower()
        assert method in ['standard', 'frederiksen']
        if cutoff is not None:
            cutoff = float(cutoff)

        # Read Born effective charges and optical dielectric tensor
        if born:
            self.read_born_charges(**kwargs)

        # Number of atoms
        natoms = len(self.indices)
        # Number of unit cells
        N = np.prod(self.N_c)
        # Matrix of force constants as a function of unit cell index in units
        # of eV / Ang**2
        C_xNav = np.empty((natoms * 3, N, natoms, 3), dtype=float)

        # Loop over all atomic displacements and calculate force constants
        for i, a in enumerate(self.indices):
            for j, v in enumerate('xyz'):
                # Atomic forces for a displacement of atom a in direction v
                basename = '%s.%d%s' % (self.name, a, v)
                fminus_av = pickleload(open(basename + '-.pckl', 'rb'))
                fplus_av = pickleload(open(basename + '+.pckl', 'rb'))

                if method == 'frederiksen':
                    fminus_av[a] -= fminus_av.sum(0)
                    fplus_av[a] -= fplus_av.sum(0)

                # Finite difference derivative
                C_av = fminus_av - fplus_av
                C_av /= 2 * self.delta

                # Slice out included atoms
                C_Nav = C_av.reshape((N, len(self.atoms), 3))[:, self.indices]
                index = 3 * i + j
                C_xNav[index] = C_Nav

        # Make unitcell index the first and reshape
        C_N = C_xNav.swapaxes(0, 1).reshape((N,) + (3 * natoms, 3 * natoms))

        # Cut off before symmetry and acoustic sum rule are imposed
        if cutoff is not None:
            self.apply_cutoff(C_N, cutoff)

        # Symmetrize force constants
        if symmetrize:
            for i in range(symmetrize):
                # Symmetrize
                C_N = self.symmetrize(C_N)
                # Restore acoustic sum-rule
                if acoustic:
                    self.acoustic(C_N)
                else:
                    break

        # Store force constants and dynamical matrix
        self.C_N = C_N
        self.D_N = C_N.copy()

        # Add mass prefactor
        m_a = self.atoms.get_masses()
        print(m_a.shape, self.indices)
        self.m_inv_x = np.repeat(m_a[self.indices]**-0.5, 3)
        M_inv = np.outer(self.m_inv_x, self.m_inv_x)
        for D in self.D_N:
            D *= M_inv