or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-tools.mdcore-phonopy.mdgruneisen.mdindex.mdloading.mdqha.mdstructure.md

structure.mddocs/

0

# Crystal Structure Handling

1

2

Handle crystalline structure representations, transformations, and symmetry operations for phonon calculations. Phonopy provides comprehensive tools for managing crystal structures including unit cells, supercells, primitive cells, and symmetry operations.

3

4

## Capabilities

5

6

### PhonopyAtoms Class

7

8

Core container for atomic structure information with comprehensive manipulation capabilities.

9

10

```python { .api }

11

class PhonopyAtoms:

12

def __init__(

13

self,

14

symbols: Optional[Sequence] = None,

15

numbers: Optional[Union[Sequence, np.ndarray]] = None,

16

masses: Optional[Union[Sequence, np.ndarray]] = None,

17

magnetic_moments: Optional[Union[Sequence, np.ndarray]] = None,

18

scaled_positions: Optional[Union[Sequence, np.ndarray]] = None,

19

positions: Optional[Union[Sequence, np.ndarray]] = None,

20

cell: Optional[Union[Sequence, np.ndarray]] = None,

21

atoms: Optional["PhonopyAtoms"] = None,

22

magmoms: Optional[Union[Sequence, np.ndarray]] = None,

23

pbc: Optional[bool] = None

24

):

25

"""

26

Initialize atomic structure container.

27

28

Parameters:

29

- symbols: Chemical symbols as list of strings

30

- numbers: Atomic numbers as list/array of integers

31

- masses: Atomic masses in atomic mass units (amu)

32

- magnetic_moments: Magnetic moments for each atom

33

- scaled_positions: Atomic positions in fractional coordinates

34

- positions: Atomic positions in Cartesian coordinates (Å)

35

- cell: Unit cell lattice vectors as 3x3 array (Å)

36

- atoms: Copy from existing PhonopyAtoms object (deprecated)

37

- magmoms: Magnetic moments for each atom (deprecated, use magnetic_moments)

38

- pbc: Periodic boundary conditions (deprecated, unused)

39

"""

40

41

def copy(self) -> PhonopyAtoms:

42

"""Create deep copy of PhonopyAtoms object."""

43

44

def __len__(self) -> int:

45

"""Get number of atoms in structure."""

46

47

def __getitem__(self, index) -> PhonopyAtoms:

48

"""Get subset of atoms by index or slice."""

49

```

50

51

**Example:**

52

53

```python

54

from phonopy.structure.atoms import PhonopyAtoms

55

import numpy as np

56

57

# Create structure from scratch

58

lattice = [[4.0, 0.0, 0.0],

59

[0.0, 4.0, 0.0],

60

[0.0, 0.0, 4.0]]

61

62

positions = [[0.0, 0.0, 0.0],

63

[0.5, 0.5, 0.5]]

64

65

symbols = ['Si', 'Si']

66

67

atoms = PhonopyAtoms(symbols=symbols,

68

scaled_positions=positions,

69

cell=lattice)

70

71

# Alternative using atomic numbers

72

numbers = [14, 14] # Silicon

73

atoms = PhonopyAtoms(numbers=numbers,

74

scaled_positions=positions,

75

cell=lattice)

76

77

# Create copy and modify

78

atoms_copy = atoms.copy()

79

print(f"Number of atoms: {len(atoms)}")

80

```

81

82

### Structure Properties

83

84

Access and manipulate structural properties.

85

86

```python { .api }

87

def get_cell(self) -> ndarray:

88

"""

89

Get unit cell lattice vectors.

90

91

Returns:

92

3x3 array of lattice vectors in Å

93

"""

94

95

def get_positions(self) -> ndarray:

96

"""

97

Get atomic positions in Cartesian coordinates.

98

99

Returns:

100

Nx3 array of positions in Å

101

"""

102

103

def get_scaled_positions(self) -> ndarray:

104

"""

105

Get atomic positions in fractional coordinates.

106

107

Returns:

108

Nx3 array of fractional positions [0,1)

109

"""

110

111

def get_masses(self) -> ndarray:

112

"""

113

Get atomic masses.

114

115

Returns:

116

Array of masses in atomic mass units (amu)

117

"""

118

119

def get_chemical_symbols(self) -> list:

120

"""

121

Get chemical symbols.

122

123

Returns:

124

List of element symbols as strings

125

"""

126

127

def get_atomic_numbers(self) -> ndarray:

128

"""

129

Get atomic numbers.

130

131

Returns:

132

Array of atomic numbers (integers)

133

"""

134

135

def get_magnetic_moments(self) -> ndarray:

136

"""Get magnetic moments for each atom."""

137

138

def get_number_of_atoms(self) -> int:

139

"""Get total number of atoms."""

140

141

@property

142

def volume(self) -> float:

143

"""Get unit cell volume in ų."""

144

```

