Changeset 899 in lmdz_wrf


Ignore:
Timestamp:
Jun 19, 2016, 2:48:04 PM (9 years ago)
Author:
lfita
Message:

Adding `p_interp.F90' vertical presssure interpolation from C. Bruyere NCAR

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
    22! 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.log
     3! f2py -m module_ForInterpolate --f90exec=/usr/bin/gfortran-4.7 -c module_generic.F90 module_ForInterpolate.F90 >& run_f2py.log
    44MODULE module_ForInterpolate
    55
     
    922922END SUBROUTINE Interpolate1DLl
    923923
     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
    9241174END MODULE module_ForInterpolate
Note: See TracChangeset for help on using the changeset viewer.