### Polarized reflectometry without analyzer

Starting from the spin-flip tutorial, we want to remove the analyzer and perform a reflectivity simulation with incident polarized neutrons and no polarization analysis of the reflected beam. All other parameters of the simulation remain unchanged.

Omitting the polarization analysis corresponds to summing up the spin-flip and non-spin-flip channels for both incident polarization states: $$I^+ = I^{++} + I^{+-} \hspace{2em} I^- = I^{- -} + I^{-+}$$

In a script, these two polarization measurements can be computed according to:

r_plus  = results_pp + results_pm
r_minus = results_mm + results_mp

Here, results_pp, results_mm are the reflectivities in the non-spin-flip channels computed by calling

q, results_pp = run_simulation(ba.kvector_t(0,  1, 0),
ba.kvector_t(0,  1, 0))
q, results_mm = run_simulation(ba.kvector_t(0, -1, 0),
ba.kvector_t(0, -1, 0))

and the spin-flip channels are computed by

q, results_pm = run_simulation(ba.kvector_t(0,  1, 0),
ba.kvector_t(0, -1, 0))
q, results_mp = run_simulation(ba.kvector_t(0, -1, 0),
ba.kvector_t(0,  1, 0))

However, this approach has the disadvantage that it requires to perform four simulations in order to compute the two reflectivity curves. Instead, BornAgain supports the direct computation of the two channels for incident polarized neutrons without polarization analysis. This can simply be achieved by not specifying any analyzer when setting up the simulation object and hence omitting the line

simulation.setAnalyzerProperties(analyzer, 1.0, 0.5)

In this example, this is achieved by calling the run_simulation function for up and down polarization of the incident neutron beam as follows:

q, results_p = run_simulation(ba.kvector_t(0,  1, 0))
q, results_m = run_simulation(ba.kvector_t(0, -1, 0))

The attached script computes the two channels with both approaches and plots the results. It is then easy to check that they are identical. This is the resulting plot that shows the computed reflectivity for up and down polarization of the incident neutrons:

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 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  #!/usr/bin/env python3 """ An example of computing splin-flip reflectivity from a magnetized sample. """ import numpy import matplotlib.pyplot as plt import bornagain as ba from bornagain import angstrom, deg, nm, nm2, kvector_t from math import sqrt def get_sample(): """ Defines sample and returns it """ # Define materials material_Ambient = ba.MaterialBySLD("Ambient", 0, 0) h = 1e8 magnetic_field = kvector_t(1/2*h, sqrt(3)/2*h, 0) material_Layer = ba.MaterialBySLD("Layer", 0.0001, 1e-08, magnetic_field) material_Substrate = ba.MaterialBySLD("Substrate", 7e-05, 2e-06) # Define layers layer_1 = ba.Layer(material_Ambient) layer_2 = ba.Layer(material_Layer, 10*nm) layer_3 = ba.Layer(material_Substrate) # Define sample sample = ba.MultiLayer() sample.addLayer(layer_1) sample.addLayer(layer_2) sample.addLayer(layer_3) return sample def get_simulation(sample, scan_size=500): """ Defines and returns a specular simulation. """ simulation = ba.SpecularSimulation() scan = ba.AngularSpecScan(1.54*angstrom, scan_size, 0, 5*deg) simulation.setScan(scan) simulation.setSample(sample) return simulation def run_simulation(polarization=ba.kvector_t(0, 1, 0), analyzer=None): """ Runs simulation and returns its result. """ sample = get_sample() simulation = get_simulation(sample) # adding polarization and analyzer operator simulation.beam().setPolarization(polarization) if analyzer: simulation.detector().setAnalyzerProperties(analyzer, 1, 0.5) simulation.runSimulation() result = simulation.result() return result.axis(), result.array() def plot(axis, data, labels): plt.figure() for d, l in zip(data, labels): plt.semilogy(axis, d, label=l, linewidth=1) plt.legend(loc='upper right') plt.gca().yaxis.set_ticks_position('both') plt.gca().xaxis.set_ticks_position('both') plt.xlabel(r"$\alpha_i$ [deg]") plt.ylabel("Reflectivity") plt.tight_layout() if __name__ == '__main__': q, results_pp = run_simulation(ba.kvector_t(0, 1, 0), ba.kvector_t(0, 1, 0)) q, results_mm = run_simulation(ba.kvector_t(0, -1, 0), ba.kvector_t(0, -1, 0)) q, results_pm = run_simulation(ba.kvector_t(0, 1, 0), ba.kvector_t(0, -1, 0)) q, results_mp = run_simulation(ba.kvector_t(0, -1, 0), ba.kvector_t(0, 1, 0)) r_plus = results_pp + results_pm r_minus = results_mm + results_mp plot(q, [r_plus, r_minus], ["$+$", "$-$"]) # same result, but need half the computational time q, results_p = run_simulation(ba.kvector_t(0, 1, 0)) q, results_m = run_simulation(ba.kvector_t(0, -1, 0)) plot(q, [results_p, results_m], ["$+$", "$-$"]) plt.show() 
PolarizedNoAnalyzer.py