Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New evaporation scheme #732

Merged
merged 1 commit into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .buildkite/longruns_gpu/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ steps:
artifact_paths: "land_longrun_gpu/*png"
agents:
slurm_gpus: 1
slurm_time: 01:00:00
slurm_time: 03:00:00
env:
CLIMACOMMS_DEVICE: "CUDA"

Expand All @@ -47,6 +47,6 @@ steps:
artifact_paths: "soil_longrun_gpu/*png"
agents:
slurm_gpus: 1
slurm_time: 01:00:00
slurm_time: 03:00:00
env:
CLIMACOMMS_DEVICE: "CUDA"
8 changes: 0 additions & 8 deletions docs/src/APIs/Soil.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,6 @@ ClimaLand.Soil.phase_change_source
ClimaLand.Soil.thermal_time
```

## Soil Surface Parameterizations

```@docs
ClimaLand.soil.soil_resistance
ClimaLand.Soil.dry_soil_layer_thickness
ClimaLand.Soil.soil_tortuosity
```

## Soil Runoff Types and Methods

```@docs
Expand Down
6 changes: 2 additions & 4 deletions docs/tutorials/standalone/Soil/evaporation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -223,10 +223,8 @@ sol = SciMLBase.solve(prob, ode_algo; dt = dt, callback = cb, saveat = saveat);

# Extract the evaporation at each saved step
evap = [
parent(
sv.saveval[k].soil.turbulent_fluxes.vapor_flux .*
(1 .- sv.saveval[k].soil.ice_frac),
)[1] for k in 1:length(sol.t)
parent(sv.saveval[k].soil.turbulent_fluxes.vapor_flux_liq)[1] for
k in 1:length(sol.t)
]
savepath = joinpath(pkgdir(ClimaLand), "docs/tutorials/standalone/Soil/")
evaporation_data =
Expand Down
14 changes: 5 additions & 9 deletions docs/tutorials/standalone/Soil/evaporation_gilat_loess.jl
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ thermo_params = LP.thermodynamic_parameters(earth_param_set);

# Parameters
K_sat = FT(0.01 / 3600 / 24)
vg_n = FT(1.45)
vg_n = FT(1.55)
vg_α = FT(1.5)
hcm = vanGenuchten{FT}(; α = vg_α, n = vg_n)
ν = FT(0.4)
Expand Down Expand Up @@ -256,10 +256,8 @@ driver_cb = ClimaLand.DriverUpdateCallback(updateat, updatefunc)
cb = SciMLBase.CallbackSet(driver_cb, saving_cb)
sol = SciMLBase.solve(prob, ode_algo; dt = dt, callback = cb, saveat = saveat)
evap = [
parent(
sv.saveval[k].soil.turbulent_fluxes.vapor_flux .*
(1 .- sv.saveval[k].soil.ice_frac),
)[1] for k in 1:length(sol.t)
parent(sv.saveval[k].soil.turbulent_fluxes.vapor_flux_liq)[1] for
k in 1:length(sol.t)
];

## Repeat with no drainage (Ksat = 0, different BC), and with evaporation, in shorter domain
Expand Down Expand Up @@ -323,10 +321,8 @@ cb = SciMLBase.CallbackSet(driver_cb, saving_cb)
sol_no_drainage =
SciMLBase.solve(prob, ode_algo; dt = dt, callback = cb, saveat = saveat)
evap_no_drainage = [
parent(
sv.saveval[k].soil.turbulent_fluxes.vapor_flux .*
(1 .- sv.saveval[k].soil.ice_frac),
)[1] for k in 1:length(sol.t)
parent(sv.saveval[k].soil.turbulent_fluxes.vapor_flux_liq)[1] for
k in 1:length(sol.t)
];


Expand Down
12 changes: 4 additions & 8 deletions docs/tutorials/standalone/Soil/sublimation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -209,16 +209,12 @@ sol = SciMLBase.solve(prob, ode_algo; dt = dt, callback = cb, saveat = saveat);