145

146

**Example:**

147

148

```python

149

# Access structure properties

150

cell = atoms.get_cell()

151

positions = atoms.get_positions() # Cartesian coordinates

152

scaled_pos = atoms.get_scaled_positions() # Fractional coordinates

153

symbols = atoms.get_chemical_symbols()

154

masses = atoms.get_masses()

155

156

print(f"Cell volume: {atoms.volume:.2f} ų")

157

print(f"Lattice parameters: {np.linalg.norm(cell, axis=1)}")

158

print(f"Chemical formula: {symbols}")

159

```

160

161

### Structure Modifications

162

163

Modify atomic structures for phonon calculations.

164

165

```python { .api }

166

def set_cell(self, cell: ArrayLike):

167

"""

168

Set unit cell lattice vectors.

169

170

Parameters:

171

- cell: 3x3 array of lattice vectors in Å

172

"""

173

174

def set_positions(self, positions: ArrayLike):

175

"""

176

Set atomic positions in Cartesian coordinates.

177

178

Parameters:

179

- positions: Nx3 array of positions in Å

180

"""

181

182

def set_scaled_positions(self, scaled_positions: ArrayLike):

183

"""

184

Set atomic positions in fractional coordinates.

185

186

Parameters:

187

- scaled_positions: Nx3 array of fractional positions

188

"""

189

190

def set_masses(self, masses: ArrayLike):

191

"""

192

Set atomic masses.

193

194

Parameters:

195

- masses: Array of masses in amu

196

"""

197

198

def set_chemical_symbols(self, symbols: list):

199

"""

200

Set chemical symbols.

201

202

Parameters:

203

- symbols: List of element symbols

204

"""

205

206

def set_magnetic_moments(self, magmoms: ArrayLike):

207

"""

208

Set magnetic moments.

209

210

Parameters:

211

- magmoms: Array of magnetic moments

212

"""

213

```

214

215

**Example:**

216

217

```python

218

# Scale unit cell (e.g., for thermal expansion)

219

new_cell = atoms.get_cell() * 1.02 # 2% expansion

220

atoms.set_cell(new_cell)

221

222

# Modify atomic positions

223

positions = atoms.get_positions()

224

positions[0] += [0.1, 0.0, 0.0] # Displace first atom

225

atoms.set_positions(positions)

226

227

# Set custom masses (e.g., for isotope effects)

228

masses = atoms.get_masses()

229

masses[0] = 28.0 # Set first atom to Si-28

230

atoms.set_masses(masses)

231

```

232

233

### Supercell Generation

234

235

Create supercells for phonon calculations.

236

237

```python { .api }

238

def get_supercell(

239

unitcell: PhonopyAtoms,

240

supercell_matrix: ArrayLike,

241

symprec: float = 1e-5

242

) -> Supercell:

243

"""

244

Create supercell from unit cell.

245

246

Parameters:

247

- unitcell: Unit cell PhonopyAtoms object

248

- supercell_matrix: 3x3 transformation matrix or [nx, ny, nz]

249

- symprec: Symmetry precision for atom mapping

250

251

Returns:

252

Supercell object (extends PhonopyAtoms)

253

"""

254

255

class Supercell(PhonopyAtoms):

256

"""Supercell structure class with additional supercell-specific methods."""

257

258

def get_supercell_to_unitcell_map(self) -> ndarray:

259

"""

260

Get mapping from supercell atoms to unit cell atoms.

261

262

Returns:

263

Array mapping each supercell atom to its unit cell origin

264

"""

265

266

def get_unitcell_to_supercell_map(self) -> list:

267

"""

268

Get mapping from unit cell atoms to supercell atoms.

269

270

Returns:

271

List of arrays containing supercell indices for each unit cell atom

272

"""

273

```

