Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ec56559
port forcing tendencies (thickness and tracers) + update doc, yml
alicebarthel Jun 19, 2026
4956cf8
added the enthalpy of mass fluxes; CtFrz has public interface
alicebarthel Jun 26, 2026
72f00b3
added a test for thermo forcing tendencies
alicebarthel Jun 26, 2026
45c792f
made mass enthalpy flux dependent on thickness flag - under discussion
alicebarthel Jun 26, 2026
36c9a37
draft a non-teos10 CtFrz in comments - WIP
alicebarthel Jun 26, 2026
9b87769
updated the documentation
alicebarthel Jun 26, 2026
fae5a4a
Revert "made mass enthalpy flux dependent on thickness flag - under d…
alicebarthel Jul 6, 2026
90f045e
updated the documentation
alicebarthel Jul 6, 2026
1226b96
correction to pressure units and ctest
alicebarthel Jul 6, 2026
db218ac
update due to fill values and review comments
alicebarthel Jul 13, 2026
965b549
resolve memory issue on GPUs
alicebarthel Jul 13, 2026
554a9ff
inlines eos::calcPtFromCt in header with kokkos_function to fix gpu w…
katsmith133 Jul 16, 2026
0fd8e35
adds linear and constant eos options to thermal forcing
katsmith133 Jul 20, 2026
b5c586f
adds notes to docs and adds suggestions from review
katsmith133 Jul 20, 2026
a739dfc
Adds reset of forcing fields if not in stream
vanroekel Jul 21, 2026
14065fc
Update components/omega/doc/devGuide/Forcing.md
cbegeman Jul 22, 2026
fded0f4
Fixup documentation
cbegeman Jul 23, 2026
9fa07ce
remove SurfInsituTemp calcs
Jul 23, 2026
5bed059
fixes GPU failures on frontier
Jul 24, 2026
0864050
Revert "fixes GPU failures on frontier"
katsmith133 Jul 28, 2026
b35ff14
fixed GPU isssues on Frontier
katsmith133 Jul 30, 2026
c561101
fixes omega_pr errors on Frontier
katsmith133 Jul 31, 2026
e799907
changes assumptions about enthalpy calculation, per PR review comments
katsmith133 Aug 12, 2026
5772ba3
added limiter and Evap Enthalpy to TendencyTerms
alicebarthel Aug 17, 2026
d1212bc
renamed latent to specify evap and updated the docs
alicebarthel Aug 17, 2026
85cff87
added missing arguments
alicebarthel Aug 17, 2026
808185a
adds non-teos option to limiter
katsmith133 Aug 17, 2026
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: 2 additions & 0 deletions components/omega/configs/Default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ Omega:
Mode: Implicit
Type: Constant
BottomDragCoeff: 1.0e-3
SfcThicknessForcingTendencyEnable: false
SfcTracerForcingTendencyEnable: false
TracerHorzAdvTendencyEnable: true
TracerDiffTendencyEnable: true
EddyDiff2: 10.0
Expand Down
67 changes: 66 additions & 1 deletion components/omega/doc/devGuide/Forcing.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ This page describes design and implementation details for forcing-related
pathways in Omega, currently this includes:

- Surface stress forcing (e.g. wind stress)
- Surface tracer restoring
- Surface thickness and tracer flux forcing (actively coupled or data-forced)
- Surface tracer restoring (soon to be ported as a field originating from the coupler)

## Surface stress forcing design

Expand Down Expand Up @@ -37,6 +38,70 @@ pathways in Omega, currently this includes:
- `Omega.Tendencies.SfcStressForcingTendencyEnable`
- gates execution of surface stress forcing tendency kernel

## Surface thickness and tracer flux forcing design

### Surface thickness and tracer flux forcing data flow

**Thickness equation pathway:**

