Exemple #1
0
def load(supercell_matrix,
         primitive_matrix=None,
         nac_params=None,
         unitcell=None,
         calculator="vasp",
         unitcell_filename=None,
         born_filename=None,
         force_sets_filename=None,
         force_constants_filename=None,
         factor=VaspToTHz,
         frequency_scale_factor=None,
         symprec=1e-5,
         is_symmetry=True,
         log_level=0):

    if unitcell is None:
        _unitcell, _ = read_crystal_structure(filename=unitcell_filename,
                                              interface_mode=calculator)
    else:
        _unitcell = unitcell

    # units keywords: factor, nac_factor, distance_to_A
    units = get_default_physical_units(calculator)
    phonon = Phonopy(_unitcell,
                     supercell_matrix,
                     primitive_matrix=primitive_matrix,
                     factor=units['factor'])

    if nac_params is None:
        if born_filename is None:
            _nac_params = None
        else:
            _nac_params = parse_BORN(phonon.primitive, filename=born_filename)
    else:
        _nac_params = nac_params

    if _nac_params is not None:
        if _nac_params['factor'] is None:
            _nac_params['factor'] = units['nac_factor']
        phonon.set_nac_params(_nac_params)

    if force_constants_filename is not None:
        dot_split = force_constants_filename.split('.')
        p2s_map = phonon.primitive.get_primitive_to_supercell_map()
        if len(dot_split) > 1 and dot_split[-1] == 'hdf5':
            fc = read_force_constants_hdf5(filename=force_constants_filename,
                                           p2s_map=p2s_map)
        else:
            fc = parse_FORCE_CONSTANTS(filename=force_constants_filename,
                                       p2s_map=p2s_map)
        phonon.set_force_constants(fc)
    elif force_sets_filename is not None:
        force_sets = parse_FORCE_SETS(filename=force_sets_filename)
        phonon.set_displacement_dataset(force_sets)
        phonon.produce_force_constants()

    return phonon
Exemple #2
0
def get_phonon(structure, NAC=False):

    force_atoms_file = structure.get_force_set()['natom']
    force_atoms_input = np.product(np.diagonal(structure.get_super_cell_phonon()))*structure.get_number_of_atoms()

    if force_atoms_file != force_atoms_input:
        print("Error: FORCE_SETS file does not match with SUPERCELL MATRIX")
        exit()


    #Preparing the bulk type object
    bulk = PhonopyAtoms(symbols=structure.get_atomic_types(),
                        scaled_positions=structure.get_scaled_positions(),
                        cell=structure.get_cell().T)

    phonon = Phonopy(bulk, structure.get_super_cell_phonon(),
                     primitive_matrix=structure.get_primitive_matrix(),
                     is_auto_displacements=False)

    #Non Analytical Corrections (NAC) from Phonopy [Frequencies only, eigenvectors no affected by this option]
    if NAC:
        print("Phonopy warning: Using Non Analytical Corrections")
        get_is_symmetry = True  #from phonopy:   settings.get_is_symmetry()
        primitive = phonon.get_primitive()
        nac_params = parse_BORN(primitive, get_is_symmetry)
        phonon.set_nac_params(nac_params=nac_params)


    phonon.set_displacement_dataset(structure.get_force_set())
    phonon.produce_force_constants(computation_algorithm="svd")


    return phonon
Exemple #3
0
    def __init__(self, primitive, supercell, folder, vasp=False):
        self.atoms = PhonopyAtoms(symbols=primitive.get_chemical_symbols(),
                                  positions=primitive.positions,
                                  masses=primitive.get_masses(),
                                  cell=primitive.cell,
                                  pbc=primitive.pbc)

        self.supercell = supercell
        self.folder = folder
        if not vasp:
            self.phonopy = Phonopy(self.atoms, supercell)
            self._get_dynmatrix()
            self.primitive = self.phonopy._dynamical_matrix.get_primitive()
        else:
            from matdb.io import vasp_to_xyz
            self.phonopy = Phonopy(self.atoms, supercell)
            if path.isfile("FORCE_CONSTANTS"):
                fc = file_IO.parse_FORCE_CONSTANTS(filename="FORCE_CONSTANTS")
                self.phonopy.set_force_constants(fc)
                self.phonopy._set_dynamical_matrix()

            self.primitive = primitive
            vasp_to_xyz(folder)
            self.parent = quippy.Atoms(path.join(folder, "output.xyz"))
Exemple #4
0
    def BZ_sample(self):
        """Returns a full sampling of the BZ by calculating frequencies at every
        unique k-point as sampled on the :attr:`dosmesh` grid.

        Returns:
            tuple: `(q-points, weights, eigenvalues)` where the `q-points` are
            the unique points after symmetry reduction; `weights` are the
            corresponding weights for each point; `eigenvalues` is a
            :class:`numpy.ndarray` of frequencies (in THz) for each point.
        """
        #This is a little convoluted because of how the phonopy API works. We
        #want to get a full sampling of the BZ, but with symmetry, and then
        #compare the eigenvalues at every point.
        if self._bzsample is None:
            with chdir(self.phonodir):
                atoms = matdb_to_phonopy(self.atoms)
                phonpy = Phonopy(atoms, np.array(self.supercell).reshape(3, 3))
                phonpy.set_force_constants(roll_fc(self.H))
                phonpy._set_dynamical_matrix()

                #Phonopy requires full settings to compute the unique grid and
                #eigenvalues. We spoof the command-line parser.
                parser = get_parser()
                (options, args) = parser.parse_args()
                option_list = parser.option_list
                options.mesh_numbers = ' '.join(map(str, self.dosmesh))
                phonopy_conf = PhonopyConfParser(options=options,
                                                 option_list=option_list)
                settings = phonopy_conf.get_settings()

                #Next, set the mesh on the phonopy object and ask it to reduce and
                #calculate frequencies.
                mesh = settings.get_mesh()
                phonpy.set_mesh(*mesh)
                self._bzsample = phonpy.get_mesh()[0:3]

        return self._bzsample
