Skip to content

Commit

Permalink
Extend photosynthesis mechanism to support fields
Browse files Browse the repository at this point in the history
This change is applied to both OptimalityFarquharParameters
and FarquharParameters. Previously, the mechanism parameter
was held as an empty struct of type ::C3 or ::C4 to allow
for dispatch. Because it is not possible to create a
ClimaCore field of different structs, the mechanism param is changed to a
is_c3 param that holds 1s and 0s. This choice was made because
reading a NetCDF file requires regridding, which must be performed over Numbers.
If the input data file must store the mechanism as a float, then it is easiest to
also internally represent the mechanism as a float. The C3/C4 structs
are now removed. The functions that previously used C3/C4 structs for dispatching
are converted to two seperate functions, which are called based on the is_c3 value.

The constructor checks that the mechanism value of field is
between 0 and 1, and throws an error otherwise. Regridding a field of
0s and 1s may result in values between 0 and 1, so the constuctor rounds them
to the nearest integer. This implementation allows for future support of
mixed mechanisms in an area represented by proportion c3 without many changes.

All calls to the FarquharParameters constructor are changed to
work with the changes to mechanism representation. Tests are also
changed to work with new constructor and representation of mechanism.

The tests in canopy_model are changed to run twice using a for loop. The first run has all the parameters
as floats, and the second run has all canopy parameters that can be fields as fields. In this
case, the photosynthesis mechanism is tested as a field that alternates between 1.0 and 0.0,
which represents alternating between C3 and C4. The tests were previously all run over a Point
domain. The tests that use FarquharParameters are changed to run on a spherical surface.
Additionally, a test for vcmax as a field is added.

Land.jl and land_region.jl are changed to use the mechanism map from
the clm data.
  • Loading branch information
