From 3c75c5e900ab91f7f1ac44e8ccd93916bc487e59 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Sun, 24 May 2026 07:26:56 +1000 Subject: [PATCH 1/2] pull some changes from #277 --- examples/global_climate_simulation.jl | 5 +- examples/near_global_ocean_simulation.jl | 4 +- examples/one_degree_simulation.jl | 27 +++++----- src/DataWrangling/metadata.jl | 64 +++++++++++++++++------- 4 files changed, 65 insertions(+), 35 deletions(-) diff --git a/examples/global_climate_simulation.jl b/examples/global_climate_simulation.jl index 0f461e63..f29d0cee 100644 --- a/examples/global_climate_simulation.jl +++ b/examples/global_climate_simulation.jl @@ -53,7 +53,7 @@ viscous_closure = Oceananigans.TurbulenceClosures.HorizontalScalarBiharmoni closures = (catke_closure, eddy_closure, viscous_closure) nothing #hide -# The ocean simulation, complete with initial conditions for temperature and salinity from ECCO. +# The ocean simulation, complete with initial conditions for temperature and salinity from ECCO on Jan 1st, 1992. ocean = ocean_simulation(grid; momentum_advection, @@ -63,7 +63,8 @@ ocean = ocean_simulation(grid; ecco_set = MetadataSet(:temperature, :salinity, :sea_ice_thickness, :sea_ice_concentration; - dataset = ECCO4Monthly()) + dataset = ECCO4Monthly(), + date = DateTime(1992, 1, 1)) Oceananigans.set!(ocean.model, ecco_set) # T, S # The sea-ice simulation, complete with initial conditions for sea-ice thickness and sea-ice concentration from ECCO. diff --git a/examples/near_global_ocean_simulation.jl b/examples/near_global_ocean_simulation.jl index 865e078b..37bbbb92 100644 --- a/examples/near_global_ocean_simulation.jl +++ b/examples/near_global_ocean_simulation.jl @@ -82,8 +82,8 @@ ocean = ocean_simulation(grid) ocean.model # We initialize the ocean model with ECCO4 temperature and salinity for January 1, 1992. - -set!(ocean.model, MetadataSet(:temperature, :salinity; dataset=ECCO4Monthly())) +date = DateTime(1992, 1, 1) +set!(ocean.model, MetadataSet(:temperature, :salinity; dataset=ECCO4Monthly(), date)) # ### Prescribed atmosphere and radiation # diff --git a/examples/one_degree_simulation.jl b/examples/one_degree_simulation.jl index 1e50a243..6b9b7774 100644 --- a/examples/one_degree_simulation.jl +++ b/examples/one_degree_simulation.jl @@ -83,28 +83,31 @@ sea_ice = sea_ice_simulation(grid, ocean; advection=tracer_advection) # We initialize the ocean and sea ice models with data from the ECCO state estimate. date = DateTime(1993, 1, 1) -ecco_set = MetadataSet(:temperature, :salinity, - :sea_ice_thickness, :sea_ice_concentration; - dataset = ECCO4Monthly(), date) +ecco_variables = (:temperature, :salinity, :sea_ice_thickness, :sea_ice_concentration) +ecco_set = MetadataSet(ecco_variables; dataset = ECCO4Monthly(), date) # A single MetadataSet drives both components; variables not in # `variable_glossary` for a given model fall through silently. set!(ocean.model, ecco_set) # picks up :temperature, :salinity → T, S set!(sea_ice.model, ecco_set) # picks up :sea_ice_thickness, :sea_ice_concentration → h, ℵ -# ### Atmospheric forcing +# ### JRA55-based atmospheric state, radiation, and land model +# +# We force the simulation with data derived from the JRA55-do atmospheric reanalysis, +# which include the atmospheric state and radiative fluxes, as well as +# land-based freshwater fluxes from rivers and icebergs. +# +# In the radiation component we prescribed a latitude-dependent ocean albedo due to +# Large & Yeager 2009. -# We force the simulation with a JRA55-do atmospheric reanalysis. +land = JRA55PrescribedLand(arch) atmosphere = JRA55PrescribedAtmosphere(arch) -# Use a latitude-dependent ocean albedo (Large & Yeager 2009); keep the -# default ocean emissivity (0.97) and sea-ice surface (albedo 0.7, -# emissivity 1.0). -radiation = JRA55PrescribedRadiation(arch; - ocean_surface = SurfaceRadiationProperties(albedo = LatitudeDependentAlbedo())) -land = JRA55PrescribedLand(arch) -# ### Coupled simulation +ocean_surface = SurfaceRadiationProperties(albedo = LatitudeDependentAlbedo()) +radiation = JRA55PrescribedRadiation(arch; ocean_surface) +# ### Coupled simulation +# # Now we are ready to build the coupled ocean--sea ice model and bring everything # together into a `simulation`. diff --git a/src/DataWrangling/metadata.jl b/src/DataWrangling/metadata.jl index c77ef783..6b6b0282 100644 --- a/src/DataWrangling/metadata.jl +++ b/src/DataWrangling/metadata.jl @@ -301,12 +301,12 @@ end ##### struct MetadataSet{V, D, R, N, F} - names :: N # NTuple{K, Symbol} — verbose dataset variable names - dataset :: V # shared - dates :: D # shared; scalar or AbstractVector - region :: R # shared - dir :: String # shared - filenames :: F # NamedTuple keyed by `names`, one entry per variable + names :: N # NTuple{K, Symbol} — verbose dataset variable names + dataset :: V # shared + dates :: D # shared; scalar or AbstractVector + region :: R # shared + dir :: String # shared + filenames :: F # NamedTuple keyed by `names`, one entry per variable end """ @@ -401,6 +401,8 @@ function MetadataSet(variable_names::Symbol...; return MetadataSet(variable_names, dataset, effective_dates, region, dir, filenames) end +MetadataSet(names::NTuple{<:Any, <:Symbol}; kw...) = MetadataSet(names...; kw...) + # Property access: variables first via filenames lookup, struct fields second. function Base.getproperty(mset::MetadataSet, name::Symbol) if name in fieldnames(MetadataSet) @@ -506,14 +508,40 @@ Only the intersection of `names` and `mset.names` is forwarded. The default `names` is every glossary key — fine for permissive models. Models that throw on unknown kwargs (`HydrostaticFreeSurfaceModel`, `SeaIceModel`) override the 2-argument form to pass a narrower `names`, letting a single -multi-component MetadataSet drive both an ocean and a sea-ice model: - -```julia -mset = MetadataSet(:temperature, :salinity, - :sea_ice_thickness, :sea_ice_concentration; - dataset = ECCO4Monthly(), date = start_date) -set!(ocean.model, mset) # consumes :temperature, :salinity → T, S -set!(sea_ice.model, mset) # consumes :sea_ice_thickness, :sea_ice_concentration → h, ℵ +multi-component MetadataSet drive both an ocean and a sea-ice model. +Each model's override of `set!(model, ::MetadataSet)` filters the same `mset` +down to the variables that model knows how to consume: + +```jldoctest +using NumericalEarth +using Oceananigans +using Statistics +using Dates + +grid = LatitudeLongitudeGrid(size = (60, 30, 5), + longitude = (-180, 180), + latitude = (-60, 60), + z = (-5000, 0), + halo = (7, 7, 7)) + +ocean = ocean_simulation(grid) + +mset = MetadataSet(:temperature, :salinity; + dataset = ECCO4Monthly(), + date = DateTime(1993, 1, 1)) + +# Ocean override routes :temperature → T, :salinity → S; sea-ice vars are +# filtered out. A `set!(sea_ice.model, mset)` call against the same `mset` +# would route :sea_ice_thickness → h, :sea_ice_concentration → ℵ. +set!(ocean.model, mset) + +T = ocean.model.tracers.T +(min = round(minimum(T), digits = 2), + max = round(maximum(T), digits = 2), + mean = round(mean(T), digits = 2)) + +# output +(min = -1.06, max = 21.41, mean = 3.3) ``` """ function Fields.set!(model, mset::MetadataSet, names=keys(variable_glossary)) @@ -528,11 +556,9 @@ end # `set!` looks up kwargs. using Oceananigans.Models.HydrostaticFreeSurfaceModels: HydrostaticFreeSurfaceModel function Fields.set!(model::HydrostaticFreeSurfaceModel, mset::MetadataSet) - short = (propertynames(model.velocities)..., - propertynames(model.tracers)..., - propertynames(model.free_surface)...) - names = Tuple(n for (n, s) in variable_glossary if s in short) - return set!(model, mset, names) + hfsm_short_names = (propertynames(model.velocities)..., propertynames(model.tracers)..., :η) + valid_long_names = Tuple(long_name for (long_name, short_name) in variable_glossary if short_name in hfsm_short_names) + return set!(model, mset, valid_long_names) end # Sea ice: ClimaSeaIce's `set!(::SeaIceModel; h, ℵ)` only accepts these two. From 10d63645f5385a533483ecea46df2fc896c2a087 Mon Sep 17 00:00:00 2001 From: "Navid C. Constantinou" Date: Sun, 24 May 2026 13:55:14 +1000 Subject: [PATCH 2/2] Update make.jl --- docs/make.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/make.jl b/docs/make.jl index dd913052..ab1a35a4 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -42,7 +42,7 @@ examples = [ # Developer examples from docs/src/developers/ directory developer_examples = [ - Example("EarthSystemModel interface", "slab_ocean", false), + # Example("EarthSystemModel interface", "slab_ocean", false), ] # Filter out long-running examples unless NUMERICAL_EARTH_BUILD_ALL_EXAMPLES is set