Skip to content
Snippets Groups Projects
Commit fb51db65 authored by Alexander Böhmländer's avatar Alexander Böhmländer
Browse files

Adjusted size distributions and renamed test files accordingly.

parent bedd742f
No related branches found
No related tags found
No related merge requests found
......@@ -137,13 +137,92 @@ def lognormal_number_distribution(number_concentration: float,
from air pollution to climate change. John Wiley & Sons. isbn: 1118947401.
"""
dNdlogdp = (number_concentration
/ (standard_deviation * np.sqrt(2 * np.pi)
dNddp = (number_concentration
/ (np.log(standard_deviation) * particle_diameter * np.sqrt(2 * np.pi)
)
* np.exp(- (np.log10(particle_diameter) - np.log10(median_particle_diameter))**2
/ (2 * np.log10(standard_deviation)**2)
* np.exp(- (np.log(particle_diameter) - np.log(median_particle_diameter))**2
/ (2 * np.log(standard_deviation)**2)
)
)
return dNddp
def lognormal_number_distribution_natural_scale(number_concentration: float,
standard_deviation: float,
median_particle_diameter: float,
particle_diameter: npt.ArrayLike) -> npt.ArrayLike:
"""
Lognormal number distribution with median diameter and
standard deviation, both on log-scale. Log is related to
the decadal logarithm. Definition taken from [1]_.
Parameters
----------
number_concentration : float
Total number concentration of particles.
standard_deviation : float
Standard deviation..
median_particle_diameter : float
Median diameter.
particle_diameter : npt.ArrayLike
Particle diameter of a given size distribution.
Returns
-------
npt.ArrayLike
Lognormal number distribution based on the median
particle diameter and the standard deviation,
both on the log-scale.
References
----------
[1] Seinfeld, J. H. and S. N. Pandis (2016). Atmospheric chemistry and physics:
from air pollution to climate change. John Wiley & Sons. isbn: 1118947401.
"""
dNdlndp = lognormal_number_distribution(number_concentration,
standard_deviation,
median_particle_diameter,
particle_diameter) * particle_diameter
return dNdlndp
def lognormal_number_distribution_log_scale(number_concentration: float,
standard_deviation: float,
median_particle_diameter: float,
particle_diameter: npt.ArrayLike) -> npt.ArrayLike:
"""
Lognormal number distribution with median diameter and
standard deviation, both on log-scale. Log is related to
the decadal logarithm. Definition taken from [1]_.
Parameters
----------
number_concentration : float
Total number concentration of particles.
standard_deviation : float
Standard deviation..
median_particle_diameter : float
Median diameter.
particle_diameter : npt.ArrayLike
Particle diameter of a given size distribution.
Returns
-------
npt.ArrayLike
Lognormal number distribution based on the median
particle diameter and the standard deviation,
both on the log-scale.
References
----------
[1] Seinfeld, J. H. and S. N. Pandis (2016). Atmospheric chemistry and physics:
from air pollution to climate change. John Wiley & Sons. isbn: 1118947401.
"""
dNdlogdp = lognormal_number_distribution(number_concentration,
standard_deviation,
median_particle_diameter,
particle_diameter) * np.log(10) * particle_diameter
return dNdlogdp
......
......@@ -7,32 +7,37 @@ Created on Sun Nov 24 00:07:14 2024
"""
import numpy as np
import pandas as pd
import math
import matplotlib.pyplot as plt
import os
from pathlib import Path
os.chdir(Path(__file__).parent)
from Calculations import size_distribution as sd
plot_path = Path(__file__).parent.joinpath('test_results/Calculations')
plot_path.mkdir(exist_ok=True, parents=True)
# Test size distributions and create suitable plots.
# Generate three modes of a size distribution in urban areas.
particle_diameter = np.geomspace(1e-3, 10, 500) # µm
number_size_distribution_nucleation = sd.lognormal_number_distribution(
number_size_distribution_nucleation = sd.lognormal_number_distribution_log_scale(
number_concentration=7100,
standard_deviation=10**0.232,
standard_deviation=np.exp(0.232),
median_particle_diameter=0.0117,
particle_diameter=particle_diameter)
number_size_distribution_aitken = sd.lognormal_number_distribution(
number_size_distribution_aitken = sd.lognormal_number_distribution_log_scale(
number_concentration=6320,
standard_deviation=10**0.250,
standard_deviation=np.exp(0.250),
median_particle_diameter=0.0373,
particle_diameter=particle_diameter)
number_size_distribution_coarse = sd.lognormal_number_distribution(
number_size_distribution_coarse = sd.lognormal_number_distribution_log_scale(
number_concentration=960,
standard_deviation=10**0.204,
standard_deviation=np.exp(0.204),
median_particle_diameter=0.151,
particle_diameter=particle_diameter)
......@@ -41,13 +46,13 @@ number_size_distribution_coarse = sd.lognormal_number_distribution(
dlogdp = np.diff(np.log10(particle_diameter)).mean()
number_concentration_nucleation = (number_size_distribution_nucleation
* dlogdp).sum()
print(number_concentration_nucleation)
assert math.isclose(7100, number_concentration_nucleation)
number_concentration_aitken = (number_size_distribution_aitken
* dlogdp).sum()
print(number_concentration_aitken)
assert math.isclose(6320, number_concentration_aitken)
number_concentration_coarse = (number_size_distribution_coarse
* dlogdp).sum()
print(number_concentration_coarse)
assert math.isclose(960, number_concentration_coarse)
# %%
fig, ax = plt.subplots()
......@@ -57,13 +62,40 @@ ax.plot(particle_diameter,
number_size_distribution_aitken, label='Aitken')
ax.plot(particle_diameter,
number_size_distribution_coarse, label='Coarse')
# ax.plot(particle_diameter,
# number_size_distribution_aitken + number_size_distribution_nucleation,
# label='Total')
ax.plot(particle_diameter,
number_size_distribution_aitken
+ number_size_distribution_nucleation
+ number_size_distribution_coarse,
label='Total')
ax.set_xlabel(r'$d_\mathrm{p}$ / µm')
ax.set_ylabel(r'd$N$/dlog$d_\mathrm{p}$ / cm${-3}$')
ax.set_xscale('log')
# ax.set_yscale('log')
ax.legend()
fig.savefig(plot_path.joinpath('test_sd.png'))
# %% Testing calculations of surface and volume distributions
total_sd = (number_size_distribution_aitken
+ number_size_distribution_nucleation
+ number_size_distribution_coarse)
total_sd = pd.DataFrame(total_sd, index=particle_diameter).T
fig, (ax, ax2, ax3) = plt.subplots(3, 1, sharex=True)
ax.plot(particle_diameter,
total_sd.iloc[0, :],
label='Number')
ax2.plot(particle_diameter,
sd.surface_distribution(total_sd).iloc[0, :],
label='Surface')
ax3.plot(particle_diameter,
sd.volume_distribution(total_sd).iloc[0, :],
label='Volume')
# ax.set_ylim(1e-3, 1e4)
for name, axis in zip(('N', 'S', 'V'), (ax, ax2, ax3)):
axis.set_ylabel(fr'd${name}$/dlog$d_\mathrm{{p}}$ / cm${-3}$')
axis.set_xscale('log')
axis.legend()
ax3.set_xlabel(r'$d_\mathrm{p}$ / µm')
ax.legend()
\ No newline at end of file
fig.savefig(plot_path.joinpath('test_sd_NSV.png'))
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment