Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
922a36e
Update Bathymetry.jl
simone-silvestri Jan 31, 2025
cc056e0
add a fill halo
simone-silvestri Feb 13, 2025
788e10a
Merge branch 'main' into ss/bathymetry
simone-silvestri Feb 13, 2025
467566e
Merge branch 'main' into ss/bathymetry
simone-silvestri Feb 14, 2025
7c9578c
Merge branch 'main' into ss/bathymetry
simone-silvestri Feb 15, 2025
f7e9c0d
Merge branch 'main' into ss/bathymetry
simone-silvestri Feb 26, 2025
3bcfa47
Merge remote-tracking branch 'origin/ss/bathymetry' into ss/arctic-si…
simone-silvestri Mar 4, 2025
e175906
starting
simone-silvestri Mar 4, 2025
96aed5b
some changes
simone-silvestri Mar 4, 2025
c89d8f9
start changing stuff
simone-silvestri Mar 4, 2025
b000466
arctic simulation
simone-silvestri Mar 4, 2025
410722c
works
simone-silvestri Mar 4, 2025
5f343d6
let's go
simone-silvestri Mar 4, 2025
6dfa96d
continue
simone-silvestri Mar 4, 2025
76bd832
a default inpainting for ECCO
simone-silvestri Mar 4, 2025
b56a44c
try it out
simone-silvestri Mar 4, 2025
d3e0c54
run it on the GPU
simone-silvestri Mar 4, 2025
9473d7d
churning on
simone-silvestri Mar 4, 2025
08b065e
try it out like this
simone-silvestri Mar 4, 2025
0ebcf53
remove this constant coefficient fluxes
simone-silvestri Mar 4, 2025
2003a46
add fluxes
simone-silvestri Mar 4, 2025
875f008
Merge branch 'ss/arctic-simulation' of github.com:CliMA/ClimaOcean.jl…
simone-silvestri Mar 4, 2025
983565a
a very diffusive ocean
simone-silvestri Mar 4, 2025
30502c7
just push it with the diffusivity
simone-silvestri Mar 4, 2025
a96e105
unfortunately it crashes about 5 minutes
simone-silvestri Mar 4, 2025
5b897af
try with 8mins
simone-silvestri Mar 4, 2025
a512a0c
to change evenutally
simone-silvestri Mar 4, 2025
6735a71
Merge branch 'main' into ss/arctic-simulation
simone-silvestri Mar 5, 2025
72abc67
5 minutes
simone-silvestri Mar 5, 2025
f50146b
Merge branch 'ss/arctic-simulation' of github.com:CliMA/ClimaOcean.jl…
simone-silvestri Mar 5, 2025
cd7cec4
add a momentum equation
simone-silvestri Mar 5, 2025
394dce6
with momentum
simone-silvestri Mar 5, 2025
4fd4a62
add stuff
simone-silvestri Mar 6, 2025
a4848fe
Merge remote-tracking branch 'origin/main' into ss/add-sea-ice-momentum
simone-silvestri Mar 11, 2025
c1a406b
vestigial code
simone-silvestri Mar 11, 2025
d7bfc84
vestigial code
simone-silvestri Mar 11, 2025
cf5dd4f
thermodynamics to ice_thermodynamics
simone-silvestri Mar 11, 2025
83d73e0
try it out
simone-silvestri Mar 11, 2025
ddafd10
woops
simone-silvestri Mar 11, 2025
7395d24
bring simulation up to speed
simone-silvestri Mar 11, 2025
f77da60
also here
simone-silvestri Mar 11, 2025
dd41cce
add a dataset
simone-silvestri Mar 11, 2025
addfdcb
correct similarity fluxes
simone-silvestri Mar 12, 2025
d4325dd
we were not capping!
simone-silvestri Mar 12, 2025
135296a
bugfix
simone-silvestri Mar 12, 2025
7c169f0
remove a mistake
simone-silvestri Mar 12, 2025
b757c78
on gpus
simone-silvestri Mar 12, 2025
d58a7c4
some kernel fusion
simone-silvestri Mar 13, 2025
379884c
Merge remote-tracking branch 'origin/main' into ss/fuse-kernels
simone-silvestri Mar 13, 2025
ceda217
back to how it was
simone-silvestri Mar 13, 2025
020a47a
add this
simone-silvestri Mar 13, 2025
16655a2
Revert "Revert "add a prescribed ocean""
simone-silvestri Mar 13, 2025
1a00396
better like this
simone-silvestri Mar 13, 2025
7e5babd
add a docstring
simone-silvestri Mar 13, 2025
83b1a8a
better comment
simone-silvestri Mar 13, 2025
70e88cf
Merge remote-tracking branch 'origin/ss/add-a-prescribed-ocean' into …
simone-silvestri Mar 13, 2025
06db8a3
arctic single column model
simone-silvestri Mar 13, 2025
d9131bb
start now
simone-silvestri Mar 13, 2025
2550442
start with this...
simone-silvestri Mar 13, 2025
45d2191
back how it was for the moment
simone-silvestri Mar 13, 2025
9eff489
see how it goes
simone-silvestri Mar 13, 2025
f1c8bde
just add this for the moment
simone-silvestri Mar 13, 2025
e1ae304
we need a looot of iterations for the moment
simone-silvestri Mar 13, 2025
af3a2e7
try it like this
simone-silvestri Mar 13, 2025
e89e9f6
small change
simone-silvestri Mar 13, 2025
bc74c08
bugfix
simone-silvestri Mar 13, 2025
57508b3
back to gpu
simone-silvestri Mar 13, 2025
84fb734
Merge remote-tracking branch 'origin/main' into ss/single-column-sea-ice
simone-silvestri Mar 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion experiments/arctic_simulation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ dynamics = SeaIceMomentumEquation(grid;
rheology = ElastoViscoPlasticRheology(),
solver = SplitExplicitSolver(120))

