Changeset 1769 in lmdz_wrf for trunk/tools/module_ForDiagnostics.f90
- Timestamp:
- Feb 8, 2018, 9:10:45 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/module_ForDiagnostics.f90
r1762 r1769 14 14 15 15 !!!!!!! Calculations 16 ! compute_cape_afwa4D: Subroutine to use WRF phys/module_diag_afwa.F `buyoancy' subroutine to compute 17 ! CAPE, CIN, ZLFC, PLFC, LI 16 18 ! compute_cllmh4D3: Computation of low, medium and high cloudiness from a 4D CLDFRA and pressure being 17 19 ! 3rd dimension the z-dim … … 22 24 ! compute_clt3D3: Computation of total cloudiness from a 3D CLDFRA being 3rd dimension the z-dim 23 25 ! compute_clt: Computation of total cloudiness 24 ! compute_psl_ptarget4d2: Compute sea level pressure using a target pressure. Similar to the Benjamin 25 ! and Miller (1990). Method found in p_interp.F90 26 ! compute_tv4d: 4D calculation of virtual temperaure 27 ! VirtualTemp1D: Function for 1D calculation of virtual temperaure 28 26 ! compute_massvertint1D: Subroutine to vertically integrate a 1D variable in eta vertical coordinates 27 ! compute_vertint1D: Subroutine to vertically integrate a 1D variable in any vertical coordinates 28 ! compute_zint4D: Subroutine to vertically integrate a 4D variable in any vertical coordinates 29 29 !!! 30 30 ! Calculations … … 455 455 END SUBROUTINE compute_clt 456 456 457 SUBROUTINE compute_psl_ptarget4d2(press, ps, hgt, ta, qv, ptarget, psl, d1, d2, d3, d4)458 ! Subroutine to compute sea level pressure using a target pressure. Similar to the Benjamin459 ! and Miller (1990). Method found in p_interp.F90460 461 IMPLICIT NONE462 463 INTEGER, INTENT(in) :: d1, d2, d3, d4464 REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(in) :: press, ta, qv465 REAL(r_k), DIMENSION(d1,d2,d4), INTENT(in) :: ps466 REAL(r_k), DIMENSION(d1,d2), INTENT(in) :: hgt467 REAL(r_k), INTENT(in) :: ptarget468 REAL(r_k), DIMENSION(d1,d2,d4), INTENT(out) :: psl469 470 ! Local471 INTEGER :: i, j, it472 INTEGER :: kin473 INTEGER :: kupper474 REAL(r_k) :: dpmin, dp, tbotextrap, &475 tvbotextrap, virtual476 ! Exponential related to standard atmosphere lapse rate r_d*gammav/g477 REAL(r_k), PARAMETER :: expon=r_d*gammav/grav478 479 !!!!!!! Variables480 ! press: Atmospheric pressure [Pa]481 ! ps: surface pressure [Pa]482 ! hgt: surface height483 ! ta: temperature [K]484 ! qv: water vapor mixing ratio485 ! dz: number of vertical levels486 ! psl: sea-level pressure487 488 fname = 'compute_psl_ptarget4d2'489 490 ! Minimal distance between pressures [Pa]491 dpmin=1.e4492 psl=0.493 494 DO i=1,d1495 DO j=1,d2496 IF (hgt(i,j) /= 0.) THEN497 DO it=1,d4498 499 ! target pressure to be used for the extrapolation [Pa] (defined in namelist.input)500 ! ptarget = 70000. default value501 502 ! We are below both the ground and the lowest data level.503 504 ! First, find the model level that is closest to a "target" pressure505 ! level, where the "target" pressure is delta-p less that the local506 ! value of a horizontally smoothed surface pressure field. We use507 ! delta-p = 150 hPa here. A standard lapse rate temperature profile508 ! passing through the temperature at this model level will be used509 ! to define the temperature profile below ground. This is similar510 ! to the Benjamin and Miller (1990) method, using511 ! 700 hPa everywhere for the "target" pressure.512 513 kupper = 0514 loop_kIN: DO kin=d3,1,-1515 kupper = kin516 dp=abs( press(i,j,kin,it) - ptarget )517 IF (dp .GT. dpmin) EXIT loop_kIN518 dpmin=min(dpmin,dp)519 ENDDO loop_kIN520 521 tbotextrap=ta(i,j,kupper,it)*(ps(i,j,it)/ptarget)**expon522 tvbotextrap=virtualTemp1D(tbotextrap,qv(i,j,kupper,it))523 524 psl(i,j,it) = ps(i,j,it)*((tvbotextrap+gammav*hgt(i,j))/tvbotextrap)**(1/expon)525 END DO526 ELSE527 psl(i,j,:) = ps(i,j,:)528 END IF529 END DO530 END DO531 532 RETURN533 534 END SUBROUTINE compute_psl_ptarget4d2535 536 457 SUBROUTINE compute_massvertint1D(var, mutot, dz, deta, integral) 537 458 ! Subroutine to vertically integrate a 1D variable in eta vertical coordinates … … 628 549 629 550 END SUBROUTINE compute_vertint1D 630 631 SUBROUTINE compute_tv4d(ta,qv,tv,d1,d2,d3,d4)632 ! 4D calculation of virtual temperaure633 634 IMPLICIT NONE635 636 INTEGER, INTENT(in) :: d1, d2, d3, d4637 REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(in) :: ta, qv638 REAL(r_k), DIMENSION(d1,d2,d3,d4), INTENT(out) :: tv639 640 ! Variables641 ! ta: temperature [K]642 ! qv: mixing ratio [kgkg-1]643 ! tv: virtual temperature644 645 tv = ta*(oneRK+(qv/epsilonv))/(oneRK+qv)646 647 END SUBROUTINE compute_tv4d648 649 FUNCTION VirtualTemp1D (ta,qv) result (tv)650 ! 1D calculation of virtual temperaure651 652 IMPLICIT NONE653 654 REAL(r_k), INTENT(in) :: ta, qv655 REAL(r_k) :: tv656 657 ! Variables658 ! ta: temperature [K]659 ! qv: mixing ratio [kgkg-1]660 661 tv = ta*(oneRK+(qv/epsilonv))/(oneRK+qv)662 663 END FUNCTION VirtualTemp1D664 665 ! ---- BEGIN modified from module_diag_afwa.F ---- !666 667 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!668 !~669 !~ Name:670 !~ Theta671 !~672 !~ Description:673 !~ This function calculates potential temperature as defined by674 !~ Poisson's equation, given temperature and pressure ( hPa ).675 !~676 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!677 FUNCTION Theta ( t, p )678 679 IMPLICIT NONE680 681 !~ Variable declaration682 ! --------------------683 REAL(r_k), INTENT ( IN ) :: t684 REAL(r_k), INTENT ( IN ) :: p685 REAL(r_k) :: theta686 687 ! Using WRF values688 !REAL :: Rd ! Dry gas constant689 !REAL :: Cp ! Specific heat of dry air at constant pressure690 !REAL :: p00 ! Standard pressure ( 1000 hPa )691 REAL(r_k) :: Rd, p00692 693 !Rd = 287.04694 !Cp = 1004.67695 !p00 = 1000.00696 697 Rd = r_d698 p00 = p1000mb/100.699 700 !~ Poisson's equation701 ! ------------------702 theta = t * ( (p00/p)**(Rd/Cp) )703 704 END FUNCTION Theta705 706 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!707 !~708 !~ Name:709 !~ Thetae710 !~711 !~ Description:712 !~ This function returns equivalent potential temperature using the713 !~ method described in Bolton 1980, Monthly Weather Review, equation 43.714 !~715 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!716 FUNCTION Thetae ( tK, p, rh, mixr )717 718 IMPLICIT NONE719 720 !~ Variable Declarations721 ! ---------------------722 REAL(r_k) :: tK ! Temperature ( K )723 REAL(r_k) :: p ! Pressure ( hPa )724 REAL(r_k) :: rh ! Relative humidity725 REAL(r_k) :: mixr ! Mixing Ratio ( kg kg^-1)726 REAL(r_k) :: te ! Equivalent temperature ( K )727 REAL(r_k) :: thetae ! Equivalent potential temperature728 729 ! Using WRF values730 !REAL, PARAMETER :: R = 287.04 ! Universal gas constant (J/deg kg)731 !REAL, PARAMETER :: P0 = 1000.0 ! Standard pressure at surface (hPa)732 REAL(r_k) :: R, p00, Lv733 !REAL, PARAMETER :: lv = 2.54*(10**6) ! Latent heat of vaporization734 ! (J kg^-1)735 !REAL, PARAMETER :: cp = 1004.67 ! Specific heat of dry air constant736 ! at pressure (J/deg kg)737 REAL(r_k) :: tlc ! LCL temperature738 739 R = r_d740 p00 = p1000mb/100.741 lv = XLV742 743 !~ Calculate the temperature of the LCL744 ! ------------------------------------745 tlc = TLCL ( tK, rh )746 747 !~ Calculate theta-e748 ! -----------------749 thetae = (tK * (p00/p)**( (R/Cp)*(1.- ( (.28E-3)*mixr*1000.) ) ) )* &750 exp( (((3.376/tlc)-.00254))*&751 (mixr*1000.*(1.+(.81E-3)*mixr*1000.)) )752 753 END FUNCTION Thetae754 755 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!756 !~757 !~ Name:758 !~ The2T.f90759 !~760 !~ Description:761 !~ This function returns the temperature at any pressure level along a762 !~ saturation adiabat by iteratively solving for it from the parcel763 !~ thetae.764 !~765 !~ Dependencies:766 !~ function thetae.f90767 !~768 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!769 FUNCTION The2T ( thetaeK, pres, flag ) result ( tparcel )770 771 IMPLICIT NONE772 773 !~ Variable Declaration774 ! --------------------775 REAL(r_k), INTENT ( IN ) :: thetaeK776 REAL(r_k), INTENT ( IN ) :: pres777 LOGICAL, INTENT ( INOUT ) :: flag778 REAL(r_k) :: tparcel779 780 REAL(r_k) :: thetaK781 REAL(r_k) :: tovtheta782 REAL(r_k) :: tcheck783 REAL(r_k) :: svpr, svpr2784 REAL(r_k) :: smixr, smixr2785 REAL(r_k) :: thetae_check, thetae_check2786 REAL(r_k) :: tguess_2, correction787 788 LOGICAL :: found789 INTEGER :: iter790 791 ! Using WRF values792 !REAL :: R ! Dry gas constant793 !REAL :: Cp ! Specific heat for dry air794 !REAL :: kappa ! Rd / Cp795 !REAL :: Lv ! Latent heat of vaporization at 0 deg. C796 REAL(r_k) :: R, kappa, Lv797 798 R = r_d799 Lv = XLV800 !R = 287.04801 !Cp = 1004.67802 Kappa = R/Cp803 !Lv = 2.500E+6804 805 !~ Make initial guess for temperature of the parcel806 ! ------------------------------------------------807 tovtheta = (pres/100000.0)**(r/cp)808 tparcel = thetaeK/exp(lv*.012/(cp*295.))*tovtheta809 810 iter = 1811 found = .false.812 flag = .false.813 814 DO815 IF ( iter > 105 ) EXIT816 817 tguess_2 = tparcel + REAL ( 1 )818 819 svpr = 6.122 * exp ( (17.67*(tparcel-273.15)) / (tparcel-29.66) )820 smixr = ( 0.622*svpr ) / ( (pres/100.0)-svpr )821 svpr2 = 6.122 * exp ( (17.67*(tguess_2-273.15)) / (tguess_2-29.66) )822 smixr2 = ( 0.622*svpr2 ) / ( (pres/100.0)-svpr2 )823 824 ! ------------------------------------------------------------------ ~!825 !~ When this function was orinially written, the final parcel ~!826 !~ temperature check was based off of the parcel temperature and ~!827 !~ not the theta-e it produced. As there are multiple temperature- ~!828 !~ mixing ratio combinations that can produce a single theta-e value, ~!829 !~ we change the check to be based off of the resultant theta-e ~!830 !~ value. This seems to be the most accurate way of backing out ~!831 !~ temperature from theta-e. ~!832 !~ ~!833 !~ Rentschler, April 2010 ~!834 ! ------------------------------------------------------------------ !835 836 !~ Old way...837 !thetaK = thetaeK / EXP (lv * smixr /(cp*tparcel) )838 !tcheck = thetaK * tovtheta839 840 !~ New way841 thetae_check = Thetae ( tparcel, pres/100., 100., smixr )842 thetae_check2 = Thetae ( tguess_2, pres/100., 100., smixr2 )843 844 !~ Whew doggies - that there is some accuracy...845 !IF ( ABS (tparcel-tcheck) < .05) THEN846 IF ( ABS (thetaeK-thetae_check) < .001) THEN847 found = .true.848 flag = .true.849 EXIT850 END IF851 852 !~ Old853 !tparcel = tparcel + (tcheck - tparcel)*.3854 855 !~ New856 correction = ( thetaeK-thetae_check ) / ( thetae_check2-thetae_check )857 tparcel = tparcel + correction858 859 iter = iter + 1860 END DO861 862 !IF ( .not. found ) THEN863 ! print*, "Warning! Thetae to temperature calculation did not converge!"864 ! print*, "Thetae ", thetaeK, "Pressure ", pres865 !END IF866 867 END FUNCTION The2T868 869 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!870 !~871 !~ Name:872 !~ VirtualTemperature873 !~874 !~ Description:875 !~ This function returns virtual temperature given temperature ( K )876 !~ and mixing ratio.877 !~878 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!879 FUNCTION VirtualTemperature ( tK, w ) result ( Tv )880 881 IMPLICIT NONE882 883 !~ Variable declaration884 real(r_k), intent ( in ) :: tK !~ Temperature885 real(r_k), intent ( in ) :: w !~ Mixing ratio ( kg kg^-1 )886 real(r_k) :: Tv !~ Virtual temperature887 888 Tv = tK * ( 1.0 + (w/0.622) ) / ( 1.0 + w )889 890 END FUNCTION VirtualTemperature891 892 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!893 !~894 !~ Name:895 !~ SaturationMixingRatio896 !~897 !~ Description:898 !~ This function calculates saturation mixing ratio given the899 !~ temperature ( K ) and the ambient pressure ( Pa ). Uses900 !~ approximation of saturation vapor pressure.901 !~902 !~ References:903 !~ Bolton (1980), Monthly Weather Review, pg. 1047, Eq. 10904 !~905 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!906 FUNCTION SaturationMixingRatio ( tK, p ) result ( ws )907 908 IMPLICIT NONE909 910 REAL(r_k), INTENT ( IN ) :: tK911 REAL(r_k), INTENT ( IN ) :: p912 REAL(r_k) :: ws913 914 REAL(r_k) :: es915 916 es = 6.122 * exp ( (17.67*(tK-273.15))/ (tK-29.66) )917 ws = ( 0.622*es ) / ( (p/100.0)-es )918 919 END FUNCTION SaturationMixingRatio920 921 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!922 !~923 !~ Name:924 !~ tlcl925 !~926 !~ Description:927 !~ This function calculates the temperature of a parcel of air would have928 !~ if lifed dry adiabatically to it's lifting condensation level (lcl).929 !~930 !~ References:931 !~ Bolton (1980), Monthly Weather Review, pg. 1048, Eq. 22932 !~933 !!!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~!!!934 FUNCTION TLCL ( tk, rh )935 936 IMPLICIT NONE937 938 REAL(r_k), INTENT ( IN ) :: tK !~ Temperature ( K )939 REAL(r_k), INTENT ( IN ) :: rh !~ Relative Humidity ( % )940 REAL(r_k) :: tlcl941 942 REAL(r_k) :: denom, term1, term2943 944 term1 = 1.0 / ( tK - 55.0 )945 !! Lluis946 ! IF ( rh > REAL (0) ) THEN947 IF ( rh > zeroRK ) THEN948 term2 = ( LOG (rh/100.0) / 2840.0 )949 ELSE950 term2 = ( LOG (0.001/oneRK) / 2840.0 )951 END IF952 denom = term1 - term2953 !! Lluis954 ! tlcl = ( 1.0 / denom ) + REAL ( 55 )955 tlcl = ( oneRK / denom ) + 55*oneRK956 957 END FUNCTION TLCL958 959 FUNCTION var_cape_afwa1D(nz, tk, rhv, p, hgt, sfc, cape, cin, zlfc, plfc, lidx, parcel) RESULT (ostat)960 ! Function to compute cape on a 1D column following implementation in phys/module_diag_afwa.F961 962 IMPLICIT NONE963 964 INTEGER, INTENT(in) :: nz, sfc965 REAL(r_k), DIMENSION(nz), INTENT(in) :: tk, rhv, p, hgt966 REAL(r_k), INTENT(out) :: cape, cin, zlfc, plfc, lidx967 INTEGER :: ostat968 INTEGER, INTENT(in) :: parcel969 970 ! Local971 !~ Derived profile variables972 ! -------------------------973 REAL(r_k), DIMENSION(nz) :: rh, ws, w, dTvK, buoy974 REAL(r_k) :: tlclK, plcl, nbuoy, pbuoy975 976 !~ Source parcel information977 ! -------------------------978 REAL(r_k) :: srctK, srcrh, srcws, srcw, srcp, &979 srctheta, srcthetaeK980 INTEGER :: srclev981 REAL(r_k) :: spdiff982 983 !~ Parcel variables984 ! ----------------985 REAL(r_k) :: ptK, ptvK, tvK, pw986 987 !~ Other utility variables988 ! -----------------------989 INTEGER :: i, j, k990 INTEGER :: lfclev991 INTEGER :: prcl992 INTEGER :: mlev993 INTEGER :: lyrcnt994 LOGICAL :: flag995 LOGICAL :: wflag996 REAL(r_k) :: freeze997 REAL(r_k) :: pdiff998 REAL(r_k) :: pm, pu, pd999 REAL(r_k) :: lidxu1000 REAL(r_k) :: lidxd1001 1002 REAL(r_k), PARAMETER :: Rd = r_d1003 REAL(r_k), PARAMETER :: RUNDEF = -9.999E301004 1005 !!!!!!! Variables1006 ! nz: Number of vertical levels1007 ! sfc: Surface level in the profile1008 ! tk: Temperature profile [K]1009 ! rhv: Relative Humidity profile [1]1010 ! rh: Relative Humidity profile [%]1011 ! p: Pressure profile [Pa]1012 ! hgt: Geopotential height profile [gpm]1013 ! cape: CAPE [Jkg-1]1014 ! cin: CIN [Jkg-1]1015 ! zlfc: LFC Height [gpm]1016 ! plfc: LFC Pressure [Pa]1017 ! lidx: Lifted index1018 ! FROM: https://en.wikipedia.org/wiki/Lifted_index1019 ! lidx >= 6: Very Stable Conditions1020 ! 6 > lidx > 1: Stable Conditions, Thunderstorms Not Likely1021 ! 0 > lidx > -2: Slightly Unstable, Thunderstorms Possible, With Lifting Mechanism (i.e., cold front, daytime heating, ...)1022 ! -2 > lidx > -6: Unstable, Thunderstorms Likely, Some Severe With Lifting Mechanism1023 ! -6 > lidx: Very Unstable, Severe Thunderstorms Likely With Lifting Mechanism1024 ! ostat: Function return status (Nonzero is bad)1025 ! parcel:1026 ! Most Unstable = 1 (default)1027 ! Mean layer = 21028 ! Surface based = 31029 !~ Derived profile variables1030 ! -------------------------1031 ! ws: Saturation mixing ratio1032 ! w: Mixing ratio1033 ! dTvK: Parcel / ambient Tv difference1034 ! buoy: Buoyancy1035 ! tlclK: LCL temperature [K]1036 ! plcl: LCL pressure [Pa]1037 ! nbuoy: Negative buoyancy1038 ! pbuoy: Positive buoyancy1039 1040 !~ Source parcel information1041 ! -------------------------1042 ! srctK: Source parcel temperature [K]1043 ! srcrh: Source parcel rh [%]1044 ! srcws: Source parcel sat. mixing ratio1045 ! srcw: Source parcel mixing ratio1046 ! srcp: Source parcel pressure [Pa]1047 ! srctheta: Source parcel theta [K]1048 ! srcthetaeK: Source parcel theta-e [K]1049 ! srclev: Level of the source parcel1050 ! spdiff: Pressure difference1051 1052 !~ Parcel variables1053 ! ----------------1054 ! ptK: Parcel temperature [K]1055 ! ptvK: Parcel virtual temperature [K]1056 ! tvK: Ambient virtual temperature [K]1057 ! pw: Parcel mixing ratio1058 1059 !~ Other utility variables1060 ! -----------------------1061 ! lfclev: Level of LFC1062 ! prcl: Internal parcel type indicator1063 ! mlev: Level for ML calculation1064 ! lyrcnt: Number of layers in mean layer1065 ! flag: Dummy flag1066 ! wflag: Saturation flag1067 ! freeze: Water loading multiplier1068 ! pdiff: Pressure difference between levs1069 ! pm, pu, pd: Middle, upper, lower pressures1070 ! lidxu: Lifted index at upper level1071 ! lidxd: Lifted index at lower level1072 1073 fname = 'var_cape_afwa'1074 1075 !~ Initialize variables1076 ! --------------------1077 rh = rhv*100.1078 ostat = 01079 CAPE = zeroRK1080 CIN = zeroRK1081 ZLFC = RUNDEF1082 PLFC = RUNDEF1083 1084 !~ Look for submitted parcel definition1085 !~ 1 = Most unstable1086 !~ 2 = Mean layer1087 !~ 3 = Surface based1088 ! -------------------------------------1089 IF ( parcel > 3 .or. parcel < 1 ) THEN1090 prcl = 11091 ELSE1092 prcl = parcel1093 END IF1094 1095 !~ Initalize our parcel to be (sort of) surface based. Because of1096 !~ issues we've been observing in the WRF model, specifically with1097 !~ excessive surface moisture values at the surface, using a true1098 !~ surface based parcel is resulting a more unstable environment1099 !~ than is actually occuring. To address this, our surface parcel1100 !~ is now going to be defined as the parcel between 25-50 hPa1101 !~ above the surface. UPDATE - now that this routine is in WRF,1102 !~ going to trust surface info. GAC 201404151103 ! ----------------------------------------------------------------1104 1105 !~ Compute mixing ratio values for the layer1106 ! -----------------------------------------1107 DO k = sfc, nz1108 ws ( k ) = SaturationMixingRatio ( tK(k), p(k) )1109 w ( k ) = ( rh(k)/100.0 ) * ws ( k )1110 END DO1111 1112 srclev = sfc1113 srctK = tK ( sfc )1114 srcrh = rh ( sfc )1115 srcp = p ( sfc )1116 srcws = ws ( sfc )1117 srcw = w ( sfc )1118 srctheta = Theta ( tK(sfc), p(sfc)/100.0 )1119 1120 !~ Compute the profile mixing ratio. If the parcel is the MU parcel,1121 !~ define our parcel to be the most unstable parcel within the lowest1122 !~ 180 mb.1123 ! -------------------------------------------------------------------1124 mlev = sfc + 11125 DO k = sfc + 1, nz1126 1127 !~ Identify the last layer within 100 hPa of the surface1128 ! -----------------------------------------------------1129 pdiff = ( p (sfc) - p (k) ) / REAL ( 100 )1130 IF ( pdiff <= REAL (100) ) mlev = k1131 1132 !~ If we've made it past the lowest 180 hPa, exit the loop1133 ! -------------------------------------------------------1134 IF ( pdiff >= REAL (180) ) EXIT1135 1136 IF ( prcl == 1 ) THEN1137 !IF ( (p(k) > 70000.0) .and. (w(k) > srcw) ) THEN1138 IF ( (w(k) > srcw) ) THEN1139 srctheta = Theta ( tK(k), p(k)/100.0 )1140 srcw = w ( k )1141 srclev = k1142 srctK = tK ( k )1143 srcrh = rh ( k )1144 srcp = p ( k )1145 END IF1146 END IF1147 1148 END DO1149 1150 !~ If we want the mean layer parcel, compute the mean values in the1151 !~ lowest 100 hPa.1152 ! ----------------------------------------------------------------1153 lyrcnt = mlev - sfc + 11154 IF ( prcl == 2 ) THEN1155 1156 srclev = sfc1157 srctK = SUM ( tK (sfc:mlev) ) / REAL ( lyrcnt )1158 srcw = SUM ( w (sfc:mlev) ) / REAL ( lyrcnt )1159 srcrh = SUM ( rh (sfc:mlev) ) / REAL ( lyrcnt )1160 srcp = SUM ( p (sfc:mlev) ) / REAL ( lyrcnt )1161 srctheta = Theta ( srctK, srcp/100. )1162 1163 END IF1164 1165 srcthetaeK = Thetae ( srctK, srcp/100.0, srcrh, srcw )1166 1167 !~ Calculate temperature and pressure of the LCL1168 ! ---------------------------------------------1169 tlclK = TLCL ( tK(srclev), rh(srclev) )1170 plcl = p(srclev) * ( (tlclK/tK(srclev))**(Cp/Rd) )1171 1172 !~ Now lift the parcel1173 ! -------------------1174 1175 buoy = REAL ( 0 )1176 pw = srcw1177 wflag = .false.1178 DO k = srclev, nz1179 IF ( p (k) <= plcl ) THEN1180 1181 !~ The first level after we pass the LCL, we're still going to1182 !~ lift the parcel dry adiabatically, as we haven't added the1183 !~ the required code to switch between the dry adiabatic and moist1184 !~ adiabatic cooling. Since the dry version results in a greater1185 !~ temperature loss, doing that for the first step so we don't over1186 !~ guesstimate the instability.1187 ! ----------------------------------------------------------------1188 1189 IF ( wflag ) THEN1190 flag = .false.1191 1192 !~ Above the LCL, our parcel is now undergoing moist adiabatic1193 !~ cooling. Because of the latent heating being undergone as1194 !~ the parcel rises above the LFC, must iterative solve for the1195 !~ parcel temperature using equivalant potential temperature,1196 !~ which is conserved during both dry adiabatic and1197 !~ pseudoadiabatic displacements.1198 ! --------------------------------------------------------------1199 ptK = The2T ( srcthetaeK, p(k), flag )1200 1201 !~ Calculate the parcel mixing ratio, which is now changing1202 !~ as we condense moisture out of the parcel, and is equivalent1203 !~ to the saturation mixing ratio, since we are, in theory, at1204 !~ saturation.1205 ! ------------------------------------------------------------1206 pw = SaturationMixingRatio ( ptK, p(k) )1207 1208 !~ Now we can calculate the virtual temperature of the parcel1209 !~ and the surrounding environment to assess the buoyancy.1210 ! ----------------------------------------------------------1211 ptvK = VirtualTemperature ( ptK, pw )1212 tvK = VirtualTemperature ( tK (k), w (k) )1213 1214 !~ Modification to account for water loading1215 ! -----------------------------------------1216 freeze = 0.033 * ( 263.15 - pTvK )1217 IF ( freeze > 1.0 ) freeze = 1.01218 IF ( freeze < 0.0 ) freeze = 0.01219 1220 !~ Approximate how much of the water vapor has condensed out1221 !~ of the parcel at this level1222 ! ---------------------------------------------------------1223 freeze = freeze * 333700.0 * ( srcw - pw ) / 1005.71224 1225 pTvK = pTvK - pTvK * ( srcw - pw ) + freeze1226 dTvK ( k ) = ptvK - tvK1227 buoy ( k ) = g * ( dTvK ( k ) / tvK )1228 1229 ELSE1230 1231 !~ Since the theta remains constant whilst undergoing dry1232 !~ adiabatic processes, can back out the parcel temperature1233 !~ from potential temperature below the LCL1234 ! --------------------------------------------------------1235 ptK = srctheta / ( 100000.0/p(k) )**(Rd/Cp)1236 1237 !~ Grab the parcel virtual temperture, can use the source1238 !~ mixing ratio since we are undergoing dry adiabatic cooling1239 ! ----------------------------------------------------------1240 ptvK = VirtualTemperature ( ptK, srcw )1241 1242 !~ Virtual temperature of the environment1243 ! --------------------------------------1244 tvK = VirtualTemperature ( tK (k), w (k) )1245 1246 !~ Buoyancy at this level1247 ! ----------------------1248 dTvK ( k ) = ptvK - tvK1249 buoy ( k ) = g * ( dtvK ( k ) / tvK )1250 1251 wflag = .true.1252 1253 END IF1254 1255 ELSE1256 1257 !~ Since the theta remains constant whilst undergoing dry1258 !~ adiabatic processes, can back out the parcel temperature1259 !~ from potential temperature below the LCL1260 ! --------------------------------------------------------1261 ptK = srctheta / ( 100000.0/p(k) )**(Rd/Cp)1262 1263 !~ Grab the parcel virtual temperture, can use the source1264 !~ mixing ratio since we are undergoing dry adiabatic cooling1265 ! ----------------------------------------------------------1266 ptvK = VirtualTemperature ( ptK, srcw )1267 1268 !~ Virtual temperature of the environment1269 ! --------------------------------------1270 tvK = VirtualTemperature ( tK (k), w (k) )1271 1272 !~ Buoyancy at this level1273 ! ---------------------1274 dTvK ( k ) = ptvK - tvK1275 buoy ( k ) = g * ( dtvK ( k ) / tvK )1276 1277 END IF1278 1279 !~ Chirp1280 ! -----1281 ! WRITE ( *,'(I15,6F15.3)' )k,p(k)/100.,ptK,pw*1000.,ptvK,tvK,buoy(k)1282 1283 END DO1284 1285 !~ Add up the buoyancies, find the LFC1286 ! -----------------------------------1287 flag = .false.1288 lfclev = -11289 nbuoy = REAL ( 0 )1290 pbuoy = REAL ( 0 )1291 DO k = sfc + 1, nz1292 IF ( tK (k) < 253.15 ) EXIT1293 CAPE = CAPE + MAX ( buoy (k), 0.0 ) * ( hgt (k) - hgt (k-1) )1294 CIN = CIN + MIN ( buoy (k), 0.0 ) * ( hgt (k) - hgt (k-1) )1295 1296 !~ If we've already passed the LFC1297 ! -------------------------------1298 IF ( flag .and. buoy (k) > REAL (0) ) THEN1299 pbuoy = pbuoy + buoy (k)1300 END IF1301 1302 !~ We are buoyant now - passed the LFC1303 ! -----------------------------------1304 IF ( .not. flag .and. buoy (k) > REAL (0) .and. p (k) < plcl ) THEN1305 flag = .true.1306 pbuoy = pbuoy + buoy (k)1307 lfclev = k1308 END IF1309 1310 !~ If we think we've passed the LFC, but encounter a negative layer1311 !~ start adding it up.1312 ! ----------------------------------------------------------------1313 IF ( flag .and. buoy (k) < REAL (0) ) THEN1314 nbuoy = nbuoy + buoy (k)1315 1316 !~ If the accumulated negative buoyancy is greater than the1317 !~ positive buoyancy, then we are capped off. Got to go higher1318 !~ to find the LFC. Reset positive and negative buoyancy summations1319 ! ----------------------------------------------------------------1320 IF ( ABS (nbuoy) > pbuoy ) THEN1321 flag = .false.1322 nbuoy = REAL ( 0 )1323 pbuoy = REAL ( 0 )1324 lfclev = -11325 END IF1326 END IF1327 1328 END DO1329 1330 !~ Calculate lifted index by interpolating difference between1331 !~ parcel and ambient Tv to 500mb.1332 ! ----------------------------------------------------------1333 DO k = sfc + 1, nz1334 1335 pm = 50000.1336 pu = p ( k )1337 pd = p ( k - 1 )1338 1339 !~ If we're already above 500mb just set lifted index to 0.1340 !~ --------------------------------------------------------1341 IF ( pd .le. pm ) THEN1342 lidx = zeroRK1343 EXIT1344 1345 ELSEIF ( pu .le. pm .and. pd .gt. pm) THEN1346 1347 !~ Found trapping pressure: up, middle, down.1348 !~ We are doing first order interpolation.1349 ! ------------------------------------------1350 lidxu = -dTvK ( k ) * ( pu / 100000. ) ** (Rd/Cp)1351 lidxd = -dTvK ( k-1 ) * ( pd / 100000. ) ** (Rd/Cp)1352 lidx = ( lidxu * (pm-pd) + lidxd * (pu-pm) ) / (pu-pd)1353 EXIT1354 1355 ENDIF1356 1357 END DO1358 1359 !~ Assuming the the LFC is at a pressure level for now1360 ! ---------------------------------------------------1361 IF ( lfclev > zeroRK ) THEN1362 PLFC = p ( lfclev )1363 ZLFC = hgt ( lfclev )1364 END IF1365 1366 IF ( PLFC /= PLFC .OR. PLFC < zeroRK ) THEN1367 PLFC = -oneRK1368 ZLFC = -oneRK1369 END IF1370 1371 IF ( CAPE /= CAPE ) cape = zeroRK1372 1373 IF ( CIN /= CIN ) cin = zeroRK1374 1375 !~ Chirp1376 ! -----1377 ! WRITE ( *,* ) ' CAPE: ', cape, ' CIN: ', cin1378 ! WRITE ( *,* ) ' LFC: ', ZLFC, ' PLFC: ', PLFC1379 ! WRITE ( *,* ) ''1380 ! WRITE ( *,* ) ' Exiting buoyancy.'1381 ! WRITE ( *,* ) ' ==================================== '1382 ! WRITE ( *,* ) ''1383 1384 RETURN1385 1386 END FUNCTION var_cape_afwa1D1387 1388 ! ---- END modified from module_diag_afwa.F ---- !1389 551 1390 552 SUBROUTINE compute_cape_afwa4D(ta, hur, press, zg, hgt, cape, cin, zlfc, plfc, li, parcelmethod, &
Note: See TracChangeset
for help on using the changeset viewer.