New URL for NEMO forge!   http://forge.nemo-ocean.eu

Since March 2022 along with NEMO 4.2 release, the code development moved to a self-hosted GitLab.
This present forge is now archived and remained online for history.
sbcblk_algo_coare3p6.F90 in NEMO/branches/2019/dev_r11085_ASINTER-05_Brodeau_Advanced_Bulk/src/OCE/SBC – NEMO

source: NEMO/branches/2019/dev_r11085_ASINTER-05_Brodeau_Advanced_Bulk/src/OCE/SBC/sbcblk_algo_coare3p6.F90 @ 11817

Last change on this file since 11817 was 11817, checked in by laurent, 4 years ago

A few rogue "STOP"s become "ctl_stop"!

File size: 26.3 KB
Line 
1MODULE sbcblk_algo_coare3p6
2   !!======================================================================
3   !!                   ***  MODULE  sbcblk_algo_coare3p6  ***
4   !!
5   !!                After Fairall et al 2018 & Edson et al 2013
6   !! Computes:
7   !!   * bulk transfer coefficients C_D, C_E and C_H
8   !!   * air temp. and spec. hum. adjusted from zt (2m) to zu (10m) if needed
9   !!   * the effective bulk wind speed at 10m U_blk
10   !!   => all these are used in bulk formulas in sbcblk.F90
11   !!
12   !!       Routine turb_coare3p6 maintained and developed in AeroBulk
13   !!                     (https://github.com/brodeau/aerobulk)
14   !!
15   !! ** Author: L. Brodeau, June 2019 / AeroBulk (https://github.com/brodeau/aerobulk)
16   !!----------------------------------------------------------------------
17   !! History :  4.0  !  2016-02  (L.Brodeau)   Original code
18   !!----------------------------------------------------------------------
19
20   !!----------------------------------------------------------------------
21   !!   turb_coare3p6  : computes the bulk turbulent transfer coefficients
22   !!                   adjusts t_air and q_air from zt to zu m
23   !!                   returns the effective bulk wind speed at 10m
24   !!----------------------------------------------------------------------
25   USE oce             ! ocean dynamics and tracers
26   USE dom_oce         ! ocean space and time domain
27   USE phycst          ! physical constants
28   USE iom             ! I/O manager library
29   USE lib_mpp         ! distribued memory computing library
30   USE in_out_manager  ! I/O manager
31   USE prtctl          ! Print control
32   USE sbcwave, ONLY   :  cdn_wave ! wave module
33#if defined key_si3 || defined key_cice
34   USE sbc_ice         ! Surface boundary condition: ice fields
35#endif
36   USE lib_fortran     ! to use key_nosignedzero
37
38   USE sbc_oce         ! Surface boundary condition: ocean fields
39   USE sbcblk_phy      ! all thermodynamics functions, rho_air, q_sat, etc... !LB
40   USE sbcblk_skin_coare ! cool-skin/warm layer scheme (CSWL_ECMWF) !LB
41
42   IMPLICIT NONE
43   PRIVATE
44
45   PUBLIC :: COARE3P6_INIT, TURB_COARE3P6
46
47   !! COARE own values for given constants:
48   REAL(wp), PARAMETER :: zi0   = 600._wp     ! scale height of the atmospheric boundary layer...
49   REAL(wp), PARAMETER :: Beta0 =  1.2_wp     ! gustiness parameter
50
51   INTEGER , PARAMETER ::   nb_itt = 10             ! number of itterations
52
53   !!----------------------------------------------------------------------
54CONTAINS
55
56
57   SUBROUTINE coare3p6_init(l_use_cs, l_use_wl)
58      !!---------------------------------------------------------------------
59      !!                  ***  FUNCTION coare3p6_init  ***
60      !!
61      !! INPUT :
62      !! -------
63      !!    * l_use_cs : use the cool-skin parameterization
64      !!    * l_use_wl : use the warm-layer parameterization
65      !!---------------------------------------------------------------------
66      LOGICAL , INTENT(in) ::   l_use_cs ! use the cool-skin parameterization
67      LOGICAL , INTENT(in) ::   l_use_wl ! use the warm-layer parameterization
68      INTEGER :: ierr
69      !!---------------------------------------------------------------------
70      IF ( l_use_wl ) THEN
71         ierr = 0
72         ALLOCATE ( Tau_ac(jpi,jpj) , Qnt_ac(jpi,jpj), dT_wl(jpi,jpj), Hz_wl(jpi,jpj), STAT=ierr )
73         IF( ierr > 0 ) CALL ctl_stop( ' COARE3P6_INIT => allocation of Tau_ac, Qnt_ac, dT_wl & Hz_wl failed!' )
74         Tau_ac(:,:) = 0._wp
75         Qnt_ac(:,:) = 0._wp
76         dT_wl(:,:)  = 0._wp
77         Hz_wl(:,:)  = Hwl_max
78      END IF
79      IF ( l_use_cs ) THEN
80         ierr = 0
81         ALLOCATE ( dT_cs(jpi,jpj), STAT=ierr )
82         IF( ierr > 0 ) CALL ctl_stop( ' COARE3P6_INIT => allocation of dT_cs failed!' )
83         dT_cs(:,:) = -0.25_wp  ! First guess of skin correction
84      END IF
85   END SUBROUTINE coare3p6_init
86
87
88
89   SUBROUTINE turb_coare3p6( kt, zt, zu, T_s, t_zt, q_s, q_zt, U_zu, l_use_cs, l_use_wl, &
90      &                      Cd, Ch, Ce, t_zu, q_zu, U_blk,                              &
91      &                      Cdn, Chn, Cen,                                              &
92      &                      Qsw, rad_lw, slp, pdT_cs,                                   & ! optionals for cool-skin (and warm-layer)
93      &                      pdT_wl, pHz_wl )                                                 ! optionals for warm-layer only
94      !!----------------------------------------------------------------------
95      !!                      ***  ROUTINE  turb_coare3p6  ***
96      !!
97      !! ** Purpose :   Computes turbulent transfert coefficients of surface
98      !!                fluxes according to Fairall et al. (2003)
99      !!                If relevant (zt /= zu), adjust temperature and humidity from height zt to zu
100      !!                Returns the effective bulk wind speed at zu to be used in the bulk formulas
101      !!
102      !!                Applies the cool-skin warm-layer correction of the SST to T_s
103      !!                if the net shortwave flux at the surface (Qsw), the downwelling longwave
104      !!                radiative fluxes at the surface (rad_lw), and the sea-leve pressure (slp)
105      !!                are provided as (optional) arguments!
106      !!
107      !! INPUT :
108      !! -------
109      !!    *  kt   : current time step (starts at 1)
110      !!    *  zt   : height for temperature and spec. hum. of air            [m]
111      !!    *  zu   : height for wind speed (usually 10m)                     [m]
112      !!    *  t_zt : potential air temperature at zt                         [K]
113      !!    *  q_zt : specific humidity of air at zt                          [kg/kg]
114      !!    *  U_zu : scalar wind speed at zu                                 [m/s]
115      !!    * l_use_cs : use the cool-skin parameterization
116      !!    * l_use_wl : use the warm-layer parameterization
117      !!
118      !! INPUT/OUTPUT:
119      !! -------------
120      !!    *  T_s  : always "bulk SST" as input                              [K]
121      !!              -> unchanged "bulk SST" as output if CSWL not used      [K]
122      !!              -> skin temperature as output if CSWL used              [K]
123      !!
124      !!    *  q_s  : SSQ aka saturation specific humidity at temp. T_s       [kg/kg]
125      !!              -> doesn't need to be given a value if skin temp computed (in case l_use_cs=True or l_use_wl=True)
126      !!              -> MUST be given the correct value if not computing skint temp. (in case l_use_cs=False or l_use_wl=False)
127      !!
128      !! OPTIONAL INPUT:
129      !! ---------------
130      !!    *  Qsw    : net solar flux (after albedo) at the surface (>0)     [W/m^2]
131      !!    *  rad_lw : downwelling longwave radiation at the surface  (>0)   [W/m^2]
132      !!    *  slp    : sea-level pressure                                    [Pa]
133      !!
134      !! OPTIONAL OUTPUT:
135      !! ----------------
136      !!    * pdT_cs  : SST increment "dT" for cool-skin correction           [K]
137      !!    * pdT_wl  : SST increment "dT" for warm-layer correction          [K]
138      !!    * pHz_wl  : thickness of warm-layer                               [m]
139      !!
140      !! OUTPUT :
141      !! --------
142      !!    *  Cd     : drag coefficient
143      !!    *  Ch     : sensible heat coefficient
144      !!    *  Ce     : evaporation coefficient
145      !!    *  t_zu   : pot. air temperature adjusted at wind height zu       [K]
146      !!    *  q_zu   : specific humidity of air        //                    [kg/kg]
147      !!    *  U_blk  : bulk wind speed at zu                                 [m/s]
148      !!
149      !!
150      !! ** Author: L. Brodeau, June 2019 / AeroBulk (https://github.com/brodeau/aerobulk/)
151      !!----------------------------------------------------------------------------------
152      INTEGER,  INTENT(in   )                     ::   kt       ! current time step
153      REAL(wp), INTENT(in   )                     ::   zt       ! height for t_zt and q_zt                    [m]
154      REAL(wp), INTENT(in   )                     ::   zu       ! height for U_zu                             [m]
155      REAL(wp), INTENT(inout), DIMENSION(jpi,jpj) ::   T_s      ! sea surface temperature                [Kelvin]
156      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   t_zt     ! potential air temperature              [Kelvin]
157      REAL(wp), INTENT(inout), DIMENSION(jpi,jpj) ::   q_s      ! sea surface specific humidity           [kg/kg]
158      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   q_zt     ! specific air humidity at zt             [kg/kg]
159      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   U_zu     ! relative wind module at zu                [m/s]
160      LOGICAL , INTENT(in   )                     ::   l_use_cs ! use the cool-skin parameterization
161      LOGICAL , INTENT(in   )                     ::   l_use_wl ! use the warm-layer parameterization
162      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Cd       ! transfer coefficient for momentum         (tau)
163      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Ch       ! transfer coefficient for sensible heat (Q_sens)
164      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Ce       ! transfert coefficient for evaporation   (Q_lat)
165      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   t_zu     ! pot. air temp. adjusted at zu               [K]
166      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   q_zu     ! spec. humidity adjusted at zu           [kg/kg]
167      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   U_blk    ! bulk wind speed at zu                     [m/s]
168      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Cdn, Chn, Cen ! neutral transfer coefficients
169      !
170      REAL(wp), INTENT(in   ), OPTIONAL, DIMENSION(jpi,jpj) ::   Qsw      !             [W/m^2]
171      REAL(wp), INTENT(in   ), OPTIONAL, DIMENSION(jpi,jpj) ::   rad_lw   !             [W/m^2]
172      REAL(wp), INTENT(in   ), OPTIONAL, DIMENSION(jpi,jpj) ::   slp      !             [Pa]
173      REAL(wp), INTENT(  out), OPTIONAL, DIMENSION(jpi,jpj) ::   pdT_cs
174      REAL(wp), INTENT(  out), OPTIONAL, DIMENSION(jpi,jpj) ::   pdT_wl   !             [K]
175      REAL(wp), INTENT(  out), OPTIONAL, DIMENSION(jpi,jpj) ::   pHz_wl   !             [m]
176      !
177      INTEGER :: j_itt
178      LOGICAL :: l_zt_equal_zu = .FALSE.      ! if q and t are given at same height as U
179      !
180      REAL(wp), DIMENSION(jpi,jpj) ::  &
181         &  u_star, t_star, q_star, &
182         &  dt_zu, dq_zu,    &
183         &  znu_a,           & !: Nu_air, Viscosity of air
184         &  z0, z0t
185      REAL(wp), DIMENSION(jpi,jpj) ::   zeta_u        ! stability parameter at height zu
186      REAL(wp), DIMENSION(jpi,jpj) ::   ztmp0, ztmp1, ztmp2
187      REAL(wp), DIMENSION(:,:), ALLOCATABLE ::   zeta_t        ! stability parameter at height zt
188      !
189      REAL(wp), DIMENSION(:,:), ALLOCATABLE :: &
190         &                zsst,   &  ! to back up the initial bulk SST
191         &                pdTc,   &  ! SST increment "dT" for cool-skin correction           [K]
192         &                pdTw,   &  ! SST increment "dT" for warm layer correction          [K]
193         &                zHwl       ! depth of warm-layer [m]
194      CHARACTER(len=40), PARAMETER :: crtnm = 'turb_coare3p6@sbcblk_algo_coare3p6'
195      !!----------------------------------------------------------------------------------
196      IF ( kt == nit000 ) CALL COARE3P6_INIT(l_use_cs, l_use_wl)
197
198      l_zt_equal_zu = .FALSE.
199      IF( ABS(zu - zt) < 0.01_wp )   l_zt_equal_zu = .TRUE.    ! testing "zu == zt" is risky with double precision
200      IF( .NOT. l_zt_equal_zu )  ALLOCATE( zeta_t(jpi,jpj) )
201
202      !! Initializations for cool skin and warm layer:
203      IF ( l_use_cs .AND. (.NOT.(PRESENT(Qsw) .AND. PRESENT(rad_lw) .AND. PRESENT(slp))) ) &
204         &   CALL ctl_stop( '['//TRIM(crtnm)//'] => ' , 'you need to provide Qsw, rad_lw & slp to use cool-skin param!' )
205
206      IF ( l_use_wl .AND. (.NOT.(PRESENT(Qsw) .AND. PRESENT(rad_lw) .AND. PRESENT(slp))) ) &
207         &   CALL ctl_stop( '['//TRIM(crtnm)//'] => ' , 'you need to provide Qsw, rad_lw & slp to use warm-layer param!' )
208
209      IF ( l_use_cs .OR. l_use_wl ) THEN
210         ALLOCATE ( zsst(jpi,jpj) )
211         zsst = T_s ! backing up the bulk SST
212         IF( l_use_cs ) T_s = T_s - 0.25_wp   ! First guess of correction
213         q_s    = rdct_qsat_salt*q_sat(MAX(T_s, 200._wp), slp) ! First guess of q_s
214      END IF
215
216
217      !! First guess of temperature and humidity at height zu:
218      t_zu = MAX( t_zt ,  180._wp )   ! who knows what's given on masked-continental regions...
219      q_zu = MAX( q_zt , 1.e-6_wp )   !               "
220
221      !! Pot. temp. difference (and we don't want it to be 0!)
222      dt_zu = t_zu - T_s ;   dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu )
223      dq_zu = q_zu - q_s ;   dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu )
224
225      znu_a = visc_air(t_zu) ! Air viscosity (m^2/s) at zt given from temperature in (K)
226
227      U_blk = SQRT(U_zu*U_zu + 0.5_wp*0.5_wp) ! initial guess for wind gustiness contribution
228
229      ztmp0   = LOG(    zu*10000._wp) ! optimization: 10000. == 1/z0 (with z0 first guess == 0.0001)
230      ztmp1   = LOG(10._wp*10000._wp) !       "                    "               "
231      u_star = 0.035_wp*U_blk*ztmp1/ztmp0       ! (u* = 0.035*Un10)
232
233      z0     = alfa_charn_3p6(U_zu)*u_star*u_star/grav + 0.11_wp*znu_a/u_star
234      z0     = MIN( MAX(ABS(z0), 1.E-9) , 1._wp )                      ! (prevents FPE from stupid values from masked region later on)
235
236      z0t    = 1._wp / ( 0.1_wp*EXP(vkarmn/(0.00115/(vkarmn/ztmp1))) )
237      z0t    = MIN( MAX(ABS(z0t), 1.E-9) , 1._wp )                      ! (prevents FPE from stupid values from masked region later on)
238
239      Cd     = (vkarmn/ztmp0)**2    ! first guess of Cd
240
241      ztmp0 = vkarmn*vkarmn/LOG(zt/z0t)/Cd
242
243      ztmp2 = Ri_bulk( zu, T_s, t_zu, q_s, q_zu, U_blk ) ! Bulk Richardson Number (BRN)
244
245      !! First estimate of zeta_u, depending on the stability, ie sign of BRN (ztmp2):
246      ztmp1 = 0.5 + SIGN( 0.5_wp , ztmp2 )
247      ztmp0 = ztmp0*ztmp2
248      zeta_u = (1._wp-ztmp1) * (ztmp0/(1._wp+ztmp2/(-zu/(zi0*0.004_wp*Beta0**3)))) & !  BRN < 0
249         &  +     ztmp1   * (ztmp0*(1._wp + 27._wp/9._wp*ztmp2/ztmp0))               !  BRN > 0
250      !#LB: should make sure that the "ztmp0" of "27./9.*ztmp2/ztmp0" is "ztmp0*ztmp2" and not "ztmp0==vkarmn*vkarmn/LOG(zt/z0t)/Cd" !
251
252      !! First guess M-O stability dependent scaling params.(u*,t*,q*) to estimate z0 and z/L
253      ztmp0  = vkarmn/(LOG(zu/z0t) - psi_h_coare(zeta_u))
254
255      u_star = MAX ( U_blk*vkarmn/(LOG(zu) - LOG(z0)  - psi_m_coare(zeta_u)) , 1.E-9 )  !  (MAX => prevents FPE from stupid values from masked region later on)
256      t_star = dt_zu*ztmp0
257      q_star = dq_zu*ztmp0
258
259      ! What needs to be done if zt /= zu:
260      IF( .NOT. l_zt_equal_zu ) THEN
261         !! First update of values at zu (or zt for wind)
262         zeta_t = zt*zeta_u/zu
263         ztmp0 = psi_h_coare(zeta_u) - psi_h_coare(zeta_t)
264         ztmp1 = LOG(zt/zu) + ztmp0
265         t_zu = t_zt - t_star/vkarmn*ztmp1
266         q_zu = q_zt - q_star/vkarmn*ztmp1
267         q_zu = (0.5_wp + SIGN(0.5_wp,q_zu))*q_zu !Makes it impossible to have negative humidity :
268         !
269         dt_zu = t_zu - T_s  ; dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu )
270         dq_zu = q_zu - q_s  ; dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu )
271      END IF
272
273      !! ITERATION BLOCK
274      DO j_itt = 1, nb_itt
275
276         !!Inverse of Monin-Obukov length (1/L) :
277         ztmp0 = One_on_L(t_zu, q_zu, u_star, t_star, q_star)  ! 1/L == 1/[Monin-Obukhov length]
278         ztmp0 = SIGN( MIN(ABS(ztmp0),200._wp), ztmp0 ) ! (prevents FPE from stupid values from masked region later on...)
279
280         ztmp1 = u_star*u_star   ! u*^2
281
282         !! Update wind at zu with convection-related wind gustiness in unstable conditions (Fairall et al. 2003, Eq.8):
283         ztmp2 = Beta0*Beta0*ztmp1*(MAX(-zi0*ztmp0/vkarmn,0._wp))**(2._wp/3._wp) ! square of wind gustiness contribution, ztmp2 == Ug^2
284         !!   ! Only true when unstable (L<0) => when ztmp0 < 0 => explains "-" before zi0
285         U_blk = MAX(SQRT(U_zu*U_zu + ztmp2), 0.2_wp)        ! include gustiness in bulk wind speed
286         ! => 0.2 prevents U_blk to be 0 in stable case when U_zu=0.
287
288         !! Stability parameters:
289         zeta_u = zu*ztmp0
290         zeta_u = SIGN( MIN(ABS(zeta_u),50.0_wp), zeta_u )
291         IF( .NOT. l_zt_equal_zu ) THEN
292            zeta_t = zt*ztmp0
293            zeta_t = SIGN( MIN(ABS(zeta_t),50.0_wp), zeta_t )
294         END IF
295
296         !! Adjustment the wind at 10m (not needed in the current algo form):
297         !IF ( zu \= 10._wp ) U10 = U_zu + u_star/vkarmn*(LOG(10._wp/zu) - psi_m_coare(10._wp*ztmp0) + psi_m_coare(zeta_u))
298
299         !! Roughness lengthes z0, z0t (z0q = z0t) :
300         ztmp2 = u_star/vkarmn*LOG(10./z0)                                 ! Neutral wind speed at 10m
301         z0    = alfa_charn_3p6(ztmp2)*ztmp1/grav + 0.11_wp*znu_a/u_star   ! Roughness length (eq.6) [ ztmp1==u*^2 ]
302         z0     = MIN( MAX(ABS(z0), 1.E-9) , 1._wp )                      ! (prevents FPE from stupid values from masked region later on)
303
304         ztmp1 = ( znu_a / (z0*u_star) )**0.72_wp     ! COARE3.6-specific! (1./Re_r)^0.72 (Re_r: roughness Reynolds number) COARE3.6-specific!
305         z0t   = MIN( 1.6E-4_wp , 5.8E-5_wp*ztmp1 )   ! COARE3.6-specific!
306         z0t   = MIN( MAX(ABS(z0t), 1.E-9) , 1._wp )                      ! (prevents FPE from stupid values from masked region later on)
307
308         !! Turbulent scales at zu :
309         ztmp0   = psi_h_coare(zeta_u)
310         ztmp1   = vkarmn/(LOG(zu) - LOG(z0t) - ztmp0) ! #LB: in ztmp0, some use psi_h_coare(zeta_t) rather than psi_h_coare(zeta_t) ???
311
312         t_star = dt_zu*ztmp1
313         q_star = dq_zu*ztmp1
314         u_star = MAX( U_blk*vkarmn/(LOG(zu) - LOG(z0) - psi_m_coare(zeta_u)) , 1.E-9 )  !  (MAX => prevents FPE from stupid values from masked region later on)
315
316         IF( .NOT. l_zt_equal_zu ) THEN
317            !! Re-updating temperature and humidity at zu if zt /= zu :
318            ztmp1 = LOG(zt/zu) + ztmp0 - psi_h_coare(zeta_t)
319            t_zu = t_zt - t_star/vkarmn*ztmp1
320            q_zu = q_zt - q_star/vkarmn*ztmp1
321         END IF
322
323
324         IF( l_use_cs ) THEN
325            !! Cool-skin contribution
326
327            CALL UPDATE_QNSOL_TAU( zu, T_s, q_s, t_zu, q_zu, u_star, t_star, q_star, U_zu, U_blk, slp, rad_lw, &
328               &                   ztmp1, zeta_u,  Qlat=ztmp2)  ! Qnsol -> ztmp1 / Tau -> zeta_u
329
330            CALL CS_COARE( Qsw, ztmp1, u_star, zsst, ztmp2 )  ! ! Qnsol -> ztmp1 / Qlat -> ztmp2
331
332            T_s(:,:) = zsst(:,:) + dT_cs(:,:)*tmask(:,:,1)
333            IF( l_use_wl ) T_s(:,:) = T_s(:,:) + dT_wl(:,:)*tmask(:,:,1)
334            q_s(:,:) = rdct_qsat_salt*q_sat(MAX(T_s(:,:), 200._wp), slp(:,:))
335
336         END IF
337
338         IF( l_use_wl ) THEN
339            !! Warm-layer contribution
340            CALL UPDATE_QNSOL_TAU( zu, T_s, q_s, t_zu, q_zu, u_star, t_star, q_star, U_zu, U_blk, slp, rad_lw, &
341               &                   ztmp1, zeta_u)  ! Qnsol -> ztmp1 / Tau -> zeta_u
342            !! In WL_COARE or , Tau_ac and Qnt_ac must be updated at the final itteration step => add a flag to do this!
343            CALL WL_COARE( Qsw, ztmp1, zeta_u, zsst, MOD(nb_itt,j_itt) )
344
345            !! Updating T_s and q_s !!!
346            T_s(:,:) = zsst(:,:) + dT_wl(:,:)*tmask(:,:,1)
347            IF( l_use_cs ) T_s(:,:) = T_s(:,:) + dT_cs(:,:)*tmask(:,:,1)
348            q_s(:,:) = rdct_qsat_salt*q_sat(MAX(T_s(:,:), 200._wp), slp(:,:))
349         END IF
350
351         IF( l_use_cs .OR. l_use_wl .OR. (.NOT. l_zt_equal_zu) ) THEN
352            dt_zu = t_zu - T_s ;  dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu )
353            dq_zu = q_zu - q_s ;  dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu )
354         END IF
355
356      END DO !DO j_itt = 1, nb_itt
357
358      ! compute transfer coefficients at zu :
359      ztmp0 = u_star/U_blk
360      Cd   = ztmp0*ztmp0
361      Ch   = ztmp0*t_star/dt_zu
362      Ce   = ztmp0*q_star/dq_zu
363
364      ztmp1 = zu + z0
365      Cdn = vkarmn*vkarmn / (log(ztmp1/z0 )*log(ztmp1/z0 ))
366      Chn = vkarmn*vkarmn / (log(ztmp1/z0t)*log(ztmp1/z0t))
367      Cen = Chn
368
369      IF( .NOT. l_zt_equal_zu ) DEALLOCATE( zeta_t )
370
371      IF ( l_use_cs .AND. PRESENT(pdT_cs) ) pdT_cs = dT_cs
372      IF ( l_use_wl .AND. PRESENT(pdT_wl) ) pdT_wl = dT_wl
373      IF ( l_use_wl .AND. PRESENT(pHz_wl) ) pHz_wl = Hz_wl
374
375      IF ( l_use_cs .OR. l_use_wl ) DEALLOCATE ( zsst )
376
377   END SUBROUTINE turb_coare3p6
378
379
380   FUNCTION alfa_charn_3p6( pwnd )
381      !!-------------------------------------------------------------------
382      !! Computes the Charnock parameter as a function of the Neutral wind speed at 10m
383      !!  "wind speed dependent formulation"
384      !!  (Eq. 13 in Edson et al., 2013)
385      !!
386      !! Author: L. Brodeau, July 2019 / AeroBulk  (https://github.com/brodeau/aerobulk/)
387      !!-------------------------------------------------------------------
388      REAL(wp), DIMENSION(jpi,jpj) :: alfa_charn_3p6
389      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pwnd   ! neutral wind speed at 10m
390      !
391      REAL(wp), PARAMETER :: charn0_max = 0.028  !: value above which the Charnock parameter levels off for winds > 18 m/s
392      !!-------------------------------------------------------------------
393      alfa_charn_3p6 = MAX( MIN( 0.0017_wp*pwnd - 0.005_wp , charn0_max) , 0._wp )
394      !!
395   END FUNCTION alfa_charn_3p6
396
397   FUNCTION alfa_charn_3p6_wave( pus, pwsh, pwps )
398      !!-------------------------------------------------------------------
399      !! Computes the Charnock parameter as a function of wave information and u*
400      !!
401      !!  (COARE 3.6, Fairall et al., 2018)
402      !!
403      !! Author: L. Brodeau, October 2019 / AeroBulk  (https://github.com/brodeau/aerobulk/)
404      !!-------------------------------------------------------------------
405      REAL(wp), DIMENSION(jpi,jpj) :: alfa_charn_3p6_wave
406      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pus   ! friction velocity             [m/s]
407      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pwsh  ! significant wave height       [m]
408      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pwps  ! phase speed of dominant waves [m/s]
409      !!-------------------------------------------------------------------
410      alfa_charn_3p6_wave = ( pwsh*0.2_wp*(pus/pwps)**2.2_wp ) * grav/(pus*pus)
411      !!
412   END FUNCTION alfa_charn_3p6_wave
413
414
415   FUNCTION psi_m_coare( pzeta )
416      !!----------------------------------------------------------------------------------
417      !! ** Purpose: compute the universal profile stability function for momentum
418      !!             COARE 3.0, Fairall et al. 2003
419      !!             pzeta : stability paramenter, z/L where z is altitude
420      !!                     measurement and L is M-O length
421      !!       Stability function for wind speed and scalars matching Kansas and free
422      !!       convection forms with weighting f convective form, follows Fairall et
423      !!       al (1996) with profile constants from Grachev et al (2000) BLM stable
424      !!       form from Beljaars and Holtslag (1991)
425      !!
426      !! ** Author: L. Brodeau, June 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
427      !!----------------------------------------------------------------------------------
428      REAL(wp), DIMENSION(jpi,jpj) :: psi_m_coare
429      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pzeta
430      !
431      INTEGER  ::   ji, jj    ! dummy loop indices
432      REAL(wp) :: zta, zphi_m, zphi_c, zpsi_k, zpsi_c, zf, zc, zstab
433      !!----------------------------------------------------------------------------------
434      !
435      DO jj = 1, jpj
436         DO ji = 1, jpi
437            !
438            zta = pzeta(ji,jj)
439            !
440            zphi_m = ABS(1. - 15.*zta)**.25    !!Kansas unstable
441            !
442            zpsi_k = 2.*LOG((1. + zphi_m)/2.) + LOG((1. + zphi_m*zphi_m)/2.)   &
443               & - 2.*ATAN(zphi_m) + 0.5*rpi
444            !
445            zphi_c = ABS(1. - 10.15*zta)**.3333                   !!Convective
446            !
447            zpsi_c = 1.5*LOG((1. + zphi_c + zphi_c*zphi_c)/3.) &
448               &     - 1.7320508*ATAN((1. + 2.*zphi_c)/1.7320508) + 1.813799447
449            !
450            zf = zta*zta
451            zf = zf/(1. + zf)
452            zc = MIN(50._wp, 0.35_wp*zta)
453            zstab = 0.5 + SIGN(0.5_wp, zta)
454            !
455            psi_m_coare(ji,jj) = (1. - zstab) * ( (1. - zf)*zpsi_k + zf*zpsi_c ) & ! (zta < 0)
456               &                -   zstab     * ( 1. + 1.*zta     &                ! (zta > 0)
457               &                         + 0.6667*(zta - 14.28)/EXP(zc) + 8.525 )   !     "
458            !
459         END DO
460      END DO
461      !
462   END FUNCTION psi_m_coare
463
464
465   FUNCTION psi_h_coare( pzeta )
466      !!---------------------------------------------------------------------
467      !! Universal profile stability function for temperature and humidity
468      !! COARE 3.0, Fairall et al. 2003
469      !!
470      !! pzeta : stability paramenter, z/L where z is altitude measurement
471      !!         and L is M-O length
472      !!
473      !! Stability function for wind speed and scalars matching Kansas and free
474      !! convection forms with weighting f convective form, follows Fairall et
475      !! al (1996) with profile constants from Grachev et al (2000) BLM stable
476      !! form from Beljaars and Holtslag (1991)
477      !!
478      !! Author: L. Brodeau, June 2016 / AeroBulk
479      !!         (https://github.com/brodeau/aerobulk/)
480      !!----------------------------------------------------------------
481      !!
482      REAL(wp), DIMENSION(jpi,jpj) :: psi_h_coare
483      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pzeta
484      !
485      INTEGER  ::   ji, jj     ! dummy loop indices
486      REAL(wp) :: zta, zphi_h, zphi_c, zpsi_k, zpsi_c, zf, zc, zstab
487      !
488      DO jj = 1, jpj
489         DO ji = 1, jpi
490            !
491            zta = pzeta(ji,jj)
492            !
493            zphi_h = (ABS(1. - 15.*zta))**.5  !! Kansas unstable   (zphi_h = zphi_m**2 when unstable, zphi_m when stable)
494            !
495            zpsi_k = 2.*LOG((1. + zphi_h)/2.)
496            !
497            zphi_c = (ABS(1. - 34.15*zta))**.3333   !! Convective
498            !
499            zpsi_c = 1.5*LOG((1. + zphi_c + zphi_c*zphi_c)/3.) &
500               &    -1.7320508*ATAN((1. + 2.*zphi_c)/1.7320508) + 1.813799447
501            !
502            zf = zta*zta
503            zf = zf/(1. + zf)
504            zc = MIN(50._wp,0.35_wp*zta)
505            zstab = 0.5 + SIGN(0.5_wp, zta)
506            !
507            psi_h_coare(ji,jj) = (1. - zstab) * ( (1. - zf)*zpsi_k + zf*zpsi_c ) &
508               &                -   zstab     * ( (ABS(1. + 2.*zta/3.))**1.5     &
509               &                           + .6667*(zta - 14.28)/EXP(zc) + 8.525 )
510            !
511         END DO
512      END DO
513      !
514   END FUNCTION psi_h_coare
515
516   !!======================================================================
517END MODULE sbcblk_algo_coare3p6
Note: See TracBrowser for help on using the repository browser.