Esempio n. 1
0
def read_aims(filename):
    '''Method to read FHI-aims geometry files in phonopy context.'''
    cell = []
    positions = []
    fractional = []
    symbols = []
    magmoms = []
    with open(filename) as f:
        while True:
            line = f.readline()
            if not line:
                break
            line = line.split()
            if line[0] == 'lattice_vector':
                cell.append([float(x) for x in line[1:4]])
            elif line[0].startswith('atom'):
                fractional.append(line[0] == 'atom_frac')
                positions.append([float(x) for x in line[1:4]])
                symbols.append(line[4])
            elif line[0] == 'initial_moment':
                magmoms.append(float(line[1]))

    for n, pos in enumerate(positions):
        if fractional[n]:
            positions[n] = [
                sum([pos[j] * cell[j][i] for j in range(3)]) for i in range(3)
            ]
    if len(magmoms) == len(positions):
        return PhonopyAtoms(cell=cell,
                            symbols=symbols,
                            positions=positions,
                            magmoms=magmoms)
    else:
        return PhonopyAtoms(cell=cell, symbols=symbols, positions=positions)
Esempio n. 2
0
def read_castep(filename):
    f_castep = open(filename)
    castep_in = CastepIn(f_castep.readlines())
    f_castep.close()
    tags = castep_in.get_tags()
    # 1st stage is to create Atoms object ignoring Spin polarization. General case.
    cell = Atoms(cell=tags['lattice_vectors'],
                 symbols=tags['atomic_species'],
                 scaled_positions=tags['coordinates'])
    # Analyse spin states and add data to Atoms instance "cell" if ones exist
    magmoms = tags['magnetic_moments']
    if magmoms is not None:
        # Print out symmetry information for magnetic cases
        # Original code from structure/symmetry.py
        symmetry = Symmetry(cell, symprec=1e-5)
        print(
            "CASTEP-interface: Magnetic structure, number of operations without spin: %d"
            % len(symmetry.get_symmetry_operations()['rotations']))
        print("CASTEP-interface: Spacegroup without spin: %s" %
              symmetry.get_international_table())

        cell.set_magnetic_moments(magmoms)
        symmetry = Symmetry(cell, symprec=1e-5)
        print(
            "CASTEP-interface: Magnetic structure, number of operations with spin: %d"
            % len(symmetry.get_symmetry_operations()['rotations']))
        print("")

    return cell
Esempio n. 3
0
    def _create_supercell(self, unitcell, symprec):
        mat = self._supercell_matrix
        frame = self._get_surrounding_frame(mat)
        sur_cell, u2sur_map = self._get_simple_supercell(frame, unitcell)
    
        # Trim the simple supercell by the supercell matrix
        trim_frame = np.array([mat[0] / float(frame[0]),
                               mat[1] / float(frame[1]),
                               mat[2] / float(frame[2])])
        supercell, sur2s_map, mapping_table = trim_cell(trim_frame,
                                                        sur_cell,
                                                        symprec)

        multi = supercell.get_number_of_atoms() // unitcell.get_number_of_atoms()
        
        if multi != determinant(self._supercell_matrix):
            print("Supercell creation failed.")
            print("Probably some atoms are overwrapped. "
                  "The mapping table is give below.")
            print(mapping_table)
            Atoms.__init__(self)
        else:            
            Atoms.__init__(self,
                           numbers=supercell.get_atomic_numbers(),
                           masses=supercell.get_masses(),
                           magmoms=supercell.get_magnetic_moments(),
                           scaled_positions=supercell.get_scaled_positions(),
                           cell=supercell.get_cell(),
                           pbc=True)
            self._u2s_map = np.arange(unitcell.get_number_of_atoms()) * multi
            self._u2u_map = dict([(j, i) for i, j in enumerate(self._u2s_map)])
            self._s2u_map = np.array(u2sur_map)[sur2s_map] * multi
Esempio n. 4
0
def read_crystal(filename):
    f_crystal = open(filename)
    crystal_in = CrystalIn(f_crystal.readlines())
    f_crystal.close()
    tags = crystal_in.get_tags()
     
     
    cell = Atoms(cell=tags['lattice_vectors'], 
                 symbols=tags['atomic_species'],
                 scaled_positions=tags['coordinates'])
    
    magmoms = tags['magnetic_moments']
    if magmoms is not None:
        # Print out symmetry information for magnetic cases
        # Original code from structure/symmetry.py
        symmetry = Symmetry(cell, symprec=1e-5)
        print("CRYSTAL-interface: Magnetic structure, number of operations without spin: %d" %
              len(symmetry.get_symmetry_operations()['rotations']))
        print("CRYSTAL-interface: Spacegroup without spin: %s" % symmetry.get_international_table())

        cell.set_magnetic_moments(magmoms)
        symmetry = Symmetry(cell, symprec=1e-5)
        print("CRYSTAL-interface: Magnetic structure, number of operations with spin: %d" %
              len(symmetry.get_symmetry_operations()['rotations']))
        print("")
    
    return cell, tags['conv_numbers']
Esempio n. 5
0
    def _create_supercell(self, unitcell, symprec):
        mat = self._supercell_matrix
        frame = self._get_surrounding_frame(mat)
        sur_cell, u2sur_map = self._get_simple_supercell(frame, unitcell)

        # Trim the simple supercell by the supercell matrix
        trim_frame = np.array([
            mat[0] / float(frame[0]), mat[1] / float(frame[1]),
            mat[2] / float(frame[2])
        ])
        supercell, sur2s_map, mapping_table = trim_cell(
            trim_frame, sur_cell, symprec)

        num_satom = supercell.get_number_of_atoms()
        num_uatom = unitcell.get_number_of_atoms()
        multi = num_satom // num_uatom

        if multi != determinant(self._supercell_matrix):
            print("Supercell creation failed.")
            print("Probably some atoms are overwrapped. "
                  "The mapping table is give below.")
            print(mapping_table)
            Atoms.__init__(self)
        else:
            Atoms.__init__(self,
                           numbers=supercell.get_atomic_numbers(),
                           masses=supercell.get_masses(),
                           magmoms=supercell.get_magnetic_moments(),
                           scaled_positions=supercell.get_scaled_positions(),
                           cell=supercell.get_cell(),
                           pbc=True)
            self._u2s_map = np.arange(num_uatom) * multi
            self._u2u_map = dict([(j, i) for i, j in enumerate(self._u2s_map)])
            self._s2u_map = np.array(u2sur_map)[sur2s_map] * multi
Esempio n. 6
0
def read_pwscf(filename):
    pwscf_in = PwscfIn(open(filename).readlines())
    tags = pwscf_in.get_tags()
    lattice = tags['cell_parameters']
    positions = [pos[1] for pos in tags['atomic_positions']]
    species = [pos[0] for pos in tags['atomic_positions']]
    mass_map = {}
    pp_map = {}
    for vals in tags['atomic_species']:
        mass_map[vals[0]] = vals[1]
        pp_map[vals[0]] = vals[2]
    masses = [mass_map[x] for x in species]
    pp_all_filenames = [pp_map[x] for x in species]

    unique_species = []
    for x in species:
        if x not in unique_species:
            unique_species.append(x)

    numbers = []
    is_unusual = False
    for x in species:
        if x in symbol_map:
            numbers.append(symbol_map[x])
        else:
            numbers.append(-unique_species.index(x))
            is_unusual = True

    if is_unusual:
        positive_numbers = []
        for n in numbers:
            if n > 0:
                if n not in positive_numbers:
                    positive_numbers.append(n)

        available_numbers = range(1, 119)
        for pn in positive_numbers:
            available_numbers.remove(pn)

        for i, n in enumerate(numbers):
            if n < 1:
                numbers[i] = available_numbers[-n]

        cell = Atoms(numbers=numbers,
                     masses=masses,
                     cell=lattice,
                     scaled_positions=positions)
    else:
        cell = Atoms(numbers=numbers,
                     cell=lattice,
                     scaled_positions=positions)

    unique_symbols = []
    pp_filenames = {}
    for i, symbol in enumerate(cell.get_chemical_symbols()):
        if symbol not in unique_symbols:
            unique_symbols.append(symbol)
            pp_filenames[symbol] = pp_all_filenames[i]

    return cell, pp_filenames
Esempio n. 7
0
def read_crystal(filename):
    f_crystal = open(filename)
    crystal_in = CrystalIn(f_crystal.readlines())
    f_crystal.close()
    tags = crystal_in.get_tags()

    cell = Atoms(cell=tags['lattice_vectors'],
                 symbols=tags['atomic_species'],
                 scaled_positions=tags['coordinates'])

    magmoms = tags['magnetic_moments']
    if magmoms is not None:
        # Print out symmetry information for magnetic cases
        # Original code from structure/symmetry.py
        symmetry = Symmetry(cell, symprec=1e-5)
        print(
            "CRYSTAL-interface: Magnetic structure, number of operations without spin: %d"
            % len(symmetry.get_symmetry_operations()['rotations']))
        print("CRYSTAL-interface: Spacegroup without spin: %s" %
              symmetry.get_international_table())

        cell.set_magnetic_moments(magmoms)
        symmetry = Symmetry(cell, symprec=1e-5)
        print(
            "CRYSTAL-interface: Magnetic structure, number of operations with spin: %d"
            % len(symmetry.get_symmetry_operations()['rotations']))
        print("")

    return cell, tags['conv_numbers']
Esempio n. 8
0
    def setUp(self):
        self._cells = []
        symbols = ['Si'] * 2 + ['O'] * 4
        lattice = [[4.65, 0, 0], [0, 4.75, 0], [0, 0, 3.25]]
        points = [[0.0, 0.0, 0.0], [0.5, 0.5, 0.5], [0.3, 0.3, 0.0],
                  [0.7, 0.7, 0.0], [0.2, 0.8, 0.5], [0.8, 0.2, 0.5]]

        self._cells.append(
            PhonopyAtoms(cell=lattice,
                         scaled_positions=points,
                         symbols=symbols))

        symbols = ['Si'] * 2
        lattice = [[0, 2.73, 2.73], [2.73, 0, 2.73], [2.73, 2.73, 0]]
        points = [[0.75, 0.75, 0.75], [0.5, 0.5, 0.5]]

        self._cells.append(
            PhonopyAtoms(cell=lattice,
                         scaled_positions=points,
                         symbols=symbols))

        self._smats = []
        self._smats.append(np.diag([1, 2, 3]))
        self._smats.append([[-1, 1, 1], [1, -1, 1], [1, 1, -1]])

        self._fnames = ("SiO2-123.yaml", "Si-conv.yaml")
