The subroutine vertInterpolation_pressKappa
performs a linear vertical
interpolation from pressure levels to model levels in the pressure kappa
formulation. It is assumed that we have a top to bottom ordering of
the vertical levels.
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
type(ESMF_Field), | intent(inout) | :: | fModel | |||
type(ESMF_Field), | intent(inout) | :: | fPres | |||
type(ESMF_Field), | intent(inout) | :: | ps | |||
real, | intent(in) | :: | plevs(:) |
pressure levels |
||
real, | intent(in) | :: | undef |
undefined value |
||
type(ESMF_Field), | intent(inout), | optional | :: | PHIS |
Surface Geopotential Heights |
|
character(len=*), | intent(in), | optional | :: | phis_units |
units of phis |
|
integer, | intent(out), | optional | :: | rc |
subroutine vertInterpolation_pressKappa (fModel, fPres, ps, plevs, & undef, phis, phis_units, rc) ! type(ESMF_Field), intent(INOUT) :: fModel type(ESMF_Field), intent(INOUT) :: fPres type(ESMF_Field), intent(INOUT) :: ps real, intent(IN) :: plevs(:) !! pressure levels real, intent(IN) :: undef !! undefined value type(ESMF_Field), optional, intent(INOUT) :: PHIS !! Surface Geopotential Heights character(len=*), optional, intent(in) :: phis_units !! units of phis integer, optional, intent(OUT) :: rc ! integer :: im, jm, lmMod, lmPres integer :: i, j, L, k, k2, k3, dims(3) integer, allocatable :: kbeg(:,:),kend(:,:) real :: vdef, vsurf, TH real,allocatable :: pl_mod(:,:,:),ple_mod(:,:,:) character(len=1) :: vartype real(REAL64), allocatable :: ak(:),bk(:) integer :: status real :: gfactor type(ESMF_Grid) :: grid real, pointer :: vMod(:,:,:), vPres(:,:,:), vPS(:,:), vPHIS(:,:) character(ESMF_MAXSTR) :: vname, units ! !------------------------------------------------------------------------------ ! get dimensions, allocate call ESMF_FieldGet(fModel,grid=grid,rc=status) _VERIFY(STATUS) call ESMF_AttributeGet(fModel,name='UNITS',value=units,rc=status) _VERIFY(STATUS) call ESMF_AttributeGet(fModel,name='LONG_NAME',value=vname,rc=status) _VERIFY(STATUS) vname = ESMF_UtilStringLowerCase(vname,rc=status) call MAPL_GridGet(grid, localCellCountPerDim=dims,rc=status) _VERIFY(STATUS) im = dims(1) jm = dims(2) lmMod = dims(3) allocate(ak(lmMod+1),stat=status) _VERIFY(STATUS) allocate(bk(lmMod+1),stat=status) _VERIFY(STATUS) allocate(pl_mod(im,jm,lmMod),stat=status) _VERIFY(STATUS) allocate(ple_mod(im,jm,lmMod+1),stat=status) _VERIFY(STATUS) allocate(kbeg(im,jm),stat=status) _VERIFY(STATUS) allocate(kend(im,jm),stat=status) _VERIFY(STATUS) call ESMF_FieldGet(fPres,grid=grid,rc=status) _VERIFY(STATUS) call MAPL_GridGet(grid, localCellCountPerDim=dims,rc=status) _VERIFY(STATUS) lmPres = dims(3) ! given PS, get AK, BK from the grid to get ple call ESMF_FieldGet(PS,0,farrayPtr=vPS,rc=status) _VERIFY(STATUS) call ESMF_FieldGet(PS,grid=grid,rc=status) _VERIFY(STATUS) call ESMF_AttributeGet(grid,name="GridAK",valuelist=ak,rc=status) _VERIFY(STATUS) call ESMF_AttributeGet(grid,name="GridBK",valuelist=bk,rc=status) _VERIFY(STATUS) do i=1,lmmod+1 ple_mod(:,:,i)=ak(i)+bk(i)*vPS(:,:) enddo do i=1,lmmod pl_mod(:,:,i)=(ple_mod(:,:,i)+ple_mod(:,:,i+1))/2.0 enddo call ESMF_FieldGet(fModel,0,farrayPtr=vMod,rc=status) _VERIFY(STATUS) call ESMF_FieldGet(fPres,0,farrayPtr=vPres,rc=status) _VERIFY(STATUS) !--------------------------------------------------------------- ! For each grid point (i,j), determine the range of model levels ! (kbeg to kend) that will be used for the main interpolation ! formula. !--------------------------------------------------------------- call searchVerticalLocations(pl_mod, plevs, kbeg, kend, im, jm, lmmod, lmpres) !------------------------------- ! Compute trapped interpolations !------------------------------- DO j = 1, jm DO i = 1, im DO L = kbeg(i,j), kend(i,j) SEARCH_LEVELS : DO k = 2, lmpres IF (plevs(k) .GE. pl_mod(i,j,L) .AND. & plevs(k-1) .LT. pl_mod(i,j,L) ) THEN IF ( (vpres(i,j,k) .NE. undef) .AND. (vpres(i,j,k-1) .NE. undef) ) THEN ! Apply the pressure to the kappa linear interpolation vmod(i,j,L) = interpVal(vpres(i,j,k), vpres(i,j,k-1), pl_mod(i,j,L), & plevs(k), plevs(k-1), MAPL_KAPPA) ELSEIF ( (vpres(i,j,k) .NE. undef) .AND. (vpres(i,j,k-1) .EQ. undef) ) THEN vmod(i,j,L) = vpres(i,j,k) ELSEIF ( (vpres(i,j,k) .EQ. undef) .AND. (vpres(i,j,k-1) .NE. undef) ) THEN vmod(i,j,L) = vpres(i,j,k-1) ELSEIF ( (vpres(i,j,k) .EQ. undef) .AND. (vpres(i,j,k-1) .EQ. undef) ) THEN ! Search for the first non undefined value vdef = undef ! First: search by going toward the surface SEARCH_DEF3: DO k3 = k+1,lmpres IF (vpres(i,j,k3) .NE. undef) THEN vdef = vpres(i,j,k3) EXIT SEARCH_DEF3 END IF END DO SEARCH_DEF3 IF (vdef .EQ. undef) THEN ! Second: search by going toward the top SEARCH_DEF4: DO k3 = k-2, 1, -1 IF (vpres(i,j,k3) .NE. undef) THEN vdef = vpres(i,j,k3) EXIT SEARCH_DEF4 END IF END DO SEARCH_DEF4 END IF if (vdef == undef) then _RETURN(ESMF_FAILURE) end if vmod(i,j,L) = vdef END IF EXIT SEARCH_LEVELS END IF ENDDO SEARCH_LEVELS ENDDO ENDDO ENDDO !-------------------------------------- ! Do extrapolation on levels below kbeg ! (toward the top of the atmosphere) !-------------------------------------- DO j = 1, jm DO i = 1, im vdef = vpres(i,j,1) IF (vdef .EQ. undef) THEN ! Search for the first non undefined value SEARCH_DEF1: DO k = 2, lmpres IF (vpres(i,j,k) .NE. undef) THEN vdef = vpres(i,j,k) EXIT SEARCH_DEF1 END IF END DO SEARCH_DEF1 END IF DO L = 1, kbeg(i,j) -1 vmod(i,j,L) = vdef ENDDO ENDDO ENDDO !-------------------------------------- ! Do extrapolation on levels above kend ! (toward the surface) get var type !-------------------------------------- ! = 'W' for winds ( U & V) ! = 'T' for temperature ! = 'H' for height ! = 'O' for any other variable if (index(vname,"wind")/=0) then varType = 'W' else if (index(vname,"temperature")/=0) then varType = 'T' else if (index(vname,"height")/=0) then varType = 'H' _ASSERT(present(PHIS),'needs informative message') call ESMF_FieldGet(PHIS,0,farrayPtr=vPHIS,rc=status) _VERIFY(STATUS) _ASSERT(present(phis_units),'needs informative message') if (trim(units)=="m" .and. trim(phis_units)=="m+2 s-2") then gfactor = MAPL_GRAV else gfactor = 1.0 end if else varType = 'O' end if DO j = 1, jm DO i = 1, im vdef = vpres(i,j,lmpres) IF (vdef .EQ. undef) THEN ! Search for the first non undefined value SEARCH_DEF2: DO k2 = lmpres-1, 1, -1 IF (vpres(i,j,k2) .NE. undef) THEN vdef = vpres(i,j,k2) EXIT SEARCH_DEF2 END IF END DO SEARCH_DEF2 DO L = kend(i,j)+1, lmmod IF (varType .EQ. 'W') THEN vsurf = 0.0 vmod(i,j,L) = interpVal(vsurf, vdef, pl_mod(i,j,L), & plevs(lmpres), plevs(k2), MAPL_KAPPA) !vmod(i,j,L) = interpVal(vdef, vsurf, pl_mod(i,j,L), & ! plevs(k2), plevs(lmpres), MAPL_KAPPA) ELSE IF (varType .EQ. 'T') THEN ! Compute the potential temperature at pressure level k2 TH = vdef / ( (plevs(k2)*1.00E-05)**(MAPL_RGAS/MAPL_CP) ) ! Reverse back to the temperature at model level L vmod(i,j,L) = TH * ( (pl_mod(i,j,L)*1.00E-05)**(MAPL_RGAS/MAPL_CP) ) ELSE IF (varType .EQ. 'H') THEN vsurf = vPHIS(i,j)/gfactor vmod(i,j,L) = interpVal(vsurf, vdef, pl_mod(i,j,L), & plevs(lmpres), plevs(k2), MAPL_KAPPA) ELSE vmod(i,j,L) = vdef END IF ENDDO ELSE DO L = kend(i,j)+1, lmmod vmod(i,j,L) = vpres(i,j,lmpres) ENDDO END IF ENDDO ENDDO deallocate(ak) deallocate(bk) deallocate(pl_mod) deallocate(ple_mod) deallocate(kbeg) deallocate(kend) _RETURN(ESMF_SUCCESS) end subroutine vertInterpolation_pressKappa