Lattice

The purpose of this document is to explain how Mantid is using information about unit cells and their orientation with respect to the laboratory frame. For a detailed description, see http://github.com/mantidproject/documents/blob/master/Design/UBMatriximplementationnotes.pdf

Theory

The physics of a system studied by neutron scattering is described by the conservation of energy and momentum. In the laboratory frame:

Q_l=  \hbar \mathbf{k}_i^{} -  \hbar \mathbf{k}_f

\Delta E_l= \frac{\hbar^2}{2m} (k_i^2 -  k_f^2)

Note that the left side in the above equations refer to what is happening to the lattice, not to the neutron.

Let’s assume that we have a periodic lattice, described by lattice parameters a,\ b,\ c,\ \alpha,\ \beta,\ \gamma. The reciprocal lattice will be described by parameters a^*,\ b^*,\ c^*,\ \alpha^*,\ \beta^*,\  \gamma^*. Note that Mantid uses a^*=\frac{1}{a} type of notation, like in crystallography.

For such a lattice, the physics will be described in terms of reciprocal lattice parameters by

Q= 2 \pi\left(h \mathbf{a}^* + k \mathbf{b}^* +l \mathbf{c}^* \right) = \left(\begin{array}{c}
                                                        h \\
                                                        k \\
                                                        l
                                                      \end{array}\right)

The UB_{}^{} matrix formalism relates Q_l^{} and Q_{}^{} with the following equation:

Q_l = 2 \pi R \cdot U \cdot B \left(\begin{array}{c}
                                                        h \\
                                                        k \\
                                                        l
                                                      \end{array}\right)

The B_{}^{} matrix transforms the h^{}_{}, k, l triplet into a Cartesian system, with the first axis along \ \mathbf{a}^*, the second in the plane defined by \ \mathbf{a}^* and \ \mathbf{b}^*, and the third axis perpendicular to this plane. In the Busing and Levi convention (W. R. Busing and H. A. Levy, Angle calculations for 3- and 4-circle X-ray and neutron diffractometers - Acta Cryst. (1967). 22, 457-464):

B = \left( \begin{array}{ccc}
    a^* & b^*\cos(\gamma^*) & c^*\cos(\beta^*) \\
    0 & b^*\sin(\gamma^*) & -c^*\sin(\beta^*)\cos(\alpha) \\
    0 & 0 & 1/c \end{array} \right)

The U_{}^{} matrix represents the rotation from this Cartesian coordinate frame to the Cartesian coordinate frame attached to the innermost axis of the goniometer that holds the sample.

The R_{}^{} matrix is the rotation matrix of the goniometer

Other useful equations:

G^* = (UB)^T UB = B^T B = \left( \begin{array}{ccc}
    a^*a^* & a^*b^*\cos(\gamma^*) & a^*c^*\cos(\beta^*) \\
    a^*b^*\cos(\gamma^*) & b^*b^* & b^*c^*\cos(\alpha^*) \\
    a^*c^*\cos(\beta^*) & b^*c^*\cos(\alpha^*) & c^*c^* \end{array} \right)

G=(G^*)^{-1}=\left( \begin{array}{ccc}
    aa & ab\cos(\gamma) & ac\cos(\beta) \\
    ab\cos(\gamma) & bb & bc\cos(\alpha) \\
    ac\cos(\beta) & bc\cos(\alpha) & cc \end{array} \right)

The distance in reciprocal space to the \left(h,k,l\right) plane is given by

d^* =\left| B \left(\begin{array}{c}
                                                        h \\
                                                        k \\
                                                        l
                                                      \end{array}\right)\right|

The distance in real space to the \left(h,k,l\right) plane is given by d=\frac{1}{d^*}

The angle between Q_1^{} and Q_2^{} is given by \cos( Q_1^{}, Q_2^{})=\frac{(BQ_1)(BQ_2)}{|(BQ_1)| |(BQ_2)|}

Unit cells

The UnitCell class provides the following functions to access direct and reciprocal lattices. The examples can be run from the script console in Mantid

