diff --git a/pyxtal/__init__.py b/pyxtal/__init__.py index feb5e2e9..c4a0faa6 100644 --- a/pyxtal/__init__.py +++ b/pyxtal/__init__.py @@ -1455,7 +1455,7 @@ def load_dict(self, dict0): sites.append(atom_site.load_dict(site)) self.atom_sites = sites - def build(self, group, species, numIons, lattice, sites, tol=1e-2): + def build(self, group, species, numIons, lattice, sites, tol=1e-2, use_hall=False): """ Build a atomic crystal based on the necessary input @@ -1475,7 +1475,7 @@ def build(self, group, species, numIons, lattice, sites, tol=1e-2): if type(group) == Group: self.group = group else: - self.group = Group(group) + self.group = Group(group, use_hall=use_hall) self.lattice = lattice self.dim = 3 @@ -2924,3 +2924,53 @@ def get_structure_factor(self, hkl, coeffs=None): if coeffs is not None: F *= coeffs return F.sum() + + def to_molecular_xtal(self, molecules, oris=None, reflects=None): + """ + Convert the atomic xtal to molecular xtal + the input molecules must have the same length of the self.atom_sites + """ + if not self.molecular: + xtal = pyxtal(molecular=True) + # updates mol_sites + sites = [] + for i, site in enumerate(self.atom_sites): + if oris is None: + ori = [0, 0, 0] + else: + ori = oris[i] + if reflects is None: + reflect = False + else: + reflect = reflects[i] + sites.append(site.to_mol_site(self.lattice, molecules[i], ori=ori, reflect=reflect)) + xtal.lattice = self.lattice + xtal.group = self.group + xtal.mol_sites = sites + xtal.numMols = [sum([wp.multiplicity for wp in self.atom_sites])] + xtal._get_formula() + xtal.valid = True + xtal.source = 'Center' + + return xtal + else: + raise RuntimeError('The input must be molecular xtal') + + def to_atomic_xtal(self): + """ + Convert the molecular + """ + if self.molecular: + xtal = pyxtal() + sites = [] + for i, site in enumerate(self.mol_sites): + sites.append(site.to_atom_site(i+1)) + xtal.lattice = self.lattice + xtal.group = self.group + xtal.atom_sites = sites + xtal._get_formula() + xtal.valid = True + xtal.source = 'Mol. Center' + return xtal + else: + raise RuntimeError('The input must be molecular xtal') diff --git a/pyxtal/representation.py b/pyxtal/representation.py index eaff05b5..2326f04f 100644 --- a/pyxtal/representation.py +++ b/pyxtal/representation.py @@ -380,9 +380,10 @@ def to_string(self, time=None, eng=None, tag=None): # data for molecule strs += "{:d} ".format(len(x)-1) for i in range(1, len(x)): - for v in x[i][:3]: + strs += "{:d} ".format(x[i][0]) + for v in x[i][1:4]: strs += "{:4.2f} ".format(v) - for v in x[i][3:-1]: + for v in x[i][4:-1]: strs += "{:6.1f} ".format(v) strs += "{:d} ".format(int(x[i][-1])) diff --git a/pyxtal/wyckoff_site.py b/pyxtal/wyckoff_site.py index 215836d3..ac882f4a 100644 --- a/pyxtal/wyckoff_site.py +++ b/pyxtal/wyckoff_site.py @@ -84,7 +84,6 @@ def _get_dof(self): #self.dof = len(freedom[freedom==True]) #self.dof = len(freedom[freedom==True]) - @classmethod def load_dict(cls, dicts): """ @@ -92,7 +91,11 @@ def load_dict(cls, dicts): """ position = dicts["position"] specie = dicts["specie"] - wp = Wyckoff_position.load_dict(dicts['wp']) + if 'wp' in dicts: + wp = Wyckoff_position.load_dict(dicts['wp']) + else: + hn, index = dicts['hn'], dicts['index'] + wp = Wyckoff_position.from_group_and_index(hn, index, use_hall=True) return cls(wp, position, specie) def perturbate(self, lattice, magnitude=0.1): @@ -307,6 +310,26 @@ def substitute_with_linear(self, eles, direction, lattice): site2.update(site2.position - shift) return site1, site2 + def to_mol_site(self, lattice, molecule, ori=[0, 0, 0], reflect=False, type_id=0): + """ + transform it to the mol_sites, i.e., to build a molecule on + the current WP + """ + dicts = {} + dicts['smile'] = molecule.smile + dicts['type'] = type_id + dicts['dim'] = 3 + dicts['PBC'] = [1, 1, 1] + dicts['hn'] = self.wp.hall_number + dicts['index'] = self.wp.index + dicts['lattice'] = lattice.matrix + dicts['lattice_type'] = lattice.ltype + dicts['center'] = self.position + if molecule.smile not in ["Cl-"]: + dicts['orientation'] = np.array(ori) + dicts['rotor'] = molecule.get_torsion_angles() + dicts['reflect'] = reflect + return mol_site.from_1D_dicts(dicts) class mol_site: """ @@ -482,6 +505,7 @@ def from_1D_dicts(cls, dicts): position = dicts["center"] #np.dot(dicts["center"], lattice.inv_matrix) position, wp, _ = wp.merge(position, lattice.matrix, 0.01) + return cls(mol, position, orientation, wp, lattice) def show(self, id=None, **kwargs): @@ -1162,3 +1186,19 @@ def get_ijk_lists(self, value=None): self.ijk_lists = ijk_lists else: self.ijk_lists = value + + def to_atom_site(self, specie=1): + """ + transform it to the mol_sites, i.e., to build a molecule on + the current WP + """ + dicts = {} + dicts['specie'] = specie + dicts['position'] = self.position + dicts['hn'] = self.wp.hall_number + dicts['index'] = self.wp.index + return atom_site.load_dict(dicts) + + + +