Skip to content

Commit db86136

Browse files
committed
Minor fixes
- Removed the PModelDrivers struct due to redundancy and broadcasting issues. Now we take in the drivers as separate arguments - Clarified units of Kc, Ko, and Gammastar - Removed T, P-dependent density of water. Now we only use constant density - Fixed accidental deletions during rebase
1 parent 8704c2f commit db86136

File tree

6 files changed

+57
-105
lines changed

6 files changed

+57
-105
lines changed

src/standalone/Vegetation/Canopy.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ include("./canopy_energy.jl")
4646
include("./canopy_parameterizations.jl")
4747
using Dates
4848
include("./autotrophic_respiration.jl")
49+
include("./spatially_varying_parameters.jl")
4950

5051
"""
5152
SharedCanopyParameters{FT <: AbstractFloat, PSE}

src/standalone/Vegetation/canopy_parameterizations.jl

Lines changed: 6 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -845,7 +845,7 @@ end
845845
R::FT) where {FT}
846846
847847
Computes the Michaelis-Menten coefficient for CO2 (`Kc`),
848-
in units of mol/mol,
848+
in units of mol/mol or Pa (depending on the units of `Kc25`),
849849
as a function of its value at 25 °C (`Kc25`),
850850
a constant (`ΔHkc`), a standard temperature (`To`),
851851
the unversal gas constant (`R`), and the temperature (`T`).
@@ -866,7 +866,7 @@ end
866866
R::FT) where {FT}
867867
868868
Computes the Michaelis-Menten coefficient for O2 (`Ko`),
869-
in units of mol/mol,
869+
in units of mol/mol or Pa (depending on the units of `Ko25`),
870870
as a function of its value at 25 °C (`Ko25`),
871871
a constant (`ΔHko`), a standard temperature (`To`),
872872
the universal gas constant (`R`), and the temperature (`T`).
@@ -1141,59 +1141,6 @@ function intrinsic_quantum_yield(
11411141
end
11421142

11431143

1144-
"""
1145-
density_h20(
1146-
T::FT,
1147-
p::FT
1148-
) where {FT}
1149-
1150-
Computes the density of water in kg/m^3 given temperature T (K) and pressure p (Pa)
1151-
according to F.H. Fisher and O.E Dial, Jr. (1975) Equation of state of pure water and
1152-
sea water, Tech. Rept., Marine Physical Laboratory, San Diego, CA.
1153-
1154-
(can consider removing the higher order terms?)
1155-
"""
1156-
function density_h2o(T::FT, p::FT) where {FT}
1157-
# Convert temperature to Celsius
1158-
T = T - FT(273.15)
1159-
# Convert pressure to bar (1 bar = 1e5 Pa)
1160-
pbar = FT(1e-5) * p
1161-
1162-
# λ(T): bar cm3/g
1163-
λ =
1164-
FT(1788.316) + FT(21.55053) * T - FT(0.4695911) * T^2 +
1165-
FT(3.096363e-3) * T^3 - FT(7.341182e-6) * T^4
1166-
1167-
# p0(T): bar
1168-
p0 =
1169-
FT(5918.499) + FT(58.05267) * T - FT(1.1253317) * T^2 +
1170-
FT(6.6123869e-3) * T^3 - FT(1.4661625e-5) * T^4
1171-
1172-
# v_inf(T): cm3/g
1173-
T_powers = (T .^ (0:9)) # T^0 to T^9
1174-
coeffs_vinf =
1175-
FT.([
1176-
0.6980547,
1177-
-7.435626e-4,
1178-
3.704258e-5,
1179-
-6.315724e-7,
1180-
9.829576e-9,
1181-
-1.197269e-10,
1182-
1.005461e-12,
1183-
-5.437898e-15,
1184-
1.69946e-17,
1185-
-2.295063e-20,
1186-
])
1187-
v_inf = dot(coeffs_vinf, T_powers)
1188-
1189-
# Specific volume [cm3/g]
1190-
v = v_inf + λ / (p0 + pbar)
1191-
1192-
# Convert to density [kg/m3]
1193-
return FT(1e3) / v
1194-
end
1195-
1196-
11971144
"""
11981145
viscosity_h20(
11991146
T::FT,
@@ -1206,16 +1153,15 @@ end
12061153
12071154
Can consider simplifying if this level of precision is not needed
12081155
"""
1209-
function viscosity_h2o(T::FT, p::FT, constant_density::Bool) where {FT}
1156+
function viscosity_h2o(T::FT, p::FT) where {FT}
12101157
# Reference constants
12111158
tk_ast = FT(647.096) # K
12121159
ρ_ast = FT(322.0) # kg/m^3
12131160
μ_ast = FT(1e-6) # Pa s
12141161

12151162
# Get density of water [kg/m^3]
12161163
earth_param_set = LP.LandParameters(FT)
1217-
ρ0 = LP.ρ_cloud_liq(earth_param_set)
1218-
constant_density ? ρ = ρ0 : ρ = density_h2o(T, p)
1164+
ρ = LP.ρ_cloud_liq(earth_param_set)
12191165

12201166
# Dimensionless variables
12211167
tbar = T / tk_ast
@@ -1278,10 +1224,9 @@ end
12781224
function compute_viscosity_ratio(
12791225
T::FT,
12801226
p::FT,
1281-
constant_density::Bool,
12821227
) where {FT}
1283-
η25 = viscosity_h2o(FT(298.15), FT(101325.0), constant_density)
1284-
ηstar = viscosity_h2o(T, p, constant_density) / η25
1228+
η25 = viscosity_h2o(FT(298.15), FT(101325.0))
1229+
ηstar = viscosity_h2o(T, p) / η25
12851230
return FT(ηstar)
12861231
end
12871232

@@ -1434,7 +1379,6 @@ end
14341379
is constant. cstar is defined as 4c, a free parameter. Wang etal (2017) derive cstar = 0.412
14351380
at STP and using Vcmax/Jmax = 1.88.
14361381
"""
1437-
# TODO: test if cstar should be made a free parameter?
14381382
function compute_mj_with_jmax_limitation(mj::FT, cstar::FT) where {FT}
14391383
return FT(mj * sqrt(1 - (cstar / mj)^(FT(2 / 3))))
14401384
end

src/standalone/Vegetation/pmodel.jl

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
export PModelParameters,
2-
PModelDrivers, PModelConstants, compute_full_pmodel_outputs, PModel
1+
export PModelParameters,
2+
PModelConstants,
3+
compute_full_pmodel_outputs,
4+
PModel
35

46
"""
57
PModelParameters{FT<:AbstractFloat}
@@ -29,42 +31,26 @@ Base.@kwdef struct PModelParameters{FT <: AbstractFloat}
2931
ϕa2::FT
3032
end
3133

32-
"""
33-
PModelDrivers{FT<:AbstractFloat}
34-
35-
The required drivers for P-model (Stocker et al. 2020). Drivers are defined as
36-
external variables used to compute the optimal photosynthetic capacities.
37-
$(DocStringExtensions.FIELDS)
38-
"""
39-
Base.@kwdef struct PModelDrivers{FT <: AbstractFloat}
40-
"Canopy temperature (K)"
41-
T_canopy::FT
42-
"Absorbed PAR in moles of photons (mol m^-2 s^-1)"
43-
I_abs::FT
44-
"Ambient CO2 partial pressure (Pa)"
45-
ca::FT
46-
"Ambient air pressure (Pa)"
47-
P_air::FT
48-
"Vapor pressure deficit (Pa)"
49-
VPD::FT
50-
"""Soil moisture stress factor (unitless)"""
51-
βm::FT
52-
end
53-
5434

5535
"""
5636
PModelConstants{FT<:AbstractFloat}
5737
5838
The required constants for P-model (Stocker et al. 2020). These are physical
5939
or biochemical constants that are not expected to change with time or space.
40+
41+
IMPORTANT NOTE: the dimensions of the Michaelis-Menten parameters Kc and Ko and compensation
42+
point Γstar correspond to gaseous concentrations, so they can either be expressed as a mixing
43+
ratio (mol mol^-1) or as a partial pressure (Pa) of 1 atm. These are equivalent up to a constant
44+
factor of P_atm = 101325 Pa. As long as you are consistent with which convention you use,
45+
the model will work correctly. By default, these constants are set using the Pa convention.
6046
$(DocStringExtensions.FIELDS)
6147
"""
6248
Base.@kwdef struct PModelConstants{FT}
6349
"""Gas constant (J mol^-1 K^-1)"""
6450
R::FT
65-
"""Michaelis-Menten parameter for carboxylation at 25°C (μmol mol^-1)"""
51+
"""Michaelis-Menten parameter for carboxylation at 25°C (mol mol^-1 or Pa)"""
6652
Kc25::FT
67-
"""Michaelis-Menten parameter for oxygenation at 25°C (μmol mol^-1)"""
53+
"""Michaelis-Menten parameter for oxygenation at 25°C (mol mol^-1 or Pa)"""
6854
Ko25::FT
6955
"""Reference temperature equal to 25˚C (K)"""
7056
To::FT
@@ -76,7 +62,7 @@ Base.@kwdef struct PModelConstants{FT}
7662
Drel::FT
7763
"""Effective energy of activation for Γstar (J mol^-1)"""
7864
ΔHΓstar::FT
79-
"""Γstar at 25 °C (Pa)"""
65+
"""Γstar at 25 °C (mol mol^-1 or Pa)"""
8066
Γstar25::FT
8167
"""Effective energy of activation for Vcmax (J mol^-1)"""
8268
Ha_Vcmax::FT
@@ -96,7 +82,7 @@ Base.@kwdef struct PModelConstants{FT}
9682
bS_Jmax::FT
9783
"""Molar mass of carbon (kg mol^-1)"""
9884
Mc::FT
99-
"""Intercellular O2 mixing ratio (unitless)"""
85+
"""Intercellular O2 mixing ratio (mol mol^-1)"""
10086
oi::FT
10187
"""First order coefficient for temp-dependent Rd (K^-1)"""
10288
aRd::FT
@@ -107,11 +93,9 @@ Base.@kwdef struct PModelConstants{FT}
10793
end
10894

10995
Base.eltype(::PModelParameters{FT}) where {FT} = FT
110-
Base.eltype(::PModelDrivers{FT}) where {FT} = FT
11196
Base.eltype(::PModelConstants{FT}) where {FT} = FT
11297

11398
Base.broadcastable(m::PModelParameters) = tuple(m)
114-
Base.broadcastable(m::PModelDrivers) = tuple(m)
11599
Base.broadcastable(m::PModelConstants) = tuple(m)
116100

117101
"""
@@ -178,10 +162,15 @@ ClimaLand.auxiliary_domain_names(::PModel) =
178162

179163
"""
180164
compute_full_pmodel_outputs(
181-
parameters::PModelParameters,
182-
drivers::PModelDrivers,
183-
constants::PModelConstants
184-
)
165+
parameters::PModelParameters{FT},
166+
constants::PModelConstants{FT},
167+
T_canopy::FT,
168+
I_abs::FT,
169+
ca::FT,
170+
P_air::FT,
171+
VPD::FT,
172+
βm::FT
173+
) where {FT}
185174
186175
Performs the P-model computations as defined in Stocker et al. (2020)
187176
and returns a dictionary of outputs. See https://github.com/geco-bern/rpmodel
@@ -207,15 +196,17 @@ Output name Description (units)
207196
"""
208197
function compute_full_pmodel_outputs(
209198
parameters::PModelParameters{FT},
210-
drivers::PModelDrivers{FT},
211199
constants::PModelConstants{FT},
200+
T_canopy::FT,
201+
I_abs::FT,
202+
ca::FT,
203+
P_air::FT,
204+
VPD::FT,
205+
βm::FT
212206
) where {FT}
213207
# Unpack parameters
214208
(; cstar, β, ϕc, ϕ0, ϕa0, ϕa1, ϕa2) = parameters
215209

216-
# Unpack drivers
217-
(; T_canopy, I_abs, ca, P_air, VPD, βm) = drivers
218-
219210
# Unpack constants
220211
(;
221212
R,
@@ -246,7 +237,7 @@ function compute_full_pmodel_outputs(
246237
ϕ0 = isnan(ϕ0) ? intrinsic_quantum_yield(T_canopy, ϕc, ϕa0, ϕa1, ϕa2) : ϕ0
247238

248239
Γstar = co2_compensation_p(T_canopy, To, P_air, R, ΔHΓstar, Γstar25)
249-
ηstar = compute_viscosity_ratio(T_canopy, P_air, true)
240+
ηstar = compute_viscosity_ratio(T_canopy, P_air)
250241
Kmm = compute_Kmm(T_canopy, P_air, Kc25, Ko25, ΔHkc, ΔHko, To, R, oi)
251242
χ, ξ, mj, mc = optimal_co2_ratio_c3(Kmm, Γstar, ηstar, ca, VPD, β, Drel)
252243
ci = χ * ca

test/Artifacts.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ end
5454
"""
5555
pmodel_unittests_path(; context = nothing)
5656
57-
Returns the filepaths for input-output pairs for the P-model.
57+
Returns the filepaths for input-output pairs for the P-model. This data is generated from the R
58+
implementation of the P-model and is used to test the ClimaLand P-model.
5859
5960
Experiment details are in `test/standalone/Vegetation/test_pmodel.jl`.
6061
"""

test/runtests.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ end
8383
@safetestset "Soil integrated water and energy content" begin
8484
include("standalone/Soil/conservation.jl")
8585
end
86+
@safetestset "Soil spatial parameters" begin
87+
include("standalone/Soil/spatial_parameters.jl")
88+
end
8689

8790
# Standalone Surface Water model tests
8891
@safetestset "Pond module tests" begin
@@ -105,6 +108,9 @@ end
105108
@safetestset "Canopy integrated water and energy content" begin
106109
include("standalone/Vegetation/conservation.jl")
107110
end
111+
@safetestset "Canopy spatial parameters" begin
112+
include("standalone/Vegetation/spatial_parameters.jl")
113+
end
108114
@safetestset "P model tests" begin
109115
include("standalone/Vegetation/test_pmodel.jl")
110116
end

test/standalone/Vegetation/test_pmodel.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,23 @@ end
190190
verbose &&
191191
println("Running test case: $testcase_name with FT = $FT")
192192

193-
# Create constants, drivers, and parameters for the current FT
193+
# prepare constants, parameters, and drivers for the current FT
194194
constants = PModelConstants(FT)
195-
drivers = PModelDrivers(inputs, FT)
196195
parameters = PModelParameters(inputs, FT)
197196

197+
T_canopy = FT(inputs["tc"] + 273.15) # Convert from Celsius to Kelvin
198+
VPD = FT(inputs["vpd"])
199+
ca = FT(inputs["co2"]) * FT(1e-6) * FT(101325.0) # Convert ppm to Pa
200+
P_air = FT(get(inputs, "patm", 101325.0))
201+
I_abs = FT(inputs["fapar"]) * FT(inputs["ppfd"])
202+
βm =
203+
Bool(inputs["do_soilmstress"]) ?
204+
quadratic_soil_moisture_stress(FT(inputs["soilm"])) : FT(1.0)
205+
198206
# Run the model
199207
outputs =
200-
compute_full_pmodel_outputs(parameters, drivers, constants)
208+
compute_full_pmodel_outputs(parameters, constants,
209+
T_canopy, I_abs, ca, P_air, VPD, βm)
201210

202211
# Compare each output field
203212
for key in keys(ref_outputs_typed)

0 commit comments

Comments
 (0)