Refactoring #2462

Envelope task #2419: Polarized reflectivity

Split calculations into a computation and measurement step

Added by rbeerwerth about 1 month ago.

Status:NewStart date:03 Jun 2020
Priority:NormalDue date:
Assignee:-% Done:


Target version:-


For polarized reflectometry the computation can conceptionally be split into two successive parts.
The first step is to calculate the transmitted and reflected amplitudes in every layer of the sample with the usual back-propagation.
In the second step then the density matrices for the incoming beam and the analyzing polarized are constructed and applied to the result in order to compute the intensity seen in the experiment.
The first step is the one that is potentially expensive (for large numbers of layers).
In the implementation, the intensity (second step) is computed in SpecularMatrixTerm::intensity, while the polarization and analyzer properties are not needed at all in the computation of the amplitudes.
Also this step is very cheap. For this reason one computation of the amplitudes could be reused to compute intensities for an arbitrary amount of different combinations of polarization and analyzer, providing a potentially significant gain in performance.

For example, in the BasicPolarizedReflectometry example, this refactoring would cut the computational cost by half:

results_pp = run_simulation(ba.kvector_t(0.0, 1.0, 0.0),
                            ba.kvector_t(0.0, 1.0, 0.0))
results_mm = run_simulation(ba.kvector_t(0.0, -1.0, 0.0),
                            ba.kvector_t(0.0, -1.0, 0.0))

These lines run two subsequent computations that are virtually identical, except the evaluation of the density matrix for the computation of the intensity.
This step is for most real-world examples probably less than 1% of the total cost.

This will probably apply similarly also to polarized GISAS, and requires rather involved refactoring possibly taking more hurdles into account.

Also available in: Atom PDF