Skip to content

Commit

Permalink
add the functions to convert between mol and atom
Browse files Browse the repository at this point in the history
  • Loading branch information
qzhu2017 committed Dec 7, 2023
1 parent 473f919 commit 675ab83
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 6 deletions.
54 changes: 52 additions & 2 deletions pyxtal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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')
5 changes: 3 additions & 2 deletions pyxtal/representation.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]))

Expand Down
44 changes: 42 additions & 2 deletions pyxtal/wyckoff_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,15 +84,18 @@ def _get_dof(self):
#self.dof = len(freedom[freedom==True])
#self.dof = len(freedom[freedom==True])


@classmethod
def load_dict(cls, dicts):
"""
load the sites from a dictionary
"""
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):
Expand Down Expand Up @@ -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:
"""
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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)




0 comments on commit 675ab83

Please sign in to comment.