diff --git a/docs/src/fieldexchanger.md b/docs/src/fieldexchanger.md index 6be11ffa0e..eb66d06c12 100644 --- a/docs/src/fieldexchanger.md +++ b/docs/src/fieldexchanger.md @@ -39,6 +39,6 @@ the atmosphere and each surface model. ```@docs ClimaCoupler.FieldExchanger.combine_surfaces! - ClimaCoupler.FieldExchanger.resolve_ocean_ice_fractions! + ClimaCoupler.FieldExchanger.resolve_area_fractions! ClimaCoupler.FieldExchanger.import_atmos_fields! ``` diff --git a/experiments/ClimaEarth/components/ocean/oceananigans.jl b/experiments/ClimaEarth/components/ocean/oceananigans.jl index b665fb981b..9135eea9c0 100644 --- a/experiments/ClimaEarth/components/ocean/oceananigans.jl +++ b/experiments/ClimaEarth/components/ocean/oceananigans.jl @@ -41,7 +41,7 @@ Specific details about the default model configuration can be found in the documentation for `ClimaOcean.ocean_simulation`. """ function OceananigansSimulation( - area_fraction, + boundary_space, start_date, stop_date; output_dir, @@ -138,7 +138,7 @@ function OceananigansSimulation( lat_cc = reshape(lat_cc, 1, length(lat_cc)) target_points_cc = @. CC.Geometry.LatLongPoint(lat_cc, long_cc) # TODO: We can remove the `nothing` after CC > 0.14.33 - remapper_cc = CC.Remapping.Remapper(axes(area_fraction), target_points_cc, nothing) + remapper_cc = CC.Remapping.Remapper(boundary_space, target_points_cc, nothing) # Construct two 2D Center/Center fields to use as scratch space while remapping scratch_cc1 = OC.Field{OC.Center, OC.Center, Nothing}(grid) @@ -176,12 +176,15 @@ function OceananigansSimulation( ocean.output_writers[:diagnostics] = netcdf_writer end + # Create a dummy area fraction that will get overwritten in `update_surface_fractions!` + area_fraction = ones(boundary_space) + sim = OceananigansSimulation(ocean, area_fraction, ocean_properties, remapping) return sim end """ - FieldExchanger.resolve_ocean_ice_fractions!(ocean_sim, ice_sim, land_fraction) + FieldExchanger.resolve_area_fractions!(ocean_sim, ice_sim, land_fraction) Ensure the ocean and ice area fractions are consistent with each other. This matters in the case of a LatitudeLongitudeGrid, which is only @@ -189,7 +192,7 @@ defined between -80 and 80 degrees latitude. In this case, we want to set the ice fraction to `1 - land_fraction` on [-90, -80] and [80, 90] degrees latitude, and make sure the ocean fraction is 0 there. """ -function FieldExchanger.resolve_ocean_ice_fractions!( +function FieldExchanger.resolve_area_fractions!( ocean_sim::OceananigansSimulation, ice_sim, land_fraction, @@ -206,7 +209,8 @@ function FieldExchanger.resolve_ocean_ice_fractions!( polar_mask .= abs.(lat) .>= FT(80) # Set ice fraction to 1 - land_fraction and ocean fraction to 0 where polar_mask is 1 - @. ice_fraction = ifelse.(polar_mask == FT(1), FT(1) - land_fraction, ice_fraction) + @. land_fraction = ifelse.(polar_mask == FT(1), FT(1), land_fraction) + @. ice_fraction = ifelse.(polar_mask == FT(1), FT(0), ice_fraction) @. ocean_fraction = ifelse.(polar_mask == FT(1), FT(0), ocean_fraction) end return nothing diff --git a/experiments/ClimaEarth/components/ocean/prescr_ocean.jl b/experiments/ClimaEarth/components/ocean/prescr_ocean.jl index f207fbfada..bf7b3b32b7 100644 --- a/experiments/ClimaEarth/components/ocean/prescr_ocean.jl +++ b/experiments/ClimaEarth/components/ocean/prescr_ocean.jl @@ -42,7 +42,7 @@ end ::Type{FT}, space, start_date, - area_fraction, + t_start, thermo_params, comms_ctx; z0m = FT(5.8e-5), @@ -65,7 +65,6 @@ function PrescribedOceanSimulation( space, start_date, t_start, - area_fraction, thermo_params, comms_ctx; z0m = FT(5.8e-5), diff --git a/experiments/ClimaEarth/components/ocean/prescr_seaice.jl b/experiments/ClimaEarth/components/ocean/prescr_seaice.jl index ca90e9f851..af180f3bf9 100644 --- a/experiments/ClimaEarth/components/ocean/prescr_seaice.jl +++ b/experiments/ClimaEarth/components/ocean/prescr_seaice.jl @@ -119,12 +119,8 @@ function PrescribedIceSimulation( ) # Get initial SIC values and use them to calculate ice fraction - SIC_init = CC.Fields.zeros(space) - evaluate!(SIC_init, SIC_timevaryinginput, tspan[1]) - - # Overwrite ice fraction with the static land area fraction anywhere we have nonzero land area - # max needed to avoid Float32 errors (see issue #271; Heisenbug on HPC) - ice_fraction = @. max(min(SIC_init, FT(1) - land_fraction), FT(0)) + ice_fraction = CC.Fields.zeros(space) + evaluate!(ice_fraction, SIC_timevaryinginput, tspan[1]) params = IceSlabParameters{FT}() diff --git a/experiments/ClimaEarth/components/ocean/slab_ocean.jl b/experiments/ClimaEarth/components/ocean/slab_ocean.jl index 9db88a0899..5da8a223b7 100644 --- a/experiments/ClimaEarth/components/ocean/slab_ocean.jl +++ b/experiments/ClimaEarth/components/ocean/slab_ocean.jl @@ -65,7 +65,6 @@ function SlabOceanSimulation( dt, saveat, space, - area_fraction, thermo_params, stepper = CTS.RK4(), evolving = true, @@ -80,7 +79,7 @@ function SlabOceanSimulation( F_turb_energy = CC.Fields.zeros(space), SW_d = CC.Fields.zeros(space), LW_d = CC.Fields.zeros(space), - area_fraction = area_fraction, + area_fraction = ones(space), thermo_params = thermo_params, α_direct = CC.Fields.ones(space) .* params.α, α_diffuse = CC.Fields.ones(space) .* params.α, diff --git a/experiments/ClimaEarth/setup_run.jl b/experiments/ClimaEarth/setup_run.jl index abc82c8aa6..a060b88a98 100644 --- a/experiments/ClimaEarth/setup_run.jl +++ b/experiments/ClimaEarth/setup_run.jl @@ -357,14 +357,11 @@ function CoupledSimulation(config_dict::AbstractDict) sic_path = subseasonal_sic, ) - ## ocean model using prescribed data - ice_fraction = Interfacer.get_field(ice_sim, Val(:area_fraction)) - ocean_fraction = FT(1) .- ice_fraction .- land_fraction - + ## ocean model if sim_mode <: CMIPMode stop_date = date(tspan[end] - tspan[begin]) ocean_sim = OceananigansSimulation( - ocean_fraction, + boundary_space, start_date, stop_date; output_dir = dir_paths.ocean_output_dir, @@ -376,7 +373,6 @@ function CoupledSimulation(config_dict::AbstractDict) boundary_space, start_date, t_start, - ocean_fraction, thermo_params, comms_ctx; sst_path = subseasonal_sst, @@ -413,7 +409,6 @@ function CoupledSimulation(config_dict::AbstractDict) dt = component_dt_dict["dt_ocean"], space = boundary_space, saveat = saveat, - area_fraction = (FT(1) .- land_fraction), ## NB: this ocean fraction includes areas covered by sea ice (unlike the one contained in the cs) thermo_params = thermo_params, evolving = evolving_ocean, ) @@ -428,6 +423,7 @@ function CoupledSimulation(config_dict::AbstractDict) =# ## collect component model simulations that have been initialized + @assert (ocean_sim isa SlabOceanSimulation && isnothing(ice_sim)) "SlabOceanSimulation should not be used with sea ice, got $(ice_sim)" model_sims = (; atmos_sim, ice_sim, land_sim, ocean_sim) model_sims = NamedTuple{filter(key -> !isnothing(model_sims[key]), keys(model_sims))}(model_sims) @@ -536,6 +532,7 @@ function CoupledSimulation(config_dict::AbstractDict) =# # 1. Make sure surface model area fractions sum to 1 everywhere. + # Note that ocean and ice fractions are not accurate until after this call. FieldExchanger.update_surface_fractions!(cs) # 2. Import atmospheric and surface fields into the coupler fields, diff --git a/experiments/ClimaEarth/test/component_model_tests/prescr_ocean_tests.jl b/experiments/ClimaEarth/test/component_model_tests/prescr_ocean_tests.jl index e593469fae..ff3a4aacce 100644 --- a/experiments/ClimaEarth/test/component_model_tests/prescr_ocean_tests.jl +++ b/experiments/ClimaEarth/test/component_model_tests/prescr_ocean_tests.jl @@ -33,7 +33,6 @@ end space, start_date, t_start, - area_fraction, thermo_params, comms_ctx, ) diff --git a/src/FieldExchanger.jl b/src/FieldExchanger.jl index 3e16043030..7b81d0f0ec 100644 --- a/src/FieldExchanger.jl +++ b/src/FieldExchanger.jl @@ -16,7 +16,7 @@ export update_sim!, exchange!, set_caches!, update_surface_fractions!, - resolve_ocean_ice_fractions! + resolve_area_fractions! """ update_surface_fractions!(cs::Interfacer.CoupledSimulation) @@ -71,7 +71,7 @@ function update_surface_fractions!(cs::Interfacer.CoupledSimulation) # ensure that ocean and ice fractions are consistent if haskey(cs.model_sims, :ice_sim) - resolve_ocean_ice_fractions!(ocean_sim, cs.model_sims.ice_sim, land_fraction) + resolve_area_fractions!(ocean_sim, cs.model_sims.ice_sim, land_fraction) end else cs.fields.scalar_temp1 .= 0 @@ -84,7 +84,7 @@ function update_surface_fractions!(cs::Interfacer.CoupledSimulation) end """ - resolve_ocean_ice_fractions!(ocean_sim, ice_sim, land_fraction) + resolve_area_fractions!(ocean_sim, ice_sim, land_fraction) Ensure that the ocean and ice fractions are consistent with each other. For most ocean and ice models, this does nothing since the ocean fraction is @@ -92,7 +92,7 @@ defined as `1 - ice_fraction - land_fraction`. However, some models may have additional constraints on the ice and ocean fractions that need to be enforced. This function can be extended for such models. """ -function resolve_ocean_ice_fractions!(ocean_sim, ice_sim, land_fraction) +function resolve_area_fractions!(ocean_sim, ice_sim, land_fraction) return nothing end