# Extract the evaporation at each saved step
evap = [
parent(
sv.saveval[k].soil.turbulent_fluxes.vapor_flux .*
(1 .- sv.saveval[k].soil.ice_frac),
)[1] for k in 1:length(sol.t)
parent(sv.saveval[k].soil.turbulent_fluxes.vapor_flux_liq)[1] for
k in 1:length(sol.t)
]
sub = [
parent(
sv.saveval[k].soil.turbulent_fluxes.vapor_flux .*
sv.saveval[k].soil.ice_frac,
)[1] for k in 1:length(sol.t)
parent(sv.saveval[k].soil.turbulent_fluxes.vapor_flux_ice)[1] for
k in 1:length(sol.t)
]

savepath = joinpath(pkgdir(ClimaLand), "docs/tutorials/standalone/Soil/")
Expand Down
2 changes: 1 addition & 1 deletion experiments/benchmarks/bucket.jl
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ if ClimaComms.device() isa ClimaComms.CUDADevice
end

if get(ENV, "BUILDKITE_PIPELINE_SLUG", nothing) == "climaland-benchmark"
PREVIOUS_BEST_TIME = 3.6
PREVIOUS_BEST_TIME = 2.8
if average_timing_s > PREVIOUS_BEST_TIME + std_timing_s
@info "Possible performance regression, previous average time was $(PREVIOUS_BEST_TIME)"
elseif average_timing_s < PREVIOUS_BEST_TIME - std_timing_s
Expand Down
6 changes: 4 additions & 2 deletions experiments/integrated/fluxnet/ozark_pft.jl
Original file line number Diff line number Diff line change
Expand Up @@ -455,8 +455,10 @@ T =
] .* (1e3 * 24 * 3600)
E =
[
parent(sv.saveval[k].soil.turbulent_fluxes.vapor_flux)[1] for
k in 1:length(sol.t)
parent(
sv.saveval[k].soil.turbulent_fluxes.vapor_flux_liq .+
sv.saveval[k].soil.turbulent_fluxes.vapor_flux_ice,
)[1] for k in 1:length(sol.t)
] .* (1e3 * 24 * 3600)
ET_model = T .+ E
if drivers.LE.status == absent
Expand Down
6 changes: 4 additions & 2 deletions experiments/integrated/fluxnet/run_fluxnet.jl
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,10 @@ T =
] .* (1e3 * 24 * 3600)
E =
[
parent(sv.saveval[k].soil.turbulent_fluxes.vapor_flux)[1] for
k in 1:length(sol.t)
parent(
sv.saveval[k].soil.turbulent_fluxes.vapor_flux_liq .+
sv.saveval[k].soil.turbulent_fluxes.vapor_flux_ice,
)[1] for k in 1:length(sol.t)
] .* (1e3 * 24 * 3600)
ET_model = T .+ E
if drivers.LE.status == absent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,10 @@ for float_type in (Float32, Float64)

# Evaporation
E = [
parent(sv.saveval[k].soil.turbulent_fluxes.vapor_flux)[1] for
k in 2:length(sol.t)
parent(
sv.saveval[k].soil.turbulent_fluxes.vapor_flux_liq .+
sv.saveval[k].soil.turbulent_fluxes.vapor_flux_ice,
)[1] for k in 2:length(sol.t)
]
# Root sink term: a positive root extraction is a sink term for soil; add minus sign
root_sink =
Expand Down
12 changes: 6 additions & 6 deletions experiments/long_runs/land.jl
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ function setup_prob(t0, tf, Δt; outdir = outdir, nelements = (101, 15))
t0,
ref_time;
output_writer = nc_writer,
output_vars = :long,
output_vars = :short,
)

diagnostic_handler =
Expand All @@ -628,7 +628,7 @@ end
function setup_and_solve_problem(; greet = false)

