def get_equivalent_smallest_vectors(atom_number_supercell,
                                    atom_number_primitive, supercell,
                                    primitive_lattice, symprec):
    distances = []
    differences = []
    reduced_bases = get_reduced_bases(supercell.get_cell(), symprec)
    positions = np.dot(supercell.get_positions(), np.linalg.inv(reduced_bases))

    # Atomic positions are confined into the lattice made of reduced bases.
    for pos in positions:
        pos -= np.rint(pos)

    p_pos = positions[atom_number_primitive]
    s_pos = positions[atom_number_supercell]
    for i in (-1, 0, 1):
        for j in (-1, 0, 1):
            for k in (-1, 0, 1):
                # The vector arrow is from the atom in primitive to
                # the atom in supercell cell plus a supercell lattice
                # point. This is related to determine the phase
                # convension when building dynamical matrix.
                diff = s_pos + [i, j, k] - p_pos
                differences.append(diff)
                vec = np.dot(diff, reduced_bases)
                distances.append(np.linalg.norm(vec))

    minimum = min(distances)
    smallest_vectors = []
    for i in range(27):
        if abs(minimum - distances[i]) < symprec:
            relative_scale = np.dot(reduced_bases,
                                    np.linalg.inv(primitive_lattice))
            smallest_vectors.append(np.dot(differences[i], relative_scale))

    return smallest_vectors
Beispiel #2
0
def get_equivalent_smallest_vectors(
    atom_number_supercell, atom_number_primitive, supercell, primitive_lattice, symprec
):
    distances = []
    differences = []
    reduced_bases = get_reduced_bases(supercell.get_cell(), symprec)
    positions = np.dot(supercell.get_positions(), np.linalg.inv(reduced_bases))

    # Atomic positions are confined into the lattice made of reduced bases.
    for pos in positions:
        pos -= np.rint(pos)

    p_pos = positions[atom_number_primitive]
    s_pos = positions[atom_number_supercell]
    for i in (-1, 0, 1):
        for j in (-1, 0, 1):
            for k in (-1, 0, 1):
                # The vector arrow is from the atom in primitive to
                # the atom in supercell cell plus a supercell lattice
                # point. This is related to determine the phase
                # convension when building dynamical matrix.
                diff = s_pos + [i, j, k] - p_pos
                differences.append(diff)
                vec = np.dot(diff, reduced_bases)
                distances.append(np.linalg.norm(vec))

    minimum = min(distances)
    smallest_vectors = []
    for i in range(27):
        if abs(minimum - distances[i]) < symprec:
            relative_scale = np.dot(reduced_bases, np.linalg.inv(primitive_lattice))
            smallest_vectors.append(np.dot(differences[i], relative_scale))

    return smallest_vectors
Beispiel #3
0
 def __init__(self, primitive_vectors):
     self._primitive_vectors = primitive_vectors  # column vectors
     self._tolerance = min(np.sum(primitive_vectors ** 2, axis=0)) * 0.01
     self._reduced_bases = get_reduced_bases(primitive_vectors.T)
     self._tmat = np.dot(np.linalg.inv(self._primitive_vectors), self._reduced_bases)
     self._tmat_inv = np.linalg.inv(self._tmat)
     self._shortest_qpoints = None
