Skip to content

Commit dc73dff

Browse files
authored
canopy cleanup (#1181)
1 parent 4b9347a commit dc73dff

15 files changed

+250
-259
lines changed

src/diagnostics/default_diagnostics.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ function default_diagnostics(
127127
"gpp",
128128
"an",
129129
"rd",
130-
"vcmax25",
131130
"nir",
132131
"anir",
133132
"rnir",
@@ -295,7 +294,6 @@ function default_diagnostics(
295294
"gpp",
296295
"an",
297296
"rd",
298-
"vcmax25",
299297
"nir",
300298
"anir",
301299
"rnir",

src/diagnostics/land_compute_methods.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ end
211211
} p.canopy.photosynthesis.GPP
212212
@diagnostic_compute "photosynthesis_net_leaf" Union{SoilCanopyModel, LandModel} p.canopy.photosynthesis.An
213213
@diagnostic_compute "respiration_leaf" Union{SoilCanopyModel, LandModel} p.canopy.photosynthesis.Rd
214-
@diagnostic_compute "vcmax25" Union{SoilCanopyModel, LandModel} p.canopy.photosynthesis.Vcmax25
215214

216215
# Canopy - Radiative Transfer
217216
@diagnostic_compute "near_infrared_radiation_down" Union{

src/integrated/land.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -392,8 +392,7 @@ function lsm_radiant_energy_fluxes!(
392392
LW_d = p.drivers.LW_d
393393
SW_d = p.drivers.SW_d
394394

395-
T_canopy =
396-
ClimaLand.Canopy.canopy_temperature(canopy.energy, canopy, Y, p, t)
395+
T_canopy = ClimaLand.Canopy.canopy_temperature(canopy.energy, canopy, Y, p)
397396

398397
α_soil_PAR = p.soil.PAR_albedo
399398
α_soil_NIR = p.soil.NIR_albedo

src/integrated/soil_canopy_model.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,7 @@ function lsm_radiant_energy_fluxes!(
299299
LW_d = p.drivers.LW_d
300300
SW_d = p.drivers.SW_d
301301

302-
T_canopy =
303-
ClimaLand.Canopy.canopy_temperature(canopy.energy, canopy, Y, p, t)
302+
T_canopy = ClimaLand.Canopy.canopy_temperature(canopy.energy, canopy, Y, p)
304303

305304
α_soil_PAR = p.soil.PAR_albedo
306305
α_soil_NIR = p.soil.NIR_albedo

src/standalone/Vegetation/Canopy.jl

Lines changed: 18 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -437,45 +437,22 @@ function ClimaLand.make_update_aux(
437437
# the current time, as they depend on prescribed fields.
438438
set_canopy_prescribed_field!(canopy.hydraulics, p, t)
439439

440-
# Other auxiliary variables being updated:
441-
Ra = p.canopy.autotrophic_respiration.Ra
440+
# Shortcut names
442441
An = p.canopy.photosynthesis.An
443-
GPP = p.canopy.photosynthesis.GPP
444-
Rd = p.canopy.photosynthesis.Rd
445442
ψ = p.canopy.hydraulics.ψ
446443
ϑ_l = Y.canopy.hydraulics.ϑ_l
447444
fa = p.canopy.hydraulics.fa
448445
par_d = p.canopy.radiative_transfer.par_d
449446
nir_d = p.canopy.radiative_transfer.nir_d
450-
451-
bc = canopy.boundary_conditions
452-
# Current atmospheric conditions
453447
cosθs = p.drivers.cosθs
454-
c_co2_air = p.drivers.c_co2
455-
P_air = p.drivers.P
456-
T_air = p.drivers.T
457-
q_air = p.drivers.q
458-
459-
# unpack parameters
460-
earth_param_set = canopy.parameters.earth_param_set
461-
c = LP.light_speed(earth_param_set)
462-
planck_h = LP.planck_constant(earth_param_set)
463-
N_a = LP.avogadro_constant(earth_param_set)
464-
grav = LP.grav(earth_param_set)
465-
ρ_l = LP.ρ_cloud_liq(earth_param_set)
466-
R = LP.gas_constant(earth_param_set)
467-
T_freeze = LP.T_freeze(earth_param_set)
468-
thermo_params = earth_param_set.thermo_params
469-
(; G_Function, Ω, λ_γ_PAR) = canopy.radiative_transfer.parameters
470-
energy_per_mole_photon_par = planck_h * c / λ_γ_PAR * N_a
471-
(; g1, g0, Drel) = canopy.conductance.parameters
472448
area_index = p.canopy.hydraulics.area_index
473449
LAI = area_index.leaf
474450
SAI = area_index.stem
475-
RAI = area_index.root
476-
(; sc, pc) = canopy.photosynthesis.parameters
451+
452+
bc = canopy.boundary_conditions
477453

478454
# update radiative transfer
455+
(; G_Function, Ω, λ_γ_PAR) = canopy.radiative_transfer.parameters
479456
@. p.canopy.radiative_transfer.ϵ =
480457
canopy.radiative_transfer.parameters.ϵ_canopy *
481458
(1 - exp(-(LAI + SAI))) #from CLM 5.0, Tech note 4.20
@@ -554,71 +531,23 @@ function ClimaLand.make_update_aux(
554531
),
555532
) * PlantHydraulics.harmonic_mean(areaip1, areai)
556533
end
557-
# We update the fa[n_stem+n_leaf] element once we have computed transpiration, below
558-
# update photosynthesis and conductance terms
559-
# This should still use T_air, P_air, q_air
560-
medlyn_factor =
561-
@. lazy(medlyn_term(g1, T_air, P_air, q_air, thermo_params))
562-
# Anywhere we use an Arrhenius factor, use T_canopy instead T_air
563-
T_canopy = canopy_temperature(canopy.energy, canopy, Y, p, t)
564-
565-
# update moisture stress
566-
i_end = n_stem + n_leaf
567-
β = @. lazy(moisture_stress(ψ.:($$i_end) * ρ_l * grav, sc, pc))
568-
569-
# Update Rd, An, Vcmax25 (if applicable to model) in place
570-
Vcmax25 = p.canopy.photosynthesis.Vcmax25
571-
update_photosynthesis!(
572-
Rd,
573-
An,
574-
Vcmax25,
575-
canopy.photosynthesis,
576-
T_canopy,
577-
p.canopy.radiative_transfer.par.abs,
578-
β,
579-
medlyn_factor,
580-
c_co2_air,
581-
R,
582-
energy_per_mole_photon_par,
583-
par_d,
584-
)
534+
# We update the fa[n_stem+n_leaf] element once we have computed transpiration
535+
536+
# Update Rd, An, Vcmax25 (if applicable to model) in place, GPP
537+
update_photosynthesis!(p, Y, canopy.photosynthesis, canopy)
538+
585539
# update SIF
586-
SIF = p.canopy.sif.SIF
587-
update_SIF!(
588-
SIF,
589-
canopy.sif,
590-
p.canopy.radiative_transfer.par.abs,
591-
T_canopy,
592-
Vcmax25,
593-
R,
594-
T_freeze,
595-
canopy.photosynthesis.parameters,
596-
energy_per_mole_photon_par,
597-
par_d,
598-
)
599-
@. GPP = compute_GPP(An, extinction_coeff(G_Function, cosθs), LAI, Ω)
600-
@. p.canopy.conductance.r_stomata_canopy =
601-
1 / upscale_leaf_conductance(
602-
medlyn_conductance(g0, Drel, medlyn_factor, An, c_co2_air), #conductance, leaf level
603-
LAI,
604-
T_air,
605-
R,
606-
P_air,
607-
)
540+
update_SIF!(p, Y, canopy.sif, canopy)
541+
542+
# update stomatal conductance
543+
update_canopy_conductance!(p, Y, canopy.conductance, canopy)
544+
608545
# update autotrophic respiration
609-
h_canopy = hydraulics.compartment_surfaces[end]
610-
@. Ra = compute_autrophic_respiration(
546+
update_autotrophic_respiration!(
547+
p,
548+
Y,
611549
canopy.autotrophic_respiration,
612-
Vcmax25,
613-
LAI,
614-
SAI,
615-
RAI,
616-
extinction_coeff(G_Function, cosθs),
617-
Ω,
618-
An,
619-
Rd,
620-
β,
621-
h_canopy,
550+
canopy,
622551
)
623552
end
624553
return update_aux!

src/standalone/Vegetation/autotrophic_respiration.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,59 @@ ClimaLand.auxiliary_types(model::AutotrophicRespirationModel{FT}) where {FT} =
5757
(FT,)
5858
ClimaLand.auxiliary_domain_names(::AutotrophicRespirationModel) = (:surface,)
5959

60+
61+
62+
"""
63+
update_autotrophic_respiration!(p, Y, autotrophic_respiration::AutotrophicRespirationModel, canopy)
64+
65+
Computes the autotrophic respiration rate (mol co2 m^-2 s^-1) as the sum of the plant maintenance
66+
and growth respirations, according to the JULES model.
67+
68+
Clark, D. B., et al. "The Joint UK Land Environment Simulator (JULES), model
69+
description–Part 2: carbon fluxes and vegetation dynamics." Geoscientific Model Development 4.3 (2011): 701-722.
70+
"""
71+
function update_autotrophic_respiration!(
72+
p,
73+
Y,
74+
autotrophic_respiration::AutotrophicRespirationModel,
75+
canopy,
76+
)
77+
hydraulics = canopy.hydraulics
78+
n_stem = hydraulics.n_stem
79+
n_leaf = hydraulics.n_leaf
80+
h_canopy = hydraulics.compartment_surfaces[end]
81+
i_end = n_stem + n_leaf
82+
ψ = p.canopy.hydraulics.ψ
83+
area_index = p.canopy.hydraulics.area_index
84+
LAI = area_index.leaf
85+
SAI = area_index.stem
86+
RAI = area_index.root
87+
earth_param_set = canopy.parameters.earth_param_set
88+
grav = LP.grav(earth_param_set)
89+
ρ_l = LP.ρ_cloud_liq(earth_param_set)
90+
(; sc, pc) = canopy.photosynthesis.parameters
91+
(; G_Function, Ω) = canopy.radiative_transfer.parameters
92+
cosθs = p.drivers.cosθs
93+
An = p.canopy.photosynthesis.An
94+
Rd = p.canopy.photosynthesis.Rd
95+
96+
β = @. lazy(moisture_stress(ψ.:($$i_end) * ρ_l * grav, sc, pc))
97+
Vcmax25 = get_Vcmax25(p, canopy.photosynthesis)
98+
@. p.canopy.autotrophic_respiration.Ra = compute_autrophic_respiration(
99+
autotrophic_respiration,
100+
Vcmax25,
101+
LAI,
102+
SAI,
103+
RAI,
104+
extinction_coeff(G_Function, cosθs),
105+
Ω,
106+
An,
107+
Rd,
108+
β,
109+
h_canopy,
110+
)
111+
end
112+
60113
"""
61114
compute_autrophic_respiration(model::AutotrophicRespirationModel,
62115
Vcmax25,

src/standalone/Vegetation/canopy_boundary_fluxes.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ A helper function which returns the temperature for the canopy
121121
model.
122122
"""
123123
function ClimaLand.surface_temperature(model::CanopyModel, Y, p, t)
124-
return canopy_temperature(model.energy, model, Y, p, t)
124+
return canopy_temperature(model.energy, model, Y, p)
125125
end
126126

127127
"""

src/standalone/Vegetation/canopy_energy.jl

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ No equation for the energy of the canopy is solved.
3636
struct PrescribedCanopyTempModel{FT} <: AbstractCanopyEnergyModel{FT} end
3737

3838
"""
39-
canopy_temperature(model::PrescribedCanopyTempModel, canopy, Y, p, t)
39+
canopy_temperature(model::PrescribedCanopyTempModel, canopy, Y, p)
4040
4141
Returns the canopy temperature under the `PrescribedCanopyTemp` model,
4242
where the canopy temperature is assumed to be the same as the atmosphere
4343
temperature.
4444
"""
45-
function canopy_temperature(model::PrescribedCanopyTempModel, canopy, Y, p, t)
45+
function canopy_temperature(model::PrescribedCanopyTempModel, canopy, Y, p)
4646
p.drivers.T
4747
end
4848

@@ -86,13 +86,12 @@ ClimaLand.prognostic_types(model::BigLeafEnergyModel{FT}) where {FT} = (FT,)
8686
ClimaLand.prognostic_domain_names(model::BigLeafEnergyModel) = (:surface,)
8787

8888
"""
89-
canopy_temperature(model::BigLeafEnergyModel, canopy, Y, p, t)
89+
canopy_temperature(model::BigLeafEnergyModel, canopy, Y, p)
9090
9191
Returns the canopy temperature under the `BigLeafEnergyModel` model,
9292
where the canopy temperature is modeled prognostically.
9393
"""
94-
canopy_temperature(model::BigLeafEnergyModel, canopy, Y, p, t) =
95-
Y.canopy.energy.T
94+
canopy_temperature(model::BigLeafEnergyModel, canopy, Y, p) = Y.canopy.energy.T
9695

9796
function make_compute_imp_tendency(
9897
model::BigLeafEnergyModel{FT},
@@ -110,19 +109,17 @@ function make_compute_imp_tendency(
110109
# area index on the LHF, as ac_canopy [J/m^2/K]
111110
# is per unit area plant.
112111

112+
# d(energy.T) = - net_energy_flux / specific_heat_capacity
113113
# To prevent dividing by zero, change AI" to
114114
# "max(AI, eps(FT))"
115-
c_per_ground_area =
116-
@. ac_canopy * max(area_index.leaf + area_index.stem, eps(FT))
117115

118-
# d(energy.T) = - net_energy_flux / specific_heat_capacity
119116
@. dY.canopy.energy.T =
120117
-(
121118
-p.canopy.radiative_transfer.LW_n -
122119
p.canopy.radiative_transfer.SW_n +
123120
p.canopy.turbulent_fluxes.shf +
124121
p.canopy.turbulent_fluxes.lhf - p.canopy.energy.fa_energy_roots
125-
) / c_per_ground_area
122+
) / (ac_canopy * max(area_index.leaf + area_index.stem, eps(FT)))
126123
end
127124
return compute_imp_tendency!
128125
end

0 commit comments

Comments
 (0)