crystod.bz#
Brillouin zones, k paths and special k points (the crystod-bz domain).
crystod.bz is the Python form of the crystod-bz command. It builds the
first Brillouin zone of a lattice as a polyhedron, generates the seekpath
high-symmetry k path or parses a manual one, folds the reciprocal lattice of
a supercell into the unit-cell zone (--trans-mat), and lists the ISO-IR
special k points of a space group (--show-kpoint). The plotting helpers
return plain Plotly scatter3d trace dictionaries, so the geometry can be
rendered by any Plotly front end or read as numbers. Reciprocal lattices are
(3, 3) arrays whose rows are b1, b2, b3; the command uses
inv(lattice).T, without the factor of 2 pi.
Brillouin-zone geometry and k paths (crystod-bz -c POSCAR)
get_brillouin_zone_3d: vertices, edges and facets of the first Brillouin zone by Voronoi decomposition of the reciprocal lattice.get_seekpath_kpath: the seekpath path of a cell as coordinate segments, labels, standardized primitive lattice and space group.parse_manual_band: a--bandstring as(N, 3)segments.prettify_label:GAMMA,X_1and the like as plot labels.build_bz_traces: the Plotly traces of the zone with its k path.
Supercell folding (crystod-bz --trans-mat)
parse_transformation_matrix: a--trans-matstring as a(3, 3)matrix.get_folded_gamma_points: the|det T|unit-cell q points that fold onto the supercell Gamma point.build_supercell_bz_traces: the Plotly traces of the unit-cell zone tiled with the supercell zone at those points.
Special k-point tables (crystod-bz --show-kpoint)
get_special_kpoints: the ISO-IR special k points of a space group in the primitive (and, for centred lattices, conventional) reciprocal basis.
A typical session:
import numpy as np
from phonopy.interface.vasp import read_vasp
from crystod import bz
from crystod.examples import example_path
cell = read_vasp(example_path("221_PPOSCAR_ScF3"))
segments, labels, lattice, symbol, number = bz.get_seekpath_kpath(cell, 1e-5)
rec_lat = np.linalg.inv(lattice).T
vertices, ridges, facets = bz.get_brillouin_zone_3d(rec_lat)
traces = bz.build_bz_traces(rec_lat, segments, labels)
sg_type, names, primitive, conventional = bz.get_special_kpoints("Fm-3m")
Attributes resolve lazily (PEP 562): import crystod.bz costs nothing beyond
NumPy, and scipy, seekpath, phonopy and the ISO-IR tables are loaded by the
first call that needs them. Bad input raises ValueError through this
namespace (the implementation modules raise SystemExit, which suits the
command line).
- crystod.bz.build_bz_traces(rec_lat, segments, label_segments)[source]#
Build the Plotly traces of a Brillouin zone with an optional k path.
This is the figure
crystod-bzwrites for the unit-cell zone: the reciprocal basis vectorsb1,b2,b3(red, green, blue), the zone edges and corners (black; hovering a corner shows its fractional coordinates) and, whensegmentsis given, the k path (goldenrod) with a marker and label at every k point. The traces are plain dictionaries ofscatter3dspecifications, ready forplotly.graph_objects.Figure(data=traces)or forjson.dumpsinto a page that loads plotly.js, which is what the command does.- Parameters:
rec_lat (ndarray[tuple[Any, ...], dtype[_ScalarT]]) –
(3, 3)reciprocal lattice, rowsb1,b2,b3(seeget_brillouin_zone_3d).segments (list[ndarray[tuple[Any, ...], dtype[_ScalarT]]] | None) – k-path segments as
(N_i, 3)arrays of fractional coordinates in the basisrec_lat, as returned byget_seekpath_kpathorparse_manual_band;Nonedraws the zone alone.label_segments (list[list[str]] | None) – One list of
N_ilabels per segment, shown afterprettify_label;Noneleaves the markers unlabelled.
- Returns:
A list of Plotly
scatter3dtrace dictionaries.- Return type:
list[dict]
Example
>>> import numpy as np >>> from crystod import bz >>> rec_lat = np.linalg.inv(4.07 * np.eye(3)).T >>> path = bz.parse_manual_band("0 0 0 1/2 0 0 1/2 1/2 0 0 0 0") >>> traces = bz.build_bz_traces(rec_lat, path, [["GM", "X", "M", "GM"]]) >>> len(traces), traces[-1]["text"] (12, ['Γ', 'X', 'M', 'Γ'])
- crystod.bz.build_supercell_bz_traces(rec_lat, rec_super_lat, centers)[source]#
Build the Plotly traces of a unit-cell zone tiled with supercell zones.
This is the figure of
crystod-bz --trans-mat: the unit-cell reciprocal basis and zone edges (black, dotted), the supercell reciprocal basis (red, green, blue) and a copy of the supercell Brillouin zone (red) centred at every point ofcenters, with a marker there whose hover text gives the unit-cell fractional coordinates. As inbuild_bz_traces, the result is a list of plainscatter3dtrace dictionaries.- Parameters:
rec_lat (ndarray[tuple[Any, ...], dtype[float64]]) –
(3, 3)reciprocal lattice of the unit cell (rows).rec_super_lat (ndarray[tuple[Any, ...], dtype[float64]]) –
(3, 3)reciprocal lattice of the supercell (rows),inv(trans_mat @ lattice).Tin the command’s convention.centers (ndarray[tuple[Any, ...], dtype[float64]]) –
(n, 3)Cartesian centres of the supercell zones, normally the output ofget_folded_gamma_points.
- Returns:
A list of Plotly
scatter3dtrace dictionaries.- Return type:
list[dict]
Example
>>> import numpy as np >>> from crystod import bz >>> lattice = 4.07 * np.eye(3) >>> T = bz.parse_transformation_matrix("2 0 0 0 2 0 0 0 2") >>> rec_lat = np.linalg.inv(lattice).T >>> rec_super_lat = np.linalg.inv(T @ lattice).T >>> centers = bz.get_folded_gamma_points(T, rec_lat) >>> traces = bz.build_supercell_bz_traces(rec_lat, rec_super_lat, centers) >>> len(centers), len(traces) (8, 61)
- crystod.bz.get_brillouin_zone_3d(rec_lat)[source]#
Construct the first Brillouin zone of a reciprocal lattice.
The first Brillouin zone is the Wigner-Seitz cell of the reciprocal lattice. It is found by a Voronoi decomposition (scipy) of the 3x3x3 block of reciprocal-lattice points around the origin: the Voronoi cell of the origin is the zone. This is the polyhedron
crystod-bzdraws, for the unit cell and, with--trans-mat, for the supercell as well.- Parameters:
rec_lat (ndarray[tuple[Any, ...], dtype[_ScalarT]]) –
(3, 3)array whose rows are the reciprocal basis vectorsb1,b2,b3. Any overall scale is accepted; the command usesinv(lattice).T(no factor of 2 pi), for whichcartesian @ inv(rec_lat)are fractional coordinates.- Returns:
The tuple
(vertices, ridges, facets)whereverticesis an(N, 3)array with the Cartesian coordinates of the zone corners,ridgesis a list with one(M + 1, 3)array per facet holding the closed polyline of its edges (the first vertex is repeated at the end), andfacetsis the same list without the repeated vertex.- Return type:
tuple[ndarray[tuple[Any, …], dtype[_ScalarT]], list, list]
Example
>>> import numpy as np >>> from crystod import bz >>> rec_lat = np.linalg.inv(4.07 * np.eye(3)).T # cubic, a = 4.07 A >>> vertices, ridges, facets = bz.get_brillouin_zone_3d(rec_lat) >>> len(vertices), len(facets) (8, 6) >>> np.allclose(np.abs(vertices @ np.linalg.inv(rec_lat)), 0.5) True
- crystod.bz.get_folded_gamma_points(trans_mat, rec_lat)[source]#
Unit-cell q points that fold onto the Gamma point of a supercell.
The reciprocal lattice of the supercell
trans_mat @ latticeis|det T|times denser than that of the unit cell, and its points fall into|det T|classes modulo the unit-cell reciprocal lattice. One representative per class, brought into the unit-cell Brillouin zone by the minimum-image rule, is a unit-cell q point that becomes Gamma in the supercell;crystod-bz --trans-matprints these points and tiles the supercell zone at each of them.- Parameters:
trans_mat (ndarray[tuple[Any, ...], dtype[float64]]) –
(3, 3)unit-cell to supercell transformation matrix (rows, integer entries), e.g. fromparse_transformation_matrix.rec_lat (ndarray[tuple[Any, ...], dtype[float64]]) –
(3, 3)reciprocal lattice of the unit cell, rowsb1,b2,b3(the command usesinv(lattice).T).
- Returns:
(|det T|, 3)array of Cartesian coordinates, Gamma included;points @ inv(rec_lat)gives them in fractional coordinates of the unit-cell reciprocal basis.- Return type:
ndarray[tuple[Any, …], dtype[float64]]
Example
>>> import numpy as np >>> from crystod import bz >>> rec_lat = np.linalg.inv(4.07 * np.eye(3)).T >>> T = bz.parse_transformation_matrix("1 1 0 -1 1 0 0 0 1") >>> points = bz.get_folded_gamma_points(T, rec_lat) >>> np.round(points @ np.linalg.inv(rec_lat), 3).tolist() [[0.0, 0.0, 0.0], [0.5, 0.5, 0.0]]
- crystod.bz.get_seekpath_kpath(cell, tolerance)[source]#
Generate the recommended high-symmetry k path of a cell with seekpath.
This is the automatic path of
crystod-bz -c POSCARwithout--band. seekpath standardizes the cell first, so the coordinates refer to the reciprocal basis of the seekpath standardized primitive cell, which is returned alongside; when that cell differs from the input, the command prints a note and draws the zone for the standardized cell.- Parameters:
cell (PhonopyAtoms) – The crystal structure as phonopy’s
PhonopyAtoms(any object withcell,scaled_positionsandnumbersattributes works).tolerance (float) – Symmetry tolerance forwarded to seekpath and spglib (
--tolerance; the command uses1e-5).
- Returns:
The tuple
(segments, label_segments, primitive_lattice, symbol, number)wheresegmentsis a list of(N, 3)arrays of fractional k coordinates, one per continuous piece of the path,label_segmentsthe matching lists ofNseekpath labels (GAMMA,X, …),primitive_latticethe(3, 3)row-vector lattice of the standardized primitive cell, andsymbol/numberthe international symbol and number of the detected space group.- Raises:
SystemExit – seekpath is not installed (
ValueErrorwhen called throughcrystod.bz).
Example
>>> from phonopy.interface.vasp import read_vasp >>> from crystod import bz >>> from crystod.examples import example_path >>> cell = read_vasp(example_path("221_PPOSCAR_ScF3")) >>> segments, labels, lattice, symbol, number = bz.get_seekpath_kpath( ... cell, 1e-5) >>> symbol, number ('Pm-3m', 221) >>> labels [['GAMMA', 'X', 'M', 'GAMMA', 'R', 'X'], ['R', 'M']]
- crystod.bz.get_special_kpoints(space_group_symbol)[source]#
Special (high-symmetry) k points of a space group in the ISO-IR convention.
This is the table behind
crystod-bz --show-kpoint --space-group Pnma. The k points and their labels (GM,X,M,R, …) come from the bundled ISO-IR tables (CIR_data), so they are the points at whichcrystod,crystod-phonon --irreps,crystod-magandcrystod-grouplabel irreps. Coordinates are given in the primitive reciprocal basis; for centred lattices (F, I, C, A, B, R) the conventional-basis coordinates are returned as well, since the two bases differ there.- Parameters:
space_group_symbol (str) – Space-group symbol (
"Pnma","Fm-3m"or the full symbol"P m -3 m") or the number as a string ("221").- Returns:
The tuple
(sg_type, names, primitive_kpoints, conventional_kpoints)wheresg_typeis the spglibSpaceGroupTyperecord of the resolved group (sg_type.number,sg_type.international_short),namesthe ISO-IR labels ordered withGMfirst and then by the sum of the absolute primitive coordinates and by name,primitive_kpointsthe matching[kx, ky, kz]lists in the primitive reciprocal basis, andconventional_kpointsthe same points in the conventional reciprocal basis, orNonefor primitive (P) lattices, where the two bases coincide.- Raises:
SystemExit – The symbol or number is not a standard space group (
ValueErrorwhen called throughcrystod.bz).
Example
>>> from crystod import bz >>> sg_type, names, primitive, conventional = bz.get_special_kpoints("Fm-3m") >>> sg_type.number, names (225, ['GM', 'X', 'L', 'W']) >>> primitive[1], conventional[1] ([0.5, 0.0, 0.5], [0.0, 1.0, 0.0])
- crystod.bz.parse_manual_band(band)[source]#
Parse a
--bandstring into k-path segments.The string has the format of the
crystod-bz --bandoption: continuous segments separated by commas, each a whitespace-separated list of fractional coordinates, three numbers per k point; fractions such as1/2are accepted. The coordinates refer to the reciprocal basis of the lattice the path is drawn on, which for the command is the input cell as given.- Parameters:
band (str) – The path string, e.g.
"0 0 0 0 1/2 0 1/2 1/2 0, 1/2 1/2 0 1/2 1/2 1/2".- Returns:
One
(N_i, 3)float array per comma-separated segment, in the order given; empty segments (a trailing comma) are skipped.- Raises:
SystemExit – The number of values in a segment is not a multiple of 3, a segment has fewer than two k points, or the string holds no k point at all (
ValueErrorwhen called throughcrystod.bz).ValueError – A token is neither a number nor a fraction.
- Return type:
list[ndarray[tuple[Any, …], dtype[_ScalarT]]]
Example
>>> from crystod import bz >>> path = "0 0 0 1/2 1/2 0, 1/2 1/2 0 1/2 1/2 1/2" >>> segments = bz.parse_manual_band(path) >>> len(segments), segments[0].tolist() (2, [[0.0, 0.0, 0.0], [0.5, 0.5, 0.0]])
- crystod.bz.parse_transformation_matrix(text)[source]#
Parse a
--trans-matstring into a(3, 3)transformation matrix.The nine numbers are read row-wise, as
crystod-bz --trans-mattakes them; fractions such as1/2are accepted. The matrixTmaps the unit-cell latticeA(row vectors) to the supercell latticeT @ A, so|det T|is the number of unit cells in the supercell.- Parameters:
text (str) – Nine whitespace-separated numbers, e.g.
"0 1 2 -1 0 2 1 -1 2".- Returns:
The
(3, 3)float matrix.- Raises:
SystemExit – The string does not hold exactly nine numbers, or the matrix is singular (
ValueErrorwhen called throughcrystod.bz).ValueError – A token is neither a number nor a fraction.
- Return type:
ndarray[tuple[Any, …], dtype[float64]]
Example
>>> from crystod import bz >>> bz.parse_transformation_matrix("2 0 0 0 2 0 0 0 2").tolist() [[2.0, 0.0, 0.0], [0.0, 2.0, 0.0], [0.0, 0.0, 2.0]]
- crystod.bz.prettify_label(label)[source]#
Convert a seekpath k-point label into its display form.
crystod-bzplaces these labels next to the k-path markers of the HTML plot:GAMMA(orGM),DELTA,SIGMAandLAMBDAbecome the Greek letters, and a_suffix becomes an HTML subscript, soX_1turns intoX<sub>1</sub>. Any other label is returned unchanged.- Parameters:
label (str) – A seekpath-style label such as
"GAMMA","X_1"or"SIGMA_0".- Returns:
The label as an HTML fragment for Plotly text.
- Return type:
str
Example
>>> from crystod import bz >>> bz.prettify_label("GAMMA"), bz.prettify_label("SIGMA_0") ('Γ', 'Σ<sub>0</sub>')