Mie Scattering#

Mie scattering is the scattering of light by spherical particles. It is named after the German physicist Gustav Mie. The Mie solution to Maxwell’s equations is an exact solution that describes the scattering of electromagnetic radiation by a sphere. Here we will discuss our integration (wrapper) of the pyMieScatt package, which is a Python implementation of the Mie solution.

We have built this wrapper for two main reasons:

  1. Reduce the complexity of calling the original package so integrations with data analysis is easier.

  2. The codification of data types in the interface. This also allows for Least Recently Used cache (lru_cache) to be used, which is a Python decorator that caches the results of a function, so if the function is called with the same arguments, the result is returned from the cache instead of calling the function again. This only works if the arguments types are hashable, so immutable.

The following imports are needed

import numpy as np

# particula imports
from particula.data.process import mie_bulk

Mie Coefficients: discretize_auto_mieq#

The discretize_auto_mieq function plays a critical role our interface with pyMieScatt, by computing Mie coefficients for a spherical particle. These coefficients are pivotal in understanding how light interacts with particles in the atmosphere, influencing phenomena such as visibility, climate change, and radiative forcing.

Function Overview#

This function utilizes the PyMieScatt library to derive several key efficiencies and factors for a single sphere, given its material properties, size, and the surrounding medium’s properties. By leveraging an LRU (Least Recently Used) cache, discretize_auto_mieq significantly enhances performance for repetitive calculations, storing up to 100,000 recent calls to avoid recalculating identical inputs.

Parameters#

  • m_sphere: Complex or real refractive index of the sphere. Real numbers can be used for non-absorbing materials, while complex numbers account for both the real and imaginary parts of the refractive index, representing absorption characteristics.

  • wavelength: Wavelength of the incident light, specified in nanometers (nm). This parameter is crucial as Mie scattering varies with wavelength, affecting how light is scattered or absorbed by particles.

  • diameter: Diameter of the spherical particle in nanometers (nm). Particle size relative to the wavelength influences scattering behavior, making this a key parameter in Mie theory.

  • m_medium (optional): Refractive index of the medium surrounding the particle, defaulting to 1.0 to represent a vacuum. This context is important for accurately modeling light-particle interactions in various environments.

Returns#

A tuple containing the calculated Mie efficiencies and parameters:

  • q_ext: Extinction efficiency, representing the fraction of light extinguished (either absorbed or scattered) by the particle.

  • q_sca: Scattering efficiency, indicating the fraction of light scattered by the particle.

  • q_abs: Absorption efficiency, showing the fraction of light absorbed by the particle.

  • g: Asymmetry factor, describing the average cosine of the scattering angle, which influences the directionality of scattering.

  • q_pr: Radiation pressure efficiency, quantifying the momentum transfer from the light to the particle, affecting particle movement.

  • q_back: Backscatter efficiency, indicating the fraction of light scattered in directions reverse to the incident light.

  • q_ratio: The ratio of backscatter to extinction efficiency, useful for understanding reflective properties.

# Calculate Mie coefficients for a non absorbing sphere
mie_coefficients = mie_bulk.discretize_auto_mieq(
    m_sphere=1.5,
    wavelength=550.0,
    diameter=200.0
)
# Calculate Mie coefficients for a absorbing sphere
mie_coefficients_abs = mie_bulk.discretize_auto_mieq(
    m_sphere=1.5 + 0.5j,
    wavelength=550.0,
    diameter=200.0
)

# Print the table header, with padding spaces
print(f"{'Property':<10} {'Non-absorbing Sphere':<25} {'Absorbing Sphere':<25}")
# Print each row of Q efficiencies
properties = ['Qext', 'Qsca', 'Qabs', 'g', 'Qpr', 'Qback', 'Qratio']
for i, prop in enumerate(properties):
    print(
        f"{prop:<10} {mie_coefficients[i]:<25} {mie_coefficients_abs[i]:<25}")
Property   Non-absorbing Sphere      Absorbing Sphere         
Qext       0.33811822921216034       1.638639216334929        
Qsca       0.33811822921216034       0.44129028057104036      
Qabs       0.0                       1.1973489357638887       
g          0.267185706667637         0.2920132136174058       
Qpr        0.2477778712028992        1.509776623367253        
Qback      0.23099105902557251       0.26574242780352036      
Qratio     0.6831665348650329        0.6021941554199726       

The mie_size_distribution Function#

The mie_size_distribution function extends the capabilities of single-particle Mie scattering calculations to entire particle size distributions, providing a comprehensive view of aerosol optical properties. This section focuses on the new variables introduced in this function, which enable it to handle distributions and offer various modes of computation.

