\(\renewcommand\AA{\unicode{x212B}}\)

MultipleScatteringCorrection v1

../_images/MultipleScatteringCorrection-v1_dlg.png

MultipleScatteringCorrection dialog.

Summary

Calculate Multiple Scattering Correction using numerical integration with the assumption of sample only, elastic scattering only, and isotropic scattering within the sample.

Properties

Name Direction Type Default Description
InputWorkspace Input MatrixWorkspace Mandatory The X values for the input workspace must be in units of wavelength
NumberOfWavelengthPoints Input number Optional The number of wavelength points for which the numerical integral is calculated (default: all points)
ElementSize Input number 1 The size of one side of an integration element cube in mm
OutputWorkspace Output WorkspaceGroup Mandatory Output workspace name. A Workspace2D containing the correction matrix that can be directly applied to the corresponding Event workspace for multiple scattering correction.

Description

This algorithm uses numerical integration to approximate the sample correction factor for multiple scattering events using the formula detailed in the concept page of Absorption and Multiple Scattering Corrections. Currently, the multiple scattering correction is only implemented for the sample, and the interaction terms between samples and containers will be implemented at a later time.

Here is a quick recap of the physical model used in the numerical integration. The scattered neutron can bounce into another atom before leaving the sample when the sample is sufficiently thick, leading to a double scattering event.

MultipleScatteringVolume.png

With the assumption of elastic and isotropic scattering as well as the approximation where we assume the intensity ratio between incoming and outgoing neutron are a fixed value, the multiple scattering intensity can be expressed as

(1)\[I_{m} = I_{total} \frac{\rho \sigma_{s} A_{2}}{4 \pi A_{1}}\]

where \(I_{total}\) is the measured intensity, \(\rho\) is the effective number density, and \(\sigma_{s}\) is the total scattering cross section. The term \(A_{1}\) is a function of wavelength, and can be defined as

(2)\[A_{1}(\lambda) = \int_V exp[-\mu(\lambda)(l_1 + l_2)] dV\]

where \(\mu\) is the sample absorption coefficient (a function of wavelength), \(l_1\) is the distance from source to scattering volume one, and \(l_2\) is the distance from volume two to the detector. Similarly, \(A_{2}\) can be defined as

(3)\[A_2(\lambda) = \int_V\int_V\frac{exp[-\mu(\lambda)(l_1 + l_{12} + l_2)]}{l_{12}^2}dVdV\]

where \(l_{12}\) is the distance between volume one and volume two.

This algorithm uses a rasterizer internally to compute all the distances and angles, therefore it is crucial to have the instrument and sample geometry properly defined within the input workspace. Also, both \(l_1\) and \(l_{12}\) are pre-computed and cached as 1D vector, which tends to occupy a significant amount of memory when the selected element size is below the standard 1 mm. Some operating system will stop Mantid from claiming/reserving the memory, leading to a memory allocation error at the starting stage. This is a known limitation and we are actively searching for a solution.

Example

The following Python script generate a synthetic data set (instrument and sample) to show case the interface

def make_sample_workspace():
    # Create a fake workspace with TOF data
    sample_ws = CreateSampleWorkspace(Function='Powder Diffraction',
                                    NumBanks=4,
                                    BankPixelWidth=1,
                                    XUnit='TOF',
                                    XMin=1000,
                                    XMax=10000)
    # fake instrument
    EditInstrumentGeometry(sample_ws,
                        PrimaryFlightPath=5.0,
                        SpectrumIDs=[1, 2, 3, 4],
                        L2=[2.0, 2.0, 2.0, 2.0],
                        Polar=[10.0, 90.0, 170.0, 90.0],
                        Azimuthal=[0.0, 0.0, 0.0, 45.0],
                        DetectorIDs=[1, 2, 3, 4],
                        InstrumentName="Instrument")
    return sample_ws

def add_cylinder_sample_to_workspace(
        ws,
        material,
        number_density,
        mass_density,
        center_bottom_base=[0.0, 0.0, 0.0],  # x,y,z of bottom base of cylinder
        height=0.1,  # in meter
        radius=0.1,  # in meter
):
    SetSample(
        ws,
        Geometry={
            "Shape": "Cylinder",
            "centre-of-bottom-base": {
                "x": center_bottom_base[0],
                "y": center_bottom_base[1],
                "z": center_bottom_base[2],
            },
            "Height": height,
            "Radius": radius,
            "Axis": 1,
        },
        Material = {
            "ChemicalFormula": material,
            "SampleNumberDensity": number_density,
            "SampleMassDensity": mass_density,
        }
    )
    return ws

# use Mutliple scattering correction
def correction_multiple_scattering(sample_ws, unit="Wavelength"):
    ConvertUnits(InputWorkspace=sample_ws,
                OutputWorkspace=sample_ws,
                Target=unit,
                EMode="Elastic")
    rst = MultipleScatteringCorrection(sample_ws)
    return rst

# start
ws = make_sample_workspace()
ws = add_cylinder_sample_to_workspace(
    ws,
    "V",
    0.07261,
    6.11,
    [0.0, -0.0284, 0.0],
    0.00295,
    0.0568,
)
ms_multi = correction_multiple_scattering(ws)

Categories: AlgorithmIndex | CorrectionFunctions

Source

C++ header: MultipleScatteringCorrection.h (last modified: 2021-08-10)

C++ source: MultipleScatteringCorrection.cpp (last modified: 2021-08-11)