16 public derive_fields, mixing_ratio
20 type :: precipitations_t
25 integer :: CONVECTION = 4
26 end type precipitations_t
28 type(precipitations_t),
parameter :: precips = precipitations_t()
64 subroutine derive_fields(imp_physics,t, rh, pres, hgt, totalWater, totalCond,&
65 nz, topoK, hprcp, hcprcp, cin, cape, &
66 ept, wbt, twp, pc, kx, lx, tott, prcpType)
70 integer,
intent(in) :: imp_physics
71 integer,
intent(in) :: nz, topok
72 real,
intent(in),
dimension(nz) :: t, rh, pres, hgt
73 real,
intent(in),
dimension(nz) :: totalwater,totalcond
74 real,
intent(in) :: hprcp, hcprcp, cin, cape
75 real,
intent(out) :: ept(nz), wbt(nz), twp(nz)
76 real,
intent(out) :: pc, kx, lx, tott
77 integer,
intent(out) :: prcptype
79 real,
allocatable :: td(:), tlc(:), wvm(:)
86 td(:) = getdewpointtemp(t(:), rh(:))
87 tlc(:) = get_tlcl(t(:), td(:))
88 wvm(:) = mixing_ratio(td(:), pres(:))
90 ept(:) = getthetae(pres(:), t(:), wvm(:), tlc(:))
91 wbt(:) = getthetaw(t(:), td(:), pres(:))
93 call calc_totalwaterpath(hgt, pres, t, totalwater, nz, twp)
96 pc = getprecipcond(totalcond, nz, topok)
99 call calc_indice(t, td, pres, wvm, nz, topok, kx, lx, tott)
101 prcptype=getpreciptype(imp_physics,pres,hgt,t,rh,wbt,nz,&
102 hprcp,hcprcp,pc,cin,cape,lx)
109 end subroutine derive_fields
114 elemental real function getdewpointtemp(t, rh)
116 real,
intent(in) :: t, rh
123 vapr = (max(1.0e-6,rh) / 100.0) * getvaporpres(t)
126 getdewpointtemp = 243.5 * rm / (17.67 - rm) + 273.15
129 end function getdewpointtemp
136 elemental real function getthetae(pres, t, wvm, tAtLCL)
138 real,
intent(in) :: pres, t, wvm, tatlcl
144 e = (2.0/7.0) * ( 1.0 - 0.28 * rmix * 0.001)
145 thtam = t * ((100000.0/pres)**e)
146 getthetae = thtam * exp( (3.376/tatlcl - 0.00254) * &
147 (rmix * (1. + (.81 * rmix * 0.001)) ))
150 end function getthetae
155 elemental real function getvaporpres(t)
157 real,
intent(in) :: t
163 getvaporpres = 611.2 * exp( 17.67*tc/(tc+243.5))
166 end function getvaporpres
171 elemental real function get_tlcl(t, td)
173 real,
intent(in) :: t, td
175 get_tlcl = 1. / (1./(td - 56.) + log(t/td)/800.0) + 56.0
178 end function get_tlcl
187 elemental real function mixing_ratio(td, pres)
189 real,
intent(in) :: td, pres
193 corr = 1.001 + ( (pres/100.0 - 100) /900.) * 0.0034
194 e = getvaporpres(td) * corr
195 mixing_ratio = 0.62197 * (e/(pres-e)) * 1000.0
198 end function mixing_ratio
204 elemental real function getthetaw(t, td, pres)
206 real,
intent(in) :: t, td, pres
208 real :: vl, cp, dt, top, bottom, twet, twetnew
221 twet = (top + bottom) / 2.0
222 rmixr = mixing_ratio(td, pres) / 1000.0
223 smixr = mixing_ratio(twet, pres) / 1000.0
225 twetnew = t - (vl/cp) * (smixr-rmixr)
226 if(twetnew < twet)
then
232 dt = abs(twet - twetnew)
241 end function getthetaw
245 real function getprecipcond(totalcond, nz, topok)
247 real,
intent(in) :: totalcond(nz)
248 integer,
intent(in) :: nz, topok
254 do k = topok, topok-2, -1
255 getprecipcond = totalcond(k) + getprecipcond
259 end function getprecipcond
265 subroutine calc_indice(t, td, pres, wvm, nz, topoK, &
266 kIndex, liftedIndex, totalTotals)
268 integer,
intent(in) :: nz, topok
269 real,
intent(in) :: t(nz), td(nz), pres(nz), wvm(nz)
270 real,
intent(out) :: kindex, liftedindex, totaltotals
273 real :: t500hpa, t700hpa, t850hpa, dpt700hpa, dpt850hpa
275 real :: surfacetemp,surfacedewpttemp,surfacepressure,surfacemixr
276 real :: tempatlcl, theta, pressatlcl, thetaeatlcl, tempfromthetae, tem
290 if ((pres(k)- 50000.0 >= 0.) .and. (pres(k-1)- 50000.0 < 0.) )
then
291 if (abs(pres(k)- 50000.0) <= 0.1)
then
293 elseif (abs(pres(k-1)- 50000.0) <= 0.1)
then
296 t500hpa = t(k) - ((pres(k)-50000.0)/(pres(k)-pres(k-1))) * (t(k)-t(k-1))
301 if ((pres(k)- 70000.0 >= 0.) .and. (pres(k-1)- 70000.0 < 0.) )
then
302 if (abs(pres(k)- 70000.0) <= 0.1)
then
305 elseif (abs(pres(k-1)- 70000.0) <= 0.1)
then
309 tem = (pres(k)-70000.0)/(pres(k)-pres(k-1))
310 t700hpa = t(k) - tem * (t(k)-t(k-1))
311 dpt700hpa = td(k) - tem * (td(k)-td(k-1))
316 if ((pres(k)- 85000.0 >= 0.) .and. (pres(k-1)- 85000.0 < 0.) )
then
317 if (abs(pres(k)- 85000.0) <= 0.1)
then
320 elseif (abs(pres(k-1)- 85000.0) <= 0.1)
then
324 tem = (pres(k)-85000.0)/(pres(k)-pres(k-1))
325 t850hpa = t(k) - tem * (t(k)-t(k-1))
326 dpt850hpa = td(k) - tem * (td(k)-td(k-1))
333 kindex = (t850hpa-t500hpa) + (dpt850hpa-273.15) - (t700hpa-dpt700hpa)
336 totaltotals = t850hpa + dpt850hpa - t500hpa * 2.0
340 surfacetemp = t(topok)
341 surfacedewpttemp = td(topok)
342 surfacepressure = pres(topok)
343 surfacemixr = wvm(topok)
345 tempatlcl = get_tlcl(surfacetemp, surfacedewpttemp)
346 theta = surfacetemp * (100000.0/surfacepressure)**0.286
347 pressatlcl = 100000.0 * (tempatlcl / theta)**3.4965
348 thetaeatlcl = getthetae(pressatlcl,tempatlcl,surfacemixr,tempatlcl)
350 tempfromthetae = gettemperature(thetaeatlcl, 50000.0)
352 liftedindex = t500hpa - tempfromthetae
355 end subroutine calc_indice
358 real function gettemperature(thetae, pres)
360 real,
intent(in) :: thetae, pres
362 real :: guess, w1, w2, thetae1, thetae2, cor
365 guess = (thetae - 0.5 * (max(thetae - 270.0, 0.0))**1.05) * &
369 w1 = calcrsubs(pres, guess)
370 w2 = calcrsubs(pres, guess + 1.0)
371 thetae1 = getthetae(pres, guess, w1, guess)
372 thetae2 = getthetae(pres, guess + 1.0, w2, guess + 1.0)
373 cor = (thetae - thetae1)/(thetae2 - thetae1)
376 if (abs(cor) < 0.01)
then
381 gettemperature = guess
384 end function gettemperature
387 elemental real function calcrsubs(pres, temp)
389 real,
intent(in) :: pres, temp
393 esubs = calcesubs(temp)
394 calcrsubs = (0.622*esubs)/(pres - esubs)
397 end function calcrsubs
400 elemental real function calcesubs(temp)
402 real,
intent(in) :: temp
405 real,
parameter :: coeffs(9) = &
406 (/ 610.5851, 44.40316, 1.430341, 0.02641412, 2.995057e-4,&
407 2.031998e-6, 6.936113e-9, 2.564861e-12, -3.704404e-14 /)
410 x= max(-80.0, temp - 273.15)
412 calcesubs = coeffs(1) + x*(coeffs(2) + x*(coeffs(3) + x*(coeffs(4) + &
413 x*(coeffs(5) + x*(coeffs(6) + x*(coeffs(7) + &
414 x*(coeffs(8) + x*coeffs(9))))))))
416 end function calcesubs
419 subroutine calc_totalwaterpath(hgt, pres, t, totalWater, nz, twp)
421 integer,
intent(in) :: nz
422 real,
intent(in) :: hgt(nz), pres(nz), t(nz), totalwater(nz)
423 real,
intent(out):: twp(nz)
425 real :: condensateintegrated
426 integer :: topidx, baseidx
436 lp200:
do m = k, 2, -1
437 if (totalwater(m) > 0.001)
then
445 if (totalwater(m) > 0.001)
then
453 if(topidx == -1 .or. baseidx == -1) cycle
454 condensateintegrated = 0.0
455 lp400:
do m = topidx, baseidx
456 if (t(m) <= 273.15)
then
457 condensateintegrated = condensateintegrated + &
458 ( ((totalwater(m)*pres(m)) / (287.05 * t(m)) ) * &
459 (hgt(m-1) - hgt(m) + 0.001))
463 twp(k) = condensateintegrated
468 end subroutine calc_totalwaterpath
471 integer function getpreciptype(imp_physics,pres, hgt, t, rh, wbt, nz, &
472 hprcp, hcprcp, pc, cin, cape, lx)
474 integer,
intent(in) :: imp_physics
475 integer,
intent(in) :: nz
476 real,
intent(in) :: pres(nz), hgt(nz), t(nz), rh(nz), wbt(nz)
477 real,
intent(in) :: hprcp,hcprcp, pc, cin, cape, lx
479 integer,
allocatable :: wxtype(:)
481 integer :: idxmelt, idxrefz, iceidx
482 real :: coldtemp, tcoldarea, wetbuldarea
484 real :: precip, precip_standard
493 if(imp_physics == 98 .or. imp_physics == 99)
then
495 precip_standard =0.045
496 else if(imp_physics == 11 .or. imp_physics == 8)
then
498 precip_standard = 0.01
502 if_conv:
if ( hcprcp >= 1.0 .and. cape >= 1000.0 .and. cin > -100. &
504 getpreciptype = precips% CONVECTION
509 if( wbt(k) > 273.15)
then
513 if (t(m) < 273.15)
then
524 lp200:
do k = nz, 1, -1
528 if_pres_wbt:
if ( pres(k) >= 15000. .or. &
529 (wbt(k) >= 200. .and. wbt(k) <= 1000.))
then
537 if( (pres(m)>=30000. .or. (hgt(m)>hgt(nz)+700.))&
538 .and. (rh(m) > 90.) .and. (t(m) < coldtemp))
then
545 if_iceidx:
if (iceidx /= k)
then
551 if (wbt(m) >= 273.15)
then
552 tcoldarea = tcoldarea + (wbt(m)-273.15) * &
561 if ( (hgt(m) <= hgt(nz)+1500) .and. &
563 wetbuldarea = wetbuldarea + (wbt(m)-273.15) * &
569 if (coldtemp > 265.15)
then
570 wxtype(k) = precips% OTHER
571 else if (tcoldarea < 350.)
then
572 if(t(k) <= 273.15)
then
573 wxtype(k) = precips% SNOW
575 wxtype(k) = precips% RAIN
577 else if (wetbuldarea <= -250.)
then
578 wxtype(k) = precips% OTHER
579 else if(t(k) <= 273.15)
then
580 wxtype(k) = precips% OTHER
582 wxtype(k) = precips% RAIN
586 wxtype(k) = precips% NONE
592 getpreciptype = precips% NONE
595 if(precip >= precip_standard)
then
597 if (wxtype(k) > getpreciptype)
then
598 getpreciptype = wxtype(k)
607 end function getpreciptype
609end module derivedfields
618 use derivedfields,
only : mixing_ratio
623 public calc_cloudlayers
626 integer,
parameter :: maxlayers = 30
633 real,
allocatable :: layerq(:)
635 integer :: topidx(maxlayers)
636 integer :: baseidx(maxlayers)
637 real :: ctt(maxlayers)
644 subroutine calc_cloudlayers(rh,t,pres,ept,vv, nz, topoK, xlat, xlon,&
647 integer,
intent(in) :: nz, topok
648 real,
intent(in) :: rh(nz),t(nz),pres(nz), ept(nz), vv(nz)
649 real,
intent(in) :: xlat,xlon
650 integer,
intent(out) :: region
651 type(
clouds_t),
intent(inout) :: clouds
654 integer :: in_cld,cur_base, num_lyr
656 integer :: k, kk, n, kstart
659 if (abs(xlat)<23.5)
then
662 elseif ( (abs(xlat)>=23.5).and.(abs(xlat)<66))
then
678 if((rh(1) >= t_rh) .and. (rh(2) >= t_rh))
then
679 num_lyr = num_lyr + 1
682 clouds%topIdx(num_lyr) = 1
683 clouds%ctt(num_lyr) = t(1)
687 if ((rh(kk-1)>=t_rh).and.(rh(kk)<t_rh))
then
688 if ((rh(kk+1)<t_rh).and.(in_cld==1))
then
689 clouds%baseIdx(num_lyr) = kk
696 kstart = cur_base + 1
698 do k = kstart, topok-1
699 if (cur_base<=k)
then
700 if ((rh(k-1)<t_rh).and.(in_cld==0))
then
701 if ((rh(k)>=t_rh).and.(rh(k+1)>=t_rh))
then
702 num_lyr = num_lyr + 1
705 clouds%topIdx(num_lyr) = k
706 clouds%ctt(num_lyr) = t(k)
709 do kk=clouds%topIdx(num_lyr),topok-1
710 if ((rh(kk-1)>=t_rh).and.(rh(kk)<t_rh))
then
711 if ((rh(kk+1)<t_rh).and.(in_cld==1))
then
712 clouds%baseIdx(num_lyr) = kk
726 clouds%baseIdx(num_lyr) = topok
729 clouds%nLayers = num_lyr
731 clouds%wmnIdx = getwarmnoseidx(t, nz)
736 clouds%avv = getaveragevertvel(t, vv, nz, &
737 clouds%topIdx(num_lyr), clouds%baseIdx(num_lyr))
743 call calc_layerq(t, rh, pres, ept, nz, clouds)
746 end subroutine calc_cloudlayers
761 integer function getwarmnoseidx(t, nz)
763 integer,
intent(in) :: nz
764 real,
intent(in) :: t(nz)
766 logical :: abovefreezing
771 abovefreezing = .false.
779 if(t(k) <= 273.15)
then
780 if (abovefreezing)
then
781 getwarmnoseidx = tmpindex
786 abovefreezing = .false.
788 if(.not. abovefreezing) tmpindex = k
789 abovefreezing = .true.
795 end function getwarmnoseidx
802 real function getaveragevertvel(t,vv,nz, topidx_lowest,baseidx_lowest)
804 integer,
intent(in) :: nz
805 real,
intent(in) :: t(nz), vv(nz)
806 integer,
intent(in) :: topidx_lowest,baseidx_lowest
808 integer :: numvertvel, k, start_base
816 if(baseidx_lowest == nz)
then
819 start_base = baseidx_lowest
822 do k = start_base, topidx_lowest, -1
823 if ( t(k) <= 260.15 .and. t(k) >= 257.15)
then
824 sumvertvel = sumvertvel + vv(k)
825 numvertvel = numvertvel + 1
826 else if (t(k) < 257.15)
then
827 sumvertvel = sumvertvel + vv(k) + vv(k+1)
833 if (numvertvel == 0)
then
834 getaveragevertvel = 0.0
836 getaveragevertvel = sumvertvel / numvertvel
840 end function getaveragevertvel
843 subroutine calc_layerq(t, rh, pres, ept, nz, clouds)
845 integer,
intent(in) :: nz
846 real,
intent(in) :: t(nz), rh(nz), pres(nz), ept(nz)
847 type(
clouds_t),
intent(inout) :: clouds
850 real :: mean_rh, te_map, rh_map, adj_q
851 real :: totalq, testthetae, q_top, q_base, q_layer, delta_te, sum_rh
852 integer :: base_k, test_k, num_layers
854 integer :: k, m, n, kk
856 clouds%layerQ(:) = 0.0
859 lp_nlayers:
do n = 1, clouds%nLayers
860 lp_k_inlayer:
do k = clouds%topIdx(n), clouds%baseIdx(n)-1
866 base_k = clouds%baseIdx(n)
868 if((testthetae-ept(m)>4.) .and. (clouds%baseIdx(n)<=m))
then
875 lp_kk:
do kk = k, base_k-1
876 q_top = mixing_ratio(t(kk), pres(kk))
877 q_base = mixing_ratio(t(kk+1), pres(kk+1))
878 q_layer = q_base - q_top
881 q_layer = q_layer * (pres(kk)/(287.05 * t(kk)))
883 if (q_layer < 0.0) q_layer = 0.0
885 delta_te = testthetae - ept(kk+1)
892 num_layers = num_layers + 1
893 sum_rh = sum_rh + rh(m)
896 if (num_layers == 0)
then
899 mean_rh = sum_rh / num_layers
902 te_map = dq_delta_te_map(delta_te)
903 rh_map = dq_rh_map(mean_rh)
904 adj_q = q_layer * te_map * rh_map
906 totalq = totalq + adj_q
909 clouds%layerQ(k) = totalq
914 end subroutine calc_layerq
918 real function dq_rh_map(rh)
920 real,
intent(in) :: rh
924 else if( rh >= 100.)
then
927 dq_rh_map = (rh-70.)/30.
931 end function dq_rh_map
935 real function dq_delta_te_map(delte)
937 real,
intent(in) :: delte
939 if (delte <= 0.0)
then
940 dq_delta_te_map = 1.0
941 else if (delte <= 4.0)
then
942 dq_delta_te_map = (4. - delte) / 4.0
944 dq_delta_te_map = 0.0
948 end function dq_delta_te_map
950end module cloudlayers
959 use ctlblk_mod,
only: me
961 use derivedfields,
only : precips
973 subroutine icing_pot(hgt, rh, t, liqCond, vv, nz, clouds, ice_pot)
975 integer,
intent(in) :: nz
976 real,
intent(in) :: hgt(nz), rh(nz), t(nz), liqcond(nz), vv(nz)
977 type(
clouds_t),
intent(in) :: clouds
978 real,
intent(out) :: ice_pot(nz)
980 real :: ctt, slw, slw_fac, vv_fac
984 real :: mapt,maprh,mapctt,mapvv,mapslw
989 lp_n:
do n = 1, clouds%nLayers
994 lp_k:
do k = clouds%topIdx(n), clouds%baseIdx(n)
997 if ( ctt>=259.15 .and. ctt<=273.15 )
then
1003 ice_pot(k) = tmap(t(k)) * rh_map(rh(k)) * ctt_map(ctt)
1006 if (vv_map(vv(k))>=0.0)
then
1007 vv_fac = (1.0-ice_pot(k)) * (0.25*vv_map(vv(k)))
1009 vv_fac = ice_pot(k) * (0.25*vv_map(vv(k)))
1013 slw_fac = (1.0 - ice_pot(k))*(0.4*slw_map(slw))
1016 if (ice_pot(k)>0.001)
then
1017 ice_pot(k) = ice_pot(k) + vv_fac + slw_fac
1021 if (ice_pot(k)>1.0)
then
1042 end subroutine icing_pot
1045 real function tmap(temp)
1047 real,
intent(in) :: temp
1049 if((temp>=248.15).and.(temp<=263.15))
then
1050 tmap=((temp-248.15)/15.0)**1.5
1051 elseif((temp>263.15).and.(temp<268.15))
then
1053 elseif((temp>268.15).and.(temp<273.15))
then
1054 tmap=((273.15 - temp)/5.0)**0.75
1064 real function rh_map(rh)
1066 real,
intent(in) :: rh
1070 elseif ( (rh<=95.0).and.(rh>=50.0) )
then
1071 rh_map=((20./9.) * ((rh/100.0)-0.5))**3.0
1081 real function ctt_map(ctt)
1083 real,
intent(in) :: ctt
1085 if((ctt>=261.0).and.(ctt<280.))
then
1087 elseif((ctt>223.0).and.(ctt<261.0 ))
then
1088 ctt_map = 0.2 + 0.8*(((ctt - 223.0)/38.0)**2.0)
1089 elseif(ctt<223.0)
then
1096 end function ctt_map
1101 real function vv_map(vv)
1103 real,
intent(in) :: vv
1107 elseif (vv<-0.5)
then
1110 vv_map = -1.0 * (vv/0.5)
1119 real function slw_map(slw)
1121 real,
intent(in) :: slw
1125 elseif (slw<=0.001)
then
1132 end function slw_map
1134end module icingpotential
1148 integer :: NO_PRECIPITAION = 0
1150 integer :: PRECIPITAION_BELOW_WARMNOSE = 1
1152 integer :: PRECIPITAION_ABOVE_WARMNOSE = 2
1154 integer :: ALL_SNOW = 3
1156 integer :: COLD_RAIN = 4
1158 integer :: WARM_PRECIPITAION = 5
1160 integer :: FREEZING_PRECIPITAION = 6
1162 integer :: CONVECTION = 7
1166 type(scenarios_t),
parameter :: SCENARIOS =
scenarios_t()
1175 real function twp_map(v, scenario)
1177 real,
intent(in) :: v
1178 integer,
intent(in) :: scenario
1180 select case (scenario)
1181 case(scenarios%PRECIPITAION_ABOVE_WARMNOSE, scenarios%ALL_SNOW, &
1182 scenarios%COLD_RAIN, scenarios%FREEZING_PRECIPITAION)
1186 else if( v < 1000.)
then
1187 twp_map = v / 1000.0
1191 case( scenarios%WARM_PRECIPITAION)
1195 else if( v < 500.)
then
1202 end function twp_map
1207 real function t_map(v, scenario)
1209 real,
intent(in) :: v
1210 integer,
intent(in) :: scenario
1212 select case (scenario)
1213 case(scenarios%PRECIPITAION_BELOW_WARMNOSE)
1215 if(v <= 269.15)
then
1217 elseif( v <= 273.15)
then
1218 t_map = (273.15 - v ) / 4.0
1226 if(v <= 248.15)
then
1228 elseif( v <= 248.65)
then
1229 t_map = (49.162215 - 0.1961*v) * 2.
1230 elseif( v <= 249.15)
then
1231 t_map = (20.617195 - 0.0813*v) * 2.
1232 elseif(v <= 251.15)
then
1233 t_map = (52.02265 - 0.203*v) / 2.0
1234 elseif(v <= 253.15)
then
1235 t_map = (36.14997 - 0.1398*v) / 2.0
1236 elseif(v <= 255.15)
then
1237 t_map = (29.51744 - 0.1136*v) / 2.0
1238 elseif(v <= 257.15)
then
1239 t_map = (25.613645-0.0983*v) / 2.0
1240 elseif(v <= 259.15)
then
1241 t_map = (22.91357 - 0.0878*v) / 2.0
1242 elseif( v <= 261.15)
then
1243 t_map = (20.918115 - 0.0801*v) / 2.
1254 real function prcpCondensate_map(v, scenario)
1256 real,
intent(in) :: v
1257 integer,
intent(in) :: scenario
1258 prcpcondensate_map = 0.0
1259 select case (scenario)
1260 case(scenarios%NO_PRECIPITAION)
1262 case(scenarios%PRECIPITAION_BELOW_WARMNOSE, scenarios%COLD_RAIN, &
1263 scenarios%PRECIPITAION_ABOVE_WARMNOSE)
1266 prcpcondensate_map = 0.
1267 elseif(v <= 0.2)
then
1268 prcpcondensate_map = (v - 0.05) / 0.15
1270 prcpcondensate_map = 1.
1272 case(scenarios%ALL_SNOW)
1275 prcpcondensate_map = 0.
1276 elseif(v <= 0.25)
then
1277 prcpcondensate_map = (v - 0.05) / 0.2
1279 prcpcondensate_map = 1.0
1281 case(scenarios%WARM_PRECIPITAION, scenarios%FREEZING_PRECIPITAION)
1284 prcpcondensate_map = 0.
1285 elseif(v <= 0.15)
then
1286 prcpcondensate_map = (.5*v - 0.025) / 0.1
1288 prcpcondensate_map = 0.5
1292 end function prcpcondensate_map
1296 real function deltaZ_map(v, scenario)
1298 real,
intent(in) :: v
1299 integer,
intent(in) :: scenario
1301 select case (scenario)
1302 case (scenarios%NO_PRECIPITAION, scenarios%WARM_PRECIPITAION)
1306 else if(v <= 1828.8)
then
1307 deltaz_map = v /1828.8
1311 case(scenarios%PRECIPITAION_BELOW_WARMNOSE)
1318 case(scenarios%ALL_SNOW)
1322 else if(v <= 2743.2)
then
1323 deltaz_map = (v - 914.4) / 1828.8
1327 case(scenarios%COLD_RAIN, scenarios%FREEZING_PRECIPITAION)
1331 else if(v <= 4267.2)
then
1332 deltaz_map = (v - 1524.) / 2743.2
1338 end function deltaz_map
1348 real function ctt_map(v)
1350 real,
intent(in) :: v
1351 if(v <= 223.15)
then
1353 elseif(v <= 233.15)
then
1354 ctt_map = (20.36251 - 0.0554*v) / 10.
1355 elseif(v <= 243.15)
then
1356 ctt_map = (46.19553 - 0.1662*v) / 10.
1357 elseif(v <= 253.15)
then
1358 ctt_map = (73.13655 - 0.277*v) / 10.
1359 elseif(v <= 261.15)
then
1360 ctt_map = (78.71061 - 0.3014*v) / 8.
1364 end function ctt_map
1369 real function vv_map(v)
1371 real,
intent(in) :: v
1374 else if(v <= 0.)
then
1386 real function cldTopDist_map(v)
1388 real,
intent(in) :: v
1389 if( v <= 609.6)
then
1390 cldtopdist_map = 1.0
1391 elseif( v <= 3048.)
then
1392 cldtopdist_map = (3048. - v) / 2438.4
1396 end function cldtopdist_map
1403 real function cldBaseDist_map(v)
1405 real,
intent(in) :: v
1406 if( v <= 304.8)
then
1407 cldbasedist_map = 1.0
1408 elseif( v <= 1524.)
then
1409 cldbasedist_map = (1524. - v) / 1219.2
1411 cldbasedist_map = 0.
1413 end function cldbasedist_map
1418 real function deltaQ_map(v)
1420 real,
intent(in) :: v
1423 elseif( v <= 1.0)
then
1428 end function deltaq_map
1432 real function moisture_map_cond(rh, liqCond, iceCond, pres, t)
1434 real,
intent(in) :: rh, liqCond, iceCond, pres, t
1435 real :: liq_m3, ice_m3, rhFactor, liqFactor,iceFactor
1437 liq_m3 = (liqcond * pres) / (287.05 * t)
1438 ice_m3 = (icecond * pres) / (287.05 * t)
1439 rhfactor = 0.5 * rh_map(rh)
1440 liqfactor = 0.6* condensate_map(liq_m3)
1441 icefactor = 0.4 * condensate_map(ice_m3)
1442 moisture_map_cond = rhfactor + (1.0 - rhfactor) * (liqfactor + icefactor)
1444 end function moisture_map_cond
1449 real function moisture_map_cwat(rh, cwat, pres, t)
1451 real,
intent(in) :: rh, cwat, pres, t
1452 real :: cwat_m3, rhFactor, cwatFactor
1454 cwat_m3 = (cwat * pres) / (287.05 * t)
1455 rhfactor = 0.5 * rh_map(rh)
1456 cwatfactor = condensate_map(cwat_m3)
1457 moisture_map_cwat = rhfactor + (1.0 - rhfactor) * cwatfactor
1459 end function moisture_map_cwat
1465 real function rh_map(v)
1467 real,
intent(in) :: v
1470 else if(v <= 100)
then
1471 rh_map = (v - 70.) / 30.
1481 real function condensate_map(v)
1483 real,
intent(in) :: v
1486 elseif( v <= 0.2)
then
1487 condensate_map = (v - 0.004) / 0.196
1491 end function condensate_map
1502 real function convect_t_map(v)
1504 real,
intent(in) :: v
1505 if(v <= 243.15)
then
1507 else if(v <= 265.15)
then
1508 convect_t_map = (v -243.15)/22.
1509 else if(v <= 269.15)
then
1511 else if(v <= 270.15)
then
1512 convect_t_map = -0.13*v + 35.9895
1513 else if(v <= 271.15)
then
1514 convect_t_map = -0.16*v + 44.094
1515 else if(v <= 272.15)
then
1516 convect_t_map = -0.21*v + 57.6515
1517 else if(v <= 273.15)
then
1518 convect_t_map = -0.50*v + 136.575
1522 end function convect_t_map
1528 real function convect_qpf_map(v)
1530 real,
intent(in) :: v
1533 else if(v <= 3.0)
then
1534 convect_qpf_map = (v - 1.) / 2.
1536 convect_qpf_map = 1.
1538 end function convect_qpf_map
1543 real function convect_cape_map(v)
1545 real,
intent(in) :: v
1547 if (v <= 1000.0)
then
1548 convect_cape_map = 0.0
1549 else if(v <= 2500.)
then
1550 convect_cape_map = (v - 1000.0) / 1400.
1552 convect_cape_map = 1.0
1554 end function convect_cape_map
1560 real function convect_liftedIdx_map(v)
1562 real,
intent(in) :: v
1564 convect_liftedidx_map = 1.0
1565 else if(v <= 0.)
then
1566 convect_liftedidx_map = -0.1 * v
1568 convect_liftedidx_map = 0.
1570 end function convect_liftedidx_map
1576 real function convect_kIdx_map(v)
1578 real,
intent(in) :: v
1580 convect_kidx_map = 0
1581 else if(v <= 40.0)
then
1582 convect_kidx_map = (v - 20.) / 20.
1584 convect_kidx_map = 1.
1586 end function convect_kidx_map
1591 real function convect_totals_map(v)
1593 real,
intent(in) :: v
1595 convect_totals_map = 0
1596 else if( v <= 55.0)
then
1597 convect_totals_map = (v - 20) / 35.
1599 convect_totals_map = 1.0
1601 end function convect_totals_map
1603end module severitymaps
1611 use derivedfields,
only : precips
1620 real,
parameter :: COLD_PRCP_T_THLD = 261.15
1624 real :: ctt, layerQ, avv
1625 integer :: nLayers, topIdx, baseIdx, wmnIdx
1627 real :: deltaZ, cloudTopDist
1629 logical :: lowestCloud
1660 subroutine icing_sev(imp_physics,hgt, rh, t, pres, vv, liqCond, iceCond, twp, &
1661 ice_pot, nz, hcprcp, cape, lx, kx, tott, pc, prcpType, clouds, &
1664 integer,
intent(in) :: imp_physics
1665 integer,
intent(in) :: nz
1666 real,
intent(in) :: hgt(nz), rh(nz), t(nz), pres(nz), vv(nz)
1667 real,
intent(in) :: liqcond(nz), icecond(nz), twp(nz), ice_pot(nz)
1668 real,
intent(in) :: hcprcp, cape, lx, kx, tott, pc
1669 integer,
intent(in) :: prcptype
1670 type(
clouds_t),
intent(in) :: clouds
1671 real,
intent(out) :: iseverity(nz)
1680 lowestcloud = .false.
1683 lp_n:
do n = 1, clouds%nLayers
1686 wmnidx = clouds%wmnIdx
1688 if (n == clouds%nLayers) lowestcloud = .true.
1691 topidx = clouds%topIdx(n)
1692 baseidx = clouds%baseIdx(n)
1694 lp_k:
do k = topidx, baseidx
1695 if (ice_pot(k) < 0.001) cycle
1700 layerq = clouds%layerQ(k)
1702 deltaz = hgt(k) - hgt(baseidx)
1703 cloudtopdist = hgt(topidx) - hgt(k)
1706 if(imp_physics == 98 .or. imp_physics == 99)
then
1707 moistint = moisture_map_cwat(rh(k), liqcond(k)+icecond(k), pres(k), t(k))
1709 moistint = moisture_map_cond(rh(k), liqcond(k),icecond(k), pres(k), t(k))
1712 if(isconvection(prcptype))
then
1713 call convectionscenario &
1714 (t(k), hcprcp, cape, lx, kx, tott, severity)
1715 elseif(isclassicprcpblwwmn(prcptype, k))
then
1716 call classicprcpblwwmnscenario &
1717 (t(k), avv, pc, ice_pot(k), severity)
1718 elseif(isclassicprcpabvwmn(prcptype, k))
then
1719 call classicprcpabvwmnscenario &
1720 (twp(k), vv(k), t(k), pc, ice_pot(k),severity)
1721 elseif(isnoprecip(prcptype))
then
1722 call noprcpscenario &
1723 (vv(k), t(k), pc, ice_pot(k), severity)
1724 elseif(issnow(prcptype))
then
1726 (twp(k), vv(k), t(k), pc, ice_pot(k), severity)
1727 elseif(iscoldrain(prcptype))
then
1728 call coldrainscenario &
1729 (twp(k), vv(k), t(k), pc, ice_pot(k), severity)
1730 elseif(iswarmprecip(prcptype))
then
1731 call warmprecipscenario &
1732 (twp(k), vv(k), t(k), pc, ice_pot(k), severity)
1733 elseif(isfreezingprecip(prcptype))
then
1734 call freezingprecipscenario &
1735 (twp(k), vv(k), t(k), pc, ice_pot(k), severity)
1771 iseverity(k)=min(1., severity)
1772 iseverity(k)=max(0., severity)
1778 end subroutine icing_sev
1781 logical function isconvection(prcpType)
1783 integer,
intent(in) :: prcptype
1785 isconvection = prcptype == precips%CONVECTION
1788 end function isconvection
1791 subroutine convectionscenario(t, hcprcp, cape, lx, kx, tott, severity)
1793 real,
intent(in) :: t, hcprcp, cape, lx, kx, tott
1794 real,
intent(out) :: severity
1798 real :: tint, prcpint, capeint, lxint, kxint,tottint
1800 real :: weights(6) = (/ 4.0, 3.0, 5.0, 5.0, 2.0, 2.0 /)
1802 sumweight = sum(weights)
1804 tint = convect_t_map(t) ** 0.5
1806 prcpint = convect_qpf_map(hcprcp)
1807 capeint = convect_cape_map(cape)
1808 lxint = convect_liftedidx_map(lx)
1809 kxint = convect_kidx_map(kx)
1810 tottint = convect_totals_map(tott)
1812 scenario = scenarios%CONVECTION
1814 severity = (weights(1) * tint + weights(2) * prcpint + &
1815 weights(3) * capeint + weights(4) * lxint + &
1816 weights(5) * kxint + weights(6) * tottint) / &
1819 end subroutine convectionscenario
1823 logical function isclassicprcpblwwmn(prcpType, k)
1825 integer,
intent(in) :: prcptype, k
1828 if ((prcptype /= precips%NONE .and. prcptype /= precips%SNOW) .and.&
1829 (wmnidx > 0 .and. k <= wmnidx .and. topidx > wmnidx) .and. &
1830 (ctt < cold_prcp_t_thld))
then
1831 isclassicprcpblwwmn = .true.
1833 isclassicprcpblwwmn = .false.
1837 end function isclassicprcpblwwmn
1840 subroutine classicprcpblwwmnscenario(t, vv, pc, ice_pot, severity)
1842 real,
intent(in) :: t, pc, vv, ice_pot
1843 real,
intent(out) :: severity
1847 real :: tint, pcint, dzint
1848 real :: cttint, vvint
1852 real :: weights(7) = (/ 3.0, 4.0, 3.0, 3.0, 3.5, 2.5, 2.0 /)
1854 sumweight = sum(weights)
1856 scenario = scenarios%PRECIPITAION_BELOW_WARMNOSE
1858 tint = t_map(t, scenario)
1859 pcint = prcpcondensate_map(pc, scenario)
1860 dzint = deltaz_map(deltaz, scenario)
1861 cttint = ctt_map(ctt)
1864 severity = (weights(1) * tint + weights(2) * pcint + &
1865 weights(3) * dzint + weights(4) * cttint + &
1866 weights(5) * moistint + weights(6) * vvint + &
1867 weights(7) * ice_pot) / sumweight
1870 end subroutine classicprcpblwwmnscenario
1875 logical function isclassicprcpabvwmn(prcpType, k)
1877 integer,
intent(in) :: prcptype, k
1880 if((prcptype /= precips%NONE .and. prcptype /= precips%SNOW) .and.&
1881 (wmnidx > 0 .and. k > wmnidx .and. topidx > wmnidx) .and. &
1882 (ctt < cold_prcp_t_thld))
then
1883 isclassicprcpabvwmn = .true.
1885 isclassicprcpabvwmn = .false.
1889 end function isclassicprcpabvwmn
1893 subroutine classicprcpabvwmnscenario(twp, vv, t, pc, ice_pot, severity)
1895 real,
intent(in) :: twp, vv, t, pc, ice_pot
1896 real,
intent(out) :: severity
1899 real :: twpint, vvint
1900 real :: tempadj, cttadj, pcadj
1904 real :: weights(4) = (/ 3.0, 3.5, 4.0, 2.0 /)
1906 sumweight = sum(weights)
1908 scenario = scenarios%PRECIPITAION_ABOVE_WARMNOSE
1910 twpint = twp_map(twp, scenario)
1917 call cal_dampingfactors(scenario, t, pc, tempadj, cttadj, pcadj)
1919 severity = (weights(1) * twpint + weights(2) * vvint + &
1920 weights(3) * moistint + weights(4) * ice_pot) / &
1921 (sumweight + 6.5*tempadj + 3.0*cttadj + 3.0*pcadj)
1924 end subroutine classicprcpabvwmnscenario
1929 logical function isnoprecip(prcpType)
1931 integer,
intent(in) :: prcptype
1933 isnoprecip = prcptype == precips%NONE
1936 end function isnoprecip
1941 subroutine noprcpscenario(vv, t, pc, ice_pot, severity)
1943 real,
intent(in) :: vv, t, pc, ice_pot
1944 real,
intent(out) :: severity
1948 real :: dqint, dzint, vvint
1949 real :: tempadj, cttadj, pcadj
1953 real :: weights(5) = (/ 3.0, 3.5, 4.0, 4.0, 3.0 /)
1955 sumweight = sum(weights)
1957 scenario = scenarios%NO_PRECIPITAION
1959 dqint = deltaq_map(layerq)
1960 dzint = deltaz_map(deltaz, scenario)
1967 call cal_dampingfactors(scenario, t, pc, tempadj, cttadj, pcadj)
1969 severity = (weights(1) * dqint + weights(2) * dzint + &
1970 weights(3) * vvint + weights(4) * moistint + &
1971 weights(5) * ice_pot) / &
1972 (sumweight + 9.0*tempadj + 4.5*cttadj)
1975 end subroutine noprcpscenario
1980 logical function issnow(prcpType)
1982 integer,
intent(in) :: prcptype
1984 issnow = prcptype == precips%SNOW
1991 subroutine snowscenario(twp, vv, t, pc, ice_pot, severity)
1993 real,
intent(in) :: twp, vv, t, pc, ice_pot
1994 real,
intent(out) :: severity
1998 real :: twpint, dzint, vvint
1999 real :: tempadj, cttadj, pcadj
2003 real :: weights(5) = (/ 3.0, 3.5, 3.5, 4.0, 3.0 /)
2005 sumweight = sum(weights)
2007 scenario = scenarios%ALL_SNOW
2009 twpint = twp_map(twp, scenario)
2010 dzint = deltaz_map(deltaz, scenario)
2017 call cal_dampingfactors(scenario, t, pc, tempadj, cttadj, pcadj)
2019 severity = (weights(1) * twpint + weights(2) * dzint + &
2020 weights(3) * vvint + weights(4) * moistint + &
2021 weights(5) * ice_pot) / &
2022 (sumweight + 9.0*tempadj + 4.0*cttadj + 4.0*pcadj)
2025 end subroutine snowscenario
2029 logical function iscoldrain(prcpType)
2031 integer,
intent(in) :: prcptype
2034 iscoldrain = prcptype == precips%RAIN .and. ctt < cold_prcp_t_thld
2037 end function iscoldrain
2041 subroutine coldrainscenario(twp, vv, t, pc, ice_pot, severity)
2043 real,
intent(in) :: twp, vv, t, pc, ice_pot
2044 real,
intent(out) :: severity
2048 real :: twpint, dzint, vvint
2049 real :: tempadj, cttadj, pcadj
2053 real :: weights(5) = (/ 3.0, 3.5, 3.5, 4.0, 2.0 /)
2055 sumweight = sum(weights)
2057 scenario = scenarios%COLD_RAIN
2059 twpint = twp_map(twp, scenario)
2060 dzint = deltaz_map(deltaz, scenario)
2067 call cal_dampingfactors(scenario, t, pc, tempadj, cttadj, pcadj)
2069 severity = (weights(1) * twpint + weights(2) * dzint + &
2070 weights(3) * vvint + weights(4) * moistint + &
2071 weights(5) * ice_pot) / &
2072 (sumweight + 8.0*tempadj + 4.0*cttadj + 4.0*pcadj)
2075 end subroutine coldrainscenario
2083 logical function iswarmprecip(prcpType)
2085 integer,
intent(in) :: prcptype
2088 if((prcptype == precips%RAIN .or. prcptype == precips%OTHER) .and. &
2089 (ctt >= cold_prcp_t_thld))
then
2090 iswarmprecip = .true.
2091 elseif((prcptype /= precips%NONE .and. prcptype /= precips%SNOW).and.&
2092 (wmnidx > 0 .and. topidx <= wmnidx) .and. &
2093 (ctt >= cold_prcp_t_thld))
then
2094 iswarmprecip = .true.
2096 iswarmprecip = .false.
2100 end function iswarmprecip
2104 subroutine warmprecipscenario(twp, vv, t, pc, ice_pot, severity)
2106 real,
intent(in) :: twp, vv, t, pc, ice_pot
2107 real,
intent(out) :: severity
2111 real :: twpint, dzint, vvint, dqint
2112 real :: tempadj, cttadj, pcadj
2116 real :: weights(6) = (/ 3.0, 3.0, 3.0, 3.5, 4.0, 2.0 /)
2118 sumweight = sum(weights)
2120 scenario = scenarios%WARM_PRECIPITAION
2122 twpint = twp_map(twp, scenario)
2123 dzint = deltaz_map(deltaz, scenario)
2125 dqint = deltaq_map(layerq)
2131 call cal_dampingfactors(scenario, t, pc, tempadj, cttadj, pcadj)
2133 severity = (weights(1) * twpint + weights(2) * dzint + &
2134 weights(3) * vvint + weights(4) * moistint + &
2135 weights(5) * ice_pot + weights(6) * dqint) / &
2136 (sumweight + 9.0*tempadj + 4.5*cttadj + 4.5*pcadj)
2139 end subroutine warmprecipscenario
2143 logical function isfreezingprecip(prcpType)
2145 integer,
intent(in) :: prcptype
2148 if (prcptype == precips%OTHER .and. ctt < cold_prcp_t_thld)
then
2149 isfreezingprecip = .true.
2151 isfreezingprecip = .false.
2155 end function isfreezingprecip
2160 subroutine freezingprecipscenario(twp, vv, t, pc, ice_pot, severity)
2162 real,
intent(in) :: twp, vv, t, pc, ice_pot
2163 real,
intent(out) :: severity
2167 real :: twpint, dzint, vvint
2168 real :: tempadj, cttadj, pcadj
2172 real :: weights(5) = (/ 3.0, 3.5, 3.5, 4.0, 2.0 /)
2174 sumweight = sum(weights)
2176 scenario = scenarios%FREEZING_PRECIPITAION
2178 twpint = twp_map(twp, scenario)
2179 dzint = deltaz_map(deltaz, scenario)
2186 call cal_dampingfactors(scenario, t, pc, tempadj, cttadj, pcadj)
2188 severity = (weights(1) * twpint + weights(2) * dzint + &
2189 weights(3) * vvint + weights(4) * moistint + &
2190 weights(5) * ice_pot) / &
2191 (sumweight + 8.0*tempadj + 4.0*cttadj + 4.0*pcadj)
2194 end subroutine freezingprecipscenario
2212 subroutine cal_dampingfactors(scenario, t, pc, tempAdj,cttAdj,condAdj)
2214 integer,
intent(in) :: scenario
2215 real,
intent(in) :: t, pc
2216 real,
intent(out) :: tempadj, cttadj, condadj
2219 tempadj = t_map(t, scenario)
2221 cttadj = ctt_map(ctt) * cldtopdist_map(cloudtopdist)
2223 if (lowestcloud)
then
2224 condadj = cldbasedist_map(deltaz)
2226 condadj = condadj * prcpcondensate_map(pc, scenario)
2230 end subroutine cal_dampingfactors
2233end module icingseverity
2238subroutine icing_algo(i,j,pres,temp,rh,hgt,omega,wh,&
2239 q,cwat,qqw,qqi,qqr,qqs,qqg,&
2240 nz,xlat,xlon,xalt,prate,cprate,&
2241 cape,cin, ice_pot, ice_sev)
2242 use ctlblk_mod,
only: imp_physics, spval, dtq2,me
2243 use physcons_post,
only: g => con_g, fv => con_fvirt, rd => con_rd
2245 use derivedfields,
only : derive_fields
2246 use cloudlayers,
only : calc_cloudlayers,
clouds_t
2247 use icingpotential,
only : icing_pot
2248 use icingseverity,
only : icing_sev
2287 integer,
intent(in) :: i,j, nz
2288 real,
intent(in),
dimension(nz) :: pres,temp,rh,hgt,omega,wh
2290 real,
intent(in),
dimension(nz) :: q,cwat,qqw,qqi,qqr,qqs,qqg
2291 real,
intent(in) :: xlat, xlon, xalt
2292 real,
intent(in) :: prate, cprate
2293 real,
intent(in) :: cape, cin
2294 real,
intent(out) :: ice_pot(nz), ice_sev(nz)
2296 real :: hprcp, hcprcp
2297 integer :: topok, region, prcptype
2298 real,
allocatable :: vv(:), ept(:), wbt(:), twp(:)
2299 real,
allocatable :: icecond(:),liqcond(:), totwater(:),totcond(:)
2300 real :: pc, kx, lx, tott
2311 allocate(icecond(nz),liqcond(nz))
2312 allocate(totwater(nz),totcond(nz))
2314 allocate(clouds%layerQ(nz))
2331 hprcp = prate * 1000. / dtq2 * 3600.
2332 hcprcp = cprate * 1000. / dtq2 * 3600.
2334 if(imp_physics == 98 .or. imp_physics == 99)
then
2340 if(cwat(k) == spval)
then
2347 if(temp(k) >=259.15)
then
2348 liqcond(k) = cwat(k) * 1000.
2352 icecond(k) = cwat(k) * 1000.
2355 totwater(k) = cwat(k) * 1000.
2357 totcond(k) = cwat(k) * 1000.
2359 else if(imp_physics == 11 .or. imp_physics == 8)
then
2364 if(vv(k) /= spval)
then
2365 tv = temp(k)*(1.+q(k)*fv)
2366 vv(k)=-vv(k)*g*(pres(k)/(rd*tv))
2369 if(qqw(k) /= spval .and. qqr(k) /= spval)
then
2370 liqcond(k) = (qqw(k) + qqr(k)) * 1000.
2375 if(qqi(k) /= spval .and. qqs(k) /= spval .and. qqg(k) /= spval)
then
2376 icecond(k) = (qqi(k) + qqs(k) + qqg(k)) * 1000.
2381 if(liqcond(k) /= spval .and. icecond(k) /= spval)
then
2382 totwater(k) = liqcond(k) + icecond(k)
2387 if(qqr(k) /= spval .and. qqs(k) /= spval .and. qqg(k) /= spval)
then
2388 totcond(k) = (qqr(k) + qqs(k) + qqg(k)) * 1000.
2394 print *,
"This schema is not supported. imp_physics=", imp_physics
2398 call derive_fields(imp_physics,temp, rh, pres, hgt, totwater,totcond, &
2399 nz, topok, hprcp, hcprcp, cin, cape,&
2400 ept, wbt, twp, pc, kx, lx, tott, prcptype)
2402 call calc_cloudlayers(rh, temp, pres, ept, vv, nz,topok, xlat,xlon,&
2410 call icing_pot(hgt, rh, temp, liqcond, vv, nz, clouds, ice_pot)
2413 call icing_sev(imp_physics, hgt, rh, temp, pres, vv, liqcond, icecond, twp, &
2414 ice_pot, nz, hcprcp, cape, lx, kx, tott, pc, prcptype, clouds, &
2434 deallocate(icecond,liqcond)
2435 deallocate(totwater,totcond)
2436 deallocate(clouds%layerQ)
2439end subroutine icing_algo
2451 real,
intent(in) :: hgt(nz)
2452 real,
intent(in) :: alt
2453 integer,
intent(in) :: nz
2457 if(hgt(nz) >= alt)
then
2461 if ((hgt(k-1) > alt) .and. (hgt(k) <= alt))
then
integer function gettopok(hgt, alt, nz)
getTopoK() Maps the topography height to the model's vertical coordinate