sea_ice = sea_ice_simulation(grid; bottom_heat_boundary_condition, dynamics, advection=WENO(order=7))
sea_ice = sea_ice_simulation(grid; bottom_heat_boundary_condition) #, dynamics, advection=WENO(order=7))

set!(sea_ice.model, h=Metadata(:sea_ice_thickness; dataset),
ℵ=Metadata(:sea_ice_concentration; dataset))
Expand Down
55 changes: 0 additions & 55 deletions experiments/flux_climatology/flux_climatology.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,32 +115,6 @@ end
##### A prescribed ocean...
#####

struct PrescribedOcean{A, G, C, U, T, F} <: AbstractModel{Nothing}
architecture :: A
grid :: G
clock :: Clock{C}
velocities :: U
tracers :: T
timeseries :: F
end

function PrescribedOcean(timeseries;
grid,
clock=Clock{Float64}(time = 0))

τx = Field{Face, Center, Nothing}(grid)
τy = Field{Center, Face, Nothing}(grid)
Jᵀ = Field{Center, Center, Nothing}(grid)
Jˢ = Field{Center, Center, Nothing}(grid)

u = XFaceField(grid, boundary_conditions=FieldBoundaryConditions(grid, (Face, Center, Center), top = FluxBoundaryCondition(τx)))
v = YFaceField(grid, boundary_conditions=FieldBoundaryConditions(grid, (Center, Face, Center), top = FluxBoundaryCondition(τy)))
T = CenterField(grid, boundary_conditions=FieldBoundaryConditions(grid, (Center, Center, Center), top = FluxBoundaryCondition(Jᵀ)))
S = CenterField(grid, boundary_conditions=FieldBoundaryConditions(grid, (Center, Center, Center), top = FluxBoundaryCondition(Jˢ)))

PrescribedOcean(architecture(grid), grid, clock, (; u, v, w=ZeroField()), (; T, S), timeseries)
end

# ...with prescribed velocity and tracer fields
version = ECCO4Monthly()
dates = all_ECCO_dates(version)[1:24]
Expand All @@ -157,35 +131,6 @@ grid = ECCO.ECCO_immersed_grid(arch)
ocean_model = PrescribedOcean((; u, v, T, S); grid)
ocean = Simulation(ocean_model, Δt=3hour, stop_time=365days)

#####
##### Need to extend a couple of methods
#####

function time_step!(model::PrescribedOcean, Δt; callbacks=[], euler=true)
tick!(model.clock, Δt)
time = Time(model.clock.time)

possible_fts = merge(model.velocities, model.tracers)
time_series_tuple = extract_field_time_series(possible_fts)

for fts in time_series_tuple
update_field_time_series!(fts, time)
end

parent(model.velocities.u) .= parent(model.timeseries.u[time])
parent(model.velocities.v) .= parent(model.timeseries.v[time])
parent(model.tracers.T) .= parent(model.timeseries.T[time])
parent(model.tracers.S) .= parent(model.timeseries.S[time])

return nothing
end

update_state!(::PrescribedOcean) = nothing
timestepper(::PrescribedOcean) = nothing

reference_density(ocean::Simulation{<:PrescribedOcean}) = 1025.6
heat_capacity(ocean::Simulation{<:PrescribedOcean}) = 3995.6

