Skip to content

Commit

Permalink
Remove t_start
Browse files Browse the repository at this point in the history
The diagnostic module was using `t_start`, but this was under the wrong
assumption.

I was under the impression that integrator.t restarts from 0 upon
restart, so that we needed to manually offset the time.

I think I got this idea from ClimaLand, where t_start is used often.

Using t_start was (probably) leading to incorrect dates being written in
NetCDF files when the simulation was restarted.
  • Loading branch information
Sbozzolo committed Sep 10, 2024
1 parent 72643ef commit ff49192
Show file tree
Hide file tree
Showing 6 changed files with 118 additions and 173 deletions.
5 changes: 5 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ ClimaAtmos.jl Release Notes
Main
-------

### ![][badge-🐛bugfix] Bug fixes

- Fixed incorrect time/date conversion in diagnostics when restarting a
simulation. PR [3287](https://github.com/CliMA/ClimaAtmos.jl/pull/3287)

v0.27.5
-------
- Update RRTMGP and allow multiple aerosols for radiation.
Expand Down
1 change: 1 addition & 0 deletions config/model_configs/plane_density_current_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ z_stretch: false
x_elem: 80
config: "plane"
z_max: 6400.0
output_default_diagnostics: false
diagnostics:
- short_name: thetaa
period: 900secs
13 changes: 4 additions & 9 deletions src/callbacks/get_callbacks.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function get_diagnostics(parsed_args, atmos_model, Y, p, t_start, dt)
function get_diagnostics(parsed_args, atmos_model, Y, p, dt)

FT = Spaces.undertype(axes(Y.c))

Expand Down Expand Up @@ -105,19 +105,15 @@ function get_diagnostics(parsed_args, atmos_model, Y, p, t_start, dt)
output_schedule = CAD.EveryCalendarDtSchedule(
period_dates;
reference_date = p.start_date,
t_start,
)
compute_schedule = CAD.EveryCalendarDtSchedule(
period_dates;
reference_date = p.start_date,
t_start,
)
else
period_seconds = FT(time_to_seconds(period_str))
output_schedule =
CAD.EveryDtSchedule(period_seconds; t_start)
compute_schedule =
CAD.EveryDtSchedule(period_seconds; t_start)
output_schedule = CAD.EveryDtSchedule(period_seconds)
compute_schedule = CAD.EveryDtSchedule(period_seconds)
end

if isnothing(output_name)
Expand Down Expand Up @@ -154,7 +150,6 @@ function get_diagnostics(parsed_args, atmos_model, Y, p, t_start, dt)
diagnostics = [
CAD.default_diagnostics(
atmos_model,
t_start,
time_to_seconds(parsed_args["t_end"]),
p.start_date;
output_writer = netcdf_writer,
Expand All @@ -177,7 +172,7 @@ function get_diagnostics(parsed_args, atmos_model, Y, p, t_start, dt)
return diagnostics, writers
end

function get_callbacks(config, sim_info, atmos, params, Y, p, t_start)
function get_callbacks(config, sim_info, atmos, params, Y, p)
(; parsed_args, comms_ctx) = config
FT = eltype(params)
(; dt, output_dir) = sim_info
Expand Down
119 changes: 38 additions & 81 deletions src/diagnostics/default_diagnostics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# level interfaces, add them here. Feel free to include extra files.

"""
default_diagnostics(model, t_start, t_end, reference_date; output_writer)
default_diagnostics(model, t_end, reference_date; output_writer)
Return a list of `ScheduledDiagnostic`s associated with the given `model` that use
`output_write` to write to disk. `t_end` is the expected simulation end time and it is used
Expand All @@ -15,7 +15,7 @@ to choose the most reasonable output frequency.
We convert time to date as
```julia
current_date = reference_date + t_start + integrator.t
current_date = reference_date + integrator.t
```
The logic is as follows:
Expand All @@ -27,8 +27,7 @@ If `t_end >= 90 year` take monthly means.
"""
function default_diagnostics(
model::AtmosModel,
t_start::Real,
t_end::Real,
t_end,
reference_date::DateTime;
output_writer,
)
Expand All @@ -39,7 +38,6 @@ function default_diagnostics(
x ->
default_diagnostics(
getfield(model, x),
t_start,
t_end,
reference_date;
output_writer,
Expand All @@ -50,11 +48,10 @@ function default_diagnostics(
# We use a map because we want to ensure that diagnostics is a well defined type, not
# Any. This reduces latency.
return vcat(
core_default_diagnostics(output_writer, t_start, t_end, reference_date),
core_default_diagnostics(output_writer, t_end, reference_date),
map(non_empty_fields) do field
default_diagnostics(
getfield(model, field),
t_start,
t_end,
reference_date;
output_writer,
Expand All @@ -68,8 +65,7 @@ end
# that all the default_diagnostics return the same type). This is used by
# default_diagnostics(model::AtmosModel; output_writer), so that we can ignore defaults for
# submodels that have no given defaults.
default_diagnostics(submodel, t_start, t_end, reference_date; output_writer) =
[]
default_diagnostics(submodel, t_end, reference_date; output_writer) = []

"""
produce_common_diagnostic_function(period, reduction)
Expand All @@ -80,7 +76,6 @@ function common_diagnostics(
period,
reduction,
output_writer,
t_start,
reference_date,
short_names...;
pre_output_hook! = nothing,
Expand All @@ -89,8 +84,8 @@ function common_diagnostics(
map(short_names) do short_name
output_schedule_func =
period isa Period ?
EveryCalendarDtSchedule(period; t_start, reference_date) :
EveryDtSchedule(period; t_start)
EveryCalendarDtSchedule(period; reference_date) :
EveryDtSchedule(period)

return ScheduledDiagnostic(
variable = get_diagnostic_variable(short_name),
Expand All @@ -107,26 +102,25 @@ end
include("standard_diagnostic_frequencies.jl")

"""
frequency_averages(t_start::Real, t_end::Real)
frequency_averages(t_end::Real)
Return the correct averaging function depending on the total simulation time.
If `t_end < 1 day` take hourly means,
if `t_end < 30 days` take daily means,
if `t_end < 90 days` take means over ten days,
If `t_end >= 90 year` take monthly means.
One month is defined as 30 days.
"""
function frequency_averages(t_start::Real, t_end::Real)
function frequency_averages(t_end)
FT = eltype(t_end)
if t_end >= 90 * 86400
return monthly_averages
return (args...; kwargs...) -> monthly_averages(FT, args...; kwargs...)
elseif t_end >= 30 * 86400
return tendaily_averages
return (args...; kwargs...) -> tendaily_averages(FT, args...; kwargs...)
elseif t_end >= 86400
return daily_averages
return (args...; kwargs...) -> daily_averages(FT, args...; kwargs...)
else
return hourly_averages
return (args...; kwargs...) -> hourly_averages(FT, args...; kwargs...)
end
end

Expand All @@ -135,7 +129,7 @@ end
########
# Core #
########
function core_default_diagnostics(output_writer, t_start, t_end, reference_date)
function core_default_diagnostics(output_writer, t_end, reference_date)
core_diagnostics = [
"ts",
"ta",
Expand All @@ -152,20 +146,21 @@ function core_default_diagnostics(output_writer, t_start, t_end, reference_date)
"hfes",
]

average_func = frequency_averages(t_start, t_end)
average_func = frequency_averages(t_end)
FT = eltype(t_end)

if t_end >= 90 * 86400
min_func = monthly_min
max_func = monthly_max
min_func = (args...; kwargs...) -> monthly_min(FT, args...; kwargs...)
max_func = (args...; kwargs...) -> monthly_max(FT, args...; kwargs...)
elseif t_end >= 30 * 86400
min_func = tendaily_min
max_func = tendaily_max
min_func = (args...; kwargs...) -> tendaily_min(FT, args...; kwargs...)
max_func = (args...; kwargs...) -> tendaily_max(FT, args...; kwargs...)
elseif t_end >= 86400
min_func = daily_min
max_func = daily_max
min_func = (args...; kwargs...) -> daily_min(FT, args...; kwargs...)
max_func = (args...; kwargs...) -> daily_max(FT, args...; kwargs...)
else
min_func = hourly_min
max_func = hourly_max
min_func = (args...; kwargs...) -> hourly_min(FT, args...; kwargs...)
max_func = (args...; kwargs...) -> hourly_max(FT, args...; kwargs...)
end

return [
Expand All @@ -179,14 +174,9 @@ function core_default_diagnostics(output_writer, t_start, t_end, reference_date)
output_writer,
output_short_name = "orog_inst",
),
average_func(
core_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
min_func("ts"; output_writer, t_start, reference_date),
max_func("ts"; output_writer, t_start, reference_date),
average_func(core_diagnostics...; output_writer, reference_date)...,
min_func("ts"; output_writer, reference_date),
max_func("ts"; output_writer, reference_date),
]
end

Expand All @@ -195,7 +185,6 @@ end
##################
function default_diagnostics(
::T,
t_start,
t_end,
reference_date;
output_writer,
Expand All @@ -214,14 +203,9 @@ function default_diagnostics(
"clwvi",
"clivi",
]
average_func = frequency_averages(t_start, t_end)
average_func = frequency_averages(t_end)
return [
average_func(
moist_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
average_func(moist_diagnostics...; output_writer, reference_date)...,
]
end

Expand All @@ -230,22 +214,16 @@ end
#######################
function default_diagnostics(
::Microphysics1Moment,
t_start,
t_end,
reference_date;
output_writer,
)
precip_diagnostics = ["husra", "hussn"]

average_func = frequency_averages(t_start, t_end)
average_func = frequency_averages(t_end)

return [
average_func(
precip_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
average_func(precip_diagnostics...; output_writer, reference_date)...,
]
end

Expand All @@ -254,7 +232,6 @@ end
##################
function default_diagnostics(
::RRTMGPI.AbstractRRTMGPMode,
t_start,
t_end,
reference_date;
output_writer,
Expand All @@ -273,22 +250,14 @@ function default_diagnostics(
"rlus",
]

average_func = frequency_averages(t_start, t_end)
average_func = frequency_averages(t_end)

return [
average_func(
rad_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
]
return [average_func(rad_diagnostics...; output_writer, reference_date)...]
end


function default_diagnostics(
::RRTMGPI.AllSkyRadiationWithClearSkyDiagnostics,
t_start,
t_end,
reference_date;
output_writer,
Expand Down Expand Up @@ -318,19 +287,13 @@ function default_diagnostics(
"rlutcs",
]

average_func = frequency_averages(t_start, t_end)
average_func = frequency_averages(t_end)

return [
average_func(
rad_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
average_func(rad_diagnostics...; output_writer, reference_date)...,
average_func(
rad_clearsky_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
]
Expand All @@ -341,7 +304,6 @@ end
##################
function default_diagnostics(
::PrognosticEDMFX,
t_start,
t_end,
reference_date;
output_writer,
Expand Down Expand Up @@ -373,19 +335,17 @@ function default_diagnostics(
"lmix",
]

average_func = frequency_averages(t_start, t_end)
average_func = frequency_averages(t_end)

return [
average_func(
edmfx_draft_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
average_func(
edmfx_env_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
]
Expand All @@ -394,7 +354,6 @@ end

function default_diagnostics(
::DiagnosticEDMFX,
t_start,
t_end,
reference_date;
output_writer,
Expand All @@ -413,19 +372,17 @@ function default_diagnostics(
]
diagnostic_edmfx_env_diagnostics = ["waen", "tke", "lmix"]

average_func = frequency_averages(t_start, t_end)
average_func = frequency_averages(t_end)

return [
average_func(
diagnostic_edmfx_draft_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
average_func(
diagnostic_edmfx_env_diagnostics...;
output_writer,
t_start,
reference_date,
)...,
]
Expand Down
Loading

0 comments on commit ff49192

Please sign in to comment.