Esempio n. 9
0
def test_magmom(convcell_cr: PhonopyAtoms):
    """Test symmetry search with hmagnetic moments."""
    symprec = 1e-5
    symmetry_nonspin = Symmetry(convcell_cr, symprec=symprec)
    atom_map_nonspin = symmetry_nonspin.get_map_atoms()
    len_sym_nonspin = len(symmetry_nonspin.symmetry_operations["rotations"])

    spin = [1, -1]
    cell_withspin = convcell_cr.copy()
    cell_withspin.magnetic_moments = spin
    symmetry_withspin = Symmetry(cell_withspin, symprec=symprec)
    atom_map_withspin = symmetry_withspin.get_map_atoms()
    len_sym_withspin = len(symmetry_withspin.symmetry_operations["rotations"])

    broken_spin = [1, -2]
    cell_brokenspin = convcell_cr.copy()
    cell_brokenspin = convcell_cr.copy()
    cell_brokenspin.magnetic_moments = broken_spin
    symmetry_brokenspin = Symmetry(cell_brokenspin, symprec=symprec)
    atom_map_brokenspin = symmetry_brokenspin.get_map_atoms()
    len_sym_brokenspin = len(
        symmetry_brokenspin.symmetry_operations["rotations"])

    assert (atom_map_nonspin == atom_map_withspin).all()
    assert (atom_map_nonspin != atom_map_brokenspin).any()
    assert len_sym_nonspin == len_sym_withspin
    assert len_sym_nonspin != len_sym_brokenspin
Esempio n. 10
0
def standardize_cell(structure):
    import spglib
    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy.structure.atoms import atom_data

    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    structure_data = (structure.cell,
                      bulk.get_scaled_positions(),
                      bulk.get_atomic_numbers())

    #lattice, refined_positions, numbers = spglib.refine_cell(structure_data, symprec=1e-5)
    lattice, standardized_positions, numbers = spglib.standardize_cell(structure_data,
                                                                       symprec=1e-5,
                                                                       to_primitive=False,
                                                                       no_idealize=False)

    symbols = [atom_data[i][1] for i in numbers]

    # print lattice, standardized_positions, numbers
    # print [site.kind_name for site in structure.sites]
    standardized_bulk = PhonopyAtoms(symbols=symbols,
                                     scaled_positions=standardized_positions,
                                     cell=lattice)

    # create new aiida structure object
    standarized = StructureData(cell=standardized_bulk.get_cell())
    for position, symbol in zip(standardized_bulk.get_positions(), standardized_bulk.get_chemical_symbols()):
        standarized.append_atom(position=position,
                                      symbols=symbol)

    return {'standardized_structure': standarized}
Esempio n. 11
0
def _distribute_forces(supercell, disp, forces, filename, symprec):
    natom = supercell.get_number_of_atoms()
    lattice = supercell.get_cell()
    symbols = supercell.get_chemical_symbols()
    positions = supercell.get_positions()
    positions[disp[0]] += disp[1]
    cell = Atoms(cell=lattice, positions=positions, symbols=symbols, pbc=True)
    symmetry = Symmetry(cell, symprec)
    independent_atoms = symmetry.get_independent_atoms()

    # Rotation matrices in Cartesian
    rotations = []
    for r in symmetry.get_symmetry_operations()["rotations"]:
        rotations.append(similarity_transformation(lattice.T, r))

    map_operations = symmetry.get_map_operations()
    map_atoms = symmetry.get_map_atoms()

    atoms_in_dot_scf = _get_independent_atoms_in_dot_scf(filename)

    if len(forces) != len(atoms_in_dot_scf):
        print("%s does not contain necessary information." % filename)
        print('Plese check if there are "FGL" lines with')
        print('"total forces" are required.')
        return False

    if len(atoms_in_dot_scf) == natom:
        print("It is assumed that there is no symmetrically-equivalent " "atoms in ")
        print("'%s' at wien2k calculation." % filename)
        force_set = forces
    elif len(forces) != len(independent_atoms):
        print("Non-equivalent atoms of %s could not be recognized by phonopy." % filename)
        return False
    else:
        # 1. Transform wien2k forces to those on independent atoms
        indep_atoms_to_wien2k = []
        forces_remap = []
        for i, pos_wien2k in enumerate(atoms_in_dot_scf):
            for j, pos in enumerate(cell.get_scaled_positions()):
                diff = pos_wien2k - pos
                diff -= np.rint(diff)
                if (abs(diff) < symprec).all():
                    forces_remap.append(np.dot(rotations[map_operations[j]], forces[i]))
                    indep_atoms_to_wien2k.append(map_atoms[j])
                    break

        if len(forces_remap) != len(forces):
            print("Atomic position mapping between Wien2k and phonopy failed.")
            print("If you think this is caused by a bug of phonopy")
            print("please report it in the phonopy mainling list.")
            return False

        # 2. Distribute forces from independent to dependent atoms.
        force_set = []
        for i in range(natom):
            j = indep_atoms_to_wien2k.index(map_atoms[i])
            force_set.append(np.dot(rotations[map_operations[i]].T, forces_remap[j]))

    return force_set
Esempio n. 12
0
def test_get_primitive_convcell_Cr(convcell_cr: PhonopyAtoms, helper_methods):
    """Test get_primitive by NaCl."""
    convcell_cr.magnetic_moments = [1, -1]
    smat = [[2, 0, 0], [0, 2, 0], [0, 0, 2]]
    scell = get_supercell(convcell_cr, smat, is_old_style=True)
    pmat = np.linalg.inv(smat)
    pcell = get_primitive(scell, pmat)
    helper_methods.compare_cells(convcell_cr, pcell)
    convcell_cr.magnetic_moments = None
Esempio n. 13
0
def read_siesta(filename):
    """Read crystal structure."""
    siesta_in = SiestaIn(open(filename).read())
    numbers = siesta_in._tags["atomicnumbers"]
    alat = siesta_in._tags["latticeconstant"]
    lattice = siesta_in._tags["latticevectors"]
    positions = siesta_in._tags["atomiccoordinates"]
    atypes = siesta_in._tags["chemicalspecieslabel"]
    cell = Atoms(numbers=numbers, cell=lattice, scaled_positions=positions)

    coordformat = siesta_in._tags["atomiccoordinatesformat"]
    if coordformat == "fractional" or coordformat == "scaledbylatticevectors":
        cell.set_scaled_positions(positions)
    elif coordformat == "scaledcartesian":
        cell.set_positions(np.array(positions) * alat)
    elif coordformat == "notscaledcartesianang" or coordformat == "ang":
        cell.set_positions(np.array(positions) / Bohr)
    elif coordformat == "notscaledcartesianbohr" or coordformat == "bohr":
        cell.set_positions(np.array(positions))
    else:
        print("The format %s for the AtomicCoordinatesFormat is not "
              "implemented." % coordformat)
        sys.exit(1)

    return cell, atypes
Esempio n. 14
0
    def _primitive_cell(self, supercell):
        trimed_cell, p2s_map, mapping_table = trim_cell(
            self._primitive_matrix, supercell, self._symprec)
        Atoms.__init__(self,
                       numbers=trimed_cell.get_atomic_numbers(),
                       masses=trimed_cell.get_masses(),
                       magmoms=trimed_cell.get_magnetic_moments(),
                       scaled_positions=trimed_cell.get_scaled_positions(),
                       cell=trimed_cell.get_cell(),
                       pbc=True)

        self._p2s_map = np.array(p2s_map, dtype='intc')
Esempio n. 15
0
    def _create_supercell(self, unitcell, symprec):
        mat = self._supercell_matrix

        if self._is_old_style:
            P = None
            multi = self._get_surrounding_frame(mat)
            # trim_fram is to trim overlapping atoms.
            trim_frame = np.array([
                mat[0] / float(multi[0]), mat[1] / float(multi[1]),
                mat[2] / float(multi[2])
            ])
        else:
            # In the new style, it is unnecessary to trim atoms,
            if (np.diag(np.diagonal(mat)) != mat).any():
                snf = SNF3x3(mat)
                snf.run()
                P = snf.P
                multi = np.diagonal(snf.A)
            else:
                P = None
                multi = np.diagonal(mat)
            trim_frame = np.eye(3)

        sur_cell, u2sur_map = self._get_simple_supercell(unitcell, multi, P)
        trimmed_cell_ = _trim_cell(trim_frame, sur_cell, symprec)
        if trimmed_cell_:
            supercell, sur2s_map, mapping_table = trimmed_cell_
        else:
            return False

        num_satom = supercell.get_number_of_atoms()
        num_uatom = unitcell.get_number_of_atoms()
        N = num_satom // num_uatom

        if N != determinant(self._supercell_matrix):
            print("Supercell creation failed.")
            print("Probably some atoms are overwrapped. "
                  "The mapping table is give below.")
            print(mapping_table)
            PhonopyAtoms.__init__(self)
        else:
            PhonopyAtoms.__init__(
                self,
                numbers=supercell.get_atomic_numbers(),
                masses=supercell.get_masses(),
                magmoms=supercell.get_magnetic_moments(),
                scaled_positions=supercell.get_scaled_positions(),
                cell=supercell.get_cell(),
                pbc=True)
            self._u2s_map = np.arange(num_uatom) * N
            self._u2u_map = {j: i for i, j in enumerate(self._u2s_map)}
            self._s2u_map = np.array(u2sur_map)[sur2s_map] * N
