def teat_countAllOperations(): count = 0 for i in range(1, 531): GR, GT = GroupOperation(i) reference = spglib.get_symmetry_from_database(i) a1 = [] # symmetry operations from spglib code a2 = [] # symmetry operations from this code for j1, j2 in zip(reference['rotations'], reference['translations']): m = [] for k1 in j1: m.append(list(k1)) a1.append([m, list(j2)]) for j1, j2 in zip(GR, GT): m = [] for k1 in j1: m.append(list(k1)) a2.append([m, list(j2)]) # print(a2) a = [m for m in a1 if m not in a2] b = [n for n in a2 if n not in a1] if not ((a is not None) and (b is not None)): print('error:', i) else: count = count + 1 # print('true') print(count)
def test_std_symmetry(self): for fname, dataset, cell, symprec in zip(self._filenames, self._datasets, self._cells, self._symprecs): symmetry = get_symmetry_from_database(dataset['hall_number']) std_pos = dataset['std_positions'] # for r, t in zip(symmetry['rotations'], symmetry['translations']): # for rp in (np.dot(std_pos, r.T) + t): # diff = std_pos - rp # diff -= np.rint(diff) # num_match = len(np.where(abs(diff).sum(axis=1) < 1e-3)[0]) # self.assertEqual(num_match, 1, msg="%s" % fname) # Equivalent above by numpy hack # 15 sec on macOS 2.3 GHz Intel Core i5 (4times faster than above) rot = symmetry['rotations'] trans = symmetry['translations'] # (n_sym, 3, n_atom) rot_pos = np.dot(rot, std_pos.T) + trans[:, :, None] for p in std_pos: diff = rot_pos - p[None, :, None] diff -= np.rint(diff) num_match = (abs(diff).sum(axis=1) < 1e-3).sum(axis=1) self.assertTrue((num_match == 1).all(), msg="%s" % fname)
def test_get_stabilized_reciprocal_mesh(self): for fname in self._filenames: cell = read_vasp("./data/%s" % fname) rotations = get_symmetry_from_database(513)['rotations'] ir_rec_mesh = get_stabilized_reciprocal_mesh(self._mesh, rotations) (mapping_table, grid_address) = ir_rec_mesh data = np.loadtxt(StringIO(result_ir_rec_mesh), dtype='intc') self.assertTrue((data[:, 0] == mapping_table).all()) self.assertTrue((data[:, 1:4] == grid_address).all())
def get_symmetry_from_database(hall_number): """ Get symmetry operations corresponding to a Hall number. Args: hall_number: Integer with the Hall number. Returns: Dictionary of symmetry operations with keys "rotations", "translations" and values Nx(3x3) array of integers, Nx3 array of float, respectively. None if `spglib` is unable to determine symmetry. Raises: ImportError: If `spglib` cannot be imported. """ _check_spglib_install() return spglib.get_symmetry_from_database(hall_number)
def __init__(self, space_group_number=1, print_info=False): if space_group_number <= 0 or space_group_number > 230: raise ValueError( 'space_group_number must be an integer between 1 and 230') self.space_group_number = space_group_number self.lattice_type = self.space_group_lattice_mapping[ self.space_group_number] self.lattice = lattice_system_dict_3D[self.lattice_type] info = spg.get_symmetry_from_database( self.space_group_hall_mapping[space_group_number]) self.translations = info['translations'] self.rotations = info['rotations'] if print_info: print( 'Space group number: {}\n'.format(space_group_number), 'lattice type: {}\n'.format(self.lattice_type), 'Default parameters for lattice: {}'.format( self.lattice.lattice_params))
def test_std_symmetry(self): for fname, dataset, cell, symprec in zip( self._filenames, self._datasets, self._cells, self._symprecs): symmetry = get_symmetry_from_database(dataset['hall_number']) std_pos = dataset['std_positions'] # for r, t in zip(symmetry['rotations'], symmetry['translations']): # for rp in (np.dot(std_pos, r.T) + t): # diff = std_pos - rp # diff -= np.rint(diff) # num_match = len(np.where(abs(diff).sum(axis=1) < 1e-3)[0]) # self.assertEqual(num_match, 1, msg="%s" % fname) # Equivalent above by numpy hack # 15 sec on macOS 2.3 GHz Intel Core i5 (4times faster than above) rot = symmetry['rotations'] trans = symmetry['translations'] # (n_sym, 3, n_atom) rot_pos = np.dot(rot, std_pos.T) + trans[:, :, None] for p in std_pos: diff = rot_pos - p[None, :, None] diff -= np.rint(diff) num_match = (abs(diff).sum(axis=1) < 1e-3).sum(axis=1) self.assertTrue((num_match == 1).all(), msg="%s" % fname)
print(" (to_primitive=1 and no_idealize=1)") lattice, positions, numbers = spglib.standardize_cell(silicon_dist, to_primitive=1, no_idealize=1, symprec=1e-1) show_cell(lattice, positions, numbers) print('') symmetry = spglib.get_symmetry(silicon) print("[get_symmetry]") print(" Number of symmetry operations of silicon conventional") print(" unit cell is %d (192)." % len(symmetry['rotations'])) show_symmetry(symmetry) print('') symmetry = spglib.get_symmetry_from_database(525) print("[get_symmetry_from_database]") print(" Number of symmetry operations of silicon conventional") print(" unit cell is %d (192)." % len(symmetry['rotations'])) show_symmetry(symmetry) print('') reduced_lattice = spglib.niggli_reduce(niggli_lattice) print("[niggli_reduce]") print(" Original lattice") show_lattice(niggli_lattice) print(" Reduced lattice") show_lattice(reduced_lattice) print('')
def make_P1(self, spgnum=-1, sg_setting=1): """ to be implemented by Julian from his topo tools :Parameters: - spgnum : integer space group number :KNOWN BUGS: - scaled_positions could be equivalent from a cif file, so it fails to make_P1 """ # how to convert international spgnum to hall number # apply operations to self.mol and generate a new mol object # use detect_conn etc to complete it. #Okay, what i did was to use ASE as: try: from ase.lattice.spacegroup import Spacegroup except: logger.error( 'make_P1 requires ASE (i.e. ase.lattice.spacegroup) to function properly' ) return # 1) if provided, use the spacegroup set by the user # 2) the spacegroup number is supplied with the cif # 3) there is at least the H-M symbol of it, try to find it via the dictionary! if spgnum == -1: try: spgnum_cif = int( self.mol.cifdata['_symmetry_int_tables_number']) try: spgsym_cif = self.mol.cifdata[ '_symmetry_space_group_name_H-M'].replace(' ', '') except: sgs = spacegroups.spacegroups spgsym_cif = str( [i for i in sgs.keys() if sgs[i] == spgsym_cif][0]) logger.info('using spacegroup number from cif file: %i (%s)' % (spgnum_cif, spgsym_cif)) spgnum = spgnum_cif except: try: spgsym_cif = self.mol.cifdata[ '_symmetry_space_group_name_H-M'].replace(' ', '') spgnum_cif = spacegroups.get_spacegroup_number(spgsym_cif) if spgnum_cif == None: logger.error( 'spacegroup %s could not be found, add it to spacegroups.py ?!' % spgsym_cif) logger.error('make_P1 failed') return False logger.info( 'using spacegroup symbol from cif file, sgnumber looked up: %i (%s)' % (spgnum_cif, spgsym_cif)) spgnum = spgnum_cif except: logger.error( 'I do not have any spacegroup informations, make_P1 failed!' ) return False dataset = spglib.get_symmetry_from_database(spgnum) #print(dataset) #self.sg = Spacegroup(spgnum,setting=sg_setting)#,sprec = 1e-3) self.sg = Spacegroup(spgnum, setting=sg_setting) #,sprec = 1e-3) new_xyz = [] new_elems = [] new_atypes = [] frac_xyz = self.mol.get_frac_xyz() #new_xyz,kinds =self.sg.equivalent_sites(frac_xyz,symprec=self.symprec) try: new_xyz, kinds = self.sg.equivalent_sites(frac_xyz, symprec=1.0e-6) except: import sys logger.error('could not get equivalent sites, ' + str(sys.exc_info()[1])) return False #now do the new elems and stuff: for i, k in enumerate(kinds): new_elems.append(self.mol.elems[k]) new_atypes.append(self.mol.atypes[k]) # fragtypes = self.mol.fragtypes[k] #### Q: work on this here? they there? ## now we try to get the connectivity right and find duplicates during the search self.mol.set_natoms(len(new_xyz)) self.mol.set_elems(new_elems) self.mol.set_atypes(new_atypes) self.mol.set_xyz_from_frac(new_xyz) self.mol.set_nofrags() #self.mol.elems = new_elems #self.mol.atypes = new_atypes self.mol.detect_conn(tresh=0.1, remove_duplicates=True) return True
def get_sym(cell, symprec=1e-3, verbose='short', angle_tolerance=-1.0, hall_number=0): '''Giving a spglib cell, return symmetry analysis This is wrapper for spglib.get_symmetry_dataset function ''' #Space group info dataset = spglib.get_symmetry_dataset(cell, symprec=symprec, angle_tolerance=angle_tolerance, hall_number=hall_number) number = dataset['number'] international = dataset['international'] # equil. to international_short hall = dataset['hall'] # equil. to hall_symbol hall_number = dataset['hall_number'] choice = dataset['choice'] transformation_matrix = dataset['transformation_matrix'] origin_shift = dataset['origin_shift'] wyckoffs = dataset['wyckoffs'] site_symmetry_symbols = dataset['site_symmetry_symbols'] equivalent_atoms = dataset['equivalent_atoms'] crystallographic_orbits = dataset['crystallographic_orbits'] mapping_to_primitive = dataset['mapping_to_primitive'] rotations = dataset['rotations'] translations = dataset['translations'] pointgroup = dataset['pointgroup'] # equil. to pointgroup_international primitive_lattice = dataset['primitive_lattice'] std_lattice = dataset['std_lattice'] std_positions = dataset['std_positions'] std_types = dataset['std_types'] std_rotation_matrix = dataset['std_rotation_matrix'] std_mapping_to_primitive = dataset['std_mapping_to_primitive'] # Get full summetry using the Hall number spacegroup_type = spglib.get_spacegroup_type(hall_number) number = spacegroup_type['number'] international_short = spacegroup_type['international_short'] international_full = spacegroup_type['international_full'] international = spacegroup_type['international'] schoenflies = spacegroup_type['schoenflies'] hall_symbol = spacegroup_type['hall_symbol'] pointgroup_schoenflies = spacegroup_type['pointgroup_schoenflies'] pointgroup_international = spacegroup_type['pointgroup_international'] arithmetic_crystal_class_number = spacegroup_type[ 'arithmetic_crystal_class_number'] arithmetic_crystal_class_symbol = spacegroup_type[ 'arithmetic_crystal_class_symbol'] atoms = utils.convert_atomtype(cell[2]) coords = cell[1] std_cell = cell_to_std(dataset, message=False) primitive_cell = cell_to_primitive(dataset, message=False) if verbose == 'short': # Cell info if compare_cells(cell, std_cell) and compare_cells( cell, primitive_cell): misc.print_msg("This is a standard/primitive unit cell") elif compare_cells(cell, std_cell): misc.print_msg("This is a standard unit cell") elif compare_cells(cell, primitive_cell): misc.print_msg("This is a primitive cell") # Basic info misc.print_msg("Space group number : {:d}".format(number)) misc.print_msg( "Short international symbol : {:s}".format(international_short)) misc.print_msg( "Hall symbol : {:s}".format(hall_symbol)) misc.print_msg( "Schoenflies symbol : {:s}".format(schoenflies)) misc.print_msg("International point group : {:s}".format( pointgroup_international)) misc.print_msg( "Origin shift : {:4.3f} {:4.3f} {:4.3f}".format( origin_shift[0], origin_shift[1], origin_shift[2])) # Atoms info # Atoms info misc.print_msg("===== Irreducible atoms list =====") misc.print_msg(" # Atom x y z") unique_atoms_idx = np.unique(equivalent_atoms, return_index=True)[1] for i, index in enumerate(unique_atoms_idx): coord = coords[index] misc.print_msg( "{:>3d} {:>3s} {:>8.5f} {:>8.5f} {:>8.5f}".format( i + 1, atoms[index], coord[0], coord[1], coord[2])) elif verbose == 'full': # Cell info if compare_cells(cell, std_cell) and compare_cells( cell, primitive_cell): misc.print_msg("This is a standard/primitive unit cell") elif compare_cells(cell, std_cell): misc.print_msg("This is a standard unit cell") elif compare_cells(cell, primitive_cell): misc.print_msg("This is a primitive cell") # Basic info misc.print_msg("Space group number : {:d}".format(number)) misc.print_msg( "Short international symbol : {:s}".format(international_short)) misc.print_msg( "Full international symbol : {:s}".format(international_full)) misc.print_msg( "Hall number : {:d}".format(hall_number)) misc.print_msg( "Hall symbol : {:s}".format(hall_symbol)) misc.print_msg( "Schoenflies symbol : {:s}".format(schoenflies)) misc.print_msg("Schoenflies point group : {:s}".format( pointgroup_schoenflies)) misc.print_msg("International point group : {:s}".format( pointgroup_international)) misc.print_msg( "Origin shift : {:4.3f} {:4.3f} {:4.3f}".format( origin_shift[0], origin_shift[1], origin_shift[2])) # Atoms info misc.print_msg("===== Full atoms list =====") misc.print_msg( " # Equil. Atom x y z Wyckoffs Site_symmetry" ) for i, atom in enumerate(atoms): misc.print_msg( "{:>3d} {:>3d} {:>3s} {:>8.5f} {:>8.5f} {:>8.5f} {:>2s} {:>5s}" .format(i + 1, equivalent_atoms[i] + 1, atoms[i], coords[i, 0], coords[i, 1], coords[i, 2], wyckoffs[i], site_symmetry_symbols[i])) elif verbose is None: # Return an standard cell object with irreducible atoms dataset = spglib.get_symmetry_dataset(std_cell, symprec=symprec, angle_tolerance=angle_tolerance, hall_number=hall_number) equivalent_atoms = dataset['equivalent_atoms'] irred_idx = np.unique(equivalent_atoms, return_index=True)[1] lattice = std_lattice irred_coord = std_positions[irred_idx, :] irred_label = std_types[irred_idx] irred_cell = (lattice, irred_coord, irred_label) spacegroup = [number, international_short] # Get symmetry operators using the Hall number: # For some reason, the symmetry operators by dataset doesn't really match its space group number to write cif file symmetry = spglib.get_symmetry_from_database(hall_number) rotations = symmetry['rotations'] translations = symmetry['translations'] return spacegroup, irred_cell, rotations, translations