diff --git a/Project.toml b/Project.toml index 4c9aee039a..f7c7a2fcf4 100644 --- a/Project.toml +++ b/Project.toml @@ -10,6 +10,7 @@ ClimaComms = "3a4d1b5c-c61d-41fd-a00a-5873ba7a1b0d" ClimaCore = "d414da3d-4745-48bb-8d80-42e94e092884" ClimaCoreTempestRemap = "d934ef94-cdd4-4710-83d6-720549644b70" ClimaLSM = "7884a58f-fab6-4fd0-82bb-ecfedb2d8430" +ClimaUtilities = "b3f4f4ca-9299-4f7f-bd9b-81e1242a7513" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" Insolation = "e98cc03f-d57e-4e3c-b70c-8d51efe9e0d8" @@ -34,6 +35,7 @@ ClimaComms = "0.5" ClimaCore = "0.10" ClimaCoreTempestRemap = "0.3" ClimaLSM = "0.3.2" +ClimaUtilities = "0.1.1" DocStringExtensions = "0.8, 0.9" Insolation = "0.6" JLD2 = "0.4" diff --git a/docs/Project.toml b/docs/Project.toml index 66005a86ff..757d5c53ae 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,5 +1,6 @@ [deps] ClimaCoupler = "4ade58fe-a8da-486c-bd89-46df092ec0c7" +ClimaUtilities = "b3f4f4ca-9299-4f7f-bd9b-81e1242a7513" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" Literate = "98b081ad-f1c9-55d3-8b20-4c87d4299306" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" diff --git a/docs/make.jl b/docs/make.jl index d6de55f844..443f171057 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -64,7 +64,6 @@ interface_pages = [ "utilities.md", "bcreader.md", "testhelper.md", - "timemanager.md", ] performance_pages = ["performance.md"] diff --git a/docs/src/timemanager.md b/docs/src/timemanager.md deleted file mode 100644 index 9fd9c162a7..0000000000 --- a/docs/src/timemanager.md +++ /dev/null @@ -1,16 +0,0 @@ -# TimeManager - -This module contains functions that handle dates and times -in simulations. The functions in this module often call -functions from Julia's [Dates](https://docs.julialang.org/en/v1/stdlib/Dates/) module. - -## TimeManager API - -```@docs -ClimaCoupler.TimeManager.current_date -ClimaCoupler.TimeManager.strdate_to_datetime -ClimaCoupler.TimeManager.datetime_to_strdate -ClimaCoupler.TimeManager.trigger_callback -ClimaCoupler.TimeManager.Monthly -ClimaCoupler.TimeManager.EveryTimestep -``` diff --git a/experiments/AMIP/modular/Manifest.toml b/experiments/AMIP/modular/Manifest.toml index 873ee26ad0..6f35318571 100644 --- a/experiments/AMIP/modular/Manifest.toml +++ b/experiments/AMIP/modular/Manifest.toml @@ -2,7 +2,7 @@ julia_version = "1.8.5" manifest_format = "2.0" -project_hash = "0c52bcb1446b52cbf673aa87a7b4c42cc1fdbcf2" +project_hash = "32aebffcff9cfbbd3d7e402ba60cde756ded70bb" [[deps.ADTypes]] git-tree-sha1 = "f5c25e8a5b29b5e941b7408bc8cc79fea4d9ef9a" @@ -239,7 +239,7 @@ uuid = "d934ef94-cdd4-4710-83d6-720549644b70" version = "0.3.5" [[deps.ClimaCoupler]] -deps = ["CLIMAParameters", "ClimaAtmos", "ClimaComms", "ClimaCore", "ClimaCoreTempestRemap", "ClimaLSM", "Dates", "DocStringExtensions", "Insolation", "JLD2", "NCDatasets", "OrdinaryDiffEq", "Plots", "PrettyTables", "SciMLBase", "StaticArrays", "Statistics", "SurfaceFluxes", "TempestRemap_jll", "TerminalLoggers", "Thermodynamics", "UnPack"] +deps = ["CLIMAParameters", "ClimaAtmos", "ClimaComms", "ClimaCore", "ClimaCoreTempestRemap", "ClimaLSM", "ClimaUtilities", "Dates", "DocStringExtensions", "Insolation", "JLD2", "NCDatasets", "OrdinaryDiffEq", "Plots", "PrettyTables", "SciMLBase", "StaticArrays", "Statistics", "SurfaceFluxes", "TempestRemap_jll", "TerminalLoggers", "Thermodynamics", "UnPack"] path = "../../.." uuid = "4ade58fe-a8da-486c-bd89-46df092ec0c7" version = "0.1.0" @@ -256,6 +256,14 @@ git-tree-sha1 = "54b602435b0107b6c2dfe7664e0f7ff5fc78fb91" uuid = "595c0a79-7f3d-439a-bc5a-b232dc3bde79" version = "0.7.7" +[[deps.ClimaUtilities]] +deps = ["CFTime", "Dates"] +git-tree-sha1 = "1d8a2368e0290a71301cb515e564b8b48ba1b759" +repo-rev = "js/timemanager" +repo-url = "https://github.com/CliMA/ClimaUtilities.jl" +uuid = "b3f4f4ca-9299-4f7f-bd9b-81e1242a7513" +version = "0.1.0" + [[deps.CloseOpenIntervals]] deps = ["Static", "StaticArrayInterface"] git-tree-sha1 = "70232f82ffaab9dc52585e0dd043b5e0c6b714f1" diff --git a/experiments/AMIP/modular/Project.toml b/experiments/AMIP/modular/Project.toml index b9d72c8c93..a9b1aac9f2 100644 --- a/experiments/AMIP/modular/Project.toml +++ b/experiments/AMIP/modular/Project.toml @@ -11,6 +11,7 @@ ClimaCoreTempestRemap = "d934ef94-cdd4-4710-83d6-720549644b70" ClimaCoupler = "4ade58fe-a8da-486c-bd89-46df092ec0c7" ClimaLSM = "7884a58f-fab6-4fd0-82bb-ecfedb2d8430" ClimaTimeSteppers = "595c0a79-7f3d-439a-bc5a-b232dc3bde79" +ClimaUtilities = "b3f4f4ca-9299-4f7f-bd9b-81e1242a7513" CloudMicrophysics = "6a9e3e04-43cd-43ba-94b9-e8782df3c71b" Colors = "5ae59095-9a9b-59fe-a467-6f913c188581" Dierckx = "39dd38d3-220a-591b-8e3c-4c3a8c710a94" diff --git a/experiments/AMIP/modular/coupler_driver_modular.jl b/experiments/AMIP/modular/coupler_driver_modular.jl index 39cd56d478..5d0d432f09 100644 --- a/experiments/AMIP/modular/coupler_driver_modular.jl +++ b/experiments/AMIP/modular/coupler_driver_modular.jl @@ -63,6 +63,7 @@ using Statistics: mean using ClimaCore.Utilities: half, PlusHalf using ClimaCore: InputOutput, Fields import ClimaCore.Spaces as Spaces +import ClimaUtilities: TimeManager if !(@isdefined parsed_args) include("cli_options.jl") @@ -115,10 +116,9 @@ import ClimaCoupler.Regridder: update_surface_fractions!, combine_surfaces!, combine_surfaces_from_sol!, dummmy_remap!, binary_mask import ClimaCoupler.ConservationChecker: EnergyConservationCheck, WaterConservationCheck, check_conservation!, plot_global_conservation -import ClimaCoupler.Utilities: CoupledSimulation, float_type, swap_space! +import ClimaCoupler.Utilities: CoupledSimulation, float_type, swap_space!, current_date import ClimaCoupler.BCReader: bcfile_info_init, float_type_bcf, update_midmonth_data!, next_date_in_file, interpolate_midmonth_to_daily -import ClimaCoupler.TimeManager: current_date, datetime_to_strdate, trigger_callback, Monthly, EveryTimestep import ClimaCoupler.Diagnostics: get_var, init_diagnostics, accumulate_diagnostics!, save_diagnostics, TimeMean import ClimaCoupler.PostProcessor: postprocess @@ -357,7 +357,7 @@ User can write custom diagnostics in the `user_diagnostics.jl`. monthly_3d_diags = init_diagnostics( (:T, :u, :q_tot, :q_liq_ice), atmos_sim.domain.center_space; - save = Monthly(), + save = TimeManager.Monthly(), operations = (; accumulate = TimeMean([Int(0)])), output_dir = COUPLER_OUTPUT_DIR, name_tag = "monthly_mean_3d_", @@ -366,7 +366,7 @@ monthly_3d_diags = init_diagnostics( monthly_2d_diags = init_diagnostics( (:precipitation_rate, :toa_fluxes, :T_sfc, :tubulent_energy_fluxes), boundary_space; - save = Monthly(), + save = TimeManager.Monthly(), operations = (; accumulate = TimeMean([Int(0)])), output_dir = COUPLER_OUTPUT_DIR, name_tag = "monthly_mean_2d_", @@ -544,18 +544,24 @@ function solve_coupler!(cs) import_atmos_fields!(cs.fields, cs.model_sims, cs.boundary_space, turbulent_fluxes) # radiative and/or turbulent ## monthly callbacks - if trigger_callback(cs, Monthly()) - ## step to the next calendar month - cs.dates.date1[1] += Dates.Month(1) - ## checkpoint model state - if monthly_checkpoint + ## function to checkpoint model state + checkpoint_func = + (monthly_checkpoint, cs, comms_ctx, t, COUPLER_ARTIFACTS_DIR) -> if monthly_checkpoint for sim in cs.model_sims if get_model_state_vector(sim) !== nothing checkpoint_model_state(sim, comms_ctx, Int(t), output_dir = COUPLER_ARTIFACTS_DIR) end end end - end + func_args = (monthly_checkpoint, cs, comms_ctx, t, COUPLER_ARTIFACTS_DIR) + ## perform monthly callback and increment `cs.dates.date1` if `cs.dates.date` passes to next month + TimeManager.trigger_callback( + cs.dates.date1[1], + cs.dates.date[1], + TimeManager.Monthly(), + checkpoint_func, + func_args, + ) end @show walltime diff --git a/src/BCReader.jl b/src/BCReader.jl index 92a81fbed9..d7723d2ab8 100644 --- a/src/BCReader.jl +++ b/src/BCReader.jl @@ -7,9 +7,10 @@ monthly to daily intervals. """ module BCReader -using ..Utilities, ..Regridder, ..TimeManager +using ..Utilities, ..Regridder using ClimaCore: Fields using ClimaComms +import ClimaUtilities: TimeManager using Dates using JLD2 diff --git a/src/Checkpointer.jl b/src/Checkpointer.jl index bfb0a86e65..a9d8e8c221 100644 --- a/src/Checkpointer.jl +++ b/src/Checkpointer.jl @@ -8,7 +8,6 @@ module Checkpointer using ClimaCore: Fields, InputOutput using ClimaCoupler: Interfacer using Dates -using ClimaCoupler.TimeManager: AbstractFrequency, Monthly, EveryTimestep, trigger_callback using ClimaComms export get_model_state_vector, checkpoint_model_state, restart_model_state! diff --git a/src/ClimaCoupler.jl b/src/ClimaCoupler.jl index bcd40ca48e..7175534b6c 100644 --- a/src/ClimaCoupler.jl +++ b/src/ClimaCoupler.jl @@ -11,7 +11,6 @@ include("CoupledSimulations/coupled_simulation.jl") include("CouplerState/coupler_state.jl") include("../test/TestHelper.jl") include("Utilities.jl") -include("TimeManager.jl") include("Regridder.jl") include("ConservationChecker.jl") include("BCReader.jl") diff --git a/src/Diagnostics.jl b/src/Diagnostics.jl index 109ddbc079..931d66e1c7 100644 --- a/src/Diagnostics.jl +++ b/src/Diagnostics.jl @@ -8,7 +8,7 @@ module Diagnostics using ClimaCore: Spaces, Fields, InputOutput using ClimaCoupler.Utilities: CoupledSimulation using Dates -using ClimaCoupler.TimeManager: AbstractFrequency, Monthly, EveryTimestep, trigger_callback +using ClimaUtilities.TimeManager: Monthly, EveryTimestep, trigger_callback using ClimaComms export get_var, init_diagnostics, accumulate_diagnostics!, save_diagnostics, TimeMean @@ -131,13 +131,20 @@ end Saves all entries in `dg` in separate HDF5 files per variable in `output_dir`. """ function save_diagnostics(cs::CoupledSimulation) - for dg in cs.diagnostics + # extract dates for callback condition check + date_cutoff = cs.dates.date1[1] + date_current = cs.dates.date[1] + # define function to perform diagnostic saving if callback is triggered + save_func = (cs) -> for dg in cs.diagnostics if trigger_callback(cs, dg.save) pre_save(dg.operations.accumulate, cs, dg) save_diagnostics(cs, dg) post_save(dg.operations.accumulate, cs, dg) end end + func_args = (cs,) + # perform monthly callback and increment `cs.dates.date1` if `date_current` passes to next month + trigger_callback(date_cutoff, date_current, Monthly(), save_func, func_args) end function save_diagnostics(cs::CoupledSimulation, dg::DiagnosticsGroup) diff --git a/src/Regridder.jl b/src/Regridder.jl index 678b3e549b..3d9b261740 100644 --- a/src/Regridder.jl +++ b/src/Regridder.jl @@ -8,10 +8,10 @@ via ClimaCoreTempestRemap wrappers. module Regridder using ..Utilities -using ..TimeManager using ..Interfacer using ClimaCore: Meshes, Domains, Topologies, Spaces, Fields, InputOutput using ClimaComms +using ClimaUtilities.TimeManager using NCDatasets using ClimaCoreTempestRemap using Dates @@ -144,7 +144,7 @@ function hdwrite_regridfile_rll_to_cgll( if "time" in ds data_dates = Dates.DateTime.(ds["time"][:]) elseif "date" in ds - data_dates = TimeManager.strdate_to_datetime.(string.(ds["date"][:])) + data_dates = strdate_to_datetime.(string.(ds["date"][:])) else @warn "No dates available in file $datafile_rll" data_dates = [Dates.DateTime(0)] diff --git a/src/TimeManager.jl b/src/TimeManager.jl deleted file mode 100644 index 51ffd098a8..0000000000 --- a/src/TimeManager.jl +++ /dev/null @@ -1,66 +0,0 @@ -""" - TimeManager - -This module facilitates calendar functions and temporal interpolations -of data. -""" -module TimeManager - -using ..Utilities -using Dates - -export current_date, - strdate_to_datetime, datetime_to_strdate, AbstractFrequency, Monthly, EveryTimestep, trigger_callback - - -""" - current_date(cs::CoupledSimulation, t::Int) - -Return the model date at the current timestep. - -# Arguments -- `cs`: [CoupledSimulation] containing info about the simulation -- `t`: [Real] number of seconds since simulation began -""" -current_date(cs::CoupledSimulation, t::Real) = cs.dates.date0[1] + Dates.Second(t) - -""" - strdate_to_datetime(strdate::String) - -Convert from String ("YYYYMMDD") to Date format, -required by the official AMIP input files. - -# Arguments -- `strdate`: [String] to be converted to Date type -""" -strdate_to_datetime(strdate::String) = - Dates.DateTime(parse(Int, strdate[1:4]), parse(Int, strdate[5:6]), parse(Int, strdate[7:8])) - -""" - datetime_to_strdate(datetime::DateTime) - -Convert from Date to String ("YYYYMMDD") format. - -# Arguments -- `datetime`: [DateTime] object to be converted to string -""" -datetime_to_strdate(datetime::DateTime) = - string(lpad(Dates.year(datetime), 4, "0")) * - string(string(lpad(Dates.month(datetime), 2, "0"))) * - string(lpad(Dates.day(datetime), 2, "0")) - -abstract type AbstractFrequency end -struct Monthly <: AbstractFrequency end -struct EveryTimestep <: AbstractFrequency end - -""" - trigger_callback(cs, ::Monthly) - -Returns `true` if the current date is equal to or exceeds the saved first of the month at time of 00:00:00. - -# Arguments -- `cs`: [CoupledSimulation] containing info about the simulation -""" -trigger_callback(cs::CoupledSimulation, ::Monthly) = cs.dates.date[1] >= cs.dates.date1[1] ? true : false - -end diff --git a/src/Utilities.jl b/src/Utilities.jl index 5d24753067..f085e458b1 100644 --- a/src/Utilities.jl +++ b/src/Utilities.jl @@ -7,8 +7,9 @@ modules in the coupler. module Utilities using ClimaCore: Fields, Spaces +using Dates -export CoupledSimulation, float_type, swap_space! +export CoupledSimulation, float_type, swap_space!, current_date """ AbstractSimulation @@ -74,4 +75,15 @@ function swap_space!(field_out, field_in::Fields.Field) return field_out end +""" + current_date(cs::CoupledSimulation, t::Int) + +Return the model date at the current timestep. + +# Arguments +- `cs`: [CoupledSimulation] containing info about the simulation +- `t`: [Real] number of seconds since simulation began +""" +current_date(cs::CoupledSimulation, t::Real) = cs.dates.date0[1] + Dates.Second(t) + end # module diff --git a/test/Project.toml b/test/Project.toml index 83c21aedd6..cdc3021d84 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -7,6 +7,7 @@ ClimaCore = "d414da3d-4745-48bb-8d80-42e94e092884" ClimaCoupler = "4ade58fe-a8da-486c-bd89-46df092ec0c7" ClimaLSM = "7884a58f-fab6-4fd0-82bb-ecfedb2d8430" ClimaTimeSteppers = "595c0a79-7f3d-439a-bc5a-b232dc3bde79" +ClimaUtilities = "b3f4f4ca-9299-4f7f-bd9b-81e1242a7513" Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6" IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" diff --git a/test/bcreader_tests.jl b/test/bcreader_tests.jl index bfaf495fc1..bf5a9fb124 100644 --- a/test/bcreader_tests.jl +++ b/test/bcreader_tests.jl @@ -2,9 +2,10 @@ Unit tests for ClimaCoupler BCReader module =# -using ClimaCoupler: Regridder, BCReader, TimeManager, Utilities +using ClimaCoupler: Regridder, BCReader, Utilities using ClimaCore: Fields, Meshes, Domains, Topologies, Spaces using ClimaComms +using ClimaUtilities: TimeManager using Test using Dates using NCDatasets @@ -198,7 +199,7 @@ for FT in (Float32, Float64) # step in time walltime = @elapsed for t in ((tspan[1] + Δt):Δt:tspan[end]) - cs_t.dates.date[1] = TimeManager.current_date(cs_t, t) # if not global, `date`` is not updated. Check that this still runs when distributed. + cs_t.dates.date[1] = Utilities.current_date(cs_t, t) # if not global, `date`` is not updated. Check that this still runs when distributed. model_date = cs_t.dates.date[1] callback_date = BCReader.next_date_in_file(bcf_info) diff --git a/test/diagnostics_tests.jl b/test/diagnostics_tests.jl index 741b8592d5..2659e4c4a0 100644 --- a/test/diagnostics_tests.jl +++ b/test/diagnostics_tests.jl @@ -5,8 +5,8 @@ using Test using Dates using ClimaCore: InputOutput using ClimaComms +using ClimaUtilities.TimeManager: Monthly, EveryTimestep using ClimaCoupler: Utilities -using ClimaCoupler.TimeManager: EveryTimestep, Monthly using ClimaCoupler.TestHelper: create_space import ClimaCoupler.Diagnostics: get_var, diff --git a/test/mpi_tests/bcreader_mpi_tests.jl b/test/mpi_tests/bcreader_mpi_tests.jl index 9fd8ddf216..8a0bbf8c75 100644 --- a/test/mpi_tests/bcreader_mpi_tests.jl +++ b/test/mpi_tests/bcreader_mpi_tests.jl @@ -8,6 +8,7 @@ that MPI can be enabled for testing of these functions. using ClimaCoupler: Regridder, BCReader, TimeManager, Utilities using ClimaCore: Fields, Meshes, Domains, Topologies, Spaces using ClimaComms +import ClimaUtilities: TimeManager using Test using Dates using NCDatasets @@ -142,7 +143,7 @@ end # step in time walltime = @elapsed for t in ((tspan[1] + Δt):Δt:tspan[end]) - cs_t.dates.date[1] = TimeManager.current_date(cs_t, t) # if not global, `date`` is not updated. Check that this still runs when distributed. + cs_t.dates.date[1] = Utilities.current_date(cs_t, t) # if not global, `date`` is not updated. Check that this still runs when distributed. model_date = cs_t.dates.date[1] callback_date = BCReader.next_date_in_file(bcf_info) diff --git a/test/runtests.jl b/test/runtests.jl index 3999d83a97..d4a2634e8d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -21,9 +21,6 @@ end @safetestset "Utilities tests" begin include("utilities_tests.jl") end -@safetestset "TimeManager tests" begin - include("time_manager_tests.jl") -end @safetestset "FieldExchanger tests" begin include("field_exchanger_tests.jl") end diff --git a/test/time_manager_tests.jl b/test/time_manager_tests.jl deleted file mode 100644 index bb711e2e41..0000000000 --- a/test/time_manager_tests.jl +++ /dev/null @@ -1,70 +0,0 @@ -#= - Unit tests for ClimaCoupler TimeManager module -=# - -using Test -using Dates -using ClimaCoupler: Utilities, TimeManager -using ClimaComms - -for FT in (Float32, Float64) - @testset "test current_date" begin - date0 = date = DateTime("19790321", dateformat"yyyymmdd") - dates = (; date = [date], date0 = [date0], date1 = [Dates.firstdayofmonth(date0)]) - tspan = (Int(1), Int(90 * 86400)) # Jan-Mar - Δt_cpl = 1 * 24 * 3600 - - # Fill in only the necessary parts of the simulation - cs = Utilities.CoupledSimulation{FT}( - ClimaComms.SingletonCommsContext(), # comms_ctx - dates, # dates - nothing, # boundary_space - nothing, # fields - nothing, # parsed_args - nothing, # conservation_checks - tspan, # tspan - Int(0), # t - Int(Δt_cpl), # Δt_cpl - (;), # surface_masks - (;), # model_sims - (;), # mode - (), # diagnostics - ) - - for t in ((tspan[1] + Δt_cpl):Δt_cpl:tspan[end]) - @test TimeManager.current_date(cs, t) == date0 + Dates.Second(t) - end - end -end - -@testset "test strdate_to_datetime" begin - @test TimeManager.strdate_to_datetime("19000101") == Dates.DateTime(1900, 1, 1) - @test TimeManager.strdate_to_datetime("00000101") == Dates.DateTime(0, 1, 1) -end - -@testset "test datetime_to_strdate" begin - @test TimeManager.datetime_to_strdate(Dates.DateTime(1900, 1, 1)) == "19000101" - @test TimeManager.datetime_to_strdate(Dates.DateTime(0, 1, 1)) == "00000101" -end - -@testset "trigger_callback" begin - date0 = date = DateTime("19790321", dateformat"yyyymmdd") - dates = (; date = [date], date0 = [date0], date1 = [Dates.firstdayofmonth(date0)]) - - cs = Utilities.CoupledSimulation{Float64}( - nothing, # comms_ctx - dates, # dates - nothing, # boundary_space - nothing, # fields - nothing, # parsed_args - nothing, # conservation_checks - (Int(0), Int(1000)), # tspan - Int(200), # t - Int(200), # Δt_cpl - (;), # surface_masks - (;), # model_sims - (;), # mode - (), # diagnostics - ) - @test TimeManager.trigger_callback(cs, TimeManager.Monthly()) == true -end diff --git a/test/utilities_tests.jl b/test/utilities_tests.jl index e26a9f8959..e87c30cd7b 100644 --- a/test/utilities_tests.jl +++ b/test/utilities_tests.jl @@ -2,7 +2,9 @@ Unit tests for ClimaCoupler Utilities module =# +import Dates using Test +import ClimaComms using ClimaCoupler: Utilities, TestHelper using ClimaCore: Fields @@ -39,4 +41,32 @@ for FT in (Float32, Float64) @test parent(field1) == parent(field2) @test axes(field2) == space2 end + + @testset "test current_date" begin + date0 = date = Dates.DateTime("19790321", Dates.dateformat"yyyymmdd") + dates = (; date = [date], date0 = [date0], date1 = [Dates.firstdayofmonth(date0)]) + tspan = (Int(1), Int(90 * 86400)) # Jan-Mar + Δt_cpl = 1 * 24 * 3600 + + # Fill in only the necessary parts of the simulation + cs = Utilities.CoupledSimulation{FT}( + ClimaComms.SingletonCommsContext(), # comms_ctx + dates, # dates + nothing, # boundary_space + nothing, # fields + nothing, # parsed_args + nothing, # conservation_checks + tspan, # tspan + Int(0), # t + Int(Δt_cpl), # Δt_cpl + (;), # surface_masks + (;), # model_sims + (;), # mode + (), # diagnostics + ) + + for t in ((tspan[1] + Δt_cpl):Δt_cpl:tspan[end]) + @test Utilities.current_date(cs, t) == date0 + Dates.Second(t) + end + end end