def init_common( self, molecules, numMols, volume_factor, select_high, allow_inversion, orientations, group, lattice, tm, sites, ): # init functionality which is shared by 3D, 2D, and 1D crystals self.valid = False self.numattempts = 0 # number of attempts to generate the crystal. if type(group) == Group: self.group = group """A pyxtal.symmetry.Group object storing information about the space/layer /Rod/point group, and its Wyckoff positions.""" else: self.group = Group(group, dim=self.dim) self.number = self.group.number """ The international group number of the crystal: 1-230 for 3D space groups 1-80 for 2D layer groups 1-75 for 1D Rod groups 1-32 for crystallographic point groups None otherwise """ self.Msgs() self.factor = volume_factor # volume factor for the unit cell. numMols = np.array(numMols) # must convert it to np.array self.numMols0 = numMols # in the PRIMITIVE cell self.numMols = self.numMols0 * cellsize( self.group) # in the CONVENTIONAL cell # boolean numbers self.allow_inversion = allow_inversion self.select_high = select_high # Set the tolerance matrix # The Tol_matrix object for checking inter-atomic distances within the structure. if type(tm) == Tol_matrix: self.tol_matrix = tm else: try: self.tol_matrix = Tol_matrix(prototype=tm) # TODO remove bare except except: msg = "Error: tm must either be a Tol_matrix object +\n" msg += "or a prototype string for initializing one." printx(msg, priority=1) return self.molecules = [] # A pyxtal_molecule objects, for mol in molecules: self.molecules.append(pyxtal_molecule(mol, self.tol_matrix)) self.sites = {} for i, mol in enumerate(self.molecules): if sites is not None and sites[i] is not None: self.check_consistency(sites[i], self.numMols[i]) self.sites[i] = sites[i] else: self.sites[i] = None # if seeds, directly parse the structure from cif # At the moment, we only support one specie if self.seed is not None: seed = structure_from_ext(self.seed, self.molecules[0].mol, relax_h=self.relax_h) if seed.match(): self.mol_sites = [seed.make_mol_site()] self.group = Group(seed.wyc.number) self.lattice = seed.lattice self.molecules = [pyxtal_molecule(seed.molecule)] self.diag = seed.diag self.valid = True # Need to add a check function else: raise ValueError("Cannot extract the structure from cif") # The valid orientations for each molecule and Wyckoff position. # May be copied when generating a new molecular_crystal to save a # small amount of time if orientations is None: self.get_orientations() else: self.valid_orientations = orientations if self.seed is None: if lattice is not None: # Use the provided lattice self.lattice = lattice self.volume = lattice.volume # Make sure the custom lattice PBC axes are correct. if lattice.PBC != self.PBC: self.lattice.PBC = self.PBC printx("\n Warning: converting custom lattice PBC to " + str(self.PBC)) else: # Determine the unique axis if self.dim == 2: if self.number in range(3, 8): unique_axis = "c" else: unique_axis = "a" elif self.dim == 1: if self.number in range(3, 8): unique_axis = "a" else: unique_axis = "c" else: unique_axis = "c" # Generate a Lattice instance self.volume = self.estimate_volume() # The Lattice object used to generate lattice matrices if self.dim == 3 or self.dim == 0: self.lattice = Lattice( self.group.lattice_type, self.volume, PBC=self.PBC, unique_axis=unique_axis, ) elif self.dim == 2: self.lattice = Lattice( self.group.lattice_type, self.volume, PBC=self.PBC, unique_axis=unique_axis, thickness=self.thickness, ) elif self.dim == 1: self.lattice = Lattice( self.group.lattice_type, self.volume, PBC=self.PBC, unique_axis=unique_axis, area=self.area, ) self.generate_crystal()
import pymatgen.analysis.structure_matcher as sm from pymatgen.symmetry.analyzer import SpacegroupAnalyzer import numpy as np from pyxtal.lattice import cellsize for G in range(1, 231): #for G in [90, 99, 105, 107, 203, 210, 224, 226, 227, 228]: g = Group(G) subs = g.get_max_t_subgroup() indices = subs['index'] hs = subs['subgroup'] relations = subs['relations'] tran = subs['transformation'] letter = str(g[0].multiplicity) + g[0].letter print(G) C1 = random_crystal(G, ['C'], [int(g[0].multiplicity / cellsize(g))], sites=[[letter]]) pmg_s1 = C1.to_pymatgen() sga1 = SpacegroupAnalyzer(pmg_s1).get_space_group_symbol() # each subgroup for i in range(len(relations)): C2 = C1.subgroup(eps=0, idx=[i], once=True) pmg_s2 = C2.to_pymatgen() try: sga2 = SpacegroupAnalyzer(pmg_s2, symprec=1e-4).get_space_group_symbol() except: #print("unable to find the space group") sga2 = None print(G, hs[i], g.symbol, sga1, Group(hs[i]).symbol, sga2, i) if not sm.StructureMatcher().fit(pmg_s1, pmg_s2):
def init_common(self, species, numIons, factor, group, lattice, sites, conventional, tm): """ Common init functionality for 0D-3D cases of random_crystal. """ self.source = 'Random' self.valid = False # Check that numIons are integers greater than 0 for num in numIons: if int(num) != num or num < 1: printx("Error: composition must be positive integers.", priority=1) return False if type(group) == Group: self.group = group else: self.group = Group(group, dim=self.dim) self.number = self.group.number """ The international group number of the crystal: 1-230 for 3D space groups 1-80 for 2D layer groups 1-75 for 1D Rod groups 1-32 for crystallographic point groups None otherwise """ # The number of attempts to generate the crystal # number of atoms # volume factor for the unit cell. # The number of atom in the PRIMITIVE cell # The number of each type of atom in the CONVENTIONAL cell. # A list of atomic symbols for the types of atoms # A list of warning messages self.numattempts = 0 numIons = np.array(numIons) self.factor = factor if not conventional: mul = cellsize(self.group) else: mul = 1 self.numIons = numIons * mul formula = "" for i, s in zip(self.numIons, species): formula += "{:s}{:d}".format(s, int(i)) self.formula = formula self.species = species # Use the provided lattice if lattice is not None: self.lattice = lattice self.volume = lattice.volume # Make sure the custom lattice PBC axes are correct. if lattice.PBC != self.PBC: self.lattice.PBC = self.PBC printx("\n Warning: converting custom lattice PBC to " + str(self.PBC)) # Generate a Lattice instance based on a given volume estimation elif lattice is None: # Determine the unique axis if self.dim == 2: if self.number in range(3, 8): unique_axis = "c" else: unique_axis = "a" elif self.dim == 1: if self.number in range(3, 8): unique_axis = "a" else: unique_axis = "c" else: unique_axis = "c" self.volume = self.estimate_volume() if self.dim == 3 or self.dim == 0: self.lattice = Lattice( self.group.lattice_type, self.volume, PBC=self.PBC, unique_axis=unique_axis, ) elif self.dim == 2: self.lattice = Lattice( self.group.lattice_type, self.volume, PBC=self.PBC, unique_axis=unique_axis, # NOTE self.thickness is part of 2D class thickness=self.thickness, ) elif self.dim == 1: self.lattice = Lattice( self.group.lattice_type, self.volume, PBC=self.PBC, unique_axis=unique_axis, # NOTE self.area is part of 1D class area=self.area, ) # Set the tolerance matrix for checking inter-atomic distances if type(tm) == Tol_matrix: self.tol_matrix = tm else: try: self.tol_matrix = Tol_matrix(prototype=tm) # TODO Remove bare except except: printx( ("Error: tm must either be a Tol_matrix object or " "a prototype string for initializing one."), priority=1, ) self.valid = False return self.sites = {} for i, specie in enumerate(self.species): if sites is not None and sites[i] is not None: self.check_consistency(sites[i], self.numIons[i]) self.sites[specie] = sites[i] else: self.sites[specie] = None # QZ: needs to check if it is compatible self.generate_crystal()
def init_common( self, molecules, numMols, volume_factor, select_high, allow_inversion, orientations, group, lattice, sites, conventional, tm, ): # init functionality which is shared by 3D, 2D, and 1D crystals self.valid = False self.numattempts = 0 # number of attempts to generate the crystal. if type(group) == Group: self.group = group else: self.group = Group(group, dim=self.dim) self.number = self.group.number """ The international group number of the crystal: 1-230 for 3D space groups 1-80 for 2D layer groups 1-75 for 1D Rod groups 1-32 for crystallographic point groups None otherwise """ self.factor = volume_factor # volume factor for the unit cell. numMols = np.array(numMols) # must convert it to np.array if not conventional: mul = cellsize(self.group) else: mul = 1 self.numMols = numMols * mul # boolean numbers self.allow_inversion = allow_inversion self.select_high = select_high # Set the tolerance matrix # The Tol_matrix object for checking inter-atomic distances within the structure. if type(tm) == Tol_matrix: self.tol_matrix = tm else: try: self.tol_matrix = Tol_matrix(prototype=tm) # TODO remove bare except except: msg = "Error: tm must either be a Tol_matrix object +\n" msg += "or a prototype string for initializing one." printx(msg, priority=1) return self.molecules = [] # A pyxtal_molecule objects, for mol in molecules: self.molecules.append(pyxtal_molecule(mol, self.tol_matrix)) self.sites = {} for i, mol in enumerate(self.molecules): if sites is not None and sites[i] is not None: self.check_consistency(sites[i], self.numMols[i]) self.sites[i] = sites[i] else: self.sites[i] = None # The valid orientations for each molecule and Wyckoff position. # May be copied when generating a new molecular_crystal to save a # small amount of time if orientations is None: self.get_orientations() else: self.valid_orientations = orientations if lattice is not None: # Use the provided lattice self.lattice = lattice self.volume = lattice.volume # Make sure the custom lattice PBC axes are correct. if lattice.PBC != self.PBC: self.lattice.PBC = self.PBC printx("\n Warning: converting custom lattice PBC to " + str(self.PBC)) else: # Determine the unique axis if self.dim == 2: if self.number in range(3, 8): unique_axis = "c" else: unique_axis = "a" elif self.dim == 1: if self.number in range(3, 8): unique_axis = "a" else: unique_axis = "c" else: unique_axis = "c" # Generate a Lattice instance self.volume = self.estimate_volume() # The Lattice object used to generate lattice matrices if self.dim == 3 or self.dim == 0: self.lattice = Lattice( self.group.lattice_type, self.volume, PBC=self.PBC, unique_axis=unique_axis, ) elif self.dim == 2: self.lattice = Lattice( self.group.lattice_type, self.volume, PBC=self.PBC, unique_axis=unique_axis, thickness=self.thickness, ) elif self.dim == 1: self.lattice = Lattice( self.group.lattice_type, self.volume, PBC=self.PBC, unique_axis=unique_axis, area=self.area, ) self.generate_crystal()