# Lattices

## Constructors and types

Electrum.RealBasisType
Electrum.LatticeBasis{S<:Electrum.BySpace,D,T} <: StaticMatrix{D,D,T}

Represents the basis vectors of a D-dimensional lattice in real or reciprocal space, depending on S. The units of LatticeBasis{Electrum.ByRealSpace} are bohr, and those of LatticeBasis{Electrum.ByReciprocalSpace} are rad*bohr⁻¹, corresponding to the convention that the dot product of a real space basis vector with a reciprocal space basis vector is 2π.

Type aliases

For convenience, the type aliases RealBasis and ReciprocalBasis are defined below:

const RealBasis = LatticeBasis{ByRealSpace}
const ReciprocalBasis = LatticeBasis{ByReciprocalSpace}
const AbstractBasis = LatticeBasis{<:BySpace}

These type aliases are exported, and in most circumstances code should refer to these types for the sake of readability, not Electrum.LatticeBasis, which is unexported.

Mathematical operations

Electrum.LatticeBasis behaves as an ordinary matrix and should support all mathematical operations commonly used, including left division with vectors (\), commonly used in the conversion between Cartesian and fractional (reduced) coordinates.

In most cases, matrix multiplications will convert the result to an ordinary StaticArray or Array. However, right multiplications of an Electrum.LatticeBasis{S,D} with an SMatrix{D,D,<:Integer} are treated as the application of a supercell building operation, and return a new Electrum.LatticeBasis{S,D} instead.

Conversion

A RealBasis may be converted to a ReciprocalBasis, or vice versa, using either convert(T::Electrum.LatticeBasis, b) or the constructor (T::Type{<:Electrum.LatticeBasis})(b). This automatically multiplies or divides by 2π as needed.

The inverse operation inv also performs this conversion. This convention may change in a future update, as the current definition may break other assumptions about matrix inversion.

Interoperability

File import and export methods in Electrum and any other software which returns these types must perform unit conversion if the units used by the other software package are different.

Internals

In order to avoid the presence of an extraneous type parameter, the backing vectors field of a LatticeBasis is not an SMatrix{D,D,T} (as this is not a concrete type), but an SVector{D,SVector{D,T}}. However, the property matrix is defined so that it returns an SMatrix{D,D,T}. The vectors property is private, and will not be revealed during REPL tab completion.

Electrum.ReciprocalBasisType
Electrum.LatticeBasis{S<:Electrum.BySpace,D,T} <: StaticMatrix{D,D,T}

Represents the basis vectors of a D-dimensional lattice in real or reciprocal space, depending on S. The units of LatticeBasis{Electrum.ByRealSpace} are bohr, and those of LatticeBasis{Electrum.ByReciprocalSpace} are rad*bohr⁻¹, corresponding to the convention that the dot product of a real space basis vector with a reciprocal space basis vector is 2π.

Type aliases

For convenience, the type aliases RealBasis and ReciprocalBasis are defined below:

const RealBasis = LatticeBasis{ByRealSpace}
const ReciprocalBasis = LatticeBasis{ByReciprocalSpace}
const AbstractBasis = LatticeBasis{<:BySpace}

These type aliases are exported, and in most circumstances code should refer to these types for the sake of readability, not Electrum.LatticeBasis, which is unexported.

Mathematical operations

Electrum.LatticeBasis behaves as an ordinary matrix and should support all mathematical operations commonly used, including left division with vectors (\), commonly used in the conversion between Cartesian and fractional (reduced) coordinates.

In most cases, matrix multiplications will convert the result to an ordinary StaticArray or Array. However, right multiplications of an Electrum.LatticeBasis{S,D} with an SMatrix{D,D,<:Integer} are treated as the application of a supercell building operation, and return a new Electrum.LatticeBasis{S,D} instead.

Conversion

A RealBasis may be converted to a ReciprocalBasis, or vice versa, using either convert(T::Electrum.LatticeBasis, b) or the constructor (T::Type{<:Electrum.LatticeBasis})(b). This automatically multiplies or divides by 2π as needed.

The inverse operation inv also performs this conversion. This convention may change in a future update, as the current definition may break other assumptions about matrix inversion.

Interoperability

