Skip to content

particula.dynamics.coagulation.coagulation_rate

coagulation_rate

Coagulation rate calculations for particle populations.

This module defines discrete and continuous ways (via summation or integration) to compute the gain and loss terms in coagulation processes. Each function isolates specific calculation details, allowing for easier testing and flexibility in usage.

References
  • Seinfeld, J. H., & Pandis, S. N. (2016). Atmospheric chemistry and physics, Chapter 13, Equation 13.61.

get_coagulation_gain_rate_continuous

get_coagulation_gain_rate_continuous(radius: Union[float, NDArray[float64]], concentration: Union[float, NDArray[float64]], kernel: NDArray[float64]) -> Union[float, NDArray[np.float64]]

Calculate the coagulation gain rate via continuous integration.

This function converts the distribution to a continuous form, then uses RectBivariateSpline to interpolate and integrate:

  • gain_rate® = ∫ kernel(r, r') × concentration® × concentration(r') dr'

Parameters:

  • - radius

    The particle radius array [m].

  • - concentration

    The particle distribution.

  • - kernel

    Coagulation kernel matrix.

Returns:

  • Union[float, NDArray[float64]]
    • The coagulation gain rate, in the shape of radius.

Examples:

import numpy as np
import particula as par

r = np.array([1e-7, 2e-7, 3e-7])
conc = np.array([1.0, 0.5, 0.2])
kern = np.ones((3, 3)) * 1e-9

gain_cont = par.dynamics.get_coagulation_gain_rate_continuous(
    r, conc, kern
)
print(gain_cont)
References
  • Seinfeld, J. H., & Pandis, S. N. (2016). Atmospheric chemistry and physics, Chapter 13, Equation 13.61.
Source code in particula/dynamics/coagulation/coagulation_rate.py
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
def get_coagulation_gain_rate_continuous(
    radius: Union[float, NDArray[np.float64]],
    concentration: Union[float, NDArray[np.float64]],
    kernel: NDArray[np.float64],
) -> Union[float, NDArray[np.float64]]:
    """Calculate the coagulation gain rate via continuous integration.

    This function converts the distribution to a continuous form, then
    uses RectBivariateSpline to interpolate and integrate:

    - gain_rate(r) = ∫ kernel(r, r') × concentration(r) × concentration(r') dr'

    Arguments:
        - radius : The particle radius array [m].
        - concentration : The particle distribution.
        - kernel : Coagulation kernel matrix.

    Returns:
        - The coagulation gain rate, in the shape of radius.

    Examples:
        ```py
        import numpy as np
        import particula as par

        r = np.array([1e-7, 2e-7, 3e-7])
        conc = np.array([1.0, 0.5, 0.2])
        kern = np.ones((3, 3)) * 1e-9

        gain_cont = par.dynamics.get_coagulation_gain_rate_continuous(
            r, conc, kern
        )
        print(gain_cont)
        ```

    References:
        - Seinfeld, J. H., & Pandis, S. N. (2016). Atmospheric chemistry and
          physics, Chapter 13, Equation 13.61.
    """
    # continuous distribution, kernel (n,n)
    # outer replaces, concentration * np.transpose([concentration])
    interp = RectBivariateSpline(
        x=radius, y=radius, z=kernel * np.outer(concentration, concentration)
    )

    dpd = np.linspace(0, radius / 2 ** (1 / 3), radius.size)  # type: ignore
    dpi = (np.transpose(radius) ** 3 - dpd**3) ** (1 / 3)

    return radius**2 * np.trapezoid(
        interp.ev(dpd, dpi) / dpi**2,  # type: ignore
        dpd,
        axis=0,  # type: ignore
    )

get_coagulation_gain_rate_discrete

get_coagulation_gain_rate_discrete(radius: Union[float, NDArray[float64]], concentration: Union[float, NDArray[float64]], kernel: NDArray[float64]) -> Union[float, NDArray[np.float64]]

Calculate the coagulation gain rate (using a quasi-continuous approach).

Though named "discrete," this function converts the discrete distribution to a PDF and uses interpolation (RectBivariateSpline) to approximate the gain term. The concept is:

  • gain_rate® = ∫ kernel(r, r') × PDF® × PDF(r') dr' (implemented via numeric integration)