Esempio n. 16
0
def test_get_supercell_Cr(convcell_cr: PhonopyAtoms, helper_methods):
    """Test of get_supercell using SNF by Cr with magnetic moments."""
    convcell_cr.magnetic_moments = [1, -1]
    smat = [[-1, 1, 1], [1, -1, 1], [1, 1, -1]]
    scell = get_supercell(convcell_cr, smat, is_old_style=True)
    np.testing.assert_allclose(
        scell.magnetic_moments,
        [1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1.0, -1.0],
        atol=1e-8,
    )
    scell_snf = get_supercell(convcell_cr, smat, is_old_style=False)
    helper_methods.compare_cells(scell, scell_snf)
    convcell_cr.magnetic_moments = None
Esempio n. 17
0
    def _primitive_cell(self, supercell):
        trimed_cell, p2s_map, mapping_table = trim_cell(self._primitive_matrix,
                                                        supercell,
                                                        self._symprec)
        Atoms.__init__(self,
                       numbers=trimed_cell.get_atomic_numbers(),
                       masses=trimed_cell.get_masses(),
                       magmoms=trimed_cell.get_magnetic_moments(),
                       scaled_positions=trimed_cell.get_scaled_positions(),
                       cell=trimed_cell.get_cell(),
                       pbc=True)

        self._p2s_map = np.array(p2s_map, dtype='intc')
Esempio n. 18
0
    def _create_supercell(self, unitcell, symprec):
        mat = self._supercell_matrix

        if self._is_old_style:
            P = None
            multi = self._get_surrounding_frame(mat)
            # trim_fram is to trim overlapping atoms.
            trim_frame = np.array([mat[0] / float(multi[0]),
                                   mat[1] / float(multi[1]),
                                   mat[2] / float(multi[2])])
        else:
            # In the new style, it is unnecessary to trim atoms,
            if (np.diag(np.diagonal(mat)) != mat).any():
                snf = SNF3x3(mat)
                snf.run()
                P = snf.P
                multi = np.diagonal(snf.A)
            else:
                P = None
                multi = np.diagonal(mat)
            trim_frame = np.eye(3)

        sur_cell, u2sur_map = self._get_simple_supercell(unitcell, multi, P)
        trimmed_cell_ = _trim_cell(trim_frame, sur_cell, symprec)
        if trimmed_cell_:
            supercell, sur2s_map, mapping_table = trimmed_cell_
        else:
            return False

        num_satom = supercell.get_number_of_atoms()
        num_uatom = unitcell.get_number_of_atoms()
        N = num_satom // num_uatom

        if N != determinant(self._supercell_matrix):
            print("Supercell creation failed.")
            print("Probably some atoms are overwrapped. "
                  "The mapping table is give below.")
            print(mapping_table)
            PhonopyAtoms.__init__(self)
        else:
            PhonopyAtoms.__init__(
                self,
                numbers=supercell.get_atomic_numbers(),
                masses=supercell.get_masses(),
                magmoms=supercell.get_magnetic_moments(),
                scaled_positions=supercell.get_scaled_positions(),
                cell=supercell.get_cell(),
                pbc=True)
            self._u2s_map = np.arange(num_uatom) * N
            self._u2u_map = {j: i for i, j in enumerate(self._u2s_map)}
            self._s2u_map = np.array(u2sur_map)[sur2s_map] * N
Esempio n. 19
0
def get_cell_settings(
    supercell_matrix=None,
    primitive_matrix=None,
    unitcell=None,
    supercell=None,
    unitcell_filename=None,
    supercell_filename=None,
    calculator=None,
    symprec=1e-5,
    log_level=0,
):
    """Return crystal structures."""
    optional_structure_info = None
    if primitive_matrix is None or (type(primitive_matrix) is str and
                                    primitive_matrix == "auto"):  # noqa E129
        pmat = "auto"
    else:
        pmat = primitive_matrix

    if unitcell_filename is not None:
        cell, optional_structure_info = _read_crystal_structure(
            filename=unitcell_filename, interface_mode=calculator)
        smat = supercell_matrix
        if log_level:
            print('Unit cell structure was read from "%s".' %
                  optional_structure_info[0])
    elif supercell_filename is not None:
        cell, optional_structure_info = read_crystal_structure(
            filename=supercell_filename, interface_mode=calculator)
        smat = np.eye(3, dtype="intc", order="C")
        if log_level:
            print('Supercell structure was read from "%s".' %
                  optional_structure_info[0])
    elif unitcell is not None:
        cell = PhonopyAtoms(atoms=unitcell)
        smat = supercell_matrix
    elif supercell is not None:
        cell = PhonopyAtoms(atoms=supercell)
        smat = np.eye(3, dtype="intc", order="C")
    else:
        raise RuntimeError("Cell has to be specified.")

    if optional_structure_info is not None and cell is None:
        filename = optional_structure_info[0]
        msg = "'%s' could not be found." % filename
        raise FileNotFoundError(msg)

    pmat = get_primitive_matrix(pmat, symprec=symprec)

    return cell, smat, pmat
Esempio n. 20
0
def phonopyAtoms_to_aseAtoms(PhonopyAtoms, pbc=[True, True, True]):
    aseAtoms = ase.Atoms(symbols=PhonopyAtoms.get_chemical_symbols(),
                         positions=PhonopyAtoms.get_positions(),
                         cell=PhonopyAtoms.get_cell())
    aseAtoms.set_pbc(pbc)
    aseAtoms.set_masses(PhonopyAtoms.get_masses())
    Atomic_numbers = PhonopyAtoms.get_atomic_numbers()
    Atomic_type_tags = np.zeros(np.shape(Atomic_numbers))
    atomic_type_unique = np.unique(Atomic_numbers)
    for i, iZ in enumerate(atomic_type_unique):
        Atomic_type_tags[Atomic_numbers == iZ] = i
    aseAtoms.set_tags(Atomic_type_tags)
    aseAtoms.set_initial_charges()

    return aseAtoms
Esempio n. 21
0
def get_cell_settings(phonopy_yaml=None,
                      supercell_matrix=None,
                      primitive_matrix=None,
                      unitcell=None,
                      supercell=None,
                      unitcell_filename=None,
                      supercell_filename=None,
                      calculator=None,
                      symprec=1e-5,
                      log_level=0):
    optional_structure_info = None
    if (primitive_matrix is None
            or (type(primitive_matrix) is str and primitive_matrix == "auto")):
        pmat = 'auto'
    else:
        pmat = primitive_matrix

    if unitcell_filename is not None:
        cell, optional_structure_info = _read_crystal_structure(
            filename=unitcell_filename, interface_mode=calculator)
        smat = supercell_matrix
        if log_level:
            print("Unit cell structure was read from \"%s\"." %
                  optional_structure_info[0])
    elif supercell_filename is not None:
        cell, optional_structure_info = read_crystal_structure(
            filename=supercell_filename, interface_mode=calculator)
        smat = np.eye(3, dtype='intc', order='C')
        if log_level:
            print("Supercell structure was read from \"%s\"." %
                  optional_structure_info[0])
    elif unitcell is not None:
        cell = PhonopyAtoms(atoms=unitcell)
        smat = supercell_matrix
    elif supercell is not None:
        cell = PhonopyAtoms(atoms=supercell)
        smat = np.eye(3, dtype='intc', order='C')
    else:
        raise RuntimeError("Cell has to be specified.")

    if optional_structure_info is not None and cell is None:
        filename = optional_structure_info[0]
        msg = "'%s' could not be found." % filename
        raise FileNotFoundError(msg)

    pmat = _get_primitive_matrix(pmat, cell, symprec)

    return cell, smat, pmat
def read_phonopy(sposcar='SPOSCAR',
                 sc_mat=np.eye(3),
                 force_constants=None,
                 disp_yaml=None,
                 force_sets=None):
    if force_constants is None and (disp_yaml is None or force_sets is None):
        raise ValueError(
            "Either FORCE_CONSTANTS or (disp.yaml&FORCE_SETS) file should be provided."
        )
    atoms = read(sposcar)
    #vesta_view(atoms)
    primitive_matrix = inv(sc_mat)
    bulk = PhonopyAtoms(symbols=atoms.get_chemical_symbols(),
                        scaled_positions=atoms.get_scaled_positions(),
                        cell=atoms.get_cell())
    phonon = Phonopy(
        bulk,
        supercell_matrix=np.eye(3),
        primitive_matrix=primitive_matrix,
        #factor=factor,
        #symprec=symprec
    )

    if disp_yaml is not None:
        disp = parse_disp_yaml(filename=disp_yaml)
        phonon.set_displacement_dataset(disp)
    if force_sets is not None:
        fc = parse_FORCE_SETS(filename=force_sets)
        phonon.set_forces(fc)

    fc = parse_FORCE_CONSTANTS(force_constants)
    phonon.set_force_constants(fc)

    return phonon
Esempio n. 23
0
def get_properties_from_phonopy(structure, phonopy_input, force_constants):
    """
    Calculate DOS and thermal properties using phonopy (locally)
    :param structure: Aiida StructureData Object
    :param phonopy_input: Aiida Parametersdata object containing a dictionary with the data needed to run phonopy:
            supercells matrix, primitive matrix and q-points mesh.
    :param force_constants:
    :return:
    """

    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy import Phonopy

    # Generate phonopy phonon object
    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonopy_input = phonopy_input.get_dict()
    force_constants = force_constants.get_array('force_constants')

    phonon = Phonopy(bulk,
                     phonopy_input['supercell'],
                     primitive_matrix=phonopy_input['primitive'])

    phonon.set_force_constants(force_constants)

    #Normalization factor primitive to unit cell
    normalization_factor = phonon.unitcell.get_number_of_atoms(
    ) / phonon.primitive.get_number_of_atoms()

    phonon.set_mesh(phonopy_input['mesh'],
                    is_eigenvectors=True,
                    is_mesh_symmetry=False)
    phonon.set_total_DOS()
    phonon.set_partial_DOS()

    # get DOS (normalized to unit cell)
    total_dos = phonon.get_total_DOS() * normalization_factor
    partial_dos = phonon.get_partial_DOS() * normalization_factor

    # Stores DOS data in DB as a workflow result
    dos = ArrayData()
    dos.set_array('frequency', total_dos[0])
    dos.set_array('total_dos', total_dos[1])
    dos.set_array('partial_dos', partial_dos[1])

    #THERMAL PROPERTIES (per primtive cell)
    phonon.set_thermal_properties()
    t, free_energy, entropy, cv = phonon.get_thermal_properties()

    # Stores thermal properties (per unit cell) data in DB as a workflow result
    thermal_properties = ArrayData()
    thermal_properties.set_array('temperature', t)
    thermal_properties.set_array('free_energy',
                                 free_energy * normalization_factor)
    thermal_properties.set_array('entropy', entropy * normalization_factor)
    thermal_properties.set_array('cv', cv * normalization_factor)

    return {'thermal_properties': thermal_properties, 'dos': dos}