t0 = 0.0
tf = 60 * 60.0 * 24 * 7 # keep short until it runs! * 365
tf = 60 * 60.0 * 24 * 14
Δt = 900.0
nelements = (101, 15)
if greet
Expand All @@ -641,12 +641,12 @@ function setup_and_solve_problem(; greet = false)
prob, cb = setup_prob(t0, tf, Δt; nelements)

# Define timestepper and ODE algorithm
stepper = CTS.ARS343()
stepper = CTS.ARS111()
ode_algo = CTS.IMEXAlgorithm(
stepper,
CTS.NewtonsMethod(
max_iters = 1,
update_j = CTS.UpdateEvery(CTS.NewTimeStep),
max_iters = 3,
update_j = CTS.UpdateEvery(CTS.NewNewtonIteration),
),
)
SciMLBase.solve(prob, ode_algo; dt = Δt, callback = cb, adaptive = false)
Expand All @@ -657,7 +657,7 @@ setup_and_solve_problem(; greet = true);
# read in diagnostics and make some plots!
#### ClimaAnalysis ####
simdir = ClimaAnalysis.SimDir(outdir)
short_names = ["gpp", "swc", "si", "sie"]
short_names = ["gpp", "ct", "lai", "swc", "si"]
for short_name in short_names
var = get(simdir; short_name)
times = ClimaAnalysis.times(var)
Expand Down
3 changes: 2 additions & 1 deletion experiments/long_runs/soil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ function setup_prob(t0, tf, Δt; outdir = outdir, nelements = (101, 15))
t0,
ref_time;
output_writer = nc_writer,
average_period = :monthly,
)

diagnostic_handler =
Expand All @@ -439,7 +440,7 @@ end
function setup_and_solve_problem(; greet = false)

t0 = 0.0
tf = 60 * 60.0 * 24 * 60 # keep short until it runs! * 365
tf = 60 * 60.0 * 24 * 340
Δt = 900.0
nelements = (101, 15)
if greet
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ function make_output_df(
(1, :soil, :turbulent_fluxes, :lhf),
collect(map(i -> (i, :soil, :T), 1:20)), # 20 shouldn't be hard-coded, but an arg, equal to n layers
collect(map(i -> (i, :soil, :θ_l), 1:20)),
(1, :soil, :turbulent_fluxes, :vapor_flux),
(1, :soil, :turbulent_fluxes, :vapor_flux_liq),
(1, :canopy, :sif, :SIF),
)

Expand Down
2 changes: 1 addition & 1 deletion lib/ClimaLandSimulations/src/utilities/makie_plots.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function timeseries_fluxes_fig(
p_ET_m = lines!(
ax_W,
datetime2unix.(climaland.DateTime),
(climaland.vapor_flux .* 1e3 .* 24 .* 3600) .+
(climaland.vapor_flux_liq .* 1e3 .* 24 .* 3600) .+
(climaland.transpiration .* 1e3 .* 24 .* 3600),
color = :blue,
) # not sure about units
Expand Down
2 changes: 1 addition & 1 deletion src/diagnostics/land_compute_methods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ end
@diagnostic_compute "soil_aerodynamic_resistance" SoilCanopyModel p.soil.turbulent_fluxes.r_ae
@diagnostic_compute "soil_latent_heat_flux" SoilCanopyModel p.soil.turbulent_fluxes.lhf
@diagnostic_compute "soil_sensible_heat_flux" SoilCanopyModel p.soil.turbulent_fluxes.shf
@diagnostic_compute "vapor_flux" SoilCanopyModel p.soil.turbulent_fluxes.vapor_flux
@diagnostic_compute "vapor_flux" SoilCanopyModel p.soil.turbulent_fluxes.vapor_flux_liq # should add ice here
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean add vapor_flux_ice?
But it currently doesn't exist?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in this PR we added it. eventually it would be nice to have sublimation as a diagnostic also, and I could add it in this PR?


# Soil - SoilCO2
function compute_heterotrophic_respiration!(
Expand Down
5 changes: 1 addition & 4 deletions src/integrated/soil_canopy_model.jl
Original file line number Diff line number Diff line change
Expand Up @@ -418,11 +418,8 @@ function soil_boundary_fluxes!(
bc = soil.boundary_conditions.top
p.soil.turbulent_fluxes .= turbulent_fluxes(bc.atmos, soil, Y, p, t)
Soil.Runoff.update_runoff!(p, bc.runoff, Y, t, soil)
# Multiply the vapor flux by 1 - p.soil.ice_frac to get
# the approximated evaporation of liquid water
@. p.soil.top_bc.water =
p.soil.infiltration +
p.soil.turbulent_fluxes.vapor_flux * (1 - p.soil.ice_frac)
p.soil.infiltration + p.soil.turbulent_fluxes.vapor_flux_liq
@. p.soil.top_bc.heat =
-p.soil.R_n + p.soil.turbulent_fluxes.lhf + p.soil.turbulent_fluxes.shf
end
Expand Down
5 changes: 4 additions & 1 deletion src/standalone/Soil/Soil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ import ClimaCore.MatrixFields: @name, ⋅
import ..Parameters as LP
import ClimaCore: Fields, Operators, Geometry, Spaces
using Thermodynamics

using SurfaceFluxes
using StaticArrays
import SurfaceFluxes.Parameters as SFP
import ClimaLand.Domains: Column, HybridBox, SphericalShell
import ClimaLand:
AbstractImExModel,
Expand All @@ -90,6 +92,7 @@ import ClimaLand:
surface_emissivity,
surface_height,
surface_resistance,
turbulent_fluxes,
get_drivers
export RichardsModel,
RichardsParameters,
Expand Down
15 changes: 6 additions & 9 deletions src/standalone/Soil/boundary_conditions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,6 @@ boundary_vars(
::ClimaLand.TopBoundary,
) = (
:turbulent_fluxes,
:ice_frac,
:R_n,
:top_bc,
:sfc_scratch,
Expand Down Expand Up @@ -692,7 +691,6 @@ boundary_var_domain_names(
:surface,
:surface,
:surface,
:surface,
Runoff.runoff_var_domain_names(bc.runoff)...,
)
"""
Expand All @@ -717,8 +715,10 @@ boundary_var_types(
},
::ClimaLand.TopBoundary,
) where {FT} = (
NamedTuple{(:lhf, :shf, :vapor_flux, :r_ae), Tuple{FT, FT, FT, FT}},
FT,
NamedTuple{
(:lhf, :shf, :vapor_flux_liq, :r_ae, :vapor_flux_ice),
Tuple{FT, FT, FT, FT, FT},
},
FT,
NamedTuple{(:water, :heat), Tuple{FT, FT}},
FT,
Expand Down Expand Up @@ -764,12 +764,9 @@ function soil_boundary_fluxes!(
p.soil.turbulent_fluxes .= turbulent_fluxes(bc.atmos, model, Y, p, t)
p.soil.R_n .= net_radiation(bc.radiation, model, Y, p, t)
update_runoff!(p, bc.runoff, Y, t, model)
# We do not model the energy flux from infiltration. We multiply
# the vapor flux by the ice fraction in order to get the contribution
# from liquid water
# We do not model the energy flux from infiltration.
@. p.soil.top_bc.water =
p.soil.infiltration +
p.soil.turbulent_fluxes.vapor_flux * (1 - p.soil.ice_frac)
p.soil.infiltration + p.soil.turbulent_fluxes.vapor_flux_liq
@. p.soil.top_bc.heat =
p.soil.R_n + p.soil.turbulent_fluxes.lhf + p.soil.turbulent_fluxes.shf
end
Expand Down
Loading
Loading