274

275

**Example:**

276

277

```python

278

from phonopy.structure.cells import get_supercell

279

280

# Create 2x2x2 supercell

281

supercell_matrix = [[2, 0, 0], [0, 2, 0], [0, 0, 2]]

282

supercell = get_supercell(atoms, supercell_matrix)

283

284

print(f"Unit cell atoms: {len(atoms)}")

285

print(f"Supercell atoms: {len(supercell)}")

286

print(f"Supercell volume: {supercell.volume:.2f} ų")

287

288

# Get atom mappings

289

sc_to_uc_map = supercell.get_supercell_to_unitcell_map()

290

uc_to_sc_map = supercell.get_unitcell_to_supercell_map()

291

292

print(f"Supercell atom 0 maps to unit cell atom: {sc_to_uc_map[0]}")

293

print(f"Unit cell atom 0 maps to supercell atoms: {uc_to_sc_map[0]}")

294

```

295

296

### Primitive Cell Operations

297

298

Handle primitive cell transformations and standardization.

299

300

```python { .api }

301

def get_primitive(

302

unitcell: PhonopyAtoms,

303

primitive_matrix: ArrayLike | str,

304

symprec: float = 1e-5

305

) -> Primitive:

306

"""

307

Create primitive cell from unit cell.

308

309

Parameters:

310

- unitcell: Unit cell PhonopyAtoms object

311

- primitive_matrix: 3x3 transformation matrix or string ('auto', 'F', 'I', etc.)

312

- symprec: Symmetry precision

313

314

Returns:

315

Primitive cell object (extends PhonopyAtoms)

316

"""

317

318

def get_primitive_matrix(

319

spacegroup_type: str,

320

lattice: ArrayLike = None

321

) -> ndarray:

322

"""

323

Get primitive transformation matrix for given space group.

324

325

Parameters:

326

- spacegroup_type: Bravais lattice type ('P', 'F', 'I', 'A', 'C', 'R')

327

- lattice: Unit cell lattice vectors for rhombohedral case

328

329

Returns:

330

3x3 primitive transformation matrix

331

"""

332

333

def guess_primitive_matrix(

334

unitcell: PhonopyAtoms,

335

symprec: float = 1e-5

336

) -> ndarray:

337

"""

338

Automatically determine primitive matrix from unit cell symmetry.

339

340

Parameters:

341

- unitcell: Unit cell structure

342

- symprec: Symmetry precision

343

344

Returns:

345

3x3 primitive transformation matrix

346

"""

347

348

class Primitive(PhonopyAtoms):

349

"""Primitive cell structure class."""

350

351

def get_primitive_to_unitcell_map(self) -> ndarray:

352

"""Get mapping from primitive to unit cell atoms."""

353

354

def get_unitcell_to_primitive_map(self) -> list:

355

"""Get mapping from unit cell to primitive atoms."""

356

```

357

358

**Example:**

359

360

```python

361

from phonopy.structure.cells import (get_primitive, get_primitive_matrix,

362

guess_primitive_matrix)

363

364

# Get primitive cell automatically

365

primitive = get_primitive(atoms, primitive_matrix='auto')

366

print(f"Unit cell atoms: {len(atoms)}")

367

print(f"Primitive cell atoms: {len(primitive)}")

368

369

# Get primitive matrix for face-centered cubic

370

fcc_matrix = get_primitive_matrix('F')

371

print("FCC primitive matrix:")

372

print(fcc_matrix)

373

374

# Guess primitive matrix from symmetry

375

guessed_matrix = guess_primitive_matrix(atoms, symprec=1e-5)

376

print("Guessed primitive matrix:")

377

print(guessed_matrix)

378

379

# Apply specific primitive matrix

380

primitive_custom = get_primitive(atoms, fcc_matrix)

381

```

382

383

### Crystal Symmetry

384

385

Analyze and apply crystal symmetry operations.

386

387