Function Example Description
UnitCell() u = UnitCell() default constructor, with a=b=c=1\rm \AA, \ \alpha=\beta=\gamma=90^\circ
UnitCell(other unit cell)
u = UnitCell()
u2 = UnitCell(u)
copy constructor
UnitCell(a,b,c) u = UnitCell(2,3.5,4) constructor using a, b, c\ (\rm {in \ \AA}), \ \alpha=\beta=\gamma=90^\circ
UnitCell(a,b,c,alpha,beta,gamma,Unit = unit)
u = UnitCell(2,3.5,4,90,90,90)
u = UnitCell(2,3.5,4,90,90,90,Unit = Degrees)
u = UnitCell(2,3.5,4,0.5*math.pi,0.5*math.pi,0.5*math.pi,Unit = Radians)
constructor using a, b, c\ (\rm {in \ \AA}), \ \alpha, \ \beta,\ \gamma \ (\rm {in \ degrees \ or \ radians}). The optional parameter “Unit” controls the units for the angles, and can have the value of “Degrees” or “Radians”. By default Unit = Degrees
a()
b()
c()
u = UnitCell(2,3.5,4)
print u.c()
returns lattice parameters a, b, c\ (\rm {in \ \AA})
a1()
a2()
a3()
u = UnitCell(2,3.5,4)
print u.a2()
returns lattice parameters a_1=a, a_2=b, a_3=c\ (\rm {in \ \AA}). Note: “International Tables for Crystallography” notation
alpha()
beta()
gamma()
u = UnitCell(2,3.5,4,95,95,105)
print u.alpha()
returns lattice parameters \alpha,\ \beta, \gamma\ (\rm {in \ degrees})
alpha1()
alpha2()
alpha3()
u = UnitCell(2,2,4,90,90,60)
print u.alpha3()
returns lattice parameters \alpha_1=\alpha,\ \alpha_2=\beta, \ \alpha_3=\gamma \ (\rm {in \ radians}). Note: “International Tables for Crystallography” notation
astar()
bstar()
cstar()
u = UnitCell(2,3.5,4)
print u.cstar()
returns reciprocal lattice parameters a^*, b^*, c^* \ (\rm {in \ \AA^{-1}})
b1()
b2()
b3()
u = UnitCell(2,3.5,4)
print u.b2()
returns lattice parameters b_1=a^*, b_2=b^*, b_3=c^*\ (\rm {in \ \AA^{-1}}). Note: “International Tables for Crystallography” notation
alphastar()
betastar()
gammastar()
u = UnitCell(2,3.5,4,95,95,105)
print u.alphastar()
returns lattice parameters \alpha^*,\ \beta^*, \gamma^*\ (\rm {in \ degrees})
beta1()
beta2()
beta3()
u = UnitCell(2,2,4,90,90,60)
print u.beta3()
returns lattice parameters \beta_1=\alpha^*,\ \beta_2=\beta^*, \ \beta_3=\gamma^* \ (\rm {in \ radians}). Note: “International Tables for Crystallography” notation
set(a,b,c,alpha,beta,gamma,Unit=unit)
u = UnitCell()
u.set(2,3.5,4,90,90,90)
u.set(2,3.5,4,90,90,90,Unit = Degrees)
u.set(2,3.5,4,0.5*math.pi,0.5*math.pi,0.5*math.pi,Unit = Radians)
sets a, b, c\ (\rm {in \ \AA}), \ \alpha, \ \beta,\ \gamma \ (\rm {in \ degrees \ or \ radians}) values. The optional parameter “Unit” controls the units for the angles, and can have the value of “Degrees” or “Radians”. By default Unit = Degrees
seta(a)
setb(b)
setc(c)
u = UnitCell(2,3.5,4)
u.setc(5)
print u.c()
sets lattice parameters a, b, c\ (\rm {in \ \AA})
setalpha(alpha,Unit=unit)
setbeta(beta,Unit=unit)
setgamma(gamma,Unit=unit)
u = UnitCell()
u.setalpha(88)
u.setbeta(95,Unit = Degrees)
u.setgamma(0.5*math.pi,Unit = Radians)
sets \alpha, \ \beta,\ \gamma \ (\rm {in \ degrees \ or \ radians}) values. The optional parameter “Unit” controls the units for the angles, and can have the value of “Degrees” or “Radians”. By default Unit = Degrees
d(h,k,l)
d(V3D vector)
u = UnitCell(2,3.5,4)
print u.d(1,1,1)
print u.d(V3D(1,1,1))
returns d^{}_{}-spacing (\rm in \ \rm \AA) for given h,k,l coordinates
dstar(h,k,l)
dstar(V3D vector)
u = UnitCell(2,3.5,4)
print u.dstar(1,1,1)
print u.dstar(V3D(1,1,1))
returns d^*=1/d \ (\rm in \ \rm \AA^{-1}) for given h,k,l coordinates
recAngle(h1,k1,l1,h2,k2,l2,Unit=unit)
u = UnitCell(2,3.5,4)
print u.recAngle(1,0,0,1,1,0)
print u.recAngle(1,0,0,1,1,1,Unit=Degrees)
print u.recAngle(1,0,0,1,1,0,Unit = Radians)
returns the angle in reciprocal space between vectors given by \left(h_1, k_1, l_1\right) and \left(h_2, k_2, l_2\right) \ (\rm {in \ degrees \ or \ radians}). The optional parameter “Unit” controls the units for the angles, and can have the value of “Degrees” or “Radians”. By default Unit = Degrees
volume()
recVolume()
u = UnitCell(2,3.5,4)
print u.volume()
print u.recVolume()
return the volume of the direct or reciprocal unit cell (\rm {in \ \AA^3 \ respectively \ \AA^{-3}})
getB()
getBinv()
u = UnitCell(2,3.5,4)
print u.getB()
print u.getBinv()
return the B^{}_{} and B^{-1}_{} matrices
getG()
getGstar()
u = UnitCell(2,3.5,4)
print u.getG()
print u.getGstar()
return the G^{}_{} and G^{*}_{} metric tensors of the direct and reciprocal lattices
recalculateFromGstar(Gstar 2D 3x3 array)
newGstar=array([[2,0,0],[0,0.5,0],[0,0,1]])
u=UnitCell()
u.recalculateFromGstar(newGstar)
recalculates the lattice parameters from the new G^{*}_{} and sets them to the current UnitCell object

