Chapter 3
15 min read
Section 26 of 70

Structure Factor and Diffraction

Reciprocal Space and Diffraction

Learning Objectives

Section 3.5 (Bloch's theorem) told us where diffraction peaks can appear: only at reciprocal-lattice points G=hb1+kb2+b3\mathbf{G} = h\mathbf{b}_1 + k\mathbf{b}_2 + \ell\mathbf{b}_3. That is the geometry. But every real crystal contains more than one atom per unit cell — and the waves scattered by those atoms interfere. Some of the geometrically-allowed peaks come out bright, some come out dim, and some come out perfectly dark. The single number that controls all of that is the structure factor F(hk)F(hk\ell). By the end of this section you will be able to:

  1. Write the structure-factor sum F(hk)=jfje2πi(hxj+kyj+zj)F(hk\ell) = \sum_j f_j\, e^{2\pi i (h x_j + k y_j + \ell z_j)} and explain every piece — the form factor fjf_j, the fractional coordinates (xj,yj,zj)(x_j, y_j, z_j), and why the exponent has a factor of 2π2\pi.
  2. Read a structure factor as a sum of vectors in the complex plane — one arrow per atom — and recognise destructive interference as the arrows cancelling head-to-tail.
  3. Derive by hand the famous selection rules: simple cubic allows everything, BCC kills h+k+h+k+\ell odd, and FCC allows only all-even or all-odd (h,k,)(h, k, \ell).
  4. Connect F2|F|^2 to the intensity an X-ray or neutron detector records, and understand why a powder diffractogram of FCC copper has the iconic (111),(200),(220),(311)(111), (200), (220), (311) sequence.
  5. Compute structure factors in a few lines of NumPy and locate where VASP uses exactly the same sum (in PAW projectors and in the charge density's Fourier components on the FFT grid).
One-line preview: the reciprocal lattice tells you where the spots can sit; the structure factor tells you how brightly each one shines. Together they are the diffraction pattern.

From Where to How Bright

Bragg's condition, 2dhksinθ=nλ2 d_{hk\ell} \sin\theta = n\lambda, is a statement about angles. Equivalently, a peak occurs whenever the scattering wavevector q=koutkin\mathbf{q} = \mathbf{k}_\text{out} - \mathbf{k}_\text{in} coincides with a reciprocal-lattice vector G\mathbf{G}. So far so good — but Bragg never asked how strong that peak is. It just says "it is allowed at this angle."

Imagine you doubled the crystal's unit cell by sliding a copy of every atom by half a lattice vector. Bragg's geometry would not notice — the lattice still has the same spacing. Yet, for a symmetrically-placed atom, half of the spots that Bragg allows would suddenly disappear. Real crystals do this all the time: BCC iron, FCC copper, the two-atom basis of diamond, the Na/Cl basis of rock salt. The geometry is fixed by the lattice, but the brightness is fixed by where the atoms sit inside the cell.

The 30-second mental model

Think of every atom jj as a tiny radio antenna, broadcasting an outgoing spherical wave whose strength is its form factor fjf_j and whose phase depends on where the atom sits. At a chosen reflection G\mathbf{G}, the detector sees the sum of all those waves. Sometimes they add up; sometimes they cancel. The structure factor is just that sum, written as a single complex number.


Laue, Bragg, and the Ewald Sphere

Before we count the brightness of peaks, let's nail down where they sit — geometrically, with no algebra hiding behind the curtain. There are three statements of the diffraction condition, all saying the same thing. Once you see them as one picture, the rest of the chapter clicks into place.

1. Elastic scattering — the magnitude rule

An X-ray (or electron, or neutron) photon comes in with wavevector kin\mathbf{k}_\text{in} of magnitude kin=2π/λ|\mathbf{k}_\text{in}| = 2\pi/\lambda. It scatters elastically — energy in equals energy out — so the outgoing wavevector kout\mathbf{k}_\text{out} has the same magnitude as the incoming one: kout=kin|\mathbf{k}_\text{out}| = |\mathbf{k}_\text{in}|. That single sentence is what makes the geometry sit on a sphere.

2. The Laue condition — direction is locked to G

The crystal can only re-route the photon by exchanging momentum with the lattice. The lattice can only absorb momenta that are reciprocal vectors (Section 3.2 told us why: any other momentum-kick would average to zero across the periodic potential). So the change in wavevector, Δkkoutkin\Delta\mathbf{k} \equiv \mathbf{k}_\text{out} - \mathbf{k}_\text{in}, must be a reciprocal-lattice vector:

  koutkin  =  G  \boxed{\;\mathbf{k}_\text{out} - \mathbf{k}_\text{in} \;=\; \mathbf{G}\;}

This is the Laue condition. It is the diffraction rule a physicist would write down — short, vector, reciprocal-space.

3. Bragg's law — angle and plane spacing

A crystallographer would prefer to talk about planes of atoms with spacing dhkd_{hk\ell} reflecting an X-ray like a mirror. Path length adds up constructively when the extra round-trip distance equals an integer number of wavelengths, giving the Bragg law:

  2dhksinθB  =  nλ  \boxed{\;2\,d_{hk\ell}\,\sin\theta_B \;=\; n\,\lambda\;}

Here θB\theta_B is the angle between the incoming beam and the (hkℓ) plane. The two formulations look nothing alike — one is in reciprocal space with vectors, the other is in real space with a triangle and a sine. We will now show they are literally the same equation.

From Laue to Bragg — three lines

Start from the Laue condition kout=kin+G\mathbf{k}_\text{out} = \mathbf{k}_\text{in} + \mathbf{G}. Square both sides and use elastic scattering kout2=kin2|\mathbf{k}_\text{out}|^2 = |\mathbf{k}_\text{in}|^2:

kin2+2kinG+G2  =  kin2        2kinG  =  G2.|\mathbf{k}_\text{in}|^2 + 2\,\mathbf{k}_\text{in}\cdot\mathbf{G} + |\mathbf{G}|^2 \;=\; |\mathbf{k}_\text{in}|^2 \;\;\Longrightarrow\;\; 2\,\mathbf{k}_\text{in}\cdot\mathbf{G} \;=\; -\,|\mathbf{G}|^2.

Divide by 2kinG2|\mathbf{k}_\text{in}||\mathbf{G}| and read the dot product as a cosine of the angle α\alpha between kin\mathbf{k}_\text{in} and G\mathbf{G}:

cosα  =  G2kin.\cos\alpha \;=\; -\,\frac{|\mathbf{G}|}{2\,|\mathbf{k}_\text{in}|}.

Now G\mathbf{G} is perpendicular to the (hkℓ) plane, so the angle θB\theta_B between the beam and the plane is α=π2+θB\alpha = \tfrac{\pi}{2} + \theta_B. That gives cosα=sinθB\cos\alpha = -\sin\theta_B, and substituting G=2π/dhk|\mathbf{G}| = 2\pi/d_{hk\ell} and kin=2π/λ|\mathbf{k}_\text{in}| = 2\pi/\lambda yields

sinθB  =  G2kin  =  2π/dhk2(2π/λ)  =  λ2dhk        2dhksinθB  =  λ.\sin\theta_B \;=\; \frac{|\mathbf{G}|}{2|\mathbf{k}_\text{in}|} \;=\; \frac{2\pi/d_{hk\ell}}{2\,(2\pi/\lambda)} \;=\; \frac{\lambda}{2\,d_{hk\ell}} \;\;\Longleftrightarrow\;\; 2\,d_{hk\ell}\,\sin\theta_B \;=\; \lambda.

Bragg's law falls out of the Laue condition with nothing more than "the magnitudes are equal." The n on the right of nλn\lambda is absorbed into the choice of G\mathbf{G}: a reflection from the nth-order plane stack is the same thing as a reflection from nGn\,\mathbf{G} on the (hkℓ) plane stack. One picture, two languages.

Why the d-spacing formula is d = 2π/|G|

A reciprocal-lattice vector Ghk\mathbf{G}_{hk\ell} is normal to the family of (hkℓ) planes (we will prove this in a moment in §3.2 if you have not seen it yet). The plane closest to the origin sits at a perpendicular distance dhkd_{hk\ell} from the origin. The plane equation, in the form G^r=dhk\hat{\mathbf{G}}\cdot\mathbf{r} = d_{hk\ell}, says that any r\mathbf{r} on the plane projects to the same length dhkd_{hk\ell} along G^\hat{\mathbf{G}}. The next plane along is at 2dhk2 d_{hk\ell}, and so on, so the phase pickup from one plane to the next is G(dhkG^)=Gdhk\mathbf{G}\cdot(d_{hk\ell}\hat{\mathbf{G}}) = |\mathbf{G}|\,d_{hk\ell}. For all planes to scatter in phase, this phase must be a multiple of 2π2\pi, giving Gdhk=2π|\mathbf{G}|\,d_{hk\ell} = 2\pi, i.e. dhk=2π/Ghkd_{hk\ell} = 2\pi/|\mathbf{G}_{hk\ell}|. This is the bridge between crystallography (planes) and physics (reciprocal vectors).

The Ewald sphere — the geometry, finally drawn

The two boxed equations share an answer; how do you actually find which (hkℓ) lights up for a given crystal orientation and wavelength? Ewald's 1913 trick was to draw the picture on the same diagram as the reciprocal lattice. The recipe is four steps:

  1. Draw the reciprocal lattice as a forest of points, with the origin O at the (000) point.
  2. Pick the incident wavevector kin\mathbf{k}_\text{in} and place its tip at O. Call its tail L (the "lab" point).
  3. Draw a sphere of radius kin=2π/λ|\mathbf{k}_\text{in}| = 2\pi/\lambda centred at L. This is the Ewald sphere.
  4. Every reciprocal-lattice point that lies on the surface of this sphere is a Bragg peak. The outgoing beam kout\mathbf{k}_\text{out} goes from L to that point, automatically with the right magnitude (it is a sphere radius!) and with koutkin=G\mathbf{k}_\text{out} - \mathbf{k}_\text{in} = \mathbf{G}.

The widget below is exactly that recipe in 2D (so the "sphere" is a circle and the lattice is a grid). Slide the wavelength to grow or shrink the circle, slide the crystal angle to roll it around the origin, and watch the Bragg peaks switch on whenever a grid point hits the curve. The orange L moves on a circle of radius kin|\mathbf{k}_\text{in}| around the white O, and the highlighted reflection's panel lists G|\mathbf{G}|, dhk=2π/Gd_{hk\ell} = 2\pi/|\mathbf{G}| and the Bragg angle θB\theta_B — verifying 2dhksinθB=λ2 d_{hk\ell} \sin\theta_B = \lambda in real time.

The Ewald construction — drag the wavelength and the beam direction

3 G on the sphere

Reciprocal lattice = grey grid of points G = (h, k). Incident beam k_in points from L (orange) into the origin O. The cyan circle (the 2-D Ewald sphere) has centre L and radius |k_in|. Any reciprocal-lattice point that sits on the circle is a Bragg peak: a scattered beam k_out = k_in + G comes out from L through that point. Move the sliders and watch peaks light up.

|k_in| / |b*|2.60
Bigger k = shorter λ = bigger sphere = more reflections in range.
crystal angle θ°20°
Rotates the incident beam (= rotates the crystal in the lab).
(-5,-1)(-4,-3)(-1,-3)LOh →k ↑
Highlighted reflection
(h, k) = (-5, -1)
|G| = 5.099 · |b*|
dhk = 2π/|G| = 0.196 · a
sinθB = |G|/(2|kin|) = 0.981
θB = 78.69°
2d sinθ = 0.385 · a → matches λ
What the colours mean
  • kin (incident beam) and the Ewald circle, radius |kin|
  • kout for the highlighted G — same length as kin
  • - - G = kout − kin (the Laue vector)
  • Bragg-allowed point (on the circle) · not currently in diffracting condition
Try this
  • Crank |kin| up — the circle bulges outward and reaches more (h, k).
  • Sweep the angle slider — the circle rolls around O and the reflections that switch on are exactly the ones a rotating crystal would record.
  • Note that O = (0, 0) always sits on the circle (the forward beam, undeviated, kout = kin).

What the slider taught you

A fixed wavelength on a fixed crystal generally puts only a handful of G-points exactly on the Ewald sphere — that is why a single-crystal X-ray photo shows isolated spots, not all the allowed (hkℓ) at once. To collect them all, experiments either (a) rotate the crystal so the sphere sweeps through reciprocal space (rotating-crystal method), (b) use a continuous band of wavelengths so the sphere's radius spans a range and many points are caught (Laue method), or (c) grind the crystal into a powder so reciprocal vectors of fixed length G|\mathbf{G}| appear in every direction — Debye–Scherrer rings (powder method).

Connecting back to ENCUT and KPOINTS

The same sphere appears inside VASP, just dressed differently. The plane-wave basis (Section 3.5 and §4.9) keeps every k+G\mathbf{k} + \mathbf{G} with 22mk+G2ENCUT\tfrac{\hbar^2}{2m}|\mathbf{k} + \mathbf{G}|^2 \le \text{ENCUT} — that is a sphere in reciprocal space, centred at k\mathbf{k}, of radius 2mENCUT/\sqrt{2m\,\text{ENCUT}}/\hbar. It is not an Ewald sphere (no diffraction is happening), but it is the same geometric construction: pick a centre in reciprocal space, draw a ball around it, keep the lattice points inside (or on) it. Once you have the Ewald picture, you have the mental machinery for every sphere-in-reciprocal-space construction in the rest of the book.


A Two-Atom Thought Experiment

Forget 3D for a moment. Picture a 1D chain of unit cells of length aa. Each cell contains two identical atoms — one at the origin and one at fractional position uu. The reciprocal lattice has the familiar points Gh=2πh/aG_h = 2\pi h/a. What is the scattered amplitude at GhG_h?

The wave reaching the detector from the corner atom has phase 0 (we set the origin there). The wave from the second atom is delayed by Gh(ua)=2πhuG_h \cdot (u a) = 2\pi h u. With both atoms having amplitude ff, the total amplitude is

F(h)  =  f  +  fe2πihu.F(h) \;=\; f \;+\; f\,e^{2\pi i\,h\,u}.

Two arrows of length ff, one at angle 0 and one at angle 2πhu2\pi h u. When the two arrows point the same way, they double up: F=2f|F| = 2f. When they point exactly opposite — i.e. when 2πhu=π2\pi h u = \pi, or equivalently hu=1/2h u = 1/2 — they cancel exactly: F=0|F| = 0. Pick u=1/2u = 1/2 (the BCC analogue): every odd hh reflection vanishes. We just discovered systematic absences with two atoms and one slider.

Hold this picture

For the rest of the section, every structure-factor calculation is this same picture, repeated for more atoms and three spatial axes. The complex number is just a compact bookkeeping device for adding up arrows.


The Structure Factor — Definition and Anatomy

Generalising the 1D toy: write each atom's fractional position as rj=xja1+yja2+zja3\mathbf{r}_j = x_j\mathbf{a}_1 + y_j\mathbf{a}_2 + z_j\mathbf{a}_3 and the reciprocal-lattice vector as Ghk=hb1+kb2+b3\mathbf{G}_{hk\ell} = h\mathbf{b}_1 + k\mathbf{b}_2 + \ell\mathbf{b}_3. Using the duality biaj=2πδij\mathbf{b}_i \cdot \mathbf{a}_j = 2\pi\,\delta_{ij} from Section 3.2, the dot product collapses beautifully:

Ghkrj  =  2π(hxj+kyj+zj).\mathbf{G}_{hk\ell}\cdot \mathbf{r}_j \;=\; 2\pi\,(h x_j + k y_j + \ell z_j).

With that in hand, the structure factor is

  F(hk)  =  j=1Ncell  fj  exp ⁣[2πi(hxj+kyj+zj)].  \boxed{\;F(hk\ell) \;=\; \sum_{j=1}^{N_\text{cell}}\; f_j\;\exp\!\bigl[\, 2\pi i\,(h x_j + k y_j + \ell z_j)\,\bigr].\;}

Five symbols, but every one of them earns its place. Let's read the equation aloud once:

SymbolWhat it isWhy it is here
F(hkℓ)Complex amplitude of the (hkℓ) reflection.What we want — the brightness and phase of one diffraction spot.
ΣⱼSum over every atom in the unit cell.Every atom is a wave source; the detector sees the sum of those waves.
fⱼAtomic form factor of atom j.Tells us how strong an antenna atom j is — bigger atoms scatter more.
(xⱼ, yⱼ, zⱼ)Fractional coordinates of atom j.Where the antenna sits inside the cell. Drives the phase via 2π(h·x+k·y+ℓ·z).
exp[2πi(...)]Phase factor.Encodes the path-length difference between this atom and the origin.
(h, k, ℓ)Miller indices = which reciprocal-lattice point.Selects which spot on the diffractogram we are evaluating.

Two conventions, one sum

Some books absorb the 2π2\pi into the reciprocal-lattice vector and write F=jfjeiGrjF = \sum_j f_j\, e^{i\mathbf{G}\cdot\mathbf{r}_j}. Others (mostly crystallographers) factor it out and write F=jfje2πi(hxj+kyj+zj)F = \sum_j f_j\, e^{2\pi i (h x_j + k y_j + \ell z_j)} with fractional coordinates. Both are the same number. Use the second form when you have a list of fractional positions in a POSCAR — the 2π2\pi shows up exactly once.


Atomic Form Factor — Why Heavy Atoms Glow Brighter

The number fjf_j is itself a function of the scattering vector G\mathbf{G}. It is the Fourier transform of atom jj's electron density ρj(r)\rho_j(\mathbf{r}):

fj(G)  =  ρj(r)eiGrd3r.f_j(\mathbf{G}) \;=\; \int \rho_j(\mathbf{r})\,e^{-i\mathbf{G}\cdot\mathbf{r}}\,d^3 r.

At G=0\mathbf{G} = 0 the integral just counts electrons: fj(0)=Zjf_j(0) = Z_j, the atomic number. So carbon has f6f \approx 6 at low angle, lead has f82f \approx 82; with X-rays, lead overwhelms carbon by a factor of (82/6)2187(82/6)^2 \approx 187 in intensity. As G|\mathbf{G}| grows the electron cloud is no longer well-resolved and fj(G)f_j(\mathbf{G}) falls off — that is why diffraction patterns fade at large 2θ2\theta.

Three flavours of f, one formula

For X-rays, fjf_j is the electron-density Fourier transform above. For neutrons it is replaced by a near-constant nuclear scattering length bjb_j (nuclei are tiny — point-like compared to a wavelength). For electrons it is the Fourier transform of the electrostatic potential. The structure-factor sum looks identical in all three; only the meaning of fjf_j changes.

For most of this section we treat the form factors as constants — the cancellations we want to expose are geometric and depend only on the atomic positions. We will revisit the angle dependence when we compute powder patterns numerically in Chapter 6.


Interactive — Drag Atoms, Watch the Pattern

The visualiser below puts a 2D structure factor in front of you. The unit cell on the left has two atoms; you can drag them anywhere within the cell and tweak each form factor. The right panel is the resulting diffraction pattern: a 7×7 grid of reciprocal-lattice points (h,k)(h,k), with the radius of each yellow spot proportional to F(h,k)|F(h,k)|. Click any spot to see its phase decomposition — two arrows in the complex plane (sky for atom 1, amber for atom 2) summed head-to-tail to produce the green total.

Preset:
Real space — drag the atoms
a₁a₂12
atom 1: (0.000, 0.000)f1 = 1.00
f:
atom 2: (0.500, 0.500)f2 = 1.00
f:
Reciprocal space — |F(h,k)|, click any spot
(1,0)hk
Spot radius ∝ |F(h,k)|. Spots that vanish are forbidden by interference.
Phase decomposition at (h, k) = (1, 0)
ReIm
f₁·eiφ₁ = 1.00 + 0.00i
f₂·eiφ₂ = -1.00 + 0.00i
F = 0.00 + 0.00i
φ₁ = 2π(h·x₁ + k·y₁) = 0.000 rad  |  φ₂ = 3.142 rad  |  |F|² = 0.000
Read me out loud

Each atom contributes a complex number of length fj and angle 2π(h·xj + k·yj). The structure factor F(h,k) is their head-to-tail sum. When the two arrows point opposite ways and have equal length, they cancel — that spot goes dark. That is a systematic absence.

Three experiments to run before moving on:

  1. Hit the Simple preset (only one atom). Every spot is the same size — pure lattice, no interference.
  2. Hit BCC-like (atoms at (0,0)(0,0) and (12,12)(\tfrac12,\tfrac12)). Watch the spots with h+kh+k odd vanish. Click one — the two arrows point opposite ways and cancel exactly. That is the systematic-absences rule made visible.
  3. Switch to Heavy + light. Now the two arrows have unequal lengths, so they can never quite cancel — the "forbidden" spots come back, dimly. This is exactly what happens for ordered binary alloys like Cu3Au or rock salt.
Pedagogical anchor: if you can predict the pattern before you drag, you understand structure factors. The rest of this section is just turning that visual intuition into a 3D formula and a few lines of code.

Worked Example 1 — Simple Cubic

One atom per cell at (0,0,0)(0, 0, 0). The sum has exactly one term:

F(hk)  =  fe0  =  ffor every (h,k,).F(hk\ell) \;=\; f\,e^{0} \;=\; f \quad \text{for every } (h,k,\ell).

Every reciprocal-lattice point is allowed and every spot has the same intensity (modulo the angle-dependence of ff). The simple-cubic powder pattern is a clean ladder of peaks at (100),(110),(111),(200),(210),(211),(220),(100), (110), (111), (200), (210), (211), (220), \ldots.


Worked Example 2 — BCC and the First Forbidden Peak

BCC has a two-atom basis on the conventional cube: corner at (0,0,0)(0, 0, 0) and body-centre at (12,12,12)(\tfrac12, \tfrac12, \tfrac12).

Loading 3D visualisation…

The structure factor is

F(hk)  =  f[1  +  eiπ(h+k+)].F(hk\ell) \;=\; f\,\bigl[\,1 \;+\; e^{i\pi(h+k+\ell)}\,\bigr].

The key observation: eiπne^{i\pi n} equals +1+1 for even nn and 1-1 for odd nn. So

h + k + ℓF(hkℓ)Allowed?
evenf · (1 + 1) = 2f✓ allowed (intensity ∝ 4f²)
oddf · (1 − 1) = 0✗ forbidden (perfect cancellation)

That single line — half of the spots Bragg permits actually disappear — is the defining experimental signature of BCC. The very first peak in the iron powder pattern is (110)(110), not (100)(100); (100)(100) is killed because 1+0+0=11+0+0 = 1 is odd. Without structure factors you would predict a peak that experiments never see.

Re-derive on the interactive

Open the BCC-like preset above. Click (1,0)(1, 0): the two arrows are antiparallel — exact cancellation. Click (1,1)(1, 1): the arrows are aligned — full amplitude. The 2D version of the same rule.


Worked Example 3 — FCC's All-Same-Parity Rule

FCC has four atoms per conventional cube at (0,0,0),(12,12,0),(12,0,12),(0,12,12)(0,0,0), (\tfrac12, \tfrac12, 0), (\tfrac12, 0, \tfrac12), (0, \tfrac12, \tfrac12). The sum factorises:

F(hk)=f[1+eiπ(h+k)+eiπ(h+)+eiπ(k+)].F(hk\ell) = f\,\bigl[\,1 + e^{i\pi(h+k)} + e^{i\pi(h+\ell)} + e^{i\pi(k+\ell)}\,\bigr].

Three sub-cases cover everything:

  • All three of h,k,h, k, \ell have the same parity (all even or all odd) ⇒ each pairwise sum h+kh+k, h+h+\ell, k+k+\ell is even ⇒ every exponential is +1+1F=4fF = 4f (intensity 16f216 f^2).
  • Mixed parity (one odd among two evens, or one even among two odds) ⇒ exactly two pairwise sums are odd ⇒ F=f(1+111)=0F = f\,(1 + 1 - 1 - 1) = 0. Forbidden.

The famous powder fingerprint of FCC copper is therefore (111),(200),(220),(311),(222),(400),(331),(420),(111), (200), (220), (311), (222), (400), (331), (420), \ldots — hit any university X-ray lab and you will see exactly this sequence on aluminum foil and copper coins.

A subtle catch

The four-atom basis above lives on the conventional cubic cell. If you instead work with the primitive rhombohedral FCC cell, there is only one atom per cell ⇒ F=fF = f for every primitive (hp,kp,p)(h_p, k_p, \ell_p). No spots are forbidden! The reason the conventional indexing has absences is that the conventional cell is four times larger — it contains fictitious reciprocal-lattice points that do not actually correspond to primitive reciprocal vectors. They "turn off" through the structure factor. The two pictures are completely consistent.


Worked Example 4 — NaCl, Where Cancellations Are Almost Perfect

Rock salt is FCC with a two-element basis: Na at (0,0,0)(0,0,0) and Cl at (12,0,0)(\tfrac12, 0, 0), plus the FCC face-centre translations applied to both. Carrying out the sum:

F(hk)=[fNa+fCleiπh][1+eiπ(h+k)+eiπ(h+)+eiπ(k+)].F(hk\ell) = \bigl[\,f_\text{Na} + f_\text{Cl}\,e^{i\pi h}\,\bigr]\,\bigl[\,1 + e^{i\pi(h+k)} + e^{i\pi(h+\ell)} + e^{i\pi(k+\ell)}\,\bigr].

The right bracket is the FCC factor (4 if all-same-parity, 0 otherwise). The left bracket is fNa+fClf_\text{Na} + f_\text{Cl} for even hh and fNafClf_\text{Na} - f_\text{Cl} for odd hh. Three regimes appear:

Reflection classFWhat it tells you
All-even, e.g. (200), (400)4 (f_Na + f_Cl)Strong: both species add. Driven by the average density.
All-odd, e.g. (111), (311)4 (f_Na − f_Cl)Weak but non-zero: difference of form factors. The signature of an ordered binary basis.
Mixed parity, e.g. (100), (110)0Forbidden by the FCC face-centre rule — the basis cannot rescue them.

The weak odd reflections of NaCl famously vanish to first approximation when fNafClf_\text{Na} \approx f_\text{Cl}, which is why early diffraction data on KCl (whose form factors are nearly equal) looked like simple cubic instead of FCC — a beautiful historical puzzle that the structure factor solved.


From |F|² to a Real Diffraction Pattern

What a detector counts at the spot (h,k,)(h, k, \ell) is, in the kinematical approximation,

Ihk    F(hk)2L(θ)P(θ)mhke2M(θ).I_{hk\ell} \;\propto\; |F(hk\ell)|^2 \cdot L(\theta) \cdot P(\theta) \cdot m_{hk\ell} \cdot e^{-2 M(\theta)}.

The structure factor gives the chemistry. The other factors are pure geometry/statistics: LL the Lorentz factor, PP the polarisation factor, mhkm_{hk\ell} the multiplicity (how many symmetry-equivalent (hk)(hk\ell) share the same dd-spacing in a powder), and e2Me^{-2M} the Debye-Waller factor that damps peaks at high angle because thermal vibration smears the atomic positions.

For the rest of this book, when we say "intensity" for a single-crystal calculation we will mean F2|F|^2 alone. The geometric corrections are handled by the powder-pattern simulator and never change the absent/present pattern — only the relative magnitudes of the present ones.


Computing Structure Factors in Python

Every formula in this section fits in twelve lines of NumPy. Below the code panel is the running execution trace — click any line on the right to see exactly what its variables hold. The example computes the first six FCC reflections and prints the allowed/forbidden verdict for each.

Structure factor — line by line
🐍structure_factor.py
1import numpy as np

NumPy is Python's numerical-computing workhorse. We need it here for two things: complex numbers (np.exp(1j*x) returns cos x + i sin x) and π (np.pi). Everything we compute is a few additions of complex numbers, so NumPy is overkill for performance — but it gives us a single dependency for the entire file.

EXECUTION STATE
📚 numpy = NumPy is a numerical-computing library: ndarray, math constants like np.pi, complex exponentials via np.exp.
as np = Standard alias so we type np.pi instead of numpy.pi everywhere.
3def structure_factor(hkl, atoms, form_factors)

Defines the central object of this section: the structure factor F(h,k,l). It accepts a Miller-index triple and a list of atoms (in fractional coordinates) with their form factors, and returns the complex amplitude scattered into the (h,k,l) reflection.

EXECUTION STATE
⬇ input: hkl = Tuple (h, k, l) of integer Miller indices. Picks one reciprocal-lattice point. Example: (1,1,1).
⬇ input: atoms = List of (x, y, z) fractional positions, one per basis atom in the unit cell. FCC example: [(0,0,0), (½,½,0), (½,0,½), (0,½,½)]
⬇ input: form_factors = List of scattering amplitudes f_j, one per atom (same order as atoms). For one element, all entries are equal; for binary compounds (NaCl) entries differ.
→ why fractional coords? = Phases involve h·x + k·y + l·z. With fractional coords, an atom at the corner is (0,0,0) regardless of cell size, so the formula is cell-size independent.
⬆ returns = Complex number F(h,k,l). |F|² is the spot's intensity (up to geometric factors).
4Docstring — what F(hkl) is

States the formula in one line: F(hkl) = Σ_j f_j · exp(2πi(hx_j + ky_j + lz_j)). This is just the Fourier transform of the electron density evaluated at the reciprocal-lattice point G_hkl.

5h, k, l = hkl

Tuple unpacking: pull the three Miller indices out of the input tuple so we can use them as scalars below.

EXECUTION STATE
h = First Miller index (integer).
k = Second Miller index (integer).
l = Third Miller index (integer). Note: lowercase L, not the digit 1.
→ example for hkl=(1,1,1) = h = 1, k = 1, l = 1
6F = 0.0 + 0.0j

Initialise F as the complex zero. The 'j' suffix is Python's notation for the imaginary unit i. We will accumulate atomic contributions into this variable inside the loop.

EXECUTION STATE
F = 0.0 + 0.0j (complex zero)
→ why complex? = Each atom contributes a vector in the complex plane (length f, angle φ). Summing them is just complex-number addition. The result's |·|² is what the detector measures.
7for (x, y, z), f in zip(atoms, form_factors):

Iterate through atoms and their form factors in lockstep. Each pass gives us one atom's fractional coords (x, y, z) and one scalar form factor f.

LOOP TRACE · 4 iterations
j=0 — corner atom, FCC
(x,y,z) = (0.0, 0.0, 0.0)
f = 1.0
j=1 — face atom (½,½,0)
(x,y,z) = (0.5, 0.5, 0.0)
f = 1.0
j=2 — face atom (½,0,½)
(x,y,z) = (0.5, 0.0, 0.5)
f = 1.0
j=3 — face atom (0,½,½)
(x,y,z) = (0.0, 0.5, 0.5)
f = 1.0
8phase = 2π(h x + k y + l z)

The phase angle (in radians) of the wave scattered by atom j when probed at reciprocal-lattice point G_hkl. The 2π factor is what turns the dimensionless dot product (h x + k y + l z) into an angle.

EXECUTION STATE
📚 np.pi = Numpy's high-precision π ≈ 3.14159265358979.
h x + k y + l z = Plain real number — the dot product G_hkl·r_j divided by 2π.
→ walked for hkl=(1,1,1), j=1 = h x + k y + l z = 1·0.5 + 1·0.5 + 1·0 = 1.0 phase = 2π · 1.0 = 6.2832 rad ≡ 0 mod 2π
→ walked for hkl=(1,0,0), j=1 = h x + k y + l z = 1·0.5 + 0·0.5 + 0·0 = 0.5 phase = 2π · 0.5 = 3.1416 rad = π
LOOP TRACE · 8 iterations
hkl=(1,0,0), j=0
phase = 2π·(0+0+0) = 0.0000 rad
hkl=(1,0,0), j=1
phase = 2π·(0.5+0+0) = 3.1416 rad = π
hkl=(1,0,0), j=2
phase = 2π·(0.5+0+0) = 3.1416 rad = π
hkl=(1,0,0), j=3
phase = 2π·(0+0+0) = 0.0000 rad
hkl=(1,1,1), j=0
phase = 0.0000 rad
hkl=(1,1,1), j=1
phase = 2π·(0.5+0.5+0) = 6.2832 rad ≡ 0
hkl=(1,1,1), j=2
phase = 2π·(0.5+0+0.5) = 6.2832 rad ≡ 0
hkl=(1,1,1), j=3
phase = 2π·(0+0.5+0.5) = 6.2832 rad ≡ 0
9F += f * np.exp(1j * phase)

Add this atom's complex contribution to F. np.exp(1j·φ) returns cos φ + i sin φ — a unit vector in the complex plane at angle φ. Multiplying by f scales it to the right amplitude.

EXECUTION STATE
📚 np.exp(1j*x) = Complex exponential. np.exp(1j*0)=1, np.exp(1j*π)=-1, np.exp(1j*π/2)=i. Encodes a wave's phase as a unit complex number.
1j = Python's literal for the imaginary unit i. (Engineers write j instead of i to avoid clashes with current.)
→ for phase=π = f · np.exp(1j·π) = 1.0 · (cos π + i sin π) = 1.0 · (-1 + 0i) = -1.0
→ for phase=0 = f · np.exp(0) = 1.0 · 1.0 = 1.0
LOOP TRACE · 2 iterations
hkl=(1,0,0): F running sum
after j=0 = F = 0 + (1.0·e^0) = 1.00 + 0.00i
after j=1 = F = 1.00 + (1.0·e^iπ) = 0.00 + 0.00i
after j=2 = F = 0.00 + (1.0·e^iπ) = −1.00 + 0.00i
after j=3 = F = −1.00 + (1.0·e^0) = 0.00 + 0.00i
hkl=(1,1,1): F running sum
after j=0 = F = 1.00 + 0.00i
after j=1 = F = 2.00 + 0.00i
after j=2 = F = 3.00 + 0.00i
after j=3 = F = 4.00 + 0.00i
10return F

Return the accumulated complex structure factor. The caller will square its magnitude to obtain the spot intensity.

EXECUTION STATE
⬆ return: F = Complex number whose modulus is |F| and whose argument is the overall phase of the (hkl) reflection.
→ for FCC(1,0,0) = F = 0.00 + 0.00i ⇒ forbidden
→ for FCC(1,1,1) = F = 4.00 + 0.00i ⇒ allowed, |F|² = 16
13atoms = [(0,0,0), (½,½,0), (½,0,½), (0,½,½)]

The conventional 4-atom basis of an FCC lattice on a cubic cell of side a. One atom at every corner (shared with seven neighbouring cells, so it counts as 1) and one at every face centre (shared with one neighbour, counts as ½ × 6 = 3). Total = 4 atoms per conventional cell.

EXECUTION STATE
atoms =
[(0.0, 0.0, 0.0),
 (0.5, 0.5, 0.0),
 (0.5, 0.0, 0.5),
 (0.0, 0.5, 0.5)]
→ why these four? = An FCC lattice has lattice points at every corner AND at every face centre of the cube. Restricting to the unit cell gives one corner point + three face-centre points (the other corners and faces are shared with neighbouring cells).
17form_factors = [1.0, 1.0, 1.0, 1.0]

All four atoms are the same element, so they all scatter equally. We use 1.0 as a normalised stand-in. For real metals (Cu, Al, Au) you would substitute tabulated f-values, which themselves depend on the scattering angle.

EXECUTION STATE
form_factors = [1.0, 1.0, 1.0, 1.0]
→ relax later = Try replacing one entry with 0.5 — you will see that the FCC absences are no longer perfect zeros. That happens for ordered alloys like Cu₃Au and produces 'superlattice peaks'.
19reflections = [...]

Six representative (hkl) triples covering the lowest-angle FCC reflections plus a couple of forbidden ones for contrast.

EXECUTION STATE
reflections = [(1,0,0), (1,1,0), (1,1,1), (2,0,0), (2,2,0), (2,2,2)]
→ expected pattern = FCC selection rule: present iff h,k,l are all even or all odd. (1,0,0): mixed → forbidden (1,1,0): mixed → forbidden (1,1,1): all odd → allowed (2,0,0): all even → allowed (2,2,0): all even → allowed (2,2,2): all even → allowed
21for hkl in reflections:

Outer loop: process each Miller-index triple in turn. Each iteration calls structure_factor(...) and prints the verdict.

LOOP TRACE · 6 iterations
iter 1
hkl = (1, 0, 0)
iter 2
hkl = (1, 1, 0)
iter 3
hkl = (1, 1, 1)
iter 4
hkl = (2, 0, 0)
iter 5
hkl = (2, 2, 0)
iter 6
hkl = (2, 2, 2)
22F = structure_factor(hkl, atoms, form_factors)

Call the function defined above. Returns a complex number — exactly zero for forbidden reflections, equal to the sum of form factors (here 4.0) for the most strongly allowed ones.

EXECUTION STATE
F (each iteration) =
(1,0,0): 0.00 + 0.00i
(1,1,0): 0.00 + 0.00i
(1,1,1): 4.00 + 0.00i
(2,0,0): 4.00 + 0.00i
(2,2,0): 4.00 + 0.00i
(2,2,2): 4.00 + 0.00i
23I = abs(F) ** 2

Compute the intensity as |F|². For a complex number z = a + bi, abs(z) = √(a² + b²), so abs(F)**2 = a² + b². This is what an X-ray detector is proportional to (after Lorentz, polarisation and multiplicity corrections, which are geometry not chemistry).

EXECUTION STATE
📚 abs(z) = Built-in. For complex z, returns |z| = √(Re² + Im²). For real z, just the absolute value.
** 2 = Square. We square the modulus because intensities go as |F|², not |F|.
I (each iteration) =
(1,0,0): 0.00
(1,1,0): 0.00
(1,1,1): 16.00
(2,0,0): 16.00
(2,2,0): 16.00
(2,2,2): 16.00
24tag = 'ALLOWED' if I > 1e-6 else 'FORBIDDEN'

Branch on the intensity. We use a tiny threshold (1e-6) instead of strict zero because floating-point arithmetic can leave a microscopic numerical residue (e.g. 1.2e-15) for a perfect cancellation.

EXECUTION STATE
1e-6 = Numerical tolerance. Anything below this is treated as zero. For real diffraction data this threshold is replaced by the experimental noise floor.
25print(...)

Format the row for human reading. Output of the whole program: (1,0,0): F = +0.00, |F|^2 = 0.00 [FORBIDDEN] (1,1,0): F = +0.00, |F|^2 = 0.00 [FORBIDDEN] (1,1,1): F = +4.00, |F|^2 = 16.00 [ALLOWED] (2,0,0): F = +4.00, |F|^2 = 16.00 [ALLOWED] (2,2,0): F = +4.00, |F|^2 = 16.00 [ALLOWED] (2,2,2): F = +4.00, |F|^2 = 16.00 [ALLOWED]

EXECUTION STATE
→ take-home = The two forbidden (1,0,0) and (1,1,0) lines are direct consequences of the four FCC atoms placed at corners and face centres. No fitting, no parameters — pure geometry through F(hkl).
8 lines without explanation
1import numpy as np
2
3def structure_factor(hkl, atoms, form_factors):
4    """F(hkl) = sum_j f_j * exp(2pi i (h x_j + k y_j + l z_j))."""
5    h, k, l = hkl
6    F = 0.0 + 0.0j
7    for (x, y, z), f in zip(atoms, form_factors):
8        phase = 2 * np.pi * (h * x + k * y + l * z)
9        F += f * np.exp(1j * phase)
10    return F
11
12# FCC: 4-atom basis on a conventional cube of side a
13atoms = [(0.0, 0.0, 0.0),
14         (0.5, 0.5, 0.0),
15         (0.5, 0.0, 0.5),
16         (0.0, 0.5, 0.5)]
17form_factors = [1.0, 1.0, 1.0, 1.0]   # one element, all equal
18
19reflections = [(1,0,0), (1,1,0), (1,1,1), (2,0,0), (2,2,0), (2,2,2)]
20
21for hkl in reflections:
22    F = structure_factor(hkl, atoms, form_factors)
23    I = abs(F) ** 2
24    tag = "ALLOWED" if I > 1e-6 else "FORBIDDEN"
25    print(f"({hkl[0]},{hkl[1]},{hkl[2]}): F = {F:+.2f}, |F|^2 = {I:5.2f}  [{tag}]")

Notice how short the function is. The whole concept — atoms scatter, their waves interfere, take the squared modulus — collapses into four real lines (the loop body plus the return). Every diffraction pattern you will ever fit is built from this primitive.


Structure Factors Inside VASP

VASP does not ship a button labelled "structure factor," but the same sum is hidden inside three of its most heavily-used routines:

  1. PAW projector setup. The non-local part of every pseudopotential is applied in reciprocal space via jeiGrjpj(G)\sum_j e^{-i\mathbf{G}\cdot\mathbf{r}_j}\,p_j(\mathbf{G}) — exactly the structure-factor sum, with PAW projector functions in place of atomic form factors. Every SCF iteration recomputes it.
  2. Charge density on the FFT grid. The pseudo charge density n~(r)\tilde{n}(\mathbf{r}) stored in CHGCAR is the inverse FFT of its plane-wave coefficients n~(G)\tilde{n}(\mathbf{G}). Those coefficients are nothing but generalised structure factors evaluated at every reciprocal-lattice vector inside the FFT box.
  3. Optical and X-ray spectra. When you set LOPTICS=.TRUE.\texttt{LOPTICS}=.\text{TRUE}., VASP needs matrix elements ψnkeiqrψmk+q\langle \psi_{n\mathbf{k}}|e^{i\mathbf{q}\cdot\mathbf{r}}|\psi_{m\mathbf{k}+\mathbf{q}}\rangle. Their ionic contribution reduces, again, to a structure-factor sum.

Pulling structure factors out of a finished VASP calculation

For a relaxed POSCAR you can compute (and plot) X-ray powder patterns in a few lines using pymatgen\texttt{pymatgen}:

🐍python
1from pymatgen.core import Structure
2from pymatgen.analysis.diffraction.xrd import XRDCalculator
3
4# Read VASP-relaxed structure straight from the CONTCAR
5struct = Structure.from_file("CONTCAR")
6
7xrd = XRDCalculator(wavelength="CuKa")          # 1.54184 Å
8pattern = xrd.get_pattern(struct, two_theta_range=(10, 90))
9
10for hkl, intensity, two_theta in zip(
11        pattern.hkls, pattern.y, pattern.x):
12    miller = hkl[0]["hkl"]
13    print(f"({miller[0]},{miller[1]},{miller[2]})  "
14          f"2θ = {two_theta:5.2f}°  I = {intensity:6.2f}")

Under the hood, XRDCalculator\texttt{XRDCalculator} calls the same sum we wrote above, with proper angle-dependent X-ray form factors from the International Tables and a Lorentz-polarisation weighting. Run it once on your favourite VASP-relaxed structure and you will see (111),(200),(220)(111), (200), (220) for FCC, (110),(200),(211)(110), (200), (211) for BCC, every time.

Sanity-check workflow

When a VASP relaxation surprises you — symmetry-broken positions, unexpected lattice parameters — a quick simulated powder pattern tells you whether the predicted structure is actually the polymorph you intended. We will use exactly this loop in Chapter 6 to validate Mn-doped CdSe supercells before spending hours on band-structure runs.


Common Pitfalls

PitfallSymptomFix
Cartesian coordinates inside the phaseF oscillates with cell size and looks lattice-parameter-dependent.Always use FRACTIONAL positions. The 2π factor presupposes them.
Conventional vs primitive basis confusionFCC powder pattern from primitive cell shows peaks at every (hkℓ) — no absences.Pick one cell consistently. Conventional + 4 atoms gives the textbook absences; primitive + 1 atom does not.
Forgetting the form-factor angle dependencePredicted high-angle peak intensities are 5–10× too strong vs experiment.Use tabulated f(sinθ/λ) (Cromer-Mann coefficients) or pymatgen, not f = Z.
Treating |F|² as the only intensity factorPowder peak intensities disagree with experiment even for simple metals.Multiply by Lorentz, polarisation, multiplicity, and Debye-Waller. They are geometry, not chemistry.
Dropping a 2π or its signSelection rules invert (e.g. you predict FCC where the data is BCC).Verify with one known reflection (the (111) of any FCC element) before trusting your code.

Summary

  • Reciprocal lattice + structure factor = diffraction pattern. The lattice fixes the spot positions; the structure factor fixes the intensities.
  • The structure factor is a sum of complex arrows in the plane, one per atom. They can add (bright spot) or cancel (forbidden spot). Geometry-driven cancellations are systematic absences, the topic of the next section.
  • Three benchmark rules to keep in your head: simple cubic allows everything, BCC demands h+k+h+k+\ell even, FCC demands (h,k,)(h, k, \ell) all the same parity.
  • The detector responds to F2|F|^2, multiplied by Lorentz, polarisation, multiplicity, and Debye-Waller weights. The latter four are geometry; only F2|F|^2 carries the chemistry.
  • Twelve lines of NumPy reproduce every textbook selection rule. Pymatgen wraps the same primitive into a one-call XRD simulator that works directly on a VASP CONTCAR\texttt{CONTCAR}.
Section 3.6 Core Insight
"The reciprocal lattice tells you where a spot can sit. The structure factor tells you how brightly it shines — and which spots disappear altogether."
Coming next: Section 3.7 — Systematic Absences — where we turn the "F = 0" rules above into a complete catalogue of selection rules, and use the absences in a real diffractogram to fingerprint the space group of an unknown crystal.
Loading comments...