Skip to content

Commit

Permalink
Merge pull request #27 from jialinl6/Fix171821
Browse files Browse the repository at this point in the history
Fix171821
  • Loading branch information
ctessum authored Feb 23, 2024
2 parents 7db3ee5 + c3f6967 commit ec4659e
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 22 deletions.
5 changes: 5 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
[deps]
AtmosphericDeposition = "1a52f20c-0d16-41d8-a00a-b2996d86a462"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
DifferentialEquations = "0c46a032-eb83-5123-abaf-570d42b7fbaa"
EarthSciMLBase = "e53f1632-a13c-4728-9402-0c66d48804b0"
ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"
Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80"
50 changes: 49 additions & 1 deletion docs/src/dry_deposition.md
Original file line number Diff line number Diff line change
@@ -1 +1,49 @@
# Dry Deposition
# Dry Deposition
## Model
This is an implementation of a box model used to calculate changes in gas species concentration due to dry deposition.

## Running the model
Here's an example of how concentration of different species, such as SO<sub>2</sub>, O<sub>3</sub>, NO<sub>2</sub>, NO, H<sub>2</sub>O<sub>2</sub> and CH<sub>2</sub>O change due to dry deposition.

We can create an instance of the model in the following manner:
```julia @example 1
using AtmosphericDeposition
using ModelingToolkit
using DifferentialEquations
using EarthSciMLBase
using Unitful

@parameters t [unit = u"s", description="Time"]
model = DrydepositionG(t)
```
Before running any simulations with the model we need to convert it into a system of differential equations.
```julia @example 1
sys = structural_simplify(get_mtk(model))
tspan = (0.0, 3600*24)
u0 = [2.0,10.0,5,5,2.34,0.15] # initial concentrations of SO₂, O₃, NO₂, NO, H₂O₂, CH₂O
sol = solve(ODEProblem(sys, u0, tspan, []),AutoTsit5(Rosenbrock23()), saveat=10.0) # default parameters
```
which we can plot as
```julia @example 1
using Plots
plot(sol, xlabel="Time (second)", ylabel="concentration (ppb)", legend=:outerright)
```

## Parameters
The parameters in the model are:
```julia @example 1
parameters(sys) # [z, z₀, u_star, L, ρA, G, T, θ]
```
where ```z``` is the top of the surface layer [m], ```z₀``` is the roughness length [m], ```u_star``` is friction velocity [m/s], and ```L``` is Monin-Obukhov length [m], ```ρA``` is air density [kg/m3], ```T``` is surface air temperature [K], ```G``` is solar irradiation [W m-2], ```Θ``` is the slope of the local terrain [radians].