New Variables Explained#

  • number_per_cm3: This array represents the number distribution of particles per cubic centimeter for each diameter in the size distribution. It’s crucial for calculating the collective optical properties of the particle ensemble, allowing for a more accurate representation of aerosol behavior in the atmosphere.

  • n_medium: The refractive index of the medium surrounding the particles, with a default value of 1.0, representing air or vacuum. This parameter is essential for adjusting the Mie scattering calculations based on the medium’s optical properties.

  • pms (Probability Mass Function): A boolean flag indicating whether the size distribution is provided in the form of a probability mass function. When True, it signifies that the number_per_cm3 array represents a binned distribution (sum of bins is total number), affecting how the bulk optical properties are computed. When False, the function assumes the array represents a continuous probability density function, where the area under the curve is equal to total particle number.

  • as_dict: This boolean flag determines the format of the function’s output. If set to True, the function returns a dictionary containing the calculated optical properties, providing a convenient structure for accessing specific values.

  • extinction_only: When set to True, this flag limits the calculations to only the extinction coefficient, simplifying the output for applications focused solely on particle extinction properties.

  • discretize: This flag enables the discretization of input parameters (m_sphere, wavelength, diameter) for potentially improved calculation stability and performance. Discretization can introduce computational errors by truncating the significant digits.

  • truncation_calculation: A boolean flag that, when True, activates the truncation of the scattering efficiency calculation. This adjustment is based on a multiple of the backscattering coefficient, addressing truncation errors inherent in certain measurement instruments.

  • truncation_b_sca_multiple: An optional float specifying the multiple of the scattering coefficient used for truncating the scattering efficiency. This parameter is required if truncation_calculation is True and is key to accurately correcting for instrument truncation effects.

Practical Implications#

These variables introduce flexibility and precision into aerosol optics modeling, allowing for detailed analysis of particle distributions under varying environmental conditions and measurement setups. By adjusting these parameters, we can simulate a wide range of atmospheric particles, enhancing our understanding of aerosol impacts on climate and air quality.

Note#

This is also where we deviate from pyMieScatt, as this is now not a wrapper of the same functions in the original package, but a new function that calls the underlining discretize_auto_mieq. We then calculate the results with more flexibility.

# Define the refractive index of the particles (complex for absorbing,
# real for non-absorbing)
m_sphere = 1.5 + 0.01j  # Example for slightly absorbing particles

# Define the wavelength of the incident light in nanometers
wavelength = 550.0

# Create a linearly spaced array of particle diameters in nanometers
# From 100 nm to 300 nm, 50 sizes
diameter_sizes = np.linspace(100.0, 500.0, 50)

# Simulate a number concentration for each particle size in #/cm³
# Decreasing concentration from 1000 to 500 #/cm³
number_per_cm3 = np.linspace(1000.0, 500.0, 50)

# Refractive index of the surrounding medium (e.g., air)
n_medium = 1.0


# Calculate the Mie scattering parameters for the given size distribution
mie_results = mie_bulk.mie_size_distribution(
    m_sphere=m_sphere,
    wavelength=wavelength,
    diameter=diameter_sizes,
    number_per_cm3=number_per_cm3,
    n_medium=n_medium,
    as_dict=True
)

# Print or process the Mie scattering results

for key, value in mie_results.items():
    print(f"{key:<8}: {value}")
b_ext   : 5024.182718003773
b_sca   : 4784.810191293376
b_abs   : 239.37252671039641
G       : 0.6715751320242712
b_pr    : 1810.8231820748451
b_back  : 657.8815183489642
b_ratio : 584.281702454577

Summary#

The provided code segments form a foundational framework for analyzing aerosol optics, specifically through the calculation of Mie scattering parameters. This framework includes:

  1. Discretization of Mie Coefficients (discretize_auto_mieq): This function computes essential Mie scattering parameters such as extinction, scattering, absorption efficiencies, the asymmetry factor, radiation pressure efficiency, backscatter efficiency, and the ratio of backscatter to extinction efficiency for spherical particles. It leverages the PyMieScatt library for calculations and optimizes performance with an LRU cache, effectively reducing computational overhead for repeated calculations.

  2. Mie Scattering for Size Distributions (mie_size_distribution): Extending the application to aerosol size distributions, this function calculates optical properties across a range of particle sizes. It supports various modes of operation, including discretization of input parameters for improved computational performance and optional truncation of scattering efficiencies. The function can output results as either a dictionary or a tuple, accommodating different analytical needs.

  3. Example Usage with Linearly Spaced Size Distribution: Demonstrated how to apply the mie_size_distribution function to a linearly spaced array of particle diameters, simulating a realistic aerosol size distribution. This example showcases how to generate a size distribution, calculate Mie scattering parameters for it, and then access these parameters for further analysis.

Building Blocks for Advanced Analysis#

These components serve as critical building blocks for more advanced analyses, particularly in studying the next section: Humidified Particle Scattering. In real atmospheric conditions, aerosol particles often undergo hygroscopic growth, absorbing water from the air and increasing in size. This water uptake significantly affects the optical properties of aerosols, influencing their scattering and absorption behaviors and, consequently, their impact on climate and visibility.

