diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 59a4c7c7cd..13f667fc5b 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -188,6 +188,14 @@ steps: # AMIP EXPERIMENTS + # Test default behavior with no config file or job ID provided + - label: "AMIP: default" + key: "amip_default" + command: "julia --color=yes --project=experiments/ClimaEarth/ experiments/ClimaEarth/run_amip.jl" + artifact_paths: "experiments/ClimaEarth/output/amip_default/artifacts/*" + agents: + slurm_mem: 20GB + - label: "AMIP target: albedo from function" key: "target_amip_albedo_function" command: "julia --color=yes --project=experiments/ClimaEarth/ experiments/ClimaEarth/run_amip.jl --config_file $CONFIG_PATH/amip_albedo_function.yml --job_id target_amip_albedo_function" diff --git a/config/amip_configs/amip.yml b/config/amip_configs/amip.yml index 3bfbf92d7e..2648ea5d43 100644 --- a/config/amip_configs/amip.yml +++ b/config/amip_configs/amip.yml @@ -3,7 +3,7 @@ albedo_model: "CouplerAlbedo" atmos_config_file: "config/longrun_configs/amip_target_diagedmf.yml" coupler_toml_file: "toml/amip.toml" dt: "120secs" -dt_cpl: 120 +dt_cpl: "120secs" dt_save_state_to_disk: "30days" dt_save_to_sol: "30days" dz_bottom: 30.0 diff --git a/config/benchmark_configs/amip_diagedmf.yml b/config/benchmark_configs/amip_diagedmf.yml index e9aff1243d..13535b9b22 100644 --- a/config/benchmark_configs/amip_diagedmf.yml +++ b/config/benchmark_configs/amip_diagedmf.yml @@ -2,7 +2,7 @@ FLOAT_TYPE: "Float32" atmos_config_file: "config/benchmark_configs/climaatmos_diagedmf.yml" atmos_config_repo: "ClimaCoupler" dt: "120secs" -dt_cpl: 120 +dt_cpl: "120secs" dt_save_state_to_disk: "Inf" dt_save_to_sol: "Inf" energy_check: false diff --git a/config/benchmark_configs/amip_diagedmf_io.yml b/config/benchmark_configs/amip_diagedmf_io.yml index b776fdaa8a..61040582d0 100644 --- a/config/benchmark_configs/amip_diagedmf_io.yml +++ b/config/benchmark_configs/amip_diagedmf_io.yml @@ -2,7 +2,7 @@ FLOAT_TYPE: "Float32" atmos_config_file: "config/benchmark_configs/climaatmos_diagedmf_io.yml" atmos_config_repo: "ClimaCoupler" dt: "120secs" -dt_cpl: 120 +dt_cpl: "120secs" dt_save_state_to_disk: "12hours" dt_save_to_sol: "12hours" energy_check: false diff --git a/config/benchmark_configs/climaatmos_diagedmf_io.yml b/config/benchmark_configs/climaatmos_diagedmf_io.yml index 506cafec76..a9a5cc8a3c 100644 --- a/config/benchmark_configs/climaatmos_diagedmf_io.yml +++ b/config/benchmark_configs/climaatmos_diagedmf_io.yml @@ -32,6 +32,6 @@ output_default_diagnostics: false prescribe_ozone: true aerosol_radiation: true prescribed_aerosols: ["CB1", "CB2", "DST01", "OC1", "OC2", "SO4", "SSLT01"] -diagnostics: +extra_atmos_diagnostics: - short_name: [pfull, rsut, rlut, pr, hus, rv] period: 10hours diff --git a/config/ci_configs/amip_albedo_function.yml b/config/ci_configs/amip_albedo_function.yml index 8fb7219f7e..bf32083c70 100644 --- a/config/ci_configs/amip_albedo_function.yml +++ b/config/ci_configs/amip_albedo_function.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "150secs" -dt_cpl: 150 +dt_cpl: "150secs" dt_rad: "1hours" dt_save_to_sol: "1days" dz_bottom: 30 diff --git a/config/ci_configs/amip_albedo_temporal_map.yml b/config/ci_configs/amip_albedo_temporal_map.yml index 928acb1933..f481bc7763 100644 --- a/config/ci_configs/amip_albedo_temporal_map.yml +++ b/config/ci_configs/amip_albedo_temporal_map.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "150secs" -dt_cpl: 150 +dt_cpl: "150secs" dt_rad: "1hours" dt_save_to_sol: "1days" dz_bottom: 30 diff --git a/config/ci_configs/amip_albedo_temporal_map_1M.yml b/config/ci_configs/amip_albedo_temporal_map_1M.yml index 5353a753b9..fc424f4287 100644 --- a/config/ci_configs/amip_albedo_temporal_map_1M.yml +++ b/config/ci_configs/amip_albedo_temporal_map_1M.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "150secs" -dt_cpl: 150 +dt_cpl: "150secs" dt_rad: "1hours" dt_save_to_sol: "1days" dz_bottom: 30 diff --git a/config/ci_configs/amip_coarse_ft32.yml b/config/ci_configs/amip_coarse_ft32.yml index b7fa9d1120..283fdd80ea 100644 --- a/config/ci_configs/amip_coarse_ft32.yml +++ b/config/ci_configs/amip_coarse_ft32.yml @@ -1,7 +1,5 @@ FLOAT_TYPE: "Float32" apply_limiter: false -dt: "400secs" -dt_cpl: 400 dt_save_to_sol: "100days" energy_check: false h_elem: 6 diff --git a/config/ci_configs/amip_coarse_ft64_hourly_checkpoints.yml b/config/ci_configs/amip_coarse_ft64_hourly_checkpoints.yml index 26e1ab41ee..e1f5cd8c6a 100644 --- a/config/ci_configs/amip_coarse_ft64_hourly_checkpoints.yml +++ b/config/ci_configs/amip_coarse_ft64_hourly_checkpoints.yml @@ -1,6 +1,4 @@ apply_limiter: false -dt: "400secs" -dt_cpl: 400 dt_save_to_sol: "1days" energy_check: false h_elem: 6 diff --git a/config/ci_configs/amip_coarse_ft64_hourly_checkpoints_restart.yml b/config/ci_configs/amip_coarse_ft64_hourly_checkpoints_restart.yml index 0fc0a6b844..03367c0b21 100644 --- a/config/ci_configs/amip_coarse_ft64_hourly_checkpoints_restart.yml +++ b/config/ci_configs/amip_coarse_ft64_hourly_checkpoints_restart.yml @@ -1,6 +1,4 @@ apply_limiter: false -dt: "400secs" -dt_cpl: 400 dt_save_restart: "10days" dt_save_to_sol: "1days" energy_check: false diff --git a/config/ci_configs/amip_coarse_mpi.yml b/config/ci_configs/amip_coarse_mpi.yml index c5fea07a2e..5894fc1fe4 100644 --- a/config/ci_configs/amip_coarse_mpi.yml +++ b/config/ci_configs/amip_coarse_mpi.yml @@ -1,6 +1,4 @@ apply_limiter: false -dt: "400secs" -dt_cpl: 400 dt_save_to_sol: "1days" energy_check: false h_elem: 6 diff --git a/config/ci_configs/amip_component_dts.yml b/config/ci_configs/amip_component_dts.yml index 01725c31bd..ea0c3d5052 100644 --- a/config/ci_configs/amip_component_dts.yml +++ b/config/ci_configs/amip_component_dts.yml @@ -3,7 +3,7 @@ dt_atmos: "150secs" dt_land: "50secs" dt_ocean: "30secs" dt_seaice: "75secs" -dt_cpl: 150 +dt_cpl: "150secs" dt_rad: "1hours" dt_save_to_sol: "1days" dz_bottom: 30 diff --git a/config/ci_configs/amip_default.yml b/config/ci_configs/amip_default.yml index f88629ea37..9369e9e02a 100644 --- a/config/ci_configs/amip_default.yml +++ b/config/ci_configs/amip_default.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "150secs" -dt_cpl: 150 +dt_cpl: "150secs" dt_rad: "1hours" dt_save_to_sol: "1days" dz_bottom: 30 diff --git a/config/ci_configs/amip_n1_shortrun.yml b/config/ci_configs/amip_n1_shortrun.yml index 6595005e04..dc09486662 100644 --- a/config/ci_configs/amip_n1_shortrun.yml +++ b/config/ci_configs/amip_n1_shortrun.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "150secs" -dt_cpl: 150 +dt_cpl: "150secs" dt_rad: "1hours" dt_save_to_sol: "1days" dz_bottom: 30 diff --git a/config/ci_configs/amip_target_topo_diagedmf_shortrun.yml b/config/ci_configs/amip_target_topo_diagedmf_shortrun.yml index d01d2025c0..e73477831f 100644 --- a/config/ci_configs/amip_target_topo_diagedmf_shortrun.yml +++ b/config/ci_configs/amip_target_topo_diagedmf_shortrun.yml @@ -3,7 +3,7 @@ apply_limiter: false atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_diagedmf_0M.yml" dt: "100secs" dt_cloud_fraction: "1hours" -dt_cpl: 100 +dt_cpl: "100secs" dt_rad: "1hours" dt_save_state_to_disk: "1days" dt_save_to_sol: "1days" diff --git a/config/ci_configs/interactive_debug.yml b/config/ci_configs/interactive_debug.yml deleted file mode 100644 index 70abc041f9..0000000000 --- a/config/ci_configs/interactive_debug.yml +++ /dev/null @@ -1,19 +0,0 @@ -apply_limiter: false -coupler_output_dir: "experiments/ClimaEarth/output" -dt: "200secs" -dt_cpl: 200 -dt_save_to_sol: "10days" -energy_check: true -evolving_ocean: true -h_elem: 4 -land_albedo_type: "function" -mode_name: "slabplanet" -moist: "equil" -mono_surface: true -precip_model: "0M" -rad: "gray" -start_date: "20100101" -surface_setup: "PrescribedSurface" -t_end: "20days" -turb_flux_partition: "CombinedStateFluxesMOST" -vert_diff: "true" diff --git a/config/ci_configs/slabplanet_albedo_function.yml b/config/ci_configs/slabplanet_albedo_function.yml index 7b499e1002..8a4c096653 100644 --- a/config/ci_configs/slabplanet_albedo_function.yml +++ b/config/ci_configs/slabplanet_albedo_function.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "3600secs" energy_check: true h_elem: 4 diff --git a/config/ci_configs/slabplanet_albedo_temporal_map.yml b/config/ci_configs/slabplanet_albedo_temporal_map.yml index 96ea2d5c43..f7fe507e86 100644 --- a/config/ci_configs/slabplanet_albedo_temporal_map.yml +++ b/config/ci_configs/slabplanet_albedo_temporal_map.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "3600secs" energy_check: true h_elem: 4 diff --git a/config/ci_configs/slabplanet_atmos_diags.yml b/config/ci_configs/slabplanet_atmos_diags.yml index 2a6e83e3b9..ecb0efbfac 100644 --- a/config/ci_configs/slabplanet_atmos_diags.yml +++ b/config/ci_configs/slabplanet_atmos_diags.yml @@ -1,7 +1,7 @@ apply_limiter: false -ci_plots: true +plot_diagnostics: true dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "9days" energy_check: true h_elem: 4 @@ -12,7 +12,7 @@ precip_model: "0M" rad: "gray" t_end: "10days" vert_diff: "true" -diagnostics: +extra_atmos_diagnostics: - short_name: [mse, lr, edt, evu, ts, mass_strf, stab, vt, egr, toa_fluxes_net] reduction_time: average period: 1days diff --git a/config/ci_configs/slabplanet_default.yml b/config/ci_configs/slabplanet_default.yml index 19aea4a20f..3dd0d678c6 100644 --- a/config/ci_configs/slabplanet_default.yml +++ b/config/ci_configs/slabplanet_default.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "9days" energy_check: true h_elem: 4 @@ -12,6 +12,6 @@ rad: "gray" t_end: "10days" vert_diff: "true" output_default_diagnostics: false -diagnostics: +extra_atmos_diagnostics: - short_name: [mse, lr, edt, evu, hfes, evspsbl, ts] period: 1days diff --git a/config/ci_configs/slabplanet_dry_norad.yml b/config/ci_configs/slabplanet_dry_norad.yml index 63ab9b298a..7658748e2f 100644 --- a/config/ci_configs/slabplanet_dry_norad.yml +++ b/config/ci_configs/slabplanet_dry_norad.yml @@ -1,7 +1,7 @@ apply_limiter: false conservation_softfail: true dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "9days" energy_check: true h_elem: 4 diff --git a/config/ci_configs/slabplanet_eisenman.yml b/config/ci_configs/slabplanet_eisenman.yml index 049a455d20..c277beed05 100644 --- a/config/ci_configs/slabplanet_eisenman.yml +++ b/config/ci_configs/slabplanet_eisenman.yml @@ -1,7 +1,7 @@ apply_limiter: false conservation_softfail: true dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "9days" energy_check: true h_elem: 6 diff --git a/config/ci_configs/slabplanet_ft32.yml b/config/ci_configs/slabplanet_ft32.yml index 264c95c506..810c70fde7 100644 --- a/config/ci_configs/slabplanet_ft32.yml +++ b/config/ci_configs/slabplanet_ft32.yml @@ -1,7 +1,7 @@ FLOAT_TYPE: "Float32" apply_limiter: false dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "9days" energy_check: true h_elem: 4 diff --git a/config/ci_configs/slabplanet_nonmono.yml b/config/ci_configs/slabplanet_nonmono.yml index 8cbb9b2a5b..56f522126f 100644 --- a/config/ci_configs/slabplanet_nonmono.yml +++ b/config/ci_configs/slabplanet_nonmono.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "9days" energy_check: true h_elem: 4 diff --git a/config/ci_configs/slabplanet_partitioned_fluxes.yml b/config/ci_configs/slabplanet_partitioned_fluxes.yml index 4978872107..c6e8b9cd06 100644 --- a/config/ci_configs/slabplanet_partitioned_fluxes.yml +++ b/config/ci_configs/slabplanet_partitioned_fluxes.yml @@ -1,6 +1,6 @@ apply_limiter: false dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "9days" energy_check: true h_elem: 4 diff --git a/config/ci_configs/slabplanet_realinsol_rayleigh.yml b/config/ci_configs/slabplanet_realinsol_rayleigh.yml index 836dca4296..72eb630c54 100644 --- a/config/ci_configs/slabplanet_realinsol_rayleigh.yml +++ b/config/ci_configs/slabplanet_realinsol_rayleigh.yml @@ -1,7 +1,7 @@ apply_limiter: false conservation_softfail: true dt: "200secs" -dt_cpl: 3600 +dt_cpl: "3600secs" dt_rad: "6hours" dt_save_to_sol: "3600secs" energy_check: true diff --git a/config/longrun_configs/amip_target.yml b/config/longrun_configs/amip_target.yml index 898a0e44e8..2c22691535 100644 --- a/config/longrun_configs/amip_target.yml +++ b/config/longrun_configs/amip_target.yml @@ -2,7 +2,7 @@ FLOAT_TYPE: "Float32" atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_0M.yml" dt: "120secs" dt_cloud_fraction: "1hours" -dt_cpl: 120 +dt_cpl: "120secs" dt_rad: "1hours" dt_save_state_to_disk: "20days" energy_check: false diff --git a/config/longrun_configs/amip_target_topo.yml b/config/longrun_configs/amip_target_topo.yml index 5e01bc6632..1081e82788 100644 --- a/config/longrun_configs/amip_target_topo.yml +++ b/config/longrun_configs/amip_target_topo.yml @@ -3,7 +3,7 @@ albedo_model: "CouplerAlbedo" atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_0M_earth.yml" dt: "120secs" dt_cloud_fraction: "1hours" -dt_cpl: 120 +dt_cpl: "120secs" dt_rad: "1hours" dt_save_state_to_disk: "20days" energy_check: false diff --git a/config/longrun_configs/amip_target_topo_diagedmf_cpu.yml b/config/longrun_configs/amip_target_topo_diagedmf_cpu.yml index f8c827515a..bca89d6cfa 100644 --- a/config/longrun_configs/amip_target_topo_diagedmf_cpu.yml +++ b/config/longrun_configs/amip_target_topo_diagedmf_cpu.yml @@ -3,7 +3,7 @@ albedo_model: "CouplerAlbedo" atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_diagedmf_0M.yml" dt: "120secs" dt_cloud_fraction: "1hours" -dt_cpl: 120 +dt_cpl: "120secs" dt_rad: "1hours" dt_save_state_to_disk: "20days" energy_check: false diff --git a/config/longrun_configs/amip_target_topo_diagedmf_gpu.yml b/config/longrun_configs/amip_target_topo_diagedmf_gpu.yml index cdf0b8f8c8..439fe0ebbc 100644 --- a/config/longrun_configs/amip_target_topo_diagedmf_gpu.yml +++ b/config/longrun_configs/amip_target_topo_diagedmf_gpu.yml @@ -3,7 +3,7 @@ albedo_model: "CouplerAlbedo" atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_diagedmf_0M.yml" dt: "120secs" dt_cloud_fraction: "1hours" -dt_cpl: 120 +dt_cpl: "120secs" dt_rad: "1hours" dt_save_state_to_disk: "20days" energy_check: false diff --git a/config/longrun_configs/longrun_amip_dyamond.yml b/config/longrun_configs/longrun_amip_dyamond.yml index b23c0f2216..68cd8e940e 100644 --- a/config/longrun_configs/longrun_amip_dyamond.yml +++ b/config/longrun_configs/longrun_amip_dyamond.yml @@ -1,6 +1,6 @@ atmos_config_file: "config/longrun_configs/longrun_aquaplanet_dyamond.yml" dt: "30secs" -dt_cpl: 30 +dt_cpl: "30secs" dt_save_state_to_disk: "0.5days" dt_save_to_sol: "0.5days" energy_check: false diff --git a/config/longrun_configs/slabplanet_aqua_atmos_sf_couple.yml b/config/longrun_configs/slabplanet_aqua_atmos_sf_couple.yml index 31d0f5d9cb..7493bbd6db 100644 --- a/config/longrun_configs/slabplanet_aqua_atmos_sf_couple.yml +++ b/config/longrun_configs/slabplanet_aqua_atmos_sf_couple.yml @@ -1,6 +1,6 @@ conservation_softfail: true dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "10days" energy_check: true evolving_ocean: false diff --git a/config/longrun_configs/slabplanet_aqua_atmos_sf_nocouple.yml b/config/longrun_configs/slabplanet_aqua_atmos_sf_nocouple.yml index 4bec7a7b2a..764274d669 100644 --- a/config/longrun_configs/slabplanet_aqua_atmos_sf_nocouple.yml +++ b/config/longrun_configs/slabplanet_aqua_atmos_sf_nocouple.yml @@ -1,6 +1,6 @@ conservation_softfail: true dt: "200secs" -dt_cpl: 1728000 +dt_cpl: "1728000secs" dt_save_to_sol: "10days" energy_check: true evolving_ocean: false diff --git a/config/longrun_configs/slabplanet_aqua_coupler_sf.yml b/config/longrun_configs/slabplanet_aqua_coupler_sf.yml index 2ce52bb35f..ae5bcf64cf 100644 --- a/config/longrun_configs/slabplanet_aqua_coupler_sf.yml +++ b/config/longrun_configs/slabplanet_aqua_coupler_sf.yml @@ -1,6 +1,6 @@ conservation_softfail: true dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "10days" energy_check: true evolving_ocean: false diff --git a/config/longrun_configs/slabplanet_aqua_coupler_sf_evolve_ocn.yml b/config/longrun_configs/slabplanet_aqua_coupler_sf_evolve_ocn.yml index a94fd257ba..4aca82c82f 100644 --- a/config/longrun_configs/slabplanet_aqua_coupler_sf_evolve_ocn.yml +++ b/config/longrun_configs/slabplanet_aqua_coupler_sf_evolve_ocn.yml @@ -1,5 +1,5 @@ dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "10days" energy_check: true evolving_ocean: true diff --git a/config/longrun_configs/slabplanet_aqua_target.yml b/config/longrun_configs/slabplanet_aqua_target.yml index 3598204e93..59eb173088 100644 --- a/config/longrun_configs/slabplanet_aqua_target.yml +++ b/config/longrun_configs/slabplanet_aqua_target.yml @@ -1,7 +1,7 @@ atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_0M.yml" dt: "120secs" dt_cloud_fraction: "1hours" -dt_cpl: 120 +dt_cpl: "120secs" dt_rad: "1hours" dt_save_state_to_disk: "20days" dt_save_to_sol: "10days" diff --git a/config/longrun_configs/slabplanet_aqua_target_evolve_ocn.yml b/config/longrun_configs/slabplanet_aqua_target_evolve_ocn.yml index 2e7394dfb0..62a9bbcee4 100644 --- a/config/longrun_configs/slabplanet_aqua_target_evolve_ocn.yml +++ b/config/longrun_configs/slabplanet_aqua_target_evolve_ocn.yml @@ -1,7 +1,7 @@ atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_0M.yml" dt: "120secs" dt_cloud_fraction: "1hours" -dt_cpl: 120 +dt_cpl: "120secs" dt_rad: "1hours" dt_save_state_to_disk: "20days" dt_save_to_sol: "10days" diff --git a/config/longrun_configs/slabplanet_aqua_target_nocouple.yml b/config/longrun_configs/slabplanet_aqua_target_nocouple.yml index 46e658604f..4caa587aca 100644 --- a/config/longrun_configs/slabplanet_aqua_target_nocouple.yml +++ b/config/longrun_configs/slabplanet_aqua_target_nocouple.yml @@ -1,7 +1,7 @@ atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_0M.yml" dt: "120secs" dt_cloud_fraction: "1hours" -dt_cpl: 10368000 +dt_cpl: "10368000secs" dt_rad: "1hours" dt_save_state_to_disk: "20days" dt_save_to_sol: "10days" diff --git a/config/longrun_configs/slabplanet_coupler_sf_evolve_ocn.yml b/config/longrun_configs/slabplanet_coupler_sf_evolve_ocn.yml index 501b5071a9..a8aafa2cec 100644 --- a/config/longrun_configs/slabplanet_coupler_sf_evolve_ocn.yml +++ b/config/longrun_configs/slabplanet_coupler_sf_evolve_ocn.yml @@ -1,5 +1,5 @@ dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "10days" energy_check: true evolving_ocean: true diff --git a/config/longrun_configs/slabplanet_target.yml b/config/longrun_configs/slabplanet_target.yml index fb428e0fed..dee938f45d 100644 --- a/config/longrun_configs/slabplanet_target.yml +++ b/config/longrun_configs/slabplanet_target.yml @@ -1,7 +1,7 @@ atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_0M.yml" dt: "120secs" dt_cloud_fraction: "1hours" -dt_cpl: 120 +dt_cpl: "120secs" dt_rad: "1hours" dt_save_state_to_disk: "20days" dt_save_to_sol: "10days" diff --git a/config/longrun_configs/slabplanet_target_evolve_ocn.yml b/config/longrun_configs/slabplanet_target_evolve_ocn.yml index bcf8f4cf3e..bdb88b729e 100644 --- a/config/longrun_configs/slabplanet_target_evolve_ocn.yml +++ b/config/longrun_configs/slabplanet_target_evolve_ocn.yml @@ -1,7 +1,7 @@ atmos_config_file: "config/longrun_configs/longrun_aquaplanet_allsky_0M.yml" dt: "120secs" dt_cloud_fraction: "1hours" -dt_cpl: 120 +dt_cpl: "120secs" dt_rad: "1hours" dt_save_state_to_disk: "20days" dt_save_to_sol: "10days" diff --git a/config/longrun_configs/slabplanet_terra.yml b/config/longrun_configs/slabplanet_terra.yml index 49036dd264..9db3573a9b 100644 --- a/config/longrun_configs/slabplanet_terra.yml +++ b/config/longrun_configs/slabplanet_terra.yml @@ -1,6 +1,6 @@ conservation_softfail: true dt: "200secs" -dt_cpl: 200 +dt_cpl: "200secs" dt_save_to_sol: "10days" energy_check: true h_elem: 4 diff --git a/config/nightly_configs/amip_coarse.yml b/config/nightly_configs/amip_coarse.yml index 8dd3910a0c..e15d9e24ae 100644 --- a/config/nightly_configs/amip_coarse.yml +++ b/config/nightly_configs/amip_coarse.yml @@ -3,7 +3,7 @@ albedo_model: "CouplerAlbedo" atmos_config_file: "config/longrun_configs/amip_target_diagedmf.yml" coupler_toml_file: "toml/amip.toml" dt: "240secs" -dt_cpl: 240 +dt_cpl: "240secs" dt_save_state_to_disk: "30days" dt_save_to_sol: "30days" dz_bottom: 100.0 diff --git a/config/nightly_configs/amip_coarse_random.yml b/config/nightly_configs/amip_coarse_random.yml index 5259572ea3..2a7f772d27 100644 --- a/config/nightly_configs/amip_coarse_random.yml +++ b/config/nightly_configs/amip_coarse_random.yml @@ -3,7 +3,7 @@ albedo_model: "CouplerAlbedo" atmos_config_file: "config/longrun_configs/amip_target_diagedmf.yml" coupler_toml_file: "toml/amip.toml" dt: "240secs" -dt_cpl: 240 +dt_cpl: "240secs" dt_save_state_to_disk: "30days" dt_save_to_sol: "30days" dz_bottom: 100.0 diff --git a/experiments/ClimaEarth/cli_options.jl b/experiments/ClimaEarth/cli_options.jl index ed0e63cc75..1c3f0e6647 100644 --- a/experiments/ClimaEarth/cli_options.jl +++ b/experiments/ClimaEarth/cli_options.jl @@ -2,107 +2,138 @@ import ArgParse function argparse_settings() s = ArgParse.ArgParseSettings() ArgParse.@add_arg_table! s begin - # ClimaCoupler flags - "--dt_cpl" - help = " Coupling time step in seconds" - arg_type = Int - default = 400 - "--dt_atmos" - help = " Atmos simulation time step" - arg_type = String - "--dt_land" - help = " Land simulation time step" - arg_type = String - "--dt_ocean" - help = " Ocean simulation time step" + ### ClimaCoupler flags + # Simulation-identifying information + "--config_file" + help = "A yaml file used to set the configuration of the coupled model [\"config/ci_configs/amip_default.yml\" (default)]" arg_type = String - "--dt_seaice" - help = " Sea Ice simulation time step" + default = "config/ci_configs/amip_default.yml" + "--job_id" + help = "A unique identifier for this run, defaults to the config file name" arg_type = String - "--energy_check" - help = "Boolean flag indicating whether to check energy conservation" - arg_type = Bool - default = false - "--ci_plots" - help = "Boolean flag indicating whether to make CI plots" - arg_type = Bool - default = false - "--conservation_softfail" - help = "Boolean flag indicating whether to soft fail on conservation errors" + default = nothing + "--print_config_dict" + help = "Boolean flag indicating whether to print the final configuration dictionary [`true` (default), `false`]" arg_type = Bool - default = false + default = true "--mode_name" help = "Mode of coupled simulation. [`amip` (default), `slabplanet`, `slabplanet_aqua`, `slabplanet_terra`, `slabplanet_eisenman`]" arg_type = String default = "amip" - "--mono_surface" - help = "Boolean flag indicating whether (1st order) monotone and conservative remapping is applied." + "--coupler_toml_file" + help = "An optional toml file used to overwrite the default model parameters." + default = nothing + # Computational simulation setup information + "--unique_seed" + help = "Boolean flag indicating whether to set the random number seed to a unique value [`false` (default), `true`]" arg_type = Bool default = false - "--turb_flux_partition" - help = "Method to partition turbulent fluxes. [`PartitionedStateFluxes`, `CombinedStateFluxesMOST` (default)]" + "--FLOAT_TYPE" + help = "Floating point precision [`Float64` (default), `Float32`]" arg_type = String - default = "CombinedStateFluxesMOST" + default = "Float64" + "--device" + help = "Device type to use [\"auto\" (default), \"CPUSingleThreaded\", \"CPUMultiThreaded\", \"CUDADevice\"]" + arg_type = String + default = "auto" + # Time information + "--t_end" + help = "End time of the simulation [\"800secs\"; allowed formats: \"Nsecs\", \"Nmins\", \"Nhours\", \"Ndays\", \"Inf\"]" + arg_type = String + default = "800secs" + "--t_start" + help = "Start time of the simulation [\"0secs\" (default); allowed formats: \"Nsecs\", \"Nmins\", \"Nhours\", \"Ndays\", \"Inf\"]" + arg_type = String + default = "0secs" + "--start_date" + help = "Start date of the simulation, in format \"YYYYMMDD\" [\"20100101\" (default)]" + arg_type = String + default = "20000101" + "--dt_cpl" + help = "Coupling time step in seconds [400 (default); allowed formats: \"Nsecs\", \"Nmins\", \"Nhours\", \"Ndays\", \"Inf\"]" + arg_type = String + default = "400secs" + "--dt" + help = "Component model time step [allowed formats: \"Nsecs\", \"Nmins\", \"Nhours\", \"Ndays\", \"Inf\"]" + arg_type = String + default = "400secs" + "--dt_atmos" + help = "Atmos simulation time step (alternative to `dt`; no default) [allowed formats: \"Nsecs\", \"Nmins\", \"Nhours\", \"Ndays\", \"Inf\"]" + arg_type = String + "--dt_land" + help = "Land simulation time step (alternative to `dt`; no default) [allowed formats: \"Nsecs\", \"Nmins\", \"Nhours\", \"Ndays\", \"Inf\"]" + arg_type = String + "--dt_ocean" + help = "Ocean simulation time step (alternative to `dt`; no default) [allowed formats: \"Nsecs\", \"Nmins\", \"Nhours\", \"Ndays\", \"Inf\"]" + arg_type = String + "--dt_seaice" + help = "Sea ice simulation time step (alternative to `dt`; no default) [allowed formats: \"Nsecs\", \"Nmins\", \"Nhours\", \"Ndays\", \"Inf\"]" + arg_type = String + "--dt_save_to_sol" + 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 intervals of 1 hour or multiple hours" + 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 (20 days by default)" + help = "Time interval for hourly checkpointing in hours [480 (default)]" arg_type = Int default = 480 - "--coupler_output_dir" - help = "Directory to save output files. Note that TempestRemap fails if interactive and paths are too long." - arg_type = String - default = "experiments/ClimaEarth/output" + # Restart information "--restart_dir" help = "Directory containing restart files" arg_type = String - default = "unspecified" + default = nothing "--restart_t" - help = "Restart time" + help = "Integer time to use at `t_start` for restarted simulation [0 (default)]" arg_type = Int default = 0 - "--config_file" - help = "A yaml file used to set the configuration of the coupled model" - arg_type = String - "--job_id" - help = "A unique identifier for this run" - arg_type = String - default = nothing - "--print_config_dict" - help = "Boolean flag indicating whether to print the final configuration dictionary" + # Diagnostics information + "--use_coupler_diagnostics" + help = "Boolean flag indicating whether to compute and output coupler diagnostics [`true` (default), `false`]" arg_type = Bool default = true - "--FLOAT_TYPE" - help = "Floating point precision [`Float64` (default), `Float32`]" - arg_type = String - default = "Float64" - "--coupler_toml_file" - help = "A toml file used to overwrite the model parameters. If nothing is specified, the default parameters are used." + # Physical simulation information "--evolving_ocean" - help = "Boolean flag indicating whether to use a dynamic slab ocean model or constant surface temperatures" + help = "Boolean flag indicating whether to use a dynamic slab ocean model, as opposed to constant surface temperatures [`true` (default), `false`]" arg_type = Bool default = true - "--device" - help = "Device type to use [`auto` (default) `CPUSingleThreaded`, `CPUMultiThreaded`, `CUDADevice`]" + "--mono_surface" + help = "Boolean flag indicating whether (1st order) monotone and conservative remapping is applied. [`false` (default), `true`]" + arg_type = Bool + default = false + "--turb_flux_partition" + help = "Method to partition turbulent fluxes. [`PartitionedStateFluxes`, `CombinedStateFluxesMOST` (default)]" arg_type = String - default = "auto" - "--use_coupler_diagnostics" - help = "Boolean flag indicating whether to compute and output coupler diagnostics [`true` (default), `false`]" + default = "CombinedStateFluxesMOST" + # Conservation information + "--energy_check" + help = "Boolean flag indicating whether to check energy conservation [`false` (default), `true`]" arg_type = Bool - default = true - "--unique_seed" - help = "Boolean flag indicating whether to set the random number seed to a unique value [`false` (default), `true`]" + default = false + "--conservation_softfail" + help = "Boolean flag indicating whether to soft fail on conservation errors [`false` (default), `true`]" + arg_type = Bool + default = false + # Output information + "--coupler_output_dir" + help = "Directory to save output files. Note that TempestRemap fails if interactive and paths are too long. [\"experiments/ClimaEarth/output\" (default)]" + arg_type = String + default = "experiments/ClimaEarth/output" + "--plot_diagnostics" + help = "Boolean flag indicating whether to make plot diagnostics [`false` (default), `true`]" arg_type = Bool default = false # ClimaAtmos specific "--surface_setup" - help = "Triggers ClimaAtmos into the coupled mode [`PrescribedSurface` (default)]" # retained here for standalone Atmos benchmarks + help = "Triggers ClimaAtmos into the coupled mode [`PrescribedSurface` (default), `DefaultMoninObukhov`]" # retained here for standalone Atmos benchmarks arg_type = String default = "PrescribedSurface" "--atmos_config_file" - help = "A yaml file used to set the atmospheric model configuration. If nothing is specified, the default configuration is used." + help = "An optional YAML file used to overwrite the default model parameters." "--albedo_model" help = "Type of albedo model. [`ConstantAlbedo`, `RegressionFunctionAlbedo`, `CouplerAlbedo` (default)]" arg_type = String @@ -111,15 +142,19 @@ function argparse_settings() help = "The repository containing the ClimaAtmos configuration file to use [`ClimaAtmos` (default), `ClimaCoupler`]" arg_type = String default = "ClimaAtmos" - # ClimaLand specific - "--land_albedo_type" - help = "Access land surface albedo information from data file. [`map_static` (default), `function`, `map_temporal`]" - arg_type = String - default = "map_static" # to be replaced by land config file, when available + "--extra_atmos_diagnostics" + help = "List of dictionaries containing information about additional atmosphere diagnostics to output [nothing (default)]" + arg_type = Vector{Dict{Any, Any}} + default = [] + ### ClimaLand specific "--land_domain_type" help = "Type of land domain. [`sphere` (default), `single_column`]" arg_type = String default = "sphere" + "--land_albedo_type" + help = "Access land surface albedo information from data file. [`map_static` (default), `function`, `map_temporal`]" + arg_type = String + default = "map_static" # to be replaced by land config file, when available "--land_temperature_anomaly" help = "Type of temperature anomaly for bucket model. [`amip`, `aquaplanet` (default)]" arg_type = String diff --git a/experiments/ClimaEarth/components/atmosphere/climaatmos.jl b/experiments/ClimaEarth/components/atmosphere/climaatmos.jl index 6e60e90daf..cad9f7ec4c 100644 --- a/experiments/ClimaEarth/components/atmosphere/climaatmos.jl +++ b/experiments/ClimaEarth/components/atmosphere/climaatmos.jl @@ -296,10 +296,22 @@ FluxCalculator.get_surface_params(sim::ClimaAtmosSimulation) = CAP.surface_fluxe get_atmos_config_dict(coupler_dict::Dict, job_id::String) Returns the specified atmospheric configuration (`atmos_config`) overwitten by arguments -in the coupler dictionary (`config_dict`). The returned `atmos_config` dictionary will then be passed to CA.AtmosConfig(). -The `atmos_config_repo` flag allows us to -use a configuration specified within the ClimaCoupler repo, which is useful for direct +in the coupler dictionary (`config_dict`). +The returned `atmos_config` dictionary will then be used to set up the atmosphere simulation. + +The `atmos_config_repo` flag allows us to use a configuration specified within +either the ClimaCoupler or ClimaAtmos repos, which is useful for direct coupled/atmos-only comparisons. + +In this function, parameters are overwritten in a specific order, from lowest to highest priority: + 1. Default atmos config + 2. Provided atmos config file (if any) + 3. TOML parameter file + 5. Output directory and timestep are set explicitly based on the coupler config + +The TOML parameter file to use is chosen using the following priority: +If a coupler TOML file is provided, it is used. Otherwise we use an atmos TOML +file if it's provided. If neither is provided, we use a default coupler TOML file. """ function get_atmos_config_dict(coupler_dict::Dict, job_id::String) atmos_config_file = coupler_dict["atmos_config_file"] @@ -344,23 +356,24 @@ function get_atmos_config_dict(coupler_dict::Dict, job_id::String) atmos_config = merge(atmos_config, Dict("toml" => [toml_file])) end - # specify atmos output directory to be inside the coupler output directory + # Specify atmos output directory to be inside the coupler output directory atmos_output_dir = joinpath(coupler_dict["coupler_output_dir"], job_id, "clima_atmos") + atmos_config["output_dir"] = atmos_output_dir + + # Access extra atmosphere diagnostics from coupler so we can rename for atmos code + atmos_config["diagnostics"] = coupler_dict["extra_atmos_diagnostics"] - # merge configs - # (if there are common keys, the last dictionary in the `merge` arguments takes precedence) # The Atmos `get_simulation` function expects the atmos config to contains its timestep size # in the `dt` field. If there is a `dt_atmos` field in coupler_dict, we add it to the atmos config as `dt` dt_atmos = haskey(coupler_dict, "dt_atmos") ? coupler_dict["dt_atmos"] : coupler_dict["dt"] - atmos_config = merge(atmos_config, Dict("output_dir" => atmos_output_dir, "dt" => dt_atmos)) - coupler_config = merge(atmos_config, coupler_dict) + atmos_config["dt"] = dt_atmos # set restart file to the initial file saved in this location if it is not nothing # TODO this is hardcoded and should be fixed once we have a better restart system if !isnothing(atmos_config["restart_file"]) atmos_config["restart_file"] = replace(atmos_config["restart_file"], "active" => "0000") end - return atmos_config, coupler_config + return atmos_config end diff --git a/experiments/ClimaEarth/run_amip.jl b/experiments/ClimaEarth/run_amip.jl index 0265ea0a0d..eb9b6f4a16 100644 --- a/experiments/ClimaEarth/run_amip.jl +++ b/experiments/ClimaEarth/run_amip.jl @@ -38,7 +38,6 @@ We then specify the input data file names. If these are not already downloaded, ## standard packages import Dates -import YAML import DelimitedFiles # ## ClimaESM packages @@ -86,133 +85,58 @@ dictionary and the simulation-specific configuration dictionary, which allows th We can additionally pass the configuration dictionary to the component model initializers, which will then override the default settings of the component models. =# -## coupler simulation default configuration include("cli_options.jl") -parsed_args = parse_commandline(argparse_settings()) - -## modify parsed args for fast testing from REPL #hide -if isinteractive() - parsed_args["config_file"] = - isnothing(parsed_args["config_file"]) ? joinpath(pkg_dir, "config/ci_configs/interactive_debug.yml") : - parsed_args["config_file"] - parsed_args["job_id"] = "interactive_debug" -end - -## the unique job id should be passed in via the command line -job_id = parsed_args["job_id"] -@assert !isnothing(job_id) "job_id must be passed in via the command line" - -## read in config dictionary from file, overriding the coupler defaults in `parsed_args` -config_dict = YAML.load_file(parsed_args["config_file"]) -config_dict = merge(parsed_args, config_dict) +include("user_io/arg_parsing.jl") +config_dict = get_coupler_config() + +# Select the correct timestep for each component model based on which are available +parse_component_dts!(config_dict) +# Add extra diagnostics if specified +add_extra_diagnostics!(config_dict) + +(; + job_id, + mode_name, + random_seed, + FT, + comms_ctx, + t_end, + t_start, + date0, + date, + Δt_cpl, + component_dt_dict, + saveat, + hourly_checkpoint, + hourly_checkpoint_dt, + restart_dir, + restart_t, + use_coupler_diagnostics, + use_land_diagnostics, + calendar_dt, + evolving_ocean, + mono_surface, + turb_flux_partition, + land_domain_type, + land_albedo_type, + land_temperature_anomaly, + energy_check, + conservation_softfail, + output_dir_root, + plot_diagnostics, +) = get_coupler_args(config_dict) -comms_ctx = Utilities.get_comms_context(config_dict) +## get component model dictionaries (if applicable) +## Note this step must come after parsing the coupler config dictionary, since +## some parameters are passed from the coupler config to the component model configs +atmos_config_dict = get_atmos_config_dict(config_dict, job_id) +(; dt_rad, output_default_diagnostics) = get_atmos_args(atmos_config_dict) ## set unique random seed if desired, otherwise use default -random_seed = config_dict["unique_seed"] ? time_ns() : 1234 Random.seed!(random_seed) @info "Random seed set to $(random_seed)" -## set up diagnostics before retrieving atmos config -mode_name = config_dict["mode_name"] -use_coupler_diagnostics = config_dict["use_coupler_diagnostics"] -t_end = Float64(Utilities.time_to_seconds(config_dict["t_end"])) -t_start = 0.0 - -function get_period(t_start, t_end) - sim_duration = t_end - t_start - secs_per_day = 86400 - if sim_duration >= 90 * secs_per_day - # if duration >= 90 days, take monthly means - period = "1months" - calendar_dt = Dates.Month(1) - elseif sim_duration >= 30 * secs_per_day - # if duration >= 30 days, take means over 10 days - period = "10days" - calendar_dt = Dates.Day(10) - elseif sim_duration >= secs_per_day - # if duration >= 1 day, take daily means - period = "1days" - calendar_dt = Dates.Day(1) - else - # if duration < 1 day, take hourly means - period = "1hours" - calendar_dt = Dates.Hour(1) - end - return (period, calendar_dt) -end - -if mode_name == "amip" && use_coupler_diagnostics - @info "Using default AMIP diagnostics" - (period, calendar_dt) = get_period(t_start, t_end) - - !haskey(config_dict, "diagnostics") && (config_dict["diagnostics"] = Vector{Dict{Any, Any}}()) - push!( - config_dict["diagnostics"], - Dict("short_name" => ["toa_fluxes_net"], "reduction_time" => "average", "period" => period), - ) -end - - -## read in some parsed command line arguments, required by this script -energy_check = config_dict["energy_check"] -const FT = config_dict["FLOAT_TYPE"] == "Float64" ? Float64 : Float32 -land_sim_name = "bucket" -t_end = Float64(Utilities.time_to_seconds(config_dict["t_end"])) -t_start = 0.0 tspan = (t_start, t_end) -Δt_cpl = Float64(config_dict["dt_cpl"]) -component_dt_names = ["dt_atmos", "dt_land", "dt_ocean", "dt_seaice"] -component_dt_dict = Dict{String, Float64}() -# check if all component dt's are specified -if all(key -> !isnothing(config_dict[key]), component_dt_names) - # when all component dt's are specified, ignore the dt field - if haskey(config_dict, "dt") - @warn "Removing dt in favor of individual component dt's" - delete!(config_dict, "dt") - end - for key in component_dt_names - component_dt = Float64(Utilities.time_to_seconds(config_dict[key])) - @assert Δ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" - component_dt_dict[key] = component_dt - end -else - # when not all component dt's are specified, use the dt field - @assert haskey(config_dict, "dt") "dt or (dt_atmos, dt_land, dt_ocean, and dt_seaice) must be specified" - for key in component_dt_names - if !isnothing(config_dict[key]) - @warn "Removing $key from config in favor of dt because not all component dt's are specified" - end - delete!(config_dict, key) - component_dt_dict[key] = Float64(Utilities.time_to_seconds(config_dict["dt"])) - end -end -## get component model dictionaries (if applicable) -atmos_config_dict, config_dict = get_atmos_config_dict(config_dict, job_id) -atmos_config_object = CA.AtmosConfig(atmos_config_dict) - -saveat = Float64(Utilities.time_to_seconds(config_dict["dt_save_to_sol"])) -date0 = date = Dates.DateTime(config_dict["start_date"], Dates.dateformat"yyyymmdd") -mono_surface = config_dict["mono_surface"] -hourly_checkpoint = config_dict["hourly_checkpoint"] -hourly_checkpoint_dt = config_dict["hourly_checkpoint_dt"] -restart_dir = config_dict["restart_dir"] -restart_t = Int(config_dict["restart_t"]) -evolving_ocean = config_dict["evolving_ocean"] -dt_rad = config_dict["dt_rad"] -use_land_diagnostics = config_dict["use_land_diagnostics"] - -#= -## Setup Communication Context -We set up communication context for CPU single thread/CPU with MPI/GPU. If no device is passed to `ClimaComms.context()` -then `ClimaComms` automatically selects the device from which this code is called. -=# - - -## make sure we don't use animations for GPU runs -if comms_ctx.device isa ClimaComms.CUDADevice - config_dict["anim"] = false -end #= ### I/O Directory Setup @@ -221,14 +145,11 @@ the plots (from postprocessing and the conservation checks) of the simulation wi temporary files will be saved. =# -COUPLER_OUTPUT_DIR = joinpath(config_dict["coupler_output_dir"], job_id) +COUPLER_OUTPUT_DIR = joinpath(output_dir_root, job_id) dir_paths = Utilities.setup_output_dirs(output_dir = COUPLER_OUTPUT_DIR, comms_ctx = comms_ctx) @info "Coupler output directory $(dir_paths.output)" @info "Coupler artifacts directory $(dir_paths.artifacts)" -@info(dir_paths.output) -config_dict["print_config_dict"] && @info(config_dict) - #= ## Data File Paths =# @@ -264,7 +185,7 @@ This uses the `ClimaAtmos.jl` model, with parameterization options specified in Utilities.show_memory_usage() ## init atmos model component -atmos_sim = atmos_init(atmos_config_object); +atmos_sim = atmos_init(CA.AtmosConfig(atmos_config_dict)); # Get surface elevation from `atmos` coordinate field surface_elevation = CC.Fields.level(CC.Fields.coordinate_field(atmos_sim.integrator.u.f).z, CC.Utilities.half) Utilities.show_memory_usage() @@ -329,9 +250,9 @@ if mode_name == "amip" land_sim = bucket_init( FT, tspan, - config_dict["land_domain_type"], - config_dict["land_albedo_type"], - config_dict["land_temperature_anomaly"], + land_domain_type, + land_albedo_type, + land_temperature_anomaly, dir_paths; dt = component_dt_dict["dt_land"], space = boundary_space, @@ -427,9 +348,9 @@ elseif mode_name in ("slabplanet", "slabplanet_aqua", "slabplanet_terra") land_sim = bucket_init( FT, tspan, - config_dict["land_domain_type"], - config_dict["land_albedo_type"], - config_dict["land_temperature_anomaly"], + land_domain_type, + land_albedo_type, + land_temperature_anomaly, dir_paths; dt = component_dt_dict["dt_land"], space = boundary_space, @@ -477,9 +398,9 @@ elseif mode_name == "slabplanet_eisenman" land_sim = bucket_init( FT, tspan, - config_dict["land_domain_type"], - config_dict["land_albedo_type"], - config_dict["land_temperature_anomaly"], + land_domain_type, + land_albedo_type, + land_temperature_anomaly, dir_paths; dt = component_dt_dict["dt_land"], space = boundary_space, @@ -622,9 +543,9 @@ callbacks = Decide on the type of turbulent flux partition, partitioned or combined (see `FluxCalculator` documentation for more details). =# turbulent_fluxes = nothing -if config_dict["turb_flux_partition"] == "PartitionedStateFluxes" +if turb_flux_partition == "PartitionedStateFluxes" turbulent_fluxes = FluxCalculator.PartitionedStateFluxes() -elseif config_dict["turb_flux_partition"] == "CombinedStateFluxesMOST" +elseif turb_flux_partition == "CombinedStateFluxesMOST" turbulent_fluxes = FluxCalculator.CombinedStateFluxesMOST() else error("turb_flux_partition must be either PartitionedStateFluxes or CombinedStateFluxesMOST") @@ -673,7 +594,7 @@ If a restart directory is specified and contains output files from the `checkpoi is specified in the `config_dict` dictionary. The `restart_t` field specifies the time step at which the restart is performed. =# -if restart_dir !== "unspecified" +if !isnothing(restart_dir) for sim in cs.model_sims if Checkpointer.get_model_prog_state(sim) !== nothing Checkpointer.restart_model_state!(sim, comms_ctx, restart_t; input_dir = restart_dir) @@ -891,7 +812,7 @@ end #= ## Postprocessing All postprocessing is performed using the root process only, if applicable. -Our postprocessing consists of outputting a number of plots and animations to visualize the model output. +Our postprocessing consists of outputting a number of plots to visualize the model output. The postprocessing includes: - Energy and water conservation checks (if running SlabPlanet with checks enabled) @@ -910,14 +831,14 @@ if ClimaComms.iamroot(comms_ctx) plot_global_conservation( cs.conservation_checks.energy, cs, - config_dict["conservation_softfail"], + conservation_softfail, figname1 = joinpath(dir_paths.artifacts, "total_energy_bucket.png"), figname2 = joinpath(dir_paths.artifacts, "total_energy_log_bucket.png"), ) plot_global_conservation( cs.conservation_checks.water, cs, - config_dict["conservation_softfail"], + conservation_softfail, figname1 = joinpath(dir_paths.artifacts, "total_water_bucket.png"), figname2 = joinpath(dir_paths.artifacts, "total_water_log_bucket.png"), ) @@ -930,7 +851,7 @@ if ClimaComms.iamroot(comms_ctx) @info "AMIP plots" ## ClimaESM - include("user_io/ci_plots.jl") + include("user_io/diagnostics_plots.jl") # define variable names and output directories for each diagnostic amip_short_names_atmos = ["ta", "ua", "hus", "clw", "pr", "ts", "toa_fluxes_net"] @@ -939,13 +860,13 @@ if ClimaComms.iamroot(comms_ctx) output_dir_coupler = dir_paths.output # Check if all output variables are available in the specified directories - make_ci_plots( + make_diagnostics_plots( output_dir_atmos, dir_paths.artifacts, short_names = amip_short_names_atmos, output_prefix = "atmos_", ) - make_ci_plots( + make_diagnostics_plots( output_dir_coupler, dir_paths.artifacts, short_names = amip_short_names_coupler, @@ -954,7 +875,7 @@ if ClimaComms.iamroot(comms_ctx) end # Check this because we only want monthly data for making plots - if t_end > 84600 * 31 * 3 && config_dict["output_default_diagnostics"] + if t_end > 84600 * 31 * 3 && output_default_diagnostics include("leaderboard/leaderboard.jl") diagnostics_folder_path = atmos_sim.integrator.p.output_dir leaderboard_base_path = dir_paths.artifacts @@ -962,10 +883,10 @@ if ClimaComms.iamroot(comms_ctx) end end ## plot extra atmosphere diagnostics if specified - if config_dict["ci_plots"] - @info "Generating CI plots" - include("user_io/ci_plots.jl") - make_ci_plots(atmos_sim.integrator.p.output_dir, dir_paths.artifacts) + if plot_diagnostics + @info "Plotting diagnostics" + include("user_io/diagnostics_plots.jl") + make_diagnostics_plots(atmos_sim.integrator.p.output_dir, dir_paths.artifacts) end ## plot all model states and coupler fields (useful for debugging) diff --git a/experiments/ClimaEarth/run_cloudless_aquaplanet.jl b/experiments/ClimaEarth/run_cloudless_aquaplanet.jl index eaa37e206d..b70ca50305 100644 --- a/experiments/ClimaEarth/run_cloudless_aquaplanet.jl +++ b/experiments/ClimaEarth/run_cloudless_aquaplanet.jl @@ -15,7 +15,6 @@ redirect_stderr(IOContext(stderr, :stacktrace_types_limited => Ref(false))) ## standard packages import Dates -import YAML # ## ClimaESM packages import ClimaAtmos as CA @@ -45,7 +44,7 @@ include("components/ocean/slab_ocean.jl") job_id = "cloudless_aquaplanet" coupler_output_dir = "$job_id" const FT = Float64 -restart_dir = "unspecified" +restart_dir = nothing restart_t = Int(0) ## coupler simulation specific configuration @@ -90,7 +89,7 @@ config_dict = Dict( "surface_setup" => "PrescribedSurface", # diagnostic (nested with period and short_name) "output_default_diagnostics" => false, - "diagnostics" => [ + "extra_atmos_diagnostics" => [ Dict( "short_name" => ["mse", "lr", "mass_strf", "stab", "vt", "egr", "ua", "va", "wa", "ta", "rhoa", "pfull"], @@ -110,7 +109,7 @@ config_dict = Dict( ) ## merge dictionaries of command line arguments, coupler dictionary and component model dictionaries -atmos_config_dict, config_dict = get_atmos_config_dict(config_dict, job_id) +atmos_config_dict = get_atmos_config_dict(config_dict, job_id) atmos_config_object = CA.AtmosConfig(atmos_config_dict) #= @@ -262,7 +261,7 @@ cs = Interfacer.CoupledSimulation{FT}( ## Restart component model states if specified in the config_dict =# -if restart_dir !== "unspecified" +if !isnothing(restart_dir) for sim in cs.model_sims if Checkpointer.get_model_prog_state(sim) !== nothing Checkpointer.restart_model_state!(sim, comms_ctx, restart_t; input_dir = restart_dir) diff --git a/experiments/ClimaEarth/run_cloudy_aquaplanet.jl b/experiments/ClimaEarth/run_cloudy_aquaplanet.jl index f01cb7a9d8..49d363d496 100644 --- a/experiments/ClimaEarth/run_cloudy_aquaplanet.jl +++ b/experiments/ClimaEarth/run_cloudy_aquaplanet.jl @@ -14,7 +14,6 @@ redirect_stderr(IOContext(stderr, :stacktrace_types_limited => Ref(false))) ## standard packages import Dates -import YAML # ## ClimaESM packages import ClimaComms @@ -45,7 +44,7 @@ include("components/ocean/slab_ocean.jl") job_id = "cloudy_aquaplanet" coupler_output_dir = "$job_id" const FT = Float64 -restart_dir = "unspecified" +restart_dir = nothing restart_t = Int(0) ## coupler simulation specific configuration @@ -90,7 +89,7 @@ config_dict = Dict( "surface_setup" => "PrescribedSurface", # diagnostic (nested with period and short_name) "output_default_diagnostics" => false, - "diagnostics" => [ + "extra_atmos_diagnostics" => [ Dict( "short_name" => ["mse", "lr", "mass_strf", "stab", "vt", "egr", "ua", "va", "wa", "ta", "rhoa", "pfull"], @@ -123,7 +122,7 @@ config_dict = Dict( ) ## merge dictionaries of command line arguments, coupler dictionary and component model dictionaries -atmos_config_dict, config_dict = get_atmos_config_dict(config_dict, job_id) +atmos_config_dict = get_atmos_config_dict(config_dict, job_id) atmos_config_object = CA.AtmosConfig(atmos_config_dict) ## override default toml parameters @@ -277,7 +276,7 @@ cs = Interfacer.CoupledSimulation{FT}( ## Restart component model states if specified in the config_dict =# -if restart_dir !== "unspecified" +if !isnothing(restart_dir) for sim in cs.model_sims if Checkpointer.get_model_prog_state(sim) !== nothing Checkpointer.restart_model_state!(sim, comms_ctx, restart_t; input_dir = restart_dir) diff --git a/experiments/ClimaEarth/run_cloudy_slabplanet.jl b/experiments/ClimaEarth/run_cloudy_slabplanet.jl index ab3951c26b..1128407b3e 100644 --- a/experiments/ClimaEarth/run_cloudy_slabplanet.jl +++ b/experiments/ClimaEarth/run_cloudy_slabplanet.jl @@ -14,7 +14,6 @@ redirect_stderr(IOContext(stderr, :stacktrace_types_limited => Ref(false))) ## standard packages import Dates -import YAML # ## ClimaESM packages import ClimaComms @@ -50,7 +49,7 @@ include("components/land/climaland_bucket.jl") job_id = "cloudy_slabplanet" coupler_output_dir = "$job_id" const FT = Float64 -restart_dir = "unspecified" +restart_dir = nothing restart_t = Int(0) ## coupler simulation specific configuration @@ -96,7 +95,7 @@ config_dict = Dict( "surface_setup" => "PrescribedSurface", # diagnostic (nested with period and short_name) "output_default_diagnostics" => false, - "diagnostics" => [ + "extra_atmos_diagnostics" => [ Dict( "short_name" => ["mse", "lr", "mass_strf", "stab", "vt", "egr", "ua", "va", "wa", "ta", "rhoa", "pfull"], @@ -127,7 +126,7 @@ config_dict = Dict( ) ## merge dictionaries of command line arguments, coupler dictionary and component model dictionaries -atmos_config_dict, config_dict = get_atmos_config_dict(config_dict, job_id) +atmos_config_dict = get_atmos_config_dict(config_dict, job_id) atmos_config_object = CA.AtmosConfig(atmos_config_dict) # override default toml parameters @@ -328,7 +327,7 @@ cs = Interfacer.CoupledSimulation{FT}( ## Restart component model states if specified in the config_dict =# -if restart_dir !== "unspecified" +if !isnothing(restart_dir) for sim in cs.model_sims if Checkpointer.get_model_prog_state(sim) !== nothing Checkpointer.restart_model_state!(sim, comms_ctx, restart_t; input_dir = restart_dir) diff --git a/experiments/ClimaEarth/run_dry_held_suarez.jl b/experiments/ClimaEarth/run_dry_held_suarez.jl index fcb4080f95..b76b615484 100644 --- a/experiments/ClimaEarth/run_dry_held_suarez.jl +++ b/experiments/ClimaEarth/run_dry_held_suarez.jl @@ -16,7 +16,6 @@ redirect_stderr(IOContext(stderr, :stacktrace_types_limited => Ref(false))) ## standard packages using Dates -import YAML ## ClimaESM packages using ClimaComms @@ -46,7 +45,7 @@ Here we follow ClimaCore's dry Held-Suarez `held_suarez_rhoe` example. job_id = "dry_held_suarez" coupler_output_dir = "$job_id" const FT = Float64 -restart_dir = "unspecified" +restart_dir = nothing restart_t = Int(0) ## coupler simulation specific configuration @@ -89,7 +88,7 @@ config_dict = Dict( "surface_setup" => "PrescribedSurface", # diagnostic (nested with period and short_name) "output_default_diagnostics" => false, - "diagnostics" => [ + "extra_atmos_diagnostics" => [ Dict( "short_name" => ["mse", "lr", "mass_strf", "stab", "vt", "egr", "ua", "va", "wa", "ta", "rhoa", "pfull"], @@ -102,7 +101,7 @@ config_dict = Dict( ) ## merge dictionaries of command line arguments, coupler dictionary and component model dictionaries -atmos_config_dict, config_dict = get_atmos_config_dict(config_dict, job_id) +atmos_config_dict = get_atmos_config_dict(config_dict, job_id) atmos_config_object = CA.AtmosConfig(atmos_config_dict) #= @@ -207,7 +206,7 @@ cs = Interfacer.CoupledSimulation{FT}( ## Restart component model states if specified in the config_dict =# -if restart_dir !== "unspecified" +if !isnothing(restart_dir) for sim in cs.model_sims if get_model_prog_state(sim) !== nothing Checkpointer.restart_model_state!(sim, comms_ctx, restart_t; input_dir = restart_dir) diff --git a/experiments/ClimaEarth/run_moist_held_suarez.jl b/experiments/ClimaEarth/run_moist_held_suarez.jl index 98cc9094b1..7fefba21f8 100644 --- a/experiments/ClimaEarth/run_moist_held_suarez.jl +++ b/experiments/ClimaEarth/run_moist_held_suarez.jl @@ -17,7 +17,6 @@ redirect_stderr(IOContext(stderr, :stacktrace_types_limited => Ref(false))) ## standard packages import Dates -import YAML # ## ClimaESM packages import ClimaComms @@ -48,7 +47,7 @@ Here we follow Thatcher and Jablonowski (2016). job_id = "moist_held_suarez" coupler_output_dir = "$job_id" const FT = Float64 -restart_dir = "unspecified" +restart_dir = nothing restart_t = Int(0) ## coupler simulation specific configuration @@ -92,7 +91,7 @@ config_dict = Dict( "surface_setup" => "PrescribedSurface", # diagnostic (nested with period and short_name) "output_default_diagnostics" => false, - "diagnostics" => [ + "extra_atmos_diagnostics" => [ Dict( "short_name" => ["mse", "lr", "mass_strf", "stab", "vt", "egr", "ua", "va", "wa", "ta", "rhoa", "pfull"], @@ -110,7 +109,7 @@ config_dict = Dict( # TODO: may need to switch to Bulk fluxes ## merge dictionaries of command line arguments, coupler dictionary and component model dictionaries -atmos_config_dict, config_dict = get_atmos_config_dict(config_dict, job_id) +atmos_config_dict = get_atmos_config_dict(config_dict, job_id) atmos_config_object = CA.AtmosConfig(atmos_config_dict) #= @@ -258,7 +257,7 @@ cs = Interfacer.CoupledSimulation{FT}( ## Restart component model states if specified in the config_dict =# -if restart_dir !== "unspecified" +if !isnothing(restart_dir) for sim in cs.model_sims if Checkpointer.get_model_prog_state(sim) !== nothing Checkpointer.restart_model_state!(sim, comms_ctx, restart_t; input_dir = restart_dir) diff --git a/experiments/ClimaEarth/test/amip_test.yml b/experiments/ClimaEarth/test/amip_test.yml index 101a17368d..71dbbc265e 100644 --- a/experiments/ClimaEarth/test/amip_test.yml +++ b/experiments/ClimaEarth/test/amip_test.yml @@ -3,7 +3,7 @@ albedo_model: "CouplerAlbedo" atmos_config_file: "config/longrun_configs/amip_target_diagedmf.yml" coupler_toml_file: "toml/amip.toml" dt: "180secs" -dt_cpl: 180 +dt_cpl: "180secs" dt_save_state_to_disk: "30days" dt_save_to_sol: "30days" dz_bottom: 100.0 diff --git a/experiments/ClimaEarth/user_io/arg_parsing.jl b/experiments/ClimaEarth/user_io/arg_parsing.jl new file mode 100644 index 0000000000..26af20034a --- /dev/null +++ b/experiments/ClimaEarth/user_io/arg_parsing.jl @@ -0,0 +1,272 @@ +import YAML + +""" + get_coupler_config() + +Read in the configuration file and job ID from the command line. +A dictionary is constructed from the input configuration file and returned. + +# Returns +- `config_dict`: A dictionary mapping configuration keys to the specified settings +""" +function get_coupler_config() + # Read in command line arguments + parsed_args = parse_commandline(argparse_settings()) + + # Extract the configuration file and job ID + config_file = parsed_args["config_file"] + job_id = parsed_args["job_id"] + # Get the job ID from the config file string if not provided + job_id = isnothing(job_id) ? string(split(split(config_file, '/')[end], '.')[1]) : job_id + + # Read in config dictionary from file, overriding the defaults in `parsed_args` + config_dict = merge(parsed_args, YAML.load_file(parsed_args["config_file"])) + config_dict["job_id"] = job_id + return config_dict +end + +""" + get_coupler_args(config_dict) + +Extract the necessary arguments from the coupled configuration dictionary. +This function may modify the input dictionary to remove unnecessary keys. + +# Arguments +- `config_dict`: A dictionary mapping configuration keys to the specified settings + +# Returns +- All arguments needed for the coupled simulation +""" +function get_coupler_args(config_dict::Dict) + # Simulation-identifying information; Print `config_dict` if requested + config_dict["print_config_dict"] && @info(config_dict) + job_id = config_dict["job_id"] + mode_name = config_dict["mode_name"] + + # Computational simulation setup information + random_seed = config_dict["unique_seed"] ? time_ns() : 1234 + FT = config_dict["FLOAT_TYPE"] == "Float64" ? Float64 : Float32 + comms_ctx = Utilities.get_comms_context(config_dict) + + # Time information + t_end = Float64(Utilities.time_to_seconds(config_dict["t_end"])) + t_start = Float64(Utilities.time_to_seconds(config_dict["t_start"])) + date0 = date = Dates.DateTime(config_dict["start_date"], Dates.dateformat"yyyymmdd") + Δt_cpl = Float64(Utilities.time_to_seconds(config_dict["dt_cpl"])) + saveat = Float64(Utilities.time_to_seconds(config_dict["dt_save_to_sol"])) + component_dt_dict = config_dict["component_dt_dict"] + + # Checkpointing information + hourly_checkpoint = config_dict["hourly_checkpoint"] + hourly_checkpoint_dt = config_dict["hourly_checkpoint_dt"] + + # Restart information + restart_dir = config_dict["restart_dir"] + restart_t = Int(config_dict["restart_t"]) + + # Diagnostics information + use_coupler_diagnostics = config_dict["use_coupler_diagnostics"] + use_land_diagnostics = config_dict["use_land_diagnostics"] + calendar_dt = config_dict["calendar_dt"] + + # Physical simulation information + evolving_ocean = config_dict["evolving_ocean"] + mono_surface = config_dict["mono_surface"] + turb_flux_partition = config_dict["turb_flux_partition"] + + # Conservation information + energy_check = config_dict["energy_check"] + conservation_softfail = config_dict["conservation_softfail"] + + # Output information + output_dir_root = config_dict["coupler_output_dir"] + plot_diagnostics = config_dict["plot_diagnostics"] + + # ClimaLand-specific information + land_domain_type = config_dict["land_domain_type"] + land_albedo_type = config_dict["land_albedo_type"] + land_temperature_anomaly = config_dict["land_temperature_anomaly"] + use_land_diagnostics = config_dict["use_land_diagnostics"] + + return (; + job_id, + mode_name, + random_seed, + FT, + comms_ctx, + t_end, + t_start, + date0, + date, + Δt_cpl, + component_dt_dict, + saveat, + hourly_checkpoint, + hourly_checkpoint_dt, + restart_dir, + restart_t, + use_coupler_diagnostics, + calendar_dt, + evolving_ocean, + mono_surface, + turb_flux_partition, + energy_check, + conservation_softfail, + output_dir_root, + plot_diagnostics, + land_domain_type, + land_albedo_type, + land_temperature_anomaly, + use_land_diagnostics, + ) +end + +""" + get_atmos_args(atmos_config_dict) + +Extract the necessary arguments from the atmosphere configuration dictionary. + +# Arguments +- `atmos_config_dict`: A dictionary mapping atmosphere configuration keys to the specified settings + +# Returns +- All arguments needed for the atmosphere simulation +""" +function get_atmos_args(atmos_config_dict) + dt_rad = atmos_config_dict["dt_rad"] + output_default_diagnostics = atmos_config_dict["output_default_diagnostics"] + + return (; dt_rad, output_default_diagnostics) +end + + +### Helper functions used in argument parsing ### + +""" + get_diag_period() + +Determine the frequency at which to average and output diagnostics based on the +simulation start and end times. + +The default periods are: +- 1 month for simulations longer than 90 days +- 10 days for simulations longer than 30 days +- 1 day for simulations longer than 1 day +- 1 hour for simulations shorter than 1 day + +# Arguments +- `t_start`: The start time of the simulation +- `t_end`: The end time of the simulation + +# Returns +- `period`: A String of how often to average and output diagnostics +- `calendar_dt`: A DateTime interval representing the period +""" +function get_diag_period(t_start, t_end) + sim_duration = t_end - t_start + secs_per_day = 86400 + if sim_duration >= 90 * secs_per_day + # if duration >= 90 days, take monthly means + period = "1months" + calendar_dt = Dates.Month(1) + elseif sim_duration >= 30 * secs_per_day + # if duration >= 30 days, take means over 10 days + period = "10days" + calendar_dt = Dates.Day(10) + elseif sim_duration >= secs_per_day + # if duration >= 1 day, take daily means + period = "1days" + calendar_dt = Dates.Day(1) + else + # if duration < 1 day, take hourly means + period = "1hours" + calendar_dt = Dates.Hour(1) + end + return (period, calendar_dt) +end + +""" + parse_component_dts!(config_dict) + +Check which timesteps are specified in the config file, and use them to choose +the correct timestep for each component model. +If all component timesteps `dt_\$component` are specified in the config file, use those +and remove `dt` if it was provided. +Otherwise, use the generic component timestep `dt` specified in the config file. +If some (but not all) component timesteps and the generic timestep `dt` are specified, +use the generic timestep and remove the others from the config dict. + +The timestep for each component model is stored in the `component_dt_dict` field of the config dict. + +# Arguments +- `config_dict`: A dictionary mapping configuration keys to the specified settings +""" +function parse_component_dts!(config_dict) + # Retrieve coupling timestep + Δt_cpl = Float64(Utilities.time_to_seconds(config_dict["dt_cpl"])) + + # Specify component model names + component_dt_names = ["dt_atmos", "dt_land", "dt_ocean", "dt_seaice"] + component_dt_dict = Dict{String, Float64}() + # check if all component dt's are specified + if all(key -> !isnothing(config_dict[key]), component_dt_names) + # when all component dt's are specified, ignore the dt field + if haskey(config_dict, "dt") + @warn "Removing dt in favor of individual component dt's" + delete!(config_dict, "dt") + end + for key in component_dt_names + component_dt = Float64(Utilities.time_to_seconds(config_dict[key])) + @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" + component_dt_dict[key] = component_dt + end + else + # when not all component dt's are specified, use the dt field + @assert haskey(config_dict, "dt") "dt or (dt_atmos, dt_land, dt_ocean, and dt_seaice) must be specified" + for key in component_dt_names + if !isnothing(config_dict[key]) + @warn "Removing $key from config in favor of dt because not all component dt's are specified" + end + delete!(config_dict, key) + component_dt_dict[key] = Float64(Utilities.time_to_seconds(config_dict["dt"])) + end + end + config_dict["component_dt_dict"] = component_dt_dict +end + +""" + add_extra_diagnostics!(config_dict) + +Conditionally add extra diagnostics to the config dictionary based on the +simulation type and flag to use diagnostics. Currently, the only extra +diagnostic is the atmosphere TOA net flux for AMIP simulations, but more diagnostics +can be added for any component by following the structure in `climaatmos_extra_diags.jl`. + +The added atmosphere diagnostics are added to the `extra_atmos_diagnostics` field +of the config dict. The `calendar_dt` field is also added to the config dict to +coordinate the output frequency of the diagnostics. + +# Arguments +- `config_dict`: A dictionary mapping configuration keys to the specified settings +""" +function add_extra_diagnostics!(config_dict) + # Diagnostics information + mode_name = config_dict["mode_name"] + use_coupler_diagnostics = config_dict["use_coupler_diagnostics"] + t_end = Float64(Utilities.time_to_seconds(config_dict["t_end"])) + t_start = Float64(Utilities.time_to_seconds(config_dict["t_start"])) + calendar_dt = nothing + if mode_name == "amip" && use_coupler_diagnostics + @info "Using default AMIP diagnostics" + (period, calendar_dt) = get_diag_period(t_start, t_end) + + # Additional atmosphere diagnostics + !haskey(config_dict, "extra_atmos_diagnostics") && + (config_dict["extra_atmos_diagnostics"] = Vector{Dict{Any, Any}}()) + push!( + config_dict["extra_atmos_diagnostics"], + Dict("short_name" => ["toa_fluxes_net"], "reduction_time" => "average", "period" => period), + ) + end + config_dict["calendar_dt"] = calendar_dt +end diff --git a/experiments/ClimaEarth/user_io/ci_plots.jl b/experiments/ClimaEarth/user_io/diagnostics_plots.jl similarity index 96% rename from experiments/ClimaEarth/user_io/ci_plots.jl rename to experiments/ClimaEarth/user_io/diagnostics_plots.jl index 944c49f28a..e0b2ba355b 100644 --- a/experiments/ClimaEarth/user_io/ci_plots.jl +++ b/experiments/ClimaEarth/user_io/diagnostics_plots.jl @@ -144,19 +144,19 @@ function map_comparison(func, simdirs, args) end """ - make_ci_plots( + make_diagnostics_plots( output_path::AbstractString, plot_path::AbstractString; short_names::Vector{<:AbstractString} = ["mse", "lr", "edt", "ts"], reduction::String = "average", output_prefix = "", ) -Create plots for the general CI diagnostics. The plots are saved to `plot_path`. -This is the default plotting function for the CI diagnostics and it can be extended +Create plots for diagnostics. The plots are saved to `plot_path`. +This is the default plotting function for diagnostics and it can be extended to include additional diagnostics. The `reduction` keyword argument should be consistent with the reduction used to save the diagnostics. """ -function make_ci_plots( +function make_diagnostics_plots( output_path::AbstractString, plot_path::AbstractString; short_names::Vector{<:AbstractString} = ["mse", "lr", "edt", "ts"], diff --git a/src/Utilities.jl b/src/Utilities.jl index 13c71a96bf..79c0166ee8 100644 --- a/src/Utilities.jl +++ b/src/Utilities.jl @@ -51,7 +51,14 @@ end """ get_comms_context(config_dict) -Sets up the appropriate ClimaComms context for the device the model is to be run on +Sets up the appropriate ClimaComms context for the device the model is to be run on, +choosing from the following options: + - CPU single threaded + - CPU with MPI + - GPU + +If no device is passed to `ClimaComms.context()` then `ClimaComms` automatically +selects the device from which this code is called. # Arguments `config_dict`: dictionary containing a "device" flag whcih decides which device context is needed