Skip to content

Commit

Permalink
fix lattice
Browse files Browse the repository at this point in the history
  • Loading branch information
qzhu2017 committed Jan 24, 2024
1 parent 4512cb3 commit 8097099
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 34 deletions.
19 changes: 19 additions & 0 deletions pyxtal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1478,7 +1478,26 @@ def build(self, group, species, numIons, lattice, sites, tol=1e-2, use_hall=Fals
else:
self.group = Group(group, use_hall=use_hall)

# Lattica needs some special handling heree
if not isinstance(lattice, Lattice):
if type(lattice) == np.ndarray:
ltype = self.group.lattice_type
if len(lattice) == 3:
lattice = Lattice.from_matrix(lattice, ltype=ltype)
elif len(lattice) == 6: # cell para
[a, b, c, alpha, beta, gamma] = lattice
lattice = Lattice.from_para(a, b, c, alpha, beta, gamma, ltype=ltype)
else:
msg = 'Cannot convert the input array to pyxtal.lattice.Lattice'
raise ValueError(msg, lattice)
else:
msg = 'Cannot convert the input array to pyxtal.lattice.Lattice'
raise ValueError(msg, lattice)
else:
msg = 'The input lattice needs to be a pyxtal.lattice.Lattice class'
raise ValueError(msg)
self.lattice = lattice

self.dim = 3
self.factor = 1.0
self.PBC = [1, 1, 1]
Expand Down
66 changes: 32 additions & 34 deletions pyxtal/lattice.py
Original file line number Diff line number Diff line change
Expand Up @@ -526,13 +526,13 @@ def mutate(self, degree=0.20, frozen=False):

def generate_para(self):
if self.dim == 3:
return generate_lattice(self.ltype, self.volume, **self.kwargs)
return generate_cellpara(self.ltype, self.volume, **self.kwargs)
elif self.dim == 2:
return generate_lattice_2D(self.ltype, self.volume, **self.kwargs)
return generate_cellpara_2D(self.ltype, self.volume, **self.kwargs)
elif self.dim == 1:
return generate_lattice_1D(self.ltype, self.volume, **self.kwargs)
return generate_cellpara_1D(self.ltype, self.volume, **self.kwargs)
elif self.dim == 0:
return generate_lattice_0D(self.ltype, self.volume, **self.kwargs)
return generate_cellpara_0D(self.ltype, self.volume, **self.kwargs)

def generate_matrix(self):
"""
Expand Down Expand Up @@ -1053,7 +1053,7 @@ def apply_transformation(self, trans):
return lat_new


def generate_lattice(
def generate_cellpara(
ltype,
volume,
minvec=1.2,
Expand All @@ -1063,11 +1063,11 @@ def generate_lattice(
**kwargs
):
"""
Generates a lattice (3x3 matrix) according to the space group symmetry and
number of atoms. If the spacegroup has centering, we will transform to
conventional cell setting. If the generated lattice does not meet the
minimum angle and vector requirements, we try to generate a new one, up to
maxattempts times.
Generates the cell parameter (a, b, c, alpha, beta, gamma) according
to the space group symmetry and number of atoms. If the spacegroup
has centering, we will transform to conventional cell setting. If the
generated lattice does not meet the minimum angle and vector
requirements, we try to generate a new one, up to maxattempts times.
Args:
volume: volume of the conventional unit cell
Expand All @@ -1082,7 +1082,7 @@ def generate_lattice(
'max_l': the third smallest allowed cell vector.
Returns:
a 3x3 matrix representing the lattice vectors of the unit cell. If
a 6-length array representing the lattice of the unit cell. If
generation fails, outputs a warning message and returns empty
"""
maxangle = np.pi - minangle
Expand Down Expand Up @@ -1210,7 +1210,7 @@ def generate_lattice(
raise VolumeError(msg)
#return

def generate_lattice_2D(
def generate_cellpara_2D(
ltype,
volume,
thickness=None,
Expand All @@ -1221,11 +1221,12 @@ def generate_lattice_2D(
**kwargs
):
"""
Generates a lattice (3x3 matrix) according to the spacegroup symmetry and
number of atoms. If the layer group has centering, we will use the
conventional cell setting. If the generated lattice does not meet the
minimum angle and vector requirements, we try to generate a new one, up to
maxattempts times.
Generates the cell parameter (a, b, c, alpha, beta, gamma) according
to the layer group symmetry and number of atoms. If the layer group
has centering, we will transform to conventional cell setting. If the
generated lattice does not meet the minimum angle and vector
requirements, we try to generate a new one, up to maxattempts times.
Note: The monoclinic layer groups have different unique axes. Groups 3-7
have unique axis c, while 8-18 have unique axis a. We use non-periodic
axis c for all layer groups.
Expand All @@ -1246,7 +1247,7 @@ def generate_lattice_2D(
'max_l': the third smallest allowed cell vector.
Returns:
a 3x3 matrix representing the lattice vectors of the unit cell. If
a 6-length representing the lattice vectors of the unit cell. If
generation fails, outputs a warning message and returns empty
"""
if "unique_axis" not in kwargs:
Expand Down Expand Up @@ -1420,7 +1421,7 @@ def generate_lattice_2D(
msg = "Cannot get lattice after {:d} cycles for volume {:.2f}".format(maxattempts, volume)
raise VolumeError(msg)

def generate_lattice_1D(
def generate_cellpara_1D(
ltype,
volume,
area=None,
Expand All @@ -1431,11 +1432,12 @@ def generate_lattice_1D(
**kwargs
):
"""
Generates a lattice (3x3 matrix) according to the spacegroup symmetry and
number of atoms. If the spacegroup has centering, we will transform to
conventional cell setting. If the generated lattice does not meet the
minimum angle and vector requirements, we try to generate a new one, up to
maxattempts times.
Generates a cell parameter (a, b, c, alpha, beta, gamma) according to
the rod group symmetry and number of atoms. If the rod group has centering,
we will transform to conventional cell setting. If the generated lattice
does not meet the minimum angle and vector requirements, we try to
generate a new one, up to maxattempts times.
Note: The monoclinic Rod groups have different unique axes. Groups 3-7
have unique axis a, while 8-12 have unique axis c. We use periodic
axis c for all Rod groups.
Expand All @@ -1456,7 +1458,7 @@ def generate_lattice_1D(
'max_l': the third smallest allowed cell vector.
Returns:
a 3x3 matrix representing the lattice vectors of the unit cell. If
a 6-length array representing the lattice of the unit cell. If
generation fails, outputs a warning message and returns empty
"""
try:
Expand Down Expand Up @@ -1631,18 +1633,14 @@ def generate_lattice_1D(
raise VolumeError(msg)


def generate_lattice_0D(
def generate_cellpara_0D(
ltype, volume, area=None, minvec=1.2, max_ratio=10.0, maxattempts=100, **kwargs
):
"""
Generates a lattice (3x3 matrix) according to the spacegroup symmetry and
number of atoms. If the spacegroup has centering, we will transform to
conventional cell setting. If the generated lattice does not meet the
minimum angle and vector requirements, we try to generate a new one, up to
maxattempts times.
Note: The monoclinic Rod groups have different unique axes. Groups 3-7
have unique axis a, while 8-12 have unique axis c. We use periodic
axis c for all Rod groups.
Generates a cell parameter (a, b, c, alpha, beta, gamma) according to the
point group symmetry and number of atoms. If the generated lattice does
not meet the minimum angle and vector requirements, we try to generate
a new one, up to maxattempts times.
Args:
num: number of the Rod group
Expand Down
25 changes: 25 additions & 0 deletions pyxtal/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,31 @@ def test_transform(self):
pmg1 = c.to_pymatgen()
self.assertTrue(sm.StructureMatcher().fit(pmg0, pmg1))

def test_build(self):
l = np.array([48.005, 7.320, 35.864, 90.000, 174.948, 90.000])
sites = [
[0.0000, 0.0000, 0.1250],
[0.2296, 0.7704, 0.5370],
[0.2296, 0.2296, 0.5370],
[0.5408, 0.0000, 0.6186],
[0.0000, 0.0000, 0.3074],
]
c = pyxtal()
c.build(9, ['S'], [8], lattice=l, sites=[sites])
pmg0 = c.to_pymatgen()
l1 = c.lattice.matrix

c.optimize_lattice()
pmg1 = c.to_pymatgen()
self.assertTrue(sm.StructureMatcher().fit(pmg0, pmg1))

c1 = pyxtal()
c1.build(9, ['S'], [8], lattice=l1, sites=[sites])
c1.optimize_lattice()
pmg2 = c1.to_pymatgen()
self.assertTrue(sm.StructureMatcher().fit(pmg0, pmg2))


def test_transforms(self):
paras = [
(5.0317, 19.2982, 5.8004, 90.0000, 122.2672, 90.0000, 'monoclinic', 6),
Expand Down

0 comments on commit 8097099

Please sign in to comment.