Exemple #5
0
def load(phonopy_yaml=None,  # phonopy.yaml-like must be the first argument.
         supercell_matrix=None,
         primitive_matrix=None,
         is_nac=True,
         calculator=None,
         unitcell=None,
         supercell=None,
         nac_params=None,
         unitcell_filename=None,
         supercell_filename=None,
         born_filename=None,
         force_sets_filename=None,
         force_constants_filename=None,
         use_alm=False,
         factor=None,
         frequency_scale_factor=None,
         symprec=1e-5,
         is_symmetry=True,
         log_level=0):
    """Create Phonopy instance from parameters and/or input files.

    When unitcell and unitcell_filename are not given, file name that is
    default for the chosen calculator is looked for in the current directory
    as the default behaviour.

    When force_sets_filename and force_constants_filename are not given,
    'FORCE_SETS' is looked for in the current directory as the default
    behaviour.

    Parameters
    ----------
    phonopy_yaml : str, optional
        Filename of "phonopy.yaml"-like file. If this is given, the data
        in the file are parsed. Default is None.
    supercell_matrix : array_like, optional
        Supercell matrix multiplied to input cell basis vectors.
        shape=(3, ) or (3, 3), where the former is considered a diagonal
        matrix. Default is the unit matrix.
        dtype=int
    primitive_matrix : array_like or str, optional
        Primitive matrix multiplied to input cell basis vectors. Default is
        the identity matrix.
        shape=(3, 3)
        dtype=float
        When 'F', 'I', 'A', 'C', or 'R' is given instead of a 3x3 matrix,
        the primitive matrix defined at
        https://atztogo.github.io/spglib/definition.html
        is used.
    is_nac : bool, optional
        If True, look for 'BORN' file. If False, NAS is turned off.
        The priority for NAC is nac_params > born_filename > is_nac ('BORN').
        Default is True.
    calculator : str, optional.
        Calculator used for computing forces. This is used to switch the set
        of physical units. Default is None, which is equivalent to "vasp".
    unitcell : PhonopyAtoms, optional
        Input unit cell. Default is None. The priority for cell is
        unitcell_filename > supercell_filename > unitcell > supercell.
    supercell : PhonopyAtoms, optional
        Input supercell cell. Default value of primitive_matrix is set to
        'auto' (can be overwitten). supercell_matrix is ignored. Default is
        None. The priority for cell is
        unitcell_filename > supercell_filename > unitcell > supercell.
    nac_params : dict, optional
        Parameters required for non-analytical term correction. Default is
        None. The priority for NAC is nac_params > born_filename > is_nac.
        {'born': Born effective charges
                 (array_like, shape=(primitive cell atoms, 3, 3), dtype=float),
         'dielectric': Dielectric constant matrix
                       (array_like, shape=(3, 3), dtype=float),
         'factor': unit conversion facotr (float)}
    unitcell_filename : str, optional
        Input unit cell filename. Default is None. The priority for cell is
        unitcell_filename > supercell_filename > unitcell > supercell.
    supercell_filename : str, optional
        Input supercell filename. Default value of primitive_matrix is set to
        'auto' (can be overwitten). supercell_matrix is ignored. Default is
        None. The priority for cell is
        unitcell_filename > supercell_filename > unitcell > supercell.
    born_filename : str, optional
        Filename corresponding to 'BORN', a file contains non-analytical term
        correction parameters.
        The priority for NAC is nac_params > born_filename > is_nac ('BORN').
    force_sets_filename : str, optional
        Filename of a file corresponding to 'FORCE_SETS', a file contains sets
        of forces and displacements. Default is None.
        The priority for force constants is
        force_constants_filename > force_sets_filename > 'FORCE_SETS'.
    force_constants_filename : str, optional
        Filename of a file corresponding to 'FORCE_CONSTANTS' or
        'force_constants.hdf5', a file contains force constants.
        Default is None.
        The priority for force constants is
        force_constants_filename > force_sets_filename > 'FORCE_SETS'.
    use_alm : bool, optional
        Default is False.
    factor : float, optional
        Phonon frequency unit conversion factor. Unless specified, default
        unit conversion factor for each calculator is used.
    frequency_scale_factor : float, optional
        Factor multiplied to calculated phonon frequency. Default is None,
        i.e., effectively 1.
    symprec : float, optional
        Tolerance used to find crystal symmetry. Default is 1e-5.
    is_symmetry : bool, optional
        Setting False, crystal symmetry except for lattice translation is not
        considered. Default is True.
    log_level : int, optional
        Verbosity control. Default is 0.

    """

    if phonopy_yaml is None:
        cell, smat, pmat = load_helper.get_cell_settings(
            supercell_matrix=supercell_matrix,
            primitive_matrix=primitive_matrix,
            unitcell=unitcell,
            supercell=supercell,
            unitcell_filename=unitcell_filename,
            supercell_filename=supercell_filename,
            calculator=calculator,
            symprec=symprec)
        _nac_params = nac_params
        _dataset = None
        _fc = None
    else:
        phpy_yaml = PhonopyYaml()
        phpy_yaml.read(phonopy_yaml)
        cell = phpy_yaml.unitcell
        smat = phpy_yaml.supercell_matrix
        if smat is None:
            smat = np.eye(3, dtype='intc', order='C')
        if primitive_matrix is 'auto':
            pmat = 'auto'
        else:
            pmat = phpy_yaml.primitive_matrix
        if is_nac:
            _nac_params = phpy_yaml.nac_params
        else:
            _nac_params = None
        _dataset = phpy_yaml.dataset
        _fc =  phpy_yaml.force_constants

    # units keywords: factor, nac_factor, distance_to_A
    units = get_default_physical_units(calculator)
    if factor is None:
        _factor = units['factor']
    else:
        _factor = factor
    phonon = Phonopy(cell,
                     smat,
                     primitive_matrix=pmat,
                     factor=_factor,
                     frequency_scale_factor=frequency_scale_factor,
                     symprec=symprec,
                     is_symmetry=is_symmetry,
                     calculator=calculator,
                     log_level=log_level)
    load_helper.set_nac_params(phonon,
                               _nac_params,
                               born_filename,
                               is_nac,
                               units['nac_factor'])
    if _fc is None:
        load_helper.set_force_constants(
            phonon,
            dataset=_dataset,
            force_constants_filename=force_constants_filename,
            force_sets_filename=force_sets_filename,
            calculator=calculator,
            use_alm=use_alm)
    else:
        phonon.force_constants = _fc
    return phonon