Oriented lattices

All the functions defined for UnitCell are inherited by the OrientedLattice objects. In addition, the following functions are defined for OrientedLattice only:

Function Example Description
OrientedLattice() o = OrientedLattice() default constructor, with a=b=c=1\rm \AA, \ \alpha=\beta=\gamma=90^\circ. The U^{}_{} matrix is set to identity
OrientedLattice(other oriented lattice)
o = OrientedLattice()
o2 = OrientedLattice(o)
copy constructor
OrientedLattice(a,b,c) o = OrientedLattice(2,3.5,4) constructor using a, b, c\ (\rm {in \ \AA}), \ \alpha=\beta=\gamma=90^\circ. The U^{}_{} matrix is set to identity
OrientedLattice(a,b,c,alpha,beta,gamma,Unit = unit)
o = OrientedLattice(2,3.5,4,90,90,90)
o = OrientedLattice(2,3.5,4,90,90,90,Unit = Degrees)
o = OrientedLattice(2,3.5,4,0.5*math.pi,0.5*math.pi,0.5*math.pi,Unit = Radians)
constructor using a, b, c\ (\rm {in \ \AA}), \ \alpha, \ \beta,\ \gamma \ (\rm {in \ degrees \ or \ radians}). The optional parameter “Unit” controls the units for the angles, and can have the value of “Degrees” or “Radians”. By default Unit = Degrees. The U^{}_{} matrix is set to identity
OrientedLattice(unit cell)
u=UnitCell(2,3,4)
o = OrientedLattice(u)
constructor from UnitCell. The U^{}_{} matrix is set to identity
getU()
getUB()
o.OrientedLattice(2,3.5,4)
print u.getU()
print u.getUB()
return the U^{}_{} and UB^{}_{} matrices
setU()
setUB()
o.OrientedLattice(2,3.5,4)
newU=array([[0,1,0],[1,0,0],[0,0,-1]])
o.setU(newU)
newUB=array([[2,1,0],[1,2,0],[2,0,-1]])
o.setUB(newUB)
sets the U^{}_{} and UB^{}_{} matrices. for setUB function, it will calculate first the lattice parameters, then the B^{}_{} matrix, and then U^{}_{}. See Note about orientation
setUFromVectors(v1,v2)
o.OrientedLattice(2,3.5,4)
o.setUFromVectors([1,0,0],[0,1,0])
o.setUFromVectors(array([1,0,0]),array([0,1,0]))
o.setUFromVectors(V3D(1,0,0),V3D(0,1,0))
recalculates and sets the U^{}_{} matrix, such as the first vector is along the beam direction, and the second vector is in the horizontal plane. See Note about orientation. In python, the v1 and v2 vectors can be of type V3D, or length 3 list, or length 3 numpy array, not necessarily the same
getuVector()
getvVector()
o.OrientedLattice(2,3.5,4)
o.setUFromVectors([5,5,0],[-2,1,0])
print o.getuVector()
print o.getvVector()
getuVector returns a vector along beam direction, while getvVector returns a vector in the horizontal plane, perpendicular to the beam direction (see http://horace.isis.rl.ac.uk/Getting_started). See Note about orientation

Note about orientation

Most of the instruments have incident beam along the \mathbf{z} direction. For an orthogonal lattice with \mathbf{a}^* along \mathbf{z}, \mathbf{b}^* along \mathbf{x}, and \mathbf{c}^* along \mathbf{y}, the U^{}_{} matrix has the form:

U =  \left( \begin{array}{ccc}
    0 & 1 & 0 \\
    0 & 0 & 1 \\
    1 & 0 & 0 \end{array} \right)

Category: Concepts