Пример #1
0
def symmetrize_2nd_rank_tensor(tensor, symmetry_operations, lattice):
    sym_cart = [similarity_transformation(lattice.T, r)
                for r in symmetry_operations]
    sum_tensor = np.zeros_like(tensor)
    for sym in sym_cart:
        sum_tensor += similarity_transformation(sym, tensor)
    return sum_tensor / len(symmetry_operations)
Пример #2
0
def symmetrize_borns_and_epsilon(borns,
                                 epsilon,
                                 ucell,
                                 symprec=1e-5,
                                 is_symmetry=True):
    lattice = ucell.get_cell()
    positions = ucell.get_scaled_positions()
    u_sym = Symmetry(ucell, is_symmetry=is_symmetry, symprec=symprec)
    rotations = u_sym.get_symmetry_operations()['rotations']
    translations = u_sym.get_symmetry_operations()['translations']
    ptg_ops = u_sym.get_pointgroup_operations()
    epsilon_ = _symmetrize_2nd_rank_tensor(epsilon, ptg_ops, lattice)

    for i, Z in enumerate(borns):
        site_sym = u_sym.get_site_symmetry(i)
        Z = _symmetrize_2nd_rank_tensor(Z, site_sym, lattice)

    borns_ = np.zeros_like(borns)
    for i in range(len(borns)):
        count = 0
        for r, t in zip(rotations, translations):
            count += 1
            diff = np.dot(positions, r.T) + t - positions[i]
            diff -= np.rint(diff)
            dist = np.sqrt(np.sum(np.dot(diff, lattice)**2, axis=1))
            j = np.nonzero(dist < symprec)[0][0]
            r_cart = similarity_transformation(lattice.T, r)
            borns_[i] += similarity_transformation(r_cart, borns[j])
        borns_[i] /= count

    return borns_, epsilon_
Пример #3
0
def get_born_OUTCAR(poscar_filename="POSCAR",
                    outcar_filename="OUTCAR",
                    primitive_axis=np.eye(3),
                    is_symmetry=True,
                    symmetrize_tensors=False):
    cell = read_vasp(poscar_filename)
    primitive = Primitive(cell, primitive_axis)
    p2p = primitive.get_primitive_to_primitive_map()
    symmetry = Symmetry(primitive, is_symmetry=is_symmetry)
    independent_atoms = symmetry.get_independent_atoms()
    prim_lat = primitive.get_cell().T
    outcar = open(outcar_filename)
    
    borns = []
    while True:
        line = outcar.readline()
        if not line:
            break
    
        if "NIONS" in line:
            num_atom = int(line.split()[11])
    
        if "MACROSCOPIC STATIC DIELECTRIC TENSOR" in line:
            epsilon = []
            outcar.readline()
            epsilon.append([float(x) for x in outcar.readline().split()])
            epsilon.append([float(x) for x in outcar.readline().split()])
            epsilon.append([float(x) for x in outcar.readline().split()])
    
        if "BORN" in line:
            outcar.readline()
            line = outcar.readline()
            if "ion" in line:
                for i in range(num_atom):
                    born = []
                    born.append([float(x) for x in outcar.readline().split()][1:])
                    born.append([float(x) for x in outcar.readline().split()][1:])
                    born.append([float(x) for x in outcar.readline().split()][1:])
                    outcar.readline()
                    borns.append(born)


    reduced_borns = []
    for p_i, u_i in enumerate(p2p):
        if p_i in independent_atoms:
            if symmetrize_tensors:
                site_sym = [similarity_transformation(prim_lat, rot)
                            for rot in symmetry.get_site_symmetry(p_i)]
                reduced_borns.append(symmetrize_tensor(borns[u_i], site_sym))
            else:
                reduced_borns.append(borns[u_i])
                
    if symmetrize_tensors:
        point_sym = [similarity_transformation(prim_lat, rot)
                     for rot in symmetry.get_pointgroup_operations()]
        epsilon = symmetrize_tensor(epsilon, point_sym)
    else:
        epsilon = np.array(epsilon)

    return np.array(reduced_borns), epsilon
Пример #4
0
def _symmetrize_borns(borns, u_sym, lattice, positions, symprec):
    borns_orig = borns.copy()
    for i, Z in enumerate(borns):
        site_sym = [similarity_transformation(lattice, r)
                    for r in u_sym.get_site_symmetry(i)]
        Z = _symmetrize_tensor(Z, site_sym)

    rotations = u_sym.get_symmetry_operations()['rotations']
    translations = u_sym.get_symmetry_operations()['translations']
    map_atoms = u_sym.get_map_atoms()
    borns_copy = np.zeros_like(borns)
    for i in range(len(borns)):
        count = 0
        for r, t in zip(rotations, translations):
            count += 1
            diff = np.dot(positions, r.T) + t - positions[i]
            diff -= np.rint(diff)
            j = np.nonzero((np.abs(diff) < symprec).all(axis=1))[0][0]
            r_cart = similarity_transformation(lattice, r)
            borns_copy[i] += similarity_transformation(r_cart, borns[j])
        borns_copy[i] /= count

    borns = borns_copy
    sum_born = borns.sum(axis=0) / len(borns)
    borns -= sum_born

    if (np.abs(borns_orig - borns) > 0.1).any():
        sys.stderr.write(
            "Born effective charge symmetrization might go wrong.\n")

    return borns
Пример #5
0
def _symmetrize_2nd_rank_tensor(tensor, symmetry_operations, lattice):
    sym_cart = [similarity_transformation(lattice.T, r)
                for r in symmetry_operations]
    sum_tensor = np.zeros_like(tensor)
    for sym in sym_cart:
        sum_tensor += similarity_transformation(sym, tensor)
    return sum_tensor / len(symmetry_operations)
Пример #6
0
def symmetrize_borns_and_epsilon(borns,
                                 epsilon,
                                 ucell,
                                 symprec=1e-5,
                                 is_symmetry=True):
    lattice = ucell.get_cell()
    positions = ucell.get_scaled_positions()
    u_sym = Symmetry(ucell, is_symmetry=is_symmetry, symprec=symprec)
    rotations = u_sym.get_symmetry_operations()['rotations']
    translations = u_sym.get_symmetry_operations()['translations']
    ptg_ops = u_sym.get_pointgroup_operations()
    epsilon_ = _symmetrize_2nd_rank_tensor(epsilon, ptg_ops, lattice)

    for i, Z in enumerate(borns):
        site_sym = u_sym.get_site_symmetry(i)
        Z = _symmetrize_2nd_rank_tensor(Z, site_sym, lattice)

    borns_ = np.zeros_like(borns)
    for i in range(len(borns)):
        count = 0
        for r, t in zip(rotations, translations):
            count += 1
            diff = np.dot(positions, r.T) + t - positions[i]
            diff -= np.rint(diff)
            dist = np.sqrt(np.sum(np.dot(diff, lattice) ** 2, axis=1))
            j = np.nonzero(dist < symprec)[0][0]
            r_cart = similarity_transformation(lattice.T, r)
            borns_[i] += similarity_transformation(r_cart, borns[j])
        borns_[i] /= count

    sum_born = borns_.sum(axis=0) / len(borns_)
    borns_ -= sum_born

    return borns_, epsilon_
Пример #7
0
def _symmetrize_borns(borns, u_sym, lattice, positions, symprec):
    borns_orig = borns.copy()
    for i, Z in enumerate(borns):
        site_sym = [
            similarity_transformation(lattice, r)
            for r in u_sym.get_site_symmetry(i)
        ]
        Z = _symmetrize_tensor(Z, site_sym)

    rotations = u_sym.get_symmetry_operations()['rotations']
    translations = u_sym.get_symmetry_operations()['translations']
    map_atoms = u_sym.get_map_atoms()
    borns_copy = np.zeros_like(borns)
    for i in range(len(borns)):
        count = 0
        for r, t in zip(rotations, translations):
            count += 1
            diff = np.dot(positions, r.T) + t - positions[i]
            diff -= np.rint(diff)
            j = np.nonzero((np.abs(diff) < symprec).all(axis=1))[0][0]
            r_cart = similarity_transformation(lattice, r)
            borns_copy[i] += similarity_transformation(r_cart, borns[j])
        borns_copy[i] /= count

    borns = borns_copy
    sum_born = borns.sum(axis=0) / len(borns)
    borns -= sum_born

    if (np.abs(borns_orig - borns) > 0.1).any():
        sys.stderr.write(
            "Born effective charge symmetrization might go wrong.\n")

    return borns
