Skip to content

add perturbed RH run #1314

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

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
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
42 changes: 30 additions & 12 deletions .buildkite/longruns_gpu/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,18 +53,6 @@ steps:
env:
CLIMACOMMS_DEVICE: "CUDA"

- label: ":snow_capped_mountain: Low-Res Snowy Land"
command:
- julia --color=yes --project=.buildkite experiments/long_runs/low_res_snowy_land.jl
artifact_paths:
- "lowres_snowy_land_longrun_gpu/*png"
- "lowres_snowy_land_longrun_gpu/*pdf"
agents:
slurm_gpus: 1
slurm_time: 3:00:00
env:
CLIMACOMMS_DEVICE: "CUDA"

- label: ":sunglasses: California regional simulation"
command:
- julia --color=yes --project=.buildkite experiments/long_runs/land_region.jl
Expand Down Expand Up @@ -95,6 +83,36 @@ steps:
env:
CLIMACOMMS_DEVICE: "CUDA"

- group: "Perturbed Low-res Global Land Models"
if: build.env("PERTURBED_RUN") != null
Copy link
Member

Choose a reason for hiding this comment

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

how does this var get set?

Copy link
Member Author

Choose a reason for hiding this comment

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

you set it in buildkite - click on new build in the top right corner, and then add your branch instead of main (or use main), and then add an environment variable
PERTURBED_RUN=""

