# ASE Tutorial 2: Atoms and Unitcell

In this section methods for manipulating atom positions and super cells declarations are discussed.

### Manipulating atomic positions

We will end up with a one layer slab with one adatom

Define the slab atoms:

```>>> from ASE import Atom, ListOfAtoms
>>> atoms = ListOfAtoms([Atom('Ni', (0, 0, 0)),
...                      Atom('Ni', (0.45, 0, 0)),
...                      Atom('Ni', (0, 0.5, 0)),
...                      Atom('Ni', (0.5, 0.5, 0))])
```

Have a look at the individual atoms:

```>>> atoms[0]
Atom('Ni', (0.0, 0.0, 0.0))
>>> atoms[1]
Atom('Ni', (0.45, 0.0, 0.0))
>>> atoms[2]
Atom('Ni', (0, 0.5, 0.0))
>>> atoms[3]
Atom('Ni', (0.5, 0.5, 0.0))
```

Let us assume we forgot how many atoms we set up:

```>>> atoms[4]
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IndexError: list index out of range
```

Change the position of the 2nd atom in the list:

```>>> atoms[1].SetCartesianPosition((0.5,0,0))
>>> atoms[1].GetCartesianPosition()
[ 0.5  0.    0.  ]
>>> atoms
[Atom('Ni', (0.0, 0.0, 0.0)),
Atom('Ni', (0.5, 0.0, 0.0)),
Atom('Ni', (0, 0.5, 0.0)),
Atom('Ni', (0.5, 0.5, 0.0))]
```

What is the unit cell so far?:

```>>> atoms.GetUnitCell()
[[ 1.  0.  0.]
[ 0.  1.  0.]
[ 0.  0.  1.]]
```

Now, setup a p(2x2) cell in a hexagonal surface a is the fcc lattice constant, the cell is 10 layers high:

```>>> from math import sqrt
>>> a=3.55
>>> cell=[(2/sqrt(2.)*a, 0, 0),
...       (1/sqrt(2.)*a, sqrt(3./2.)*a, 0),
...       (0, 0, 10*sqrt(3.)/3.*a)]
>>> cell
(5.0204581464244864, 0, 0),
(2.5102290732122432, 4.3478442934401409, 0),
(0, 0, 20.495934556231713)]
>>> atoms.SetUnitCell(cell)
>>> atoms
[Atom('Ni', (0.0, 0.0, 0.0)),
Atom('Ni', (2.5102290732122432, 0.0, 0.0)),
Atom('Ni', (1.2551145366061216, 2.1739221467200704, 0.0)),
Atom('Ni', (3.7653436098183644, 2.1739221467200704, 0.0))]
```

Plot the whole system, repeating the slab 2 times in each direction:

```>>> from ASE.Visualization.RasMol import RasMol
>>> plot = RasMol(atoms,(2,2,2))
```

We now add an adatom. Since the super cell is now declared in our unit cell, we would have to either declare the position of the new atom in Angstroms or to convert back the unit cell

```>>> xyzcell=[(1, 0, 0), (0, 1, 0), (0, 0, 1)]
>>> atoms.SetUnitCell(xyzcell)
>>> atoms.append(Atom('Ni', (1/6., 1/6., .1)))
```

Declare again the unit cell and update the plot:

```>>> atoms.SetUnitCell(cell)
>>> plot.Update()
```

### Manipulating the unitcell

Conventional setup of unit cell:

```>>> import Numeric as num
>>> a=3.55
>>> cell=[(2/sqrt(2.)*a, 0, 0),
...      (1/sqrt(2.)*a, sqrt(3./2.)*a, 0),
...      (0, 0, 10*sqrt(3.)/3.*a)]
>>> cell
[(5.0204581464244864, 0, 0),
(2.5102290732122432, 4.3478442934401409, 0),
(0, 0, 20.495934556231713)]
```

Alternative setup of same cell:

```>>> cell=num.array([(2/sqrt(2.), 0, 0),
...                 (1/sqrt(2.), sqrt(3./2.), 0),
...                 (0, 0, 10*sqrt(3.)/3.)])
>>> cell=cell*a
>>> cell
[[5.0204581464244864, 0.0, 0.0],
[2.5102290732122432, 4.3478442934401409, 0.0],
[0.0, 0.0, 20.495934556231713]]
```

Now we decide to change the height of the unit cell:

```>>> cell[2,2]=cell[2,2]*0.5
>>> cell
[[5.0204581464244864, 0.0, 0.0],
[2.5102290732122432, 4.3478442934401409, 0.0],
[0.0, 0.0, 10.247967278115857]]
```

When changing the super cell, the atoms must now be fixed at their Cartesian coordinates in Angstroms:

```>>> atoms[4].GetCartesianPosition()
[ 1.25511454  0.72464072  2.04959346]
>>> atoms.SetUnitCell(cell, fix=True)
>>> atoms[4].GetCartesianPosition()
[ 1.25511454  0.72464072  2.04959346]
```

If one forgets to fix the atoms, they are stretched with the super cell:

```>>> cell[2,2]=cell[2,2]*2
>>> cell
[[5.0204581464244864, 0.0, 0.0],
[2.5102290732122432, 4.3478442934401409, 0.0],
[0.0, 0.0, 20.495934556231713]]
>>> atoms[4].GetCartesianPosition()
[ 1.25511454  0.72464072  2.04959346]
>>> atoms.SetUnitCell(cell)
>>> atoms[4].GetCartesianPosition()
[ 1.25511454  0.72464072  4.09918691]
```