Пример #8
0
def get_born_parameters(f, primitive, symmetry):
    from phonopy.harmonic.force_constants import similarity_transformation

    # Read unit conversion factor, damping factor, ...
    line_arr = f.readline().split()
    if len(line_arr) < 1:
        print("BORN file format of line 1 is incorrect")
        return False
    if len(line_arr) > 0:
        try:
            factor = float(line_arr[0])
        except (ValueError, TypeError):
            factor = None

    # Read dielectric constant
    line = f.readline().split()
    if not len(line) == 9:
        print("BORN file format of line 2 is incorrect")
        return False
    dielectric = np.reshape([float(x) for x in line], (3, 3))

    # Read Born effective charge
    independent_atoms = symmetry.get_independent_atoms()
    born = np.zeros((primitive.get_number_of_atoms(), 3, 3), dtype=float)

    for i in independent_atoms:
        line = f.readline().split()
        if len(line) == 0:
            print("Number of lines for Born effect charge is not enough.")
            return False
        if not len(line) == 9:
            print("BORN file format of line %d is incorrect" % (i + 3))
            return False
        born[i] = np.reshape([float(x) for x in line], (3, 3))

    # Check that the number of atoms in the BORN file was correct
    line = f.readline().split()
    if len(line) > 0:
        print(
            "Too many atoms in the BORN file (it should only contain symmetry-independent atoms)"
        )
        return False

    # Expand Born effective charges to all atoms in the primitive cell
    rotations = symmetry.get_symmetry_operations()['rotations']
    map_operations = symmetry.get_map_operations()
    map_atoms = symmetry.get_map_atoms()

    for i in range(primitive.get_number_of_atoms()):
        # R_cart = L R L^-1
        rot_cartesian = similarity_transformation(
            primitive.get_cell().transpose(), rotations[map_operations[i]])
        # R_cart^T B R_cart^-T (inverse rotation is required to transform)
        born[i] = similarity_transformation(rot_cartesian.transpose(),
                                            born[map_atoms[i]])

    non_anal = {'born': born, 'factor': factor, 'dielectric': dielectric}

    return non_anal
Пример #9
0
def get_born_parameters(f, primitive, symmetry):
    from phonopy.harmonic.force_constants import similarity_transformation

    # Read unit conversion factor, damping factor, ...
    line_arr = f.readline().split()
    if len(line_arr) < 1:
        print("BORN file format of line 1 is incorrect")
        return False
    if len(line_arr) > 0:
        try:
            factor = float(line_arr[0])
        except (ValueError, TypeError):
            factor = None

    # Read dielectric constant
    line = f.readline().split()
    if not len(line) == 9:
        print("BORN file format of line 2 is incorrect")
        return False
    dielectric = np.reshape([float(x) for x in line], (3, 3))
    
    # Read Born effective charge
    independent_atoms = symmetry.get_independent_atoms()
    born = np.zeros((primitive.get_number_of_atoms(), 3, 3), dtype=float)

    for i in independent_atoms:
        line = f.readline().split()
        if len(line) == 0:
            print("Number of lines for Born effect charge is not enough.")
            return False
        if not len(line) == 9:
            print("BORN file format of line %d is incorrect" % (i + 3))
            return False
        born[i] = np.reshape([float(x) for x in line], (3, 3))

    # Expand Born effective charges to all atoms in the primitive cell
    rotations = symmetry.get_symmetry_operations()['rotations']
    map_operations = symmetry.get_map_operations()
    map_atoms = symmetry.get_map_atoms()

    for i in range(primitive.get_number_of_atoms()):
        # R_cart = L R L^-1
        rot_cartesian = similarity_transformation(
            primitive.get_cell().transpose(), rotations[map_operations[i]])
        # R_cart^T B R_cart^-T (inverse rotation is required to transform)
        born[i] = similarity_transformation(rot_cartesian.transpose(),
                                            born[map_atoms[i]])

    non_anal = {'born': born,
                'factor': factor,
                'dielectric': dielectric }

    return non_anal
Пример #10
0
def _expand_borns(borns, primitive, prim_symmetry):
    # Expand Born effective charges to all atoms in the primitive cell
    rotations = prim_symmetry.get_symmetry_operations()['rotations']
    map_operations = prim_symmetry.get_map_operations()
    map_atoms = prim_symmetry.get_map_atoms()

    for i in range(primitive.get_number_of_atoms()):
        # R_cart = L R L^-1
        rot_cartesian = similarity_transformation(
            primitive.get_cell().transpose(), rotations[map_operations[i]])
        # R_cart^T B R_cart^-T (inverse rotation is required to transform)
        borns[i] = similarity_transformation(rot_cartesian.transpose(),
                                             borns[map_atoms[i]])
Пример #11
0
def _expand_borns(borns, primitive: PhonopyAtoms, prim_symmetry: Symmetry):
    # Expand Born effective charges to all atoms in the primitive cell
    rotations = prim_symmetry.symmetry_operations["rotations"]
    map_operations = prim_symmetry.get_map_operations()
    map_atoms = prim_symmetry.get_map_atoms()

    for i in range(len(primitive)):
        # R_cart = L R L^-1
        rot_cartesian = similarity_transformation(primitive.cell.T,
                                                  rotations[map_operations[i]])
        # R_cart^T B R_cart^-T (inverse rotation is required to transform)
        borns[i] = similarity_transformation(rot_cartesian.T,
                                             borns[map_atoms[i]])
Пример #12
0
def get_born_parameters(f, primitive, is_symmetry):
    # Read unit conversion factor, damping factor, ...
    factors = [float(x) for x in f.readline().split()]
    if len(factors) < 1:
        print "BORN file format of line 1 is incorrect"
        return False
    if len(factors) < 2:
        factors = factors[0]

    # Read dielectric constant
    line = f.readline().split()
    if not len(line) == 9:
        print "BORN file format of line 2 is incorrect"
        return False
    dielectric = np.reshape([float(x) for x in line], (3, 3))

    # Read Born effective charge
    symmetry = Symmetry(primitive, is_symmetry=is_symmetry)
    independent_atoms = symmetry.get_independent_atoms()
    born = np.zeros((primitive.get_number_of_atoms(), 3, 3), dtype=float)

    for i in independent_atoms:
        line = f.readline().split()
        if len(line) == 0:
            print "Number of lines for Born effect charge is not enough."
            return False
        if not len(line) == 9:
            print "BORN file format of line %d is incorrect" % (i + 3)
            return False
        born[i] = np.reshape([float(x) for x in line], (3, 3))

    # Expand Born effective charges to all atoms in the primitive cell
    rotations = symmetry.get_symmetry_operations()['rotations']
    map_operations = symmetry.get_map_operations()
    map_atoms = symmetry.get_map_atoms()

    for i in range(primitive.get_number_of_atoms()):
        # R_cart = L R L^-1
        rot_cartesian = similarity_transformation(
            primitive.get_cell().transpose(), rotations[map_operations[i]])
        # R_cart^T B R_cart^-T (inverse rotation is required to transform)
        born[i] = similarity_transformation(rot_cartesian.transpose(),
                                            born[map_atoms[i]])

    non_anal = {'born': born,
                'factor': factors,
                'dielectric': dielectric }

    return non_anal
Пример #13
0
def _expand_borns(borns, primitive, prim_symmetry):
    from phonopy.harmonic.force_constants import similarity_transformation

    # Expand Born effective charges to all atoms in the primitive cell
    rotations = prim_symmetry.get_symmetry_operations()['rotations']
    map_operations = prim_symmetry.get_map_operations()
    map_atoms = prim_symmetry.get_map_atoms()

    for i in range(primitive.get_number_of_atoms()):
        # R_cart = L R L^-1
        rot_cartesian = similarity_transformation(
            primitive.get_cell().transpose(), rotations[map_operations[i]])
        # R_cart^T B R_cart^-T (inverse rotation is required to transform)
        borns[i] = similarity_transformation(rot_cartesian.transpose(),
                                             borns[map_atoms[i]])
Пример #14
0
    def _distribute_3(self, disps_3, forces_3, second_atom_num, third_atom_num,
                      reduced_bond_sym):
        positions = self._positions.copy() - self._positions[second_atom_num]
        rot_map_syms = get_positions_sent_by_rot_inv(positions,
                                                     reduced_bond_sym,
                                                     self._symprec)

        sym_cart = None
        rot_atom_map = None
        for i, sym in enumerate(reduced_bond_sym):
            if disps_3[rot_map_syms[i, third_atom_num]] is not None:
                sym_cart = similarity_transformation(self._lattice, sym)
                rot_atom_map = rot_map_syms[i, :]
                break

        assert sym_cart is not None, "Something is wrong."

        forces = [
            np.dot(f[rot_atom_map], sym_cart.T)
            for f in forces_3[rot_atom_map[third_atom_num]]
        ]
        disps = [[d3[0], d3[1], np.dot(sym_cart, d3[2])]
                 for d3 in disps_3[rot_atom_map[third_atom_num]]]

        disps_3[third_atom_num] = disps
        forces_3[third_atom_num] = forces
Пример #15
0
    def _distribute_2(self, disps, forces, first_atom_num, second_atom_num,
                      reduced_site_sym):
        positions = self._positions.copy() - self._positions[first_atom_num]
        rot_map_syms = get_positions_sent_by_rot_inv(positions,
                                                     reduced_site_sym,
                                                     self._symprec)

        sym_cart = None
        rot_atom_map = None
        for i, sym in enumerate(reduced_site_sym):
            if disps[rot_map_syms[i, second_atom_num]] is not None:
                sym_cart = similarity_transformation(self._lattice, sym)
                rot_atom_map = rot_map_syms[i, :]
                break

        assert sym_cart is not None, "Something is wrong."

        forces[second_atom_num] = []
        disps[second_atom_num] = []
        for i in range(self._num_atom):
            forces_2 = [
                np.dot(f[rot_atom_map], sym_cart.T)
                for f in forces[rot_atom_map[second_atom_num]][rot_atom_map[i]]
            ]
            disps_2 = [[
                d3[0], np.dot(sym_cart, d3[1]),
                np.dot(sym_cart, d3[2])
            ] for d3 in disps[rot_atom_map[second_atom_num]][rot_atom_map[i]]]

            forces[second_atom_num].append(forces_2)
            disps[second_atom_num].append(disps_2)
