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 @ 11329

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

LB: cosmetic syntax homogenization.

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