Beispiel #4
0
def get_equivalent_smallest_vectors_np(atom_number_supercell,
                                       atom_number_primitive, supercell,
                                       primitive_lattice, symprec):
    distances = []
    differences = []
    reduced_bases = get_reduced_bases(supercell.get_cell(), symprec)
    positions = np.dot(supercell.get_positions(), np.linalg.inv(reduced_bases))

    # Atomic positions are confined into the lattice made of reduced bases.
    positions -= np.rint(positions)

    p_pos = positions[atom_number_primitive]
    s_pos = positions[atom_number_supercell]
    sc_range_1 = np.array([-1, 0, 1])[:, None] * np.array([1, 0, 0])[None, :]
    sc_range_2 = np.array([-1, 0, 1])[:, None] * np.array([0, 1, 0])[None, :]
    sc_range_3 = np.array([-1, 0, 1])[:, None] * np.array([0, 0, 1])[None, :]
    # The vector arrow is from the atom in primitive to
    # the atom in supercell cell plus a supercell lattice
    # point. This is related to determine the phase
    # convension when building dynamical matrix.
    differences = (s_pos + sc_range_1[:, None, None] +
                   sc_range_2[None, :, None] + sc_range_3[None, None, :] -
                   p_pos)
    vecs = np.dot(differences, reduced_bases)
    distances = np.linalg.norm(vecs, axis=-1)

    relative_scale = np.dot(reduced_bases, np.linalg.inv(primitive_lattice))
    minimum = np.min(distances)
    indices = np.where(np.abs(minimum - distances) < symprec)
    smallest_vectors = np.dot(differences[indices], relative_scale)
    smallest_vectors = smallest_vectors.reshape(-1, 3)

    return smallest_vectors
 def __init__(self, primitive_vectors):
     self._primitive_vectors = primitive_vectors # column vectors
     self._tolerance = min(np.sum(primitive_vectors ** 2, axis=0)) * 0.01
     self._reduced_bases = get_reduced_bases(primitive_vectors.T)
     self._tmat = np.dot(np.linalg.inv(self._primitive_vectors),
                         self._reduced_bases)
     self._tmat_inv = np.linalg.inv(self._tmat)
     self._shortest_qpoints = None
Beispiel #6
0
def cutoff_force_constants(force_constants,
                           supercell,
                           cutoff_radius,
                           symprec=1e-5):
    num_atom = supercell.get_number_of_atoms()
    reduced_bases = get_reduced_bases(supercell.get_cell(), tolerance=symprec)
    positions = np.dot(supercell.get_positions(), np.linalg.inv(reduced_bases))
    for i in range(num_atom):
        pos_i = positions[i]
        for j in range(num_atom):
            pos_j = positions[j]
            min_distance = _get_shortest_distance_in_PBC(
                pos_i, pos_j, reduced_bases)
            if min_distance > cutoff_radius:
                force_constants[i, j] = 0.0
Beispiel #7
0
def cutoff_force_constants(force_constants,
                           supercell,
                           cutoff_radius,
                           symprec=1e-5):
    num_atom = supercell.get_number_of_atoms()
    reduced_bases = get_reduced_bases(supercell.get_cell(), symprec)
    positions = np.dot(supercell.get_positions(),
                       np.linalg.inv(reduced_bases))
    for i in range(num_atom):
        pos_i = positions[i]
        for j in range(num_atom):
            pos_j = positions[j]
            min_distance = _get_shortest_distance_in_PBC(pos_i,
                                                         pos_j,
                                                         reduced_bases)
            if min_distance > cutoff_radius:
                force_constants[i, j] = 0.0
Beispiel #8
0
    def __init__(self, reciprocal_lattice, tolerance=0.01):
        """Init method.

        Parameters
        ----------
        reciprocal_lattice : array_like
            Reciprocal primitive cell basis vectors given in column vectors.
            shape=(3,3)
            dtype=float
        tolerance : float, optional
            Default = 0.01

        """
        self._reciprocal_lattice = np.array(reciprocal_lattice)
        self._tolerance = min(np.sum(reciprocal_lattice**2,
                                     axis=0)) * tolerance
        self._reduced_bases = get_reduced_bases(reciprocal_lattice.T)
        self._tmat = np.dot(np.linalg.inv(self._reciprocal_lattice),
                            self._reduced_bases.T)
        self._tmat_inv = np.linalg.inv(self._tmat)
        self.shortest_qpoints = None
Beispiel #9
0
    def __init__(self, reciprocal_lattice, tolerance=0.01):
        """

        Parameters
        ----------
        reciprocal_lattice : array_like
            Reciprocal primitive cell basis vectors given in column vectors.
            shape=(3,3)
            dtype=float
        tolerance : float, optional
            Default = 0.01

        """

        self._reciprocal_lattice = np.array(reciprocal_lattice)
        self._tolerance = min(
            np.sum(reciprocal_lattice ** 2, axis=0)) * tolerance
        self._reduced_bases = get_reduced_bases(reciprocal_lattice.T)
        self._tmat = np.dot(np.linalg.inv(self._reciprocal_lattice),
                            self._reduced_bases.T)
        self._tmat_inv = np.linalg.inv(self._tmat)
        self.shortest_qpoints = None