Пример #16
0
def solve_fc3(fc3,
              first_atom_num,
              supercell,
              site_symmetry,
              displacements_first,
              delta_fc2s,
              symprec,
              pinv="numpy"):
    lattice = supercell.get_cell().T
    site_sym_cart = [similarity_transformation(lattice, sym)
                     for sym in site_symmetry]
    num_atom = supercell.get_number_of_atoms()
    positions = supercell.get_scaled_positions()
    pos_center = positions[first_atom_num].copy()
    positions -= pos_center
    rot_map_syms = get_positions_sent_by_rot_inv(positions,
                                                 site_symmetry,
                                                 symprec)
    
    rot_disps = get_rotated_displacement(displacements_first, site_sym_cart)

    if pinv == "numpy":
        inv_U = np.linalg.pinv(rot_disps)
    else:
        try:
            import anharmonic._phono3py as phono3c
            inv_U = np.zeros((rot_disps.shape[1], rot_disps.shape[0]),
                             dtype='double')
            phono3c.pinv(inv_U, rot_disps, 1e-13)
        except ImportError:
            inv_U = np.linalg.pinv(rot_disps)
            
    for (i, j) in list(np.ndindex(num_atom, num_atom)):
        fc3[first_atom_num, i, j] = np.dot(inv_U, _get_rotated_fc2s(
                i, j, delta_fc2s, rot_map_syms, site_sym_cart)).reshape(3, 3, 3)
Пример #17
0
def distribute_fc3(fc3,
                   first_disp_atoms,
                   lattice,
                   positions,
                   rotations,
                   translations,
                   symprec,
                   verbose):
    num_atom = len(positions)

    for i in range(num_atom):
        if i in first_disp_atoms:
            continue

        for atom_index_done in first_disp_atoms:
            rot_num = get_atom_mapping_by_symmetry(positions,
                                                   i,
                                                   atom_index_done,
                                                   rotations,
                                                   translations,
                                                   symprec)
            if rot_num > -1:
                i_rot = atom_index_done
                rot = rotations[rot_num]
                trans = translations[rot_num]
                break

        if rot_num < 0:
            print "Position or symmetry may be wrong."
            raise ValueError

        if verbose > 2:
            print "    [ %d, x, x ] to [ %d, x, x ]" % (i_rot + 1, i + 1)
            sys.stdout.flush()

        atom_mapping = np.zeros(num_atom, dtype='intc')
        for j in range(num_atom):
            atom_mapping[j] = get_atom_by_symmetry(positions,
                                                   rot,
                                                   trans,
                                                   j,
                                                   symprec)
            
        rot_cart_inv = np.double(
            similarity_transformation(lattice, rot).T.copy())

        try:
            import anharmonic._phono3py as phono3c
            phono3c.distribute_fc3(fc3,
                                   i,
                                   atom_mapping,
                                   rot_cart_inv)
        
        except ImportError:
            for j in range(num_atom):
                j_rot = atom_mapping[j]
                for k in range(num_atom):
                    k_rot = atom_mapping[k]
                    fc3[i, j, k] = third_rank_tensor_rotation(
                        rot_cart_inv, fc3[i_rot, j_rot, k_rot])
Пример #18
0
    def get_gv_by_sr0_at_stars(self, s, i, t):
        deg_sets = degenerate_sets(self._frequencies[i])
        grid_point = self._grid_points[i]
        orig_address = self._grid_address[grid_point]
        rotations = get_rotations_for_star(orig_address, self._mesh,
                                           self._kpoint_operations)
        # self._get_group_veclocities_at_star(i, gv)
        gv_by_F_tensor = []
        rec_lat = np.linalg.inv(self._primitive.get_cell())
        rotations_cartesian = [
            similarity_transformation(rec_lat, r) for r in rotations
        ]
        for rot_c in rotations_cartesian:
            gvs_rot = np.dot(rot_c, self._gv[i].T).T
            F_rot = np.dot(rot_c, self._F0[s, i, t].T).T

            # Take average of group veclocities of degenerate phonon modes
            # and then calculate gv x gv to preserve symmetry
            gvs = np.zeros_like(gvs_rot)
            Fs = np.zeros_like(F_rot)
            for deg in deg_sets:
                gv_ave = gvs_rot[deg].sum(axis=0) / len(deg)
                F_ave = F_rot[deg].sum(axis=0) / len(deg)
                for j in deg:
                    gvs[j] = gv_ave
                    Fs[j] = F_ave
            gv_by_F_tensor.append(
                [np.outer(gvs[b], Fs[b]) for b in range(len(gvs))])

        return np.array(gv_by_F_tensor)
Пример #19
0
def _solve_fc4(fc4,
               first_atom_num,
               supercell,
               site_symmetry,
               displacements_first,
               delta_fc3s,
               symprec):
    lattice = supercell.get_cell().T
    site_sym_cart = np.double([similarity_transformation(lattice, sym)
                               for sym in site_symmetry])
    num_atom = supercell.get_number_of_atoms()
    positions = supercell.get_scaled_positions()
    pos_center = positions[first_atom_num].copy()
    positions -= pos_center
    rot_map_syms = get_positions_sent_by_rot_inv(positions,
                                                 site_symmetry,
                                                 symprec)
    
    rot_disps = get_rotated_displacement(displacements_first, site_sym_cart)
    inv_U = np.linalg.pinv(rot_disps)

    for (i, j, k) in list(np.ndindex(num_atom, num_atom, num_atom)):
        fc4[first_atom_num, i, j, k] = np.dot(
            inv_U, _rotate_delta_fc3s(
                i, j, k, delta_fc3s, rot_map_syms, site_sym_cart)
            ).reshape(3, 3, 3, 3)
Пример #20
0
    def _distribute_2(self,
                      disps,
                      forces,
                      first_atom_num,
                      second_atom_num,
                      reduced_site_sym):
        positions = self._positions.copy() - self._positions[first_atom_num]
        rot_map_syms = get_positions_sent_by_rot_inv(positions,
                                                     reduced_site_sym,
                                                     self._symprec)

        sym_cart = None
        rot_atom_map = None
        for i, sym in enumerate(reduced_site_sym):
            if disps[rot_map_syms[i, second_atom_num]] is not None:
                sym_cart = similarity_transformation(self._lattice, sym)
                rot_atom_map = rot_map_syms[i, :]
                break

        assert sym_cart is not None, "Something is wrong."

        forces[second_atom_num] = []
        disps[second_atom_num] = []
        for i in range(self._num_atom):
            forces_2 = [
                np.dot(f[rot_atom_map], sym_cart.T)
                for f in forces[rot_atom_map[second_atom_num]][rot_atom_map[i]]]
            disps_2 = [
                [d3[0], np.dot(sym_cart, d3[1]), np.dot(sym_cart, d3[2])]
                for d3 in disps[rot_atom_map[second_atom_num]][rot_atom_map[i]]]

            forces[second_atom_num].append(forces_2)
            disps[second_atom_num].append(disps_2)
Пример #21
0
    def _distribute_3(self,
                      disps_3,
                      forces_3,
                      second_atom_num,
                      third_atom_num,
                      reduced_bond_sym):
        positions = self._positions.copy() - self._positions[second_atom_num]
        rot_map_syms = get_positions_sent_by_rot_inv(positions,
                                                     reduced_bond_sym,
                                                     self._symprec)

        sym_cart = None
        rot_atom_map = None
        for i, sym in enumerate(reduced_bond_sym):
            if disps_3[rot_map_syms[i, third_atom_num]] is not None:
                sym_cart = similarity_transformation(self._lattice, sym)
                rot_atom_map = rot_map_syms[i, :]
                break

        assert sym_cart is not None, "Something is wrong."

        forces = [np.dot(f[rot_atom_map], sym_cart.T)
                  for f in forces_3[rot_atom_map[third_atom_num]]]
        disps = [[d3[0], d3[1], np.dot(sym_cart, d3[2])]
                 for d3 in disps_3[rot_atom_map[third_atom_num]]]

        disps_3[third_atom_num] = disps
        forces_3[third_atom_num] = forces
