Bragg’s law: indexing powder XRD peaks#

Each line of a diffraction pattern is a family of \((hkl)\) planes that satisfies Bragg’s law \(n\lambda=2d\sin\theta\). powder_xrd_peaks() computes each reflection’s structure factor (structure_factor()) directly from atomic positions and Miller indices, so BCC’s and FCC’s systematic absences (reflections with zero intensity by symmetry) fall out automatically rather than being hardcoded as a rule.

import matplotlib.pyplot as plt
import numpy as np

from chemistrykit.crystal.systems.xrd import powder_xrd_peaks
from chemistrykit.crystal.visualizers.crystal_plots import plot_xrd_pattern

wavelength = 154.18  # Cu-Kalpha, pm

iron_bcc = powder_xrd_peaks("BCC", a=286.65, wavelength=wavelength, hkl_max=3)
copper_fcc = powder_xrd_peaks("FCC", a=361.5, wavelength=wavelength, hkl_max=3)
polonium_sc = powder_xrd_peaks("SC", a=336.0, wavelength=wavelength, hkl_max=2)

print("Fe (BCC) allowed reflections (h+k+l even only):")
for peak in iron_bcc:
    print(f"  {peak.hkl}  2theta={peak.two_theta:6.2f} deg  d={peak.d_spacing:6.2f} pm")

print("\nCu (FCC) allowed reflections (unmixed parity only):")
for peak in copper_fcc:
    print(f"  {peak.hkl}  2theta={peak.two_theta:6.2f} deg  d={peak.d_spacing:6.2f} pm")

print("\nalpha-Po (SC) allowed reflections (no absences):")
for peak in polonium_sc:
    print(f"  {peak.hkl}  2theta={peak.two_theta:6.2f} deg  d={peak.d_spacing:6.2f} pm")
Fe (BCC) allowed reflections (h+k+l even only):
  (1, 1, 0)  2theta= 44.71 deg  d=202.69 pm
  (1, 0, 1)  2theta= 44.71 deg  d=202.69 pm
  (0, 1, 1)  2theta= 44.71 deg  d=202.69 pm
  (2, 0, 0)  2theta= 65.08 deg  d=143.32 pm
  (0, 2, 0)  2theta= 65.08 deg  d=143.32 pm
  (0, 0, 2)  2theta= 65.08 deg  d=143.32 pm
  (2, 1, 1)  2theta= 82.41 deg  d=117.02 pm
  (1, 2, 1)  2theta= 82.41 deg  d=117.02 pm
  (1, 1, 2)  2theta= 82.41 deg  d=117.02 pm
  (2, 2, 0)  2theta= 99.04 deg  d=101.35 pm
  (2, 0, 2)  2theta= 99.04 deg  d=101.35 pm
  (0, 2, 2)  2theta= 99.04 deg  d=101.35 pm
  (3, 1, 0)  2theta=116.52 deg  d= 90.65 pm
  (3, 0, 1)  2theta=116.52 deg  d= 90.65 pm
  (1, 3, 0)  2theta=116.52 deg  d= 90.65 pm
  (1, 0, 3)  2theta=116.52 deg  d= 90.65 pm
  (0, 3, 1)  2theta=116.52 deg  d= 90.65 pm
  (0, 1, 3)  2theta=116.52 deg  d= 90.65 pm
  (2, 2, 2)  2theta=137.38 deg  d= 82.75 pm

Cu (FCC) allowed reflections (unmixed parity only):
  (1, 1, 1)  2theta= 43.35 deg  d=208.71 pm
  (2, 0, 0)  2theta= 50.49 deg  d=180.75 pm
  (0, 2, 0)  2theta= 50.49 deg  d=180.75 pm
  (0, 0, 2)  2theta= 50.49 deg  d=180.75 pm
  (2, 2, 0)  2theta= 74.19 deg  d=127.81 pm
  (2, 0, 2)  2theta= 74.19 deg  d=127.81 pm
  (0, 2, 2)  2theta= 74.19 deg  d=127.81 pm
  (3, 1, 1)  2theta= 90.03 deg  d=109.00 pm
  (1, 3, 1)  2theta= 90.03 deg  d=109.00 pm
  (1, 1, 3)  2theta= 90.03 deg  d=109.00 pm
  (2, 2, 2)  2theta= 95.25 deg  d=104.36 pm
  (3, 3, 1)  2theta=136.73 deg  d= 82.93 pm
  (3, 1, 3)  2theta=136.73 deg  d= 82.93 pm
  (1, 3, 3)  2theta=136.73 deg  d= 82.93 pm

