Querying and property methods
Crystals.Structures.is_fractional
— Function.is_fractional(crystal)
True if the crystal structure is fractional.
Crystals.Structures.are_compatible_lattices
— Function.are_compatible_lattices(lattices...)
True if the lattices are mathematically equivalent. Two lattices are equivalent if they represent the same periodicity. In practice, this means the two lattices have the same volume, and their cell vectors are integer linear combinations of one another.
Parameters
lattices::Vararg{Union{Matrix, Crystal}}
: Any number of latticesdigits::Integer
: when checking the cells are integer co-linear, the product $A^{-1}B$ is first rounded to this number of digitsrtol::Real
: relative tolerance when checking the volumes correspond (no units). Default to 1.0e-8.atol::Real
: absolute tolerance when checking the volumes correspond (no units). Default to 1.0e-8.
Examples
using Crystals, Unitful
crystal = Crystal([0 2.1 2.1; 2.1 0 2.1; 2.1 2.1 0]u"nm")
cells = Matrix{Int64}[eye(3)]
while length(cells) < 5
cell = rand(-5:5, (3, 3))
volume(cell) == 1 && push!(cells, cell)
end
lattices = [crystal.cell * c for c in cells]
are_compatible_lattices(crystal, lattices...)
# output
true
Crystals.Structures.volume
— Function.volume(crystal)
Returns the volume of a Crystal
instance or of a cell. It comes down to computing $|det(A)|$ where $A$ is the crystal cell.
Examples
julia> using Crystals
julia> volume(Crystal([0 2 2; 2 0 2; 2 2 0]u"nm"))
16.0 nm^3
julia> volume([0 2 2; 2 0 2; 2 2 0]u"nm")
16.0 nm^3
julia> volume([0 2 2; 2 0 2; 2 2 0])
16.0
Crystals.Utilities.cell_parameters
— Function.cell_parameters(a::Quantity, b::Quantity, c::Quantity,
α::Quantity=(π/2)u"rad", β::Quantity=(π/2)u"rad",
γₒ::Quantity=(π/2)u"rad")
Computes the cell matrix from the cell parameters [a, b, c, α, β, γ].
cell_parameters(cell::AbstractMatrix)
cell_parameters(cell::Crystal)
Parameters (a, b, c, α, β, γ) of the input cell returned in a named tuple.
Crystals.Gruber.gruber
— Function.gruber(cell::Matrix;
tolerance::Real=default_tolerance, itermax::Unsigned=50,
max_no_change::Unsigned=10)
Determines Gruber cell of an input cell.
The Gruber cell is an optimal parameterization of a lattice, e.g. shortest cell-vectors and angles closest to 90 degrees. The new cell is in the same basis as the origin cell: no rotation has been incurred. The cell parameters are uniquely determined, even though the cell itself is not (certain symmetry operations leaving the structure unchanged may yield a more recognizable cell). If you want a unique Cartesian cell (in a different Cartesian basis), use the niggly
algorithm.
Arguments
cell::Matrix
: the input lattice cell-vectors. Cannot be singular.itermax::Integer
: maximum number of iterations before bailing outtolerance::Number
: tolerance parameter when comparing real numbersmax_no_change::Integer
: Maximum number of times to go through algorithm without changes before bailing out
Crystals.Gruber.niggly
— Function.niggly(cell::Matrix; kwargs...)
Determines a unique Cartesian cell equivalent to the input, with the shortest possible vectors and squarest angles. For an explanation of the parameters, see gruber
. In practice, this function computes the cell-parameters of a gruber
cell and then reconstructs the cell matrix. Hence, the result should be quite unique for any lattice representation, including any rotation of the underlying Cartesian coordinates.
Crystals.Utilities.is_periodic
— Function.is_periodic(a::AbstractVector, b::AbstractVector, cell::AbstractMatrix;
tolerance::Real=1.0e-8)
True if the positions are one-to-one periodic with respect to the input cell.
is_periodic(a::AbstractMatrix, b::AbstractVector, cell::AbstractMatrix;
tolerance::Real=1.0e-8)
Array of boolean describing whether positions in a
are periodic with positions in b
.
Crystals.SpaceGroup.is_primitive
— Function.is_primitive(cartesian::AbstractMatrix, cell::AbstractMatrix, species::AbstractVector;
tolerance::Real=1.0e-8)
is_primitive(crystal::Crystal, col::Union{Symbol, AbstractVector{Symbol}}; kwargs...)
is_primitive(crystal::Crystal; kwargs...)
True if the crystal structure is primitive, e.g. not a supercell, e.g. not reducible to an equivalent lattice with fewer atoms.
Typical container and DataFrame methods are also available, such as names
, size
, ndims
, nrow
, ncol
, endof
.
Looping
Crystals.CrystalAtoms.eachatom
— Function.Iterator over each atom in the crystal
eachindex
is also available. It returns the range over atoms indices 1:size(crystal, 1)
.
Modifying, building up and building down
Base.round
— Function.round(crystal, args)
Rounds the cell and positions of a crystal. See Base.round
for possible parameters.
Examples
using Crystals
crystal = Crystal([0 0.501 0.501; 0.496 0.001 0.497; 0.497 0.497 0]u"nm",
position=[0.001, -0.001, -0.001]u"nm",
position=[0.25, 0.251, -0.247]u"nm")
round(crystal, 2)
# output
cell(nm):
0.0 0.5 0.5
0.5 0.0 0.5
0.5 0.5 0.0
│ Atom │ Cartesian │
├──────┼─────────────────────┤
│ 1 │ (0.0, -0.0, -0.0) │
│ 2 │ (0.25, 0.25, -0.25) │
Crystals.Structures.round!
— Function.round!(crystal, args)
Rounds the cell and positions of a crystal. See round
for possible parameters.
Crystals.Utilities.into_cell
— Function.into_cell(pos, cell; tolerance)
Folds periodic positions into cell
Crystals.Utilities.into_voronoi
— Function.into_voronoi(positions::AbstractArray, cell::AbstractMatrix; extent::Integer=1)
Folds positions into first Brillouin zone of the input cell. Makes a well-meaning effort at returning the periodic image with the smallest possible norm. It recenter the atoms around the origin and then looks for the smallest periodic images within -extent:extent
cells. If the cell is quite pathological, then the result will not be within the Voronoi cell.
Crystals.Utilities.origin_centered
— Function.origin_centered(positions::AbstractArrays, cell::AbstractMatrix)
Folds positions back to origin, such that each fractional component $x_f$ is between $-0.5\leq x_f < 0.5$. If the input is in Cartesian (fractional) coordinates, then the result is also in Cartesian (fractional) coordinates.
is_primitive
can be queried to figure out whether a crystal is a primitive cell or a supercell.
Point-group, space-group, and geometry
Crystals.SpaceGroup.point_group
— Function.Finds and stores point group operations for a given lattice
A lattice is defined by a 3x3 matrix or cell. Rotations are determined from G-vector triplets with the same norm as the unit-cell vectors.
Implementation taken from ENUM.
Crystals.SpaceGroup.space_group
— Function.space_group(crystal; kwargs...)
Computes the space-group operations of a crystal. By default, all atomic properties are considered when determining whether atomic sites are related by symmetry. However, it is possible to specify a subset of atomic properties. An empty subset of atomic properties implies that all atoms sites are equivalent. It is also possible to specify an array of integers, serving as labels for each atomic site.
space_group(cell, positions, species; kwargs...)
Computes the space-group of a crystal specified using standard Julia types.
Crystals.Utilities.hart_forcade
— Function.hart_forcade(lattice, supercell; digits)
Computes the cyclic group of a supercell with respect to a lattice. It makes it possible to identify the class of periodically equivalent cell that a given position within the supercell belongs to. The function returns a named tuple with the transform and the quotient.
Examples
using Crystals, Unitful
fcc = [0 0.5 0.5; 0.5 0 0.5; 0.5 0.5 0]u"nm"
supercell = [0 2 2; 0 -4 2; -1 0 -2]
ht = hart_forcade(fcc, fcc * supercell)
println(ht)
println("Positions in supercell:")
for index in CartesianRange((ht.quotient...))
position = inv(ht.transform) * [index[u] for u in eachindex(ht.quotient)]
println("- ", ustrip.(position), " (", unit(eltype(position)), ")")
end
# output
Hart-Forcade transform
- transform (nm^-1): [-1.0 -1.0 1.0; -1.0 1.0 1.0; -1.0 1.0 3.0]
- quotient: [1, 2, 6]
Positions in supercell:
- [-1.0, 0.0, 0.0] (nm)
- [-2.0, 0.5, -0.5] (nm)
- [-0.5, 0.0, 0.5] (nm)
- [-1.5, 0.5, 0.0] (nm)
- [0.0, 0.0, 1.0] (nm)
- [-1.0, 0.5, 0.5] (nm)
- [0.5, 0.0, 1.5] (nm)
- [-0.5, 0.5, 1.0] (nm)
- [1.0, 0.0, 2.0] (nm)
- [0.0, 0.5, 1.5] (nm)
- [1.5, 0.0, 2.5] (nm)
- [0.5, 0.5, 2.0] (nm)
Crystals.SpaceGroup.primitive
— Function.primitive(crystal::Crystal; tolerance::Real=1.0e-8)
Computes the primitive cell of the input crystal. If the crystal is primitive, it is returned as is, otherwise a new crystal is returned.
Crystals.Utilities.supercell
— Function.supercell(lattice, supercell; site_id, tolerance)
Creates a supercell from an input lattice.
# Parameters
lattice::Crystal
: the original latticesupercell::AbstractMatrix
: the cell of the supercell in Cartesian coordinatessite_id::Bool
: Whether to add/modify an atomic property indicating the index of the site in the original latticecell_id::Bool
: Whether to add/modify an atomic property indicating the index of the cell the site belongs to
Predefined lattices
A small number of standard lattices are available for construction in the exported Lattices
submodule.
For instance, the body-centered lattice:
using Crystals
Lattices.bcc()
cell(nm):
-0.5 0.5 0.5
0.5 -0.5 0.5
0.5 0.5 -0.5
│ Atom │ Cartesian │
├──────┼─────────────────┤
│ 1 │ (0.0, 0.0, 0.0) │
Or more complex lattices, such as b5 spinels:
Lattices.b5()
cell(nm):
0.0 0.5 0.5
0.5 0.0 0.5
0.5 0.5 0.0
│ Atom │ Cartesian │ species │
├──────┼───────────────────────┼─────────┤
│ 1 │ (0.5, 0.5, 0.5) │ 'A' │
│ 2 │ (0.5, 0.25, 0.25) │ 'A' │
│ 3 │ (0.25, 0.5, 0.25) │ 'A' │
│ 4 │ (0.25, 0.25, 0.5) │ 'A' │
│ 5 │ (0.875, 0.875, 0.875) │ 'B' │
│ 6 │ (0.125, 0.125, 0.125) │ 'B' │
│ 7 │ (0.25, 0.25, 0.25) │ 'X' │
│ 8 │ (0.25, 0.5, 0.5) │ 'X' │
│ 9 │ (0.5, 0.25, 0.5) │ 'X' │
│ 10 │ (0.5, 0.5, 0.25) │ 'X' │
│ 11 │ (0.75, 0.75, 0.75) │ 'X' │
│ 12 │ (0.75, 0.5, 0.5) │ 'X' │
│ 13 │ (0.5, 0.75, 0.5) │ 'X' │
│ 14 │ (0.5, 0.5, 0.75) │ 'X' │
Crystals.Lattices.b5
— Function.b5()
b5(T; unit)
b5 (spinel) lattice
Crystals.Lattices.bcc
— Function.bcc()
bcc(T; unit)
Creates a body-centered lattice with a single site
Crystals.Lattices.diamond
— Function.diamond()
diamond(T; unit)
Diamond lattice
Crystals.Lattices.fcc
— Function.fcc()
fcc(T; unit)
Creates an face centered lattice with a single site
Crystals.Lattices.rock_salt
— Function.rock_salt()
rock_salt(T; unit)
Rock-salt lattice
Crystals.Lattices.wurtzite
— Function.wurtzite()
wurtzite(T; unit)
Wurtzite lattice
Crystals.Lattices.zinc_blende
— Function.zinc_blende()
zinc_blende(T; unit)
Zinc-blende lattice
Output and Logging
Information and errors during calculations are displayed using an internal log provided by MicroLogging. Verbosity can be set manually with:
using MicroLogging
using Crystals
configure_logging(Crystals, min_level=:error)