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_coare.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_coare.F90 @ 11217

Last change on this file since 11217 was 11215, checked in by laurent, 5 years ago

LB: inclusion of "cool-skin/warm-layer" support (a la ECMWF) into COARE 3.0 algorithm.

  • Property svn:keywords set to Id
File size: 21.4 KB
Line 
1MODULE sbcblk_algo_coare
2   !!======================================================================
3   !!                   ***  MODULE  sbcblk_algo_coare  ***
4   !! Computes:
5   !!   * bulk transfer coefficients C_D, C_E and C_H
6   !!   * air temp. and spec. hum. adjusted from zt (2m) to zu (10m) if needed
7   !!   * the effective bulk wind speed at 10m U_blk
8   !!   => all these are used in bulk formulas in sbcblk.F90
9   !!
10   !!    Using the bulk formulation/param. of COARE v3, Fairall et al., 2003
11   !!
12   !!       Routine turb_coare 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_coare  : 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     ! cool-skin/warm layer scheme (CSWL_ECMWF) !LB
41
42   IMPLICIT NONE
43   PRIVATE
44
45   PUBLIC ::   TURB_COARE   ! called by sbcblk.F90
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.250_wp   ! gustiness parameter
50
51   INTEGER , PARAMETER ::   nb_itt = 5             ! number of itterations
52
53   !!----------------------------------------------------------------------
54CONTAINS
55
56   SUBROUTINE turb_coare( zt, zu, T_s, t_zt, q_s, q_zt, U_zu, &
57      &                   Cd, Ch, Ce, t_zu, q_zu, U_blk,      &
58      &                   Cdn, Chn, Cen,                      &
59      &                   Qsw, rad_lw, slp                   )
60      !!----------------------------------------------------------------------
61      !!                      ***  ROUTINE  turb_coare  ***
62      !!
63      !! ** Purpose :   Computes turbulent transfert coefficients of surface
64      !!                fluxes according to Fairall et al. (2003)
65      !!                If relevant (zt /= zu), adjust temperature and humidity from height zt to zu
66      !!                Returns the effective bulk wind speed at 10m to be used in the bulk formulas
67      !!
68      !!                Applies the cool-skin warm-layer correction of the SST to T_s
69      !!                if the net shortwave flux at the surface (Qsw), the downwelling longwave
70      !!                radiative fluxes at the surface (rad_lw), and the sea-leve pressure (slp)
71      !!                are provided as (optional) arguments!
72      !!
73      !! INPUT :
74      !! -------
75      !!    *  zt   : height for temperature and spec. hum. of air            [m]
76      !!    *  zu   : height for wind speed (generally 10m)                   [m]
77      !!    *  U_zu : scalar wind speed at 10m                                [m/s]
78      !!    *  t_zt : potential air temperature at zt                         [K]
79      !!    *  q_zt : specific humidity of air at zt                          [kg/kg]
80      !!
81      !! INPUT/OUTPUT:
82      !! -------------
83      !!    *  T_s  : SST or skin temperature                                 [K]
84      !!    *  q_s  : SSQ aka saturation specific humidity at temp. T_s       [kg/kg]
85      !!              -> doesn't need to be given a value if skin temp computed (in case l_use_skin=True)
86      !!              -> MUST be given the correct value if not computing skint temp. (in case l_use_skin=False)
87      !!
88      !! OPTIONAL INPUT (will trigger l_use_skin=TRUE if present!):
89      !! ---------------
90      !!    *  Qsw    : net solar flux (after albedo) at the surface (>0)     [W/m^2]
91      !!    *  rad_lw : downwelling longwave radiation at the surface  (>0)   [W/m^2]
92      !!    *  slp    : sea-level pressure                                    [Pa]
93      !!
94      !! OUTPUT :
95      !! --------
96      !!    *  Cd     : drag coefficient
97      !!    *  Ch     : sensible heat coefficient
98      !!    *  Ce     : evaporation coefficient
99      !!    *  t_zu   : pot. air temperature adjusted at wind height zu       [K]
100      !!    *  q_zu   : specific humidity of air        //                    [kg/kg]
101      !!    *  U_blk  : bulk wind speed at 10m                                [m/s]
102      !!
103      !!
104      !! ** Author: L. Brodeau, June 2019 / AeroBulk (https://github.com/brodeau/aerobulk/)
105      !!----------------------------------------------------------------------------------
106      REAL(wp), INTENT(in   )                     ::   zt       ! height for t_zt and q_zt                    [m]
107      REAL(wp), INTENT(in   )                     ::   zu       ! height for U_zu                             [m]
108      REAL(wp), INTENT(inout), DIMENSION(jpi,jpj) ::   T_s      ! sea surface temperature                [Kelvin]
109      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   t_zt     ! potential air temperature              [Kelvin]
110      REAL(wp), INTENT(inout), DIMENSION(jpi,jpj) ::   q_s      ! sea surface specific humidity           [kg/kg]
111      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   q_zt     ! specific air humidity at zt             [kg/kg]
112      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   U_zu     ! relative wind module at zu                [m/s]
113      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Cd       ! transfer coefficient for momentum         (tau)
114      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Ch       ! transfer coefficient for sensible heat (Q_sens)
115      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Ce       ! transfert coefficient for evaporation   (Q_lat)
116      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   t_zu     ! pot. air temp. adjusted at zu               [K]
117      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   q_zu     ! spec. humidity adjusted at zu           [kg/kg]
118      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   U_blk    ! bulk wind at 10m                          [m/s]
119      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Cdn, Chn, Cen ! neutral transfer coefficients
120      !
121      REAL(wp), INTENT(in   ), OPTIONAL, DIMENSION(jpi,jpj) ::   Qsw      !             [W/m^2]
122      REAL(wp), INTENT(in   ), OPTIONAL, DIMENSION(jpi,jpj) ::   rad_lw   !             [W/m^2]
123      REAL(wp), INTENT(in   ), OPTIONAL, DIMENSION(jpi,jpj) ::   slp      !             [Pa]
124      !
125      INTEGER :: j_itt
126      LOGICAL :: l_zt_equal_zu = .FALSE.      ! if q and t are given at same height as U
127      !
128      REAL(wp), DIMENSION(jpi,jpj) ::  &
129         &  u_star, t_star, q_star, &
130         &  dt_zu, dq_zu,    &
131         &  znu_a,           & !: Nu_air, Viscosity of air
132         &  z0, z0t
133      REAL(wp), DIMENSION(jpi,jpj) ::   zeta_u        ! stability parameter at height zu
134      REAL(wp), DIMENSION(jpi,jpj) ::   ztmp0, ztmp1, ztmp2
135      REAL(wp), DIMENSION(:,:), ALLOCATABLE ::   zeta_t        ! stability parameter at height zt
136      !
137      ! Cool skin:
138      LOGICAL :: l_use_skin = .FALSE.
139      REAL(wp), DIMENSION(jpi,jpj) :: zsst    ! to back up the initial bulk SST
140      !!----------------------------------------------------------------------------------
141      !
142      ! Cool skin ?
143      IF( PRESENT(Qsw) .AND. PRESENT(rad_lw) .AND. PRESENT(slp) ) THEN
144         l_use_skin = .TRUE.
145      END IF
146      IF (lwp) PRINT *, ' *** LOLO(sbcblk_algo_ecmwf.F90) => l_use_skin =', l_use_skin
147
148      l_zt_equal_zu = .FALSE.
149      IF( ABS(zu - zt) < 0.01_wp )   l_zt_equal_zu = .TRUE.    ! testing "zu == zt" is risky with double precision
150
151      IF( .NOT. l_zt_equal_zu )  ALLOCATE( zeta_t(jpi,jpj) )
152
153      !! Initialization for cool skin:
154      IF( l_use_skin ) THEN
155         zsst   = T_s    ! save the bulk SST
156         T_s    = T_s - 0.25                      ! First guess of correction
157         q_s    = rdct_qsat_salt*q_sat(MAX(T_s, 200._wp), slp) ! First guess of q_s
158      END IF
159
160      !! First guess of temperature and humidity at height zu:
161      t_zu = MAX( t_zt ,  180._wp )   ! who knows what's given on masked-continental regions...
162      q_zu = MAX( q_zt , 1.e-6_wp )   !               "
163
164      !! Pot. temp. difference (and we don't want it to be 0!)
165      dt_zu = t_zu - T_s ;   dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu )
166      dq_zu = q_zu - q_s ;   dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu )
167
168      znu_a = visc_air(t_zu) ! Air viscosity (m^2/s) at zt given from temperature in (K)
169
170      ztmp2 = 0.5_wp*0.5_wp  ! initial guess for wind gustiness contribution
171      U_blk = SQRT(U_zu*U_zu + ztmp2)
172
173      ztmp2   = 10000._wp     ! optimization: ztmp2 == 1/z0 (with z0 first guess == 0.0001)
174      ztmp0   = LOG(zu*ztmp2)
175      ztmp1   = LOG(10.*ztmp2)
176      u_star = 0.035_wp*U_blk*ztmp1/ztmp0       ! (u* = 0.035*Un10)
177
178      z0     = alfa_charn(U_blk)*u_star*u_star/grav + 0.11_wp*znu_a/u_star
179      z0     = MIN(ABS(z0), 0.001_wp)  ! (prevent FPE from stupid values from masked region later on...) !#LOLO
180      z0t    = 1._wp / ( 0.1_wp*EXP(vkarmn/(0.00115/(vkarmn/ztmp1))) )
181      z0t    = MIN(ABS(z0t), 0.001_wp)  ! (prevent FPE from stupid values from masked region later on...) !#LOLO
182
183      ztmp2  = vkarmn/ztmp0
184      Cd     = ztmp2*ztmp2    ! first guess of Cd
185
186      ztmp0 = vkarmn*vkarmn/LOG(zt/z0t)/Cd
187
188      ztmp2 = Ri_bulk( zu, T_s, t_zu, q_s, q_zu, U_blk ) ! Bulk Richardson Number (BRN)
189
190      !! First estimate of zeta_u, depending on the stability, ie sign of BRN (ztmp2):
191      ztmp1 = 0.5 + SIGN( 0.5_wp , ztmp2 )
192      ztmp0 = ztmp0*ztmp2
193      zeta_u = (1._wp-ztmp1) * (ztmp0/(1._wp+ztmp2/(-zu/(zi0*0.004_wp*Beta0**3)))) & !  BRN < 0
194         &  +     ztmp1   * (ztmp0*(1._wp + 27._wp/9._wp*ztmp2/ztmp0))               !  BRN > 0
195      !#LB: should make sure that the "ztmp0" of "27./9.*ztmp2/ztmp0" is "ztmp0*ztmp2" and not "ztmp0==vkarmn*vkarmn/LOG(zt/z0t)/Cd" !
196
197      !! First guess M-O stability dependent scaling params.(u*,t*,q*) to estimate z0 and z/L
198      ztmp0  = vkarmn/(LOG(zu/z0t) - psi_h_coare(zeta_u))
199
200      u_star = U_blk*vkarmn/(LOG(zu) - LOG(z0)  - psi_m_coare(zeta_u))
201      t_star = dt_zu*ztmp0
202      q_star = dq_zu*ztmp0
203
204      ! What's need to be done if zt /= zu:
205      IF( .NOT. l_zt_equal_zu ) THEN
206         !! First update of values at zu (or zt for wind)
207         zeta_t = zt*zeta_u/zu
208         ztmp0 = psi_h_coare(zeta_u) - psi_h_coare(zeta_t)
209         ztmp1 = LOG(zt/zu) + ztmp0
210         t_zu = t_zt - t_star/vkarmn*ztmp1
211         q_zu = q_zt - q_star/vkarmn*ztmp1
212         q_zu = (0.5_wp + SIGN(0.5_wp,q_zu))*q_zu !Makes it impossible to have negative humidity :
213         !
214         dt_zu = t_zu - T_s  ; dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu )
215         dq_zu = q_zu - q_s  ; dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu )
216      END IF
217
218      !! ITERATION BLOCK
219      DO j_itt = 1, nb_itt
220
221         !!Inverse of Monin-Obukov length (1/L) :
222         ztmp0 = One_on_L(t_zu, q_zu, u_star, t_star, q_star)  ! 1/L == 1/[Monin-Obukhov length]
223         ztmp0 = SIGN( MIN(ABS(ztmp0),200._wp), ztmp0 ) ! (prevents FPE from stupid values from masked region later on...) !#LOLO
224
225         ztmp1 = u_star*u_star   ! u*^2
226
227         !! Update wind at 10m taking into acount convection-related wind gustiness:
228         ! Ug = Beta*w*  (Beta = 1.25, Fairall et al. 2003, Eq.8):
229         ztmp2 = Beta0*Beta0*ztmp1*(MAX(-zi0*ztmp0/vkarmn,0._wp))**(2./3.)   ! => ztmp2 == Ug^2
230         !!   ! Only true when unstable (L<0) => when ztmp0 < 0 => explains "-" before 600.
231         U_blk = MAX(sqrt(U_zu*U_zu + ztmp2), 0.2_wp)        ! include gustiness in bulk wind speed
232         ! => 0.2 prevents U_blk to be 0 in stable case when U_zu=0.
233
234         !! Updating Charnock parameter, increases with the wind (Fairall et al., 2003 p. 577-578)
235         ztmp2 = alfa_charn(U_blk)  ! alpha Charnock parameter
236
237         !! Roughness lengthes z0, z0t (z0q = z0t) :
238         z0    = ztmp2*ztmp1/grav + 0.11_wp*znu_a/u_star  ! Roughness length (eq.6)
239         ztmp1 = z0*u_star/znu_a                          ! Re_r: roughness Reynolds number
240         z0t  = MIN( 1.1E-4_wp , 5.5E-5_wp*ztmp1**(-0.6_wp) ) ! Scalar roughness for both theta and q (eq.28)
241
242         !! Stability parameters:
243         zeta_u = zu*ztmp0
244         zeta_u = SIGN( MIN(ABS(zeta_u),50.0_wp), zeta_u )
245         IF( .NOT. l_zt_equal_zu ) THEN
246            zeta_t = zt*ztmp0
247            zeta_t = SIGN( MIN(ABS(zeta_t),50.0_wp), zeta_t )
248         END IF
249
250         !! Turbulent scales at zu=10m :
251         ztmp0   = psi_h_coare(zeta_u)
252         ztmp1   = vkarmn/(LOG(zu) - LOG(z0t) - ztmp0)
253
254         t_star = dt_zu*ztmp1
255         q_star = dq_zu*ztmp1
256         u_star = U_blk*vkarmn/(LOG(zu) - LOG(z0) - psi_m_coare(zeta_u))
257
258         IF( .NOT. l_zt_equal_zu ) THEN
259            ! What's need to be done if zt /= zu
260            !! Re-updating temperature and humidity at zu :
261            ztmp2 = ztmp0 - psi_h_coare(zeta_t)
262            ztmp1 = log(zt/zu) + ztmp2
263            t_zu = t_zt - t_star/vkarmn*ztmp1
264            q_zu = q_zt - q_star/vkarmn*ztmp1
265         END IF
266
267         !! SKIN related part
268         !! -----------------
269         IF( l_use_skin ) THEN
270            !! compute transfer coefficients at zu : lolo: verifier...
271            ztmp0 = u_star/U_blk
272            Ch   = ztmp0*t_star/dt_zu
273            Ce   = ztmp0*q_star/dq_zu
274            ! Non-Solar heat flux to the ocean:
275            ztmp1 = U_blk*MAX(rho_air(t_zu, q_zu, slp), 1._wp)     ! rho*U10
276            ztmp2 = T_s*T_s
277            ztmp1 = ztmp1 * ( Ce*rLevap*(q_zu - q_s) + Ch*rCp_dry*(t_zu - T_s) ) & ! Total turb. heat flux
278               &       +    (rad_lw - emiss_w*stefan*ztmp2*ztmp2)                  ! Net longwave flux
279            !! Updating the values of the skin temperature T_s and q_s :
280            CALL CSWL_ECMWF( Qsw, ztmp1, u_star, zsst, T_s ) ! yes ECMWF, because more advanced than COARE (warm-layer added!)
281            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
282         END IF
283
284         IF( (l_use_skin).OR.(.NOT. l_zt_equal_zu) ) THEN
285            dt_zu = t_zu - T_s ;  dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6_wp), dt_zu )
286            dq_zu = q_zu - q_s ;  dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9_wp), dq_zu )
287         END IF
288
289      END DO !DO j_itt = 1, nb_itt
290
291      ! compute transfer coefficients at zu :
292      ztmp0 = u_star/U_blk
293      Cd   = ztmp0*ztmp0
294      Ch   = ztmp0*t_star/dt_zu
295      Ce   = ztmp0*q_star/dq_zu
296      !
297      ztmp1 = zu + z0
298      Cdn = vkarmn*vkarmn / (log(ztmp1/z0 )*log(ztmp1/z0 ))
299      Chn = vkarmn*vkarmn / (log(ztmp1/z0t)*log(ztmp1/z0t))
300      Cen = Chn
301      !
302      IF( .NOT. l_zt_equal_zu ) DEALLOCATE( zeta_t )
303      !
304   END SUBROUTINE turb_coare
305
306
307   FUNCTION alfa_charn( pwnd )
308      !!-------------------------------------------------------------------
309      !! Compute the Charnock parameter as a function of the wind speed
310      !!
311      !! (Fairall et al., 2003 p.577-578)
312      !!
313      !! Wind below 10 m/s :  alfa = 0.011
314      !! Wind between 10 and 18 m/s : linear increase from 0.011 to 0.018
315      !! Wind greater than 18 m/s :  alfa = 0.018
316      !!
317      !! Author: L. Brodeau, June 2016 / AeroBulk  (https://github.com/brodeau/aerobulk/)
318      !!-------------------------------------------------------------------
319      REAL(wp), DIMENSION(jpi,jpj) :: alfa_charn
320      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pwnd   ! wind speed
321      !
322      INTEGER  ::   ji, jj         ! dummy loop indices
323      REAL(wp) :: zw, zgt10, zgt18
324      !!-------------------------------------------------------------------
325      !
326      DO jj = 1, jpj
327         DO ji = 1, jpi
328            !
329            zw = pwnd(ji,jj)   ! wind speed
330            !
331            ! Charnock's constant, increases with the wind :
332            zgt10 = 0.5 + SIGN(0.5_wp,(zw - 10)) ! If zw<10. --> 0, else --> 1
333            zgt18 = 0.5 + SIGN(0.5_wp,(zw - 18.)) ! If zw<18. --> 0, else --> 1
334            !
335            alfa_charn(ji,jj) =  (1. - zgt10)*0.011    &    ! wind is lower than 10 m/s
336               &     + zgt10*((1. - zgt18)*(0.011 + (0.018 - 0.011) &
337               &      *(zw - 10.)/(18. - 10.)) + zgt18*( 0.018 ) )    ! Hare et al. (1999)
338            !
339         END DO
340      END DO
341      !
342   END FUNCTION alfa_charn
343
344   FUNCTION psi_m_coare( pzeta )
345      !!----------------------------------------------------------------------------------
346      !! ** Purpose: compute the universal profile stability function for momentum
347      !!             COARE 3.0, Fairall et al. 2003
348      !!             pzeta : stability paramenter, z/L where z is altitude
349      !!                     measurement and L is M-O length
350      !!       Stability function for wind speed and scalars matching Kansas and free
351      !!       convection forms with weighting f convective form, follows Fairall et
352      !!       al (1996) with profile constants from Grachev et al (2000) BLM stable
353      !!       form from Beljaars and Holtslag (1991)
354      !!
355      !! ** Author: L. Brodeau, June 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
356      !!----------------------------------------------------------------------------------
357      REAL(wp), DIMENSION(jpi,jpj) :: psi_m_coare
358      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pzeta
359      !
360      INTEGER  ::   ji, jj    ! dummy loop indices
361      REAL(wp) :: zta, zphi_m, zphi_c, zpsi_k, zpsi_c, zf, zc, zstab
362      !!----------------------------------------------------------------------------------
363      !
364      DO jj = 1, jpj
365         DO ji = 1, jpi
366            !
367            zta = pzeta(ji,jj)
368            !
369            zphi_m = ABS(1. - 15.*zta)**.25    !!Kansas unstable
370            !
371            zpsi_k = 2.*LOG((1. + zphi_m)/2.) + LOG((1. + zphi_m*zphi_m)/2.)   &
372               & - 2.*ATAN(zphi_m) + 0.5*rpi
373            !
374            zphi_c = ABS(1. - 10.15*zta)**.3333                   !!Convective
375            !
376            zpsi_c = 1.5*LOG((1. + zphi_c + zphi_c*zphi_c)/3.) &
377               &     - 1.7320508*ATAN((1. + 2.*zphi_c)/1.7320508) + 1.813799447
378            !
379            zf = zta*zta
380            zf = zf/(1. + zf)
381            zc = MIN(50._wp, 0.35_wp*zta)
382            zstab = 0.5 + SIGN(0.5_wp, zta)
383            !
384            psi_m_coare(ji,jj) = (1. - zstab) * ( (1. - zf)*zpsi_k + zf*zpsi_c ) & ! (zta < 0)
385               &                -   zstab     * ( 1. + 1.*zta     &                ! (zta > 0)
386               &                         + 0.6667*(zta - 14.28)/EXP(zc) + 8.525 )   !     "
387            !
388         END DO
389      END DO
390      !
391   END FUNCTION psi_m_coare
392
393
394   FUNCTION psi_h_coare( pzeta )
395      !!---------------------------------------------------------------------
396      !! Universal profile stability function for temperature and humidity
397      !! COARE 3.0, Fairall et al. 2003
398      !!
399      !! pzeta : stability paramenter, z/L where z is altitude measurement
400      !!         and L is M-O length
401      !!
402      !! Stability function for wind speed and scalars matching Kansas and free
403      !! convection forms with weighting f convective form, follows Fairall et
404      !! al (1996) with profile constants from Grachev et al (2000) BLM stable
405      !! form from Beljaars and Holtslag (1991)
406      !!
407      !! Author: L. Brodeau, June 2016 / AeroBulk
408      !!         (https://github.com/brodeau/aerobulk/)
409      !!----------------------------------------------------------------
410      !!
411      REAL(wp), DIMENSION(jpi,jpj) :: psi_h_coare
412      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pzeta
413      !
414      INTEGER  ::   ji, jj     ! dummy loop indices
415      REAL(wp) :: zta, zphi_h, zphi_c, zpsi_k, zpsi_c, zf, zc, zstab
416      !
417      DO jj = 1, jpj
418         DO ji = 1, jpi
419            !
420            zta = pzeta(ji,jj)
421            !
422            zphi_h = (ABS(1. - 15.*zta))**.5  !! Kansas unstable   (zphi_h = zphi_m**2 when unstable, zphi_m when stable)
423            !
424            zpsi_k = 2.*LOG((1. + zphi_h)/2.)
425            !
426            zphi_c = (ABS(1. - 34.15*zta))**.3333   !! Convective
427            !
428            zpsi_c = 1.5*LOG((1. + zphi_c + zphi_c*zphi_c)/3.) &
429               &    -1.7320508*ATAN((1. + 2.*zphi_c)/1.7320508) + 1.813799447
430            !
431            zf = zta*zta
432            zf = zf/(1. + zf)
433            zc = MIN(50._wp,0.35_wp*zta)
434            zstab = 0.5 + SIGN(0.5_wp, zta)
435            !
436            psi_h_coare(ji,jj) = (1. - zstab) * ( (1. - zf)*zpsi_k + zf*zpsi_c ) &
437               &                -   zstab     * ( (ABS(1. + 2.*zta/3.))**1.5     &
438               &                           + .6667*(zta - 14.28)/EXP(zc) + 8.525 )
439            !
440         END DO
441      END DO
442      !
443   END FUNCTION psi_h_coare
444
445   !!======================================================================
446END MODULE sbcblk_algo_coare
Note: See TracBrowser for help on using the repository browser.