Пример #22
0
    def _create_displacement_matrix(self, disp_pairs, site_symmetry,
                                    rot_atom_map):
        rot_disp1s = []
        rot_disp2s = []
        rot_pair12 = []
        rot_pair21 = []
        rot_pair11 = []
        rot_pair22 = []

        for disp_pairs_u1 in disp_pairs:
            for rot_atom_num, ssym in zip(rot_atom_map, site_symmetry):
                ssym_c = similarity_transformation(self._lattice, ssym)
                for (u1, u2) in disp_pairs_u1[rot_atom_num]:
                    Su1 = np.dot(ssym_c, u1)
                    Su2 = np.dot(ssym_c, u2)
                    rot_disp1s.append(Su1)
                    rot_disp2s.append(Su2)
                    rot_pair12.append(np.outer(Su1, Su2).flatten() / 2)
                    rot_pair21.append(np.outer(Su2, Su1).flatten() / 2)
                    rot_pair11.append(np.outer(Su1, Su1).flatten() / 2)
                    rot_pair22.append(np.outer(Su2, Su2).flatten() / 2)

        ones = np.ones(len(rot_disp1s)).reshape((-1, 1))

        return np.hstack((ones, rot_disp1s, rot_disp2s, rot_pair12, rot_pair21,
                          rot_pair11, rot_pair22))
Пример #23
0
def get_born_OUTCAR(
    poscar_filename="POSCAR",
    outcar_filename="OUTCAR",
    primitive_axis=np.eye(3),
    supercell_matrix=np.eye(3, dtype="intc"),
    is_symmetry=True,
    symmetrize_tensors=False,
    symprec=1e-5,
):
    ucell = read_vasp(poscar_filename)
    outcar = open(outcar_filename)

    borns, epsilon = _read_born_and_epsilon(outcar)
    num_atom = len(borns)
    assert num_atom == ucell.get_number_of_atoms()

    if symmetrize_tensors:
        lattice = ucell.get_cell().T
        positions = ucell.get_scaled_positions()
        u_sym = Symmetry(ucell, is_symmetry=is_symmetry, symprec=symprec)
        point_sym = [similarity_transformation(lattice, r) for r in u_sym.get_pointgroup_operations()]
        epsilon = _symmetrize_tensor(epsilon, point_sym)
        borns = _symmetrize_borns(borns, u_sym, lattice, positions, symprec)

    inv_smat = np.linalg.inv(supercell_matrix)
    scell = get_supercell(ucell, supercell_matrix, symprec=symprec)
    pcell = get_primitive(scell, np.dot(inv_smat, primitive_axis), symprec=symprec)
    p2s = np.array(pcell.get_primitive_to_supercell_map(), dtype="intc")
    p_sym = Symmetry(pcell, is_symmetry=is_symmetry, symprec=symprec)
    s_indep_atoms = p2s[p_sym.get_independent_atoms()]
    u2u = scell.get_unitcell_to_unitcell_map()
    u_indep_atoms = [u2u[x] for x in s_indep_atoms]
    reduced_borns = borns[u_indep_atoms].copy()

    return reduced_borns, epsilon
Пример #24
0
    def _copy_dataset_2nd(self, second_atom_num, set_of_disps, sets_of_forces,
                          unique_second_atom_nums, reduced_site_sym,
                          rot_map_syms):
        sym_cart = None
        rot_atom_map = None
        for i, sym in enumerate(reduced_site_sym):
            if rot_map_syms[i, second_atom_num] in unique_second_atom_nums:
                sym_cart = similarity_transformation(self._lattice, sym)
                rot_atom_map = rot_map_syms[i, :]
                break

        assert sym_cart is not None, "Something is wrong."

        forces = []
        disps = []

        for set_of_forces_orig in sets_of_forces[
                rot_atom_map[second_atom_num]]:
            forces.append(np.dot(set_of_forces_orig[rot_atom_map], sym_cart.T))

        disps = [
            np.dot(sym_cart, d)
            for d in set_of_disps[rot_atom_map[second_atom_num]]
        ]

        return forces, disps
Пример #25
0
    def get_gv_by_sr0_at_stars(self, s,i,t):
        deg_sets = degenerate_sets(self._frequencies[i])
        grid_point = self._grid_points[i]
        orig_address = self._grid_address[grid_point]
        rotations=get_rotations_for_star(orig_address, self._mesh, self._kpoint_operations)
        # self._get_group_veclocities_at_star(i, gv)
        gv_by_F_tensor = []
        rec_lat = np.linalg.inv(self._primitive.get_cell())
        rotations_cartesian = [similarity_transformation(rec_lat, r)
                               for r in rotations]
        for rot_c in rotations_cartesian:
            gvs_rot = np.dot(rot_c, self._gv[i].T).T
            F_rot = np.dot(rot_c, self._F0[s,i,t].T).T

            # Take average of group veclocities of degenerate phonon modes
            # and then calculate gv x gv to preserve symmetry
            gvs = np.zeros_like(gvs_rot)
            Fs = np.zeros_like(F_rot)
            for deg in deg_sets:
                gv_ave = gvs_rot[deg].sum(axis=0) / len(deg)
                F_ave = F_rot[deg].sum(axis=0)/len(deg)
                for j in deg:
                    gvs[j] = gv_ave
                    Fs[j]=F_ave
            gv_by_F_tensor.append([np.outer(gvs[b], Fs[b]) for b in range(len(gvs))])

        return np.array(gv_by_F_tensor)
Пример #26
0
    def _create_displacement_matrix(self,
                                    disp_pairs,
                                    site_symmetry,
                                    rot_atom_map):
        rot_disp1s = []
        rot_disp2s = []
        rot_pair12 = []
        rot_pair21 = []
        rot_pair11 = []
        rot_pair22 = []

        for disp_pairs_u1 in disp_pairs:
            for rot_atom_num, ssym in zip(rot_atom_map, site_symmetry):
                ssym_c = similarity_transformation(self._lattice, ssym)
                for (u1, u2) in disp_pairs_u1[rot_atom_num]:
                    Su1 = np.dot(ssym_c, u1)
                    Su2 = np.dot(ssym_c, u2)
                    rot_disp1s.append(Su1)
                    rot_disp2s.append(Su2)
                    rot_pair12.append(np.outer(Su1, Su2).flatten() / 2)
                    rot_pair21.append(np.outer(Su2, Su1).flatten() / 2)
                    rot_pair11.append(np.outer(Su1, Su1).flatten() / 2)
                    rot_pair22.append(np.outer(Su2, Su2).flatten() / 2)
    
        ones = np.ones(len(rot_disp1s)).reshape((-1, 1))

        return np.hstack((ones, rot_disp1s, rot_disp2s,
                          rot_pair12, rot_pair21, rot_pair11, rot_pair22))
Пример #27
0
    def _copy_dataset_2nd(self,
                          second_atom_num,
                          set_of_disps,
                          sets_of_forces,
                          unique_second_atom_nums,
                          reduced_site_sym,
                          rot_map_syms):
        sym_cart = None
        rot_atom_map = None
        for i, sym in enumerate(reduced_site_sym):
            if rot_map_syms[i, second_atom_num] in unique_second_atom_nums:
                sym_cart = similarity_transformation(self._lattice, sym)
                rot_atom_map = rot_map_syms[i, :]
                break

        assert sym_cart is not None, "Something is wrong."

        forces = []
        disps = []

        for set_of_forces_orig in sets_of_forces[rot_atom_map[second_atom_num]]:
            forces.append(np.dot(set_of_forces_orig[rot_atom_map], sym_cart.T))

        disps = [np.dot(sym_cart, d)
                 for d in set_of_disps[rot_atom_map[second_atom_num]]]

        return forces, disps
Пример #28
0
def _get_rotated_fc2s(i, j, fc2s, rot_map_syms, site_sym_cart):
    rotated_fc2s = []
    for fc2 in fc2s:
        for sym, map_sym in zip(site_sym_cart, rot_map_syms):
            fc2_rot = fc2[map_sym[i], map_sym[j]]
            rotated_fc2s.append(similarity_transformation(sym, fc2_rot))
    return np.reshape(rotated_fc2s, (-1, 9))
Пример #29
0
    def _symmetrize_group_velocity_matrix(self, gvm, q):
        """Symmetrize obtained group velocity matrices.

        The following symmetries are applied:
            1. site symmetries
            2. band hermicity

        """
        # site symmetries
        rotations = []
        for r in self._symmetry.reciprocal_operations:
            q_in_BZ = q - np.rint(q)
            diff = q_in_BZ - np.dot(r, q_in_BZ)
            if (np.abs(diff) < self._symmetry.tolerance).all():
                rotations.append(r)

        gvm_sym = np.zeros_like(gvm)
        for r in rotations:
            r_cart = similarity_transformation(self._reciprocal_lattice, r)
            gvm_sym += np.einsum("ij,jkl->ikl", r_cart, gvm)
        gvm_sym = gvm_sym / len(rotations)

        # band hermicity
        gvm_sym = (gvm_sym + gvm_sym.transpose(0, 2, 1).conj()) / 2

        return gvm_sym
