CrystOD for phonopy users#

crystod-phonon runs on the files a phonopy calculation leaves behind and adds the symmetry layer: which irrep every mode belongs to, in the labels of the space-group tables, and which structures an imaginary mode can lower the crystal to. Nothing has to be recomputed on the phonopy side, and the phonopy API objects can be handed to CrystOD directly from Python.

What you already have#

phonopy file

how crystod-phonon uses it

unit cell (POSCAR)

-c POSCAR

FORCE_SETS

read by default from the current directory, as phonopy does (--modulation also looks next to the -c file; the other modes stop with a one-line error when it is missing)

FORCE_CONSTANTS

--readfc

the supercell (DIM)

--dim "4 4 4" (or --dim 4 4 4; a nine-value diagonal matrix works too)

phonopy_disp.yaml

supplies the supercell to --modulation when --dim is omitted

phonopy_params.yaml

--yaml phonopy_params.yaml, in place of -c + --dim in --modulation and --subgroup

BORN

--nac in --fatband and --lt

The unit cell is reduced to its primitive cell (primitive_matrix="auto"), so q points are given in primitive reciprocal coordinates, either as three numbers or as a special-point label (GM, R, X, M, …).

A unit cell plus 4x4x4 FORCE_SETS of cubic SrTiO3 is bundled with the package, and --example copies them into the current directory and runs the ordinary command line, so everything on this page can be tried before your own data is at hand:

crystod-phonon --example
Examples bundled with crystod-phonon (run one with --example NAME):

  SrTiO3           ISO-IR irrep labels of the phonon modes of cubic SrTiO3 (writes phonon_irreps.yaml)
                   = crystod-phonon --irreps --dim '4 4 4' -c 221_PPOSCAR_SrTiO3
  SrTiO3_subgroup  space groups the imaginary R-point phonon of cubic SrTiO3 can condense into
                   = crystod-phonon --subgroup --dim '4 4 4' -c 221_PPOSCAR_SrTiO3 --qpoint R

Irreps at every special point (--irreps)#

phonopy’s --irreps (the IRREPS tag) works one q point per run, and assigns Mulliken labels of the point group (T1u, Eg, …) at the Gamma point only; elsewhere it prints the characters. crystod-phonon --irreps labels every degenerate level at every special q point of the space group in one run, with the ISO-IR labels (GM4-, R5-, X5+, … - the Miller-Love convention of the ISOTROPY Software Suite, GM4- being T1u in m-3m). These are the labels the isotropy-subgroup tables and the direct-product tables use, so a level can be carried straight into crystod-group --parent or --product.

mkdir phonopy-guide && cd phonopy-guide
crystod-phonon --example SrTiO3
Wrote 221_PPOSCAR_SrTiO3 (bundled example input)
Wrote FORCE_SETS (bundled example input)
Running: crystod-phonon --irreps --dim '4 4 4' -c 221_PPOSCAR_SrTiO3

Phonon irreps written to: phonon_irreps.yaml

The result is the file, phonon_irreps.yaml: the special points of the space group, then for each of them the modes grouped into degenerate sets, with their irrep and frequency in THz:

space_group: Pm-3m
special_points:
- # GM
  q_position: [0.0, 0.0, 0.0]
- # R
  q_position: [0.5, 0.5, 0.5]
- # X
  q_position: [0.0, 0.5, 0.0]
- # M
  q_position: [0.5, 0.5, 0.0]

irreps:
- q_label: GM
  q_position: [0.0, 0.0, 0.0]
  - # 1 2 3
    irrep_label: ['GM4-(3)']
    frequency:   0.0000003685
  - # 4 5 6
    irrep_label: ['GM4-(3)']
    frequency:   2.6629186664
  - # 7 8 9
    irrep_label: ['GM4-(3)']
    frequency:   4.7144147359
  - # 10 11 12
    irrep_label: ['GM5-(3)']
    frequency:   7.3464877515
  - # 13 14 15
    irrep_label: ['GM4-(3)']
    frequency:  15.3054117938

- q_label: R
  q_position: [0.5, 0.5, 0.5]
  - # 1 2 3
    irrep_label: ['R5-(3)']
    frequency:  -1.0867090338
  - # 4 5 6
    irrep_label: ['R4-(3)']
    frequency:   3.9890931052
  ...