File import and export methods in Electrum and any other software which returns these types must perform unit conversion if the units used by the other software package are different.

Internals

In order to avoid the presence of an extraneous type parameter, the backing vectors field of a LatticeBasis is not an SMatrix{D,D,T} (as this is not a concrete type), but an SVector{D,SVector{D,T}}. However, the property matrix is defined so that it returns an SMatrix{D,D,T}. The vectors property is private, and will not be revealed during REPL tab completion.

Electrum.AbstractBasisType
Electrum.LatticeBasis{S<:Electrum.BySpace,D,T} <: StaticMatrix{D,D,T}

Represents the basis vectors of a D-dimensional lattice in real or reciprocal space, depending on S. The units of LatticeBasis{Electrum.ByRealSpace} are bohr, and those of LatticeBasis{Electrum.ByReciprocalSpace} are rad*bohr⁻¹, corresponding to the convention that the dot product of a real space basis vector with a reciprocal space basis vector is 2π.

Type aliases

For convenience, the type aliases RealBasis and ReciprocalBasis are defined below:

const RealBasis = LatticeBasis{ByRealSpace}
const ReciprocalBasis = LatticeBasis{ByReciprocalSpace}
const AbstractBasis = LatticeBasis{<:BySpace}

These type aliases are exported, and in most circumstances code should refer to these types for the sake of readability, not Electrum.LatticeBasis, which is unexported.

Mathematical operations

Electrum.LatticeBasis behaves as an ordinary matrix and should support all mathematical operations commonly used, including left division with vectors (\), commonly used in the conversion between Cartesian and fractional (reduced) coordinates.

In most cases, matrix multiplications will convert the result to an ordinary StaticArray or Array. However, right multiplications of an Electrum.LatticeBasis{S,D} with an SMatrix{D,D,<:Integer} are treated as the application of a supercell building operation, and return a new Electrum.LatticeBasis{S,D} instead.

Conversion

A RealBasis may be converted to a ReciprocalBasis, or vice versa, using either convert(T::Electrum.LatticeBasis, b) or the constructor (T::Type{<:Electrum.LatticeBasis})(b). This automatically multiplies or divides by 2π as needed.

The inverse operation inv also performs this conversion. This convention may change in a future update, as the current definition may break other assumptions about matrix inversion.

Interoperability

File import and export methods in Electrum and any other software which returns these types must perform unit conversion if the units used by the other software package are different.

Internals

In order to avoid the presence of an extraneous type parameter, the backing vectors field of a LatticeBasis is not an SMatrix{D,D,T} (as this is not a concrete type), but an SVector{D,SVector{D,T}}. However, the property matrix is defined so that it returns an SMatrix{D,D,T}. The vectors property is private, and will not be revealed during REPL tab completion.

## Methods

Electrum.eachvertexFunction
eachvertex([m::AbstractMatrix], r::AbstractArray...)

Returns an iterator of SVector{size(r),eltype(r)} objects representing each vertex whose reduced coordinates lie in ranges r. If no matrix is given, the iterator generates all vectors whose coordinates are in corresponding arrays r. A supplied matrix will be left-multiplied with these vectors to generate Cartesian representation of those vectors.

eachvertex(b::StaticMatrix)
eachvertex(b::AbstractMatrix)

Returns an iterator of AbstractVector objects corresponding to each vertex of the parallelepiped spanned by the column vectors of b.

In the case of StaticMatrix subtypes, this function returns SVector objects, allowing for efficient collection into an Array{SVector{D},D}, preserving the arrangement of the vertices in space. However, for other AbstractMatrix objects whose sizes are not known at compile time, the iterator can only be collected into a Vector{<:Vector} to preserve type stability. We generally recommend working with static matrix types like the provided RealBasis and ReciprocalBasis.

Electrum.basisFunction
basis(x)

Returns the lattice basis associated with a data structure. By default, this returns getproperty(x, :basis). This may be implemented for custom data types by either adding a method to basis() or by defining custom getproperty() and propertynames() methods.

Although basis(x) should always return an Electrum.LatticeBasis, the exact return type may vary: not only can the numeric type vary, some data strucutres may store a real space lattice, and others may store a reciprocal space lattice, allowing for properties of the data contained to be inferred. For predictable results, use convert(T, basis(x)) where T is the desired type.

