SCALE-RM
scale_bulkflux.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
11 !-------------------------------------------------------------------------------
13  !-----------------------------------------------------------------------------
14  !
15  !++ used modules
16  !
17  use scale_precision
18  use scale_stdio
19  !-----------------------------------------------------------------------------
20  implicit none
21  private
22  !-----------------------------------------------------------------------------
23  !
24  !++ Public procedure
25  !
26  public :: bulkflux_setup
27 
28  abstract interface
29  subroutine bc( &
30  Ustar, & ! (out)
31  tstar, & ! (out)
32  qstar, & ! (out)
33  uabs, & ! (out)
34  fracu10, & ! (out)
35  fract2, & ! (out)
36  fracq2, & ! (out)
37  t1, & ! (in)
38  t0, & ! (in)
39  p1, & ! (in)
40  p0, & ! (in)
41  q1, & ! (in)
42  q0, & ! (in)
43  u1, & ! (in)
44  v1, & ! (in)
45  z1, & ! (in)
46  pbl, & ! (in)
47  z0m, & ! (in)
48  z0h, & ! (in)
49  z0e ) ! (in)
50  use scale_precision
51  implicit none
52 
53  real(RP), intent(out) :: Ustar ! friction velocity [m/s]
54  real(RP), intent(out) :: Tstar ! friction temperature [K]
55  real(RP), intent(out) :: Qstar ! friction mixing rate [kg/kg]
56  real(RP), intent(out) :: Uabs ! modified absolute velocity [m/s]
57  real(RP), intent(out) :: FracU10 ! calculation parameter for U10 [-]
58  real(RP), intent(out) :: FracT2 ! calculation parameter for T2 [-]
59  real(RP), intent(out) :: FracQ2 ! calculation parameter for Q2 [-]
60 
61  real(RP), intent(in) :: T1 ! tempearature at the lowest atmospheric layer [K]
62  real(RP), intent(in) :: T0 ! skin temperature [K]
63  real(RP), intent(in) :: P1 ! pressure at the lowest atmospheric layer [Pa]
64  real(RP), intent(in) :: P0 ! surface pressure [Pa]
65  real(RP), intent(in) :: Q1 ! mixing ratio at the lowest atmospheric layer [kg/kg]
66  real(RP), intent(in) :: Q0 ! surface mixing ratio [kg/kg]
67  real(RP), intent(in) :: U1 ! zonal wind at the lowest atmospheric layer [m/s]
68  real(RP), intent(in) :: V1 ! meridional wind at the lowest atmospheric layer [m/s]
69  real(RP), intent(in) :: Z1 ! height at the lowest atmospheric layer [m]
70  real(RP), intent(in) :: PBL ! the top of atmospheric mixing layer [m]
71  real(RP), intent(in) :: Z0M ! roughness length of momentum [m]
72  real(RP), intent(in) :: Z0H ! roughness length of heat [m]
73  real(RP), intent(in) :: Z0E ! roughness length of moisture [m]
74  end subroutine bc
75  end interface
76 
77  procedure(bc), pointer :: bulkflux => null()
78  public :: bulkflux
79 
80  !-----------------------------------------------------------------------------
81  !
82  !++ Public parameters & variables
83  !
84  !-----------------------------------------------------------------------------
85  !
86  !++ Private procedure
87  !
88  private :: bulkflux_u95
89  private :: bulkflux_b91w01
90  private :: fm_unstable
91  private :: fh_unstable
92  private :: fm_stable
93  private :: fh_stable
94 
95  !-----------------------------------------------------------------------------
96  !
97  !++ Private parameters & variables
98  !
99  character(len=H_SHORT), private :: bulkflux_type = 'B91W01'
100 
101  integer, private :: bulkflux_itr_sa_max = 5 ! maximum iteration number for successive approximation
102  integer, private :: bulkflux_itr_nr_max = 10 ! maximum iteration number for Newton-Raphson method
103 
104  real(RP), private :: bulkflux_err_min = 1.0e-3_rp ! minimum value of error
105 
106  real(RP), private :: bulkflux_wscf ! empirical scaling factor of Wstar (Beljaars 1994)
107 
108  ! limiter
109  real(RP), private :: bulkflux_uabs_min = 1.0e-2_rp ! minimum of Uabs [m/s]
110  real(RP), private :: bulkflux_wstar_min = 1.0e-4_rp ! minimum of W* [m/s]
111 
112 contains
113 
114  !-----------------------------------------------------------------------------
115  !
116  !-----------------------------------------------------------------------------
117  subroutine bulkflux_setup( dx )
118  use scale_process, only: &
120  implicit none
121  real(RP), intent(in) :: dx
122 
123  namelist / param_bulkflux / &
124  bulkflux_type, &
125  bulkflux_itr_sa_max, &
126  bulkflux_itr_nr_max, &
127  bulkflux_err_min, &
128  bulkflux_wscf, &
129  bulkflux_uabs_min, &
130  bulkflux_wstar_min
131 
132  integer :: ierr
133  !---------------------------------------------------------------------------
134 
135  if( io_l ) write(io_fid_log,*)
136  if( io_l ) write(io_fid_log,*) '++++++ Module[BULKFLUX] / Categ[COUPLER] / Origin[SCALElib]'
137 
138  ! WSCF = 1.2 for dx > 1 km (Beljaars 1994)
139  ! lim_{dx->0} WSCF = 0 for LES (Fig. 6 Kitamura and Ito 2016 BLM)
140  bulkflux_wscf = 1.2_rp * min(dx*1.e-3_rp, 1.0_rp)
141 
142 
143  !--- read namelist
144  rewind(io_fid_conf)
145  read(io_fid_conf,nml=param_bulkflux,iostat=ierr)
146 
147  if( ierr < 0 ) then !--- missing
148  if( io_l ) write(io_fid_log,*) '*** Not found namelist. Default used.'
149  elseif( ierr > 0 ) then !--- fatal error
150  write(*,*) 'xxx Not appropriate names in namelist PARAM_BULKFLUX. Check!'
151  call prc_mpistop
152  endif
153  if( io_nml ) write(io_fid_nml,nml=param_bulkflux)
154 
155  if( io_l ) write(io_fid_log,*)
156  if( io_l ) write(io_fid_log,*) '*** Scheme for surface bulk flux : ', trim(bulkflux_type)
157  select case(bulkflux_type)
158  case('U95')
159  if( io_l ) write(io_fid_log,*) '*** => Uno et al.(1995)'
160  bulkflux => bulkflux_u95
161  case('B91W01')
162  if( io_l ) write(io_fid_log,*) '*** => Beljaars (1991) and Wilson (2001)'
163  bulkflux => bulkflux_b91w01
164  case default
165  write(*,*) 'xxx Unsupported BULKFLUX_type. STOP'
166  call prc_mpistop
167  end select
168 
169  return
170  end subroutine bulkflux_setup
171 
172  !-----------------------------------------------------------------------------
173  ! ref. Uno et al. (1995)
174  !-----------------------------------------------------------------------------
175  subroutine bulkflux_u95( &
176  Ustar, & ! (out)
177  tstar, & ! (out)
178  qstar, & ! (out)
179  uabs, & ! (out)
180  fracu10, & ! (out)
181  fract2, & ! (out)
182  fracq2, & ! (out)
183  t1, & ! (in)
184  t0, & ! (in)
185  p1, & ! (in)
186  p0, & ! (in)
187  q1, & ! (in)
188  q0, & ! (in)
189  u1, & ! (in)
190  v1, & ! (in)
191  z1, & ! (in)
192  pbl, & ! (in)
193  z0m, & ! (in)
194  z0h, & ! (in)
195  z0e ) ! (in)
196  use scale_const, only: &
197  grav => const_grav, &
198  karman => const_karman, &
199  rdry => const_rdry, &
200  cpdry => const_cpdry, &
201  pre00 => const_pre00
202  implicit none
203 
204  ! parameter
205  real(RP), parameter :: tprn = 0.74_rp ! turbulent Prandtl number (Businger et al. 1971)
206  real(RP), parameter :: lfb = 9.4_rp ! Louis factor b (Louis 1979)
207  real(RP), parameter :: lfbp = 4.7_rp ! Louis factor b' (Louis 1979)
208  real(RP), parameter :: lfdm = 7.4_rp ! Louis factor d for momemtum (Louis 1979)
209  real(RP), parameter :: lfdh = 5.3_rp ! Louis factor d for heat (Louis 1979)
210 
211  ! argument
212  real(RP), intent(out) :: ustar ! friction velocity [m/s]
213  real(RP), intent(out) :: tstar ! friction temperature [K]
214  real(RP), intent(out) :: qstar ! friction mixing rate [kg/kg]
215  real(RP), intent(out) :: uabs ! modified absolute velocity [m/s]
216  real(RP), intent(out) :: fracu10 ! calculation parameter for U10 [-]
217  real(RP), intent(out) :: fract2 ! calculation parameter for T2 [-]
218  real(RP), intent(out) :: fracq2 ! calculation parameter for Q2 [-]
219 
220  real(RP), intent(in) :: t1 ! tempearature at the lowest atmospheric layer [K]
221  real(RP), intent(in) :: t0 ! skin temperature [K]
222  real(RP), intent(in) :: p1 ! pressure at the lowest atmospheric layer [Pa]
223  real(RP), intent(in) :: p0 ! surface pressure [Pa]
224  real(RP), intent(in) :: q1 ! mixing ratio at the lowest atmospheric layer [kg/kg]
225  real(RP), intent(in) :: q0 ! surface mixing ratio [kg/kg]
226  real(RP), intent(in) :: u1 ! zonal wind at the lowest atmospheric layer [m/s]
227  real(RP), intent(in) :: v1 ! meridional wind at the lowest atmospheric layer [m/s]
228  real(RP), intent(in) :: z1 ! height at the lowest atmospheric layer [m]
229  real(RP), intent(in) :: pbl ! the top of atmospheric mixing layer [m]
230  real(RP), intent(in) :: z0m ! roughness length of momentum [m]
231  real(RP), intent(in) :: z0h ! roughness length of heat [m]
232  real(RP), intent(in) :: z0e ! roughness length of moisture [m]
233 
234  ! work
235  real(RP) :: rib0, rib ! bulk Richardson number [-]
236  real(RP) :: c0z1, c010, c002 ! initial drag coefficient [-]
237  real(RP) :: cmz1, chz1, cqz1, fmz1, fhz1, t0thz1, q0qez1
238  real(RP) :: cm10, fm10
239  real(RP) :: cm02, ch02, cq02, fm02, fh02, t0th02, q0qe02
240  real(RP) :: th1, th0
241  real(RP) :: logz1z0m, log10z0m, log02z0m
242  real(RP) :: logz0mz0e
243  real(RP) :: logz0mz0h
244  !---------------------------------------------------------------------------
245 
246  logz1z0m = log( z1 / z0m )
247  log10z0m = log( 10.0_rp / z0m )
248  log02z0m = log( 2.0_rp / z0m )
249 
250  logz0mz0e = max( log( z0m/z0e ), 1.0_rp )
251  logz0mz0h = max( log( z0m/z0h ), 1.0_rp )
252 
253  uabs = max( sqrt( u1**2 + v1**2 ), bulkflux_uabs_min )
254  th1 = t1 * ( pre00 / p1 )**( rdry / cpdry )
255  th0 = t0 * ( pre00 / p0 )**( rdry / cpdry )
256 
257  ! bulk Richardson number
258  rib0 = grav * z1 * ( th1 - th0 ) / ( th1 * uabs**2 )
259 
260  c0z1 = ( karman / logz1z0m )**2
261  c010 = ( karman / log10z0m )**2
262  c002 = ( karman / log02z0m )**2
263 
264  rib = rib0
265 
266  if( rib0 > 0.0_rp ) then
267  ! stable condition
268  fmz1 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
269  fhz1 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
270  fm10 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
271  fm02 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
272  fh02 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
273  else
274  ! unstable condition
275  fmz1 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdm * c0z1 * sqrt( z1 / z0m ) * sqrt( abs( rib ) ) )
276  fhz1 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdh * c0z1 * sqrt( z1 / z0m ) * sqrt( abs( rib ) ) )
277  fm10 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdm * c010 * sqrt( 10.0_rp / z0m ) * sqrt( abs( rib ) ) )
278  fm02 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdm * c002 * sqrt( 2.0_rp / z0m ) * sqrt( abs( rib ) ) )
279  fh02 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdh * c002 * sqrt( 2.0_rp / z0m ) * sqrt( abs( rib ) ) )
280  end if
281 
282  t0thz1 = 1.0_rp / ( 1.0_rp + logz0mz0h / logz1z0m / sqrt( fmz1 ) * fhz1 )
283  q0qez1 = 1.0_rp / ( 1.0_rp + logz0mz0e / logz1z0m / sqrt( fmz1 ) * fhz1 )
284  t0th02 = 1.0_rp / ( 1.0_rp + logz0mz0h / log02z0m / sqrt( fm02 ) * fh02 )
285  q0qe02 = 1.0_rp / ( 1.0_rp + logz0mz0e / log02z0m / sqrt( fm02 ) * fh02 )
286 
287  rib = rib * t0thz1
288 
289  if( rib0 > 0.0_rp ) then
290  ! stable condition
291  fmz1 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
292  fhz1 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
293  fm10 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
294  fm02 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
295  fh02 = 1.0_rp / ( 1.0_rp + lfbp * rib )**2
296  else
297  ! unstable condition
298  fmz1 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdm * c0z1 * sqrt( z1 / z0m ) * sqrt( abs( rib ) ) )
299  fhz1 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdh * c0z1 * sqrt( z1 / z0m ) * sqrt( abs( rib ) ) )
300  fm10 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdm * c010 * sqrt( 10.0_rp / z0m ) * sqrt( abs( rib ) ) )
301  fm02 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdm * c002 * sqrt( 2.0_rp / z0m ) * sqrt( abs( rib ) ) )
302  fh02 = 1.0_rp - lfb * rib / ( 1.0_rp + lfb * lfdh * c002 * sqrt( 2.0_rp / z0m ) * sqrt( abs( rib ) ) )
303  end if
304 
305  t0thz1 = 1.0_rp / ( 1.0_rp + logz0mz0h / logz1z0m / sqrt( fmz1 ) * fhz1 )
306  q0qez1 = 1.0_rp / ( 1.0_rp + logz0mz0e / logz1z0m / sqrt( fmz1 ) * fhz1 )
307  t0th02 = 1.0_rp / ( 1.0_rp + logz0mz0h / log02z0m / sqrt( fm02 ) * fh02 )
308  q0qe02 = 1.0_rp / ( 1.0_rp + logz0mz0e / log02z0m / sqrt( fm02 ) * fh02 )
309 
310  cmz1 = c0z1 * fmz1
311  chz1 = c0z1 * fhz1 * t0thz1 / tprn
312  cqz1 = c0z1 * fhz1 * q0qez1 / tprn
313  cm10 = c010 * fm10
314  cm02 = c002 * fm02
315  ch02 = c002 * fh02 * t0th02 / tprn
316  cq02 = c002 * fh02 * q0qe02 / tprn
317 
318  ustar = sqrt( cmz1 ) * uabs
319  tstar = chz1 * uabs / ustar * ( th1 - th0 )
320  qstar = cqz1 * uabs / ustar * ( q1 - q0 )
321 
322  fracu10 = sqrt( cmz1 / cm10 )
323  fract2 = chz1 / ch02 * sqrt( cm02 / cmz1 )
324  fracq2 = cqz1 / cq02 * sqrt( cm02 / cmz1 )
325 
326  return
327  end subroutine bulkflux_u95
328 
329  !-----------------------------------------------------------------------------
330  !
331  ! refs. Beljaars (1991) and Wilson (2001)
332  !
333  ! If you want to run with the original Beljaars scheme (Beljaars and Holtslag 1994),
334  ! you should fix the stability functions (fm_unstable, fh_unstable, fm_stable, and fh_stable).
335  !
336  ! Iteration method: refs. JMA-NHM Description Note II, Mar 2008
337  !
338  !-----------------------------------------------------------------------------
339  subroutine bulkflux_b91w01( &
340  Ustar, & ! (out)
341  tstar, & ! (out)
342  qstar, & ! (out)
343  uabs, & ! (out)
344  fracu10, & ! (out)
345  fract2, & ! (out)
346  fracq2, & ! (out)
347  t1, & ! (in)
348  t0, & ! (in)
349  p1, & ! (in)
350  p0, & ! (in)
351  q1, & ! (in)
352  q0, & ! (in)
353  u1, & ! (in)
354  v1, & ! (in)
355  z1, & ! (in)
356  pbl, & ! (in)
357  z0m, & ! (in)
358  z0h, & ! (in)
359  z0e ) ! (in)
360  use scale_const, only: &
361  grav => const_grav, &
362  karman => const_karman, &
363  rdry => const_rdry, &
364  cpdry => const_cpdry, &
365  epstvap => const_epstvap, &
366  eps => const_eps, &
367  pre00 => const_pre00
368  implicit none
369 
370  ! parameter
371  real(DP), parameter :: dil = 1.0e-6_dp ! delta [1/m]
372 
373  ! argument
374  real(RP), intent(out) :: ustar ! friction velocity [m/s]
375  real(RP), intent(out) :: tstar ! friction temperature [K]
376  real(RP), intent(out) :: qstar ! friction mixing rate [kg/kg]
377  real(RP), intent(out) :: uabs ! modified absolute velocity [m/s]
378  real(RP), intent(out) :: fracu10 ! calculation parameter for U10 [-]
379  real(RP), intent(out) :: fract2 ! calculation parameter for T2 [-]
380  real(RP), intent(out) :: fracq2 ! calculation parameter for Q2 [-]
381 
382  real(RP), intent(in) :: t1 ! tempearature at the lowest atmospheric layer [K]
383  real(RP), intent(in) :: t0 ! skin temperature [K]
384  real(RP), intent(in) :: p1 ! pressure at the lowest atmospheric layer [Pa]
385  real(RP), intent(in) :: p0 ! surface pressure [Pa]
386  real(RP), intent(in) :: q1 ! mixing ratio at the lowest atmospheric layer [kg/kg]
387  real(RP), intent(in) :: q0 ! mixing ratio at surface [kg/kg]
388  real(RP), intent(in) :: u1 ! zonal wind at the lowest atmospheric layer [m/s]
389  real(RP), intent(in) :: v1 ! meridional wind at the lowest atmospheric layer [m/s]
390  real(RP), intent(in) :: z1 ! height at the lowest atmospheric layer [m]
391  real(RP), intent(in) :: pbl ! the top of atmospheric mixing layer [m]
392  real(RP), intent(in) :: z0m ! roughness length of momentum [m]
393  real(RP), intent(in) :: z0h ! roughness length of heat [m]
394  real(RP), intent(in) :: z0e ! roughness length of moisture [m]
395 
396  ! work
397  integer :: n
398 
399  real(DP) :: il ! inversed Obukhov length [1/m]
400  real(DP) :: res ! residual
401  real(DP) :: dres ! d(residual)/dIL
402 
403  real(DP) :: rib0 ! bulk Richardson number [no unit]
404  real(DP) :: wstar, dwstar ! free convection velocity scale [m/s]
405 
406  real(DP) :: uabsus, uabss, uabsc
407  real(DP) :: duabsus, duabss
408 
409  real(DP) :: ustarus, ustars, ustarc
410  real(DP) :: tstarus, tstars, tstarc
411  real(DP) :: qstarus, qstars, qstarc
412 
413  real(DP) :: dustarus, dustars, dustarc
414  real(DP) :: dtstarus, dtstars, dtstarc
415  real(DP) :: dqstarus, dqstars, dqstarc
416 
417  real(DP) :: fracu10us, fracu10s, fracu10c
418  real(DP) :: fract2us, fract2s, fract2c
419  real(DP) :: fracq2us, fracq2s, fracq2c
420 
421  real(DP) :: th1, th0, thm
422  real(DP) :: tv1, tv0, tvm
423  real(DP) :: qm
424  real(DP) :: sw, tmp
425 
426  real(DP) :: bflx, dbflx
427 
428  real(DP) :: dp_z1, dp_z0m, dp_z0h, dp_z0e
429  real(DP) :: log_z1ovz0m, log_z1ovz0h, log_z1ovz0e
430  real(DP) :: log_10ovz0m, log_02ovz0h, log_02ovz0e
431  !---------------------------------------------------------------------------
432 
433  ! convert to DP
434  dp_z1 = real( z1, kind=dp )
435  dp_z0m = real( z0m, kind=dp )
436  dp_z0h = real( z0h, kind=dp )
437  dp_z0e = real( z0e, kind=dp )
438 
439  uabsc = max( sqrt( u1**2 + v1**2 ), bulkflux_uabs_min )
440 
441  th1 = t1 * ( pre00 / p1 )**( rdry / cpdry )
442  th0 = t0 * ( pre00 / p0 )**( rdry / cpdry )
443  thm = ( th1 + th0 ) * 0.5_rp
444  qm = ( q1 + q0 ) * 0.5_rp
445  tv1 = th1 * ( 1.0_dp + epstvap * q1 )
446  tv0 = th0 * ( 1.0_dp + epstvap * q0 )
447  tvm = ( tv1 + tv0 ) * 0.5_rp
448 
449  ! make log constant
450  log_z1ovz0m = log( dp_z1 / dp_z0m )
451  log_z1ovz0h = log( dp_z1 / dp_z0h )
452  log_z1ovz0e = log( dp_z1 / dp_z0e )
453 
454  log_10ovz0m = log( 10.0_dp / dp_z0m )
455  log_02ovz0h = log( 2.0_dp / dp_z0h )
456  log_02ovz0e = log( 2.0_dp / dp_z0e )
457 
458  ! bulk Richardson number at initial step
459  rib0 = grav * dp_z1 * ( tv1 - tv0 ) / ( tvm * uabsc**2 )
460 
461  ! inversed Obukhov length at initial step
462  il = rib0 / dp_z1 * log_z1ovz0m**2 / log_z1ovz0h
463 
464  ! free convection velocity scale at initial step
465  wstar = bulkflux_wstar_min
466  dwstar = bulkflux_wstar_min
467 
468  ! Successive approximation
469  do n = 1, bulkflux_itr_sa_max
470  ! unstable condition
471  uabsus = max( sqrt( u1**2 + v1**2 + (bulkflux_wscf*wstar)**2 ), real( BULKFLUX_Uabs_min, kind=DP ) )
472  ustarus = karman / ( log_z1ovz0m - fm_unstable(dp_z1,il) + fm_unstable(dp_z0m,il) ) * uabsus
473  tstarus = karman / ( log_z1ovz0h - fh_unstable(dp_z1,il) + fh_unstable(dp_z0h,il) ) * ( th1 - th0 )
474  qstarus = karman / ( log_z1ovz0e - fh_unstable(dp_z1,il) + fh_unstable(dp_z0e,il) ) * ( q1 - q0 )
475 
476  ! stable condition
477  uabss = max( sqrt( u1**2 + v1**2 ), bulkflux_uabs_min )
478  ustars = karman / ( log_z1ovz0m - fm_stable(dp_z1,il) + fm_stable(dp_z0m,il) ) * uabss
479  tstars = karman / ( log_z1ovz0h - fh_stable(dp_z1,il) + fh_stable(dp_z0h,il) ) * ( th1 - th0 )
480  qstars = karman / ( log_z1ovz0e - fh_stable(dp_z1,il) + fh_stable(dp_z0e,il) ) * ( q1 - q0 )
481 
482  sw = 0.5_dp - sign( 0.5_dp, il ) ! if unstable, sw = 1
483 
484  ustarc = ( sw ) * ustarus + ( 1.0_dp-sw ) * ustars
485  tstarc = ( sw ) * tstarus + ( 1.0_dp-sw ) * tstars
486  qstarc = ( sw ) * qstarus + ( 1.0_dp-sw ) * qstars
487 
488  ! estimate buoyancy flux
489  bflx = - ustarc * tstarc * ( 1.0_rp + epstvap * qm ) - epstvap * ustarc * qstarc * thm
490 
491  ! update free convection velocity scale
492  tmp = pbl * grav / t1 * bflx
493  sw = 0.5_dp + sign( 0.5_dp, tmp ) ! if tmp is plus, sw = 1
494 
495  wstar = ( tmp * sw )**( 1.0_dp / 3.0_dp )
496 
497  ! avoid zero division with UstarC = 0
498  sw = 0.5_dp + sign( 0.5_dp, abs( ustarc ) - eps )
499 
500  ustarc = ( sw ) * ustarc + ( 1.0_dp-sw ) * eps
501 
502  ! estimate the inversed Obukhov length
503  il = - karman * grav * bflx / ( ustarc**3 * thm )
504  end do
505 
506  ! Newton-Raphson method
507  do n = 1, bulkflux_itr_nr_max
508  ! unstable condition
509  uabsus = max( sqrt( u1**2 + v1**2 + (bulkflux_wscf*wstar)**2 ), real( BULKFLUX_Uabs_min, kind=DP ) )
510  ustarus = karman / ( log_z1ovz0m - fm_unstable(dp_z1,il) + fm_unstable(dp_z0m,il) ) * uabsus
511  tstarus = karman / ( log_z1ovz0h - fh_unstable(dp_z1,il) + fh_unstable(dp_z0h,il) ) * ( th1 - th0 )
512  qstarus = karman / ( log_z1ovz0e - fh_unstable(dp_z1,il) + fh_unstable(dp_z0e,il) ) * ( q1 - q0 )
513 
514  ! stable condition
515  uabss = max( sqrt( u1**2 + v1**2 ), bulkflux_uabs_min )
516  ustars = karman / ( log_z1ovz0m - fm_stable(dp_z1,il) + fm_stable(dp_z0m,il) ) * uabss
517  tstars = karman / ( log_z1ovz0h - fh_stable(dp_z1,il) + fh_stable(dp_z0h,il) ) * ( th1 - th0 )
518  qstars = karman / ( log_z1ovz0e - fh_stable(dp_z1,il) + fh_stable(dp_z0e,il) ) * ( q1 - q0 )
519 
520  sw = 0.5_dp - sign( 0.5_dp, il ) ! if unstable, sw = 1
521 
522  ustarc = ( sw ) * ustarus + ( 1.0_dp-sw ) * ustars
523  tstarc = ( sw ) * tstarus + ( 1.0_dp-sw ) * tstars
524  qstarc = ( sw ) * qstarus + ( 1.0_dp-sw ) * qstars
525 
526  ! estimate buoyancy flux
527  bflx = - ustarc * tstarc * ( 1.0_rp + epstvap * qm ) - epstvap * ustarc * qstarc * thm
528 
529  ! update free convection velocity scale
530  tmp = pbl * grav / t1 * bflx
531  sw = 0.5_dp + sign( 0.5_dp, tmp ) ! if tmp is plus, sw = 1
532 
533  wstar = ( tmp * sw )**( 1.0_dp / 3.0_dp )
534 
535  ! avoid zero division with UstarC = 0
536  sw = 0.5_dp + sign( 0.5_dp, abs( ustarc ) - eps )
537 
538  ustarc = ( sw ) * ustarc + ( 1.0_dp-sw ) * eps
539 
540  ! calculate residual
541  res = il + karman * grav * bflx / ( ustarc**3 * thm )
542 
543  ! unstable condition
544  duabsus = max( sqrt( u1**2 + v1**2 + (bulkflux_wscf*dwstar)**2 ), real( BULKFLUX_Uabs_min, kind=DP ) )
545  dustarus = karman / ( log_z1ovz0m - fm_unstable(dp_z1,il+dil) + fm_unstable(dp_z0m,il+dil) ) * duabsus
546  dtstarus = karman / ( log_z1ovz0h - fh_unstable(dp_z1,il+dil) + fh_unstable(dp_z0h,il+dil) ) * ( th1 - th0 )
547  dqstarus = karman / ( log_z1ovz0e - fh_unstable(dp_z1,il+dil) + fh_unstable(dp_z0e,il+dil) ) * ( q1 - q0 )
548 
549  ! stable condition
550  duabss = max( sqrt( u1**2 + v1**2 ), bulkflux_uabs_min )
551  dustars = karman / ( log_z1ovz0m - fm_stable(dp_z1,il+dil) + fm_stable(dp_z0m,il+dil) ) * duabss
552  dtstars = karman / ( log_z1ovz0h - fh_stable(dp_z1,il+dil) + fh_stable(dp_z0h,il+dil) ) * ( th1 - th0 )
553  dqstars = karman / ( log_z1ovz0e - fh_stable(dp_z1,il+dil) + fh_stable(dp_z0e,il+dil) ) * ( q1 - q0 )
554 
555  sw = 0.5_dp - sign( 0.5_dp, il+dil ) ! if unstable, sw = 1
556 
557  dustarc = ( sw ) * dustarus + ( 1.0_dp-sw ) * dustars
558  dtstarc = ( sw ) * dtstarus + ( 1.0_dp-sw ) * dtstars
559  dqstarc = ( sw ) * dqstarus + ( 1.0_dp-sw ) * dqstars
560 
561  ! estimate buoyancy flux
562  dbflx = - dustarc * dtstarc * ( 1.0_rp + epstvap * qm ) - epstvap * dustarc * dqstarc * thm
563 
564  ! update d(free convection velocity scale)
565  tmp = pbl * grav / t1 * dbflx
566  sw = 0.5_dp + sign( 0.5_dp, tmp ) ! if tmp is plus, sw = 1
567 
568  dwstar = ( tmp * sw )**( 1.0_dp / 3.0_dp )
569 
570  ! avoid zero division with dUstarC = 0
571  sw = 0.5_dp + sign( 0.5_dp, abs( dustarc ) - eps )
572 
573  dustarc = ( sw ) * dustarc + ( 1.0_dp-sw ) * eps
574 
575  ! calculate d(residual)/dIL
576  dres = 1.0_dp + karman * grav / ( thm * dil ) * ( dbflx / dustarc**3 - bflx / ustarc**3 )
577 
578  ! stop iteration to prevent numerical error
579  if( abs( dres ) < eps ) exit
580 
581  ! convergence test with error levels
582  if( abs( res/dres ) < bulkflux_err_min ) exit
583 
584  ! avoid sign changing
585  if( il * ( il - res / dres ) < 0.0_rp ) exit
586 
587  ! update the inversed Obukhov length
588  il = il - res / dres
589  end do
590 
591  ! Successive approximation after Newton-Raphson method
592  if( .NOT. abs( res/dres ) < bulkflux_err_min ) then
593  ! unstable condition
594  uabsus = max( sqrt( u1**2 + v1**2 + (bulkflux_wscf*wstar)**2 ), real( BULKFLUX_Uabs_min, kind=DP ) )
595  ustarus = karman / ( log_z1ovz0m - fm_unstable(dp_z1,il) + fm_unstable(dp_z0m,il) ) * uabsus
596  tstarus = karman / ( log_z1ovz0h - fh_unstable(dp_z1,il) + fh_unstable(dp_z0h,il) ) * ( th1 - th0 )
597  qstarus = karman / ( log_z1ovz0e - fh_unstable(dp_z1,il) + fh_unstable(dp_z0e,il) ) * ( q1 - q0 )
598 
599  ! stable condition
600  uabss = max( sqrt( u1**2 + v1**2 ), bulkflux_uabs_min )
601  ustars = karman / ( log_z1ovz0m - fm_stable(dp_z1,il) + fm_stable(dp_z0m,il) ) * uabss
602  tstars = karman / ( log_z1ovz0h - fh_stable(dp_z1,il) + fh_stable(dp_z0h,il) ) * ( th1 - th0 )
603  qstars = karman / ( log_z1ovz0e - fh_stable(dp_z1,il) + fh_stable(dp_z0e,il) ) * ( q1 - q0 )
604 
605  sw = 0.5_dp - sign( 0.5_dp, il ) ! if unstable, sw = 1
606 
607  ustarc = ( sw ) * ustarus + ( 1.0_dp-sw ) * ustars
608  tstarc = ( sw ) * tstarus + ( 1.0_dp-sw ) * tstars
609  qstarc = ( sw ) * qstarus + ( 1.0_dp-sw ) * qstars
610 
611  ! estimate buoyancy flux
612  bflx = - ustarc * tstarc * ( 1.0_rp + epstvap * qm ) - epstvap * ustarc * qstarc * thm
613 
614  ! update free convection velocity scale
615  tmp = pbl * grav / t1 * bflx
616  sw = 0.5_dp + sign( 0.5_dp, tmp ) ! if tmp is plus, sw = 1
617 
618  wstar = ( tmp * sw )**( 1.0_dp / 3.0_dp )
619 
620  ! avoid zero division with UstarC = 0
621  sw = 0.5_dp + sign( 0.5_dp, abs( ustarc ) - eps )
622 
623  ustarc = ( sw ) * ustarc + ( 1.0_dp-sw ) * eps
624 
625  ! estimate the inversed Obukhov length
626  il = - karman * grav * bflx / ( ustarc**3 * thm )
627  end if
628 
629  ! calculate Ustar, Tstar, and Qstar based on IL
630 
631  ! unstable condition
632  uabsus = max( sqrt( u1**2 + v1**2 + (bulkflux_wscf*wstar)**2 ), real( BULKFLUX_Uabs_min, kind=DP ) )
633  ustarus = karman / ( log_z1ovz0m - fm_unstable(dp_z1,il) + fm_unstable(dp_z0m,il) ) * uabsus
634  tstarus = karman / ( log_z1ovz0h - fh_unstable(dp_z1,il) + fh_unstable(dp_z0h,il) ) * ( th1 - th0 )
635  qstarus = karman / ( log_z1ovz0e - fh_unstable(dp_z1,il) + fh_unstable(dp_z0e,il) ) * ( q1 - q0 )
636 
637  fracu10us = ( log_10ovz0m - fm_unstable(10.0_dp,il) + fm_unstable(dp_z0m,il) ) &
638  / ( log_z1ovz0m - fm_unstable( dp_z1,il) + fm_unstable(dp_z0m,il) )
639  fract2us = ( log_02ovz0h - fm_unstable( 2.0_dp,il) + fm_unstable(dp_z0h,il) ) &
640  / ( log_z1ovz0h - fm_unstable( dp_z1,il) + fm_unstable(dp_z0h,il) )
641  fracq2us = ( log_02ovz0e - fm_unstable( 2.0_dp,il) + fm_unstable(dp_z0e,il) ) &
642  / ( log_z1ovz0e - fm_unstable( dp_z1,il) + fm_unstable(dp_z0e,il) )
643 
644  ! stable condition
645  uabss = max( sqrt( u1**2 + v1**2 ), bulkflux_uabs_min )
646  ustars = karman / ( log_z1ovz0m - fm_stable(dp_z1,il) + fm_stable(dp_z0m,il) ) * uabss
647  tstars = karman / ( log_z1ovz0h - fh_stable(dp_z1,il) + fh_stable(dp_z0h,il) ) * ( th1 - th0 )
648  qstars = karman / ( log_z1ovz0e - fh_stable(dp_z1,il) + fh_stable(dp_z0e,il) ) * ( q1 - q0 )
649 
650  fracu10s = ( log_10ovz0m - fm_stable(10.0_dp,il) + fm_stable(dp_z0m,il) ) &
651  / ( log_z1ovz0m - fm_stable( dp_z1,il) + fm_stable(dp_z0m,il) )
652  fract2s = ( log_02ovz0h - fm_stable( 2.0_dp,il) + fm_stable(dp_z0h,il) ) &
653  / ( log_z1ovz0h - fm_stable( dp_z1,il) + fm_stable(dp_z0h,il) )
654  fracq2s = ( log_02ovz0e - fm_stable( 2.0_dp,il) + fm_stable(dp_z0e,il) ) &
655  / ( log_z1ovz0e - fm_stable( dp_z1,il) + fm_stable(dp_z0e,il) )
656 
657  sw = 0.5_dp - sign( 0.5_dp, il ) ! if unstable, sw = 1
658 
659  ustarc = ( sw ) * ustarus + ( 1.0_dp-sw ) * ustars
660  tstarc = ( sw ) * tstarus + ( 1.0_dp-sw ) * tstars
661  qstarc = ( sw ) * qstarus + ( 1.0_dp-sw ) * qstars
662  uabsc = ( sw ) * uabsus + ( 1.0_dp-sw ) * uabss
663  fracu10c = ( sw ) * fracu10us + ( 1.0_dp-sw ) * fracu10s
664  fract2c = ( sw ) * fract2us + ( 1.0_dp-sw ) * fract2s
665  fracq2c = ( sw ) * fracq2us + ( 1.0_dp-sw ) * fracq2s
666 
667  ! revert to RP
668  ustar = real( ustarc, kind=rp )
669  tstar = real( tstarc, kind=rp )
670  qstar = real( qstarc, kind=rp )
671  uabs = real( uabsc, kind=rp )
672  fracu10 = real( fracu10c, kind=rp )
673  fract2 = real( fract2c, kind=rp )
674  fracq2 = real( fracq2c, kind=rp )
675 
676  return
677  end subroutine bulkflux_b91w01
678 
679  !-----------------------------------------------------------------------------
680  ! stability function for momemtum in unstable condition
681  function fm_unstable( Z, IL )
682  !use scale_const, only: &
683  ! PI => CONST_PI
684  implicit none
685 
686  ! argument
687  real(DP), intent(in) :: z
688  real(DP), intent(in) :: il
689 
690  ! function
691  real(DP) :: fm_unstable
692 
693  ! works
694  real(DP) :: r
695  !real(DP) :: r4R
696  !---------------------------------------------------------------------------
697 
698  r = min( z * il, 0.0_dp )
699 
700  ! Wilson (2001)
701  fm_unstable = 3.0_dp * log( ( 1.0_dp + sqrt( 1.0_dp + 3.6_dp * (-r)**(2.0_dp/3.0_dp) ) ) * 0.5_dp )
702 
703  ! If you want to run with the original Beljaars scheme (Beljaars and Holtslag 1994),
704  ! you should comment out the above line (Wilson 2001) and uncomment the below lines (Paulson 1974; Dyer 1974).
705  !
706  !! Paulson (1974); Dyer (1974)
707  !r4R = ( 1.0_DP - 16.0_DP * R )**0.25_DP
708  !fm_unstable = log( ( 1.0_DP + r4R )**2 * ( 1.0_DP + r4R * r4R ) * 0.125_DP ) - 2.0_DP * atan( r4R ) + PI * 0.5_DP
709 
710  return
711  end function fm_unstable
712 
713  !-----------------------------------------------------------------------------
714  ! stability function for heat/vapor in unstable condition
715  function fh_unstable( Z, IL )
716  implicit none
717 
718  ! argument
719  real(DP), intent(in) :: z
720  real(DP), intent(in) :: il
721 
722  ! function
723  real(DP) :: fh_unstable
724 
725  ! Wilson (2001)
726  real(DP), parameter :: pt = 0.95_dp ! turbulent Prandtl number
727 
728  ! works
729  real(DP) :: r
730  !---------------------------------------------------------------------------
731 
732  r = min( z * il, 0.0_dp )
733 
734  ! Wilson (2001)
735  fh_unstable = 3.0_dp * log( ( 1.0_dp + sqrt( 1.0_dp + 7.9_dp * (-r)**(2.0_dp/3.0_dp) ) ) * 0.5_dp )
736  fh_unstable = pt * fh_unstable + ( 1.0_dp - pt ) * log( z )
737 
738  ! If you want to run with the original Beljaars scheme (Beljaars and Holtslag 1994),
739  ! you should comment out the above line (Wilson 2001) and uncomment the below lines (Paulson 1974; Dyer 1974).
740  !
741  !! Paulson (1974); Dyer (1974)
742  !fh_unstable = 2.0_DP * log( ( 1.0_DP + sqrt( 1.0_DP - 16.0_DP * R ) ) * 0.5_DP )
743 
744  return
745  end function fh_unstable
746 
747  !-----------------------------------------------------------------------------
748  ! stability function for momemtum in stable condition
749  function fm_stable( Z, IL )
750  implicit none
751 
752  ! argument
753  real(DP), intent(in) :: z
754  real(DP), intent(in) :: il
755 
756  ! function
757  real(DP) :: fm_stable
758 
759  ! parameters of stability functions (Beljaars and Holtslag 1991)
760  real(DP), parameter :: a = 1.0_dp
761  real(DP), parameter :: b = 0.667_dp
762  real(DP), parameter :: c = 5.0_dp
763  real(DP), parameter :: d = 0.35_dp
764 
765  ! works
766  real(DP) :: r
767  !---------------------------------------------------------------------------
768 
769  r = max( z * il, 0.0_dp )
770 
771  ! Holtslag and DeBruin (1988)
772 #if defined(PGI) || defined(SX)
773  fm_stable = - a*r - b*( r - c/d )*exp( -min( d*r, 1.e+3_rp ) ) - b*c/d ! apply exp limiter
774 #else
775  fm_stable = - a*r - b*( r - c/d )*exp( -d*r ) - b*c/d
776 #endif
777 
778  return
779  end function fm_stable
780 
781  !-----------------------------------------------------------------------------
782  ! stability function for heat/vapor in stable condition
783  function fh_stable( Z, IL )
784  implicit none
785 
786  ! argument
787  real(DP), intent(in) :: z
788  real(DP), intent(in) :: il
789 
790  ! function
791  real(DP) :: fh_stable
792 
793  ! parameters of stability functions (Beljaars and Holtslag 1991)
794  real(DP), parameter :: a = 1.0_dp
795  real(DP), parameter :: b = 0.667_dp
796  real(DP), parameter :: c = 5.0_dp
797  real(DP), parameter :: d = 0.35_dp
798 
799  ! works
800  real(DP) :: r
801  !---------------------------------------------------------------------------
802 
803  r = max( z * il, 0.0_dp )
804 
805  ! Beljaars and Holtslag (1991)
806 #if defined(PGI) || defined(SX)
807  fh_stable = 1.0_dp - ( 1.0_dp + 2.0_dp/3.0_dp * a*r )**1.5_dp - b*( r - c/d )*exp( -min( d*r, 1.e+3_rp ) ) - b*c/d ! apply exp limiter
808 #else
809  fh_stable = 1.0_dp - ( 1.0_dp + 2.0_dp/3.0_dp * a*r )**1.5_dp - b*( r - c/d )*exp( -d*r ) - b*c/d
810 #endif
811 
812  return
813  end function fh_stable
814 
815 end module scale_bulkflux
real(rp), public const_cpdry
specific heat (dry air,constant pressure) [J/kg/K]
Definition: scale_const.F90:58
subroutine, public prc_mpistop
Abort MPI.
logical, public io_l
output log or not? (this process)
Definition: scale_stdio.F90:61
module STDIO
Definition: scale_stdio.F90:12
real(rp), parameter, public const_karman
von Karman constant
Definition: scale_const.F90:52
real(rp), public const_rdry
specific gas constant (dry air) [J/kg/K]
Definition: scale_const.F90:57
logical, public io_nml
output log or not? (for namelist, this process)
Definition: scale_stdio.F90:62
real(rp), public const_pre00
pressure reference [Pa]
Definition: scale_const.F90:90
procedure(bc), pointer, public bulkflux
real(rp), public const_grav
standard acceleration of gravity [m/s2]
Definition: scale_const.F90:48
module PROCESS
real(rp), public const_epstvap
1 / epsilon - 1
Definition: scale_const.F90:72
module CONSTANT
Definition: scale_const.F90:14
module Surface bulk flux
real(rp), public const_eps
small number
Definition: scale_const.F90:36
module PRECISION
integer, public io_fid_conf
Config file ID.
Definition: scale_stdio.F90:55
subroutine, public bulkflux_setup(dx)
integer, public io_fid_log
Log file ID.
Definition: scale_stdio.F90:56
integer, parameter, public rp
integer, parameter, public dp
integer, public io_fid_nml
Log file ID (only for output namelist)
Definition: scale_stdio.F90:57