At Gamma the 15 modes of the five-atom cell are 4 x GM4- (T1u: the acoustic triplet plus the three infrared-active modes) + 1 x GM5- (T2u, the silent mode), the textbook count for a cubic perovskite. At R the lowest level is a negative-frequency R5- triplet: the antiferrodistortive octahedral-rotation instability of cubic SrTiO3, which the rest of this page follows. The comment line above each set (# 1 2 3) gives the 1-based band indices, the same numbering --vector --mode and --modulation --mode take.

--all-irreps also labels the midpoint of every seekpath path segment, i.e. the symmetry lines (DT, Z, SM, LD, S, T for Pm-3m), and writes phonon_irreps_all.yaml instead, so the two surveys coexist:

crystod-phonon --irreps --dim "4 4 4" -c 221_PPOSCAR_SrTiO3 --all-irreps
# -> phonon_irreps_all.yaml
k_path: GM-X-M-GM-R-X | R-M  # seekpath
path_midpoints:  # midpoints of the k-path segments, ISO-IR k-vector types
- # DT (midpoint of GM-X)
  q_position: [0.0, 0.25, 0.0]
- # Z (midpoint of X-M)
  q_position: [0.25, 0.5, 0.0]
  ...

- q_label: DT
  segment: GM-X
  q_position: [0.0, 0.25, 0.0]
  - # 1 2
    irrep_label: ['DT5(2)']
  ...

This is what tells two branches of the same line apart (which DT5 is which) and takes a few times longer than the special-points-only default (about 10 s against 2 s for this example). --readfc reads FORCE_CONSTANTS in place of FORCE_SETS in every mode. Documentation: 21. Phonon irreps, Symmetry lines as well.

Imaginary modes: which structures? (--subgroup)#

An imaginary mode says the structure is unstable; its irrep says what it can turn into. --subgroup labels the imaginary levels and lists the isotropy subgroups of their irreps, i.e. every order-parameter direction of the degenerate level and the space group it condenses into:

crystod-phonon --example SrTiO3_subgroup
Kept 221_PPOSCAR_SrTiO3 (identical to the bundled example input)
Kept FORCE_SETS (identical to the bundled example input)
Running: crystod-phonon --subgroup --dim '4 4 4' -c 221_PPOSCAR_SrTiO3 --qpoint R

* Parent structure *
Pm-3m (No. 221)

* Imaginary mode at q = (0.5, 0.5, 0.5) (R) *
mode 1, 2, 3: -1.086709 THz, irrep R5- (degeneracy 3)

irrep                subgroup           size  index
R5-(0,0,a)           140 I4/mcm         2     6
R5-(a,a,a)           167 R-3c           2     8
R5-(0,a,a)           74 Imma            2     12
R5-(0,a,b)           12 C2/m            2     24
R5-(a,a,b)           15 C2/c            2     24
R5-(a,b,c)           2 P-1              2     48

The distortion of each order-parameter direction can be generated with
crystod-phonon --modulation, or by adding --modulate here.

This is the R-point story of SrTiO3 in one table. The R5- triplet is the rotation of the TiO6 octahedra about one, two or three cubic axes: rotating about one axis, (0,0,a), gives the tetragonal I4/mcm phase that SrTiO3 actually adopts below 105 K; equal rotations about all three, (a,a,a), give R-3c (the LaAlO3 structure); two axes, (0,a,a), give Imma; and the unequal combinations (0,a,b), (a,a,b), (a,b,c) lower the symmetry to C2/m, C2/c and P-1. size is the primitive cell of the daughter phase in units of the parent one, index the index of the subgroup. Freezing in a single eigenvector, the way a MODULATION run does, explores one of these six directions, and which one depends on the eigenvector the diagonalizer happened to return for the degenerate level.

Without --qpoint every q point commensurate with the supercell is scanned (64 of them for 4x4x4), most unstable level first, so the unstable q points do not have to be known beforehand; for this force set only the R triplet turns up. --threshold sets what counts as imaginary (default -0.1 THz), and --yaml phonopy_params.yaml replaces -c + --dim.

--modulate writes the distorted structure of every direction as well (--example passes further options on):

crystod-phonon --example SrTiO3_subgroup --modulate
* Distorted structures (amplitude 0.3 A) *
R5-(0,0,a)             I4/mcm     -> MPOSCAR_R_R5-_0-0-a_I4mcm
    crystod-phonon --modulation -c 221_PPOSCAR_SrTiO3 --dim "4 4 4" --qpoint 0.5 0.5 0.5 --mode 1 --amplitude 0.3
R5-(0,a,a)             Imma       -> MPOSCAR_R_R5-_0-a-a_Imma
    crystod-phonon --modulation -c 221_PPOSCAR_SrTiO3 --dim "4 4 4" --qpoint 0.5 0.5 0.5 --mode 1 2 --amplitude 0.3 0.3
R5-(0,a,b)             C2/m       -> MPOSCAR_R_R5-_0-a-b_C2m
    crystod-phonon --modulation -c 221_PPOSCAR_SrTiO3 --dim "4 4 4" --qpoint 0.5 0.5 0.5 --mode 1 2 --amplitude 0.3 0.16434
R5-(a,a,a)             R-3c       -> MPOSCAR_R_R5-_a-a-a_R-3c
    crystod-phonon --modulation -c 221_PPOSCAR_SrTiO3 --dim "4 4 4" --qpoint 0.5 0.5 0.5 --mode 1 2 3 --amplitude 0.3 0.3 0.3
R5-(a,a,b)             C2/c       -> MPOSCAR_R_R5-_a-a-b_C2c
    crystod-phonon --modulation -c 221_PPOSCAR_SrTiO3 --dim "4 4 4" --qpoint 0.5 0.5 0.5 --mode 1 2 3 --amplitude 0.3 0.3 0.16434
R5-(a,b,c)             P-1        -> MPOSCAR_R_R5-_a-b-c_P-1
    crystod-phonon --modulation -c 221_PPOSCAR_SrTiO3 --dim "4 4 4" --qpoint 0.5 0.5 0.5 --mode 1 2 3 --amplitude 0.3 0.16434 0.08913

Six POSCAR files, one per direction, named after the subgroup, each with the --modulation command that reproduces it; the space group of every file is measured with spglib, not assumed. These are the candidate structures to relax in a structure search. --amplitude scales all of them (default 0.3 A). Documentation: 27. Subgroups from imaginary modes, Generating the daughter structures, and the theory in Isotropy subgroups.

--modulation versus phonopy’s MODULATION#

phonopy’s MODULATION tag (MODULATION = 2 2 2, 1/2 1/2 1/2 1 0.3: supercell, q point, band index, amplitude) freezes one eigenvector of the dynamical matrix into MPOSCAR. For a non-degenerate mode that is all there is to it. For a degenerate level, the eigenvector behind a band index is whatever the diagonalizer returned, an arbitrary combination within the level, and the structure it produces has no defined symmetry. crystod-phonon --modulation block-diagonalizes the dynamical matrix in the irrep-projected basis first, so that each mode number is one component of the order parameter: --mode 1 of the R triplet is the (0,0,a) rotation, --mode 1 2 3 with equal amplitudes is (a,a,a). It also prints the irrep and degeneracy of every mode, the star of q, and the space group of the structure it wrote, which it names after that space group.

What is frozen in is the same physical displacement: phonopy’s eigenvector divided by the square root of the atomic mass, with its Bloch phase, so for a non-degenerate mode at a time-reversal-invariant q the pattern is the one MODULATION writes, up to its sign. Only the amplitude is counted differently. phonopy multiplies that field by its amplitude divided by the square root of the number of supercell atoms (a quantity in Å·√amu); --amplitude is in Å, the norm of the displacement of one primitive cell. See What is frozen in.

Without --mode, the mode table is printed so the modes can be chosen:

crystod-phonon --modulation -c 221_PPOSCAR_SrTiO3 --qpoint 0.5 0.5 0.5
Supercell 4x4x4 inferred from the 320 atoms of FORCE_SETS; pass --dim if that is not the supercell of your force calculation. Primitive cell: 5 atoms of the 5-atom input cell (primitive_matrix auto).
Loading '221_PPOSCAR_SrTiO3 + FORCE_SETS' at q = [0.5, 0.5, 0.5]...

Phonon modes at q = [0.5 0.5 0.5]
 Mode    Freq (THz)         Irrep   Degeneracy
--------------------------------------------------
    1       -1.0867        R5-(3)            3
    2       -1.0867        R5-(3)            3
    3       -1.0867        R5-(3)            3
    4        3.9891        R4-(3)            3
    5        3.9891        R4-(3)            3
    6        3.9891        R4-(3)            3
    7       11.6887        R5+(3)            3
    ...
   15       23.2302        R2-(1)            1

Star of q (arms related by the space-group rotations):
  |G| = 48, |G_k| = 48, |star of k| = 1
  arm 1: k = [+0.5, +0.5, +0.5]

No --mode given. Choose mode number(s) from the table above and rerun with
--mode (and optionally --amplitude) to generate a modulated structure.

Then with the modes:

crystod-phonon --modulation -c 221_PPOSCAR_SrTiO3 --qpoint 0.5 0.5 0.5 --mode 1 2 3 --amplitude 0.3
Generating modulated structure...
  q-point: [0.5, 0.5, 0.5]
  Modes: [1, 2, 3]
  Amplitudes (A): [0.3, 0.3, 0.3]

Symmetry of the generated structure:
Space group: R-3c (#167)
Hall symbol: -R 3 2"c

Modulated structure written to: MPOSCAR_R_mode1+2+3_R5-_R-3c

Note that --dim was not given: --modulation takes the supercell from --dim if present, else from the supercell_matrix of a phonopy_disp.yaml (or phonopy_params.yaml) in the current directory, else from the atom count of FORCE_SETS, and always prints which. --yaml phonopy_params.yaml in place of -c writes the same file byte for byte. Several q points combine through --qpoint1/--mode1/--amplitude1, --qpoint2/..., which is how the arms of a multi-arm star (the three M points of a perovskite) are frozen in together. Any arm, written as any q + G, is accepted: -0.5 0.5 0 and 0.5 0.5 0 differ by a reciprocal lattice vector and give one structure. Documentation: 25. Phonon modulation, Where the supercell comes from.

Fatbands, L/T character and eigenvectors#

--fatband draws the dispersion along the seekpath path with the element-projected weight of every mode as the dot size, one PDF per element in the VESTA element colors, straight from -c + FORCE_SETS; no band.conf or band.yaml is needed. --element O restricts it to one element, --band/--band-labels give a manual path, and --nac reads BORN for the LO/TO splitting (the files are written as fatband_nac_<El>.pdf and phonon_band_LT_nac.pdf, so both versions coexist). Documentation: 22. Phonon fatbands.

crystod-phonon --fatband --dim 4 4 4 -c 221_PPOSCAR_SrTiO3
Space group: Pm-3m (#221)
k-path (seekpath): $\Gamma$-X-M-$\Gamma$-R-X  R-M

Computing phonon band structure with eigenvectors (306 q-points)...
Fatband for Sr written to: fatband_Sr.pdf
Fatband for Ti written to: fatband_Ti.pdf
Fatband for O written to: fatband_O.pdf

--lt draws the same dispersion colored by the longitudinal/transverse character of each mode, the norm of the eigenvector projected onto the propagation direction (red = longitudinal, blue = transverse, white = mixed), valid along diagonal path segments as well; with --nac the split-off LO branches come out purely red. Documentation: 23. Longitudinal/transverse bands.

crystod-phonon --lt --dim 4 4 4 -c 221_PPOSCAR_SrTiO3
# -> phonon_band_LT.pdf

--vector diagonalizes the dynamical matrix at one q point, prints the mode table with irrep labels, and exports the chosen modes as .vesta files with displacement arrows; --mode takes several numbers and sums them, degenerate levels are exported in the same symmetry-adapted form as --modulation, and --conventional writes the conventional cell. For a zone-boundary q point the commensurate supercell and the Bloch phases are applied automatically: Documentation: 24. Phonon eigenvectors.

crystod-phonon --vector --dim "4 4 4" -c 221_PPOSCAR_SrTiO3 --qpoint R --mode 1 2 3
Selected q-point: R = [0.5, 0.5, 0.5]

Phonon modes at q = R
 Mode    Freq (THz)  Irrep
----------------------------------------
    1       -1.0867  R5-(3)
    2       -1.0867  R5-(3)
    3       -1.0867  R5-(3)
    4        3.9891  R4-(3)
    ...

Mode table written to: phonon_modes_SrTiO3_R.txt

Commensurate supercell for visualization: 2x2x2 primitive cells
  + mode 1: R5-(3), -1.0867 THz
  + mode 2: R5-(3), -1.0867 THz
  + mode 3: R5-(3), -1.0867 THz
Sum of modes 1+2+3 written to: POSCAR_SrTiO3_R_mode01+02+03_R5-.vesta

The remaining mode, --vibration, needs no forces at all: it lists the irrep-grouped vibration spaces at a q point from the crystal symmetry alone (26. Vibration bases).

The Python API on a live Phonopy object#

Everything above is also a function of crystod.phonon, taking the Phonopy object you already have. label_phonon_modes is --irreps without the YAML file, imaginary_mode_subgroups is --subgroup at one q point, and scan_imaginary_modes is the full scan:

import phonopy
from crystod.phonon import label_phonon_modes, imaginary_mode_subgroups

ph = phonopy.load(supercell_matrix=[4, 4, 4], primitive_matrix="auto",
                  unitcell_filename="221_PPOSCAR_SrTiO3",
                  force_sets_filename="FORCE_SETS")

for mode in label_phonon_modes(ph, [0.5, 0.5, 0.5]):
    print(mode)

for result in imaginary_mode_subgroups(ph, [0.5, 0.5, 0.5]):
    mode = result.mode
    print(f"{mode.frequency:.4f} THz  {'+'.join(mode.labels)}  (degeneracy {mode.degeneracy})")
    for sub in result.subgroups:
        print("   ", sub.label, "->", sub.symbol)
modes 1,2,3: -1.0867 THz  R5-
modes 4,5,6: 3.9891 THz  R4-
modes 7,8,9: 11.6887 THz  R5+
modes 10,11,12: 12.6621 THz  R4-
modes 13,14: 14.8133 THz  R3-
modes 15: 23.2302 THz  R2-
-1.0867 THz  R5-  (degeneracy 3)
    R5-(0,0,a) -> I4/mcm
    R5-(a,a,a) -> R-3c
    R5-(0,a,a) -> Imma
    R5-(0,a,b) -> C2/m
    R5-(a,a,b) -> C2/c
    R5-(a,b,c) -> P-1

Each PhononMode carries band_indices (1-based), frequency, labels, qpoint, qpoint_label, degeneracy and is_imaginary; a q point given as another arm of the star ([-0.5, 0.5, 0.5]) is mapped onto the tabulated one. scan_imaginary_modes(ph) runs the same over every commensurate q point (commensurate_qpoints(ph), 64 here), most unstable level first, and a level whose irrep has no tabulated subgroups comes back with the reason in result.errors instead of stopping the scan:

from crystod.phonon import scan_imaginary_modes, commensurate_qpoints

len(commensurate_qpoints(ph))          # 64
for result in scan_imaginary_modes(ph):
    print(result.mode, [sub.symbol for sub in result.subgroups], result.errors)
modes 1,2,3: -1.0867 THz  R5- ['I4/mcm', 'R-3c', 'Imma', 'C2/m', 'C2/c', 'P-1'] {}

Note

Build the Phonopy object with primitive_matrix="auto", as above. With an identity primitive matrix on a supercell-sized unit cell, a zone-boundary instability folds onto the supercell Gamma point, where no irrep of the parent space group can be attached to it. The -c route of the command line always uses "auto".

Documentation: Phonon modes and their irreps, From imaginary phonons to subgroups.

Where next#

  • Python API: the full API page, including crystod.group.isotropy_subgroups for the subgroups of any irrep without a phonon calculation.

  • Tutorials: notebook 01 (phonon irrep labeling, with the labels drawn on a matplotlib dispersion) and notebook 02 (the isotropy subgroup search, including the experiment that shows what freezing one eigenvector at a time misses).

  • crystod-phonon: the reference of every mode flag, and 13. Isotropy subgroups for the same tables from crystod-group --parent Pm-3m --irrep R5-.