Base.invMethod
inv(b::LatticeBasis{D}) -> SMatrix{D,D}

Returns the matrix which, when left or right multiplied by b, returns the identity matrix, up to rounding error. Because the result of this calculation is not the dual lattice associated with b, the return type is simply an SMatrix{D,D}.

For the dual space lattice basis vectors, use dual(x) or dualbasis(x).

Electrum.dualFunction
dual(b::RealBasis) -> ReciprocalBasis
dual(b::ReciprocalBasis) -> RealBasis

Returns the basis of the dual lattice, which is the lattice in dual space whose product with the original lattice is equal to the identity matrix multiplied by 2π.

Electrum.dualbasisFunction
dualbasis(x)

Returns the dual basis associated with a data structure x; equal to dual(basis(x)).

This function should never be defined directly: instead, basis(::T) should be implemented for a custom type T.

Electrum.lengthsMethod
lengths(b::LatticeBasis{S,D}) -> SVector{D}

Returns the lengths of the basis vectors. The units correspond to the type of the basis vectors: for RealBasis the units are bohr, and for ReciprocalBasis the units are rad*bohr⁻¹.

Electrum.volumeMethod
volume(b::LatticeBasis) -> Real

Returns the volume of a unit cell defined by a matrix. This volume does not carry the sign (negative for cells that do not follow the right hand rule). The units correspond to the type of the basis vectors: for RealBasis the units are bohr³, and for ReciprocalBasis the units are rad³*bohr⁻³.

Electrum.angles_cosFunction
angles_cos(b::LatticeBasis{S,D}) -> SVector{binomial(D,2)}

Generates the cosines of the unit cell angles.

The angles are generated in the correct order [α, β, γ] for 3-dimensional cells. This is achieved by reversing the output of Electrum.generate_pairs(). For crystals with more spatial dimensions, this may lead to unexpected results.

Electrum.angles_radFunction
angles_rad(b::LatticeBasis{S,D}) -> SVector{binomial(D,2)}

Returns the angles (in radians) between each pair of basis vectors.

The angles are generated in the correct order [α, β, γ] for 3-dimensional cells. This is achieved by reversing the output of Electrum.generate_pairs(). For crystals with more spatial dimensions, this may lead to unexpected results.

Electrum.angles_degFunction
angles_deg(b::LatticeBasis{S,D}) -> SVector{binomial(D,2)}

Returns the angles (in degrees) between each pair of basis vectors.

The angles are generated in the correct order [α, β, γ] for 3-dimensional cells. This is achieved by reversing the output of Electrum.generate_pairs(). For crystals with more spatial dimensions, this may lead to unexpected results.

Electrum.gramFunction
gram(b::LatticeBasis{S,D}) -> SMatrix{D,D}

Returns the Gram matrix associated with a set of basis vectors. The entries of this matrix are the dot products associated with all possible combinations of basis vectors.

Electrum.triangularizeFunction
triangularize(l::T) where T<:LatticeBasis -> T

Converts a set of basis vectors to an upper triangular form using QR decomposition.

triangularize(l::T, sc::AbstractMatrix{<:Integer}) where T<:LatticeBasis -> T

Converts a set of basis vectors to an upper triangular form using QR decomposition, with an included conversion to a larger supercell. The resulting matrix that describes the basis vectors will have only positive values along the diagonal, and therefore, is always right-handed (regardless of the transformation matrix used).

LAMMPS expects that basis vectors are given in this format.

Electrum.maxHKLindexFunction
Electrum.maxHKLindex(b::LatticeBasis, ecut::Real; prim=true, c = 2)

Determines the maximum integer values of the reciprocal lattice vectors needed to store data out to a specific energy cutoff for a 3D lattice.

By default, the energy cutoff is assumed to be in units of Hartree, the reciprocal lattice vector lengths are assumed to be in radbohr⁻¹, and the value of c is that of the constant (2mₑ/ħ²). In Hartree atomic units, this value is 2 - but for VASP WAVECAR outputs, the value is given in eV⁻¹angstrom⁻² - see Electrum.CVASP for more information.

The functionality implemented here was taken from WaveTrans: https://www.andrew.cmu.edu/user/feenstra/wavetrans/