Creating Structures#

pyscal works with standard ASE Atoms objects. You can create structures in three ways:

  1. ASE built-in builders (ase.build.bulk, ase.build.molecule, etc.)

  2. pyscal structure creators (make_crystal, make_element, make_grain_boundary)

  3. Reading from file (ase.io.read supports LAMMPS, POSCAR, CIF, XYZ, …)

1. Using ASE Builders#

from ase.build import bulk

# Primitive FCC cell (1 atom)
cu_prim = bulk("Cu", "fcc")
print(f"Primitive: {len(cu_prim)} atom, cell = {cu_prim.cell.lengths()}")

# Conventional cubic cell (4 atoms)
cu_conv = bulk("Cu", "fcc", cubic=True)
print(f"Conventional: {len(cu_conv)} atoms, cell = {cu_conv.cell.lengths()}")

# Supercell (4x4x4 = 256 atoms)
cu_super = cu_conv.repeat(4)
print(f"Supercell: {len(cu_super)} atoms")
Primitive: 1 atom, cell = [2.55265548 2.55265548 2.55265548]
Conventional: 4 atoms, cell = [3.61 3.61 3.61]
Supercell: 256 atoms

2. pyscal Structure Creators#

make_crystal creates a supercell of a given Bravais type with a specified lattice constant.

from pyscal.structures import make_crystal, available_structures

print(f"Available crystal types: {available_structures()}")
Available crystal types: ['simple_cubic', 'bcc', 'fcc', 'hcp', 'dhcp', 'diamond', 'a15', 'l12', 'b2']
# FCC with explicit lattice constant
fcc = make_crystal("fcc", lattice_constant=3.6, repetitions=(4, 4, 4))
print(f"FCC: {len(fcc)} atoms")

# BCC
bcc = make_crystal("bcc", lattice_constant=2.87, repetitions=(4, 4, 4))
print(f"BCC: {len(bcc)} atoms")

# HCP (needs ca_ratio)
hcp = make_crystal("hcp", lattice_constant=3.2, repetitions=(4, 4, 4), ca_ratio=1.633)
print(f"HCP: {len(hcp)} atoms")

# Diamond cubic
dia = make_crystal("diamond", lattice_constant=5.43, repetitions=(3, 3, 3))
print(f"Diamond: {len(dia)} atoms")
FCC: 256 atoms
BCC: 128 atoms
HCP: 256 atoms
Diamond: 216 atoms

make_element looks up the lattice constant automatically for a given element.

from pyscal.structures import make_element, available_elements

print(f"Available elements (first 15): {available_elements()[:15]}")

fe = make_element("Fe", repetitions=(4, 4, 4))
print(f"\nFe: {len(fe)} atoms, cell = {fe.cell.lengths()}")

al = make_element("Al", repetitions=(4, 4, 4))
print(f"Al: {len(al)} atoms, cell = {al.cell.lengths()}")
Available elements (first 15): ['Ac', 'Ag', 'Al', 'Ar', 'Au', 'Ba', 'Be', 'Ca', 'Cd', 'Ce', 'Co', 'Cr', 'Cs', 'Cu', 'Dy']

Fe: 128 atoms, cell = [11.48 11.48 11.48]
Al: 256 atoms, cell = [16.2 16.2 16.2]

Grain Boundaries#

make_grain_boundary creates a bicrystal with a symmetric tilt grain boundary. You must provide structure (and lattice_constant) or element.

from pyscal.structures import make_grain_boundary

gb = make_grain_boundary(
    axis=[1, 0, 0],
    structure="fcc",
    lattice_constant=4.05,
    sigma=5,
    gb_plane=(0, 1, 3),
)
print(f"Grain boundary: {len(gb)} atoms, cell = {gb.cell.lengths()}")
Grain boundary: 80 atoms, cell = [25.61444904  4.05       12.80722452]

3. Reading from Files#

Use ASE’s read function. All standard formats are supported.

from ase.io import read

# LAMMPS dump file
atoms = read("conf.fcc.dump", format="lammps-dump-text")
print(f"From LAMMPS dump: {len(atoms)} atoms")

# Another LAMMPS dump
atoms2 = read("conf.bcc.dump", format="lammps-dump-text")
print(f"From BCC dump: {len(atoms2)} atoms")
From LAMMPS dump: 1008 atoms
From BCC dump: 1024 atoms

Summary#

Method

When to use

ase.build.bulk()

Standard crystal structures with ASE conventions

make_crystal()

Quick creation with explicit structure type + lattice constant

make_element()

Element-based creation with automatic lattice constant lookup

make_grain_boundary()

Bicrystal grain boundary structures

ase.io.read()

Loading from LAMMPS, POSCAR, CIF, XYZ, etc.