#####
##### A prescribed atmosphere...
#####
Expand Down
114 changes: 114 additions & 0 deletions experiments/single_column_sea_ice.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
using ClimaOcean
using ClimaSeaIce
using Oceananigans
using Oceananigans.Grids
using Oceananigans.Units
using ClimaOcean.OceanSimulations
using ClimaOcean.ECCO
using ClimaOcean.DataWrangling
using ClimaSeaIce.SeaIceThermodynamics: IceWaterThermalEquilibrium
using Printf

# A single column grid with one point in the Arctic ocean
grid = LatitudeLongitudeGrid(size = 1,
latitude = 87.0,
longitude = 33.0,
z = (-10, 0),
topology = (Flat, Flat, Bounded))

#####
##### A Prescribed Ocean model
#####

dataset = ECCO4Monthly()
dates = all_dates(dataset)[1:24]

T = ECCOFieldTimeSeries(:temperature, grid; dates, inpainting=nothing, time_indices_in_memory=24)
S = ECCOFieldTimeSeries(:salinity, grid; dates, inpainting=nothing, time_indices_in_memory=24)

ocean_model = PrescribedOceanModel((; T, S); grid)
ocean = Simulation(ocean_model, Δt=30minutes, stop_time=730days)

#####
##### A Prescribed Atmosphere model
#####

atmosphere = JRA55PrescribedAtmosphere(latitude = 87.0,
longitude = 33.0,
backend = InMemory())

#####
##### A Prognostic Sea-ice model with no dynamics
#####

# Remember to pass the SSS as a bottom bc to the sea ice!
SSS = view(ocean.model.tracers.S, :, :, 1)
bottom_heat_boundary_condition = IceWaterThermalEquilibrium(SSS)

sea_ice = sea_ice_simulation(grid; bottom_heat_boundary_condition)

set!(sea_ice.model, h=Metadata(:sea_ice_thickness; dataset, dates=first(dates)),
ℵ=Metadata(:sea_ice_concentration; dataset, dates=first(dates)))

#####
##### Radiation of the Ocean and the Sea ice
#####

# to mimick snow, as in Semtner (1975) we use a sea ice albedo that is 0.64 for top temperatures
# above -0.1 ᵒC and 0.75 for top temperatures below -0.1 ᵒC. We also disable radiation for the ocean.
radiation = Radiation(sea_ice_albedo=0.7, ocean_albedo=1, ocean_emissivity=0)

#####
##### Arctic coupled model
#####

arctic = OceanSeaIceModel(ocean, sea_ice; atmosphere, radiation)
arctic = Simulation(arctic, Δt=30minutes, stop_time=730days)

# Sea-ice variables
h = sea_ice.model.ice_thickness
ℵ = sea_ice.model.ice_concentration

# Fluxes
Tu = arctic.model.interfaces.atmosphere_sea_ice_interface.temperature
Qˡ = arctic.model.interfaces.atmosphere_sea_ice_interface.fluxes.latent_heat
Qˢ = arctic.model.interfaces.atmosphere_sea_ice_interface.fluxes.sensible_heat
Qⁱ = arctic.model.interfaces.sea_ice_ocean_interface.fluxes.interface_heat
Qᶠ = arctic.model.interfaces.sea_ice_ocean_interface.fluxes.frazil_heat
Qᵗ = arctic.model.interfaces.net_fluxes.sea_ice_top.heat
Qᴮ = arctic.model.interfaces.net_fluxes.sea_ice_bottom.heat

# Output writers
arctic.output_writers[:vars] = JLD2OutputWriter(sea_ice.model, (; h, ℵ, Tu, Qˡ, Qˢ, Qⁱ, Qᶠ, Qᵗ, Qᴮ),
filename = "sea_ice_quantities.jld2",
schedule = IterationInterval(12),
overwrite_existing=true)

wall_time = Ref(time_ns())

using Statistics

function progress(sim)
sea_ice = sim.model.sea_ice
h = first(sea_ice.model.ice_thickness)
ℵ = first(sea_ice.model.ice_concentration)
T = first(sim.model.interfaces.atmosphere_sea_ice_interface.temperature)

step_time = 1e-9 * (time_ns() - wall_time[])

msg1 = @sprintf("time: %s, iteration: %d, Δt: %s, ", prettytime(sim), iteration(sim), prettytime(sim.Δt))
msg2 = @sprintf("h: %.2e m, ℵ: %.2e , T: %.2e ᴼC", h, ℵ, T)
msg3 = @sprintf("wall time: %s \n", prettytime(step_time))

@info msg1 * msg2 * msg3

wall_time[] = time_ns()
return nothing
end

