Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
clean

format

path fix

spinup

clean

pip

revs

rev
  • Loading branch information
LenkaNovak committed May 28, 2024
1 parent f2f6a6e commit 145c2b6
Show file tree
Hide file tree
Showing 5 changed files with 252 additions and 1 deletion.
10 changes: 10 additions & 0 deletions .buildkite/hierarchies/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ steps:
slurm_gpus: 1
modules: common

- label: "Clima: GPU ClimaCoupler Cloudless Aquaplanet"
command:
- "julia --color=yes --project=experiments/ClimaEarth/ experiments/ClimaEarth/run_cloudless_aquaplanet.jl"
artifact_paths: "cloudless_aquaplanet/cloudless_aquaplanet/clima_atmos/*"
agents:
queue: clima
slurm_mem: 20GB
slurm_gpus: 1
modules: common

- label: "Clima: GPU ClimaCoupler Cloudy Aquaplanet"
command:
- "julia --color=yes --project=experiments/ClimaEarth/ experiments/ClimaEarth/run_cloudy_aquaplanet.jl"
Expand Down
19 changes: 18 additions & 1 deletion .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,16 @@ steps:
agents:
slurm_mem: 20GB

- label: ":construction: Cloudless Aquaplanet"
key: "cloudless_aquaplanet"
command:
- sed 's/t_end = "1000days"/t_end = "1days"/' experiments/ClimaEarth/run_cloudless_aquaplanet.jl > experiments/ClimaEarth/run_cloudless_aquaplanet_short.jl
- "julia --color=yes --project=experiments/ClimaEarth/ experiments/ClimaEarth/run_cloudless_aquaplanet_short.jl"
artifact_paths: "cloudless_aquaplanet/cloudless_aquaplanet/clima_atmos/*"

agents:
slurm_mem: 20GB

- label: ":construction: Cloudy Aquaplanet"
key: "cloudy_aquaplanet"
command:
Expand All @@ -417,7 +427,14 @@ steps:
agents:
slurm_mem: 20GB


- wait
- label: ":construction: Hierarchy plots"
key: "hierarchy_plots"
command:
- "julia --color=yes --project=experiments/ClimaEarth/ experiments/ClimaEarth/hierarchy/climate_plots.jl"
artifact_paths: "paper_figs/*"
agents:
slurm_mem: 20GB

- group: "GPU integration tests"
steps:
Expand Down
16 changes: 16 additions & 0 deletions experiments/ClimaEarth/hierarchy/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Hierarchy Experiments for Global Climate Models

This directory contains a series of experiments that demonstrate the use of hierarchical modeling using ClimaEarth, with a focus on the atmospheric component. The hierarchy spans from a simple dry atmosphere to a more complex moist atmosphere with clouds and an Earth-like surface. The experiments are designed to be run in sequence, with each experiment building on the previous one. Each experiment is a self-contained run script that contains all necessary configurations.

## Experiments
- Dry Held-Suarez
- Moist Held-Suarez
- Cloudless Aquaplanet
- Cloudy Aquaplanet
- Cloudy Slabplanet

## Postprocessing
We provide a simple postprocessing script `climate_plots.jl` that can be used to visualize the results of each experiment, with some helper functions in `plot_helper.jl`.

## Associated publication
- (in preparation)
89 changes: 89 additions & 0 deletions experiments/ClimaEarth/hierarchy/climate_plots.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# paper_figs
using NCDatasets
using Statistics
using Plots

import Interpolations: LinearInterpolation
import DelimitedFiles: writedlm, readdlm

include("plot_helper.jl")

for job_id in ["dry_held_suarez", "moist_held_suarez"]
if isinteractive()
DATA_DIR = "experiments/ClimaEarth/$job_id/$job_id/clima_atmos/output_active/"
else
build = ENV["BUILDKITE_BUILD_NUMBER"]
DATA_DIR = "/central/scratch/esm/slurm-buildkite/climacoupler-ci/$build/climacoupler-ci/$job_id/$job_id/clima_atmos/output_active/"
end

reduction = "6h_inst"
PLOT_DIR = "paper_figs"

mkpath(PLOT_DIR)

# SUPPLEMENTAL: animation of surface temperature
ta_sfc, lat, lon, z, time = get_nc_data_all("ta", reduction, DATA_DIR)
anim = Plots.@animate for i in 1:size(ta_sfc, 1)
Plots.contourf(
lon,
lat,
ta_sfc[i, :, :, 1]',
xlabel = "Longitude",
ylabel = "Latitude",
title = "$var",
color = :viridis,
clims = (260, 315),
)
end
Plots.mp4(anim, joinpath(PLOT_DIR, "anim_ta_sfc.mp4"), fps = 10)

