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)
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_
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
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
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)
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_
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
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
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
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]])
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]])
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
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]])
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
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)
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)
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])
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)
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)
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)
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
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))
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
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
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)
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
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))
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
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
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
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
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)
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))
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
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
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_
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)
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)
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
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)
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')
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)
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))
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')
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 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
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')
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')
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
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)
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))
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)