# And add it as a callback to the simulation.
add_callback!(arctic, progress, IterationInterval(10))

run!(arctic)

h = FieldTimeSeries("sea_ice_quantities.jld2", "h")
10 changes: 10 additions & 0 deletions src/ClimaOcean.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ using DataDeps
using Oceananigans.OutputReaders: GPUAdaptedFieldTimeSeries, FieldTimeSeries
using Oceananigans.Grids: node

# Does not really matter if there is no model
reference_density(::Nothing) = 0
heat_capacity(::Nothing) = 0

reference_density(unsupported) =
throw(ArgumentError("Cannot extract reference density from $(typeof(unsupported))"))

heat_capacity(unsupported) =
throw(ArgumentError("Cannot deduce the heat capacity from $(typeof(unsupported))"))

const SomeKindOfFieldTimeSeries = Union{FieldTimeSeries,
GPUAdaptedFieldTimeSeries}

Expand Down
5 changes: 2 additions & 3 deletions src/DataWrangling/ECCO/ECCO_restoring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -138,15 +138,14 @@ function ECCOFieldTimeSeries(metadata::ECCOMetadata, grid::AbstractGrid;
return fts
end

function ECCOFieldTimeSeries(variable_name::Symbol;
function ECCOFieldTimeSeries(variable_name::Symbol, arch_or_grid=CPU();
dataset = ECCO4Monthly(),
architecture = CPU(),
dates = all_dates(dataset, variable_name),
dir = download_ECCO_cache,
kw...)

metadata = Metadata(variable_name, dates, dataset, dir)
return ECCOFieldTimeSeries(metadata, architecture; kw...)
return ECCOFieldTimeSeries(metadata, arch_or_grid; kw...)
end

# Variable names for restorable data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ function compute_net_sea_ice_fluxes!(coupled_model)
kernel_parameters = interface_kernel_parameters(grid)

sea_ice_surface_temperature = coupled_model.interfaces.atmosphere_sea_ice_interface.temperature
ice_concentration = sea_ice_concentration(sea_ice)

launch!(arch, grid, kernel_parameters,
_assemble_net_sea_ice_fluxes!,
Expand All @@ -186,6 +187,7 @@ function compute_net_sea_ice_fluxes!(coupled_model)
freshwater_flux,
sea_ice_surface_temperature,
downwelling_radiation,
ice_concentration,
sea_ice_properties,
atmos_sea_ice_properties)

Expand All @@ -201,6 +203,7 @@ end
freshwater_flux, # Where do we add this one?
surface_temperature,
downwelling_radiation,
ice_concentration,
sea_ice_properties,
atmos_sea_ice_properties)

Expand All @@ -211,13 +214,13 @@ end
@inbounds begin
Ts = surface_temperature[i, j, kᴺ]
Ts = convert_to_kelvin(sea_ice_properties.temperature_units, Ts)

ℵi = ice_concentration[i, j, 1]
Qs = downwelling_radiation.Qs[i, j, 1]
Qℓ = downwelling_radiation.Qℓ[i, j, 1]
Qc = atmosphere_sea_ice_fluxes.sensible_heat[i, j, 1] # sensible or "conductive" heat flux
Qv = atmosphere_sea_ice_fluxes.latent_heat[i, j, 1] # latent heat flux
Qf = sea_ice_ocean_fluxes.frazil_heat[i, j, 1] # frazil heat flux
Qi = sea_ice_ocean_fluxes.interface_heat[i, j, 1] # interfacial heat flux
Qi = sea_ice_ocean_fluxes.interface_heat[i, j, 1] # interfacial heat flux
end

ρτx = atmosphere_sea_ice_fluxes.x_momentum # zonal momentum flux
Expand All @@ -230,8 +233,8 @@ end
Qu = upwelling_radiation(Ts, σ, ϵ)
Qd = net_downwelling_radiation(i, j, grid, time, α, ϵ, Qs, Qℓ)

ΣQt = Qd + Qu + Qc + Qv
ΣQb = Qf + Qi
ΣQt = (Qd + Qu + Qc + Qv) * ℵi # We need to multiply these times the concentration?
ΣQb = Qf + Qi

# Mask fluxes over land for convenience
inactive = inactive_node(i, j, kᴺ, grid, c, c, c)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Oceananigans.Operators: intrinsic_vector
using Oceananigans.Grids: inactive_node
using ClimaOcean.OceanSimulations
using ClimaOcean.OceanSeaIceModels.PrescribedAtmospheres: thermodynamics_parameters,
surface_layer_height,
boundary_layer_height
Expand Down Expand Up @@ -70,7 +71,6 @@ end

i, j = @index(Global, NTuple)
kᴺ = size(grid, 3) # index of the top ocean cell
time = Time(clock.time)

@inbounds begin
uₐ = atmosphere_state.u[i, j, 1]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ end
h_bℓ = atmosphere_state.h_bℓ)