Пример #30
0
def get_born_parameters(f, primitive, is_symmetry):
    # Read unit conversion factor, damping factor, ...
    factors = [float(x) for x in f.readline().split()]
    if len(factors) < 1:
        print "BORN file format of line 1 is incorrect"
        return False
    if len(factors) < 2:
        factors = factors[0]

    # Read dielectric constant
    line = f.readline().split()
    if not len(line) == 9:
        print "BORN file format of line 2 is incorrect"
        return False
    dielectric = np.reshape([float(x) for x in line], (3, 3))

    # Read Born effective charge
    symmetry = Symmetry(primitive, is_symmetry=is_symmetry)
    independent_atoms = symmetry.get_independent_atoms()
    born = np.zeros((primitive.get_number_of_atoms(), 3, 3), dtype=float)

    for i in independent_atoms:
        line = f.readline().split()
        if len(line) == 0:
            print "Number of lines for Born effect charge is not enough."
            return False
        if not len(line) == 9:
            print "BORN file format of line %d is incorrect" % (i + 3)
            return False
        born[i] = np.reshape([float(x) for x in line], (3, 3))

    # Expand Born effective charges to all atoms in the primitive cell
    rotations = symmetry.get_symmetry_operations()['rotations']
    map_operations = symmetry.get_map_operations()
    map_atoms = symmetry.get_map_atoms()

    for i in range(primitive.get_number_of_atoms()):
        # R_cart = L R L^-1
        rot_cartesian = similarity_transformation(
            primitive.get_cell().transpose(), rotations[map_operations[i]])
        # R_cart^T B R_cart^-T (inverse rotation is required to transform)
        born[i] = similarity_transformation(rot_cartesian.transpose(),
                                            born[map_atoms[i]])

    non_anal = {'born': born, 'factor': factors, 'dielectric': dielectric}

    return non_anal
Пример #31
0
def distribute_fc3(fc3,
                   first_disp_atoms,
                   lattice,
                   positions,
                   rotations,
                   translations,
                   symprec,
                   verbose):
    num_atom = len(positions)

    for i in range(num_atom):
        if i in first_disp_atoms:
            continue

        for atom_index_done in first_disp_atoms:
            rot_num = get_atom_mapping_by_symmetry(positions,
                                                   i,
                                                   atom_index_done,
                                                   rotations,
                                                   translations,
                                                   symprec)
            if rot_num > -1:
                i_rot = atom_index_done
                rot = rotations[rot_num]
                trans = translations[rot_num]
                break

        if rot_num < 0:
            print "Position or symmetry may be wrong."
            raise ValueError

        if verbose > 2:
            print "  [ %d, x, x ] to [ %d, x, x ]" % (i_rot + 1, i + 1)
            sys.stdout.flush()

        atom_mapping = np.zeros(num_atom, dtype='intc')
        for j in range(num_atom):
            atom_mapping[j] = get_atom_by_symmetry(positions,
                                                   rot,
                                                   trans,
                                                   j,
                                                   symprec)
        rot_cart_inv = np.double(
            similarity_transformation(lattice, rot).T.copy())

        try:
            import anharmonic._phono3py as phono3c
            phono3c.distribute_fc3(fc3,
                                   i,
                                   atom_mapping,
                                   rot_cart_inv)
        
        except ImportError:
            for j in range(num_atom):
                j_rot = atom_mapping[j]
                for k in range(num_atom):
                    k_rot = atom_mapping[k]
                    fc3[i, j, k] = third_rank_tensor_rotation(
                        rot_cart_inv, fc3[i_rot, j_rot, k_rot])
Пример #32
0
def distribute_fc3(
    fc3_least_atoms,
    first_disp_atoms,
    lattice,
    positions,
    rotations,
    translations,
    symprec,
    overwrite=True,
    verbose=False,
):
    num_atom = len(positions)
    atom_mapping = np.zeros(num_atom, dtype="intc")

    if overwrite:
        fc3 = fc3_least_atoms
    else:
        fc3 = np.zeros((num_atom, num_atom, num_atom, 3, 3, 3), dtype="double")

    for i in range(num_atom):
        # if i in first_disp_atoms:
        #     continue

        for atom_index_done in first_disp_atoms:
            rot_num = get_atom_mapping_by_symmetry(positions, i, atom_index_done, rotations, translations, symprec)
            if rot_num > -1:
                i_rot = atom_index_done
                rot = rotations[rot_num]
                trans = translations[rot_num]
                break

        if rot_num < 0:
            print "Position or symmetry may be wrong."
            raise ValueError

        for j in range(num_atom):
            atom_mapping[j] = get_atom_by_symmetry(positions, rot, trans, j, symprec)

        rot_cart_inv = np.array(similarity_transformation(lattice, rot).T, dtype="double", order="C")

        if not (overwrite and i == i_rot):
            if verbose > 2:
                print "    [ %d, x, x ] to [ %d, x, x ]" % (i_rot + 1, i + 1)
                sys.stdout.flush()

            try:
                import anharmonic._phono3py as phono3c

                phono3c.distribute_fc3(fc3, fc3_least_atoms, i, atom_mapping, rot_cart_inv)

            except ImportError:
                for j in range(num_atom):
                    j_rot = atom_mapping[j]
                    for k in range(num_atom):
                        k_rot = atom_mapping[k]
                        fc3[i, j, k] = third_rank_tensor_rotation(rot_cart_inv, fc3_least_atoms[i_rot, j_rot, k_rot])

    if not overwrite:
        return fc3
Пример #33
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
Пример #34
0
    def _transform_rotations(self, tmat, rotations):
        trans_rots = []

        for r in rotations:
            r_conv = similarity_transformation(np.linalg.inv(tmat), r)
            trans_rots.append(np.rint(r_conv).astype(int))

        return np.array(trans_rots)
Пример #35
0
def _get_rotated_fc2s(i, j, fc2s, rot_map_syms, site_sym_cart):
    num_sym = len(site_sym_cart)
    rotated_fc2s = []
    for fc2 in fc2s:
        for sym, map_sym in zip(site_sym_cart, rot_map_syms):
            fc2_rot = fc2[map_sym[i], map_sym[j]]
            rotated_fc2s.append(similarity_transformation(sym, fc2_rot))
    return np.reshape(rotated_fc2s, (-1, 9))
Пример #36
0
def symmetrize_borns(borns,
                     rotations,
                     translations,
                     lattice,
                     positions,
                     symprec):
    borns_orig = borns.copy()
    for i, Z in enumerate(borns):
        site_sym = get_site_symmetry(i,
                                     lattice,
                                     positions,
                                     rotations,
                                     translations,
                                     symprec)
        Z = symmetrize_2nd_rank_tensor(Z, site_sym, lattice)

    borns_copy = np.zeros_like(borns)
    for i in range(len(borns)):
        count = 0
        for r, t in zip(rotations, translations):
            count += 1
            diff = np.dot(positions, r.T) + t - positions[i]
            diff -= np.rint(diff)
            dist = np.sqrt(np.sum(np.dot(diff, lattice) ** 2, axis=1))
            j = np.nonzero(dist < symprec)[0][0]
            r_cart = similarity_transformation(lattice.T, r)
            borns_copy[i] += similarity_transformation(r_cart, borns[j])
        borns_copy[i] /= count

    borns = borns_copy
    sum_born = borns.sum(axis=0) / len(borns)
    borns -= sum_born

    if (np.abs(borns_orig - borns) > 0.1).any():
        sys.stderr.write(
            "Born effective charge symmetrization might go wrong.\n")

        sys.stderr.write("Sum of Born charges:\n")
        sys.stderr.write(str(borns_orig.sum(axis=0)))
        sys.stderr.write("\n")

        # for b_o, b in zip(borns_orig, borns):
        #     sys.stderr.write(str(b - b_o))
        #     sys.stderr.write("\n")

    return borns
Пример #37
0
    def _transform_rotations(self, tmat, rotations):
        trans_rots = []

        for r in rotations:
            r_conv = similarity_transformation(np.linalg.inv(tmat), r)
            trans_rots.append(np.rint(r_conv).astype(int))

        return np.array(trans_rots)
Пример #38
0
    def _fit(self, first_atom_num, disp_triplets, sets_of_forces):
        site_symmetry = self._symmetry.get_site_symmetry(first_atom_num)
        positions = self._positions.copy() - self._positions[first_atom_num]
        rot_map_syms = get_positions_sent_by_rot_inv(positions,
                                                     site_symmetry,
                                                     self._symprec)
        site_syms_cart = np.array([similarity_transformation(self._lattice, sym)
                                   for sym in site_symmetry],
                                  dtype='double')

        (disp_triplets_rearranged,
         num_triplets) = self._create_displacement_triplets_for_c(disp_triplets)
        max_num_disp = np.amax(num_triplets[:, :, :, 1])

        for second_atom_num in range(self._num_atom):
            print second_atom_num + 1

            rot_disps_set = []
            for third_atom_num in range(self._num_atom):
                try:
                    import anharmonic._forcefit as forcefit
                    rot_disps_set.append(self._create_displacement_matrix_c(
                            second_atom_num,
                            third_atom_num,
                            disp_triplets_rearranged,
                            num_triplets,
                            site_syms_cart,
                            rot_map_syms,
                            max_num_disp))
                except ImportError:
                    rot_disps_set.append(self._create_displacement_matrix(
                            second_atom_num,
                            third_atom_num,
                            disp_triplets,
                            site_syms_cart,
                            rot_map_syms))
                    
                print third_atom_num + 1, rot_disps_set[third_atom_num].shape

            inv_disps_set = self._invert_displacements(rot_disps_set)

            for third_atom_num in range(self._num_atom):
                rot_forces = self._create_force_matrix(
                    second_atom_num,
                    third_atom_num,
                    sets_of_forces,
                    site_syms_cart,
                    rot_map_syms)

                fc = self._solve(inv_disps_set[third_atom_num], rot_forces)

                # For elements with index exchange symmetry 
                fc2 = fc[:, 7:10, :].reshape((self._num_atom, 3, 3))
                fc3 = fc[:, 46:55, :].reshape((self._num_atom, 3, 3, 3))
                fc4 = fc[:, 172:199, :].reshape((self._num_atom, 3, 3, 3, 3))
                self._fc2[third_atom_num] = fc2
                self._fc3[second_atom_num, third_atom_num] = fc3
                self._fc4[first_atom_num, second_atom_num, third_atom_num] = fc4
Пример #39
0
def _take_average_of_borns(borns, rotations, translations, cell, symprec):
    lattice = cell.cell
    positions = cell.scaled_positions
    borns_ = np.zeros_like(borns)
    for i in range(len(borns)):
        for r, t in zip(rotations, translations):
            diff = np.dot(positions, r.T) + t - positions[i]
            diff -= np.rint(diff)
            dist = np.sqrt(np.sum(np.dot(diff, lattice)**2, axis=1))
            j = np.nonzero(dist < symprec)[0][0]
            r_cart = similarity_transformation(lattice.T, r)
            borns_[i] += similarity_transformation(r_cart, borns[j])
        borns_[i] /= len(rotations)

    sum_born = borns_.sum(axis=0) / len(borns_)
    borns_ -= sum_born

    return borns_
Пример #40
0
def solve_fc3(fc3,
              first_atom_num,
              supercell,
              site_symmetry,
              displacements_first,
              delta_fc2s,
              symprec,
              pinv="numpy",
              verbose=False):

    if verbose:
        text = "Solving fc3[ %d, x, x ] with " % (first_atom_num + 1)
        if len(displacements_first) > 1:
            text += "displacements:"
        else:
            text += "a displacement:"
        print(text)
        for i, v in enumerate(displacements_first):
            print("    [%7.4f %7.4f %7.4f]" % tuple(v))
            sys.stdout.flush()
        if verbose > 2:
            print("  Site symmetry:")
            for i, v in enumerate(site_symmetry):
                print("    [%2d %2d %2d] #%2d" % tuple(list(v[0]) + [i + 1]))
                print("    [%2d %2d %2d]" % tuple(v[1]))
                print("    [%2d %2d %2d]\n" % tuple(v[2]))
                sys.stdout.flush()

    lattice = supercell.get_cell().T
    site_sym_cart = [
        similarity_transformation(lattice, sym) for sym in site_symmetry
    ]
    num_atom = supercell.get_number_of_atoms()
    positions = supercell.get_scaled_positions()
    pos_center = positions[first_atom_num].copy()
    positions -= pos_center
    rot_map_syms = get_positions_sent_by_rot_inv(positions, site_symmetry,
                                                 symprec)

    rot_disps = get_rotated_displacement(displacements_first, site_sym_cart)

    if pinv == "numpy":
        inv_U = np.linalg.pinv(rot_disps)
    else:
        try:
            import phonopy._lapackepy as lapackepy
            inv_U = np.zeros((rot_disps.shape[1], rot_disps.shape[0]),
                             dtype='double')
            lapackepy.pinv(inv_U, rot_disps, 1e-13)
        except ImportError:
            inv_U = np.linalg.pinv(rot_disps)

    for (i, j) in list(np.ndindex(num_atom, num_atom)):
        fc3[first_atom_num, i, j] = np.dot(
            inv_U,
            _get_rotated_fc2s(i, j, delta_fc2s, rot_map_syms,
                              site_sym_cart)).reshape(3, 3, 3)
Пример #41
0
def solve_fc3(fc3,
              first_atom_num,
              supercell,
              site_symmetry,
              displacements_first,
              delta_fc2s,
              symprec,
              pinv="numpy",
              verbose=False):

    if verbose:
        text = "Solving fc3[ %d, x, x ] with " % (first_atom_num + 1)
        if len(displacements_first) > 1:
            text += "displacements:"
        else:
            text += "a displacement:"
        print(text)
        for i, v in enumerate(displacements_first):
            print("    [%7.4f %7.4f %7.4f]" % tuple(v))
            sys.stdout.flush()
        if verbose > 2:
            print("  Site symmetry:")
            for i, v in enumerate(site_symmetry):
                print("    [%2d %2d %2d] #%2d" % tuple(list(v[0])+[i + 1]))
                print("    [%2d %2d %2d]" % tuple(v[1]))
                print("    [%2d %2d %2d]\n" % tuple(v[2]))
                sys.stdout.flush()

    lattice = supercell.get_cell().T
    site_sym_cart = [similarity_transformation(lattice, sym)
                     for sym in site_symmetry]
    num_atom = supercell.get_number_of_atoms()
    positions = supercell.get_scaled_positions()
    pos_center = positions[first_atom_num].copy()
    positions -= pos_center
    rot_map_syms = get_positions_sent_by_rot_inv(positions,
                                                 site_symmetry,
                                                 symprec)

    rot_disps = get_rotated_displacement(displacements_first, site_sym_cart)

    if pinv == "numpy":
        inv_U = np.linalg.pinv(rot_disps)
    else:
        try:
            import phonopy._lapackepy as lapackepy
            inv_U = np.zeros((rot_disps.shape[1], rot_disps.shape[0]),
                             dtype='double')
            lapackepy.pinv(inv_U, rot_disps, 1e-13)
        except ImportError:
            inv_U = np.linalg.pinv(rot_disps)

    for (i, j) in list(np.ndindex(num_atom, num_atom)):
        fc3[first_atom_num, i, j] = np.dot(inv_U, _get_rotated_fc2s(
                i, j, delta_fc2s, rot_map_syms, site_sym_cart)).reshape(3, 3, 3)
Пример #42
0
    def _fit(self, first_atom_num, disp_triplets, sets_of_forces):
        site_symmetry = self._symmetry.get_site_symmetry(first_atom_num)
        positions = self._positions.copy() - self._positions[first_atom_num]
        rot_map_syms = get_positions_sent_by_rot_inv(self._lattice, positions,
                                                     site_symmetry,
                                                     self._symprec)
        site_syms_cart = np.array([
            similarity_transformation(self._lattice, sym)
            for sym in site_symmetry
        ],
                                  dtype='double')

        (disp_triplets_rearranged, num_triplets
         ) = self._create_displacement_triplets_for_c(disp_triplets)
        max_num_disp = np.amax(num_triplets[:, :, :, 1])

        for second_atom_num in range(self._num_atom):
            print second_atom_num + 1

            rot_disps_set = []
            for third_atom_num in range(self._num_atom):
                try:
                    import anharmonic._forcefit as forcefit
                    rot_disps_set.append(
                        self._create_displacement_matrix_c(
                            second_atom_num, third_atom_num,
                            disp_triplets_rearranged, num_triplets,
                            site_syms_cart, rot_map_syms, max_num_disp))
                except ImportError:
                    rot_disps_set.append(
                        self._create_displacement_matrix(
                            second_atom_num, third_atom_num, disp_triplets,
                            site_syms_cart, rot_map_syms))

                print third_atom_num + 1, rot_disps_set[third_atom_num].shape

            inv_disps_set = self._invert_displacements(rot_disps_set)

            for third_atom_num in range(self._num_atom):
                rot_forces = self._create_force_matrix(second_atom_num,
                                                       third_atom_num,
                                                       sets_of_forces,
                                                       site_syms_cart,
                                                       rot_map_syms)

                fc = self._solve(inv_disps_set[third_atom_num], rot_forces)

                # For elements with index exchange symmetry
                fc2 = fc[:, 7:10, :].reshape((self._num_atom, 3, 3))
                fc3 = fc[:, 46:55, :].reshape((self._num_atom, 3, 3, 3))
                fc4 = fc[:, 172:199, :].reshape((self._num_atom, 3, 3, 3, 3))
                self._fc2[third_atom_num] = fc2
                self._fc3[second_atom_num, third_atom_num] = fc3
                self._fc4[first_atom_num, second_atom_num,
                          third_atom_num] = fc4
Пример #43
0
    def _get_ground_matrix(self):
        matrices = []

        for (r, t) in zip(self._rotations_at_q, self._translations_at_q):

            lat = self._primitive.get_cell().T
            r_cart = similarity_transformation(lat, r)

            perm_mat = self._get_modified_permutation_matrix(r, t)
            matrices.append(np.kron(perm_mat, r_cart))

        return np.array(matrices)
