2D Paracrystal

Scattering from monodisperse cylinders distributed along a two-dimensional square paracrystal.

  • The particles are cylinders with constant radii and heights equal to $5$ nm.
  • They are deposited on a substrate, following a two-dimensional square paracrystalline pattern.
  • This 2D paracrystal is characterized by:
    • a lattice length of $20$ nm along both axes of the reference Cartesian frame,
    • a damping length equal to $0$,
    • “coherent’ domains with a size of $20$ $\mu$m along the axes of the reference Cartesian frame.
  • The incident beam is characterized by a wavelength of 0.1 nm and angles $\alpha_i = 0.2 ^{\circ}$ and $\varphi_i = 0^{\circ}$.

Note:

A damping length is used to introduce finite size effects by applying a multiplicative coefficient equal to $exp \left(-\frac{peak\_distance}{damping\_length}\right)$ to the Fourier transform of the probability densities. $damping\_length$ is equal to $0$ by default and, in this case, no correction is applied.

Intensity image

 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
#!/usr/bin/env python3
"""
2D paracrystal
"""
import bornagain as ba
from bornagain import ba_plot as bp, deg, nm


def get_sample():
    """
    Returns a sample with cylinders on a substrate, forming a 2D paracrystal
    """

    # Define materials
    material_Particle = ba.RefractiveMaterial("Particle", 0.0006, 2e-08)
    material_Substrate = ba.RefractiveMaterial("Substrate", 6e-06, 2e-08)
    material_Vacuum = ba.RefractiveMaterial("Vacuum", 0, 0)

    # Define form factors
    ff = ba.Cylinder(4*nm, 5*nm)

    # Define particles
    particle = ba.Particle(material_Particle, ff)

    # Define 2D lattices
    lattice = ba.BasicLattice2D(10*nm, 10*nm, 90*deg, 0)

    # Define interference functions
    iff = ba.Interference2DParacrystal(lattice, 0, 20000*nm, 20000*nm)
    iff.setIntegrationOverXi(True)
    iff_pdf_1 = ba.Profile2DCauchy(1*nm, 1*nm, 0)
    iff_pdf_2 = ba.Profile2DCauchy(1*nm, 1*nm, 0)
    iff.setProbabilityDistributions(iff_pdf_1, iff_pdf_2)

    # Define particle layouts
    layout = ba.ParticleLayout()
    layout.addParticle(particle)
    layout.setInterference(iff)
    layout.setTotalParticleSurfaceDensity(0.01)

    # Define layers
    layer_1 = ba.Layer(material_Vacuum)
    layer_1.addLayout(layout)
    layer_2 = ba.Layer(material_Substrate)

    # Define sample
    sample = ba.MultiLayer()
    sample.addLayer(layer_1)
    sample.addLayer(layer_2)

    return sample


def get_simulation(sample):
    beam = ba.Beam(1e9, 0.1*nm, 0.2*deg)
    n = bp.simargs['n']
    detector = ba.SphericalDetector(n, -2*deg, 2*deg, n, 0, 2*deg)
    simulation = ba.ScatteringSimulation(beam, sample, detector)
    return simulation


if __name__ == '__main__':
    bp.parse_args(sim_n=200)
    sample = get_sample()
    simulation = get_simulation(sample)
    result = simulation.simulate()
    bp.plot_simulation_result(result)
Examples/scatter2d/Interference2DParacrystal.py

Explanation

Similarly to the 2D interference function, the 2D paracrystal is used to model the scattering from particles positioned at some regular intervals on a plane. However, the 2D paracrystal model posesses only short range order. The disorder is cumulative at further distance.

The plot above represents a schematic view of the 2D paracrystal. Each circle on the plot represents an area where the probability to find a particle, given a particle at the origin, is above some arbitrary threshold. The growing size of the areas emphasizes the fact that our knowledge about the next neighbor’s location decreases with the distance to the origin.

The two-dimensional paracrystal model in BornAgain is implemented as a simple convolution of two one-dimensional paracrystals along the lattice basis directions.

The user defines lattice constants and provides probability distributions of the first neighbor along each of two lattice axes. On the plot above, these distributions are marked $P_a$ and $P_b$ and are represented by two circles of same size. The probability distributions of finding other particles along lattice vectors will be deduced from accumulating position uncertainties of previous particles towards the origin. In the general case, $P_a$ and $P_b$ can have different sizes and have different orientation with respect to the lattice axes.

The BornAgain user manual (Chapter 3.5, Paracrystal) details the theoretical model and gives some links to the literature.

Interference2DParacrystal constructor

The interference is created using its constructor.

