UFO
ufo_atmsfc_mod.F90
Go to the documentation of this file.
1 module atmsfc_mod
2 
3 contains
4 
5 subroutine sfc_wind_fact_gsi(u, v, tsen, q, psfc, prsi1, prsi2,&
6  skint, z0, lsmask, f10m)
7  ! compute wind reduction factor
8  ! aka the coefficient to multiply u,v in lowest model level
9  ! to get u,v at 'obshgt' aka 10m agl
10  ! based off of compute_fact10 from GSI
11  use kinds
14  implicit none
15  real(kind_real), intent(in) :: u, v, tsen, q, psfc, prsi1, prsi2,&
16  skint, z0, lsmask
17  real(kind_real), intent(out) :: f10m
18  real(kind_real), parameter :: alpha = 5.0_kind_real
19  real(kind_real), parameter :: a0 = -3.975_kind_real
20  real(kind_real), parameter :: a1 = 12.32_kind_real
21  real(kind_real), parameter :: b1 = -7.755_kind_real
22  real(kind_real), parameter :: b2 = 6.041_kind_real
23  real(kind_real), parameter :: a0p = -7.941_kind_real
24  real(kind_real), parameter :: a1p = 24.75_kind_real
25  real(kind_real), parameter :: b1p = -8.705_kind_real
26  real(kind_real), parameter :: b2p = 7.899_kind_real
27  real(kind_real), parameter :: vis = 1.4e-5_kind_real
28  real(kind_real), parameter :: fv = rv_over_rd - one
29  real(kind_real),parameter:: charnok = 0.014_kind_real
30 
31  real(kind_real) :: rat, restar, ustar, del, tem, prki1, prki2, prkl, prsl
32  real(kind_real) :: wspd, wind, q0, theta1, tv1, thv1, tvs, z1
33  real(kind_real) :: z0max, ztmax, dtv, adtv, rb, fm, fh, hlinf, fm10
34  real(kind_real) :: hl1, hl0inf, hltinf, aa, aa0, bb, bb0, pm, ph, fms, fhs
35  real(kind_real) :: hl0, hlt, hl110, pm10, hl12, ph2, olinf
36 
37 
38  rat=zero
39  restar=zero
40  ustar=zero
41  del = (prsi1-prsi2)*1.0e-3_kind_real
42  tem = (one + rd_over_cp) * del
43  prki1 = (prsi1*1.0e-5_kind_real)**rd_over_cp
44  prki2 = (prsi2*1.0e-5_kind_real)**rd_over_cp
45  prkl = (prki1*(prsi1*1.0e-3_kind_real)-prki2*(prsi2*1.0e-3_kind_real))/tem
46  prsl = 1.0e5_kind_real*prkl**(one/rd_over_cp)
47  wspd = sqrt( u*u + v*v )
48  wind = max(wspd,one)
49  q0 = max(q,1.e-8_kind_real)
50  theta1 = tsen * (prki1/prkl)
51  tv1 = tsen * (one+fv*q0)
52  thv1 = theta1 * (one+fv*q0)
53  tvs = skint * (one+fv*q0) ! fix this
54  z1 = -rd*tv1*log(prsl/psfc)/grav
55 
56  ! compute stability dependent exchange coefficients
57  if (lsmask < 0.01_kind_real) then
58  ustar = sqrt(grav * z0 / charnok)
59  end if
60  ! compute stability indices (rb and hlinf)
61  z0max = min(z0,one*z1)
62  ztmax = z0max
63  if (lsmask < 0.01_kind_real) then
64  restar = ustar * z0max / vis
65  restar = max(restar, 1.e-6_kind_real)
66  ! rat taken from Zeng, Zhao and Dickinson 1997
67  rat = 2.67_kind_real * restar**quarter - 2.57_kind_real
68  rat = min(rat, 7.0_kind_real)
69  ztmax = z0max * exp(-rat)
70  end if
71 
72  dtv = thv1 - tvs
73  adtv = abs(dtv)
74  adtv = max(adtv,1.e-3_kind_real)
75  dtv = sign(one,dtv)*adtv
76  rb = grav * dtv * z1 / (half * (thv1 + tvs) * wind * wind)
77  rb = max(rb,-5.e3_kind_real)
78  fm = log((z0max + z1) / z0max)
79  fh = log((ztmax + z1) / ztmax)
80  hlinf = rb * fm * fm / fh
81  fm10 = log((z0max + 10.0_kind_real) / z0max)
82 
83  ! stable case
84  if (dtv >= zero) then
85  hl1 = hlinf
86  end if
87  if ((dtv >= zero) .and. (hlinf > quarter)) then
88  hl0inf = z0max * hlinf / z1
89  hltinf = ztmax * hlinf / z1
90  aa = sqrt(one + four*alpha*hlinf)
91  aa0 = sqrt(one + four*alpha*hl0inf)
92  bb = aa
93  bb0 = sqrt(one + four*alpha*hltinf)
94  pm = aa0 - aa + log((aa+one)/(aa0+one))
95  ph = bb0 - bb + log((bb+one)/(bb0+one))
96  fms = fm - pm
97  fhs = fh - ph
98  hl1 = fms * fms * rb / fhs
99  end if
100  ! second iteration
101  if (dtv >= zero) then
102  hl0 = z0max * hl1 / z1
103  hlt = ztmax * hl1 / z1
104  aa = sqrt(one + four*alpha*hl1)
105  aa0 = sqrt(one + four*alpha*hl0)
106  bb = aa
107  bb0 = sqrt(one + four*alpha*hlt)
108  pm = aa0 - aa + log((aa+one)/(aa0+one))
109  ph = bb0 - bb + log((bb+one)/(bb0+one))
110  hl110 = hl1 * ten / z1
111  aa = sqrt(one + four*alpha*hl110)
112  pm10 = aa0 - aa + log((aa+one)/(aa0+one))
113  hl12 = hl1 * two / z1
114  bb = sqrt(one + four * alpha * hl12)
115  ph2 = bb0 - bb + log((bb+one)/(bb0+one))
116  end if
117 
118  ! unstable case
119  ! check for unphysical obukhov length
120  if (dtv < zero) then
121  olinf = z1 / hlinf
122  if ( abs(olinf) <= z0max * 50.0_kind_real ) then
123  hlinf = -z1 / (50.0_kind_real * z0max)
124  end if
125  end if
126 
127  ! get pm and ph
128  if (dtv < zero .and. hlinf >= (-half)) then
129  hl1 = hlinf
130  pm = (a0 + a1*hl1) * hl1 / (one + b1*hl1 + b2*hl1*hl1)
131  ph = (a0p + a1p*hl1)*hl1/(one + b1p*hl1 + b2*hl1*hl1)
132  hl110 = hl1 * ten / z1
133  pm10 = (a0 + a1*hl110)*hl110/(one + b1*hl110 + b2*hl110*hl110)
134  hl12 = hl1 * two / z1
135  ph2 = (a0p + a1p*hl12)*hl12/(one + b1p*hl12 + b2p*hl12*hl12)
136  end if
137  if (dtv < zero .and. hlinf < (-half)) then
138  hl1 = -hlinf
139  pm = log(hl1) + two*hl1**(-quarter) - 0.8776_kind_real
140  ph = log(hl1) + half*hl1**(-half) + 1.386_kind_real
141  hl110 = hl1 * ten / z1
142  pm10 = log(hl110) + two*hl110**(-quarter) - 0.8776_kind_real
143  hl12 = hl1 * two / z1
144  ph2 = log(hl12) + half*hl12**(-half) + 1.386_kind_real
145  end if
146 
147  ! finish the exchange coefficient computation to provide fm and fh
148  fm = fm - pm
149  fh = fh - ph
150  fm10 = fm10 - pm10
151  f10m = max(zero, min(fm10/fm, one))
152 
153  return
154 
155 end subroutine sfc_wind_fact_gsi
156 
157 !--------------------------------------------------------------------------
158 
159 subroutine calc_psi_vars_gsi(rib, gzsoz0, gzzoz0, thv1, thv2,&
160  V2, th1, thg, phi1, obshgt, &
161  psim, psih, psimz, psihz)
162  ! calculate psi based off of near-surface atmospheric regime
163  use kinds
164  use ufo_constants_mod, only: grav, von_karman, zero, quarter, &
165  one, two, five, ten
166  implicit none
167  real(kind_real), intent(in) :: rib, gzsoz0, gzzoz0, thv1, thv2, &
168  V2, th1, thg, phi1, obshgt
169  real(kind_real), intent(out) :: psim, psih, psimz, psihz
170 
171  real(kind_real), parameter :: r0_2 = 0.2_kind_real
172  real(kind_real), parameter :: r1_1 = 1.1_kind_real
173  real(kind_real), parameter :: r0_9 = 0.9_kind_real
174  real(kind_real), parameter :: r16 = 16.0_kind_real
175  real(kind_real) :: cc, mol, ust, hol, holz, xx, yy
176 
177  ! stable conditions
178  if (rib >= r0_2) then
179  psim = -ten*gzsoz0
180  psimz = -ten*gzzoz0
181  psim = max(psim,-ten)
182  psimz = max(psimz,-ten)
183  psih = psim
184  psihz = psimz
185  ! mechanically driven turbulence
186  else if ((rib < r0_2) .and. (rib > zero)) then
187  psim = ( -five * rib) * gzsoz0 / (r1_1 - five*rib)
188  psimz = ( -five * rib) * gzzoz0 / (r1_1 - five*rib)
189  psim = max(psim,-ten)
190  psimz = max(psimz,-ten)
191  psih = psim
192  psihz = psimz
193  ! unstable forced convection
194  else if ((rib == zero) .or. (rib < zero .and. thv2>thv1)) then
195  psim = zero
196  psimz = zero
197  psih = psim
198  psihz = psimz
199  ! free convection
200  else
201  psim = zero
202  psih = zero
203  cc = two * atan(one)
204  ! friction speed
205  ust = von_karman * sqrt(v2) / (gzsoz0 - psim)
206  ! heat flux factor
207  mol = von_karman * (th1 - thg)/(gzsoz0 - psih)
208  ! ratio of PBL height to Monin-Obukhov length
209  if (ust < 0.01_kind_real) then
210  hol = rib * gzsoz0
211  else
212  hol = von_karman * grav * phi1 * mol / (th1 * ust * ust)
213  end if
214  hol = min(hol,zero)
215  hol = max(hol,-ten)
216  holz = (obshgt / phi1) * hol
217  holz = min(holz,zero)
218  holz = max(holz,-ten)
219 
220  xx = (one - r16 * hol) ** quarter
221  yy = log((one+xx*xx)/two)
222  psim = two * log((one+xx)/two) + yy - two * atan(xx) + cc
223  psih = two * yy
224 
225  xx = (one - r16 * holz) ** quarter
226  yy = log((one+xx*xx)/two)
227  psimz = two * log((one+xx)/two) + yy - two * atan(xx) + cc
228  psihz = two * yy
229 
230  psim = min(psim,r0_9*gzsoz0)
231  psimz = min(psimz, r0_9*gzzoz0)
232  psih = min(psih,r0_9*gzsoz0)
233  psihz = min(psihz,r0_9*gzzoz0)
234 
235  end if
236 
237 
238 end subroutine calc_psi_vars_gsi
239 
240 !--------------------------------------------------------------------------
241 
242 subroutine calc_conv_vel_gsi(u1, v1, thvg, thv1, V2)
243  ! compute convective velocity for use in computing psi vars
244  use kinds
245  implicit none
246  real(kind_real), intent(in) :: u1, v1, thvg, thv1
247  real(kind_real), intent(out) :: V2
248  real(kind_real) :: wspd2, Vc2
249 
250  wspd2 = u1*u1 + v1*v1
251  if (thvg >= thv1) then
252  vc2 = 4.0_kind_real * (thvg - thv1)
253  else
254  vc2 = 0.0_kind_real
255  end if
256 
257  v2 = 1e-6_kind_real + wspd2 + vc2
258 
259 end subroutine calc_conv_vel_gsi
260 
261 !--------------------------------------------------------------------------
262 
263 end module atmsfc_mod
subroutine calc_conv_vel_gsi(u1, v1, thvg, thv1, V2)
subroutine sfc_wind_fact_gsi(u, v, tsen, q, psfc, prsi1, prsi2, skint, z0, lsmask, f10m)
subroutine calc_psi_vars_gsi(rib, gzsoz0, gzzoz0, thv1, thv2, V2, th1, thg, phi1, obshgt, psim, psih, psimz, psihz)
real(kind_real), parameter, public ten
real(kind_real), parameter, public quarter
real(kind_real), parameter, public one
real(kind_real), parameter, public grav
real(kind_real), parameter, public von_karman
real(kind_real), parameter, public rd
real(kind_real), parameter, public four
real(kind_real), parameter, public zero
real(kind_real), parameter, public five
real(kind_real), parameter, public rv_over_rd
real(kind_real), parameter, public rd_over_cp
real(kind_real), parameter, public two
real(kind_real), parameter, public half