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 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, 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 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 _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 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 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 _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 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 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 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_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 get_born_OUTCAR(poscar_filename="POSCAR", outcar_filename="OUTCAR", primitive_matrix=None, supercell_matrix=None, is_symmetry=True, symmetrize_tensors=False, symprec=1e-5): if primitive_matrix is None: pmat = np.eye(3) else: pmat = primitive_matrix if supercell_matrix is None: smat = np.eye(3, dtype='intc') else: smat = supercell_matrix ucell = read_vasp(poscar_filename) outcar = open(outcar_filename) borns, epsilon = _read_born_and_epsilon(outcar) num_atom = len(borns) assert num_atom == ucell.get_number_of_atoms() if symmetrize_tensors: lattice = ucell.get_cell().T positions = ucell.get_scaled_positions() u_sym = Symmetry(ucell, is_symmetry=is_symmetry, symprec=symprec) point_sym = [ similarity_transformation(lattice, r) for r in u_sym.get_pointgroup_operations() ] epsilon = _symmetrize_tensor(epsilon, point_sym) borns = _symmetrize_borns(borns, u_sym, lattice, positions, symprec) inv_smat = np.linalg.inv(smat) scell = get_supercell(ucell, smat, symprec=symprec) pcell = get_primitive(scell, np.dot(inv_smat, pmat), symprec=symprec) p2s = np.array(pcell.get_primitive_to_supercell_map(), dtype='intc') p_sym = Symmetry(pcell, is_symmetry=is_symmetry, symprec=symprec) s_indep_atoms = p2s[p_sym.get_independent_atoms()] u2u = scell.get_unitcell_to_unitcell_map() u_indep_atoms = [u2u[x] for x in s_indep_atoms] reduced_borns = borns[u_indep_atoms].copy() return reduced_borns, epsilon, s_indep_atoms
def get_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_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 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 not 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 print "" force_set = forces elif not 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) < 0.00001).all(): forces_remap.append( np.dot(forces[i], rotations[map_operations[j]].T)) indep_atoms_to_wien2k.append(map_atoms[j]) break if not 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): force_set.append( np.dot(forces_remap[indep_atoms_to_wien2k.index(map_atoms[i])], rotations[map_operations[i]])) return force_set
def average_force_constants_spg(self, symprec=1e-5): atoms = self._atoms fc_orig = self._force_constants atoms_symmetry = self._atoms_ideal symmetry = Symmetry(atoms_symmetry) symbols = atoms.get_chemical_symbols() symboltypes = sorted(set(symbols), key=symbols.index) rotations_cart = get_rotations_cart(atoms_symmetry) mappings = StructureAnalyzer( atoms_symmetry).get_mappings_for_symops(prec=symprec) mappings_inv = MappingsModifier(mappings).invert_mappings() print("mappings: Finished.") (nsym, natoms) = mappings.shape print("nsym: {}".format(nsym)) print("natoms: {}".format(natoms)) fc_mean = np.zeros_like(fc_orig) fc_mean_square = np.zeros_like(fc_orig) fc_mean_symbols, fc_mean_square_symbols, fc_std_symbols, counters = ( self.initialize_fc_symbols(fc_orig, symboltypes) ) for (minv, r) in zip(mappings_inv, rotations_cart): for i1 in symmetry.get_independent_atoms(): for i2 in range(natoms): j1 = minv[i1] j2 = minv[i2] s1 = symbols[j1] s2 = symbols[j2] tmp = np.dot(np.dot(r, fc_orig[j1, j2]), r.T) tmp2 = tmp ** 2 fc_mean[i1, i2] += tmp fc_mean_square[i1, i2] += tmp2 fc_mean_symbols[(s1, s2)][i1, i2] += tmp fc_mean_square_symbols[(s1, s2)][i1, i2] += tmp2 counters[(s1, s2)][i1, i2] += 1 fc_mean /= float(len(rotations_cart)) fc_mean_square /= float(len(rotations_cart)) for i1 in symmetry.get_independent_atoms(): for i2 in range(natoms): for (key, c) in counters.items(): if c[i1, i2] != 0: fc_mean_symbols [key][i1, i2] /= c[i1, i2] fc_mean_square_symbols[key][i1, i2] /= c[i1, i2] else: fc_mean_symbols [key][i1, i2] = np.nan fc_mean_square_symbols[key][i1, i2] = np.nan ######################################## # STD ######################################## fc_std = get_matrix_std(fc_mean, fc_mean_square) for key in counters.keys(): fc_std_symbols[key] = get_matrix_std( fc_mean_symbols[key], fc_mean_square_symbols[key]) ######################################## # Distribution ######################################## fc_mean = self.distribute_force_constants_spg( fc_mean, symmetry, rotations_cart, mappings) fc_std = self.distribute_force_constants_spg( fc_std, symmetry, rotations_cart, mappings) for key in counters.keys(): fc_mean_symbols[key] = self.distribute_force_constants_spg( fc_mean_symbols[key], symmetry, rotations_cart, mappings) fc_std_symbols[key] = self.distribute_force_constants_spg( fc_std_symbols[key], symmetry, rotations_cart, mappings) # After the distributions, the signs of SDs can be changed. # However, the signs of SDs have no meaning. # To suppress the meaningless signs, we take the absolute values here. # TODO(ikeda): Consider the meaning of SDs for vectors or tensors. fc_std = np.abs(fc_std) for key in counters.keys(): fc_std_symbols[key] = np.abs(fc_std_symbols[key]) self._force_constants_symmetrized = fc_mean self._force_constants_sd = fc_std self._force_constants_pair = fc_mean_symbols self._force_constants_pair_sd = fc_std_symbols
def average_force_constants_spg(self, symprec=1e-5): atoms = self._atoms fc_orig = self._force_constants atoms_symmetry = self._atoms_ideal symmetry = Symmetry(atoms_symmetry) symbols = atoms.get_chemical_symbols() symboltypes = sorted(set(symbols), key=symbols.index) rotations_cart = get_rotations_cart(atoms_symmetry) mappings = StructureAnalyzer(atoms_symmetry).get_mappings_for_symops( prec=symprec) mappings_inv = MappingsModifier(mappings).invert_mappings() print("mappings: Finished.") (nsym, natoms) = mappings.shape print("nsym: {}".format(nsym)) print("natoms: {}".format(natoms)) fc_mean = np.zeros_like(fc_orig) fc_mean_square = np.zeros_like(fc_orig) fc_mean_symbols, fc_mean_square_symbols, fc_std_symbols, counters = ( self.initialize_fc_symbols(fc_orig, symboltypes)) for (minv, r) in zip(mappings_inv, rotations_cart): for i1 in symmetry.get_independent_atoms(): for i2 in range(natoms): j1 = minv[i1] j2 = minv[i2] s1 = symbols[j1] s2 = symbols[j2] tmp = np.dot(np.dot(r, fc_orig[j1, j2]), r.T) tmp2 = tmp**2 fc_mean[i1, i2] += tmp fc_mean_square[i1, i2] += tmp2 fc_mean_symbols[(s1, s2)][i1, i2] += tmp fc_mean_square_symbols[(s1, s2)][i1, i2] += tmp2 counters[(s1, s2)][i1, i2] += 1 fc_mean /= float(len(rotations_cart)) fc_mean_square /= float(len(rotations_cart)) for i1 in symmetry.get_independent_atoms(): for i2 in range(natoms): for (key, c) in counters.items(): if c[i1, i2] != 0: fc_mean_symbols[key][i1, i2] /= c[i1, i2] fc_mean_square_symbols[key][i1, i2] /= c[i1, i2] else: fc_mean_symbols[key][i1, i2] = np.nan fc_mean_square_symbols[key][i1, i2] = np.nan ######################################## # STD ######################################## fc_std = get_matrix_std(fc_mean, fc_mean_square) for key in counters.keys(): fc_std_symbols[key] = get_matrix_std(fc_mean_symbols[key], fc_mean_square_symbols[key]) ######################################## # Distribution ######################################## fc_mean = self.distribute_force_constants_spg(fc_mean, symmetry, rotations_cart, mappings) fc_std = self.distribute_force_constants_spg(fc_std, symmetry, rotations_cart, mappings) for key in counters.keys(): fc_mean_symbols[key] = self.distribute_force_constants_spg( fc_mean_symbols[key], symmetry, rotations_cart, mappings) fc_std_symbols[key] = self.distribute_force_constants_spg( fc_std_symbols[key], symmetry, rotations_cart, mappings) # After the distributions, the signs of SDs can be changed. # However, the signs of SDs have no meaning. # To suppress the meaningless signs, we take the absolute values here. # TODO(ikeda): Consider the meaning of SDs for vectors or tensors. fc_std = np.abs(fc_std) for key in counters.keys(): fc_std_symbols[key] = np.abs(fc_std_symbols[key]) self._force_constants_symmetrized = fc_mean self._force_constants_sd = fc_std self._force_constants_pair = fc_mean_symbols self._force_constants_pair_sd = fc_std_symbols
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): ucell = read_vasp(poscar_filename) scell = get_supercell(ucell, supercell_matrix) inv_smat = np.linalg.inv(supercell_matrix) pcell = get_primitive(scell, np.dot(inv_smat, primitive_axis)) u_sym = Symmetry(ucell, is_symmetry=is_symmetry) p_sym = Symmetry(pcell, is_symmetry=is_symmetry) lattice = ucell.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) borns = np.array(borns, dtype='double') epsilon = np.array(epsilon, dtype='double') if symmetrize_tensors: borns_orig = borns.copy() point_sym = [similarity_transformation(lattice, r) for r in u_sym.get_pointgroup_operations()] epsilon = symmetrize_tensor(epsilon, point_sym) for i in range(num_atom): z = borns[i] site_sym = [similarity_transformation(lattice, r) for r in u_sym.get_site_symmetry(i)] borns[i] = symmetrize_tensor(z, site_sym) rotations = u_sym.get_symmetry_operations()['rotations'] map_atoms = u_sym.get_map_atoms() borns_copy = np.zeros_like(borns) for i, m_i in enumerate(map_atoms): count = 0 for j, r_j in enumerate(u_sym.get_map_operations()): if map_atoms[j] == m_i: count += 1 r_cart = similarity_transformation(lattice, rotations[r_j]) borns_copy[i] += similarity_transformation(r_cart, borns[j]) borns_copy[i] /= count borns = borns_copy sum_born = borns.sum(axis=0) / len(borns) borns -= sum_born if (np.abs(borns_orig - borns) > 0.1).any(): sys.stderr.write( "Born effective charge symmetrization might go wrong.\n") p2s = np.array(pcell.get_primitive_to_supercell_map(), dtype='intc') 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 get_born_OUTCAR(poscar_filename="POSCAR", outcar_filename=None, primitive_matrix=None, supercell_matrix=None, is_symmetry=True, symmetrize_tensors=False, read_vasprunxml=False, symprec=1e-5): if outcar_filename is None: if read_vasprunxml: filename = "vasprun.xml" else: filename = "OUTCAR" else: filename = outcar_filename if primitive_matrix is None: pmat = np.eye(3) else: pmat = primitive_matrix if supercell_matrix is None: smat = np.eye(3, dtype='intc') else: smat = supercell_matrix ucell = read_vasp(poscar_filename) if read_vasprunxml: import io borns = [] epsilon = [] with io.open(outcar_filename, "rb") as f: vasprun = VasprunxmlExpat(f) if vasprun.parse(): epsilon = vasprun.get_epsilon() borns = vasprun.get_born() else: borns, epsilon = _read_born_and_epsilon(filename) num_atom = len(borns) assert num_atom == ucell.get_number_of_atoms(), \ "num_atom %d != len(borns) %d" % (ucell.get_number_of_atoms(), len(borns)) if symmetrize_tensors: lattice = ucell.get_cell() positions = ucell.get_scaled_positions() u_sym = Symmetry(ucell, is_symmetry=is_symmetry, symprec=symprec) rotations = u_sym.get_symmetry_operations()['rotations'] translations = u_sym.get_symmetry_operations()['translations'] ptg_ops = get_pointgroup_operations(rotations) epsilon = symmetrize_2nd_rank_tensor(epsilon, ptg_ops, lattice) borns = symmetrize_borns(borns, rotations, translations, lattice, positions, symprec) inv_smat = np.linalg.inv(smat) scell = get_supercell(ucell, smat, symprec=symprec) pcell = get_primitive(scell, np.dot(inv_smat, pmat), symprec=symprec) p2s = np.array(pcell.get_primitive_to_supercell_map(), dtype='intc') p_sym = Symmetry(pcell, is_symmetry=is_symmetry, symprec=symprec) s_indep_atoms = p2s[p_sym.get_independent_atoms()] u2u = scell.get_unitcell_to_unitcell_map() u_indep_atoms = [u2u[x] for x in s_indep_atoms] reduced_borns = borns[u_indep_atoms].copy() return reduced_borns, epsilon, s_indep_atoms