Esempio n. 24
0
def test_structure_to_phonopy_atoms(sc_structure):
    actual = structure_to_phonopy_atoms(sc_structure)
    expected = PhonopyAtoms(symbols=["H"],
                            cell=np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0],
                                           [0.0, 0.0, 1.0]]),
                            scaled_positions=np.array([[0.0, 0.0, 0.0]]))
    assert_same_phonopy_atoms(actual, expected)
Esempio n. 25
0
def get_phonon(structure, NAC=False, setup_forces=True, custom_supercell=None):

    super_cell_phonon = structure.get_supercell_phonon()
    if not(isinstance(custom_supercell, type(None))):
        super_cell_phonon = custom_supercell

    #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, super_cell_phonon,
                     primitive_matrix=structure.get_primitive_matrix())

    # 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 not structure.forces_available():
    #    if not np.array(structure.get_force_constants()).any() and not np.array(structure.get_force_sets()).any():
            print('No force sets/constants available!')
            exit()
        if np.array(structure.get_force_constants()).any():
            phonon.set_force_constants(structure.get_force_constants())
        else:
            phonon.set_displacement_dataset(structure.get_force_sets())
            phonon.produce_force_constants(computation_algorithm="svd")

    return phonon
Esempio n. 26
0
def analyse_phonopy_equivalent_atoms(atoms,
                                     symprec=1e-5,
                                     angle_tolerance=-1.0):
    """
    Args: (read phonopy.structure.spglib for more details)
        symprec:
            float: Symmetry search tolerance in the unit of length.
        angle_tolerance:
            float: Symmetry search tolerance in the unit of angle deg.
                If the value is negative, an internally optimized routine
                is used to judge symmetry.

    """
    s.publication_add(publication())
    positions = atoms.get_scaled_positions()
    cell = atoms.cell
    types = atoms.get_chemical_symbols()
    types = list(types)
    natom = len(types)
    positions = np.reshape(np.array(positions), (natom, 3))
    cell = np.reshape(np.array(cell), (3, 3))
    unitcell = PhonopyAtoms(symbols=types,
                            cell=cell,
                            scaled_positions=positions)
    ops = spg.get_symmetry(unitcell,
                           symprec=symprec,
                           angle_tolerance=angle_tolerance)
    return ops['equivalent_atoms']
Esempio n. 27
0
def get_cell_from_disp_yaml(dataset):
    """Read cell from disp.yaml like file."""
    if "lattice" in dataset:
        lattice = dataset["lattice"]
        if "points" in dataset:
            data_key = "points"
            pos_key = "coordinates"
        elif "atoms" in dataset:
            data_key = "atoms"
            pos_key = "position"
        else:
            data_key = None
            pos_key = None

        try:
            positions = [x[pos_key] for x in dataset[data_key]]
        except KeyError:
            msg = ('"disp.yaml" format is too old. '
                   'Please re-create it as "phonopy_disp.yaml" to contain '
                   "supercell crystal structure information.")
            raise RuntimeError(msg)
        symbols = [x["symbol"] for x in dataset[data_key]]
        cell = PhonopyAtoms(cell=lattice,
                            scaled_positions=positions,
                            symbols=symbols,
                            pbc=True)
        return cell
    else:
        return get_cell_from_disp_yaml(dataset["supercell"])
Esempio n. 28
0
def check_symmetry(phonon, optional_structure_info):
    # Assumed that primitive cell is the cell that user is interested in.
    print(_get_symmetry_yaml(phonon.primitive,
                             phonon.primitive_symmetry,
                             phonon.version))

    if phonon.unitcell.magnetic_moments is None:
        base_fname = get_default_cell_filename(phonon.calculator)
        symprec = phonon.primitive_symmetry.get_symmetry_tolerance()
        (bravais_lattice,
         bravais_pos,
         bravais_numbers) = spglib.refine_cell(phonon.primitive, symprec)
        bravais = PhonopyAtoms(numbers=bravais_numbers,
                               scaled_positions=bravais_pos,
                               cell=bravais_lattice)
        filename = 'B' + base_fname
        print("# Symmetrized conventional unit cell is written into %s."
              % filename)
        trans_mat = guess_primitive_matrix(bravais, symprec=symprec)
        primitive = get_primitive(bravais, trans_mat, symprec=symprec)
        write_crystal_structure(
            filename,
            bravais,
            interface_mode=phonon.calculator,
            optional_structure_info=optional_structure_info)

        filename = 'P' + base_fname
        print("# Symmetrized primitive is written into %s." % filename)
        write_crystal_structure(
            filename,
            primitive,
            interface_mode=phonon.calculator,
            optional_structure_info=optional_structure_info)
Esempio n. 29
0
def get_commensurate_points(supercell_matrix):  # wrt primitive cell
    """Commensurate q-points are returned.

    Parameters
    ----------
    supercell_matrix : array_like
        Supercell matrix with respect to primitive cell basis vectors.
        shape=(3, 3), dtype=int

    Returns
    -------
    commensurate_points : ndarray
        Commensurate points corresponding to supercell matrix.
        shape=(N, 3), dtype='double', order='C'
        where N = det(supercell_matrix)

    """

    smat = np.array(supercell_matrix, dtype=int)
    rec_primitive = PhonopyAtoms(numbers=[1],
                                 scaled_positions=[[0, 0, 0]],
                                 cell=np.diag([1, 1, 1]),
                                 pbc=True)
    rec_supercell = get_supercell(rec_primitive, smat.T)
    q_pos = rec_supercell.scaled_positions
    return np.array(np.where(q_pos > 1 - 1e-15, q_pos - 1, q_pos),
                    dtype='double',
                    order='C')
Esempio n. 30
0
def phonons(model, bulk, supercell, dx, mesh=None, points=None, n_points=50):

    import model

    unitcell = PhonopyAtoms(symbols=bulk.get_chemical_symbols(),
                            cell=bulk.get_cell(),
                            scaled_positions=bulk.get_scaled_positions())
    phonon = Phonopy(unitcell, supercell)
    phonon.generate_displacements(distance=dx)

    sets_of_forces = []

    for s in phonon.get_supercells_with_displacements():
        at = Atoms(cell=s.get_cell(),
                   symbols=s.get_chemical_symbols(),
                   scaled_positions=s.get_scaled_positions(),
                   pbc=3 * [True])
        at.set_calculator(model.calculator)
        sets_of_forces.append(at.get_forces())

    phonon.set_forces(sets_of_forces=sets_of_forces)
    phonon.produce_force_constants()

    properties = {}

    if mesh is not None:
        phonon.set_mesh(mesh, is_gamma_center=True)
        qpoints, weights, frequencies, eigvecs = phonon.get_mesh()

        properties["frequencies"] = frequencies.tolist()
        properties["weights"] = weights.tolist()

    if points is not None:
        bands = []
        for i in range(len(points) - 1):
            band = []
            for r in np.linspace(0, 1, n_points):
                band.append(points[i] + (points[i + 1] - points[i]) * r)
            bands.append(band)

        phonon.set_band_structure(bands,
                                  is_eigenvectors=True,
                                  is_band_connection=False)
        band_q_points, band_distances, band_frequencies, band_eigvecs = phonon.get_band_structure(
        )

        band_distance_max = np.max(band_distances)
        band_distances = [(_b / band_distance_max).tolist()
                          for _b in band_distances]

        band_frequencies = [_b.tolist() for _b in band_frequencies]

        properties["band_q_points"] = band_q_points
        properties["band_distances"] = band_distances
        properties["band_frequencies"] = band_frequencies
        properties["band_eigvecs"] = band_eigvecs

    properties["phonopy"] = phonon

    return properties
Esempio n. 31
0
def get_cell_from_disp_yaml(dataset):
    if 'lattice' in dataset:
        lattice = dataset['lattice']
        if 'points' in dataset:
            data_key = 'points'
            pos_key = 'coordinates'
        elif 'atoms' in dataset:
            data_key = 'atoms'
            pos_key = 'position'
        else:
            data_key = None
            pos_key = None

        try:
            positions = [x[pos_key] for x in dataset[data_key]]
        except KeyError:
            msg = ("\"disp.yaml\" format is too old. "
                   "Please re-create it as \"phonopy_disp.yaml\" to contain "
                   "supercell crystal structure information.")
            raise RuntimeError(msg)
        symbols = [x['symbol'] for x in dataset[data_key]]
        cell = PhonopyAtoms(cell=lattice,
                            scaled_positions=positions,
                            symbols=symbols,
                            pbc=True)
        return cell
    else:
        return get_cell_from_disp_yaml(dataset['supercell'])
Esempio n. 32
0
def get_equivalent_q_points_by_symmetry(q_point, structure):

    from phonopy.structure.symmetry import Symmetry
    bulk = PhonopyAtoms(symbols=structure.get_atomic_elements(),
                        scaled_positions=structure.get_scaled_positions(),
                        cell=structure.get_cell().T)

    tot_points = []
    for operation_matrix in Symmetry(bulk).get_reciprocal_operations():
        operation_matrix_q = np.dot(
            np.linalg.inv(structure.get_primitive_matrix()),
            operation_matrix.T)
        operation_matrix_q = np.dot(operation_matrix_q,
                                    structure.get_primitive_matrix())

        q_point_test = np.dot(q_point, operation_matrix_q)

        if (q_point_test >= 0).all():
            tot_points.append(q_point_test)