Parameters:

  • - radius

    The particle radius array [m].

  • - concentration

    The particle distribution.

  • - kernel

    Coagulation kernel matrix.

Returns:

  • Union[float, NDArray[float64]]
    • The coagulation gain rate, matched to the shape of radius.

Examples:

import numpy as np
import particula as par

r = np.array([1e-7, 2e-7, 3e-7])
conc = np.array([1.0, 0.5, 0.2])
kern = np.ones((3, 3)) * 1e-9

gain_val = par.dynamics.get_coagulation_gain_rate_discrete(
    r, conc, kern
)
print(gain_val)
References
  • Seinfeld, J. H., & Pandis, S. N. (2016). Atmospheric chemistry and physics, Chapter 13, Equation 13.61.
Source code in particula/dynamics/coagulation/coagulation_rate.py
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
def get_coagulation_gain_rate_discrete(
    radius: Union[float, NDArray[np.float64]],
    concentration: Union[float, NDArray[np.float64]],
    kernel: NDArray[np.float64],
) -> Union[float, NDArray[np.float64]]:
    """Calculate the coagulation gain rate (using a quasi-continuous approach).

    Though named "discrete," this function converts the discrete distribution
    to a PDF and uses interpolation (RectBivariateSpline) to approximate the
    gain term. The concept is:

    - gain_rate(r) = ∫ kernel(r, r') × PDF(r) × PDF(r') dr'
      (implemented via numeric integration)

    Arguments:
        - radius : The particle radius array [m].
        - concentration : The particle distribution.
        - kernel : Coagulation kernel matrix.

    Returns:
        - The coagulation gain rate, matched to the shape of radius.

    Examples:
        ```py
        import numpy as np
        import particula as par

        r = np.array([1e-7, 2e-7, 3e-7])
        conc = np.array([1.0, 0.5, 0.2])
        kern = np.ones((3, 3)) * 1e-9

        gain_val = par.dynamics.get_coagulation_gain_rate_discrete(
            r, conc, kern
        )
        print(gain_val)
        ```

    References:
        - Seinfeld, J. H., & Pandis, S. N. (2016). Atmospheric chemistry and
          physics, Chapter 13, Equation 13.61.
    """
    # Calculate bin widths (delta_x_array)
    # Handle Union type: ensure radius is an array for indexing
    if not isinstance(radius, np.ndarray):
        radius = np.asarray([radius])
    if not isinstance(concentration, np.ndarray):
        concentration = np.asarray([concentration])

    delta_x_array = np.diff(radius, append=2 * radius[-1] - radius[-2])

    # Convert concentration to a probability density function (PDF)
    concentration_pdf = concentration / delta_x_array

    # Prepare interpolation for continuous distribution
    interp = RectBivariateSpline(
        x=radius,
        y=radius,
        z=kernel * np.outer(concentration_pdf, concentration_pdf),
    )

    # Define dpd and dpi for integration
    # integration variable
    dpd = np.linspace(0, radius / 2 ** (1 / 3), radius.size)
    # adjusted for broadcasting
    dpi = (np.transpose(radius) ** 3 - dpd**3) ** (1 / 3)

    # Compute gain using numerical integration
    gain = radius**2 * np.trapezoid(interp.ev(dpd, dpi) / dpi**2, dpd, axis=0)  # type: ignore

    # Convert back to original scale (from PDF to PMF)
    return gain * delta_x_array

get_coagulation_loss_rate_continuous

get_coagulation_loss_rate_continuous(radius: Union[float, NDArray[float64]], concentration: Union[float, NDArray[float64]], kernel: NDArray[float64]) -> Union[float, NDArray[np.float64]]

Calculate the coagulation loss rate via continuous integration.

This method integrates the product of kernel and concentration over the radius grid. The equation is:

  • loss_rate® = concentration® × ∫ kernel(r, r') × concentration(r') dr'

Parameters:

  • - radius

    The particle radius array [m].

  • - concentration

    The particle distribution.

  • - kernel

    Coagulation kernel matrix (NDArray[np.float64]).

Returns:

  • Union[float, NDArray[float64]]
    • The coagulation loss rate.

Examples:

import numpy as np
import particula as par

r = np.array([1e-7, 2e-7, 3e-7])
conc = np.array([1.0, 0.5, 0.2])
kern = np.ones((3, 3)) * 1e-9

