1 subroutine da_sfc_wtq (psfc, tg, ps, ts, qs, us, vs, &
2 hs, roughness, xland, dx, u10, v10, t2, q2, regime, &
3 has_lsm, regime_wrf, qsfc_wrf, znt_wrf, ust_wrf, mol_wrf, hfx, qfx, pblh)
5 !---------------------------------------------------------------------------
6 ! Purpose: Calculate the 10m wind, 2m temperature and moisture based on the
9 ! The unit for pressure : psfc, ps is Pa.
10 ! The unit for temperature: tg, ts, t2 is K.
11 ! The unit for moisture : qs, q2 is kg/kg.
12 ! The unit for wind : us, vs, u10, v10 is m/s.
13 ! The unit for height : hs, roughness is m.
14 ! xland and regime are dimensionless.
16 ! History: Nov 2010 - improve calculation consistency with WRF model (Eric Chiang)
17 ! Jul 2015 - further improvement on consistency
24 ! psfc, tg : surface pressure and ground temperature
25 ! ps, ts, qs, us, vs, hs : model variable at lowlest half sigma level
26 ! dx (m) : horizontal resolution
31 ! hs : height at the lowest half sigma level
32 ! roughness : roughness
33 ! xland : land-water-mask (=2 water, =1 land)
38 ! u10, v10 : 10-m high observed wind components
39 ! t2 , q2 : 2-m high observed temperature and mixing ratio
41 !---------------------------------------------------------------------------
43 ! psim : mechanical psi at lowlest sigma level
44 ! psim2 : mechanical psi at 2m
45 ! psimz : mechanical psi at 10m
47 !---------------------------------------------------------------------------
51 real, intent (in) :: ps , ts , qs , us, vs
52 real, intent (in) :: psfc, tg
53 real, intent (in) :: hs, roughness, xland
54 real, intent (out) :: regime
55 real, intent (out) :: u10, v10, t2, q2
56 logical, intent(in), optional :: has_lsm
57 real, intent(in), optional :: regime_wrf, qsfc_wrf, znt_wrf, ust_wrf, mol_wrf
58 real, intent(in), optional :: hfx, qfx, pblh
60 logical :: use_table = .true.
61 logical :: use_ust_wrf = .false.
65 real :: cqs2, chs2, rho, rhox, fluxc, visc, restar, z0t, z0q
67 ! h10 is the height of 10m where the wind observed
68 ! h2 is the height of 2m where the temperature and
71 real, parameter :: h10 = 10.0, h2 = 2.0
73 ! Default roughness over the land
75 real, parameter :: zint0 = 0.01
79 real, parameter :: k_kar = 0.4
83 real :: Vc2, Va2, V2, vc, wspd
84 real :: rib, rcp, xx, yy, cc
85 real :: psiw, psiz, mol, ust, hol, holz, hol2
86 real :: psim, psimz, psim2, psih, psihz, psih2
87 real :: psit, psit2, psiq, psiq2
88 real :: gzsoz0, gz10oz0, gz2oz0
89 real :: eg, qg, tvg, tvs, tvs2
90 real :: ths, thg, thvs, thvg, thvs2, vsgd, vsgd2, dx
93 real, parameter :: ka = 2.4E-5
95 if (trace_use_dull) call da_trace_entry("da_sfc_wtq")
99 ! 1 Compute the roughness length based upon season and land use
101 ! 1.1 Define the roughness length
105 if (z0 < 0.0001) z0 = 0.0001
107 if ( present(znt_wrf) ) then
108 if ( znt_wrf > 0.0 ) then
113 ! 1.2 Define the rouhgness length for moisture
115 if (xland .ge. 1.5) then
121 ! 1.3 Define the some constant variable for psi
125 gz10oz0 = log(h10/z0)
130 ! 2. Calculate the virtual temperature
132 ! 2.1 Compute Virtual temperature on the lowest half sigma level
134 tvs = ts * (1.0 + 0.608 * qs)
136 ! 2.2 Convert ground virtual temperature assuming it's saturated
138 call da_tp_to_qs(tg, psfc, eg, qg) !output qg is specific humidity
139 qg = qg*(1.0-qg) !hcl convert to mixing ratio
140 if ( present(qsfc_wrf) ) then
141 if ( qsfc_wrf > 0.0 ) then
146 tvg = tg * (1.0 + 0.608 * qg)
148 ! 3. Compute the potential temperature
150 ! 3.1 Potential temperature on the lowest half sigma level
152 ths = ts * (1000.0 / (ps/100.0)) ** rcp
154 ! 3.2 Potential temperature at the ground
156 thg = tg * (1000.0 / (psfc/100.0)) ** rcp
158 ! 4. Virtual potential temperature
160 ! 4.1 Virtual potential temperature on the lowest half sigma level
162 thvs = tvs * (1000.0 / (ps/100.0)) ** rcp
164 ! 4.2 Virtual potential temperature at ground
166 thvg = tvg * (1000.0 / (psfc/100.0)) ** rcp
169 ! 5. BULK RICHARDSON NUMBER AND MONI-OBUKOV LENGTH
177 ! Convective velocity:
180 if ( present(hfx) .and. present(qfx) .and. present(pblh) ) then
181 ! calculating vconv over land following wrf method
182 if ( pblh > 0.0 ) then
187 if (thvg >= thvs) then
188 ! prior to V3.7, Vc2 = 4.0 * (thvg - thvs)
193 if ( xland < 1.5 ) then !land
194 if ( vconv_wrf ) then
195 ! following the calculation as in module_sf_sfclay.F
196 rhox = psfc/(gas_constant*tvg)
197 fluxc = max(hfx/rhox/cp+0.608*tvg*qfx/rhox, 0.0)
198 vc = (gravity/tg*pblh*fluxc)**0.33
203 ! Calculate Mahrt and Sun low-res correction ! Add by Eric Chiang ( July 2010 )
204 vsgd = 0.32 * (max(dx/5000.-1.,0.))**0.33 ! Add by Eric Chiang ( July 2010 )
205 vsgd2 = vsgd * vsgd ! Add by Eric Chiang ( July 2010 )
207 V2 = Va2 + Vc2 + vsgd2 ! Add by Eric Chiang ( July 2010 )
212 ! 5.2 Bulk richardson number
214 rib = (gravity * hs / ths) * (thvs - thvg) / V2
216 ! if previously unstable, do not let into regime 1 and 2
217 if ( present(mol_wrf) ) then
218 if ( mol_wrf < 0.0 ) rib = min(rib, 0.0)
221 ! Calculate ust, m/L (mol), h/L (hol)
228 if ( present(ust_wrf) ) then
229 if ( ust_wrf > 0.0 ) then
234 if ( .not. use_ust_wrf ) then
235 !ust = 0.0001 !init value as in phys/module_physics_init.F
236 ust = k_kar * sqrt(v2) /(gzsoz0 - psim)
241 if ( present(mol_wrf) ) then
244 mol = k_kar * (ths - thg)/(gzsoz0 - psih)
248 ! set regimes based on rib
249 if (rib .GE. 0.2) then
250 ! Stable conditions (REGIME 1)
252 else if ((rib .LT. 0.2) .AND. (rib .GT. 0.0)) then
253 ! Mechanically driven turbulence (REGIME 2)
255 else if (rib .EQ. 0.0) then
256 ! Unstable Forced convection (REGIME 3)
259 ! Free convection (REGIME 4)
263 if ( present(regime_wrf) ) then
264 if ( regime_wrf > 0.0 ) then
269 ! 6. CALCULATE PSI BASED UPON REGIME
271 !if (rib .GE. 0.2) then
272 if ( nint(regime) == 1 ) then
273 ! 6.1 Stable conditions (REGIME 1)
274 ! ---------------------------
277 psim = max(psim,-10.0)
278 psimz = h10/hs * psim
279 psimz = max(psimz,-10.0)
280 psim2 = h2 /hs * psim
281 psim2 = max(psim2,-10.0)
286 !else if ((rib .LT. 0.2) .AND. (rib .GT. 0.0)) then
287 else if ( nint(regime) == 2 ) then
289 ! 6.2 Mechanically driven turbulence (REGIME 2)
292 psim = (-5.0 * rib) * gzsoz0 / (1.1 - 5.0*rib)
293 psim = max(psim,-10.0)
294 psimz = h10/hs * psim
295 psimz = max(psimz,-10.0)
296 psim2 = h2 /hs * psim
297 psim2 = max(psim2,-10.0)
302 !else if (rib .EQ. 0.0) then
303 else if ( nint(regime) == 3 ) then
304 ! 6.3 Unstable Forced convection (REGIME 3)
315 ! 6.4 Free convection (REGIME 4)
320 ! Ratio of PBL height to Monin-Obukhov length
322 if (ust .LT. 0.01) then
325 hol = k_kar * gravity * hs * mol / (ths * ust * ust)
328 ! 6.4.2 Calculate n, nz, R, Rz
330 holz = (h10 / hs) * hol
331 hol2 = (h2 / hs) * hol
334 hol = max(hol,-9.9999)
337 holz = max(holz,-9.9999)
340 hol2 = max(hol2,-9.9999)
342 ! 6.4.3 Calculate Psim & psih
344 if ( use_table ) then
345 ! Using the look-up table:
346 nn = int(-100.0 * hol)
347 rr = (-100.0 * hol) - nn
348 psim = psimtb(nn) + rr * (psimtb(nn+1) - psimtb(nn))
349 psih = psihtb(nn) + rr * (psihtb(nn+1) - psihtb(nn))
351 ! Using the continuous function:
352 xx = (1.0 - 16.0 * hol) ** 0.25
353 yy = log((1.0+xx*xx)/2.0)
354 psim = 2.0 * log((1.0+xx)/2.0) + yy - 2.0 * atan(xx) + cc
358 if ( use_table ) then
359 ! Using the look-up table:
360 nz = int(-100.0 * holz)
361 rz = (-100.0 * holz) - nz
362 psimz = psimtb(nz) + rz * (psimtb(nz+1) - psimtb(nz))
363 psihz = psihtb(nz) + rz * (psihtb(nz+1) - psihtb(nz))
365 ! Using the continuous function:
366 xx = (1.0 - 16.0 * holz) ** 0.25
367 yy = log((1.0+xx*xx)/2.0)
368 psimz = 2.0 * log((1.0+xx)/2.0) + yy - 2.0 * atan(xx) + cc
372 if ( use_table ) then
373 ! Using the look-up table:
374 n2 = int(-100.0 * hol2)
375 r2 = (-100.0 * hol2) - n2
376 psim2 = psimtb(n2) + r2 * (psimtb(n2+1) - psimtb(n2))
377 psih2 = psihtb(n2) + r2 * (psihtb(n2+1) - psihtb(n2))
379 ! Using the continuous function:
380 xx = (1.0 - 16.0 * hol2) ** 0.25
381 yy = log((1.0+xx*xx)/2.0)
382 psim2 = 2.0 * log((1.0+xx)/2.0) + yy - 2.0 * atan(xx) + cc
386 ! 6.4.4 Define the limit value for psim & psih
388 psim = min(psim,0.9*gzsoz0)
389 psimz = min(psimz,0.9*gz10oz0)
390 psim2 = min(psim2,0.9*gz2oz0)
391 psih = min(psih,0.9*gzsoz0)
392 psihz = min(psihz,0.9*gz10oz0)
393 psih2 = min(psih2,0.9*gz2oz0)
396 ! 7. Calculate psi for wind, temperature and moisture
399 psiz = gz10oz0 - psimz
400 psit = max(gzsoz0-psih, 2.0)
401 psit2 = gz2oz0 - psih2
403 if ( .not. use_ust_wrf ) then
404 ! re-calculate ust since psim is now available
405 ust = k_kar * sqrt(v2) /(gzsoz0 - psim)
408 psiq = log(k_kar*ust*hs/ka + hs / zq0) - psih
409 psiq2 = log(k_kar*ust*h2/ka + h2 / zq0) - psih2
411 !V3.7, as in module_sf_sfclay.F
412 if ( xland >= 1.5 ) then !water
413 visc = (1.32+0.009*(ts-273.15))*1.e-5
415 z0t = (5.5e-5)*(restar**(-0.60))
416 z0t = min(z0t,1.0e-4)
417 z0t = max(z0t,2.0e-9)
419 psiq = max(log((hs+z0q)/z0q)-psih, 2.)
420 psit = max(log((hs+z0t)/z0t)-psih, 2.)
421 psiq2 = max(log((2.+z0q)/z0q)-psih2, 2.)
422 psit2 = max(log((2.+z0t)/z0t)-psih2, 2.)
425 ! 8. Calculate 10m wind, 2m temperature and moisture
427 u10 = us * psiz / psiw
428 v10 = vs * psiz / psiw
429 t2 = (thg + (ths - thg)*psit2/psit)*((psfc/100.0)/1000.0)**rcp
430 q2 = qg + (qs - qg)*psiq2/psiq
432 if ( present(has_lsm) ) then
434 !cqs2: 2m surface exchange coefficient for moisture
435 !chs2: 2m surface exchange coefficient for heat
436 cqs2 = ust*k_kar/psiq2
437 if (xland .ge. 1.5) then
439 chs2 = ust*k_kar/psit2
442 chs2 = cqs2 !as in subroutine lsm in phys/module_sf_noahdrv.F
445 !re-calculate T2/Q2 as in module_sf_sfcdiags.F
446 rho = psfc/(gas_constant*tg)
447 if ( cqs2 < 1.e-5 ) then
450 if ( present(qfx) ) then
451 q2 = qg - qfx/(rho*cqs2)
454 if ( chs2 < 1.e-5 ) then
457 if ( present(hfx) ) then
458 t2 = tg - hfx/(rho*cp*chs2)
464 if (trace_use_dull) call da_trace_exit("da_sfc_wtq")
466 end subroutine da_sfc_wtq