Pollu
POLLU air-pollution photochemistry mechanism from GasChem.jl. 20 species and 25 reactions (15 thermal + 10 photolytic) describing tropospheric NOx / odd-oxygen / hydrocarbon / sulfur chemistry. Introduced by Verwer (1994) as a stiff-ODE benchmark for chemical-kinetics integrators and widely used since as a standard stiff test problem. Hand-translated from the upstream Catalyst @reaction_network in GasChem.jl src/Pollu.jl: 25 rate constants carried verbatim as parameters, 20 species with their declared reservoir defaults, and 25 mass-action reactions numbered R1..R25 in the canonical POLLU order. All reaction rates are bare parameter references and all substrate stoichiometries are 1, so the serialized mass-action system matches the upstream combinatoric_ratelaws=false ReactionSystem exactly.
Description
POLLU air-pollution photochemistry mechanism from GasChem.jl. 20 species and 25 reactions (15 thermal + 10 photolytic) describing tropospheric NOx / odd-oxygen / hydrocarbon / sulfur chemistry. Introduced by Verwer (1994) as a stiff-ODE benchmark for chemical-kinetics integrators and widely used since as a standard stiff test problem. Hand-translated from the upstream Catalyst @reaction_network in GasChem.jl src/Pollu.jl: 25 rate constants carried verbatim as parameters, 20 species with their declared reservoir defaults, and 25 mass-action reactions numbered R1..R25 in the canonical POLLU order. All reaction rates are bare parameter references and all substrate stoichiometries are 1, so the serialized mass-action system matches the upstream combinatoric_ratelaws=false ReactionSystem exactly.
Reference
Verwer, J. G.: Gauss-Seidel iteration for stiff ODEs from chemical kinetics, SIAM Journal on Scientific Computing, 15(5), 1243-1250, 1994.
Source: GasChem.jl src/Pollu.jl @ 8c12c048482b515fb8eb2110bf8ab4b4f4e71309 (esm-4sxf). Hand-translated from the upstream Catalyst @reaction_network. POLLU is a classic stiff-ODE air-pollution benchmark: 20 species, 25 reactions (15 thermal + 10 photolytic). Reactions are numbered R1..R25 following the canonical POLLU ordering – the upstream rate-constant names (k2, k3, k6, …) already encode these indices, and the j-prefixed photolysis constants fill the remaining indices. Every reaction rate is a single rate-constant parameter and every substrate stoichiometry is 1, so the ESM mass-action rate law v = k * prod(S_i) reproduces the upstream ReactionSystem exactly regardless of combinatoric_ratelaws (src/Pollu.jl builds the model with combinatoric_ratelaws=false). The rate constants are the pre-scaled per-second / per-ppb values from src/Pollu.jl (k3 updated to match Fontana pollu.f upstream). Inline-test expected values are an upstream reference run of GasChem.jl Pollu() (Rosenbrock23, abstol=reltol=1e-12); the pollu_benchmark O3 values at 60 s and 3600 s reproduce the published POLLU reference solution to 1e-8. POLLU’s deliberately extreme stiffness (rate constants spanning k238e-7 to k19~7e9 1/s) is why this document declares solver.stiffness = “high” (esm-spec 2.2): an explicit non-stiff method cannot integrate it – Julia’s Tsit5 gives up with retcode MaxIters on every assertion of every test in this file – while each binding’s implicit pick (scipy BDF, Rosenbrock23) integrates the full 3600 s benchmark in well under a second and reproduces the upstream Rosenbrock23 trajectory. The declaration is what carries that fact to all three bindings; the inline-test gates used to carry a per-file solver table each instead, and no longer do.
- DOI: 10.1137/0915076
- URL: https://epubs.siam.org/doi/10.1137/0915076
Parameters
| Name | Units | Default | Description |
|---|---|---|---|
jNO2_O3P | 1/s | 0.005833333333333333 | Photolysis rate constant for NO2 -> NO + O3P (POLLU reaction 1) |
k2 | 1/(ppb*s) | 0.00044333333333333334 | Rate constant for NO + O3 -> NO2 (POLLU reaction 2) |
k3 | 1/(ppb*s) | 0.205 | Rate constant for HO2 + NO -> NO2 + OH (POLLU reaction 3) |
jH2COa | 1/s | 1.4333333333333332e-05 | Photolysis rate constant for CH2O -> 2 HO2 + CO (POLLU reaction 4) |
jH2COb | 1/s | 1.3666666666666666e-05 | Photolysis rate constant for CH2O -> CO (POLLU reaction 5) |
k6 | 1/(ppb*s) | 0.25 | Rate constant for CH2O + OH -> HO2 + CO (POLLU reaction 6) |
jALD | 1/s | 2.1666666666666665e-06 | Photolysis rate constant for ALD -> MEO2 + HO2 + CO (POLLU reaction 7) |
k8 | 1/(ppb*s) | 0.4 | Rate constant for ALD + OH -> C2O3 (POLLU reaction 8) |
k9 | 1/(ppb*s) | 0.275 | Rate constant for C2O3 + NO -> NO2 + MEO2 + CO2 (POLLU reaction 9) |
k10 | 1/(ppb*s) | 0.15 | Rate constant for C2O3 + NO2 -> PAN (POLLU reaction 10) |
jPAN | 1/s | 0.00036666666666666667 | First-order decomposition rate constant for PAN -> C2O3 + NO2 (POLLU reaction 11) |
k12 | 1/(ppb*s) | 0.2 | Rate constant for MEO2 + NO -> CH3O + NO2 (POLLU reaction 12) |
k13 | 1/s | 0.03133333333333333 | Rate constant for CH3O -> CH2O + HO2 (POLLU reaction 13) |
k14 | 1/(ppb*s) | 0.27166666666666667 | Rate constant for NO2 + OH -> HNO3 (POLLU reaction 14) |
k15 | 1/s | 80000.0 | Pseudo-first-order rate constant for O3P -> O3 (POLLU reaction 15) |
jO3_O1D | 1/s | 5.833333333333333e-06 | Photolysis rate constant for O3 -> O1D (POLLU reaction 16) |
jO3_O3P | 1/s | 0.0002916666666666667 | Photolysis rate constant for O3 -> O3P (POLLU reaction 17) |
k18 | 1/s | 1666666.6666666667 | Rate constant for O1D -> 2 OH (POLLU reaction 18) |
k19 | 1/s | 7400000000.0 | Rate constant for O1D -> O3P (POLLU reaction 19) |
k20 | 1/(ppb*s) | 0.020666666666666667 | Rate constant for SO2 + OH -> SO4 + HO2 (POLLU reaction 20) |
jNO3_NO | 1/s | 0.035 | Photolysis rate constant for NO3 -> NO (POLLU reaction 21) |
jNO3_NO2 | 1/s | 0.09633333333333334 | Photolysis rate constant for NO3 -> NO2 + O3P (POLLU reaction 22) |
k23 | 1/(ppb*s) | 7.9e-07 | Rate constant for NO2 + O3 -> NO3 (POLLU reaction 23) |
k24 | 1/(ppb*s) | 0.029666666666666668 | Rate constant for NO3 + NO2 -> N2O5 (POLLU reaction 24) |
jN2O5 | 1/s | 0.052000000000000005 | First-order decomposition rate constant for N2O5 -> NO3 + NO2 (POLLU reaction 25) |
Species
| Species | Units | Default | Constant | Description |
|---|---|---|---|---|
NO2 | ppb | 0.0004 | Nitrogen dioxide | |
NO | ppb | 0.0004 | Nitric oxide | |
O3P | ppb | 0.0 | Ground-state atomic oxygen O(3P) | |
O3 | ppb | 40.0 | Ozone | |
HO2 | ppb | 4e-06 | Hydroperoxyl radical | |
OH | ppb | 4e-06 | Hydroxyl radical | |
CH2O | ppb | 4e-06 | Formaldehyde | |
CO | ppb | 100.0 | Carbon monoxide | |
ALD | ppb | 1e-11 | Lumped non-formaldehyde aldehydes | |
MEO2 | ppb | 4e-06 | Methyl peroxy radical CH3O2 | |
C2O3 | ppb | 0.0 | Acetyl peroxy radical CH3C(O)O2 | |
CO2 | ppb | 355000.0 | Carbon dioxide | |
PAN | ppb | 1e-11 | Peroxyacetyl nitrate CH3C(O)O2NO2 | |
CH3O | ppb | 0.0 | Methoxy radical CH3O | |
HNO3 | ppb | 4e-06 | Nitric acid | |
O1D | ppb | 0.0 | Excited-state atomic oxygen O(1D) | |
SO2 | ppb | 1e-11 | Sulfur dioxide | |
SO4 | ppb | 1e-11 | Sulfate SO4 | |
NO3 | ppb | 4e-06 | Nitrate radical | |
N2O5 | ppb | 4e-06 | Dinitrogen pentoxide |
Reactions
| ID | Substrates | Products | Rate | |
|---|---|---|---|---|
R1 | NO2 | → | NO + O3P | $$jNO2_{O3P}$$ |
R2 | NO + O3 | → | NO2 | $$k2$$ |
R3 | HO2 + NO | → | NO2 + OH | $$k3$$ |
R4 | CH2O | → | 2 HO2 + CO | $$jH2COa$$ |
R5 | CH2O | → | CO | $$jH2COb$$ |
R6 | CH2O + OH | → | HO2 + CO | $$k6$$ |
R7 | ALD | → | MEO2 + HO2 + CO | $$jALD$$ |
R8 | ALD + OH | → | C2O3 | $$k8$$ |
R9 | C2O3 + NO | → | NO2 + MEO2 + CO2 | $$k9$$ |
R10 | C2O3 + NO2 | → | PAN | $$k10$$ |
R11 | PAN | → | C2O3 + NO2 | $$jPAN$$ |
R12 | MEO2 + NO | → | CH3O + NO2 | $$k12$$ |
R13 | CH3O | → | CH2O + HO2 | $$k13$$ |
R14 | NO2 + OH | → | HNO3 | $$k14$$ |
R15 | O3P | → | O3 | $$k15$$ |
R16 | O3 | → | O1D | $$jO3_{O1D}$$ |
R17 | O3 | → | O3P | $$jO3_{O3P}$$ |
R18 | O1D | → | 2 OH | $$k18$$ |
R19 | O1D | → | O3P | $$k19$$ |
R20 | SO2 + OH | → | SO4 + HO2 | $$k20$$ |
R21 | NO3 | → | NO | $$jNO3_{NO}$$ |
R22 | NO3 | → | NO2 + O3P | $$jNO3_{NO2}$$ |
R23 | NO2 + O3 | → | NO3 | $$k23$$ |
R24 | NO3 + NO2 | → | N2O5 | $$k24$$ |
R25 | N2O5 | → | NO3 + NO2 | $$jN2O5$$ |
Raw .esm
Raw .esm JSON (this component)
{
"reference": {
"doi": "10.1137/0915076",
"citation": "Verwer, J. G.: Gauss-Seidel iteration for stiff ODEs from chemical kinetics, SIAM Journal on Scientific Computing, 15(5), 1243-1250, 1994.",
"url": "https://epubs.siam.org/doi/10.1137/0915076",
"notes": "Source: GasChem.jl src/Pollu.jl @ 8c12c048482b515fb8eb2110bf8ab4b4f4e71309 (esm-4sxf). Hand-translated from the upstream Catalyst @reaction_network. POLLU is a classic stiff-ODE air-pollution benchmark: 20 species, 25 reactions (15 thermal + 10 photolytic). Reactions are numbered R1..R25 following the canonical POLLU ordering -- the upstream rate-constant names (k2, k3, k6, ...) already encode these indices, and the j-prefixed photolysis constants fill the remaining indices. Every reaction rate is a single rate-constant parameter and every substrate stoichiometry is 1, so the ESM mass-action rate law v = k * prod(S_i) reproduces the upstream ReactionSystem exactly regardless of combinatoric_ratelaws (src/Pollu.jl builds the model with combinatoric_ratelaws=false). The rate constants are the pre-scaled per-second / per-ppb values from src/Pollu.jl (k3 updated to match Fontana pollu.f upstream). Inline-test expected values are an upstream reference run of GasChem.jl Pollu() (Rosenbrock23, abstol=reltol=1e-12); the pollu_benchmark O3 values at 60 s and 3600 s reproduce the published POLLU reference solution to ~1e-8. POLLU's deliberately extreme stiffness (rate constants spanning k23~8e-7 to k19~7e9 1/s) is why this document declares solver.stiffness = \"high\" (esm-spec 2.2): an explicit non-stiff method cannot integrate it -- Julia's Tsit5 gives up with retcode MaxIters on every assertion of every test in this file -- while each binding's implicit pick (scipy BDF, Rosenbrock23) integrates the full 3600 s benchmark in well under a second and reproduces the upstream Rosenbrock23 trajectory. The declaration is what carries that fact to all three bindings; the inline-test gates used to carry a per-file solver table each instead, and no longer do."
},
"parameters": {
"jNO2_O3P": {
"units": "1/s",
"default": 0.005833333333333333,
"description": "Photolysis rate constant for NO2 -> NO + O3P (POLLU reaction 1)"
},
"k2": {
"units": "1/(ppb*s)",
"default": 0.00044333333333333334,
"description": "Rate constant for NO + O3 -> NO2 (POLLU reaction 2)"
},
"k3": {
"units": "1/(ppb*s)",
"default": 0.205,
"description": "Rate constant for HO2 + NO -> NO2 + OH (POLLU reaction 3)"
},
"jH2COa": {
"units": "1/s",
"default": 1.4333333333333332e-05,
"description": "Photolysis rate constant for CH2O -> 2 HO2 + CO (POLLU reaction 4)"
},
"jH2COb": {
"units": "1/s",
"default": 1.3666666666666666e-05,
"description": "Photolysis rate constant for CH2O -> CO (POLLU reaction 5)"
},
"k6": {
"units": "1/(ppb*s)",
"default": 0.25,
"description": "Rate constant for CH2O + OH -> HO2 + CO (POLLU reaction 6)"
},
"jALD": {
"units": "1/s",
"default": 2.1666666666666665e-06,
"description": "Photolysis rate constant for ALD -> MEO2 + HO2 + CO (POLLU reaction 7)"
},
"k8": {
"units": "1/(ppb*s)",
"default": 0.4,
"description": "Rate constant for ALD + OH -> C2O3 (POLLU reaction 8)"
},
"k9": {
"units": "1/(ppb*s)",
"default": 0.275,
"description": "Rate constant for C2O3 + NO -> NO2 + MEO2 + CO2 (POLLU reaction 9)"
},
"k10": {
"units": "1/(ppb*s)",
"default": 0.15,
"description": "Rate constant for C2O3 + NO2 -> PAN (POLLU reaction 10)"
},
"jPAN": {
"units": "1/s",
"default": 0.00036666666666666667,
"description": "First-order decomposition rate constant for PAN -> C2O3 + NO2 (POLLU reaction 11)"
},
"k12": {
"units": "1/(ppb*s)",
"default": 0.2,
"description": "Rate constant for MEO2 + NO -> CH3O + NO2 (POLLU reaction 12)"
},
"k13": {
"units": "1/s",
"default": 0.03133333333333333,
"description": "Rate constant for CH3O -> CH2O + HO2 (POLLU reaction 13)"
},
"k14": {
"units": "1/(ppb*s)",
"default": 0.27166666666666667,
"description": "Rate constant for NO2 + OH -> HNO3 (POLLU reaction 14)"
},
"k15": {
"units": "1/s",
"default": 80000.0,
"description": "Pseudo-first-order rate constant for O3P -> O3 (POLLU reaction 15)"
},
"jO3_O1D": {
"units": "1/s",
"default": 5.833333333333333e-06,
"description": "Photolysis rate constant for O3 -> O1D (POLLU reaction 16)"
},
"jO3_O3P": {
"units": "1/s",
"default": 0.0002916666666666667,
"description": "Photolysis rate constant for O3 -> O3P (POLLU reaction 17)"
},
"k18": {
"units": "1/s",
"default": 1666666.6666666667,
"description": "Rate constant for O1D -> 2 OH (POLLU reaction 18)"
},
"k19": {
"units": "1/s",
"default": 7400000000.0,
"description": "Rate constant for O1D -> O3P (POLLU reaction 19)"
},
"k20": {
"units": "1/(ppb*s)",
"default": 0.020666666666666667,
"description": "Rate constant for SO2 + OH -> SO4 + HO2 (POLLU reaction 20)"
},
"jNO3_NO": {
"units": "1/s",
"default": 0.035,
"description": "Photolysis rate constant for NO3 -> NO (POLLU reaction 21)"
},
"jNO3_NO2": {
"units": "1/s",
"default": 0.09633333333333334,
"description": "Photolysis rate constant for NO3 -> NO2 + O3P (POLLU reaction 22)"
},
"k23": {
"units": "1/(ppb*s)",
"default": 7.9e-07,
"description": "Rate constant for NO2 + O3 -> NO3 (POLLU reaction 23)"
},
"k24": {
"units": "1/(ppb*s)",
"default": 0.029666666666666668,
"description": "Rate constant for NO3 + NO2 -> N2O5 (POLLU reaction 24)"
},
"jN2O5": {
"units": "1/s",
"default": 0.052000000000000005,
"description": "First-order decomposition rate constant for N2O5 -> NO3 + NO2 (POLLU reaction 25)"
}
},
"species": {
"NO2": {
"units": "ppb",
"default": 0.0004,
"description": "Nitrogen dioxide"
},
"NO": {
"units": "ppb",
"default": 0.0004,
"description": "Nitric oxide"
},
"O3P": {
"units": "ppb",
"default": 0.0,
"description": "Ground-state atomic oxygen O(3P)"
},
"O3": {
"units": "ppb",
"default": 40.0,
"description": "Ozone"
},
"HO2": {
"units": "ppb",
"default": 4e-06,
"description": "Hydroperoxyl radical"
},
"OH": {
"units": "ppb",
"default": 4e-06,
"description": "Hydroxyl radical"
},
"CH2O": {
"units": "ppb",
"default": 4e-06,
"description": "Formaldehyde"
},
"CO": {
"units": "ppb",
"default": 100.0,
"description": "Carbon monoxide"
},
"ALD": {
"units": "ppb",
"default": 1e-11,
"description": "Lumped non-formaldehyde aldehydes"
},
"MEO2": {
"units": "ppb",
"default": 4e-06,
"description": "Methyl peroxy radical CH3O2"
},
"C2O3": {
"units": "ppb",
"default": 0.0,
"description": "Acetyl peroxy radical CH3C(O)O2"
},
"CO2": {
"units": "ppb",
"default": 355000.0,
"description": "Carbon dioxide"
},
"PAN": {
"units": "ppb",
"default": 1e-11,
"description": "Peroxyacetyl nitrate CH3C(O)O2NO2"
},
"CH3O": {
"units": "ppb",
"default": 0.0,
"description": "Methoxy radical CH3O"
},
"HNO3": {
"units": "ppb",
"default": 4e-06,
"description": "Nitric acid"
},
"O1D": {
"units": "ppb",
"default": 0.0,
"description": "Excited-state atomic oxygen O(1D)"
},
"SO2": {
"units": "ppb",
"default": 1e-11,
"description": "Sulfur dioxide"
},
"SO4": {
"units": "ppb",
"default": 1e-11,
"description": "Sulfate SO4"
},
"NO3": {
"units": "ppb",
"default": 4e-06,
"description": "Nitrate radical"
},
"N2O5": {
"units": "ppb",
"default": 4e-06,
"description": "Dinitrogen pentoxide"
}
},
"reactions": [
{
"id": "R1",
"substrates": [
{
"species": "NO2",
"stoichiometry": 1
}
],
"products": [
{
"species": "NO",
"stoichiometry": 1
},
{
"species": "O3P",
"stoichiometry": 1
}
],
"rate": "jNO2_O3P"
},
{
"id": "R2",
"substrates": [
{
"species": "NO",
"stoichiometry": 1
},
{
"species": "O3",
"stoichiometry": 1
}
],
"products": [
{
"species": "NO2",
"stoichiometry": 1
}
],
"rate": "k2"
},
{
"id": "R3",
"substrates": [
{
"species": "HO2",
"stoichiometry": 1
},
{
"species": "NO",
"stoichiometry": 1
}
],
"products": [
{
"species": "NO2",
"stoichiometry": 1
},
{
"species": "OH",
"stoichiometry": 1
}
],
"rate": "k3"
},
{
"id": "R4",
"substrates": [
{
"species": "CH2O",
"stoichiometry": 1
}
],
"products": [
{
"species": "HO2",
"stoichiometry": 2
},
{
"species": "CO",
"stoichiometry": 1
}
],
"rate": "jH2COa"
},
{
"id": "R5",
"substrates": [
{
"species": "CH2O",
"stoichiometry": 1
}
],
"products": [
{
"species": "CO",
"stoichiometry": 1
}
],
"rate": "jH2COb"
},
{
"id": "R6",
"substrates": [
{
"species": "CH2O",
"stoichiometry": 1
},
{
"species": "OH",
"stoichiometry": 1
}
],
"products": [
{
"species": "HO2",
"stoichiometry": 1
},
{
"species": "CO",
"stoichiometry": 1
}
],
"rate": "k6"
},
{
"id": "R7",
"substrates": [
{
"species": "ALD",
"stoichiometry": 1
}
],
"products": [
{
"species": "MEO2",
"stoichiometry": 1
},
{
"species": "HO2",
"stoichiometry": 1
},
{
"species": "CO",
"stoichiometry": 1
}
],
"rate": "jALD"
},
{
"id": "R8",
"substrates": [
{
"species": "ALD",
"stoichiometry": 1
},
{
"species": "OH",
"stoichiometry": 1
}
],
"products": [
{
"species": "C2O3",
"stoichiometry": 1
}
],
"rate": "k8"
},
{
"id": "R9",
"substrates": [
{
"species": "C2O3",
"stoichiometry": 1
},
{
"species": "NO",
"stoichiometry": 1
}
],
"products": [
{
"species": "NO2",
"stoichiometry": 1
},
{
"species": "MEO2",
"stoichiometry": 1
},
{
"species": "CO2",
"stoichiometry": 1
}
],
"rate": "k9"
},
{
"id": "R10",
"substrates": [
{
"species": "C2O3",
"stoichiometry": 1
},
{
"species": "NO2",
"stoichiometry": 1
}
],
"products": [
{
"species": "PAN",
"stoichiometry": 1
}
],
"rate": "k10"
},
{
"id": "R11",
"substrates": [
{
"species": "PAN",
"stoichiometry": 1
}
],
"products": [
{
"species": "C2O3",
"stoichiometry": 1
},
{
"species": "NO2",
"stoichiometry": 1
}
],
"rate": "jPAN"
},
{
"id": "R12",
"substrates": [
{
"species": "MEO2",
"stoichiometry": 1
},
{
"species": "NO",
"stoichiometry": 1
}
],
"products": [
{
"species": "CH3O",
"stoichiometry": 1
},
{
"species": "NO2",
"stoichiometry": 1
}
],
"rate": "k12"
},
{
"id": "R13",
"substrates": [
{
"species": "CH3O",
"stoichiometry": 1
}
],
"products": [
{
"species": "CH2O",
"stoichiometry": 1
},
{
"species": "HO2",
"stoichiometry": 1
}
],
"rate": "k13"
},
{
"id": "R14",
"substrates": [
{
"species": "NO2",
"stoichiometry": 1
},
{
"species": "OH",
"stoichiometry": 1
}
],
"products": [
{
"species": "HNO3",
"stoichiometry": 1
}
],
"rate": "k14"
},
{
"id": "R15",
"substrates": [
{
"species": "O3P",
"stoichiometry": 1
}
],
"products": [
{
"species": "O3",
"stoichiometry": 1
}
],
"rate": "k15"
},
{
"id": "R16",
"substrates": [
{
"species": "O3",
"stoichiometry": 1
}
],
"products": [
{
"species": "O1D",
"stoichiometry": 1
}
],
"rate": "jO3_O1D"
},
{
"id": "R17",
"substrates": [
{
"species": "O3",
"stoichiometry": 1
}
],
"products": [
{
"species": "O3P",
"stoichiometry": 1
}
],
"rate": "jO3_O3P"
},
{
"id": "R18",
"substrates": [
{
"species": "O1D",
"stoichiometry": 1
}
],
"products": [
{
"species": "OH",
"stoichiometry": 2
}
],
"rate": "k18"
},
{
"id": "R19",
"substrates": [
{
"species": "O1D",
"stoichiometry": 1
}
],
"products": [
{
"species": "O3P",
"stoichiometry": 1
}
],
"rate": "k19"
},
{
"id": "R20",
"substrates": [
{
"species": "SO2",
"stoichiometry": 1
},
{
"species": "OH",
"stoichiometry": 1
}
],
"products": [
{
"species": "SO4",
"stoichiometry": 1
},
{
"species": "HO2",
"stoichiometry": 1
}
],
"rate": "k20"
},
{
"id": "R21",
"substrates": [
{
"species": "NO3",
"stoichiometry": 1
}
],
"products": [
{
"species": "NO",
"stoichiometry": 1
}
],
"rate": "jNO3_NO"
},
{
"id": "R22",
"substrates": [
{
"species": "NO3",
"stoichiometry": 1
}
],
"products": [
{
"species": "NO2",
"stoichiometry": 1
},
{
"species": "O3P",
"stoichiometry": 1
}
],
"rate": "jNO3_NO2"
},
{
"id": "R23",
"substrates": [
{
"species": "NO2",
"stoichiometry": 1
},
{
"species": "O3",
"stoichiometry": 1
}
],
"products": [
{
"species": "NO3",
"stoichiometry": 1
}
],
"rate": "k23"
},
{
"id": "R24",
"substrates": [
{
"species": "NO3",
"stoichiometry": 1
},
{
"species": "NO2",
"stoichiometry": 1
}
],
"products": [
{
"species": "N2O5",
"stoichiometry": 1
}
],
"rate": "k24"
},
{
"id": "R25",
"substrates": [
{
"species": "N2O5",
"stoichiometry": 1
}
],
"products": [
{
"species": "NO3",
"stoichiometry": 1
},
{
"species": "NO2",
"stoichiometry": 1
}
],
"rate": "jN2O5"
}
],
"tests": [
{
"id": "pollu_benchmark_nox_ozone",
"description": "Classic POLLU air-pollution benchmark (Verwer 1994), NOx / odd-oxygen pathways. Initial conditions are the standard POLLU problem state (NO=200, O3=40, CH2O=100, CO=300, ALD=10, SO2=7 ppb; all radicals and secondary products zero), matching GasChem.jl test/pollu_test.jl. Integrated 0..3600 s. O3 climbs from 40 ppb down to ~3.3 ppb and back up to ~5.5 ppb while NO (200 ppb) is converted to NO2 and ultimately to HNO3 / N2O5. The O3 values at 60 s and 3600 s reproduce the published POLLU reference solution (3.299406575662 and 5.52314020747798 ppb) to ~1e-8. Expected values are an upstream reference run of the GasChem.jl Pollu() ReactionSystem (Rosenbrock23, abstol=reltol=1e-12).\n\nTolerance rationale (test-level rel=1e-5): the ESS scipy-BDF integration reproduces the upstream Rosenbrock23 reference to <=1.5e-6 across every assertion in this file; rel=1e-5 leaves ~6x headroom for cross-environment solver-truncation variation.",
"initial_conditions": {
"NO2": 0.0,
"NO": 200.0,
"O3P": 0.0,
"O3": 40.0,
"HO2": 0.0,
"OH": 0.0,
"CH2O": 100.0,
"CO": 300.0,
"ALD": 10.0,
"MEO2": 0.0,
"C2O3": 0.0,
"CO2": 0.0,
"PAN": 0.0,
"CH3O": 0.0,
"HNO3": 0.0,
"O1D": 0.0,
"SO2": 7.0,
"SO4": 0.0,
"NO3": 0.0,
"N2O5": 0.0
},
"time_span": {
"start": 0.0,
"end": 3600.0
},
"tolerance": {
"rel": 1e-05
},
"assertions": [
{
"variable": "O3",
"time": 60.0,
"expected": 3.2994065585833074
},
{
"variable": "NO",
"time": 60.0,
"expected": 162.5132541096391
},
{
"variable": "NO2",
"time": 60.0,
"expected": 37.326304316021215
},
{
"variable": "HNO3",
"time": 60.0,
"expected": 0.1395946402838492
},
{
"variable": "O3",
"time": 360.0,
"expected": 3.3019885626845236
},
{
"variable": "NO",
"time": 360.0,
"expected": 158.9289939721817
},
{
"variable": "NO2",
"time": 360.0,
"expected": 40.03870361089256
},
{
"variable": "HNO3",
"time": 360.0,
"expected": 0.9627454219929577
},
{
"variable": "O3",
"time": 1200.0,
"expected": 3.974120041890565
},
{
"variable": "NO",
"time": 1200.0,
"expected": 150.92528896734098
},
{
"variable": "NO2",
"time": 1200.0,
"expected": 45.72027350810146
},
{
"variable": "HNO3",
"time": 1200.0,
"expected": 3.190629002032954
},
{
"variable": "O3",
"time": 3600.0,
"expected": 5.523140206743763
},
{
"variable": "NO",
"time": 3600.0,
"expected": 134.24841304206876
},
{
"variable": "NO2",
"time": 3600.0,
"expected": 56.46255479994428
},
{
"variable": "HNO3",
"time": 3600.0,
"expected": 8.964884857331883
},
{
"variable": "NO3",
"time": 360.0,
"expected": 0.0006624872234791833
},
{
"variable": "N2O5",
"time": 360.0,
"expected": 0.014808862165153794
},
{
"variable": "NO3",
"time": 1200.0,
"expected": 0.000996712044191727
},
{
"variable": "N2O5",
"time": 1200.0,
"expected": 0.025761754989217178
},
{
"variable": "NO3",
"time": 3600.0,
"expected": 0.0017721465129384223
},
{
"variable": "N2O5",
"time": 3600.0,
"expected": 0.056829432882838544
}
]
},
{
"id": "pollu_benchmark_carbon_radicals",
"description": "Classic POLLU air-pollution benchmark (Verwer 1994), carbon, sulfur and radical pools. Same standard POLLU initial state and 0..3600 s window as pollu_benchmark_nox_ozone. Tracks the formaldehyde / aldehyde oxidation chain (CH2O and ALD deplete, CO and CO2 build up), PAN formation, the SO2 -> SO4 oxidation, and the HOx / acetyl-peroxy radical pool. Expected values are an upstream reference run of the GasChem.jl Pollu() ReactionSystem (Rosenbrock23, abstol=reltol=1e-12).\n\nTolerance rationale (test-level rel=1e-5): the ESS scipy-BDF integration reproduces the upstream Rosenbrock23 reference to <=1.1e-7 across every assertion in this test, including the quasi-steady-state radicals HO2, OH and CH3O; rel=1e-5 leaves ample headroom for cross-environment solver-truncation variation.",
"initial_conditions": {
"NO2": 0.0,
"NO": 200.0,
"O3P": 0.0,
"O3": 40.0,
"HO2": 0.0,
"OH": 0.0,
"CH2O": 100.0,
"CO": 300.0,
"ALD": 10.0,
"MEO2": 0.0,
"C2O3": 0.0,
"CO2": 0.0,
"PAN": 0.0,
"CH3O": 0.0,
"HNO3": 0.0,
"O1D": 0.0,
"SO2": 7.0,
"SO4": 0.0,
"NO3": 0.0,
"N2O5": 0.0
},
"time_span": {
"start": 0.0,
"end": 3600.0
},
"tolerance": {
"rel": 1e-05
},
"assertions": [
{
"variable": "CH2O",
"time": 60.0,
"expected": 99.42310366611129
},
{
"variable": "CO",
"time": 60.0,
"expected": 300.6173127758226
},
{
"variable": "CH2O",
"time": 360.0,
"expected": 96.95947560714808
},
{
"variable": "CO",
"time": 360.0,
"expected": 303.3648851352528
},
{
"variable": "CH2O",
"time": 1200.0,
"expected": 90.92249463276721
},
{
"variable": "CO",
"time": 1200.0,
"expected": 310.0767218791533
},
{
"variable": "CH2O",
"time": 3600.0,
"expected": 77.8424911901163
},
{
"variable": "CO",
"time": 3600.0,
"expected": 324.5075353393118
},
{
"variable": "ALD",
"time": 60.0,
"expected": 9.926994938303086
},
{
"variable": "ALD",
"time": 1200.0,
"expected": 8.891758790942236
},
{
"variable": "ALD",
"time": 3600.0,
"expected": 7.494013383946816
},
{
"variable": "CO2",
"time": 360.0,
"expected": 0.3375472127563113
},
{
"variable": "PAN",
"time": 360.0,
"expected": 0.0392767833767802
},
{
"variable": "SO4",
"time": 360.0,
"expected": 0.013884153944735377
},
{
"variable": "CO2",
"time": 1200.0,
"expected": 0.9724793237222531
},
{
"variable": "PAN",
"time": 1200.0,
"expected": 0.11128830050001731
},
{
"variable": "SO4",
"time": 1200.0,
"expected": 0.04141809601218517
},
{
"variable": "CO2",
"time": 3600.0,
"expected": 2.230505975552533
},
{
"variable": "PAN",
"time": 3600.0,
"expected": 0.20871628837599582
},
{
"variable": "SO4",
"time": 3600.0,
"expected": 0.10078030373668498
},
{
"variable": "SO2",
"time": 60.0,
"expected": 6.997397465743142
},
{
"variable": "SO2",
"time": 3600.0,
"expected": 6.899219696263298
},
{
"variable": "HO2",
"time": 60.0,
"expected": 0.00031151619390190985
},
{
"variable": "OH",
"time": 60.0,
"expected": 0.00026534918498784184
},
{
"variable": "CH3O",
"time": 60.0,
"expected": 0.027858639531295276
},
{
"variable": "HO2",
"time": 3600.0,
"expected": 0.000201897726213688
},
{
"variable": "OH",
"time": 3600.0,
"expected": 0.0001464541863171435
},
{
"variable": "CH3O",
"time": 3600.0,
"expected": 0.013969210163673966
}
]
},
{
"id": "default_reservoir_state",
"description": "Declared-default reservoir state: integrates 0..3600 s from the per-species reservoir defaults declared on the reaction system (O3=40, CO=100, CO2=3.55e5 ppb; NOx and radicals at trace 1e-4..1e-6 ppb levels). The initial conditions are pinned explicitly to the declared species defaults so the test is runner-agnostic. This guards the serialized species and parameter defaults: under this near-background state the long-lived pools (O3, CO, CO2) are almost unchanged while OH and HNO3 build up slowly. Expected values are an upstream reference run of the GasChem.jl Pollu() ReactionSystem (Rosenbrock23, abstol=reltol=1e-12).\n\nTolerance rationale (test-level rel=1e-5): the ESS scipy-BDF integration reproduces the upstream Rosenbrock23 reference to <=1.6e-6 across every assertion in this test (worst case: the slowly accumulating HNO3 trace); rel=1e-5 leaves ~6x headroom for cross-environment solver-truncation variation.",
"initial_conditions": {
"NO2": 0.0004,
"NO": 0.0004,
"O3P": 0.0,
"O3": 40.0,
"HO2": 4e-06,
"OH": 4e-06,
"CH2O": 4e-06,
"CO": 100.0,
"ALD": 1e-11,
"MEO2": 4e-06,
"C2O3": 0.0,
"CO2": 355000.0,
"PAN": 1e-11,
"CH3O": 0.0,
"HNO3": 4e-06,
"O1D": 0.0,
"SO2": 1e-11,
"SO4": 1e-11,
"NO3": 4e-06,
"N2O5": 4e-06
},
"time_span": {
"start": 0.0,
"end": 3600.0
},
"tolerance": {
"rel": 1e-05
},
"assertions": [
{
"variable": "O3",
"time": 60.0,
"expected": 39.99984952796007
},
{
"variable": "O3",
"time": 3600.0,
"expected": 39.999559353209776
},
{
"variable": "CO",
"time": 3600.0,
"expected": 100.00000094188971
},
{
"variable": "CO2",
"time": 3600.0,
"expected": 355000.0
},
{
"variable": "HNO3",
"time": 360.0,
"expected": 5.321459574631042e-06
},
{
"variable": "HNO3",
"time": 1200.0,
"expected": 1.6385436558727387e-05
},
{
"variable": "HNO3",
"time": 3600.0,
"expected": 9.44547614093343e-05
},
{
"variable": "OH",
"time": 1200.0,
"expected": 0.00011784431329352004
},
{
"variable": "OH",
"time": 3600.0,
"expected": 0.0002919122494210695
},
{
"variable": "NO2",
"time": 3600.0,
"expected": 0.000542215133966588
},
{
"variable": "NO",
"time": 3600.0,
"expected": 0.0001791995102912521
}
]
}
]
}