# Atoms

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

`NamedAtom`

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`

.

### Constructors

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.

### Sorting

`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.

### Sorting

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.

`Electrum.supercell`

— Function`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.

## Crystals

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.

[1]: https://en.wikipedia.org/wiki/Smith*normal*form