Once a lattice is defined, we can include other data, and atomic coordinates are one of the most common datasets encountered.


A NamedAtom contains two pieces of information: an atom name and the associated atomic number. The atom name is a string no longer than 15 codepoints (internally, we use InlineStrings.InlineString15 to store this data), and the atomic number is an Int.


The default constructor for NamedAtom is NamedAtom(::AbstractString, ::Integer). The atom name can be inferred and specified automatically as the associated symbol if only a number is given.

In the case of only a string being provided, the atomic number may be inferred. This is done by matching the first letters up to a non-letter character of the string with a known symbol. If no match is found, the atomic number will be 0, corresponding to a dummy atom (see below).


Support for inferring from symbols representing unnamed elements or atomic numbers of those elements (for instance, element 119, Uue) is not yet implemented.


NamedAtom types are sorted by atomic number first, then by name.

Dummy atoms

Sometimes, it is useful to include dummy atoms: sites which do not correspond to a real atomic position, but are useful to track in certain circumstances. Dummy atoms have atomic number zero.

If no string is provided, NamedAtom(0) returns NamedAtom("dummy", 0), as does any argument not between 1 and 118.

Atomic positions

Atom position data

Atomic positions are given by a CartesianAtomPosition{D} for Cartesian coordinates, or a FractionalAtomPosition{D} for fractional coordinates with respect to a lattice. This information consists of a NamedAtom, a coordinate in real space as an SVector{D,Float64}, and optional occupancy data for partially occupied sites - if not specified, it defaults to 1 (fully occupied).

Lists of atomic positions

The AbstractAtomList{D} type represents a list of atoms.

AtomList{D} is a wrapper for Vector{CartesianAtomPosition{D}}, and represents atomic positions in an arbitrary D-dimensional space.

PeriodicAtomList{D} wraps Vector{FractionalAtomPosition{D}}, but also includes the basis vectors of the lattice associated with fractional coordinates.

The two types can be interconverted with the appropriate constructors. An AtomList can be constructed from a PeriodicAtomList directly, but for the reverse conversion, the basis vectors of the new PeriodicAtomList must be specified.


Structures often have many identical NamedAtom instances, so sorting of FractionalAtomPosition and CartesianAtomPosition is accomplished by whichever has the lowest initial coordinate, moving to the next coordinate in the case of ties.

Constructing supercells

In many cases, it is useful to construct a supercell from a unit cell. This can be done to convert a primitive cell to a conventional representation, or to a cell of a larger size or different shape.

The supercell(::PeriodicAtomList, ::AbstractMatrix{<:Integer}) function takes an AbstractMatrix{<:Integer}, which transforms the lattice basis vectors by right multiplication, and fills the new lattice with copies of atoms from the original cell. Scalar arguments (calling supercell(::PeriodicAtomList, ::Integer)) scale each direction by the identity matrix multiplied by the scalar, and vector arguments (calling supercell(::PeriodicAtomList, ::Integer)) convert the vector to a diagonal matrix.

Internally, this is done using the [Smith normal form][1] of the transformation matrix, using the diagonal factors to extend the lattice the correct number of times along specific dimensions, and moving them into the cell with the help of the unimodular factors associated with the Smith normal form.

supercell(l::PeriodicAtomList, M) -> PeriodicAtomList

Creates a new AtomList with the basis vectors of a supercell generated by transforming the basis vectors of the space by M, which may be an integer matrix, an integer vector which is treated as a diagonal matrix, or a plain integer, which performs a uniform scaling. This function will also generate new atomic positions to fill the cell.

The function performs this transformation by calculating the Smith normal form of the transformation matrix. This matrix provides the integer scaling factors needed to stretch the supercell, and the left unimodular factor is then used to perform the final transformation.


The Crystal{D} represents a generating set of atomic positions for a periodic structure. Along with a PeriodicAtomList, a Crystal{D} contains the space group and origin setting associated with the data, as well as an integer matrix transformation describing the unit cell generated by the given cell. The set_transform! function allows for the transformation matrix to be altered after the creation of a Crystal{D} object.

This data can be converted to a PeriodicAtomList{D} with a constructor or Base.convert call, and this uses the supercell function to construct the full list of atoms from the generating set.


At the moment, the use of space group data to generate atomic sites is not yet implemented. A space group number and setting may be provided, but this will not be used to generate any atomic sites.

Additionally, we provide the CrystalWithDatasets{D,K,V}, which associates a Crystal{D} with a Dict{K,V} containing datasets associated with the structure. This data structure may be indexed like the underlying dictionary.


CrystalWithDatasets{D,K,V} will likely be changed significantly or removed in Electrum 0.2.