@mat3ra/made 2024.6.25-0 → 2024.6.29-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mat3ra/made",
3
- "version": "2024.6.25-0",
3
+ "version": "2024.6.29-0",
4
4
  "description": "MAterials DEsign library",
5
5
  "scripts": {
6
6
  "lint": "eslint --cache src/js tests/js && prettier --write src/js tests/js",
@@ -1,24 +1,21 @@
1
1
  from typing import List, Optional
2
2
 
3
3
  import numpy as np
4
- from ase import Atoms
5
- from pymatgen.core import IStructure as PymatgenIStructure
6
4
 
7
5
  from ..material import Material
8
6
  from .convert import decorator_convert_material_args_kwargs_to_atoms, to_pymatgen
9
-
10
- PymatgenIStructure = PymatgenIStructure
7
+ from .third_party import ASEAtoms, PymatgenIStructure
11
8
 
12
9
 
13
10
  @decorator_convert_material_args_kwargs_to_atoms
14
11
  def get_average_interlayer_distance(
15
- interface_atoms: Atoms, tag_substrate: str, tag_film: str, threshold: float = 0.5
12
+ interface_atoms: ASEAtoms, tag_substrate: str, tag_film: str, threshold: float = 0.5
16
13
  ) -> float:
17
14
  """
18
15
  Calculate the average distance between the top layer of substrate atoms and the bottom layer of film atoms.
19
16
 
20
17
  Args:
21
- interface_atoms (ase.Atoms): The ASE Atoms object containing both sets of atoms.
18
+ interface_atoms (ase.ASEAtoms): The ASE ASEAtoms object containing both sets of atoms.
22
19
  tag_substrate (int): The tag representing the substrate atoms.
23
20
  tag_film (int): The tag representing the film atoms.
24
21
  threshold (float): The threshold for identifying the top and bottom layers of atoms.
@@ -48,12 +45,12 @@ def get_average_interlayer_distance(
48
45
 
49
46
 
50
47
  @decorator_convert_material_args_kwargs_to_atoms
51
- def get_surface_area(atoms: Atoms):
48
+ def get_surface_area(atoms: ASEAtoms):
52
49
  """
53
50
  Calculate the area of the surface perpendicular to the z-axis of the atoms structure.
54
51
 
55
52
  Args:
56
- atoms (ase.Atoms): The Atoms object to calculate the surface area of.
53
+ atoms (ase.ASEAtoms): The ASEAtoms object to calculate the surface area of.
57
54
 
58
55
  Returns:
59
56
  float: The surface area of the atoms.
@@ -64,12 +61,12 @@ def get_surface_area(atoms: Atoms):
64
61
 
65
62
 
66
63
  @decorator_convert_material_args_kwargs_to_atoms
67
- def get_chemical_formula(atoms: Atoms):
64
+ def get_chemical_formula(atoms: ASEAtoms):
68
65
  """
69
66
  Calculate the formula of the atoms structure.
70
67
 
71
68
  Args:
72
- atoms (ase.Atoms): The Atoms object to calculate the formula of.
69
+ atoms (ase.ASEAtoms): The ASEAtoms object to calculate the formula of.
73
70
 
74
71
  Returns:
75
72
  str: The formula of the atoms.
@@ -2,15 +2,16 @@ from typing import List, Callable
2
2
 
3
3
  from mat3ra.made.material import Material
4
4
  from pydantic import BaseModel
5
- from pymatgen.analysis.defects.core import (
6
- Substitution as PymatgenSubstitution,
7
- Vacancy as PymatgenVacancy,
8
- Interstitial as PymatgenInterstitial,
9
- )
10
- from pymatgen.core import PeriodicSite as PymatgenPeriodicSite
11
5
 
6
+ from ...third_party import (
7
+ PymatgenStructure,
8
+ PymatgenPeriodicSite,
9
+ PymatgenVacancy,
10
+ PymatgenSubstitution,
11
+ PymatgenInterstitial,
12
+ )
12
13
  from ...build import BaseBuilder
13
- from ...convert import PymatgenStructure, to_pymatgen
14
+ from ...convert import to_pymatgen
14
15
  from ..mixins import ConvertGeneratedItemsPymatgenStructureMixin
15
16
  from .configuration import PointDefectConfiguration
16
17
 
@@ -1,4 +1,5 @@
1
- from ..convert import from_ase, from_pymatgen, ASEAtoms, PymatgenStructure
1
+ from ..convert import from_ase, from_pymatgen
2
+ from ..third_party import ASEAtoms, PymatgenStructure
2
3
 
3
4
 
4
5
  class ConvertGeneratedItemsASEAtomsMixin:
@@ -1,18 +1,16 @@
1
- from pymatgen.core.surface import SlabGenerator as PymatgenSlabGenerator
2
- from ...convert import label_pymatgen_slab_termination
3
1
  from typing import List
4
2
  from pydantic import BaseModel
5
3
 
6
-
7
4
  from mat3ra.made.material import Material
8
5
 
9
- from .termination import Termination
6
+ from ...third_party import PymatgenSlab, PymatgenSlabGenerator, label_pymatgen_slab_termination
10
7
  from ...analyze import get_chemical_formula
11
- from ...convert import to_pymatgen, PymatgenSlab
8
+ from ...convert import to_pymatgen
12
9
  from ...build import BaseBuilder
13
10
  from ...build.mixins import ConvertGeneratedItemsPymatgenStructureMixin
14
11
  from ..supercell import create_supercell
15
12
  from .configuration import SlabConfiguration
13
+ from .termination import Termination
16
14
 
17
15
 
18
16
  class SlabSelectorParameters(BaseModel):
@@ -1,10 +1,10 @@
1
1
  from typing import List, Tuple, Any
2
+ from pydantic import BaseModel
2
3
 
3
4
  from mat3ra.code.entity import InMemoryEntity
4
- from pymatgen.symmetry.analyzer import SpacegroupAnalyzer as PymatgenSpacegroupAnalyzer
5
- from pydantic import BaseModel
6
5
 
7
6
  from mat3ra.made.material import Material
7
+ from ...third_party import PymatgenSpacegroupAnalyzer
8
8
  from ...convert import to_pymatgen, from_pymatgen
9
9
 
10
10
 
@@ -1,15 +1,14 @@
1
1
  from typing import List
2
- from ase import Atoms
3
- from ase.build.supercells import make_supercell
4
2
 
5
3
  from mat3ra.made.material import Material
4
+ from ..third_party import ASEAtoms, ase_make_supercell
6
5
  from ..utils import decorator_convert_2x2_to_3x3
7
6
  from ..convert import from_ase, decorator_convert_material_args_kwargs_to_atoms
8
7
 
9
8
 
10
9
  @decorator_convert_2x2_to_3x3
11
10
  @decorator_convert_material_args_kwargs_to_atoms
12
- def create_supercell(atoms: Atoms, supercell_matrix: List[List[int]]) -> Material:
11
+ def create_supercell(atoms: ASEAtoms, supercell_matrix: List[List[int]]) -> Material:
13
12
  """
14
13
  Create a supercell of the atoms.
15
14
 
@@ -21,5 +20,5 @@ def create_supercell(atoms: Atoms, supercell_matrix: List[List[int]]) -> Materia
21
20
  Material: The supercell of the atoms.
22
21
  """
23
22
 
24
- supercell_atoms = make_supercell(atoms, supercell_matrix)
23
+ supercell_atoms = ase_make_supercell(atoms, supercell_matrix)
25
24
  return Material(from_ase(supercell_atoms))
@@ -1,22 +1,19 @@
1
1
  from typing import Optional
2
2
 
3
- from ase import Atoms
4
- from ase.calculators.calculator import Calculator
5
- from ase.calculators.emt import EMT
6
-
7
3
  from ..material import Material
8
4
  from .analyze import get_surface_area
9
5
  from .build.interface.utils import get_slab
10
6
  from .convert import decorator_convert_material_args_kwargs_to_atoms
7
+ from .third_party import ASEAtoms, ASECalculator, ASECalculatorEMT
11
8
 
12
9
 
13
10
  @decorator_convert_material_args_kwargs_to_atoms
14
- def calculate_total_energy(atoms: Atoms, calculator: Calculator):
11
+ def calculate_total_energy(atoms: ASEAtoms, calculator: ASECalculator):
15
12
  """
16
13
  Set calculator for ASE Atoms and calculate the total energy.
17
14
 
18
15
  Args:
19
- atoms (ase.Atoms): The Atoms object to calculate the energy of.
16
+ atoms (ASEAtoms): The Atoms object to calculate the energy of.
20
17
  calculator (ase.calculators.calculator.Calculator): The calculator to use for the energy calculation.
21
18
 
22
19
  Returns:
@@ -27,12 +24,12 @@ def calculate_total_energy(atoms: Atoms, calculator: Calculator):
27
24
 
28
25
 
29
26
  @decorator_convert_material_args_kwargs_to_atoms
30
- def calculate_total_energy_per_atom(atoms: Atoms, calculator: Calculator):
27
+ def calculate_total_energy_per_atom(atoms: ASEAtoms, calculator: ASECalculator):
31
28
  """
32
29
  Set calculator for ASE Atoms and calculate the total energy per atom.
33
30
 
34
31
  Args:
35
- atoms (ase.Atoms): The Atoms object to calculate the energy of.
32
+ atoms (ASEAtoms): The Atoms object to calculate the energy of.
36
33
  calculator (ase.calculators.calculator.Calculator): The calculator to use for the energy calculation.
37
34
 
38
35
  Returns:
@@ -42,13 +39,13 @@ def calculate_total_energy_per_atom(atoms: Atoms, calculator: Calculator):
42
39
 
43
40
 
44
41
  @decorator_convert_material_args_kwargs_to_atoms
45
- def calculate_surface_energy(slab: Atoms, bulk: Atoms, calculator: Calculator):
42
+ def calculate_surface_energy(slab: ASEAtoms, bulk: ASEAtoms, calculator: ASECalculator):
46
43
  """
47
44
  Calculate the surface energy by subtracting the weighted bulk energy from the slab energy.
48
45
 
49
46
  Args:
50
- slab (ase.Atoms): The slab Atoms object to calculate the surface energy of.
51
- bulk (ase.Atoms): The bulk Atoms object to calculate the surface energy of.
47
+ slab (ASEAtoms): The slab Atoms object to calculate the surface energy of.
48
+ bulk (ASEAtoms): The bulk Atoms object to calculate the surface energy of.
52
49
  calculator (ase.calculators.calculator.Calculator): The calculator to use for the energy calculation.
53
50
 
54
51
  Returns:
@@ -62,7 +59,9 @@ def calculate_surface_energy(slab: Atoms, bulk: Atoms, calculator: Calculator):
62
59
 
63
60
 
64
61
  @decorator_convert_material_args_kwargs_to_atoms
65
- def calculate_adhesion_energy(interface: Atoms, substrate_slab: Atoms, film_slab: Atoms, calculator: Calculator):
62
+ def calculate_adhesion_energy(
63
+ interface: ASEAtoms, substrate_slab: ASEAtoms, film_slab: ASEAtoms, calculator: ASECalculator
64
+ ):
66
65
  """
67
66
  Calculate the adhesion energy.
68
67
  The adhesion energy is the difference between the energy of the interface and
@@ -70,9 +69,9 @@ def calculate_adhesion_energy(interface: Atoms, substrate_slab: Atoms, film_slab
70
69
  According to: 10.1088/0953-8984/27/30/305004
71
70
 
72
71
  Args:
73
- interface (ase.Atoms): The interface Atoms object to calculate the adhesion energy of.
74
- substrate_slab (ase.Atoms): The substrate slab Atoms object to calculate the adhesion energy of.
75
- film_slab (ase.Atoms): The film slab Atoms object to calculate the adhesion energy of.
72
+ interface (ASEAtoms): The interface ASEAtoms object to calculate the adhesion energy of.
73
+ substrate_slab (ASEAtoms): The substrate slab ASEAtoms object to calculate the adhesion energy of.
74
+ film_slab (ASEAtoms): The film slab ASEAtoms object to calculate the adhesion energy of.
76
75
  calculator (ase.calculators.calculator.Calculator): The calculator to use for the energy calculation.
77
76
 
78
77
  Returns:
@@ -91,7 +90,7 @@ def calculate_interfacial_energy(
91
90
  substrate_bulk: Optional[Material] = None,
92
91
  film_slab: Optional[Material] = None,
93
92
  film_bulk: Optional[Material] = None,
94
- calculator: Calculator = EMT(),
93
+ calculator: ASECalculator = ASECalculatorEMT(),
95
94
  ):
96
95
  """
97
96
  Calculate the interfacial energy.
@@ -5,20 +5,22 @@ from typing import Any, Callable, Dict, Union
5
5
  from mat3ra.made.material import Material
6
6
  from mat3ra.made.utils import map_array_with_id_value_to_array
7
7
  from mat3ra.utils.mixins import RoundNumericValuesMixin
8
- from pymatgen.io.ase import AseAtomsAdaptor
9
- from pymatgen.io.vasp.inputs import Poscar
10
8
 
11
- from .utils import (
12
- INTERFACE_LABELS_MAP,
9
+ from ..third_party import (
13
10
  ASEAtoms,
11
+ PymatgenAseAtomsAdaptor,
14
12
  PymatgenInterface,
15
13
  PymatgenLattice,
14
+ PymatgenPoscar,
16
15
  PymatgenSlab,
17
16
  PymatgenStructure,
17
+ label_pymatgen_slab_termination,
18
+ )
19
+ from .utils import (
20
+ INTERFACE_LABELS_MAP,
18
21
  extract_labels_from_pymatgen_structure,
19
22
  extract_metadata_from_pymatgen_structure,
20
23
  extract_tags_from_ase_atoms,
21
- label_pymatgen_slab_termination,
22
24
  map_array_to_array_with_id_value,
23
25
  )
24
26
 
@@ -138,7 +140,7 @@ def to_poscar(material_or_material_data: Union[Material, Dict[str, Any]]) -> str
138
140
  str: A POSCAR string.
139
141
  """
140
142
  structure = to_pymatgen(material_or_material_data)
141
- poscar = Poscar(structure)
143
+ poscar = PymatgenPoscar(structure)
142
144
  # For pymatgen `2023.6.23` supporting py3.8 the method name is "get_string"
143
145
  # TODO: cleanup the if statement when dropping support for py3.8
144
146
  if hasattr(poscar, "get_string"):
@@ -175,7 +177,7 @@ def to_ase(material_or_material_data: Union[Material, Dict[str, Any]]) -> ASEAto
175
177
  else:
176
178
  material_config = material_or_material_data
177
179
  structure = to_pymatgen(material_config)
178
- atoms = AseAtomsAdaptor.get_atoms(structure)
180
+ atoms = PymatgenAseAtomsAdaptor.get_atoms(structure)
179
181
 
180
182
  atomic_labels = material_config["basis"].get("labels", [])
181
183
  if atomic_labels:
@@ -196,7 +198,7 @@ def from_ase(ase_atoms: ASEAtoms) -> Dict[str, Any]:
196
198
  dict: A dictionary containing the material information in ESSE format.
197
199
  """
198
200
  # TODO: check that atomic labels/tags are properly handled
199
- structure = AseAtomsAdaptor.get_structure(ase_atoms)
201
+ structure = PymatgenAseAtomsAdaptor.get_structure(ase_atoms)
200
202
  material = from_pymatgen(structure)
201
203
  ase_tags = extract_tags_from_ase_atoms(ase_atoms)
202
204
  material["basis"]["labels"] = ase_tags
@@ -1,22 +1,10 @@
1
1
  import json
2
2
  from typing import Any, Dict, List, Union
3
3
 
4
- from ase import Atoms as ASEAtoms
5
4
  from mat3ra.made.utils import map_array_to_array_with_id_value
6
5
  from mat3ra.utils.object import NumpyNDArrayRoundEncoder
7
- from pymatgen.core.interface import Interface as PymatgenInterface
8
- from pymatgen.core.interface import label_termination
9
- from pymatgen.core.structure import Lattice as PymatgenLattice
10
- from pymatgen.core.structure import Structure as PymatgenStructure
11
- from pymatgen.core.surface import Slab as PymatgenSlab
12
-
13
- # Re-exported imports to allow for both use in type hints and instantiation
14
- PymatgenLattice = PymatgenLattice
15
- PymatgenStructure = PymatgenStructure
16
- PymatgenSlab = PymatgenSlab
17
- PymatgenInterface = PymatgenInterface
18
- ASEAtoms = ASEAtoms
19
- label_pymatgen_slab_termination = label_termination
6
+
7
+ from ..third_party import ASEAtoms, PymatgenInterface, PymatgenStructure
20
8
 
21
9
  INTERFACE_LABELS_MAP = {"substrate": 0, "film": 1}
22
10
 
@@ -1,11 +1,10 @@
1
1
  from typing import List, Union
2
2
 
3
3
  from mat3ra.made.material import Material
4
- from pymatgen.analysis.structure_analyzer import SpacegroupAnalyzer
5
- from pymatgen.core.structure import Structure
6
4
 
7
5
  from .analyze import get_atom_indices_within_layer_by_atom_index, get_atom_indices_within_radius_pbc
8
6
  from .convert import decorator_convert_material_args_kwargs_to_structure
7
+ from .third_party import PymatgenSpacegroupAnalyzer, PymatgenStructure
9
8
  from .utils import translate_to_bottom_pymatgen_structure
10
9
 
11
10
 
@@ -30,7 +29,7 @@ def filter_by_label(material: Material, label: Union[int, str]) -> Material:
30
29
 
31
30
 
32
31
  @decorator_convert_material_args_kwargs_to_structure
33
- def translate_to_bottom(structure: Structure, use_conventional_cell: bool = True):
32
+ def translate_to_bottom(structure: PymatgenStructure, use_conventional_cell: bool = True):
34
33
  """
35
34
  Translate atoms to the bottom of the cell (vacuum on top) to allow for the correct consecutive interface generation.
36
35
  If use_conventional_cell is passed, conventional cell is used.
@@ -42,20 +41,20 @@ def translate_to_bottom(structure: Structure, use_conventional_cell: bool = True
42
41
  Structure: The normalized pymatgen Structure object.
43
42
  """
44
43
  if use_conventional_cell:
45
- structure = SpacegroupAnalyzer(structure).get_conventional_standard_structure()
44
+ structure = PymatgenSpacegroupAnalyzer(structure).get_conventional_standard_structure()
46
45
  structure = translate_to_bottom_pymatgen_structure(structure)
47
46
  return structure
48
47
 
49
48
 
50
49
  @decorator_convert_material_args_kwargs_to_structure
51
- def wrap_to_unit_cell(structure: Structure):
50
+ def wrap_to_unit_cell(structure: PymatgenStructure):
52
51
  """
53
52
  Wrap atoms to the cell
54
53
 
55
54
  Args:
56
- structure (Structure): The pymatgen Structure object to normalize.
55
+ structure (PymatgenStructure): The pymatgen PymatgenStructure object to normalize.
57
56
  Returns:
58
- Structure: The wrapped pymatgen Structure object.
57
+ PymatgenStructure: The wrapped pymatgen PymatgenStructure object.
59
58
  """
60
59
  structure.make_supercell((1, 1, 1), to_unit_cell=True)
61
60
  return structure
@@ -0,0 +1,41 @@
1
+ from ase import Atoms as ASEAtoms
2
+ from ase.build.supercells import make_supercell as ase_make_supercell
3
+ from ase.calculators.calculator import Calculator as ASECalculator
4
+ from ase.calculators.emt import EMT as ASECalculatorEMT
5
+ from pymatgen.analysis.defects.core import Interstitial as PymatgenInterstitial
6
+ from pymatgen.analysis.defects.core import Substitution as PymatgenSubstitution
7
+ from pymatgen.analysis.defects.core import Vacancy as PymatgenVacancy
8
+ from pymatgen.core import IStructure as PymatgenIStructure
9
+ from pymatgen.core import PeriodicSite as PymatgenPeriodicSite
10
+ from pymatgen.core.interface import Interface as PymatgenInterface
11
+ from pymatgen.core.interface import label_termination as label_pymatgen_slab_termination
12
+ from pymatgen.core.structure import Lattice as PymatgenLattice
13
+ from pymatgen.core.structure import Structure as PymatgenStructure
14
+ from pymatgen.core.surface import Slab as PymatgenSlab
15
+ from pymatgen.core.surface import SlabGenerator as PymatgenSlabGenerator
16
+ from pymatgen.io.ase import AseAtomsAdaptor as PymatgenAseAtomsAdaptor
17
+ from pymatgen.io.vasp.inputs import Poscar as PymatgenPoscar
18
+ from pymatgen.symmetry.analyzer import SpacegroupAnalyzer as PymatgenSpacegroupAnalyzer
19
+
20
+ # Re-exported imports to allow for both use in type hints and instantiation
21
+
22
+ __all__ = [
23
+ "ASEAtoms",
24
+ "ASECalculator",
25
+ "ASECalculatorEMT",
26
+ "PymatgenLattice",
27
+ "PymatgenStructure",
28
+ "PymatgenIStructure",
29
+ "PymatgenSlab",
30
+ "PymatgenSlabGenerator",
31
+ "PymatgenInterface",
32
+ "PymatgenPeriodicSite",
33
+ "PymatgenSpacegroupAnalyzer",
34
+ "PymatgenVacancy",
35
+ "PymatgenSubstitution",
36
+ "PymatgenInterstitial",
37
+ "label_pymatgen_slab_termination",
38
+ "ase_make_supercell",
39
+ "PymatgenAseAtomsAdaptor",
40
+ "PymatgenPoscar",
41
+ ]
@@ -4,18 +4,19 @@ from typing import Callable, List
4
4
  import numpy as np
5
5
  from mat3ra.made.basis import Basis
6
6
  from mat3ra.utils.matrix import convert_2x2_to_3x3
7
- from pymatgen.core.structure import Structure
7
+
8
+ from .third_party import PymatgenStructure
8
9
 
9
10
 
10
11
  # TODO: convert to accept ASE Atoms object
11
- def translate_to_bottom_pymatgen_structure(structure: Structure):
12
+ def translate_to_bottom_pymatgen_structure(structure: PymatgenStructure):
12
13
  """
13
14
  Translate the structure to the bottom of the cell.
14
15
  Args:
15
- structure (Structure): The pymatgen Structure object to translate.
16
+ structure (PymatgenStructure): The pymatgen Structure object to translate.
16
17
 
17
18
  Returns:
18
- Structure: The translated pymatgen Structure object.
19
+ PymatgenStructure: The translated pymatgen Structure object.
19
20
  """
20
21
  min_c = min(site.c for site in structure)
21
22
  translation_vector = [0, 0, -min_c]