imreddyTeja committed Sep 17, 2024
1 parent b47ef0f commit 3e9a73a
Show file tree
Hide file tree
Showing 28 changed files with 244 additions and 159 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ ClimaLand.jl Release Notes
main
--------
- Add regional simulation example PR [#757](https://github.com/CliMA/ClimaLand.jl/pull/757)
- ![][badge-💥breaking] Extend photosynthesis mechanism parameter to support fields.
PR[#774](https://github.com/CliMA/ClimaLand.jl/pull/774)

v0.14.3
--------
Expand Down
7 changes: 4 additions & 3 deletions docs/src/standalone/apps/leaf_an.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@ function ParamViz.parameterisation(
Γstar = co2_compensation(Γstar25, ΔHΓstar, T, To, R)
medlynt = 1 + g1 / sqrt(VPD)
ci = intercellular_co2(ca, Γstar, medlynt)
Aj = light_assimilation(Canopy.C3(), J, ci, Γstar)
is_c3 = 1.0
Aj = light_assimilation(is_c3, J, ci, Γstar)
Kc = MM_Kc(Kc25, ΔHkc, T, To, R)
Ko = MM_Ko(Ko25, ΔHko, T, To, R)
Ac = rubisco_assimilation(Canopy.C3(), Vcmax, ci, Γstar, Kc, Ko, oi)
Ac = rubisco_assimilation(is_c3, Vcmax, ci, Γstar, Kc, Ko, oi)
Rd = dark_respiration(Vcmax25, β, f, ΔHRd, T, To, R)
An = net_photosynthesis(Ac, Aj, Rd, β)
return An
Expand Down Expand Up @@ -83,7 +84,7 @@ function An_app_f()
"Ω", # Clumping index
"Γstar25", # co2 compensation at 25c
"ΔHΓstar", # a constant energy of activation
"To", # a standard temperature
"To", # a standard temperature
"R", # the universal gas constant
"Vcmax25", # the maximum rate of carboxylation of Rubisco
"ΔHJmax", # a constant
Expand Down
7 changes: 4 additions & 3 deletions docs/src/standalone/apps/leaf_an_ci.jl
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,9 @@ function ParamViz.parameterisation(
Γstar = co2_compensation(Γstar25, ΔHΓstar, T, To, R)
Kc = MM_Kc(Kc25, ΔHkc, T, To, R)
Ko = MM_Ko(Ko25, ΔHko, T, To, R)
Ac = rubisco_assimilation(Canopy.C3(), Vcmax, ci, Γstar, Kc, Ko, oi)
Aj = light_assimilation(Canopy.C3(), J, ci, Γstar)
is_c3 = 1.0
Ac = rubisco_assimilation(is_c3, Vcmax, ci, Γstar, Kc, Ko, oi)
Aj = light_assimilation(is_c3, J, ci, Γstar)
Rd = dark_respiration(Vcmax25, β, f, ΔHRd, T, To, R)
An = net_photosynthesis(Ac, Aj, Rd, β)
return An
Expand Down Expand Up @@ -79,7 +80,7 @@ function An_ci_app_f()
"Ω", # Clumping index
"Γstar25", # co2 compensation at 25c
"ΔHΓstar", # a constant energy of activation
"To", # a standard temperature
"To", # a standard temperature
"R", # the universal gas constant
"ΔHJmax", # a constant
"θj", # an empirical "curvature parameter"
Expand Down
3 changes: 2 additions & 1 deletion docs/tutorials/integrated/soil_canopy_tutorial.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,8 +231,9 @@ radiative_transfer_args = (;

conductance_args = (; parameters = MedlynConductanceParameters(FT; g1 = 141))

is_c3 = FT(1) # set the photosynthesis mechanism to C3
photosynthesis_args =
(; parameters = FarquharParameters(FT, Canopy.C3(); Vcmax25 = FT(5e-5)));
(; parameters = FarquharParameters(FT, is_c3; Vcmax25 = FT(5e-5)));

K_sat_plant = FT(1.8e-8)
RAI = (SAI + maxLAI) * f_root_to_shoot;
Expand Down
6 changes: 3 additions & 3 deletions docs/tutorials/standalone/Canopy/canopy_tutorial.jl
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ land_domain = Point(; z_sfc = FT(0.0))
# the simulation with atmospheric and radiative flux models. We also
# read in the observed LAI and let that vary in time in a prescribed manner.

# Use the data tools for reading FLUXNET data sets
# Use the data tools for reading FLUXNET data sets
include(
joinpath(pkgdir(ClimaLand), "experiments/integrated/fluxnet/data_tools.jl"),
);
Expand Down Expand Up @@ -174,8 +174,8 @@ cond_params = MedlynConductanceParameters(FT; g1 = FT(141.0))
stomatal_model = MedlynConductanceModel{FT}(cond_params);

# Arguments for photosynthesis model:

photo_params = FarquharParameters(FT, Canopy.C3(); Vcmax25 = FT(5e-5))
is_c3 = FT(1) # set the photosynthesis mechanism to C3
photo_params = FarquharParameters(FT, is_c3; Vcmax25 = FT(5e-5))

photosynthesis_model = FarquharModel{FT}(photo_params);

Expand Down
17 changes: 10 additions & 7 deletions experiments/benchmarks/land.jl
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,14 @@ function setup_prob(t0, tf, Δt; nelements = (101, 15))
regridder_kwargs = (; extrapolation_bc,),
file_reader_kwargs = (; preprocess_func = (data) -> data / 1_000_000,),
)
# photosynthesis mechanism is read as a float, where 1.0 indicates c3 and 0.0 c4
is_c3 = SpaceVaryingInput(
joinpath(clm_artifact_path, "mechanism_map.nc"),
"c3_dominant",
surface_space;
regridder_type,
regridder_kwargs = (; extrapolation_bc,),
)

# Plant Hydraulics and general plant parameters
SAI = FT(0.0) # m2/m2
Expand Down Expand Up @@ -465,13 +473,8 @@ function setup_prob(t0, tf, Δt; nelements = (101, 15))
conductance_args =
(; parameters = Canopy.MedlynConductanceParameters(FT; g1))
# Set up photosynthesis
photosynthesis_args = (;
parameters = Canopy.FarquharParameters(
FT,
Canopy.C3();
Vcmax25 = Vcmax25,
)
)
photosynthesis_args =
(; parameters = Canopy.FarquharParameters(FT, is_c3; Vcmax25 = Vcmax25))
# Set up plant hydraulics
# Note that we clip all values of LAI below 0.05 to zero.
# This is because we currently run into issues when LAI is
Expand Down
3 changes: 2 additions & 1 deletion experiments/integrated/fluxnet/ozark_pft.jl
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,9 @@ radiative_transfer_args = (;
conductance_args = (; parameters = MedlynConductanceParameters(FT; g1))
# Set up photosynthesis
# Set up photosynthesis
is_c3 = FT(1) # set the photosynthesis mechanism to C3
photosynthesis_args =
(; parameters = FarquharParameters(FT, Canopy.C3(); Vcmax25 = Vcmax25))
(; parameters = FarquharParameters(FT, is_c3; Vcmax25 = Vcmax25))
# Set up plant hydraulics
ai_parameterization = PrescribedSiteAreaIndex{FT}(LAIfunction, SAI, RAI)

Expand Down
3 changes: 2 additions & 1 deletion experiments/integrated/fluxnet/run_fluxnet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,9 @@ radiative_transfer_args = (;
# Set up conductance
conductance_args = (; parameters = MedlynConductanceParameters(FT; g1))
# Set up photosynthesis
is_c3 = FT(1) # set the photosynthesis mechanism to C3
photosynthesis_args =
(; parameters = FarquharParameters(FT, Canopy.C3(); Vcmax25 = Vcmax25))
(; parameters = FarquharParameters(FT, is_c3; Vcmax25 = Vcmax25))
# Set up plant hydraulics
ai_parameterization = PrescribedSiteAreaIndex{FT}(LAIfunction, SAI, RAI)

Expand Down
6 changes: 3 additions & 3 deletions experiments/integrated/global/global_soil_canopy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -222,9 +222,9 @@ radiative_transfer_args = (;
# Set up conductance
conductance_args = (; parameters = Canopy.MedlynConductanceParameters(FT; g1))
# Set up photosynthesis
photosynthesis_args = (;
parameters = Canopy.FarquharParameters(FT, Canopy.C3(); Vcmax25 = Vcmax25)
)
is_c3 = FT(1) # set the photosynthesis mechanism to C3
photosynthesis_args =
(; parameters = Canopy.FarquharParameters(FT, is_c3; Vcmax25 = Vcmax25))
# Set up plant hydraulics
# Not ideal
LAIfunction = TimeVaryingInput(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,9 @@ radiative_transfer_args = (;
# Set up conductance
conductance_args = (; parameters = MedlynConductanceParameters(FT; g1))
# Set up photosynthesis
is_c3 = FT(1) # set the photosynthesis mechanism to C3
photosynthesis_args =
(; parameters = FarquharParameters(FT, Canopy.C3(); Vcmax25 = Vcmax25))
(; parameters = FarquharParameters(FT, is_c3; Vcmax25 = Vcmax25))
# Set up plant hydraulics
ai_parameterization = PrescribedSiteAreaIndex{FT}(LAIfunction, SAI, RAI)

Expand Down
3 changes: 2 additions & 1 deletion experiments/integrated/performance/profile_allocations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,9 @@ radiative_transfer_args = (; parameters = TwoStreamParameters(FT))
# Set up conductance
conductance_args = (; parameters = MedlynConductanceParameters(FT; g1))
# Set up photosynthesis
is_c3 = FT(1) # set the photosynthesis mechanism to C3
photosynthesis_args =
(; parameters = FarquharParameters(FT, Canopy.C3(); Vcmax25 = Vcmax25))
(; parameters = FarquharParameters(FT, is_c3; Vcmax25 = Vcmax25))
# Set up plant hydraulics
ai_parameterization = PrescribedSiteAreaIndex{FT}(LAIfunction, SAI, RAI)
function root_distribution(z::T) where {T}
Expand Down
18 changes: 10 additions & 8 deletions experiments/long_runs/land.jl
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,14 @@ function setup_prob(t0, tf, Δt; outdir = outdir, nelements = (101, 15))
regridder_kwargs = (; extrapolation_bc,),
file_reader_kwargs = (; preprocess_func = (data) -> data / 1_000_000,),
)

# photosynthesis mechanism is read as a float, where 1.0 indicates c3 and 0.0 c4
is_c3 = SpaceVaryingInput(
joinpath(clm_artifact_path, "mechanism_map.nc"),
"c3_dominant",
surface_space;
regridder_type,
regridder_kwargs = (; extrapolation_bc,),
)
# Plant Hydraulics and general plant parameters
SAI = FT(0.0) # m2/m2
f_root_to_shoot = FT(3.5)
Expand Down Expand Up @@ -474,13 +481,8 @@ function setup_prob(t0, tf, Δt; outdir = outdir, nelements = (101, 15))
conductance_args =
(; parameters = Canopy.MedlynConductanceParameters(FT; g1))
# Set up photosynthesis
photosynthesis_args = (;
parameters = Canopy.FarquharParameters(
FT,
Canopy.C3();
Vcmax25 = Vcmax25,
)
)
photosynthesis_args =
(; parameters = Canopy.FarquharParameters(FT, is_c3; Vcmax25 = Vcmax25))
# Set up plant hydraulics

# Note that we clip all values of LAI below 0.05 to zero.
Expand Down
30 changes: 17 additions & 13 deletions experiments/long_runs/land_region.jl
Original file line number Diff line number Diff line change
Expand Up @@ -368,8 +368,18 @@ function setup_prob(t0, tf, Δt; outdir = outdir, nelements = (10, 10, 15))

# Energy Balance model
ac_canopy = FT(2.5e4) # this will likely be 10x smaller!

clm_artifact_path = ClimaLand.Artifacts.clm_data_folder_path(; context)
# Conductance Model
# g1 is read in units of sqrt(kPa) and then converted to sqrt(Pa)
g1 = SpaceVaryingInput(
joinpath(clm_artifact_path, "vegetation_properties_map.nc"),
"medlynslope",
surface_space;
regridder_type,
regridder_kwargs = (; extrapolation_bc,),
file_reader_kwargs = (; preprocess_func = (data) -> data * 10^(3 / 2),),
)

# vcmax is read in units of umol CO2/m^2/s and then converted to mol CO2/m^2/s
Vcmax25 = SpaceVaryingInput(
joinpath(clm_artifact_path, "vegetation_properties_map.nc"),
Expand All @@ -380,14 +390,13 @@ function setup_prob(t0, tf, Δt; outdir = outdir, nelements = (10, 10, 15))
file_reader_kwargs = (; preprocess_func = (data) -> data / 1_000_000,),
)

# g1 is read in units of sqrt(kPa) and then converted to sqrt(Pa)
g1 = SpaceVaryingInput(
joinpath(clm_artifact_path, "vegetation_properties_map.nc"),
"medlynslope",
# c3 is read in as a float
is_c3 = SpaceVaryingInput(
joinpath(clm_artifact_path, "mechanism_map.nc"),
"c3_dominant",
surface_space;
regridder_type,
regridder_kwargs = (; extrapolation_bc,),
file_reader_kwargs = (; preprocess_func = (data) -> data * 10^(3 / 2),),
)

# Plant Hydraulics and general plant parameters
Expand Down Expand Up @@ -474,13 +483,8 @@ function setup_prob(t0, tf, Δt; outdir = outdir, nelements = (10, 10, 15))
conductance_args =
(; parameters = Canopy.MedlynConductanceParameters(FT; g1))
# Set up photosynthesis
photosynthesis_args = (;
parameters = Canopy.FarquharParameters(
FT,
Canopy.C3();
Vcmax25 = Vcmax25,
)
)
photosynthesis_args =
(; parameters = Canopy.FarquharParameters(FT, is_c3; Vcmax25 = Vcmax25))
# Set up plant hydraulics

# Note that we clip all values of LAI below 0.05 to zero.
Expand Down
4 changes: 2 additions & 2 deletions experiments/standalone/Vegetation/no_vegetation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ cond_params = MedlynConductanceParameters(FT; g1 = FT(141.0))

stomatal_model = MedlynConductanceModel{FT}(cond_params);


photo_params = FarquharParameters(FT, Canopy.C3(); Vcmax25 = FT(5e-5))
is_c3 = FT(1) # set the photosynthesis mechanism to C3
photo_params = FarquharParameters(FT, is_c3; Vcmax25 = FT(5e-5))

photosynthesis_model = FarquharModel{FT}(photo_params);

Expand Down
4 changes: 2 additions & 2 deletions experiments/standalone/Vegetation/varying_lai.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ cond_params = MedlynConductanceParameters(FT; g1 = FT(141.0))

stomatal_model = MedlynConductanceModel{FT}(cond_params);


photo_params = FarquharParameters(FT, Canopy.C3(); Vcmax25 = FT(5e-5))
is_c3 = FT(1) # set the photosynthesis mechanism to C3
photo_params = FarquharParameters(FT, is_c3; Vcmax25 = FT(5e-5))

photosynthesis_model = FarquharModel{FT}(photo_params);

Expand Down
4 changes: 2 additions & 2 deletions experiments/standalone/Vegetation/varying_lai_with_stem.jl
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ cond_params = MedlynConductanceParameters(FT; g1 = FT(141.0))

stomatal_model = MedlynConductanceModel{FT}(cond_params);


photo_params = FarquharParameters(FT, Canopy.C3(); Vcmax25 = FT(5e-5))
is_c3 = FT(1) # set the photosynthesis mechanism to C3
photo_params = FarquharParameters(FT, is_c3; Vcmax25 = FT(5e-5))

photosynthesis_model = FarquharModel{FT}(photo_params);

Expand Down
37 changes: 25 additions & 12 deletions ext/CreateParametersExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,14 @@ end
"""
function FarquharParameters(
FT,
mechanism::AbstractPhotosynthesisMechanism;
is_c3::Union{FT, ClimaCore.Fields.Field};
Vcmax25 = FT(5e-5),
kwargs... # For individual parameter overrides
)
function FarquharParameters(
toml_dict::CP.AbstractTOMLDict,
mechanism::AbstractPhotosynthesisMechanism;
is_c3::Union{AbstractFloat, ClimaCore.Fields.Field};
Vcmax25 = FT(5e-5),
kwargs... # For individual parameter overrides
)
Expand All @@ -123,25 +123,25 @@ Constructors for the FarquharParameters struct. Two variants:
1. Pass in the float-type and retrieve parameter values from the default TOML dict.
2. Pass in a TOML dictionary to retrieve parameter values.Possible calls:
```julia
ClimaLand.Canopy.FarquharParameters(Float64, ClimaLand.Canopy.C3())
ClimaLand.Canopy.FarquharParameters(Float64, 1.0)
# Kwarg overrides
ClimaLand.Canopy.FarquharParameters(Float64, ClimaLand.Canopy.C3(); Vcmax25 = 99999999, pc = 444444444)
ClimaLand.Canopy.FarquharParameters(Float64, 1.0; Vcmax25 = 99999999, pc = 444444444)
# TOML Dictionary:
import ClimaParams as CP
toml_dict = CP.create_toml_dict(Float32);
ClimaLand.Canopy.FarquharParameters(toml_dict, ClimaLand.Canopy.C3(); Vcmax25 = 99999999, pc = 444444444)
ClimaLand.Canopy.FarquharParameters(toml_dict, 1.0f0; Vcmax25 = 99999999, pc = 444444444)
```
"""
FarquharParameters(
::Type{FT},
mechanism;
is_c3::Union{FT, ClimaCore.Fields.Field};
kwargs...,
) where {FT <: AbstractFloat} =
FarquharParameters(CP.create_toml_dict(FT), mechanism; kwargs...)
FarquharParameters(CP.create_toml_dict(FT), is_c3; kwargs...)

function FarquharParameters(
toml_dict::CP.AbstractTOMLDict,
mechanism;
is_c3::Union{AbstractFloat, ClimaCore.Fields.Field};
Vcmax25 = 5e-5,
kwargs...,
)
Expand All @@ -165,11 +165,24 @@ function FarquharParameters(
)
parameters = CP.get_parameter_values(toml_dict, name_map, "Land")
FT = CP.float_type(toml_dict)
MECH = typeof(mechanism)
if maximum(is_c3) > 1
error(
"is_c3 has maximum of $(maximum(is_c3)). is_c3 should be between 0 and 1",
)
end
if minimum(is_c3) < 0
error(
"is_c3 has minimum of $(minimum(is_c3)). is_c3 should be between 0 and 1",
)
end
# if is_c3 is a field, is_c3 may contain values between 0.0 and 1.0 after regridding
# this deals with that possibility by rounding to the closest int
is_c3 = round.(is_c3)
MECH = typeof(is_c3)
Vcmax25 = FT.(Vcmax25)
VC = typeof(Vcmax25)
return FarquharParameters{FT, MECH, VC}(;
mechanism,
is_c3,
Vcmax25,
parameters...,
kwargs...,
Expand Down Expand Up @@ -229,8 +242,8 @@ function OptimalityFarquharParameters(toml_dict; kwargs...)

params = CP.get_parameter_values(toml_dict, name_map, "Land")
FT = CP.float_type(toml_dict)
mechanism = ClimaLand.Canopy.C3()
return OptimalityFarquharParameters{FT}(; params..., kwargs..., mechanism)
is_c3 = FT(1)
return OptimalityFarquharParameters{FT, FT}(; params..., kwargs..., is_c3)
end


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ function conductance_harvard(;
end

function photosynthesis_harvard(;
mechanism = Canopy.C3(),
is_c3 = FT(1),
oi = FT(0.209),
ϕ = FT(0.6),
θj = FT(0.9),
Expand Down Expand Up @@ -176,7 +176,7 @@ function photosynthesis_harvard(;
f,
sc,
pc,
mechanism,
is_c3,
)
end

Expand Down
Loading

0 comments on commit 3e9a73a

Please sign in to comment.