Beispiel #10
0
def get_phonon_tb(
    # phonopy_atoms=[],
    atoms=[],
    fc=[],
    out_file="phonopyTB_hr.dat",
    distance_to_A=1.0,
    scell=np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
    factor=VaspToTHz,
    symprec=1e-05,
    displacement_distance=0.01,
):
    """Generate phonon TB Hamiltonia, along with WannierHamn."""
    # Forked from Wannier-tools
    unitcell = atoms.phonopy_converter()
    # unitcell = phonopy_atoms
    prim_mat = np.array(PhonopyInputs(atoms).prim_axis().split("=")[1].split(),
                        dtype="float").reshape(3, 3)
    # print("cell", unitcell.cell)
    num_atom = unitcell.get_number_of_atoms()
    num_satom = determinant(scell) * num_atom
    if fc.shape[0] != num_satom:
        print("Check Force constant matrix.")
    phonon = Phonopy(
        unitcell,
        scell,
        primitive_matrix=prim_mat,
        factor=factor,
        dynamical_matrix_decimals=None,
        force_constants_decimals=None,
        symprec=symprec,
        is_symmetry=True,
        use_lapack_solver=False,
        log_level=1,
    )

    supercell = phonon.get_supercell()
    primitive = phonon.get_primitive()
    # Set force constants
    phonon.set_force_constants(fc)
    phonon._set_dynamical_matrix()
    dmat = phonon._dynamical_matrix
    # rescale fcmat by THZ**2
    fcmat = dmat._force_constants * factor**2  # FORCE_CONSTANTS
    # fcmat = dmat._force_constants * factor ** 2  # FORCE_CONSTANTS
    smallest_vectors = dmat._smallest_vectors
    # mass = dmat._mass
    mass = dmat._pcell.get_masses()
    print("mass=", mass)
    multi = dmat._multiplicity
    reduced_bases = get_reduced_bases(supercell.get_cell(), symprec)
    positions = np.dot(supercell.get_positions(), np.linalg.inv(reduced_bases))
    # for pos in positions: pos -= np.rint(pos)
    relative_scale = np.dot(reduced_bases, np.linalg.inv(primitive.get_cell()))
    super_pos = np.zeros((num_satom, 3), dtype=np.float64)
    for i in range(num_satom):
        super_pos[i] = np.dot(positions[i], relative_scale)
    p2s_map = dmat._p2s_map = primitive.get_primitive_to_supercell_map()
    s2p_map = dmat._s2p_map = primitive.get_supercell_to_primitive_map()
    num_satom = supercell.get_number_of_atoms()
    num_patom = primitive.get_number_of_atoms()
    get_phonon_hr(
        fcmat,
        smallest_vectors,
        mass,
        multi,
        super_pos,
        p2s_map,
        s2p_map,
        num_satom,
        num_patom,
        out_file,
    )
    print("phonopy_TB.dat generated! ")
Beispiel #11
0
if len(symbols_with_no_mass) > 0:
    if log_level > 0:
        print_end()
    sys.exit(1)

phonon.set_dynamical_matrix()
dmat = phonon._dynamical_matrix

# rescale fcmat by THZ**2
fcmat = dmat._force_constants * factor**2  # FORCE_CONSTANTS
smallest_vectors = dmat._smallest_vectors
#mass = dmat._mass
mass = dmat._pcell.get_masses()
multi = dmat._multiplicity

reduced_bases = get_reduced_bases(supercell.get_cell(), options.symprec)
positions = np.dot(supercell.get_positions(), np.linalg.inv(reduced_bases))
#for pos in positions: pos -= np.rint(pos)

relative_scale = np.dot(reduced_bases, np.linalg.inv(primitive.get_cell()))
super_pos = np.zeros((num_satom, 3), dtype=np.float64)
for i in range(num_satom):
    super_pos[i] = np.dot(positions[i], relative_scale)

p2s_map = dmat._p2s_map = primitive.get_primitive_to_supercell_map()
s2p_map = dmat._s2p_map = primitive.get_supercell_to_primitive_map()

num_satom = supercell.get_number_of_atoms()
num_patom = primitive.get_number_of_atoms()

# get hr
Beispiel #12
0
def _relocate_BZ_grid_address(
    D_diag,
    Q,
    reciprocal_lattice,  # column vectors
    is_shift=None,
    store_dense_gp_map=False,
):
    """Grid addresses are relocated to be inside first Brillouin zone.

    Number of ir-grid-points inside Brillouin zone is returned.
    It is assumed that the following arrays have the shapes of
        bz_grid_address : (num_grid_points_in_FBZ, 3)

    Note that the shape of grid_address is (prod(mesh), 3) and the
    addresses in grid_address are arranged to be in parallelepiped
    made of reciprocal basis vectors. The addresses in bz_grid_address
    are inside the first Brillouin zone or on its surface. Each
    address in grid_address is mapped to one of those in
    bz_grid_address by a reciprocal lattice vector (including zero
    vector) with keeping element order. For those inside first BZ, the
    mapping is one-to-one. For those on the first BZ surface, more
    than one addresses in bz_grid_address that are equivalent by the
    reciprocal lattice translations are mapped to one address in
    grid_address. The bz_grid_address and bz_map are given in the
    following format depending on the choice of `store_dense_gp_map`.

    store_dense_gp_map = False
    --------------------------
    Those grid points on the BZ surface except for one of them are
    appended to the tail of this array, for which bz_grid_address has
    the following data storing:

    |------------------array size of bz_grid_address-------------------------|
    |--those equivalent to grid_address--|--those on surface except for one--|
    |-----array size of grid_address-----|

    Number of grid points stored in bz_grid_address is returned.
    bz_map is used to recover grid point index expanded to include BZ
    surface from grid address. The grid point indices are mapped to
    (mesh[0] * 2) x (mesh[1] * 2) x (mesh[2] * 2) space (bz_map).
    bz_map[(prod(mesh) * 8):(prod(mesh) * 9 + 1)] contains equivalent
    information to bz_map[:] with `store_dense_gp_map=True`.

    shape=(prod(mesh * 9) + 1, )

    store_dense_gp_map = True
    -------------------------
    The translationally equivalent grid points corresponding to one grid point
    on BZ surface are stored in continuously. If the multiplicity (number of
    equivalent grid points) is 1, 2, 1, 4, ... for the grid points,
    ``bz_map`` stores the multiplicites and the index positions of the first
    grid point of the equivalent grid points, i.e.,

    bz_map[:] = [0, 1, 3, 4, 8...]
    grid_address[0] -> bz_grid_address[0:1]
    grid_address[1] -> bz_grid_address[1:3]
    grid_address[2] -> bz_grid_address[3:4]
    grid_address[3] -> bz_grid_address[4:8]

    shape=(prod(mesh) + 1, )

    """
    import phono3py._phono3py as phono3c

    if is_shift is None:
        _is_shift = np.zeros(3, dtype="int_")
    else:
        _is_shift = np.array(is_shift, dtype="int_")
    bz_grid_addresses = np.zeros((np.prod(D_diag) * 8, 3),
                                 dtype="int_",
                                 order="C")
    bzg2grg = np.zeros(len(bz_grid_addresses), dtype="int_")

    if store_dense_gp_map:
        bz_map = np.zeros(np.prod(D_diag) + 1, dtype="int_")
    else:
        bz_map = np.zeros(np.prod(D_diag) * 9 + 1, dtype="int_")

    reclat_T = np.array(reciprocal_lattice.T, dtype="double", order="C")
    reduced_basis = get_reduced_bases(reclat_T)
    tmat_inv = np.dot(np.linalg.inv(reduced_basis.T), reclat_T.T)
    tmat_inv_int = np.rint(tmat_inv).astype("int_")
    assert (np.abs(tmat_inv - tmat_inv_int) < 1e-5).all()

    num_gp = phono3c.bz_grid_addresses(
        bz_grid_addresses,
        bz_map,
        bzg2grg,
        np.array(D_diag, dtype="int_"),
        np.array(np.dot(tmat_inv_int, Q), dtype="int_", order="C"),
        _is_shift,
        np.array(reduced_basis.T, dtype="double", order="C"),
        store_dense_gp_map * 1 + 1,
    )

    bz_grid_addresses = np.array(bz_grid_addresses[:num_gp],
                                 dtype="int_",
                                 order="C")
    bzg2grg = np.array(bzg2grg[:num_gp], dtype="int_")
    return bz_grid_addresses, bz_map, bzg2grg