From 94fab253e9fefc03a1184c63a85972711346e7a6 Mon Sep 17 00:00:00 2001 From: Edward Speer Date: Wed, 9 Aug 2023 16:00:19 -0700 Subject: [PATCH] Diurnal cycle of diffuse radiation fraction --- docs/Manifest.toml | 2 +- docs/Project.toml | 1 + docs/tutorials/Bucket/bucket_tutorial.jl | 12 ++++- docs/tutorials/Canopy/canopy_tutorial.jl | 1 - docs/tutorials/Canopy/soil_canopy_tutorial.jl | 1 - .../ozark/conservation/ozark_conservation.jl | 1 - experiments/integrated/ozark/ozark.jl | 1 - .../ozark/ozark_met_drivers_FLUXNET.jl | 12 +++-- experiments/standalone/Soil/evaporation.jl | 6 ++- src/shared_utilities/drivers.jl | 20 +++++--- src/standalone/Vegetation/Canopy.jl | 20 +++++++- .../Vegetation/canopy_parameterizations.jl | 47 +++++++++++++++++-- src/standalone/Vegetation/radiation.jl | 4 -- test/standalone/Bucket/albedo_types.jl | 16 ++++++- test/standalone/Bucket/snow_bucket_tests.jl | 6 ++- test/standalone/Bucket/soil_bucket_tests.jl | 11 ++++- test/standalone/Soil/climate_drivers.jl | 6 ++- test/standalone/Vegetation/canopy_model.jl | 10 ++-- .../Vegetation/plant_hydraulics_test.jl | 20 +++++--- .../test_bigleaf_parameterizations.jl | 6 ++- test/standalone/Vegetation/test_two_stream.jl | 2 +- 21 files changed, 161 insertions(+), 44 deletions(-) diff --git a/docs/Manifest.toml b/docs/Manifest.toml index 705634c629..d1e7a04e6b 100644 --- a/docs/Manifest.toml +++ b/docs/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.9.1" manifest_format = "2.0" -project_hash = "cdeba84bbd82f27d7197cfd1d66867d60cc95b15" +project_hash = "db0cff940cb734405cc8ed1edd362cc4e50ddc3e" [[deps.AMD]] deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse_jll"] diff --git a/docs/Project.toml b/docs/Project.toml index ddf4a2eedf..d745d1501f 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -4,6 +4,7 @@ CLIMAParameters = "6eacf6c3-8458-43b9-ae03-caf5306d3d53" ClimaCore = "d414da3d-4745-48bb-8d80-42e94e092884" ClimaLSM = "7884a58f-fab6-4fd0-82bb-ecfedb2d8430" ClimaTimeSteppers = "595c0a79-7f3d-439a-bc5a-b232dc3bde79" +Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Dierckx = "39dd38d3-220a-591b-8e3c-4c3a8c710a94" DiffEqBase = "2b5f629d-d688-5b77-993f-72d75c75574e" DiffEqCallbacks = "459566f4-90b8-5000-8ac3-15dfb0a30def" diff --git a/docs/tutorials/Bucket/bucket_tutorial.jl b/docs/tutorials/Bucket/bucket_tutorial.jl index 6b33638cb0..7027e8d567 100644 --- a/docs/tutorials/Bucket/bucket_tutorial.jl +++ b/docs/tutorials/Bucket/bucket_tutorial.jl @@ -151,6 +151,9 @@ using ClimaLSM: # We also want to plot the solution using Plots +# And we need to use the DateTime type to store reference times +using Dates + FT = Float64; # As mentioned we use CLIMAParameters for earth parameters that are @@ -212,6 +215,11 @@ bucket_domain = LSMSingleColumnDomain(; zlim = (-soil_depth, 0.0), nelements = 10); +# The PrescribedAtmosphere and PrescribedRadiation need to take in a reference +# time, the date of the start of the simulation. In this tutorial we will +# consider this January 1, 2005. +ref_time = DateTime(2005); + # To drive the system in standalone mode, # the user must provide # prescribed functions of time for the water volume flux in precipitation, @@ -227,7 +235,8 @@ LW_d = (t) -> eltype(t)(300); bucket_rad = PrescribedRadiativeFluxes( FT, SW_d, - LW_d; + LW_d, + ref_time; orbital_data = Insolation.OrbitalData(), ); @@ -250,6 +259,7 @@ bucket_atmos = PrescribedAtmosphere( u_atmos, q_atmos, P_atmos, + ref_time, h_atmos, ); diff --git a/docs/tutorials/Canopy/canopy_tutorial.jl b/docs/tutorials/Canopy/canopy_tutorial.jl index 065804e972..aeafb7d255 100644 --- a/docs/tutorials/Canopy/canopy_tutorial.jl +++ b/docs/tutorials/Canopy/canopy_tutorial.jl @@ -134,7 +134,6 @@ rt_params = TwoStreamParameters{FT}(; λ_γ_PAR = FT(5e-7), λ_γ_NIR = FT(1.65e-6), n_layers = UInt64(20), - diff_perc = FT(0.5), ) rt_model = TwoStreamModel{FT}(rt_params); diff --git a/docs/tutorials/Canopy/soil_canopy_tutorial.jl b/docs/tutorials/Canopy/soil_canopy_tutorial.jl index 3f557b29cb..06f40f4ee9 100644 --- a/docs/tutorials/Canopy/soil_canopy_tutorial.jl +++ b/docs/tutorials/Canopy/soil_canopy_tutorial.jl @@ -197,7 +197,6 @@ radiative_transfer_args = (; λ_γ_PAR = FT(5e-7), λ_γ_NIR = FT(1.65e-6), n_layers = UInt64(20), - diff_perc = FT(0.5), ) ) diff --git a/experiments/integrated/ozark/conservation/ozark_conservation.jl b/experiments/integrated/ozark/conservation/ozark_conservation.jl index 44c62297ce..ea7e436161 100644 --- a/experiments/integrated/ozark/conservation/ozark_conservation.jl +++ b/experiments/integrated/ozark/conservation/ozark_conservation.jl @@ -86,7 +86,6 @@ radiative_transfer_args = (; α_NIR_leaf = α_NIR_leaf, τ_NIR_leaf = τ_NIR_leaf, n_layers = n_layers, - diff_perc = diff_perc, ) ) # Set up conductance diff --git a/experiments/integrated/ozark/ozark.jl b/experiments/integrated/ozark/ozark.jl index e69feb7167..5e92f8e142 100644 --- a/experiments/integrated/ozark/ozark.jl +++ b/experiments/integrated/ozark/ozark.jl @@ -83,7 +83,6 @@ radiative_transfer_args = (; α_NIR_leaf = α_NIR_leaf, τ_NIR_leaf = τ_NIR_leaf, n_layers = n_layers, - diff_perc = diff_perc, ) ) # Set up conductance diff --git a/experiments/integrated/ozark/ozark_met_drivers_FLUXNET.jl b/experiments/integrated/ozark/ozark_met_drivers_FLUXNET.jl index be3fa3da81..d958106143 100644 --- a/experiments/integrated/ozark/ozark_met_drivers_FLUXNET.jl +++ b/experiments/integrated/ozark/ozark_met_drivers_FLUXNET.jl @@ -92,7 +92,8 @@ precipitation_function(t::FT) where {FT} = p_spline(t) < 0.0 ? p_spline(t) : 0.0 snow_precip(t) = eltype(t)(0) # this is likely not correct -# Construct the drivers +# Construct the drivers. For the reference time we will use the UTC time at the +# start of the simulation atmos = ClimaLSM.PrescribedAtmosphere( precipitation_function, snow_precip, @@ -100,6 +101,7 @@ atmos = ClimaLSM.PrescribedAtmosphere( atmos_u, atmos_q, atmos_p, + UTC_DATETIME[1], atmos_h; c_co2 = atmos_co2, ) @@ -109,13 +111,14 @@ long = FT(-92.2000) # degree function zenith_angle( t::FT, - orbital_data; + orbital_data, + ref_time; latitude = lat, longitude = long, insol_params = earth_param_set.insol_params, ) where {FT} # This should be time in UTC - dt = DateTime("2005-01-01-06", "yyyy-mm-dd-HH") + Dates.Second(round(t)) + dt = ref_time + Dates.Second(round(t)) FT( instantaneous_zenith_angle( dt, @@ -131,7 +134,8 @@ end radiation = ClimaLSM.PrescribedRadiativeFluxes( FT, SW_IN_spline, - LW_IN_spline; + LW_IN_spline, + UTC_DATETIME[1]; θs = zenith_angle, orbital_data = Insolation.OrbitalData(), ) diff --git a/experiments/standalone/Soil/evaporation.jl b/experiments/standalone/Soil/evaporation.jl index 87f722993a..5444b04ee9 100644 --- a/experiments/standalone/Soil/evaporation.jl +++ b/experiments/standalone/Soil/evaporation.jl @@ -8,6 +8,7 @@ import CLIMAParameters as CP using RootSolvers using SurfaceFluxes using StaticArrays +using Dates using ClimaLSM using ClimaLSM.Domains: Column @@ -54,12 +55,14 @@ NIR_albedo = FT(0.4) z_0m = 1e-4 z_0b = 1e-5 +ref_time = DateTime(2005) SW_d = (t) -> eltype(t)(0) LW_d = (t) -> eltype(t)(301.15^4 * 5.67e-8) radiation = PrescribedRadiativeFluxes( FT, SW_d, - LW_d; + LW_d, + ref_time; orbital_data = Insolation.OrbitalData(), ) # Atmos @@ -86,6 +89,7 @@ atmos = PrescribedAtmosphere( u_atmos, q_atmos, P_atmos, + ref_time, h_atmos; gustiness = gustiness, ) diff --git a/src/shared_utilities/drivers.jl b/src/shared_utilities/drivers.jl index 04b29c0a0b..5278d11604 100644 --- a/src/shared_utilities/drivers.jl +++ b/src/shared_utilities/drivers.jl @@ -34,7 +34,7 @@ An abstract type of radiative drivers of land models. abstract type AbstractRadiativeDrivers{FT <: AbstractFloat} end """ - PrescribedAtmosphere{FT, LP, SP, TA, UA, QA, RA, CA} <: AbstractAtmosphericDrivers{FT} + PrescribedAtmosphere{FT, LP, SP, TA, UA, QA, RA, CA, DT} <: AbstractAtmosphericDrivers{FT} Container for holding prescribed atmospheric drivers and other information needed for computing turbulent surface fluxes when @@ -44,7 +44,7 @@ Since not all models require co2 concentration, the default for that is `nothing`. $(DocStringExtensions.FIELDS) """ -struct PrescribedAtmosphere{FT, LP, SP, TA, UA, QA, RA, CA} <: +struct PrescribedAtmosphere{FT, LP, SP, TA, UA, QA, RA, CA, DT} <: AbstractAtmosphericDrivers{FT} "Precipitation (m/s) function of time: positive by definition" liquid_precip::LP @@ -60,6 +60,8 @@ struct PrescribedAtmosphere{FT, LP, SP, TA, UA, QA, RA, CA} <: P::RA "CO2 concentration in atmosphere (mol/mol)" c_co2::CA + "Reference time - the datetime corresponding to t=0 for the simulation" + ref_time::DT "Reference height (m), relative to surface elevation" h::FT "Minimum wind speed (gustiness; m/s)" @@ -71,11 +73,12 @@ struct PrescribedAtmosphere{FT, LP, SP, TA, UA, QA, RA, CA} <: u, q, P, + ref_time, h::FT; gustiness = FT(1), c_co2 = nothing, ) where {FT} - args = (liquid_precip, snow_precip, T, u, q, P, c_co2) + args = (liquid_precip, snow_precip, T, u, q, P, c_co2, ref_time) return new{typeof(h), typeof.(args)...}(args..., h, gustiness) end @@ -241,17 +244,19 @@ function surface_fluxes_at_a_point( end """ - PrescribedRadiativeFluxes{FT, SW, LW, T} <: AbstractRadiativeDrivers{FT} + PrescribedRadiativeFluxes{FT, SW, LW, DT, T, OD} <: AbstractRadiativeDrivers{FT} Container for the prescribed radiation functions needed to drive land models in standalone mode. $(DocStringExtensions.FIELDS) """ -struct PrescribedRadiativeFluxes{FT, SW, LW, T, OD} <: +struct PrescribedRadiativeFluxes{FT, SW, LW, DT, T, OD} <: AbstractRadiativeDrivers{FT} "Downward shortwave radiation function of time (W/m^2): positive indicates towards surface" SW_d::SW "Downward longwave radiation function of time (W/m^2): positive indicates towards surface" LW_d::LW + "Reference time - the datetime corresponding to t=0 for the simulation" + ref_time::DT "Sun zenith angle, in radians" θs::T "Orbital Data for Insolation.jl" @@ -259,11 +264,12 @@ struct PrescribedRadiativeFluxes{FT, SW, LW, T, OD} <: function PrescribedRadiativeFluxes( FT, SW_d, - LW_d; + LW_d, + ref_time; θs = nothing, orbital_data, ) - args = (SW_d, LW_d, θs, orbital_data) + args = (SW_d, LW_d, ref_time, θs, orbital_data) @assert !isnothing(orbital_data) return new{FT, typeof.(args)...}(args...) end diff --git a/src/standalone/Vegetation/Canopy.jl b/src/standalone/Vegetation/Canopy.jl index 9e1fe8c2a9..2b7108d7d5 100644 --- a/src/standalone/Vegetation/Canopy.jl +++ b/src/standalone/Vegetation/Canopy.jl @@ -36,6 +36,7 @@ include("./stomatalconductance.jl") include("./photosynthesis.jl") include("./radiation.jl") include("./canopy_parameterizations.jl") +using Dates """ SharedCanopyParameters{FT <: AbstractFloat, PSE} @@ -414,7 +415,8 @@ function ClimaLSM.make_update_aux( (; sc, pc) = canopy.photosynthesis.parameters # Current atmospheric conditions - θs::FT = canopy.radiation.θs(t, canopy.radiation.orbital_data) + ref_time = canopy.atmos.ref_time + θs::FT = canopy.radiation.θs(t, canopy.radiation.orbital_data, ref_time) c_co2::FT = canopy.atmos.c_co2(t) P::FT = canopy.atmos.P(t) u::FT = canopy.atmos.u(t) @@ -427,6 +429,21 @@ function ClimaLSM.make_update_aux( K = extinction_coeff(ld, θs) PAR .= compute_PAR(RT, canopy.radiation, t) NIR .= compute_NIR(RT, canopy.radiation, t) + e_sat = + Thermodynamics.saturation_vapor_pressure.( + Ref(thermo_params), + T, + Ref(Thermodynamics.Liquid()), + ) + e = + Thermodynamics.partial_pressure_vapor.( + Ref(thermo_params), + P, + Ref(PhasePartition(q)), + ) + rel_hum = e / e_sat + DOY = Dates.dayofyear(ref_time + Dates.Second(floor(Int64, t))) + frac_diff = @. diffuse_fraction(DOY, T, PAR + NIR, rel_hum, θs) APAR, ANIR = compute_absorbances( RT, PAR ./ (energy_per_photon_PAR * N_a), @@ -436,6 +453,7 @@ function ClimaLSM.make_update_aux( θs, ground_albedo_PAR(canopy), ground_albedo_NIR(canopy), + frac_diff, ) # update plant hydraulics aux diff --git a/src/standalone/Vegetation/canopy_parameterizations.jl b/src/standalone/Vegetation/canopy_parameterizations.jl index 258346140a..27498cf964 100644 --- a/src/standalone/Vegetation/canopy_parameterizations.jl +++ b/src/standalone/Vegetation/canopy_parameterizations.jl @@ -33,6 +33,7 @@ export plant_absorbed_pfd, _, _, _, + _, ) Computes the APAR and ANIR absorbances for a canopy in the case of the @@ -50,6 +51,7 @@ function compute_absorbances( _, _, _, + _, ) where {FT} RTP = RT.parameters APAR = @. plant_absorbed_pfd(RT, PAR, RTP.α_PAR_leaf, LAI, K) @@ -67,6 +69,7 @@ end θs, α_soil_PAR, α_soil_NIR, + frac_diff, ) Compute APAR and ANIR absorbances for a canopy in the case of the @@ -84,6 +87,7 @@ function compute_absorbances( θs, α_soil_PAR, α_soil_NIR, + frac_diff, ) where {FT} RTP = RT.parameters APAR = @. plant_absorbed_pfd( @@ -95,6 +99,7 @@ function compute_absorbances( K, θs, α_soil_PAR, + frac_diff, ) ANIR = @. plant_absorbed_pfd( RT, @@ -105,6 +110,7 @@ function compute_absorbances( K, θs, α_soil_NIR, + frac_diff, ) return (APAR, ANIR) end @@ -174,9 +180,10 @@ function plant_absorbed_pfd( K::FT, θs::FT, α_soil::FT, + frac_diff::FT, ) where {FT} - (; ld, Ω, n_layers, diff_perc) = RT.parameters + (; ld, Ω, n_layers) = RT.parameters # Compute μ̄, the average inverse diffuse optical length per LAI μ̄ = 1 / (2 * ld) @@ -294,7 +301,7 @@ function plant_absorbed_pfd( end # Add radiation absorbed in the layer to total absorbed radiation - F_abs += (1 - diff_perc) * I_dir_abs + (diff_perc) * I_dif_abs + F_abs += (1 - frac_diff) * I_dir_abs + (frac_diff) * I_dif_abs # Save input/output values to compute energy balance of next layer I_dir_up_prev = I_dir_up @@ -311,6 +318,40 @@ function plant_absorbed_pfd( return FT(SW_IN * F_abs) end +""" + diffuse_fraction(td::FT, T::FT, SW_IN::FT, RH::FT, θs::FT) where {FT} + +Computes the fraction of diffuse radiation (`diff_frac`) as a function +of the solar zenith angle (`θs`), the total surface incident shortwave radiation (`SW_IN`), +the air temperature (`T`), the relative humidity (`RH`), and the day of the year +(`td`). + +See Appendix A of Braghiere, "Evaluation of turbulent fluxes of CO2, sensible heat, +and latent heat as a function of aerosol optical depth over the course of deforestation +in the Brazilian Amazon" 2013. +""" +function diffuse_fraction(td, T::FT, SW_IN::FT, RH::FT, θs::FT) where {FT} + k₀ = FT(1370 * (1 + 0.033 * cos(360 * td / 365)) * cos(θs)) + kₜ = SW_IN / k₀ + if kₜ ≤ 0.3 + diff_frac = FT( + kₜ * + (1 - 0.232 * kₜ + 0.0239 * cos(θs) - 6.82e-4 * T + 0.0195 * RH), + ) + elseif kₜ ≤ 0.78 + diff_frac = FT( + kₜ * ( + 1.329 - 1.716 * kₜ + 0.267 * cos(θs) - 3.57e-3 * T + 0.106 * RH + ), + ) + else + diff_frac = + FT(kₜ * (0.426 * kₜ + 0.256 * cos(θs) - 3.49e-3 * T + 0.0734 * RH)) + end + return diff_frac +end + + """ extinction_coeff(ld::FT, θs::FT) where {FT} @@ -567,7 +608,7 @@ the total net carbon assimilation (`An`), the extinction coefficient (`K`), leaf area index (`LAI`) and the clumping index (`Ω`). """ function compute_GPP(An::FT, K::FT, LAI::FT, Ω::FT) where {FT} - GPP = An * (1 - exp(-K * LAI * Ω)) / K + GPP = An * (1 - exp(-K * LAI * Ω)) / (K * Ω) return GPP end diff --git a/src/standalone/Vegetation/radiation.jl b/src/standalone/Vegetation/radiation.jl index 64454bcf23..a7dfff7226 100644 --- a/src/standalone/Vegetation/radiation.jl +++ b/src/standalone/Vegetation/radiation.jl @@ -86,8 +86,6 @@ struct TwoStreamParameters{FT <: AbstractFloat} λ_γ_NIR::FT "number of layers to simulate radiative transfer through" n_layers::UInt64 - "Proportion of diffuse radiation" - diff_perc::FT end """ @@ -116,7 +114,6 @@ function TwoStreamParameters{FT}(; λ_γ_PAR = FT(5e-7), λ_γ_NIR = FT(1.65e-6), n_layers = UInt64(20), - diff_perc = FT(0), ) where {FT} return TwoStreamParameters{FT}( ld, @@ -128,7 +125,6 @@ function TwoStreamParameters{FT}(; λ_γ_PAR, λ_γ_NIR, n_layers, - diff_perc, ) end diff --git a/test/standalone/Bucket/albedo_types.jl b/test/standalone/Bucket/albedo_types.jl index 5704d85d6e..1a9fcc106d 100644 --- a/test/standalone/Bucket/albedo_types.jl +++ b/test/standalone/Bucket/albedo_types.jl @@ -287,9 +287,11 @@ end for bucket_domain in bucket_domains # Radiation + ref_time = DateTime(2005) SW_d = (t) -> eltype(t)(0.0) LW_d = (t) -> eltype(t)(5.67e-8 * 280.0^4.0) - bucket_rad = PrescribedRadiativeFluxes(FT, SW_d, LW_d; orbital_data) + bucket_rad = + PrescribedRadiativeFluxes(FT, SW_d, LW_d, ref_time; orbital_data) # Atmos precip = (t) -> eltype(t)(0) # no precipitation T_atmos = (t) -> eltype(t)(280.0) @@ -304,6 +306,7 @@ end u_atmos, q_atmos, P_atmos, + ref_time, h_atmos, ) Δt = FT(1.0) @@ -431,9 +434,16 @@ end albedo_model = BulkAlbedoTemporal{FT}(regrid_dirpath, date_ref, t_start, space) # Radiation + ref_time = DateTime(2005) SW_d = (t) -> eltype(t)(0.0) LW_d = (t) -> eltype(t)(5.67e-8 * 280.0^4.0) - bucket_rad = PrescribedRadiativeFluxes(FT, SW_d, LW_d; orbital_data) + bucket_rad = PrescribedRadiativeFluxes( + FT, + SW_d, + LW_d, + ref_time; + orbital_data, + ) # Atmos precip = (t) -> eltype(t)(0) # no precipitation T_atmos = (t) -> eltype(t)(280.0) @@ -441,6 +451,7 @@ end q_atmos = (t) -> eltype(t)(0.0) # no atmos water h_atmos = FT(1e-8) P_atmos = (t) -> eltype(t)(101325) + ref_time = DateTime(2005) bucket_atmos = PrescribedAtmosphere( precip, precip, @@ -448,6 +459,7 @@ end u_atmos, q_atmos, P_atmos, + ref_time, h_atmos, ) Δt = FT(1.0) diff --git a/test/standalone/Bucket/snow_bucket_tests.jl b/test/standalone/Bucket/snow_bucket_tests.jl index 5233b84788..e6c733d9e6 100644 --- a/test/standalone/Bucket/snow_bucket_tests.jl +++ b/test/standalone/Bucket/snow_bucket_tests.jl @@ -2,6 +2,7 @@ using Test using Statistics using Insolation +using Dates using ClimaCore using ClimaLSM.Bucket: BucketModel, @@ -62,9 +63,11 @@ for bucket_domain in bucket_domains @testset "Conservation of water and energy" begin "Radiation" + ref_time = DateTime(2005) SW_d = (t) -> eltype(t)(20.0) LW_d = (t) -> eltype(t)(20.0) - bucket_rad = PrescribedRadiativeFluxes(FT, SW_d, LW_d; orbital_data) + bucket_rad = + PrescribedRadiativeFluxes(FT, SW_d, LW_d, ref_time; orbital_data) "Atmos" precip = (t) -> eltype(t)(0) # no precipitation T_atmos = (t) -> eltype(t)(280.0) @@ -79,6 +82,7 @@ for bucket_domain in bucket_domains u_atmos, q_atmos, P_atmos, + ref_time, h_atmos, ) Δt = FT(1.0) diff --git a/test/standalone/Bucket/soil_bucket_tests.jl b/test/standalone/Bucket/soil_bucket_tests.jl index 289c92f34e..ca58a0796b 100644 --- a/test/standalone/Bucket/soil_bucket_tests.jl +++ b/test/standalone/Bucket/soil_bucket_tests.jl @@ -1,5 +1,6 @@ using Test +using Dates using Statistics using Insolation using ClimaCore @@ -59,9 +60,11 @@ init_temp(z::FT, value::FT) where {FT} = FT(value) for bucket_domain in bucket_domains @testset "Zero flux tendency" begin # Radiation + ref_time = DateTime(2005) SW_d = (t) -> eltype(t)(0.0) LW_d = (t) -> eltype(t)(5.67e-8 * 280.0^4.0) - bucket_rad = PrescribedRadiativeFluxes(FT, SW_d, LW_d; orbital_data) + bucket_rad = + PrescribedRadiativeFluxes(FT, SW_d, LW_d, ref_time; orbital_data) # Atmos precip = (t) -> eltype(t)(0) # no precipitation T_atmos = (t) -> eltype(t)(280.0) @@ -76,6 +79,7 @@ for bucket_domain in bucket_domains u_atmos, q_atmos, P_atmos, + ref_time, h_atmos, ) Δt = FT(1.0) @@ -147,9 +151,11 @@ for bucket_domain in bucket_domains @testset "Energy + Moisture Conservation" begin "Radiation" + ref_time = DateTime(2005) SW_d = (t) -> eltype(t)(10.0) LW_d = (t) -> eltype(t)(300.0) - bucket_rad = PrescribedRadiativeFluxes(FT, SW_d, LW_d; orbital_data) + bucket_rad = + PrescribedRadiativeFluxes(FT, SW_d, LW_d, ref_time; orbital_data) "Atmos" precip = (t) -> eltype(t)(1e-6) T_atmos = (t) -> eltype(t)(298.0) @@ -164,6 +170,7 @@ for bucket_domain in bucket_domains u_atmos, q_atmos, P_atmos, + ref_time, h_atmos, ) Δt = FT(100.0) diff --git a/test/standalone/Soil/climate_drivers.jl b/test/standalone/Soil/climate_drivers.jl index e3fb2a8cb2..a1190fa08d 100644 --- a/test/standalone/Soil/climate_drivers.jl +++ b/test/standalone/Soil/climate_drivers.jl @@ -7,6 +7,7 @@ using ClimaLSM.Soil import ClimaLSM import ClimaLSM.Parameters as LSMP using Insolation +using Dates include(joinpath(pkgdir(ClimaLSM), "parameters", "create_parameters.jl")) @testset "Surface fluxes and radiation for soil" begin FT = Float32 @@ -58,12 +59,14 @@ include(joinpath(pkgdir(ClimaLSM), "parameters", "create_parameters.jl")) z_0m = FT(0.001) z_0b = z_0m # Radiation + ref_time = DateTime(2005) SW_d = (t) -> eltype(t)(500) LW_d = (t) -> eltype(t)(5.67e-8 * 280.0^4.0) radiation = PrescribedRadiativeFluxes( FT, SW_d, - LW_d; + LW_d, + ref_time; orbital_data = Insolation.OrbitalData(), ) # Atmos @@ -80,6 +83,7 @@ include(joinpath(pkgdir(ClimaLSM), "parameters", "create_parameters.jl")) u_atmos, q_atmos, P_atmos, + ref_time, h_atmos, ) @test atmos.gustiness == FT(1) diff --git a/test/standalone/Vegetation/canopy_model.jl b/test/standalone/Vegetation/canopy_model.jl index c7cf708f3c..3744e2c68d 100644 --- a/test/standalone/Vegetation/canopy_model.jl +++ b/test/standalone/Vegetation/canopy_model.jl @@ -42,14 +42,15 @@ include(joinpath(pkgdir(ClimaLSM), "parameters", "create_parameters.jl")) function zenith_angle( t::FT, - orbital_data; + orbital_data, + ref_time; latitude = lat, longitude = long, insol_params = earth_param_set.insol_params, ) where {FT} return FT( instantaneous_zenith_angle( - DateTime(t), + ref_time + Dates.Second(round(t)), orbital_data, longitude, latitude, @@ -80,6 +81,7 @@ include(joinpath(pkgdir(ClimaLSM), "parameters", "create_parameters.jl")) P_atmos = t -> eltype(t)(1e5) # Pa h_atmos = h_int # m c_atmos = (t) -> eltype(t)(4.11e-4) # mol/mol + ref_time = DateTime(2005) atmos = PrescribedAtmosphere( liquid_precip, snow_precip, @@ -87,13 +89,15 @@ include(joinpath(pkgdir(ClimaLSM), "parameters", "create_parameters.jl")) u_atmos, q_atmos, P_atmos, + ref_time, h_atmos; c_co2 = c_atmos, ) radiation = PrescribedRadiativeFluxes( FT, shortwave_radiation, - longwave_radiation; + longwave_radiation, + ref_time; θs = zenith_angle, orbital_data = Insolation.OrbitalData(), ) diff --git a/test/standalone/Vegetation/plant_hydraulics_test.jl b/test/standalone/Vegetation/plant_hydraulics_test.jl index c86787b606..283fef0858 100644 --- a/test/standalone/Vegetation/plant_hydraulics_test.jl +++ b/test/standalone/Vegetation/plant_hydraulics_test.jl @@ -127,14 +127,15 @@ end function zenith_angle( t::FT, - orbital_data; + orbital_data, + ref_time; latitude = lat, longitude = long, insol_params = earth_param_set.insol_params, ) where {FT} return FT( instantaneous_zenith_angle( - DateTime(t), + ref_time + Dates.Second(round(t)), orbital_data, longitude, latitude, @@ -165,6 +166,7 @@ end P_atmos = t -> eltype(t)(1e5) # Pa h_atmos = h_int # m c_atmos = (t) -> eltype(t)(4.11e-4) # mol/mol + ref_time = DateTime(2005) atmos = PrescribedAtmosphere( liquid_precip, snow_precip, @@ -172,13 +174,15 @@ end u_atmos, q_atmos, P_atmos, + ref_time, h_atmos; c_co2 = c_atmos, ) radiation = PrescribedRadiativeFluxes( FT, shortwave_radiation, - longwave_radiation; + longwave_radiation, + ref_time; θs = zenith_angle, orbital_data = Insolation.OrbitalData(), ) @@ -410,14 +414,15 @@ end function zenith_angle( t::FT, - orbital_data; + orbital_data, + ref_time; latitude = lat, longitude = long, insol_params = earth_param_set.insol_params, ) where {FT} return FT( instantaneous_zenith_angle( - DateTime(t), + ref_time + Dates.Second(round(t)), orbital_data, longitude, latitude, @@ -448,6 +453,7 @@ end P_atmos = t -> eltype(t)(1e5) # Pa h_atmos = h_int # m c_atmos = (t) -> eltype(t)(4.11e-4) # mol/mol + ref_time = DateTime(2005) atmos = PrescribedAtmosphere( liquid_precip, snow_precip, @@ -455,13 +461,15 @@ end u_atmos, q_atmos, P_atmos, + ref_time, h_atmos; c_co2 = c_atmos, ) radiation = PrescribedRadiativeFluxes( FT, shortwave_radiation, - longwave_radiation; + longwave_radiation, + ref_time; θs = zenith_angle, orbital_data = Insolation.OrbitalData(), ) diff --git a/test/standalone/Vegetation/test_bigleaf_parameterizations.jl b/test/standalone/Vegetation/test_bigleaf_parameterizations.jl index 91cf7f6cf6..b5a1eaaf95 100644 --- a/test/standalone/Vegetation/test_bigleaf_parameterizations.jl +++ b/test/standalone/Vegetation/test_bigleaf_parameterizations.jl @@ -153,11 +153,13 @@ include(joinpath(pkgdir(ClimaLSM), "parameters", "create_parameters.jl")) @test all( @.( stomatal_conductance ≈ - stomatal_g_params.g0 + stomatal_g_params.Drel * m_t * (An / ca) + (stomatal_g_params.g0 + stomatal_g_params.Drel * m_t * (An / ca)) ) ) GPP = compute_GPP.(An, K_c, LAI, RTparams.Ω) # mol m-2 s-1 - @test all(@.(GPP ≈ An * (1 - exp(-K_c * LAI * RTparams.Ω)) / K_c)) + @test all( + @.(GPP ≈ An * (1 - exp(-K_c * LAI * RTparams.Ω)) / (K_c * RTparams.Ω)) + ) @test all( @.( diff --git a/test/standalone/Vegetation/test_two_stream.jl b/test/standalone/Vegetation/test_two_stream.jl index c85d040684..8912129fe9 100644 --- a/test/standalone/Vegetation/test_two_stream.jl +++ b/test/standalone/Vegetation/test_two_stream.jl @@ -60,7 +60,6 @@ py_FAPAR = FT.(test_set[2:end, column_names .== "FAPAR"]) λ_γ_PAR = λ_γ_PAR, λ_γ_NIR = λ_γ_NIR, n_layers = n_layers[i], - diff_perc = PropDif[i], ) # Initialize the TwoStream model @@ -77,6 +76,7 @@ py_FAPAR = FT.(test_set[2:end, column_names .== "FAPAR"]) K, θs[i], a_soil[i], + PropDif[i], ) # Check that the predictions are app. equivalent to the Python model