Exemple #1
0
def write_supercells_with_displacements(interface_mode,
                                        supercell,
                                        cells_with_disps,
                                        optional_structure_info,
                                        displacement_ids=None,
                                        zfill_width=3,
                                        additional_info=None):
    """Utility method to write out supercell structures with displacements

    interface_mode : str
        Calculator interface such as 'vasp', 'qe', ...
    supercell : Supercell
        Supercell.
    cells_with_disps : list of PhonopyAtoms
        Supercells with displacements.
    optional_structure_info : tuple
        Information returned by the method ``read_crystal_structure``.
        See the docstring.
    displacements_ids : array_like or None, optional
        Integer 1d array with the length of cells_with_disps, containing
        numbers to be assigned to the supercells with displacements.
        Default is None, which gives [1, 2, 3, ...].
    zfill_width : int, optional
        Supercell numbers are filled by zeros from the left with the digits
        as given, which results in 001, 002, ..., when zfill_width=3.
    additional_info : dict or None, optional
        Any information expected to be given to writers of calculators.
        Default is None.

    """

    if displacement_ids is None:
        ids = np.arange(len(cells_with_disps), dtype=int) + 1
    else:
        ids = displacement_ids

    args = (supercell, cells_with_disps, ids)
    kwargs = {'width': zfill_width}
    if 'pre_filename' in additional_info:
        kwargs['pre_filename'] = additional_info['pre_filename']

    if interface_mode is None or interface_mode == 'vasp':
        import phonopy.interface.vasp as vasp
        vasp.write_supercells_with_displacements(*args, **kwargs)
        write_magnetic_moments(supercell, sort_by_elements=True)
    elif interface_mode == 'abinit':
        import phonopy.interface.abinit as abinit
        abinit.write_supercells_with_displacements(*args, **kwargs)
    elif interface_mode == 'qe':
        import phonopy.interface.qe as qe
        pp_filenames = optional_structure_info[1]
        qe_args = args + (pp_filenames, )
        qe.write_supercells_with_displacements(*qe_args, **kwargs)
        write_magnetic_moments(supercell, sort_by_elements=False)
    elif interface_mode == 'wien2k':
        import phonopy.interface.wien2k as wien2k
        unitcell_filename, npts, r0s, rmts = optional_structure_info
        N = abs(determinant(additional_info['supercell_matrix']))
        w2k_args = args + (npts, r0s, rmts, N)
        if 'pre_filename' not in kwargs:
            kwargs['pre_filename'] = unitcell_filename
        wien2k.write_supercells_with_displacements(*w2k_args, **kwargs)
    elif interface_mode == 'elk':
        import phonopy.interface.elk as elk
        sp_filenames = optional_structure_info[1]
        elk_args = args + (sp_filenames, )
        elk.write_supercells_with_displacements(*elk_args, **kwargs)
    elif interface_mode == 'siesta':
        import phonopy.interface.siesta as siesta
        atypes = optional_structure_info[1]
        sst_args = args + (atypes, )
        siesta.write_supercells_with_displacements(*sst_args, **kwargs)
    elif interface_mode == 'cp2k':
        import phonopy.interface.cp2k as cp2k
        cp2k_args = args + (optional_structure_info, )
        cp2k.write_supercells_with_displacements(*cp2k_args, **kwargs)
    elif interface_mode == 'crystal':
        import phonopy.interface.crystal as crystal
        if additional_info is None:
            kwargs['template_file'] = "TEMPLATE"
        else:
            kwargs['template_file'] = additional_info.get(
                'template_file', "TEMPLATE")
        conv_numbers = optional_structure_info[1]
        N = abs(determinant(additional_info['supercell_matrix']))
        cst_args = args + (conv_numbers, N)
        crystal.write_supercells_with_displacements(*cst_args, **kwargs)
    elif interface_mode == 'dftbp':
        import phonopy.interface.dftbp as dftbp
        dftbp.write_supercells_with_displacements(*args, **kwargs)
    elif interface_mode == 'turbomole':
        import phonopy.interface.turbomole as turbomole
        turbomole.write_supercells_with_displacements(*args, **kwargs)
    elif interface_mode == 'aims':
        import phonopy.interface.aims as aims
        aims.write_supercells_with_displacements(*args, **kwargs)
    else:
        raise RuntimeError("No calculator interface was found.")
