As described in the documentation, the a
, b
, and c
vectors passed into ase.build.cut
define lines that make up your cell. To see that the vectors you passed in give a (111) surface, consider the third vector c
, which when it is not explicitly passed in, is formed using $\vec{c}=\vec{a} \times \vec{b}$. $\vec{c}$ is then the normal vector to plane formed by $\vec{a}$ and $\vec{b}$, which is exactly the Miller index for the plane.
$$(1,-1,0)\times(0,1,-1)=(1,1,1)\to (111)$$
So we can see that this will give a (111) surface. But how would we select these vectors to begin with? We can use another way that Miller indices are defined in terms of intersections with lattice vectors. For example, a (111) surface should have its intercept one unit along each axis, i.e. at the points (1,0,0),(0,1,0), and (0,0,1). These 3 noncollinear points determine a plane, but we can also express this plane using two intersecting lines, which we can generate by forming vectors between pairs of these points.
$$(1,0,0)-(0,1,0)=(1,-1,0)=\vec{a}\\
(0,1,0)-(0,0,1)=(0,1,-1)=\vec{b}$$
The particular choice of pairs is arbitrary and you could just as well have used e.g (1,0,-1) for $\vec{b}$ and still produced the same plane.
So how would you make a (112) surface? We want to change the surface normal to be (1,1,2), or equivalently to intersect with the first two lattice vectors as 1 and the third at 1/2. So we can substitute $\vec{b}=(0,1,-1/2)$, which will give a surface normal of $\vec{c}=(1/2,1/2,1)$, which after multiplying by the least common denominator we can see leads to a (112) surface.
When generating a surface of a single compound, any scaling factor applied to each vector is irrelevant, as it will still result in a surface from the same family. However, if you are considering multiple types of surfaces forming an interface or multiple layers, you will need to consider these factors, as these will affect the relative positioning of the surfaces. An example of this given in the documentation for ase.build.stack
:
import ase
from ase.spacegroup import crystal
# Create an Ag(110)-Si(110) interface with three atomic layers
# on each side.
a_ag = 4.09
ag = crystal(['Ag'], basis=[(0,0,0)], spacegroup=225,
cellpar=[a_ag, a_ag, a_ag, 90., 90., 90.])
ag110 = cut(ag, (0, 0, 3), (-1.5, 1.5, 0), nlayers=3)
a_si = 5.43
si = crystal(['Si'], basis=[(0,0,0)], spacegroup=227,
cellpar=[a_si, a_si, a_si, 90., 90., 90.])
si110 = cut(si, (0, 0, 2), (-1, 1, 0), nlayers=3)
Here, you can work out that these should be (110) surface, but you can also see that the vectors passed for each are different to avoid placing them right on top of each other.