# Figure 2: climatology
# this plots the time-mean (upper-level and surface) slices and zonal means of
# the mass streamfunction, zonal wind, meridional wind, temperature, max. Eady growth rate, and vertical velocity
vars = ["mass_strf", "va", "ua", "ta", "egr", "wa"]
for var in vars
plot_climate(var, DATA_DIR, PLOT_DIR, job_id, reduction = reduction, interpolate_to_pressure = true)
end

# Figure 4: storm track diagnostics
# this extracts the eddy heat flux and plots its climatology
lev_st = 6
ta_zm, ta_sfc, lat, lon, z = mean_climate_data("ta", reduction, DATA_DIR, lev_i = lev_st)
va_zm, va_sfc, lat, lon, z = mean_climate_data("va", reduction, DATA_DIR, lev_i = lev_st)
vT_zm, vT_sfc, lat, lon, z = mean_climate_data("vt", reduction, DATA_DIR, lev_i = lev_st)
heat_flux_zm = vT_zm .- va_zm .* ta_zm

pa_zm, ~, ~, ~, ~ = mean_climate_data("pfull", reduction, DATA_DIR)
pa_zm = pa_zm ./ 100 # convert to hPa
pa_grid = [950, 800, 700, 600, 500, 400, 300, 200, 50]

heat_flux_int_zm = interpolate_to_pressure_coord_2d(heat_flux_zm, pa_zm, pa_grid)
Plots.contourf(
lat,
-pa_grid,
heat_flux_int_zm',
xlabel = "Latitude (deg N)",
ylabel = "Pressure (hPa)",
title = "Heat flux",
color = :viridis,
ylims = (-pa_grid[1], -pa_grid[end]),
yticks = (-pa_grid, pa_grid),
)
png(joinpath(PLOT_DIR, "$(job_id)_heat_flux.png"))

# Figure 5: storm track diagnostics reduced to timeseries
# this plots the eddy heat flux and max. Eady growth rate in a sectorial selection
lev_i, lat_s_i, lat_n_i, lon_w_i, lon_e_i = lev_st, 60, 75, 1, 30
println(
"Sectorial selevtion for timeseries: \n level: $(z[lev_i]), lat: $(lat[lat_s_i]) to $(lat[lat_n_i]), lon: $(lon[lon_w_i]) to $(lon[lon_e_i])",
)

egr_all, lat, lon, z, time = get_nc_data_all("egr", reduction, DATA_DIR)
egr_t = point_timeseries_data(egr_all, [lon_w_i, lon_e_i], [lat_s_i, lat_n_i], lev_i)

vT_all, lat, lon, z, time = get_nc_data_all("vt", reduction, DATA_DIR)
va_all, lat, lon, z, time = get_nc_data_all("va", reduction, DATA_DIR)
ta_all, lat, lon, z, time = get_nc_data_all("ta", reduction, DATA_DIR)
heat_flux_all = vT_all .- va_all .* ta_all
heat_flux_t = point_timeseries_data(heat_flux_all, [lon_w_i, lon_e_i], [lat_s_i, lat_n_i], lev_i)
end
119 changes: 119 additions & 0 deletions experiments/ClimaEarth/hierarchy/plot_helper.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# plot_helper

"""
get_nc_data_all(var, red, DATA_DIR)
Reads the netcdf file for the variable `var` and reduction `red` from the directory `DATA_DIR` and returns the variable, lat, lon, z, and time.
"""
get_nc_data_all = (var, red, DATA_DIR) -> begin
ds = NCDataset("$DATA_DIR/$(var)_$red.nc")
var = ds["$var"][:, :, :, :]
lat = ds["lat"][:]
lon = ds["lon"][:]
z = ds["z"][:]
time = ds["time"][:]
close(ds)
return var, lat, lon, z, time
end

"""
mean_climate_data(varname, reduction, DATA_DIR; lev_i = 1, spinup=1)
Postprocesses the climate data for the variable `varname` and `reduction` from the directory `DATA_DIR`. Returns the zonal mean and horizontal surface slice mean of the variable.
"""
mean_climate_data =
(varname, reduction, DATA_DIR; lev_i = 1, spinup = 1) -> begin