Пример #44
0
    def __init__(self,
                 interaction,
                 point_operations=None,
                 ir_grid_points=None,
                 rot_grid_points=None,
                 temperature=None,
                 sigma=None,
                 is_reducible_collision_matrix=False,
                 log_level=0,
                 lang='C'):
        self._pp = None
        self._sigma = None
        self._frequency_points = None
        self._temperature = None
        self._grid_point = None
        self._lang = None
        self._imag_self_energy = None
        self._collision_matrix = None
        self._pp_strength = None
        self._frequencies = None
        self._triplets_at_q = None
        self._triplets_map_at_q = None
        self._weights_at_q = None
        self._band_indices = None
        self._unit_conversion = None
        self._cutoff_frequency = None
        self._g = None
        self._mesh = None
        self._is_collision_matrix = None
        self._unit_conversion = None
        self._log_level = log_level

        ImagSelfEnergy.__init__(self,
                                interaction,
                                temperature=temperature,
                                sigma=sigma,
                                lang=lang)

        self._is_reducible_collision_matrix = is_reducible_collision_matrix
        self._is_collision_matrix = True

        if not self._is_reducible_collision_matrix:
            self._ir_grid_points = ir_grid_points
            self._rot_grid_points = rot_grid_points
            self._point_operations = point_operations
            self._primitive = self._pp.get_primitive()
            rec_lat = np.linalg.inv(self._primitive.get_cell())
            self._rotations_cartesian = np.array([
                similarity_transformation(rec_lat, r)
                for r in self._point_operations
            ],
                                                 dtype='double',
                                                 order='C')
Пример #45
0
    def _get_ground_matrix(self):
        matrices = []
        
        for (r, t) in zip(self._rotations_at_q,
                          self._translations_at_q):
    
            lat = self._primitive.get_cell().T
            r_cart = similarity_transformation(lat, r)
    
            perm_mat = self._get_modified_permutation_matrix(r, t)
            matrices.append(np.kron(perm_mat, r_cart))

        return np.array(matrices)
Пример #46
0
    def _symmetrize_group_velocity(self, gv, q):
        rotations = []
        for r in self._symmetry.get_reciprocal_operations():
            q_in_BZ = q - np.rint(q)
            diff = q_in_BZ - np.dot(r, q_in_BZ)
            if (np.abs(diff) < self._symmetry.get_symmetry_tolerance()).all():
                rotations.append(r)

        gv_sym = np.zeros_like(gv)
        for r in rotations:
            r_cart = similarity_transformation(self._reciprocal_lattice, r)
            gv_sym += np.dot(r_cart, gv.T).T
        return gv_sym / len(rotations)
Пример #47
0
    def _symmetrize_group_velocity(self, gv, q):
        rotations = []
        for r in self._symmetry.get_reciprocal_operations():
            q_in_BZ = q - np.rint(q)
            diff = q_in_BZ - np.dot(r, q_in_BZ)
            if (np.abs(diff) < self._symmetry.get_symmetry_tolerance()).all():
                rotations.append(r)

        gv_sym = np.zeros_like(gv)
        for r in rotations:
            r_cart = similarity_transformation(self._reciprocal_lattice, r)
            gv_sym += np.dot(r_cart, gv.T).T

        return gv_sym / len(rotations)
Пример #48
0
    def _set_kappa(self, i_sigma, i_temp, X):
        num_band = self._primitive.get_number_of_atoms() * 3

        if self._is_reducible_collision_matrix:
            num_mesh_points = np.prod(self._mesh)
            num_grid_points = num_mesh_points
            from phonopy.harmonic.force_constants import similarity_transformation
            point_operations = self._symmetry.get_reciprocal_operations()
            rec_lat = np.linalg.inv(self._primitive.get_cell())
            rotations_cartesian = np.array(
                [similarity_transformation(rec_lat, r)
                 for r in point_operations], dtype='double')
            inv_col_mat = np.kron(
                self._collision_matrix[i_sigma, i_temp].reshape(
                    num_mesh_points * num_band,
                    num_mesh_points * num_band), np.eye(3))
        else:
            num_ir_grid_points = len(self._ir_grid_points)
            num_grid_points = num_ir_grid_points
            rotations_cartesian = self._rotations_cartesian
            inv_col_mat = self._collision_matrix[i_sigma, i_temp].reshape(
                num_ir_grid_points * num_band * 3,
                num_ir_grid_points * num_band * 3)

        Y = np.dot(inv_col_mat, X.ravel()).reshape(-1, 3)

        for i, (v_gp, f_gp) in enumerate(zip(X.reshape(num_grid_points,
                                                       num_band, 3),
                                             Y.reshape(num_grid_points,
                                                       num_band, 3))):
            for j, (v, f) in enumerate(zip(v_gp, f_gp)):
                sum_k = np.zeros((3, 3), dtype='double')
                for r in rotations_cartesian:
                    sum_k += np.outer(np.dot(r, v), np.dot(r, f))
                sum_k = sum_k + sum_k.T
                for k, vxf in enumerate(
                        ((0, 0), (1, 1), (2, 2), (1, 2), (0, 2), (0, 1))):
                    self._mode_kappa[i_sigma, i_temp, i, j, k] = sum_k[vxf]

        t = self._temperatures[i_temp]
        self._mode_kappa *= (self._conversion_factor * Kb * t ** 2
                             / np.prod(self._mesh))
        
        if self._is_reducible_collision_matrix:
            self._mode_kappa /= len(point_operations)
        
        self._kappa[i_sigma, i_temp] = (
            self._mode_kappa[i_sigma, i_temp].sum(axis=0).sum(axis=0))
Пример #49
0
    def __init__(self,
                 interaction,
                 point_operations=None,
                 ir_grid_points=None,
                 rotated_grid_points=None,
                 temperature=None,
                 sigma=None,
                 is_reducible_collision_matrix=False,
                 lang='C'):
        self._pp = None
        self._sigma = None
        self._frequency_points = None
        self._temperature = None
        self._grid_point = None
        self._lang = None
        self._imag_self_energy = None
        self._collision_matrix = None
        self._pp_strength = None
        self._frequencies = None
        self._triplets_at_q = None
        self._triplets_map_at_q = None
        self._weights_at_q = None
        self._band_indices = None
        self._unit_conversion = None
        self._cutoff_frequency = None
        self._g = None
        self._mesh = None
        self._is_collision_matrix = None
        self._unit_conversion = None
        
        ImagSelfEnergy.__init__(self,
                                interaction,
                                temperature=temperature,
                                sigma=sigma,
                                lang=lang)

        self._is_reducible_collision_matrix = is_reducible_collision_matrix
        self._is_collision_matrix = True

        if not self._is_reducible_collision_matrix:
            self._ir_grid_points = ir_grid_points
            self._rot_grid_points = rotated_grid_points
            self._point_operations = point_operations
            self._primitive = self._pp.get_primitive()
            rec_lat = np.linalg.inv(self._primitive.get_cell())
            self._rotations_cartesian = np.array(
                [similarity_transformation(rec_lat, r)
                 for r in self._point_operations], dtype='double', order='C')
Пример #50
0
    def _set_kappa(self, i_sigma, i_temp, X):
        num_band = self._primitive.get_number_of_atoms() * 3

        if self._is_reducible_collision_matrix:
            num_mesh_points = np.prod(self._mesh)
            num_grid_points = num_mesh_points
            from phonopy.harmonic.force_constants import similarity_transformation
            point_operations = self._symmetry.get_reciprocal_operations()
            rec_lat = np.linalg.inv(self._primitive.get_cell())
            rotations_cartesian = np.array(
                [similarity_transformation(rec_lat, r)
                 for r in point_operations], dtype='double')
            inv_col_mat = np.kron(
                self._collision_matrix[i_sigma, i_temp].reshape(
                    num_mesh_points * num_band,
                    num_mesh_points * num_band), np.eye(3))
        else:
            num_ir_grid_points = len(self._ir_grid_points)
            num_grid_points = num_ir_grid_points
            rotations_cartesian = self._rotations_cartesian
            inv_col_mat = self._collision_matrix[i_sigma, i_temp].reshape(
                num_ir_grid_points * num_band * 3,
                num_ir_grid_points * num_band * 3)

        Y = np.dot(inv_col_mat, X.ravel()).reshape(-1, 3)

        for i, (v_gp, f_gp) in enumerate(zip(X.reshape(num_grid_points,
                                                       num_band, 3),
                                             Y.reshape(num_grid_points,
                                                       num_band, 3))):
            for j, (v, f) in enumerate(zip(v_gp, f_gp)):
                sum_k = np.zeros((3, 3), dtype='double')
                for r in rotations_cartesian:
                    sum_k += np.outer(np.dot(r, v), np.dot(r, f))
                sum_k = sum_k + sum_k.T
                for k, vxf in enumerate(
                        ((0, 0), (1, 1), (2, 2), (1, 2), (0, 2), (0, 1))):
                    self._mode_kappa[i_sigma, i_temp, i, j, k] = sum_k[vxf]

        t = self._temperatures[i_temp]
        self._mode_kappa *= (self._conversion_factor * Kb * t ** 2
                             / np.prod(self._mesh))
        
        if self._is_reducible_collision_matrix:
            self._mode_kappa /= len(point_operations)
        
        self._kappa[i_sigma, i_temp] = (
            self._mode_kappa[i_sigma, i_temp].sum(axis=0).sum(axis=0))
