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_coare3p5.F90 in branches/2017/dev_r7881_no_wrk_alloc/NEMOGCM/NEMO/OPA_SRC/SBC – NEMO

source: branches/2017/dev_r7881_no_wrk_alloc/NEMOGCM/NEMO/OPA_SRC/SBC/sbcblk_algo_coare3p5.F90 @ 7910

Last change on this file since 7910 was 7910, checked in by timgraham, 7 years ago

All wrk_alloc removed

File size: 19.1 KB
Line 
1MODULE sbcblk_algo_coare3p5
2   !!======================================================================
3   !!                       ***  MODULE  sbcblk_algo_coare3p5  ***
4   !! Computes turbulent components of surface fluxes
5   !!         according to Edson et al. 2013 (COARE v3.5) /JPO
6   !!
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   !!    Using the bulk formulation/param. of COARE v3.5, Edson et al. 2013
13   !!
14   !!
15   !!       Routine turb_coare3p5 maintained and developed in AeroBulk
16   !!                     (http://aerobulk.sourceforge.net/)
17   !!
18   !!            Author: Laurent Brodeau, 2016, brodeau@gmail.com
19   !!
20   !!======================================================================
21   !! History :  3.6  !  2016-02  (L.Brodeau)  Original code
22   !!----------------------------------------------------------------------
23
24   !!----------------------------------------------------------------------
25   !!   turb_coare3p5  : computes the bulk turbulent transfer coefficients
26   !!                   adjusts t_air and q_air from zt to zu m
27   !!                   returns the effective bulk wind speed at 10m
28   !!----------------------------------------------------------------------
29   USE oce             ! ocean dynamics and tracers
30   USE dom_oce         ! ocean space and time domain
31   USE phycst          ! physical constants
32   USE sbc_oce         ! Surface boundary condition: ocean fields
33   USE sbcwave, ONLY   :  cdn_wave ! wave module
34#if defined key_lim3 || defined key_cice
35   USE sbc_ice         ! Surface boundary condition: ice fields
36#endif
37   !
38   USE iom             ! I/O manager library
39   USE lib_mpp         ! distribued memory computing library
40   USE timing          ! Timing
41   USE in_out_manager  ! I/O manager
42   USE prtctl          ! Print control
43   USE lib_fortran     ! to use key_nosignedzero
44
45   IMPLICIT NONE
46   PRIVATE
47
48   PUBLIC ::   TURB_COARE3P5   ! called by sbcblk.F90
49
50   !                                   ! COARE own values for given constants:
51   REAL(wp), PARAMETER ::   charn0_max =   0.028   ! value above which the Charnock paramter levels off for winds > 18
52   REAL(wp), PARAMETER ::   zi0        = 600.      ! scale height of the atmospheric boundary layer...1
53   REAL(wp), PARAMETER ::   Beta0      =   1.25    ! gustiness parameter
54   REAL(wp), PARAMETER ::   rctv0      =   0.608   ! constant to obtain virtual temperature...
55
56   !!----------------------------------------------------------------------
57CONTAINS
58
59   SUBROUTINE turb_coare3p5( zt, zu, sst, t_zt, ssq, q_zt, U_zu, &
60      &                   Cd, Ch, Ce, t_zu, q_zu, U_blk )
61      !!----------------------------------------------------------------------------------
62      !!                      ***  ROUTINE  turb_coare3p5  ***
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      !!
68      !! ** Method : Monin Obukhov Similarity Theory
69      !!
70      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)
71      !!
72      !! INPUT :
73      !! -------
74      !!    *  zt   : height for temperature and spec. hum. of air            [m]
75      !!    *  zu   : height for wind speed (generally 10m)                   [m]
76      !!    *  U_zu : scalar wind speed at 10m                                [m/s]
77      !!    *  sst  : SST                                                     [K]
78      !!    *  t_zt : potential air temperature at zt                         [K]
79      !!    *  ssq  : specific humidity at saturation at SST                  [kg/kg]
80      !!    *  q_zt : specific humidity of air at zt                          [kg/kg]
81      !!
82      !!
83      !! OUTPUT :
84      !! --------
85      !!    *  Cd     : drag coefficient
86      !!    *  Ch     : sensible heat coefficient
87      !!    *  Ce     : evaporation coefficient
88      !!    *  t_zu   : pot. air temperature adjusted at wind height zu       [K]
89      !!    *  q_zu   : specific humidity of air        //                    [kg/kg]
90      !!    *  U_blk  : bulk wind at 10m                                      [m/s]
91      !!
92      !!----------------------------------------------------------------------------------
93      REAL(wp), INTENT(in   )                     ::   zt       ! height for t_zt and q_zt                   [m]
94      REAL(wp), INTENT(in   )                     ::   zu       ! height for U_zu                              [m]
95      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   sst      ! sea surface temperature              [Kelvin]
96      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   t_zt     ! potential air temperature            [Kelvin]
97      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   ssq      ! sea surface specific humidity         [kg/kg]
98      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   q_zt     ! specific air humidity                 [kg/kg]
99      REAL(wp), INTENT(in   ), DIMENSION(jpi,jpj) ::   U_zu     ! relative wind module at zu            [m/s]
100      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Cd       ! transfer coefficient for momentum         (tau)
101      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Ch       ! transfer coefficient for sensible heat (Q_sens)
102      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   Ce       ! transfert coefficient for evaporation   (Q_lat)
103      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   t_zu     ! pot. air temp. adjusted at zu             [K]
104      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   q_zu     ! spec. humidity adjusted at zu             [kg/kg]
105      REAL(wp), INTENT(  out), DIMENSION(jpi,jpj) ::   U_blk    ! bulk wind at 10m                          [m/s]
106      !
107      INTEGER :: j_itt
108      LOGICAL ::   l_zt_equal_zu = .FALSE.      ! if q and t are given at same height as U
109      INTEGER , PARAMETER ::   nb_itt = 4       ! number of itterations
110      !
111
112      REAL(wp), DIMENSION(jpi,jpj) ::   u_star, t_star, q_star 
113      REAL(wp), DIMENSION(jpi,jpj) ::   dt_zu, dq_zu   
114      REAL(wp), DIMENSION(jpi,jpj) ::   znu_a            !: Nu_air, Viscosity of air
115      REAL(wp), DIMENSION(jpi,jpj) ::   z0, z0t
116      REAL(wp), DIMENSION(jpi,jpj) ::   zeta_u        ! stability parameter at height zu
117      REAL(wp), DIMENSION(jpi,jpj) ::   zeta_t        ! stability parameter at height zt
118      REAL(wp), DIMENSION(jpi,jpj) ::   ztmp0, ztmp1, ztmp2
119      !!----------------------------------------------------------------------------------
120      !
121      IF( nn_timing == 1 )  CALL timing_start('turb_coare3p5')
122
123
124      l_zt_equal_zu = .FALSE.
125      IF( ABS(zu - zt) < 0.01 ) l_zt_equal_zu = .TRUE.    ! testing "zu == zt" is risky with double precision
126
127
128      !! First guess of temperature and humidity at height zu:
129      t_zu = MAX(t_zt , 0.0)    ! who knows what's given on masked-continental regions...
130      q_zu = MAX(q_zt , 1.E-6)  !               "
131
132      !! Pot. temp. difference (and we don't want it to be 0!)
133      dt_zu = t_zu - sst ;  dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6), dt_zu )
134      dq_zu = q_zu - ssq ;  dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9), dq_zu )
135
136      znu_a = visc_air(t_zt) ! Air viscosity (m^2/s) at zt given from temperature in (K)
137
138      ztmp2 = 0.5*0.5  ! initial guess for wind gustiness contribution
139      U_blk = SQRT(U_zu*U_zu + ztmp2)
140
141      ztmp2   = 10000.     ! optimization: ztmp2 == 1/z0 (with z0 first guess == 0.0001)
142      ztmp0   = LOG(zu*ztmp2)
143      ztmp1   = LOG(10.*ztmp2)
144      u_star = 0.035*U_blk*ztmp1/ztmp0       ! (u* = 0.035*Un10)
145
146      !! COARE 3.5 first guess of UN10 is U_zu
147      ztmp2 = MIN( 0.0017*U_zu - 0.005 , charn0_max)  ! alpha Charnock parameter (Eq. 13 Edson al. 2013)
148      ztmp2 = MAX( ztmp2 , 0. )                       ! alpha Charnock parameter (Eq. 13 Edson al. 2013)
149      z0     = ztmp2*u_star*u_star/grav + 0.11*znu_a/u_star
150      z0t    = 0.1*EXP(vkarmn/(0.00115/(vkarmn/ztmp1)))   !  WARNING: 1/z0t !
151
152      ztmp2  = vkarmn/ztmp0
153      Cd     = ztmp2*ztmp2    ! first guess of Cd
154
155      ztmp0 = vkarmn*vkarmn/LOG(zt*z0t)/Cd
156
157      !Ribcu = -zu/(zi0*0.004*Beta0**3) !! Saturation Rib, zi0 = tropicalbound. layer depth
158      ztmp2  = grav*zu*(dt_zu + rctv0*t_zu*dq_zu)/(t_zu*U_blk*U_blk)  !! Ribu Bulk Richardson number
159      ztmp1 = 0.5 + sign(0.5 , ztmp2)
160      ztmp0 = ztmp0*ztmp2
161      !!             Ribu < 0                                 Ribu > 0   Beta = 1.25
162      zeta_u = (1.-ztmp1) * (ztmp0/(1.+ztmp2/(-zu/(zi0*0.004*Beta0**3)))) &
163         &  +     ztmp1   * (ztmp0*(1. + 27./9.*ztmp2/ztmp0))
164
165      !! First guess M-O stability dependent scaling params.(u*,t*,q*) to estimate z0 and z/L
166      ztmp0  =  vkarmn/(LOG(zu*z0t) - psi_h_coare(zeta_u))
167
168      u_star = U_blk*vkarmn/(LOG(zu) - LOG(z0)  - psi_m_coare(zeta_u))
169      t_star = dt_zu*ztmp0
170      q_star = dq_zu*ztmp0
171
172      ! What's need to be done if zt /= zu:
173      IF( .NOT. l_zt_equal_zu ) THEN
174
175         zeta_t = zt*zeta_u/zu
176
177         !! First update of values at zu (or zt for wind)
178         ztmp0 = psi_h_coare(zeta_u) - psi_h_coare(zeta_t)
179         ztmp1 = log(zt/zu) + ztmp0
180         t_zu = t_zt - t_star/vkarmn*ztmp1
181         q_zu = q_zt - q_star/vkarmn*ztmp1
182         q_zu = (0.5 + sign(0.5,q_zu))*q_zu !Makes it impossible to have negative humidity :
183
184         dt_zu = t_zu - sst  ; dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6), dt_zu )
185         dq_zu = q_zu - ssq  ; dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9), dq_zu )
186
187      END IF
188
189      !! ITERATION BLOCK
190      DO j_itt = 1, nb_itt
191
192         !!Inverse of Monin-Obukov length (1/L) :
193         ztmp0 = One_on_L(t_zu, q_zu, u_star, t_star, q_star)  ! 1/L == 1/[Monin-Obukhov length]
194
195         ztmp1 = u_star*u_star   ! u*^2
196
197         !! Update wind at 10m taking into acount convection-related wind gustiness:
198         ! Ug = Beta*w*  (Beta = 1.25, Fairall et al. 2003, Eq.8):
199         ztmp2 = Beta0*Beta0*ztmp1*(MAX(-zi0*ztmp0/vkarmn,0.))**(2./3.)   ! => ztmp2 == Ug^2
200         !!   ! Only true when unstable (L<0) => when ztmp0 < 0 => explains "-" before 600.
201         U_blk = MAX(sqrt(U_zu*U_zu + ztmp2), 0.2)        ! include gustiness in bulk wind speed
202         ! => 0.2 prevents U_blk to be 0 in stable case when U_zu=0.
203
204         !! COARE 3.5: Charnock parameter is computed from the neutral wind speed at 10m: Eq. 13 (Edson al. 2013)
205         ztmp2 = u_star/vkarmn*LOG(10./z0)   ! UN10 Neutral wind at 10m!
206         ztmp2 = MIN( 0.0017*ztmp2 - 0.005 , charn0_max)  ! alpha Charnock parameter (Eq. 13 Edson al. 2013)
207         ztmp2 = MAX( ztmp2 , 0. )
208
209         !! Roughness lengthes z0, z0t (z0q = z0t) :
210         z0   = ztmp2*ztmp1/grav + 0.11*znu_a/u_star ! Roughness length (eq.6)
211         ztmp1 = z0*u_star/znu_a                             ! Re_r: roughness Reynolds number
212         !z0t  = MIN( 1.1E-4 , 5.5E-5*ztmp1**(-0.6) )   ! COARE 3.0
213         !! Chris Fairall and Jim Edsson, private communication, March 2016 / COARE 3.5 :
214         z0t   = MIN( 1.6e-4 , 5.8E-5*ztmp1**(-0.72)) ! These thermal roughness lengths give Stanton and
215         !z0q = z0t                                   ! Dalton numbers that closely approximate COARE3.0
216
217         !! Stability parameters:
218         zeta_u = zu*ztmp0 ; zeta_u = sign( min(abs(zeta_u),50.0), zeta_u )
219         IF( .NOT. l_zt_equal_zu ) THEN
220            zeta_t = zt*ztmp0 ;  zeta_t = sign( min(abs(zeta_t),50.0), zeta_t )
221         END IF
222
223         !! Turbulent scales at zu=10m :
224         ztmp0   = psi_h_coare(zeta_u)
225         ztmp1   = vkarmn/(LOG(zu) -LOG(z0t) - ztmp0)
226
227         t_star = dt_zu*ztmp1
228         q_star = dq_zu*ztmp1
229         u_star = U_blk*vkarmn/(LOG(zu) -LOG(z0) - psi_m_coare(zeta_u))
230
231         IF( .NOT. l_zt_equal_zu ) THEN
232            ! What's need to be done if zt /= zu
233            !! Re-updating temperature and humidity at zu :
234            ztmp2 = ztmp0 - psi_h_coare(zeta_t)
235            ztmp1 = log(zt/zu) + ztmp2
236            t_zu = t_zt - t_star/vkarmn*ztmp1
237            q_zu = q_zt - q_star/vkarmn*ztmp1
238            dt_zu = t_zu - sst ;  dt_zu = SIGN( MAX(ABS(dt_zu),1.E-6), dt_zu )
239            dq_zu = q_zu - ssq ;  dq_zu = SIGN( MAX(ABS(dq_zu),1.E-9), dq_zu )
240         END IF
241
242      END DO
243      !
244      ! compute transfer coefficients at zu :
245      ztmp0 = u_star/U_blk
246      Cd   = ztmp0*ztmp0
247      Ch   = ztmp0*t_star/dt_zu
248      Ce   = ztmp0*q_star/dq_zu
249      !
250
251      IF( nn_timing == 1 )  CALL timing_stop('turb_coare3p5')
252
253   END SUBROUTINE turb_coare3p5
254
255
256
257   FUNCTION One_on_L( ptha, pqa, pus, pts, pqs )
258      !!------------------------------------------------------------------------
259      !!
260      !! Evaluates the 1./(Monin Obukhov length) from air temperature and
261      !!  specific humidity, and frictional scales u*, t* and q*
262      !!
263      !! Author: L. Brodeau, june 2016 / AeroBulk
264      !!         (https://sourceforge.net/p/aerobulk)
265      !!------------------------------------------------------------------------
266      REAL(wp), DIMENSION(jpi,jpj)             :: One_on_L         !: 1./(Monin Obukhov length) [m^-1]
267      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptha,  &  !: average potetntial air temperature [K]
268         &                                        pqa,   &  !: average specific humidity of air   [kg/kg]
269         &                                      pus, pts, pqs   !: frictional velocity, temperature and humidity
270      !
271      INTEGER  ::   ji, jj         ! dummy loop indices
272      REAL(wp) ::     zqa          ! local scalar
273      !
274      DO jj = 1, jpj
275         DO ji = 1, jpi
276            !
277            zqa = (1. + rctv0*pqa(ji,jj))
278            !
279            One_on_L(ji,jj) =  grav*vkarmn*(pts(ji,jj)*zqa + rctv0*ptha(ji,jj)*pqs(ji,jj)) &
280               &                      / ( pus(ji,jj)*pus(ji,jj) * ptha(ji,jj)*zqa )
281            !
282         END DO
283      END DO
284      !
285   END FUNCTION One_on_L
286
287
288   FUNCTION psi_m_coare( pzeta )
289      !!----------------------------------------------------------------------------------
290      !! ** Purpose: compute the universal profile stability function for momentum
291      !!             COARE 3.0, Fairall et al. 2003
292      !!             pzeta : stability paramenter, z/L where z is altitude
293      !!                     measurement and L is M-O length
294      !!       Stability function for wind speed and scalars matching Kansas and free
295      !!       convection forms with weighting f convective form, follows Fairall et
296      !!       al (1996) with profile constants from Grachev et al (2000) BLM stable
297      !!       form from Beljaars and Holtslag (1991)
298      !!
299      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://sourceforge.net/p/aerobulk)
300      !!----------------------------------------------------------------------------------
301      REAL(wp), DIMENSION(jpi,jpj) :: psi_m_coare
302      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pzeta
303      !
304      INTEGER  ::   ji, jj    ! dummy loop indices
305      REAL(wp) :: zta, zphi_m, zphi_c, zpsi_k, zpsi_c, zf, zc, zstab
306      !!----------------------------------------------------------------------------------
307      !
308      DO jj = 1, jpj
309         DO ji = 1, jpi
310            !
311            zta = pzeta(ji,jj)
312            !
313            zphi_m = ABS(1. - 15.*zta)**.25    !!Kansas unstable
314            !
315            zpsi_k = 2.*LOG((1. + zphi_m)/2.) + LOG((1. + zphi_m*zphi_m)/2.)   &
316               & - 2.*ATAN(zphi_m) + 0.5*rpi
317            !
318            zphi_c = ABS(1. - 10.15*zta)**.3333                   !!Convective
319            !
320            zpsi_c = 1.5*LOG((1. + zphi_c + zphi_c*zphi_c)/3.) &
321               &     - 1.7320508*ATAN((1. + 2.*zphi_c)/1.7320508) + 1.813799447
322            !
323            zf = zta*zta
324            zf = zf/(1. + zf)
325            zc = MIN(50., 0.35*zta)
326            zstab = 0.5 + SIGN(0.5, zta)
327            !
328            psi_m_coare(ji,jj) = (1. - zstab) * ( (1. - zf)*zpsi_k + zf*zpsi_c ) & ! (zta < 0)
329               &                -   zstab     * ( 1. + 1.*zta     &                ! (zta > 0)
330               &                         + 0.6667*(zta - 14.28)/EXP(zc) + 8.525 )   !     "
331            !
332         END DO
333      END DO
334      !
335   END FUNCTION psi_m_coare
336
337
338   FUNCTION psi_h_coare( pzeta )
339      !!---------------------------------------------------------------------
340      !! Universal profile stability function for temperature and humidity
341      !! COARE 3.0, Fairall et al. 2003
342      !!
343      !! pzeta : stability paramenter, z/L where z is altitude measurement
344      !!         and L is M-O length
345      !!
346      !! Stability function for wind speed and scalars matching Kansas and free
347      !! convection forms with weighting f convective form, follows Fairall et
348      !! al (1996) with profile constants from Grachev et al (2000) BLM stable
349      !! form from Beljaars and Holtslag (1991)
350      !!
351      !! Author: L. Brodeau, june 2016 / AeroBulk
352      !!         (https://sourceforge.net/p/aerobulk)
353      !!----------------------------------------------------------------
354      !!
355      REAL(wp), DIMENSION(jpi,jpj) :: psi_h_coare
356      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pzeta
357      !
358      INTEGER  ::   ji, jj     ! dummy loop indices
359      REAL(wp) :: zta, zphi_h, zphi_c, zpsi_k, zpsi_c, zf, zc, zstab
360      !
361      DO jj = 1, jpj
362         DO ji = 1, jpi
363            !
364            zta = pzeta(ji,jj)
365            !
366            zphi_h = (ABS(1. - 15.*zta))**.5  !! Kansas unstable   (zphi_h = zphi_m**2 when unstable, zphi_m when stable)
367            !
368            zpsi_k = 2.*LOG((1. + zphi_h)/2.)
369            !
370            zphi_c = (ABS(1. - 34.15*zta))**.3333   !! Convective
371            !
372            zpsi_c = 1.5*LOG((1. + zphi_c + zphi_c*zphi_c)/3.) &
373               &    -1.7320508*ATAN((1. + 2.*zphi_c)/1.7320508) + 1.813799447
374            !
375            zf = zta*zta
376            zf = zf/(1. + zf)
377            zc = MIN(50.,0.35*zta)
378            zstab = 0.5 + SIGN(0.5, zta)
379            !
380            psi_h_coare(ji,jj) = (1. - zstab) * ( (1. - zf)*zpsi_k + zf*zpsi_c ) &
381               &                -   zstab     * ( (ABS(1. + 2.*zta/3.))**1.5     &
382               &                           + .6667*(zta - 14.28)/EXP(zc) + 8.525 )
383            !
384         END DO
385      END DO
386      !
387   END FUNCTION psi_h_coare
388
389
390   FUNCTION visc_air( ptak )
391      !!---------------------------------------------------------------------
392      !! Air kinetic viscosity (m^2/s) given from temperature in degrees...
393      !!
394      !! Author: L. Brodeau, june 2016 / AeroBulk
395      !!         (https://sourceforge.net/p/aerobulk)
396      !!---------------------------------------------------------------------
397      REAL(wp), DIMENSION(jpi,jpj)             ::   visc_air
398      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   ptak       ! air temperature   [K]
399      !
400      INTEGER  ::   ji, jj         ! dummy loop indices
401      REAL(wp) ::   ztc, ztc2      ! local scalar
402      !
403      DO jj = 1, jpj
404         DO ji = 1, jpi
405            ztc  = ptak(ji,jj) - rt0   ! air temp, in deg. C
406            ztc2 = ztc*ztc
407            visc_air(ji,jj) = 1.326E-5*(1. + 6.542E-3*ztc + 8.301E-6*ztc2 - 4.84E-9*ztc2*ztc)
408         END DO
409      END DO
410      !
411   END FUNCTION visc_air
412
413   !!======================================================================
414END MODULE sbcblk_algo_coare3p5
Note: See TracBrowser for help on using the repository browser.