The per-outer-step weight that turns the salt/heat budget ACCUMULATORS into the state change they must account for.
ssp_rk2 (is_pc = .false.) -> 0.5 (= RK2_STAGE_WEIGHT)
pred_corr (is_pc = .true. ) -> 1.0
ms%{salt,heat}_budget_* are += accumulators filled by the tracer
chain, zeroed once per OUTER step. Under split_scheme="ssp_rk2"
the chain runs on BOTH identical stages, so the accumulator holds
twice the step’s contribution and 0.5 converts it. Under
split_scheme="pred_corr" there is ONE prognostic tracer update — the
corrector; the predictor runs TR_MODE_NONE and contributes
nothing — so the accumulator already equals the step’s contribution
1:1 and halving it reports exactly half the true source/transport.
This is the same distinction ocean_frazil_heat_src documents for
the frazil accumulator (filled once per outer step ⇒ full weight).
MEASURED, 2026-09-13: with the 0.5 weight applied to a pred_corr run
the console src came out exactly half its ssp_rk2 value on every
surface-flux case (acc_channel -1.057E+15 -> -5.285E+14;
epbl_basin -4.720E+16 -> -2.360E+16) while the Heat TOTAL matched
to every printed digit, and the closed-budget residual went from
~1e-13 to ~5e-4. Ten shipped namelists failed the stability suite’s
conservation gate on that alone. Sole home of the mapping.
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| logical, | intent(in) | :: | is_pc |
pure function ocean_budget_stage_weight(is_pc) result(w) !! The per-outer-step weight that turns the salt/heat budget !! ACCUMULATORS into the state change they must account for. !! !! ssp_rk2 (is_pc = .false.) -> 0.5 (= `RK2_STAGE_WEIGHT`) !! pred_corr (is_pc = .true. ) -> 1.0 !! !! `ms%{salt,heat}_budget_*` are `+=` accumulators filled by the tracer !! chain, zeroed once per OUTER step. Under `split_scheme="ssp_rk2"` !! the chain runs on BOTH identical stages, so the accumulator holds !! twice the step's contribution and 0.5 converts it. Under !! `split_scheme="pred_corr"` there is ONE prognostic tracer update — the !! corrector; the predictor runs `TR_MODE_NONE` and contributes !! nothing — so the accumulator already equals the step's contribution !! 1:1 and halving it reports exactly half the true source/transport. !! !! This is the same distinction `ocean_frazil_heat_src` documents for !! the frazil accumulator (filled once per outer step ⇒ full weight). !! !! MEASURED, 2026-09-13: with the 0.5 weight applied to a pred_corr run !! the console `src` came out exactly half its ssp_rk2 value on every !! surface-flux case (`acc_channel` -1.057E+15 -> -5.285E+14; !! `epbl_basin` -4.720E+16 -> -2.360E+16) while the Heat TOTAL matched !! to every printed digit, and the closed-budget residual went from !! ~1e-13 to ~5e-4. Ten shipped namelists failed the stability suite's !! conservation gate on that alone. Sole home of the mapping. logical, intent(in) :: is_pc real(wp) :: w if (is_pc) then w = 1.0_wp else w = RK2_STAGE_WEIGHT end if end function ocean_budget_stage_weight