Пример #51
0
    def _get_matrices(self, first_atom_num):
        disps = []
        sets_of_forces = []
        for dataset_1st in self._dataset["first_atoms"]:
            if first_atom_num != dataset_1st["number"]:
                continue
            disps.append(dataset_1st["displacement"])
            sets_of_forces.append(dataset_1st["forces"])

        site_symmetry = self._symmetry.get_site_symmetry(first_atom_num)
        positions = self._positions.copy() - self._positions[first_atom_num]
        rot_map_syms = get_positions_sent_by_rot_inv(positions, site_symmetry, self._symprec)
        site_sym_cart = [similarity_transformation(self._lattice, sym) for sym in site_symmetry]
        rot_disps = self._create_displacement_matrix(disps, site_sym_cart)
        rot_forces = self._create_force_matrix(sets_of_forces, site_sym_cart, rot_map_syms)
        return rot_disps, rot_forces
Пример #52
0
def can_use_std_lattice(conv_lat, tmat, std_lattice, rotations, symprec=1e-5):
    """Inspect if std_lattice can be used as conv_lat.

    r_s is the rotation matrix of conv_lat.
    Return if conv_lat rotated by det(r_s)*r_s and std_lattice are equivalent.
    det(r_s) is necessary to make improper rotation to proper rotation.

    """
    for r in rotations:
        r_s = similarity_transformation(tmat, r)
        if np.allclose(
                np.linalg.det(r_s) * np.dot(np.transpose(conv_lat), r_s),
                np.transpose(std_lattice),
                atol=symprec,
        ):
            return True
    return False
Пример #53
0
 def _create_force_matrix(self,
                          sets_of_forces,
                          site_symmetry,
                          rot_atom_map,
                          rot_map_syms):
     site_syms_cart = [similarity_transformation(self._lattice, sym)
                       for sym in site_symmetry]
     force_matrix = []
     for i in range(self._num_atom):
         force_matrix_atom = []
         for sets_of_forces_u1 in sets_of_forces:
             for map_sym, rot_atom_num, sym in zip(
                 rot_map_syms, rot_atom_map, site_syms_cart):
                 for forces in sets_of_forces_u1[rot_atom_num]:
                     force_matrix_atom.append(
                         np.dot(sym, forces[map_sym[i]]))
         force_matrix.append(force_matrix_atom)
     return np.array(force_matrix, dtype='double', order='C')
Пример #54
0
 def _create_force_matrix(self, sets_of_forces, site_symmetry, rot_atom_map,
                          rot_map_syms):
     site_syms_cart = [
         similarity_transformation(self._lattice, sym)
         for sym in site_symmetry
     ]
     force_matrix = []
     for i in range(self._num_atom):
         force_matrix_atom = []
         for sets_of_forces_u1 in sets_of_forces:
             for map_sym, rot_atom_num, sym in zip(rot_map_syms,
                                                   rot_atom_map,
                                                   site_syms_cart):
                 for forces in sets_of_forces_u1[rot_atom_num]:
                     force_matrix_atom.append(
                         np.dot(sym, forces[map_sym[i]]))
         force_matrix.append(force_matrix_atom)
     return np.array(force_matrix, dtype='double', order='C')
Пример #55
0
def get_born_OUTCAR(poscar_filename="POSCAR",
                    outcar_filename="OUTCAR",
                    primitive_matrix=None,
                    supercell_matrix=None,
                    is_symmetry=True,
                    symmetrize_tensors=False,
                    symprec=1e-5):
    if primitive_matrix is None:
        pmat = np.eye(3)
    else:
        pmat = primitive_matrix
    if supercell_matrix is None:
        smat = np.eye(3, dtype='intc')
    else:
        smat = supercell_matrix
    ucell = read_vasp(poscar_filename)
    outcar = open(outcar_filename)

    borns, epsilon = _read_born_and_epsilon(outcar)
    num_atom = len(borns)
    assert num_atom == ucell.get_number_of_atoms()

    if symmetrize_tensors:
        lattice = ucell.get_cell().T
        positions = ucell.get_scaled_positions()
        u_sym = Symmetry(ucell, is_symmetry=is_symmetry, symprec=symprec)
        point_sym = [
            similarity_transformation(lattice, r)
            for r in u_sym.get_pointgroup_operations()
        ]
        epsilon = _symmetrize_tensor(epsilon, point_sym)
        borns = _symmetrize_borns(borns, u_sym, lattice, positions, symprec)

    inv_smat = np.linalg.inv(smat)
    scell = get_supercell(ucell, smat, symprec=symprec)
    pcell = get_primitive(scell, np.dot(inv_smat, pmat), symprec=symprec)
    p2s = np.array(pcell.get_primitive_to_supercell_map(), dtype='intc')
    p_sym = Symmetry(pcell, is_symmetry=is_symmetry, symprec=symprec)
    s_indep_atoms = p2s[p_sym.get_independent_atoms()]
    u2u = scell.get_unitcell_to_unitcell_map()
    u_indep_atoms = [u2u[x] for x in s_indep_atoms]
    reduced_borns = borns[u_indep_atoms].copy()

    return reduced_borns, epsilon, s_indep_atoms
Пример #56
0
 def get_gv_by_gv(self,i):
     deg_sets = degenerate_sets(self._frequency[i])
     orbits, rotations = self._reverse_mapping[i], self._kpt_rotations_at_stars[i]
     # self._get_group_veclocities_at_star(i, gv)
     gv2_tensor = []
     rec_lat = np.linalg.inv(self._cell.get_cell())
     rotations_cartesian = [similarity_transformation(rec_lat, r)
                            for r in rotations]
     for rot_c in rotations_cartesian:
         gvs_rot = np.dot(rot_c, self._gv[i].T).T
         # Take average of group veclocities of degenerate phonon modes
         # and then calculate gv x gv to preserve symmetry
         gvs = np.zeros_like(gvs_rot)
         for deg in deg_sets:
             gv_ave = gvs_rot[deg].sum(axis=0) / len(deg)
             for j in deg:
                 gvs[j] = gv_ave
         gv2_tensor.append([np.outer(gv, gv) for gv in gvs])
     return np.array(gv2_tensor)
Пример #57
0
    def _get_matrices(self, first_atom_num):
        disps = []
        sets_of_forces = []
        for dataset_1st in self._dataset['first_atoms']:
            if first_atom_num != dataset_1st['number']:
                continue
            disps.append(dataset_1st['displacement'])
            sets_of_forces.append(dataset_1st['forces'])

        site_symmetry = self._symmetry.get_site_symmetry(first_atom_num)
        positions = (self._positions.copy() - self._positions[first_atom_num])
        rot_map_syms = get_positions_sent_by_rot_inv(positions, site_symmetry,
                                                     self._symprec)
        site_sym_cart = [
            similarity_transformation(self._lattice, sym)
            for sym in site_symmetry
        ]
        rot_disps = self._create_displacement_matrix(disps, site_sym_cart)
        rot_forces = self._create_force_matrix(sets_of_forces, site_sym_cart,
                                               rot_map_syms)
        return rot_disps, rot_forces
    def _get_kappa(self, i_sigma, i_temp, X):
        num_ir_grid_points = len(self._ir_grid_points)
        num_band = self._primitive.get_number_of_atoms() * 3

        if self._is_reducible_collision_matrix:
            num_mesh_points = np.prod(self._mesh)
            inv_col_mat = np.kron(
                self._collision_matrix[i_sigma, i_temp].reshape(
                    num_mesh_points * num_band,
                    num_mesh_points * num_band), np.eye(3))
        else:
            inv_col_mat = self._collision_matrix[i_sigma, i_temp].reshape(
                num_ir_grid_points * num_band * 3,
                num_ir_grid_points * num_band * 3)
        Y = np.dot(inv_col_mat, X.ravel()).reshape(-1, 3)

        if self._is_reducible_collision_matrix:
            from phonopy.harmonic.force_constants import similarity_transformation
            point_operations = self._symmetry.get_reciprocal_operations()
            rec_lat = np.linalg.inv(self._primitive.get_cell())
            rotations_cartesian = np.array(
                [similarity_transformation(rec_lat, r)
                 for r in point_operations], dtype='double')
        else:
            rotations_cartesian = self._rotations_cartesian

        # Acoustic mode at Gamma is not summed.
        RX = np.dot(X[3:], rotations_cartesian.reshape(-1, 3).T)
        RY = np.dot(Y[3:], rotations_cartesian.reshape(-1, 3).T)
        sum_outer = np.zeros((3, 3), dtype='double')
        for v, f in zip(RX.reshape(-1, 3), RY.reshape(-1, 3)):
            sum_outer += np.outer(v, f)
        t = self._temperatures[i_temp]

        if self._is_reducible_collision_matrix:
            return ((sum_outer + sum_outer.T) * self._conversion_factor *
                    Kb * t ** 2 / np.prod(self._mesh) / len(point_operations))
        else:
            return ((sum_outer + sum_outer.T) * self._conversion_factor *
                    Kb * t ** 2 / np.prod(self._mesh))
Пример #59
0
def _symmetrize_tensor(tensor, symmetry_operations):
    sum_tensor = np.zeros_like(tensor)
    for sym in symmetry_operations:
        sum_tensor += similarity_transformation(sym, tensor)
    return sum_tensor / len(symmetry_operations)