Skip to content

Add temperature/snow-dependent sea ice albedo#163

Merged
simone-silvestri merged 16 commits into
mainfrom
ss/sea-ice-albedo
May 20, 2026
Merged

Add temperature/snow-dependent sea ice albedo#163
simone-silvestri merged 16 commits into
mainfrom
ss/sea-ice-albedo

Conversation

@simone-silvestri
Copy link
Copy Markdown
Member

@simone-silvestri simone-silvestri commented Apr 15, 2026

Summary

Add a state-dependent sea ice albedo parameterization following the CCSM3 scheme
(Briegleb et al. 2004; Briegleb & Light 2007), replacing the default constant albedo.
The SeaIceAlbedo struct stores references to sea ice model fields and is evaluated
pointwise via stateindex inside the atmosphere--sea-ice flux kernel.

Also adds Adapt.adapt_structure for InterfaceProperties so that nested structs
containing GPU field references (like SeaIceAlbedo) are properly adapted when
passed to GPU kernels.

Algorithm

The broadband albedo is computed in four steps:

1. Temperature-dependent melt reduction

Near the melting point, albedo is reduced to represent implicit melt-pond formation:

fT = clamp((Ts - Tm + ΔT) / ΔT, 0, 1)

αi = αi_cold - Δαi * fT
αs = αs_cold - Δαs * fT

where αi_cold = 0.54, αs_cold = 0.83, Δαi = 0.075, Δαs = 0.10, and ΔT = 1 K.

2. Thin-ice transition to ocean albedo

For ice thinner than h_min = 0.5 m, the bare-ice albedo blends toward ocean albedo αo = 0.06:

fh = clamp(hi / h_min, 0, 1)

αi = αo + (αi - αo) * fh

3. Snow cover blending

Snow depth interpolates between bare-ice and snow albedo, reaching full snow cover at hs_min = 0.02 m:

fs = clamp(hs / hs_min, 0, 1)

4. Final albedo

α = fs * αs + (1 - fs) * αi

Default parameters

Parameter Default Source
Cold ice albedo αi_cold 0.54 0.52 × 0.73 + 0.48 × 0.33 (vis + nir weighted)
Cold snow albedo αs_cold 0.83 0.52 × 0.96 + 0.48 × 0.68
Ice melt reduction Δαi 0.075 Briegleb et al. (2004)
Snow melt reduction Δαs 0.10 Briegleb et al. (2004)
Melting temperature Tm 0 °C
Temperature range ΔT 1 K
Ocean albedo αo 0.06
Min ice thickness h_min 0.5 m
Min snow depth hs_min 0.02 m

Changes

  • New file: sea_ice_albedo.jlSeaIceAlbedo struct, constructor, stateindex, Adapt.adapt_structure
  • InterfaceComputations.jl — export SeaIceAlbedo, include sea_ice_albedo.jl
  • interface_states.jlAdapt.adapt_structure for InterfaceProperties
  • atmosphere_sea_ice_fluxes.jl — evaluate radiation properties via stateindex before the similarity-theory iteration; pass local_interface_properties with scalar albedo/emissivity

References

  • Briegleb, B.P., C.M. Bitz, E.C. Hunke, W.H. Lipscomb, and M.M. Schramm (2004):
    Scientific description of the sea ice component in CCSM3. NCAR Tech Note NCAR/TN-463+STR.
  • Briegleb, B.P. and B. Light (2007): NCAR/TN-472+STR.

Tests

test/test_sea_ice_albedo.jl — 8 test sets:

  • Constructor (Float64/Float32)
  • Nothing snow thickness
  • Cold thick ice, no snow → α = 0.54
  • Cold thick ice, deep snow → α = 0.83
  • Melting ice, no snow → α = 0.465
  • Zero ice → ocean albedo α = 0.06
  • Partial snow cover → weighted blend
  • Adapt.adapt_structure for SeaIceAlbedo and InterfaceProperties

