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 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 -= diff.round() 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