1. External fields provide freshwater and salt flux components:
- `SnowFlux`, `RainFlux`, `EvaporationFlux`
- `SeaIceFreshWaterFlux`, `IceRunoffFlux`, `RiverRunoffFlux`
- `SeaIceSaltFlux`
2. `Forcing` stores the flux fields in `TracerForcingVars`
3. The tendency term `SfcThicknessForcingOnCell` sums the freshwater and salt mass fluxes and applies them to
the surface layer pseudo-thickness.

**Tracer equation pathway:**

1. External fields provide heat and salt flux components:
- `LatentHeatFluxEvap`, `SensibleHeatFlux`
- `LongWaveHeatFluxUp`, `LongWaveHeatFluxDown`
- `SeaIceHeatFlux`, `ShortWaveHeatFlux`
- mass fluxes which add energy changes (`SnowFlux`, `RainFlux`, `IceRunoffFlux`, `RiverRunoffFlux`)
- `SeaIceSaltFlux`
2. `Forcing` stores the flux fields in `TracerForcingVars`
3. The tendency term `SfcTracerForcingOnCell` converts the summed external heat fluxes to a conservative-temperature tendency,
and applies the external sea-ice salt flux to the top layer salt content thus impacting salinity.

### Surface thickness and tracer flux forcing key classes/components

- `TracerForcingVars`
- Stores 13 coupled flux cell-centered fields: 6 freshwater fluxes, 6 heat
fluxes, and 1 salt flux component
- Fields initialized to zero and registered in `Forcing` field group
- `SfcThicknessForcingOnCell` tendency term
- Computes the layer mass contribution (converted to pseudo-thickness): $\sum (\text{SnowFlux} + \text{RainFlux} + \text{EvaporationFlux} + \text{SeaIceFreshWaterFlux} + \text{IceRunoffFlux} + \text{RiverRunoffFlux} + \text{SeaIceSaltFlux}) / \rho_{sw}$
- Applied only at surface layer (top active layer) using `MinLayerCell`
Comment thread
cbegeman marked this conversation as resolved.
Comment thread
cbegeman marked this conversation as resolved.
- `SfcTracerForcingOnCell` tendency term
- For temperature: adds the direct heat fluxes
Q_{\text{sensible}} + Q_{\text{lw,up}} + Q_{\text{lw,down}} + Q_{\text{sw}}$,
the enthalpy flux from sea-ice interactions (conduction, phase-change and enthalpy of mass flux) Q_{\text{ice}}, the enthalpy of added freshwater mass $(\text{RainFlux} + \text{RiverRunoffFlux}) c^0_{p,sw} max(C_T(0,0,0),C_T^{\text{top}})$ (freshwater $T >= 0$), the evaporation terms ($Q_{\text{latentEvap}} + EvapFlux c^0_{p,sw} C_T^{\text{top}})
, the enthalpy change for frozen mass $(\text{SnowFlux} + \text{IceRunoffFlux}) PotEnthalpyIce$, where PotEnthalpyIce is the potential enthalpy of solid ice (which includes phase change and enthalpy of the melted mass). To first order, $PotEnthalpyIce$ is approximated by $-LatIce$, the engineering handbook value, neglecting 0.1%.
These potential enthalpy terms are then scaled by $H_{\text{FluxFac}}$ to provide the layer tracer tendency.
- For salinity: applies the mass salt flux with the appropriate unit conversion: $\text{SeaIceSaltFlux} \times S_{\text{FluxFac}}$
- Applied only at surface layer using `MinLayerCell`
- Uses tracer index validation to apply to specific tracers only
- `Forcing`
- Manages `TracerForcingVars` instance
- `Tendencies`
- Calls `SfcThicknessForcingOnCell` in `computePseudoThicknessTendenciesOnly`
- Calls `SfcTracerForcingOnCell` in `computeTracerTendenciesOnly` after surface tracer restoring

### Surface thickness and tracer flux forcing config coupling