Exemple #2
0
def load_phonopy(filename, structure, dim, symprec=0.01, primitive_matrix=None,
                 factor=VaspToTHz, symmetrise=True, born=None, write_fc=False):
    """Load phonopy output and return an ``phonopy.Phonopy`` object.

    Args:
        filename (str): Path to phonopy output. Can be any of ``FORCE_SETS``,
            ``FORCE_CONSTANTS``, or ``force_constants.hdf5``.
        structure (:obj:`~pymatgen.core.structure.Structure`): The unitcell
            structure.
        dim (list): The supercell size, as a :obj:`list` of :obj:`float`.
        symprec (:obj:`float`, optional): The tolerance for determining the
            crystal symmetry.
        primitive_matrix (:obj:`list` or :obj:`str`, optional): The
            transformation matrix from the conventional to primitive cell. Only
            required when the conventional cell was used as the starting
            structure. Should be provided as a 3x3 :obj:`list` of :obj:`float`.
            Alternatively the str 'auto' may be provided.
        factor (:obj:`float`, optional): The conversion factor for phonon
            frequency. Defaults to :obj:`phonopy.units.VaspToTHz`.
        symmetrise (:obj:`bool`, optional): Symmetrise the force constants.
            Defaults to ``True``.
        born (:obj:`str`, optional): Path to file containing Born effective
            charges. Should be in the same format as the file produced by the
            ``phonopy-vasp-born`` script provided by phonopy.
        write_fc (:obj:`bool` or :obj:`str`,  optional): Write the force
            constants to disk. If ``True``, a ``FORCE_CONSTANTS`` file will be
            written. Alternatively, if set to ``"hdf5"``, a
            ``force_constants.hdf5`` file will be written. Defaults to
            ``False`` (force constants not written).
    """
    unitcell = get_phonopy_structure(structure)
    num_atom = unitcell.get_number_of_atoms()
    num_satom = determinant(dim) * num_atom

    phonon = Phonopy(unitcell, dim, primitive_matrix=primitive_matrix,
                     factor=factor, symprec=symprec)

    if 'FORCE_CONSTANTS' == filename or '.hdf5' in filename:
        # if force constants exist, use these to avoid recalculating them
        if '.hdf5' in filename:
            fc = file_IO.read_force_constants_hdf5(filename)

        elif 'FORCE_CONSTANTS' == filename:
            fc = file_IO.parse_FORCE_CONSTANTS(filename=filename)

        if fc.shape[0] != num_satom:
            msg = ("\nNumber of atoms in supercell is not consistent with the "
                   "matrix shape of\nforce constants read from {}.\nPlease"
                   "carefully check --dim.")
            logging.error(msg.format(filename))
            sys.exit()

        phonon.set_force_constants(fc)

    elif 'FORCE_SETS' == filename:
        # load the force sets from file and calculate force constants
        fs = file_IO.parse_FORCE_SETS()

        if fs['natom'] != num_satom:
            msg = ("\nNumber of atoms in supercell is not consistent with the "
                   "the data in FORCE_SETS\nPlease carefully check --dim.")
            logging.error(msg.format(filename))
            sys.exit()

        phonon.set_displacement_dataset(fs)

        logging.info("Calculating force constants...")
        phonon.produce_force_constants()

    if born:
        # load born parameters from a file
        nac_params = file_IO.parse_BORN(phonon._primitive,
                                        symprec=symprec,
                                        filename=born)

        # set the nac unit conversion factor manual,  specific to VASP
        nac_params['factor'] = Hartree * Bohr
        phonon.set_nac_params(nac_params)

    if symmetrise:
        phonon.symmetrize_force_constants()

    if write_fc == 'hdf5':
        file_IO.write_force_constants_to_hdf5(phonon.get_force_constants())
        logging.info("Force constants written to force_constants.hdf5.")

    elif write_fc:
        file_IO.write_FORCE_CONSTANTS(phonon.get_force_constants())
        logging.info("Force constants written to FORCE_CONSTANTS.")

    return phonon
