Skip to content

Commit 51a8e47

Browse files
committed
Working ClimaLand calibration [skip ci]
1 parent b6e3103 commit 51a8e47

File tree

6 files changed

+53
-43
lines changed

6 files changed

+53
-43
lines changed

.buildkite/Manifest-v1.11.toml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -429,8 +429,8 @@ weakdeps = ["GeoMakie", "Makie"]
429429

430430
[[deps.ClimaCalibrate]]
431431
deps = ["Dates", "Distributed", "Distributions", "EnsembleKalmanProcesses", "JLD2", "Logging", "Random", "TOML", "YAML"]
432-
git-tree-sha1 = "2408ba55a30ac0f67550ef9d87cebfc372af3cca"
433-
repo-rev = "main"
432+
git-tree-sha1 = "fe9ddc24349035098116663fd0136e960d3cbb3c"
433+
repo-rev = "kp/identity"
434434
repo-url = "https://github.com/CliMA/ClimaCalibrate.jl.git"
435435
uuid = "4347a170-ebd6-470c-89d3-5c705c0cacc2"
436436
version = "0.1.2"
@@ -1251,9 +1251,9 @@ weakdeps = ["Makie"]
12511251

12521252
[[deps.GeoMakie]]
12531253
deps = ["Colors", "CoordinateTransformations", "Downloads", "GeoFormatTypes", "GeoInterface", "GeoInterfaceMakie", "GeoJSON", "Geodesy", "GeometryBasics", "GeometryOps", "ImageIO", "LinearAlgebra", "Makie", "NaturalEarth", "Proj", "Reexport", "Statistics", "StructArrays"]
1254-
git-tree-sha1 = "8ef9756e37ca5bc892e920551f9aa683d5b8fab3"
1254+
git-tree-sha1 = "2db1d309af35a1ad440e75b9275e4b3b4715ed39"
12551255
uuid = "db073c08-6b98-4ee5-b6a4-5efafb3259c6"
1256-
version = "0.7.13"
1256+
version = "0.7.12"
12571257

12581258
[[deps.Geodesy]]
12591259
deps = ["CoordinateTransformations", "Dates", "LinearAlgebra", "StaticArrays"]

experiments/better_calibration/generate_observations.jl

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,20 @@ function preprocess_single_era5_var(var::OutputVar, short_name, nelements)
145145
end
146146

147147
if abspath(PROGRAM_FILE) == @__FILE__
148+
# covar_estimator =
149+
# ClimaCalibrate.ObservationRecipe.SeasonalDiagonalCovariance(;
150+
# model_error_scale = Float32(0.05),
151+
# regularization = Float32(25.0),
152+
# ignore_nan = true,
153+
# use_latitude_weights = true,
154+
# min_cosd_lat = 0.1
155+
# )
148156
covar_estimator =
149-
ClimaCalibrate.ObservationRecipe.SeasonalDiagonalCovariance(
150-
model_error_scale = Float32(0.05),
151-
regularization = Float32(25.0),
152-
ignore_nan = true,
157+
ClimaCalibrate.ObservationRecipe.ScalarCovariance(;
158+
scalar = 25.0,
159+
use_latitude_weights = true,
160+
min_cosd_lat = 0.1,
153161
)
154-
155162
(; nelements, sample_date_ranges, short_names) = get_config()
156163
@info "The number of samples is $(length(sample_date_ranges))"
157164

experiments/better_calibration/getters.jl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function get_config()
4949
# start of DJF and SON
5050
sample_date_ranges = [
5151
(Dates.DateTime(year, 12, 1), Dates.DateTime(year + 1, 9, 1)) for
52-
year in 2000:2020
52+
year in 2000:2009
5353
],
5454
spinup = Dates.Month(3), # Dates.Year(1)
5555
# TODO: Not sure if sample_date_ranges is the best way of determining
@@ -75,7 +75,7 @@ Return a named tuple consisting of
7575
function get_calibration_config()
7676
rng_seed = 42
7777
rng = Random.MersenneTwister(rng_seed)
78-
return (; minibatch_size = 3, n_iterations = 7, rng = rng) # TODO Change this!
78+
return (; minibatch_size = 2, n_iterations = 6, rng = rng)
7979
end
8080

8181
"""
@@ -119,14 +119,14 @@ end
119119
"""
120120
function get_prior()
121121
priors = [
122-
# EKP.constrained_gaussian("α_0", 0.64, 0.05, 0.2, 0.8),
123122
# EKP.constrained_gaussian("Δα", 0.2, 0.1, 0.0, 1.0),
124123
# EKP.constrained_gaussian("k", 10, 5, 2, 25),
125124
# EKP.constrained_gaussian("beta_snow", 0.4, 0.2, 0.1, 0.8),
126125
# EKP.constrained_gaussian("x0_snow", 0.4, 0.2, 0.1, 0.8),
127-
EKP.constrained_gaussian("beta_snow_cover", 1.77, 0.2, 0.1, 2.5);
128-
EKP.constrained_gaussian("z0_snow_cover", 0.106, 0.03, 0.0, 0.3);
129-
EKP.constrained_gaussian("Δα", 0.7, 0.2, 0.0, 1.0);
126+
EKP.constrained_gaussian("beta_snow_cover", 1.77, 0.2, 0.1, 2.5),
127+
EKP.constrained_gaussian("z0_snow_cover", 0.106, 0.03, 0.0, 0.3),
128+
EKP.constrained_gaussian("α_0", 0.7, 0.2, 0.0, 1.0),
129+
# EKP.constrained_gaussian("Δα", 0.7, 0.2, 0.0, 1.0);
130130
# EKP.constrained_gaussian("z0_snow", 0.106, 0.05, 0.01, 0.3),
131131
]
132132
return EKP.combine_distributions(priors)

experiments/better_calibration/model_interface.jl

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,9 @@ function setup_model(
7474
calibrate_param_dict,
7575
)
7676
# TODO: This should be better when the interface improved
77-
α_0 = FT(get(calibrate_param_dict, "α_0", 0.64))
78-
Δα = FT(get(calibrate_param_dict, "Δα", 0.06))
79-
k = FT(get(calibrate_param_dict, "k", 2))
80-
beta_snow = FT(get(calibrate_param_dict, "beta_snow", 0.4))
81-
x0_snow = FT(get(calibrate_param_dict, "x0_snow", 0.2))
77+
α_0 = FT(get(calibrate_param_dict, "α_0", 0.7))
8278
beta_snow_cover = FT(get(calibrate_param_dict, "beta_snow_cover", 0.2))
8379
z0_snow_cover = FT(get(calibrate_param_dict, "z0_snow_cover", 0.2))
84-
Δα = FT(get(calibrate_param_dict, "Δα", 0.2))
8580

8681
time_interpolation_method =
8782
LONGER_RUN ? LinearInterpolation() :
@@ -305,15 +300,15 @@ function setup_model(
305300
)
306301

307302
# Snow model
308-
# α_snow = Snow.ConstantAlbedoModel(FT(0.7))
303+
α_snow = Snow.ConstantAlbedoModel(FT(α_0))
309304
# Set β = 0 in order to regain model without density dependence
310-
α_snow = Snow.ZenithAngleAlbedoModel(
311-
FT(α_0),
312-
FT(Δα),
313-
FT(k);
314-
β = FT(beta_snow),
315-
x0 = FT(x0_snow),
316-
)
305+
# α_snow = Snow.ZenithAngleAlbedoModel(
306+
# FT(α_0),
307+
# FT(Δα),
308+
# FT(k);
309+
# β = FT(beta_snow),
310+
# x0 = FT(x0_snow),
311+
# )
317312
horz_degree_res =
318313
sum(ClimaLand.Domains.average_horizontal_resolution_degrees(domain)) / 2 # mean of resolution in latitude and longitude, in degrees
319314
scf = Snow.WuWuSnowCoverFractionModel(
@@ -356,6 +351,12 @@ function setup_model(
356351
return land
357352
end
358353

354+
function close_diagnostics(sim)
355+
for diagnostic in sim.diagnostics
356+
close(diagnostic.output_writer)
357+
end
358+
end
359+
359360
function ClimaCalibrate.forward_model(iteration, member)
360361
(; output_dir, sample_date_ranges, nelements, spinup, extend) = get_config()
361362
ensemble_member_path =
@@ -407,5 +408,6 @@ function ClimaCalibrate.forward_model(iteration, member)
407408
simulation = LandSimulation(FT, start_date, stop_date, Δt, model; outdir)
408409
@info "Simulation is setted up. Going to solve the simulation."
409410
ClimaLand.Simulations.solve!(simulation)
411+
close_diagnostics(simulation)
410412
return nothing
411413
end

experiments/better_calibration/observation_map.jl

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,19 @@ function process_member_data(
9090
vars = map(short_names) do short_name
9191
var = sim_var_dict[short_name]()
9292
var =
93-
ClimaAnalysis.average_season_across_time(var, ignore_nan = true)
93+
ClimaAnalysis.average_season_across_time(var, ignore_nan = false)
9494

9595
ocean_mask = make_ocean_mask(nelements)
9696
var = ocean_mask(var)
9797

9898
# Replace all NaNs on land with the mean value
9999
# This is needed to stop small NaN values from stopping the calibration
100-
nanmean_land_val = mean(filter(!isnan, var.data))
100+
# TODO: This is a stopgap. It might be better to leave them as NaNs. As a temporary
101+
# solution, we replace with 500.0
102+
nanmean_land_val = 500.0 # mean(filter(!isnan, var.data))
101103
var = ClimaAnalysis.replace(val -> isnan(val) ? nanmean_land_val : val, var)
102104
var = ocean_mask(var)
103105

104-
105106
lons = ClimaAnalysis.longitudes(var)
106107
var = ClimaAnalysis.window(
107108
var,
@@ -172,16 +173,16 @@ function ClimaCalibrate.analyze_iteration(
172173
# EKP.TransformUnscented
173174
diagnostics_folder_path = joinpath(output_path, "global_diagnostics")
174175
try
175-
# compute_monthly_leaderboard(
176-
# output_path,
177-
# diagnostics_folder_path,
178-
# "ERA5",
179-
# )
180-
# compute_seasonal_leaderboard(
181-
# output_path,
182-
# diagnostics_folder_path,
183-
# "ERA5",
184-
# )
176+
compute_monthly_leaderboard(
177+
output_path,
178+
diagnostics_folder_path,
179+
"ERA5",
180+
)
181+
compute_seasonal_leaderboard(
182+
output_path,
183+
diagnostics_folder_path,
184+
"ERA5",
185+
)
185186
catch e
186187
@error "Error in `analyze_iteration`" error = e
187188
end

experiments/better_calibration/observation_utils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,6 @@ function make_ocean_mask(nelements)
8383
landsea_var,
8484
NaN,
8585
1.0;
86-
threshold = 0.99,
86+
threshold = 0.5,
8787
)
8888
end

0 commit comments

Comments
 (0)