Exemple #6
0
def get_phonon(structure,
               NAC=False,
               setup_forces=True,
               super_cell_phonon=np.identity(3),
               primitive_matrix=np.identity(3),
               symmetrize=True):
    """
    Return a phonopy phonon object (instance of the class Phonon)
    
    :param structure: unit cell matrix (lattice vectors in rows)
    :param NAC: (Bool) activate/deactivate Non-analytic corrections
    :param setup_forces: (Bool) decide if pre-calculate harmonic forces in phonon object
    :param super_cell_phonon: 3x3 array containing the supercell to be used to calculate the force constants
    :param primitive_matrix: 3x3 array containing the primitive axis (in rows) which define the primitive cell
    :param symmetrize: decide if symmetrize the force constants
    :return: phonopy phonon object
    """

    phonon = Phonopy(structure,
                     super_cell_phonon,
                     primitive_matrix=primitive_matrix,
                     symprec=1e-5,
                     is_symmetry=symmetrize)

    # Non Analytical Corrections (NAC) from Phonopy [Frequencies only, eigenvectors no affected by this option]

    if setup_forces:
        if structure.get_force_constants() is not None:
            phonon.set_force_constants(
                structure.get_force_constants().get_array())
        elif structure.get_force_sets() is not None:
            phonon.set_displacement_dataset(
                structure.get_force_sets().get_dict())
            phonon.produce_force_constants(computation_algorithm="svd")
            structure.set_force_constants(
                ForceConstants(
                    phonon.get_force_constants(),
                    supercell=structure.get_force_sets().get_supercell()))
        else:
            print('No force sets/constants available!')
            exit()

    if NAC:
        print("Using non-analytical corrections")
        primitive = phonon.get_primitive()
        try:
            nac_params = parse_BORN(primitive, is_symmetry=True)
            phonon.set_nac_params(nac_params=nac_params)
        except OSError:
            print('Required BORN file not found!')
            exit()

    return phonon
Exemple #7
0
def get_phonon(structure, NAC=False, setup_forces=True, custom_supercell=None):

    if custom_supercell is None:
        super_cell_phonon = structure.get_supercell_phonon()
    else:
        super_cell_phonon = custom_supercell

    # Preparing the bulk type object
    bulk = PhonopyAtoms(symbols=structure.get_atomic_elements(),
                        scaled_positions=structure.get_scaled_positions(),
                        cell=structure.get_cell().T)

    phonon = Phonopy(bulk,
                     super_cell_phonon,
                     primitive_matrix=structure.get_primitive_matrix(),
                     symprec=1e-5)

    # Non Analytical Corrections (NAC) from Phonopy [Frequencies only, eigenvectors no affected by this option]

    if NAC:
        print("Phonopy warning: Using Non Analytical Corrections")
        get_is_symmetry = True  # from phonopy: settings.get_is_symmetry()
        primitive = phonon.get_primitive()
        nac_params = parse_BORN(primitive, get_is_symmetry)
        phonon.set_nac_params(nac_params=nac_params)

    if setup_forces:
        if structure.get_force_constants() is not None:
            phonon.set_force_constants(
                structure.get_force_constants().get_array())
        elif structure.get_force_sets() is not None:
            phonon.set_displacement_dataset(
                structure.get_force_sets().get_dict())
            phonon.produce_force_constants(computation_algorithm="svd")
        else:
            print('No force sets/constants available!')
            exit()

    return phonon
Exemple #8
0
def load(phonopy_yaml=None,  # phonopy.yaml-like must be the first argument.
         supercell_matrix=None,
         primitive_matrix=None,
         is_nac=True,
         calculator=None,
         unitcell=None,
         supercell=None,
         nac_params=None,
         unitcell_filename=None,
         supercell_filename=None,
         born_filename=None,
         force_sets_filename=None,
         force_constants_filename=None,
         fc_calculator=None,
         fc_calculator_options=None,
         factor=None,
         frequency_scale_factor=None,
         produce_fc=True,
         is_symmetry=True,
         symmetrize_fc=True,
         is_compact_fc=True,
         symprec=1e-5,
         log_level=0):
    """Create Phonopy instance from parameters and/or input files.

    "phonopy_yaml"-like file is parsed unless crystal structure information
    is given by unitcell_filename, supercell_filename, unitcell
    (PhonopyAtoms-like), or supercell (PhonopyAtoms-like).
    Even when "phonopy_yaml"-like file is parse, parameters except for
    crystal structure can be overwritten.

    Phonopy default files of 'FORCE_SETS' and 'BORN' are parsed when they
    are found in current directory and those data are not yet provided by
    other means.

    Crystal structure
    -----------------
    Means to provide crystal structure(s) and their priority:
        1. unitcell_filename (with supercell_matrix)
        2. supercell_filename
        3. unitcell (with supercell_matrix)
        4. supercell.
        5. phonopy_yaml

    Force sets or force constants
    -----------------------------
    Optional. Means to provide information to generate force constants
    and their priority:
        1. force_constants_filename
        2. force_sets_filename
        3. phonopy_yaml if force constants are found in phonoy_yaml.
        4. phonopy_yaml if forces are found in phonoy_yaml.dataset.
        5. 'FORCE_CONSTANTS' is searched in current directory.
        6. 'force_constants.hdf5' is searched in current directory.
        7. 'FORCE_SETS' is searched in current directory.
    When both of 3 and 4 are satisfied but not others, force constants and
    dataset are stored in Phonopy instance, but force constants are not
    produced from dataset.

    Parameters for non-analytical term correctiion (NAC)
    ----------------------------------------------------
    Optional. Means to provide NAC parameters and their priority:
        1. born_filename
        2. nac_params
        3. phonopy_yaml.nac_params if existed and is_nac=True.
        4. 'BORN' is searched in current directory when is_nac=True.

    Parameters
    ----------
    phonopy_yaml : str, optional
        Filename of "phonopy.yaml"-like file. If this is given, the data
        in the file are parsed. Default is None.
    supercell_matrix : array_like, optional
        Supercell matrix multiplied to input cell basis vectors.
        shape=(3, ) or (3, 3), where the former is considered a diagonal
        matrix. Default is the unit matrix.
        dtype=int
    primitive_matrix : array_like or str, optional
        Primitive matrix multiplied to input cell basis vectors. Default is
        None, which is equivalent to 'auto'.
        For array_like, shape=(3, 3), dtype=float.
        When 'F', 'I', 'A', 'C', or 'R' is given instead of a 3x3 matrix,
        the primitive matrix for the character found at
        https://spglib.github.io/spglib/definition.html
        is used.
    is_nac : bool, optional
        If True, look for 'BORN' file. If False, NAS is turned off.
        Default is True.
    calculator : str, optional.
        Calculator used for computing forces. This is used to switch the set
        of physical units. Default is None, which is equivalent to "vasp".
    unitcell : PhonopyAtoms, optional
        Input unit cell. Default is None.
    supercell : PhonopyAtoms, optional
        Input supercell. With given, default value of primitive_matrix is set
        to 'auto' (can be overwitten). supercell_matrix is ignored. Default is
        None.
    nac_params : dict, optional
        Parameters required for non-analytical term correction. Default is
        None.
        {'born': Born effective charges
                 (array_like, shape=(primitive cell atoms, 3, 3), dtype=float),
         'dielectric': Dielectric constant matrix
                       (array_like, shape=(3, 3), dtype=float),
         'factor': unit conversion facotr (float)}
    unitcell_filename : str, optional
        Input unit cell filename. Default is None.
    supercell_filename : str, optional
        Input supercell filename. When this is specified, supercell_matrix is
        ignored. Default is None.
    born_filename : str, optional
        Filename corresponding to 'BORN', a file contains non-analytical term
        correction parameters.
    force_sets_filename : str, optional
        Filename of a file corresponding to 'FORCE_SETS', a file contains sets
        of forces and displacements. Default is None.
    force_constants_filename : str, optional
        Filename of a file corresponding to 'FORCE_CONSTANTS' or
        'force_constants.hdf5', a file contains force constants. Default is
        None.
    fc_calculator : str, optional
        Force constants calculator. Currently only 'alm'. Default is None.
    fc_calculator_options : str, optional
        Optional parameters that are passed to the external fc-calculator.
        This is given as one text string. How to parse this depends on the
        fc-calculator. For alm, each parameter is splitted by comma ',',
        and each set of key and value pair is written in 'key = value'.
    factor : float, optional
        Phonon frequency unit conversion factor. Unless specified, default
        unit conversion factor for each calculator is used.
    frequency_scale_factor : float, optional
        Factor multiplied to calculated phonon frequency. Default is None,
        i.e., effectively 1.
    produce_fc : bool, optional
        Setting False, force constants are not calculated from displacements
        and forces. Default is True.
    is_symmetry : bool, optional
        Setting False, crystal symmetry except for lattice translation is not
        considered. Default is True.
    symmetrize_fc : bool, optional
        Setting False, force constants are not symmetrized when creating
        force constants from displacements and forces. Default is True.
    is_compact_fc : bool
        Force constants are produced in the array whose shape is
            True: (primitive, supecell, 3, 3)
            False: (supercell, supecell, 3, 3)
        where 'supercell' and 'primitive' indicate number of atoms in these
        cells. Default is True.
    symprec : float, optional
        Tolerance used to find crystal symmetry. Default is 1e-5.
    log_level : int, optional
        Verbosity control. Default is 0.

    """

    if (supercell is not None or
        supercell_filename is not None or
        unitcell is not None or
        unitcell_filename is not None):
        cell, smat, pmat = load_helper.get_cell_settings(
            supercell_matrix=supercell_matrix,
            primitive_matrix=primitive_matrix,
            unitcell=unitcell,
            supercell=supercell,
            unitcell_filename=unitcell_filename,
            supercell_filename=supercell_filename,
            calculator=calculator,
            symprec=symprec,
            log_level=log_level)
        _calculator = calculator
        _nac_params = nac_params
        _dataset = None
        _fc = None
    elif phonopy_yaml is not None:
        phpy_yaml = PhonopyYaml()
        phpy_yaml.read(phonopy_yaml)
        cell = phpy_yaml.unitcell
        smat = phpy_yaml.supercell_matrix
        if smat is None:
            smat = np.eye(3, dtype='intc', order='C')
        if primitive_matrix is not None:
            pmat = get_primitive_matrix(primitive_matrix, symprec=symprec)
        else:
            pmat = phpy_yaml.primitive_matrix
        if nac_params is not None:
            _nac_params = nac_params
        elif is_nac:
            _nac_params = phpy_yaml.nac_params
        else:
            _nac_params = None
        _dataset = phpy_yaml.dataset
        _fc = phpy_yaml.force_constants
        if calculator is None:
            _calculator = phpy_yaml.calculator
        else:
            _calculator = calculator
    else:
        msg = ("Cell information could not found. "
               "Phonopy instance loading failed.")
        raise RuntimeError(msg)

    if log_level and _calculator is not None:
        print("Set \"%s\" mode." % _calculator)

    # units keywords: factor, nac_factor, distance_to_A
    units = get_default_physical_units(_calculator)
    if factor is None:
        _factor = units['factor']
    else:
        _factor = factor
    phonon = Phonopy(cell,
                     smat,
                     primitive_matrix=pmat,
                     factor=_factor,
                     frequency_scale_factor=frequency_scale_factor,
                     symprec=symprec,
                     is_symmetry=is_symmetry,
                     calculator=_calculator,
                     log_level=log_level)

    # NAC params
    if born_filename is not None or _nac_params is not None or is_nac:
        ret_nac_params = load_helper.get_nac_params(
            primitive=phonon.primitive,
            nac_params=_nac_params,
            born_filename=born_filename,
            is_nac=is_nac,
            nac_factor=units['nac_factor'],
            log_level=log_level)
        if ret_nac_params is not None:
            phonon.nac_params = ret_nac_params

    # Displacements, forces, and force constants
    load_helper.set_dataset_and_force_constants(
        phonon,
        _dataset,
        _fc,
        force_constants_filename=force_constants_filename,
        force_sets_filename=force_sets_filename,
        fc_calculator=fc_calculator,
        fc_calculator_options=fc_calculator_options,
        produce_fc=produce_fc,
        symmetrize_fc=symmetrize_fc,
        is_compact_fc=is_compact_fc,
        log_level=log_level)

    return phonon
Exemple #9
0
class HessianSupercell(object):
    """Represents a supercell configuration generator that has a set of eigenvalues
    and eigenvectors compatible with Hessian fitting.

    Args:
        primitive (ase.Atoms): primitive configuration to create the supercell
          from.
        supercell (np.array): array of `int` supercell matrix.
        folder (str): path to the `phonopy` folder where `FORCE_SETS` and
          displacements are kept; or where `vasprun.xml` is located when the
          full Hessian is calculated using VASP.

    Attributes:
        phonopy (phonopy.Phonopy): phonopy class for generating dynamical
          matrix, eigenvalues and eigenvectors.
    """
    def __init__(self, primitive, supercell, folder, vasp=False):
        self.atoms = PhonopyAtoms(symbols=primitive.get_chemical_symbols(),
                                  positions=primitive.positions,
                                  masses=primitive.get_masses(),
                                  cell=primitive.cell,
                                  pbc=primitive.pbc)

        self.supercell = supercell
        self.folder = folder
        if not vasp:
            self.phonopy = Phonopy(self.atoms, supercell)
            self._get_dynmatrix()
            self.primitive = self.phonopy._dynamical_matrix.get_primitive()
        else:
            from matdb.io import vasp_to_xyz
            self.phonopy = Phonopy(self.atoms, supercell)
            if path.isfile("FORCE_CONSTANTS"):
                fc = file_IO.parse_FORCE_CONSTANTS(filename="FORCE_CONSTANTS")
                self.phonopy.set_force_constants(fc)
                self.phonopy._set_dynamical_matrix()

            self.primitive = primitive
            vasp_to_xyz(folder)
            self.parent = quippy.Atoms(path.join(folder, "output.xyz"))

    def diagonalize(self, q):
        """Diagonalizes the dynamical matrix at `q`.

        Args:
            q (numpy.array): q-point to diagonalize at.

        Returns:
            tuple: `(eigvals, eigvecs)`, where the eigenvalues are in units of
            `THz` and both eigenvalues and eigenvectors are in the *primitive*
            cell.
        """
        return self.phonopy.get_frequencies_with_eigenvectors(q)

    def _get_phase_factor(self, modulation, argument):
        """Returns a phase factor corresponding to the given modulation.

        Args:
            modulation (numpy.ndarray): list of displacements, one for each
              atom.
            argument (float): phase angle (in degrees) to manipulate the
              displacement by.
        """
        u = np.ravel(modulation)
        index_max_elem = np.argmax(abs(u))
        max_elem = u[index_max_elem]
        phase_for_zero = max_elem / abs(max_elem)
        phase_factor = np.exp(1j * np.pi * argument / 180) / phase_for_zero

        return phase_factor

    def _map_eigvec_supercell(self, supercell, eigvec):
        """Maps the specified eigenvector to the target supercell.

        Args:
            supercell (phonopy.structure.cells.Supercell): the target supercell
              that the atoms will be displaced in.
            eigvec (numpy.ndarray): target eigenvector from the *primitive* cell.
        """
        s2u_map = supercell.get_supercell_to_unitcell_map()
        u2u_map = supercell.get_unitcell_to_unitcell_map()
        s2uu_map = [u2u_map[x] for x in s2u_map]
        result = []

        for i in range(supercell.get_number_of_atoms()):
            eig_index = s2uu_map[i] * 3
            ej = eigvec[eig_index:eig_index + 3]
            result.append(ej)

        return np.array(result)

    def _get_displacements(self, supercell, eigvec, q, amplitude, argument):
        """Returns the vector of displacements for a single eigenvector.

        .. warning:: The supercell *must* be comensurate with the selected
          q-vector.

        Args:
            supercell (phonopy.structure.cells.Supercell): the target supercell
              that the atoms will be displaced in.
            eigvec (numpy.ndarray): target eigenvector from the *primitive* cell.
        """
        m = supercell.get_masses()
        spos = supercell.get_scaled_positions()
        dim = supercell.get_supercell_matrix()
        coefs = np.exp(
            2j * np.pi * np.dot(np.dot(spos, dim.T), q)) / np.sqrt(m)
        meigvec = self._map_eigvec_supercell(supercell, eigvec)
        u = (meigvec.T * coefs).T
        u = np.array(u) / np.sqrt(len(m))
        phase_factor = self._get_phase_factor(u, argument)
        u *= phase_factor * amplitude

        return u

    def iterate(self, method="hessian", supercell=None, q=None, nrattle=0):
        """Returns a list of possible configurations, one for each eigenmode in the
        system, that has `supercell` is compatible with the specified `q`
        vector.

        Args:
            method (str): desired method for computing the eigenvalues and
              eigenvectors. Possible choices are :meth:`hessian` or
              :meth:`dynmat`.
            supercell (numpy.ndarray): supercell matrix to use in generating the
              configs.
            q (numpy.ndarray): q-vector that the resulting supercell should be
              compatible with.
            nrattle (int): number of additional, empty configs to include via
              :meth:`quippy.Atoms.rattle`.
        """
        if method == "hessian":
            dmd = self.hessian()
        elif method == "vasp_hessian":
            dmd = self.vasp_hessian()
        else:
            dmd = self.dynmat(supercell, q)

        hname = "hessian1"
        seed = quippy.Atoms()
        seed.copy_from(dmd["template"])
        result = quippy.AtomsList()
        result.append(dmd["template"])

        #Delete the force, energy and virial information from the copy, so that
        #we don't duplicate it all over.
        del seed.params["dft_energy"]
        del seed.params["dft_virial"]
        del seed.properties["dft_force"]

        for l, v in zip(dmd["eigvals"], dmd["eigvecs"]):
            atc = seed.copy()

            #Add this eigenvector to its own configuration.
            atc.add_property(hname, 0.0, n_cols=3)
            H = np.reshape(v.real, (atc.n, 3)).T
            setattr(atc, hname, H)

            #Same thing for the eigenvalue. Then save it to the group folder
            #structure.
            atc.params.set_value(hname, l)
            atc.params.set_value("n_hessian", 1)
            #atc.add_property("force", 0.0, n_cols=3)
            result.append(atc)

        for i in range(nrattle):
            atRand = seed.copy()
            quippy.randomise(atRand.pos, 0.2)
            result.append(atRand)

        # atz = seed.copy()
        # atz.add_property("dft_force", 0.0, n_cols=3)
        #atz.params.set_value("dft_energy",

        return result

    def vasp_hessian(self):
        """Extracts the hessian from `vasprun.xml`.
        """
        import xml.etree.ElementTree as ET
        tree = ET.parse('vasprun.xml')
        root = tree.getroot()
        calc = root.getchildren()[-2]
        dynm = calc.find("dynmat")
        hessian = dynm.getchildren()[0]
        H = []
        for v in hessian.getchildren():
            H.append(map(float, v.text.split()))

        H = -np.array(H)
        eigvals, eigvecs = np.linalg.eigh(H)
        Na = self.primitive.n * int(np.linalg.det(self.supercell))

        result = {
            "template": self.parent,
            "eigvals": [],
            "eigvecs": [],
            "hessian": H
        }

        for i, l in enumerate(eigvals):
            if np.abs(l) > 1e-3:
                result["eigvals"].append(l)
                result["eigvecs"].append(eigvecs[:, i].reshape(Na, 3))

        return result

    def hessian(self):
        """Returns the non-zero eigenvalues and their corresponding eigenvectors.
        """
        supercell = self.phonopy.get_supercell()
        Na = supercell.get_number_of_atoms()
        Nf = Na * 3
        H = self.phonopy._dynamical_matrix._force_constants.reshape((Nf, Nf))
        eigvals, eigvecs = np.linalg.eigh(H)

        result = {
            "template": phonopy_to_ase(supercell),
            "eigvals": [],
            "eigvecs": []
        }

        for i, l in enumerate(eigvals):
            if np.abs(l) > 0.1:
                result["eigvals"].append(l)
                result["eigvecs"].append(eigvecs[:, i].reshape(Na, 3))

        return result

    def dynmat(self, supercell, q=None, cutoff=0.1):
        """Returns the non-zero eigenvalues and their corresponding eigenvectors
        for the specified supercell.

        Args:
            supercell (numpy.ndarray): supercell matrix to use in generating the
              configs.
            q (numpy.ndarray): q-vector that the resulting supercell should be
              compatible with.
            cutoff (float): minimum value an eigenvalue should have before it is
              included in the set.
        """
        #We need to determine the supercell matrix that is compatible with the
        #given `q` and has `N` atoms.
        scell = get_supercell(self.primitive, supercell)
        eigvals, eigvecs = self.diagonalize(q)

        result = {
            "template": phonopy_to_ase(scell),
            "eigvals": [],
            "eigvecs": []
        }
        for i, l in enumerate(eigvals):
            if np.abs(l) > 0.1:
                meigvec = self._map_eigvec_supercell(scell, eigvecs[:, i])
                result["eigvals"].append(l)
                result["eigvecs"].append(meigvec)

        return result

    def _get_dynmatrix(self):
        """Extracts the force constants from `FORCE_SETS` and constructs the
        dynamical matrix for the calculation.
        """
        with chdir(self.folder):
            force_sets = file_IO.parse_FORCE_SETS()
            self.phonopy.set_displacement_dataset(force_sets)
            self.phonopy.produce_force_constants(
                calculate_full_force_constants=True,
                computation_algorithm="svd")
            self.phonopy._set_dynamical_matrix()
