Magnetic particles

This tutorial demonstrates how to include particles with non-zero magnetization.

As an example we are going to use magnetic spherical particles embedded in the substrate of a simple 2-layer system. We will simulate this sample with a polarized beam and use polarization analysis to focus on the spin-flip channel.

Creating materials with magnetization density

Magnetic materials in BornAgain are defined by their refractive index, as for non-mangetic materials, and the magnetization density vector, given in units of A/m. The following code first defines the magnetization density vector and then creates a material with this magnetization.

# Magnetization of the particle's material (A/m)
magnetization_particle = ba.kvector_t(0.0, 0.0, 1e7)
particle_material = ba.HomogeneousMaterial("Particle", 2e-5, 4e-7,
                                           magnetization_particle)

Using the magnetic material for a particle

A magnetic material can be used just as a non-magnetic one when defining particles or layers. For the spherical particle of this example, we use the following code to define it.

# spherical magnetic particle
sphere_ff = ba.FormFactorFullSphere(5*nm)
sphere = ba.Particle(particle_material, sphere_ff)

Defining a polarized beam and polarization analysis

When magnetic materials are present, some of the scattering may appear as spin-flip scattering. This contribution to the scattering can be isolated during an experiment by using a polarized beam and using polarization analysis at the detector.

The polarization state of the beam is fully defined by its Bloch vector, which points in the preferred direction of the neutron's spin and whose size determines if the neutron is in a mixed or pure state. In this example, we will define a pure state for the neutron, with spin pointing in the positive z-axis.

# define the beam polarization state
beampol = ba.kvector_t(0.0, 0.0, 1.0)
simulation.setBeamPolarization(beampol)

Polarization analysis is defined in BornAgain by the direction along which the spin will be analyzed, the efficiency of the analyzer and the total transmission.

In this example, we will define the analysis to be in negative z-direction to gain information on the spin-flip channel. We set the efficiency to 1 and the total transmission to 0.5.

# define the polarization analysis properties
analyzer_dir = ba.kvector_t(0.0, 0.0, -1.0)
simulation.setAnalyzerProperties(analyzer_dir, 1.0, 0.5)

Complete example

The full example embeds the previously defined spherical particle inside the substrate and simulates the spin-flip channel along the z-axis.

"""
Simulation demo: magnetic spheres in substrate
"""
import bornagain as ba
from bornagain import deg, angstrom, nm


# Magnetization of the particle's material (A/m)
magnetization_particle = ba.kvector_t(0.0, 0.0, 1e7)


def get_sample():
    """
    Returns a sample with magnetic spheres in the substrate.
    """
    # defining materials
    particle_material = ba.HomogeneousMaterial("Particle", 2e-5, 4e-7,
                                               magnetization_particle)
    air_material = ba.HomogeneousMaterial("Air", 0.0, 0.0)
    substrate_material = ba.HomogeneousMaterial("Substrate", 7e-6, 1.8e-7)

    # spherical magnetic particle
    sphere_ff = ba.FormFactorFullSphere(5*nm)
    sphere = ba.Particle(particle_material, sphere_ff)
    position = ba.kvector_t(0.0, 0.0, -10.0*nm)
    particle_layout = ba.ParticleLayout()
    particle_layout.addParticle(sphere, 1.0, position)

    # defining layers
    air_layer = ba.Layer(air_material)
    substrate_layer = ba.Layer(substrate_material)
    substrate_layer.addLayout(particle_layout)

    # defining the multilayer
    multi_layer = ba.MultiLayer()
    multi_layer.addLayer(air_layer)
    multi_layer.addLayer(substrate_layer)

    return multi_layer


def get_simulation():
    """
    Returns a GISAXS simulation with beam and detector defined
    """
    simulation = ba.GISASSimulation()
    simulation.setDetectorParameters(200, -3.0*deg, 3.0*deg, 200, 0.0*deg, 6.0*deg)
    simulation.setBeamParameters(1.*angstrom, 0.5*deg, 0.0*deg)
    simulation.setBeamIntensity(1e12)

    analyzer_dir = ba.kvector_t(0.0, 0.0, -1.0)
    beampol = ba.kvector_t(0.0, 0.0, 1.0)
    simulation.setBeamPolarization(beampol)
    simulation.setAnalyzerProperties(analyzer_dir, 1.0, 0.5)

    return simulation


def run_simulation():
    """
    Runs simulation and returns intensity map.
    """
    simulation = get_simulation()
    simulation.setSample(get_sample())
    simulation.runSimulation()
    return simulation.getIntensityData()


if __name__ == '__main__':
    result = run_simulation()
    ba.plot_intensity_data(result)