- Bathymetry: minor fix in regrid_bathymetry
- DataWrangling: inpainting and restoring improvements
- Diagnostics: MLD minor update
- EarthSystemModels: simplify time stepping, minor earth_system_model cleanup
- InterfaceComputations: minor refactors in sea_ice_ocean fluxes and heat flux formulations

Note: Ocean simulation refactoring (flux_and_restoring, Oceans.jl, ocean_simulation.jl)
and Diagnostics (interface_fluxes) are handled in PR #155 and #158.
- Bathymetry: minor fix in regrid_bathymetry
- DataWrangling: inpainting and restoring improvements
- Diagnostics: interface flux diagnostics and MLD updates
- Oceans: refactor ocean simulation, extract flux_and_restoring
- EarthSystemModels: simplify time stepping, minor earth_system_model cleanup
- InterfaceComputations: minor refactors in sea_ice_ocean fluxes and heat flux formulations
New type SeaIceAlbedo implementing the CCSM3 albedo parameterization
(Briegleb et al. 2004):
- Broadband albedos: bare ice 0.54, snow-covered 0.83
- Temperature-dependent reduction near melting (implicit melt ponds)
- Thin-ice transition to ocean albedo below 0.5 m
- Snow cover blending (full snow albedo at hs > 0.02 m)
- Handles nothing snow_thickness gracefully

Also evaluates state-dependent albedo to scalar via stateindex at
the top of the atmosphere-sea ice flux kernel, fixing a potential
struct-in-arithmetic bug when the albedo is not a plain number.

Changes to atmosphere_sea_ice_fluxes.jl:
- Evaluate radiation properties (α, ϵ) via stateindex before iteration
- Pass local_interface_properties with scalar values to compute_interface_state
- Add hs (snow thickness) to local_interior_state
- Rename h → hi for ice thickness in interior state

References:
- Briegleb et al. (2004): NCAR Tech Note
- Briegleb & Light (2007): NCAR/TN-472+STR
simone-silvestri and others added 2 commits April 15, 2026 14:31
- Add Adapt.adapt_structure for InterfaceProperties so that
  SeaIceAlbedo Fields are properly adapted for GPU kernels
