def _search_primitive_symmetry(self): self._primitive_symmetry = Symmetry(self._primitive, self._symprec, self._is_symmetry) if (len(self._symmetry.get_pointgroup_operations()) != len( self._primitive_symmetry.get_pointgroup_operations())): print("Warning: point group symmetries of supercell and primitive" "cell are different.")
def check_symmetry(input_cell, primitive_axis=np.eye(3, dtype=float), symprec=1e-5, phonopy_version=None): cell = Primitive(input_cell, primitive_axis, symprec) symmetry = Symmetry(cell, symprec) print get_symmetry_yaml(cell, symmetry, phonopy_version), if input_cell.get_magnetic_moments() == None: primitive = find_primitive(cell, symprec) if not primitive == None: print "# Primitive cell was found. It is written into PPOSCAR." write_vasp('PPOSCAR', primitive) # Overwrite symmetry and cell symmetry = Symmetry(primitive, symprec) cell = primitive bravais_lattice, bravais_pos, bravais_numbers = \ spg.refine_cell(cell, symprec) bravais = Atoms(numbers=bravais_numbers, scaled_positions=bravais_pos, cell=bravais_lattice, pbc=True) print "# Bravais lattice is written into BPOSCAR." write_vasp('BPOSCAR', bravais)
def write_supercells_with_displacements(supercell, cells_with_displacements, npts, r0s, rmts, supercell_matrix, filename="wien2k-"): v = supercell_matrix det = v[0,0] * v[1,1] * v[2,2] \ + v[0,1] * v[1,2] * v[2,0] \ + v[0,2] * v[1,0] * v[2,1] \ - v[0,0] * v[1,2] * v[2,1] \ - v[0,1] * v[1,0] * v[2,2] \ - v[0,2] * v[1,1] * v[2,0] npts_super = [] r0s_super = [] rmts_super = [] for i, j, k in zip(npts, r0s, rmts): for l in range(abs(det)): npts_super.append(i) r0s_super.append(j) rmts_super.append(k) w = open(filename.split('/')[-1] + "S", 'w') w.write(get_wien2k_struct(supercell, npts_super, r0s_super, rmts_super)) w.close() for i, cell in enumerate(cells_with_displacements): symmetry = Symmetry(cell) print "Number of non-equivalent atoms in %sS-%03d: %d" % ( filename, i + 1, len(symmetry.get_independent_atoms())) w = open(filename.split('/')[-1] + "S-%03d" % (i + 1), 'w') w.write(get_wien2k_struct(cell, npts_super, r0s_super, rmts_super)) w.close()
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 gencastep(fn,modenum,basis,natom,typatsym,symprec,atpos): from phonopy import Phonopy import phonopy.structure.spglib as spg from phonopy.structure.atoms import PhonopyAtoms as Atoms from phonopy.structure.symmetry import Symmetry, find_primitive, get_pointgroup fh=open(fn,'w') unitcell = Atoms(symbols=typatsym, cell=basis, positions=atpos) pbasis=np.eye(3) for i in range(len(basis)): pbasis[i]=basis[i]/np.linalg.norm(basis[i]) symmetry = Symmetry(unitcell, symprec) rotations = symmetry.get_symmetry_operations()['rotations'] translations = symmetry.get_symmetry_operations()['translations'] print('Space group International symbol: %s' % symmetry.get_international_table()) fh.write('%BLOCK LATTICE_CART\n') for bl in basis: fh.write('%s\n' % ''.join(' %12.8f' % b for b in bl)) fh.write('%ENDBLOCK LATTICE_CART\n\n') fh.write('%BLOCK POSITIONS_ABS\n') for i in range(len(typatsym)): fh.write(" %3s " % typatsym[i]) fh.write('%s\n' % ''.join(' %12.8f' % p for p in atpos[i].tolist())) fh.write('%ENDBLOCK POSITIONS_ABS\n\n') fh.write('SYMMETRY_TOL : %f ang\n' % symprec) fh.write('SYMMETRY_GENERATE \n') fh.write('#KPOINT_MP_GRID : 4 4 4\n#KPOINT_MP_OFFSET : 0.5 0.5 0.5\n')
def gencastep(fn, modenum, basis, natom, typatsym, symprec, atpos): from phonopy import Phonopy import phonopy.structure.spglib as spg from phonopy.structure.atoms import PhonopyAtoms as Atoms from phonopy.structure.symmetry import Symmetry, find_primitive, get_pointgroup fh = open(fn, 'w') unitcell = Atoms(symbols=typatsym, cell=basis, positions=atpos) pbasis = np.eye(3) for i in range(len(basis)): pbasis[i] = basis[i] / np.linalg.norm(basis[i]) symmetry = Symmetry(unitcell, symprec) rotations = symmetry.get_symmetry_operations()['rotations'] translations = symmetry.get_symmetry_operations()['translations'] print('Space group International symbol: %s' % symmetry.get_international_table()) fh.write('%BLOCK LATTICE_CART\n') for bl in basis: fh.write('%s\n' % ''.join(' %12.8f' % b for b in bl)) fh.write('%ENDBLOCK LATTICE_CART\n\n') fh.write('%BLOCK POSITIONS_ABS\n') for i in range(len(typatsym)): fh.write(" %3s " % typatsym[i]) fh.write('%s\n' % ''.join(' %12.8f' % p for p in atpos[i].tolist())) fh.write('%ENDBLOCK POSITIONS_ABS\n\n') fh.write('SYMMETRY_TOL : %f ang\n' % symprec) fh.write('SYMMETRY_GENERATE \n') fh.write('#KPOINT_MP_GRID : 4 4 4\n#KPOINT_MP_OFFSET : 0.5 0.5 0.5\n')
def __init__(self, fc4, supercell, primitive, mesh, temperatures=None, band_indices=None, frequency_factor_to_THz=VaspToTHz, is_nosym=False, symprec=1e-3, cutoff_frequency=1e-4, log_level=False, lapack_zheev_uplo='L'): self._fc4 = fc4 self._supercell = supercell self._primitive = primitive self._masses = np.double(self._primitive.get_masses()) self._mesh = np.intc(mesh) if temperatures is None: self._temperatures = np.double([0]) else: self._temperatures = np.double(temperatures) num_band = primitive.get_number_of_atoms() * 3 if band_indices is None: self._band_indices = np.arange(num_band, dtype='intc') else: self._band_indices = np.intc(band_indices) self._frequency_factor_to_THz = frequency_factor_to_THz self._is_nosym = is_nosym self._symprec = symprec self._cutoff_frequency = cutoff_frequency self._log_level = log_level self._lapack_zheev_uplo = lapack_zheev_uplo symmetry = Symmetry(primitive, symprec=symprec) self._point_group_operations = symmetry.get_pointgroup_operations() self._grid_address = None self._bz_map = None self._set_grid_address() self._grid_point = None self._quartets_at_q = None self._weights_at_q = None self._phonon_done = None self._frequencies = None self._eigenvectors = None self._dm = None self._nac_q_direction = None self._frequency_shifts = None # Unit to THz of Delta self._unit_conversion = (EV / Angstrom ** 4 / AMU ** 2 / (2 * np.pi * THz) ** 2 * Hbar * EV / (2 * np.pi * THz) / 8 / np.prod(self._mesh)) self._allocate_phonon()
def read_crystal(filename): f_crystal = open(filename) crystal_in = CrystalIn(f_crystal.readlines()) f_crystal.close() tags = crystal_in.get_tags() cell = Atoms(cell=tags['lattice_vectors'], symbols=tags['atomic_species'], scaled_positions=tags['coordinates']) magmoms = tags['magnetic_moments'] if magmoms is not None: # Print out symmetry information for magnetic cases # Original code from structure/symmetry.py symmetry = Symmetry(cell, symprec=1e-5) print("CRYSTAL-interface: Magnetic structure, number of operations without spin: %d" % len(symmetry.get_symmetry_operations()['rotations'])) print("CRYSTAL-interface: Spacegroup without spin: %s" % symmetry.get_international_table()) cell.set_magnetic_moments(magmoms) symmetry = Symmetry(cell, symprec=1e-5) print("CRYSTAL-interface: Magnetic structure, number of operations with spin: %d" % len(symmetry.get_symmetry_operations()['rotations'])) print("") return cell, tags['conv_numbers']
def write_supercells_with_displacements(supercell, cells_with_displacements, ids, npts, r0s, rmts, num_unitcells_in_supercell, pre_filename="wien2k", width=3): npts_super = [] r0s_super = [] rmts_super = [] for i, j, k in zip(npts, r0s, rmts): for l in range(num_unitcells_in_supercell): npts_super.append(i) r0s_super.append(j) rmts_super.append(k) _pre_filename = pre_filename.split('/')[-1] + "S" write_wein2k(_pre_filename, supercell, npts_super, r0s_super, rmts_super) for i, cell in zip(ids, cells_with_displacements): symmetry = Symmetry(cell) filename = "{pre_filename}-{0:0{width}}.in".format( i, pre_filename=_pre_filename, width=width) print("Number of non-equivalent atoms in %s: %d" % (filename, len(symmetry.get_independent_atoms()))) write_wein2k(filename, cell, npts_super, r0s_super, rmts_super)
def write_born_file(initial_structure, phonopy_inputs, dielectric_tensor, born_effective_charge_tensor, file_path): """ Creates the born file that phonopy needs for the non-analytical correction to be applied. """ phonon = get_initialized_phononopy_instance(initial_structure, phonopy_inputs) symm = Symmetry(cell=phonon.get_primitive(), symprec=phonopy_inputs['symprec']) independent_atom_indices_list = symm.get_independent_atoms() born_file = File() born_file += "14.400" flat_dielectric_list = misc.flatten_multi_dimensional_list( dielectric_tensor) born_file += " ".join(str(component) for component in flat_dielectric_list) print "Independent atom indices:", independent_atom_indices_list for atomic_bec_index in independent_atom_indices_list: atomic_bec = born_effective_charge_tensor[atomic_bec_index] flat_atomic_bec = misc.flatten_multi_dimensional_list(atomic_bec) born_file += " ".join(str(component) for component in flat_atomic_bec) born_file.write_to_path(file_path)
def _extract_independent_borns(borns, ucell, primitive_matrix=None, supercell_matrix=None, is_symmetry=True, 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 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, s_indep_atoms
def write_supercells_with_displacements( supercell, cells_with_displacements, npts, r0s, rmts, supercell_matrix, filename="wien2k-" ): v = supercell_matrix det = v[0,0] * v[1,1] * v[2,2] \ + v[0,1] * v[1,2] * v[2,0] \ + v[0,2] * v[1,0] * v[2,1] \ - v[0,0] * v[1,2] * v[2,1] \ - v[0,1] * v[1,0] * v[2,2] \ - v[0,2] * v[1,1] * v[2,0] npts_super = [] r0s_super = [] rmts_super = [] for i, j, k in zip(npts, r0s, rmts): for l in range(abs(det)): npts_super.append(i) r0s_super.append(j) rmts_super.append(k) w = open(filename.split('/')[-1]+"S", 'w') w.write( get_wien2k_struct(supercell, npts_super, r0s_super, rmts_super) ) w.close() for i, cell in enumerate( cells_with_displacements ): symmetry = Symmetry( cell ) print "Number of non-equivalent atoms in %sS-%03d: %d" % ( filename, i+1, len( symmetry.get_independent_atoms() ) ) w = open(filename.split('/')[-1]+"S-%03d" % (i+1), 'w') w.write( get_wien2k_struct(cell, npts_super, r0s_super, rmts_super) ) w.close()
def check_symmetry(input_cell, primitive_axis=None, symprec=1e-5, distance_to_A=1.0, phonopy_version=None): if primitive_axis is None: cell = get_primitive(input_cell, np.eye(3), symprec=symprec) else: cell = get_primitive(input_cell, primitive_axis, symprec=symprec) lattice = cell.get_cell() * distance_to_A cell.set_cell(lattice) symmetry = Symmetry(cell, symprec) print(_get_symmetry_yaml(cell, symmetry, phonopy_version)) if input_cell.get_magnetic_moments() is None: primitive = find_primitive(cell, symprec) if primitive is not None: print("# Primitive cell was found. It is written into PPOSCAR.") write_vasp('PPOSCAR', primitive) # Overwrite symmetry and cell symmetry = Symmetry(primitive, symprec) cell = primitive (bravais_lattice, bravais_pos, bravais_numbers) = spg.refine_cell(cell, symprec) bravais = Atoms(numbers=bravais_numbers, scaled_positions=bravais_pos, cell=bravais_lattice, pbc=True) print("# Bravais lattice is written into BPOSCAR.") write_vasp('BPOSCAR', bravais)
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 write_supercells_with_displacements(supercell, cells_with_displacements, npts, r0s, rmts, num_unitcells_in_supercell, filename="wien2k-"): npts_super = [] r0s_super = [] rmts_super = [] for i, j, k in zip(npts, r0s, rmts): for l in range(num_unitcells_in_supercell): npts_super.append(i) r0s_super.append(j) rmts_super.append(k) w = open(filename.split('/')[-1] + "S", 'w') w.write(_get_wien2k_struct(supercell, npts_super, r0s_super, rmts_super)) w.close() for i, cell in enumerate(cells_with_displacements): symmetry = Symmetry(cell) supercell_filename = filename.split('/')[-1] + "S-%03d" % (i + 1) print("Number of non-equivalent atoms in %s: %d" % (supercell_filename, len(symmetry.get_independent_atoms()))) w = open(supercell_filename, 'w') w.write(_get_wien2k_struct(cell, npts_super, r0s_super, rmts_super)) w.close()
def __init__(self, fc4, supercell, primitive, mesh, temperatures=None, band_indices=None, frequency_factor_to_THz=VaspToTHz, is_nosym=False, symprec=1e-3, cutoff_frequency=1e-4, log_level=False, lapack_zheev_uplo='L'): self._fc4 = fc4 self._supercell = supercell self._primitive = primitive self._masses = np.double(self._primitive.get_masses()) self._mesh = np.intc(mesh) if temperatures is None: self._temperatures = np.double([0]) else: self._temperatures = np.double(temperatures) num_band = primitive.get_number_of_atoms() * 3 if band_indices is None: self._band_indices = np.arange(num_band, dtype='intc') else: self._band_indices = np.intc(band_indices) self._frequency_factor_to_THz = frequency_factor_to_THz self._is_nosym = is_nosym self._symprec = symprec self._cutoff_frequency = cutoff_frequency self._log_level = log_level self._lapack_zheev_uplo = lapack_zheev_uplo symmetry = Symmetry(primitive, symprec=symprec) self._point_group_operations = symmetry.get_pointgroup_operations() self._grid_address = None self._bz_map = None self._set_grid_address() self._grid_point = None self._quartets_at_q = None self._weights_at_q = None self._phonon_done = None self._frequencies = None self._eigenvectors = None self._dm = None self._nac_q_direction = None self._frequency_shifts = None # Unit to THz of Delta self._unit_conversion = (EV / Angstrom**4 / AMU**2 / (2 * np.pi * THz)**2 * Hbar * EV / (2 * np.pi * THz) / 8 / np.prod(self._mesh)) self._allocate_phonon()
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 __init__(self, mesh, primitive, supercell, fc2, nac_params=None, nac_q_direction=None, sigma=None, cutoff_frequency=None, frequency_step=None, num_frequency_points=None, temperatures=None, frequency_factor_to_THz=VaspToTHz, frequency_scale_factor=1.0, is_mesh_symmetry=True, symprec=1e-5, filename=None, log_level=False, lapack_zheev_uplo='L'): self._grid_point = None self._mesh = np.array(mesh, dtype='intc') self._primitive = primitive self._supercell = supercell self._fc2 = fc2 self._nac_params = nac_params self._nac_q_direction = None self.set_nac_q_direction(nac_q_direction) self._sigma = None self.set_sigma(sigma) if cutoff_frequency is None: self._cutoff_frequency = 0 else: self._cutoff_frequency = cutoff_frequency self._frequency_step = frequency_step self._num_frequency_points = num_frequency_points self._temperatures = temperatures self._frequency_factor_to_THz = frequency_factor_to_THz self._frequency_scale_factor = frequency_scale_factor self._is_mesh_symmetry = is_mesh_symmetry self._symprec = symprec self._filename = filename self._log_level = log_level self._lapack_zheev_uplo = lapack_zheev_uplo self._num_band = self._primitive.get_number_of_atoms() * 3 self._reciprocal_lattice = np.linalg.inv(self._primitive.get_cell()) self._init_dynamical_matrix() self._symmetry = Symmetry(primitive, symprec) self._tetrahedron_method = None self._phonon_done = None self._frequencies = None self._eigenvectors = None self._joint_dos = None self._frequency_points = None
def _search_primitive_symmetry_ideal(self): self._primitive_symmetry = Symmetry(self._primitive_ideal, self._symprec, self._is_symmetry) n0 = len(self._symmetry.get_pointgroup_operations()) n1 = len(self._primitive_symmetry.get_pointgroup_operations()) if n0 != n1: raise Warning("Point group symmetries of supercell and primitive" "cell are different.")
def get_number_of_triplets(primitive, mesh, grid_point, symprec=1e-5): mesh = np.array(mesh, dtype='intc') symmetry = Symmetry(primitive, symprec) point_group = symmetry.get_pointgroup_operations() primitive_lattice = np.linalg.inv(primitive.get_cell()) triplets_at_q, _, _, _, _, _ = get_triplets_at_q(grid_point, mesh, point_group, primitive_lattice) return len(triplets_at_q)
def test_magmom(self): symprec = 1e-5 cell = get_unitcell_from_phonopy_yaml(os.path.join(data_dir,"Cr.yaml")) symmetry_nonspin = Symmetry(cell, symprec=symprec) atom_map_nonspin = symmetry_nonspin.get_map_atoms() len_sym_nonspin = len( symmetry_nonspin.get_symmetry_operations()['rotations']) spin = [1, -1] cell_withspin = cell.copy() cell_withspin.set_magnetic_moments(spin) symmetry_withspin = Symmetry(cell_withspin, symprec=symprec) atom_map_withspin = symmetry_withspin.get_map_atoms() len_sym_withspin = len( symmetry_withspin.get_symmetry_operations()['rotations']) broken_spin = [1, -2] cell_brokenspin = cell.copy() cell_brokenspin = cell.copy() cell_brokenspin.set_magnetic_moments(broken_spin) symmetry_brokenspin = Symmetry(cell_brokenspin, symprec=symprec) atom_map_brokenspin = symmetry_brokenspin.get_map_atoms() len_sym_brokenspin = len( symmetry_brokenspin.get_symmetry_operations()['rotations']) self.assertTrue((atom_map_nonspin == atom_map_withspin).all()) self.assertFalse((atom_map_nonspin == atom_map_brokenspin).all()) self.assertTrue(len_sym_nonspin == len_sym_withspin) self.assertFalse(len_sym_nonspin == len_sym_brokenspin)
def test_magmom(convcell_cr: PhonopyAtoms): """Test symmetry search with hmagnetic moments.""" symprec = 1e-5 symmetry_nonspin = Symmetry(convcell_cr, symprec=symprec) atom_map_nonspin = symmetry_nonspin.get_map_atoms() len_sym_nonspin = len(symmetry_nonspin.symmetry_operations["rotations"]) spin = [1, -1] cell_withspin = convcell_cr.copy() cell_withspin.magnetic_moments = spin symmetry_withspin = Symmetry(cell_withspin, symprec=symprec) atom_map_withspin = symmetry_withspin.get_map_atoms() len_sym_withspin = len(symmetry_withspin.symmetry_operations["rotations"]) broken_spin = [1, -2] cell_brokenspin = convcell_cr.copy() cell_brokenspin = convcell_cr.copy() cell_brokenspin.magnetic_moments = broken_spin symmetry_brokenspin = Symmetry(cell_brokenspin, symprec=symprec) atom_map_brokenspin = symmetry_brokenspin.get_map_atoms() len_sym_brokenspin = len( symmetry_brokenspin.symmetry_operations["rotations"]) assert (atom_map_nonspin == atom_map_withspin).all() assert (atom_map_nonspin != atom_map_brokenspin).any() assert len_sym_nonspin == len_sym_withspin assert len_sym_nonspin != len_sym_brokenspin
def get_coarse_ir_grid_points(primitive, mesh, mesh_divisors, coarse_mesh_shifts, is_kappa_star=True, symprec=1e-5): mesh = np.array(mesh, dtype='intc') symmetry = Symmetry(primitive, symprec) point_group = symmetry.get_pointgroup_operations() if mesh_divisors is None: (ir_grid_points, ir_grid_weights, grid_address, grid_mapping_table) = get_ir_grid_points(mesh, point_group) else: mesh_divs = np.array(mesh_divisors, dtype='intc') coarse_mesh = mesh // mesh_divs if coarse_mesh_shifts is None: coarse_mesh_shifts = [False, False, False] if not is_kappa_star: coarse_grid_address = get_grid_address(coarse_mesh) coarse_grid_points = np.arange(np.prod(coarse_mesh), dtype='intc') coarse_grid_weights = np.ones(len(coarse_grid_points), dtype='intc') else: (coarse_ir_grid_points, coarse_ir_grid_weights, coarse_grid_address, coarse_grid_mapping_table) = get_ir_grid_points( coarse_mesh, point_group, mesh_shifts=coarse_mesh_shifts) ir_grid_points = from_coarse_to_dense_grid_points( mesh, mesh_divs, coarse_grid_points, coarse_grid_address, coarse_mesh_shifts=coarse_mesh_shifts) grid_address = get_grid_address(mesh) ir_grid_weights = ir_grid_weights primitive_lattice = np.linalg.inv(primitive.get_cell()) bz_grid_address, bz_map = spg.relocate_BZ_grid_address(grid_address, mesh, primitive_lattice) return (ir_grid_points, ir_grid_weights, bz_grid_address, grid_mapping_table)
def get_coarse_ir_grid_points(primitive, mesh, mesh_divisors, coarse_mesh_shifts, is_kappa_star=True, symprec=1e-5): mesh = np.array(mesh, dtype='intc') symmetry = Symmetry(primitive, symprec) point_group = symmetry.get_pointgroup_operations() if mesh_divisors is None: (ir_grid_points, ir_grid_weights, grid_address, grid_mapping_table) = get_ir_grid_points(mesh, point_group) else: mesh_divs = np.array(mesh_divisors, dtype='intc') coarse_mesh = mesh // mesh_divs if coarse_mesh_shifts is None: coarse_mesh_shifts = [False, False, False] if not is_kappa_star: coarse_grid_address = get_grid_address(coarse_mesh) coarse_grid_points = np.arange(np.prod(coarse_mesh), dtype='uintp') else: (coarse_ir_grid_points, coarse_ir_grid_weights, coarse_grid_address, coarse_grid_mapping_table) = get_ir_grid_points( coarse_mesh, point_group, mesh_shifts=coarse_mesh_shifts) ir_grid_points = from_coarse_to_dense_grid_points( mesh, mesh_divs, coarse_grid_points, coarse_grid_address, coarse_mesh_shifts=coarse_mesh_shifts) grid_address = get_grid_address(mesh) ir_grid_weights = ir_grid_weights reciprocal_lattice = np.linalg.inv(primitive.get_cell()) bz_grid_address, bz_map = spg.relocate_BZ_grid_address(grid_address, mesh, reciprocal_lattice, is_dense=True) return (ir_grid_points, ir_grid_weights, bz_grid_address, grid_mapping_table)
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 test_parse_wien2k_struct(self): cell, npts, r0s, rmts = parse_wien2k_struct("BaGa2.struct") lattice = cell.get_cell().T displacements, supercell = parse_disp_yaml("disp_BaGa2.yaml", return_cell=True) symmetry = Symmetry(cell) print(PhonopyAtoms(atoms=cell)) sym_op = symmetry.get_symmetry_operations() print(symmetry.get_international_table()) for i, (r, t) in enumerate( zip(sym_op['rotations'], sym_op['translations'])): print("--- %d ---" % (i + 1)) print(r) print(t)
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 get_number_of_triplets(primitive, mesh, grid_point, symprec=1e-5): mesh = np.array(mesh, dtype='intc') symmetry = Symmetry(primitive, symprec) point_group = symmetry.get_pointgroup_operations() primitive_lattice = np.linalg.inv(primitive.get_cell()) triplets_at_q, _, _, _, _, _ = get_triplets_at_q( grid_point, mesh, point_group, primitive_lattice) return len(triplets_at_q)
def parse_BORN( primitive, filename = "BORN" ): file = open( filename, 'r' ) # Read unit conversion factor, damping factor, ... factors = [ float( x ) for x in file.readline().split() ] if len( factors ) < 1: print "BORN file format of line 1 is incorrect" return None if len( factors ) < 2: factors.append( Damping_Factor ) # Read dielectric constant line = file.readline().split() if 9 < len( line ) or len( line ) < 9: print "BORN file format of line 2 is incorrect" return None dielectric = np.reshape( [ float( x ) for x in line ], ( 3, 3 ) ) # Read Born effective charge symmetry = Symmetry( primitive ) independent_atoms = symmetry.get_independent_atoms() born = np.zeros( ( primitive.get_number_of_atoms(), 3, 3 ), dtype=float ) for i in independent_atoms: line = file.readline().split() if 9 < len( line ) or len( line ) < 9: print "BORN file format of line %d is incorrect" % ( i + 3 ) return None 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 __init__( self, supercell: Supercell, primitive: Primitive, fc2, mesh=None, nac_params=None, nac_q_direction=None, sigmas=None, cutoff_frequency=1e-4, frequency_step=None, num_frequency_points=None, num_points_in_batch=None, temperatures=None, frequency_factor_to_THz=VaspToTHz, frequency_scale_factor=None, use_grg=False, SNF_coordinates="reciprocal", is_mesh_symmetry=True, is_symmetry=True, store_dense_gp_map=False, symprec=1e-5, output_filename=None, log_level=0, ): """Init method.""" self._primitive = primitive self._supercell = supercell self._fc2 = fc2 self._temperatures = temperatures self._nac_params = nac_params self._nac_q_direction = nac_q_direction if sigmas is None: self._sigmas = [None] else: self._sigmas = sigmas self._cutoff_frequency = cutoff_frequency self._frequency_factor_to_THz = frequency_factor_to_THz self._frequency_scale_factor = frequency_scale_factor self._is_mesh_symmetry = is_mesh_symmetry self._is_symmetry = is_symmetry self._store_dense_gp_map = store_dense_gp_map self._use_grg = use_grg self._SNF_coordinates = SNF_coordinates self._symprec = symprec self._filename = output_filename self._log_level = log_level self._bz_grid = None self._joint_dos = None self._num_frequency_points_in_batch = num_points_in_batch self._frequency_step = frequency_step self._num_frequency_points = num_frequency_points self._primitive_symmetry = Symmetry(self._primitive, self._symprec, self._is_symmetry) if mesh is not None: self.mesh_numbers = mesh self.initialize(mesh)
def parse_BORN_from_strings(strings, primitive, symprec=1e-5, is_symmetry=True): f = StringIO.StringIO(strings) symmetry = Symmetry(primitive, symprec=symprec, is_symmetry=is_symmetry) return get_born_parameters(f, primitive, symmetry)
def get_data(args, interface_mode=None): args = parse_args() cell, _ = read_crystal_structure(args.filenames[0], interface_mode=interface_mode) f = h5py.File(args.filenames[1]) primitive_matrix = np.reshape( [fracval(x) for x in args.primitive_matrix.split()], (3, 3)) primitive = get_primitive(cell, primitive_matrix) symmetry = Symmetry(primitive) data = {} data['cell'] = primitive data['symmetry'] = symmetry data['mesh'] = np.array(f['mesh'][:], dtype='intc') # (3) data['weight'] = f['weight'][:] # (gp) data['group_velocity'] = f['group_velocity'][:] # (gp, band, 3) data['qpoint'] = f['qpoint'][:] # (gp, 3) data['frequency'] = f['frequency'][:] # (gp, band) if 'gamma_N' in f: data['gamma_N'] = f['gamma_N'][:] # (temps, gp, band) data['gamma_U'] = f['gamma_U'][:] # (temps, gp, band) if 'gamma_isotope' in f: data['gamma_isotope'] = f['gamma_isotope'][:] # (gp, band) data['heat_capacity'] = f['heat_capacity'][:] # (temps, gp, band) data['temperature'] = np.array(f['temperature'][:], dtype='double') # (temps) ir_grid_points, grid_address, _ = get_grid_symmetry(data) data['ir_grid_points'] = ir_grid_points data['grid_address'] = grid_address return data
def _search_phonon_supercell_symmetry(self): if self._phonon_supercell_matrix is None: self._phonon_supercell_symmetry = self._symmetry else: self._phonon_supercell_symmetry = Symmetry(self._phonon_supercell, self._symprec, self._is_symmetry)
def get_equivalent_q_points_by_symmetry(q_point, structure): from phonopy.structure.symmetry import Symmetry bulk = PhonopyAtoms(symbols=structure.get_atomic_elements(), scaled_positions=structure.get_scaled_positions(), cell=structure.get_cell().T) tot_points = [] for operation_matrix in Symmetry(bulk).get_reciprocal_operations(): operation_matrix_q = np.dot( np.linalg.inv(structure.get_primitive_matrix()), operation_matrix.T) operation_matrix_q = np.dot(operation_matrix_q, structure.get_primitive_matrix()) q_point_test = np.dot(q_point, operation_matrix_q) if (q_point_test >= 0).all(): tot_points.append(q_point_test) # print tot_points # print(np.vstack({tuple(row) for row in tot_points})) return np.vstack({tuple(row) for row in tot_points})
def get_BORN_txt(structure, parameters, nac_data, symprec=1.e-5): from phonopy.structure.cells import get_primitive, get_supercell from phonopy.structure.symmetry import Symmetry from phonopy.interface import get_default_physical_units from phonopy.structure.atoms import Atoms as PhonopyAtoms born_charges = nac_data.get_array('born_charges') epsilon = nac_data.get_array('epsilon') print ('inside born parameters') pmat = parameters['primitive'] smat = parameters['supercell'] ucell = PhonopyAtoms(symbols=[site.kind_name for site in structure.sites], positions=[site.position for site in structure.sites], cell=structure.cell) num_atom = len(born_charges) assert num_atom == ucell.get_number_of_atoms(), \ "num_atom %d != len(borns) %d" % (ucell.get_number_of_atoms(), len(born_charges)) 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=True, 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 = born_charges[u_indep_atoms].copy() factor = get_default_physical_units('vasp')['nac_factor'] # born charges in VASP units born_txt = ('{}\n'.format(factor)) for num in epsilon.flatten(): born_txt += ('{0:4.8f}'.format(num)) born_txt += ('\n') for atom in reduced_borns: for num in atom: born_txt += ('{0:4.8f}'.format(num)) born_txt += ('\n') born_txt += ('{}\n'.format(factor)) return born_txt
def _search_primitive_symmetry(self): self._primitive_symmetry = Symmetry(self._primitive, self._symprec, self._is_symmetry) if (len(self._symmetry.get_pointgroup_operations()) != len(self._primitive_symmetry.get_pointgroup_operations())): print("Warning: point group symmetries of supercell and primitive" "cell are different.")
def set_grid(self): self._point_operations= get_pointgroup_operations( Symmetry(self._cell).get_pointgroup_operations()) self._kpoint_operations = get_kpoint_group(self._mesh, self._point_operations) (mapping, rot_mappings) =get_mappings(self._mesh, Symmetry(self._cell).get_pointgroup_operations(), qpoints=np.array([0,0,0],dtype="double")) self._rot_mappings = self._kpoint_operations[rot_mappings] self._mapping, self._grid=spg.get_ir_reciprocal_mesh(self._mesh, self._cell) assert (self._mapping==mapping).all() self._map_to_ir_index=np.zeros_like(mapping) reverse_mapping=[] for i,u in enumerate(np.unique(mapping)): reverse_mapping.append(np.where(mapping==u)[0]) self._map_to_ir_index[np.where(mapping==u)] = i self._reverse_mapping=reverse_mapping
def __init__(self, mesh, primitive, supercell, fc2, nac_params=None, nac_q_direction=None, sigma=None, cutoff_frequency=None, frequency_step=None, num_frequency_points=None, temperatures=None, frequency_factor_to_THz=VaspToTHz, frequency_scale_factor=1.0, is_nosym=False, symprec=1e-5, filename=None, log_level=False, lapack_zheev_uplo='L'): self._grid_point = None self._mesh = np.array(mesh, dtype='intc') self._primitive = primitive self._supercell = supercell self._fc2 = fc2 self._nac_params = nac_params self._nac_q_direction = None self.set_nac_q_direction(nac_q_direction) self._sigma = None self.set_sigma(sigma) if cutoff_frequency is None: self._cutoff_frequency = 0 else: self._cutoff_frequency = cutoff_frequency self._frequency_step = frequency_step self._num_frequency_points = num_frequency_points self._temperatures = temperatures self._frequency_factor_to_THz = frequency_factor_to_THz self._frequency_scale_factor = frequency_scale_factor self._is_nosym = is_nosym self._symprec = symprec self._filename = filename self._log_level = log_level self._lapack_zheev_uplo = lapack_zheev_uplo self._num_band = self._primitive.get_number_of_atoms() * 3 self._reciprocal_lattice = np.linalg.inv(self._primitive.get_cell()) self._set_dynamical_matrix() self._symmetry = Symmetry(primitive, symprec) self._tetrahedron_method = None self._phonon_done = None self._frequencies = None self._eigenvectors = None self._joint_dos = None self._frequency_points = None
def read_castep(filename): f_castep = open(filename) castep_in = CastepIn(f_castep.readlines()) f_castep.close() tags = castep_in.get_tags() # 1st stage is to create Atoms object ignoring Spin polarization. General case. cell = Atoms(cell=tags['lattice_vectors'], symbols=tags['atomic_species'], scaled_positions=tags['coordinates']) # Analyse spin states and add data to Atoms instance "cell" if ones exist magmoms = tags['magnetic_moments'] if magmoms is not None: # Print out symmetry information for magnetic cases # Original code from structure/symmetry.py symmetry = Symmetry(cell, symprec=1e-5) print( "CASTEP-interface: Magnetic structure, number of operations without spin: %d" % len(symmetry.get_symmetry_operations()['rotations'])) print("CASTEP-interface: Spacegroup without spin: %s" % symmetry.get_international_table()) cell.set_magnetic_moments(magmoms) symmetry = Symmetry(cell, symprec=1e-5) print( "CASTEP-interface: Magnetic structure, number of operations with spin: %d" % len(symmetry.get_symmetry_operations()['rotations'])) print("") return cell
def read_crystal(filename): f_crystal = open(filename) crystal_in = CrystalIn(f_crystal.readlines()) f_crystal.close() tags = crystal_in.get_tags() cell = Atoms(cell=tags['lattice_vectors'], symbols=tags['atomic_species'], scaled_positions=tags['coordinates']) magmoms = tags['magnetic_moments'] if magmoms is not None: # Print out symmetry information for magnetic cases # Original code from structure/symmetry.py symmetry = Symmetry(cell, symprec=1e-5) print( "CRYSTAL-interface: Magnetic structure, number of operations without spin: %d" % len(symmetry.get_symmetry_operations()['rotations'])) print("CRYSTAL-interface: Spacegroup without spin: %s" % symmetry.get_international_table()) cell.set_magnetic_moments(magmoms) symmetry = Symmetry(cell, symprec=1e-5) print( "CRYSTAL-interface: Magnetic structure, number of operations with spin: %d" % len(symmetry.get_symmetry_operations()['rotations'])) print("") return cell, tags['conv_numbers']
def __init__( self, mesh, primitive, mass_variances=None, # length of list is num_atom. band_indices=None, sigma=None, bz_grid=None, frequency_factor_to_THz=VaspToTHz, use_grg=False, store_dense_gp_map=True, symprec=1e-5, cutoff_frequency=None, lapack_zheev_uplo="L", ): """Init method.""" self._mesh = mesh if mass_variances is None: self._mass_variances = get_mass_variances(primitive) else: self._mass_variances = np.array(mass_variances, dtype="double") self._primitive = primitive self._sigma = sigma self._bz_grid = bz_grid self._symprec = symprec if cutoff_frequency is None: self._cutoff_frequency = 0 else: self._cutoff_frequency = cutoff_frequency self._frequency_factor_to_THz = frequency_factor_to_THz self._lapack_zheev_uplo = lapack_zheev_uplo self._nac_q_direction = None self._grid_points = None self._frequencies = None self._eigenvectors = None self._phonon_done = None self._dm = None self._gamma = None self._tetrahedron_method = None num_band = len(self._primitive) * 3 if band_indices is None: self._band_indices = np.arange(num_band, dtype="int_") else: self._band_indices = np.array(band_indices, dtype="int_") if self._bz_grid is None: primitive_symmetry = Symmetry(self._primitive, self._symprec) self._bz_grid = BZGrid( self._mesh, lattice=self._primitive.cell, symmetry_dataset=primitive_symmetry.dataset, use_grg=use_grg, store_dense_gp_map=store_dense_gp_map, )
def test_get_map_operations(self): symprec = 1e-5 cell = get_unitcell_from_phonopy_yaml("../NaCl.yaml") scell = get_supercell(cell, np.diag([2, 2, 2]), symprec=symprec) symmetry = Symmetry(scell, symprec=symprec) map_ops_cmp = [ 0, 2, 51, 53, 8, 1, 65, 98, 3, 14, 34, 24, 76, 69, 54, 110, 576, 198, 229, 208, 201, 192, 210, 294, 5, 67, 36, 57, 18, 90, 23, 114, 0, 9, 1, 96, 6, 323, 98, 326, 3, 42, 17, 293, 16, 130, 99, 337, 192, 194, 202, 199, 205, 196, 200, 193, 12, 5, 30, 108, 37, 128, 291, 302 ] start = time.time() symmetry._set_map_operations() end = time.time() # print(end - start) map_ops = symmetry.get_map_operations() self.assertTrue((map_ops_cmp == map_ops).all())
def get_crystal_structure(cell, conv_numbers, write_symmetry=False): lattice = cell.get_cell() positions = cell.get_positions() numbers = cell.get_atomic_numbers() # Create and EXTERNAL file (fort.34) # Dimensionality, centring, crystal type lines = "3 1 1\n" # Cartesian components of the lattice vectors for lattvec in lattice: lines += ("%12.8f" * 3 + "\n") % tuple(lattvec) # Symmetry operators if write_symmetry: symmetry = Symmetry(cell, symprec=1e-5) rotations = symmetry.get_symmetry_operations()['rotations'] translations = symmetry.get_symmetry_operations()['translations'] N_symmops = 0 symmlines = "" for i in range(0, len(rotations)): N_symmops += 1 for j in range(0, 3): symmlines += (" %5.2f" * 3 + "\n") % tuple(rotations[i][j]) symmlines += (" %5.2f" * 3 + "\n") % tuple(translations[i]) lines += ("%d\n" % N_symmops) lines += symmlines else: lines += "1\n" lines += " 1.00 0.00 0.00\n" lines += " 0.00 1.00 0.00\n" lines += " 0.00 0.00 1.00\n" lines += " 0.00 0.00 0.00\n" # Number of atoms in the unit cell (asymmetric unit) lines += ("%d\n") % len(positions) # Conventional atomic number and cartesian coordinates of the atoms for i, pos in zip(conv_numbers, positions): lines += (" %d " + "%16.12f"*3 + "\n") % (i, pos[0], pos[1], pos[2]) return lines
def get_crystal_structure(cell, conv_numbers, write_symmetry=False): lattice = cell.get_cell() positions = cell.get_positions() numbers = cell.get_atomic_numbers() # Create and EXTERNAL file (fort.34) # Dimensionality, centring, crystal type lines = "3 1 1\n" # Cartesian components of the lattice vectors for lattvec in lattice: lines += ("%12.8f" * 3 + "\n") % tuple(lattvec) # Symmetry operators if write_symmetry: symmetry = Symmetry(cell, symprec=1e-5) rotations = symmetry.get_symmetry_operations()['rotations'] translations = symmetry.get_symmetry_operations()['translations'] N_symmops = 0 symmlines = "" for i in range(0, len(rotations)): N_symmops += 1 for j in range(0, 3): symmlines += (" %5.2f" * 3 + "\n") % tuple(rotations[i][j]) symmlines += (" %5.2f" * 3 + "\n") % tuple(translations[i]) lines += ("%d\n" % N_symmops) lines += symmlines else: lines += "1\n" lines += " 1.00 0.00 0.00\n" lines += " 0.00 1.00 0.00\n" lines += " 0.00 0.00 1.00\n" lines += " 0.00 0.00 0.00\n" # Number of atoms in the unit cell (asymmetric unit) lines += ("%d\n") % len(positions) # Conventional atomic number and cartesian coordinates of the atoms for i, pos in zip(conv_numbers, positions): lines += (" %d " + "%16.12f" * 3 + "\n") % (i, pos[0], pos[1], pos[2]) return lines
def get_born_parameters(phonon, born_charges, epsilon, symprec=1e-5): from phonopy.structure.cells import get_primitive, get_supercell from phonopy.structure.symmetry import Symmetry from phonopy.interface import get_default_physical_units print('inside born parameters') pmat = phonon.get_primitive_matrix() smat = phonon.get_supercell_matrix() ucell = phonon.get_unitcell() print pmat print smat print ucell num_atom = len(born_charges) assert num_atom == ucell.get_number_of_atoms(), \ "num_atom %d != len(borns) %d" % (ucell.get_number_of_atoms(), len(born_charges)) 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=True, 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 = born_charges[u_indep_atoms].copy() factor = get_default_physical_units('vasp')[ 'nac_factor'] # born charges in VASP units born_dict = { 'born': reduced_borns, 'dielectric': epsilon, 'factor': factor } print('final born dict', born_dict) return born_dict
def get_coarse_ir_grid_points(primitive, mesh, mesh_divisors, coarse_mesh_shifts, is_nosym=False, symprec=1e-5): if mesh_divisors is None: mesh_divs = [1, 1, 1] else: mesh_divs = mesh_divisors mesh = np.array(mesh, dtype='intc') mesh_divs = np.array(mesh_divs, dtype='intc') coarse_mesh = mesh // mesh_divs if coarse_mesh_shifts is None: coarse_mesh_shifts = [False, False, False] if is_nosym: coarse_grid_address = get_grid_address(coarse_mesh) coarse_grid_points = np.arange(np.prod(coarse_mesh), dtype='intc') coarse_grid_weights = np.ones(len(coarse_grid_points), dtype='intc') else: symmetry = Symmetry(primitive, symprec) (coarse_grid_points, coarse_grid_weights, coarse_grid_address) = get_ir_grid_points( coarse_mesh, symmetry.get_pointgroup_operations(), mesh_shifts=coarse_mesh_shifts) grid_points = from_coarse_to_dense_grid_points( mesh, mesh_divs, coarse_grid_points, coarse_grid_address, coarse_mesh_shifts=coarse_mesh_shifts) grid_address = get_grid_address(mesh) primitive_lattice = np.linalg.inv(primitive.get_cell()) bz_grid_address, _ = spg.relocate_BZ_grid_address(grid_address, mesh, primitive_lattice) return grid_points, coarse_grid_weights, bz_grid_address
def set_grid_point(self, grid_point, grid_points2=None, weights2 = None): "The grid_point is numbered using the bz scheme" self._grid_point = grid_point if self._grid_address is None: primitive_lattice = np.linalg.inv(self._primitive.get_cell()) self._grid_address, self._bz_map, self._bz_to_pp_map = get_bz_grid_address( self._mesh, primitive_lattice, with_boundary=True, is_bz_map_to_pp=True) if grid_points2 is not None: self._grid_points2 = grid_points2 self._weights2 = weights2 elif not self._is_nosym: symmetry = Symmetry(self._primitive, symprec=self._symprec) qpoint = self._grid_address[grid_point] / np.double(self._mesh) mapping, grid_points = spg.get_stabilized_reciprocal_mesh(self._mesh, symmetry.get_pointgroup_operations(), is_shift=np.zeros(3, dtype='intc'), is_time_reversal=True, qpoints=[qpoint]) grid_points2 = np.unique(mapping) # weight = np.zeros_like(grid_points2) # bz_grid_points2 = np.zeros_like(grid_points2) # for g, grid in enumerate(grid_points2): # weight[g] = len(np.where(grid == mapping)[0]) # bz_grid_points2[g] = np.where(grid == self._bz_to_pp_map)[0][0] # self._grid_points2 = bz_grid_points2 weight_temp = np.bincount(mapping) weight = weight_temp[np.nonzero(weight_temp)] self._grid_points2 = grid_points2 self._weights2 = weight else: self._grid_points2 = np.arange(np.prod(self._mesh)) self._weights2 = np.ones_like(self._grid_points2, dtype="intc")
def test_get_map_operations(self): symprec = 1e-5 cell = get_unitcell_from_phonopy_yaml( os.path.join(data_dir,"../NaCl.yaml")) scell = get_supercell(cell, np.diag([2, 2, 2]), symprec=symprec) symmetry = Symmetry(scell, symprec=symprec) start = time.time() symmetry._set_map_operations() end = time.time() # print(end - start) map_ops = symmetry.get_map_operations() map_atoms = symmetry.get_map_atoms() positions = scell.get_scaled_positions() rotations = symmetry.get_symmetry_operations()['rotations'] translations = symmetry.get_symmetry_operations()['translations'] for i, (op_i, atom_i) in enumerate(zip(map_ops, map_atoms)): r_pos = np.dot(rotations[op_i], positions[i]) + translations[op_i] diff = positions[atom_i] - r_pos diff -= np.rint(diff) self.assertTrue((diff < symprec).all())
class Phonopy: def __init__(self, unitcell, supercell_matrix, primitive_matrix=None, nac_params=None, distance=0.01, factor=VaspToTHz, is_auto_displacements=True, dynamical_matrix_decimals=None, force_constants_decimals=None, symprec=1e-5, is_symmetry=True, log_level=0): self._symprec = symprec self._factor = factor self._is_symmetry = is_symmetry self._log_level = log_level # Create supercell and primitive cell self._unitcell = unitcell self._supercell_matrix = supercell_matrix self._primitive_matrix = primitive_matrix self._supercell = None self._primitive = None self._build_supercell() self._build_primitive_cell() # Set supercell and primitive symmetry self._symmetry = None self._primitive_symmetry = None self._search_symmetry() self._search_primitive_symmetry() # set_displacements (used only in preprocess) self._displacement_dataset = None self._displacements = None self._displacement_directions = None self._supercells_with_displacements = None if is_auto_displacements: self.generate_displacements(distance=distance) # set_force_constants or set_forces self._force_constants = None self._force_constants_decimals = force_constants_decimals # set_dynamical_matrix self._dynamical_matrix = None self._nac_params = nac_params self._dynamical_matrix_decimals = dynamical_matrix_decimals # set_band_structure self._band_structure = None # set_mesh self._mesh = None # set_tetrahedron_method self._tetrahedron_method = None # set_thermal_properties self._thermal_properties = None # set_thermal_displacements self._thermal_displacements = None # set_thermal_displacement_matrices self._thermal_displacement_matrices = None # set_partial_DOS self._pdos = None # set_total_DOS self._total_dos = None # set_modulation self._modulation = None # set_character_table self._irreps = None # set_group_velocity self._group_velocity = None def set_post_process(self, primitive_matrix=None, sets_of_forces=None, displacement_dataset=None, force_constants=None, is_nac=None): print print ("********************************** Warning" "**********************************") print "set_post_process will be obsolete." print (" produce_force_constants is used instead of set_post_process" " for producing") print (" force constants from forces.") if primitive_matrix is not None: print (" primitive_matrix has to be given at Phonopy::__init__" " object creation.") print ("******************************************" "**********************************") print if primitive_matrix is not None: self._primitive_matrix = primitive_matrix self._build_primitive_cell() self._search_primitive_symmetry() if sets_of_forces is not None: self.set_forces(sets_of_forces) elif displacement_dataset is not None: self._displacement_dataset = displacement_dataset elif force_constants is not None: self.set_force_constants(force_constants) if self._displacement_dataset is not None: self.produce_force_constants() def set_masses(self, masses): p_masses = np.array(masses) self._primitive.set_masses(p_masses) p2p_map = self._primitive.get_primitive_to_primitive_map() s_masses = p_masses[[p2p_map[x] for x in self._primitive.get_supercell_to_primitive_map()]] self._supercell.set_masses(s_masses) u2s_map = self._supercell.get_unitcell_to_supercell_map() u_masses = s_masses[u2s_map] self._unitcell.set_masses(u_masses) def get_primitive(self): return self._primitive primitive = property(get_primitive) def get_unitcell(self): return self._unitcell unitcell = property(get_unitcell) def get_supercell(self): return self._supercell supercell = property(get_supercell) def set_supercell(self, supercell): self._supercell = supercell def get_symmetry(self): """return symmetry of supercell""" return self._symmetry symmetry = property(get_symmetry) def get_primitive_symmetry(self): """return symmetry of primitive cell""" return self._primitive_symmetry def get_unit_conversion_factor(self): return self._factor unit_conversion_factor = property(get_unit_conversion_factor) def produce_force_constants(self, forces=None, calculate_full_force_constants=True, computation_algorithm="svd"): if forces is not None: self.set_forces(forces) if calculate_full_force_constants: self._run_force_constants_from_forces( decimals=self._force_constants_decimals, computation_algorithm=computation_algorithm) else: p2s_map = self._primitive.get_primitive_to_supercell_map() self._run_force_constants_from_forces( distributed_atom_list=p2s_map, decimals=self._force_constants_decimals, computation_algorithm=computation_algorithm) def set_nac_params(self, nac_params=None, method=None): if method is not None: print "set_nac_params:" print " Keyword argument of \"method\" is not more supported." self._nac_params = nac_params def generate_displacements(self, distance=0.01, is_plusminus='auto', is_diagonal=True, is_trigonal=False): """Generate displacements automatically displacemsts: List of displacements in Cartesian coordinates. [[0, 0.01, 0.00, 0.00], ...] where each set of elements is defined by: First value: Atom index in supercell starting with 0 Second to fourth: Displacement in Cartesian coordinates displacement_directions: List of directions with respect to axes. This gives only the symmetrically non equivalent directions. The format is like: [[0, 1, 0, 0], [7, 1, 0, 1], ...] where each list is defined by: First value: Atom index in supercell starting with 0 Second to fourth: If the direction is displaced or not ( 1, 0, or -1 ) with respect to the axes. """ displacement_directions = get_least_displacements( self._symmetry, is_plusminus=is_plusminus, is_diagonal=is_diagonal, is_trigonal=is_trigonal, log_level=self._log_level) displacement_dataset = direction_to_displacement( displacement_directions, distance, self._supercell) self.set_displacement_dataset(displacement_dataset) def set_displacements(self, displacements): print print ("********************************** Warning" "**********************************") print "set_displacements is obsolete. Do nothing." print ("******************************************" "**********************************") print def get_displacements(self): return self._displacements displacements = property(get_displacements) def get_displacement_directions(self): return self._displacement_directions displacement_directions = property(get_displacement_directions) def get_displacement_dataset(self): return self._displacement_dataset def get_supercells_with_displacements(self): if self._displacement_dataset is None: return None else: self._build_supercells_with_displacements() return self._supercells_with_displacements def get_dynamical_matrix(self): return self._dynamical_matrix dynamical_matrix = property(get_dynamical_matrix) def set_forces(self, sets_of_forces): """ sets_of_forces: [[[f_1x, f_1y, f_1z], [f_2x, f_2y, f_2z], ...], # first supercell [[f_1x, f_1y, f_1z], [f_2x, f_2y, f_2z], ...], # second supercell ... ] """ for disp, forces in zip( self._displacement_dataset['first_atoms'], sets_of_forces): disp['forces'] = forces def set_force_constants_zero_with_radius(self, cutoff_radius): cutoff_force_constants(self._force_constants, self._supercell, cutoff_radius, symprec=self._symprec) def set_force_constants(self, force_constants): self._force_constants = force_constants def set_force_sets(self, force_sets): print print ("********************************** Warning" "**********************************") print "set_force_sets will be obsolete." print (" The method name is changed to set_displacement_dataset.") print ("******************************************" "**********************************") print self.set_displacement_dataset(force_sets) def set_displacement_dataset(self, displacement_dataset): """ displacement_dataset: {'natom': number_of_atoms_in_supercell, 'first_atoms': [ {'number': atom index of displaced atom, 'displacement': displacement in Cartesian coordinates, 'direction': displacement direction with respect to axes 'forces': forces on atoms in supercell}, {...}, ...]} """ self._displacement_dataset = displacement_dataset self._displacements = [] self._displacement_directions = [] for disp in self._displacement_dataset['first_atoms']: x = disp['displacement'] self._displacements.append([disp['number'], x[0], x[1], x[2]]) if 'direction' in disp: y = disp['direction'] self._displacement_directions.append( [disp['number'], y[0], y[1], y[2]]) if not self._displacement_directions: self._displacement_directions = None def symmetrize_force_constants(self, iteration=3): symmetrize_force_constants(self._force_constants, iteration) def symmetrize_force_constants_by_space_group(self): rotations = self._symmetry.get_symmetry_operations()['rotations'] translations = self._symmetry.get_symmetry_operations()['translations'] set_tensor_symmetry(self._force_constants, self._supercell.get_cell().T, self._supercell.get_scaled_positions(), rotations, translations, self._symprec) def get_force_constants(self): return self._force_constants force_constants = property(get_force_constants) def get_rotational_condition_of_fc(self): return rotational_invariance(self._force_constants, self._supercell, self._primitive, self._symprec) def set_dynamical_matrix(self): self._set_dynamical_matrix() def get_dynamical_matrix_at_q(self, q): self._set_dynamical_matrix() self._dynamical_matrix.set_dynamical_matrix(q) return self._dynamical_matrix.get_dynamical_matrix() def get_frequencies(self, q): """ Calculate phonon frequencies at q q: q-vector in reduced coordinates of primitive cell """ self._set_dynamical_matrix() self._dynamical_matrix.set_dynamical_matrix(q) dm = self._dynamical_matrix.get_dynamical_matrix() frequencies = [] for eig in np.linalg.eigvalsh(dm).real: if eig < 0: frequencies.append(-np.sqrt(-eig)) else: frequencies.append(np.sqrt(eig)) return np.array(frequencies) * self._factor def get_frequencies_with_eigenvectors(self, q): """ Calculate phonon frequencies and eigenvectors at q q: q-vector in reduced coordinates of primitive cell """ self._set_dynamical_matrix() self._dynamical_matrix.set_dynamical_matrix(q) dm = self._dynamical_matrix.get_dynamical_matrix() frequencies = [] eigvals, eigenvectors = np.linalg.eigh(dm) frequencies = [] for eig in eigvals: if eig < 0: frequencies.append(-np.sqrt(-eig)) else: frequencies.append(np.sqrt(eig)) return np.array(frequencies) * self._factor, eigenvectors def set_band_structure(self, bands, is_eigenvectors=False, is_band_connection=False): self._set_dynamical_matrix() self._band_structure = BandStructure( bands, self._dynamical_matrix, is_eigenvectors=is_eigenvectors, is_band_connection=is_band_connection, group_velocity=self._group_velocity, factor=self._factor) def get_band_structure(self): band = self._band_structure return (band.get_qpoints(), band.get_distances(), band.get_frequencies(), band.get_eigenvectors()) def plot_band_structure(self, symbols=None): return self._band_structure.plot_band(symbols) def write_yaml_band_structure(self): self._band_structure.write_yaml() def set_mesh(self, mesh, shift=None, is_time_reversal=True, is_mesh_symmetry=True, is_eigenvectors=False, is_gamma_center=False): self._set_dynamical_matrix() self._mesh = Mesh( self._dynamical_matrix, mesh, shift=shift, is_time_reversal=is_time_reversal, is_mesh_symmetry=is_mesh_symmetry, is_eigenvectors=is_eigenvectors, is_gamma_center=is_gamma_center, group_velocity=self._group_velocity, rotations=self._primitive_symmetry.get_pointgroup_operations(), factor=self._factor) def get_mesh(self): return (self._mesh.get_qpoints(), self._mesh.get_weights(), self._mesh.get_frequencies(), self._mesh.get_eigenvectors()) def write_yaml_mesh(self): self._mesh.write_yaml() def set_thermal_properties(self, t_step=10, t_max=1000, t_min=0, is_projection=False, band_indices=None, cutoff_frequency=None): if self._mesh is None: print "set_mesh has to be done before set_thermal_properties" return False else: tp = ThermalProperties(self._mesh.get_frequencies(), weights=self._mesh.get_weights(), eigenvectors=self._mesh.get_eigenvectors(), is_projection=is_projection, band_indices=band_indices, cutoff_frequency=cutoff_frequency) tp.set_thermal_properties(t_step=t_step, t_max=t_max, t_min=t_min) self._thermal_properties = tp def get_thermal_properties(self): temps, fe, entropy, cv = \ self._thermal_properties.get_thermal_properties() return temps, fe, entropy, cv def plot_thermal_properties(self): return self._thermal_properties.plot_thermal_properties() def write_yaml_thermal_properties(self, filename='thermal_properties.yaml'): self._thermal_properties.write_yaml(filename=filename) def set_partial_DOS(self, sigma=None, freq_min=None, freq_max=None, freq_pitch=None, tetrahedron_method=False, direction=None): if self._mesh is None: print "set_mesh has to be done before set_thermal_properties" sys.exit(1) if self._mesh.get_eigenvectors() is None: print "Eigenvectors have to be calculated." sys.exit(1) if direction is not None: direction_cart = np.dot(direction, self._primitive.get_cell()) else: direction_cart = None pdos = PartialDos(self._mesh, sigma=sigma, tetrahedron_method=tetrahedron_method, direction=direction_cart) pdos.set_draw_area(freq_min, freq_max, freq_pitch) pdos.run() self._pdos = pdos def get_partial_DOS(self): """ Retern frequencies and partial_dos. The first element is freqs and the second is partial_dos. frequencies: [freq1, freq2, ...] partial_dos: [[atom1-freq1, atom1-freq2, ...], [atom2-freq1, atom2-freq2, ...], ...] """ return self._pdos.get_partial_dos() def plot_partial_DOS(self, pdos_indices=None, legend=None): return self._pdos.plot_pdos(indices=pdos_indices, legend=legend) def write_partial_DOS(self): self._pdos.write() def set_total_DOS(self, sigma=None, freq_min=None, freq_max=None, freq_pitch=None, tetrahedron_method=False): if self._mesh is None: print "set_mesh has to be done before set_thermal_properties" sys.exit(1) total_dos = TotalDos(self._mesh, sigma=sigma, tetrahedron_method=tetrahedron_method) total_dos.set_draw_area(freq_min, freq_max, freq_pitch) total_dos.run() self._total_dos = total_dos def get_total_DOS(self): """ Retern frequencies and total dos. The first element is freqs and the second is total dos. frequencies: [freq1, freq2, ...] total_dos: [dos1, dos2, ...] """ return self._total_dos.get_dos() def set_Debye_frequency(self, freq_max_fit=None): self._total_dos.set_Debye_frequency( self._primitive.get_number_of_atoms(), freq_max_fit=freq_max_fit) def get_Debye_frequency(self): return self._total_dos.get_Debye_frequency() def plot_total_DOS(self): return self._total_dos.plot_dos() def write_total_DOS(self): self._total_dos.write() def set_thermal_displacements(self, t_step=10, t_max=1000, t_min=0, direction=None, cutoff_frequency=None): """ cutoff_frequency: phonon modes that have frequencies below cutoff_frequency are ignored. direction: Projection direction in reduced coordinates """ if self._mesh is None: print "set_mesh has to be done before set_thermal_properties" sys.exit(1) eigvecs = self._mesh.get_eigenvectors() frequencies = self._mesh.get_frequencies() mesh_nums = self._mesh.get_mesh_numbers() if self._mesh.get_eigenvectors() is None: print "Eigenvectors have to be calculated." sys.exit(1) if np.prod(mesh_nums) != len(eigvecs): print "Sampling mesh must not be symmetrized." sys.exit(1) td = ThermalDisplacements(frequencies, eigvecs, self._primitive.get_masses(), cutoff_frequency=cutoff_frequency) td.set_temperature_range(t_min, t_max, t_step) if direction is not None: td.project_eigenvectors(direction, self._primitive.get_cell()) td.run() self._thermal_displacements = td def get_thermal_displacements(self): if self._thermal_displacements is not None: return self._thermal_displacements.get_thermal_displacements() def plot_thermal_displacements(self, is_legend=False): return self._thermal_displacements.plot(is_legend) def write_yaml_thermal_displacements(self): self._thermal_displacements.write_yaml() def set_thermal_displacement_matrices(self, t_step=10, t_max=1000, t_min=0, cutoff_frequency=None): """ cutoff_frequency: phonon modes that have frequencies below cutoff_frequency are ignored. direction: Projection direction in reduced coordinates """ if self._mesh is None: print "set_mesh has to be done before set_thermal_properties" sys.exit(1) eigvecs = self._mesh.get_eigenvectors() frequencies = self._mesh.get_frequencies() mesh_nums = self._mesh.get_mesh_numbers() if self._mesh.get_eigenvectors() is None: print "Eigenvectors have to be calculated." sys.exit(1) if np.prod(mesh_nums) != len(eigvecs): print "Sampling mesh must not be symmetrized." sys.exit(1) tdm = ThermalDisplacementMatrices(frequencies, eigvecs, self._primitive.get_masses(), cutoff_frequency=cutoff_frequency) tdm.set_temperature_range(t_min, t_max, t_step) tdm.run() self._thermal_displacement_matrices = tdm def get_thermal_displacement_matrices(self): if self._thermal_displacement_matrices is not None: return self._thermal_displacement_matrices.get_thermal_displacement_matrices() def write_yaml_thermal_displacement_matrices(self): self._thermal_displacement_matrices.write_yaml() def set_thermal_distances(self, atom_pairs, t_step=10, t_max=1000, t_min=0, cutoff_frequency=None): """ atom_pairs: List of list Mean square distances are calculated for the atom_pairs e.g. [[1, 2], [1, 4]] cutoff_frequency: phonon modes that have frequencies below cutoff_frequency are ignored. """ td = ThermalDistances(self._mesh.get_frequencies(), self._mesh.get_eigenvectors(), self._supercell, self._primitive, self._mesh.get_qpoints(), cutoff_frequency=cutoff_frequency) td.set_temperature_range(t_min, t_max, t_step) td.run(atom_pairs) self._thermal_distances = td def write_yaml_thermal_distances(self): self._thermal_distances.write_yaml() def set_qpoints_phonon(self, q_points, nac_q_direction=None, is_eigenvectors=False, write_dynamical_matrices=False, factor=VaspToTHz): self._set_dynamical_matrix() self._qpoints_phonon = QpointsPhonon( q_points, self._dynamical_matrix, nac_q_direction=nac_q_direction, is_eigenvectors=is_eigenvectors, group_velocity=self._group_velocity, write_dynamical_matrices=write_dynamical_matrices, factor=self._factor) def get_qpoints_phonon(self): return (self._qpoints_phonon.get_frequencies(), self._qpoints_phonon.get_eigenvectors()) def write_yaml_qpoints_phonon(self): self._qpoints_phonon.write_yaml() def write_animation(self, q_point=None, anime_type='v_sim', band_index=None, amplitude=None, num_div=None, shift=None, filename=None): self._set_dynamical_matrix() if q_point is None: animation = Animation([0, 0, 0], self._dynamical_matrix, shift=shift) else: animation = Animation(q_point, self._dynamical_matrix, shift=shift) if anime_type == 'v_sim': if amplitude: amplitude_ = amplitude else: amplitude_ = 1.0 if filename: animation.write_v_sim(amplitude=amplitude_, factor=self._factor, filename=filename) else: animation.write_v_sim(amplitude=amplitude_, factor=self._factor) if (anime_type == 'arc' or anime_type == 'xyz' or anime_type == 'jmol' or anime_type == 'poscar'): if band_index is None or amplitude is None or num_div is None: print "Parameters are not correctly set for animation." sys.exit(1) if anime_type == 'arc' or anime_type is None: if filename: animation.write_arc(band_index, amplitude, num_div, filename=filename) else: animation.write_arc(band_index, amplitude, num_div) if anime_type == 'xyz': if filename: animation.write_xyz(band_index, amplitude, num_div, self._factor, filename=filename) else: animation.write_xyz(band_index, amplitude, num_div, self._factor) if anime_type == 'jmol': if filename: animation.write_xyz_jmol(amplitude=amplitude, factor=self._factor, filename=filename) else: animation.write_xyz_jmol(amplitude=amplitude, factor=self._factor) if anime_type == 'poscar': if filename: animation.write_POSCAR(band_index, amplitude, num_div, filename=filename) else: animation.write_POSCAR(band_index, amplitude, num_div) def set_modulations(self, dimension, phonon_modes, delta_q=None, derivative_order=None, nac_q_direction=None): self._set_dynamical_matrix() self._modulation = Modulation(self._dynamical_matrix, dimension, phonon_modes, delta_q=delta_q, derivative_order=derivative_order, nac_q_direction=nac_q_direction, factor=self._factor) self._modulation.run() def get_modulations(self): """Returns cells with modulations as Atoms objects""" return self._modulation.get_modulations() def get_delta_modulations(self): """Return modulations relative to equilibrium supercell (modulations, supercell) modulations: Atomic modulations of supercell in Cartesian coordinates supercell: Supercell as an Atoms object. """ return self._modulation.get_delta_modulations() def write_modulations(self): """Create MPOSCAR's""" self._modulation.write() def write_yaml_modulations(self): self._modulation.write_yaml() def set_irreps(self, q, is_little_cogroup=False, nac_q_direction=None, degeneracy_tolerance=1e-4): self._set_dynamical_matrix() self._irreps = IrReps( self._dynamical_matrix, q, is_little_cogroup=is_little_cogroup, nac_q_direction=nac_q_direction, factor=self._factor, symprec=self._symprec, degeneracy_tolerance=degeneracy_tolerance, log_level=self._log_level) return self._irreps.run() def get_irreps(self): return self._irreps def show_irreps(self, show_irreps=False): self._irreps.show(show_irreps=show_irreps) def write_yaml_irreps(self, show_irreps=False): self._irreps.write_yaml(show_irreps=show_irreps) def set_group_velocity(self, q_length=None): self._set_dynamical_matrix() self._group_velocity = GroupVelocity( self._dynamical_matrix, q_length=q_length, symmetry=self._primitive_symmetry, frequency_factor_to_THz=self._factor) def get_group_velocity(self): return self._group_velocity.get_group_velocity() def get_group_velocity_at_q(self, q_point): if self._group_velocity is None: self.set_group_velocity() self._group_velocity.set_q_points([q_point]) return self._group_velocity.get_group_velocity()[0] def _run_force_constants_from_forces(self, distributed_atom_list=None, decimals=None, computation_algorithm="svd"): if self._displacement_dataset is not None: self._force_constants = get_fc2( self._supercell, self._symmetry, self._displacement_dataset, atom_list=distributed_atom_list, decimals=decimals, computation_algorithm=computation_algorithm) def _set_dynamical_matrix(self): if self._nac_params is None: self._dynamical_matrix = DynamicalMatrix( self._supercell, self._primitive, self._force_constants, decimals=self._dynamical_matrix_decimals, symprec=self._symprec) else: self._dynamical_matrix = DynamicalMatrixNAC( self._supercell, self._primitive, self._force_constants, nac_params=self._nac_params, decimals=self._dynamical_matrix_decimals, symprec=self._symprec) def _search_symmetry(self): self._symmetry = Symmetry(self._supercell, self._symprec, self._is_symmetry) def _search_primitive_symmetry(self): self._primitive_symmetry = Symmetry(self._primitive, self._symprec, self._is_symmetry) if (len(self._symmetry.get_pointgroup_operations()) != len(self._primitive_symmetry.get_pointgroup_operations())): print ("Warning: point group symmetries of supercell and primitive" "cell are different.") def _build_supercell(self): self._supercell = get_supercell(self._unitcell, self._supercell_matrix, self._symprec) def _build_supercells_with_displacements(self): supercells = [] for disp in self._displacement_dataset['first_atoms']: positions = self._supercell.get_positions() positions[disp['number']] += disp['displacement'] supercells.append(Atoms( numbers=self._supercell.get_atomic_numbers(), masses=self._supercell.get_masses(), magmoms=self._supercell.get_magnetic_moments(), positions=positions, cell=self._supercell.get_cell(), pbc=True)) self._supercells_with_displacements = supercells def _build_primitive_cell(self): """ primitive_matrix: Relative axes of primitive cell to the input unit cell. Relative axes to the supercell is calculated by: supercell_matrix^-1 * primitive_matrix Therefore primitive cell lattice is finally calculated by: (supercell_lattice * (supercell_matrix)^-1 * primitive_matrix)^T """ inv_supercell_matrix = np.linalg.inv(self._supercell_matrix) if self._primitive_matrix is None: trans_mat = inv_supercell_matrix else: trans_mat = np.dot(inv_supercell_matrix, self._primitive_matrix) self._primitive = get_primitive( self._supercell, trans_mat, self._symprec) num_satom = self._supercell.get_number_of_atoms() num_patom = self._primitive.get_number_of_atoms() if abs(num_satom * np.linalg.det(trans_mat) - num_patom) < 0.1: return True else: return False
class Phono3py: def __init__(self, unitcell, supercell_matrix, primitive_matrix=None, phonon_supercell_matrix=None, masses=None, mesh=None, band_indices=None, sigmas=None, cutoff_frequency=1e-4, frequency_factor_to_THz=VaspToTHz, is_symmetry=True, is_nosym=False, symmetrize_fc3_q=False, symprec=1e-5, log_level=0, lapack_zheev_uplo='L'): if sigmas is None: sigmas = [] self._symprec = symprec self._sigmas = sigmas self._frequency_factor_to_THz = frequency_factor_to_THz self._is_symmetry = is_symmetry self._is_nosym = is_nosym self._lapack_zheev_uplo = lapack_zheev_uplo self._symmetrize_fc3_q = symmetrize_fc3_q self._cutoff_frequency = cutoff_frequency self._log_level = log_level # Create supercell and primitive cell self._unitcell = unitcell self._supercell_matrix = supercell_matrix self._primitive_matrix = primitive_matrix self._phonon_supercell_matrix = phonon_supercell_matrix # optional self._supercell = None self._primitive = None self._phonon_supercell = None self._phonon_primitive = None self._build_supercell() self._build_primitive_cell() self._build_phonon_supercell() self._build_phonon_primitive_cell() if masses is not None: self._set_masses(masses) # Set supercell, primitive, and phonon supercell symmetries self._symmetry = None self._primitive_symmetry = None self._phonon_supercell_symmetry = None self._search_symmetry() self._search_primitive_symmetry() self._search_phonon_supercell_symmetry() # Displacements and supercells self._supercells_with_displacements = None self._displacement_dataset = None self._phonon_displacement_dataset = None self._phonon_supercells_with_displacements = None # Thermal conductivity self._thermal_conductivity = None # conductivity_RTA object # Imaginary part of self energy at frequency points self._imag_self_energy = None self._scattering_event_class = None # Linewidth (Imaginary part of self energy x 2) at temperatures self._linewidth = None self._grid_points = None self._frequency_points = None self._temperatures = None # Other variables self._fc2 = None self._fc3 = None # Setup interaction self._interaction = None self._mesh = None self._band_indices = None self._band_indices_flatten = None if mesh is not None: self._mesh = np.array(mesh, dtype='intc') self.set_band_indices(band_indices) def set_band_indices(self, band_indices): if band_indices is None: num_band = self._primitive.get_number_of_atoms() * 3 self._band_indices = [np.arange(num_band, dtype='intc')] else: self._band_indices = band_indices self._band_indices_flatten = np.hstack(self._band_indices).astype('intc') def set_phph_interaction(self, nac_params=None, nac_q_direction=None, constant_averaged_interaction=None, frequency_scale_factor=None, unit_conversion=None): self._interaction = Interaction( self._supercell, self._primitive, self._mesh, self._primitive_symmetry, fc3=self._fc3, band_indices=self._band_indices_flatten, constant_averaged_interaction=constant_averaged_interaction, frequency_factor_to_THz=self._frequency_factor_to_THz, unit_conversion=unit_conversion, cutoff_frequency=self._cutoff_frequency, is_nosym=self._is_nosym, symmetrize_fc3_q=self._symmetrize_fc3_q, lapack_zheev_uplo=self._lapack_zheev_uplo) self._interaction.set_dynamical_matrix( self._fc2, self._phonon_supercell, self._phonon_primitive, nac_params=nac_params, frequency_scale_factor=frequency_scale_factor) self._interaction.set_nac_q_direction(nac_q_direction=nac_q_direction) def generate_displacements(self, distance=0.03, cutoff_pair_distance=None, is_plusminus='auto', is_diagonal=True): direction_dataset = get_third_order_displacements( self._supercell, self._symmetry, is_plusminus=is_plusminus, is_diagonal=is_diagonal) self._displacement_dataset = direction_to_displacement( direction_dataset, distance, self._supercell, cutoff_distance=cutoff_pair_distance) if self._phonon_supercell_matrix is not None: phonon_displacement_directions = get_least_displacements( self._phonon_supercell_symmetry, is_plusminus=is_plusminus, is_diagonal=False) self._phonon_displacement_dataset = direction_to_displacement_fc2( phonon_displacement_directions, distance, self._phonon_supercell) def produce_fc2(self, forces_fc2, displacement_dataset=None, is_permutation_symmetry=False, translational_symmetry_type=0): if displacement_dataset is None: disp_dataset = self._displacement_dataset else: disp_dataset = displacement_dataset for forces, disp1 in zip(forces_fc2, disp_dataset['first_atoms']): disp1['forces'] = forces self._fc2 = get_fc2(self._phonon_supercell, self._phonon_supercell_symmetry, disp_dataset) if is_permutation_symmetry: set_permutation_symmetry(self._fc2) if translational_symmetry_type: set_translational_invariance( self._fc2, translational_symmetry_type=translational_symmetry_type) def produce_fc3(self, forces_fc3, displacement_dataset=None, cutoff_distance=None, # set fc3 zero translational_symmetry_type=0, is_permutation_symmetry=False, is_permutation_symmetry_fc2=False): if displacement_dataset is None: disp_dataset = self._displacement_dataset else: disp_dataset = displacement_dataset for forces, disp1 in zip(forces_fc3, disp_dataset['first_atoms']): disp1['forces'] = forces fc2 = get_fc2(self._supercell, self._symmetry, disp_dataset) if is_permutation_symmetry_fc2: set_permutation_symmetry(fc2) if translational_symmetry_type: set_translational_invariance( fc2, translational_symmetry_type=translational_symmetry_type) count = len(disp_dataset['first_atoms']) for disp1 in disp_dataset['first_atoms']: for disp2 in disp1['second_atoms']: disp2['delta_forces'] = forces_fc3[count] - disp1['forces'] count += 1 self._fc3 = get_fc3( self._supercell, disp_dataset, fc2, self._symmetry, translational_symmetry_type=translational_symmetry_type, is_permutation_symmetry=is_permutation_symmetry, verbose=self._log_level) # Set fc3 elements zero beyond cutoff_distance if cutoff_distance: if self._log_level: print("Cutting-off fc3 by zero (cut-off distance: %f)" % cutoff_distance) self.cutoff_fc3_by_zero(cutoff_distance) # Set fc2 if self._fc2 is None: self._fc2 = fc2 def cutoff_fc3_by_zero(self, cutoff_distance): cutoff_fc3_by_zero(self._fc3, self._supercell, cutoff_distance, self._symprec) def set_permutation_symmetry(self): if self._fc2 is not None: set_permutation_symmetry(self._fc2) if self._fc3 is not None: set_permutation_symmetry_fc3(self._fc3) def set_translational_invariance(self, translational_symmetry_type=1): if self._fc2 is not None: set_translational_invariance( self._fc2, translational_symmetry_type=translational_symmetry_type) if self._fc3 is not None: set_translational_invariance_fc3( self._fc3, translational_symmetry_type=translational_symmetry_type) def get_interaction_strength(self): return self._interaction def get_fc2(self): return self._fc2 def set_fc2(self, fc2): self._fc2 = fc2 def get_fc3(self): return self._fc3 def set_fc3(self, fc3): self._fc3 = fc3 def get_primitive(self): return self._primitive def get_unitcell(self): return self._unitcell def get_supercell(self): return self._supercell def get_phonon_supercell(self): return self._phonon_supercell def get_phonon_primitive(self): return self._phonon_primitive def get_symmetry(self): """return symmetry of supercell""" return self._symmetry def get_primitive_symmetry(self): return self._primitive_symmetry def get_phonon_supercell_symmetry(self): return self._phonon_supercell_symmetry def set_displacement_dataset(self, dataset): self._displacement_dataset = dataset def get_displacement_dataset(self): return self._displacement_dataset def get_phonon_displacement_dataset(self): return self._phonon_displacement_dataset def get_supercells_with_displacements(self): if self._supercells_with_displacements is None: self._build_supercells_with_displacements() return self._supercells_with_displacements def get_phonon_supercells_with_displacements(self): if self._phonon_supercells_with_displacements is None: if self._phonon_displacement_dataset is not None: self._phonon_supercells_with_displacements = \ self._build_phonon_supercells_with_displacements( self._phonon_supercell, self._phonon_displacement_dataset) return self._phonon_supercells_with_displacements def run_imag_self_energy(self, grid_points, frequency_step=None, num_frequency_points=None, temperatures=None, scattering_event_class=None, run_with_g=True, write_details=False): if temperatures is None: temperatures = [0.0, 300.0] self._grid_points = grid_points self._temperatures = temperatures self._scattering_event_class = scattering_event_class self._imag_self_energy, self._frequency_points = get_imag_self_energy( self._interaction, grid_points, self._sigmas, frequency_step=frequency_step, num_frequency_points=num_frequency_points, temperatures=temperatures, scattering_event_class=scattering_event_class, run_with_g=run_with_g, write_details=write_details, log_level=self._log_level) def write_imag_self_energy(self, filename=None): write_imag_self_energy( self._imag_self_energy, self._mesh, self._grid_points, self._band_indices, self._frequency_points, self._temperatures, self._sigmas, scattering_event_class=self._scattering_event_class, filename=filename) def run_linewidth(self, grid_points, temperatures=np.arange(0, 1001, 10, dtype='double'), run_with_g=True, write_details=False): self._grid_points = grid_points self._temperatures = temperatures self._linewidth = get_linewidth(self._interaction, grid_points, self._sigmas, temperatures=temperatures, run_with_g=run_with_g, write_details=write_details, log_level=self._log_level) def write_linewidth(self, filename=None): write_linewidth(self._linewidth, self._band_indices, self._mesh, self._grid_points, self._sigmas, self._temperatures, filename=filename) def run_thermal_conductivity( self, is_LBTE=True, temperatures=np.arange(0, 1001, 10, dtype='double'), sigmas=None, is_isotope=False, mass_variances=None, grid_points=None, boundary_mfp=None, # in micrometre use_averaged_pp_interaction=False, gamma_unit_conversion=None, mesh_divisors=None, coarse_mesh_shifts=None, is_reducible_collision_matrix=False, no_kappa_stars=False, gv_delta_q=None, # for group velocity run_with_g=True, # integration weights for smearing method, too pinv_cutoff=1.0e-8, # for pseudo-inversion of collision matrix write_gamma=False, read_gamma=False, write_collision=False, read_collision=False, write_amplitude=False, read_amplitude=False, input_filename=None, output_filename=None): if sigmas is None: sigmas = [] if is_LBTE: self._thermal_conductivity = get_thermal_conductivity_LBTE( self._interaction, self._primitive_symmetry, temperatures=temperatures, sigmas=self._sigmas, is_isotope=is_isotope, mass_variances=mass_variances, grid_points=grid_points, boundary_mfp=boundary_mfp, is_reducible_collision_matrix=is_reducible_collision_matrix, no_kappa_stars=no_kappa_stars, gv_delta_q=gv_delta_q, pinv_cutoff=pinv_cutoff, write_collision=write_collision, read_collision=read_collision, input_filename=input_filename, output_filename=output_filename, log_level=self._log_level) else: self._thermal_conductivity = get_thermal_conductivity_RTA( self._interaction, self._primitive_symmetry, temperatures=temperatures, sigmas=self._sigmas, is_isotope=is_isotope, mass_variances=mass_variances, grid_points=grid_points, boundary_mfp=boundary_mfp, use_averaged_pp_interaction=use_averaged_pp_interaction, gamma_unit_conversion=gamma_unit_conversion, mesh_divisors=mesh_divisors, coarse_mesh_shifts=coarse_mesh_shifts, no_kappa_stars=no_kappa_stars, gv_delta_q=gv_delta_q, run_with_g=run_with_g, write_gamma=write_gamma, read_gamma=read_gamma, input_filename=input_filename, output_filename=output_filename, log_level=self._log_level) def get_thermal_conductivity(self): return self._thermal_conductivity def get_frequency_shift(self, grid_points, epsilons=None, temperatures=np.arange(0, 1001, 10, dtype='double'), output_filename=None): if epsilons is None: epsilons = [0.1] self._grid_points = grid_points get_frequency_shift(self._interaction, self._grid_points, self._band_indices, epsilons, temperatures, output_filename=output_filename, log_level=self._log_level) def _search_symmetry(self): self._symmetry = Symmetry(self._supercell, self._symprec, self._is_symmetry) def _search_primitive_symmetry(self): self._primitive_symmetry = Symmetry(self._primitive, self._symprec, self._is_symmetry) if (len(self._symmetry.get_pointgroup_operations()) != len(self._primitive_symmetry.get_pointgroup_operations())): print("Warning: point group symmetries of supercell and primitive" "cell are different.") def _search_phonon_supercell_symmetry(self): if self._phonon_supercell_matrix is None: self._phonon_supercell_symmetry = self._symmetry else: self._phonon_supercell_symmetry = Symmetry(self._phonon_supercell, self._symprec, self._is_symmetry) def _build_supercell(self): self._supercell = get_supercell(self._unitcell, self._supercell_matrix, self._symprec) def _build_primitive_cell(self): """ primitive_matrix: Relative axes of primitive cell to the input unit cell. Relative axes to the supercell is calculated by: supercell_matrix^-1 * primitive_matrix Therefore primitive cell lattice is finally calculated by: (supercell_lattice * (supercell_matrix)^-1 * primitive_matrix)^T """ self._primitive = self._get_primitive_cell( self._supercell, self._supercell_matrix, self._primitive_matrix) def _build_phonon_supercell(self): """ phonon_supercell: This supercell is used for harmonic phonons (frequencies, eigenvectors, group velocities, ...) phonon_supercell_matrix: Different supercell size can be specified. """ if self._phonon_supercell_matrix is None: self._phonon_supercell = self._supercell else: self._phonon_supercell = get_supercell( self._unitcell, self._phonon_supercell_matrix, self._symprec) def _build_phonon_primitive_cell(self): if self._phonon_supercell_matrix is None: self._phonon_primitive = self._primitive else: self._phonon_primitive = self._get_primitive_cell( self._phonon_supercell, self._phonon_supercell_matrix, self._primitive_matrix) if self._primitive is not None: if (self._primitive.get_atomic_numbers() != self._phonon_primitive.get_atomic_numbers()).any(): print("********************* Warning *********************") print(" Primitive cells for fc2 and fc3 can be different.") print("********************* Warning *********************") def _build_phonon_supercells_with_displacements(self, supercell, displacement_dataset): supercells = [] magmoms = supercell.get_magnetic_moments() masses = supercell.get_masses() numbers = supercell.get_atomic_numbers() lattice = supercell.get_cell() for disp1 in displacement_dataset['first_atoms']: disp_cart1 = disp1['displacement'] positions = supercell.get_positions() positions[disp1['number']] += disp_cart1 supercells.append( Atoms(numbers=numbers, masses=masses, magmoms=magmoms, positions=positions, cell=lattice, pbc=True)) return supercells def _build_supercells_with_displacements(self): supercells = [] magmoms = self._supercell.get_magnetic_moments() masses = self._supercell.get_masses() numbers = self._supercell.get_atomic_numbers() lattice = self._supercell.get_cell() supercells = self._build_phonon_supercells_with_displacements( self._supercell, self._displacement_dataset) for disp1 in self._displacement_dataset['first_atoms']: disp_cart1 = disp1['displacement'] for disp2 in disp1['second_atoms']: if 'included' in disp2: included = disp2['included'] else: included = True if included: positions = self._supercell.get_positions() positions[disp1['number']] += disp_cart1 positions[disp2['number']] += disp2['displacement'] supercells.append(Atoms(numbers=numbers, masses=masses, magmoms=magmoms, positions=positions, cell=lattice, pbc=True)) else: supercells.append(None) self._supercells_with_displacements = supercells def _get_primitive_cell(self, supercell, supercell_matrix, primitive_matrix): inv_supercell_matrix = np.linalg.inv(supercell_matrix) if primitive_matrix is None: t_mat = inv_supercell_matrix else: t_mat = np.dot(inv_supercell_matrix, primitive_matrix) return get_primitive(supercell, t_mat, self._symprec) def _set_masses(self, masses): p_masses = np.array(masses) self._primitive.set_masses(p_masses) p2p_map = self._primitive.get_primitive_to_primitive_map() s_masses = p_masses[[p2p_map[x] for x in self._primitive.get_supercell_to_primitive_map()]] self._supercell.set_masses(s_masses) u2s_map = self._supercell.get_unitcell_to_supercell_map() u_masses = s_masses[u2s_map] self._unitcell.set_masses(u_masses) self._phonon_primitive.set_masses(p_masses) p2p_map = self._phonon_primitive.get_primitive_to_primitive_map() s_masses = p_masses[ [p2p_map[x] for x in self._phonon_primitive.get_supercell_to_primitive_map()]] self._phonon_supercell.set_masses(s_masses)
self._set_x_tags('xred') def _set_x_tags(self, tagname): xtag = [] natom = self._tags['natom'] for val in self._values: xtag += self._get_numerical_values(val) if len(xtag) >= natom * 3: break self._tags[tagname] = np.reshape(xtag[:natom * 3], (-1, 3)) def _set_znucl(self): znucl = [] ntypat = self._tags['ntypat'] for val in self._values: znucl += self._get_numerical_values(val, num_type='int') if len(znucl) >= ntypat: break self._tags['znucl'] = znucl[:ntypat] if __name__ == '__main__': import sys from phonopy.structure.symmetry import Symmetry abinit = AbinitIn(open(sys.argv[1]).readlines()) cell = read_abinit(sys.argv[1]) symmetry = Symmetry(cell) print("# %s" % symmetry.get_international_table()) print(get_abinit_structure(cell))
self._tags['plat'] = plat def _set_alat(self, header): hlist = header.split() for j in hlist: if j.startswith('alat'): alat = float(j.split('=')[1]) break self._tags['alat'] = alat def _check_ord(self, header): if not 'xpos' in header.split(): print('EXIT(1): LMTO Interface requires site', end=' ') print('files to be in fractional co-ordinates') sys.exit(1) def get_variables(self, header, sites): self._check_ord(header) self._set_atoms(sites) self._set_plat(header) self._set_alat(header) return self._tags if __name__ == '__main__': import sys from phonopy.structure.symmetry import Symmetry cell = read_lmto(sys.argv[1]) symmetry = Symmetry(cell) print('# %s' % symmetry.get_international_table()) print(get_lmto_structure(cell))
def _search_symmetry(self): self._symmetry = Symmetry(self._supercell, self._symprec, self._is_symmetry)
class JointDos: def __init__(self, mesh, primitive, supercell, fc2, nac_params=None, nac_q_direction=None, sigma=None, cutoff_frequency=None, frequency_step=None, num_frequency_points=None, temperatures=None, frequency_factor_to_THz=VaspToTHz, frequency_scale_factor=1.0, is_nosym=False, symprec=1e-5, filename=None, log_level=False, lapack_zheev_uplo='L'): self._grid_point = None self._mesh = np.array(mesh, dtype='intc') self._primitive = primitive self._supercell = supercell self._fc2 = fc2 self._nac_params = nac_params self._nac_q_direction = None self.set_nac_q_direction(nac_q_direction) self._sigma = None self.set_sigma(sigma) if cutoff_frequency is None: self._cutoff_frequency = 0 else: self._cutoff_frequency = cutoff_frequency self._frequency_step = frequency_step self._num_frequency_points = num_frequency_points self._temperatures = temperatures self._frequency_factor_to_THz = frequency_factor_to_THz self._frequency_scale_factor = frequency_scale_factor self._is_nosym = is_nosym self._symprec = symprec self._filename = filename self._log_level = log_level self._lapack_zheev_uplo = lapack_zheev_uplo self._num_band = self._primitive.get_number_of_atoms() * 3 self._reciprocal_lattice = np.linalg.inv(self._primitive.get_cell()) self._set_dynamical_matrix() self._symmetry = Symmetry(primitive, symprec) self._tetrahedron_method = None self._phonon_done = None self._frequencies = None self._eigenvectors = None self._joint_dos = None self._frequency_points = None def run(self): try: import anharmonic._phono3py as phono3c self._run_c() except ImportError: print "Joint density of states in python is not implemented." return None, None def get_joint_dos(self): return self._joint_dos def get_frequency_points(self): return self._frequency_points def get_phonons(self): return self._frequencies, self._eigenvectors, self._phonon_done def get_primitive(self): return self._primitive def get_mesh_numbers(self): return self._mesh def set_nac_q_direction(self, nac_q_direction=None): if nac_q_direction is not None: self._nac_q_direction = np.array(nac_q_direction, dtype='double') def set_sigma(self, sigma): if sigma is None: self._sigma = None else: self._sigma = float(sigma) def set_grid_point(self, grid_point): self._grid_point = grid_point self._set_triplets() num_grid = np.prod(len(self._grid_address)) num_band = self._num_band if self._phonon_done is None: self._phonon_done = np.zeros(num_grid, dtype='byte') self._frequencies = np.zeros((num_grid, num_band), dtype='double') self._eigenvectors = np.zeros((num_grid, num_band, num_band), dtype='complex128') self._joint_dos = None self._frequency_points = None self.set_phonon(np.array([grid_point], dtype='intc')) def get_triplets_at_q(self): return self._triplets_at_q, self._weights_at_q def get_grid_address(self): return self._grid_address def get_bz_map(self): return self._bz_map def _run_c(self, lang='C'): if self._sigma is None: if lang == 'C': self._run_c_with_g() else: if self._temperatures is not None: print "JDOS with phonon occupation numbers doesn't work", print "in this option." self._run_py_tetrahedron_method() else: self._run_c_with_g() # self._run_smearing_method() is an older and direct implementation. # This requies less memory space. self._run_c_with_g can be used # for smearing method and can share same code with tetrahedron # method. Therefore maintainance cost of code can be reduced by # without using self._run_smearing_method(). def _run_c_with_g(self): self.set_phonon(self._triplets_at_q.ravel()) if self._sigma is None: f_max = np.max(self._frequencies) * 2 else: f_max = np.max(self._frequencies) * 2 + self._sigma * 4 f_max *= 1.005 f_min = 0 self._set_frequency_points(f_min, f_max) num_freq_points = len(self._frequency_points) num_mesh = np.prod(self._mesh) if self._temperatures is None: jdos = np.zeros((num_freq_points, 2), dtype='double') else: num_temps = len(self._temperatures) jdos = np.zeros((num_temps, num_freq_points, 2), dtype='double') occ_phonons = [] for t in self._temperatures: freqs = self._frequencies[self._triplets_at_q[:, 1:]] occ_phonons.append(np.where(freqs > self._cutoff_frequency, occupation(freqs, t), 0)) for i, freq_point in enumerate(self._frequency_points): g = get_triplets_integration_weights( self, np.array([freq_point], dtype='double'), self._sigma, is_collision_matrix=True, neighboring_phonons=(i == 0)) if self._temperatures is None: jdos[i, 0] = np.sum( np.tensordot(g[0, :, 0], self._weights_at_q, axes=(0, 0))) gx = g[2] - g[0] jdos[i, 1] = np.sum( np.tensordot(gx[:, 0], self._weights_at_q, axes=(0, 0))) else: for j, n in enumerate(occ_phonons): for k, l in list(np.ndindex(g.shape[3:])): jdos[j, i, 0] += np.dot( (n[:, 0, k] + n[:, 1, l] + 1) * g[0, :, 0, k, l], self._weights_at_q) jdos[j, i, 1] += np.dot((n[:, 0, k] - n[:, 1, l]) * g[1, :, 0, k, l], self._weights_at_q) self._joint_dos = jdos / num_mesh def _run_py_tetrahedron_method(self): thm = TetrahedronMethod(self._reciprocal_lattice, mesh=self._mesh) self._vertices = get_tetrahedra_vertices( thm.get_tetrahedra(), self._mesh, self._triplets_at_q, self._grid_address, self._bz_map) self.set_phonon(self._vertices.ravel()) f_max = np.max(self._frequencies) * 2 f_max *= 1.005 f_min = 0 self._set_frequency_points(f_min, f_max) num_freq_points = len(self._frequency_points) jdos = np.zeros((num_freq_points, 2), dtype='double') for vertices, w in zip(self._vertices, self._weights_at_q): for i, j in list(np.ndindex(self._num_band, self._num_band)): f1 = self._frequencies[vertices[0], i] f2 = self._frequencies[vertices[1], j] thm.set_tetrahedra_omegas(f1 + f2) thm.run(self._frequency_points) iw = thm.get_integration_weight() jdos[:, 0] += iw * w thm.set_tetrahedra_omegas(f1 - f2) thm.run(self._frequency_points) iw = thm.get_integration_weight() jdos[:, 1] += iw * w thm.set_tetrahedra_omegas(-f1 + f2) thm.run(self._frequency_points) iw = thm.get_integration_weight() jdos[:, 1] += iw * w self._joint_dos = jdos / np.prod(self._mesh) def _run_smearing_method(self): import anharmonic._phono3py as phono3c self.set_phonon(self._triplets_at_q.ravel()) f_max = np.max(self._frequencies) * 2 + self._sigma * 4 f_min = np.min(self._frequencies) * 2 - self._sigma * 4 self._set_frequency_points(f_min, f_max) jdos = np.zeros((len(self._frequency_points), 2), dtype='double') phono3c.joint_dos(jdos, self._frequency_points, self._triplets_at_q, self._weights_at_q, self._frequencies, self._sigma) jdos /= np.prod(self._mesh) self._joint_dos = jdos def _set_dynamical_matrix(self): self._dm = get_dynamical_matrix( self._fc2, self._supercell, self._primitive, nac_params=self._nac_params, frequency_scale_factor=self._frequency_scale_factor, symprec=self._symprec) def _set_triplets(self): if self._is_nosym: if self._log_level: print "Triplets at q without considering symmetry" sys.stdout.flush() (self._triplets_at_q, self._weights_at_q, self._grid_address, self._bz_map, map_triplets, map_q) = get_nosym_triplets_at_q( self._grid_point, self._mesh, self._reciprocal_lattice, with_bz_map=True) else: (self._triplets_at_q, self._weights_at_q, self._grid_address, self._bz_map, map_triplets, map_q) = get_triplets_at_q( self._grid_point, self._mesh, self._symmetry.get_pointgroup_operations(), self._reciprocal_lattice) def set_phonon(self, grid_points): set_phonon_c(self._dm, self._frequencies, self._eigenvectors, self._phonon_done, grid_points, self._grid_address, self._mesh, self._frequency_factor_to_THz, self._nac_q_direction, self._lapack_zheev_uplo) def _set_frequency_points(self, f_min, f_max): if self._num_frequency_points is None: if self._frequency_step is not None: self._frequency_points = np.arange( f_min, f_max, self._frequency_step, dtype='double') else: self._frequency_points = np.array(np.linspace( f_min, f_max, 201), dtype='double') else: self._frequency_points = np.array(np.linspace( f_min, f_max, self._num_frequency_points), dtype='double')
class PhonopyUnfolding(Phonopy): """ unitcell: before symmetrization """ def __init__(self, unitcell, unitcell_ideal, supercell_matrix, primitive_matrix_ideal, nac_params=None, distance=0.01, factor=VaspToTHz, is_auto_displacements=True, dynamical_matrix_decimals=None, force_constants_decimals=None, star="none", mode="eigenvector", symprec=1e-5, is_symmetry=True, use_lapack_solver=False, log_level=0): self._symprec = symprec self._distance = distance self._factor = factor self._is_auto_displacements = is_auto_displacements self._is_symmetry = is_symmetry self._use_lapack_solver = use_lapack_solver self._log_level = log_level # Create supercell and primitive cell self._unitcell = unitcell self._unitcell_ideal = unitcell_ideal self._supercell_matrix = supercell_matrix self._primitive_matrix = None self._primitive_matrix_ideal = primitive_matrix_ideal self._supercell = None self._primitive = None self._build_supercell() self._build_primitive_cell() self._build_supercell_ideal() self._build_primitive_cell_ideal() # Set supercell and primitive symmetry self._symmetry = None self._primitive_symmetry = None self._search_symmetry() self._search_primitive_symmetry() self._search_symmetry_ideal() self._search_primitive_symmetry_ideal() # set_force_constants or set_forces self._force_constants = None self._force_constants_decimals = force_constants_decimals # set_dynamical_matrix self._dynamical_matrix = None self._nac_params = nac_params self._dynamical_matrix_decimals = dynamical_matrix_decimals # set_band_structure self._band_structure = None # set_mesh self._mesh = None # set_tetrahedron_method self._tetrahedron_method = None # set_thermal_properties self._thermal_properties = None # set_thermal_displacements self._thermal_displacements = None # set_thermal_displacement_matrices self._thermal_displacement_matrices = None # set_partial_DOS self._pdos = None # set_total_DOS self._total_dos = None # set_modulation self._modulation = None # set_character_table self._irreps = None # set_group_velocity self._group_velocity = None self._star = star self._mode = mode # Single point def run_single_point(self, qpoint, distance): SinglePoint( qpoint, distance, dynamical_matrix=self._dynamical_matrix, unitcell_ideal=self._unitcell_ideal, primitive_matrix_ideal=self._primitive_matrix_ideal, factor=self._factor, star=self._star, mode=self._mode, verbose=True) # Band structure def set_band_structure(self, bands, is_eigenvectors=False, is_band_connection=False): if self._dynamical_matrix is None: print("Warning: Dynamical matrix has not yet built.") self._band_structure = None return False self._band_structure = BandStructure( bands, self._dynamical_matrix, self._unitcell_ideal, self._primitive_matrix_ideal, is_eigenvectors=is_eigenvectors, is_band_connection=is_band_connection, group_velocity=self._group_velocity, factor=self._factor, star=self._star, mode=self._mode, verbose=True) return True # Sampling mesh def set_mesh(self, mesh, shift=None, is_time_reversal=True, is_mesh_symmetry=True, is_eigenvectors=False, is_gamma_center=False): if self._dynamical_matrix is None: print("Warning: Dynamical matrix has not yet built.") self._mesh = None return False # TODO(ikeda): Check how "rotations" works. self._mesh = MeshUnfolding( self._dynamical_matrix, self._unitcell_ideal, self._primitive_matrix_ideal, mesh, shift=shift, is_time_reversal=is_time_reversal, is_mesh_symmetry=is_mesh_symmetry, is_eigenvectors=is_eigenvectors, is_gamma_center=is_gamma_center, star=self._star, group_velocity=self._group_velocity, rotations=self._primitive_symmetry.get_pointgroup_operations(), factor=self._factor, use_lapack_solver=self._use_lapack_solver, mode=self._mode) return True # DOS def set_total_DOS(self, sigma=None, freq_min=None, freq_max=None, freq_pitch=None, tetrahedron_method=False): if self._mesh is None: print("Warning: \'set_mesh\' has to finish correctly " "before DOS calculation.") self._total_dos = None return False total_dos = TotalDosUnfolding( self._mesh, sigma=sigma, tetrahedron_method=tetrahedron_method) total_dos.set_draw_area(freq_min, freq_max, freq_pitch) total_dos.run() self._total_dos = total_dos return True def _set_dynamical_matrix(self): self._dynamical_matrix = None if self._supercell is None or self._primitive is None: print("Bug: Supercell or primitive is not created.") return False elif self._force_constants is None: print("Warning: Force constants are not prepared.") return False elif self._primitive.get_masses() is None: print("Warning: Atomic masses are not correctly set.") return False else: if self._nac_params is None: self._dynamical_matrix = DynamicalMatrix( self._supercell, self._primitive, self._force_constants, decimals=self._dynamical_matrix_decimals, symprec=self._symprec) else: raise ValueError( 'Currently NAC is not available for unfolding.') return True def _search_symmetry_ideal(self): self._symmetry = Symmetry(self._supercell_ideal, self._symprec, self._is_symmetry) def _search_primitive_symmetry_ideal(self): self._primitive_symmetry = Symmetry(self._primitive_ideal, self._symprec, self._is_symmetry) n0 = len(self._symmetry.get_pointgroup_operations()) n1 = len(self._primitive_symmetry.get_pointgroup_operations()) if n0 != n1: raise Warning("Point group symmetries of supercell and primitive" "cell are different.") def _build_supercell_ideal(self): self._supercell_ideal = get_supercell( self._unitcell_ideal, self._supercell_matrix, self._symprec) def _build_primitive_cell_ideal(self): """ primitive_matrix: Relative axes of primitive cell to the input unit cell. Relative axes to the supercell is calculated by: supercell_matrix^-1 * primitive_matrix Therefore primitive cell lattice is finally calculated by: (supercell_lattice * (supercell_matrix)^-1 * primitive_matrix)^T """ inv_supercell_matrix = np.linalg.inv(self._supercell_matrix) if self._primitive_matrix_ideal is None: trans_mat = inv_supercell_matrix else: trans_mat = np.dot(inv_supercell_matrix, self._primitive_matrix_ideal) self._primitive_ideal = get_primitive( self._supercell_ideal, trans_mat, self._symprec) num_satom = self._supercell_ideal.get_number_of_atoms() num_patom = self._primitive_ideal.get_number_of_atoms() if abs(num_satom * np.linalg.det(trans_mat) - num_patom) < 0.1: return True else: return False def average_masses(self): masses = self._unitcell.get_masses() masses_average = calculate_average_masses( masses, Symmetry(self._unitcell_ideal)) self._unitcell.set_masses(masses_average) self._build_supercell() self._build_primitive_cell() self._search_symmetry() self._search_primitive_symmetry() def average_force_constants(self): fc_symmetrizer_spg = FCSymmetrizerSPG( force_constants=self._force_constants, atoms=self._unitcell, atoms_ideal=self._unitcell_ideal, supercell_matrix=self._supercell_matrix, ) fc_symmetrizer_spg.average_force_constants_spg() fc_symmetrizer_spg.write_force_constants_symmetrized() fc_average = fc_symmetrizer_spg.get_force_constants_symmetrized() self.set_force_constants(fc_average) # Dynamical matrices are also prepared inside.
magmom = [] for numxmag in text.split(): if '*' in numxmag: num, mag = numxmag.split('*') magmom += [float(mag)] * int(num) else: magmom.append(float(numxmag)) return magmom def parse_incar(filename): for line in open(filename): for conf in line.split(';'): if 'MAGMOM' in conf: return get_magmom(conf.split('=')[1]) cell = read_vasp("POSCAR") symmetry = Symmetry(cell, symprec=1e-3) map_nonspin = symmetry.get_map_atoms() print "Number of operations w/o spin", len(symmetry.get_symmetry_operations()['rotations']) magmoms = parse_incar("INCAR") cell.set_magnetic_moments(magmoms) symmetry = Symmetry(cell, symprec=1e-3) print "Number of operations w spin", len(symmetry.get_symmetry_operations()['rotations']) map_withspin = symmetry.get_map_atoms() if ((map_nonspin - map_withspin) == 0).all(): print True else: print False print map_nonspin print map_withspin
elif tag == "atomiccoordinatesandatomicspecies": lines = block.split('\n')[:-1] self._tags["atomiccoordinates"] = [ [float(x) for x in atom.split()[:3]] for atom in lines ] self._tags["atomicspecies"] = [ int(atom.split()[3]) for atom in lines] #check if the block are present self.check_present("atomicspecies") self.check_present("atomiccoordinates") self.check_present("latticevectors") self.check_present("chemicalspecieslabel") #translate the atomicspecies to atomic numbers self._tags["atomicnumbers"] = [self._tags["atomicnumbers"][atype] for atype in self._tags["atomicspecies"]] def check_present(self,tag): if not self._tags[tag]: print "%s not present"%tag exit() def __str__(): return self._tags if __name__ == '__main__': import sys from phonopy.structure.symmetry import Symmetry cell,atypes = read_siesta(sys.argv[1]) symmetry = Symmetry(cell) print "#", symmetry.get_international_table() print get_siesta_structure(cell,atypes)
shortest_indices = [i for i, d in enumerate(distances - min_dist) if abs(d) < self._tolerance] self._shortest_qpoints.append( np.dot(search_space[shortest_indices] + q, self._tmat.T)) def get_shortest_qpoints(self): return self._shortest_qpoints if __name__ == '__main__': from phonopy.interface.vasp import read_vasp from phonopy.structure.symmetry import Symmetry, get_lattice_vector_equivalence from phonopy.structure.spglib import get_ir_reciprocal_mesh, relocate_BZ_grid_address import sys cell = read_vasp(sys.argv[1]) symmetry = Symmetry(cell) mesh = [4, 4, 4] is_shift = np.array([0, 0, 0], dtype='intc') mapping_table, grid_address = get_ir_reciprocal_mesh( mesh, cell, is_shift=is_shift) ir_grid_points = np.unique(mapping_table) primitive_vectors = np.linalg.inv(cell.get_cell()) bz_grid_address, bz_map = relocate_BZ_grid_address( grid_address, mesh, np.linalg.inv(cell.get_cell()), is_shift=is_shift) bz_points = np.extract(bz_map > -1, bz_map)