Let's run some simulation with different value for parameter ```z```.
```julia @example 1
@unpack O3 = sys

p1 = [50,0.04,0.44,0,1.2,300,298,0]
p2 = [10,0.04,0.44,0,1.2,300,298,0]
sol1 = solve(ODEProblem(sys, u0, tspan, p1),AutoTsit5(Rosenbrock23()), saveat=10.0)
sol2 = solve(ODEProblem(sys, u0, tspan, p2),AutoTsit5(Rosenbrock23()), saveat=10.0)

plot([sol1[O3],sol2[O3]], label = ["z=50m" "z=10m"], title = "Change of O3 concentration due to dry deposition", xlabel="Time (second)", ylabel="concentration (ppb)")
```
2 changes: 1 addition & 1 deletion src/dry_deposition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ function DryDepGas(z, z₀, u_star, L, ρA, gasData::GasData, G, Ts, θ, iSeason
Dg = dH2O(Ts) / gasData.Dh2oPerDx # Diffusivity of gas of interest [m2/s]
Sc = sc(μ, ρA, Dg)
Rb = RbGas(Sc, u_star)
Rc = SurfaceResistance(gasData, G * G_unitless, (Ts * T_unitless - 273), θ, iSeason::Int, iLandUse::Int, rain::Bool, dew::Bool, isSO2::Bool, isO3::Bool) * Rc_unit
Rc = WesleySurfaceResistance(gasData, G * G_unitless, (Ts * T_unitless - 273), θ, iSeason::Int, iLandUse::Int, rain::Bool, dew::Bool, isSO2::Bool, isO3::Bool) * Rc_unit
return 1 / (Ra + Rb + Rc)
end

Expand Down
19 changes: 3 additions & 16 deletions src/wesley1989.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export GasData, r_s, r_dc, r_mx, r_smx, r_lux, r_clx, r_gsx, SurfaceResistance, inf, r_i, r_lu, r_ac, r_gsS, r_gsO, r_clS, r_clO, So2Data, O3Data, No2Data, NoData, Hno3Data, H2o2Data, GasData, AldData, HchoData, OpData, PaaData, OraData, Nh3Data, PanData, Hno2Data
export GasData, r_s, r_dc, r_mx, r_smx, r_lux, r_clx, r_gsx, WesleySurfaceResistance, inf, r_i, r_lu, r_ac, r_gsS, r_gsO, r_clS, r_clO, So2Data, O3Data, No2Data, NoData, Hno3Data, H2o2Data, GasData, AldData, HchoData, OpData, PaaData, OraData, Nh3Data, PanData, Hno2Data


const inf = 1.e25
Expand Down Expand Up @@ -88,14 +88,7 @@ const Hno2Data = GasData(1.6, 1.e5, 0.1) # Nitrous acid
# Calculate bulk canopy stomatal resistance [s m-1] based on Wesely (1989) equation 3 when given the solar irradiation (G [W m-2]), the surface air temperature (Ts [°C]), the season index (iSeason), the land use index (iLandUse), and whether there is currently rain or dew.
function r_s(G, Ts, iSeason::Int, iLandUse::Int, rainOrDew::Bool)
rs = 0.0
rs = IfElse.ifelse((Ts >= 39.9) & (Ts <= 0.1), inf, r_i[iSeason, iLandUse] * (1 + (200.0 * 1.0 / (G + 1.0))^2) *
(400.0 * 1.0 / (Ts * (40.0 - Ts))))
# if Ts >= 39.9 || Ts <= 0.1
# rs = inf
# else
# rs = r_i[iSeason, iLandUse] * (1 + (200.0 * 1.0 / (G + 1.0))^2) *
# (400.0 * 1.0 / (Ts * (40.0 - Ts)))
# end
rs = IfElse.ifelse((Ts >= 39.9) & (Ts <= 0.1), inf, r_i[iSeason, iLandUse] * (1 + (200.0 * 1.0 / (G + 1.0))^2) * (400.0 * 1.0 / (Ts * (40.0 - Ts))))
# Adjust for dew and rain (from "Effects of dew and rain" section).
if rainOrDew
rs *= 3
Expand Down Expand Up @@ -171,7 +164,7 @@ end

# Calculates surface resistance to dry depostion [s m-1] based on Wesely (1989) equation 2 when given information on the chemical of interest (gasData), solar irradiation (G [W m-2]), the surface air temperature (Ts [°C]), the slope of the local terrain (Θ [radians]), the season index (iSeason), the land use index (iLandUse), whether there is currently rain or dew, and whether the chemical of interest is either SO2 (isSO2) or O3 (isO3).
# From Wesely (1989) regarding rain and dew inputs: "A direct computation of the surface wetness would be most desirable, e.g. by estimating the amount of free surface water accumulated and then evaporated. Alternatively, surface relative humidity might be a useful index. After dewfall and rainfall events are completed, surface wetness often disappears as a result of evaporation after approximately 2 hours of good atmospheric mixing, the period of time recommended earlier (Sheih et al., 1986)".
function SurfaceResistance(gasData::GasData, G, Ts, θ,
function WesleySurfaceResistance(gasData::GasData, G, Ts, θ,
iSeason, iLandUse, rain::Bool, dew::Bool, isSO2::Bool, isO3::Bool)
rs = r_s(G, Ts, iSeason, iLandUse, rain || dew)
rmx = r_mx(gasData.Hstar, gasData.Fo)
Expand Down Expand Up @@ -199,12 +192,6 @@ function SurfaceResistance(gasData::GasData, G, Ts, θ,
rlux += correction
rclx += correction
rgsx += correction
# if Ts < 0.0
# correction = 1000.0 * exp(-Ts-4) # [s m-1] #mark
# rlux += correction
# rclx += correction
# rgsx += correction
# end

r_c = 1.0 / (1.0 / (rsmx) + 1.0 / rlux + 1.0 / (rdc + rclx) + 1.0 / (rac + rgsx))
r_c = max(r_c, 10.0) # From "Results and conclusions" section to avoid extremely high deposition velocities over extremely rough surfaces.
Expand Down
8 changes: 4 additions & 4 deletions test/wesely1989_test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -122,20 +122,20 @@ function TestWesely()
for iSeason in 1:5
for ig in 1:5
G = Garr[ig]
r_c = SurfaceResistance(gasData[i], G, Ts[iSeason], θ,
r_c = WesleySurfaceResistance(gasData[i], G, Ts[iSeason], θ,
iSeason, iLandUse, false, false, isSO2, isO3)
if different(r_c, polData[iSeason, ig])
println(pol, iSeason, G, r_c, polData[iSeason, ig])
return false
end
end
r_c = SurfaceResistance(gasData[i], 0.0, Ts[iSeason], θ,
r_c = WesleySurfaceResistance(gasData[i], 0.0, Ts[iSeason], θ,
iSeason, iLandUse, false, true, isSO2, isO3) # dew
if different(r_c, polData[iSeason, 6])
println(pol, iSeason, "dew", r_c, polData[iSeason, 6])
return false
end
r_c = SurfaceResistance(gasData[i], 0.0, Ts[iSeason], θ,
r_c = WesleySurfaceResistance(gasData[i], 0.0, Ts[iSeason], θ,
iSeason, iLandUse, true, false, isSO2, isO3) # rain
if different(r_c, polData[iSeason, 7])
println(pol, iSeason, "rain", r_c, polData[iSeason, 7])
Expand All @@ -155,5 +155,5 @@ end
@test r_lux(1.0, 1.0, 1, 1, true, false, true, false) 50
@test r_clx(1.0, 1.0, 1, 1) 9.999899563027895e24
@test r_gsx(1.0, 1.0, 1, 1) 299.9977500168749
@test SurfaceResistance(So2Data, 1.0, 1.0, 1.0, 1, 1, true, true, true, false) 45.45454545454546
@test WesleySurfaceResistance(So2Data, 1.0, 1.0, 1.0, 1, 1, true, true, true, false) 45.45454545454546
end

0 comments on commit ec4659e

Please sign in to comment.