var, lat, lon, z, time = get_nc_data_all(varname, reduction, DATA_DIR)
@assert spinup < size(var, 1)

var_time_zonal_mean = mean(var[spinup:end, :, :, :], dims = (1, 2))[1, 1, :, :]
var_time_mean_sfc = mean(var[spinup:end, :, :, :], dims = (1))[1, :, :, lev_i]

return var_time_zonal_mean, var_time_mean_sfc, lat, lon, z
end

"""
point_timeseries_data(variable, lon_i, lat_i, lev_i)
Returns the time series data for the variable `variable` at the indices `lon_i`, `lat_i`, and `lev_i`.
"""
point_timeseries_data =
(variable, lon_i, lat_i, lev_i) -> begin

variable_time_mean = mean(variable[:, lon_i[1]:lon_i[2], lat_i[1]:lat_i[2], lev_i], dims = (2, 3))[:, 1, 1]

return variable_time_mean
end

"""
plot_climate(var, DATA_DIR, PLOT_DIR, job_id; reduction = "inst", interpolate_to_pressure = false)
Plots the zonal mean and horizontal surface slice mean of the variable `var` from the directory `DATA_DIR` and saves the plots in the directory `PLOT_DIR`.
"""
function plot_climate(var, DATA_DIR, PLOT_DIR, job_id; reduction = "inst", interpolate_to_pressure = false)
strf_zm, strf_sfc, lat, lon, z = mean_climate_data(var, reduction, DATA_DIR)
strf_zm, strf_upper, lat, lon, z = mean_climate_data(var, reduction, DATA_DIR, lev_i = 10)

# vertical-lat plot of zonal and time mean
if interpolate_to_pressure
pa_zm, ~, ~, ~, ~ = mean_climate_data("pfull", reduction, DATA_DIR)
pa_zm = pa_zm ./ 100 # convert to hPa
pa_grid = [950, 800, 700, 600, 500, 400, 300, 200, 50]
strf_zm = interpolate_to_pressure_coord_2d(strf_zm, pa_zm, pa_grid)
Plots.contourf(
lat,
-pa_grid,
strf_zm',
xlabel = "Latitude (deg N)",
ylabel = "Pressure (hPa)",
title = "$var",
color = :viridis,
ylims = (-pa_grid[1], -pa_grid[end]),
yticks = (-pa_grid, pa_grid),
)# , clims=(-1e10, 1e10))
png(joinpath(PLOT_DIR, "$(job_id)_$(var)_pa.png"))
else
Plots.contourf(
lat,
z,
strf_zm',
xlabel = "Latitude",
ylabel = "Height (km)",
title = "$var",
color = :viridis,
ylims = (0, 3e4),
yscale = :log10,
yticks = ([1e3, 5e3, 10e3, 20e3, 30e3], ["1", "5", "10", "20", "30"]),
)# , clims=(-1e10, 1e10)
png(joinpath(PLOT_DIR, "$(job_id)_$var.png"))
end

# horizontal slices
Plots.contourf(lon, lat, strf_sfc', xlabel = "Longitude", ylabel = "Latitude", title = "$var", color = :viridis)#, clims=(-1e10, 1e10))
png(joinpath(PLOT_DIR, "$(job_id)_$(var)_sfc.png"))

Plots.contourf(lon, lat, strf_upper', xlabel = "Longitude", ylabel = "Latitude", title = "$var", color = :viridis)#, clims=(-1e10, 1e10))
png(joinpath(PLOT_DIR, "$(job_id)_$(var)_10km.png"))
end

"""
interpolate_to_pressure_coord_2d(var_zm, pa, pa_grid)
Interpolates the 2D variable `var_zm` to the pressure grid `pa_grid` using the pressure values `pa`.
"""
function interpolate_to_pressure_coord_2d(var_zm, pa, pa_grid)
var_on_pa = zeros(size(var_zm, 1), length(pa_grid))
for lat_i in collect(1:size(var_zm, 1))
# Extract ua and corresponding ta values
var_values = var_zm[lat_i, :]
pa_values = pa[lat_i, :]

# Interpolate ua onto ta_grid
for (pa_j, pa_val) in enumerate(pa_grid)
itp_var = LinearInterpolation(-pa_values, var_values)
var_on_pa[lat_i, pa_j] = itp_var(-pa_val)
end
end
return var_on_pa
end

0 comments on commit 145c2b6

Please sign in to comment.