- `Omega.Tendencies.SfcThicknessForcingTendencyEnable`
- gates execution of coupled flux thickness kernel
- controls freshwater and salt flux forcing on sea surface height
- `Omega.Tendencies.SfcTracerForcingTendencyEnable`
- gates execution of coupled flux tracer kernel
- controls direct heat flux forcing on temperature and salt flux forcing on salinity

## Notes

- Currently all forcing is applied to the surface layer only. In the future, vertical spreading of river runoff contributions will be needed.
Comment thread
katsmith133 marked this conversation as resolved.
- `SeaIceFreshWaterFlux` is the pure freshwater mass from sea ice. The full mass flux from sea ice is `SeaIceFreshWaterFlux + SeaIceSaltFlux`

## Surface tracer restoring design

### Surface tracer restoring data flow
Expand Down
6 changes: 4 additions & 2 deletions components/omega/doc/devGuide/TendencyTerms.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ implemented:
- `TracerHighOrderHorzAdvOnCell`
- `TracerDiffOnCell`
- `TracerHyperDiffOnCell`
- `SfcThicknessForcingOnCell`
- `SfcTracerForcingOnCell`
- `SurfaceTracerRestoringOnCell`

## See Also

Additional information on forcing (currently wind forcing and surface tracer
restoring) is detailed in [](omega-dev-forcing).
Additional information on forcing (surface stress, surface mass and tracer flux forcing, and
surface tracer restoring) is detailed in [](omega-dev-forcing).
69 changes: 69 additions & 0 deletions components/omega/doc/userGuide/Forcing.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
This page documents the user-facing configuration and behavior for current forcing in Omega:

- Surface stress forcing (e.g. wind stress)
- Coupled tracer flux forcing (mass, energy and salt)
- Surface tracer restoring

## Surface stress forcing
Expand Down Expand Up @@ -39,6 +40,74 @@ Surface stress forcing uses surface stress input fields:
These are stored in forcing variables and used to form edge-normal stress
(`NormalStressEdge`) that enters momentum tendencies.

## Surface thickness and tracer flux forcing

Surface thickness and tracer flux forcing applies ocean-atmosphere and ocean-sea ice fluxes from the other model
components (atmosphere, sea ice) to the thickness and tracer equations. This enables
the ocean to respond to heat, freshwater, and salt exchanges at the surface. These fluxes can be from data or (active) coupled components.

### Surface thickness and tracer flux forcing configuration

Surface thickness and tracer flux forcing is controlled by two configuration flags:

```yaml
Omega:
Tendencies:
SfcThicknessForcingTendencyEnable: false
SfcTracerForcingTendencyEnable: false
```

- `Tendencies.SfcThicknessForcingTendencyEnable`: enables coupled freshwater and salt flux forcing on thickness
- `Tendencies.SfcTracerForcingTendencyEnable`: enables coupled heat and salt flux forcing on tracers


### Required input fields

Coupled tracer flux forcing uses 13 auxiliary fields organized by type:

**Freshwater mass fluxes (kg m⁻² s⁻¹):**
- `SnowFlux`: precipitation from snow
- `RainFlux`: precipitation from rain
- `EvaporationFlux`: evaporative water loss
- `SeaIceFreshWaterFlux`: freshwater mass flux from sea-ice melt or formation
- `IceRunoffFlux`: runoff from land ice
- `RiverRunoffFlux`: runoff from rivers

**Heat/Enthalpy fluxes (W m⁻²):**
- `LatentHeatFluxEvap`: latent heat flux from evaporation phase change
- `SensibleHeatFlux`: sensible heat flux
- `LongWaveHeatFluxUp`: upward longwave radiation
- `LongWaveHeatFluxDown`: downward longwave radiation
- `SeaIceHeatFlux`: heat/energy from sea-ice interaction (incl. enthalpy of meltwater)
- `ShortWaveHeatFlux`: shortwave (solar) radiation

**Salt mass flux (kg m⁻² s⁻¹):**
- `SeaIceSaltFlux`: salt flux from sea-ice formation/melt processes

These fields are populated by external coupling components (typically atmosphere
and ice models). Omega assumes the incoming values match the documented units.
For now, there are assumed to come from a `forcing.nc` file, but later will be provided
by the equivalent `ocn_comp_mct.F`.

### Notes

- Coupled fluxes are applied only at the surface layer (top active layer) for each cell. In the future, vertical spreading of contributions from river runoff will be needed.
- Pseudo-thickness tendency is computed from the (six) freshwater mass fluxes and the salt mass flux
`SeaIceSaltFlux`, converted to a pseudo-thickness change.
- Temperature tendency is computed from direct heat flux plus
mass-flux enthalpy terms, converted to conservative-temperature tendency via
$H_{\text{FluxFac}} = 1.0 / (\rho_{sw} c^0_{p,sw})$ where $c^0_{p,sw}$ is the reference
specific heat of seawater defined by TEOS-10. The enthalpy associated with mass fluxes is currently hard-coded to SST for liquid fluxes and the freezing temperature for solid fluxes (which are melted using a constant latent heat of fusion). Note that the enthalpy of liquid meltwater from sea ice is already included in `SeaIceHeatFlux`.
- Salinity tendency from `SeaIceSaltFlux` is scaled by
$S_{\text{FluxFac}} = 1.0e3 / \rho_{sw}$ to account for unit conversion from
kg/(m²·s) to salinity units (g/kg).
- Fluxes are assumed to be in the documented units (i.e. net mass fluxes);
any unit conversion should be performed by the coupling component before providing flux
values to Omega.
- The reference density used here ($\rho_{sw}$) is not a Boussinesq density, it is the
conversion factor from mass to pseudo-thickness.
- No iceberg fluxes are included for now.
Comment thread
cbegeman marked this conversation as resolved.

## Surface tracer restoring

Surface tracer restoring applies a piston-velocity tendency, or damping, at the ocean
Expand Down
9 changes: 7 additions & 2 deletions components/omega/doc/userGuide/TendencyTerms.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ tendency terms are currently implemented:
| TracerHyperDiffOnCell | biharmonic horizontal mixing of thickness-weighted tracers
| SfcStressForcingOnEdge | forcing by surface stress (e.g. wind), defined on edges
| BottomDragOnEdge | bottom drag, defined on edges
| SfcThicknessForcingOnCell | surface pseudo-thickness forcing from coupled freshwater and salt fluxes, defined on cells
| SfcTracerForcingOnCell | surface tracer forcing from coupled heat and salt fluxes, with direct heat always and mass-flux enthalpy terms gated by thickness forcing, defined on cells
| SurfaceTracerRestoringOnCell | surface tracer restoring, defined on cells

Among the internal data stored by each functor is a `bool` which can enable or
Expand Down Expand Up @@ -57,6 +59,8 @@ the currently available tendency terms:
| | BottomDragTendency:Mode | bottom drag mode; `Implicit` or `Explicit`
| | BottomDragTendency:Type | bottom drag type; `Constant`
| | BottomDragTendency:BottomDragCoeff | bottom drag coefficient
| SfcThicknessForcingOnCell | SfcThicknessForcingTendencyEnable | enable/disable term
| SfcTracerForcingOnCell | SfcTracerForcingTendencyEnable | enable/disable term
| SurfaceTracerRestoringOnCell | SurfaceTracerRestoringEnable | enable/disable term

## Second Order Horizontal Advection Algorithm
Expand Down Expand Up @@ -142,5 +146,6 @@ Tracer higer order convergence example of a cosine bell advected on a sphere sho

## See Also

