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}$.

Scattering intensity

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


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

    # Materials
    particle_color = (0.86, 0.24, 0.18)
    particle_mat = ba.RefractiveMaterial("Particle", particle_color, 6e-5, 2e-08)
    substrate_color = (0.28, 0.57, 0.82)
    substrate_mat = ba.RefractiveMaterial("Substrate", substrate_color, 6e-06, 2e-08)
    vacuum = ba.Vacuum()

    # Particles
    ff = ba.Cylinder(4*nm, 5*nm)
    particle = ba.Particle(particle_mat, ff)

    # 2D lattices
    lattice = ba.BasicLattice2D(10*nm, 10*nm, 90*deg, 0)
    layout = ba.Paracrystal2D(particle, lattice, 0, 20000*nm, 20000*nm)
    layout.setIntegrationOverXi(True)
    profile_1 = ba.Profile2DCauchy(80*nm, 80*nm, 0)
    profile_2 = ba.Profile2DCauchy(80*nm, 80*nm, 0)
    layout.setProbabilityDistributions(profile_1, profile_2)

    # Layers
    layer_1 = ba.Layer(vacuum)
    layer_1.deposit2D(layout)
    layer_2 = ba.Layer(substrate_mat)

    # Sample
    sample = ba.Sample()
    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 = 200
    detector = ba.SphericalDetector(n, -2*deg, 2*deg, n, 0, 2*deg)
    simulation = ba.ScatteringSimulation(beam, sample, detector)
    return simulation


if __name__ == '__main__':
    sample = get_sample()
    ba.showSample3D(sample, sample_size=300*nm, seed=0)
    simulation = get_simulation(sample)
    result = simulation.simulate()
    bp.plot_datafield(result, unit_aspect=1)
    bp.plt.show()
auto/Examples/scatter2d/Paracrystal.py

Explanation

Similarly to the 2D crystal structure, the 2D paracrystal is used to model the scattering from particles positioned at regular intervals on a plane. The 2D paracrystal model, however, possesses 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.

Constructor

Create the lattice first, then construct the paracrystal from the particle and that lattice:

lattice = ba.BasicLattice2D(length1, length2, alpha, xi)
structure = ba.Paracrystal2D(
    particle, lattice, damping_length, domain_size_1, domain_size_2
)

Arguments:

length1, length2  # lattice-vector lengths, in nanometers
alpha             # angle between lattice vectors, in radians
xi                # lattice rotation with respect to the x axis, in radians
damping_length    # damping/coherence length, in nanometers
domain_size_1     # coherent-domain size along first lattice vector
domain_size_2     # coherent-domain size along second lattice vector

For square and hexagonal unit cells, use the convenience lattice classes:

lattice = ba.SquareLattice2D(lattice_constant, xi)
lattice = ba.HexagonalLattice2D(lattice_constant, xi)

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 equal to 0 means no damping-length correction.

Probability distributions

To account for next neighbor position uncertainty, assign probability distributions with setProbabilityDistributions(pdf1, pdf2).

profile_1 = ba.Profile2DCauchy(30*nm, 30*nm, 0)
profile_2 = ba.Profile2DCauchy(30*nm, 30*nm, 0)
structure.setProbabilityDistributions(profile_1, profile_2)

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:

ba.Profile2DCauchy(omega_x, omega_y, delta)
ba.Profile2DGauss(omega_x, omega_y, delta)
ba.Profile2DGate(omega_x, omega_y, delta)
ba.Profile2DTriangle(omega_x, omega_y, delta)
ba.Profile2DVoigt(omega_x, omega_y, eta, delta)

All distributions have parameters:

omega_x  # half-width along distribution x-axis, in nanometers
omega_y  # half-width along distribution y-axis, in nanometers
gamma    # angle between first lattice vector and distribution x-axis

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 2D paracrystal provides a way to calculate the scattering from a finite portion of the paracrystal using the setDomainSizes(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.

lattice = ba.SquareLattice2D(20*nm, 0)
structure = ba.Paracrystal2D(particle, lattice, 0, 0, 0)
structure.setProbabilityDistributions(
    ba.Profile2DCauchy(30*nm, 30*nm, 0),
    ba.Profile2DCauchy(30*nm, 30*nm, 0),
)
structure.setDomainSizes(10000*nm, 10000*nm)

Lattice-orientation averaging

The paracrystal 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 ignored and numeric integration will be performed for $\xi$ in the range 0 to 360 degrees. Averaging provides a convenient way of getting an isotropic structure at the cost of longer computation time.

structure.setIntegrationOverXi(True)

Particle density

The particle density is determined from the 2D lattice parameters. There is no separate particle-density setting for Paracrystal2D.