Changeset 899 in lmdz_wrf
- Timestamp:
- Jun 19, 2016, 2:48:04 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/module_ForInterpolate.F90
r768 r899 1 ! Module to interpolate values from a giving projection 1 ! Module to interpolate values from a giving projection and pressure interpolation 2 2 ! To be included in a python 3 ! f2py -m module_ForInterpolate --f90exec=/usr/bin/gfortran-4.7 -c module_ ForInterpolate.F90 module_generic.F90>& run_f2py.log3 ! f2py -m module_ForInterpolate --f90exec=/usr/bin/gfortran-4.7 -c module_generic.F90 module_ForInterpolate.F90 >& run_f2py.log 4 4 MODULE module_ForInterpolate 5 5 … … 922 922 END SUBROUTINE Interpolate1DLl 923 923 924 925 SUBROUTINE interp (data_out, data_in, pres_field, interp_levels, psfc, ter, tk, qv, ix, iy, iz, it, & 926 num_metgrid_levels, LINLOG, extrapolate, GEOPT, MISSING) 927 ! Interpolation subroutine from the p_interp.F90 NCAR program 928 ! Program to read wrfout data and interpolate to pressure levels 929 ! The program reads namelist.pinterp 930 ! November 2007 - Cindy Bruyere 931 ! 932 INTEGER :: ix, iy, iz, it 933 INTEGER :: num_metgrid_levels, LINLOG 934 REAL, DIMENSION(ix, iy, num_metgrid_levels, it) :: data_out 935 REAL, DIMENSION(ix, iy, iz, it) :: data_in, pres_field, tk, qv 936 REAL, DIMENSION(ix, iy, it) :: psfc 937 REAL, DIMENSION(ix, iy) :: ter 938 REAL, DIMENSION(num_metgrid_levels) :: interp_levels 939 940 INTEGER :: i, j, itt, k, kk, kin 941 REAL, DIMENSION(num_metgrid_levels) :: data_out1D 942 REAL, DIMENSION(iz) :: data_in1D, pres_field1D 943 INTEGER :: extrapolate 944 REAL :: MISSING 945 REAL, DIMENSION(ix, iy, num_metgrid_levels, it) :: N 946 REAL :: sumA, sumN, AVE_geopt 947 LOGICAL :: GEOPT 948 949 !!!!!!! Variables 950 ! data_out: interpolated field 951 ! data_in: field to interpolate 952 ! pres_field: pressure field [Pa] 953 ! interp_levels: pressure levels to interpolate [hPa] 954 ! psfc: surface pressure [Pa] 955 ! ter: terrein height [m] 956 ! tk: temperature [K] 957 ! qv: mositure mizing ratio [kg/kg] 958 ! i[x/y/z/t]: size of the matrices 959 ! num_metgrid_levels: number of pressure values to interpolate 960 ! LINLOG: if abs(linlog)=1 use linear interp in pressure 961 ! if abs(linlog)=2 linear interp in ln(pressure) 962 ! extrapolate: whether to set to missing value below/above model ground and top (0), or extrapolate (1) 963 ! GEOPT: Wether the file is the geopotential file or not 964 ! MISSING: Missing value 965 966 N = 1.0 967 968 expon=287.04*.0065/9.81 969 970 do itt = 1, it 971 do j = 1, iy 972 do i = 1, ix 973 data_in1D(:) = data_in(i,j,:,itt) 974 pres_field1D(:) = pres_field(i,j,:,itt) 975 CALL int1D (data_out1D, data_in1D, pres_field1D, interp_levels, iz, num_metgrid_levels, LINLOG, MISSING) 976 data_out(i,j,:,itt) = data_out1D(:) 977 end do 978 end do 979 end do 980 981 982 ! Fill in missing values 983 IF ( extrapolate == 0 ) RETURN !! no extrapolation - we are out of here 984 985 ! First find where about 400 hPa is located 986 kk = 0 987 find_kk : do k = 1, num_metgrid_levels 988 kk = k 989 if ( interp_levels(k) <= 40000. ) exit find_kk 990 end do find_kk 991 992 993 IF ( GEOPT ) THEN !! geopt is treated different below ground 994 995 do itt = 1, it 996 do k = 1, kk 997 do j = 1, iy 998 do i = 1, ix 999 IF ( data_out(i,j,k,itt) == MISSING .AND. interp_levels(k) < psfc(i,j,itt) ) THEN 1000 1001 ! We are below the first model level, but above the ground 1002 1003 data_out(i,j,k,itt) = ((interp_levels(k) - pres_field(i,j,1,itt))*ter(i,j)*9.81 + & 1004 (psfc(i,j,itt) - interp_levels(k))*data_in(i,j,1,itt) ) / & 1005 (psfc(i,j,itt) - pres_field(i,j,1,itt)) 1006 1007 ELSEIF ( data_out(i,j,k,itt) == MISSING ) THEN 1008 1009 ! We are below both the ground and the lowest data level. 1010 1011 ! First, find the model level that is closest to a "target" pressure 1012 ! level, where the "target" pressure is delta-p less that the local 1013 ! value of a horizontally smoothed surface pressure field. We use 1014 ! delta-p = 150 hPa here. A standard lapse rate temperature profile 1015 ! passing through the temperature at this model level will be used 1016 ! to define the temperature profile below ground. This is similar 1017 ! to the Benjamin and Miller (1990) method, except that for 1018 ! simplicity, they used 700 hPa everywhere for the "target" pressure. 1019 ! Code similar to what is implemented in RIP4 1020 1021 ptarget = (psfc(i,j,itt)*.01) - 150. 1022 dpmin=1.e4 1023 kupper = 0 1024 loop_kIN : do kin=iz,1,-1 1025 kupper = kin 1026 dp=abs( (pres_field(i,j,kin,itt)*.01) - ptarget ) 1027 if (dp.gt.dpmin) exit loop_kIN 1028 dpmin=min(dpmin,dp) 1029 enddo loop_kIN 1030 1031 pbot=max(pres_field(i,j,1,itt),psfc(i,j,itt)) 1032 zbot=min(data_in(i,j,1,itt)/9.81,ter(i,j)) 1033 1034 tbotextrap=tk(i,j,kupper,itt)*(pbot/pres_field(i,j,kupper,itt))**expon 1035 tvbotextrap=virtual(tbotextrap,qv(i,j,1,itt)) 1036 1037 data_out(i,j,k,itt) = (zbot+tvbotextrap/.0065*(1.-(interp_levels(k)/pbot)**expon))*9.81 1038 1039 ENDIF 1040 enddo 1041 enddo 1042 enddo 1043 enddo 1044 1045 1046 !!! Code for filling missing data with an average - we don't want to do this 1047 !!do itt = 1, it 1048 !!loop_levels : do k = 1, num_metgrid_levels 1049 !!sumA = SUM(data_out(:,:,k,itt), MASK = data_out(:,:,k,itt) /= MISSING) 1050 !!sumN = SUM(N(:,:,k,itt), MASK = data_out(:,:,k,itt) /= MISSING) 1051 !!IF ( sumN == 0. ) CYCLE loop_levels 1052 !!AVE_geopt = sumA/sumN 1053 !!WHERE ( data_out(:,:,k,itt) == MISSING ) 1054 !!data_out(:,:,k,itt) = AVE_geopt 1055 !!END WHERE 1056 !!end do loop_levels 1057 !!end do 1058 1059 END IF 1060 1061 !!! All other fields and geopt at higher levels come here 1062 do itt = 1, it 1063 do j = 1, iy 1064 do i = 1, ix 1065 do k = 1, kk 1066 if ( data_out(i,j,k,itt) == MISSING ) data_out(i,j,k,itt) = data_in(i,j,1,itt) 1067 end do 1068 do k = kk+1, num_metgrid_levels 1069 if ( data_out(i,j,k,itt) == MISSING ) data_out(i,j,k,itt) = data_in(i,j,iz,itt) 1070 end do 1071 end do 1072 end do 1073 end do 1074 1075 END SUBROUTINE interp 1076 1077 SUBROUTINE int1D(xxout, xxin, ppin, ppout, npin, npout, LINLOG, MISSING) 1078 1079 ! Modified from int2p - NCL code 1080 ! routine to interpolate from one set of pressure levels 1081 ! . to another set using linear or ln(p) interpolation 1082 ! 1083 ! NCL: xout = int2p (pin,xin,pout,linlog) 1084 ! This code was originally written for a specific purpose. 1085 ! . Several features were added for incorporation into NCL's 1086 ! . function suite including linear extrapolation. 1087 ! 1088 ! nomenclature: 1089 ! 1090 ! . ppin - input pressure levels. The pin can be 1091 ! . be in ascending or descending order 1092 ! . xxin - data at corresponding input pressure levels 1093 ! . npin - number of input pressure levels >= 2 1094 ! . ppout - output pressure levels (input by user) 1095 ! . same (ascending or descending) order as pin 1096 ! . xxout - data at corresponding output pressure levels 1097 ! . npout - number of output pressure levels 1098 ! . linlog - if abs(linlog)=1 use linear interp in pressure 1099 ! . if abs(linlog)=2 linear interp in ln(pressure) 1100 ! . missing- missing data code. 1101 1102 ! ! input types 1103 INTEGER :: npin,npout,linlog,ier 1104 real :: ppin(npin),xxin(npin),ppout(npout) 1105 real :: MISSING 1106 logical :: AVERAGE 1107 ! ! output 1108 real :: xxout(npout) 1109 INTEGER :: j1,np,nl,nin,nlmax,nplvl 1110 INTEGER :: nlsave,np1,no1,n1,n2,nlstrt 1111 real :: slope,pa,pb,pc 1112 1113 ! automatic arrays 1114 real :: pin(npin),xin(npin),p(npin),x(npin) 1115 real :: pout(npout),xout(npout) 1116 1117 1118 xxout = MISSING 1119 pout = ppout 1120 p = ppin 1121 x = xxin 1122 nlmax = npin 1123 1124 ! exact p-level matches 1125 nlstrt = 1 1126 nlsave = 1 1127 do np = 1,npout 1128 xout(np) = MISSING 1129 do nl = nlstrt,nlmax 1130 if (pout(np).eq.p(nl)) then 1131 xout(np) = x(nl) 1132 nlsave = nl + 1 1133 go to 10 1134 end if 1135 end do 1136 10 nlstrt = nlsave 1137 end do 1138 1139 if (LINLOG.eq.1) then 1140 do np = 1,npout 1141 do nl = 1,nlmax - 1 1142 if (pout(np).lt.p(nl) .and. pout(np).gt.p(nl+1)) then 1143 slope = (x(nl)-x(nl+1))/ (p(nl)-p(nl+1)) 1144 xout(np) = x(nl+1) + slope* (pout(np)-p(nl+1)) 1145 end if 1146 end do 1147 end do 1148 elseif (LINLOG.eq.2) then 1149 do np = 1,npout 1150 do nl = 1,nlmax - 1 1151 if (pout(np).lt.p(nl) .and. pout(np).gt.p(nl+1)) then 1152 pa = log(p(nl)) 1153 pb = log(pout(np)) 1154 ! special case: in case someone inadvertently enter p=0. 1155 if (p(nl+1).gt.0.d0) then 1156 pc = log(p(nl+1)) 1157 else 1158 pc = log(1.d-4) 1159 end if 1160 1161 slope = (x(nl)-x(nl+1))/ (pa-pc) 1162 xout(np) = x(nl+1) + slope* (pb-pc) 1163 end if 1164 end do 1165 end do 1166 end if 1167 1168 1169 ! place results in the return array; 1170 xxout = xout 1171 1172 END SUBROUTINE int1D 1173 924 1174 END MODULE module_ForInterpolate
Note: See TracChangeset
for help on using the changeset viewer.