Skip to content

Commit 4f3e853

Browse files
authored
Merge pull request #90 from ahxbcn/build_slab
Tool for build slab
2 parents 7747a7b + 0e5d2b3 commit 4f3e853

2 files changed

Lines changed: 96 additions & 0 deletions

File tree

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import os
2+
from pathlib import Path
3+
from typing import Literal, Tuple
4+
5+
from abacusagent.init_mcp import mcp
6+
from abacusagent.modules.submodules.structure_editor import build_slab as _build_slab
7+
8+
@mcp.tool()
9+
def build_slab(stru_file: Path,
10+
stru_type: Literal["cif", "poscar", "abacus/stru"] = "cif",
11+
miller_indices: Tuple[int, int, int] = (1, 0, 0),
12+
layers: int = 3,
13+
surface_supercell: Tuple[int, int] = (1, 1),
14+
vacuum: float = 15.0,
15+
vacuum_direction: Literal['a', 'b', 'c'] = 'b'):
16+
"""
17+
Build slab from given structure file.
18+
19+
Args:
20+
stru_file (Path): Path to structure file.
21+
stru_type (Literal["cif", "poscar", "abacus/stru"]): Type of structure file. Defaults to "cif".
22+
miller_indices (Tuple[int, int, int]): Miller indices of the surface. Defaults to (1, 0, 0), which means (100) surface of the structure.
23+
layers (int, optional): Number of layers of the surface. Note that the layers is number of equivalent layers, not number of layers of atoms. Defaults to 3.
24+
surface_supercell (Tuple[int, int], optional): Supercell size of the surface. Default is (1, 1), which means no supercell.
25+
vacuum (float, optional): Vacuum space between the cleaved surface and its periodic image. The total vacuum size will be twice this value. Units in Angstrom. Defaults to 15.0.
26+
vacuum_direction (Literal['a', 'b', 'c']): The direction of the vacuum space. Defaults to 'b'.
27+
Returns:
28+
A dictionary containing the path to the surface structure file.
29+
Keys:
30+
- surface_stru_file: Path to the surface structure file. The format of the generated structure file depends on the input structure file.
31+
Raises:
32+
ValueError: If stru_type is not supported.
33+
"""
34+
return _build_slab(stru_file, stru_type, miller_indices, layers, surface_supercell, vacuum, vacuum_direction)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
from pathlib import Path
2+
from typing import Literal, Tuple
3+
from ase.build import surface, make_supercell
4+
from ase.io import read
5+
6+
from abacustest.constant import A2BOHR
7+
from abacustest.lib_prepare.stru import AbacusSTRU
8+
9+
def build_slab(stru_file: Path,
10+
stru_type: Literal["cif", "poscar", "abacus/stru"] = "cif",
11+
miller_indices: Tuple[int, int, int] = (1, 0, 0),
12+
layers: int = 3,
13+
surface_supercell: Tuple[int, int] = (1, 1),
14+
vacuum: float = 15.0,
15+
vacuum_direction: Literal['a', 'b', 'c'] = 'b'):
16+
"""
17+
Build slab from given structure file.
18+
19+
Args:
20+
stru_file (Path): Path to structure file.
21+
stru_type (Literal["cif", "poscar", "abacus/stru"]): Type of structure file. Defaults to "cif".
22+
miller_indices (Tuple[int, int, int]): Miller indices of the surface. Defaults to (1, 0, 0), which means (100) surface of the structure.
23+
layers (int, optional): Number of layers of the surface. Note that the layers is number of equivalent layers, not number of layers of atoms. Defaults to 3.
24+
surface_supercell (Tuple[int, int], optional): Supercell size of the surface. Default is (1, 1), which means no supercell.
25+
vacuum (float, optional): Vacuum space between the cleaved surface and its periodic image. The total vacuum size will be twice this value. Units in Angstrom. Defaults to 15.0.
26+
vacuum_direction (Literal['a', 'b', 'c']): The direction of the vacuum space. Defaults to 'b'.
27+
Returns:
28+
A dictionary containing the path to the surface structure file.
29+
Keys:
30+
- surface_stru_file: Path to the surface structure file. The format of the generated structure file depends on the input structure file.
31+
Raises:
32+
ValueError: If stru_type is not supported.
33+
"""
34+
if stru_type == 'abacus/stru':
35+
stru = AbacusSTRU.read(stru_file, fmt="stru")
36+
stru_ase = stru.to("ase")
37+
elif stru_type in ['cif', 'poscar']:
38+
stru_ase = read(stru_file, format=stru_type)
39+
else:
40+
raise ValueError(f"Unsupported structure file type: {stru_type}")
41+
42+
stru_surface = surface(stru_ase, miller_indices, layers, vacuum=vacuum/2, periodic=True)
43+
stru_surface = make_supercell(stru_surface, [[surface_supercell[0], 0, 0], [0, surface_supercell[1], 0], [0, 0, 1]])
44+
stru_surface_abacusstru = AbacusSTRU.from_ase(stru_surface, metadata={
45+
"lattice_constant": A2BOHR,
46+
"atom_type": "cartesian",
47+
})
48+
stru_surface_abacusstru.sort()
49+
50+
# Permute axis to set vacuum direction along given axis. The vacuum direction create by ase.build.surface is always along z axis.
51+
if vacuum_direction == "a":
52+
stru_surface_abacusstru.permute_lat_vec(mode="cab", rotate_cart_coord=True)
53+
elif vacuum_direction == "b":
54+
stru_surface_abacusstru.permute_lat_vec(mode="bca", rotate_cart_coord=True)
55+
elif vacuum_direction == "c":
56+
pass
57+
58+
h, k, l = miller_indices
59+
surface_stru_file = Path(f"./{stru_file.stem}_{h}{k}{l}_{layers}layer.STRU").absolute()
60+
stru_surface_abacusstru.write(surface_stru_file, fmt=stru_type)
61+
62+
return {'surface_stru_file': surface_stru_file}

0 commit comments

Comments
 (0)