downwelling_radiation = (; Qs, Qℓ)
local_interior_state = (u=uᵢ, v=vᵢ, T=Tᵢ, S=Sᵢ, h=hᵢ)
local_interior_state = (u=uᵢ, v=vᵢ, T=Tᵢ, S=Sᵢ, h=hᵢ, ℵ=ℵᵢ)

# Estimate initial interface state
u★ = convert(FT, 1e-4)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ function default_ao_specific_humidity(ocean)
end

"""
ComponentInterfaces(atmosphere, ocean, sea_ice=nothing;
ComponentInterfaces(atmosphere, ocean, sea_ice;
radiation = Radiation(),
freshwater_density = 1000,
atmosphere_ocean_flux_formulation = SimilarityTheoryFluxes(),
Expand All @@ -262,11 +262,11 @@ end
sea_ice_reference_density = reference_density(sea_ice),
sea_ice_heat_capacity = heat_capacity(sea_ice))
"""
function ComponentInterfaces(atmosphere, ocean, sea_ice=nothing;
function ComponentInterfaces(atmosphere, ocean, sea_ice;
radiation = Radiation(),
freshwater_density = 1000,
atmosphere_ocean_flux_formulation = SimilarityTheoryFluxes(eltype(ocean.model.grid)),
atmosphere_sea_ice_flux_formulation = SimilarityTheoryFluxes(eltype(ocean.model.grid)),
atmosphere_sea_ice_flux_formulation = SimilarityTheoryFluxes(eltype(ocean.model.grid), solver_maxiter=10000, stability_functions=atmosphere_sea_ice_stability_functions()),
atmosphere_ocean_interface_temperature = BulkTemperature(),
atmosphere_ocean_velocity_difference = RelativeVelocity(),
atmosphere_ocean_interface_specific_humidity = default_ao_specific_humidity(ocean),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,20 +212,21 @@ end
F = st.internal_flux
k = F.conductivity
h = Ψᵢ.h
ℵ = Ψᵢ.ℵ

# Bottom temperature at the melting temperature
Tᵢ = ClimaSeaIce.SeaIceThermodynamics.melting_temperature(ℙᵢ.liquidus, Ψᵢ.S)
Tᵢ = convert_to_kelvin(ℙᵢ.temperature_units, Tᵢ)
Tₛ⁻ = Ψₛ.T

#=
σ = ℙₛ.radiation.σ
ϵ = ℙₛ.radiation.ϵ
α = σ * ϵ
Tₛ = (Tᵢ - h / k * (Qₐ + 4α * Tₛ⁻^4)) / (1 + 4α * h * Tₛ⁻^3 / k)
=#

T★ = Tᵢ - Qₐ * h / k
T★ = Tᵢ - Qₐ * h / k * ℵ # We need to multiply the flux by the concentration?

# Fix a NaN
T★ = ifelse(isnan(T★), Tₛ⁻, T★)
Expand Down
2 changes: 1 addition & 1 deletion src/OceanSeaIceModels/InterfaceComputations/radiation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function Base.show(io::IO, r::Radiation)
print(io, "├── stefan_boltzmann_constant: ", prettysummary(σ), '\n')
print(io, "├── emission: ", summary(r.emission), '\n')
print(io, "│ ├── ocean: ", prettysummary(r.emission.ocean), '\n')
print(io, "│ └── sea_ice: ", prettysummary(r.emission.ocean), '\n')
print(io, "│ └── sea_ice: ", prettysummary(r.emission.sea_ice), '\n')
print(io, "└── reflection: ", summary(r.reflection), '\n')
print(io, " ├── ocean: ", prettysummary(r.reflection.ocean), '\n')
print(io, " └── sea_ice: ", prettysummary(r.reflection.sea_ice))
Expand Down
5 changes: 2 additions & 3 deletions src/OceanSeaIceModels/OceanSeaIceModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@ using ClimaSeaIce: SeaIceModel
using ClimaSeaIce.SeaIceThermodynamics: melting_temperature

using ClimaOcean: stateindex

using KernelAbstractions: @kernel, @index
using KernelAbstractions.Extras.LoopInfo: @unroll

import ClimaOcean: reference_density, heat_capacity

function downwelling_radiation end
function freshwater_flux end
function reference_density end
function heat_capacity end

const default_gravitational_acceleration = 9.80665
const default_freshwater_density = 1000
Expand Down
Loading