Exemple #3
0
def get_phonon_tb(
    # phonopy_atoms=[],
    atoms=[],
    fc=[],
    out_file="phonopyTB_hr.dat",
    distance_to_A=1.0,
    scell=np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
    factor=VaspToTHz,
    symprec=1e-05,
    displacement_distance=0.01,
):
    """Generate phonon TB Hamiltonia, along with WannierHamn."""
    # Forked from Wannier-tools
    unitcell = atoms.phonopy_converter()
    # unitcell = phonopy_atoms
    prim_mat = np.array(PhonopyInputs(atoms).prim_axis().split("=")[1].split(),
                        dtype="float").reshape(3, 3)
    # print("cell", unitcell.cell)
    num_atom = unitcell.get_number_of_atoms()
    num_satom = determinant(scell) * num_atom
    if fc.shape[0] != num_satom:
        print("Check Force constant matrix.")
    phonon = Phonopy(
        unitcell,
        scell,
        primitive_matrix=prim_mat,
        factor=factor,
        dynamical_matrix_decimals=None,
        force_constants_decimals=None,
        symprec=symprec,
        is_symmetry=True,
        use_lapack_solver=False,
        log_level=1,
    )

    supercell = phonon.get_supercell()
    primitive = phonon.get_primitive()
    # Set force constants
    phonon.set_force_constants(fc)
    phonon._set_dynamical_matrix()
    dmat = phonon._dynamical_matrix
    # rescale fcmat by THZ**2
    fcmat = dmat._force_constants * factor**2  # FORCE_CONSTANTS
    # fcmat = dmat._force_constants * factor ** 2  # FORCE_CONSTANTS
    smallest_vectors = dmat._smallest_vectors
    # mass = dmat._mass
    mass = dmat._pcell.get_masses()
    print("mass=", mass)
    multi = dmat._multiplicity
    reduced_bases = get_reduced_bases(supercell.get_cell(), symprec)
    positions = np.dot(supercell.get_positions(), np.linalg.inv(reduced_bases))
    # for pos in positions: pos -= np.rint(pos)
    relative_scale = np.dot(reduced_bases, np.linalg.inv(primitive.get_cell()))
    super_pos = np.zeros((num_satom, 3), dtype=np.float64)
    for i in range(num_satom):
        super_pos[i] = np.dot(positions[i], relative_scale)
    p2s_map = dmat._p2s_map = primitive.get_primitive_to_supercell_map()
    s2p_map = dmat._s2p_map = primitive.get_supercell_to_primitive_map()
    num_satom = supercell.get_number_of_atoms()
    num_patom = primitive.get_number_of_atoms()
    get_phonon_hr(
        fcmat,
        smallest_vectors,
        mass,
        multi,
        super_pos,
        p2s_map,
        s2p_map,
        num_satom,
        num_patom,
        out_file,
    )
    print("phonopy_TB.dat generated! ")
Exemple #4
0
def get_reciprocal_operations(rotations,
                              transformation_matrix,
                              D,
                              Q,
                              is_time_reversal=True):
    """Generate reciprocal rotation matrices.

    Collect unique real space rotation matrices and transpose them.
    When is_time_reversal=True, inversion is added if it is not in the
    list of the rotation matrices.

    Parameters
    ----------
    rotations : ndarray
        Rotation matrices in real space. x' = Rx.
        shape=(rotations, 3, 3), dtype='int_'
    transformation_matrxi : array_like
        Transformation matrix of basis vectors in real space. Using this
        rotation matrices are transformed.
    D : array_like
        D of smith normal form 3x3.
        shape=(3, 3)
    Q : array_like
        Q of smith normal form 3x3.
        shape=(3, 3)
    is_time_reversal : bool
        When True, inversion operation is added.

    Returns
    -------
    rotations_for_Q : ndarray
        Rotation matrices in reciprocal space. Grid points are sent by the
        symmetrically equivalent grid points as follows:

        g' = (R_Q g) % diagonal(D)

        shape=(rotations, 3, 3), dtype='int_', order='C'

    """
    unique_rots = []
    tmat_inv = np.linalg.inv(transformation_matrix)
    for r in collect_unique_rotations(rotations):
        _r = similarity_transformation(tmat_inv, r)
        _r_int = np.rint(_r).astype(int)
        assert (np.abs(_r - _r_int) < 1e-5).all()
        unique_rots.append(_r_int)

    ptg_ops, rec_ops = get_pointgroup_operations(
        unique_rots, is_time_reversal=is_time_reversal)

    Q_inv = np.linalg.inv(Q)
    rec_ops_Q = []
    for r in rec_ops:
        _r = similarity_transformation(Q_inv, r)
        _r = similarity_transformation(D, _r)
        _r_int = np.rint(_r).astype(int)
        assert (np.abs(_r - _r_int) < 1e-5).all()
        assert abs(determinant(_r_int)) == 1
        rec_ops_Q.append(_r_int)

    return np.array(rec_ops_Q, dtype="int_", order="C")