(it is also how we trigger longer runs if you want to do a one off run of those. Otherwise we set the environment variable in our scheduled long run here: https://buildkite.com/clima/climaland-long-runs/settings/schedules/c7373c40-27cc-4051-b13a-58769f62f5e7)

steps:

- label: ":snow_capped_mountain: Low-Res Snowy Land Perturbed Temperature"
command:
- julia --color=yes --project=.buildkite experiments/long_runs/low_res_snowy_land_temp.jl
artifact_paths:
- "lowres_snowy_land_longrun_temp_gpu/*png"
- "lowres_snowy_land_longrun_temp_gpu/*pdf"
agents:
slurm_gpus: 1
slurm_time: 3:00:00
env:
CLIMACOMMS_DEVICE: "CUDA"
PERTURBED_RUN: ""

- label: ":snow_capped_mountain: Low-Res Snowy Land Perturbed RH"
command:
- julia --color=yes --project=.buildkite experiments/long_runs/low_res_snowy_land_rh.jl
artifact_paths:
- "lowres_snowy_land_longrun_rh_gpu/*png"
- "lowres_snowy_land_longrun_rh_gpu/*pdf"
agents:
slurm_gpus: 1
slurm_time: 3:00:00
env:
CLIMACOMMS_DEVICE: "CUDA"
PERTURBED_RUN: ""

- group: "Longer runs of Global Land Models"
if: build.env("LONGER_RUN") != null
steps:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ context = ClimaComms.context()
ClimaComms.init(context)
device = ClimaComms.device()
device_suffix = device isa ClimaComms.CPUSingleThreaded ? "cpu" : "gpu"
root_path = "lowres_snowy_land_longrun_$(device_suffix)"
root_path = "lowres_snowy_land_longrun_rh_$(device_suffix)"
diagnostics_outdir = joinpath(root_path, "global_diagnostics")
outdir =
ClimaUtilities.OutputPathGenerator.generate_output_path(diagnostics_outdir)
Expand All @@ -58,12 +58,12 @@ function setup_model(FT, start_date, stop_date, Δt, domain, earth_param_set)
context,
lowres = true,
)
atmos, radiation = ClimaLand.prescribed_perturbed_forcing_era5(
atmos, radiation = ClimaLand.prescribed_perturbed_rh_era5(
era5_ncdata_path,
surface_space,
start_date,
earth_param_set,
5.0,
-0.2,
FT;
max_wind_speed = 25.0,
time_interpolation_method = LinearInterpolation(PeriodicCalendar()),
Expand Down
185 changes: 185 additions & 0 deletions experiments/long_runs/low_res_snowy_land_temp.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# # Global run of land model at low resolution

# The code sets up and runs ClimaLand v1, which
# includes soil, canopy, and snow, on a spherical domain,
# using low resolution ERA5 data as forcing.

# Simulation Setup
# Number of spatial elements: 30 in horizontal, 15 in vertical
# Soil depth: 50 m
# Simulation duration: 730 d
# Timestep: 450 s
# Timestepper: ARS111
# Fixed number of iterations: 3
# Jacobian update: every new Newton iteration
# Atmos forcing update: every 3 hours

import ClimaComms
ClimaComms.@import_required_backends
using ClimaUtilities.ClimaArtifacts
import ClimaUtilities.TimeManager: ITime, date

import ClimaDiagnostics
import ClimaUtilities

import ClimaUtilities.TimeVaryingInputs:
TimeVaryingInput, LinearInterpolation, PeriodicCalendar
import ClimaUtilities.ClimaArtifacts: @clima_artifact
import ClimaParams as CP
using ClimaCore
using ClimaLand
using ClimaLand.Snow
using ClimaLand.Soil
using ClimaLand.Canopy
import ClimaLand
import ClimaLand.Parameters as LP
import ClimaLand.Simulations: LandSimulation, solve!

using Dates

using CairoMakie, GeoMakie, Poppler_jll, ClimaAnalysis
import ClimaLand.LandSimVis as LandSimVis

const FT = Float64;
context = ClimaComms.context()
ClimaComms.init(context)
device = ClimaComms.device()
device_suffix = device isa ClimaComms.CPUSingleThreaded ? "cpu" : "gpu"
root_path = "lowres_snowy_land_longrun_temp_$(device_suffix)"
diagnostics_outdir = joinpath(root_path, "global_diagnostics")
outdir =
ClimaUtilities.OutputPathGenerator.generate_output_path(diagnostics_outdir)

function setup_model(FT, start_date, stop_date, Δt, domain, earth_param_set)
surface_domain = ClimaLand.Domains.obtain_surface_domain(domain)
surface_space = domain.space.surface
# Forcing data
era5_ncdata_path = ClimaLand.Artifacts.era5_land_forcing_data2008_path(;
context,
lowres = true,
)
atmos, radiation = ClimaLand.prescribed_perturbed_temperature_era5(
era5_ncdata_path,
surface_space,
start_date,
earth_param_set,
10.0,
FT;
max_wind_speed = 25.0,
time_interpolation_method = LinearInterpolation(PeriodicCalendar()),
)
forcing = (; atmos, radiation)

# Read in LAI from MODIS data
modis_lai_ncdata_path = ClimaLand.Artifacts.modis_lai_multiyear_paths(;
context = nothing,
start_date,
end_date = stop_date,
)
LAI = ClimaLand.prescribed_lai_modis(
modis_lai_ncdata_path,
surface_space,
start_date;
time_interpolation_method = LinearInterpolation(),
)

# Overwrite some defaults for the canopy model
# Energy model
ac_canopy = FT(2.5e3)
energy = Canopy.BigLeafEnergyModel{FT}(; ac_canopy)

# Plant hydraulics
a = FT(0.2 * 0.0098) # 1/m
retention_model = Canopy.PlantHydraulics.LinearRetentionCurve{FT}(a)
hydraulics =
Canopy.PlantHydraulicsModel{FT}(surface_domain, LAI; retention_model)

# Roughness lengths
h_canopy = hydraulics.compartment_surfaces[end]
z0_m = FT(0.13) * h_canopy
z0_b = FT(0.1) * z0_m

ground = ClimaLand.PrognosticGroundConditions{FT}()
canopy_forcing = (; atmos, radiation, ground)

canopy = ClimaLand.Canopy.CanopyModel{FT}(
surface_domain,
canopy_forcing,
LAI,
earth_param_set;
prognostic_land_components = (:canopy, :snow, :soil, :soilco2),
energy,
hydraulics,
z_0m = z0_m,
z_0b = z0_b,
)

# Snow model setup
# Set β = 0 in order to regain model without density dependence
α_snow = Snow.ZenithAngleAlbedoModel(
FT(0.64),
FT(0.06),
FT(2);
β = FT(0.4),
x0 = FT(0.2),
)
horz_degree_res =
sum(ClimaLand.Domains.average_horizontal_resolution_degrees(domain)) / 2 # mean of resolution in latitude and longitude, in degrees
scf = Snow.WuWuSnowCoverFractionModel(
FT(0.08),
FT(1.77),
FT(1.0),
horz_degree_res,
)
snow = Snow.SnowModel(
FT,
surface_domain,
forcing,
earth_param_set,
Δt;
prognostic_land_components = (:canopy, :snow, :soil, :soilco2),
α_snow,
scf,
)

# Construct the land model with all default components except for snow
land =
LandModel{FT}(forcing, LAI, earth_param_set, domain, Δt; snow, canopy)
return land
end
# Note that since the Northern hemisphere's winter season is defined as DJF,
# we simulate from and until the beginning of
# March so that a full season is included in seasonal metrics.
start_date = DateTime("2008-03-01")
stop_date = DateTime("2010-03-02")
Δt = 450.0
nelements = (30, 15)
domain = ClimaLand.Domains.global_domain(
FT;
context,
nelements,
mask_threshold = FT(0.99),
)
params = LP.LandParameters(FT)
model = setup_model(FT, start_date, stop_date, Δt, domain, params)
user_callbacks = (
ClimaLand.NaNCheckCallback(
Dates.Month(6),
start_date,
ITime(Δt, epoch = start_date),
mask = ClimaLand.Domains.landsea_mask(ClimaLand.get_domain(model)),
),
ClimaLand.ReportCallback(10000),
)
simulation =
LandSimulation(FT, start_date, stop_date, Δt, model; user_callbacks, outdir)
@info "Run: Global Soil-Canopy-Snow Model"
@info "Resolution: $nelements"
@info "Timestep: $Δt s"
@info "Start Date: $start_date"
@info "Stop Date: $stop_date"
ClimaLand.Simulations.solve!(simulation)

LandSimVis.make_annual_timeseries(simulation; savedir = root_path)
LandSimVis.make_heatmaps(simulation; savedir = root_path, date = stop_date)
LandSimVis.make_leaderboard_plots(simulation; savedir = root_path)
Loading
Loading