Skip to content

Commit

Permalink
Simplify callbacks
Browse files Browse the repository at this point in the history
This commit removes most of the callback infrastructure in
`ClimaCoupler` in favor of a simpler one that leverages what we already
use in other packages. The current "schedule" system is the one from
`ClimaDiagnostics`, but the plan is to move it to `ClimaUtilities` as
part of the work towards the integer time.

Using the schedule system from `ClimaDiagnostics` eliminated the need
for keeping track of the first day of the month.

I also updated the checkpointing callbacks so that they can run with
frequencies that are smaller than one hour.
  • Loading branch information
Sbozzolo committed Dec 12, 2024
1 parent 5318c3b commit 9d7609b
Show file tree
Hide file tree
Showing 28 changed files with 182 additions and 462 deletions.
31 changes: 28 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,52 @@ ClimaCoupler.jl Release Notes

### ClimaEarth features

### Sea-surface temperature and sea ice concentration data can now be automatically downloaded
#### Sea-surface temperature and sea ice concentration data can now be automatically downloaded

Sea-surface temperature and sea ice concentration require external files. Now, a
low-resolution version of such files is automatically downloaded when a
higher-resolution version is not available. Please, refer to
[ClimaArtifacts](https://github.com/CliMA/ClimaArtifacts) for more information.

### A higher resolution land-sea mask is now used and automatically downloaded - PR [#1006](https://github.com/CliMA/ClimaCoupler.jl/pull/1006)
#### A higher resolution land-sea mask is now used and automatically downloaded - PR [#1006](https://github.com/CliMA/ClimaCoupler.jl/pull/1006)

A 60 arcsecond land-sea mask constructed from topographic data is now used.
Topographic data is automatically downloaded and a land-sea mask is constructed
by identifying where elevation is greater than 0. Note, this can lead to
misidentification of ocean in some areas of the globe that are inland but below
sea level (Dead Sea, Death Valley, ...).

### Leaderboard for variables over longitude, latitude, time, and pressure - PR [#1094](https://github.com/CliMA/ClimaCoupler.jl/pull/1094)
#### Leaderboard for variables over longitude, latitude, time, and pressure - PR [#1094](https://github.com/CliMA/ClimaCoupler.jl/pull/1094)

As a part of the post processing pipeline, bias plots for variables at the
pressure levels of 850.0, 500.0, 250.0 hPa and bias plots over latitude and
pressure levels are being created.

### Breaking changes

#### `hourly_checkpoint_dt` is now just `checkpoint_dt`

Previously, the checkpointing frequency had to be specified in hours and it was
not possible to checkpoint with smaller frequencies. Now, the argument
`hourly_checkpoint_dt` was renamed to `checkpoint_dt` and any frequency can be
specified (e.g., "2months", "200secs").

Callbacks were also reworked, and the previous system was removed. Here is an example of the
new way to create a callback that runs every month:
```julia
import ClimaCouper.TimeManager: Callback, maybe_trigger_callback
import ClimaDiagnostics.Schedules: EveryCalendarDtSchedule # This will be moved to ClimaUtilities
import Dates

start_date = Dates.DateTime(1912, 4, 15)
func(cs) = println(maxima(cs.fields.T_s))
schedule = EveryCalendarDtSchedule(Dates.Month(1); start_date)
callback = Callback(schedule, func)

# Then, call it with
maybe_trigger_callback(callback, cs, t)
```

### Code cleanup

#### Output path updates - PRs [#1106](https://github.com/CliMA/ClimaCoupler.jl/pull/1058),
Expand Down
3 changes: 1 addition & 2 deletions config/amip_configs/amip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ dt_save_to_sol: "30days"
dz_bottom: 30.0
energy_check: false
h_elem: 16
hourly_checkpoint: true
hourly_checkpoint_dt: 720
checkpoint_dt: "720hours"
land_albedo_type: "map_temporal"
mode_name: "amip"
mono_surface: false
Expand Down
1 change: 0 additions & 1 deletion config/ci_configs/amip_coarse_ft64_hourly_checkpoints.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ apply_limiter: false
dt_save_to_sol: "1days"
energy_check: false
h_elem: 6
hourly_checkpoint: true
mode_name: "amip"
moist: "equil"
mono_surface: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ dt_save_restart: "10days"
dt_save_to_sol: "1days"
energy_check: false
h_elem: 6
hourly_checkpoint: true
hourly_checkpoint_dt: 1
checkpoint_dt: 1
mode_name: "amip"
moist: "equil"
mono_surface: false
Expand Down
1 change: 0 additions & 1 deletion config/ci_configs/amip_target_topo_diagedmf_shortrun.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ dt_rad: "1hours"
dt_save_state_to_disk: "1days"
dt_save_to_sol: "1days"
energy_check: false
hourly_checkpoint: true
insolation: "timevarying"
land_albedo_type: "map_temporal"
mode_name: "amip"
Expand Down
1 change: 0 additions & 1 deletion config/longrun_configs/amip_target.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ dt_cpl: "120secs"
dt_rad: "1hours"
dt_save_state_to_disk: "20days"
energy_check: false
hourly_checkpoint: true
insolation: "timevarying"
land_albedo_type: "map_temporal"
mode_name: "amip"
Expand Down
1 change: 0 additions & 1 deletion config/longrun_configs/amip_target_topo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ dt_cpl: "120secs"
dt_rad: "1hours"
dt_save_state_to_disk: "20days"
energy_check: false
hourly_checkpoint: true
insolation: "timevarying"
land_albedo_type: "map_temporal"
mode_name: "amip"
Expand Down
2 changes: 1 addition & 1 deletion config/longrun_configs/amip_target_topo_diagedmf_cpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ dt_rad: "1hours"
dt_save_state_to_disk: "20days"
energy_check: false
insolation: "timevarying"
hourly_checkpoint: false
checkpoint_dt: "30days"
land_albedo_type: "map_temporal"
mode_name: "amip"
mono_surface: false
Expand Down
2 changes: 1 addition & 1 deletion config/longrun_configs/amip_target_topo_diagedmf_gpu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ dt_rad: "1hours"
dt_save_state_to_disk: "20days"
energy_check: false
insolation: "timevarying"
hourly_checkpoint: false
checkpoint_dt: "300days"
land_albedo_type: "map_temporal"
mode_name: "amip"
mono_surface: false
Expand Down
1 change: 0 additions & 1 deletion config/longrun_configs/slabplanet_aqua_target.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ dt_save_state_to_disk: "20days"
dt_save_to_sol: "10days"
energy_check: false
evolving_ocean: false
hourly_checkpoint: true
land_albedo_type: "function"
mode_name: "slabplanet_aqua"
mono_surface: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ dt_save_state_to_disk: "20days"
dt_save_to_sol: "10days"
energy_check: false
evolving_ocean: true
hourly_checkpoint: true
land_albedo_type: "function"
mode_name: "slabplanet_aqua"
mono_surface: false
Expand Down
1 change: 0 additions & 1 deletion config/longrun_configs/slabplanet_aqua_target_nocouple.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ dt_save_state_to_disk: "20days"
dt_save_to_sol: "10days"
energy_check: false
evolving_ocean: false
hourly_checkpoint: true
land_albedo_type: "function"
mode_name: "slabplanet_aqua"
mono_surface: false
Expand Down
1 change: 0 additions & 1 deletion config/longrun_configs/slabplanet_target.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ dt_save_state_to_disk: "20days"
dt_save_to_sol: "10days"
energy_check: false
evolving_ocean: false
hourly_checkpoint: true
land_albedo_type: "function"
mode_name: "slabplanet"
mono_surface: false
Expand Down
1 change: 0 additions & 1 deletion config/longrun_configs/slabplanet_target_evolve_ocn.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ dt_save_state_to_disk: "20days"
dt_save_to_sol: "10days"
energy_check: false
evolving_ocean: true
hourly_checkpoint: true
land_albedo_type: "function"
mode_name: "slabplanet"
mono_surface: false
Expand Down
3 changes: 1 addition & 2 deletions config/nightly_configs/amip_coarse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ dt_save_to_sol: "30days"
dz_bottom: 100.0
energy_check: false
h_elem: 8
hourly_checkpoint: true
hourly_checkpoint_dt: 720
checkpoint_dt: "720hours"
land_albedo_type: "map_temporal"
mode_name: "amip"
mono_surface: false
Expand Down
3 changes: 1 addition & 2 deletions config/nightly_configs/amip_coarse_random.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@ dt_save_to_sol: "30days"
dz_bottom: 100.0
energy_check: false
h_elem: 8
hourly_checkpoint: true
hourly_checkpoint_dt: 720
checkpoint_dt: "720hours"
land_albedo_type: "map_temporal"
mode_name: "amip"
mono_surface: false
Expand Down
12 changes: 1 addition & 11 deletions docs/src/timemanager.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,5 @@ functions from Julia's [Dates](https://docs.julialang.org/en/v1/stdlib/Dates/) m
ClimaCoupler.TimeManager.current_date
ClimaCoupler.TimeManager.strdate_to_datetime
ClimaCoupler.TimeManager.datetime_to_strdate
ClimaCoupler.TimeManager.trigger_callback
ClimaCoupler.TimeManager.AbstractFrequency
ClimaCoupler.TimeManager.Monthly
ClimaCoupler.TimeManager.EveryTimestep
ClimaCoupler.TimeManager.trigger_callback!
ClimaCoupler.TimeManager.CouplerCallback
ClimaCoupler.TimeManager.HourlyCallback
ClimaCoupler.TimeManager.MonthlyCallback
ClimaCoupler.TimeManager.update_firstdayofmonth!
ClimaCoupler.TimeManager.dt_cb
ClimaCoupler.TimeManager.do_nothing
ClimaCoupler.TimeManager.maybe_trigger_callback
```
13 changes: 4 additions & 9 deletions experiments/ClimaEarth/cli_options.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,10 @@ function argparse_settings()
help = "Time interval for saving output [\"10days\" (default); allowed formats: \"Nsecs\", \"Nmins\", \"Nhours\", \"Ndays\", \"Inf\"]"
arg_type = String
default = "10days"
# Checkpointing information
"--hourly_checkpoint"
help = "Boolean flag indicating whether to checkpoint at multiple-hourly intervals [false (default), true]"
arg_type = Bool
default = false
"--hourly_checkpoint_dt"
help = "Time interval for hourly checkpointing in hours [480 (default)]"
arg_type = Int
default = 480
"--checkpoint_dt"
help = "Time interval for hourly checkpointing [480hours (default)]"
arg_type = String
default = "480hours"
# Restart information
"--restart_dir"
help = "Directory containing restart files"
Expand Down
59 changes: 19 additions & 40 deletions experiments/ClimaEarth/run_amip.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ import Interpolations # triggers InterpolationsExt in ClimaUtilities
# Random is used by RRMTGP for some cloud properties
import Random

# TODO: Move to ClimaUtilities once we move the Schedules to ClimaUtilities
import ClimaDiagnostics.Schedules: EveryCalendarDtSchedule

pkg_dir = pkgdir(ClimaCoupler)

#=
Expand Down Expand Up @@ -106,8 +109,7 @@ add_extra_diagnostics!(config_dict)
Δt_cpl,
component_dt_dict,
saveat,
hourly_checkpoint,
hourly_checkpoint_dt,
checkpoint_dt,
restart_dir,
restart_t,
use_coupler_diagnostics,
Expand Down Expand Up @@ -472,7 +474,7 @@ Utilities.show_memory_usage()
model_sims = (atmos_sim = atmos_sim, ice_sim = ice_sim, land_sim = land_sim, ocean_sim = ocean_sim);

## dates
dates = (; date = [date], date0 = [date0], date1 = [Dates.firstdayofmonth(date0)], new_month = [false])
dates = (; date = [date], date0 = [date0])

#=
## Initialize Conservation Checks
Expand Down Expand Up @@ -500,38 +502,23 @@ end
Callbacks are used to update at a specified interval. The callbacks are initialized here and
saved in a global `Callbacks` struct, `callbacks`. The `trigger_callback!` function is used to call the callback during the simulation below.
The frequency of the callbacks is specified in the `HourlyCallback` and `MonthlyCallback` structs. The `func` field specifies the function to be called,
the `ref_date` field specifies the first date for the callback, and the `active` field specifies whether the callback is active or not.
The currently implemented callbacks are:
- `checkpoint_cb`: generates a checkpoint of all model states at a specified interval. This is mainly used for restarting simulations.
- `update_firstdayofmonth!_cb`: generates a callback to update the first day of the month for monthly message print (and other monthly operations).
- `albedo_cb`: for the amip mode, the water albedo is time varying (since the reflectivity of water depends on insolation and wave characteristics, with the latter
being approximated from wind speed). It is updated at the same frequency as the atmospheric radiation.
NB: Eventually, we will call all of radiation from the coupler, in addition to the albedo calculation.
=#
schedule_checkpoint = EveryCalendarDtSchedule(TimeManager.time_to_period(dt_checkpoint); start_date = date0)
checkpoint_cb = Callback(schedule_checkpoint, Checkpointer.checkpoint_sims)

checkpoint_cb = TimeManager.HourlyCallback(
dt = hourly_checkpoint_dt,
func = Checkpointer.checkpoint_sims,
ref_date = [dates.date[1]],
active = hourly_checkpoint,
) # 20 days
update_firstdayofmonth!_cb = TimeManager.MonthlyCallback(
dt = FT(1),
func = TimeManager.update_firstdayofmonth!,
ref_date = [dates.date1[1]],
active = true,
)
dt_water_albedo = parse(FT, filter(x -> !occursin(x, "hours"), dt_rad))
albedo_cb = TimeManager.HourlyCallback(
dt = dt_water_albedo,
func = FluxCalculator.water_albedo_from_atmosphere!,
ref_date = [dates.date[1]],
active = mode_name == "amip",
)
callbacks =
(; checkpoint = checkpoint_cb, update_firstdayofmonth! = update_firstdayofmonth!_cb, water_albedo = albedo_cb)
if mode_name == "amip"
schedule_albedo = EveryCalendarDtSchedule(TimeManager.time_to_period(dt_water_albedo); start_date = date0)
else
schedule_albedo = TimeManager.NeverSchedule()
end
albedo_cb = Callback(schedule_albedo, func = FluxCalculator.water_albedo_from_atmosphere!)

callbacks = (; checkpoint = checkpoint_cb, water_albedo = albedo_cb)

#=
## Initialize turbulent fluxes
Expand Down Expand Up @@ -670,14 +657,10 @@ function solve_coupler!(cs)
@info("Starting coupling loop")
## step in time
for t in ((tspan[begin] + Δt_cpl):Δt_cpl:tspan[end])

cs.dates.date[1] = TimeManager.current_date(cs, t)

## print date on the first of month
cs.dates.date[1] >= cs.dates.date1[1] && @info(cs.dates.date[1])
# Update date
cs.dates.date[] = TimeManager.current_date(cs, t)

if cs.mode.name == "amip"

evaluate!(Interfacer.get_field(ocean_sim, Val(:surface_temperature)), cs.mode.SST_timevaryinginput, t)
evaluate!(Interfacer.get_field(ice_sim, Val(:area_fraction)), cs.mode.SIC_timevaryinginput, t)

Expand All @@ -694,8 +677,7 @@ function solve_coupler!(cs)

## update water albedo from wind at dt_water_albedo
## (this will be extended to a radiation callback from the coupler)
TimeManager.trigger_callback!(cs, cs.callbacks.water_albedo)

TimeManager.maybe_trigger_callback(cs.callbacks.water_albedo, cs, t)

## update the surface fractions for surface models,
## and update all component model simulations with the current fluxes stored in the coupler
Expand Down Expand Up @@ -728,11 +710,8 @@ function solve_coupler!(cs)
## update the coupler with the new atmospheric properties
FieldExchanger.import_atmos_fields!(cs.fields, cs.model_sims, cs.boundary_space, cs.turbulent_fluxes) # radiative and/or turbulent

## callback to update the fist day of month if needed
TimeManager.trigger_callback!(cs, cs.callbacks.update_firstdayofmonth!)

## callback to checkpoint model state
TimeManager.trigger_callback!(cs, cs.callbacks.checkpoint)
TimeManager.maybe_trigger_callback(cs.callbacks.checkpoint, cs, t)

## compute/output AMIP diagnostics if scheduled for this timestep
## wrap the current CoupledSimulation fields and time in a NamedTuple to match the ClimaDiagnostics interface
Expand Down
Loading

0 comments on commit 9d7609b

Please sign in to comment.