Skip to content

Commit ac406d2

Browse files
committed
Add a AbstractSoilMoistureStressModel, 3 methods
This commits adds a portion of Yuchen Li PR #1330, a new Canopy component: AbstractSoilMoistureStressModel, with 3 methods: the existing one (Tuzet) which was previously in PlantHydraulics, a Piecewise method using dry to wet soil moisture, and no moisture stress. Co-authored-by: AlexisRenchon <[email protected]> Co-authored-by: ychnli <[email protected]> [skip ci]
1 parent 54a20ee commit ac406d2

File tree

7 files changed

+526
-77
lines changed

7 files changed

+526
-77
lines changed

src/integrated/land.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,17 @@ function LandModel{FT}(;
184184
energy_model = PrescribedCanopyTempModel{FT}()
185185
end
186186

187+
if :soil_moisture_stress in propertynames(canopy_component_types)
188+
soil_moisture_stress_model =
189+
canopy_component_types.soil_moisture_stress(
190+
canopy_component_args.soil_moisture_stress...,
191+
)
192+
else
193+
@info "No soil moisture stress model provided, using NoMoistureStressModel (βm = 1.0)"
194+
soil_moisture_stress_model =
195+
ClimaLand.Canopy.NoMoistureStressModel{FT}()
196+
end
197+
187198
canopy = Canopy.CanopyModel{FT}(;
188199
autotrophic_respiration = canopy_component_types.autotrophic_respiration(
189200
canopy_component_args.autotrophic_respiration...,
@@ -197,6 +208,7 @@ function LandModel{FT}(;
197208
conductance = canopy_component_types.conductance(
198209
canopy_component_args.conductance...,
199210
),
211+
soil_moisture_stress = soil_moisture_stress_model,
200212
hydraulics = canopy_component_types.hydraulics(;
201213
transpiration = transpiration,
202214
canopy_component_args.hydraulics...,

src/standalone/Vegetation/Canopy.jl

Lines changed: 93 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export SharedCanopyParameters, CanopyModel, set_canopy_prescribed_field!
4040
include("./component_models.jl")
4141
include("./PlantHydraulics.jl")
4242
using .PlantHydraulics
43+
include("./soil_moisture_stress.jl")
4344
include("./stomatalconductance.jl")
4445
include("./photosynthesis.jl")
4546
include("./photosynthesis_farquhar.jl")
@@ -137,8 +138,6 @@ end
137138
ϕa1 = FT(0.022),
138139
ϕa2 = FT(-0.00034),
139140
α = FT(0.933),
140-
sc = LP.get_default_parameter(FT, :low_water_pressure_sensitivity),
141-
pc = LP.get_default_parameter(FT, :moisture_stress_ref_water_pressure),
142141
) where {FT <: AbstractFloat}
143142
144143
Constructs a P-model (an optimality model for photosynthesis) using default parameters.
@@ -153,10 +152,7 @@ The following default parameters are used:
153152
- ϕa1 = 0.022 (K^-1) - first order term in quadratic intrinsic quantum yield (Stocker 2020)
154153
- ϕa2 = -0.00034 (K^-2) - second order term in quadratic intrinsic quantum yield (Stocker 2020)
155154
- α = 0.933 (unitless) - 1 - 1/T where T is the timescale of Vcmax, Jmax acclimation. Here T = 15 days. (Mengoli 2022)
156-
- sc = 5e-6 (Pa^{-1}) - sensitivity to low water pressure in the moisture stress factor [Tuzet et al. (2003)]
157-
- pc = -2e6 (Pa) - reference water pressure for the moisture stress factor [Tuzet et al. (2003)]
158155
"""
159-
160156
function PModel{FT}(;
161157
cstar = FT(0.41),
162158
β = FT(146),
@@ -166,8 +162,6 @@ function PModel{FT}(;
166162
ϕa1 = FT(0.022),
167163
ϕa2 = FT(-0.00034),
168164
α = FT(0.933),
169-
sc = LP.get_default_parameter(FT, :low_water_pressure_sensitivity),
170-
pc = LP.get_default_parameter(FT, :moisture_stress_ref_water_pressure),
171165
) where {FT <: AbstractFloat}
172166
parameters = ClimaLand.Canopy.PModelParameters(
173167
cstar = cstar,
@@ -178,8 +172,6 @@ function PModel{FT}(;
178172
ϕa1 = ϕa1,
179173
ϕa2 = ϕa2,
180174
α = α,
181-
sc = sc,
182-
pc = pc,
183175
)
184176

185177
return PModel{FT}(parameters)
@@ -402,6 +394,22 @@ function PModelConductance{FT}(; Drel = FT(1.6)) where {FT <: AbstractFloat}
402394
return PModelConductance{FT}(cond_params)
403395
end
404396

397+
"""
398+
TuzetMoistureStressModel{FT}() where {FT <: AbstractFloat}
399+
Creates a TuzetMoistureStressModel using default parameters of type FT.
400+
The parameters are set to:
401+
- sc = 5e-6 (Pa^{-1}) - sensitivity to low water pressure
402+
- pc = -2e6 (Pa) - reference water pressure for the moisture stress factor
403+
"""
404+
function TuzetMoistureStressModel{FT}(;
405+
sc = LP.get_default_parameter(FT, :low_water_pressure_sensitivity),
406+
pc = LP.get_default_parameter(FT, :moisture_stress_ref_water_pressure),
407+
) where {FT <: AbstractFloat}
408+
parameters = TuzetMoistureStressParameters{FT}(sc, pc)
409+
return TuzetMoistureStressModel{eltype(parameters), typeof(parameters)}(
410+
parameters,
411+
)
412+
end
405413

406414
########################################################
407415
# End component model convenience constructors
@@ -423,19 +431,23 @@ struct SharedCanopyParameters{FT <: AbstractFloat, PSE}
423431
end
424432

425433
"""
426-
CanopyModel{FT, AR, RM, PM, SM, PHM, EM, SM, A, R, S, PS, D} <: ClimaLand.AbstractImExModel{FT}
434+
CanopyModel{FT, AR, RM, PM, SM, PHM, EM, SM, SMSM, A, R, S, PS, D} <: ClimaLand.AbstractImExModel{FT}
427435
428436
The model struct for the canopy, which contains
429437
- the canopy model domain (a point for site-level simulations, or
430438
an extended surface (plane/spherical surface) for regional or global simulations.
431439
- subcomponent model type for radiative transfer. This is of type
432440
`AbstractRadiationModel`.
433441
- subcomponent model type for photosynthesis. This is of type
434-
`AbstractPhotosynthesisModel`, and currently only the `FarquharModel`
435-
is supported.
442+
`AbstractPhotosynthesisModel` and supports `FarquharModel`, and `PModel`.
436443
- subcomponent model type for stomatal conductance. This is of type
437-
`AbstractStomatalConductanceModel` and currently only the `MedlynModel`
438-
is supported
444+
`AbstractStomatalConductanceModel` and supports `MedlynConductanceModel` and
445+
`PModelConductance`. Note if `PModel` is used for photosynthesis, then you
446+
must also use `PModelConductance` for stomatal conductance, since these two models
447+
are derived from the same set of conditions.
448+
- subcomponent model type for soil moisture stress. This is of type
449+
`AbstractSoilMoistureStressModel`. Currently we support `TuzetMoistureStressModel` (default)
450+
`PiecewiseMoistureStressModel`, and `NoMoistureStressModel` (stress factor = 1).
439451
- subcomponent model type for plant hydraulics. This is of type
440452
`AbstractPlantHydraulicsModel` and currently only a version which
441453
prognostically solves Richards equation in the plant is available.
@@ -465,7 +477,7 @@ treated differently.
465477
466478
$(DocStringExtensions.FIELDS)
467479
"""
468-
struct CanopyModel{FT, AR, RM, PM, SM, PHM, EM, SIFM, B, PS, D} <:
480+
struct CanopyModel{FT, AR, RM, PM, SM, SMSM, PHM, EM, SIFM, B, PS, D} <:
469481
ClimaLand.AbstractImExModel{FT}
470482
"Autotrophic respiration model, a canopy component model"
471483
autotrophic_respiration::AR
@@ -475,6 +487,8 @@ struct CanopyModel{FT, AR, RM, PM, SM, PHM, EM, SIFM, B, PS, D} <:
475487
photosynthesis::PM
476488
"Stomatal conductance model, a canopy component model"
477489
conductance::SM
490+
"Soil moisture stress parameterization, a canopy component model"
491+
soil_moisture_stress::SMSM
478492
"Plant hydraulics model, a canopy component model"
479493
hydraulics::PHM
480494
"Energy balance model, a canopy component model"
@@ -495,6 +509,7 @@ end
495509
radiative_transfer::AbstractRadiationModel{FT},
496510
photosynthesis::AbstractPhotosynthesisModel{FT},
497511
conductance::AbstractStomatalConductanceModel{FT},
512+
soil_moisture_stress::AbstractSoilMoistureStressModel{FT} = TuzetMoistureStressModel{FT}(),
498513
hydraulics::AbstractPlantHydraulicsModel{FT},
499514
energy::AbstractCanopyEnergyModel{FT},
500515
sif::AbstractSIFModel{FT},
@@ -519,6 +534,9 @@ function CanopyModel{FT}(;
519534
radiative_transfer::AbstractRadiationModel{FT},
520535
photosynthesis::AbstractPhotosynthesisModel{FT},
521536
conductance::AbstractStomatalConductanceModel{FT},
537+
soil_moisture_stress::AbstractSoilMoistureStressModel{FT} = TuzetMoistureStressModel{
538+
FT,
539+
}(),
522540
hydraulics::AbstractPlantHydraulicsModel{FT},
523541
energy = PrescribedCanopyTempModel{FT}(),
524542
sif = Lee2015SIFModel{FT}(),
@@ -548,6 +566,7 @@ function CanopyModel{FT}(;
548566
radiative_transfer,
549567
photosynthesis,
550568
conductance,
569+
soil_moisture_stress,
551570
hydraulics,
552571
energy,
553572
sif,
@@ -575,6 +594,7 @@ end
575594
radiative_transfer = TwoStreamModel{FT}(domain),
576595
photosynthesis = FarquharModel{FT}(domain),
577596
conductance = MedlynConductanceModel{FT}(domain),
597+
soil_moisture_stress = TuzetMoistureStressModel{FT}(),
578598
hydraulics = PlantHydraulicsModel{FT}(domain, LAI, toml_dict),
579599
energy = BigLeafEnergyModel{FT}(),
580600
sif = Lee2015SIFModel{FT}(),
@@ -614,6 +634,7 @@ function CanopyModel{FT}(
614634
radiative_transfer = TwoStreamModel{FT}(domain),
615635
photosynthesis = FarquharModel{FT}(domain),
616636
conductance = MedlynConductanceModel{FT}(domain),
637+
soil_moisture_stress = TuzetMoistureStressModel{FT}(),
617638
hydraulics = PlantHydraulicsModel{FT}(domain, LAI, toml_dict),
618639
energy = BigLeafEnergyModel{FT}(),
619640
sif = Lee2015SIFModel{FT}(),
@@ -631,6 +652,7 @@ function CanopyModel{FT}(
631652
radiative_transfer,
632653
photosynthesis,
633654
conductance,
655+
soil_moisture_stress,
634656
hydraulics,
635657
energy,
636658
sif,
@@ -691,6 +713,7 @@ canopy_components(::CanopyModel) = (
691713
:autotrophic_respiration,
692714
:energy,
693715
:sif,
716+
:soil_moisture_stress,
694717
)
695718

696719
"""
@@ -878,13 +901,18 @@ function initialize_boundary_vars(model::CanopyModel{FT}, coords) where {FT}
878901
end
879902

880903
"""
881-
ClimaLand.make_update_aux(canopy::CanopyModel{FT,
882-
<:AutotrophicRespirationModel,
883-
<:AbstractRadiationModel,
884-
<:AbstractPhotosynthesisModel,
885-
<:AbstractStomatalConductanceModel,
886-
<:PlantHydraulicsModel,},
887-
) where {FT}
904+
ClimaLand.make_update_aux(
905+
canopy::CanopyModel{
906+
FT,
907+
<:AutotrophicRespirationModel,
908+
<:AbstractRadiationModel,
909+
<:AbstractPhotosynthesisModel,
910+
<:AbstractStomatalConductanceModel,
911+
<:PlantHydraulicsModel,
912+
<:AbstractCanopyEnergyModel,
913+
<:AbstractSoilMoistureStressModel,
914+
},
915+
) where {FT}
888916
889917
Creates the `update_aux!` function for the `CanopyModel`; a specific
890918
method for `update_aux!` for the case where the canopy model components
@@ -909,6 +937,7 @@ function ClimaLand.make_update_aux(
909937
<:AbstractStomatalConductanceModel,
910938
<:PlantHydraulicsModel,
911939
<:AbstractCanopyEnergyModel,
940+
<:AbstractSoilMoistureStressModel,
912941
},
913942
) where {FT}
914943
function update_aux!(p, Y, t)
@@ -1015,6 +1044,9 @@ function ClimaLand.make_update_aux(
10151044
end
10161045
# We update the fa[n_stem+n_leaf] element once we have computed transpiration
10171046

1047+
# Update soil moisture stress, used in photosynthesis and conductance
1048+
update_soil_moisture_stress!(p, Y, canopy.soil_moisture_stress, canopy)
1049+
10181050
# Update Rd, An, Vcmax25 (if applicable to model) in place, GPP
10191051
update_photosynthesis!(p, Y, canopy.photosynthesis, canopy)
10201052

@@ -1049,6 +1081,7 @@ function make_compute_exp_tendency(
10491081
<:AbstractStomatalConductanceModel,
10501082
<:PlantHydraulicsModel,
10511083
<:AbstractCanopyEnergyModel,
1084+
<:AbstractSoilMoistureStressModel,
10521085
},
10531086
) where {FT}
10541087
components = canopy_components(canopy)
@@ -1079,6 +1112,7 @@ function make_compute_imp_tendency(
10791112
<:AbstractStomatalConductanceModel,
10801113
<:PlantHydraulicsModel,
10811114
<:AbstractCanopyEnergyModel,
1115+
<:AbstractSoilMoistureStressModel,
10821116
},
10831117
) where {FT}
10841118
components = canopy_components(canopy)
@@ -1216,4 +1250,41 @@ function set_historical_cache!(p, Y0, m::AbstractPhotosynthesisModel, canopy)
12161250
return nothing
12171251
end
12181252

1253+
"""
1254+
required_model_callbacks(start_date, t0, dt, model::CanopyModel)
1255+
For some canopy components (namely the P-model), we need a callback to ensure regular
1256+
updates at a preset frequency. This method dispatches off of the type of the photosynthesis
1257+
model.
1258+
"""
1259+
function required_model_callbacks(start_date, t0, dt, model::CanopyModel)
1260+
return required_photosynthesis_model_callbacks(
1261+
start_date,
1262+
t0,
1263+
dt,
1264+
model,
1265+
model.photosynthesis,
1266+
)
1267+
end
1268+
1269+
1270+
"""
1271+
required_photosynthesis_model_callbacks(
1272+
start_date,
1273+
t0,
1274+
dt,
1275+
canopy,
1276+
photo_model::AbstractPhotosynthesisModel,
1277+
)
1278+
For an AbstractPhotosynthesisModel in general, add no additional model callbacks.
1279+
"""
1280+
function required_photosynthesis_model_callbacks(
1281+
start_date,
1282+
t0,
1283+
dt,
1284+
canopy,
1285+
photo_model::AbstractPhotosynthesisModel,
1286+
)
1287+
return ()
1288+
end
1289+
12191290
end

src/standalone/Vegetation/autotrophic_respiration.jl

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ abstract type AbstractAutotrophicRespirationModel{FT} <:
66
"""
77
AutotrophicRespirationParameters{FT<:AbstractFloat}
88
9-
The required parameters for the autrophic respiration model, which is based
9+
The required parameters for the autrophic respiration model, which is based
1010
off of the JULES model.
1111
Clark, D. B., et al. "The Joint UK Land Environment Simulator (JULES), model description–Part 2: carbon fluxes and vegetation dynamics." Geoscientific Model Development 4.3 (2011): 701-722.
1212
$(DocStringExtensions.FIELDS)
@@ -29,7 +29,7 @@ end
2929
Base.eltype(::AutotrophicRespirationParameters{FT}) where {FT} = FT
3030

3131
"""
32-
AutotrophicRespirationModel{FT, ARP <: AutotrophicRespirationParameters{FT},} <: AbstractAutotrophicRespirationModel{FT}
32+
AutotrophicRespirationModel{FT, ARP <: AutotrophicRespirationParameters{FT},} <: AbstractAutotrophicRespirationModel{FT}
3333
3434
The JULES autotrophic respiration model.
3535
@@ -65,7 +65,7 @@ ClimaLand.auxiliary_domain_names(::AutotrophicRespirationModel) = (:surface,)
6565
Computes the autotrophic respiration rate (mol co2 m^-2 s^-1) as the sum of the plant maintenance
6666
and growth respirations, according to the JULES model.
6767
68-
Clark, D. B., et al. "The Joint UK Land Environment Simulator (JULES), model
68+
Clark, D. B., et al. "The Joint UK Land Environment Simulator (JULES), model
6969
description–Part 2: carbon fluxes and vegetation dynamics." Geoscientific Model Development 4.3 (2011): 701-722.
7070
"""
7171
function update_autotrophic_respiration!(
@@ -87,10 +87,9 @@ function update_autotrophic_respiration!(
8787
earth_param_set = canopy.parameters.earth_param_set
8888
grav = LP.grav(earth_param_set)
8989
ρ_l = LP.ρ_cloud_liq(earth_param_set)
90-
(; sc, pc) = canopy.photosynthesis.parameters
9190
(; G_Function, Ω) = canopy.radiative_transfer.parameters
9291
cosθs = p.drivers.cosθs
93-
β = @. lazy(moisture_stress(ψ.:($$i_end) * ρ_l * grav, sc, pc))
92+
β = p.canopy.soil_moisture_stress.βm
9493
Vcmax25_leaf = get_Vcmax25_leaf(p, canopy.photosynthesis)
9594
Rd_leaf = get_Rd_leaf(p, canopy.photosynthesis)
9695
An_leaf = get_An_leaf(p, canopy.photosynthesis)

src/standalone/Vegetation/canopy_boundary_fluxes.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,8 @@ end
161161
<:AbstractPhotosynthesisModel,
162162
<:AbstractStomatalConductanceModel,
163163
<:PlantHydraulicsModel,
164-
<:AbstractCanopyEnergyModel}
164+
<:AbstractCanopyEnergyModel,
165+
<:AbstractSoilMoistureStressModel,
165166
},
166167
Y::ClimaCore.Fields.FieldVector,
167168
t,
@@ -188,6 +189,7 @@ function canopy_boundary_fluxes!(
188189
<:AbstractStomatalConductanceModel,
189190
<:PlantHydraulicsModel,
190191
<:AbstractCanopyEnergyModel,
192+
<:AbstractSoilMoistureStressModel,
191193
},
192194
Y::ClimaCore.Fields.FieldVector,
193195
t,

src/standalone/Vegetation/canopy_parameterizations.jl

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ export canopy_sw_rt_beer_lambert, # Radiative transfer
33
canopy_sw_rt_two_stream,
44
extinction_coeff,
55
compute_G,
6-
moisture_stress,
76
# Conductance
87
medlyn_term,
98
medlyn_conductance,
@@ -392,24 +391,6 @@ function extinction_coeff(G_Function, cosθs::FT) where {FT}
392391
return K
393392
end
394393

395-
"""
396-
moisture_stress(pl::FT,
397-
sc::FT,
398-
pc::FT) where {FT}
399-
400-
Computes the moisture stress factor (`β`), which is unitless,
401-
as a function of
402-
a constant (`sc`, 1/Pa), a reference pressure (`pc`, Pa), and
403-
the leaf water pressure (`pl`, Pa) .
404-
405-
See Eqn 12.57 of G. Bonan's textbook,
406-
Climate Change and Terrestrial Ecosystem Modeling (2019).
407-
"""
408-
function moisture_stress(pl::FT, sc::FT, pc::FT) where {FT}
409-
β = min(FT(1), (1 + exp(sc * pc)) / (1 + exp(sc * (pc - pl))))
410-
return β
411-
end
412-
413394
"""
414395
conductance_molar_flux_to_m_per_s(gs::FT, T::FT, R::FT, P::FT) where {FT}
415396

0 commit comments

Comments
 (0)