Skip to content

Commit 790bf3e

Browse files
authored
add perturbed RH run (#1314)
1 parent 68e41a2 commit 790bf3e

File tree

6 files changed

+680
-235
lines changed

6 files changed

+680
-235
lines changed

.buildkite/longruns_gpu/pipeline.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ steps:
3939

4040
- group: "Global Land Models"
4141
if: build.env("LONGER_RUN") == null
42+
if: build.env("PERTURBED_RUN") == null
4243
steps:
4344

4445
- label: ":snow_capped_mountain: Snowy Land"
@@ -105,6 +106,34 @@ steps:
105106
env:
106107
CLIMACOMMS_DEVICE: "CUDA"
107108

109+
- group: "Perturbed Low-res Global Land Models"
110+
if: build.env("PERTURBED_RUN") != null
111+
steps:
112+
113+
- label: ":snow_capped_mountain: Low-Res Snowy Land Perturbed Temperature"
114+
command:
115+
- julia --color=yes --project=.buildkite experiments/long_runs/low_res_snowy_land_temp.jl
116+
artifact_paths:
117+
- "lowres_snowy_land_longrun_temp_gpu/*png"
118+
agents:
119+
slurm_gpus: 1
120+
slurm_time: 3:00:00
121+
env:
122+
CLIMACOMMS_DEVICE: "CUDA"
123+
PERTURBED_RUN: ""
124+
125+
- label: ":snow_capped_mountain: Low-Res Snowy Land Perturbed RH"
126+
command:
127+
- julia --color=yes --project=.buildkite experiments/long_runs/low_res_snowy_land_rh.jl
128+
artifact_paths:
129+
- "lowres_snowy_land_longrun_rh_gpu/*png"
130+
agents:
131+
slurm_gpus: 1
132+
slurm_time: 3:00:00
133+
env:
134+
CLIMACOMMS_DEVICE: "CUDA"
135+
PERTURBED_RUN: ""
136+
108137
- group: "Longer runs of Global Land Models"
109138
if: build.env("LONGER_RUN") != null
110139
steps:
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
1# # Global run of land model at low resolution
2+
3+
# The code sets up and runs ClimaLand v1, which
4+
# includes soil, canopy, and snow, on a spherical domain,
5+
# using low resolution ERA5 data as forcing.
6+
7+
# Simulation Setup
8+
# Number of spatial elements: 30 in horizontal, 15 in vertical
9+
# Soil depth: 50 m
10+
# Simulation duration: 730 d
11+
# Timestep: 450 s
12+
# Timestepper: ARS111
13+
# Fixed number of iterations: 3
14+
# Jacobian update: every new Newton iteration
15+
# Atmos forcing update: every 3 hours
16+
17+
import ClimaComms
18+
ClimaComms.@import_required_backends
19+
using ClimaUtilities.ClimaArtifacts
20+
import ClimaUtilities.TimeManager: ITime, date
21+
22+
import ClimaDiagnostics
23+
import ClimaUtilities
24+
25+
import ClimaUtilities.TimeVaryingInputs:
26+
TimeVaryingInput, LinearInterpolation, PeriodicCalendar
27+
import ClimaUtilities.ClimaArtifacts: @clima_artifact
28+
import ClimaParams as CP
29+
using ClimaCore
30+
using ClimaLand
31+
using ClimaLand.Snow
32+
using ClimaLand.Soil
33+
using ClimaLand.Canopy
34+
import ClimaLand
35+
import ClimaLand.Parameters as LP
36+
import ClimaLand.Simulations: LandSimulation, solve!
37+
38+
using Dates
39+
40+
using CairoMakie, GeoMakie, ClimaAnalysis
41+
import ClimaLand.LandSimVis as LandSimVis
42+
43+
const FT = Float64;
44+
context = ClimaComms.context()
45+
ClimaComms.init(context)
46+
device = ClimaComms.device()
47+
device_suffix = device isa ClimaComms.CPUSingleThreaded ? "cpu" : "gpu"
48+
root_path = "lowres_snowy_land_longrun_rh_$(device_suffix)"
49+
diagnostics_outdir = joinpath(root_path, "global_diagnostics")
50+
outdir =
51+
ClimaUtilities.OutputPathGenerator.generate_output_path(diagnostics_outdir)
52+
53+
function setup_model(FT, start_date, stop_date, Δt, domain, earth_param_set)
54+
surface_domain = ClimaLand.Domains.obtain_surface_domain(domain)
55+
surface_space = domain.space.surface
56+
# Forcing data
57+
era5_ncdata_path = ClimaLand.Artifacts.era5_land_forcing_data2008_path(;
58+
context,
59+
lowres = true,
60+
)
61+
atmos, radiation = ClimaLand.prescribed_perturbed_rh_era5(
62+
era5_ncdata_path,
63+
surface_space,
64+
start_date,
65+
earth_param_set,
66+
-0.2,
67+
FT;
68+
max_wind_speed = 25.0,
69+
time_interpolation_method = LinearInterpolation(PeriodicCalendar()),
70+
)
71+
forcing = (; atmos, radiation)
72+
73+
# Read in LAI from MODIS data
74+
modis_lai_ncdata_path = ClimaLand.Artifacts.modis_lai_multiyear_paths(;
75+
context = nothing,
76+
start_date,
77+
end_date = stop_date,
78+
)
79+
LAI = ClimaLand.prescribed_lai_modis(
80+
modis_lai_ncdata_path,
81+
surface_space,
82+
start_date;
83+
time_interpolation_method = LinearInterpolation(),
84+
)
85+
86+
# Overwrite some defaults for the canopy model
87+
# Energy model
88+
ac_canopy = FT(2.5e3)
89+
energy = Canopy.BigLeafEnergyModel{FT}(; ac_canopy)
90+
91+
# Plant hydraulics
92+
a = FT(0.2 * 0.0098) # 1/m
93+
retention_model = Canopy.PlantHydraulics.LinearRetentionCurve{FT}(a)
94+
hydraulics =
95+
Canopy.PlantHydraulicsModel{FT}(surface_domain, LAI; retention_model)
96+
97+
# Roughness lengths
98+
h_canopy = hydraulics.compartment_surfaces[end]
99+
z0_m = FT(0.13) * h_canopy
100+
z0_b = FT(0.1) * z0_m
101+
102+
ground = ClimaLand.PrognosticGroundConditions{FT}()
103+
canopy_forcing = (; atmos, radiation, ground)
104+
105+
canopy = ClimaLand.Canopy.CanopyModel{FT}(
106+
surface_domain,
107+
canopy_forcing,
108+
LAI,
109+
earth_param_set;
110+
prognostic_land_components = (:canopy, :snow, :soil, :soilco2),
111+
energy,
112+
hydraulics,
113+
z_0m = z0_m,
114+
z_0b = z0_b,
115+
)
116+
117+
# Snow model setup
118+
# Set β = 0 in order to regain model without density dependence
119+
α_snow = Snow.ZenithAngleAlbedoModel(
120+
FT(0.64),
121+
FT(0.06),
122+
FT(2);
123+
β = FT(0.4),
124+
x0 = FT(0.2),
125+
)
126+
horz_degree_res =
127+
sum(ClimaLand.Domains.average_horizontal_resolution_degrees(domain)) / 2 # mean of resolution in latitude and longitude, in degrees
128+
scf = Snow.WuWuSnowCoverFractionModel(
129+
FT(0.08),
130+
FT(1.77),
131+
FT(1.0),
132+
horz_degree_res,
133+
)
134+
snow = Snow.SnowModel(
135+
FT,
136+
surface_domain,
137+
forcing,
138+
earth_param_set,
139+
Δt;
140+
prognostic_land_components = (:canopy, :snow, :soil, :soilco2),
141+
α_snow,
142+
scf,
143+
)
144+
145+
# Construct the land model with all default components except for snow
146+
land =
147+
LandModel{FT}(forcing, LAI, earth_param_set, domain, Δt; snow, canopy)
148+
return land
149+
end
150+
# Note that since the Northern hemisphere's winter season is defined as DJF,
151+
# we simulate from and until the beginning of
152+
# March so that a full season is included in seasonal metrics.
153+
start_date = DateTime("2008-03-01")
154+
stop_date = DateTime("2010-03-02")
155+
Δt = 450.0
156+
nelements = (30, 15)
157+
domain = ClimaLand.Domains.global_domain(
158+
FT;
159+
context,
160+
nelements,
161+
mask_threshold = FT(0.99),
162+
)
163+
params = LP.LandParameters(FT)
164+
model = setup_model(FT, start_date, stop_date, Δt, domain, params)
165+
user_callbacks = (
166+
ClimaLand.NaNCheckCallback(
167+
Dates.Month(6),
168+
start_date,
169+
ITime(Δt, epoch = start_date),
170+
mask = ClimaLand.Domains.landsea_mask(ClimaLand.get_domain(model)),
171+
),
172+
ClimaLand.ReportCallback(10000),
173+
)
174+
simulation =
175+
LandSimulation(start_date, stop_date, Δt, model; user_callbacks, outdir)
176+
@info "Run: Global Soil-Canopy-Snow Model"
177+
@info "Resolution: $nelements"
178+
@info "Timestep: $Δt s"
179+
@info "Start Date: $start_date"
180+
@info "Stop Date: $stop_date"
181+
ClimaLand.Simulations.solve!(simulation)
182+
183+
LandSimVis.make_annual_timeseries(simulation; savedir = root_path)
184+
LandSimVis.make_heatmaps(simulation; savedir = root_path, date = stop_date)

experiments/long_runs/low_res_snowy_land.jl renamed to experiments/long_runs/low_res_snowy_land_temp.jl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ context = ClimaComms.context()
4545
ClimaComms.init(context)
4646
device = ClimaComms.device()
4747
device_suffix = device isa ClimaComms.CPUSingleThreaded ? "cpu" : "gpu"
48-
root_path = "lowres_snowy_land_longrun_$(device_suffix)"
48+
root_path = "lowres_snowy_land_longrun_temp_$(device_suffix)"
4949
diagnostics_outdir = joinpath(root_path, "global_diagnostics")
5050
outdir =
5151
ClimaUtilities.OutputPathGenerator.generate_output_path(diagnostics_outdir)
@@ -58,12 +58,12 @@ function setup_model(FT, start_date, stop_date, Δt, domain, earth_param_set)
5858
context,
5959
lowres = true,
6060
)
61-
atmos, radiation = ClimaLand.prescribed_perturbed_forcing_era5(
61+
atmos, radiation = ClimaLand.prescribed_perturbed_temperature_era5(
6262
era5_ncdata_path,
6363
surface_space,
6464
start_date,
6565
earth_param_set,
66-
5.0,
66+
10.0,
6767
FT;
6868
max_wind_speed = 25.0,
6969
time_interpolation_method = LinearInterpolation(PeriodicCalendar()),
@@ -182,4 +182,3 @@ ClimaLand.Simulations.solve!(simulation)
182182

183183
LandSimVis.make_annual_timeseries(simulation; savedir = root_path)
184184
LandSimVis.make_heatmaps(simulation; savedir = root_path, date = stop_date)
185-
LandSimVis.make_leaderboard_plots(simulation; savedir = root_path)

src/ClimaLand.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ include("shared_utilities/checkpoints.jl")
2424
include("shared_utilities/utils.jl")
2525
include("shared_utilities/models.jl")
2626
include("shared_utilities/drivers.jl")
27+
include("shared_utilities/perturbed_drivers.jl")
2728
include("shared_utilities/boundary_conditions.jl")
2829
include("shared_utilities/sources.jl")
2930
include("shared_utilities/implicit_timestepping.jl")

0 commit comments

Comments
 (0)