The code and methodologies discussed provide a starting point for such advanced analyses, enabling the exploration of how aerosol optical properties change with humidity. This understanding is crucial for accurately assessing aerosols’ environmental and climatic impacts, highlighting the importance of these computational tools in atmospheric sciences.

help(mie_bulk.discretize_auto_mieq)
Help on _lru_cache_wrapper in module particula.data.process.mie_bulk:

discretize_auto_mieq(m_sphere: Union[complex, float], wavelength: float, diameter: float, m_medium: float = 1.0) -> Tuple[float, ...]
    Computes Mie coefficients for a spherical particle based on its material
    properties, size, and the properties of the surrounding medium.
    
    This function leverages the PyMieScatt library to calculate the extinction
    (q_ext), scattering (q_sca), absorption (q_abs) efficiencies, the
    asymmetry factor (g), radiation pressure efficiency (q_pr), backscatter
    efficiency (q_back), and the ratio of backscatter to extinction efficiency
    (q_ratio) for a single sphere under specified conditions.
    
    This function is optimized with an LRU (Least Recently Used) cache to
    enhance performance by storing up to 100,000 recent calls. The cache
    memorizes the results of expensive function calls and returns the cached
    result when the same inputs occur again, reducing the need to recompute
    these values.
    
    Args
    ----------
    m_sphere : The complex refractive index of the sphere. For non-absorbing
        material a real number can be provided.
    wavelength : The wavelength of the incident light in nanometers (nm).
    diameter : The diameter of the sphere in nanometers (nm).
    mMedium : The refractive index of the surrounding medium.
        Defaults to 1.0, corresponding to vacuum.
    
    Returns
    -------
    Tuple[float, float, float, float, float, float, float]
        A tuple containing the calculated Mie efficiencies and parameters:
        q_ext (extinction efficiency), q_sca (scattering efficiency),
        q_abs (absorption efficiency), g (asymmetry factor),
        q_pr (radiation pressure efficiency), q_back (backscatter efficiency),
        and q_ratio (the ratio of backscatter to extinction efficiency).
help(mie_bulk.mie_size_distribution)
Help on function mie_size_distribution in module particula.data.process.mie_bulk:

mie_size_distribution(m_sphere: Union[complex, float], wavelength: float, diameter: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], number_per_cm3: numpy.ndarray[typing.Any, numpy.dtype[numpy.float64]], n_medium: float = 1.0, pms: bool = True, as_dict: bool = False, extinction_only: bool = False, discretize: bool = False, truncation_calculation: bool = False, truncation_b_sca_multiple: Optional[float] = None) -> Union[numpy.ndarray[Any, numpy.dtype[numpy.float64]], dict[str, numpy.ndarray[Any, numpy.dtype[numpy.float64]]], Tuple[numpy.ndarray[Any, numpy.dtype[numpy.float64]], ...]]
    Calculates Mie scattering parameters for a size distribution of spherical
    particles.
    
    This function computes optical properties such as extinction, scattering,
    absorption coefficients, asymmetry factor, backscatter efficiency, and
    their ratios for a given size distribution of spherical particles. It
    supports various modes of calculation, including discretization of input
    parameters and optional truncation of the scattering efficiency.
    
    Parameters
    ----------
    m_sphere : Union[complex, float]
        The complex refractive index of the particles. Real values can be used
        for non-absorbing materials.
    wavelength : float
        The wavelength of the incident light in nanometers (nm).
    diameter : NDArray[np.float64]
        An array of particle diameters in nanometers (nm).
    number_per_cm3 : NDArray[np.float64]
        The number distribution of particles per cubic centimeter (#/cm^3).
    n_medium : float, optional
        The refractive index of the medium. Defaults to 1.0 (air or vacuum).
    pms : bool, optional
        Specifies if the size distribution is in probability mass form.
    as_dict : bool, optional
        If True, results are returned as a dictionary. Otherwise, as a tuple.
    extinction_only : bool, optional
        If True, only the extinction coefficient is calculated and returned.
    discretize : bool, optional
        If True, input parameters (m, wavelength, dp) are discretized for
        computation. Defaults to False.
    truncation_calculation : bool, optional
        Enables truncation of the scattering efficiency based on a multiple
        of the backscattering coefficient. Defaults to False.
    truncation_b_sca_multiple : Optional[float], optional
        The multiple of the backscattering coefficient used for truncating the
        scattering efficiency. Required if `truncation_calculation` is True.
    
    Returns
    -------
    Union[float, Dict[str, float], Tuple[float, ...]]
        Depending on the parameters `asDict` and `extinction_only`, the
        function can return:
        - A single float (extinction coefficient) if `extinction_only` is True.
        - A dictionary of computed optical properties if `asDict` is True.
        - A tuple of computed optical properties.
    
    Raises
    ------
    ValueError
        If `truncation_calculation` is True but `truncation_b_sca_multiple`
        is not specified.