Interference2DParacrystal(length1, length2, alpha, xi = 0.0, damping_length = 0.0)
"""
length1, length2 : lengths of the lattice cell, in nanometers
alpha            : angle between lattice vectors, in radians
xi               : rotation angle of the lattice with respect to the x-axis, in radians
damping_length   : The damping (coherence) length of the paracrystal in nanometers.
"""

length1 and length2 are lengths of lattice vectors $a$, $b$ expressed in nanometers (see plot below). alpha is the angle between the lattice basis vectors $a$, $b$ in direct space (in radians). xi is the angle defining the lattice orientation . It is taken as the angle between the first lattice basis vector and the x-axis of the reference cartesian frame. It is expressed in radians and set to 0 by default.

When the beam azimuthal angle $\varphi_f$ is zero, the beam direction coincides with x-axis of the reference frame, so angle $\xi$ can be considered as the lattice rotation with respect to the beam.

The parameter damping_length is used to introduce finite size effects by applying a multiplicative coefficient equal to exp(-lattice_constant/damping_length) to the Fourier transform of the probability density of a nearest neighbor. damping_length is equal to 0 by default and, in this case, no correction is applied. On the plot above the damping length is provisionally depicted as an area contributing to the scattering.

Probability distributions

To account for next neighbor position uncertainty a probability distribution should be assigned to the interference function. This is done using the setProbabilityDistribution(pdf1, pdf2) method of the 2d paracrystal object, with pdf1,2 related to each main axis of the paracrystal.

The probability distribution is parameterized with its type, size and orientation with respect to the lattice vector. $x_d$, $y_d$ on the plot below represent an orthonormal coordinate system of the distribution in real space which is rotated by the angle gamma with respect to the lattice vector. pdf1 is defined for lattice vector $a$, and pdf2 for lattice vector $b$.

The following PDF distributions are available

# Fourier transform of Cauchy-Lorentzian
FTDistribution2DCauchy(omega_x, omega_y, delta=0)

# Fourier transform of a Gaussian
FTDistribution2DGauss(omega_x, omega_y, delta=0)

# Fourier transform of a gate distribution
FTDistribution2DGate(omega_x, omega_y, delta=0)

# Fourier transform of a triangle distribution
FTDistribution2DTriangle(omega_x, omega_y, delta=0)

# Fourier transform of a pseudo-Voigt distribution: eta*Gauss + (1-eta)*Cauchy
FTDistribution2DVoigt(omega_x, omega_y, eta, delta=0)

All distributions have parameters

omega_x  : half-width of the distribution along its x-axis in nanometers
omega_y  : half-width of the distribution along its y-axis in nanometers
gamma    : angle in direct space between first lattice vector and x-axis of the distribution

In the case of the Voigt distribution, an additional dimensionless parameter eta is used to balance between Gaussian and Cauchy profiles.

Sizes of coherence domains

The interference function of a 2D paracrystal provides a way to calculate the scattering from a finite portion of the paracrystal using the setDomainSize(size1, size2) method. Here size1, size2 are given in nanometers and represent the sizes of the coherence domains in the first and second lattice directions.

The resulting behaviour is similar to the case when damping_length is used (the difference in computation is explained in the user manual). In the code snippet below, the paracrystal is created without specifying the damping_length (i.e. to rely on its default value 0), and then the setDomainSize method is used to introduce the alternative mechanism for finite size corrections.

iff = Interference2DParacrystal(20.0*nm, 20.0*nm, 90.0*deg)
iff.setProbabilityDistribution(FTDistribution2DCauchy(30.0*nm), FTDistribution2DCauchy(30.0*nm))
iff.setDomainSize(10000*nm, 10000*nm)

Convenience functions

Two convenience functions allow to create square and hexagonal paracrystals without the need to specify the second lattice vector and the lattice angle.

# interference function of a square lattice
Interference2DParacrystal.createSquare(lattice_constant, damping_length=0, domain_size1=0, domain_size2=0)

# interference function of a hexagonal lattice
Interference2DLattice.createHexagonal(lattice_constant, damping_length=0, domain_size1=0, domain_size2=0)

Particle density

The computational kernel provides an automatic calculation of particle densities using the parameters of the 2D lattice. This means that the user’s settings of particle densities via the ParticleLayout.setParticleDensity() method (which is a required step in the case of a radial paracrystal interference function) is ignored. Averaging over lattice rotation angle.

The paracrystal 2D interference function can be averaged over all azimuthal angles $\xi$ using the setIntegrationOverXi(True) method. In this case the initial lattice rotation angle $\xi$, if set, will be ingnored and numeric integration will be performed for $\xi$ in the range 0, 360 degrees. Averaging provides a convenient way of getting an isotropic interference function for the cost of bigger computational time.