| name | abacustest-stru-class |
| description | Programmatically manipulate ABACUS structure files using the AbacusSTRU Python class from abacustest package. Use when: reading/writing STRU files, modifying crystal structures, format conversion (VASP/CIF/ASE/etc.), batch processing structures, fixing atoms, setting magnetic moments, and other programmatic tasks. |
| metadata | {"openclaw":{"emoji":"🐍","requires":{"pip":["abacustest"]}}} |
AbacusSTRU Class Usage Guide
AbacusSTRU is the core Python class in the abacustest package for programmatically manipulating ABACUS crystal structures. It provides complete functionality for structure reading, writing, modification, and conversion.
⚠️ When to Use This Skill
✅ Use this skill:
- "Read and modify STRU files using Python code"
- "Batch convert CIF to STRU format"
- "Fix bottom layers of a surface slab in code"
- "Set magnetic moments for antiferromagnetic systems"
- "Convert structures from ASE/Pymatgen to ABACUS"
- "Apply random perturbations for MD initial structures"
❌ Do not use:
- Manually write/edit STRU file format → Use
abacus-stru skill
- Batch prepare ABACUS inputs via command line → Use
abacustest-prepare-inputs skill
- Modify INPUT parameters → Use
abacus-input-parameter skill
Quick Start
Import Classes
from abacustest.lib_prepare.stru import AbacusSTRU, AbacusATOM
Read Structures
stru = AbacusSTRU.read("STRU", fmt="stru")
stru = AbacusSTRU.read("POSCAR", fmt="poscar")
stru = AbacusSTRU.read("structure.cif", fmt="cif")
Write Structures
stru.write("STRU", fmt="stru")
stru.write("POSCAR", fmt="poscar")
stru.write("structure.cif", fmt="cif")
Basic Property Access
print(stru.natoms)
print(stru.cell)
print(stru.labels)
print(stru.coords)
print(stru.elements)
Core Classes
1. AbacusSTRU - Structure Class
Represents a complete ABACUS crystal structure.
Creation Methods
Method 1: Read from file
stru = AbacusSTRU.read("STRU", fmt="stru")
Method 2: Convert from other formats
stru = AbacusSTRU.from_ase(ase_atoms)
stru = AbacusSTRU.from_pymatgen(pmg_structure)
stru = AbacusSTRU.from_dpdata(dpdata_system, index=0)
stru = AbacusSTRU.from_phonopy(phonopy_atoms)
Method 3: Create from scratch
cell = [[4.0, 0.0, 0.0],
[0.0, 4.0, 0.0],
[0.0, 0.0, 4.0]]
atoms = [
AbacusATOM(label="Si", coord=(0.0, 0.0, 0.0)),
AbacusATOM(label="Si", coord=(2.0, 2.0, 2.0)),
]
stru = AbacusSTRU(cell=cell, atoms=atoms)
Writing to Files
stru.write("STRU", fmt="stru")
stru.write("STRU", fmt="stru", direct=True)
stru.write("STRU", fmt="stru", direct=False)
stru.write("STRU", fmt="stru", empty2x=True)
Export to Other Formats
ase_atoms = stru.to("ase")
pmg_struct = stru.to("pymatgen")
phonopy_atoms = stru.to("phonopy")
2. AbacusATOM - Atom Class
Represents all properties of a single atom.
Creating an Atom
atom = AbacusATOM(
label="Fe",
coord=(0.0, 0.0, 0.0),
element="Fe",
mass=55.845,
pp="Fe.upf",
orb="Fe.orb",
type_mag=2.0,
move=(True, True, True),
mag=3.0,
velocity=(0.0, 0.0, 0.0),
)
Accessing Properties
print(atom.label)
print(atom.coord)
print(atom.element)
print(atom.mass)
print(atom.atommag)
print(atom.noncolinear)
Setting Magnetic Moments
atom.set_atommag(mag=3.0)
atom.set_atommag(mag=2.0, angle1=90, angle2=45)
atom.set_atommag(mag=(1.0, 0.0, 0.0))
Setting Magnetic Constraints (DeltaSpin/CDFT)
atom.constrain = True
atom.constrain = (True, True, True)
atom.constrain = (True, False, True)
atom.constrain = True
atom.lambda_ = 0.1
stru = AbacusSTRU.read("STRU")
for atom in stru.atoms:
if atom.element == "Fe":
atom.constrain = True
Important Notes for Constrain:
constrain=True is used in DeltaSpin/CDFT calculations to fix atomic magnetic moments
- For collinear calculations (
nspin=2), constrain is a boolean
- For non-collinear calculations (
nspin=4), constrain can be a tuple of 3 booleans for x/y/z components
- The
lambda_ parameter controls the constraint strength in DeltaSpin calculations
- Constrained atoms will have their magnetic moments fixed during SCF iterations
Structure Operations
Modifying the Cell
stru.cell = [[5.0, 0.0, 0.0],
[0.0, 5.0, 0.0],
[0.0, 0.0, 5.0]]
import numpy as np
rot_mat = np.array([[0, 1, 0],
[-1, 0, 0],
[0, 0, 1]])
stru.rotate(rot_mat)
stru.permute_lat_vec(mode="bca")
stru.permute_lat_vec(mode="cab")
Modifying Atomic Coordinates
new_coords = [(0.0, 0.0, 0.0), (2.0, 2.0, 2.0)]
stru.coords = new_coords
stru.coords_direct = [(0, 0, 0), (0.5, 0.5, 0.5)]
stru[0].coord = (1.0, 1.0, 1.0)
new_atom = AbacusATOM(label="C", coord=(0.5, 0.5, 0.5))
stru.append(new_atom)
stru.insert(0, new_atom)
del stru[0]
subset = stru.create_subset([0, 1, 2])
Setting Magnetic Moments
stru.atom_mags = [1.0, -1.0, 0.5, 2.0]
stru.atom_mags = [
(1.0, 0.0, 0.0),
(0.0, 1.0, 0.0),
(0.0, 0.0, 1.0),
]
stru.atoms[0].set_atommag(2.0, angle1=90, angle2=0)
Fixing Atoms (for Structure Relaxation)
stru.fix_atom_by_index([0, 1, 2], move=(False, False, False))
stru.fix_atom_by_coord(
min=0.0,
max=5.0,
cartesian=True,
direction=2,
move=(False, False, False)
)
stru.fix_atom_by_index([0, 1], move=(False, False, False), only=True)
Setting Pseudopotential/Orbital Files
pp_dict = {"Si": "Si.upf", "C": "C.upf", "O": "O.upf"}
stru.set_pp(pp_dict, key_type="element")
orb_dict = {"Si": "Si.orb", "C": "C.orb"}
stru.set_orb(orb_dict)
paw_dict = {"Si": "Si.paw"}
stru.set_paw(paw_dict)
Atom Sorting
indices = stru.sort(keep_first_order=True)
Build Supercell
stru_super = stru.supercell([2, 2, 2])
stru_super = stru.supercell([3, 1, 2])
Getting High-Symmetry k-Point Path
point_coords, path = stru.get_kline(
with_time_reversal=True,
recipe="hpkot",
symprec=1e-5
)
Common Use Cases
Use Case 1: Batch Format Conversion
from pathlib import Path
for poscar in Path(".").glob("*/POSCAR"):
stru = AbacusSTRU.read(str(poscar), fmt="poscar")
stru.write(poscar.parent / "STRU", fmt="stru")
Use Case 2: Fix Surface Bottom Layers
stru = AbacusSTRU.read("STRU")
stru.fix_atom_by_coord(min=0.0, max=5.0, cartesian=True, direction=2)
stru.write("STRU_fixed", fmt="stru")
Use Case 3: Set Antiferromagnetic System
stru = AbacusSTRU.read("STRU")
for i, atom in enumerate(stru.atoms):
if i % 2 == 0:
atom.set_atommag(3.0)
else:
atom.set_atommag(-3.0)
stru.write("STRU_AFM", fmt="stru")
Use Case 4: Create ABACUS Input from CIF
stru = AbacusSTRU.read("structure.cif", fmt="cif")
stru.set_pp({"Si": "Si.upf", "O": "O.upf"})
stru.set_orb({"Si": "Si.orb", "O": "O.orb"})
stru.write("STRU", fmt="stru")
Use Case 5: Structure Perturbation (for MD Initial Structure)
import numpy as np
import copy
def perturb_structure(stru, amplitude=0.01):
"""Apply random perturbations to atomic positions"""
new_stru = copy.deepcopy(stru)
for atom in new_stru.atoms:
displacement = np.random.uniform(-amplitude, amplitude, 3)
atom.coord = tuple(c + d for c, d in zip(atom.coord, displacement))
return new_stru
stru = AbacusSTRU.read("STRU")
stru_perturbed = perturb_structure(stru, amplitude=0.02)
stru_perturbed.write("STRU_md", fmt="stru")
Use Case 6: Build Supercell
stru = AbacusSTRU.read("STRU")
stru_super = stru.supercell([2, 2, 2])
stru_super.write("STRU_2x2x2", fmt="stru")
stru_super = stru.supercell([3, 1, 2])
stru_super.write("STRU_3x1x2", fmt="stru")
Use Case 7: DeltaSpin/CDFT Calculation Setup
stru = AbacusSTRU.read("STRU")
for atom in stru.atoms:
if atom.element == "Fe":
atom.set_atommag(mag=3.0)
atom.constrain = True
for atom in stru.atoms:
if atom.element == "Co":
atom.set_atommag(mag=2.0, angle1=90, angle2=0)
atom.constrain = (True, True, False)
for atom in stru.atoms:
if atom.constrain:
atom.lambda_ = 0.1
stru.write("STRU_deltaconstrain", fmt="stru")
Note: For DeltaSpin/CDFT calculations, also set appropriate parameters in INPUT file:
dft_plus_u 1 - Enable DFT+U (if needed)
sc_mag_switch 1 - Enable DeltaSpin constraint
- See
abacus-input-parameter skill for detailed INPUT settings
Unit Conventions
| Operation | Unit | Description |
|---|
| Coordinates/cell in Python API | Angstrom (Å) | Code uniformly uses Å |
| STRU file read/write | Bohr | Automatically converted |
| Direct coordinates | Dimensionless | Fractional coordinates (0-1) |
Magnetic Moment Settings
| Parameter | Description | Priority |
|---|
type_mag | Atom type-level magnetic moment (defined once per type in STRU) | Low |
mag | Single atom-level magnetic moment | High (overrides type_mag) |
angle1/angle2 | Angle settings for non-collinear magnetism | Used with mag |
constrain | Constraint flag for DeltaSpin/CDFT calculations | N/A |
lambda_ | Lambda parameter for constraint strength (DeltaSpin) | N/A |
Non-collinear magnetism: When both mag (3 components) and angle1/angle2 are set:
- ABACUS first calculates the magnitude of
mag: |mag| = √(mx² + my² + mz²)
- Then uses
angle1/angle2 to define the direction
- Final magnetic moment =
|mag| along the direction specified by angles
Magnetic constraints (DeltaSpin/CDFT):
constrain=True (collinear) or constrain=(True, True, True) (non-collinear) fixes the magnetic moment during SCF
- Used in DeltaSpin and Constrained DFT (CDFT) calculations
lambda_ parameter controls the constraint strength (typical values: 0.01-1.0)
- For non-collinear calculations,
constrain can be a tuple to constrain specific components (e.g., (True, False, True) constrains x and z, leaves y free)
Common Errors and Fixes
Error 1: Element Label Mismatch
stru.set_pp({"Si": "Si.upf"}, key_type="label")
Error 2: Atom Types Not Sorted
stru.sort(keep_first_order=True)
stru.write("STRU", fmt="stru")
Error 3: Magnetic Moment Count Mismatch
stru.atom_mags = [1.0, -1.0]
stru.atom_mags = [1.0, -1.0, 1.0, -1.0]
Error 4: Pseudopotential Path Issues
stru.set_pp({"Si": "/absolute/path/Si.upf"}, key_type="label")
Tips
| Tip | Description |
|---|
Use Direct coordinates for output | More readable and easier to modify |
| Match atom labels exactly | Case-sensitive matching |
Set move=(False,False,False) for substrate atoms | Fix bottom layers for surface calculations |
Use Cartesian_angstrom for MD | Easier to set velocities |
| Verify pseudopotential paths | Missing files cause ABACUS crash |
Use latname to avoid manual cell setup | Reduces errors |
Use constrain=True for DeltaSpin/CDFT | Fix magnetic moments of specific atoms |
Set lambda_ for constraint strength | Typical values: 0.01-1.0 |
Related Skills
- STRU file format:
abacus-stru
- Batch input preparation:
abacustest-prepare-inputs
- Model calculations:
abacustest-models
- INPUT parameters:
abacus-input-parameter
- Format conversion:
abacustest-abacus2VaspQeCp2k
External Resources