alpha-Po (SC) allowed reflections (no absences):
  (1, 0, 0)  2theta= 26.53 deg  d=336.00 pm
  (0, 1, 0)  2theta= 26.53 deg  d=336.00 pm
  (0, 0, 1)  2theta= 26.53 deg  d=336.00 pm
  (1, 1, 0)  2theta= 37.87 deg  d=237.59 pm
  (1, 0, 1)  2theta= 37.87 deg  d=237.59 pm
  (0, 1, 1)  2theta= 37.87 deg  d=237.59 pm
  (1, 1, 1)  2theta= 46.83 deg  d=193.99 pm
  (2, 0, 0)  2theta= 54.63 deg  d=168.00 pm
  (0, 2, 0)  2theta= 54.63 deg  d=168.00 pm
  (0, 0, 2)  2theta= 54.63 deg  d=168.00 pm
  (2, 1, 0)  2theta= 61.73 deg  d=150.26 pm
  (2, 0, 1)  2theta= 61.73 deg  d=150.26 pm
  (1, 2, 0)  2theta= 61.73 deg  d=150.26 pm
  (1, 0, 2)  2theta= 61.73 deg  d=150.26 pm
  (0, 2, 1)  2theta= 61.73 deg  d=150.26 pm
  (0, 1, 2)  2theta= 61.73 deg  d=150.26 pm
  (2, 1, 1)  2theta= 68.39 deg  d=137.17 pm
  (1, 2, 1)  2theta= 68.39 deg  d=137.17 pm
  (1, 1, 2)  2theta= 68.39 deg  d=137.17 pm
  (2, 2, 0)  2theta= 80.92 deg  d=118.79 pm
  (2, 0, 2)  2theta= 80.92 deg  d=118.79 pm
  (0, 2, 2)  2theta= 80.92 deg  d=118.79 pm
  (2, 2, 1)  2theta= 86.99 deg  d=112.00 pm
  (2, 1, 2)  2theta= 86.99 deg  d=112.00 pm
  (1, 2, 2)  2theta= 86.99 deg  d=112.00 pm
  (2, 2, 2)  2theta=105.27 deg  d= 96.99 pm

BCC’s (100) reflection (h+k+l=1, odd) is absent – the first line is (110) instead. FCC’s (100) and (110) are both absent (mixed parity) – the first line is (111).

bcc_hkls = {p.hkl for p in iron_bcc}
fcc_hkls = {p.hkl for p in copper_fcc}
print(f"\n(100) present for BCC? {(1, 0, 0) in bcc_hkls}")
print(f"(110) present for BCC? {(1, 1, 0) in bcc_hkls}")
print(f"(100) present for FCC? {(1, 0, 0) in fcc_hkls}")
print(f"(111) present for FCC? {(1, 1, 1) in fcc_hkls}")
(100) present for BCC? False
(110) present for BCC? True
(100) present for FCC? False
(111) present for FCC? True

Every listed peak obeys Bragg’s law exactly – recover the wavelength from each peak’s d-spacing and angle, and the NaCl-style inverse problem (lattice constant from a measured angle) that the Braggs solved:

for peak in copper_fcc:
    lam = 2.0 * peak.d_spacing * np.sin(np.radians(peak.two_theta / 2.0))
    assert abs(lam - wavelength) < 1e-9
first = copper_fcc[0]
h, k, l = first.hkl
a_recovered = wavelength / (2.0 * np.sin(np.radians(first.two_theta / 2.0))) * np.sqrt(h * h + k * k + l * l)
print(f"\nCu lattice constant recovered from the (111) angle via Bragg's law: {a_recovered:.2f} pm")
Cu lattice constant recovered from the (111) angle via Bragg's law: 361.50 pm
fig, axes = plt.subplots(3, 1, figsize=(8, 8), sharex=True)
plot_xrd_pattern(iron_bcc, ax=axes[0])
axes[0].set_title("Fe (BCC)")
plot_xrd_pattern(copper_fcc, ax=axes[1])
axes[1].set_title("Cu (FCC)")
plot_xrd_pattern(polonium_sc, ax=axes[2])
axes[2].set_title("alpha-Po (SC)")
plt.tight_layout()
plt.show()
Fe (BCC), Cu (FCC), alpha-Po (SC)

Total running time of the script: (0 minutes 0.126 seconds)

Gallery generated by Sphinx-Gallery