Beam Angualr Spread in Specular Simulations

This example demonstrates beam angular spread effects in reflectivity computations. It also offers a comparison with data generated using another well known code: GenX. Further information about reflectometry simulations can be found in the Reflectometry Simulation Tutorial.

The observed reflectometry signal can be affected either by a spread in the beam wavelength or in the incident angle.

In this example, a Gaussian distribution is used to spread the incident angle, with a standard deviation of $\sigma_{\alpha} = 0.01^{\circ}$.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120  """ An example of taking into account beam angular divergence and beam footprint correction in reflectometry calculations with BornAgain. """ import numpy as np import bornagain as ba from os import path # input parameters wavelength = 1.54 * ba.angstrom alpha_i_min = 0.0 * ba.deg # min incident angle, deg alpha_i_max = 2.0 * ba.deg # max incident angle, rad beam_sample_ratio = 0.01 # beam-to-sample size ratio # convolution parameters d_ang = 0.01 * ba.deg # spread width for incident angle n_sig = 3 # number of sigmas to convolve over n_points = 25 # number of points to convolve over # substrate (Si) si_sld_real = 2.0704e-06 # \AA^{-2} # layer parameters n_repetitions = 10 # Ni ni_sld_real = 9.4245e-06 # \AA^{-2} d_ni = 70 * ba.angstrom # Ti ti_sld_real = -1.9493e-06 # \AA^{-2} d_ti = 30 * ba.angstrom def get_sample(): # defining materials m_air = ba.MaterialBySLD("Air", 0.0, 0.0) m_ni = ba.MaterialBySLD("Ni", ni_sld_real, 0.0) m_ti = ba.MaterialBySLD("Ti", ti_sld_real, 0.0) m_substrate = ba.MaterialBySLD("SiSubstrate", si_sld_real, 0.0) air_layer = ba.Layer(m_air) ni_layer = ba.Layer(m_ni, d_ni) ti_layer = ba.Layer(m_ti, d_ti) substrate_layer = ba.Layer(m_substrate) multi_layer = ba.MultiLayer() multi_layer.addLayer(air_layer) for i in range(n_repetitions): multi_layer.addLayer(ti_layer) multi_layer.addLayer(ni_layer) multi_layer.addLayer(substrate_layer) return multi_layer def create_real_data(): """ Loading data from genx_angular_divergence.dat """ filepath = path.join(path.dirname(path.realpath(__file__)), "genx_angular_divergence.dat.gz") ax_values, real_data = np.loadtxt(filepath, usecols=(0, 1), skiprows=3, unpack=True) # translating axis values from double incident angle # to incident angle ax_values *= 0.5 return ax_values, real_data def get_simulation(scan_size=500): """ Returns a specular simulation with beam and detector defined. """ footprint = ba.FootprintFactorSquare(beam_sample_ratio) alpha_distr = ba.RangedDistributionGaussian(n_points, n_sig) scan = ba.AngularSpecScan(wavelength, scan_size, alpha_i_min, alpha_i_max) scan.setFootprintFactor(footprint) scan.setAbsoluteAngularResolution(alpha_distr, d_ang) simulation = ba.SpecularSimulation() simulation.setScan(scan) return simulation def run_simulation(): """ Runs simulation and returns it. """ sample = get_sample() simulation = get_simulation() simulation.setSample(sample) simulation.runSimulation() return simulation.result() def plot(results): """ :param results: :return: """ from matplotlib import pyplot as plt ba.plot_simulation_result(results, postpone_show=True) genx_axis, genx_values = create_real_data() plt.semilogy(genx_axis, genx_values, 'ko', markevery=300) plt.legend(['BornAgain', 'GenX'], loc='upper right') plt.show() if __name__ == '__main__': results = run_simulation() plot(results) 
BeamAngularDivergence.py