Exemple #10
0
def load(phonopy_yaml=None,  # phonopy.yaml-like must be the first argument.
         supercell_matrix=None,
         primitive_matrix=None,
         is_nac=True,
         calculator=None,
         unitcell=None,
         supercell=None,
         nac_params=None,
         unitcell_filename=None,
         supercell_filename=None,
         born_filename=None,
         force_sets_filename=None,
         force_constants_filename=None,
         use_alm=False,
         factor=None,
         frequency_scale_factor=None,
         symprec=1e-5,
         is_symmetry=True,
         log_level=0):
    """Create Phonopy instance from parameters and/or input files.

    When unitcell and unitcell_filename are not given, file name that is
    default for the chosen calculator is looked for in the current directory
    as the default behaviour.

    When force_sets_filename and force_constants_filename are not given,
    'FORCE_SETS' is looked for in the current directory as the default
    behaviour.

    Parameters
    ----------
    phonopy_yaml : str, optional
        Filename of "phonopy.yaml"-like file. If this is given, the data
        in the file are parsed. Default is None.
    supercell_matrix : array_like, optional
        Supercell matrix multiplied to input cell basis vectors.
        shape=(3, ) or (3, 3), where the former is considered a diagonal
        matrix. Default is the unit matrix.
        dtype=int
    primitive_matrix : array_like or str, optional
        Primitive matrix multiplied to input cell basis vectors. Default is
        the identity matrix.
        shape=(3, 3)
        dtype=float
        When 'F', 'I', 'A', 'C', or 'R' is given instead of a 3x3 matrix,
        the primitive matrix defined at
        https://atztogo.github.io/spglib/definition.html
        is used.
    is_nac : bool, optional
        If True, look for 'BORN' file. If False, NAS is turned off.
        The priority for NAC is nac_params > born_filename > is_nac ('BORN').
        Default is True.
    calculator : str, optional.
        Calculator used for computing forces. This is used to switch the set
        of physical units. Default is None, which is equivalent to "vasp".
    unitcell : PhonopyAtoms, optional
        Input unit cell. Default is None. The priority for cell is
        unitcell_filename > supercell_filename > unitcell > supercell.
    supercell : PhonopyAtoms, optional
        Input supercell cell. Default value of primitive_matrix is set to
        'auto' (can be overwitten). supercell_matrix is ignored. Default is
        None. The priority for cell is
        unitcell_filename > supercell_filename > unitcell > supercell.
    nac_params : dict, optional
        Parameters required for non-analytical term correction. Default is
        None. The priority for NAC is nac_params > born_filename > is_nac.
        {'born': Born effective charges
                 (array_like, shape=(primitive cell atoms, 3, 3), dtype=float),
         'dielectric': Dielectric constant matrix
                       (array_like, shape=(3, 3), dtype=float),
         'factor': unit conversion facotr (float)}
    unitcell_filename : str, optional
        Input unit cell filename. Default is None. The priority for cell is
        unitcell_filename > supercell_filename > unitcell > supercell.
    supercell_filename : str, optional
        Input supercell filename. Default value of primitive_matrix is set to
        'auto' (can be overwitten). supercell_matrix is ignored. Default is
        None. The priority for cell is
        unitcell_filename > supercell_filename > unitcell > supercell.
    born_filename : str, optional
        Filename corresponding to 'BORN', a file contains non-analytical term
        correction parameters.
        The priority for NAC is nac_params > born_filename > is_nac ('BORN').
    force_sets_filename : str, optional
        Filename of a file corresponding to 'FORCE_SETS', a file contains sets
        of forces and displacements. Default is None.
        The priority for force constants is
        force_constants_filename > force_sets_filename > 'FORCE_SETS'.
    force_constants_filename : str, optional
        Filename of a file corresponding to 'FORCE_CONSTANTS' or
        'force_constants.hdf5', a file contains force constants.
        Default is None.
        The priority for force constants is
        force_constants_filename > force_sets_filename > 'FORCE_SETS'.
    use_alm : bool, optional
        Default is False.
    factor : float, optional
        Phonon frequency unit conversion factor. Unless specified, default
        unit conversion factor for each calculator is used.
    frequency_scale_factor : float, optional
        Factor multiplied to calculated phonon frequency. Default is None,
        i.e., effectively 1.
    symprec : float, optional
        Tolerance used to find crystal symmetry. Default is 1e-5.
    is_symmetry : bool, optional
        Setting False, crystal symmetry except for lattice translation is not
        considered. Default is True.
    log_level : int, optional
        Verbosity control. Default is 0.

    """

    if phonopy_yaml is None:
        cell, smat, pmat = load_helper.get_cell_settings(
            supercell_matrix=supercell_matrix,
            primitive_matrix=primitive_matrix,
            unitcell=unitcell,
            supercell=supercell,
            unitcell_filename=unitcell_filename,
            supercell_filename=supercell_filename,
            calculator=calculator,
            symprec=symprec)
        _nac_params = nac_params
        _dataset = None
        _fc = None
    else:
        phpy_yaml = PhonopyYaml()
        phpy_yaml.read(phonopy_yaml)
        cell = phpy_yaml.unitcell
        smat = phpy_yaml.supercell_matrix
        if smat is None:
            raise RuntimeError("%s could not be parsed.")
        if primitive_matrix is 'auto':
            pmat = 'auto'
        else:
            pmat = phpy_yaml.primitive_matrix
        if is_nac:
            _nac_params = phpy_yaml.nac_params
        else:
            _nac_params = None
        _dataset = phpy_yaml.dataset
        _fc =  phpy_yaml.force_constants

    # units keywords: factor, nac_factor, distance_to_A
    units = get_default_physical_units(calculator)
    if factor is None:
        _factor = units['factor']
    else:
        _factor = factor
    phonon = Phonopy(cell,
                     smat,
                     primitive_matrix=pmat,
                     factor=_factor,
                     frequency_scale_factor=frequency_scale_factor,
                     symprec=symprec,
                     is_symmetry=is_symmetry,
                     calculator=calculator,
                     log_level=log_level)
    load_helper.set_nac_params(phonon,
                               _nac_params,
                               born_filename,
                               is_nac,
                               units['nac_factor'])
    if _fc is None:
        load_helper.set_force_constants(
            phonon,
            dataset=_dataset,
            force_constants_filename=force_constants_filename,
            force_sets_filename=force_sets_filename,
            calculator=calculator,
            use_alm=use_alm)
    else:
        phonon.force_constants = _fc
    return phonon
Exemple #11
0
def get_phonon(structure,
               NAC=False,
               setup_forces=True,
               super_cell_phonon=np.identity(3),
               primitive_axis=np.identity(3)):

    phonon = Phonopy(structure, super_cell_phonon,
                     primitive_matrix=primitive_axis,
                     symprec=1e-5)

    # Non Analytical Corrections (NAC) from Phonopy [Frequencies only, eigenvectors no affected by this option]

    if setup_forces:
        if structure.get_force_constants() is not None:
            phonon.set_force_constants(structure.get_force_constants().get_array())
        elif structure.get_force_sets() is not None:
            phonon.set_displacement_dataset(structure.get_force_sets().get_dict())
            phonon.produce_force_constants(computation_algorithm="svd")
            structure.set_force_constants(ForceConstants(phonon.get_force_constants(),
                                                         supercell=structure.get_force_sets().get_supercell()))
        else:
            print('No force sets/constants available!')
            exit()

    if NAC:
        print("Using non-analytical corrections")
        primitive = phonon.get_primitive()
        nac_params = parse_BORN(primitive, is_symmetry=True)
        phonon.set_nac_params(nac_params=nac_params)

    return phonon
Exemple #12
0
 def _get_phonon(self):
     cell = read_vasp(os.path.join(data_dir, "..", "POSCAR_NaCl"))
     phonon = Phonopy(cell,
                      np.diag([2, 2, 2]),
                      primitive_matrix=[[0, 0.5, 0.5], [0.5, 0, 0.5],
                                        [0.5, 0.5, 0]])
     filename = os.path.join(data_dir, "..", "FORCE_SETS_NaCl")
     force_sets = parse_FORCE_SETS(filename=filename)
     phonon.set_displacement_dataset(force_sets)
     phonon.produce_force_constants()
     phonon.symmetrize_force_constants()
     filename_born = os.path.join(data_dir, "..", "BORN_NaCl")
     nac_params = parse_BORN(phonon.get_primitive(), filename=filename_born)
     phonon.set_nac_params(nac_params)
     return phonon
def get_phonon(structure, NAC=False, setup_forces=True, custom_supercell=None):

    if custom_supercell is None:
        super_cell_phonon = structure.get_supercell_phonon()
    else:
        super_cell_phonon = custom_supercell

    # Preparing the bulk type object
    bulk = PhonopyAtoms(symbols=structure.get_atomic_elements(),
                        scaled_positions=structure.get_scaled_positions(),
                        cell=structure.get_cell())

    phonon = Phonopy(bulk, super_cell_phonon,
                     primitive_matrix=structure.get_primitive_matrix(),
                     symprec=1e-5)

    # Non Analytical Corrections (NAC) from Phonopy [Frequencies only, eigenvectors no affected by this option]

    if setup_forces:
        if structure.get_force_constants() is not None:
            phonon.set_force_constants(structure.get_force_constants().get_array())
        elif structure.get_force_sets() is not None:
            phonon.set_displacement_dataset(structure.get_force_sets().get_dict())
            phonon.produce_force_constants()
            structure.set_force_constants(ForceConstants(phonon.get_force_constants(),
                                                         supercell=structure.get_force_sets().get_supercell()))
        else:
            print('No force sets/constants available!')
            exit()

    if NAC:
        print("Warning: Using Non Analytical Corrections")
        primitive = phonon.get_primitive()
        nac_params = parse_BORN(primitive, is_symmetry=True)
        phonon.set_nac_params(nac_params=nac_params)

    return phonon