-
Notifications
You must be signed in to change notification settings - Fork 1
Add pyxtal wrapper #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
af6decd
Add pyxtal wrapper
pmrv db70155
Add dependency
pmrv 9feddde
Skip test if pyxtal not installed
pmrv 34e83bf
Restructure so that pyxtal is optional gracefully
pmrv 7eecb9c
Add missing import
pmrv e9bd816
Swap imports to avoid shadowing pyxtal
pmrv ff4f613
Update test_pyxtal.py
pmrv 9738ea5
Updates to pyxtal
jan-janssen 9d60033
Separate minimal environment and full environment
jan-janssen b8693ab
Merge branch 'pyxtal_patch' into merge_main
jan-janssen 5279abf
Merge pull request #41 from pyiron/merge_main
jan-janssen eec6966
Merge pull request #25 from pyiron/pyxtal_patch
jan-janssen 9626f54
Numba does not support numpy 1.25
jan-janssen f86061e
Numba does not support numpy 1.25
jan-janssen 467201c
Update environment.yml
jan-janssen e213d91
Update setup.py
jan-janssen File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,4 +7,4 @@ dependencies: | |
- codacy-coverage | ||
- matplotlib-base =3.7.2 | ||
- numpy =1.25.1 | ||
- scipy =1.11.1 | ||
- scipy =1.11.1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# coding: utf-8 | ||
# Copyright (c) Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department | ||
# Distributed under the terms of "New BSD License", see the LICENSE file. | ||
|
||
from typing import Union, List, Tuple | ||
import warnings | ||
|
||
try: | ||
from tqdm.auto import tqdm | ||
except ImportError: | ||
tqdm = lambda x: x | ||
|
||
from ase import Atoms | ||
from structuretoolkit.common.helper import center_coordinates_in_unit_cell | ||
|
||
|
||
def pyxtal( | ||
group: Union[int, List[int]], | ||
species: Tuple[str], | ||
num_ions: Tuple[int], | ||
dim=3, | ||
repeat=1, | ||
allow_exceptions=True, | ||
**kwargs, | ||
) -> Union[Atoms, List[dict]]: | ||
""" | ||
Generate random crystal structures with PyXtal. | ||
|
||
`group` must be between 1 and the largest possible value for the given dimensionality: | ||
dim=3 => 1 - 230 (space groups) | ||
dim=2 => 1 - 80 (layer groups) | ||
dim=1 => 1 - 75 (rod groups) | ||
dim=0 => 1 - 58 (point groups) | ||
|
||
When `group` is passed as a list of integers or `repeat>1`, generate multiple structures and return them in a list | ||
of dicts containing the keys `atoms`, `symmetry` and `repeat` for the ASE structure, the symmetry group | ||
number and which iteration it is, respectively. | ||
|
||
Args: | ||
group (list of int, or int): the symmetry group to generate or a list of them | ||
species (tuple of str): which species to include, defines the stoichiometry together with `num_ions` | ||
num_ions (tuple of int): how many of each species to include, defines the stoichiometry together with `species` | ||
dim (int): dimensionality of the symmetry group, 0 is point groups, 1 is rod groups, 2 is layer groups and 3 is space groups | ||
repeat (int): how many random structures to generate | ||
allow_exceptions (bool): when generating multiple structures, silence errors when the requested stoichiometry and symmetry group are incompatible | ||
**kwargs: passed to `pyxtal.pyxtal` function verbatim | ||
|
||
Returns: | ||
:class:`~.Atoms`: the generated structure, if repeat==1 and only one symmetry group is requested | ||
list of dict of all generated structures, if repeat>1 or multiple symmetry groups are requested | ||
|
||
Raises: | ||
ValueError: if `species` and `num_ions` are not of the same length | ||
ValueError: if stoichiometry and symmetry group are incompatible and allow_exceptions==False or only one structure is requested | ||
""" | ||
from pyxtal import pyxtal as _pyxtal | ||
from pyxtal.msg import Comp_CompatibilityError | ||
|
||
if len(species) != len(num_ions): | ||
raise ValueError( | ||
"species and num_ions must be of same length, " | ||
f"not {species} and {num_ions}!" | ||
) | ||
stoich = "".join(f"{s}{n}" for s, n in zip(species, num_ions)) | ||
|
||
def generate(group): | ||
s = _pyxtal() | ||
try: | ||
s.from_random( | ||
dim=dim, group=group, species=species, numIons=num_ions, **kwargs | ||
) | ||
except Comp_CompatibilityError as e: | ||
if not allow_exceptions: | ||
raise ValueError( | ||
f"Symmetry group {group} incompatible with stoichiometry {stoich}!" | ||
) from None | ||
else: | ||
return None | ||
s = s.to_ase() | ||
s = center_coordinates_in_unit_cell(structure=s) | ||
return s | ||
|
||
# return a single structure | ||
if repeat == 1 and isinstance(group, int): | ||
allow_exceptions = False | ||
return generate(group) | ||
else: | ||
structures = [] | ||
if isinstance(group, int): | ||
group = [group] | ||
failed_groups = [] | ||
for g in tqdm(group, desc="Spacegroups"): | ||
for i in range(repeat): | ||
s = generate(g) | ||
if s is None: | ||
failed_groups.append(g) | ||
continue | ||
structures.append({ | ||
"atoms": s, | ||
"symmetry": g, | ||
"repeat": i | ||
}) | ||
if len(failed_groups) > 0: | ||
warnings.warn( | ||
f'Groups [{", ".join(map(str,failed_groups))}] could not be generated with stoichiometry {stoich}!' | ||
) | ||
return structures |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from unittest import TestCase, skipIf | ||
from ase import Atoms | ||
import structuretoolkit as stk | ||
|
||
|
||
try: | ||
import pyxtal | ||
skip_pyxtal_test = False | ||
except ImportError: | ||
skip_pyxtal_test = True | ||
|
||
|
||
@skipIf(skip_pyxtal_test, "pyxtal is not installed, so the pyxtal tests are skipped.") | ||
class TestPyxtal(TestCase): | ||
|
||
def test_args_raised(self): | ||
"""pyxtal should raise appropriate errors when called with wrong arguments""" | ||
|
||
with self.assertRaises(ValueError, msg="No error raised when num_ions and species do not match!"): | ||
stk.build.pyxtal(1, species=['Fe'], num_ions=[1,2]) | ||
|
||
with self.assertRaises(ValueError, msg="No error raised when num_ions and species do not match!"): | ||
stk.build.pyxtal(1, species=['Fe', 'Cr'], num_ions=[1]) | ||
|
||
try: | ||
stk.build.pyxtal([193, 194], ['Mg'], num_ions=[1], allow_exceptions=True) | ||
except ValueError: | ||
self.fail("Error raised even though allow_exceptions=True was passed!") | ||
|
||
with self.assertRaises(ValueError, msg="No error raised even though allow_exceptions=False was passed!"): | ||
stk.build.pyxtal(194, ['Mg'], num_ions=[1], allow_exceptions=False) | ||
|
||
def test_return_value(self): | ||
"""pyxtal should either return Atoms or list of dict, depending on arguments""" | ||
|
||
self.assertIsInstance(stk.build.pyxtal(1, species=['Fe'], num_ions=[1]), Atoms, | ||
"returned not an Atoms with scalar arguments") | ||
self.assertIsInstance(stk.build.pyxtal([1, 2], species=['Fe'], num_ions=[1]), list, | ||
"returned not a StructureStorage with multiple groups") | ||
self.assertIsInstance(stk.build.pyxtal(1, species=['Fe'], num_ions=[1], repeat=5), list, | ||
"returned not a StructureStorage with repeat given") | ||
self.assertEqual(len(stk.build.pyxtal(1, species=['Fe'], num_ions=[1], repeat=5)), 5, | ||
"returned number of structures did not match given repeat") | ||
self.assertTrue(all(isinstance(d, dict) for d in stk.build.pyxtal(1, species=['Fe'], num_ions=[1], repeat=5)), | ||
"returned list should contain only dicts") |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.