Exemple #5
0
def create_phono3py_supercells(unitcell,
                               supercell_matrix,
                               phonon_supercell_matrix,
                               displacement_distance,
                               is_plusminus,
                               is_diagonal,
                               cutoff_pair_distance,
                               write_supercells_with_displacements,
                               optional_structure_file_information,
                               is_symmetry,
                               symprec,
                               interface_mode='vasp',
                               output_filename=None,
                               log_level=1):
    if displacement_distance is None:
        if interface_mode in ('qe', 'abinit', 'turbomole'):
            distance = 0.06
        elif interface_mode == 'crystal':
            distance = 0.03
        else:
            distance = 0.03
    else:
        distance = displacement_distance
    phono3py = Phono3py(unitcell,
                        supercell_matrix,
                        phonon_supercell_matrix=phonon_supercell_matrix,
                        is_symmetry=is_symmetry,
                        symprec=symprec)
    supercell = phono3py.get_supercell()
    phono3py.generate_displacements(distance=distance,
                                    cutoff_pair_distance=cutoff_pair_distance,
                                    is_plusminus=is_plusminus,
                                    is_diagonal=is_diagonal)
    dds = phono3py.get_displacement_dataset()

    if log_level:
        print('')
        print("Displacement distance: %s" % distance)

    if output_filename is None:
        filename = 'disp_fc3.yaml'
    else:
        filename = 'disp_fc3.' + output_filename + '.yaml'

    num_disps, num_disp_files = write_disp_fc3_yaml(dds,
                                                    supercell,
                                                    filename=filename)
    cells_with_disps = phono3py.get_supercells_with_displacements()
    if interface_mode == 'qe':
        pp_filenames = optional_structure_file_information[1]
        write_supercells_with_displacements(supercell,
                                            cells_with_disps,
                                            pp_filenames,
                                            width=5)
    elif interface_mode == 'crystal':
        conv_numbers = optional_structure_file_information[1]
        # N_FC3 = num_unitcells_in_supercell (here for FC3 supercell)
        N_FC3 = abs(determinant(supercell_matrix))
        write_supercells_with_displacements(supercell,
                                            cells_with_disps,
                                            conv_numbers,
                                            N_FC3,
                                            width=5,
                                            template_file="TEMPLATE3")
    elif interface_mode == 'abinit':
        write_supercells_with_displacements(supercell,
                                            cells_with_disps,
                                            width=5)
    elif interface_mode == 'turbomole':
        write_supercells_with_displacements(supercell,
                                            cells_with_disps,
                                            width=5)
    else:  # VASP
        write_supercells_with_displacements(supercell,
                                            cells_with_disps,
                                            width=5)

    if log_level:
        print("Number of displacements: %d" % num_disps)
        if cutoff_pair_distance is not None:
            print("Cutoff distance for displacements: %s" %
                  cutoff_pair_distance)
            print("Number of displacement supercell files created: %d" %
                  num_disp_files)

    if phonon_supercell_matrix is not None:
        phonon_dds = phono3py.get_phonon_displacement_dataset()
        phonon_supercell = phono3py.get_phonon_supercell()
        if output_filename is None:
            filename = 'disp_fc2.yaml'
        else:
            filename = 'disp_fc2.' + output_filename + '.yaml'

        num_disps = write_disp_fc2_yaml(phonon_dds,
                                        phonon_supercell,
                                        filename=filename)
        cells_with_disps = phono3py.get_phonon_supercells_with_displacements()
        if interface_mode == 'qe':
            pp_filenames = optional_structure_file_information[1]
            write_supercells_with_displacements(phonon_supercell,
                                                cells_with_disps,
                                                pp_filenames,
                                                pre_filename="supercell_fc2",
                                                width=5)
        elif interface_mode == 'crystal':
            conv_numbers = optional_structure_file_information[1]
            # N = num_unitcells_in_supercell (here for FC2 supercell)
            N_FC2 = abs(determinant(phonon_supercell_matrix))
            write_supercells_with_displacements(phonon_supercell,
                                                cells_with_disps,
                                                conv_numbers,
                                                N_FC2,
                                                pre_filename="supercell_fc2",
                                                width=5,
                                                template_file="TEMPLATE")
        elif interface_mode == 'abinit':
            write_supercells_with_displacements(phonon_supercell,
                                                cells_with_disps,
                                                pre_filename="supercell_fc2",
                                                width=5)
        elif interface_mode == 'turbomole':
            write_supercells_with_displacements(phonon_supercell,
                                                cells_with_disps,
                                                pre_filename="supercell_fc2",
                                                width=5)
        else:
            write_supercells_with_displacements(phonon_supercell,
                                                cells_with_disps,
                                                pre_filename="POSCAR_FC2",
                                                width=5)

        if log_level:
            print("Number of displacements for special fc2: %d" % num_disps)

    return phono3py
Exemple #6
0
            or interface_mode == 'elk' or interface_mode == 'pwscf'
            or interface_mode == 'siesta'):
        displacement_distance = 0.02
    else:  # default or vasp
        displacement_distance = 0.01
else:
    displacement_distance = settings.get_displacement_distance()

# Supercell matrix
if settings.get_supercell_matrix() is None:
    print_error_message("Supercell matrix (DIM or --dim) is not found.")
    if log_level > 0:
        print_end()
    sys.exit(1)
num_atom = unitcell.get_number_of_atoms()
num_satom = determinant(settings.get_supercell_matrix()) * num_atom
if settings.get_is_force_constants() == 'read':
    if file_exists("FORCE_CONSTANTS", log_level):
        fc = file_IO.parse_FORCE_CONSTANTS(filename="FORCE_CONSTANTS")
        fc_filename = "FORCE_CONSTANTS"

    if log_level > 0:
        print("Force constants are read from %s." % fc_filename)

    if fc.shape[0] != num_satom:
        error_text = ("Number of atoms in supercell is not consistent with "
                      "the matrix shape of\nforce constants read from ")
        if settings.get_is_hdf5():
            error_text += "force_constants.hdf5.\n"
        else:
            error_text += "FORCE_CONSTANTS.\n"