Changeset 11615 for NEMO/branches/2019/dev_r11085_ASINTER-05_Brodeau_Advanced_Bulk/src/OCE/SBC/sbcblk_algo_ecmwf.F90
- Timestamp:
- 2019-09-30T15:18:21+02:00 (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
NEMO/branches/2019/dev_r11085_ASINTER-05_Brodeau_Advanced_Bulk/src/OCE/SBC/sbcblk_algo_ecmwf.F90
r11329 r11615 39 39 USE sbc_oce ! Surface boundary condition: ocean fields 40 40 USE sbcblk_phy ! all thermodynamics functions, rho_air, q_sat, etc... !LB 41 USE sbcblk_skin ! cool-skin/warm layer scheme (CSWL_ECMWF)!LB41 USE sbcblk_skin_ecmwf ! cool-skin/warm layer scheme !LB 42 42 43 43 IMPLICIT NONE … … 60 60 CONTAINS 61 61 62 SUBROUTINE turb_ecmwf( zt, zu, T_s, t_zt, q_s, q_zt, U_zu, &62 SUBROUTINE turb_ecmwf( zt, zu, T_s, t_zt, q_s, q_zt, U_zu, l_use_cs, l_use_wl, & 63 63 & Cd, Ch, Ce, t_zu, q_zu, U_blk, & 64 64 & Cdn, Chn, Cen, & 65 & Qsw, rad_lw, slp, &66 & Tsk_b )65 & Qsw, rad_lw, slp, pdT_cs, & ! optionals for cool-skin (and warm-layer) 66 & pdT_wl ) ! optionals for warm-layer only 67 67 !!---------------------------------------------------------------------- 68 68 !! *** ROUTINE turb_ecmwf *** 69 69 !! 70 70 !! ** Purpose : Computes turbulent transfert coefficients of surface 71 !! fluxes according to IFS doc. (cycle 4 0)71 !! fluxes according to IFS doc. (cycle 45r1) 72 72 !! If relevant (zt /= zu), adjust temperature and humidity from height zt to zu 73 73 !! Returns the effective bulk wind speed at zu to be used in the bulk formulas … … 82 82 !! * zt : height for temperature and spec. hum. of air [m] 83 83 !! * zu : height for wind speed (usually 10m) [m] 84 !! * U_zu : scalar wind speed at zu [m/s]85 84 !! * t_zt : potential air temperature at zt [K] 86 85 !! * q_zt : specific humidity of air at zt [kg/kg] 86 !! * U_zu : scalar wind speed at zu [m/s] 87 !! * l_use_cs : use the cool-skin parameterization 88 !! * l_use_wl : use the warm-layer parameterization 87 89 !! 88 90 !! INPUT/OUTPUT: … … 101 103 !! * rad_lw : downwelling longwave radiation at the surface (>0) [W/m^2] 102 104 !! * slp : sea-level pressure [Pa] 103 !! * Tsk_b : estimate of skin temperature at previous time-step [K] 105 !! * pdT_cs : SST increment "dT" for cool-skin correction [K] 106 !! * pdT_wl : SST increment "dT" for warm-layer correction [K] 104 107 !! 105 108 !! OUTPUT : … … 122 125 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: q_zt ! specific air humidity at zt [kg/kg] 123 126 REAL(wp), INTENT(in ), DIMENSION(jpi,jpj) :: U_zu ! relative wind module at zu [m/s] 127 LOGICAL , INTENT(in ) :: l_use_cs ! use the cool-skin parameterization 128 LOGICAL , INTENT(in ) :: l_use_wl ! use the warm-layer parameterization 124 129 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: Cd ! transfer coefficient for momentum (tau) 125 130 REAL(wp), INTENT( out), DIMENSION(jpi,jpj) :: Ch ! transfer coefficient for sensible heat (Q_sens) … … 133 138 REAL(wp), INTENT(in ), OPTIONAL, DIMENSION(jpi,jpj) :: rad_lw ! [W/m^2] 134 139 REAL(wp), INTENT(in ), OPTIONAL, DIMENSION(jpi,jpj) :: slp ! [Pa] 135 REAL(wp), INTENT(in ), OPTIONAL, DIMENSION(jpi,jpj) :: Tsk_b ! [Pa] 140 REAL(wp), INTENT( out), OPTIONAL, DIMENSION(jpi,jpj) :: pdT_cs 141 ! 142 REAL(wp), INTENT( out), OPTIONAL, DIMENSION(jpi,jpj) :: pdT_wl ! [K] 136 143 ! 137 144 INTEGER :: j_itt … … 145 152 & z0, z0t, z0q 146 153 ! 147 ! Cool skin: 148 LOGICAL :: l_use_skin = .FALSE. 149 REAL(wp), DIMENSION(jpi,jpj) :: zsst ! to back up the initial bulk SST 154 REAL(wp), DIMENSION(:,:), ALLOCATABLE :: & 155 & zsst, & ! to back up the initial bulk SST 156 & pdTc, & ! SST increment "dT" for cool-skin correction [K] 157 & pdTw ! SST increment "dT" for warm layer correction [K] 150 158 ! 151 159 REAL(wp), DIMENSION(jpi,jpj) :: func_m, func_h 152 160 REAL(wp), DIMENSION(jpi,jpj) :: ztmp0, ztmp1, ztmp2 153 !!---------------------------------------------------------------------------------- 154 155 ! Cool skin ? 156 IF( PRESENT(Qsw) .AND. PRESENT(rad_lw) .AND. PRESENT(slp) ) THEN 157 l_use_skin = .TRUE. 158 END IF 159 IF (lwp) PRINT *, ' *** LOLO(sbcblk_algo_ecmwf.F90) => l_use_skin =', l_use_skin 160 161 ! Identical first gess as in COARE, with IFS parameter values though... 162 ! 161 CHARACTER(len=40), PARAMETER :: crtnm = 'turb_ecmwf@sbcblk_algo_ecmwf.F90' 162 !!---------------------------------------------------------------------------------- 163 163 164 l_zt_equal_zu = .FALSE. 164 165 IF( ABS(zu - zt) < 0.01_wp ) l_zt_equal_zu = .TRUE. ! testing "zu == zt" is risky with double precision 165 166 166 !! Initialization for cool skin: 167 zsst = T_s ! save the bulk SST 168 IF( l_use_skin ) THEN 169 ! First guess for skin temperature: 170 IF( PRESENT(Tsk_b) ) THEN 171 T_s = Tsk_b 172 ELSE 173 T_s = T_s - 0.25 ! sst - 0.25 174 END IF 175 q_s = rdct_qsat_salt*q_sat(MAX(T_s, 200._wp), slp) ! First guess of q_s 167 !! Initializations for cool skin and warm layer: 168 IF ( l_use_cs ) THEN 169 IF( .NOT.(PRESENT(Qsw) .AND. PRESENT(rad_lw) .AND. PRESENT(slp)) ) THEN 170 PRINT *, ' * PROBLEM ('//trim(crtnm)//'): you need to provide Qsw, rad_lw & slp to use cool-skin param!' 171 STOP 172 END IF 173 ALLOCATE ( pdTc(jpi,jpj) ) 174 pdTc(:,:) = -0.25_wp ! First guess of skin correction 176 175 END IF 177 176 177 IF ( l_use_wl ) THEN 178 IF(.NOT.(PRESENT(Qsw) .AND. PRESENT(rad_lw) .AND. PRESENT(slp))) THEN 179 PRINT *, ' * PROBLEM ('//trim(crtnm)//'): you need to provide Qsw, rad_lw & slp to use warm-layer param!' 180 STOP 181 END IF 182 ALLOCATE ( pdTw(jpi,jpj) ) 183 pdTw(:,:) = 0._wp 184 END IF 185 186 IF ( l_use_cs .OR. l_use_wl ) THEN 187 ALLOCATE ( zsst(jpi,jpj) ) 188 zsst = T_s ! backing up the bulk SST 189 IF( l_use_cs ) T_s = T_s - 0.25_wp ! First guess of correction 190 q_s = rdct_qsat_salt*q_sat(MAX(T_s, 200._wp), slp) ! First guess of q_s !LOLO WL too!!! 191 END IF 192 193 194 ! Identical first gess as in COARE, with IFS parameter values though... 195 ! 178 196 !! First guess of temperature and humidity at height zu: 179 197 t_zu = MAX( t_zt , 180._wp ) ! who knows what's given on masked-continental regions... … … 197 215 z0t = MIN(ABS(z0t), 0.001_wp) ! (prevent FPE from stupid values from masked region later on...) !#LOLO 198 216 199 ztmp2 = vkarmn/ztmp0 200 Cd = ztmp2*ztmp2 ! first guess of Cd 217 Cd = (vkarmn/ztmp0)**2 ! first guess of Cd 201 218 202 219 ztmp0 = vkarmn*vkarmn/LOG(zt/z0t)/Cd … … 265 282 z0q = MIN( ABS( alpha_Q*ztmp1 ) , 0.001_wp) 266 283 267 !! Update wind at 10m taking into acount convection-related wind gustiness: 268 !! => Chap. 3.2, IFS doc - Cy40r1, Eq.3.17 and Eq.3.18 + Eq.3.8 269 ! Only true when unstable (L<0) => when ztmp0 < 0 => - !!! 270 ztmp2 = ztmp2 * ( MAX(-zi0*Linv/vkarmn , 0._wp))**(2._wp/3._wp) ! => w*^2 (combining Eq. 3.8 and 3.18, hap.3, IFS doc - Cy31r1) 271 !! => equivalent using Beta=1 (gustiness parameter, 1.25 for COARE, also zi0=600 in COARE..) 272 U_blk = MAX( SQRT(U_zu*U_zu + ztmp2) , 0.2_wp ) ! eq.3.17, Chap.3, p.32, IFS doc - Cy31r1 284 !! Update wind at zu with convection-related wind gustiness in unstable conditions (Chap. 3.2, IFS doc - Cy40r1, Eq.3.17 and Eq.3.18 + Eq.3.8) 285 ztmp2 = Beta0*Beta0*ztmp2*(MAX(-zi0*Linv/vkarmn,0._wp))**(2._wp/3._wp) ! square of wind gustiness contribution (combining Eq. 3.8 and 3.18, hap.3, IFS doc - Cy31r1) 286 !! ! Only true when unstable (L<0) => when ztmp0 < 0 => explains "-" before zi0 287 U_blk = MAX(SQRT(U_zu*U_zu + ztmp2), 0.2_wp) ! include gustiness in bulk wind speed 273 288 ! => 0.2 prevents U_blk to be 0 in stable case when U_zu=0. 274 289 … … 303 318 func_h = log(zu) - LOG(z0t) - psi_h_ecmwf(ztmp0) + psi_h_ecmwf(z0t*Linv) 304 319 305 !! SKIN related part 306 !! ----------------- 307 IF( l_use_skin ) THEN 308 !! compute transfer coefficients at zu : lolo: verifier... 309 Ch = vkarmn*vkarmn/(func_m*func_h) 310 ztmp1 = LOG(zu) - LOG(z0q) - psi_h_ecmwf(ztmp0) + psi_h_ecmwf(z0q*Linv) ! func_q 311 Ce = vkarmn*vkarmn/(func_m*ztmp1) 312 ! Non-Solar heat flux to the ocean: 313 ztmp1 = U_blk*MAX(rho_air(t_zu, q_zu, slp), 1._wp) ! rho*U10 314 ztmp2 = T_s*T_s 315 ztmp1 = ztmp1 * ( Ce*L_vap(T_s)*(q_zu - q_s) + Ch*cp_air(q_zu)*(t_zu - T_s) ) & ! Total turb. heat flux 316 & + emiss_w*(rad_lw - stefan*ztmp2*ztmp2) ! Net longwave flux 317 !! => "ztmp1" is the net non-solar surface heat flux ! 318 !! Updating the values of the skin temperature T_s and q_s : 319 CALL CSWL_ECMWF( Qsw, ztmp1, u_star, zsst, T_s ) 320 q_s = rdct_qsat_salt*q_sat(MAX(T_s, 200._wp), slp) ! 200 -> just to avoid numerics problem on masked regions if silly values are given 321 END IF 322 323 IF( (l_use_skin).OR.(.NOT. l_zt_equal_zu) ) THEN 320 321 IF( l_use_cs ) THEN 322 !! Cool-skin contribution 323 324 CALL UPDATE_QNSOL_TAU( T_s, q_s, t_zu, q_zu, u_star, t_star, q_star, U_blk, slp, rad_lw, & 325 & ztmp1, ztmp0, Qlat=ztmp2) ! Qnsol -> ztmp1 / Tau -> ztmp0 326 327 CALL CS_ECMWF( Qsw, ztmp1, u_star, zsst, pdTc ) ! Qnsol -> ztmp1 328 329 T_s(:,:) = zsst(:,:) + pdTc(:,:) 330 IF( l_use_wl ) T_s(:,:) = T_s(:,:) + pdTw(:,:) 331 q_s(:,:) = rdct_qsat_salt*q_sat(MAX(T_s(:,:), 200._wp), slp(:,:)) 332 333 END IF 334 335 IF( l_use_wl ) THEN 336 !! Warm-layer contribution 337 CALL UPDATE_QNSOL_TAU( T_s, q_s, t_zu, q_zu, u_star, t_star, q_star, U_blk, slp, rad_lw, & 338 & ztmp1, ztmp2) ! Qnsol -> ztmp1 / Tau -> ztmp2 339 CALL WL_ECMWF( Qsw, ztmp1, u_star, zsst, pdTw ) 340 !! Updating T_s and q_s !!! 341 T_s(:,:) = zsst(:,:) + pdTw(:,:) 342 IF( l_use_cs ) T_s(:,:) = T_s(:,:) + pdTc(:,:) 343 q_s(:,:) = rdct_qsat_salt*q_sat(MAX(T_s(:,:), 200._wp), slp(:,:)) 344 END IF 345 346 347 IF( l_use_cs .OR. l_use_wl .OR. (.NOT. l_zt_equal_zu) ) THEN 324 348 dt_zu = t_zu - T_s ; dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu ) 325 349 dq_zu = q_zu - q_s ; dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu ) … … 337 361 Cen = vkarmn*vkarmn / (log(zu/z0q)*log(zu/z0q)) 338 362 339 END SUBROUTINE TURB_ECMWF 363 IF ( l_use_cs .AND. PRESENT(pdT_cs) ) pdT_cs = pdTc 364 IF ( l_use_wl .AND. PRESENT(pdT_wl) ) pdT_wl = pdTw 365 366 IF ( l_use_cs .OR. l_use_wl ) DEALLOCATE ( zsst ) 367 IF ( l_use_cs ) DEALLOCATE ( pdTc ) 368 IF ( l_use_wl ) DEALLOCATE ( pdTw ) 369 370 END SUBROUTINE turb_ecmwf 340 371 341 372 … … 433 464 434 465 435 436 437 438 466 !!====================================================================== 439 467 END MODULE sbcblk_algo_ecmwf
Note: See TracChangeset
for help on using the changeset viewer.