#    print tot_points
#    print(np.vstack({tuple(row) for row in tot_points}))

    return np.vstack({tuple(row) for row in tot_points})
Esempio n. 33
0
def get_force_sets_inline(**kwargs):
    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy import Phonopy

    structure = kwargs.pop('structure')
    phonopy_input = kwargs.pop('phonopy_input').get_dict()

    # Generate phonopy phonon object
    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonon = Phonopy(bulk,
                     phonopy_input['supercell'],
                     primitive_matrix=phonopy_input['primitive'],
                     symprec=phonopy_input['symmetry_precision'])

    phonon.generate_displacements(distance=phonopy_input['distance'])

    # Build data_sets from forces of supercells with displacments
    data_sets = phonon.get_displacement_dataset()
    for i, first_atoms in enumerate(data_sets['first_atoms']):
        first_atoms['forces'] = kwargs.pop(
            'force_{}'.format(i)).get_array('forces')[-1]

    data = ArrayData()
    data.set_array('force_sets', np.array(data_sets))

    return {'phonopy_output': data}
Esempio n. 34
0
def create_supercells_with_displacements_inline(**kwargs):
    from phonopy.structure.atoms import Atoms as PhonopyAtoms
    from phonopy import Phonopy

    structure = kwargs.pop('structure')
    phonopy_input = kwargs.pop('phonopy_input').get_dict()

    # Generate phonopy phonon object
    bulk = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites],
                        positions=[site.position for site in structure.sites],
                        cell=structure.cell)

    phonon = Phonopy(bulk,
                     phonopy_input['supercell'],
                     primitive_matrix=phonopy_input['primitive'],
                     symprec=phonopy_input['symmetry_precision'])

    phonon.generate_displacements(distance=phonopy_input['distance'])

    cells_with_disp = phonon.get_supercells_with_displacements()

    # Transform cells to StructureData and set them ready to return
    disp_cells = {}

    for i, phonopy_supercell in enumerate(cells_with_disp):
        supercell = StructureData(cell=phonopy_supercell.get_cell())
        for symbol, position in zip(phonopy_supercell.get_chemical_symbols(),
                                    phonopy_supercell.get_positions()):
            supercell.append_atom(position=position, symbols=symbol)
        disp_cells["structure_{}".format(i)] = supercell

    return disp_cells
Esempio n. 35
0
    def _get_cell(self, lattice, points, symbols, masses=None):
        if lattice:
            _lattice = lattice
        else:
            _lattice = None
        if points:
            _points = points
        else:
            _points = None
        if symbols:
            _symbols = symbols
        else:
            _symbols = None
        if masses:
            _masses = masses
        else:
            _masses = None

        if _lattice and _points and _symbols:
            return PhonopyAtoms(symbols=_symbols,
                                cell=_lattice,
                                masses=_masses,
                                scaled_positions=_points)
        else:
            return None
Esempio n. 36
0
def read_siesta(filename):
    siesta_in = SiestaIn(open(filename).read())
    numbers = siesta_in._tags["atomicnumbers"]
    alat = siesta_in._tags["latticeconstant"]
    lattice = siesta_in._tags["latticevectors"]
    positions = siesta_in._tags["atomiccoordinates"]
    atypes = siesta_in._tags["chemicalspecieslabel"]
    cell = Atoms(numbers=numbers, cell=lattice, scaled_positions=positions)

    coordformat = siesta_in._tags["atomiccoordinatesformat"]
    if coordformat == "fractional" or coordformat == "scaledbylatticevectors":
        cell.set_scaled_positions(positions)
    elif coordformat == "scaledcartesian":
        cell.set_positions(np.array(positions) * alat)
    elif coordformat == "notscaledcartesianang" or coordformat == "ang":
        cell.set_positions(np.array(positions) / Bohr) 
    elif coordformat == "notscaledcartesianbohr" or coordformat == "bohr":
        cell.set_positions(np.array(positions))
    else:
        print("The format %s for the AtomicCoordinatesFormat is not "
              "implemented." % coordformat)
        sys.exit(1) 
    
    return cell, atypes
