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.
sbc_phy.F90 in NEMO/trunk/src/OCE/SBC – NEMO

source: NEMO/trunk/src/OCE/SBC/sbc_phy.F90 @ 14072

Last change on this file since 14072 was 14072, checked in by laurent, 3 years ago

Merging branch "2020/dev_r13648_ASINTER-04_laurent_bulk_ice", ticket #2369

File size: 58.7 KB
RevLine 
[13655]1MODULE sbc_phy
[12015]2   !!======================================================================
[13655]3   !!                       ***  MODULE  sbc_phy  ***
[12015]4   !! A set of functions to compute air themodynamics parameters
5   !!                     needed by Aerodynamic Bulk Formulas
6   !!=====================================================================
[13655]7   !!            4.x  !  2020 L. Brodeau from AeroBulk package (https://github.com/brodeau/aerobulk/)
[12015]8   !!----------------------------------------------------------------------
9
10   !!   virt_temp     : virtual (aka sensible) temperature (potential or absolute)
11   !!   rho_air       : density of (moist) air (depends on T_air, q_air and SLP
12   !!   visc_air      : kinematic viscosity (aka Nu_air) of air from temperature
13   !!   L_vap         : latent heat of vaporization of water as a function of temperature
14   !!   cp_air        : specific heat of (moist) air (depends spec. hum. q_air)
15   !!   gamma_moist   : adiabatic lapse-rate of moist air
[13655]16   !!   One_on_L      : 1. / ( Obukhov length )
[12015]17   !!   Ri_bulk       : bulk Richardson number aka BRN
18   !!   q_sat         : saturation humidity as a function of SLP and temperature
19   !!   q_air_rh      : specific humidity as a function of RH (fraction, not %), t_air and SLP
20
21   USE dom_oce        ! ocean space and time domain
22   USE phycst         ! physical constants
23
24   IMPLICIT NONE
[14036]25   !PRIVATE
26   PUBLIC !! Haleluja that was the solution
[12015]27
[13655]28   INTEGER , PARAMETER, PUBLIC  :: nb_iter0 = 5 ! Default number of itterations in bulk-param algorithms (can be overriden b.m.o `nb_iter` optional argument)
29
[12015]30   !!  (mainly removed from sbcblk.F90)
31   REAL(wp), PARAMETER, PUBLIC :: rCp_dry = 1005.0_wp   !: Specic heat of dry air, constant pressure      [J/K/kg]
32   REAL(wp), PARAMETER, PUBLIC :: rCp_vap = 1860.0_wp   !: Specic heat of water vapor, constant pressure  [J/K/kg]
33   REAL(wp), PARAMETER, PUBLIC :: R_dry   = 287.05_wp   !: Specific gas constant for dry air              [J/K/kg]
34   REAL(wp), PARAMETER, PUBLIC :: R_vap   = 461.495_wp  !: Specific gas constant for water vapor          [J/K/kg]
35   REAL(wp), PARAMETER, PUBLIC :: reps0   = R_dry/R_vap !: ratio of gas constant for dry air and water vapor => ~ 0.622
[12895]36   REAL(wp), PARAMETER, PUBLIC :: rctv0   = R_vap/R_dry - 1._wp  !: for virtual temperature (== (1-eps)/eps) => ~ 0.608
[12015]37   REAL(wp), PARAMETER, PUBLIC :: rCp_air = 1000.5_wp   !: specific heat of air (only used for ice fluxes now...)
38   REAL(wp), PARAMETER, PUBLIC :: albo    = 0.066_wp    !: ocean albedo assumed to be constant
39   !
40   REAL(wp), PARAMETER, PUBLIC :: rho0_a  = 1.2_wp      !: Approx. of density of air                       [kg/m^3]
41   REAL(wp), PARAMETER, PUBLIC :: rho0_w  = 1025._wp    !: Density of sea-water  (ECMWF->1025)             [kg/m^3]
42   REAL(wp), PARAMETER, PUBLIC :: radrw = rho0_a/rho0_w !: Density ratio
43   REAL(wp), PARAMETER, PUBLIC :: sq_radrw = SQRT(rho0_a/rho0_w)
44   REAL(wp), PARAMETER, PUBLIC :: rCp0_w  = 4190._wp    !: Specific heat capacity of seawater (ECMWF 4190) [J/K/kg]
45   REAL(wp), PARAMETER, PUBLIC :: rnu0_w  = 1.e-6_wp    !: kinetic viscosity of water                      [m^2/s]
46   REAL(wp), PARAMETER, PUBLIC :: rk0_w   = 0.6_wp      !: thermal conductivity of water (at 20C)          [W/m/K]
47   !
[13655]48   REAL(wp), PARAMETER, PUBLIC :: emiss_w = 0.98_wp     !: Long-wave (thermal) emissivity of sea-water []
49   !
50   REAL(wp), PARAMETER, PUBLIC :: emiss_i = 0.996_wp    !:  "   for ice and snow => but Rees 1993 suggests can be lower in winter on fresh snow... 0.72 ...
51
52   REAL(wp), PARAMETER, PUBLIC :: wspd_thrshld_ice = 0.2_wp !: minimum scalar wind speed accepted over sea-ice... [m/s]
53
54   !
[12015]55   REAL(wp), PARAMETER, PUBLIC :: rdct_qsat_salt = 0.98_wp  !: reduction factor on specific humidity at saturation (q_sat(T_s)) due to salt
56   REAL(wp), PARAMETER, PUBLIC :: rtt0 = 273.16_wp        !: triple point of temperature    [K]
57   !
58   REAL(wp), PARAMETER, PUBLIC :: rcst_cs = -16._wp*9.80665_wp*rho0_w*rCp0_w*rnu0_w*rnu0_w*rnu0_w/(rk0_w*rk0_w) !: for cool-skin parameterizations... (grav = 9.80665_wp)
59   !                              => see eq.(14) in Fairall et al. 1996   (eq.(6) of Zeng aand Beljaars is WRONG! (typo?)
60
[13655]61   REAL(wp), PARAMETER, PUBLIC :: z0_sea_max = 0.0025_wp   !: maximum realistic value for roughness length of sea-surface... [m]
[12015]62
[13655]63   REAL(wp), PUBLIC, SAVE ::   pp_cldf = 0.81    !: cloud fraction over sea ice, summer CLIO value   [-]
64
65
66   REAL(wp), PARAMETER, PUBLIC :: Cx_min = 0.1E-3_wp ! smallest value allowed for bulk transfer coefficients (usually in stable conditions with now wind)
67
68   REAL(wp), PARAMETER :: &
69                                !! Constants for Goff formula in the presence of ice:
70      &      rAg_i = -9.09718_wp, &
71      &      rBg_i = -3.56654_wp, &
72      &      rCg_i = 0.876793_wp, &
73      &      rDg_i = LOG10(6.1071_wp)
74
75   REAL(wp), PARAMETER :: rc_louis  = 5._wp
76   REAL(wp), PARAMETER :: rc2_louis = rc_louis * rc_louis
77   REAL(wp), PARAMETER :: ram_louis = 2. * rc_louis
78   REAL(wp), PARAMETER :: rah_louis = 3. * rc_louis
79
80
81   INTERFACE virt_temp
82      MODULE PROCEDURE virt_temp_vctr, virt_temp_sclr
83   END INTERFACE virt_temp
84
85   INTERFACE visc_air
86      MODULE PROCEDURE visc_air_vctr, visc_air_sclr
87   END INTERFACE visc_air
88
[12015]89   INTERFACE gamma_moist
90      MODULE PROCEDURE gamma_moist_vctr, gamma_moist_sclr
91   END INTERFACE gamma_moist
92
93   INTERFACE e_sat
94      MODULE PROCEDURE e_sat_vctr, e_sat_sclr
95   END INTERFACE e_sat
96
[13655]97   INTERFACE e_sat_ice
98      MODULE PROCEDURE e_sat_ice_vctr, e_sat_ice_sclr
99   END INTERFACE e_sat_ice
100   INTERFACE de_sat_dt_ice
101      MODULE PROCEDURE de_sat_dt_ice_vctr, de_sat_dt_ice_sclr
102   END INTERFACE de_sat_dt_ice
103
104   INTERFACE Ri_bulk
105      MODULE PROCEDURE Ri_bulk_vctr, Ri_bulk_sclr
106   END INTERFACE Ri_bulk
107
108   INTERFACE q_sat
109      MODULE PROCEDURE q_sat_vctr, q_sat_sclr
110   END INTERFACE q_sat
111
112   INTERFACE dq_sat_dt_ice
113      MODULE PROCEDURE dq_sat_dt_ice_vctr, dq_sat_dt_ice_sclr
114   END INTERFACE dq_sat_dt_ice
115
[12015]116   INTERFACE L_vap
117      MODULE PROCEDURE L_vap_vctr, L_vap_sclr
118   END INTERFACE L_vap
119
120   INTERFACE rho_air
121      MODULE PROCEDURE rho_air_vctr, rho_air_sclr
122   END INTERFACE rho_air
123
124   INTERFACE cp_air
125      MODULE PROCEDURE cp_air_vctr, cp_air_sclr
126   END INTERFACE cp_air
127
128   INTERFACE alpha_sw
129      MODULE PROCEDURE alpha_sw_vctr, alpha_sw_sclr
130   END INTERFACE alpha_sw
131
132   INTERFACE bulk_formula
133      MODULE PROCEDURE bulk_formula_vctr, bulk_formula_sclr
134   END INTERFACE bulk_formula
135
[13655]136   INTERFACE qlw_net
137      MODULE PROCEDURE qlw_net_vctr, qlw_net_sclr
138   END INTERFACE qlw_net
[12015]139
[13655]140   INTERFACE f_m_louis
141      MODULE PROCEDURE f_m_louis_vctr, f_m_louis_sclr
142   END INTERFACE f_m_louis
[12015]143
[13655]144   INTERFACE f_h_louis
145      MODULE PROCEDURE f_h_louis_vctr, f_h_louis_sclr
146   END INTERFACE f_h_louis
147
148
[12015]149   PUBLIC virt_temp
150   PUBLIC rho_air
151   PUBLIC visc_air
152   PUBLIC L_vap
153   PUBLIC cp_air
154   PUBLIC gamma_moist
155   PUBLIC One_on_L
156   PUBLIC Ri_bulk
157   PUBLIC q_sat
158   PUBLIC q_air_rh
[13655]159   PUBLIC dq_sat_dt_ice
[12015]160   !:
161   PUBLIC update_qnsol_tau
162   PUBLIC alpha_sw
163   PUBLIC bulk_formula
[13655]164   PUBLIC qlw_net
165   !
166   PUBLIC f_m_louis, f_h_louis
167   PUBLIC z0_from_Cd
168   PUBLIC Cd_from_z0
169   PUBLIC UN10_from_ustar
170   PUBLIC UN10_from_CD
171   PUBLIC z0tq_LKB
[12015]172
[12340]173   !! * Substitutions
174#  include "do_loop_substitute.h90"
[12015]175   !!----------------------------------------------------------------------
176   !! NEMO/OCE 4.0 , NEMO Consortium (2018)
177   !! $Id: sbcblk.F90 10535 2019-01-16 17:36:47Z clem $
178   !! Software governed by the CeCILL license (see ./LICENSE)
179   !!----------------------------------------------------------------------
180CONTAINS
181
[13655]182
183   FUNCTION virt_temp_sclr( pta, pqa )
[12015]184      !!------------------------------------------------------------------------
185      !!
[13655]186      !! Compute the (absolute/potential) VIRTUAL temperature, based on the
[12015]187      !! (absolute/potential) temperature and specific humidity
188      !!
[13655]189      !! If input temperature is absolute then output virtual temperature is absolute
190      !! If input temperature is potential then output virtual temperature is potential
[12015]191      !!
192      !! Author: L. Brodeau, June 2019 / AeroBulk
193      !!         (https://github.com/brodeau/aerobulk/)
194      !!------------------------------------------------------------------------
[13655]195      REAL(wp)             :: virt_temp_sclr !: virtual temperature [K]
196      REAL(wp), INTENT(in) :: pta       !: absolute or potential air temperature [K]
197      REAL(wp), INTENT(in) :: pqa       !: specific humidity of air   [kg/kg]
[12015]198      !!-------------------------------------------------------------------
199      !
[13655]200      virt_temp_sclr = pta * (1._wp + rctv0*pqa)
[12015]201      !!
[13655]202      !! This is exactly the same thing as:
203      !! virt_temp_sclr = pta * ( pwa + reps0) / (reps0*(1.+pwa))
[12015]204      !! with wpa (mixing ration) defined as : pwa = pqa/(1.-pqa)
205      !
[13655]206   END FUNCTION virt_temp_sclr
207   !!
208   FUNCTION virt_temp_vctr( pta, pqa )
209      REAL(wp), DIMENSION(jpi,jpj)             :: virt_temp_vctr !: virtual temperature [K]
210      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pta !: absolute or potential air temperature [K]
211      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pqa !: specific humidity of air   [kg/kg]
212      virt_temp_vctr(:,:) = pta(:,:) * (1._wp + rctv0*pqa(:,:))
213   END FUNCTION virt_temp_vctr
214   !===============================================================================================
[12015]215
[13655]216
217   FUNCTION rho_air_vctr( ptak, pqa, ppa )
[12015]218      !!-------------------------------------------------------------------------------
219      !!                           ***  FUNCTION rho_air_vctr  ***
220      !!
221      !! ** Purpose : compute density of (moist) air using the eq. of state of the atmosphere
222      !!
223      !! ** Author: L. Brodeau, June 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
224      !!-------------------------------------------------------------------------------
225      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   ptak      ! air temperature             [K]
226      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   pqa       ! air specific humidity   [kg/kg]
[13655]227      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   ppa      ! pressure in                [Pa]
[12015]228      REAL(wp), DIMENSION(jpi,jpj)             ::   rho_air_vctr   ! density of moist air   [kg/m^3]
229      !!-------------------------------------------------------------------------------
[13655]230      rho_air_vctr = MAX( ppa / (R_dry*ptak * ( 1._wp + rctv0*pqa )) , 0.8_wp )
[12015]231   END FUNCTION rho_air_vctr
232
[13655]233   FUNCTION rho_air_sclr( ptak, pqa, ppa )
[12015]234      !!-------------------------------------------------------------------------------
235      !!                           ***  FUNCTION rho_air_sclr  ***
236      !!
237      !! ** Purpose : compute density of (moist) air using the eq. of state of the atmosphere
238      !!
239      !! ** Author: L. Brodeau, June 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
240      !!-------------------------------------------------------------------------------
241      REAL(wp), INTENT(in) :: ptak           ! air temperature             [K]
242      REAL(wp), INTENT(in) :: pqa            ! air specific humidity   [kg/kg]
[13655]243      REAL(wp), INTENT(in) :: ppa           ! pressure in                [Pa]
[12015]244      REAL(wp)             :: rho_air_sclr   ! density of moist air   [kg/m^3]
245      !!-------------------------------------------------------------------------------
[13655]246      rho_air_sclr = MAX( ppa / (R_dry*ptak * ( 1._wp + rctv0*pqa )) , 0.8_wp )
[12015]247   END FUNCTION rho_air_sclr
248
249
250
[13655]251
252   FUNCTION visc_air_sclr(ptak)
[12015]253      !!----------------------------------------------------------------------------------
[13655]254      !! Air kinetic viscosity (m^2/s) given from air temperature in Kelvin
[12015]255      !!
256      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
257      !!----------------------------------------------------------------------------------
[13655]258      REAL(wp)             :: visc_air_sclr   ! kinetic viscosity (m^2/s)
259      REAL(wp), INTENT(in) :: ptak       ! air temperature in (K)
[12015]260      !
261      REAL(wp) ::   ztc, ztc2   ! local scalar
262      !!----------------------------------------------------------------------------------
263      !
[13655]264      ztc  = ptak - rt0   ! air temp, in deg. C
265      ztc2 = ztc*ztc
266      visc_air_sclr = 1.326e-5*(1. + 6.542E-3*ztc + 8.301e-6*ztc2 - 4.84e-9*ztc2*ztc)
267      !
268   END FUNCTION visc_air_sclr
269
270   FUNCTION visc_air_vctr(ptak)
271      REAL(wp), DIMENSION(jpi,jpj)             ::   visc_air_vctr   ! kinetic viscosity (m^2/s)
272      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   ptak       ! air temperature in (K)
273      INTEGER  ::   ji, jj      ! dummy loop indices
[13305]274      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
[13655]275      visc_air_vctr(ji,jj) = visc_air_sclr( ptak(ji,jj) )
[12340]276      END_2D
[13655]277   END FUNCTION visc_air_vctr
[12015]278
[13655]279
[12015]280   FUNCTION L_vap_vctr( psst )
281      !!---------------------------------------------------------------------------------
282      !!                           ***  FUNCTION L_vap_vctr  ***
283      !!
284      !! ** Purpose : Compute the latent heat of vaporization of water from temperature
285      !!
286      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
287      !!----------------------------------------------------------------------------------
288      REAL(wp), DIMENSION(jpi,jpj)             ::   L_vap_vctr   ! latent heat of vaporization   [J/kg]
289      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   psst   ! water temperature                [K]
290      !!----------------------------------------------------------------------------------
291      !
292      L_vap_vctr = (  2.501_wp - 0.00237_wp * ( psst(:,:) - rt0)  ) * 1.e6_wp
293      !
294   END FUNCTION L_vap_vctr
295
296   FUNCTION L_vap_sclr( psst )
297      !!---------------------------------------------------------------------------------
298      !!                           ***  FUNCTION L_vap_sclr  ***
299      !!
300      !! ** Purpose : Compute the latent heat of vaporization of water from temperature
301      !!
302      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
303      !!----------------------------------------------------------------------------------
304      REAL(wp)             ::   L_vap_sclr   ! latent heat of vaporization   [J/kg]
305      REAL(wp), INTENT(in) ::   psst         ! water temperature                [K]
306      !!----------------------------------------------------------------------------------
307      !
308      L_vap_sclr = (  2.501_wp - 0.00237_wp * ( psst - rt0)  ) * 1.e6_wp
309      !
310   END FUNCTION L_vap_sclr
311
312
313   FUNCTION cp_air_vctr( pqa )
314      !!-------------------------------------------------------------------------------
315      !!                           ***  FUNCTION cp_air_vctr  ***
316      !!
317      !! ** Purpose : Compute specific heat (Cp) of moist air
318      !!
319      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
320      !!-------------------------------------------------------------------------------
321      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   pqa      ! air specific humidity         [kg/kg]
322      REAL(wp), DIMENSION(jpi,jpj)             ::   cp_air_vctr   ! specific heat of moist air   [J/K/kg]
323      !!-------------------------------------------------------------------------------
324      cp_air_vctr = rCp_dry + rCp_vap * pqa
325   END FUNCTION cp_air_vctr
326
327   FUNCTION cp_air_sclr( pqa )
328      !!-------------------------------------------------------------------------------
329      !!                           ***  FUNCTION cp_air_sclr  ***
330      !!
331      !! ** Purpose : Compute specific heat (Cp) of moist air
332      !!
333      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
334      !!-------------------------------------------------------------------------------
335      REAL(wp), INTENT(in) :: pqa           ! air specific humidity         [kg/kg]
336      REAL(wp)             :: cp_air_sclr   ! specific heat of moist air   [J/K/kg]
337      !!-------------------------------------------------------------------------------
338      cp_air_sclr = rCp_dry + rCp_vap * pqa
339   END FUNCTION cp_air_sclr
340
341
342
[13655]343   !===============================================================================================
[12015]344   FUNCTION gamma_moist_sclr( ptak, pqa )
345      !!----------------------------------------------------------------------------------
346      !! ** Purpose : Compute the moist adiabatic lapse-rate.
347      !!     => http://glossary.ametsoc.org/wiki/Moist-adiabatic_lapse_rate
348      !!     => http://www.geog.ucsb.edu/~joel/g266_s10/lecture_notes/chapt03/oh10_3_01/oh10_3_01.html
349      !!
350      !! ** Author: L. Brodeau, June 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
351      !!----------------------------------------------------------------------------------
[13655]352      REAL(wp)             :: gamma_moist_sclr !                           [K/m]
353      REAL(wp), INTENT(in) ::   ptak           ! absolute air temperature  [K] !#LB: double check it's absolute !!!
354      REAL(wp), INTENT(in) ::   pqa            ! specific humidity     [kg/kg]
[12015]355      !
[13655]356      REAL(wp) :: zta, zqa, zwa, ziRT, zLvap        ! local scalars
[12015]357      !!----------------------------------------------------------------------------------
358      zta = MAX( ptak,  180._wp) ! prevents screw-up over masked regions where field == 0.
359      zqa = MAX( pqa,  1.E-6_wp) !    "                   "                     "
360      !!
361      zwa = zqa / (1._wp - zqa)   ! w is mixing ratio w = q/(1-q) | q = w/(1+w)
362      ziRT = 1._wp / (R_dry*zta)    ! 1/RT
[13655]363      zLvap = L_vap_sclr( ptak )
[12015]364      !!
[13655]365      gamma_moist_sclr = grav * ( 1._wp + zLvap*zwa*ziRT ) / ( rCp_dry + zLvap*zLvap*zwa*reps0*ziRT/zta )
366      !!
[12015]367   END FUNCTION gamma_moist_sclr
[13655]368   !!
369   FUNCTION gamma_moist_vctr( ptak, pqa )
370      REAL(wp), DIMENSION(jpi,jpj)             ::   gamma_moist_vctr
371      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   ptak
372      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   pqa
373      INTEGER  :: ji, jj
374      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
375      gamma_moist_vctr(ji,jj) = gamma_moist_sclr( ptak(ji,jj), pqa(ji,jj) )
376      END_2D
377   END FUNCTION gamma_moist_vctr
378   !===============================================================================================
[12015]379
[13655]380
[12015]381   FUNCTION One_on_L( ptha, pqa, pus, pts, pqs )
382      !!------------------------------------------------------------------------
383      !!
[13655]384      !! Evaluates the 1./(Obukhov length) from air temperature,
385      !! air specific humidity, and frictional scales u*, t* and q*
[12015]386      !!
[13655]387      !! Author: L. Brodeau, June 2019 / AeroBulk
[12015]388      !!         (https://github.com/brodeau/aerobulk/)
389      !!------------------------------------------------------------------------
[13655]390      REAL(wp), DIMENSION(jpi,jpj)             :: One_on_L     !: 1./(Obukhov length) [m^-1]
391      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptha         !: reference potential temperature of air [K]
392      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pqa          !: reference specific humidity of air   [kg/kg]
393      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pus          !: u*: friction velocity [m/s]
394      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pts, pqs     !: \theta* and q* friction aka turb. scales for temp. and spec. hum.
[12015]395      !
396      INTEGER  ::   ji, jj         ! dummy loop indices
397      REAL(wp) ::     zqa          ! local scalar
398      !!-------------------------------------------------------------------
399      !
[13305]400      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
[13655]401      !
402      zqa = (1._wp + rctv0*pqa(ji,jj))
403      !
404      ! The main concern is to know whether, the vertical turbulent flux of virtual temperature, < u' theta_v' > is estimated with:
405      !  a/  -u* [ theta* (1 + 0.61 q) + 0.61 theta q* ] => this is the one that seems correct! chose this one!
406      !                      or
407      !  b/  -u* [ theta*              + 0.61 theta q* ]
408      !
409      One_on_L(ji,jj) = grav*vkarmn*( pts(ji,jj)*zqa + rctv0*ptha(ji,jj)*pqs(ji,jj) ) &
410         &               / MAX( pus(ji,jj)*pus(ji,jj)*ptha(ji,jj)*zqa , 1.E-9_wp )
411      !
[12340]412      END_2D
[12015]413      !
414      One_on_L = SIGN( MIN(ABS(One_on_L),200._wp), One_on_L ) ! (prevent FPE from stupid values over masked regions...)
415      !
416   END FUNCTION One_on_L
417
[13655]418
419   !===============================================================================================
420   FUNCTION Ri_bulk_sclr( pz, psst, ptha, pssq, pqa, pub,  pta_layer, pqa_layer )
[12015]421      !!----------------------------------------------------------------------------------
422      !! Bulk Richardson number according to "wide-spread equation"...
423      !!
[13655]424      !!    Reminder: the Richardson number is the ratio "buoyancy" / "shear"
425      !!
[12015]426      !! ** Author: L. Brodeau, June 2019 / AeroBulk (https://github.com/brodeau/aerobulk/)
427      !!----------------------------------------------------------------------------------
[13655]428      REAL(wp)             :: Ri_bulk_sclr
429      REAL(wp), INTENT(in) :: pz    ! height above the sea (aka "delta z")  [m]
430      REAL(wp), INTENT(in) :: psst  ! SST                                   [K]
431      REAL(wp), INTENT(in) :: ptha  ! pot. air temp. at height "pz"         [K]
432      REAL(wp), INTENT(in) :: pssq  ! 0.98*q_sat(SST)                   [kg/kg]
433      REAL(wp), INTENT(in) :: pqa   ! air spec. hum. at height "pz"     [kg/kg]
434      REAL(wp), INTENT(in) :: pub   ! bulk wind speed                     [m/s]
435      REAL(wp), INTENT(in), OPTIONAL :: pta_layer ! when possible, a better guess of absolute temperature WITHIN the layer [K]
436      REAL(wp), INTENT(in), OPTIONAL :: pqa_layer ! when possible, a better guess of specific humidity    WITHIN the layer [kg/kg]
437      !!
438      LOGICAL  :: l_ptqa_l_prvd = .FALSE.
439      REAL(wp) :: zqa, zta, zgamma, zdthv, ztv, zsstv  ! local scalars
440      !!-------------------------------------------------------------------
441      IF( PRESENT(pta_layer) .AND. PRESENT(pqa_layer) ) l_ptqa_l_prvd=.TRUE.
442      !
443      zsstv = virt_temp_sclr( psst, pssq )          ! virtual SST (absolute==potential because z=0!)
444      !
445      zdthv = virt_temp_sclr( ptha, pqa  ) - zsstv  ! air-sea delta of "virtual potential temperature"
446      !
447      !! ztv: estimate of the ABSOLUTE virtual temp. within the layer
448      IF( l_ptqa_l_prvd ) THEN
449         ztv = virt_temp_sclr( pta_layer, pqa_layer )
450      ELSE
451         zqa = 0.5_wp*( pqa  + pssq )                             ! ~ mean q within the layer...
452         zta = 0.5_wp*( psst + ptha - gamma_moist(ptha, zqa)*pz ) ! ~ mean absolute temperature of air within the layer
453         zta = 0.5_wp*( psst + ptha - gamma_moist( zta, zqa)*pz ) ! ~ mean absolute temperature of air within the layer
454         zgamma =  gamma_moist(zta, zqa)                          ! Adiabatic lapse-rate for moist air within the layer
455         ztv = 0.5_wp*( zsstv + virt_temp_sclr( ptha-zgamma*pz, pqa ) )
456      END IF
457      !
458      Ri_bulk_sclr = grav*zdthv*pz / ( ztv*pub*pub )      ! the usual definition of Ri_bulk_sclr
459      !
460   END FUNCTION Ri_bulk_sclr
461   !!
462   FUNCTION Ri_bulk_vctr( pz, psst, ptha, pssq, pqa, pub,  pta_layer, pqa_layer )
463      REAL(wp), DIMENSION(jpi,jpj)             :: Ri_bulk_vctr
[12015]464      REAL(wp)                    , INTENT(in) :: pz    ! height above the sea (aka "delta z")  [m]
465      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: psst  ! SST                                   [K]
466      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptha  ! pot. air temp. at height "pz"         [K]
467      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pssq  ! 0.98*q_sat(SST)                   [kg/kg]
468      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pqa   ! air spec. hum. at height "pz"     [kg/kg]
469      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pub   ! bulk wind speed                     [m/s]
[13655]470      REAL(wp), DIMENSION(jpi,jpj), INTENT(in), OPTIONAL :: pta_layer ! when possible, a better guess of absolute temperature WITHIN the layer [K]
471      REAL(wp), DIMENSION(jpi,jpj), INTENT(in), OPTIONAL :: pqa_layer ! when possible, a better guess of specific humidity    WITHIN the layer [kg/kg]
472      !!
473      LOGICAL  :: l_ptqa_l_prvd = .FALSE.
474      INTEGER  ::   ji, jj
475      IF( PRESENT(pta_layer) .AND. PRESENT(pqa_layer) ) l_ptqa_l_prvd=.TRUE.
[13305]476      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
[13655]477      IF( l_ptqa_l_prvd ) THEN
478         Ri_bulk_vctr(ji,jj) = Ri_bulk_sclr( pz, psst(ji,jj), ptha(ji,jj), pssq(ji,jj), pqa(ji,jj), pub(ji,jj), &
479            &                                pta_layer=pta_layer(ji,jj ),  pqa_layer=pqa_layer(ji,jj ) )
480      ELSE
481         Ri_bulk_vctr(ji,jj) = Ri_bulk_sclr( pz, psst(ji,jj), ptha(ji,jj), pssq(ji,jj), pqa(ji,jj), pub(ji,jj) )
482      END IF
[12340]483      END_2D
[13655]484   END FUNCTION Ri_bulk_vctr
485   !===============================================================================================
[12015]486
[13655]487   !===============================================================================================
[12015]488   FUNCTION e_sat_sclr( ptak )
489      !!----------------------------------------------------------------------------------
490      !!                   ***  FUNCTION e_sat_sclr  ***
491      !!                  < SCALAR argument version >
492      !! ** Purpose : water vapor at saturation in [Pa]
493      !!              Based on accurate estimate by Goff, 1957
494      !!
495      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
496      !!
497      !!    Note: what rt0 should be here, is 273.16 (triple point of water) and not 273.15 like here
498      !!----------------------------------------------------------------------------------
[13655]499      REAL(wp)             ::   e_sat_sclr   ! water vapor at saturation   [kg/kg]
[12015]500      REAL(wp), INTENT(in) ::   ptak    ! air temperature                  [K]
501      REAL(wp) ::   zta, ztmp   ! local scalar
502      !!----------------------------------------------------------------------------------
503      zta = MAX( ptak , 180._wp )   ! air temp., prevents fpe0 errors dute to unrealistically low values over masked regions...
[13655]504      ztmp = rt0 / zta   !#LB: rt0 or rtt0 ???? (273.15 vs 273.16 )
[12015]505      !
506      ! Vapour pressure at saturation [Pa] : WMO, (Goff, 1957)
507      e_sat_sclr = 100.*( 10.**( 10.79574*(1. - ztmp) - 5.028*LOG10(zta/rt0)        &
508         &    + 1.50475*10.**(-4)*(1. - 10.**(-8.2969*(zta/rt0 - 1.)) )  &
509         &    + 0.42873*10.**(-3)*(10.**(4.76955*(1. - ztmp)) - 1.) + 0.78614) )
510      !
511   END FUNCTION e_sat_sclr
[13655]512   !!
513   FUNCTION e_sat_vctr(ptak)
514      REAL(wp), DIMENSION(jpi,jpj)             :: e_sat_vctr !: vapour pressure at saturation  [Pa]
515      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptak    !: temperature (K)
516      INTEGER  ::   ji, jj         ! dummy loop indices
517      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
518      e_sat_vctr(ji,jj) = e_sat_sclr(ptak(ji,jj))
519      END_2D
520   END FUNCTION e_sat_vctr
521   !===============================================================================================
[12015]522
[13655]523   !===============================================================================================
524   FUNCTION e_sat_ice_sclr(ptak)
525      !!---------------------------------------------------------------------------------
526      !! Same as "e_sat" but over ice rather than water!
527      !!---------------------------------------------------------------------------------
528      REAL(wp)             :: e_sat_ice_sclr !: vapour pressure at saturation in presence of ice [Pa]
529      REAL(wp), INTENT(in) :: ptak
530      !!
531      REAL(wp) :: zta, zle, ztmp
532      !!---------------------------------------------------------------------------------
533      zta = MAX( ptak , 180._wp )   ! air temp., prevents fpe0 errors dute to unrealistically low values over masked regions...
534      ztmp = rtt0/zta
535      !!
536      zle  = rAg_i*(ztmp - 1._wp) + rBg_i*LOG10(ztmp) + rCg_i*(1._wp - zta/rtt0) + rDg_i
537      !!
538      e_sat_ice_sclr = 100._wp * 10._wp**zle
539   END FUNCTION e_sat_ice_sclr
540   !!
541   FUNCTION e_sat_ice_vctr(ptak)
542      !! Same as "e_sat" but over ice rather than water!
543      REAL(wp), DIMENSION(jpi,jpj) :: e_sat_ice_vctr !: vapour pressure at saturation in presence of ice [Pa]
544      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptak
545      INTEGER  :: ji, jj
[12015]546      !!----------------------------------------------------------------------------------
[13655]547      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
548      e_sat_ice_vctr(ji,jj) = e_sat_ice_sclr( ptak(ji,jj) )
549      END_2D
550   END FUNCTION e_sat_ice_vctr
551   !!
552   FUNCTION de_sat_dt_ice_sclr(ptak)
553      !!---------------------------------------------------------------------------------
554      !! d [ e_sat_ice ] / dT   (derivative / temperature)
555      !! Analytical exact formulation: double checked!!!
556      !!  => DOUBLE-check possible / finite-difference version with "./bin/test_phymbl.x"
557      !!---------------------------------------------------------------------------------
558      REAL(wp)             :: de_sat_dt_ice_sclr !:  [Pa/K]
559      REAL(wp), INTENT(in) :: ptak
[12015]560      !!
[13655]561      REAL(wp) :: zta, zde
562      !!---------------------------------------------------------------------------------
563      zta = MAX( ptak , 180._wp )   ! air temp., prevents fpe0 errors dute to unrealistically low values over masked regions...
[12015]564      !!
[13655]565      zde = -(rAg_i*rtt0)/(zta*zta) - rBg_i/(zta*LOG(10._wp)) - rCg_i/rtt0
566      !!
567      de_sat_dt_ice_sclr = LOG(10._wp) * zde * e_sat_ice_sclr(zta)
568   END FUNCTION de_sat_dt_ice_sclr
569   !!
570   FUNCTION de_sat_dt_ice_vctr(ptak)
571      !! Same as "e_sat" but over ice rather than water!
572      REAL(wp), DIMENSION(jpi,jpj) :: de_sat_dt_ice_vctr !: vapour pressure at saturation in presence of ice [Pa]
573      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptak
574      INTEGER  :: ji, jj
575      !!----------------------------------------------------------------------------------
576      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
577      de_sat_dt_ice_vctr(ji,jj) = de_sat_dt_ice_sclr( ptak(ji,jj) )
578      END_2D
579   END FUNCTION de_sat_dt_ice_vctr
580
581
582
583   !===============================================================================================
584
585   !===============================================================================================
586   FUNCTION q_sat_sclr( pta, ppa,  l_ice )
587      !!---------------------------------------------------------------------------------
588      !!                           ***  FUNCTION q_sat_sclr  ***
589      !!
590      !! ** Purpose : Conputes specific humidity of air at saturation
591      !!
[12015]592      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
593      !!----------------------------------------------------------------------------------
[13655]594      REAL(wp) :: q_sat_sclr
595      REAL(wp), INTENT(in) :: pta  !: absolute temperature of air [K]
596      REAL(wp), INTENT(in) :: ppa  !: atmospheric pressure        [Pa]
597      LOGICAL,  INTENT(in), OPTIONAL :: l_ice  !: we are above ice
598      REAL(wp) :: ze_s
599      LOGICAL  :: lice
600      !!----------------------------------------------------------------------------------
601      lice = .FALSE.
602      IF( PRESENT(l_ice) ) lice = l_ice
603      IF( lice ) THEN
604         ze_s = e_sat_ice( pta )
605      ELSE
606         ze_s = e_sat( pta ) ! Vapour pressure at saturation (Goff) :
607      END IF
608      q_sat_sclr = reps0*ze_s/(ppa - (1._wp - reps0)*ze_s)
609   END FUNCTION q_sat_sclr
610   !!
611   FUNCTION q_sat_vctr( pta, ppa,  l_ice )
612      REAL(wp), DIMENSION(jpi,jpj) :: q_sat_vctr
613      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pta  !: absolute temperature of air [K]
614      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ppa  !: atmospheric pressure        [Pa]
615      LOGICAL,  INTENT(in), OPTIONAL :: l_ice  !: we are above ice
616      LOGICAL  :: lice
617      INTEGER  :: ji, jj
618      !!----------------------------------------------------------------------------------
619      lice = .FALSE.
620      IF( PRESENT(l_ice) ) lice = l_ice
621      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
622      q_sat_vctr(ji,jj) = q_sat_sclr( pta(ji,jj) , ppa(ji,jj), l_ice=lice )
623      END_2D
624   END FUNCTION q_sat_vctr
625   !===============================================================================================
626
627
628   !===============================================================================================
629   FUNCTION dq_sat_dt_ice_sclr( pta, ppa )
630      !!---------------------------------------------------------------------------------
631      !!     ***  FUNCTION dq_sat_dt_ice_sclr  ***
632      !!    => d [ q_sat_ice(T) ] / dT
633      !! Analytical exact formulation: double checked!!!
634      !!  => DOUBLE-check possible / finite-difference version with "./bin/test_phymbl.x"
635      !!----------------------------------------------------------------------------------
636      REAL(wp) :: dq_sat_dt_ice_sclr
637      REAL(wp), INTENT(in) :: pta  !: absolute temperature of air [K]
638      REAL(wp), INTENT(in) :: ppa  !: atmospheric pressure        [Pa]
639      REAL(wp) :: ze_s, zde_s_dt, ztmp
640      !!----------------------------------------------------------------------------------
641      ze_s     =  e_sat_ice_sclr( pta ) ! Vapour pressure at saturation  in presence of ice (Goff)
642      zde_s_dt = de_sat_dt_ice(   pta )
[12015]643      !
[13655]644      ztmp = (reps0 - 1._wp)*ze_s + ppa
645      !
646      dq_sat_dt_ice_sclr = reps0*ppa*zde_s_dt / ( ztmp*ztmp )
647      !
648   END FUNCTION dq_sat_dt_ice_sclr
649   !!
650   FUNCTION dq_sat_dt_ice_vctr( pta, ppa )
651      REAL(wp), DIMENSION(jpi,jpj) :: dq_sat_dt_ice_vctr
652      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pta  !: absolute temperature of air [K]
653      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ppa  !: atmospheric pressure        [Pa]
654      INTEGER  :: ji, jj
[12015]655      !!----------------------------------------------------------------------------------
[13305]656      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
[13655]657      dq_sat_dt_ice_vctr(ji,jj) = dq_sat_dt_ice_sclr( pta(ji,jj) , ppa(ji,jj) )
[12340]658      END_2D
[13655]659   END FUNCTION dq_sat_dt_ice_vctr
660   !===============================================================================================
[12015]661
[13655]662
663   !===============================================================================================
664   FUNCTION q_air_rh(prha, ptak, ppa)
[12015]665      !!----------------------------------------------------------------------------------
666      !! Specific humidity of air out of Relative Humidity
667      !!
668      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
669      !!----------------------------------------------------------------------------------
670      REAL(wp), DIMENSION(jpi,jpj)             :: q_air_rh
671      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: prha        !: relative humidity      [fraction, not %!!!]
672      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ptak        !: air temperature        [K]
[13655]673      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ppa        !: atmospheric pressure   [Pa]
[12015]674      !
675      INTEGER  ::   ji, jj      ! dummy loop indices
676      REAL(wp) ::   ze      ! local scalar
677      !!----------------------------------------------------------------------------------
678      !
[13305]679      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
[13655]680      ze = prha(ji,jj)*e_sat_sclr(ptak(ji,jj))
681      q_air_rh(ji,jj) = ze*reps0/(ppa(ji,jj) - (1. - reps0)*ze)
[12340]682      END_2D
[12015]683      !
684   END FUNCTION q_air_rh
685
686
[13655]687   SUBROUTINE UPDATE_QNSOL_TAU( pzu, pTs, pqs, pTa, pqa, pust, ptst, pqst, pwnd, pUb, ppa, prlw, &
[12015]688      &                         pQns, pTau,  &
689      &                         Qlat)
690      !!----------------------------------------------------------------------------------
691      !! Purpose: returns the non-solar heat flux to the ocean aka "Qlat + Qsen + Qlw"
692      !!          and the module of the wind stress => pTau = Tau
693      !! ** Author: L. Brodeau, Sept. 2019 / AeroBulk (https://github.com/brodeau/aerobulk/)
694      !!----------------------------------------------------------------------------------
695      REAL(wp),                     INTENT(in)  :: pzu  ! height above the sea-level where all this takes place (normally 10m)
696      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pTs  ! water temperature at the air-sea interface [K]
697      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pqs  ! satur. spec. hum. at T=pTs   [kg/kg]
698      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pTa  ! potential air temperature at z=pzu [K]
699      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pqa  ! specific humidity at z=pzu [kg/kg]
700      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pust ! u*
701      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: ptst ! t*
702      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pqst ! q*
703      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pwnd ! wind speed module at z=pzu [m/s]
704      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pUb  ! bulk wind speed at z=pzu (inc. pot. effect of gustiness etc) [m/s]
[13655]705      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: ppa ! sea-level atmospheric pressure [Pa]
[12015]706      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: prlw ! downwelling longwave radiative flux [W/m^2]
707      !
708      REAL(wp), DIMENSION(jpi,jpj), INTENT(out) :: pQns ! non-solar heat flux to the ocean aka "Qlat + Qsen + Qlw" [W/m^2]]
709      REAL(wp), DIMENSION(jpi,jpj), INTENT(out) :: pTau ! module of the wind stress [N/m^2]
710      !
711      REAL(wp), DIMENSION(jpi,jpj), OPTIONAL, INTENT(out) :: Qlat
712      !
[13655]713      REAL(wp) :: zdt, zdq, zCd, zCh, zCe, zz0, zQlat, zQsen, zQlw
[12015]714      INTEGER  ::   ji, jj     ! dummy loop indices
715      !!----------------------------------------------------------------------------------
[13305]716      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
[13655]717      zdt = pTa(ji,jj) - pTs(ji,jj) ;  zdt = SIGN( MAX(ABS(zdt),1.E-6_wp), zdt )
718      zdq = pqa(ji,jj) - pqs(ji,jj) ;  zdq = SIGN( MAX(ABS(zdq),1.E-9_wp), zdq )
719      zz0 = pust(ji,jj)/pUb(ji,jj)
720      zCd = zz0*zz0
721      zCh = zz0*ptst(ji,jj)/zdt
722      zCe = zz0*pqst(ji,jj)/zdq
[12015]723
[13655]724      CALL BULK_FORMULA( pzu, pTs(ji,jj), pqs(ji,jj), pTa(ji,jj), pqa(ji,jj), zCd, zCh, zCe, &
725         &              pwnd(ji,jj), pUb(ji,jj), ppa(ji,jj), &
726         &              pTau(ji,jj), zQsen, zQlat )
[12015]727
[13655]728      zQlw = qlw_net_sclr( prlw(ji,jj), pTs(ji,jj) ) ! Net longwave flux
[12015]729
[13655]730      pQns(ji,jj) = zQlat + zQsen + zQlw
[12015]731
[13655]732      IF( PRESENT(Qlat) ) Qlat(ji,jj) = zQlat
[12340]733      END_2D
[12015]734   END SUBROUTINE UPDATE_QNSOL_TAU
735
736
737   SUBROUTINE BULK_FORMULA_SCLR( pzu, pTs, pqs, pTa, pqa, &
738      &                          pCd, pCh, pCe,           &
[13655]739      &                          pwnd, pUb, ppa,         &
[12615]740      &                          pTau, pQsen, pQlat,      &
741      &                          pEvap, prhoa, pfact_evap )
[12015]742      !!----------------------------------------------------------------------------------
743      REAL(wp),                     INTENT(in)  :: pzu  ! height above the sea-level where all this takes place (normally 10m)
744      REAL(wp), INTENT(in)  :: pTs  ! water temperature at the air-sea interface [K]
745      REAL(wp), INTENT(in)  :: pqs  ! satur. spec. hum. at T=pTs   [kg/kg]
746      REAL(wp), INTENT(in)  :: pTa  ! potential air temperature at z=pzu [K]
747      REAL(wp), INTENT(in)  :: pqa  ! specific humidity at z=pzu [kg/kg]
748      REAL(wp), INTENT(in)  :: pCd
749      REAL(wp), INTENT(in)  :: pCh
750      REAL(wp), INTENT(in)  :: pCe
751      REAL(wp), INTENT(in)  :: pwnd ! wind speed module at z=pzu [m/s]
752      REAL(wp), INTENT(in)  :: pUb  ! bulk wind speed at z=pzu (inc. pot. effect of gustiness etc) [m/s]
[13655]753      REAL(wp), INTENT(in)  :: ppa ! sea-level atmospheric pressure [Pa]
[12015]754      !!
755      REAL(wp), INTENT(out) :: pTau  ! module of the wind stress [N/m^2]
756      REAL(wp), INTENT(out) :: pQsen !  [W/m^2]
757      REAL(wp), INTENT(out) :: pQlat !  [W/m^2]
758      !!
759      REAL(wp), INTENT(out), OPTIONAL :: pEvap ! Evaporation [kg/m^2/s]
760      REAL(wp), INTENT(out), OPTIONAL :: prhoa ! Air density at z=pzu [kg/m^3]
[12615]761      REAL(wp), INTENT(in) , OPTIONAL :: pfact_evap  ! ABOMINATION: corrective factor for evaporation (doing this against my will! /laurent)
[12015]762      !!
[12615]763      REAL(wp) :: ztaa, zgamma, zrho, zUrho, zevap, zfact_evap
[12015]764      INTEGER  :: jq
765      !!----------------------------------------------------------------------------------
[12615]766      zfact_evap = 1._wp
767      IF( PRESENT(pfact_evap) ) zfact_evap = pfact_evap
[13655]768
[12081]769      !! Need ztaa, absolute temperature at pzu (formula to estimate rho_air needs absolute temperature, not the potential temperature "pTa")
770      ztaa = pTa ! first guess...
771      DO jq = 1, 4
[13655]772         zgamma = gamma_moist( 0.5*(ztaa+pTs) , pqa )  !#LB: why not "0.5*(pqs+pqa)" rather then "pqa" ???
[12081]773         ztaa = pTa - zgamma*pzu   ! Absolute temp. is slightly colder...
774      END DO
[13655]775      zrho = rho_air(ztaa, pqa, ppa)
776      zrho = rho_air(ztaa, pqa, ppa-zrho*grav*pzu) ! taking into account that we are pzu m above the sea level where SLP is given!
[12015]777
[12081]778      zUrho = pUb*MAX(zrho, 1._wp)     ! rho*U10
779
780      pTau = zUrho * pCd * pwnd ! Wind stress module
781
782      zevap = zUrho * pCe * (pqa - pqs)
783      pQsen = zUrho * pCh * (pTa - pTs) * cp_air(pqa)
784      pQlat = L_vap(pTs) * zevap
785
[12615]786      IF( PRESENT(pEvap) ) pEvap = - zfact_evap * zevap
[12081]787      IF( PRESENT(prhoa) ) prhoa = zrho
788
[12015]789   END SUBROUTINE BULK_FORMULA_SCLR
[13655]790   !!
[12615]791   SUBROUTINE BULK_FORMULA_VCTR( pzu, pTs, pqs, pTa, pqa, &
792      &                          pCd, pCh, pCe,           &
[13655]793      &                          pwnd, pUb, ppa,         &
794      &                          pTau, pQsen, pQlat,      &
795      &                          pEvap, prhoa, pfact_evap )
[12615]796      !!----------------------------------------------------------------------------------
797      REAL(wp),                     INTENT(in)  :: pzu  ! height above the sea-level where all this takes place (normally 10m)
798      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pTs  ! water temperature at the air-sea interface [K]
799      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pqs  ! satur. spec. hum. at T=pTs   [kg/kg]
800      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pTa  ! potential air temperature at z=pzu [K]
801      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pqa  ! specific humidity at z=pzu [kg/kg]
802      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pCd
803      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pCh
804      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pCe
805      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pwnd ! wind speed module at z=pzu [m/s]
806      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: pUb  ! bulk wind speed at z=pzu (inc. pot. effect of gustiness etc) [m/s]
[13655]807      REAL(wp), DIMENSION(jpi,jpj), INTENT(in)  :: ppa ! sea-level atmospheric pressure [Pa]
[12615]808      !!
809      REAL(wp), DIMENSION(jpi,jpj), INTENT(out) :: pTau  ! module of the wind stress [N/m^2]
810      REAL(wp), DIMENSION(jpi,jpj), INTENT(out) :: pQsen !  [W/m^2]
811      REAL(wp), DIMENSION(jpi,jpj), INTENT(out) :: pQlat !  [W/m^2]
812      !!
813      REAL(wp), DIMENSION(jpi,jpj), INTENT(out), OPTIONAL :: pEvap ! Evaporation [kg/m^2/s]
814      REAL(wp), DIMENSION(jpi,jpj), INTENT(out), OPTIONAL :: prhoa ! Air density at z=pzu [kg/m^3]
815      REAL(wp),                     INTENT(in) , OPTIONAL :: pfact_evap  ! ABOMINATION: corrective factor for evaporation (doing this against my will! /laurent)
816      !!
817      REAL(wp) :: ztaa, zgamma, zrho, zUrho, zevap, zfact_evap
818      INTEGER  :: ji, jj
819      !!----------------------------------------------------------------------------------
820      zfact_evap = 1._wp
821      IF( PRESENT(pfact_evap) ) zfact_evap = pfact_evap
[12015]822
[13305]823      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
[12015]824
[13655]825      CALL BULK_FORMULA_SCLR( pzu, pTs(ji,jj), pqs(ji,jj), pTa(ji,jj), pqa(ji,jj), &
826         &                    pCd(ji,jj), pCh(ji,jj), pCe(ji,jj),                  &
827         &                    pwnd(ji,jj), pUb(ji,jj), ppa(ji,jj),                &
828         &                    pTau(ji,jj), pQsen(ji,jj), pQlat(ji,jj),             &
829         &                    pEvap=zevap, prhoa=zrho, pfact_evap=zfact_evap       )
[12015]830
[13655]831      IF( PRESENT(pEvap) ) pEvap(ji,jj) = zevap
832      IF( PRESENT(prhoa) ) prhoa(ji,jj) = zrho
[12615]833      END_2D
834   END SUBROUTINE BULK_FORMULA_VCTR
835
836
[12015]837   FUNCTION alpha_sw_vctr( psst )
838      !!---------------------------------------------------------------------------------
839      !!                           ***  FUNCTION alpha_sw_vctr  ***
840      !!
[13655]841      !! ** Purpose : ROUGH estimate of the thermal expansion coefficient of sea-water at the surface (P =~ 1010 hpa)
[12015]842      !!
843      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
844      !!----------------------------------------------------------------------------------
845      REAL(wp), DIMENSION(jpi,jpj)             ::   alpha_sw_vctr   ! thermal expansion coefficient of sea-water [1/K]
846      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) ::   psst   ! water temperature                [K]
847      !!----------------------------------------------------------------------------------
848      alpha_sw_vctr = 2.1e-5_wp * MAX(psst(:,:)-rt0 + 3.2_wp, 0._wp)**0.79
849   END FUNCTION alpha_sw_vctr
850
851   FUNCTION alpha_sw_sclr( psst )
852      !!---------------------------------------------------------------------------------
853      !!                           ***  FUNCTION alpha_sw_sclr  ***
854      !!
[13655]855      !! ** Purpose : ROUGH estimate of the thermal expansion coefficient of sea-water at the surface (P =~ 1010 hpa)
[12015]856      !!
857      !! ** Author: L. Brodeau, june 2016 / AeroBulk (https://github.com/brodeau/aerobulk/)
858      !!----------------------------------------------------------------------------------
859      REAL(wp)             ::   alpha_sw_sclr   ! thermal expansion coefficient of sea-water [1/K]
860      REAL(wp), INTENT(in) ::   psst   ! sea-water temperature                   [K]
861      !!----------------------------------------------------------------------------------
862      alpha_sw_sclr = 2.1e-5_wp * MAX(psst-rt0 + 3.2_wp, 0._wp)**0.79
863   END FUNCTION alpha_sw_sclr
864
865
[13655]866   !===============================================================================================
867   FUNCTION qlw_net_sclr( pdwlw, pts,  l_ice )
868      !!---------------------------------------------------------------------------------
869      !!                           ***  FUNCTION qlw_net_sclr  ***
870      !!
871      !! ** Purpose : Estimate of the net longwave flux at the surface
872      !!----------------------------------------------------------------------------------
873      REAL(wp) :: qlw_net_sclr
874      REAL(wp), INTENT(in) :: pdwlw !: downwelling longwave (aka infrared, aka thermal) radiation [W/m^2]
875      REAL(wp), INTENT(in) :: pts   !: surface temperature [K]
876      LOGICAL,  INTENT(in), OPTIONAL :: l_ice  !: we are above ice
877      REAL(wp) :: zemiss, zt2
878      LOGICAL  :: lice
879      !!----------------------------------------------------------------------------------
880      lice = .FALSE.
881      IF( PRESENT(l_ice) ) lice = l_ice
882      IF( lice ) THEN
883         zemiss = emiss_i
884      ELSE
885         zemiss = emiss_w
886      END IF
887      zt2 = pts*pts
888      qlw_net_sclr = zemiss*( pdwlw - stefan*zt2*zt2)  ! zemiss used both as the IR albedo and IR emissivity...
889   END FUNCTION qlw_net_sclr
890   !!
891   FUNCTION qlw_net_vctr( pdwlw, pts,  l_ice )
892      REAL(wp), DIMENSION(jpi,jpj) :: qlw_net_vctr
893      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pdwlw !: downwelling longwave (aka infrared, aka thermal) radiation [W/m^2]
894      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pts   !: surface temperature [K]
895      LOGICAL,  INTENT(in), OPTIONAL :: l_ice  !: we are above ice
896      LOGICAL  :: lice
897      INTEGER  :: ji, jj
898      !!----------------------------------------------------------------------------------
899      lice = .FALSE.
900      IF( PRESENT(l_ice) ) lice = l_ice
901      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
902      qlw_net_vctr(ji,jj) = qlw_net_sclr( pdwlw(ji,jj) , pts(ji,jj), l_ice=lice )
903      END_2D
904   END FUNCTION qlw_net_vctr
905   !===============================================================================================
[12015]906
[13655]907   FUNCTION z0_from_Cd( pzu, pCd,  ppsi )
908      REAL(wp), DIMENSION(jpi,jpj) :: z0_from_Cd        !: roughness length [m]
909      REAL(wp)                    , INTENT(in) :: pzu   !: reference height zu [m]
910      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pCd   !: (neutral or non-neutral) drag coefficient []
911      REAL(wp), DIMENSION(jpi,jpj), INTENT(in), OPTIONAL :: ppsi !: "Psi_m(pzu/L)" stability correction profile for momentum []
912      !!
913      !! If pCd is the NEUTRAL-STABILITY drag coefficient then ppsi must be 0 or not given
914      !! If pCd is the drag coefficient (in stable or unstable conditions) then pssi must be provided
915      !!----------------------------------------------------------------------------------
916      IF( PRESENT(ppsi) ) THEN
917         !! Cd provided is the actual Cd (not the neutral-stability CdN) :
918         z0_from_Cd = pzu * EXP( - ( vkarmn/SQRT(pCd(:,:)) + ppsi(:,:) ) ) !LB: ok, double-checked!
919      ELSE
920         !! Cd provided is the neutral-stability Cd, aka CdN :
921         z0_from_Cd = pzu * EXP( - vkarmn/SQRT(pCd(:,:)) )            !LB: ok, double-checked!
922      END IF
923   END FUNCTION z0_from_Cd
924
925   FUNCTION Cd_from_z0( pzu, pz0,  ppsi )
926      REAL(wp), DIMENSION(jpi,jpj) :: Cd_from_z0        !: (neutral or non-neutral) drag coefficient []
927      REAL(wp)                    , INTENT(in) :: pzu   !: reference height zu [m]
928      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pz0   !: roughness length [m]
929      REAL(wp), DIMENSION(jpi,jpj), INTENT(in), OPTIONAL :: ppsi !: "Psi_m(pzu/L)" stability correction profile for momentum []
930      !!
931      !! If we want to return the NEUTRAL-STABILITY drag coefficient then ppsi must be 0 or not given
932      !! If we want to return the stability-corrected Cd (i.e. in stable or unstable conditions) then pssi must be provided
933      !!----------------------------------------------------------------------------------
934      IF( PRESENT(ppsi) ) THEN
935         !! The Cd we return is the actual Cd (not the neutral-stability CdN) :
936         Cd_from_z0 = 1._wp / ( LOG( pzu / pz0(:,:) ) - ppsi(:,:) )
937      ELSE
938         !! The Cd we return is the neutral-stability Cd, aka CdN :
939         Cd_from_z0 = 1._wp /   LOG( pzu / pz0(:,:) )
940      END IF
941      Cd_from_z0 = vkarmn2 * Cd_from_z0 * Cd_from_z0
942   END FUNCTION Cd_from_z0
943
944
945   FUNCTION f_m_louis_sclr( pzu, pRib, pCdn, pz0 )
946      !!----------------------------------------------------------------------------------
947      !!  Stability correction function for MOMENTUM
948      !!                 Louis (1979)
949      !!----------------------------------------------------------------------------------
950      REAL(wp)             :: f_m_louis_sclr ! term "f_m" in Eq.(6) when option "Louis" rather than "Psi(zeta) is chosen, Lupkes & Gryanik (2015),
951      REAL(wp), INTENT(in) :: pzu     ! reference height (height for pwnd)  [m]
952      REAL(wp), INTENT(in) :: pRib    ! Bulk Richardson number
953      REAL(wp), INTENT(in) :: pCdn    ! neutral drag coefficient
954      REAL(wp), INTENT(in) :: pz0     ! roughness length                      [m]
955      !!----------------------------------------------------------------------------------
956      REAL(wp) :: ztu, zts, zstab
957      !!----------------------------------------------------------------------------------
958      zstab = 0.5 + SIGN(0.5_wp, pRib) ; ! Unstable (Ri<0) => zstab = 0 | Stable (Ri>0) => zstab = 1
959      !
960      ztu = pRib / ( 1._wp + 3._wp * rc2_louis * pCdn * SQRT( ABS( -pRib * ( pzu / pz0 + 1._wp) ) ) ) ! ABS is just here for when it's stable conditions and ztu is not used anyways
961      zts = pRib / SQRT( ABS( 1._wp + pRib ) ) ! ABS is just here for when it's UNstable conditions and zts is not used anyways
962      !
963      f_m_louis_sclr = (1._wp - zstab) *         ( 1._wp - ram_louis * ztu )  &  ! Unstable Eq.(A6)
964         &               +      zstab  * 1._wp / ( 1._wp + ram_louis * zts )     ! Stable   Eq.(A7)
965      !
966   END FUNCTION f_m_louis_sclr
967   !!
968   FUNCTION f_m_louis_vctr( pzu, pRib, pCdn, pz0 )
969      REAL(wp), DIMENSION(jpi,jpj)             :: f_m_louis_vctr
970      REAL(wp),                     INTENT(in) :: pzu
971      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pRib
972      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pCdn
973      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pz0
974      INTEGER  :: ji, jj
975      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
976      f_m_louis_vctr(ji,jj) = f_m_louis_sclr( pzu, pRib(ji,jj), pCdn(ji,jj), pz0(ji,jj) )
977      END_2D
978   END FUNCTION f_m_louis_vctr
979
980
981   FUNCTION f_h_louis_sclr( pzu, pRib, pChn, pz0 )
982      !!----------------------------------------------------------------------------------
983      !!  Stability correction function for HEAT
984      !!                 Louis (1979)
985      !!----------------------------------------------------------------------------------
986      REAL(wp)             :: f_h_louis_sclr ! term "f_h" in Eq.(6) when option "Louis" rather than "Psi(zeta) is chosen, Lupkes & Gryanik (2015),
987      REAL(wp), INTENT(in) :: pzu     ! reference height (height for pwnd)  [m]
988      REAL(wp), INTENT(in) :: pRib    ! Bulk Richardson number
989      REAL(wp), INTENT(in) :: pChn    ! neutral heat transfer coefficient
990      REAL(wp), INTENT(in) :: pz0     ! roughness length                      [m]
991      !!----------------------------------------------------------------------------------
992      REAL(wp) :: ztu, zts, zstab
993      !!----------------------------------------------------------------------------------
994      zstab = 0.5 + SIGN(0.5_wp, pRib) ; ! Unstable (Ri<0) => zstab = 0 | Stable (Ri>0) => zstab = 1
995      !
996      ztu = pRib / ( 1._wp + 3._wp * rc2_louis * pChn * SQRT( ABS(-pRib * ( pzu / pz0 + 1._wp) ) ) )
997      zts = pRib / SQRT( ABS( 1._wp + pRib ) )
998      !
999      f_h_louis_sclr = (1._wp - zstab) *         ( 1._wp - rah_louis * ztu )  &  ! Unstable Eq.(A6)
1000         &              +       zstab  * 1._wp / ( 1._wp + rah_louis * zts )     ! Stable   Eq.(A7)  !#LB: in paper it's "ram_louis" and not "rah_louis" typo or what????
1001      !
1002   END FUNCTION f_h_louis_sclr
1003   !!
1004   FUNCTION f_h_louis_vctr( pzu, pRib, pChn, pz0 )
1005      REAL(wp), DIMENSION(jpi,jpj)             :: f_h_louis_vctr
1006      REAL(wp),                     INTENT(in) :: pzu
1007      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pRib
1008      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pChn
1009      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pz0
1010      INTEGER  :: ji, jj
1011      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
1012      f_h_louis_vctr(ji,jj) = f_h_louis_sclr( pzu, pRib(ji,jj), pChn(ji,jj), pz0(ji,jj) )
1013      END_2D
1014   END FUNCTION f_h_louis_vctr
1015
1016   FUNCTION UN10_from_ustar( pzu, pUzu, pus, ppsi )
1017      !!----------------------------------------------------------------------------------
1018      !!  Provides the neutral-stability wind speed at 10 m
1019      !!----------------------------------------------------------------------------------
1020      REAL(wp), DIMENSION(jpi,jpj)             :: UN10_from_ustar  !: neutral stability wind speed at 10m [m/s]
1021      REAL(wp),                     INTENT(in) :: pzu   !: measurement heigh of wind speed   [m]
1022      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pUzu  !: bulk wind speed at height pzu m   [m/s]
1023      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pus   !: friction velocity                 [m/s]
1024      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ppsi !: "Psi_m(pzu/L)" stability correction profile for momentum []
1025      !!----------------------------------------------------------------------------------
1026      UN10_from_ustar(:,:) = pUzu(:,:) - pus(:,:)/vkarmn * ( LOG(pzu/10._wp) - ppsi(:,:) )
1027      !!
1028   END FUNCTION UN10_from_ustar
1029
1030
1031   FUNCTION UN10_from_CD( pzu, pUb, pCd, ppsi )
1032      !!----------------------------------------------------------------------------------
1033      !!  Provides the neutral-stability wind speed at 10 m
1034      !!----------------------------------------------------------------------------------
1035      REAL(wp), DIMENSION(jpi,jpj)             :: UN10_from_CD  !: [m/s]
1036      REAL(wp),                     INTENT(in) :: pzu  !: measurement heigh of bulk wind speed
1037      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pUb  !: bulk wind speed at height pzu m   [m/s]
1038      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pCd  !: drag coefficient
1039      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: ppsi !: "Psi_m(pzu/L)" stability correction profile for momentum []
1040      !!----------------------------------------------------------------------------------
1041      !! Reminder: UN10 = u*/vkarmn * log(10/z0)
1042      !!     and: u* = sqrt(Cd) * Ub
1043      !!                                  u*/vkarmn * log(   10   /       z0    )
1044      UN10_from_CD(:,:) = SQRT(pCd(:,:))*pUb/vkarmn * LOG( 10._wp / z0_from_Cd( pzu, pCd(:,:), ppsi=ppsi(:,:) ) )
1045      !!
1046   END FUNCTION UN10_from_CD
1047
1048
1049   FUNCTION z0tq_LKB( iflag, pRer, pz0 )
1050      !!---------------------------------------------------------------------------------
1051      !!       ***  FUNCTION z0tq_LKB  ***
1052      !!
1053      !! ** Purpose : returns the "temperature/humidity roughness lengths"
1054      !!              * iflag==1 => temperature => returns: z_{0t}
1055      !!              * iflag==2 => humidity    => returns: z_{0q}
1056      !!              from roughness reynold number "pRer" (i.e. [z_0 u*]/Nu_{air})
1057      !!              between 0 and 1000. Out of range "pRer" indicated by prt=-999.
1058      !!              and roughness length (for momentum)
1059      !!
1060      !!              Based on Liu et al. (1979) JAS 36 1722-1723s
1061      !!
1062      !!              Note: this is what is used into COARE 2.5 to estimate z_{0t} and z_{0q}
1063      !!
1064      !! ** Author: L. Brodeau, April 2020 / AeroBulk (https://github.com/brodeau/aerobulk/)
1065      !!----------------------------------------------------------------------------------
1066      REAL(wp), DIMENSION(jpi,jpj)             :: z0tq_LKB
1067      INTEGER,                      INTENT(in) :: iflag     !: 1 => dealing with temperature; 2 => dealing with humidity
1068      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pRer      !: roughness Reynolds number  [z_0 u*]/Nu_{air}
1069      REAL(wp), DIMENSION(jpi,jpj), INTENT(in) :: pz0       !: roughness length (for momentum) [m]
1070      !-------------------------------------------------------------------
1071      ! Scalar Re_r relation from Liu et al.
1072      REAL(wp), DIMENSION(8,2), PARAMETER :: &
1073         & XA = (/ 0.177, 1.376, 1.026, 1.625, 4.661, 34.904, 1667.19, 5.88e5,  &
1074         &         0.292, 1.808, 1.393, 1.956, 4.994, 30.709, 1448.68, 2.98e5 /)
1075      !!
1076      REAL(wp), DIMENSION(8,2), PARAMETER :: &
1077         & XB = (/ 0., 0.929, -0.599, -1.018, -1.475, -2.067, -2.907, -3.935,  &
1078         &         0., 0.826, -0.528, -0.870, -1.297, -1.845, -2.682, -3.616 /)
1079      !!
1080      REAL(wp), DIMENSION(0:8),   PARAMETER :: &
1081         & XRAN = (/ 0., 0.11, 0.825, 3.0, 10.0, 30.0, 100., 300., 1000. /)
1082      !-------------------------------------------------------------------
1083      !
1084      !-------------------------------------------------------------------
1085      ! Scalar Re_r relation from Moana Wave data.
1086      !
1087      !      real*8 A(9,2),B(9,2),RAN(9),pRer,prt
1088      !      integer iflag
1089      !      DATA A/0.177,2.7e3,1.03,1.026,1.625,4.661,34.904,1667.19,5.88E5,
1090      !     &       0.292,3.7e3,1.4,1.393,1.956,4.994,30.709,1448.68,2.98E5/
1091      !      DATA B/0.,4.28,0,-0.599,-1.018,-1.475,-2.067,-2.907,-3.935,
1092      !     &       0.,4.28,0,-0.528,-0.870,-1.297,-1.845,-2.682,-3.616/
1093      !      DATA RAN/0.11,.16,1.00,3.0,10.0,30.0,100.,300.,1000./
1094      !-------------------------------------------------------------------
1095
1096      LOGICAL  :: lfound=.FALSE.
1097      REAL(wp) :: zrr
1098      INTEGER  :: ji, jj, jm
1099
1100      z0tq_LKB(:,:) = -999._wp
1101
1102      DO_2D( nn_hls, nn_hls, nn_hls, nn_hls )
1103
1104      zrr    = pRer(ji,jj)
1105      lfound = .FALSE.
1106
1107      IF( (zrr > 0.).AND.(zrr < 1000.) ) THEN
1108         jm = 0
1109         DO WHILE ( .NOT. lfound )
1110            jm = jm + 1
1111            lfound = ( (zrr > XRAN(jm-1)) .AND. (zrr <= XRAN(jm)) )
1112         END DO
1113
1114         z0tq_LKB(ji,jj) = XA(jm,iflag)*zrr**XB(jm,iflag) * pz0(ji,jj)/zrr
1115
1116      END IF
1117
1118      END_2D
1119
1120      z0tq_LKB(:,:) = MIN( MAX(ABS(z0tq_LKB(:,:)), 1.E-9) , 0.05_wp )
1121
1122   END FUNCTION z0tq_LKB
1123
1124
[12015]1125   !!======================================================================
[13655]1126END MODULE sbc_phy
Note: See TracBrowser for help on using the repository browser.