Magnitude of the surface drag coefficient increases with timestep under certain conditions
Context
- Branches impacted:
branch_4.2
,main
- Dependencies:
key_si3
+key_isf
+ln_isfcav
+ln_lin
+ln_drgice_imp
Analysis
This issue concerns the updating of the surface drag coefficient (rCdU_top
) with the sea ice drag (rCdU_ice
) in zdf_phy:
IF( l_zdfdrg ) THEN !== update top/bottom drag ==! (non-linear cases)
!
! !* bottom drag
CALL zdf_drg( kt, Kmm, mbkt , r_Cdmin_bot, r_Cdmax_bot, & ! <<== in
& r_z0_bot, r_ke0_bot, rCd0_bot, &
& rCdU_bot ) ! ==>> out : bottom drag [m/s]
IF( ln_isfcav ) THEN !* top drag (ocean cavities)
CALL zdf_drg( kt, Kmm, mikt , r_Cdmin_top, r_Cdmax_top, & ! <<== in
& r_z0_top, r_ke0_top, rCd0_top, &
& rCdU_top ) ! ==>> out : bottom drag [m/s]
ENDIF
ENDIF
!
#if defined key_si3
IF ( ln_drgice_imp) THEN
IF ( ln_isfcav ) THEN
DO_2D( 1, 1, 1, 1 )
rCdU_top(ji,jj) = rCdU_top(ji,jj) + ssmask(ji,jj) * tmask(ji,jj,1) * rCdU_ice(ji,jj)
END_2D
ELSE
! Needed on 1st halo points by dyn_zdf (if ln_drgice_imp or ln_isfcav)
DO_2D( 1, 1, 1, 1 )
rCdU_top(ji,jj) = rCdU_ice(ji,jj)
END_2D
ENDIF
ENDIF
#endif
In the linear drag case (ln_lin
), rCdU_top
is set once in drg_init
during initialisation. In the above code when ln_lin=T
and ln_drgice_imp=T
and ln_isfcav=T
, rCdU_ice
is added to rCdU_top
so that rCdU_top
increases in magnitude with each timestep.
This does not occur for the nonlinear drag case (ln_non_lin
), because rCdU_top
is updated on every timestep.
Fix
rCdU_top
must be reset to its initial value on every timestep if using linear drag with these specific configuration choices. This has been addressed by reorganising some of the zdfdrg.F90
code:
-
Moved the initial calculation of
pCdU
in the linear (ndrg == np_lin
) and frictionless (ndrg == np_OFF
) cases into a new subroutinezdf_drg_lin
-
Renamed the
zdf_drg
subroutine tozdf_drg_nonlin
-
Replaced the
zdf_drg
subroutine with one that handles both linear and nonlinear drag cases-
The code updating the drag coefficients in
zdf_phy
has been moved into this routine and replaced by:CALL zdf_drg( kt, Kmm, 'BOTTOM' ) ! bottom drag IF( ln_isfcav .OR. ln_drgice_imp ) CALL zdf_drg( kt, Kmm, 'TOP' ) ! top drag (ocean cavities)
-
This has fewer arguments than before:
- SUBROUTINE zdf_drg( kt, Kmm, k_mk, pCdmin, pCdmax, pz0, pke0, pCd0, pCdU ) + SUBROUTINE zdf_drg( kt, Kmm, cd_topbot )
Most of the input arguments are now set within
zdf_drg
, depending on whethercd_topbot="BOTTOM"
(bottom drag) orcd_topbot="TOP"
(surface drag).
-
-
The bug itself has been fixed by calling
zdf_drg_lin
fromzdf_drg
to resetrCdU_top
to its initial values on every timestep:#if defined key_si3 IF( ln_drgice_imp ) THEN IF( ln_isfcav ) THEN + ! In the linear case, we must reset rCdU_top on every timestep to avoid a cumulative sum + IF( .NOT. l_zdfdrg ) CALL zdf_drg_lin( rCd0_top(:,:), rCdU_top(:,:) ) DO_2D( 1, 1, 1, 1 ) rCdU_top(ji,jj) = rCdU_top(ji,jj) + ssmask(ji,jj) * tmask(ji,jj,1) * rCdU_ice(ji,jj) END_2D ELSE DO_2D( 1, 1, 1, 1 ) rCdU_top(ji,jj) = rCdU_ice(ji,jj) END_2D ENDIF ENDIF #endif
I also made some other minor changes that shouldn't affect results.