Esempio n. 37
0
class Phonopy(object):
    def __init__(self,
                 unitcell,
                 supercell_matrix,
                 primitive_matrix=None,
                 nac_params=None,
                 distance=None,
                 factor=VaspToTHz,
                 is_auto_displacements=None,
                 dynamical_matrix_decimals=None,
                 force_constants_decimals=None,
                 symprec=1e-5,
                 is_symmetry=True,
                 use_lapack_solver=False,
                 log_level=0):

        if is_auto_displacements is not None:
            print("Warning: \'is_auto_displacements\' argument is obsolete.")
            if is_auto_displacements is False:
                print("Sets of displacements are not created as default.")
            else:
                print("Use \'generate_displacements\' method explicitly to "
                      "create sets of displacements.")

        if distance is not None:
            print("Warning: \'distance\' keyword argument is obsolete at "
                  "Phonopy instantiation.")
            print("Specify \'distance\' keyword argument when calling "
                  "\'generate_displacements\'")
            print("method (See the Phonopy API document).")

        self._symprec = symprec
        self._factor = factor
        self._is_symmetry = is_symmetry
        self._use_lapack_solver = use_lapack_solver
        self._log_level = log_level

        # Create supercell and primitive cell
        self._unitcell = Atoms(atoms=unitcell)
        self._supercell_matrix = supercell_matrix
        self._primitive_matrix = primitive_matrix
        self._supercell = None
        self._primitive = None
        self._build_supercell()
        self._build_primitive_cell()

        # Set supercell and primitive symmetry
        self._symmetry = None
        self._primitive_symmetry = None
        self._search_symmetry()
        self._search_primitive_symmetry()

        # set_displacements (used only in preprocess)
        self._displacement_dataset = None
        self._displacements = None
        self._displacement_directions = None
        self._supercells_with_displacements = None

        # set_force_constants or set_forces
        self._force_constants = None
        self._force_constants_decimals = force_constants_decimals

        # set_dynamical_matrix
        self._dynamical_matrix = None
        self._nac_params = nac_params
        self._dynamical_matrix_decimals = dynamical_matrix_decimals

        # set_band_structure
        self._band_structure = None

        # set_mesh
        self._mesh = None

        # set_tetrahedron_method
        self._tetrahedron_method = None

        # set_thermal_properties
        self._thermal_properties = None

        # set_thermal_displacements
        self._thermal_displacements = None

        # set_thermal_displacement_matrices
        self._thermal_displacement_matrices = None

        # set_partial_DOS
        self._pdos = None

        # set_total_DOS
        self._total_dos = None

        # set_modulation
        self._modulation = None

        # set_character_table
        self._irreps = None

        # set_group_velocity
        self._group_velocity = None

    def get_version(self):
        return __version__

    def get_primitive(self):
        return self._primitive
    primitive = property(get_primitive)

    def get_unitcell(self):
        return self._unitcell
    unitcell = property(get_unitcell)

    def get_supercell(self):
        return self._supercell
    supercell = property(get_supercell)

    def get_symmetry(self):
        """return symmetry of supercell"""
        return self._symmetry
    symmetry = property(get_symmetry)

    def get_primitive_symmetry(self):
        """return symmetry of primitive cell"""
        return self._primitive_symmetry

    def get_supercell_matrix(self):
        return self._supercell_matrix

    def get_primitive_matrix(self):
        return self._primitive_matrix

    def get_unit_conversion_factor(self):
        return self._factor
    unit_conversion_factor = property(get_unit_conversion_factor)

    def get_displacement_dataset(self):
        return self._displacement_dataset

    def get_displacements(self):
        return self._displacements
    displacements = property(get_displacements)

    def get_displacement_directions(self):
        return self._displacement_directions
    displacement_directions = property(get_displacement_directions)

    def get_supercells_with_displacements(self):
        if self._displacement_dataset is None:
            return None
        else:
            self._build_supercells_with_displacements()
            return self._supercells_with_displacements

    def get_force_constants(self):
        return self._force_constants
    force_constants = property(get_force_constants)

    def get_rotational_condition_of_fc(self):
        return rotational_invariance(self._force_constants,
                                     self._supercell,
                                     self._primitive,
                                     self._symprec)

    def get_nac_params(self):
        return self._nac_params

    def get_dynamical_matrix(self):
        return self._dynamical_matrix
    dynamical_matrix = property(get_dynamical_matrix)

    def set_unitcell(self, unitcell):
        self._unitcell = unitcell
        self._build_supercell()
        self._build_primitive_cell()
        self._search_symmetry()
        self._search_primitive_symmetry()
        self._displacement_dataset = None

    def set_masses(self, masses):
        p_masses = np.array(masses)
        self._primitive.set_masses(p_masses)
        p2p_map = self._primitive.get_primitive_to_primitive_map()
        s_masses = p_masses[[p2p_map[x] for x in
                             self._primitive.get_supercell_to_primitive_map()]]
        self._supercell.set_masses(s_masses)
        u2s_map = self._supercell.get_unitcell_to_supercell_map()
        u_masses = s_masses[u2s_map]
        self._unitcell.set_masses(u_masses)
        self._set_dynamical_matrix()

    def set_nac_params(self, nac_params=None):
        self._nac_params = nac_params
        self._set_dynamical_matrix()

    def set_displacement_dataset(self, displacement_dataset):
        """
        displacement_dataset:
           {'natom': number_of_atoms_in_supercell,
            'first_atoms': [
              {'number': atom index of displaced atom,
               'displacement': displacement in Cartesian coordinates,
               'direction': displacement direction with respect to axes
               'forces': forces on atoms in supercell},
              {...}, ...]}
        """
        self._displacement_dataset = displacement_dataset

        self._displacements = []
        self._displacement_directions = []
        for disp in self._displacement_dataset['first_atoms']:
            x = disp['displacement']
            self._displacements.append([disp['number'], x[0], x[1], x[2]])
            if 'direction' in disp:
                y = disp['direction']
                self._displacement_directions.append(
                    [disp['number'], y[0], y[1], y[2]])
        if not self._displacement_directions:
            self._displacement_directions = None

    def set_forces(self, sets_of_forces):
        """
        sets_of_forces:
           [[[f_1x, f_1y, f_1z], [f_2x, f_2y, f_2z], ...], # first supercell
             [[f_1x, f_1y, f_1z], [f_2x, f_2y, f_2z], ...], # second supercell
             ...                                                  ]
        """
        for disp, forces in zip(
                self._displacement_dataset['first_atoms'], sets_of_forces):
            disp['forces'] = forces

    def set_force_constants(self, force_constants):
        self._force_constants = force_constants
        self._set_dynamical_matrix()

    def set_force_constants_zero_with_radius(self, cutoff_radius):
        cutoff_force_constants(self._force_constants,
                               self._supercell,
                               cutoff_radius,
                               symprec=self._symprec)
        self._set_dynamical_matrix()

    def set_dynamical_matrix(self):
        self._set_dynamical_matrix()

    def generate_displacements(self,
                               distance=0.01,
                               is_plusminus='auto',
                               is_diagonal=True,
                               is_trigonal=False):
        """Generate displacements automatically

        displacemsts: List of displacements in Cartesian coordinates.
           [[0, 0.01, 0.00, 0.00], ...]
        where each set of elements is defined by:
           First value:      Atom index in supercell starting with 0
           Second to fourth: Displacement in Cartesian coordinates

        displacement_directions:
          List of directions with respect to axes. This gives only the
          symmetrically non equivalent directions. The format is like:
             [[0, 1, 0, 0],
              [7, 1, 0, 1], ...]
          where each list is defined by:
             First value:      Atom index in supercell starting with 0
             Second to fourth: If the direction is displaced or not ( 1, 0, or -1 )
                               with respect to the axes.

        """
        displacement_directions = get_least_displacements(
            self._symmetry,
            is_plusminus=is_plusminus,
            is_diagonal=is_diagonal,
            is_trigonal=is_trigonal,
            log_level=self._log_level)
        displacement_dataset = direction_to_displacement(
            displacement_directions,
            distance,
            self._supercell)
        self.set_displacement_dataset(displacement_dataset)

    def produce_force_constants(self,
                                forces=None,
                                calculate_full_force_constants=True,
                                computation_algorithm="svd"):
        if forces is not None:
            self.set_forces(forces)

        # A primitive check if 'forces' key is in displacement_dataset.
        for disp in self._displacement_dataset['first_atoms']:
            if 'forces' not in disp:
                return False

        if calculate_full_force_constants:
            self._run_force_constants_from_forces(
                decimals=self._force_constants_decimals,
                computation_algorithm=computation_algorithm)
        else:
            p2s_map = self._primitive.get_primitive_to_supercell_map()
            self._run_force_constants_from_forces(
                distributed_atom_list=p2s_map,
                decimals=self._force_constants_decimals,
                computation_algorithm=computation_algorithm)

        self._set_dynamical_matrix()

        return True

    def symmetrize_force_constants(self, iteration=3):
        symmetrize_force_constants(self._force_constants, iteration)
        self._set_dynamical_matrix()

    def symmetrize_force_constants_by_space_group(self):
        from phonopy.harmonic.force_constants import (set_tensor_symmetry,
                                                      set_tensor_symmetry_PJ)
        set_tensor_symmetry_PJ(self._force_constants,
                               self._supercell.get_cell().T,
                               self._supercell.get_scaled_positions(),
                               self._symmetry)

        self._set_dynamical_matrix()

    #####################
    # Phonon properties #
    #####################

    # Single q-point
    def get_dynamical_matrix_at_q(self, q):
        self._set_dynamical_matrix()
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            return None

        self._dynamical_matrix.set_dynamical_matrix(q)
        return self._dynamical_matrix.get_dynamical_matrix()


    def get_frequencies(self, q):
        """
        Calculate phonon frequencies at q

        q: q-vector in reduced coordinates of primitive cell
        """
        self._set_dynamical_matrix()
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            return None

        self._dynamical_matrix.set_dynamical_matrix(q)
        dm = self._dynamical_matrix.get_dynamical_matrix()
        frequencies = []
        for eig in np.linalg.eigvalsh(dm).real:
            if eig < 0:
                frequencies.append(-np.sqrt(-eig))
            else:
                frequencies.append(np.sqrt(eig))

        return np.array(frequencies) * self._factor

    def get_frequencies_with_eigenvectors(self, q):
        """
        Calculate phonon frequencies and eigenvectors at q

        q: q-vector in reduced coordinates of primitive cell
        """
        self._set_dynamical_matrix()
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            return None

        self._dynamical_matrix.set_dynamical_matrix(q)
        dm = self._dynamical_matrix.get_dynamical_matrix()
        frequencies = []
        eigvals, eigenvectors = np.linalg.eigh(dm)
        frequencies = []
        for eig in eigvals:
            if eig < 0:
                frequencies.append(-np.sqrt(-eig))
            else:
                frequencies.append(np.sqrt(eig))

        return np.array(frequencies) * self._factor, eigenvectors

    # Band structure
    def set_band_structure(self,
                           bands,
                           is_eigenvectors=False,
                           is_band_connection=False):
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            self._band_structure = None
            return False

        self._band_structure = BandStructure(
            bands,
            self._dynamical_matrix,
            is_eigenvectors=is_eigenvectors,
            is_band_connection=is_band_connection,
            group_velocity=self._group_velocity,
            factor=self._factor)
        return True

    def get_band_structure(self):
        band = self._band_structure
        return (band.get_qpoints(),
                band.get_distances(),
                band.get_frequencies(),
                band.get_eigenvectors())

    def plot_band_structure(self, labels=None):
        import matplotlib.pyplot as plt
        if labels:
            from matplotlib import rc
            rc('text', usetex=True)

        self._band_structure.plot(plt, labels=labels)
        return plt

    def write_yaml_band_structure(self,
                                  labels=None,
                                  comment=None,
                                  filename="band.yaml"):
        self._band_structure.write_yaml(labels=labels,
                                        comment=comment,
                                        filename=filename)

    # Sampling mesh
    def set_mesh(self,
                 mesh,
                 shift=None,
                 is_time_reversal=True,
                 is_mesh_symmetry=True,
                 is_eigenvectors=False,
                 is_gamma_center=False):
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            self._mesh = None
            return False

        self._mesh = Mesh(
            self._dynamical_matrix,
            mesh,
            shift=shift,
            is_time_reversal=is_time_reversal,
            is_mesh_symmetry=is_mesh_symmetry,
            is_eigenvectors=is_eigenvectors,
            is_gamma_center=is_gamma_center,
            group_velocity=self._group_velocity,
            rotations=self._primitive_symmetry.get_pointgroup_operations(),
            factor=self._factor,
            use_lapack_solver=self._use_lapack_solver)
        return True

    def get_mesh(self):
        if self._mesh is None:
            return None
        else:
            return (self._mesh.get_qpoints(),
                    self._mesh.get_weights(),
                    self._mesh.get_frequencies(),
                    self._mesh.get_eigenvectors())
    
    def get_mesh_grid_info(self):
        if self._mesh is None:
            return None
        else:
            return (self._mesh.get_grid_address(),
                    self._mesh.get_ir_grid_points(),
                    self._mesh.get_grid_mapping_table())

    def write_hdf5_mesh(self):
        self._mesh.write_hdf5()

    def write_yaml_mesh(self):
        self._mesh.write_yaml()

    # Plot band structure and DOS (PDOS) together
    def plot_band_structure_and_dos(self, pdos_indices=None, labels=None):
        import matplotlib.pyplot as plt
        import matplotlib.gridspec as gridspec
        if labels:
            from matplotlib import rc
            rc('text', usetex=True)

        plt.figure(figsize=(10, 6))
        gs = gridspec.GridSpec(1, 2, width_ratios=[3, 1])
        ax1 = plt.subplot(gs[0, 0])
        self._band_structure.plot(plt, labels=labels)
        ax2 = plt.subplot(gs[0, 1], sharey=ax1)
        plt.subplots_adjust(wspace=0.03)
        plt.setp(ax2.get_yticklabels(), visible=False)

        if pdos_indices is None:
            self._total_dos.plot(plt,
                                 ylabel="",
                                 draw_grid=False,
                                 flip_xy=True)
        else:
            self._pdos.plot(plt,
                            indices=pdos_indices,
                            ylabel="",
                            draw_grid=False,
                            flip_xy=True)

        return plt

    # DOS
    def set_total_DOS(self,
                      sigma=None,
                      freq_min=None,
                      freq_max=None,
                      freq_pitch=None,
                      tetrahedron_method=False):

        if self._mesh is None:
            print("Warning: \'set_mesh\' has to finish correctly "
                  "before DOS calculation.")
            self._total_dos = None
            return False

        total_dos = TotalDos(self._mesh,
                             sigma=sigma,
                             tetrahedron_method=tetrahedron_method)
        total_dos.set_draw_area(freq_min, freq_max, freq_pitch)
        total_dos.run()
        self._total_dos = total_dos
        return True

    def get_total_DOS(self):
        """
        Retern frequencies and total dos.
        The first element is freqs and the second is total dos.

        frequencies: [freq1, freq2, ...]
        total_dos: [dos1, dos2, ...]
        """
        return self._total_dos.get_dos()

    def set_Debye_frequency(self, freq_max_fit=None):
        self._total_dos.set_Debye_frequency(
            self._primitive.get_number_of_atoms(),
            freq_max_fit=freq_max_fit)

    def get_Debye_frequency(self):
        return self._total_dos.get_Debye_frequency()

    def plot_total_DOS(self):
        import matplotlib.pyplot as plt
        self._total_dos.plot(plt)
        return plt

    def write_total_DOS(self):
        self._total_dos.write()

    # PDOS
    def set_partial_DOS(self,
                        sigma=None,
                        freq_min=None,
                        freq_max=None,
                        freq_pitch=None,
                        tetrahedron_method=False,
                        direction=None,
                        xyz_projection=False):
        self._pdos = None

        if self._mesh is None:
            print("Warning: \'set_mesh\' has to be called before "
                  "PDOS calculation.")
            return False

        if self._mesh.get_eigenvectors() is None:
            print("Warning: Eigenvectors have to be calculated.")
            return False

        num_grid = np.prod(self._mesh.get_mesh_numbers())
        if num_grid != len(self._mesh.get_ir_grid_points()):
            print("Warning: \'set_mesh\' has to be called with "
                  "is_mesh_symmetry=False.")
            return False

        if direction is not None:
            direction_cart = np.dot(direction, self._primitive.get_cell())
        else:
            direction_cart = None
        self._pdos = PartialDos(self._mesh,
                                sigma=sigma,
                                tetrahedron_method=tetrahedron_method,
                                direction=direction_cart,
                                xyz_projection=xyz_projection)
        self._pdos.set_draw_area(freq_min, freq_max, freq_pitch)
        self._pdos.run()
        return True

    def get_partial_DOS(self):
        """
        Retern frequencies and partial_dos.
        The first element is freqs and the second is partial_dos.

        frequencies: [freq1, freq2, ...]
        partial_dos:
          [[atom1-freq1, atom1-freq2, ...],
           [atom2-freq1, atom2-freq2, ...],
           ...]
        """
        return self._pdos.get_partial_dos()

    def plot_partial_DOS(self, pdos_indices=None, legend=None):
        import matplotlib.pyplot as plt
        self._pdos.plot(plt,
                        indices=pdos_indices,
                        legend=legend)
        return plt

    def write_partial_DOS(self):
        self._pdos.write()

    # Thermal property
    def set_thermal_properties(self,
                               t_step=10,
                               t_max=1000,
                               t_min=0,
                               temperatures=None,
                               is_projection=False,
                               band_indices=None,
                               cutoff_frequency=None):
        if self._mesh is None:
            print("Warning: set_mesh has to be done before "
                  "set_thermal_properties")
            return False
        else:
            tp = ThermalProperties(self._mesh.get_frequencies(),
                                   weights=self._mesh.get_weights(),
                                   eigenvectors=self._mesh.get_eigenvectors(),
                                   is_projection=is_projection,
                                   band_indices=band_indices,
                                   cutoff_frequency=cutoff_frequency)
            if temperatures is None:
                tp.set_temperature_range(t_step=t_step,
                                         t_max=t_max,
                                         t_min=t_min)
            else:
                tp.set_temperatures(temperatures)
            tp.run()
            self._thermal_properties = tp

    def get_thermal_properties(self):
        temps, fe, entropy, cv = \
            self._thermal_properties.get_thermal_properties()
        return temps, fe, entropy, cv

    def plot_thermal_properties(self):
        import matplotlib.pyplot as plt
        self._thermal_properties.plot(plt)
        return plt

    def write_yaml_thermal_properties(self, filename='thermal_properties.yaml'):
        self._thermal_properties.write_yaml(filename=filename)

    # Thermal displacement
    def set_thermal_displacements(self,
                                  t_step=10,
                                  t_max=1000,
                                  t_min=0,
                                  temperatures=None,
                                  direction=None,
                                  cutoff_frequency=None):
        """
        cutoff_frequency:
          phonon modes that have frequencies below cutoff_frequency
          are ignored.

        direction:
          Projection direction in reduced coordinates
        """
        self._thermal_displacements = None

        if self._mesh is None:
            print("Warning: \'set_mesh\' has to finish correctly "
                  "before \'set_thermal_displacements\'.")
            return False

        eigvecs = self._mesh.get_eigenvectors()
        frequencies = self._mesh.get_frequencies()
        mesh_nums = self._mesh.get_mesh_numbers()

        if self._mesh.get_eigenvectors() is None:
            print("Warning: Eigenvectors have to be calculated.")
            return False

        if np.prod(mesh_nums) != len(eigvecs):
            print("Warning: Sampling mesh must not be symmetrized.")
            return False

        td = ThermalDisplacements(frequencies,
                                  eigvecs,
                                  self._primitive.get_masses(),
                                  cutoff_frequency=cutoff_frequency)
        if temperatures is None:
            td.set_temperature_range(t_min, t_max, t_step)
        else:
            td.set_temperatures(temperatures)
        if direction is not None:
            td.project_eigenvectors(direction, self._primitive.get_cell())
        td.run()

        self._thermal_displacements = td
        return True

    def get_thermal_displacements(self):
        if self._thermal_displacements is not None:
            return self._thermal_displacements.get_thermal_displacements()

    def plot_thermal_displacements(self, is_legend=False):
        import matplotlib.pyplot as plt
        self._thermal_displacements.plot(plt, is_legend=is_legend)
        return plt

    def write_yaml_thermal_displacements(self):
        self._thermal_displacements.write_yaml()

    # Thermal displacement matrix
    def set_thermal_displacement_matrices(self,
                                          t_step=10,
                                          t_max=1000,
                                          t_min=0,
                                          cutoff_frequency=None,
                                          t_cif=None):
        """
        cutoff_frequency:
          phonon modes that have frequencies below cutoff_frequency
          are ignored.

        direction:
          Projection direction in reduced coordinates
        """
        self._thermal_displacement_matrices = None

        if self._mesh is None:
            print("Warning: \'set_mesh\' has to finish correctly "
                  "before \'set_thermal_displacement_matrices\'.")
            return False

        eigvecs = self._mesh.get_eigenvectors()
        frequencies = self._mesh.get_frequencies()
        mesh_nums = self._mesh.get_mesh_numbers()

        if self._mesh.get_eigenvectors() is None:
            print("Warning: Eigenvectors have to be calculated.")
            return False

        if np.prod(mesh_nums) != len(eigvecs):
            print("Warning: Sampling mesh must not be symmetrized.")
            return False

        tdm = ThermalDisplacementMatrices(frequencies,
                                          eigvecs,
                                          self._primitive.get_masses(),
                                          cutoff_frequency=cutoff_frequency,
                                          lattice=self._primitive.get_cell().T)
        if t_cif is None:
            tdm.set_temperature_range(t_min, t_max, t_step)
        else:
            tdm.set_temperatures([t_cif])
        tdm.run()

        self._thermal_displacement_matrices = tdm
        return True

    def get_thermal_displacement_matrices(self):
        tdm = self._thermal_displacement_matrices
        if tdm is not None:
            return tdm.get_thermal_displacement_matrices()

    def write_yaml_thermal_displacement_matrices(self):
        self._thermal_displacement_matrices.write_yaml()

    def write_thermal_displacement_matrix_to_cif(self,
                                                 temperature_index):
        self._thermal_displacement_matrices.write_cif(self._primitive,
                                                      temperature_index)

    # Mean square distance between a pair of atoms
    def set_thermal_distances(self,
                              atom_pairs,
                              t_step=10,
                              t_max=1000,
                              t_min=0,
                              cutoff_frequency=None):
        """
        atom_pairs: List of list
          Mean square distances are calculated for the atom_pairs
          e.g. [[1, 2], [1, 4]]

        cutoff_frequency:
          phonon modes that have frequencies below cutoff_frequency
          are ignored.
        """

        td = ThermalDistances(self._mesh.get_frequencies(),
                              self._mesh.get_eigenvectors(),
                              self._supercell,
                              self._primitive,
                              self._mesh.get_qpoints(),
                              cutoff_frequency=cutoff_frequency)
        td.set_temperature_range(t_min, t_max, t_step)
        td.run(atom_pairs)

        self._thermal_distances = td

    def write_yaml_thermal_distances(self):
        self._thermal_distances.write_yaml()

    # Sampling at q-points
    def set_qpoints_phonon(self,
                           q_points,
                           nac_q_direction=None,
                           is_eigenvectors=False,
                           write_dynamical_matrices=False):
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            self._qpoints_phonon = None
            return False

        self._qpoints_phonon = QpointsPhonon(
            np.reshape(q_points, (-1, 3)),
            self._dynamical_matrix,
            nac_q_direction=nac_q_direction,
            is_eigenvectors=is_eigenvectors,
            group_velocity=self._group_velocity,
            write_dynamical_matrices=write_dynamical_matrices,
            factor=self._factor)
        return True

    def get_qpoints_phonon(self):
        return (self._qpoints_phonon.get_frequencies(),
                self._qpoints_phonon.get_eigenvectors())

    def write_hdf5_qpoints_phonon(self):
        self._qpoints_phonon.write_hdf5()

    def write_yaml_qpoints_phonon(self):
        self._qpoints_phonon.write_yaml()

    # Normal mode animation
    def write_animation(self,
                        q_point=None,
                        anime_type='v_sim',
                        band_index=None,
                        amplitude=None,
                        num_div=None,
                        shift=None,
                        filename=None):
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            return False

        if q_point is None:
            animation = Animation([0, 0, 0],
                                  self._dynamical_matrix,
                                  shift=shift)
        else:
            animation = Animation(q_point,
                                  self._dynamical_matrix,
                                  shift=shift)
        if anime_type == 'v_sim':
            if amplitude:
                amplitude_ = amplitude
            else:
                amplitude_ = 1.0

            if filename:
                animation.write_v_sim(amplitude=amplitude_,
                                      factor=self._factor,
                                      filename=filename)
            else:
                animation.write_v_sim(amplitude=amplitude_,
                                      factor=self._factor)
        if (anime_type == 'arc' or
            anime_type == 'xyz' or
            anime_type == 'jmol' or
            anime_type == 'poscar'):
            if band_index is None or amplitude is None or num_div is None:
                print("Warning: Parameters are not correctly set for "
                      "animation.")
                return False

            if anime_type == 'arc' or anime_type is None:
                if filename:
                    animation.write_arc(band_index,
                                        amplitude,
                                        num_div,
                                        filename=filename)
                else:
                    animation.write_arc(band_index,
                                        amplitude,
                                        num_div)

            if anime_type == 'xyz':
                if filename:
                    animation.write_xyz(band_index,
                                        amplitude,
                                        num_div,
                                        self._factor,
                                        filename=filename)
                else:
                    animation.write_xyz(band_index,
                                        amplitude,
                                        num_div,
                                        self._factor)

            if anime_type == 'jmol':
                if filename:
                    animation.write_xyz_jmol(amplitude=amplitude,
                                             factor=self._factor,
                                             filename=filename)
                else:
                    animation.write_xyz_jmol(amplitude=amplitude,
                                             factor=self._factor)

            if anime_type == 'poscar':
                if filename:
                    animation.write_POSCAR(band_index,
                                           amplitude,
                                           num_div,
                                           filename=filename)
                else:
                    animation.write_POSCAR(band_index,
                                           amplitude,
                                           num_div)

        return True

    # Atomic modulation of normal mode
    def set_modulations(self,
                        dimension,
                        phonon_modes,
                        delta_q=None,
                        derivative_order=None,
                        nac_q_direction=None):
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            self._modulation = None
            return False

        self._modulation = Modulation(self._dynamical_matrix,
                                      dimension,
                                      phonon_modes,
                                      delta_q=delta_q,
                                      derivative_order=derivative_order,
                                      nac_q_direction=nac_q_direction,
                                      factor=self._factor)
        self._modulation.run()
        return True

    def get_modulated_supercells(self):
        """Returns cells with modulations as Atoms objects"""
        return self._modulation.get_modulated_supercells()

    def get_modulations_and_supercell(self):
        """Return modulations and supercell

        (modulations, supercell)

        modulations: Atomic modulations of supercell in Cartesian coordinates
        supercell: Supercell as an Atoms object.

        """
        return self._modulation.get_modulations_and_supercell()

    def write_modulations(self):
        """Create MPOSCAR's"""
        self._modulation.write()

    def write_yaml_modulations(self):
        self._modulation.write_yaml()

    # Irreducible representation
    def set_irreps(self,
                   q,
                   is_little_cogroup=False,
                   nac_q_direction=None,
                   degeneracy_tolerance=1e-4):
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            self._irreps = None
            return None

        self._irreps = IrReps(
            self._dynamical_matrix,
            q,
            is_little_cogroup=is_little_cogroup,
            nac_q_direction=nac_q_direction,
            factor=self._factor,
            symprec=self._symprec,
            degeneracy_tolerance=degeneracy_tolerance,
            log_level=self._log_level)

        return self._irreps.run()

    def get_irreps(self):
        return self._irreps

    def show_irreps(self, show_irreps=False):
        self._irreps.show(show_irreps=show_irreps)

    def write_yaml_irreps(self, show_irreps=False):
        self._irreps.write_yaml(show_irreps=show_irreps)

    # Group velocity
    def set_group_velocity(self, q_length=None):
        if self._dynamical_matrix is None:
            print("Warning: Dynamical matrix has not yet built.")
            self._group_velocity = None
            return False

        self._group_velocity = GroupVelocity(
            self._dynamical_matrix,
            q_length=q_length,
            symmetry=self._primitive_symmetry,
            frequency_factor_to_THz=self._factor)
        return True

    def get_group_velocity(self):
        return self._group_velocity.get_group_velocity()

    def get_group_velocity_at_q(self, q_point):
        if self._group_velocity is None:
            self.set_group_velocity()
        self._group_velocity.set_q_points([q_point])
        return self._group_velocity.get_group_velocity()[0]

    # Moment
    def set_moment(self,
                   order=1,
                   is_projection=False,
                   freq_min=None,
                   freq_max=None):
        if self._mesh is None:
            print("Warning: set_mesh has to be done before set_moment")
            return False
        else:
            if is_projection:
                if self._mesh.get_eigenvectors() is None:
                    print("Warning: Eigenvectors have to be calculated.")
                    return False
                moment = PhononMoment(
                    self._mesh.get_frequencies(),
                    weights=self._mesh.get_weights(),
                    eigenvectors=self._mesh.get_eigenvectors())
            else:
                moment = PhononMoment(
                    self._mesh.get_frequencies(),
                    weights=self._mesh.get_weights())
            if freq_min is not None or freq_max is not None:
                moment.set_frequency_range(freq_min=freq_min,
                                           freq_max=freq_max)
            moment.run(order=order)
            self._moment = moment.get_moment()
            return True

    def get_moment(self):
        return self._moment

    #################
    # Local methods #
    #################
    def _run_force_constants_from_forces(self,
                                         distributed_atom_list=None,
                                         decimals=None,
                                         computation_algorithm="svd"):
        if self._displacement_dataset is not None:
            self._force_constants = get_fc2(
                self._supercell,
                self._symmetry,
                self._displacement_dataset,
                atom_list=distributed_atom_list,
                decimals=decimals,
                computation_algorithm=computation_algorithm)

    def _set_dynamical_matrix(self):
        self._dynamical_matrix = None

        if (self._supercell is None or self._primitive is None):
            print("Bug: Supercell or primitive is not created.")
            return False
        elif self._force_constants is None:
            print("Warning: Force constants are not prepared.")
            return False
        elif self._primitive.get_masses() is None:
            print("Warning: Atomic masses are not correctly set.")
            return False
        else:
            if self._nac_params is None:
                self._dynamical_matrix = DynamicalMatrix(
                    self._supercell,
                    self._primitive,
                    self._force_constants,
                    decimals=self._dynamical_matrix_decimals,
                    symprec=self._symprec)
            else:
                self._dynamical_matrix = DynamicalMatrixNAC(
                    self._supercell,
                    self._primitive,
                    self._force_constants,
                    nac_params=self._nac_params,
                    decimals=self._dynamical_matrix_decimals,
                    symprec=self._symprec)
            return True

    def _search_symmetry(self):
        self._symmetry = Symmetry(self._supercell,
                                  self._symprec,
                                  self._is_symmetry)

    def _search_primitive_symmetry(self):
        self._primitive_symmetry = Symmetry(self._primitive,
                                            self._symprec,
                                            self._is_symmetry)

        if (len(self._symmetry.get_pointgroup_operations()) !=
            len(self._primitive_symmetry.get_pointgroup_operations())):
            print("Warning: Point group symmetries of supercell and primitive"
                  "cell are different.")

    def _build_supercell(self):
        self._supercell = get_supercell(self._unitcell,
                                        self._supercell_matrix,
                                        self._symprec)

    def _build_supercells_with_displacements(self):
        supercells = []
        for disp in self._displacement_dataset['first_atoms']:
            positions = self._supercell.get_positions()
            positions[disp['number']] += disp['displacement']
            supercells.append(Atoms(
                    numbers=self._supercell.get_atomic_numbers(),
                    masses=self._supercell.get_masses(),
                    magmoms=self._supercell.get_magnetic_moments(),
                    positions=positions,
                    cell=self._supercell.get_cell(),
                    pbc=True))

        self._supercells_with_displacements = supercells

    def _build_primitive_cell(self):
        """
        primitive_matrix:
          Relative axes of primitive cell to the input unit cell.
          Relative axes to the supercell is calculated by:
             supercell_matrix^-1 * primitive_matrix
          Therefore primitive cell lattice is finally calculated by:
             (supercell_lattice * (supercell_matrix)^-1 * primitive_matrix)^T
        """

        inv_supercell_matrix = np.linalg.inv(self._supercell_matrix)
        if self._primitive_matrix is None:
            trans_mat = inv_supercell_matrix
        else:
            trans_mat = np.dot(inv_supercell_matrix, self._primitive_matrix)
        self._primitive = get_primitive(
            self._supercell, trans_mat, self._symprec)
        num_satom = self._supercell.get_number_of_atoms()
        num_patom = self._primitive.get_number_of_atoms()
        if abs(num_satom * np.linalg.det(trans_mat) - num_patom) < 0.1:
            return True
        else:
            return False
Esempio n. 38
0
    def __init__(self,
                 unitcell,
                 supercell_matrix,
                 primitive_matrix=None,
                 nac_params=None,
                 distance=None,
                 factor=VaspToTHz,
                 is_auto_displacements=None,
                 dynamical_matrix_decimals=None,
                 force_constants_decimals=None,
                 symprec=1e-5,
                 is_symmetry=True,
                 use_lapack_solver=False,
                 log_level=0):

        if is_auto_displacements is not None:
            print("Warning: \'is_auto_displacements\' argument is obsolete.")
            if is_auto_displacements is False:
                print("Sets of displacements are not created as default.")
            else:
                print("Use \'generate_displacements\' method explicitly to "
                      "create sets of displacements.")

        if distance is not None:
            print("Warning: \'distance\' keyword argument is obsolete at "
                  "Phonopy instantiation.")
            print("Specify \'distance\' keyword argument when calling "
                  "\'generate_displacements\'")
            print("method (See the Phonopy API document).")

        self._symprec = symprec
        self._factor = factor
        self._is_symmetry = is_symmetry
        self._use_lapack_solver = use_lapack_solver
        self._log_level = log_level

        # Create supercell and primitive cell
        self._unitcell = Atoms(atoms=unitcell)
        self._supercell_matrix = supercell_matrix
        self._primitive_matrix = primitive_matrix
        self._supercell = None
        self._primitive = None
        self._build_supercell()
        self._build_primitive_cell()

        # Set supercell and primitive symmetry
        self._symmetry = None
        self._primitive_symmetry = None
        self._search_symmetry()
        self._search_primitive_symmetry()

        # set_displacements (used only in preprocess)
        self._displacement_dataset = None
        self._displacements = None
        self._displacement_directions = None
        self._supercells_with_displacements = None

        # set_force_constants or set_forces
        self._force_constants = None
        self._force_constants_decimals = force_constants_decimals

        # set_dynamical_matrix
        self._dynamical_matrix = None
        self._nac_params = nac_params
        self._dynamical_matrix_decimals = dynamical_matrix_decimals

        # set_band_structure
        self._band_structure = None

        # set_mesh
        self._mesh = None

        # set_tetrahedron_method
        self._tetrahedron_method = None

        # set_thermal_properties
        self._thermal_properties = None

        # set_thermal_displacements
        self._thermal_displacements = None

        # set_thermal_displacement_matrices
        self._thermal_displacement_matrices = None

        # set_partial_DOS
        self._pdos = None

        # set_total_DOS
        self._total_dos = None

        # set_modulation
        self._modulation = None

        # set_character_table
        self._irreps = None

        # set_group_velocity
        self._group_velocity = None