Additional information on forcing (currently wind forcing and surface tracer
restoring) is detailed in [](omega-user-forcing).
Additional information on forcing, including surface stress forcing,
surface thickness and tracer flux forcing, and surface tracer restoring, is detailed in
[](omega-user-forcing).
16 changes: 0 additions & 16 deletions components/omega/src/ocn/Eos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,22 +330,6 @@ void Eos::computeBruntVaisalaFreqSq(const Array2DReal &ConservTemp,
}
}

Real Eos::calcPtFromCt(const Real &Sa, const Real &Ct) const {
if (EosChoice == EosType::Teos10Eos) {
return ComputeSpecVolTeos10.calcPtFromCt(Sa, Ct);
}

return Ct;
}

Real Eos::calcCtFromPt(const Real &Sa, const Real &Pt) const {
if (EosChoice == EosType::Teos10Eos) {
return ComputeSpecVolTeos10.calcCtFromPt(Sa, Pt);
}

return Pt;
}

/// Define IO fields and metadata for output
void Eos::defineFields() {

Expand Down
47 changes: 42 additions & 5 deletions components/omega/src/ocn/Eos.h
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,8 @@ class Teos10Eos {
/// (polynomial error in [-5e-4, 6e-4] K, from GSW package).
/// P is relative pressure (gauge pressure in Pa, i.e., absolute pressure
/// minus the standard atmosphere).
KOKKOS_FUNCTION Real calcCtFreezing(const Real Sa, const Real P,
const Real SaturationFract) const {
static KOKKOS_FUNCTION Real calcCtFreezingTeos10(
const Real Sa, const Real P, const Real SaturationFract) {
constexpr Real Sso = 35.16504;
constexpr Real C0 = 0.017947064327968736;
constexpr Real C1 = -6.076099099929818;
Expand Down Expand Up @@ -1022,10 +1022,47 @@ class Eos {
const Array2DReal &SpecVol);

/// Convert Conservative Temperature to potential temperature
Real calcPtFromCt(const Real &Sa, const Real &Ct) const;
/// For TEOS-10, uses the TEOS-10 polynomial
/// For other EOS choices, conservative temperature is equal to potential
/// temperature
KOKKOS_FUNCTION Real calcPtFromCt(const Real &Sa, const Real &Ct) const {
if (EosChoice == EosType::Teos10Eos) {
return ComputeSpecVolTeos10.calcPtFromCt(Sa, Ct);
}
return Ct;
}

/// Convert potential temperature to Conservative Temperature.
/// For TEOS-10, uses the TEOS-10 polynomial
/// For other EOS choices, potential temperature equals conservative
/// temperature
KOKKOS_FUNCTION Real calcCtFromPt(const Real &Sa, const Real &Pt) const {
if (EosChoice == EosType::Teos10Eos) {
return ComputeSpecVolTeos10.calcCtFromPt(Sa, Pt);
}
return Pt;
}

/// Convert potential temperature to Conservative Temperature
Real calcCtFromPt(const Real &Sa, const Real &Pt) const;
/// Calculate freezing temperature of seawater.
/// For TEOS-10, uses the Roquet et al. 75-term polynomial.
/// For LinearEos, uses a simple linear salinity-dependent approximation.
/// For ConstantEos, returns a constant approximate ocean freezing point.
static KOKKOS_FUNCTION Real calcCtFreezing(EosType Choice, const Real Sa,
const Real P,
const Real SaturationFract) {
if (Choice == EosType::Teos10Eos) {
return Teos10Eos::calcCtFreezingTeos10(Sa, P, SaturationFract);
}
if (Choice == EosType::LinearEos) {
// Linear salinity-dependent freezing point; coefficient -0.054
// degC/PSU with absolute-to-practical salinity conversion (g/kg ->
// PSU).
constexpr Real Coeff = -0.054_Real;
return Coeff * Sa / Psu2Gpkg;
}
// ConstantEos: constant approximate ocean freezing point (degC)
return -1.9_Real;
}

/// Initialize EOS from config and mesh
static void init();
Expand Down
Loading
Loading