```python { .api }

388

class Symmetry:

389

"""Crystal symmetry operations and analysis."""

390

391

def __init__(

392

self,

393

cell: PhonopyAtoms,

394

symprec: float = 1e-5,

395

angle_tolerance: float = -1.0,

396

is_symmetry: bool = True

397

):

398

"""

399

Initialize symmetry analysis.

400

401

Parameters:

402

- cell: Crystal structure

403

- symprec: Symmetry precision

404

- angle_tolerance: Angle tolerance for symmetry detection

405

- is_symmetry: Whether to use symmetry

406

"""

407

408

def get_symmetry_operations(self) -> dict:

409

"""

410

Get symmetry operations.

411

412

Returns:

413

Dictionary with 'rotations' and 'translations' arrays

414

"""

415

416

def get_reciprocal_operations(self) -> ndarray:

417

"""Get symmetry operations in reciprocal space."""

418

419

def get_pointgroup_operations(self) -> ndarray:

420

"""Get point group operations (rotations only)."""

421

422

def get_international_table(self) -> str:

423

"""Get international space group symbol."""

424

425

def get_wyckoff_positions(self) -> list:

426

"""Get Wyckoff positions for atoms."""

427

428

@property

429

def dataset(self) -> dict:

430

"""Symmetry dataset from spglib."""

431

```

432

433

**Example:**

434

435

```python

436

from phonopy.structure.symmetry import Symmetry

437

438

# Analyze crystal symmetry

439

symmetry = Symmetry(atoms, symprec=1e-5)

440

441

# Get symmetry operations

442

sym_ops = symmetry.get_symmetry_operations()

443

rotations = sym_ops['rotations']

444

translations = sym_ops['translations']

445

446

print(f"Number of symmetry operations: {len(rotations)}")

447

print(f"Space group: {symmetry.get_international_table()}")

448

449

# Get point group operations

450

point_group = symmetry.get_pointgroup_operations()

451

print(f"Point group order: {len(point_group)}")

452

453

# Wyckoff positions

454

wyckoff = symmetry.get_wyckoff_positions()

455

print(f"Wyckoff positions: {wyckoff}")

456

```

457

458

### Brillouin Zone Operations

459

460

Handle Brillouin zone operations and k-point generation.

461

462

```python { .api }

463

class BrillouinZone:

464

"""Brillouin zone operations and k-point handling."""

465

466

def __init__(

467

self,

468

primitive: PhonopyAtoms,

469

mesh: ArrayLike = None,

470

is_shift: ArrayLike = None,

471

is_time_reversal: bool = True,

472

is_gamma_center: bool = False,

473

rotations: ArrayLike = None,

474

qpoints: ArrayLike = None

475

):

476

"""

477

Initialize Brillouin zone operations.

478

479

Parameters:

480

- primitive: Primitive cell structure

481

- mesh: k-point mesh dimensions [nx, ny, nz]

482

- is_shift: Mesh shift [sx, sy, sz]

483

- is_time_reversal: Apply time-reversal symmetry

484

- is_gamma_center: Center mesh on gamma point

485

- rotations: Symmetry rotation matrices

486

- qpoints: Specific q-points to use

487

"""

488

489

def get_qpoints(self) -> ndarray:

490

"""Get q-points in reciprocal space."""

491

492

def get_weights(self) -> ndarray:

493

"""Get integration weights for q-points."""

494

495

def get_grid_points(self) -> ndarray:

496

"""Get grid point indices."""

497

498

def get_ir_reciprocal_mesh(self) -> tuple:

499

"""

500

Get irreducible reciprocal mesh.

501

502

Returns:

503

Tuple of (grid_points, weights, grid_mapping)

504

"""

505

```

506

507

### Distance Calculations

508

509

Calculate atomic distances and coordination environments.

510

511

```python { .api }

512

class ShortestPairs:

513

"""Calculate shortest interatomic distances and coordination."""

514

515

def __init__(

516

self,

517

cell: PhonopyAtoms,

518

cutoff_radius: float = None

519

):

520

"""

521

Initialize distance calculations.

522

523

Parameters:

524

- cell: Crystal structure

525

- cutoff_radius: Maximum distance to consider (Å)

526

"""

527

528

def get_shortest_distances(self) -> ndarray:

529

"""Get shortest distances between atoms."""

530

531

def get_nearest_neighbors(self, atom_index: int) -> dict:

532

"""

533

Get nearest neighbors for specific atom.

534

535

Parameters:

536

- atom_index: Index of target atom

537

538

Returns:

539

Dictionary with neighbor indices, distances, and vectors

540

"""

541

```

542

543

## Structure Creation Examples

544

545

### From Crystallographic Data

546

547

```python

548

# Silicon diamond structure

549

lattice_parameter = 5.43 # Å

550

lattice = [[lattice_parameter, 0, 0],

551

[0, lattice_parameter, 0],

552

[0, 0, lattice_parameter]]

553

554

positions = [[0.0, 0.0, 0.0],

555

[0.25, 0.25, 0.25]]

556

557

si_structure = PhonopyAtoms(

558

symbols=['Si', 'Si'],

559

scaled_positions=positions,

560

cell=lattice

561

)

562

563

# Face-centered cubic (FCC) structure

564

fcc_lattice = [[0.0, 2.0, 2.0],

565

[2.0, 0.0, 2.0],

566

[2.0, 2.0, 0.0]]

567

568

fcc_structure = PhonopyAtoms(

569

symbols=['Al'],

570

scaled_positions=[[0.0, 0.0, 0.0]],

571

cell=fcc_lattice

572

)

573

```

574

575

### From File Formats

576

577

```python

578

from phonopy.interface.vasp import read_vasp

579

from phonopy.interface.phonopy_yaml import PhonopyYaml

580

581

# Read from VASP POSCAR

582

atoms_vasp = read_vasp("POSCAR")

583

584

# Read from phonopy.yaml

585

ph_yaml = PhonopyYaml("phonopy.yaml")

586

atoms_yaml = ph_yaml.unitcell

587

```

588

589

### Structure Transformations

590

591

```python

592

# Apply strain to unit cell

593

strain_matrix = [[1.02, 0, 0], # 2% expansion along a

594

[0, 1.0, 0], # No change along b

595

[0, 0, 0.98]] # 2% compression along c

596

597

strained_cell = np.dot(atoms.get_cell(), strain_matrix)

598

atoms_strained = atoms.copy()

599

atoms_strained.set_cell(strained_cell)

600

601

# Rotate structure

602

from scipy.spatial.transform import Rotation

603

rotation = Rotation.from_euler('z', 45, degrees=True) # 45° around z

604

rotation_matrix = rotation.as_matrix()

605

606

rotated_cell = np.dot(atoms.get_cell(), rotation_matrix.T)

607

rotated_positions = np.dot(atoms.get_positions(), rotation_matrix.T)

608

609

atoms_rotated = atoms.copy()

610

atoms_rotated.set_cell(rotated_cell)

611

atoms_rotated.set_positions(rotated_positions)

612

```

613

614

### Complete Structure Workflow

615

616

```python

617

from phonopy import Phonopy

618

from phonopy.structure.atoms import PhonopyAtoms

619

from phonopy.structure.cells import get_supercell, get_primitive

620

from phonopy.structure.symmetry import Symmetry

621

622

# 1. Create or load unit cell structure

623

unitcell = PhonopyAtoms(

624

symbols=['Mg', 'O'],

625

scaled_positions=[[0.0, 0.0, 0.0], [0.5, 0.5, 0.5]],

626

cell=[[4.2, 0, 0], [0, 4.2, 0], [0, 0, 4.2]]

627

)

628

629

# 2. Analyze symmetry

630

symmetry = Symmetry(unitcell, symprec=1e-5)

631

print(f"Space group: {symmetry.get_international_table()}")

632

633

# 3. Get primitive cell

634

primitive = get_primitive(unitcell, primitive_matrix='auto')

635

print(f"Primitive cell volume: {primitive.volume:.2f} ų")

636

637

# 4. Create supercell for phonon calculations

638

supercell_matrix = [[2, 0, 0], [0, 2, 0], [0, 0, 2]]

639

supercell = get_supercell(unitcell, supercell_matrix)

640

641

# 5. Initialize Phonopy with structures

642

ph = Phonopy(unitcell, supercell_matrix, primitive_matrix='auto')

643

644

print(f"Unit cell: {len(ph.unitcell)} atoms")

645

print(f"Primitive: {len(ph.primitive)} atoms")

646

print(f"Supercell: {len(ph.supercell)} atoms")

647

```