! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE build_wrf_grid ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE build_wrf_grid(nx_wrf,ny_wrf,nxlg_wrf,nylg_wrf,dx_wrf,dy_wrf,&,24 mapproj_wrf,sclfct_wrf,lattru_wrf,lontru_wrf, & ctrlat_wrf,ctrlon_wrf,swx_wrf,swy_wrf, & lat_wrf,lon_wrf,lat_ll,lat_ul,lat_ur,lat_lr, & lon_ll,lon_ul,lon_ur,lon_lr,istatus) !----------------------------------------------------------------------- ! ! PURPOSE: ! ! Set up WRF mapprojection and get lat/lon of the WRF grid points. ! ! Get lat/lon at the four corners of the WRF domain. After the call ! Only processor 0 has valid lat/lon at corners. ! !----------------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: nx_wrf, ny_wrf INTEGER, INTENT(IN) :: nxlg_wrf, nylg_wrf REAL, INTENT(IN) :: dx_wrf, dy_wrf INTEGER, INTENT(IN) :: mapproj_wrf REAL, INTENT(INOUT):: sclfct_wrf REAL, INTENT(IN) :: lattru_wrf(2),lontru_wrf REAL, INTENT(IN) :: ctrlat_wrf,ctrlon_wrf REAL, INTENT(OUT) :: swx_wrf,swy_wrf REAL, INTENT(OUT) :: lat_wrf(nx_wrf,ny_wrf,3) REAL, INTENT(OUT) :: lon_wrf(nx_wrf,ny_wrf,3) REAL, INTENT(OUT) :: lat_ll(4), lon_ll(4) REAL, INTENT(OUT) :: lat_ul(4), lon_ul(4) REAL, INTENT(OUT) :: lat_ur(4), lon_ur(4) REAL, INTENT(OUT) :: lat_lr(4), lon_lr(4) INTEGER, INTENT(OUT) :: istatus !----------------------------------------------------------------------- ! ! Misc. local variables ! !----------------------------------------------------------------------- INTEGER :: i, j REAL :: sclf_wrf REAL :: dx_wrfscl, dy_wrfscl REAL :: ctrx, ctry REAL :: xsub0, ysub0 INTEGER :: mptag, source INTEGER, PARAMETER :: fzone_wrf = 1 REAL, ALLOCATABLE :: x_wrf(:), y_wrf(:) REAL, ALLOCATABLE :: xs_wrf(:), ys_wrf(:) INCLUDE 'mp.inc' !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Begin of executable code ... ... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IF( sclfct_wrf /= 1.0) THEN sclf_wrf = 1.0/sclfct_wrf dx_wrfscl = dx_wrf*sclf_wrf dy_wrfscl = dy_wrf*sclf_wrf ELSE sclf_wrf = 1.0 dx_wrfscl = dx_wrf dy_wrfscl = dy_wrf END IF sclfct_wrf = sclf_wrf CALL setmapr(mapproj_wrf,sclf_wrf,lattru_wrf,lontru_wrf) CALL lltoxy( 1,1, ctrlat_wrf,ctrlon_wrf, ctrx, ctry ) swx_wrf = ctrx - 0.5*(nxlg_wrf-1) * dx_wrfscl swy_wrf = ctry - 0.5*(nylg_wrf-1) * dy_wrfscl CALL setorig( 1, swx_wrf, swy_wrf) xsub0 = dx_wrf * (nx_wrf-fzone_wrf) * (loc_x-1) ysub0 = dy_wrf * (ny_wrf-fzone_wrf) * (loc_y-1) !----------------------------------------------------------------------- ! ! Assign WRF grid arrays ! !----------------------------------------------------------------------- ALLOCATE(x_wrf (nx_wrf), STAT = istatus) ALLOCATE(y_wrf (ny_wrf), STAT = istatus) ALLOCATE(xs_wrf(nx_wrf), STAT = istatus) ALLOCATE(ys_wrf(ny_wrf), STAT = istatus) DO i=1,nx_wrf x_wrf(i)= sclf_wrf*xsub0 + (i-1)*dx_wrfscl END DO DO j=1,ny_wrf y_wrf(j)= sclf_wrf*ysub0 + (j-1)*dy_wrfscl END DO DO i=1,nx_wrf-1 xs_wrf(i)=0.5*(x_wrf(i)+x_wrf(i+1)) END DO xs_wrf(nx_wrf)=2.*xs_wrf(nx_wrf-1)-xs_wrf(nx_wrf-2) DO j=1,ny_wrf-1 ys_wrf(j)=0.5*(y_wrf(j)+y_wrf(j+1)) END DO ys_wrf(ny_wrf)=2.*ys_wrf(ny_wrf-1)-ys_wrf(ny_wrf-2) !----------------------------------------------------------------------- ! ! Find latitude and longitude of WRF grid. ! ! 1 -- T point, 2 -- U point, 3 -- V point, 4 -- massless point ! !----------------------------------------------------------------------- CALL xytoll(nx_wrf,ny_wrf,xs_wrf,ys_wrf,lat_wrf(:,:,1),lon_wrf(:,:,1)) CALL xytoll(nx_wrf,ny_wrf, x_wrf,ys_wrf,lat_wrf(:,:,2),lon_wrf(:,:,2)) CALL xytoll(nx_wrf,ny_wrf,xs_wrf, y_wrf,lat_wrf(:,:,3),lon_wrf(:,:,3)) !----------------------------------------------------------------------- ! ! Get lat/lon at each corners ! ! ul - upper left corner ur - upper right corner ! ll - lower left corner lr - lower right corner ! !----------------------------------------------------------------------- lat_ll(1) = lat_wrf( 1, 1,1) lat_ul(1) = lat_wrf( 1,ny_wrf-1,1) lat_ur(1) = lat_wrf(nx_wrf-1,ny_wrf-1,1) lat_lr(1) = lat_wrf(nx_wrf-1, 1,1) lon_ll(1) = lon_wrf( 1, 1,1) lon_ul(1) = lon_wrf( 1,ny_wrf-1,1) lon_ur(1) = lon_wrf(nx_wrf-1,ny_wrf-1,1) lon_lr(1) = lon_wrf(nx_wrf-1, 1,1) lat_ll(2) = lat_wrf( 1, 1,2) lat_ul(2) = lat_wrf( 1,ny_wrf-1,2) lat_ur(2) = lat_wrf(nx_wrf, ny_wrf-1,2) lat_lr(2) = lat_wrf(nx_wrf, 1,2) lon_ll(2) = lon_wrf( 1, 1,2) lon_ul(2) = lon_wrf( 1,ny_wrf-1,2) lon_ur(2) = lon_wrf(nx_wrf, ny_wrf-1,2) lon_lr(2) = lon_wrf(nx_wrf, 1,2) lat_ll(3) = lat_wrf( 1, 1,3) lat_ul(3) = lat_wrf( 1, ny_wrf,3) lat_ur(3) = lat_wrf(nx_wrf-1, ny_wrf,3) lat_lr(3) = lat_wrf(nx_wrf-1, 1,3) lon_ll(3) = lon_wrf( 1, 1,3) lon_ul(3) = lon_wrf( 1, ny_wrf,3) lon_ur(3) = lon_wrf(nx_wrf-1, ny_wrf,3) lon_lr(3) = lon_wrf(nx_wrf-1, 1,3) CALL xytoll(1,1,x_wrf(1), y_wrf(1), lat_ll(4),lon_ll(4)) CALL xytoll(1,1,x_wrf(1), y_wrf(ny_wrf),lat_ul(4),lon_ul(4)) CALL xytoll(1,1,x_wrf(nx_wrf),y_wrf(ny_wrf),lat_ur(4),lon_ur(4)) CALL xytoll(1,1,x_wrf(nx_wrf),y_wrf(1), lat_lr(4),lon_lr(4)) IF (mp_opt > 0 ) THEN CALL inctag mptag = gentag + 2 ! passing UL to 0 source = (nproc_y-1)*nproc_x IF (myproc == source) THEN CALL mpsendr(lat_ul,4,0,mptag, istatus) CALL mpsendr(lon_ul,4,0,mptag+1,istatus) END IF IF (myproc == 0) THEN CALL mprecvr(lat_ul,4,source,mptag, istatus) CALL mprecvr(lon_ul,4,source,mptag+1,istatus) END IF mptag = gentag + 4 ! Pasing UR to 0 source = (nproc_y-1)*nproc_x + nproc_x-1 IF (myproc == source) THEN CALL mpsendr(lat_ur,4,0,mptag, istatus) CALL mpsendr(lon_ur,4,0,mptag+1,istatus) END IF IF (myproc == 0) THEN CALL mprecvr(lat_ur,4,source,mptag, istatus) CALL mprecvr(lon_ur,4,source,mptag+1,istatus) END IF mptag = gentag + 6 ! Passing LR to 0 source = nproc_x-1 IF (myproc == source) THEN CALL mpsendr(lat_lr,4,0,mptag,istatus) CALL mpsendr(lon_lr,4,0,mptag+1,istatus) END IF IF (myproc == 0) THEN CALL mprecvr(lat_lr,4,source,mptag, istatus) CALL mprecvr(lon_lr,4,source,mptag+1,istatus) END IF CALL mpbarrier END IF !----------------------------------------------------------------------- ! ! Returning ! !----------------------------------------------------------------------- DEALLOCATE( x_wrf, y_wrf) DEALLOCATE(xs_wrf,ys_wrf) istatus = 0 RETURN END SUBROUTINE build_wrf_grid ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE prepinterp ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE prepinterp(nx,ny,nxlg,nylg,nx_wrf,ny_wrf,dx,dy,x,y,xs,ys, & 1,14 mapproj,scalef,latnot,trulon,ctrlat,ctrlon,swx,swy, & lat_wrf,lon_wrf,x2d,y2d,iloc,jloc, & dxfld,rdxfld,dyfld,rdyfld,istatus) ! !----------------------------------------------------------------------- ! ! PURPOSE: ! ! Prepare horizontal interpolation arrays. ! ! Do NOT support MPI. ! !----------------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: nx, ny INTEGER, INTENT(IN) :: nxlg, nylg INTEGER, INTENT(IN) :: nx_wrf, ny_wrf REAL, INTENT(IN) :: dx, dy REAL, INTENT(IN) :: x(nx), y(ny) REAL, INTENT(IN) :: xs(nx), ys(ny) INTEGER, INTENT(IN) :: mapproj REAL, INTENT(IN) :: scalef REAL, INTENT(IN) :: latnot(2) REAL, INTENT(IN) :: trulon REAL, INTENT(IN) :: ctrlat,ctrlon REAL, INTENT(OUT) :: swx, swy REAL, INTENT(IN) :: lat_wrf(nx_wrf,ny_wrf,3) REAL, INTENT(IN) :: lon_wrf(nx_wrf,ny_wrf,3) REAL, INTENT(OUT) :: x2d(nx_wrf,ny_wrf,3) REAL, INTENT(OUT) :: y2d(nx_wrf,ny_wrf,3) INTEGER, INTENT(OUT) :: iloc(nx_wrf,ny_wrf,3) INTEGER, INTENT(OUT) :: jloc(nx_wrf,ny_wrf,3) REAL, INTENT(OUT) :: dxfld(nx,3) REAL, INTENT(OUT) :: rdxfld(nx,3) REAL, INTENT(OUT) :: dyfld(ny,3) REAL, INTENT(OUT) :: rdyfld(ny,3) INTEGER, INTENT(OUT) :: istatus !----------------------------------------------------------------------- ! ! Misc. local variables ! !----------------------------------------------------------------------- INTEGER :: n INTEGER :: iproj REAL :: scl, trlat(2), trlon,x0,y0 REAL :: ctrx, ctry !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Begin of executable code ... ... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! !----------------------------------------------------------------------- ! ! Save previous map projection values ! !----------------------------------------------------------------------- ! CALL getmapr(iproj,scl,trlat,trlon,x0,y0) !----------------------------------------------------------------------- ! ! Set ARPS map projection ! !----------------------------------------------------------------------- CALL setmapr(mapproj,scalef,latnot,trulon) CALL lltoxy( 1,1, ctrlat,ctrlon, ctrx, ctry ) swx = ctrx - (FLOAT((nxlg-3))/2.) * dx*scalef swy = ctry - (FLOAT((nylg-3))/2.) * dy*scalef CALL setorig(1,swx,swy) DO n = 1,3 ! For T, U, V three staggers CALL lltoxy(nx_wrf,ny_wrf,lat_wrf(:,:,n),lon_wrf(:,:,n), & x2d(:,:,n),y2d(:,:,n)) END DO IF(MAXVAL(x2d) > x(nx) .OR. MINVAL(x2d) < x(1) .OR. & MAXVAL(y2d) > y(ny) .OR. MINVAL(y2d) < y(1) ) THEN WRITE(6,'(/,a,/,2(4(a,F15.2),a,/))') & 'It seems that WRF domain is outside of the ARPS physical domain.',& 'ARPS domain [',x(1),' -- ',x(nx),' ; ',y(1), ' -- ', y(ny), ' ]',& 'WRF domain [',MINVAL(x2d),' -- ', MAXVAL(x2d), ' ; ', & MINVAL(y2d),' -- ', MAXVAL(y2d), ' ]' CALL arpsstop('Domain error.',1) END IF CALL setijloc(nx_wrf,ny_wrf,nx,ny,x2d(:,:,1),y2d(:,:,1), & xs,ys,iloc(:,:,1),jloc(:,:,1)) ! T points CALL setijloc(nx_wrf,ny_wrf,nx,ny,x2d(:,:,2),y2d(:,:,2), & x,ys,iloc(:,:,2),jloc(:,:,2)) ! U points CALL setijloc(nx_wrf,ny_wrf,nx,ny,x2d(:,:,3),y2d(:,:,3), & xs,y,iloc(:,:,3),jloc(:,:,3)) ! V points CALL setdxdy(nx,ny,1,nx,1,ny,xs,ys, & dxfld(:,1),dyfld(:,1),rdxfld(:,1),rdyfld(:,1)) CALL setdxdy(nx,ny,1,nx,1,ny,x,ys, & dxfld(:,2),dyfld(:,2),rdxfld(:,2),rdyfld(:,2)) CALL setdxdy(nx,ny,1,nx,1,ny,xs,y, & dxfld(:,3),dyfld(:,3),rdxfld(:,3),rdyfld(:,3)) ! !----------------------------------------------------------------------- ! ! Reset map projection to previous values ! !----------------------------------------------------------------------- ! CALL setmapr(iproj,scl,trlat,trlon) CALL setorig(1,x0,y0) istatus = 0 RETURN END SUBROUTINE prepinterp ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE hinterp ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE hinterp(nx,ny,nz,nx_ext,ny_ext,iorder, & 18,1 iloc,jloc,x,y,x2d,y2d, & varin,dxfld,dyfld,rdxfld,rdyfld, & varout,slopey,alphay,betay) !----------------------------------------------------------------------- ! PURPOSE: ! ! Interpolates ARPS 3D array varin horizontally to WRF or other ! grids. The output array varout is a 3D interplation array with ! the same vertical coordinate as the input array varin. ! ! NOTE: ! Refer to function pntint2d in src/adas/intfield.f90. ! !----------------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: nx,ny,nz ! Grid size for input array INTEGER, INTENT(IN) :: nx_ext,ny_ext ! Horizontal grid size of the ! interpolated array INTEGER, INTENT(IN) :: iorder ! polynomial order of the interpolation ! = 1 bi-linear ! > 2 quadratic INTEGER, INTENT(IN) :: iloc(nx_ext,ny_ext) ! ARPS index of external grid points INTEGER, INTENT(IN) :: jloc(nx_ext,ny_ext) ! ARPS index of external grid points REAL, INTENT(IN) :: x(nx), y(ny) ! Grid coordiate of the input array REAL, INTENT(IN) :: x2d(nx_ext,ny_ext), y2d(nx_ext,ny_ext) ! x and y coordinate of external grid point in ARPS coordinate REAL, INTENT(IN) :: varin(nx,ny,nz) REAL, INTENT(IN) :: dxfld(nx),rdxfld(nx) REAL, INTENT(IN) :: dyfld(ny),rdyfld(ny) REAL, INTENT(OUT) :: varout(nx_ext,ny_ext,nz) REAL, INTENT(OUT) :: slopey(nx,ny,nz) REAL, INTENT(OUT) :: alphay(nx,ny,nz) REAL, INTENT(OUT) :: betay(nx,ny,nz) !----------------------------------------------------------------------- ! ! Misc. local variables ! !----------------------------------------------------------------------- INTEGER :: i,j,k INTEGER :: ii,jj REAL :: delx,dely REAL :: varm1,var00,varp1 REAL :: rtwodx, alpha, beta !---------------------------------------------------------------------- ! ! External interpolation function ! Interpolate a 2-d field for a single point on that plane. ! !---------------------------------------------------------------------- ! REAL :: pntint2d ! the function doing horizontal ! interpolation for one grid point ! ! On some platform, it is hard to make pntint2d inline for efficiency. ! So we hardcoded the function pntint2d inside this subroutine. ! ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! !----------------------------------------------------------------------- ! ! Compute derivative terms ! !----------------------------------------------------------------------- ! CALL setdrvy(nx,ny,nz,1,nx,1,ny,1,nz, & dyfld,rdyfld,varin,slopey,alphay,betay) ! !----------------------------------------------------------------------- ! ! Horizontal interpolation ! !----------------------------------------------------------------------- ! IF(iorder == 1) THEN ! !----------------------------------------------------------------------- ! ! Loop through all WRF grid points ! !----------------------------------------------------------------------- ! DO k = 1,nz DO j = 1,ny_ext DO i = 1,nx_ext ! !----------------------------------------------------------------------- ! ! Compute bilinear interpolated value ! !----------------------------------------------------------------------- ! ii=MIN(MAX(iloc(i,j),2),(nx-2)) jj=MIN(MAX(jloc(i,j),2),(ny-2)) delx=(x2d(i,j)-x(ii)) dely=(y2d(i,j)-y(jj)) varout(i,j,k)= (1.-delx*rdxfld(ii))* & (varin(ii, jj,k)+slopey(ii, jj,k)*dely) & + (delx*rdxfld(ii))* & (varin(ii+1,jj,k)+slopey(ii+1,jj,k)*dely) END DO END DO END DO ELSE ! !----------------------------------------------------------------------- ! ! Loop through all WRF grid points ! !----------------------------------------------------------------------- ! DO k = 1,nz DO j = 1,ny_ext DO i = 1,nx_ext ! !----------------------------------------------------------------------- ! ! Compute biquadratic ! !----------------------------------------------------------------------- ! ii=MIN(MAX(iloc(i,j),(2+1)),(nx-2)) jj=MIN(MAX(jloc(i,j),(2+1)),(ny-2)) delx=(x2d(i,j)-x(ii)) dely=(y2d(i,j)-y(jj)) ! !----------------------------------------------------------------------- ! ! Stencil is ii-1 to ii+1 and jj-1 to jj + 1 ! ! Interpolate in y. ! !----------------------------------------------------------------------- ! varm1=(alphay(ii-1,jj,k)*dely+betay(ii-1,jj,k))*dely & + varin(ii-1,jj,k) var00=(alphay(ii ,jj,k)*dely+betay(ii ,jj,k))*dely & + varin(ii ,jj,k) varp1=(alphay(ii+1,jj,k)*dely+betay(ii+1,jj,k))*dely & + varin(ii+1,jj,k) ! !----------------------------------------------------------------------- ! ! Interpolate intermediate results in x. ! !----------------------------------------------------------------------- ! rtwodx=1./(dxfld(ii-1)+dxfld(ii)) alpha=((varp1-var00)*rdxfld(ii ) & + (varm1-var00)*rdxfld(ii-1))*rtwodx beta= (varp1-var00)*rdxfld(ii) & - dxfld(ii)*alpha varout(i,j,k)=(alpha*delx+beta)*delx+var00 END DO END DO END DO END IF ! varout(i,j,k) = pntint2d(nx,ny,2,nx-1,2,ny-1, & ! iorder,x,y,x2d(i,j),y2d(i,j),iloc(i,j),jloc(i,j), & ! varin(:,:,k),dxfld,dyfld,rdxfld,rdyfld, & ! slopey(:,:,k),alphay(:,:,k),betay(:,:,k)) RETURN END SUBROUTINE hinterp ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE compute_eta_3d ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE compute_eta_3d(nx,ny,nz,p,t,mix,zp,ztopo,ptop,eta,mu) 1,1 !------------------------------------------------------------------- ! ! PURPOSE ! ! Subroutine to compute eta on a 3D grid. Also computes mu as a ! function of the terrain passed in. ! ! The Eta-P coordinate. ! ! Pdry - Ptop Pdry = Dry pressure (Pa) ! EtaP = ---------- Ptop = Pressure at model top (Pa) ! mu mu = Psfc - Pvapor_bottom - Ptop ! ! General Procedure: ! ! 1. Compute downward integrated vapor-pressure for each gridpoint ! ( Pvapor) ! 2. Subtract the Pvapor value from the pressure at each point to ! get the dry pressure (Pdry) at each point ! 3. Compute mu (dry surface pressure minus top pressure) ! 4. Compute EtaP value using newly compute dry pressure for each ! point ! ! NOTE: ! refer to subroutine compute_eta_3d in WRFSI src/mod/module_vinterp_utils.F ! ARPS physical domain is from 2 to nz-1. ! Water mixing ratio "mix" is passed in instead of RH. ! !------------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: nx,ny ! Horizontal dimensions of array ! in WRF grid INTEGER, INTENT(IN) :: nz ! Horizontal dimensions of array ! in ARPS grid REAL, INTENT(IN) :: p(nx,ny,nz) ! 3D Pressure (Pa) REAL, INTENT(IN) :: t(nx,ny,nz) ! 3D Temperature (K) REAL, INTENT(IN) :: mix(nx,ny,nz)! 3D water vapor mixing ratio REAL, INTENT(IN) :: zp(nx,ny,nz) ! 3D GPH (gpm) REAL, INTENT(IN) :: ztopo(nx,ny) ! WRF Topography REAL, INTENT(IN) :: ptop ! Top pressure (Pa) REAL, INTENT(OUT) :: eta(nx,ny,nz) ! Eta values REAL, INTENT(OUT) :: mu(nx,ny) ! Mu !------------------------------------------------------------------ ! ! Misc. Local variables ! !------------------------------------------------------------------ REAL, ALLOCATABLE :: rho(:) REAL, ALLOCATABLE :: pdry(:) REAL, ALLOCATABLE :: iqvp(:) REAL :: tsfc, psfc, qvsfc, dz, qvbar,iqvp_sfc REAL :: wgt0, wgt1 LOGICAL :: found_level INTEGER :: i,j,k REAL, PARAMETER :: g = 9.81 !------------------------------------------------------------------ ! ! External functions ! !------------------------------------------------------------------ REAL :: compute_density ! function to compute grid point density ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ALLOCATE (rho (nz)) ! Density for each level in a column ALLOCATE (pdry(nz)) ! Dry air pressure (iqvp removed) ALLOCATE (iqvp(nz)) ! Integrated (downward) vapor pressure DO j = 1, ny DO i = 1, nx ! Compute density and qv in the column DO k = 1,nz rho(k)= compute_density(t(i,j,k),p(i,j,k)) ENDDO ! Compute the dry pressure values and iqvp for the column ! (pdry+iqvp = p) CALL compute_column_pdry(nz,p(i,j,:),rho,mix(i,j,:),zp(i,j,:), & pdry,iqvp) ! Compute mu at this point using the terrain height. Mu is just ! the dry surface pressure, which would be the model-adjusted ! surface pressure minus the integrated water vapor. IF (ztopo(i,j) .LE. zp(i,j,2) ) THEN ! ARPS physical domain is ! 2 -> (nz-1) ! WRF terrain below lowest BG model level. Make crude adjustment ! using 10 Pa per meter to get surface pressure and assume a ! constant qv for moisture. Assume a standard 6.5 K/km lapse rate ! for temperature k = 2 dz = zp(i,j,2)-ztopo(i,j) psfc = p(i,j,2) + dz*10. qvbar = mix(i,j,2) tsfc = t(i,j,2) + dz*.0065 ELSE found_level = .false. find_level: DO k = 3, nz-1 IF ( (ztopo(i,j) .LE. zp(i,j,k)) .AND. & (ztopo(i,j) .GT. zp(i,j,k-1)) ) THEN found_level = .true. EXIT find_level END IF END DO find_level IF (.NOT. found_level) THEN PRINT *, 'COMPUTE_ETA_3D: This should not happen.' PRINT *, 'Could not find where to insert WRF surface.' PRINT *, 'I/J = ',i,j PRINT *, 'Topo = ', ztopo(i,j) PRINT *, 'Z in column = ', zp(i,j,:) STOP 'level_problem' END IF ! Determine pressure, temperature, and qv psfc = EXP ( ( ztopo(i,j)*ALOG(p(i,j,k-1)/p(i,j,k)) - & zp(i,j,k)*ALOG(p(i,j,k-1)) + & zp(i,j,k-1)*ALOG(p(i,j,k)) ) / & ( zp(i,j,k-1) - zp(i,j,k) ) ) IF ( (zp(i,j,k)-zp(i,j,k-1)) .GE. 1.) THEN wgt0 = (zp(i,j,k)-ztopo(i,j)) / (zp(i,j,k)-zp(i,j,k-1)) wgt1 = 1 - wgt0 ELSE wgt0 = 0.0 wgt1 = 1.0 ENDIF tsfc = t(i,j,k-1)*wgt0 + t(i,j,k)*wgt1 qvsfc = mix(i,j,k-1)*wgt0 + mix(i,j,k)*wgt1 qvbar = (qvsfc + mix(i,j,k))*0.5 dz = zp(i,j,k) - ztopo(i,j) ENDIF ! Now compute the integrated vapor pressure between ! the surface and the next lowest level iqvp_sfc = iqvp(k)+g*qvbar*rho(k)*dz/(1.+qvbar) mu(i,j) = psfc - iqvp_sfc - ptop ! We now have everything we need to compute eta for the column DO k = 1,nz eta(i,j,k) = (pdry(k) - ptop) / mu(i,j) END DO IF ((i == nx/2) .AND. (j == ny/2)) THEN ! Some diagnostic prints from the center of the column PRINT *, 'Eta values on background grid center column:' PRINT *, 'TOPO/PSFC/MU = ',ztopo(i,j), psfc, mu(i,j) PRINT *, 'Z PRESS PRESSDRY IQVAPORP ETA' PRINT *, '---------- ---------- ---------- ---------- ----------' DO k=1,nz-1 PRINT '(F10.1,1x,F10.1,1x,F10.1,1x,F10.6,1x,F10.6)',zp(i,j,k), & p(i,j,k), pdry(k),iqvp(k),eta(i,j,k) END DO PRINT *, ' ' END IF END DO END DO DEALLOCATE (rho) DEALLOCATE (pdry) DEALLOCATE (iqvp) RETURN END SUBROUTINE compute_eta_3d !################################################################## !################################################################## !###### ###### !###### SUBROUTINE vinterp ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE vinterp(nx,ny,nz_in,nz_out,korder,eta_in, eta_out, & 9 data_in, data_out, extrapolate) !------------------------------------------------------------------- ! ! PURPOSE: ! ! Interpolates each column of data from ARPS height surface ! to WRF mass vertical coordinate. ! ! NOTE: ! Refer to subroutine interp_eta2eta_lin in WRFSI src/mod/module_vinterp_utils.F ! o ARPS vertical physical domain is from 2 to nz-1 ! o We added two supported interpolations method, linear and ! quadratic while WRFSI only support linear interoplation so far. ! !------------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: nx ! X dimension of WRF grid INTEGER, INTENT(IN) :: ny ! Y dimension of WRF grid INTEGER, INTENT(IN) :: nz_in ! Vertical dimension of ARPS grid INTEGER, INTENT(IN) :: nz_out ! Vertical dimension of WRF grid (mass) INTEGER, INTENT(IN) :: korder ! polyn. interpolation order REAL, INTENT(IN) :: eta_in(nx,ny,nz_in) ! mass value at ARPS grid REAL, INTENT(IN) :: eta_out(nz_out) ! Desired mass levels REAL, INTENT(IN) :: data_in(nx,ny,nz_in) REAL, INTENT(OUT):: data_out(nx,ny,nz_out) LOGICAL, INTENT(IN) :: extrapolate ! Whether to do extrapolation !------------------------------------------------------------------ ! ! External function ! !------------------------------------------------------------------ REAL :: intpnt_lin ! do vertical interpolation linearly REAL :: intpnt_quad ! do vertical interpolation quadratically ! !----------------------------------------------------------------- ! ! Misc. Local variables ! !----------------------------------------------------------------- INTEGER :: i,j,k,kk, ki REAL :: desired_eta REAL :: dvaldeta INTEGER :: nz_top !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ data_out(:,:,:) = -99999.9 nz_top = nz_in - 1 DO j = 1, ny DO i = 1, nx output_loop: DO k = 1, nz_out desired_eta = eta_out(k) IF (desired_eta .GT. eta_in(i,j,2)) THEN IF ((desired_eta - eta_in(i,j,2)).LT. 0.0001) THEN data_out(i,j,k) = data_in(i,j,2) ELSE IF (extrapolate) THEN ! Extrapolate downward because desired eta level is below ! the lowest level in our input data. Extrapolate using simple ! 1st derivative of value with respect to eta for the bottom 2 ! input layers. ! Add a check to make sure we are not using the gradient of ! a very thin layer IF ( (eta_in(i,j,2)-eta_in(i,j,3)) .GT. 0.001) THEN dvaldeta = (data_in(i,j,2) - data_in(i,j,3)) / & (eta_in(i,j,2) - eta_in(i,j,3) ) ELSE dvaldeta = (data_in(i,j,2) - data_in(i,j,4)) / & (eta_in(i,j,2) - eta_in(i,j,4) ) ENDIF data_out(i,j,k) = data_in(i,j,2) + & dvaldeta * (desired_eta-eta_in(i,j,2)) ELSE data_out(i,j,k) = data_in(i,j,2) ENDIF ENDIF ELSE IF (desired_eta .LE. eta_in(i,j,nz_top)) THEN IF ( abs(eta_in(i,j,nz_top) - desired_eta) .LT. 0.0001) THEN data_out(i,j,k) = data_in(i,j,nz_top) ELSE IF (extrapolate) THEN ! Extrapolate upward IF ( (eta_in(i,j,nz_top-1)-eta_in(i,j,nz_top)) .GT. 0.0005) THEN dvaldeta = (data_in(i,j,nz_top) - data_in(i,j,nz_top-1)) / & (eta_in(i,j,nz_top) - eta_in(i,j,nz_top-1)) ELSE dvaldeta = (data_in(i,j,nz_top) - data_in(i,j,nz_top-2)) / & (eta_in(i,j,nz_top) - eta_in(i,j,nz_top-2)) ENDIF data_out(i,j,k) = data_in(i,j,nz_top) + & dvaldeta * (desired_eta-eta_in(i,j,nz_top)) ELSE data_out(i,j,k) = data_in(i,j,nz_top) ENDIF ENDIF ELSE ! We can trap between two levels and linearly interpolate input_loop: DO kk = 2, nz_top-1 IF (desired_eta .EQ. eta_in(i,j,kk) )THEN data_out(i,j,k) = data_in(i,j,kk) EXIT input_loop ELSE IF ( (desired_eta .LT. eta_in(i,j,kk)) .AND. & (desired_eta .GT. eta_in(i,j,kk+1)) ) THEN IF(korder == 1) THEN data_out(i,j,k) = intpnt_lin( eta_in(i,j,kk), & eta_in(i,j,kk+1), desired_eta, & data_in(i,j,kk), data_in(i,j,kk+1) ) ELSE IF(korder == 2) THEN IF ( ABS(desired_eta - eta_in(i,j,kk)) <= & ABS(desired_eta - eta_in(i,j,kk+1)) ) THEN ki = kk ELSE IF ( kk == nz_top-1 ) THEN ki = kk ELSE ki = kk+1 END IF data_out(i,j,k) = intpnt_quad( eta_in(i,j,ki-1), & eta_in(i,j,ki),eta_in(i,j,ki+1), & desired_eta, data_in(i,j,ki-1), & data_in(i,j,ki),data_in(i,j,ki+1) ) ELSE WRITE(6,*) 'Unsupported polynomial interpolation order:',korder STOP 'Unsupported korder' END IF EXIT input_loop ENDIF ENDDO input_loop ENDIF ENDDO output_loop ENDDO ! i ENDDO ! j RETURN END SUBROUTINE vinterp ! !################################################################## !################################################################## !###### ###### !###### FUNCTION intpnt_lin ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! FUNCTION intpnt_lin(x1,x2,x,d1,d2) RESULT(d) !------------------------------------------------------------------ ! ! PURPOSE: ! Fuction to do vertical interpolation linearly ! !----------------------------------------------------------------------- ! ! Author: Yunheng Wang. ! !----------------------------------------------------------------- IMPLICIT NONE REAL, INTENT(IN) :: x1 ! coordinate of first point REAL, INTENT(IN) :: x2 ! coordinate of second point REAL, INTENT(IN) :: x ! coordinate of desired point REAL, INTENT(IN) :: d1 ! data at first point REAL, INTENT(IN) :: d2 ! data at second point REAL :: d ! Interpolated value !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ REAL :: wgt !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ wgt = (x - x2) / (x1 - x2) d = wgt*d1 + (1.-wgt)*d2 RETURN END FUNCTION intpnt_lin !################################################################## !################################################################## !###### ###### !###### FUNCTION intpnt_quad ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! FUNCTION intpnt_quad(x0,x1,x2,x,d0,d1,d2) RESULT(d) !------------------------------------------------------------------- ! ! PURPOSE: ! ! Quadratically interpolates from the given three points ! !----------------------------------------------------------------------- ! ! Author: Yunheng Wang. ! !------------------------------------------------------------------- IMPLICIT NONE REAL, INTENT(IN) :: x0 ! coordinate of the first point REAL, INTENT(IN) :: x1 ! coordinate of the second point REAL, INTENT(IN) :: x2 ! coordinate of the third point REAL, INTENT(IN) :: x ! coordinate of the desired point REAL, INTENT(IN) :: d0 ! value at the first point REAL, INTENT(IN) :: d1 ! value at the second point REAL, INTENT(IN) :: d2 ! value at the third point REAL :: d ! value to be calculated ! !----------------------------------------------------------------- ! ! Misc. Local variables ! !----------------------------------------------------------------- REAL :: b1,b2, tmp !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ !----------------------------------------------------------------------- ! ! Quadratic interpolation ! ! f(x) = f(x0) + b1*(x-x0) + b2*(x-x0)(x-x1) ! ! f(x1)-f(x0) ! b1 = ---------- ! x1 - x0 ! ! f(x2)-f(x1) f(x1)-f(x0) ! ----------- - ------------ ! x2 - x1 x1 - x0 ! b2 = ----------------------------- ! x2 - x0 ! !------------------------------------------------------------------------ ! b1 = (d1 - d0) / (x1 - x0) tmp = (d2 - d1) / (x2 - x1) b2 = (tmp - b1) / (x2 - x0) d = d0 + b1*(x-x0) + b2*(x-x0)*(x-x1) RETURN END FUNCTION intpnt_quad ! !################################################################## !################################################################## !###### ###### !###### FUNCTION compute_density ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! FUNCTION compute_density(t_k, p_pa) RESULT(rho) !----------------------------------------------------------------- ! ! PURPOSE: ! Computes density (kg/m{-3}) given temperature (K) and pressure (Pa) ! ! NOTE: ! Refer to the same function in WRFSI src/mode/module_diagnostic_vars.F. ! !----------------------------------------------------------------- IMPLICIT NONE REAL, INTENT(IN) :: t_k REAL, INTENT(IN) :: p_pa REAL :: rho REAL, PARAMETER :: Rd = 287.04 ! J deg{-1} kg{-1} ! Gas constant for dry air rho = p_pa / (Rd * t_k) RETURN END FUNCTION compute_density ! !################################################################## !################################################################## !###### ###### !###### FUNCTION compute_column_pdry ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE compute_column_pdry(nz,p,rho,qv,z,pdry,pvapor) 1 !----------------------------------------------------------------- ! ! PURPOSE: ! ! Given full pressure in Pascals (p), dry air density in kg/m^3 (rho), ! water vapor mixing ratio in kg/kg (qv), compute the dry pressure value ! at each grid point in the column of nz elements. ! This routine assumes the pressure array decreases monotonically from ! 1->nz and that the rho and qv arrays match the pressure array. ! ! NOTE: ! Refer to subroutine compute_column_pdry in WRFSI src/mod/module_vinterp_utils.F. ! !----------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: nz REAL, INTENT(IN) :: p (nz) REAL, INTENT(IN) :: rho(nz) REAL, INTENT(IN) :: qv (nz) REAL, INTENT(IN) :: z (nz) REAL, INTENT(OUT) :: pdry (nz) REAL, INTENT(OUT) :: pvapor(nz) INTEGER :: kbot, k REAL :: qv_mean,dz REAL, PARAMETER :: g = 9.8 ! Set top vapor pressure to zero and top dry pressure equal to ! top total pressure pvapor(nz) = 0. pdry(nz) = p(nz) ! Integrate moisture downward main_loop: DO kbot = nz-1, 1, -1 ! Initialize for upcoming sums. pvapor(kbot) = 0. ! Integrate downward down_to_here: DO k = nz-1,kbot,-1 ! Compute delta-Z and mean Qv for this layer dz = z(k+1) - z(k) qv_mean = (qv(k) + qv(k+1)) * 0.5 ! Compute pvapor for this layer and sum with previous layer pvapor(kbot) = pvapor(kbot)+g*qv_mean*rho(k)*dz/(1.+qv_mean) END DO down_to_here ! Subtract the integrated vapor pressure from the total pressure pdry(kbot) = p(kbot) - pvapor(kbot) END DO main_loop END SUBROUTINE compute_column_pdry ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE compute_ph ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE compute_ph(nx,ny,nz,ht,znw,ptop,mu_input, & 1,2 pt_input,qv,mu,mub,ph,phb,pt,p,pb, & t_init,alb,alt,al) !------------------------------------------------------------------ ! ! PURPOSE: ! ! Compute WRF variables, such as geopotential, air mass and potential ! temperature etc. ! ! NOTE: ! Refered to subroutine init_domain_rk in WRF dyn_em/module_initialize_real.f. ! !------------------------------------------------------------------ USE wrf_metadata IMPLICIT NONE INTEGER, INTENT(IN) :: nx,ny,nz ! WRF dimension size REAL, INTENT(IN) :: ht(nx,ny) ! Topographic height REAL, INTENT(IN) :: znw(nz) ! full vertical levels REAL, INTENT(IN) :: ptop ! model top pressure (Pa) REAL, INTENT(IN) :: mu_input(nx,ny) ! Total air mass in column REAL, INTENT(IN) :: pt_input(nx,ny,nz) ! potential temperature REAL, INTENT(IN) :: qv(nx,ny,nz) ! water vapor mixing ratio REAL, INTENT(OUT) :: ph(nx,ny,nz) ! base-state geopotential REAL, INTENT(OUT) :: phb(nx,ny,nz)! perturbation geopotential REAL, INTENT(OUT) :: mu(nx,ny) ! perturbation dry air mass in column REAL, INTENT(OUT) :: mub(nx,ny) ! base state dry air mass in column REAL, INTENT(OUT) :: pt(nx,ny,nz) ! perturbation potential temperature REAL, INTENT(OUT) :: p(nx,ny,nz) REAL, INTENT(OUT) :: pb(nx,ny,nz) ! base state pressure ! work arrays below REAL, INTENT(OUT) :: t_init(nx,ny,nz) ! REAL, INTENT(OUT) :: alb(nx,ny,nz) ! inverse of reference density REAL, INTENT(OUT) :: alt(nx,ny,nz) ! inverse of perturb. density REAL, INTENT(OUT) :: al(nx,ny,nz) ! inverse of density !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ REAL :: p00,t00,a REAL :: p_surf ! surface pressure REAL :: qvf1,qvf2,qvf REAL :: znu(nz-1) ! half level locations REAL :: dnw(nz-1) ! layer thickness REAL :: rdn(nz-1) INTEGER :: i,j,k !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ DO k = 1, nz-1 znu(k) = 0.5*( znw(k+1) + znw(k) ) dnw(k) = znw(k+1) - znw(k) END DO DO k = 2, nz-1 rdn(k) = 1.0/(0.5*(dnw(k)+dnw(k-1))) END DO ! To define the base state, we call a USER MODIFIED routine to set the three ! necessary constants: p00 (sea level pressure, Pa), t00 (sea level temperature, K), ! and A (temperature difference, from 1000 mb to 300 mb, K). CALL const_module_initialize ( p00 , t00 , a ) ! bast state pressure is a function of eta level and terrain only DO j = 1, ny-1 DO i = 1,nx-1 p_surf = p00*EXP(-t00/a + ((t00/a)**2 - 2.*g_wrf*ht(i,j)/a/r_d)**0.5) DO k = 1,nz-1 pb(i,j,k) = znu(k)*(p_surf-ptop) + ptop t_init(i,j,k) = (t00 + a*LOG(pb(i,j,k)/p00))*(p00/pb(i,j,k))**(r_d/cp_wrf) - t0 alb(i,j,k) = (r_d/p1000mb)*(t_init(i,j,k)+t0)*(pb(i,j,k)/p1000mb)**cvpm END DO mub(i,j) = p_surf - ptop ! base state dry air mass mu(i,j) = mu_input(i,j) + ptop - p_surf ! perturbation dry air mass phb(i,j,1) = g_wrf*ht(i,j) ! base geopotential at the lowest level ! is terrain elevation * gravity ! Integerate base geopotential. this assures that the base state ! is in exact hydrostatic balance with respect to the model equations. ! this field is on full levels. DO k = 2, nz phb(i,j,k) = phb(i,j,k-1) - dnw(k-1)*mub(i,j)*alb(i,j,k-1) END DO END DO END DO ! Filling edges mub(nx,:) = mub(nx-1,:) mu (nx,:) = mu(nx-1,:) pb (nx,:,1:nz-1) = pb(nx-1,:,1:nz-1) alb(nx,:,1:nz-1) = alb(nx-1,:,1:nz-1) t_init(nx,:,1:nz-1) = t_init(nx-1,:,1:nz-1) phb(nx,:,:) = pb(nx-1,:,:) mub(:,ny) = mub(:,ny-1) mu (:,ny) = mu(:,ny-1) pb (:,ny,1:nz-1) = pb(:,ny-1,1:nz-1) alb(:,ny,1:nz-1) = alb(:,ny-1,1:nz-1) t_init(:,ny,1:nz-1) = t_init(:,ny-1,1:nz-1) phb (:,ny,:) = pb(:,ny-1,:) pt = pt_input - t0 DO j = 1, ny-1 DO i = 1, nx-1 ! first get the pressure perturbation, moisture and inverse density ! at the top-most level qvf1 = qv(i,j,nz-1) qvf2 = 1./(1.+qvf1) qvf1 = qvf1*qvf2 p(i,j,nz-1) = - 0.5*(mu(i,j) + qvf1*mub(i,j))*dnw(nz-1)/qvf2 qvf = 1.0 + rvovrd*qv(i,j,nz-1) alt(i,j,nz-1) = (r_d/p1000mb)*(pt(i,j,nz-1)+t0)*qvf* & (((p(i,j,nz-1)+pb(i,j,nz-1))/p1000mb)**cvpm) al(i,j,nz-1) = alt(i,j,nz-1) - alb(i,j,nz-1) ! now, integrate down the column. DO k = nz-2,1,-1 qvf1 = 0.5*(qv(i,j,k)+ qv(i,j,k+1)) qvf2 = 1./(1.+qvf1) qvf1 = qvf1*qvf2 p(i,j,k) = p(i,j,k+1) - (mu(i,j) + qvf1*mub(i,j))/qvf2/rdn(k+1) qvf = 1.0 + rvovrd*qv(i,j,k) alt(i,j,k) = (r_d/p1000mb)*(pt(i,j,k)+t0)*qvf* & (((p(i,j,k)+pb(i,j,k))/p1000mb)**cvpm) al(i,j,k) = alt(i,j,k) - alb(i,j,k) END DO ph(i,j,1) = 0.0 DO k = 2, nz ph(i,j,k) = ph(i,j,k-1) - dnw(k-1) * & ( (mub(i,j)+mu(i,j))*al(i,j,k-1)+mu(i,j)*alb(i,j,k-1)) END DO END DO END DO RETURN END SUBROUTINE compute_ph ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE init_soil_depth ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## SUBROUTINE init_soil_depth(sfcphys, zs,dzs,nzsoil) 1 !------------------------------------------------------------------ ! ! Define layers (top layer = 0.01 m). Double the thicknesses at ! each step (dzs values). The distance from the ground level to ! the midpoint of the layer is given by zs. ! ! ------- Ground Level ---------- || || || || ! || || || || zs(1) = 0.005 m ! -- -- -- -- -- -- -- -- -- || || || \/ ! || || || ! ----------------------------------- || || || \/ dzs(1) = 0.01 m ! || || || ! || || || zs(2) = 0.02 ! -- -- -- -- -- -- -- -- -- || || \/ ! || || ! || || ! ----------------------------------- || || \/ dzs(2) = 0.02 m ! || || ! || || ! || || ! || || zs(3) = 0.05 ! -- -- -- -- -- -- -- -- -- || \/ ! || ! || ! || ! || ! ----------------------------------- \/ dzs(3) = 0.04 m ! !---------------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: sfcphys REAL, INTENT(OUT) :: zs(6), dzs(6) INTEGER, INTENT(OUT) :: nzsoil !------------------------------------------------------------------ ! ! Misc. local variables ! !------ ----------------------------------------------------------- INTEGER :: k !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IF(sfcphys == 1) THEN nzsoil = 5 dzs(1) = 0.01 zs(1) = 0.5*dzs(1) DO k=2,nzsoil dzs(k)=2*dzs(k-1) zs(k)=zs(k-1)+.5*dzs(k-1)+.5*dzs(k) END DO ELSE IF(sfcphys == 2) THEN nzsoil = 4 dzs(1:4) = (/ 0.1 , 0.3 , 0.6 , 1.0 /) zs(1)=.5*dzs(1) DO k=2,nzsoil zs(k)=zs(k-1)+.5*dzs(k-1)+.5*dzs(k) END DO ELSE IF(sfcphys == 3) THEN nzsoil = 6 zs(1:6) = (/ 0.00 , 0.05 , 0.20 , 0.40 , 1.60 , 3.00 /) dzs(1:6) = (/ 0.00 , 0.125, 0.175 , 0.70 , 1.30 , 1.40 /) ELSE WRITE(6,*) ' Wrong bl_surface_physics option', sfcphys WRITE(6,*) ' Must be 1, 2 or 3' STOP END IF RETURN END SUBROUTINE init_soil_depth ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE vinterp_soil ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE vinterp_soil(nx,ny,nzsoil_in,zs_in,tsoil_in,qsoil_in, & 1 nzsoil_out,zs_out,tsoil_out,qsoil_out) !------------------------------------------------------------------ ! ! PURPOSE: ! ! Vertically interpolate ARPS soil variables to WRF soil layers. ! !------------------------------------------------------------------ IMPLICIT NONE INTEGER, INTENT(IN) :: nx,ny ! WRF horizontal grid size INTEGER, INTENT(IN) :: nzsoil_in ! ARPS soil layer size REAL, INTENT(IN) :: zs_in(nx,ny,nzsoil_in) ! ARPS soil layer depth REAL, INTENT(IN) :: tsoil_in(nx,ny,nzsoil_in) REAL, INTENT(IN) :: qsoil_in(nx,ny,nzsoil_in) INTEGER, INTENT(IN) :: nzsoil_out ! WRF soil layer size REAL, INTENT(IN) :: zs_out(nzsoil_out) ! WRF soil layer depth REAL, INTENT(OUT) :: tsoil_out(nx,ny,nzsoil_out) REAL, INTENT(OUT) :: qsoil_out(nx,ny,nzsoil_out) !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ INTEGER :: i,j,k,m REAL :: w1,w2 REAL :: dist,wt,wq !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ IF(nzsoil_in == 2) THEN ! suppose ARPS old soil model ! contains two layers, ! soil layer -- 0-10 cm, (0.05m)and ! deep soil -- 10-100 cm (0.55m) DO k = 1, nzsoil_out IF(zs_out(k) < 0.05) THEN ! extrapolation dist = 0.05 - zs_out(k) DO j = 1,ny DO i = 1,nx wt = (tsoil_in(i,j,1) - tsoil_in(i,j,2))/0.5 tsoil_out(i,j,k) = tsoil_in(i,j,1) + wt*dist wq = (qsoil_in(i,j,1) - qsoil_in(i,j,2))/0.5 qsoil_out(i,j,k) = qsoil_in(i,j,1) + wq*dist END DO END DO ELSE IF(zs_out(k) >= 0.55) THEN ! constant layers tsoil_out(:,:,k) = tsoil_in(:,:,2) qsoil_out(:,:,k) = qsoil_in(:,:,2) ELSE w1 = ( 0.55 - zs_out(k) )/0.5 w2 = ( zs_out(k) - 0.05 )/0.5 DO j = 1,ny DO i = 1,nx tsoil_out(i,j,k) = tsoil_in(i,j,1)*w1 + tsoil_in(i,j,2)*w2 qsoil_out(i,j,k) = qsoil_in(i,j,1)*w1 + qsoil_in(i,j,2)*w2 END DO END DO END IF END DO ELSE IF(nzsoil_in > 2) THEN ! ARPS new soil model DO j = 1,ny DO i = 1,nx DO k = 1, nzsoil_out IF(zs_out(k) < zs_in(i,j,1)) THEN ! extrapolation dist = zs_in(i,j,1) - zs_out(k) wt = (tsoil_in(i,j,1) - tsoil_in(i,j,2))/(zs_in(i,j,2)-zs_in(i,j,1)) wq = (qsoil_in(i,j,1) - qsoil_in(i,j,2))/(zs_in(i,j,2)-zs_in(i,j,1)) tsoil_out(i,j,k) = tsoil_in(i,j,1) + wt*dist qsoil_out(i,j,k) = qsoil_in(i,j,1) + wq*dist ELSE IF(zs_out(k) >= zs_in(i,j,nzsoil_in)) THEN ! constant layers tsoil_out(i,j,k) = tsoil_in(i,j,nzsoil_in) qsoil_out(i,j,k) = qsoil_in(i,j,nzsoil_in) ELSE ! linear interpolation DO m = 1, nzsoil_in IF(zs_in(i,j,m) > zs_out(k)) EXIT END DO w1 = (zs_in(i,j,m) - zs_out(k))/(zs_in(i,j,m)-zs_in(i,j,m-1)) w2 = (zs_out(k) - zs_in(i,j,m-1) )/(zs_in(i,j,m)-zs_in(i,j,m-1)) tsoil_out(:,:,k) = tsoil_in(:,:,m-1)*w1 + tsoil_in(:,:,m)*w2 qsoil_out(:,:,k) = qsoil_in(:,:,m-1)*w1 + qsoil_in(:,:,m)*w2 END IF END DO ! k END DO ! i END DO ! j ELSE WRITE(6,*) ' Wrong soil levels, nzsoil_arps = ',nzsoil_in STOP END IF RETURN END SUBROUTINE vinterp_soil ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE get_sfcdt ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE get_sfcdt(sfcinitopt,sfcdtfl,ncompressx,ncompressy,nxsm,nysm,& 1,5 nx,ny,nstyps,dx,dy,mapproj,trulat1,trulat2,trulon,sclfct, & ctrlat,ctrlon,soiltyp,stypfrct,vegtyp,veg,tem1, & hinterp_needed,nx_wrf,ny_wrf,dx_wrf,dy_wrf, & mapproj_wrf,trulat1_wrf,trulat2_wrf,trulon_wrf,jday, & x2d,y2d,xs,ys,iloc,jloc, & hgt_wrf,soiltyp_wrf,vegtyp_wrf,vegfrct_wrf,xice,xland, & tmn_wrf,shdmin,shdmax,albbck,snoalb,istatus) !----------------------------------------------------------------------- ! ! PURPOSE: ! Read in surface characteristic data to intialize ! ! ARPS WRF ARPS WRF ! =========== ============ ============ ============== ! soiltyp soiltyp_wrf stypfrct stypfrct_wrf ! vegtyp vegtyp_wrf veg veg_wrf ! vegfrct_wrf ! xice xland ! !----------------------------------------------------------------------- ! IMPLICIT NONE CHARACTER(LEN=*), INTENT(IN) :: sfcinitopt CHARACTER(LEN=*), INTENT(IN) :: sfcdtfl INTEGER, INTENT(IN) :: ncompressx,ncompressy INTEGER, INTENT(IN) :: nxsm, nysm INTEGER, INTENT(IN) :: nx, ny, nstyps, nx_wrf, ny_wrf REAL, INTENT(IN) :: dx, dy, dx_wrf, dy_wrf INTEGER, INTENT(IN) :: mapproj, mapproj_wrf REAL, INTENT(IN) :: trulat1,trulat2, trulat1_wrf,trulat2_wrf REAL, INTENT(IN) :: trulon, trulon_wrf REAL, INTENT(IN) :: ctrlat,ctrlon INTEGER, INTENT(IN) :: sclfct, jday LOGICAL, INTENT(IN) :: hinterp_needed REAL, INTENT(IN) :: x2d(nx_wrf,ny_wrf), y2d(nx_wrf,ny_wrf) INTEGER, INTENT(IN) :: iloc(nx_wrf,ny_wrf), jloc(nx_wrf,ny_wrf) REAL, INTENT(IN) :: xs(nx), ys(ny) INTEGER :: soiltyp (nx,ny,nstyps) ! ARPS arrays REAL :: stypfrct(nx,ny,nstyps) INTEGER :: vegtyp(nx,ny) REAL :: veg(nx,ny) REAL :: tem1(nx,ny,3) ! ARPS work arrays REAL, INTENT(OUT) :: hgt_wrf(nx_wrf,ny_wrf) ! WRF arrays INTEGER, INTENT(OUT) :: soiltyp_wrf(nx_wrf,ny_wrf) INTEGER, INTENT(OUT) :: vegtyp_wrf(nx_wrf,ny_wrf) REAL, INTENT(OUT) :: vegfrct_wrf(nx_wrf,ny_wrf) REAL, INTENT(OUT) :: xice(nx_wrf,ny_wrf) REAL, INTENT(OUT) :: xland(nx_wrf,ny_wrf) REAL, INTENT(OUT) :: tmn_wrf(nx_wrf,ny_wrf) REAL, INTENT(OUT) :: shdmax(nx_wrf,ny_wrf) REAL, INTENT(OUT) :: shdmin(nx_wrf,ny_wrf) REAL, INTENT(OUT) :: albbck(nx_wrf,ny_wrf) REAL, INTENT(OUT) :: snoalb(nx_wrf,ny_wrf) INTEGER, INTENT(OUT) :: istatus INCLUDE 'mp.inc' !----------------------------------------------------------------------- ! ! Misc. local variables ! !----------------------------------------------------------------------- INTEGER, ALLOCATABLE :: soiltypsm (:,:,:) REAL, ALLOCATABLE :: stypfrctsm(:,:,:) INTEGER, ALLOCATABLE :: vegtypsm (:,:) REAL, ALLOCATABLE :: vegsm (:,:) INTEGER :: i, j, ii, jj, ia, ja INTEGER :: lenfil CHARACTER(LEN=256) :: tmpstr !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Begin of executable code ... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ lenfil = LEN_TRIM(sfcdtfl) WRITE(tmpstr,'(a)') TRIM(sfcdtfl) IF(sfcinitopt(1:4) == 'ARPS') THEN DO jj = 1, ncompressy DO ii = 1, ncompressx IF (mp_opt > 0 .AND. readsplit <= 0) THEN WRITE(tmpstr(lenfil+1:lenfil+5),'(a,i2.2,i2.2)') '_', & ncompressx*(loc_x-1)+ii,ncompressy*(loc_y-1)+jj lenfil= lenfil + 5 END IF IF (mp_opt > 0 .AND. readsplit > 0) THEN CALL readsplitsfcdt(nx,ny,nstyps,TRIM(tmpstr),dx,dy, & mapproj,trulat1,trulat2,trulon,sclfct,ctrlat,ctrlon, & soiltyp,stypfrct,vegtyp,tem1(:,:,1),tem1(:,:,2), & veg, tem1(:,:,3)) ELSE ALLOCATE(soiltypsm (nxsm,nysm,nstyps), STAT = istatus) ALLOCATE(stypfrctsm(nxsm,nysm,nstyps), STAT = istatus) ALLOCATE(vegtypsm (nxsm,nysm), STAT = istatus) ALLOCATE(vegsm (nxsm,nysm), STAT = istatus) CALL readsfcdt(nx,ny,nstyps,TRIM(tmpstr),dx,dy, & mapproj,trulat1,trulat2,trulon,sclfct,ctrlat,ctrlon, & soiltypsm,stypfrctsm,vegtypsm,tem1(:,:,1),tem1(:,:,2), & vegsm, tem1(:,:,3)) END IF END DO END DO IF(ncompressx > 1 .OR. ncompressy > 1) THEN ! need join DO j = 1, nysm ja = (jj-1)*(nysm-3)+j DO i = 1, nxsm ia = (ii-1)*(nxsm-3)+i soiltyp(ia,ja,:) = soiltypsm(i,j,:) stypfrct(ia,ja,:) = stypfrctsm(i,j,:) vegtyp(ia,ja) = vegtypsm(i,j) veg(ia,ja) = vegsm(i,j) END DO END DO END IF IF (ALLOCATED(soiltypsm)) DEALLOCATE(soiltypsm) IF (ALLOCATED(stypfrctsm)) DEALLOCATE(stypfrctsm) IF (ALLOCATED(vegtypsm)) DEALLOCATE(vegtypsm) IF (ALLOCATED(vegsm)) DEALLOCATE(vegsm) CALL sfcinterp(nx_wrf,ny_wrf,nx,ny,nstyps,hinterp_needed, & x2d,y2d,xs,ys,iloc,jloc, & soiltyp,stypfrct,vegtyp,veg, & soiltyp_wrf,vegtyp_wrf,vegfrct_wrf,xice,xland) vegfrct_wrf(:,:) = vegfrct_wrf(:,:)*100. IF (myproc == 0) THEN WRITE(6,'(/,2(a,/),3(10x,a/),a,/)') & ' ************************** WARNING ************************', & ' WARNING: Noah land-surface model, sf_surface_physics = 2, requires',& 'annual MAX/MIN veg fraction, MAX snow albedo, background albedo.', & 'However, ARPSSFC does not provide such variables. You had better ', & 'use sfcinitopt = "WRFSI" or "WRF". see arps2wrf.input.', & ' ************************** WARNING ************************' END IF hgt_wrf(:,:) = 0.0 tmn_wrf(:,:) = -999.0 ! indicates it is not available shdmax(:,:) = 0.0 shdmin(:,:) = 0.0 snoalb(:,:) = 0.0 albbck(:,:) = 0.0 istatus = 1 ! change to 0 if you want to read ARPSSFC data ELSE IF(sfcinitopt(1:5) == 'WRFSI') THEN CALL get_sfcdt_wrfsi(TRIM(tmpstr),nx_wrf,ny_wrf,dx_wrf,dy_wrf, & mapproj_wrf,trulat1_wrf,trulat2_wrf,trulon_wrf,jday, & hgt_wrf,soiltyp_wrf,vegtyp_wrf,vegfrct_wrf,xice, & xland,tmn_wrf,shdmin,shdmax,albbck,snoalb,istatus) ELSE IF (sfcinitopt(1:3) == 'WRF') THEN CALL get_sfcdt_wrf(TRIM(tmpstr),nx_wrf,ny_wrf,dx_wrf,dy_wrf, & mapproj_wrf,trulat1_wrf,trulat2_wrf,trulon_wrf,jday, & hgt_wrf,soiltyp_wrf,vegtyp_wrf,vegfrct_wrf,xice, & xland,tmn_wrf,shdmin,shdmax,albbck,snoalb,istatus) ELSE WRITE(6,*) 'Unsupported surface data format: ',sfcinitopt istatus = -1 END IF RETURN END SUBROUTINE get_sfcdt ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE sfcinterp ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE sfcinterp(nx,ny,nx_ext,ny_ext,nstyps_ext,interp, & 1 x2d,y2d,x_ext,y_ext,iloc,jloc, & soiltyp_ext,stypfrct_ext,vegtyp_ext,vegfrct_ext, & soiltyp,vegtyp,vegfrct,xice,xland) !------------------------------------------------------------------ ! ! Purpose: ! Interpolate ARPS surface variables to WRF grid. Those variables ! include soil types, vegtation types, vegatation fraction ! ice flage and land flage etc. ! !------------------------------------------------------------------ IMPLICIT NONE INTEGER, INTENT(IN) :: nx,ny ! WRF grid size INTEGER, INTENT(IN) :: nx_ext,ny_ext ! ARPS grid size INTEGER, INTENT(IN) :: nstyps_ext ! ARPS soil type size LOGICAL, INTENT(IN) :: interp ! whether interpolation is needed REAL, INTENT(IN) :: x2d(nx,ny) REAL, INTENT(IN) :: y2d(nx,ny) INTEGER, INTENT(IN) :: iloc(nx,ny) INTEGER, INTENT(IN) :: jloc(nx,ny) REAL, INTENT(IN) :: x_ext(nx_ext) ! ARPS grid coordinate REAL, INTENT(IN) :: y_ext(ny_ext) INTEGER, INTENT(IN) :: soiltyp_ext(nx_ext,ny_ext,nstyps_ext) INTEGER, INTENT(IN) :: vegtyp_ext(nx_ext,ny_ext) REAL, INTENT(IN) :: stypfrct_ext(nx_ext,ny_ext,nstyps_ext) REAL, INTENT(IN) :: vegfrct_ext(nx_ext,ny_ext) INTEGER, INTENT(OUT) :: soiltyp(nx,ny) INTEGER, INTENT(OUT) :: vegtyp(nx,ny) REAL, INTENT(OUT) :: vegfrct(nx,ny) REAL, INTENT(OUT) :: xice(nx,ny) REAL, INTENT(OUT) :: xland(nx,ny) !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ INTEGER :: i,j INTEGER :: ii,jj INTEGER :: k REAL :: dx,dy REAL :: dxmid,dymid INTEGER :: itmp(1) INTEGER, PARAMETER :: veg_table(14) = (/19,22, 7, 9, 6,11,14, & 13,24, 3,17, 8,19,16 /) ! ! ARPS WRF ! ==== ==== ! 1 ! Desert 19 ! Bar. Sparse Veg. ! 2 ! Tundra 22 ! Mixed Tundra ! 3 ! Grassland 7 ! Grassland ! 4 ! Grassland with shrub cover 9 ! Mix Shrb./Grs. ! 5 ! Grassland with tree cover 6 ! Crop./Wood Mosc ! 6 ! Deciduous forest 11 ! Decids. Broadlf. ! 7 ! Evergreen forest 14 ! Evergrn. Needlf. ! 8 ! Rain forest 13 ! Evergn Broadlf Forest ! 9 ! Ice 24 ! Snow or Ice ! 10 ! Cultivation 3 ! Irrg. Crop. Past. ! 11 ! Bog or marsh 17 ! Herb. Wetland ! 12 ! Dwarf shrub 8 ! Shrubland ! 13 ! Semidesert 19 ! Bar. Sparse Veg. ! 14 ! Water 16 ! Water bodies ! INTEGER, PARAMETER :: soil_table(13) = (/ 1, 2, 3, 4, 6, 7, 8, & 9,10,11,12,14,14 /) ! ! ARPS WRF || ARPS WRF ! ===== ==== || ===== ==== ! 1 1 ! Sand || 8 9 ! Clay loam ! 2 2 ! Loamy sand || 9 10 ! Sandy clay ! 3 3 ! Sandy loam || 10 11 ! Silty clay ! 4 4 ! Silt loam || 11 12 ! Clay ! 5 6 ! Loam || 12 16 ! Ice ! 6 7 ! Sandy clay loam || ! Changed to 14 by Jerry, 10/20/2003 ! 7 8 ! Silty clay loam || 13 14 ! Water ! INTEGER, PARAMETER :: ice = 24 ! vegetation type INTEGER, PARAMETER :: water = 16 ! vegetation type !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ dxmid = (x_ext(3)-x_ext(2))/2.0 dymid = (y_ext(3)-y_ext(2))/2.0 ! !(ii,jj+1) (ii+1,jj+1) ! _____________________ ! | | | ! | | | ! | | | ! |---------|----------| ! | | | ! dymid{| dxmid | | ! |_________|__________| ! (ii,jj) (ii+1,jj) ! ! nearest neighbor interpolation DO j = 1,ny DO i = 1,nx IF(interp) THEN ii = iloc(i,j) jj = jloc(i,j) dx = x2d(i,j) - x_ext(ii) dy = y2d(i,j) - y_ext(jj) IF(dx > dxmid) ii = ii + 1 IF(dy > dymid) jj = jj + 1 ELSE ii = i+1 jj = j+1 END IF vegtyp(i,j) = veg_table(vegtyp_ext(ii,jj)) vegfrct(i,j) = vegfrct_ext(ii,jj) itmp = MAXLOC(stypfrct_ext(ii,jj,:)) k = itmp(1) soiltyp(i,j) = soil_table(soiltyp_ext(ii,jj,k)) xice(i,j) = 0.0 IF(vegtyp(i,j) == ice) xice(i,j) = 1. xland(i,j) = 1.0 IF(vegtyp(i,j) == water) THEN xland(i,j) = 2.0 vegfrct(i,j) = 0 END IF IF(soiltyp(i,j) == 14 .AND. xland(i,j) < 1.5) THEN soiltyp(i,j) = 7 ELSE IF(xland(i,j) > 1.5) THEN soiltyp(i,j) = 14 END IF ! IF(vegtyp(i,j) == 0) & ! WRITE(6,*) 'Vegtyp is zero at i = ',i,' j = ',j ! IF(soiltyp(i,j) == 0) & ! WRITE(6,*) 'Soiltyp is zero at i = ',i,' j = ',j END DO END DO RETURN END SUBROUTINE sfcinterp ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE get_sfcdt_wrfsi ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE get_sfcdt_wrfsi(filnam,nx,ny,dx,dy, & 1,17 mapproj,trulat1,trulat2,trulon,jday, & hgt,soiltyp,vegtyp,vegfrct,xice, & xland,tmn,shdmin,shdmax,albbck,snoalb,istatus) !------------------------------------------------------------------ ! ! PURPOSE: ! Read surface variables from NetCDF static file created by ! gridgen_model of WRFSI package ! ! NOTE: ! Those data must be at the same WRF grid as that specified ! by the arguments. ! !------------------------------------------------------------------ USE wrf_metadata IMPLICIT NONE CHARACTER(LEN=*), INTENT(IN) :: filnam ! static file name INTEGER, INTENT(IN) :: nx,ny ! WRF grid size INTEGER, INTENT(IN) :: mapproj ! Map projection REAL, INTENT(IN) :: dx,dy ! WRF grid length REAL, INTENT(IN) :: trulat1,trulat2,trulon ! Map projection specification INTEGER, INTENT(IN) :: jday ! julian day of the year REAL, INTENT(OUT) :: hgt (nx,ny) INTEGER, INTENT(OUT) :: soiltyp(nx,ny) INTEGER, INTENT(OUT) :: vegtyp (nx,ny) REAL, INTENT(OUT) :: vegfrct(nx,ny) REAL, INTENT(OUT) :: xice (nx,ny) REAL, INTENT(OUT) :: xland (nx,ny) REAL, INTENT(OUT) :: tmn (nx,ny) REAL, INTENT(OUT) :: shdmin (nx,ny) REAL, INTENT(OUT) :: shdmax (nx,ny) REAL, INTENT(OUT) :: albbck (nx,ny) REAL, INTENT(OUT) :: snoalb (nx,ny) INTEGER, INTENT(OUT) :: istatus !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ LOGICAL :: ISAME INTEGER :: nscid REAL, ALLOCATABLE :: landusef(:,:,:) REAL, ALLOCATABLE :: soiltyp_top(:,:,:),soiltyp_bot(:,:,:) INTEGER :: i,j,k INTEGER :: nxlg, nylg REAL, ALLOCATABLE :: var3d1(:,:,:), var3d2(:,:,:), var3d3(:,:,:) REAL, ALLOCATABLE :: var2d(:,:) REAL :: rdummy(1,1,12) INCLUDE 'mp.inc' !----------------------------------------------------------------- INTERFACE SUBROUTINE get_static_landusef(ncid,var3d) INTEGER, INTENT(IN) :: ncid REAL, INTENT(OUT) :: var3d(:,:,:) END SUBROUTINE get_static_landusef SUBROUTINE get_static_soil(ncid,var3d1,var3d2) INTEGER, INTENT(IN) :: ncid REAL, INTENT(OUT) :: var3d1(:,:,:) REAL, INTENT(OUT) :: var3d2(:,:,:) END SUBROUTINE get_static_soil SUBROUTINE get_static_monthly(staticopt,ncid, vartype, jday, & var2d, varin3d, istatus) INTEGER, INTENT(IN) :: staticopt INTEGER, INTENT(IN) :: ncid CHARACTER(LEN=1), INTENT(IN) :: vartype INTEGER, INTENT(IN) :: jday REAL, INTENT(OUT) :: var2d(:,:) REAL, INTENT(IN) :: varin3d(:,:,:) INTEGER, INTENT(OUT) :: istatus END SUBROUTINE get_static_monthly SUBROUTINE get_static_2d(ncid,varname,var2d) INTEGER, INTENT(IN) :: ncid CHARACTER(LEN=3), INTENT(IN) :: varname REAL, INTENT(OUT) :: var2d(:,:) END SUBROUTINE get_static_2d END INTERFACE !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ nxlg = (nx - 1)*nproc_x + 1 nylg = (ny - 1)*nproc_y + 1 ! write(0,*) 'nx = ',nx, 'ny = ',ny, 'nxlg = ',nxlg, 'nylg = ',nylg ALLOCATE(landusef(nx,ny,LanduseCategories), STAT = istatus) ALLOCATE(soiltyp_top(nx,ny,SoilCategories), STAT = istatus) ALLOCATE(soiltyp_bot(nx,ny,SoilCategories), STAT = istatus) ALLOCATE(var3d1(nxlg,nylg,LanduseCategories), STAT = istatus) ALLOCATE(var3d2(nxlg,nylg,SoilCategories), STAT = istatus) ALLOCATE(var3d3(nxlg,nylg,SoilCategories), STAT = istatus) ALLOCATE(var2d (nxlg,nylg), STAT = istatus) ! ! Open the static NetCDF file which is created by gridgen_model. ! IF(myproc == 0) CALL open_static_file(filnam,nscid) ! we need to check whether the static file is ! on the same grid as WRF grid IF(myproc == 0) THEN CALL check_static_grid(0,nscid,nx,ny,dx,dy,mapproj, & trulat1,trulat2,trulon,isame) IF(.NOT. ISAME) CALL mpexit(1) END IF IF (myproc == 0) THEN CALL get_static_landusef(nscid,var3d1) CALL get_static_soil(nscid,var3d2,var3d3) END IF CALL wrf_split3d(var3d1,nx,ny,LanduseCategories,1,landusef) CALL wrf_split3d(var3d2,nx,ny,SoilCategories,1,soiltyp_top) CALL wrf_split3d(var3d3,nx,ny,SoilCategories,1,soiltyp_bot) IF (myproc == 0) CALL get_static_monthly (0,nscid, 'g', jday, var2d, rdummy,istatus) IF (istatus /= 0) CALL mpexit(1) CALL wrf_split2d(var2d,nx,ny,1,vegfrct) IF (myproc == 0) CALL get_static_monthly (0,nscid, 'a', jday, var2d, rdummy,istatus) IF (istatus /= 0) CALL mpexit(1) CALL wrf_split2d(var2d,nx,ny,1,albbck) IF (myproc == 0) CALL get_static_2d(nscid,'gnn',var2d) CALL wrf_split2d(var2d,nx,ny,1,shdmin) IF (myproc == 0) CALL get_static_2d(nscid,'gnx',var2d) CALL wrf_split2d(var2d,nx,ny,1,shdmax) IF (myproc == 0) CALL get_static_2d(nscid,'alb',var2d) CALL wrf_split2d(var2d,nx,ny,1,snoalb) IF (myproc == 0) CALL get_static_2d(nscid,'avc',var2d) CALL wrf_split2d(var2d,nx,ny,1,hgt) IF (myproc == 0) CALL get_static_2d(nscid,'tmp',var2d) CALL wrf_split2d(var2d,nx,ny,1,tmn) IF(myproc == 0) CALL close_static_file(nscid) DEALLOCATE(var3d1,var3d2,var3d3) DEALLOCATE(var2d) !-------------------------------------------------------------------- ! ! Vegetation index and soil texture indexSoilCategories ! !-------------------------------------------------------------------- CALL land_soil_cat(nx,ny,LanduseCategories,SoilCategories, & landusef,soiltyp_top,soiltyp_bot, & vegtyp,soiltyp,xland,xice,istatus) DEALLOCATE(landusef, soiltyp_top, soiltyp_bot) RETURN END SUBROUTINE get_sfcdt_wrfsi ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE get_sfcdt_wrf ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE get_sfcdt_wrf(filnam,nx,ny,dx,dy, & 1,30 mapproj,trulat1,trulat2,trulon,jday, & hgt,soiltyp,vegtyp,vegfrct,xice, & xland,tmn,shdmin,shdmax,albbck,snoalb,istatus) !------------------------------------------------------------------ ! ! PURPOSE: ! Read surface variables from NetCDF static file created by ! staticpost of WRFSI package or wrfstatic from ARPS package ! ! NOTE: ! Those data must be at the same WRF grid as that specified ! by the arguments. ! !------------------------------------------------------------------ USE wrf_metadata IMPLICIT NONE CHARACTER(LEN=*), INTENT(IN) :: filnam ! static file name INTEGER, INTENT(IN) :: nx,ny ! WRF grid size INTEGER, INTENT(IN) :: mapproj ! Map projection REAL, INTENT(IN) :: dx,dy ! WRF grid length REAL, INTENT(IN) :: trulat1,trulat2,trulon ! Map projection specification INTEGER, INTENT(IN) :: jday ! julian day of the year REAL, INTENT(OUT) :: hgt (nx,ny) INTEGER, INTENT(OUT) :: soiltyp(nx,ny) INTEGER, INTENT(OUT) :: vegtyp (nx,ny) REAL, INTENT(OUT) :: vegfrct(nx,ny) REAL, INTENT(OUT) :: xice (nx,ny) REAL, INTENT(OUT) :: xland (nx,ny) REAL, INTENT(OUT) :: tmn (nx,ny) REAL, INTENT(OUT) :: shdmin (nx,ny) REAL, INTENT(OUT) :: shdmax (nx,ny) REAL, INTENT(OUT) :: albbck (nx,ny) REAL, INTENT(OUT) :: snoalb (nx,ny) INTEGER, INTENT(OUT) :: istatus !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ LOGICAL :: ISAME INTEGER :: nscid REAL, ALLOCATABLE :: landusef(:,:,:) REAL, ALLOCATABLE :: soiltyp_top(:,:,:),soiltyp_bot(:,:,:) INTEGER :: i,j,k INTEGER :: nxlg, nylg REAL, ALLOCATABLE :: temdm(:,:,:) REAL, ALLOCATABLE :: var3d1(:,:,:), var3d2(:,:,:), var3d3(:,:,:) REAL, ALLOCATABLE :: var2d(:,:) INCLUDE 'mp.inc' !----------------------------------------------------------------- INTERFACE SUBROUTINE get_static_monthly(staticopt,ncid, vartype, jday, & var2d, varin3d, istatus) INTEGER, INTENT(IN) :: staticopt INTEGER, INTENT(IN) :: ncid CHARACTER(LEN=1), INTENT(IN) :: vartype INTEGER, INTENT(IN) :: jday REAL, INTENT(OUT) :: var2d(:,:) REAL, INTENT(IN) :: varin3d(:,:,:) INTEGER, INTENT(OUT) :: istatus END SUBROUTINE get_static_monthly END INTERFACE !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ nxlg = (nx - 1)*nproc_x + 1 nylg = (ny - 1)*nproc_y + 1 ! write(0,*) 'nx = ',nx, 'ny = ',ny, 'nxlg = ',nxlg, 'nylg = ',nylg ALLOCATE(landusef(nx,ny,LanduseCategories), STAT = istatus) ALLOCATE(soiltyp_top(nx,ny,SoilCategories), STAT = istatus) ALLOCATE(soiltyp_bot(nx,ny,SoilCategories), STAT = istatus) ALLOCATE(var3d1(nxlg,nylg,LanduseCategories), STAT = istatus) ALLOCATE(var3d2(nxlg,nylg,SoilCategories), STAT = istatus) ALLOCATE(var3d3(nxlg,nylg,SoilCategories), STAT = istatus) ALLOCATE(var2d (nxlg,nylg), STAT = istatus) ALLOCATE(temdm(nxlg-1,nylg-1,MAX(LanduseCategories,SoilCategories)), STAT = istatus) ! ! Open the static NetCDF file which is created by wrfstatic. ! IF(myproc == 0) CALL open_static_file(filnam,nscid) ! we need to check whether the static file is ! on the same grid as WRF grid IF(myproc == 0) THEN CALL check_static_grid(1,nscid,nx,ny,dx,dy,mapproj, & trulat1,trulat2,trulon,isame) IF(.NOT. ISAME) CALL mpexit(1) END IF IF (myproc == 0) THEN CALL get_ncd_3d(nscid,1,'LANDUSEF',nxlg-1,nylg-1,LanduseCategories,temdm,istatus) DO k = 1, LanduseCategories DO j = 1,nylg-1 DO i = 1,nxlg-1 var3d1(i,j,k) = temdm(i,j,k) END DO END DO END DO CALL get_ncd_3d(nscid,1,'SOILCTOP',nxlg-1,nylg-1,SoilCategories,temdm,istatus) DO k = 1, SoilCategories DO j = 1,nylg-1 DO i = 1,nxlg-1 var3d2(i,j,k) = temdm(i,j,k) END DO END DO END DO CALL get_ncd_3d(nscid,1,'SOILCBOT',nxlg-1,nylg-1,SoilCategories,temdm,istatus) DO k = 1, SoilCategories DO j = 1,nylg-1 DO i = 1,nxlg-1 var3d3(i,j,k) = temdm(i,j,k) END DO END DO END DO CALL edgfill(var3d1,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,LanduseCategories,1,LanduseCategories) CALL edgfill(var3d2,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,SoilCategories,1,SoilCategories) CALL edgfill(var3d3,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,SoilCategories,1,SoilCategories) END IF CALL wrf_split3d(var3d1,nx,ny,LanduseCategories,1,landusef) CALL wrf_split3d(var3d2,nx,ny,SoilCategories,1,soiltyp_top) CALL wrf_split3d(var3d3,nx,ny,SoilCategories,1,soiltyp_bot) IF (myproc == 0) THEN CALL get_ncd_3d(nscid,1,'GREEN12M',nxlg-1,nylg-1,12,temdm,istatus) DO k = 1, 12 DO j = 1,nylg-1 DO i = 1,nxlg-1 var3d1(i,j,k) = temdm(i,j,k) END DO END DO END DO CALL edgfill(var3d1,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,12,1,12) CALL get_static_monthly (1,nscid, 'g', jday, var2d, var3d1,istatus) END IF IF (istatus /= 0) CALL mpexit(1) CALL wrf_split2d(var2d,nx,ny,1,vegfrct) IF (myproc == 0) THEN CALL get_ncd_3d(nscid,1,'ALBDO12M',nxlg-1,nylg-1,12,temdm,istatus) DO k = 1, 12 DO j = 1,nylg-1 DO i = 1,nxlg-1 var3d2(i,j,k) = temdm(i,j,k) END DO END DO END DO CALL edgfill(var3d2,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,12,1,12) CALL get_static_monthly (1,nscid, 'a', jday, var2d, var3d2,istatus) END IF IF (istatus /= 0) CALL mpexit(1) CALL wrf_split2d(var2d,nx,ny,1,albbck) IF (myproc == 0) THEN CALL get_ncd_2d(nscid,1,'SHDMIN',nxlg-1,nylg-1,temdm,istatus) DO j = 1,nylg-1 DO i = 1,nxlg-1 var2d(i,j) = temdm(i,j,1) END DO END DO CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1) END IF CALL wrf_split2d(var2d,nx,ny,1,shdmin) IF (myproc == 0) THEN CALL get_ncd_2d(nscid,1,'SHDMAX',nxlg-1,nylg-1,temdm,istatus) DO j = 1,nylg-1 DO i = 1,nxlg-1 var2d(i,j) = temdm(i,j,1) END DO END DO CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1) END IF CALL wrf_split2d(var2d,nx,ny,1,shdmax) IF (myproc == 0) THEN CALL get_ncd_2d(nscid,1,'SNOALB',nxlg-1,nylg-1,temdm,istatus) DO j = 1,nylg-1 DO i = 1,nxlg-1 var2d(i,j) = temdm(i,j,1) END DO END DO CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1) END IF CALL wrf_split2d(var2d,nx,ny,1,snoalb) IF (myproc == 0) THEN CALL get_ncd_2d(nscid,1,'HGT',nxlg-1,nylg-1,temdm,istatus) DO j = 1,nylg-1 DO i = 1,nxlg-1 var2d(i,j) = temdm(i,j,1) END DO END DO CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1) END IF CALL wrf_split2d(var2d,nx,ny,1,hgt) IF (myproc == 0) THEN CALL get_ncd_2d(nscid,1,'TMN',nxlg-1,nylg-1,temdm,istatus) DO j = 1,nylg-1 DO i = 1,nxlg-1 var2d(i,j) = temdm(i,j,1) END DO END DO CALL edgfill(var2d,1,nxlg,1,nxlg-1,1,nylg,1,nylg-1,1,1,1,1) END IF CALL wrf_split2d(var2d,nx,ny,1,tmn) IF(myproc == 0) CALL close_static_file(nscid) DEALLOCATE(temdm) DEALLOCATE(var3d1,var3d2,var3d3) DEALLOCATE(var2d) CALL land_soil_cat(nx,ny,LanduseCategories,SoilCategories, & landusef,soiltyp_top,soiltyp_bot, & vegtyp,soiltyp,xland,xice,istatus) DEALLOCATE(landusef, soiltyp_top, soiltyp_bot) RETURN END SUBROUTINE get_sfcdt_wrf ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE land_soil_cat ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE land_soil_cat(nx,ny,land_cat,soil_cat, & 2,1 landusef,soiltyp_top,soiltyp_bot, & vegtyp,soiltyp,xland,xice,istatus) !----------------------------------------------------------------------- ! ! PURPOSE ! Extract dominant landuse and soil texture index ! ! See subroutine process_percent_cat_new in share/module_soil_pre.F ! !----------------------------------------------------------------------- use wrf_metadata IMPLICIT NONE INTEGER, INTENT(IN) :: nx, ny INTEGER, INTENT(IN) :: land_cat, soil_cat REAL, INTENT(IN) :: landusef(nx,ny,land_cat) REAL, INTENT(IN) :: soiltyp_top(nx,ny,soil_cat) REAL, INTENT(IN) :: soiltyp_bot(nx,ny,soil_cat) INTEGER, INTENT(OUT) :: soiltyp(nx,ny) INTEGER, INTENT(OUT) :: vegtyp (nx,ny) REAL, INTENT(OUT) :: xice (nx,ny) REAL, INTENT(OUT) :: xland (nx,ny) INTEGER, INTENT(OUT) :: istatus INTEGER :: i,j,k REAL :: dominant_value INTEGER :: dominant_index !-------------------------------------------------------------------- ! ! Vegetation index and soil texture index SoilCategories ! !-------------------------------------------------------------------- DO j = 1, ny DO i = 1,nx dominant_value = landusef(i,j,1) dominant_index = 1 DO k = 2,LanduseCategories IF(k == ISWATER .AND. landusef(i,j,k) >= 0.5) THEN dominant_value = landusef(i,j,ISWATER) dominant_index = k ELSE IF(k /= ISWATER .AND. landusef(i,j,k) > dominant_value) THEN dominant_value = landusef(i,j,k) dominant_index = k END IF END DO IF(dominant_index == ISWATER) THEN xland(i,j) = 2. ELSE xland(i,j) = 1. END IF vegtyp(i,j) = dominant_index END DO END DO ! Compute the dominant SOIL TEXTURE INDEX, TOP. DO j = 1, ny DO i = 1,nx dominant_value = soiltyp_top(i,j,1) dominant_index = 1 IF(xland(i,j) < 1.5) THEN DO k = 2,SoilCategories IF(k /= ISWATER_SOIL .AND. soiltyp_top(i,j,k) > dominant_value) THEN dominant_value = soiltyp_top(i,j,k) dominant_index = k END IF END DO IF(dominant_value < 0.01) THEN dominant_index = 8 END IF ELSE dominant_index = ISWATER_SOIL END IF soiltyp(i,j) = dominant_index END DO END DO xice = 0. WHERE(vegtyp == ISICE) xice = 1. istatus = 0 RETURN END SUBROUTINE land_soil_cat ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE couple ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE couple(nx,ny,nz,vname,mu,mub,var3d,msf,out3d,tem) 10 !----------------------------------------------------------------- ! ! PURPOSE ! Couple the input variable with the air mass and the map scale ! factor. ! ! NOTE: Refer to the same subroutine in WRF dyn_em/module_big_step_utilities_em.f. ! !---------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: nx,ny,nz CHARACTER(1), INTENT(IN) :: vname REAL, INTENT(IN) :: mu(nx,ny), mub(nx,ny) REAL, INTENT(IN) :: var3d(nx,ny,nz) REAL, INTENT(IN) :: msf(nx,ny) REAL, INTENT(OUT) :: out3d(nx,ny,nz) REAL, INTENT(OUT) :: tem(nx,ny) !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ ! INTEGER :: i,j,k INCLUDE 'mp.inc' !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! tem = 0.0 IF(vname == 'U') THEN CALL wrf_mpsendrecv1de(mu, nx,ny,tem) ! to make sure the fake zone, mu(nx,:) CALL wrf_mpsendrecv1de(mub,nx,ny,tem) ! & mub(nx,:) contains valid data DO j = 1,ny DO i = 2,nx tem(i,j) = 0.5*(mu(i-1,j)+mub(i-1,j)+mu(i,j)+mub(i,j)) END DO END DO tem(1,:) = mu(1,:) + mub(1,:) ! The first row may be invalid !tem(nx,:) = mu(nx-1,:) + mub(nx-1,:) DO k = 1, nz DO j = 1, ny DO i = 1, nx out3d(i,j,k) = var3d(i,j,k)*tem(i,j)/msf(i,j) END DO END DO END DO ELSE IF(vname == 'V') THEN CALL wrf_mpsendrecv1dn(mu, nx,ny,tem) ! to make sure the fake zone, mu(:,ny) CALL wrf_mpsendrecv1dn(mub,nx,ny,tem) ! & mub(:,ny) contains valid data DO j = 2,ny DO i = 1,nx tem(i,j) = 0.5*(mu(i,j-1)+mub(i,j-1)+mu(i,j)+mub(i,j)) END DO END DO tem(:,1) = mu(:,1) + mub(:,1) ! The firs column may be invalid !tem(:,ny) = mu(:,ny-1) + mub(:,ny-1) DO k = 1, nz DO j = 1, ny DO i = 1, nx out3d(i,j,k) = var3d(i,j,k)*tem(i,j)/msf(i,j) END DO END DO END DO ELSE IF(vname == 'W') THEN ! No variable uses this "vname" so far DO k = 1, nz DO j = 1, ny DO i = 1, nx out3d(i,j,k) = var3d(i,j,k)*(mu(i,j)+mub(i,j))/msf(i,j) END DO END DO END DO ELSE ! vname == 'H', or 'T', vertical does not matter here DO k = 1, nz DO j = 1, ny DO i = 1, nx out3d(i,j,k) = var3d(i,j,k)*(mu(i,j)+mub(i,j)) END DO END DO END DO END IF RETURN END SUBROUTINE couple ! !################################################################## !################################################################## !###### ###### !###### FUNCTION stuff_bdy ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE stuff_bdy(nx,ny,nz,bdy_width,stag,var3d,bs,bn,bw,be) !----------------------------------------------------------------- ! ! Assign boundary arrays ! ! NOTE: Refer to the same subroutine in WRF share/module_bc.f. ! !----------------------------------------------------------------- IMPLICIT NONE ! nx,ny and nz must be the non-staggered values INTEGER, INTENT(IN) :: nx,ny,nz,bdy_width CHARACTER(LEN=1), INTENT(IN) :: stag REAL, INTENT(IN) :: var3d(nx,ny,nz) ! coupled variable REAL, INTENT(OUT) :: bs(nx,nz,bdy_width) ! south boundary REAL, INTENT(OUT) :: bn(nx,nz,bdy_width) ! north boundary REAL, INTENT(OUT) :: bw(ny,nz,bdy_width) ! west boundary REAL, INTENT(OUT) :: be(ny,nz,bdy_width) ! east boundary !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ ! INTEGER :: i,j,k INTEGER :: ii,jj !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! X start boundary WEST DO k = 1,nz DO j = 1,ny DO i = 1, bdy_width bw(j,k,i) = var3d(i,j,k) END DO END DO END DO ! X end boundary EAST IF(stag == 'U') THEN DO k = 1,nz DO j = 1,ny DO i = nx, nx-bdy_width+1,-1 ii = nx - i + 1 be(j,k,ii) = var3d(i,j,k) END DO END DO END DO ELSE DO k = 1,nz DO j = 1,ny DO i = nx-1, nx-bdy_width,-1 ii = nx - i be(j,k,ii) = var3d(i,j,k) END DO END DO END DO END IF ! Y start boundary SOUTH DO k = 1, nz DO j = 1, bdy_width DO i = 1, nx bs(i,k,j) = var3d(i,j,k) END DO END DO END DO ! Y end boundary NORTH IF(stag == 'V') THEN DO k = 1, nz DO j = ny, ny-bdy_width+1,-1 DO i = 1, nx jj = ny - j + 1 bn(i,k,jj) = var3d(i,j,k) END DO END DO END DO ELSE DO k = 1, nz DO j = ny-1, ny-bdy_width,-1 DO i = 1, nx jj = ny - j bn(i,k,jj) = var3d(i,j,k) END DO END DO END DO END IF RETURN END SUBROUTINE stuff_bdy ! !################################################################## !################################################################## !###### ###### !###### SUBROTINE stuff_bdytend ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE stuff_bdytend(nx,ny,nz,bdy_width,stag,var3dold,var3dnew, & time_diff,bs,bn,bw,be) !----------------------------------------------------------------- ! ! Compute and assign boundary tendency. ! ! NOTE: Refer to the same subroutine in WRF share/module_bc.f. ! !----------------------------------------------------------------- IMPLICIT NONE ! nx,ny and nz must be the non-staggered values INTEGER, INTENT(IN) :: nx,ny,nz,bdy_width CHARACTER(LEN=1), INTENT(IN) :: stag REAL, INTENT(IN) :: var3dold(nx,ny,nz) REAL, INTENT(IN) :: var3dnew(nx,ny,nz) REAL, INTENT(IN) :: time_diff REAL, INTENT(OUT) :: bs(nx,nz,bdy_width) ! south boundary tendency REAL, INTENT(OUT) :: bn(nx,nz,bdy_width) ! north REAL, INTENT(OUT) :: bw(ny,nz,bdy_width) ! west REAL, INTENT(OUT) :: be(ny,nz,bdy_width) ! east !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ ! INTEGER :: i,j,k INTEGER :: ii,jj !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! X start boundary WEST DO k = 1,nz DO j = 1,ny DO i = 1, bdy_width bw(j,k,i) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff END DO END DO END DO ! X end boundary EAST IF(stag == 'U') THEN DO k = 1,nz DO j = 1,ny DO i = nx, nx-bdy_width+1,-1 ii = nx - i + 1 be(j,k,ii) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff END DO END DO END DO ELSE DO k = 1,nz DO j = 1,ny DO i = nx-1, nx-bdy_width,-1 ii = nx - i be(j,k,ii) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff END DO END DO END DO END IF ! Y start boundary SOUTH DO k = 1, nz DO j = 1, bdy_width DO i = 1, nx bs(i,k,j) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff END DO END DO END DO ! Y end boundary NORTH IF(stag == 'V') THEN DO k = 1, nz DO j = ny, ny-bdy_width+1,-1 DO i = 1, nx jj = ny - j + 1 bn(i,k,jj) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff END DO END DO END DO ELSE DO k = 1, nz DO j = ny-1, ny-bdy_width,-1 DO i = 1, nx jj = ny - j bn(i,k,jj) = (var3dnew(i,j,k)-var3dold(i,j,k))/time_diff END DO END DO END DO END IF RETURN END SUBROUTINE stuff_bdytend ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE stuff_bdy2d ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE stuff_bdy2d(nx,ny,nz,bdy_width,var2d,bs,bn,bw,be) !------------------------------------------------------------------ ! ! Assign boundary arrays for 2D array. ! !----------------------------------------------------------------- IMPLICIT NONE ! nx,ny and nz must be the non-staggered values INTEGER, INTENT(IN) :: nx,ny,nz,bdy_width REAL, INTENT(IN) :: var2d(nx,ny) REAL, INTENT(OUT) :: bs(nx,nz,bdy_width) ! south boundary array REAL, INTENT(OUT) :: bn(nx,nz,bdy_width) ! north REAL, INTENT(OUT) :: bw(ny,nz,bdy_width) ! west REAL, INTENT(OUT) :: be(ny,nz,bdy_width) ! east !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ ! INTEGER :: i,j,k INTEGER :: ii,jj !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! X start boundary WEST DO k = 1,nz DO j = 1,ny DO i = 1, bdy_width bw(j,k,i) = var2d(i,j) END DO END DO END DO ! X end boundary EAST DO k = 1,nz DO j = 1,ny DO i = nx-1, nx-bdy_width,-1 ii = nx - i be(j,k,ii) = var2d(i,j) END DO END DO END DO ! Y start boundary SOUTH DO k = 1, nz DO j = 1, bdy_width DO i = 1, nx bs(i,k,j) = var2d(i,j) END DO END DO END DO ! Y end boundary NORTH DO k = 1, nz DO j = ny-1, ny-bdy_width,-1 DO i = 1, nx jj = ny - j bn(i,k,jj) = var2d(i,j) END DO END DO END DO RETURN END SUBROUTINE stuff_bdy2d ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE stuff_bdytend2d ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE stuff_bdytend2d(nx,ny,nz,bdy_width,var2dold,var2dnew, & time_diff,bs,bn,bw,be) IMPLICIT NONE ! nx,ny and nz must be the non-staggered values INTEGER, INTENT(IN) :: nx,ny,nz,bdy_width REAL, INTENT(IN) :: var2dold(nx,ny) REAL, INTENT(IN) :: var2dnew(nx,ny) REAL, INTENT(IN) :: time_diff REAL, INTENT(OUT) :: bs(nx,nz,bdy_width) REAL, INTENT(OUT) :: bn(nx,nz,bdy_width) REAL, INTENT(OUT) :: bw(ny,nz,bdy_width) REAL, INTENT(OUT) :: be(ny,nz,bdy_width) !------------------------------------------------------------------ ! ! Misc. local variables ! !------------------------------------------------------------------ ! INTEGER :: i,j,k INTEGER :: ii,jj !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Beginning of executable code... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! X start boundary WEST DO k = 1,nz DO j = 1,ny DO i = 1, bdy_width bw(j,k,i) = (var2dnew(i,j)-var2dold(i,j))/time_diff END DO END DO END DO ! X end boundary EAST DO k = 1,nz DO j = 1,ny DO i = nx-1, nx-bdy_width,-1 ii = nx - i be(j,k,ii) = (var2dnew(i,j)-var2dold(i,j))/time_diff END DO END DO END DO ! Y start boundary SOUTH DO k = 1, nz DO j = 1, bdy_width DO i = 1, nx bs(i,k,j) = (var2dnew(i,j)-var2dold(i,j))/time_diff END DO END DO END DO ! Y end boundary NORTH DO k = 1, nz DO j = ny-1, ny-bdy_width,-1 DO i = 1, nx jj = ny - j bn(i,k,jj) = (var2dnew(i,j)-var2dold(i,j))/time_diff END DO END DO END DO RETURN END SUBROUTINE stuff_bdytend2d ! !################################################################## !################################################################## !###### ###### !###### SUBROUTINE rotate_UV ###### !###### ###### !###### Developed by ###### !###### Center for Analysis and Prediction of Storms ###### !###### University of Oklahoma ###### !###### ###### !################################################################## !################################################################## ! SUBROUTINE rotate_UV(nx_wrf,ny_wrf,nz_wrf,mapproj,sclfct,latnot,trulon, & 1,11 swx_arps,swy_arps,mapproj_wrf, & sclfct_wrf,lattru_wrf,lontru_wrf,swx_wrf,swy_wrf, & lonu_wrf,lonv_wrf,u_wrf,v_wrf,uatv_wrf,vatu_wrf, & tem1,tem2,tem3,tem4,istatus) ! !----------------------------------------------------------------------- ! ! PURPOSE: ! ! Get uatv_wrf & vatu_wrf for doing horizontal interpolation. ! Do not support mpi. ! !----------------------------------------------------------------------- IMPLICIT NONE INTEGER, INTENT(IN) :: nx_wrf, ny_wrf, nz_wrf INTEGER, INTENT(IN) :: mapproj, mapproj_wrf REAL, INTENT(IN) :: sclfct, sclfct_wrf REAL, INTENT(IN) :: latnot(2),lattru_wrf(2) REAL, INTENT(IN) :: trulon, lontru_wrf REAL, INTENT(IN) :: swx_arps, swx_wrf REAL, INTENT(IN) :: swy_arps, swy_wrf REAL, INTENT(IN) :: lonu_wrf(nx_wrf,ny_wrf) REAL, INTENT(IN) :: lonv_wrf(nx_wrf,ny_wrf) REAL, INTENT(INOUT) :: u_wrf(nx_wrf,ny_wrf,nz_wrf) REAL, INTENT(INOUT) :: v_wrf(nx_wrf,ny_wrf,nz_wrf) REAL, INTENT(OUT) :: uatv_wrf(nx_wrf,ny_wrf,nz_wrf) REAL, INTENT(OUT) :: vatu_wrf(nx_wrf,ny_wrf,nz_wrf) REAL, INTENT(OUT) :: tem1(nx_wrf,ny_wrf,nz_wrf) REAL, INTENT(OUT) :: tem2(nx_wrf,ny_wrf,nz_wrf) REAL, INTENT(OUT) :: tem3(nx_wrf,ny_wrf,nz_wrf) REAL, INTENT(OUT) :: tem4(nx_wrf,ny_wrf,nz_wrf) INTEGER, INTENT(OUT) :: istatus !----------------------------------------------------------------------- ! ! Misc. local variables ! !----------------------------------------------------------------------- INTEGER :: i, j, k INTEGER :: iproj REAL :: scl, trlat(2), trlon,x0,y0 !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! ! Begin of executable code ... ... ! !@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ! !----------------------------------------------------------------------- ! ! Save previous map projection values ! !----------------------------------------------------------------------- ! CALL getmapr(iproj,scl,trlat,trlon,x0,y0) ! !----------------------------------------------------------------------- ! ! Get uatv and vatu ! !----------------------------------------------------------------------- ! DO k=1,nz_wrf ! get u at v grid point locations DO j=2,ny_wrf DO i=1,nx_wrf-1 uatv_wrf(i,j,k) = 0.25*(u_wrf(i,j-1,k)+u_wrf(i+1,j-1,k) & + u_wrf(i,j,k)+u_wrf(i+1,j,k)) END DO END DO DO i=1,nx_wrf-1 uatv_wrf(i,1,k) = 0.5*(u_wrf(i,1,k)+u_wrf(i+1,1,k)) END DO DO j=2,ny_wrf uatv_wrf(nx_wrf,j,k) = 0.5*(u_wrf(nx_wrf,j-1,k)+u_wrf(nx_wrf,j,k)) END DO uatv_wrf(nx_wrf,1,k) = u_wrf(nx_wrf,1,k) ! get v at u grid point locations DO j=1,ny_wrf-1 DO i=2,nx_wrf vatu_wrf(i,j,k) = 0.25*(v_wrf(i-1,j,k)+v_wrf(i,j,k) & +v_wrf(i-1,j+1,k)+v_wrf(i,j+1,k)) END DO END DO DO j=1,ny_wrf-1 vatu_wrf(1,j,k) = 0.5*(v_wrf(1,j,k)+v_wrf(1,j+1,k)) END DO DO i=2,nx_wrf vatu_wrf(i,ny_wrf,k) = 0.5*(v_wrf(i-1,ny_wrf,k)+v_wrf(i,ny_wrf,k)) END DO vatu_wrf(1,ny_wrf,k) = v_wrf(1,ny_wrf,k) END DO ! !----------------------------------------------------------------------- ! ! Establish ARPS map projection ! !----------------------------------------------------------------------- ! CALL setmapr(mapproj,sclfct,latnot,trulon) CALL setorig(1,swx_arps,swy_arps) ! !----------------------------------------------------------------------- ! ! Rotate from ARPS grid to earth-relative ! !----------------------------------------------------------------------- ! DO k = 1,nz_wrf CALL uvmptoe(nx_wrf,ny_wrf,u_wrf(:,:,k),vatu_wrf(:,:,k), & lonu_wrf,tem1(:,:,k),tem2(:,:,k)) CALL uvmptoe(nx_wrf,ny_wrf,uatv_wrf(:,:,k),v_wrf(:,:,k), & lonv_wrf,tem3(:,:,k),tem4(:,:,k)) END DO ! tem1 = u, tem2 = vatu ! tem3 = uatv, tem4 = v ! !----------------------------------------------------------------------- ! ! Establish WRF map projection ! !----------------------------------------------------------------------- ! CALL setmapr(mapproj_wrf,sclfct_wrf,lattru_wrf,lontru_wrf) CALL setorig( 1, swx_wrf, swy_wrf) ! !----------------------------------------------------------------------- ! ! Rotate from earth to WRF grid-relative ! !----------------------------------------------------------------------- ! DO k = 1,nz_wrf CALL uvetomp(nx_wrf,ny_wrf,tem1(:,:,k),tem2(:,:,k), & lonu_wrf,u_wrf(:,:,k),vatu_wrf(:,:,k)) CALL uvetomp(nx_wrf,ny_wrf,tem3(:,:,k),tem4(:,:,k), & lonv_wrf,uatv_wrf(:,:,k),v_wrf(:,:,k)) END DO ! !----------------------------------------------------------------------- ! ! Reset map projection to previous values ! !----------------------------------------------------------------------- ! CALL setmapr(iproj,scl,trlat,trlon) CALL setorig(1,x0,y0) istatus = 0 RETURN END SUBROUTINE rotate_UV