Polarized specular reflectometry with non-perfect polarizer and analyzer

In this example, we show how to perform a specular reflectometry simulation with polarized neutrons and both a non-perfect polarizer as well as analyzer. The example is inspired by and performed with parameters close to the ones in the paper by Devishvili et al.. This example is a saturated iron film on top of a MgO substrate. On top of the iron layer is a thin Pd cap layer.

We don’t explain the whole script in detail here, it combines all concepts that were introduced before in the polarized reflectometry section. Instrument resolution is simulated as explained in the ToF - Resolution effects example. Furthermore, a constant background is added:

simulation.setBackground( ba.ConstantBackground( 1e-7 ) )

For a more detailed explanation we refer to the example on adding a constant background.

The values for the efficiency of the polarizer and analyzer are taken from the above mentioned paper by Devishvili et al.:

polarizer_efficiency = 0.986
analyzer_efficiency  = 0.970

These values are used to initialize the polarizer and analyzer:

simulation.setBeamPolarization(polarization * polarizer_efficiency)
simulation.setAnalyzerProperties(analyzer, analyzer_efficiency, 0.5)

This setup is then utilized to simulate the four reflectivity channels

results_pp = run_simulation(polarization = R3(0, 1, 0),
                            analyzer     = R3(0, 1, 0),
                            polarizer_efficiency = polarizer_efficiency,
                            analyzer_efficiency  = analyzer_efficiency )
results_mm = run_simulation(polarization = R3(0, -1, 0),
                            analyzer     = R3(0, -1, 0),
                            polarizer_efficiency = polarizer_efficiency,
                            analyzer_efficiency  = analyzer_efficiency )

results_pm = run_simulation(polarization = R3(0,  1, 0),
                            analyzer     = R3(0, -1, 0),
                            polarizer_efficiency = polarizer_efficiency,
                            analyzer_efficiency  = analyzer_efficiency )
results_mp = run_simulation(polarization = R3(0, -1, 0),
                            analyzer     = R3(0,  1, 0),
                            polarizer_efficiency = polarizer_efficiency,
                            analyzer_efficiency  = analyzer_efficiency )

The computed reflectivity looks like this:

Reflectivity

Due to the different values for the polarizer and analyzer efficiency, we obtain different reflectivity curves for the two spin-flip channels. As one can verify, these results are in good agreement with the measurement as well as the simulations presented by Devishvili et al.

Here is the complete example:

 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
#!/usr/bin/env python3
"""
Realistic (imperfect) example for polarized reflectometry.
Sample contains a magnetic layer,
similar to Devishvili et al., Rev. Sci. Instrum. 84, 025112 (2013).
"""
import numpy
import matplotlib.pyplot as plt
import bornagain as ba
from bornagain import angstrom, ba_plot as bp, deg, R3
from math import sin, cos

def get_sample():
    # Materials
    Bmag = 1.6e6
    Bangle = 0 * deg
    B = R3(Bmag*sin(Bangle), Bmag*cos(Bangle), 0)
    vacuum = ba.MaterialBySLD("Vacuum", 0, 0)
    material_Pd = ba.MaterialBySLD("Pd", 4.0099e-6, 1.3019e-09)
    material_Fe = ba.MaterialBySLD("Fe", 8.0241e-06, 6.0448e-10, B)
    material_substrate = ba.MaterialBySLD("MgO", 5.9803e-06, 9.3996e-12)

    # Layers
    layer_vacuum = ba.Layer(vacuum)
    layer_Pd = ba.Layer(material_Pd, 120*angstrom)
    layer_Fe = ba.Layer(material_Fe, 1000*angstrom)
    layer_substrate = ba.Layer(material_substrate)

    roughness = ba.LayerRoughness(20*angstrom)

    # Multilayer
    sample = ba.MultiLayer()
    sample.addLayer(layer_vacuum)
    sample.addLayerWithTopRoughness(layer_Pd, roughness)
    sample.addLayerWithTopRoughness(layer_Fe, roughness)
    sample.addLayerWithTopRoughness(layer_substrate, roughness)

    return sample


def simulate(p_dir, a_dir, p_eff, a_eff, title):
    sample = get_sample()

    qzs = numpy.linspace(0.1, 1.5, 1500)
    distr = ba.DistributionGaussian(0., 1., 25, 4.)

    scan = ba.QzScan(qzs)
    scan.setAbsoluteQResolution(distr, 0.008)

    scan.setPolarization(p_dir*p_eff)
    scan.setAnalyzer(a_dir*a_eff)

    simulation = ba.SpecularSimulation(scan, sample)
    simulation.setBackground(ba.ConstantBackground(1e-7))

    result = simulation.simulate()
    result.setTitle(title)

    return result


if __name__ == '__main__':
    # polarizer and analyzer efficiencies
    p_eff = 0.986
    a_eff = 0.970

    results_pp = simulate(R3(0, +1, 0), R3(0, +1, 0), p_eff, a_eff, "$++$")
    results_pm = simulate(R3(0, +1, 0), R3(0, -1, 0), p_eff, a_eff, "$+-$")
    results_mp = simulate(R3(0, -1, 0), R3(0, +1, 0), p_eff, a_eff, "$-+$")
    results_mm = simulate(R3(0, -1, 0), R3(0, -1, 0), p_eff, a_eff, "$--$")

    results = [results_pp, results_pm, results_mp, results_mm]
    bp.plot_multicurve(results)
    bp.show_or_export()
auto/Examples/specular/MagneticLayerImperfect.py