Skip to content

Commit ed59e27

Browse files
committed
add callbacks to read in prescribed data daily
1 parent 5903070 commit ed59e27

File tree

4 files changed

+33
-8
lines changed

4 files changed

+33
-8
lines changed

experiments/ClimaEarth/components/ocean/prescr_ocean.jl

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import ClimaUtilities.ClimaArtifacts: @clima_artifact
33
import Interpolations # triggers InterpolationsExt in ClimaUtilities
44
import Thermodynamics as TD
55
import ClimaCoupler: Checkpointer, FieldExchanger, Interfacer
6+
import ClimaDiagnostics.Schedules: EveryCalendarDtSchedule
67

78
"""
89
PrescribedOceanSimulation{C}
@@ -84,6 +85,8 @@ function PrescribedOceanSimulation(
8485
SST_init = zeros(space)
8586
evaluate!(SST_init, SST_timevaryinginput, t_start)
8687

88+
SST_schedule = CD.Schedules.EveryCalendarDtSchedule(TimeManager.time_to_period("1days"); start_date = date0)
89+
8790
# Create the cache
8891
cache = (;
8992
T_sfc = SST_init,
@@ -97,6 +100,7 @@ function PrescribedOceanSimulation(
97100
phase = TD.Liquid(),
98101
thermo_params = thermo_params,
99102
SST_timevaryinginput = SST_timevaryinginput,
103+
SST_schedule = SST_schedule,
100104
)
101105
return PrescribedOceanSimulation(cache)
102106
end
@@ -107,10 +111,11 @@ end
107111
Interfacer.step!(sim::PrescribedOceanSimulation, t)
108112
109113
Update the cached surface temperature field using the prescribed data
110-
at each timestep.
114+
at each timestep. This doesn't happen at every timestep,
115+
but only when the SST data is scheduled to be updated.
111116
"""
112117
function Interfacer.step!(sim::PrescribedOceanSimulation, t)
113-
evaluate!(sim.cache.T_sfc, sim.cache.SST_timevaryinginput, t)
118+
sim.cache.SST_schedule(t) && evaluate!(sim.cache.T_sfc, sim.cache.SST_timevaryinginput, t)
114119
end
115120

116121
function Checkpointer.get_model_cache(sim::PrescribedOceanSimulation)

experiments/ClimaEarth/components/ocean/prescr_seaice.jl

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import SciMLBase
22
import ClimaCore as CC
3+
import ClimaDiagnostics as CD
34
import ClimaTimeSteppers as CTS
45
import ClimaUtilities.TimeVaryingInputs: TimeVaryingInput, evaluate!
56
import ClimaUtilities.ClimaArtifacts: @clima_artifact
@@ -143,8 +144,20 @@ function PrescribedIceSimulation(
143144
tspan = Float64.(tspan)
144145
saveat = Float64.(saveat)
145146
end
147+
148+
# Set up a callback to read in SST data daily
149+
SIC_schedule = CD.Schedules.EveryCalendarDtSchedule(TimeManager.time_to_period("1days"); start_date = date0)
150+
SIC_update_cb = TimeManager.Callback(SIC_schedule, read_sic_data!)
151+
146152
problem = SciMLBase.ODEProblem(ode_function, Y, tspan, (; cache..., params = params))
147-
integrator = SciMLBase.init(problem, ode_algo, dt = dt, saveat = saveat, adaptive = false)
153+
integrator = SciMLBase.init(
154+
problem,
155+
ode_algo,
156+
dt = dt,
157+
saveat = saveat,
158+
adaptive = false,
159+
callback = SciMLBase.CallbackSet(SIC_update_cb),
160+
)
148161

149162
sim = PrescribedIceSimulation(params, space, integrator)
150163

@@ -153,6 +166,16 @@ function PrescribedIceSimulation(
153166
return sim
154167
end
155168

169+
"""
170+
read_sic_data!(integrator)
171+
172+
Read in the sea ice concentration data at the current time step.
173+
This function is intended to be used within a callback
174+
"""
175+
function read_sic_data!(integrator)
176+
evaluate!(integrator.p.area_fraction, integrator.p.SIC_timevaryinginput, integrator.t)
177+
end
178+
156179
# extensions required by Interfacer
157180
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:area_fraction}) = sim.integrator.p.area_fraction
158181
Interfacer.get_field(sim::PrescribedIceSimulation, ::Val{:roughness_buoyancy}) = sim.integrator.p.params.z0b
@@ -237,9 +260,6 @@ function ice_rhs!(dY, Y, p, t)
237260
FT = eltype(Y)
238261
params = p.params
239262

240-
# Update the cached area fraction with the current SIC
241-
evaluate!(p.area_fraction, p.SIC_timevaryinginput, t)
242-
243263
# Overwrite ice fraction with the static land area fraction anywhere we have nonzero land area
244264
# max needed to avoid Float32 errors (see issue #271; Heisenbug on HPC)
245265
@. p.area_fraction = max(min(p.area_fraction, FT(1) - p.land_fraction), FT(0))

experiments/ClimaEarth/setup_run.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ function setup_and_run(config_dict::AbstractDict)
527527
NB: Eventually, we will call all of radiation from the coupler, in addition to the albedo calculation.
528528
=#
529529
schedule_checkpoint = EveryCalendarDtSchedule(TimeManager.time_to_period(checkpoint_dt); start_date = date0)
530-
checkpoint_cb = TimeManager.TimeManager.Callback(schedule_checkpoint, Checkpointer.checkpoint_sims)
530+
checkpoint_cb = TimeManager.Callback(schedule_checkpoint, Checkpointer.checkpoint_sims)
531531

532532
if sim_mode <: AMIPMode
533533
schedule_albedo = EveryCalendarDtSchedule(TimeManager.time_to_period(dt_rad); start_date = date0)

experiments/ClimaEarth/user_io/arg_parsing.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ function parse_component_dts!(config_dict)
236236
@assert all(key -> !isnothing(config_dict[key]), component_dt_names) || haskey(config_dict, "dt") "all model-specific timesteps (dt_atmos, dt_land, dt_ocean, and dt_seaice) or a generic timestep (dt) must be specified"
237237

238238
for key in component_dt_names
239-
if haskey(config_dict, key)
239+
if !isnothing(config_dict[key])
240240
# Check if the component timestep is specified
241241
component_dt = Float64(Utilities.time_to_seconds(config_dict[key]))
242242
@assert isapprox(Δt_cpl % component_dt, 0.0) "Coupler dt must be divisible by all component dt's\n dt_cpl = $Δt_cpl\n $key = $component_dt"

0 commit comments

Comments
 (0)