!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE RADIATION ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE radiation(nx,ny,nz,rbufsz, & 2,4
ptprt,pprt,qv,qc,qr,qi,qs,qh, &
ptbar,pbar,ppi,rhostr, &
x,y,z,zp,j3inv, &
soiltyp, tsfc, wetsfc,snowdpth, &
radfrc, radsw, rnflx,radswnet,radlwin, &
rsirbm,rsirdf,rsuvbm,rsuvdf, &
cosz, cosss, &
fdirir,fdifir,fdirpar,fdifpar, &
tem1, tem2, tem3, tem4, tem5, &
tem6, tem7, tem8, tem9, tem10, &
tem11,tem12,tem13,tem14,tem15,tem16, &
radbuf, sh, tem17)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! This subroutine is the main driver of ARPS radiation package. To
! control the driver, the parameters and variables should be set:
!
! Input control variables (in namelist &radiation, arps.input)
!
! radopt Option to switch on/off radiation physics
! = 0, No radiation physics;
! = 1, Simplified surface radiation physics;
! = 2, Atmospheric radiation transfer parameterization.
!
! Notes: When sfcphy is chosen to 3 or 4, radopt=0 will be adjusted
! to 1 in order to compute the surface energy balance for
! soil model. However radopt=2 will not be changed.
!
! radstgr Option for radiation computing at staggering points
! = 0, No staggering; Radiation calculation on x-y plane is at
! all points;
! = 1, staggering; Radiation calculation on x-y plane is at
! (even,even) and (odd,odd) points. The values at
! (even,odd) (odd,even) points are averaged from the
! surrounding four points. For example for nx=ny=9, the
! directly calculation are performed at the "x" points,
! then calculate radiation variables at "o" by averaging
! from their surrounding "x" points. This scheme can
! reduce ALMOST HALF of radiation calculation.
!
!
! j
!
! 9 | x o x o x o x o x
! 8 | o x o x o x o x o
! 7 | x o x o x o x o x
! 6 | o x o x o x o x o
! 5 | x o x o x o x o x
! 4 | o x o x o x o x o
! 3 | x o x o x o x o x
! 2 | o x o x o x o x o
! 1 | x o x o x o x o x
! +------------------- i
! 1 2 3 4 5 6 7 8 9
!
! On boundary, the zero-gradient is assumed.
!
! rlwopt Option to choose the longwave schemes.
! = 0, high = .false. in code, transmission functions are
! computed using the k-distribution method with linear
! pressure scaling. cooling rates are not calculated
! accurately for pressures less than 20 mb. The
! computation is faster with high=.false. than with
! high=.true.
! = 1, high = .true. in code, transmission functions in the
! co2, o3 in the co2, o3, and the three water vapor bands
! with strong absorption are computed using table look-up.
! cooling rates are computed accurately from the surface
! up to 0.01 mb.
!
! dtrad Time interval (seconds) to update the radiation forcing
!
! raddiag Option to dump radiation variables to a file in GrADS
! format for diagnostic review. The frequency is
! controled by dtrad. (Effective when radopt=2)
! = 0, no such dump
! = 1, dump to a file with a name like 'runname.radout'
! and its control file has a name like 'runname.radctl'
!
!-----------------------------------------------------------------------
!
! AUTHOR: Yuhe Liu
! 03/11/1996
!
! MODIFICATION HISTORY:
!
! 4/13/98 (D.Weber and V. Wong)
! Added precipitable water term in the radopt=1 air emissivity
! coefficient.
!
! 11/18/98 (Keith Brewster)
! Changed pibar to ppi (full pi).
!
! 12/8/1998 (Donghai Wang and Vince Wong)
! Added a new 2-D permanent array, snowcvr(nx,ny), for snow cover.
! We just used a simple scheme to consider the snow cover process.
!
! 2000/01/10 (Gene Bassett)
! Snow cover (0 or 1) changed to a fractional value (0 to 1)
! determined from snow depth.
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
INTEGER :: nx,ny,nz
INTEGER :: rbufsz
!
!-----------------------------------------------------------------------
!
! Define ARPS variables
!
!-----------------------------------------------------------------------
!
REAL :: ptprt (nx,ny,nz)
REAL :: pprt (nx,ny,nz)
REAL :: qv (nx,ny,nz)
REAL :: qc (nx,ny,nz)
REAL :: qr (nx,ny,nz)
REAL :: qi (nx,ny,nz)
REAL :: qs (nx,ny,nz)
REAL :: qh (nx,ny,nz)
REAL :: ptbar (nx,ny,nz)
REAL :: pbar (nx,ny,nz)
REAL :: ppi (nx,ny,nz)
REAL :: rhostr(nx,ny,nz)
REAL :: x (nx)
REAL :: y (ny)
REAL :: z (nz)
REAL :: zp (nx,ny,nz) ! The physical height coordinate defined at
! w-point of staggered grid.
REAL :: j3inv (nx,ny,nz)
INTEGER :: soiltyp(nx,ny) ! Soil type at each point
REAL :: tsfc (nx,ny)
REAL :: wetsfc (nx,ny) ! Surface soil moisture in the top 1 cm layer
REAL :: snowdpth(nx,ny) ! Snow depth (m)
REAL :: radfrc(nx,ny,nz) ! Radiation forcing (K/s)
REAL :: radsw (nx,ny) ! Solar radiation down to the surface
REAL :: rnflx (nx,ny) ! Net radiation flux absorbed by surface
REAL :: radswnet (nx,ny) ! Net solar radiation
REAL :: radlwin (nx,ny) ! Incoming longwave radiation
REAL :: rsirbm(nx,ny) ! Solar IR surface albedo for beam radiation
REAL :: rsirdf(nx,ny) ! Solar IR surface albedo for diffuse radiation
REAL :: rsuvbm(nx,ny) ! Solar UV surface albedo for beam radiation
REAL :: rsuvdf(nx,ny) ! Solar UV surface albedo for diffuse radiation
REAL :: cosz (nx,ny) ! Cosine of zenith
REAL :: cosss (nx,ny) ! Cosine of angle between sun light and
! surface terrain slope
REAL :: fdirir (nx,ny) ! all-sky direct downward IR flux
! (0.7-10 micron) at the surface
REAL :: fdifir (nx,ny) ! all-sky diffuse downward IR flux
! at the surface
REAL :: fdirpar(nx,ny) ! all-sky direct downward par flux
! (0.4-0.7 micron) at the surface
REAL :: fdifpar(nx,ny) ! all-sky diffuse downward par flux
! at the surface
REAL :: radbuf(rbufsz) ! temporary arrays used for radiation
! transfer computing
!
!-----------------------------------------------------------------------
!
! Temporary arrays which have the vertical coordinate inversed, that
! is, k=1 is for top while k=nz is at the surface.
!
!-----------------------------------------------------------------------
!
REAL :: tem1 (nx,ny,nz) ! pinv, slpmag, slpdir
REAL :: tem2 (nx,ny,nz) ! tinv
REAL :: tem3 (nx,ny,nz) ! qvinv
REAL :: tem4 (nx,ny,nz) ! o3a
REAL :: tem5 (nx,ny,nz) ! ccld
REAL :: tem6 (nx,ny,nz) ! flxir
REAL :: tem7 (nx,ny,nz) ! flcir
REAL :: tem8 (nx,ny,nz) ! flxuv
REAL :: tem9 (nx,ny,nz) ! flcuv
REAL :: tem10(nx,ny,nz) ! dfdts
REAL :: tem11(nx,ny,nz) ! tauir
REAL :: tem12(nx,ny,nz) ! taual
REAL :: tem13(nx,ny,nz) ! tauswi
REAL :: tem14(nx,ny,nz) ! tauswl
REAL :: tem15(nx,ny,nz) ! reffi
REAL :: tem16(nx,ny,nz) ! reffl
! add variable sh(nx,ny) & tem17
REAL :: sh(nx,ny) ! Work array for radiation shade
! shadow induced by a topography
! = 1 not shaded, =0 shaded
REAL :: tem17(nx,ny,nz) ! Work array for message passing
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
!
INCLUDE 'globcst.inc'
INCLUDE 'phycst.inc'
INCLUDE 'radcst.inc'
INCLUDE 'soilcst.inc'
!
!-----------------------------------------------------------------------
!
! Local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j,k
REAL :: albedo, albedoz
! augustin
! add variables saltitude,sazimuth
! they are outputs of ZENANGL and inputs of SHADE
!
REAL :: saltitude,sazimuth ! solar altitude and azimuth
REAL :: tema,temb
REAL :: rad2deg
REAL :: frac_snowcover
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
IF ( radopt == 1 .AND. ( sfcphy /= 3 .AND. sfcphy /= 4 ) ) THEN
RETURN
END IF
!
!-----------------------------------------------------------------------
!
! Calculate solar zenith angle. Array radsw is used as a2dr2
! temporarily.
!
! zp(*,*,2) = surface terrain
! cosz = cosine of zenith
! cosss = cosine of angle between sun light and terrain slope
!
! radsw = a2dr2, square ratio of average distance to the time
! dependent distance from the earth to the sun
!
! Array tem1 and tem2 are used as temporary 2-D arrays
!
! tem1(*,*,1) = rjday
! tem1(*,*,2) = tloc
! tem1(*,*,3) = latscl
! tem1(*,*,4) = lonscl
!
! tem2(*,*,1) = slpmag
! tem2(*,*,2) = slpdir
! tem2(*,*,3) = tem1(*,*)
! tem2(*,*,4) = tem2(*,*)
!
!-----------------------------------------------------------------------
!augustin
! add saltitude and sazimuth in the outputs of zenangl
CALL zenangl
( nx,ny, x,y, zp(1,1,2), cosz, cosss, radsw, &
tem1(1,1,1),tem1(1,1,2),tem1(1,1,3),tem1(1,1,4), &
tem2(1,1,1),tem2(1,1,2),tem2(1,1,3),tem2(1,1,4), &
saltitude,sazimuth )
!
!-----------------------------------------------------------------------
! augustin added shade
!
! Computes the shade induced by a topography
!
! radshade = 0 no shade computed
! radshade = 1 shade computed
! radshade = 2 shade computed on the whole topography
! but only sh(i=1,nx,j=ny/2) is used
! (useful for idealized norht south oriented valleys )
!
!-----------------------------------------------------------------------
!
sh(:,:) = 1.0 ! default for radshade == 0
! If radshade = 0 the matrix shade is set to 1
! at every grid point
IF ( radshade /= 0 ) &
CALL shade
(nx,ny,x,y,saltitude,sazimuth,zp(:,:,2),sh)
!
!-----------------------------------------------------------------------
!
! Calculate surface albedo which is dependent on solar zenith angle
! and soil moisture. Set the albedo for different types of solar
! flux to be same.
!
! rsirbm Solar IR surface albedo for beam radiation
! rsirdf Solar IR surface albedo for diffuse radiation
! rsuvbm Solar UV surface albedo for beam radiation
! rsuvdf Solar UV surface albedo for diffuse radiation
!
!-----------------------------------------------------------------------
!
rad2deg = 180.0/3.141592654
DO j=1,ny-1
DO i=1,nx-1
albedoz = 0.01 * ( EXP( 0.003286 & ! zenith dependent albedo
* SQRT( ( ACOS(cosz(i,j))*rad2deg ) ** 3 ) ) - 1.0 )
IF ( sfcphy == 0 ) THEN ! soil type not defined
tema = 0
ELSE
tema = wetsfc(i,j)/wsat(soiltyp(i,j))
END IF
frac_snowcover = MIN(snowdpth(i,j)/snowdepth_crit, 1.0)
IF ( tema > 0.5 ) THEN
albedo = albedoz + (1.-frac_snowcover)*0.14 &
+ frac_snowcover*snow_albedo
ELSE
albedo = albedoz + (1.-frac_snowcover)*(0.31 - 0.34 * tema) &
+ frac_snowcover*snow_albedo
END IF
rsirbm(i,j) = albedo
rsirdf(i,j) = albedo
rsuvbm(i,j) = albedo
rsuvdf(i,j) = albedo
END DO
END DO
IF ( radopt == 1 ) THEN
DO k=1,nz-1
DO j=1,ny-1
DO i=1,nx-1
tem2(i,j,k) = (ptbar(i,j,k)+ptprt(i,j,k))*ppi(i,j,k)
tem3(i,j,k) = pbar(i,j,k) + pprt(i,j,k)
END DO
END DO
END DO
!
!-----------------------------------------------------------------------
!
! Calculate solar radiation at the surface using a simplified
! scheme.
!
! tem1(*,*,1) = prcpln, precipitation path length
!
! tem2 = temperature
! tem3 = total pressure
!
! fdirir = fraction of solar radiation reaching the surface
!
! Note: added precipitable water contribution to the emissa term
! for radopt=1.
!
!-----------------------------------------------------------------------
!
CALL solrsfc
( nx,ny,nz, &
tem2, tem3, qv, cosz, tem1(1,1,1), fdirir )
DO j=1,ny-1
DO i=1,nx-1
tema = 0.5 * ( tem2(i,j,1) + tem2(i,j,2) ) ! surface air temp.
!
! new code to include the water part of the downward emissa
! coefficient....
!
temb = 0.0
DO k = 2,nz-2
temb = temb+rhostr(i,j,k)*qv(i,j,k)*(zp(i,j,k+1)-zp(i,j,k))
END DO
temb = 0.17*ALOG10(temb*0.1)
temb = MIN(1.0,temb+emissa)
! end of new code for emissa..
! augustin
! if the shading is not taken into account this just mutliplies radsw
! and rnflx by 1
!
! else it sets radsw to zero in the shaded area
! and it sets to zero the direct compounds of the net radiation flux
radsw(i,j) = solarc * radsw(i,j) * cosss(i,j) * fdirir(i,j) &
* sh(i,j)
rnflx(i,j) = radsw(i,j) * (1.0-rsirbm(i,j)) &
+ temb * sbcst * tema**4 &
- emissg * sbcst * tsfc(i,j)**4
radswnet(i,j) = 0.9*radsw(i,j)
radlwin(i,j) = temb * sbcst * tema**4
END DO
END DO
ELSE IF ( radopt == 2 ) THEN
!
!-----------------------------------------------------------------------
!
! Compute the atmospheric radiation forcing
!
! Temporary arrays are used for
!
! tem1 = pinv, Pressure in mb at scalar points
! tem2 = tinv, Temperature
! tem3 = qvinv, Water vapor mixing ratio (g/g)
! tem4 = o3a, Ozone (o3) mixing ratio (g/g)
! tem5 = ccld, Cloud coverage (fraction)
! tem6 = flxir, all-sky net downward LW flux
! tem7 = flcir, clear-sky net downward LW flux
! tem8 = flxuv, all-sky solar flux (downward minus upward)
! tem9 = flcuv, clear-sky solar flux (downward minus upward)
! tem10 = dfdts, Sensitivity of net downward flux to surface temperature
! tem11 = tauir, Cloud optical depth for LW IR
! tem12 = taual, Aerosol optical thickness
! tem13 = tauswi, Cloud optical depth for solar IR for ice particles
! tem14 = tauswl, Cloud optical depth for solar IR for liquid particles
! tem15 = reffi, Effective cloud-particle size for ice particles
! tem16 = reffl, Effective cloud-particle size for liquid particles
!
! cosss = cosine of angle between sun light and terrain slope
!
! radsw = a2dr2, input, square ratio of average distance to the
! time dependent distance from the earth to
! the sun
! = radsw, output, solar radiation reaching the surface
! rnflx = st4, temporary, longwave upward flux at surface
! = rnflx, output, net radiation flux absorbed by surface
!
!-----------------------------------------------------------------------
! augustin add sh
!
CALL radtrns
(nx,ny,nz, rbufsz, &
ptprt,pprt,qv,qc,qr,qi,qs,qh, &
ptbar,pbar,ppi,rhostr, tsfc, &
x,y,z,zp, j3inv, &
radfrc, radsw,rnflx,radswnet,radlwin, cosss, &
rsirbm,rsirdf,rsuvbm,rsuvdf, cosz, &
fdirir,fdifir,fdirpar,fdifpar, rnflx, &
tem1, tem2, tem3, tem4, tem5, &
tem6, tem7, tem8, tem9, tem10, &
tem11,tem12,tem13,tem14,tem15,tem16, &
radbuf,sh, tem17)
END IF
RETURN
END SUBROUTINE radiation
!
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE SOLRSFC ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE solrsfc(nx,ny,nz, & 1
temp, pres, qv, cosz, prcpln, trsw )
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Calculate the atmosphere transmittance for solar radiation
!
!-----------------------------------------------------------------------
!
! AUTHOR: Yuhe Liu
! 03/25/1996
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
INTEGER :: nx,ny,nz
!
!-----------------------------------------------------------------------
!
! Define ARPS variables
!
!-----------------------------------------------------------------------
!
REAL :: temp (nx,ny,nz) ! temperature
REAL :: pres (nx,ny,nz) ! total pressure
REAL :: qv (nx,ny,nz) ! Mixing ratio
REAL :: cosz (nx,ny)
REAL :: prcpln(nx,ny) ! Precipitation path length
REAL :: trsw (nx,ny)
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
!
INCLUDE 'globcst.inc'
INCLUDE 'phycst.inc'
INCLUDE 'soilcst.inc'
!
!-----------------------------------------------------------------------
!
! Local variables
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j,k
REAL :: dirf
REAL :: trrg
REAL :: trwv
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
!
!-----------------------------------------------------------------------
!
! Calculate the precipitation path length by a vertical integral if
! moist > 0.
!
!-----------------------------------------------------------------------
!
DO j = 1, ny-1
DO i = 1, nx-1
prcpln(i,j) = 0.0
END DO
END DO
IF ( moist /= 0 ) THEN
DO j = 1, ny-1
DO i = 1, nx-1
prcpln(i,j) = 0.0
DO k = 2, nz-2
prcpln(i,j) = prcpln(i,j) &
+ 0.5*(qv(i,j,k)+qv(i,j,k+1)) &
* 0.5*(pres(i,j,k)+pres(i,j,k+1))/101300.0 &
* SQRT(2.*273.16/(temp(i,j,k)+temp(i,j,k+1))) &
* (pres(i,j,k)-pres(i,j,k+1))
END DO
prcpln(i,j) = prcpln(i,j) / g
END DO
END DO
END IF
DO j = 1, ny-1
DO i = 1, nx-1
!
!-----------------------------------------------------------------------
!
! Calculate the direction fractor of transmisivity
!
!-----------------------------------------------------------------------
!
dirf = 35.0 / SQRT( 1224.0 * cosz(i,j)**2 + 1.0 )
!
!-----------------------------------------------------------------------
!
! Calculate Rayleigh sccattering and absorption transmisivity, trrg.
!
!-----------------------------------------------------------------------
!
trrg = 1.021 - 0.084 * SQRT( dirf &
* ( 949. * 0.5*(pres(i,j,2)+pres(i,j,1)) &
* 1.e-8 + .051 ) )
! Rayleigh scatt. and abs. transmission
! AB, Eq. 2, psfc in Pascal
!
!-----------------------------------------------------------------------
!
! Calculate the transmisivity of water vapor, trwv. The
! precipitation path length used in the calculation has been
! calculated and stored in prcpln(i,j).
!
! For cloud cover, use constant dirfc = 5/3 as the direction
! fractor. (How to determine if cloudy or not?)
!
! For clear sky, use dirf as the direction fractor, instead of dirfc
!
!-----------------------------------------------------------------------
!
trwv = 1.0 - 2.9 * prcpln(i,j) * dirf &
/ ( 5.925 * prcpln(i,j) * dirf &
+ ( 1. + 141.5 * prcpln(i,j) * dirf ) ** 0.634 )
!
!-----------------------------------------------------------------------
!
! Calculate the fraction of solar radiation reaching the surface.
!
!-----------------------------------------------------------------------
!
trsw(i,j) = trrg * trwv
END DO
END DO
RETURN
END SUBROUTINE solrsfc
!
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE ZENANGL ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE zenangl(nx,ny, x,y, hterain, cosz, cosss, a2dr2, & 1,5
rjday,tloc, latscl,lonscl, slpmag,slpdir, &
tem1,tem2,saltitude,sazimuth)
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! Calculate cosine of solar zenith angle.
!
!-----------------------------------------------------------------------
!
! AUTHOR: Yuhe Liu and Vince Wong
! 11/16/93
!
! MODIFICATION HISTORY:
! 2/2/99 Vince Wong and Jik Leong
! This modification calculates the solar declination angle and
! equation of time using a method found on page C24 of the
! 1996 Astronomical Almanac.
! The mothod is good to 0.01 degrees in the sky over the
! period 1950 to 2050.
!
! augustin
! 8/23/01 Augustin Colette EFML/ Stanford University
!
! Computation of the solar altitude and azimuth
! saltitude and sazimuth are outputs of zenangl to be used in shade
! sources:
! http://www.usc.edu/dept/architecture/mbs/tools/vrsolar/Help/ &
! solar_concepts.html
! http://www.uwinnipeg.ca/~blair/physclim/lab2.htm
! http://ra.stsci.edu/cgi-bin/gethelp.cgi?altaz.src
!
!-----------------------------------------------------------------------
!
! INPUT:
!
! nx Number of grid points in the x-direction (east/west)
! ny Number of grid points in the y-direction (north/south)
!
! x X coordinates at scalar points
! y Y coordinates at scalar points
! hterain Surface terrain
!
! OUTPUT:
!
! cosz Cosine of zenith
! cosss Cosine of angle between sun light and terrain slope
! a2dr2 Square ratio of average distance to the time
! dependent distance from the earth to the sun
!
!augustin
! sazimuth solar azimuth
! saltitude solar altitude
!
! WORK ARRAY:
!
! rjday Julian day at each grid point
! tloc Local time at each grid point
! latscl Latitudes at scalar points
! lonscl Longitudes at scalar points
! slpmag Surface terrain slope magnitude
! slpdir Surface terrain slope direction
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
INTEGER :: nx,ny
REAL :: x(nx)
REAL :: y(ny)
REAL :: hterain(nx,ny)
REAL :: cosz(nx,ny), cosss(nx,ny), a2dr2(nx,ny)
REAL :: rjday(nx,ny), tloc(nx,ny)
REAL :: latscl(nx,ny), lonscl(nx,ny)
REAL :: slpmag(nx,ny), slpdir(nx,ny)
!augustin add saltitude and sazimuth in the outputs of zenanlg
REAL :: saltitude
REAL :: sazimuth
REAL :: tem1(nx,ny), tem2(nx,ny)
!
!-----------------------------------------------------------------------
!
! Include file:
!
!-----------------------------------------------------------------------
!
INCLUDE 'globcst.inc'
INCLUDE 'grid.inc' ! Grid & map parameters.
INCLUDE 'phycst.inc'
INCLUDE 'mp.inc'
!
!-----------------------------------------------------------------------
!
! Local variables:
!
!-----------------------------------------------------------------------
!
INTEGER :: i,j
REAL :: xs, ys
REAL :: hour0, yrday
REAL :: deg2rad, pi, pi2
REAL :: etau, shrangl, sdeclin
REAL :: azimuth, sinz
REAL :: dpsi, sinpsi, cospsi
REAL :: anncyc
REAL :: hr, days2k, lsun, gsun, obliq, lambda, xsun, ysun
REAL :: asun, alpha, rad2deg
LOGICAL :: firstcall ! First call flag of this subroutine
SAVE firstcall, hour0, pi, pi2, deg2rad, yrday, rad2deg
DATA firstcall/.true./
! added to calculate saltitude and sazimuth at the middle domain
INTEGER :: nxmid, nymid, source
SAVE nxmid, nymid, source
REAL :: shrangl_mid
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
IF (firstcall) THEN
pi = 3.14159265358979
pi2 = 2.0 * pi
deg2rad = pi/180.0
rad2deg = 1./deg2rad
hour0 = FLOAT(hour) &
+ FLOAT(minute)/60.0 &
+ FLOAT(second)/3600.0
IF ( MOD(year, 4) == 0 ) THEN
yrday = 366.
ELSE
yrday = 365.
END IF
nxmid = CEILING( 0.5*((nx-3)*nproc_x + 3) ) ! Middle point index at
nymid = CEILING( 0.5*((ny-3)*nproc_y + 3) ) ! global domain
source = proc( (nxmid-2)/(nx-3)+1 + ( (nymid-2)/(ny-3) )*nproc_x )
! source processor contain the middle point.
nxmid = MOD( (nxmid-2), (nx-3) ) + 2 ! local index of central domain
nymid = MOD( (nymid-2), (ny-3) ) + 2
firstcall = .false.
END IF
CALL sfcslp
( nx,ny, hterain, slpmag,slpdir, tem1,tem2 )
IF ( mapproj == 0 ) THEN
DO j=1,ny-1
DO i=1,nx-1
latscl(i,j) = ctrlat
lonscl(i,j) = ctrlon
END DO
END DO
ELSE
DO j=1,ny-1
ys = 0.5*(y(j)+y(j+1))
DO i=1,nx-1
xs = 0.5*(x(i)+x(i+1))
CALL xytoll
(1,1, xs,ys, latscl(i,j), lonscl(i,j))
END DO
END DO
END IF
!
!-----------------------------------------------------------------------
!
! Calculate the local time at each grid point. The
! following formula is based on that the input time is the GMT
! time at the reference grid point of the center.
!
!-----------------------------------------------------------------------
!
DO j=1,ny-1
DO i=1,nx-1
latscl(i,j) = deg2rad * latscl(i,j) ! lat: -90 to 90
tloc(i,j) = hour0 + (curtim-dtbig)/3600.0 &
+ lonscl(i,j)/15.0
rjday(i,j) = jday + INT( tloc(i,j)/24.0 )
tloc(i,j) = MOD( tloc(i,j), 24.0 )
IF ( tloc(i,j) < 0. ) THEN
tloc(i,j) = tloc(i,j) + 24.0 ! Local time
rjday(i,j) = MOD( rjday(i,j)-1, yrday ) ! Julian day at each pts
END IF
END DO
END DO
DO j=1,ny-1
DO i=1,nx-1
anncyc = pi2 * ( rjday(i,j) - 1.0 ) / yrday
a2dr2(i,j) = 1.000110 &
+ 0.034221 * COS(anncyc) &
+ 0.00128 * SIN(anncyc) &
+ 0.000719 * COS(2.*anncyc) &
+ 0.000077 * SIN(2.*anncyc) ! PX, Eq. 17
hr = hour + minute / 60.
! days before (-ve) or after (+ve) 1/1/2000
days2k = 367 * year - 7 * ( year + ( month + 9 ) / 12 ) / 4 &
+ 275 * month / 9 + day - 730531.5 + hr / 24.
lsun = 280.461 + 0.9856474 * days2k ! Mean Longitude of the Sun
950 IF ( lsun < 0 ) THEN
lsun = lsun + 360.
GO TO 950
ELSE IF ( lsun > 360 ) THEN
lsun = lsun - 360.
GO TO 950
END IF
gsun = 357.528 + 0.9856003 * days2k ! Mean anomaly of the Sun
960 IF ( gsun < 0 ) THEN
gsun = gsun + 360.
GO TO 960
ELSE IF ( gsun > 360 ) THEN
gsun = gsun - 360.
GO TO 960
END IF
lambda = lsun + 1.915 * SIN(gsun*deg2rad) & ! Ecliptic longitude
+ 0.02 * SIN(2*gsun*deg2rad)
970 IF ( lambda < 0 ) THEN
lambda = lambda + 360.
GO TO 970
ELSE IF ( lambda > 360 ) THEN
lambda = lambda - 360.
GO TO 970
END IF
obliq = 23.439 - 0.0000004 * days2k ! Obliquity of the ecliptic
xsun = COS(lambda*deg2rad)
ysun = COS(obliq*deg2rad) * SIN(lambda*deg2rad)
asun = ATAN(ysun/xsun)*rad2deg
IF ( xsun < 0. ) THEN
alpha = asun + 180 ! Right Ascension (RA)
ELSE IF ( ( ysun < 0. ) .AND. ( xsun > 0. ) ) THEN
alpha = asun + 360
ELSE
alpha = asun
END IF
etau = ( lsun - alpha ) * 4. / 60. ! Equation of time in hour
! etau = 0.158 * sin( pi*(rjday(i,j)+10.)/91.25 ) ! Equation of time
! : + 0.125 * sin( pi*rjday(i,j)/182.5 ) ! Wong, Eq. 8
shrangl = 15.0 * deg2rad & ! Hour angle
* ( tloc(i,j) + etau - 12.0) ! Wong, Eq. 7
! sdeclin = 23.5 * deg2rad
! : * cos( 2.0*pi*(rjday(i,j)-173.)/yrday ) ! Wong, Eq. 6
sdeclin = ASIN(SIN(obliq*deg2rad)*SIN(lambda*deg2rad))
! Declination (in radian)
cosz(i,j) = COS(latscl(i,j)) * COS(sdeclin) * COS(shrangl) &
+ SIN(latscl(i,j)) * SIN(sdeclin)
! print *, cos(latscl(i,j)),cos(sdeclin),cos(shrangl)
! print *, sin(latscl(i,j)),sin(sdeclin)
! print *,sdeclin,shrangl
sinz = SIN ( ACOS(cosz(i,j)) )
!
!-----------------------------------------------------------------------
!
! Consider the effects of the terrain slope on the solar radiation.
! The slope magnitude and direction has been computed by subroutine
! SFCSLP and passed in by slpmag and slpdir.
!
!-----------------------------------------------------------------------
!
sinpsi = COS(sdeclin) * SIN(shrangl) *COS(latscl(i,j))
cospsi = COSZ(i,j) * SIN( latscl(i,j) ) - SIN( sdeclin )
azimuth = ATAN2( sinpsi, cospsi)
dpsi = azimuth - slpdir(i,j)
cosss(i,j) = COS( slpmag(i,j) ) * cosz(i,j) &
+ SIN( slpmag(i,j) ) * sinz * COS( dpsi )
cosz (i,j) = MAX( cosz (i,j), 0.0 )
cosss(i,j) = MAX( cosss(i,j), 0.0 )
! added to calculate saltitude and sazimuth later for shading
IF( radshade /= 0) THEN
IF (i == nxmid .AND. j == nymid) THEN
! augustin
! computes the solar altitudes and azimuth,
! sazimuth: 0=North; pi/2=East; Pi=South; 3*pi/2=West
! see the reference listed in the header of subroutine ZENANGL for more
! information
saltitude = pi/2-ACOS(cosz(i,j))
! the following code is not computation safe (division by zero) DBW
! sazimuth = ACOS ( (SIN(sdeclin) * COS (latscl(i,j)) &
! - COS(sdeclin) * SIN (latscl(i,j)) &
! * COS (shrangl))/sinz)
! the above is replaced with: DBW
sinpsi = COS(sdeclin) * SIN(shrangl) * COS(latscl(i,j))
cospsi = - COSZ(i,j) * SIN( latscl(i,j) ) + SIN( sdeclin )
sazimuth = ABS( ATAN2(sinpsi, cospsi) )
! end or replacement code DBW
shrangl_mid = shrangl
END IF
END IF ! end of radshade if block...
END DO
END DO
IF( radshade /= 0) THEN
! broadcast these value from source to all other processors
CALL mpbcastr
(saltitude, source)
CALL mpbcastr
(sazimuth, source)
CALL mpbcastr
(shrangl_mid, source)
! modification of shrangl
! In the definition of the hour angle, shrangl should be
! between -pi and 0 before solar noon and between 0 and pi after.
! Before this error, zenangl gave positive values
! between pi and 2*pi of shrangl
! before solar noon for some latitudes and day.
! for instance, +45 deg north March 21 2001
! it causes not problem in the original ARPS since it is just
! a problem of module but subroutine shade needs to have shrangl
! between -pi and pi
IF ((shrangl_mid > pi) .AND. (shrangl_mid < pi2)) THEN
shrangl_mid = shrangl_mid - pi2
END IF
IF ((shrangl_mid > pi2) .AND. (shrangl_mid < pi2+pi)) THEN
shrangl_mid = shrangl_mid - pi2
END IF
IF (shrangl_mid > 0) THEN
sazimuth = pi2 - sazimuth
END IF
END IF ! end of radshade if block...
RETURN
END SUBROUTINE zenangl
!
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE SFCSLP ######
!###### ######
!###### Developed by ######
!###### Center for Analysis and Prediction of Storms ######
!###### University of Oklahoma ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE sfcslp( nx,ny, hterain, slpmag,slpdir, tem1,tem2 ) 1,5
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! This program is to compute the terrain slope vector in terms of
! magnitude and direction.
!
! Magnitude slpmag:
!
! 1
! cos(slpmag) = -----------------------------------, 0 <= slpmag <= pi/2
! sqrt( 1 + (dz/dx)**2 + (dz/dy)**2 )
!
! Direction slpdir:
!
! dz/dx
! tan(slpdir) = -----, - pi <= slpdir <= pi
! dz/dy
!
!-----------------------------------------------------------------------
!
! AUTHOR: Yuhe Liu and Vince Wong
! 2/16/94
!
! MODIFICATION HISTORY:
!
!
!-----------------------------------------------------------------------
!
! INPUT:
!
! nx Number of grid points in the x-direction (east/west)
! ny Number of grid points in the y-direction (north/south)
!
! hterain The heights of terrain
!
! OUTPUT:
!
! slpmag Magnitude of terrain surface slope vector
! slpdir Direction of terrain surface slope vector from north
! clockwise
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
!
INTEGER :: nx,ny
REAL :: hterain(nx,ny) ! The heights of terrain
REAL :: slpmag (nx,ny) ! Terrain surface slope vector magnitude
REAL :: slpdir (nx,ny) ! Terrain surface slope vector direction
! from north clockwise
REAL :: tem1(nx,ny) ! 2-D temporary array
REAL :: tem2(nx,ny) ! 2-D temporary array
!
!-----------------------------------------------------------------------
!
! Local declarations
!
!-----------------------------------------------------------------------
!
REAL :: pi
PARAMETER ( pi = 3.141592654)
REAL :: twdxinv, twdyinv, dzsds2
INTEGER :: i, j
!
!-----------------------------------------------------------------------
!
! Include files:
!
!-----------------------------------------------------------------------
!
INCLUDE 'globcst.inc'
INCLUDE 'grid.inc' ! Grid & map parameters.
INCLUDE 'bndry.inc'
INCLUDE 'mp.inc' ! Message passing parameters.
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
IF ( ternopt == 0 ) THEN
DO j = 1, ny-1
DO i = 1, nx-1
slpmag(i,j) = 0.
slpdir(i,j) = 0.
END DO
END DO
ELSE
!
!-----------------------------------------------------------------------
!
! dz dz
! Use the central difference to calculate ---- and ----.
! dx dy
!
!-----------------------------------------------------------------------
!
twdxinv = 1.0 / (2.0*dx)
DO j = 1, ny-1
DO i = 2, nx-2
tem1(i,j) = ( hterain(i+1,j) - hterain(i-1,j) ) * twdxinv
END DO
END DO
twdyinv = 1.0 / (2.0*dy)
DO j = 2, ny-2
DO i = 1, nx-1
tem2(i,j) = ( hterain(i,j+1) - hterain(i,j-1) ) * twdyinv
END DO
END DO
IF (mp_opt > 0) THEN
CALL acct_interrupt
(mp_acct)
CALL mpsendrecv1dew
(tem1,nx,ny,ebc,wbc,0,slpmag) ! use slpmag as temp
CALL mpsendrecv1dns
(tem2,nx,ny,nbc,sbc,0,slpmag) ! use slpmag as temp
END IF
CALL acct_interrupt
(bc_acct)
IF ( wbc == 1 ) THEN
DO j = 1,ny-1
tem1(1,j) = - tem1(2,j)
END DO
ELSE IF ( wbc == 2 ) THEN
IF (mp_opt == 0) THEN
DO j = 1,ny-1
tem1(1,j) = tem1(nx-2,j)
END DO
END IF
ELSE IF ( wbc /= 0 ) THEN
DO j = 1, ny-1
tem1(1,j) = ( hterain(2,j) - hterain(1,j) ) / dx
END DO
END IF
IF ( ebc == 1 ) THEN
DO j = 1, ny-1
tem1(nx-1,j) = - tem1(nx-2,j)
END DO
ELSE IF ( ebc == 2 ) THEN
IF (mp_opt == 0) THEN
DO j = 1,ny-1
tem1(nx-1,j) = tem1(2,j)
END DO
END IF
ELSE IF ( ebc /= 0 ) THEN
DO j = 1, ny-1
tem1(nx-1,j) = ( hterain(nx-1,j) - hterain(nx-2,j) ) / dx
END DO
END IF
IF ( sbc == 1 ) THEN
DO i = 1, nx-1
tem2(i,1) = - tem2(i,2)
END DO
ELSE IF ( sbc == 2 ) THEN
IF (mp_opt == 0) THEN
DO i = 1, nx-1
tem2(i,1) = tem2(i,ny-2)
END DO
END IF
ELSE IF ( sbc /= 0 ) THEN
DO i = 1, nx-1
tem2(i,1) = ( hterain(i,2) - hterain(i,1) ) / dy
END DO
END IF
IF ( nbc == 1 ) THEN
DO i = 1, nx-1
tem2(i,ny-1) = - tem2(i,ny-2)
END DO
ELSE IF ( nbc == 2 ) THEN
IF (mp_opt == 0) THEN
DO i = 1, nx-1
tem2(i,ny-1) = tem2(i,2)
END DO
END IF
ELSE IF ( nbc /= 0 ) THEN
DO i = 1, nx-1
tem2(i,ny-1) = ( hterain(i,ny-1) - hterain(i,ny-2) ) / dy
END DO
END IF
CALL acct_stop_inter
DO j = 1, ny-1
DO i = 1, nx-1
dzsds2 = tem1(i,j)**2 + tem2(i,j)**2
slpmag(i,j) = ACOS( 1. / SQRT( 1. + dzsds2 ) )
IF ( dzsds2 == 0. ) THEN
slpdir(i,j) = 0.
ELSE
slpdir(i,j) = ATAN2( tem1(i,j), tem2(i,j) )
END IF
END DO
END DO
END IF
RETURN
END SUBROUTINE sfcslp
!
!##################################################################
!##################################################################
!###### ######
!###### SUBROUTINE SHADE ######
!###### ######
!###### Developed by ######
!###### Augustin Colette / Robert L. Street ######
!###### Stanford University ######
!###### Environmental Fluid Mechanics Laboratory ######
!###### Stanford, CA 94305 ######
!###### augustin@stanford.edu, street@stanford.edu ######
!###### ######
!###### ######
!###### June 2002 ######
!###### ######
!##################################################################
!##################################################################
!
SUBROUTINE shade(nx,ny,x,y,saltitude,sazimuth,hterain,sh) 1,4
!
!-----------------------------------------------------------------------
!
! PURPOSE:
!
! This subroutine computes the shadow induced by a topography
! by drawing a line from each node and the sun
! and checking if it hits the topography
!
!----------------------------------------------------------------------
! Modification:
!
! 2003/02/19 (Yunheng Wang)
! Added code to do message passing for multiple processors.
!
!-----------------------------------------------------------------------
!
! INPUT:
! nx Number of grid points in the x-direction (east/west)
! ny Number of grid points in the y-direction (north/south)
! x(nx) x-coordinates
! y(ny) y-coordinates
! sazimuth azimuth (radians)
! saltitude solar altitude (radians)
! hterain(nx,ny) topography
!
! OUTPUT:
! sh(nx,ny) Matrix shade: 0: shaded, 1:enlightened.
!
!-----------------------------------------------------------------------
!
! Variable Declarations.
!
!
!-----------------------------------------------------------------------
!
IMPLICIT NONE
INTEGER :: nx,ny
!
!-----------------------------------------------------------------------
!
! Define ARPS variables
!
!-----------------------------------------------------------------------
!
REAL :: x(nx) ! x-coordinates
REAL :: y(ny) ! y-coordinates
REAL :: sazimuth ! azimuth (radians)
REAL :: saltitude ! solar altitude (radians)
REAL :: hterain(nx,ny) ! topography
!-----------------------------------------------------------------------
!
! Output
!
!-----------------------------------------------------------------------
REAL :: sh(nx,ny)
!
!-----------------------------------------------------------------------
!
! Include file:
!
!-----------------------------------------------------------------------
!
INCLUDE 'globcst.inc'
INCLUDE 'grid.inc'
INCLUDE 'phycst.inc'
INCLUDE 'bndry.inc'
INCLUDE 'mp.inc'
!
!-----------------------------------------------------------------------
!
! Local variables
!
!-----------------------------------------------------------------------
!
REAL :: ztest ! altitude of a test point on a sun ray
REAL :: htest ! averaged topography at the test point
INTEGER :: i,j,l ! indices
INTEGER :: II,IF,dI,JI,JF,dJ ! extrema of the iteration
REAL :: a,b,C,D,E,F,H ! definition of the quadrant (NE,NW,SW,SE)
REAL :: xg,yg ! local grid cell where the test
! is performed
REAL :: Sx,Sy ! coordinates of the point to be tested
REAL :: pi,pi2,pi32,p2i ! multiple of pi
INTEGER :: xh,yh,xhh,yhh
! CHARACTER (LEN = 132) :: fname
!----------------------------------------------------------------------
!
! MP variables
!
!----------------------------------------------------------------------
INTEGER :: nxlg, nylg, istat
REAL, ALLOCATABLE :: xlg(:), ylg(:)
REAL, ALLOCATABLE :: hterainlg(:,:)
REAL, ALLOCATABLE :: shlg(:,:)
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
!
! Beginning of executable code...
!
!@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
nxlg = (nx-3)*nproc_x + 3
nylg = (ny-3)*nproc_y + 3
ALLOCATE(xlg(nxlg), STAT=istat)
ALLOCATE(ylg(nylg), STAT=istat)
ALLOCATE(hterainlg(nxlg,nylg), STAT=istat)
ALLOCATE(shlg(nxlg,nylg), STAT=istat)
CALL mpimerge1dx
(x,nx,xlg)
CALL mpimerge1dy
(y,ny,ylg)
CALL mpimerge2d
(hterain, nx,ny, hterainlg)
! initialization
! in the subroutine, sh will be set to zero in the shaded areas
! nothing will be done if the point is illuminated
shlg(:,:)=1
pi=3.14159265358979;
pi2=pi/2.0;
pi32=3.0 * pi/2.0;
p2i=2.0 * pi;
! modification of azimuth
! in the subroutine zenangl azimuth has the usual definition:
! sazimuth: 0:N pi/2:E, Pi:S, 3*pi/2:W
!
! in the subroutine shade azimuth is 0:E, pi/2:N, pi:W, 3pi/2:S
! (for better comparison with the trigonometric circle)
! Check if azimuth is > 0 and < 2*pi
IF (sazimuth > p2i) THEN
! print*,'aziumth zenangl was > 2pi'
sazimuth =sazimuth-p2i
END IF
IF (sazimuth < 0) THEN
! print*,'aziumth zenangl was <0'
sazimuth =p2i+sazimuth
END IF
! second translate sazimuth
IF (( sazimuth >= 0 ) .AND. ( sazimuth < pi/2)) THEN !
sazimuth=pi/2.0-sazimuth
ELSE
sazimuth=p2i+pi/2.0-sazimuth
END IF
!print*,'azshade',sazimuth
!print*,'sdshade',saltitude
!-----------------------------------------------------------
!
! Four differents cases must be considered
! the iteration will vary if the sun is NE,NW,SW,SE because:
! - the shade can not be computed on the most nothern point
! if the sun is north
! - when going along the line going towards the sun, the direction
! of 'propagation' will vary
!
! consequently the iteration extremas and increment vary
! to avoid writting four times the subroutine, local variables
! are used depending on the azimuth of the sun
!
!---------------------------------------------------------
! First quadrant : NE
IF ( (0 <= sazimuth) .AND. (sazimuth < pi2) ) THEN
a=1
b=1
C=1
D=1
E=0
F=0
H=0
END IF
! Second quadrant NW
IF ( (pi2 <= sazimuth) .AND. (sazimuth < pi) ) THEN
a=-1
b=1
C=2
D=0
E=1
F=0
H=0
END IF
! Third quadrant SW
IF ((pi <= sazimuth) .AND. (sazimuth < pi32) ) THEN
a=-1
b=-1
C=3
D=0
E=0
F=1
H=0
END IF
! Fourth quadrant SE
IF ((pi32 <= sazimuth) .AND. (sazimuth <p2i)) THEN
a=1
b=-1
C=4
D=0
E=0
F=0
H=1
END IF
! Iteration extremas and increment
II=D*2+E*(nxlg-2)+F*(nxlg-2)+H*2 ! initial i index
IF=D*(nxlg-3)+E*(3)+F*(3)+H*(nxlg-3) ! final i index
dI=a*1 ! i increment
JI=D*2+E*2+F*(nylg-2)+H*(nylg-2) ! initial j index
JF=D*(nylg-3)+E*(nylg-3)+F*3+H*3 ! final j index
dJ=b*1 ! j increment
!----------------------------------------------------------------------
!
! Exceptions : sun ray directly N,S,E,W
!
! If the sun is 'exactly' at the N,S,E or W
! the algorithm must be changed
! e.g. to avoid the evaluation of tan(pi/2)
!
!-----------------------------------------------------------------------
IF(myproc == 0) THEN
IF (( ABS(sazimuth-0) < 0.0001) .OR. (ABS(sazimuth-pi2) < 0.0001) .OR. &
(ABS(sazimuth-pi) < 0.0001) .OR. (ABS(sazimuth-pi32) < 0.0001) ) THEN
DO i = II,IF,dI ! we will test each grid point starting from the
DO j = JI,JF,dJ ! farthest node form the sun
xg=xlg(i) ! x and y coordinates of the test point along the line
yg=ylg(j) !
Sx=xlg(i) + a*dx*D + a*dx*F ! x and y coordinate of the first
Sy=ylg(j) + b*dy*E + b*dy*H ! intersection of the line going toward the sun
! and the horizontal grid
DO l=1,(2*nxlg+2*nylg) ! incrementation along the line
! (2*nxlg+2*nylg) is choosen so that we are certain
! to explore the whole domain
IF ((xg >= xlg(nxlg)) .OR. (yg >= ylg(nylg)) &
.OR. (xg <= xlg(1)) .OR. (yg <= ylg(1)) ) EXIT
! if we are outside the topography, then :END
ztest = hterainlg(i,j) &
+ SQRT((Sx-xlg(i))*(Sx-xlg(i))+(Sy-ylg(j))*(Sy-ylg(j))) &
* TAN(saltitude)
! ztest is the altitude of the point to be tested
! as the altitude of the initial point (hterain(i,j)
! plus the elevation gain along the line
! as the distance between the initial point
! and the current testing point times tan(saltitude)
xh = 2 + NINT((xg + (D+F)*a*dx) / dx) ! find the x and y coordinates
yh = 2 + NINT((yg + (E+H)*b*dy) / dy) ! of the point to be tested
! xg and yg may not be on the grid !
IF (xh < 1 .OR. xh > nxlg .OR. yh < 1 .OR. yh > nylg) EXIT ! EMK NEW
htest = hterainlg(xh,yh)
IF (ztest < htest) THEN ! perform the test
shlg(i,j) = 0.0
EXIT
END IF
xg = xg + a*dx*(D+F) !if not shaded, increment xg and yg
yg = yg + b*dy*(E+H) ! by going toward the sun
Sx = Sx + a*dx*(D+F)
Sy = Sy + b*dy*(E+H)
END DO
END DO
END DO
!-----------------------------------------------------------------------
!
! General case: NE,NW,SE,SW
! if the sun is not exactly N,S,E,W
!
!-----------------------------------------------------------------------
ELSE
DO i=II,IF,dI
DO j=JI,JF,dJ
xg = xlg(i) ! x and y coordinates of the first point along the line
yg = ylg(j)
Sx = xlg(i) + a*(b*(yg+b*dy)-b*ylg(j))*((D+F)*TAN(C*pi2-sazimuth) &
+ (E+H)*TAN(sazimuth-(C-1)*pi2))
Sy = ylg(j) + b*(a*(xg+a*dx)-a*xlg(i))*((E+H)*TAN(C*pi2-sazimuth) &
+ (D+F)*TAN(sazimuth-(C-1)*pi2))
! x and y coordinate of the first intersection
! between the line and the grid
DO l=1,(2*nxlg+2*nylg) ! incrementation (See above)
IF ((xg >= xlg(nxlg)) .OR. (yg >= ylg(nylg)) &
.OR. (xg <= xlg(1)) .OR. (yg <= ylg(1)) ) EXIT
! if we are outside the grid: STOP
IF (( abs(Sy-(yg+b*dy)) < 0.01) .AND. &
( abs(Sx-(xg+a*dx)) < 0.01) ) THEN
! if the next testing point is very close to a grid point
! the test wil be performed with this grid point
ztest = hterainlg(i,j) &
+ SQRT((Sx-xlg(i))*(Sx-xlg(i))+(Sy-ylg(j))*(Sy-ylg(j))) &
*TAN(saltitude)
! altitude of the test point along the line
xh = 2+NINT((xg+a*dx)/dx) ! x and y coordinates
yh = 2+NINT((yg+b*dy)/dy) ! of the point where the test will be performed
IF (xh < 1 .OR. xh > nxlg .OR. yh < 1 .OR. yh > nylg) EXIT ! EMK NEW
htest = hterainlg(xh,yh) ! altitude of this point
IF (ztest < htest) THEN ! test itself (see above)
shlg(i,j) = 0.0
EXIT
END IF
xg = xg+a*dx ! incrementation, the point xg,yg has been tested
yg = yg+b*dy ! we can continue to the next one
Sx = xlg(i) + a*(b*(yg+b*dy)-b*ylg(j))*((D+F)*TAN(C*pi2-sazimuth) &
+ (E+H)*TAN(sazimuth-(C-1.0)*pi2))
Sy = ylg(j) + b*(a*(xg+a*dx)-a*xlg(i))*((E+H)*TAN(C*pi2-sazimuth) &
+ (D+F)*TAN(sazimuth-(C-1.0)*pi2))
! x and y's of the next point to be tested
ELSE IF ( abs(Sy-yg) >dy ) THEN
! if the line hits first a horizontal grid line
! the test will be peformed on the horizontal
! grid cell boundary
ztest = hterainlg(i,j) &
+ SQRT((Sx-xlg(i))*(Sx-xlg(i)) &
+((yg+b*dy)-ylg(j))*((yg+b*dy)-ylg(j))) &
*TAN(saltitude)
! altitude along the line
xh = 2+NINT((xg+a*dx)/dx) ! coordinates of the neighboring
yh = 2+NINT((yg+b*dy)/dy) ! test points
IF (xh < 1 .OR. xh > nxlg .OR. yh < 1 .OR. yh > nylg) EXIT ! EMK NEW
xhh = 2+NINT(xg/dx)
yhh = 2+NINT((yg+b*dy)/dy)
IF (xhh < 1 .OR. xhh > nxlg .OR. yhh < 1 .OR. yhh > nylg) EXIT ! EMK NEW
htest = (a*(Sx-xg)*hterainlg(xh,yh) &
+a*((xg+a*dx)-Sx)*hterainlg(xhh,yhh)) / dx
! altitude of the topography
! linearly interpolated along the grid cell boundary
IF (ztest < htest) THEN ! test itself
shlg(i,j) = 0.0
EXIT
END IF
xg = xg ! incrementation since we hit first a horizontal
yg = yg+b*dy ! grid cell boundary, we increment only y not x
Sx = xlg(i) &
+ a*(b*(yg+b*dy)-b*ylg(j)) &
*((D+F)*TAN(C*pi2-sazimuth)+(E+H)*TAN(sazimuth-(C-1.0)*pi2))
Sy = ylg(j) &
+ b*(a*(xg+a*dx)-a*xlg(i)) &
*((E+H)*TAN(C*pi2-sazimuth)+(D+F)*TAN(sazimuth-(C-1.0)*pi2))
! x and y of the next testing point
ELSE IF ( abs(Sy-yg) < dy ) THEN ! see the previous case for comments
ztest = hterainlg(i,j) &
+ SQRT(((xg+a*dx)-xlg(i))*((xg+a*dx)-xlg(i)) &
+(Sy-ylg(j))*(Sy-ylg(j)))*TAN(saltitude)
xh = 2+NINT((xg+a*dx)/dx)
yh = 2+NINT((yg+b*dy)/dy)
IF (xh < 1 .OR. xh > nxlg .OR. yh < 1 .OR. yh > nylg) EXIT ! EMK NEW
xhh = 2+NINT((xg+a*dx)/dx)
yhh = 2+NINT(yg/dy)
IF (xhh < 1 .OR. xhh > nxlg .OR. yhh < 1 .OR. yhh > nylg) EXIT ! EMK NEW
htest = (b*(Sy-yg)*hterainlg(xh,yh)+b*((yg+b*dy)-Sy) &
*hterainlg(xhh,yhh)) / dy
IF (ztest < htest) THEN
shlg(i,j) = 0.0
EXIT
END IF
yg = yg
xg = xg+a*dx
Sx = xlg(i) + a*(b*(yg+b*dy)-b*ylg(j))*((D+F)*TAN(C*pi2-sazimuth) &
+(E+H)*TAN(sazimuth-(C-1.0)*pi2))
Sy = ylg(j) + b*(a*(xg+a*dx)-a*xlg(i))*((E+H)*TAN(C*pi2-sazimuth) &
+(D+F)*TAN(sazimuth-(C-1.0)*pi2))
END IF
END DO ! l
END DO ! j
END DO ! i
END IF
!-----------------------------------------------------------------------
!
! Extrapolation in the direction of the sun
! part of the domain where the shade can not be computed
! the shade is set to its value at the neighboring point
!
!-----------------------------------------------------------------------
IF ( C==1 ) THEN
DO i=2,nxlg-3
shlg(i,nylg-2)=shlg(i,nylg-3)
END DO
DO j=2,nylg-3
shlg(nxlg-2,j)=shlg(nxlg-3,j)
END DO
shlg(nxlg-2,nylg-2)=shlg(nxlg-3,nylg-3)
END IF
IF (C==2) THEN
DO i=3,nxlg-2
shlg(i,nylg-2)=shlg(i,nylg-3)
END DO
DO j=2,nylg-3
shlg(2,j)=shlg(3,j)
END DO
shlg(2,nylg-2)=shlg(3,nylg-3)
END IF
IF (C==3) THEN
DO i=3,nxlg-2
shlg(i,2)=shlg(i,3)
END DO
DO j=3,nylg-2
shlg(2,j)=shlg(3,j)
END DO
shlg(2,2)=shlg(3,3)
END IF
IF (C==4) THEN
DO i=2,nxlg-3
shlg(i,2)=shlg(i,3)
END DO
DO j=3,nylg-2
shlg(nxlg-2,j)=shlg(nxlg-3,j)
END DO
shlg(nxlg-2,2)=shlg(nxlg-3,3)
END IF
! Extrapolation at the boundaries, outside the actual grid used in arps
! i,j=1 and i,j=nxlg (or nylg)
! first for i,j=1 and i,j=N-1
! second for i,j = N
DO i=2,nxlg-2
shlg(i,1)=shlg(i,2)
shlg(i,nylg-1)=shlg(i,nylg-2)
END DO
DO j=2,nylg-2
shlg(1,j)=shlg(2,j)
shlg(nxlg-1,j)=shlg(nxlg-2,j)
END DO
shlg(1,1)=shlg(2,2)
shlg(1,nylg-1)=shlg(2,nylg-2)
shlg(nxlg-1,1)=shlg(nxlg-2,2)
shlg(nxlg-1,nylg-1)=shlg(nxlg-2,nylg-2)
DO i=1,nxlg-1
shlg(i,nylg)=shlg(i,nylg-1)
END DO
DO j=1,nylg-1
shlg(nxlg,j)=shlg(nxlg-1,j)
END DO
shlg(nxlg,nylg)=shlg(nxlg-1,nylg-1)
! If the topography is two-dimensional in a 3D run(e.g. a periodic valley)
! the shlgade is set to be two-dimensionnal by setting it to
! its value at the middle of the domain
IF (radshade == 2) THEN
l=NINT(0.5*nylg)
DO j=1,nylg
DO i=1,nxlg
shlg(i,j)=shlg(i,l)
END DO
END DO
END IF
END IF ! myproc == 0
CALL mpisplit2d
(shlg,nx,ny,sh)
IF(myproc == 0 ) print*,'The shade was computed.'
DEALLOCATE(xlg,ylg,hterainlg,shlg)
RETURN
END SUBROUTINE shade