loss_cont = par.dynamics.get_coagulation_loss_rate_continuous(
    r, conc, kern
)
print(loss_cont)
References
  • Seinfeld, J. H., & Pandis, S. N. (2016). Atmospheric chemistry and physics, Chapter 13, Equation 13.61.
Source code in particula/dynamics/coagulation/coagulation_rate.py
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
def get_coagulation_loss_rate_continuous(
    radius: Union[float, NDArray[np.float64]],
    concentration: Union[float, NDArray[np.float64]],
    kernel: NDArray[np.float64],
) -> Union[float, NDArray[np.float64]]:
    """Calculate the coagulation loss rate via continuous integration.

    This method integrates the product of kernel and concentration over
    the radius grid. The equation is:

    - loss_rate(r) = concentration(r) × ∫ kernel(r, r') × concentration(r') dr'

    Arguments:
        - radius : The particle radius array [m].
        - concentration : The particle distribution.
        - kernel : Coagulation kernel matrix (NDArray[np.float64]).

    Returns:
        - The coagulation loss rate.

    Examples:
        ```py
        import numpy as np
        import particula as par

        r = np.array([1e-7, 2e-7, 3e-7])
        conc = np.array([1.0, 0.5, 0.2])
        kern = np.ones((3, 3)) * 1e-9

        loss_cont = par.dynamics.get_coagulation_loss_rate_continuous(
            r, conc, kern
        )
        print(loss_cont)
        ```

    References:
        - Seinfeld, J. H., & Pandis, S. N. (2016). Atmospheric chemistry and
          physics, Chapter 13, Equation 13.61.
    """
    # concentration (n,) and kernel (n,n)
    # Cast result to handle numpy return type
    # Using type: ignore for np.trapezoid return type compatibility
    return concentration * np.trapezoid(y=kernel * concentration, x=radius)  # type: ignore[operator,return-value]

get_coagulation_loss_rate_discrete

get_coagulation_loss_rate_discrete(concentration: Union[float, NDArray[float64]], kernel: NDArray[float64]) -> Union[float, NDArray[np.float64]]

Calculate the coagulation loss rate via a discrete summation approach.

This function computes the loss rate of particles from collisions by summing over all size classes. The equation is:

  • loss_rate = ΣᵢΣⱼ [kernel(i, j) × concentration(i) × concentration(j)]

Parameters:

  • - concentration

    The distribution of particles.

  • - kernel

    The coagulation kernel matrix (NDArray[np.float64]).

Returns:

  • Union[float, NDArray[float64]]
    • The coagulation loss rate (float or NDArray[np.float64]).

Examples:

import numpy as np
import particula as par

conc = np.array([1.0, 2.0, 3.0])
kern = np.ones((3, 3))
loss = par.dynamics.get_coagulation_loss_rate_discrete(conc, kern)
print(loss)
# Example output: 36.0
References
  • Seinfeld, J. H., & Pandis, S. N. (2016). Atmospheric chemistry and physics, Chapter 13, Equation 13.61.
Source code in particula/dynamics/coagulation/coagulation_rate.py
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
def get_coagulation_loss_rate_discrete(
    concentration: Union[float, NDArray[np.float64]],
    kernel: NDArray[np.float64],
) -> Union[float, NDArray[np.float64]]:
    """Calculate the coagulation loss rate via a discrete summation approach.

    This function computes the loss rate of particles from collisions by
    summing over all size classes. The equation is:

    - loss_rate = ΣᵢΣⱼ [kernel(i, j) × concentration(i) × concentration(j)]

    Arguments:
        - concentration : The distribution of particles.
        - kernel : The coagulation kernel matrix (NDArray[np.float64]).

    Returns:
        - The coagulation loss rate (float or NDArray[np.float64]).

    Examples:
        ```py
        import numpy as np
        import particula as par

        conc = np.array([1.0, 2.0, 3.0])
        kern = np.ones((3, 3))
        loss = par.dynamics.get_coagulation_loss_rate_discrete(conc, kern)
        print(loss)
        # Example output: 36.0
        ```

    References:
        - Seinfeld, J. H., & Pandis, S. N. (2016). Atmospheric chemistry and
          physics, Chapter 13, Equation 13.61.
    """
    return np.sum(kernel * np.outer(concentration, concentration), axis=0)