CCPP SciDoc v7.0.0  v7.0.0
Common Community Physics Package Developed at DTC
 
Loading...
Searching...
No Matches
sfc_diff.f
1
5
7 module sfc_diff
8
9 use machine , only : kind_phys
10
11 implicit none
12
13 public :: sfc_diff_run
14 public :: stability
15
16 private
17
18 real (kind=kind_phys), parameter :: ca=0.4_kind_phys ! ca - von karman constant
19
20 contains
21
57 subroutine sfc_diff_run (im,rvrdm1,eps,epsm1,grav, & !intent(in)
58 & ps,t1,q1,z1,garea,wind, & !intent(in)
59 & prsl1,prslki,prsik1,prslk1, & !intent(in)
60 & sigmaf,vegtype,shdmax,ivegsrc, & !intent(in)
61 & z0pert,ztpert, & ! mg, sfc-perts !intent(in)
62 & flag_iter,redrag, & !intent(in)
63 & flag_lakefreeze, & !intent(in)
64 & u10m,v10m,sfc_z0_type, & !hafs,z0 type !intent(in)
65 & u1,v1,usfco,vsfco,icplocn2atm, &
66 & wet,dry,icy, & !intent(in)
67 & thsfc_loc, & !intent(in)
68 & tskin_wat, tskin_lnd, tskin_ice, & !intent(in)
69 & tsurf_wat, tsurf_lnd, tsurf_ice, & !intent(in)
70 & z0rl_wat, z0rl_lnd, z0rl_ice, & !intent(inout)
71 & z0rl_wav, & !intent(inout)
72 & ustar_wat, ustar_lnd, ustar_ice, & !intent(inout)
73 & cm_wat, cm_lnd, cm_ice, & !intent(inout)
74 & ch_wat, ch_lnd, ch_ice, & !intent(inout)
75 & rb_wat, rb_lnd, rb_ice, & !intent(inout)
76 & stress_wat,stress_lnd,stress_ice, & !intent(inout)
77 & fm_wat, fm_lnd, fm_ice, & !intent(inout)
78 & fh_wat, fh_lnd, fh_ice, & !intent(inout)
79 & fm10_wat, fm10_lnd, fm10_ice, & !intent(inout)
80 & fh2_wat, fh2_lnd, fh2_ice, & !intent(inout)
81 & ztmax_wat, ztmax_lnd, ztmax_ice, & !intent(inout)
82 & zvfun, & !intent(out)
83 & errmsg, errflg) !intent(out)
84!
85 implicit none
86!
87 integer, parameter :: kp = kind_phys
88 integer, intent(in) :: im, ivegsrc
89 integer, intent(in) :: sfc_z0_type ! option for calculating surface roughness length over ocean
90 integer, intent(in) :: icplocn2atm ! option for including ocean current in the computation of flux
91
92 integer, dimension(:), intent(in) :: vegtype
93
94 logical, intent(in) :: redrag ! reduced drag coeff. flag for high wind over sea (j.han)
95 logical, dimension(:), intent(in) :: flag_iter, dry, icy
96 logical, dimension(:), intent(in) :: flag_lakefreeze
97 logical, dimension(:), intent(inout) :: wet
98
99 logical, intent(in) :: thsfc_loc ! Flag for reference pressure in theta calculation
100
101 real(kind=kind_phys), dimension(:), intent(in) :: u10m,v10m
102 real(kind=kind_phys), dimension(:), intent(in) :: u1,v1
103 real(kind=kind_phys), dimension(:), intent(in) :: usfco,vsfco
104 real(kind=kind_phys), intent(in) :: rvrdm1, eps, epsm1, grav
105 real(kind=kind_phys), dimension(:), intent(in) :: &
106 & ps,t1,q1,z1,garea,prsl1,prslki,prsik1,prslk1, &
107 & wind,sigmaf,shdmax, &
108 & z0pert,ztpert ! mg, sfc-perts
109 real(kind=kind_phys), dimension(:), intent(in) :: &
110 & tskin_wat, tskin_lnd, tskin_ice, &
111 & tsurf_wat, tsurf_lnd, tsurf_ice
112
113 real(kind=kind_phys), dimension(:), intent(in) :: z0rl_wav
114 real(kind=kind_phys), dimension(:), intent(inout) :: &
115 & z0rl_wat, z0rl_lnd, z0rl_ice, &
116 & ustar_wat, ustar_lnd, ustar_ice, &
117 & cm_wat, cm_lnd, cm_ice, &
118 & ch_wat, ch_lnd, ch_ice, &
119 & rb_wat, rb_lnd, rb_ice, &
120 & stress_wat,stress_lnd,stress_ice, &
121 & fm_wat, fm_lnd, fm_ice, &
122 & fh_wat, fh_lnd, fh_ice, &
123 & fm10_wat, fm10_lnd, fm10_ice, &
124 & fh2_wat, fh2_lnd, fh2_ice, &
125 & ztmax_wat, ztmax_lnd, ztmax_ice
126 real(kind=kind_phys), dimension(:), intent(out) :: zvfun
127!
128 character(len=*), intent(out) :: errmsg
129 integer, intent(out) :: errflg
130!
131! locals
132!
133 integer i
134 real(kind=kind_phys) :: windrel
135!
136 real(kind=kind_phys) :: rat, tv1, thv1, restar, wind10m,
137 & czilc, tem1, tem2, virtfac
138!
139
140 real(kind=kind_phys) :: tvs, z0, z0max, ztmax, gdx
141!
142 real(kind=kind_phys), parameter :: z0lo=0.1, z0up=1.0
143!
144 real(kind=kind_phys), parameter ::
145 & one=1.0_kp, zero=0.0_kp, half=0.5_kp, qmin=1.0e-8_kp
146 &, charnock=.018_kp, z0s_max=.317e-2_kp &! a limiting value at high winds over sea
147 &, zmin=1.0e-6_kp &
148 &, vis=1.4e-5_kp, rnu=1.51e-5_kp, visi=one/vis &
149 &, log01=log(0.01_kp), log05=log(0.05_kp), log07=log(0.07_kp)
150
151! parameter (charnock=.014,ca=.4)!c ca is the von karman constant
152! parameter (alpha=5.,a0=-3.975,a1=12.32,b1=-7.755,b2=6.041)
153! parameter (a0p=-7.941,a1p=24.75,b1p=-8.705,b2p=7.899,vis=1.4e-5)
154
155! real(kind=kind_phys) aa1,bb1,bb2,cc,cc1,cc2,arnu
156! parameter (aa1=-1.076,bb1=.7045,cc1=-.05808)
157! parameter (bb2=-.1954,cc2=.009999)
158! parameter (arnu=.135*rnu)
159!
160! z0s_max=.196e-2 for u10_crit=25 m/s
161! z0s_max=.317e-2 for u10_crit=30 m/s
162! z0s_max=.479e-2 for u10_crit=35 m/s
163!
164! mbek -- toga-coare flux algorithm
165! parameter (rnu=1.51e-5,arnu=0.11*rnu)
166
167! Initialize CCPP error handling variables
168 errmsg = ''
169 errflg = 0
170
171! initialize variables. all units are supposedly m.k.s. unless specified
172! ps is in pascals, wind is wind speed,
173! surface roughness length is converted to m from cm
174!
175! write(0,*)'in sfc_diff, sfc_z0_type=',sfc_z0_type
176
177 do i=1,im
178 if(flag_iter(i) .or. flag_lakefreeze(i)) then
179
180 ! Need to initialize ztmax arrays
181 ztmax_lnd(i) = 1. ! log(1) = 0
182 ztmax_ice(i) = 1. ! log(1) = 0
183 ztmax_wat(i) = 1. ! log(1) = 0
184
185 virtfac = one + rvrdm1 * max(q1(i),qmin)
186
187 tv1 = t1(i) * virtfac ! Virtual temperature in middle of lowest layer
188 if(thsfc_loc) then ! Use local potential temperature
189 thv1 = t1(i) * prslki(i) * virtfac
190 else ! Use potential temperature reference to 1000 hPa
191 thv1 = t1(i) / prslk1(i) * virtfac
192 endif
193
194 zvfun(i) = zero
195 gdx = sqrt(garea(i))
196
197! compute stability dependent exchange coefficients
198! this portion of the code is presently suppressed
199!
200 if (dry(i)) then ! Some land
201
202 if(thsfc_loc) then ! Use local potential temperature
203 tvs = half * (tsurf_lnd(i)+tskin_lnd(i)) * virtfac
204 else ! Use potential temperature referenced to 1000 hPa
205 tvs = half * (tsurf_lnd(i)+tskin_lnd(i))/prsik1(i)
206 & * virtfac
207 endif
208
209 z0max = max(zmin, min(0.01_kp * z0rl_lnd(i), z1(i)))
210!** xubin's new z0 over land
211 tem1 = one - shdmax(i)
212 tem2 = tem1 * tem1
213 tem1 = one - tem2
214
215 if( ivegsrc == 1 ) then
216
217 if (vegtype(i) == 10) then
218 z0max = exp( tem2*log01 + tem1*log07 )
219 elseif (vegtype(i) == 6) then
220 z0max = exp( tem2*log01 + tem1*log05 )
221 elseif (vegtype(i) == 7) then
222! z0max = exp( tem2*log01 + tem1*log01 )
223 z0max = 0.01_kp
224 elseif (vegtype(i) == 16) then
225! z0max = exp( tem2*log01 + tem1*log01 )
226 z0max = 0.01_kp
227 else
228 z0max = exp( tem2*log01 + tem1*log(z0max) )
229 endif
230
231 elseif (ivegsrc == 2 ) then
232
233 if (vegtype(i) == 7) then
234 z0max = exp( tem2*log01 + tem1*log07 )
235 elseif (vegtype(i) == 8) then
236 z0max = exp( tem2*log01 + tem1*log05 )
237 elseif (vegtype(i) == 9) then
238! z0max = exp( tem2*log01 + tem1*log01 )
239 z0max = 0.01_kp
240 elseif (vegtype(i) == 11) then
241! z0max = exp( tem2*log01 + tem1*log01 )
242 z0max = 0.01_kp
243 else
244 z0max = exp( tem2*log01 + tem1*log(z0max) )
245 endif
246
247 endif
248! mg, sfc-perts: add surface perturbations to z0max over land
249 if (z0pert(i) /= zero ) then
250 z0max = z0max * (10.0_kp**z0pert(i))
251 endif
252
253 z0max = max(z0max, zmin)
254
255!! czilc = 10.0 ** (- (0.40/0.07) * z0) ! fei's canopy height dependance of czil
256! czilc = 0.8_kp
257!
258! tem1 = 1.0_kp - sigmaf(i)
259! ztmax_lnd(i) = z0max*exp( - tem1*tem1
260! & * czilc*ca*sqrt(ustar_lnd(i)*(0.01/1.5e-05)))
261!
262 czilc = 10.0_kp ** (- 4.0_kp * z0max) ! Trier et al. (2011,WAF)
263 czilc = max(min(czilc, 0.8_kp), 0.08_kp)
264 tem1 = 1.0_kp - sigmaf(i)
265 czilc = czilc * tem1 * tem1
266 ztmax_lnd(i) = z0max * exp( - czilc * ca
267 & * 258.2_kp * sqrt(ustar_lnd(i)*z0max) )
268!
269! mg, sfc-perts: add surface perturbations to ztmax/z0max ratio over land
270 if (ztpert(i) /= zero) then
271 ztmax_lnd(i) = ztmax_lnd(i) * (10.0_kp**ztpert(i))
272 endif
273 ztmax_lnd(i) = max(ztmax_lnd(i), zmin)
274!
275! compute a function of surface roughness & green vegetation fraction (zvfun)
276!
277 tem1 = (z0max - z0lo) / (z0up - z0lo)
278 tem1 = min(max(tem1, zero), 1.0_kp)
279 tem2 = max(sigmaf(i), 0.1_kp)
280 zvfun(i) = sqrt(tem1 * tem2)
281!
282 call stability
283! --- inputs:
284 & (z1(i), zvfun(i), gdx, tv1, thv1, wind(i),
285 & z0max, ztmax_lnd(i), tvs, grav, thsfc_loc,
286! --- outputs:
287 & rb_lnd(i), fm_lnd(i), fh_lnd(i), fm10_lnd(i), fh2_lnd(i),
288 & cm_lnd(i), ch_lnd(i), stress_lnd(i), ustar_lnd(i))
289 endif ! Dry points
290
291 if (icy(i)) then ! Some ice
292
293 zvfun(i) = zero
294
295 if(thsfc_loc) then ! Use local potential temperature
296 tvs = half * (tsurf_ice(i)+tskin_ice(i)) * virtfac
297 else ! Use potential temperature referenced to 1000 hPa
298 tvs = half * (tsurf_ice(i)+tskin_ice(i))/prsik1(i)
299 & * virtfac
300 endif
301
302 z0max = max(zmin, min(0.01_kp * z0rl_ice(i), z1(i)))
303!** xubin's new z0 over land and sea ice
304 tem1 = one - shdmax(i)
305 tem2 = tem1 * tem1
306 tem1 = one - tem2
307
308! Removed the following lines by W. Zheng, for effective z0m (z0max) is applied only
309! for land.
310!wz if( ivegsrc == 1 ) then
311!wz
312!wz z0max = exp( tem2*log01 + tem1*log(z0max) )
313!wz elseif (ivegsrc == 2 ) then
314!wz z0max = exp( tem2*log01 + tem1*log(z0max) )
315!wz endif
316
317 z0max = max(z0max, zmin)
318
319!! czilc = 10.0 ** (- (0.40/0.07) * z0) ! fei's canopy height
320! dependance of czil
321! czilc = 0.8_kp
322!
323! tem1 = 1.0_kp - sigmaf(i)
324! ztmax_ice(i) = z0max*exp( - tem1*tem1
325! & * czilc*ca*sqrt(ustar_ice(i)*(0.01/1.5e-05)))
326!
327 czilc = 10.0_kp ** (- 4.0_kp * z0max)
328 czilc = max(min(czilc, 0.8_kp), 0.08_kp)
329 tem1 = 1.0_kp - sigmaf(i)
330 czilc = czilc * tem1 * tem1
331 ztmax_ice(i) = z0max * exp( - czilc * ca
332 & * 258.2_kp * sqrt(ustar_ice(i)*z0max) )
333!
334 ztmax_ice(i) = max(ztmax_ice(i), 1.0e-6)
335!
336 call stability
337! --- inputs:
338 & (z1(i), zvfun(i), gdx, tv1, thv1, wind(i),
339 & z0max, ztmax_ice(i), tvs, grav, thsfc_loc,
340! --- outputs:
341 & rb_ice(i), fm_ice(i), fh_ice(i), fm10_ice(i), fh2_ice(i),
342 & cm_ice(i), ch_ice(i), stress_ice(i), ustar_ice(i))
343 endif ! Icy points
344
345! BWG: Everything from here to end of subroutine was after
346! the stuff now put into "stability"
347
348 if (wet(i)) then ! Some open ocean
349
350 zvfun(i) = zero
351
352 if(thsfc_loc) then ! Use local potential temperature
353 tvs = half * (tsurf_wat(i)+tskin_wat(i)) * virtfac
354 else
355 tvs = half * (tsurf_wat(i)+tskin_wat(i))/prsik1(i)
356 & * virtfac
357 endif
358
359 if (icplocn2atm == 0) then
360 wind10m=sqrt(u10m(i)*u10m(i)+v10m(i)*v10m(i))
361 windrel=wind(i)
362 else if (icplocn2atm ==1) then
363 wind10m=sqrt((u10m(i)-usfco(i))**2+(v10m(i)-vsfco(i))**2)
364 windrel=sqrt((u1(i)-usfco(i))**2+(v1(i)-vsfco(i))**2)
365 endif
366
367 if (sfc_z0_type == -1) then ! using wave model derived momentum roughness
368 tem1 = 0.11 * vis / ustar_wat(i)
369 z0 = tem1 + 0.01_kp * z0rl_wav(i)
370
371 if (redrag) then
372 z0max = max(min(z0, z0s_max),1.0e-7_kp)
373 else
374 z0max = max(min(z0,0.1_kp), 1.0e-7_kp)
375 endif
376 z0rl_wat(i) = 100.0_kp * z0max ! cm
377 else
378 z0 = 0.01_kp * z0rl_wat(i)
379 z0max = max(zmin, min(z0,z1(i)))
380 endif
381!
382!** test xubin's new z0
383
384! ztmax = z0max
385
386 restar = max(ustar_wat(i)*z0max*visi, 0.000001_kp)
387
388! restar = log(restar)
389! restar = min(restar,5.)
390! restar = max(restar,-5.)
391! rat = aa1 + (bb1 + cc1*restar) * restar
392! rat = rat / (1. + (bb2 + cc2*restar) * restar))
393! rat taken from zeng, zhao and dickinson 1997
394
395 rat = min(7.0_kp, 2.67_kp * sqrt(sqrt(restar)) - 2.57_kp)
396 ztmax_wat(i) = max(z0max * exp(-rat), zmin)
397!
398 if (sfc_z0_type == 6) then
399 call znot_t_v6(wind10m, ztmax_wat(i)) ! 10-m wind,m/s, ztmax(m)
400 else if (sfc_z0_type == 7) then
401 call znot_t_v7(wind10m, ztmax_wat(i)) ! 10-m wind,m/s, ztmax(m)
402 else if (sfc_z0_type > 0) then
403 write(0,*)'no option for sfc_z0_type=',sfc_z0_type
404 errflg = 1
405 errmsg = 'ERROR(sfc_diff_run): no option for sfc_z0_type'
406 return
407 endif
408!
409 call stability
410! --- inputs:
411 & (z1(i), zvfun(i), gdx, tv1, thv1, windrel,
412 & z0max, ztmax_wat(i), tvs, grav, thsfc_loc,
413! --- outputs:
414 & rb_wat(i), fm_wat(i), fh_wat(i), fm10_wat(i), fh2_wat(i),
415 & cm_wat(i), ch_wat(i), stress_wat(i), ustar_wat(i))
416!
417! update z0 over ocean
418!
419 if (sfc_z0_type >= 0) then
420 if (sfc_z0_type == 0) then
421! z0 = (charnock / grav) * ustar_wat(i) * ustar_wat(i)
422 tem1 = 0.11 * vis / ustar_wat(i)
423 z0 = tem1 + (charnock/grav)*ustar_wat(i)*ustar_wat(i)
424
425
426! mbek -- toga-coare flux algorithm
427! z0 = (charnock / grav) * ustar(i)*ustar(i) + arnu/ustar(i)
428! new implementation of z0
429! cc = ustar(i) * z0 / rnu
430! pp = cc / (1. + cc)
431! ff = grav * arnu / (charnock * ustar(i) ** 3)
432! z0 = arnu / (ustar(i) * ff ** pp)
433
434 if (redrag) then
435 z0rl_wat(i) = 100.0_kp * max(min(z0, z0s_max), &
436 & 1.0e-7_kp)
437 else
438 z0rl_wat(i) = 100.0_kp * max(min(z0,0.1_kp), 1.e-7_kp)
439 endif
440
441 elseif (sfc_z0_type == 6) then ! wang
442 call znot_m_v6(wind10m, z0) ! wind, m/s, z0, m
443 z0rl_wat(i) = 100.0_kp * z0 ! cm
444 elseif (sfc_z0_type == 7) then ! wang
445 call znot_m_v7(wind10m, z0) ! wind, m/s, z0, m
446 z0rl_wat(i) = 100.0_kp * z0 ! cm
447 else
448 z0rl_wat(i) = 1.0e-4_kp
449 endif
450
451 elseif (z0rl_wav(i) <= 1.0e-7_kp .or.
452 & z0rl_wav(i) > 1.0_kp) then
453! z0 = (charnock / grav) * ustar_wat(i) * ustar_wat(i)
454 tem1 = 0.11 * vis / ustar_wat(i)
455 z0 = tem1 + (charnock/grav)*ustar_wat(i)*ustar_wat(i)
456
457 if (redrag) then
458 z0rl_wat(i) = 100.0_kp * max(min(z0, z0s_max),1.0e-7_kp)
459 else
460 z0rl_wat(i) = 100.0_kp * max(min(z0,0.1_kp), 1.0e-7_kp)
461 endif
462
463 endif
464
465 endif ! end of if(open ocean)
466!
467 endif ! end of if(flagiter) loop
468 enddo
469
470 return
471 end subroutine sfc_diff_run
472
473!----------------------------------------
475 subroutine stability &
476! --- inputs:
477 & ( z1, zvfun, gdx, tv1, thv1, wind, z0max, ztmax, tvs, grav, &
478 & thsfc_loc, &
479! --- outputs:
480 & rb, fm, fh, fm10, fh2, cm, ch, stress, ustar)
481!-----
482
483 integer, parameter :: kp = kind_phys
484! --- inputs:
485 real(kind=kind_phys), intent(in) :: &
486 & z1, zvfun, gdx, tv1, thv1, wind, z0max, ztmax, tvs, grav
487 logical, intent(in) :: thsfc_loc
488
489! --- outputs:
490 real(kind=kind_phys), intent(out) :: &
491 & rb, fm, fh, fm10, fh2, cm, ch, stress, ustar
492
493! --- locals:
494 real(kind=kind_phys), parameter :: alpha=5.0_kp, a0=-3.975_kp &
495 &, a1=12.32_kp, alpha4=4.0_kp*alpha &
496 &, b1=-7.755_kp, b2=6.041_kp &
497 &, xkrefsqr=0.3_kp, xkmin=0.05_kp &
498 &, xkgdx=3000.0_kp &
499 &, a0p=-7.941_kp, a1p=24.75_kp, b1p=-8.705_kp, b2p=7.899_kp&
500 &, zolmin=-10.0_kp, zero=0.0_kp, one=1.0_kp
501
502 real(kind=kind_phys) aa, aa0, bb, bb0, dtv, adtv,
503 & hl1, hl12, pm, ph, pm10, ph2,
504 & z1i,
505 & fms, fhs, hl0, hl0inf, hlinf,
506 & hl110, hlt, hltinf, olinf,
507 & tem1, tem2, zolmax
508
509 real(kind=kind_phys) xkzo
510
511 z1i = one / z1
512
513!
514! set background diffusivities with one for gdx >= xkgdx and
515! as a function of horizontal grid size for gdx < xkgdx
516! (i.e., gdx/xkgdx for gdx < xkgdx)
517!
518 if(gdx >= xkgdx) then
519 xkzo = one
520 else
521 xkzo = gdx / xkgdx
522 endif
523
524 tem1 = tv1 - tvs
525 if(tem1 > zero) then
526 tem2 = xkzo * zvfun
527 xkzo = min(max(tem2, xkmin), xkzo)
528 endif
529
530 zolmax = xkrefsqr / sqrt(xkzo)
531
532! compute stability indices (rb and hlinf)
533
534 dtv = thv1 - tvs
535 adtv = max(abs(dtv),0.001_kp)
536 dtv = sign(1.0_kp,dtv) * adtv
537
538 if(thsfc_loc) then ! Use local potential temperature
539 rb = max(-5000.0_kp, (grav+grav) * dtv * z1
540 & / ((thv1 + tvs) * wind * wind))
541 else ! Use potential temperature referenced to 1000 hPa
542 rb = max(-5000.0_kp, grav * dtv * z1
543 & / (tv1 * wind * wind))
544 endif
545
546 tem1 = one / z0max
547 tem2 = one / ztmax
548 fm = log((z0max+z1) * tem1)
549 fh = log((ztmax+z1) * tem2)
550 fm10 = log((z0max+10.0_kp) * tem1)
551 fh2 = log((ztmax+2.0_kp) * tem2)
552 hlinf = rb * fm * fm / fh
553 hlinf = min(max(hlinf,zolmin),zolmax)
554!
555! stable case
556!
557 if (dtv >= zero) then
558 hl1 = hlinf
559 if(hlinf > 0.25_kp) then
560 tem1 = hlinf * z1i
561 hl0inf = z0max * tem1
562 hltinf = ztmax * tem1
563 aa = sqrt(one + alpha4 * hlinf)
564 aa0 = sqrt(one + alpha4 * hl0inf)
565 bb = aa
566 bb0 = sqrt(one + alpha4 * hltinf)
567 pm = aa0 - aa + log( (aa + one)/(aa0 + one) )
568 ph = bb0 - bb + log( (bb + one)/(bb0 + one) )
569 fms = fm - pm
570 fhs = fh - ph
571 hl1 = fms * fms * rb / fhs
572 hl1 = min(hl1, zolmax)
573 endif
574!
575! second iteration
576!
577 tem1 = hl1 * z1i
578 hl0 = z0max * tem1
579 hlt = ztmax * tem1
580 aa = sqrt(one + alpha4 * hl1)
581 aa0 = sqrt(one + alpha4 * hl0)
582 bb = aa
583 bb0 = sqrt(one + alpha4 * hlt)
584 pm = aa0 - aa + log( (one+aa)/(one+aa0) )
585 ph = bb0 - bb + log( (one+bb)/(one+bb0) )
586 hl110 = hl1 * 10.0_kp * z1i
587 aa = sqrt(one + alpha4 * hl110)
588 pm10 = aa0 - aa + log( (one+aa)/(one+aa0) )
589 hl12 = (hl1+hl1) * z1i
590! aa = sqrt(one + alpha4 * hl12)
591 bb = sqrt(one + alpha4 * hl12)
592 ph2 = bb0 - bb + log( (one+bb)/(one+bb0) )
593!
594! unstable case - check for unphysical obukhov length
595!
596 else ! dtv < 0 case
597 olinf = z1 / hlinf
598 tem1 = 50.0_kp * z0max
599 if(abs(olinf) <= tem1) then
600 hlinf = -z1 / tem1
601 hlinf = max(hlinf, zolmin)
602 endif
603!
604! get pm and ph
605!
606 if (hlinf >= -0.5_kp) then
607 hl1 = hlinf
608 pm = (a0 + a1*hl1) * hl1 / (one+ (b1+b2*hl1) *hl1)
609 ph = (a0p + a1p*hl1) * hl1 / (one+ (b1p+b2p*hl1)*hl1)
610 hl110 = hl1 * 10.0_kp * z1i
611 pm10 = (a0 + a1*hl110) * hl110/(one+(b1+b2*hl110)*hl110)
612 hl12 = (hl1+hl1) * z1i
613 ph2 = (a0p + a1p*hl12) * hl12/(one+(b1p+b2p*hl12)*hl12)
614 else ! hlinf < 0.05
615 hl1 = -hlinf
616 tem1 = one / sqrt(hl1)
617 pm = log(hl1) + 2.0_kp * sqrt(tem1) - .8776_kp
618 ph = log(hl1) + 0.5_kp * tem1 + 1.386_kp
619! pm = log(hl1) + 2.0 * hl1 ** (-.25) - .8776
620! ph = log(hl1) + 0.5 * hl1 ** (-.5) + 1.386
621 hl110 = hl1 * 10.0_kp * z1i
622 pm10 = log(hl110) + 2.0_kp/sqrt(sqrt(hl110)) - 0.8776_kp
623! pm10 = log(hl110) + 2. * hl110 ** (-.25) - .8776
624 hl12 = (hl1+hl1) * z1i
625 ph2 = log(hl12) + 0.5_kp / sqrt(hl12) + 1.386_kp
626! ph2 = log(hl12) + .5 * hl12 ** (-.5) + 1.386
627 endif
628
629 endif ! end of if (dtv >= 0 ) then loop
630!
631! finish the exchange coefficient computation to provide fm and fh
632!
633 fm = fm - pm
634 fh = fh - ph
635 fm10 = fm10 - pm10
636 fh2 = fh2 - ph2
637 cm = ca * ca / (fm * fm)
638 ch = ca * ca / (fm * fh)
639 tem1 = 0.00001_kp/z1
640 cm = max(cm, tem1)
641 ch = max(ch, tem1)
642 stress = cm * wind * wind
643 ustar = sqrt(stress)
644
645 return
646!.................................
647 end subroutine stability
648!---------------------------------
649
650
653 SUBROUTINE znot_m_v6(uref, znotm)
654 use machine , only : kind_phys
655 IMPLICIT NONE
656! Calculate areodynamical roughness over water with input 10-m wind
657! For low-to-moderate winds, try to match the Cd-U10 relationship from COARE V3.5 (Edson et al. 2013)
658! For high winds, try to fit available observational data
659!
660! Bin Liu, NOAA/NCEP/EMC 2017
661!
662! uref(m/s) : wind speed at 10-m height
663! znotm(meter): areodynamical roughness scale over water
664!
665
666 REAL(kind=kind_phys), INTENT(IN) :: uref
667 REAL(kind=kind_phys), INTENT(OUT):: znotm
668 real(kind=kind_phys), parameter :: p13 = -1.296521881682694e-02,
669 & p12 = 2.855780863283819e-01, p11 = -1.597898515251717e+00,
670 & p10 = -8.396975715683501e+00,
671
672 & p25 = 3.790846746036765e-10, p24 = 3.281964357650687e-09,
673 & p23 = 1.962282433562894e-07, p22 = -1.240239171056262e-06,
674 & p21 = 1.739759082358234e-07, p20 = 2.147264020369413e-05,
675
676 & p35 = 1.840430200185075e-07, p34 = -2.793849676757154e-05,
677 & p33 = 1.735308193700643e-03, p32 = -6.139315534216305e-02,
678 & p31 = 1.255457892775006e+00, p30 = -1.663993561652530e+01,
679
680 & p40 = 4.579369142033410e-04
681
682
683 if (uref >= 0.0 .and. uref <= 6.5 ) then
684 znotm = exp(p10 + uref * (p11 + uref * (p12 + uref*p13)))
685 elseif (uref > 6.5 .and. uref <= 15.7) then
686 znotm = p20 + uref * (p21 + uref * (p22 + uref * (p23
687 & + uref * (p24 + uref * p25))))
688 elseif (uref > 15.7 .and. uref <= 53.0) then
689 znotm = exp( p30 + uref * (p31 + uref * (p32 + uref * (p33
690 & + uref * (p34 + uref * p35)))))
691 elseif ( uref > 53.0) then
692 znotm = p40
693 else
694 print*, 'Wrong input uref value:',uref
695 endif
696
697 END SUBROUTINE znot_m_v6
698
704!
705!! uref(m/s) : wind speed at 10-m height
706!! znott(meter): scalar roughness scale over water
707 SUBROUTINE znot_t_v6(uref, znott)
708 use machine , only : kind_phys
709 IMPLICIT NONE
710
711
712
713 REAL(kind=kind_phys), INTENT(IN) :: uref
714 REAL(kind=kind_phys), INTENT(OUT):: znott
715 real(kind=kind_phys), parameter :: p00 = 1.100000000000000e-04,
716 & p15 = -9.144581627678278e-10, p14 = 7.020346616456421e-08,
717 & p13 = -2.155602086883837e-06, p12 = 3.333848806567684e-05,
718 & p11 = -2.628501274963990e-04, p10 = 8.634221567969181e-04,
719
720 & p25 = -8.654513012535990e-12, p24 = 1.232380050058077e-09,
721 & p23 = -6.837922749505057e-08, p22 = 1.871407733439947e-06,
722 & p21 = -2.552246987137160e-05, p20 = 1.428968311457630e-04,
723
724 & p35 = 3.207515102100162e-12, p34 = -2.945761895342535e-10,
725 & p33 = 8.788972147364181e-09, p32 = -3.814457439412957e-08,
726 & p31 = -2.448983648874671e-06, p30 = 3.436721779020359e-05,
727
728 & p45 = -3.530687797132211e-11, p44 = 3.939867958963747e-09,
729 & p43 = -1.227668406985956e-08, p42 = -1.367469811838390e-05,
730 & p41 = 5.988240863928883e-04, p40 = -7.746288511324971e-03,
731
732 & p56 = -1.187982453329086e-13, p55 = 4.801984186231693e-11,
733 & p54 = -8.049200462388188e-09, p53 = 7.169872601310186e-07,
734 & p52 = -3.581694433758150e-05, p51 = 9.503919224192534e-04,
735 & p50 = -1.036679430885215e-02,
736
737 & p60 = 4.751256171799112e-05
738
739 if (uref >= 0.0 .and. uref < 5.9 ) then
740 znott = p00
741 elseif (uref >= 5.9 .and. uref <= 15.4) then
742 znott = p10 + uref * (p11 + uref * (p12 + uref * (p13
743 & + uref * (p14 + uref * p15))))
744 elseif (uref > 15.4 .and. uref <= 21.6) then
745 znott = p20 + uref * (p21 + uref * (p22 + uref * (p23
746 & + uref * (p24 + uref * p25))))
747 elseif (uref > 21.6 .and. uref <= 42.2) then
748 znott = p30 + uref * (p31 + uref * (p32 + uref * (p33
749 & + uref * (p34 + uref * p35))))
750 elseif ( uref > 42.2 .and. uref <= 53.3) then
751 znott = p40 + uref * (p41 + uref * (p42 + uref * (p43
752 & + uref * (p44 + uref * p45))))
753 elseif ( uref > 53.3 .and. uref <= 80.0) then
754 znott = p50 + uref * (p51 + uref * (p52 + uref * (p53
755 & + uref * (p54 + uref * (p55 + uref * p56)))))
756 elseif ( uref > 80.0) then
757 znott = p60
758 else
759 print*, 'Wrong input uref value:',uref
760 endif
761
762 END SUBROUTINE znot_t_v6
763
764
769!
770!! Bin Liu, NOAA/NCEP/EMC 2018
771!
772!! uref(m/s) : wind speed at 10-m height
773!! znotm(meter): areodynamical roughness scale over water
774 SUBROUTINE znot_m_v7(uref, znotm)
775 use machine , only : kind_phys
776 IMPLICIT NONE
777
778
779
780 REAL(kind=kind_phys), INTENT(IN) :: uref
781 REAL(kind=kind_phys), INTENT(OUT):: znotm
782
783 real(kind=kind_phys), parameter :: p13 = -1.296521881682694e-02,
784 & p12 = 2.855780863283819e-01, p11 = -1.597898515251717e+00,
785 & p10 = -8.396975715683501e+00,
786
787 & p25 = 3.790846746036765e-10, p24 = 3.281964357650687e-09,
788 & p23 = 1.962282433562894e-07, p22 = -1.240239171056262e-06,
789 & p21 = 1.739759082358234e-07, p20 = 2.147264020369413e-05,
790
791 & p35 = 1.897534489606422e-07, p34 = -3.019495980684978e-05,
792 & p33 = 1.931392924987349e-03, p32 = -6.797293095862357e-02,
793 & p31 = 1.346757797103756e+00, p30 = -1.707846930193362e+01,
794
795 & p40 = 3.371427455376717e-04
796
797 if (uref >= 0.0 .and. uref <= 6.5 ) then
798 znotm = exp( p10 + uref * (p11 + uref * (p12 + uref * p13)))
799 elseif (uref > 6.5 .and. uref <= 15.7) then
800 znotm = p20 + uref * (p21 + uref * (p22 + uref * (p23
801 & + uref * (p24 + uref * p25))))
802 elseif (uref > 15.7 .and. uref <= 53.0) then
803 znotm = exp( p30 + uref * (p31 + uref * (p32 + uref * (p33
804 & + uref * (p34 + uref * p35)))))
805 elseif ( uref > 53.0) then
806 znotm = p40
807 else
808 print*, 'Wrong input uref value:',uref
809 endif
810
811 END SUBROUTINE znot_m_v7
812
822 SUBROUTINE znot_t_v7(uref, znott)
823 use machine , only : kind_phys
824 IMPLICIT NONE
825
826!
827
828 REAL(kind=kind_phys), INTENT(IN) :: uref
829 REAL(kind=kind_phys), INTENT(OUT):: znott
830
831 real(kind=kind_phys), parameter :: p00 = 1.100000000000000e-04,
832
833 & p15 = -9.193764479895316e-10, p14 = 7.052217518653943e-08,
834 & p13 = -2.163419217747114e-06, p12 = 3.342963077911962e-05,
835 & p11 = -2.633566691328004e-04, p10 = 8.644979973037803e-04,
836
837 & p25 = -9.402722450219142e-12, p24 = 1.325396583616614e-09,
838 & p23 = -7.299148051141852e-08, p22 = 1.982901461144764e-06,
839 & p21 = -2.680293455916390e-05, p20 = 1.484341646128200e-04,
840
841 & p35 = 7.921446674311864e-12, p34 = -1.019028029546602e-09,
842 & p33 = 5.251986927351103e-08, p32 = -1.337841892062716e-06,
843 & p31 = 1.659454106237737e-05, p30 = -7.558911792344770e-05,
844
845 & p45 = -2.694370426850801e-10, p44 = 5.817362913967911e-08,
846 & p43 = -5.000813324746342e-06, p42 = 2.143803523428029e-04,
847 & p41 = -4.588070983722060e-03, p40 = 3.924356617245624e-02,
848
849 & p56 = -1.663918773476178e-13, p55 = 6.724854483077447e-11,
850 & p54 = -1.127030176632823e-08, p53 = 1.003683177025925e-06,
851 & p52 = -5.012618091180904e-05, p51 = 1.329762020689302e-03,
852 & p50 = -1.450062148367566e-02, p60 = 6.840803042788488e-05
853
854 if (uref >= 0.0 .and. uref < 5.9 ) then
855 znott = p00
856 elseif (uref >= 5.9 .and. uref <= 15.4) then
857 znott = p10 + uref * (p11 + uref * (p12 + uref * (p13
858 & + uref * (p14 + uref * p15))))
859 elseif (uref > 15.4 .and. uref <= 21.6) then
860 znott = p20 + uref * (p21 + uref * (p22 + uref * (p23
861 & + uref * (p24 + uref * p25))))
862 elseif (uref > 21.6 .and. uref <= 42.6) then
863 znott = p30 + uref * (p31 + uref * (p32 + uref * (p33
864 & + uref * (p34 + uref * p35))))
865 elseif ( uref > 42.6 .and. uref <= 53.0) then
866 znott = p40 + uref * (p41 + uref * (p42 + uref * (p43
867 & + uref * (p44 + uref * p45))))
868 elseif ( uref > 53.0 .and. uref <= 80.0) then
869 znott = p50 + uref * (p51 + uref * (p52 + uref * (p53
870 & + uref * (p54 + uref * (p55 + uref * p56)))))
871 elseif ( uref > 80.0) then
872 znott = p60
873 else
874 print*, 'Wrong input uref value:',uref
875 endif
876
877 END SUBROUTINE znot_t_v7
879 end module sfc_diff
subroutine znot_m_v7(uref, znotm)
Calculate areodynamical roughness over water with input 10-m wind For low-to-moderate winds,...
Definition sfc_diff.f:775
subroutine znot_t_v7(uref, znott)
Calculate scalar roughness over water with input 10-m wind For low-to-moderate winds,...
Definition sfc_diff.f:823
subroutine, public sfc_diff_run(im, rvrdm1, eps, epsm1, grav, ps, t1, q1, z1, garea, wind, prsl1, prslki, prsik1, prslk1, sigmaf, vegtype, shdmax, ivegsrc, z0pert, ztpert, flag_iter, redrag, flag_lakefreeze, u10m, v10m, sfc_z0_type, u1, v1, usfco, vsfco, icplocn2atm, wet, dry, icy, thsfc_loc, tskin_wat, tskin_lnd, tskin_ice, tsurf_wat, tsurf_lnd, tsurf_ice, z0rl_wat, z0rl_lnd, z0rl_ice, z0rl_wav, ustar_wat, ustar_lnd, ustar_ice, cm_wat, cm_lnd, cm_ice, ch_wat, ch_lnd, ch_ice, rb_wat, rb_lnd, rb_ice, stress_wat, stress_lnd, stress_ice, fm_wat, fm_lnd, fm_ice, fh_wat, fh_lnd, fh_ice, fm10_wat, fm10_lnd, fm10_ice, fh2_wat, fh2_lnd, fh2_ice, ztmax_wat, ztmax_lnd, ztmax_ice, zvfun, errmsg, errflg)
Definition sfc_diff.f:84
subroutine znot_m_v6(uref, znotm)
add fitted z0,zt curves for hurricane application (used in HWRF/HMON) Weiguo Wang,...
Definition sfc_diff.f:654
subroutine znot_t_v6(uref, znott)
Calculate scalar roughness over water with input 10-m wind For low-to-moderate winds,...
Definition sfc_diff.f:708
subroutine, public stability(z1, zvfun, gdx, tv1, thv1, wind, z0max, ztmax, tvs, grav, thsfc_loc, rb, fm, fh, fm10, fh2, cm, ch, stress, ustar)
Definition sfc_diff.f:481
This module contains the CCPP-compliant GFS surface layer scheme.
Definition sfc_diff.f:7