- Fix get_snow_thickness call to pass grid argument

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
simone-silvestri added a commit that referenced this pull request Apr 15, 2026
Strip out changes that belong to other PRs or branches:
- FluxAndRestoring struct and plumbing (separate PR)
- Bottom drag rework (drag_bulk_velocity, Uᴮ)
- Barotropic potential toggle, clock kwarg, materialize_buoyancy_gradients
- TKE advection change, meridional heat transport deletion
- Bathymetry minimum depth, inpainting NaN fill, restoring extract_field_time_series
- Sea ice albedo (CCSM3 scheme) and Adapt for InterfaceProperties (PR #163)
- ocean_surface_salinity/temperature view change

Keep only snow model integration: snow thermodynamics, snowfall routing,
IceSnowConductiveFlux flux balance, hs in exchanger and interior state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
simone-silvestri and others added 2 commits April 15, 2026 15:12
Strip out changes that belong to other PRs: FluxAndRestoring, bottom drag
rework, barotropic potential toggle, meridional heat transport deletion,
bathymetry/inpainting/restoring changes, NCAR bulk flux includes/exports,
snow-specific h→hi rename and hs additions.

Keep only sea ice albedo: SeaIceAlbedo struct, stateindex evaluation in
atmosphere-sea-ice kernel, Adapt for InterfaceProperties, export/include.

Add test_sea_ice_albedo.jl covering: constructor, cold/melting ice,
thin ice→ocean transition, snow cover blending, nothing snow thickness,
Adapt.adapt_structure for both SeaIceAlbedo and InterfaceProperties.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@simone-silvestri simone-silvestri changed the base branch from ss/patch-1 to main April 15, 2026 13:13
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 15, 2026

Codecov Report

❌ Patch coverage is 81.81818% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/Radiations/sea_ice_albedo.jl 81.81% 4 Missing ⚠️

📢 Thoughts on this report? Let us know!

simone-silvestri added a commit that referenced this pull request May 12, 2026
* Misc cleanups and refactors

- Bathymetry: minor fix in regrid_bathymetry
- DataWrangling: inpainting and restoring improvements
- Diagnostics: MLD minor update
- EarthSystemModels: simplify time stepping, minor earth_system_model cleanup
- InterfaceComputations: minor refactors in sea_ice_ocean fluxes and heat flux formulations

Note: Ocean simulation refactoring (flux_and_restoring, Oceans.jl, ocean_simulation.jl)
and Diagnostics (interface_fluxes) are handled in PR #155 and #158.

* Misc cleanups and refactors

- Bathymetry: minor fix in regrid_bathymetry
- DataWrangling: inpainting and restoring improvements
- Diagnostics: interface flux diagnostics and MLD updates
- Oceans: refactor ocean simulation, extract flux_and_restoring
- EarthSystemModels: simplify time stepping, minor earth_system_model cleanup
- InterfaceComputations: minor refactors in sea_ice_ocean fluxes and heat flux formulations

* Add temperature/snow-dependent sea ice albedo (CCSM3 scheme)

New type SeaIceAlbedo implementing the CCSM3 albedo parameterization
(Briegleb et al. 2004):
- Broadband albedos: bare ice 0.54, snow-covered 0.83
- Temperature-dependent reduction near melting (implicit melt ponds)
- Thin-ice transition to ocean albedo below 0.5 m
- Snow cover blending (full snow albedo at hs > 0.02 m)
- Handles nothing snow_thickness gracefully

Also evaluates state-dependent albedo to scalar via stateindex at
the top of the atmosphere-sea ice flux kernel, fixing a potential
struct-in-arithmetic bug when the albedo is not a plain number.

Changes to atmosphere_sea_ice_fluxes.jl:
- Evaluate radiation properties (α, ϵ) via stateindex before iteration
- Pass local_interface_properties with scalar values to compute_interface_state
- Add hs (snow thickness) to local_interior_state
- Rename h → hi for ice thickness in interior state

References:
- Briegleb et al. (2004): NCAR Tech Note
- Briegleb & Light (2007): NCAR/TN-472+STR

* Add Adapt for InterfaceProperties, fix get_snow_thickness call

- Add Adapt.adapt_structure for InterfaceProperties so that
  SeaIceAlbedo Fields are properly adapted for GPU kernels
- Fix get_snow_thickness call to pass grid argument

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Integrate ClimaSeaIce snow model

Snow support for OMIP simulations:

Sea ice model changes:
- sea_ice_simulation: add with_snow, snow_conductivity, snowfall kwargs
- Update imports for ClimaSeaIce ss/snow-model (SlabThermodynamics,
  sea_ice_slab_thermodynamics, snow_slab_thermodynamics)
- default_ai_temperature dispatches on IceSnowConductiveFlux when snow present
- Add snowfall to net_fluxes (top fluxes NamedTuple)
- Sea ice exchanger state: rename h → hi, add hs (snow thickness)

Surface temperature solve:
- New flux_balance_temperature dispatch for IceSnowConductiveFlux
  using combined resistance R = hs/ks + hi/ki
- Refactored into shared conductive_flux_balance_temperature (DRY)
- ConductiveFlux dispatch updated: Ψi.h → Ψi.hi

Snowfall routing:
- Atmosphere exchanger: add Jˢⁿ field (interpolated snow flux)
- Interpolation kernel: interpolate snow component separately
- Sea ice flux assembly: write Jˢⁿ into top_fluxes.snowfall
- ClimaSeaIce reads model.snowfall during thermodynamic step

Requires ClimaSeaIce >= 0.4.8 (snow-model branch merged).

* Fix PhaseTransitions kwargs for updated ClimaSeaIce API

ice_heat_capacity → heat_capacity, ice_density → density

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix issue 2

* Remove unrelated changes from snow-model-integration PR

Strip out changes that belong to other PRs or branches:
- FluxAndRestoring struct and plumbing (separate PR)
- Bottom drag rework (drag_bulk_velocity, Uᴮ)
- Barotropic potential toggle, clock kwarg, materialize_buoyancy_gradients
- TKE advection change, meridional heat transport deletion
- Bathymetry minimum depth, inpainting NaN fill, restoring extract_field_time_series
- Sea ice albedo (CCSM3 scheme) and Adapt for InterfaceProperties (PR #163)
- ocean_surface_salinity/temperature view change

Keep only snow model integration: snow thermodynamics, snowfall routing,
IceSnowConductiveFlux flux balance, hs in exchanger and interior state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Add unit and integration tests for snow model

Unit tests:
- sea_ice_simulation with/without snow (with_snow kwarg)
- PhaseTransitions API (heat_capacity/density kwargs)
- ComponentExchanger includes hs (ZeroField without snow, Field with snow)
- default_ai_temperature dispatches on ConductiveFlux vs IceSnowConductiveFlux
- net_fluxes includes snowfall
- Thermal resistance: R_snow > R_ice

Integration tests:
- Coupled model without snow (time_step succeeds)
- Coupled model with snow (time_step succeeds)
- Snowfall routing: Jsn in exchanger, snowfall in net fluxes
- Snow insulation: IceSnowConductiveFlux wired with correct conductivities

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Replace arithmetic test with snow insulation integration test

Build two coupled models (bare ice vs ice+snow), time-step both,
verify the snowy surface temperature is warmer due to added thermal
resistance from the snow layer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove redundant coupled-model-without-snow test

Already covered by test_ocean_sea_ice_model.jl.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove unused imports of immersed bottom drag functions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix ConstantField setindex! error in snowfall flux assembly

When with_snow=false, sea_ice.model.snowfall is a ConstantField(0) which
cannot be written to. Always allocate a writable Field for the net snowfall
flux since the kernel writes into it unconditionally.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* correct the snowfall

* just pass a default snow thermodynamics

* Backwards-compatible checkpoint restore for ClimaSeaIce >= 0.4.8

Monkey-patch restore_prognostic_state! for SeaIceModel so that old
checkpoints (saved before snow_thickness was added to the model) can
be restored without error. The snow_thickness field is only restored
if present in the checkpoint state; otherwise it is silently skipped.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Fix snow NaN: PrescribedTemperature for snow top BC + interface temperature dispatch

Two fixes from ss/omip-prototype debugging:

1. default_snow_thermodynamics: pass PrescribedTemperature as the snow
   top heat BC. Without this, ClimaSeaIce runs its own surface temperature
   solve (MeltingConstrainedFluxBalance) that conflicts with NumericalEarth's
   coupled flux solver, producing NaN on the first time step.

2. atmosphere_sea_ice_interface: use snow_thermo.top_surface_temperature
   when snow is present. The atmosphere interacts with the snow surface,
   not the ice-snow interface.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* Remove OMIPSimulations files from snow model PR

These were accidentally included from the omip-prototype branch.
The experiments/ directory belongs in ss/omip-prototype, not here.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* just pass a default snow thermodynamics

* fix reference

* remove with_snow from the tests

* fix the tests

* update breeze

* remove fragile computation of sea ice top temperature

* use the correct source

* correct source for Breeze

* remove source from weakdep

* some fixes

* fix all the tests

* import correct function

* fix more tests

* fix projects to point to correct version of ClimaSeaIce

* fix the snow thingy

* just pass 0

* fix radiation iteration

* remove breeze custom path

* complete merge

* download also land to avoid conflicts

* merge main

* correct the fluxes

* new ClimaSeaIce

* typo

* test fixes

* new climaseaice

* fix snow tests

* Apply suggestion from @simone-silvestri

* Apply suggestion from @simone-silvestri

* Apply suggestion from @simone-silvestri

* Apply suggestion from @simone-silvestri

* Apply suggestion from @simone-silvestri

* small change

* restart CI

* fix veros ocean

* fix radiation for veros

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@simone-silvestri simone-silvestri requested a review from xkykai May 18, 2026 14:53
@simone-silvestri simone-silvestri merged commit 798921e into main May 20, 2026
14 of 16 checks passed
@simone-silvestri simone-silvestri deleted the ss/sea-ice-albedo branch May 20, 2026 09:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants